From dc46f521f2ca195c265f6d7ed51899e58f3b6eb9 Mon Sep 17 00:00:00 2001 From: dvossel Date: Wed, 6 Jul 2011 15:30:28 +0000 Subject: Merged revisions 326484 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.8 ........ r326484 | dvossel | 2011-07-06 10:26:49 -0500 (Wed, 06 Jul 2011) | 10 lines Reverts fix for timerfd locking issue. jrose discovered a performance issue with this fix that prevents his analog phones from working when using timerfd as a timing source. Until it is understood what is causing this performance problem, this patch is being reverted. ........ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@326485 f38db490-d61c-443f-a65b-d21fe96a405b --- res/res_timing_timerfd.c | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/res/res_timing_timerfd.c b/res/res_timing_timerfd.c index 3e686f810..ae5d2b411 100644 --- a/res/res_timing_timerfd.c +++ b/res/res_timing_timerfd.c @@ -162,35 +162,7 @@ static void timerfd_timer_ack(int handle, unsigned int quantity) uint64_t expirations; int read_result = 0; - struct timerfd_timer *our_timer, find_helper = { - .handle = handle, - }; - - if (!(our_timer = ao2_find(timerfd_timers, &find_helper, OBJ_POINTER))) { - ast_log(LOG_ERROR, "Couldn't find timer with handle %d\n", handle); - return; - } - - if (our_timer->saved_timer.it_value.tv_nsec == 0L) { - ast_log(LOG_DEBUG, "Reading attempt on idle timerfd.\n"); - return; - } - do { - struct itimerspec timer_status; - - if (timerfd_gettime(handle, &timer_status)) { - ast_log(LOG_ERROR, "Call to timerfd_gettime() error: %s\n", strerror(errno)); - expirations = 0; - break; - } - - if ((timer_status.it_value.tv_sec == 0) && (timer_status.it_value.tv_nsec == 0)) { - ast_log(LOG_DEBUG, "Call to timerfd_timer_ack() with disarmed timer - break now.\n"); - expirations = 0; - break; - } - read_result = read(handle, &expirations, sizeof(expirations)); if (read_result == -1) { if (errno == EINTR || errno == EAGAIN) { -- cgit v1.2.3 From bacd87fb8e73ef3eed30c2f49a5a7a38842f3b51 Mon Sep 17 00:00:00 2001 From: dvossel Date: Wed, 6 Jul 2011 17:39:36 +0000 Subject: Fixes newlines from being stripped from out of dialog sip MESSAGES. git-svn-id: http://svn.digium.com/svn/asterisk/trunk@326544 f38db490-d61c-443f-a65b-d21fe96a405b --- channels/chan_sip.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 18eba2371..1f2c72379 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -16079,7 +16079,11 @@ static void receive_message(struct sip_pvt *p, struct sip_request *req, struct a return; } - if (get_msg_text2(&buf, req, FALSE)) { + /* If this is an out of dialog msg, add back newlines, otherwise strip the new lines. + * In dialog msg's newlines are stripped to preserve the behavior of how Asterisk has worked + * in the past. If it is found later that new lines can be added into in dialog msgs as well, + * then change this. */ + if (get_msg_text2(&buf, req, p->owner ? FALSE : TRUE)) { ast_log(LOG_WARNING, "Unable to retrieve text from %s\n", p->callid); transmit_response(p, "202 Accepted", req); if (!p->owner) -- cgit v1.2.3 From 9b10a0c265265d787eba75de81be2bc5a286734b Mon Sep 17 00:00:00 2001 From: twilson Date: Wed, 6 Jul 2011 20:58:12 +0000 Subject: Replace Berkeley DB with SQLite 3 There were some bugs in the very ancient version of Berkeley DB that Asterisk used. Instead of spending the time tracking down the bugs in the Berkeley code we move to the much better documented SQLite 3. Conversion of the old astdb happens at runtime by running the included astdb2sqlite3 utility. The ast_db API with SQLite 3 backend should behave identically to the old Berkeley backend, but in the future we could offer a much more robust interface. We do not include the SQLite 3 library in the source tree, but instead rely upon the distribution-provided libraries. SQLite is so ubiquitous that this should not place undue burden on administrators. git-svn-id: http://svn.digium.com/svn/asterisk/trunk@326589 f38db490-d61c-443f-a65b-d21fe96a405b --- CHANGES | 8 + Makefile | 1 + UPGRADE.txt | 7 + configure | 924 ++++++++++++++++------------------ configure.ac | 6 + main/Makefile | 16 +- main/asterisk.c | 10 +- main/db.c | 618 ++++++++++++++--------- main/db1-ast/Makefile | 71 --- main/db1-ast/btree/bt_close.c | 182 ------- main/db1-ast/btree/bt_conv.c | 221 -------- main/db1-ast/btree/bt_debug.c | 329 ------------ main/db1-ast/btree/bt_delete.c | 657 ------------------------ main/db1-ast/btree/bt_get.c | 105 ---- main/db1-ast/btree/bt_open.c | 458 ----------------- main/db1-ast/btree/bt_overflow.c | 228 --------- main/db1-ast/btree/bt_page.c | 100 ---- main/db1-ast/btree/bt_put.c | 321 ------------ main/db1-ast/btree/bt_search.c | 213 -------- main/db1-ast/btree/bt_seq.c | 460 ----------------- main/db1-ast/btree/bt_split.c | 829 ------------------------------ main/db1-ast/btree/bt_utils.c | 260 ---------- main/db1-ast/btree/btree.h | 391 --------------- main/db1-ast/btree/extern.h | 70 --- main/db1-ast/db/db.c | 103 ---- main/db1-ast/hash/README | 72 --- main/db1-ast/hash/extern.h | 65 --- main/db1-ast/hash/hash.c | 999 ------------------------------------- main/db1-ast/hash/hash.h | 293 ----------- main/db1-ast/hash/hash_bigkey.c | 668 ------------------------- main/db1-ast/hash/hash_buf.c | 355 ------------- main/db1-ast/hash/hash_func.c | 225 --------- main/db1-ast/hash/hash_log2.c | 56 --- main/db1-ast/hash/hash_page.c | 946 ----------------------------------- main/db1-ast/hash/hsearch.c | 107 ---- main/db1-ast/hash/ndbm.c | 235 --------- main/db1-ast/hash/page.h | 92 ---- main/db1-ast/hash/search.h | 51 -- main/db1-ast/include/circ-queue.h | 131 ----- main/db1-ast/include/compat.h | 49 -- main/db1-ast/include/db.h | 250 ---------- main/db1-ast/include/mpool.h | 115 ----- main/db1-ast/include/ndbm.h | 79 --- main/db1-ast/libdb.map | 11 - main/db1-ast/mpool/README | 7 - main/db1-ast/mpool/mpool.c | 502 ------------------- main/db1-ast/recno/extern.h | 54 -- main/db1-ast/recno/rec_close.c | 183 ------- main/db1-ast/recno/rec_delete.c | 197 -------- main/db1-ast/recno/rec_get.c | 311 ------------ main/db1-ast/recno/rec_open.c | 241 --------- main/db1-ast/recno/rec_put.c | 280 ----------- main/db1-ast/recno/rec_search.c | 126 ----- main/db1-ast/recno/rec_seq.c | 131 ----- main/db1-ast/recno/rec_utils.c | 122 ----- main/db1-ast/recno/recno.h | 39 -- tests/test_db.c | 28 ++ utils/Makefile | 10 + utils/astdb2sqlite3.c | 231 +++++++++ utils/db1-ast/Makefile | 71 +++ utils/db1-ast/btree/bt_close.c | 182 +++++++ utils/db1-ast/btree/bt_conv.c | 221 ++++++++ utils/db1-ast/btree/bt_debug.c | 329 ++++++++++++ utils/db1-ast/btree/bt_delete.c | 657 ++++++++++++++++++++++++ utils/db1-ast/btree/bt_get.c | 105 ++++ utils/db1-ast/btree/bt_open.c | 458 +++++++++++++++++ utils/db1-ast/btree/bt_overflow.c | 228 +++++++++ utils/db1-ast/btree/bt_page.c | 100 ++++ utils/db1-ast/btree/bt_put.c | 321 ++++++++++++ utils/db1-ast/btree/bt_search.c | 213 ++++++++ utils/db1-ast/btree/bt_seq.c | 460 +++++++++++++++++ utils/db1-ast/btree/bt_split.c | 829 ++++++++++++++++++++++++++++++ utils/db1-ast/btree/bt_utils.c | 260 ++++++++++ utils/db1-ast/btree/btree.h | 391 +++++++++++++++ utils/db1-ast/btree/extern.h | 70 +++ utils/db1-ast/db/db.c | 103 ++++ utils/db1-ast/hash/README | 72 +++ utils/db1-ast/hash/extern.h | 65 +++ utils/db1-ast/hash/hash.c | 999 +++++++++++++++++++++++++++++++++++++ utils/db1-ast/hash/hash.h | 293 +++++++++++ utils/db1-ast/hash/hash_bigkey.c | 668 +++++++++++++++++++++++++ utils/db1-ast/hash/hash_buf.c | 355 +++++++++++++ utils/db1-ast/hash/hash_func.c | 225 +++++++++ utils/db1-ast/hash/hash_log2.c | 56 +++ utils/db1-ast/hash/hash_page.c | 946 +++++++++++++++++++++++++++++++++++ utils/db1-ast/hash/hsearch.c | 107 ++++ utils/db1-ast/hash/ndbm.c | 235 +++++++++ utils/db1-ast/hash/page.h | 92 ++++ utils/db1-ast/hash/search.h | 51 ++ utils/db1-ast/include/circ-queue.h | 131 +++++ utils/db1-ast/include/compat.h | 49 ++ utils/db1-ast/include/db.h | 250 ++++++++++ utils/db1-ast/include/mpool.h | 115 +++++ utils/db1-ast/include/ndbm.h | 79 +++ utils/db1-ast/libdb.map | 11 + utils/db1-ast/mpool/README | 7 + utils/db1-ast/mpool/mpool.c | 498 ++++++++++++++++++ utils/db1-ast/recno/extern.h | 54 ++ utils/db1-ast/recno/rec_close.c | 183 +++++++ utils/db1-ast/recno/rec_delete.c | 197 ++++++++ utils/db1-ast/recno/rec_get.c | 311 ++++++++++++ utils/db1-ast/recno/rec_open.c | 241 +++++++++ utils/db1-ast/recno/rec_put.c | 280 +++++++++++ utils/db1-ast/recno/rec_search.c | 126 +++++ utils/db1-ast/recno/rec_seq.c | 131 +++++ utils/db1-ast/recno/rec_utils.c | 122 +++++ utils/db1-ast/recno/recno.h | 39 ++ utils/utils.xml | 3 + 108 files changed, 13093 insertions(+), 12745 deletions(-) delete mode 100644 main/db1-ast/Makefile delete mode 100644 main/db1-ast/btree/bt_close.c delete mode 100644 main/db1-ast/btree/bt_conv.c delete mode 100644 main/db1-ast/btree/bt_debug.c delete mode 100644 main/db1-ast/btree/bt_delete.c delete mode 100644 main/db1-ast/btree/bt_get.c delete mode 100644 main/db1-ast/btree/bt_open.c delete mode 100644 main/db1-ast/btree/bt_overflow.c delete mode 100644 main/db1-ast/btree/bt_page.c delete mode 100644 main/db1-ast/btree/bt_put.c delete mode 100644 main/db1-ast/btree/bt_search.c delete mode 100644 main/db1-ast/btree/bt_seq.c delete mode 100644 main/db1-ast/btree/bt_split.c delete mode 100644 main/db1-ast/btree/bt_utils.c delete mode 100644 main/db1-ast/btree/btree.h delete mode 100644 main/db1-ast/btree/extern.h delete mode 100644 main/db1-ast/db/db.c delete mode 100644 main/db1-ast/hash/README delete mode 100644 main/db1-ast/hash/extern.h delete mode 100644 main/db1-ast/hash/hash.c delete mode 100644 main/db1-ast/hash/hash.h delete mode 100644 main/db1-ast/hash/hash_bigkey.c delete mode 100644 main/db1-ast/hash/hash_buf.c delete mode 100644 main/db1-ast/hash/hash_func.c delete mode 100644 main/db1-ast/hash/hash_log2.c delete mode 100644 main/db1-ast/hash/hash_page.c delete mode 100644 main/db1-ast/hash/hsearch.c delete mode 100644 main/db1-ast/hash/ndbm.c delete mode 100644 main/db1-ast/hash/page.h delete mode 100644 main/db1-ast/hash/search.h delete mode 100644 main/db1-ast/include/circ-queue.h delete mode 100644 main/db1-ast/include/compat.h delete mode 100644 main/db1-ast/include/db.h delete mode 100644 main/db1-ast/include/mpool.h delete mode 100644 main/db1-ast/include/ndbm.h delete mode 100644 main/db1-ast/libdb.map delete mode 100644 main/db1-ast/mpool/README delete mode 100644 main/db1-ast/mpool/mpool.c delete mode 100644 main/db1-ast/recno/extern.h delete mode 100644 main/db1-ast/recno/rec_close.c delete mode 100644 main/db1-ast/recno/rec_delete.c delete mode 100644 main/db1-ast/recno/rec_get.c delete mode 100644 main/db1-ast/recno/rec_open.c delete mode 100644 main/db1-ast/recno/rec_put.c delete mode 100644 main/db1-ast/recno/rec_search.c delete mode 100644 main/db1-ast/recno/rec_seq.c delete mode 100644 main/db1-ast/recno/rec_utils.c delete mode 100644 main/db1-ast/recno/recno.h create mode 100644 utils/astdb2sqlite3.c create mode 100644 utils/db1-ast/Makefile create mode 100644 utils/db1-ast/btree/bt_close.c create mode 100644 utils/db1-ast/btree/bt_conv.c create mode 100644 utils/db1-ast/btree/bt_debug.c create mode 100644 utils/db1-ast/btree/bt_delete.c create mode 100644 utils/db1-ast/btree/bt_get.c create mode 100644 utils/db1-ast/btree/bt_open.c create mode 100644 utils/db1-ast/btree/bt_overflow.c create mode 100644 utils/db1-ast/btree/bt_page.c create mode 100644 utils/db1-ast/btree/bt_put.c create mode 100644 utils/db1-ast/btree/bt_search.c create mode 100644 utils/db1-ast/btree/bt_seq.c create mode 100644 utils/db1-ast/btree/bt_split.c create mode 100644 utils/db1-ast/btree/bt_utils.c create mode 100644 utils/db1-ast/btree/btree.h create mode 100644 utils/db1-ast/btree/extern.h create mode 100644 utils/db1-ast/db/db.c create mode 100644 utils/db1-ast/hash/README create mode 100644 utils/db1-ast/hash/extern.h create mode 100644 utils/db1-ast/hash/hash.c create mode 100644 utils/db1-ast/hash/hash.h create mode 100644 utils/db1-ast/hash/hash_bigkey.c create mode 100644 utils/db1-ast/hash/hash_buf.c create mode 100644 utils/db1-ast/hash/hash_func.c create mode 100644 utils/db1-ast/hash/hash_log2.c create mode 100644 utils/db1-ast/hash/hash_page.c create mode 100644 utils/db1-ast/hash/hsearch.c create mode 100644 utils/db1-ast/hash/ndbm.c create mode 100644 utils/db1-ast/hash/page.h create mode 100644 utils/db1-ast/hash/search.h create mode 100644 utils/db1-ast/include/circ-queue.h create mode 100644 utils/db1-ast/include/compat.h create mode 100644 utils/db1-ast/include/db.h create mode 100644 utils/db1-ast/include/mpool.h create mode 100644 utils/db1-ast/include/ndbm.h create mode 100644 utils/db1-ast/libdb.map create mode 100644 utils/db1-ast/mpool/README create mode 100644 utils/db1-ast/mpool/mpool.c create mode 100644 utils/db1-ast/recno/extern.h create mode 100644 utils/db1-ast/recno/rec_close.c create mode 100644 utils/db1-ast/recno/rec_delete.c create mode 100644 utils/db1-ast/recno/rec_get.c create mode 100644 utils/db1-ast/recno/rec_open.c create mode 100644 utils/db1-ast/recno/rec_put.c create mode 100644 utils/db1-ast/recno/rec_search.c create mode 100644 utils/db1-ast/recno/rec_seq.c create mode 100644 utils/db1-ast/recno/rec_utils.c create mode 100644 utils/db1-ast/recno/recno.h diff --git a/CHANGES b/CHANGES index 53587b598..7241a7652 100644 --- a/CHANGES +++ b/CHANGES @@ -188,6 +188,14 @@ Applications * Added ability to include '@parkinglot' to ParkedCall extension in order to specify a specific parkinglot on which to search the extension. +Asterisk Database +----------------- + * The internal Asterisk database has been switched from Berkeley DB 1.86 to + SQLite 3. An existing Berkeley astdb file can be converted with the astdb2sqlite3 + utility in the UTILS section of menuselect. If an existing astdb is found and no + astdb.sqlite3 exists, astdb2sqlite3 will be compiled automatically. Asterisk will + convert an existing astdb to the SQLite3 version automatically at runtime. + ------------------------------------------------------------------------------ --- Functionality changes from Asterisk 1.6.2 to Asterisk 1.8 ---------------- ------------------------------------------------------------------------------ diff --git a/Makefile b/Makefile index 0615d60c8..85149c94a 100644 --- a/Makefile +++ b/Makefile @@ -838,6 +838,7 @@ sounds: cleantest: @cmp -s .cleancount .lastclean || $(MAKE) clean + @[ -f "$(DESTDIR)$(ASTDBDIR)/astdb.sqlite3" ] || [ ! -f "$(DESTDIR)$(ASTDBDIR)/astdb" ] || [ ! -f menuselect.makeopts ] || grep -q MENUSELECT_UTILS=.*astdb2sqlite3 menuselect.makeopts || (sed -i.orig -e's/MENUSELECT_UTILS=\(.*\)/MENUSELECT_UTILS=\1 astdb2sqlite3/' menuselect.makeopts && echo "Updating menuselect.makeopts to include astdb2sqlite3" && echo "Original version backed up to menuselect.makeopts.orig") $(SUBDIRS_UNINSTALL): +@$(SUBMAKE) -C $(@:-uninstall=) uninstall diff --git a/UPGRADE.txt b/UPGRADE.txt index dfa85684e..6f111eff0 100644 --- a/UPGRADE.txt +++ b/UPGRADE.txt @@ -54,5 +54,12 @@ Queue: - Mark QUEUE_MEMBER_PENALTY Deprecated it never worked for realtime members - QUEUE_MEMBER is now R/W supporting setting paused, ignorebusy and penalty. + Asterisk Database: + - The internal Asterisk database has been switched from Berkeley DB 1.86 to + SQLite 3. An existing Berkeley astdb file can be converted with the astdb2sqlite3 + utility in the UTILS section of menuselect. If an existing astdb is found and no + astdb.sqlite3 exists, astdb2sqlite3 will be compiled automatically. Asterisk will + convert an existing astdb to the SQLite3 version automatically at runtime. + =========================================================== =========================================================== diff --git a/configure b/configure index f9e46a63d..3abd3cb69 100755 --- a/configure +++ b/configure @@ -1,14 +1,14 @@ #! /bin/sh -# From configure.ac Revision: 320561 . +# From configure.ac Revision: 323321 . # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.65 for asterisk trunk. +# Generated by GNU Autoconf 2.67 for asterisk trunk. # # Report bugs to . # # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, -# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, -# Inc. +# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software +# Foundation, Inc. # # # This configure script is free software; the Free Software Foundation @@ -322,7 +322,7 @@ $as_echo X"$as_dir" | test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" - } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p @@ -362,19 +362,19 @@ else fi # as_fn_arith -# as_fn_error ERROR [LINENO LOG_FD] -# --------------------------------- +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the -# script with status $?, using 1 if that was 0. +# script with STATUS, using 1 if that was 0. as_fn_error () { - as_status=$?; test $as_status -eq 0 && as_status=1 - if test "$3"; then - as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi - $as_echo "$as_me: error: $1" >&2 + $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error @@ -536,7 +536,7 @@ test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. -# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` @@ -1312,8 +1312,9 @@ do fi case $ac_option in - *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; - *) ac_optarg=yes ;; + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. @@ -1358,7 +1359,7 @@ do ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error "invalid feature name: $ac_useropt" + as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in @@ -1384,7 +1385,7 @@ do ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error "invalid feature name: $ac_useropt" + as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in @@ -1588,7 +1589,7 @@ do ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error "invalid package name: $ac_useropt" + as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in @@ -1604,7 +1605,7 @@ do ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error "invalid package name: $ac_useropt" + as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in @@ -1634,8 +1635,8 @@ do | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; - -*) as_fn_error "unrecognized option: \`$ac_option' -Try \`$0 --help' for more information." + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" ;; *=*) @@ -1643,7 +1644,7 @@ Try \`$0 --help' for more information." # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) - as_fn_error "invalid variable name: \`$ac_envvar'" ;; + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; @@ -1661,13 +1662,13 @@ done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` - as_fn_error "missing argument to $ac_option" + as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; - fatal) as_fn_error "unrecognized options: $ac_unrecognized_opts" ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi @@ -1690,7 +1691,7 @@ do [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac - as_fn_error "expected an absolute directory name for --$ac_var: $ac_val" + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' @@ -1704,8 +1705,8 @@ target=$target_alias if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe - $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. - If a cross compiler is detected then cross compile mode will be used." >&2 + $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used" >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi @@ -1720,9 +1721,9 @@ test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || - as_fn_error "working directory cannot be determined" + as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || - as_fn_error "pwd does not report name of working directory" + as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. @@ -1761,11 +1762,11 @@ else fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." - as_fn_error "cannot find sources ($ac_unique_file) in $srcdir" + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( - cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error "$ac_msg" + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then @@ -1805,7 +1806,7 @@ Configuration: --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit - -q, --quiet, --silent do not print \`checking...' messages + -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files @@ -2029,9 +2030,9 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF asterisk configure trunk -generated by GNU Autoconf 2.65 +generated by GNU Autoconf 2.67 -Copyright (C) 2009 Free Software Foundation, Inc. +Copyright (C) 2010 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. @@ -2103,7 +2104,7 @@ $as_echo "$ac_try_echo"; } >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } >/dev/null && { + test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : @@ -2127,10 +2128,10 @@ fi ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : + if eval "test \"\${$3+set}\"" = set; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } -if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$3+set}\"" = set; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 @@ -2166,7 +2167,7 @@ if ac_fn_c_try_cpp "$LINENO"; then : else ac_header_preproc=no fi -rm -f conftest.err conftest.$ac_ext +rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } @@ -2189,17 +2190,15 @@ $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} -( cat <<\_ASBOX -## ------------------------------------------ ## +( $as_echo "## ------------------------------------------ ## ## Report this to https://issues.asterisk.org ## -## ------------------------------------------ ## -_ASBOX +## ------------------------------------------ ##" ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } -if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$3+set}\"" = set; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" @@ -2263,7 +2262,7 @@ ac_fn_c_check_header_compile () as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } -if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$3+set}\"" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -2344,7 +2343,7 @@ $as_echo "$ac_try_echo"; } >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } >/dev/null && { + test $ac_status = 0; } > conftest.i && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.err }; then : @@ -2414,7 +2413,7 @@ ac_fn_c_check_func () as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } -if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$3+set}\"" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -2482,7 +2481,7 @@ ac_fn_c_check_type () as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } -if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$3+set}\"" = set; then : $as_echo_n "(cached) " >&6 else eval "$3=no" @@ -2536,7 +2535,7 @@ ac_fn_c_check_member () as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5 $as_echo_n "checking for $2.$3... " >&6; } -if { as_var=$4; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$4+set}\"" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -2770,10 +2769,10 @@ rm -f conftest.val ac_fn_cxx_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : + if eval "test \"\${$3+set}\"" = set; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } -if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$3+set}\"" = set; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 @@ -2809,7 +2808,7 @@ if ac_fn_cxx_try_cpp "$LINENO"; then : else ac_header_preproc=no fi -rm -f conftest.err conftest.$ac_ext +rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } @@ -2832,17 +2831,15 @@ $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} -( cat <<\_ASBOX -## ------------------------------------------ ## +( $as_echo "## ------------------------------------------ ## ## Report this to https://issues.asterisk.org ## -## ------------------------------------------ ## -_ASBOX +## ------------------------------------------ ##" ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } -if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$3+set}\"" = set; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" @@ -2910,7 +2907,7 @@ ac_fn_cxx_check_header_compile () as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } -if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$3+set}\"" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -2936,7 +2933,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by asterisk $as_me trunk, which was -generated by GNU Autoconf 2.65. Invocation command line was +generated by GNU Autoconf 2.67. Invocation command line was $ $0 $@ @@ -3046,11 +3043,9 @@ trap 'exit_status=$? { echo - cat <<\_ASBOX -## ---------------- ## + $as_echo "## ---------------- ## ## Cache variables. ## -## ---------------- ## -_ASBOX +## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( @@ -3084,11 +3079,9 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; ) echo - cat <<\_ASBOX -## ----------------- ## + $as_echo "## ----------------- ## ## Output variables. ## -## ----------------- ## -_ASBOX +## ----------------- ##" echo for ac_var in $ac_subst_vars do @@ -3101,11 +3094,9 @@ _ASBOX echo if test -n "$ac_subst_files"; then - cat <<\_ASBOX -## ------------------- ## + $as_echo "## ------------------- ## ## File substitutions. ## -## ------------------- ## -_ASBOX +## ------------------- ##" echo for ac_var in $ac_subst_files do @@ -3119,11 +3110,9 @@ _ASBOX fi if test -s confdefs.h; then - cat <<\_ASBOX -## ----------- ## + $as_echo "## ----------- ## ## confdefs.h. ## -## ----------- ## -_ASBOX +## ----------- ##" echo cat confdefs.h echo @@ -3178,7 +3167,12 @@ _ACEOF ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then - ac_site_file1=$CONFIG_SITE + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site @@ -3193,7 +3187,11 @@ do { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 - . "$ac_site_file" + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5 ; } fi done @@ -3273,7 +3271,7 @@ if $ac_cache_corrupted; then $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} - as_fn_error "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## @@ -3290,16 +3288,22 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu # cross-compile macros ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do - for ac_t in install-sh install.sh shtool; do - if test -f "$ac_dir/$ac_t"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/$ac_t -c" - break 2 - fi - done + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi done if test -z "$ac_aux_dir"; then - as_fn_error "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 + as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 fi # These three variables are undocumented and unsupported, @@ -3313,7 +3317,7 @@ ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || - as_fn_error "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 + as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 $as_echo_n "checking build system type... " >&6; } @@ -3324,16 +3328,16 @@ else test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` test "x$ac_build_alias" = x && - as_fn_error "cannot guess build type; you must specify one" "$LINENO" 5 + as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || - as_fn_error "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 $as_echo "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; -*) as_fn_error "invalid value of canonical build" "$LINENO" 5;; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5 ;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' @@ -3358,7 +3362,7 @@ else ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || - as_fn_error "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 fi fi @@ -3366,7 +3370,7 @@ fi $as_echo "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; -*) as_fn_error "invalid value of canonical host" "$LINENO" 5;; +*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5 ;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' @@ -3388,16 +3392,22 @@ case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac ac_aux_dir= for ac_dir in `pwd` "$srcdir"/`pwd`; do - for ac_t in install-sh install.sh shtool; do - if test -f "$ac_dir/$ac_t"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/$ac_t -c" - break 2 - fi - done + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi done if test -z "$ac_aux_dir"; then - as_fn_error "cannot find install-sh, install.sh, or shtool in \`pwd\` \"$srcdir\"/\`pwd\`" "$LINENO" 5 + as_fn_error $? "cannot find install-sh, install.sh, or shtool in \`pwd\` \"$srcdir\"/\`pwd\`" "$LINENO" 5 fi # These three variables are undocumented and unsupported, @@ -3539,8 +3549,8 @@ fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error "no acceptable C compiler found in \$PATH -See \`config.log' for more details." "$LINENO" 5; } +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5 ; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 @@ -3654,9 +3664,8 @@ sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -{ as_fn_set_status 77 -as_fn_error "C compiler cannot create executables -See \`config.log' for more details." "$LINENO" 5; }; } +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5 ; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } @@ -3698,8 +3707,8 @@ done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error "cannot compute suffix of executables: cannot compile and link -See \`config.log' for more details." "$LINENO" 5; } +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5 ; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 @@ -3756,9 +3765,9 @@ $as_echo "$ac_try_echo"; } >&5 else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error "cannot run C compiled programs. +as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. -See \`config.log' for more details." "$LINENO" 5; } +See \`config.log' for more details" "$LINENO" 5 ; } fi fi fi @@ -3809,8 +3818,8 @@ sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error "cannot compute suffix of object files: cannot compile -See \`config.log' for more details." "$LINENO" 5; } +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5 ; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi @@ -4074,7 +4083,7 @@ else # Broken: fails on valid input. continue fi -rm -f conftest.err conftest.$ac_ext +rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. @@ -4090,11 +4099,11 @@ else ac_preproc_ok=: break fi -rm -f conftest.err conftest.$ac_ext +rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.err conftest.$ac_ext +rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi @@ -4133,7 +4142,7 @@ else # Broken: fails on valid input. continue fi -rm -f conftest.err conftest.$ac_ext +rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. @@ -4149,18 +4158,18 @@ else ac_preproc_ok=: break fi -rm -f conftest.err conftest.$ac_ext +rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.err conftest.$ac_ext +rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error "C preprocessor \"$CPP\" fails sanity check -See \`config.log' for more details." "$LINENO" 5; } +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5 ; } fi ac_ext=c @@ -4221,7 +4230,7 @@ esac done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then - as_fn_error "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP @@ -4287,7 +4296,7 @@ esac done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then - as_fn_error "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP @@ -4419,8 +4428,7 @@ do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " -eval as_val=\$$as_ac_Header - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF @@ -5423,7 +5431,7 @@ else # Broken: fails on valid input. continue fi -rm -f conftest.err conftest.$ac_ext +rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. @@ -5439,11 +5447,11 @@ else ac_preproc_ok=: break fi -rm -f conftest.err conftest.$ac_ext +rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.err conftest.$ac_ext +rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi @@ -5482,7 +5490,7 @@ else # Broken: fails on valid input. continue fi -rm -f conftest.err conftest.$ac_ext +rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. @@ -5498,18 +5506,18 @@ else ac_preproc_ok=: break fi -rm -f conftest.err conftest.$ac_ext +rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.err conftest.$ac_ext +rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error "C preprocessor \"$CPP\" fails sanity check -See \`config.log' for more details." "$LINENO" 5; } +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5 ; } fi ac_ext=c @@ -5556,7 +5564,7 @@ else # Broken: fails on valid input. continue fi -rm -f conftest.err conftest.$ac_ext +rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. @@ -5572,11 +5580,11 @@ else ac_preproc_ok=: break fi -rm -f conftest.err conftest.$ac_ext +rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.err conftest.$ac_ext +rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi @@ -5615,7 +5623,7 @@ else # Broken: fails on valid input. continue fi -rm -f conftest.err conftest.$ac_ext +rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. @@ -5631,18 +5639,18 @@ else ac_preproc_ok=: break fi -rm -f conftest.err conftest.$ac_ext +rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.err conftest.$ac_ext +rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error "C++ preprocessor \"$CXXCPP\" fails sanity check -See \`config.log' for more details." "$LINENO" 5; } +as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5 ; } fi ac_ext=c @@ -5710,7 +5718,7 @@ esac done IFS=$as_save_IFS if test -z "$ac_cv_path_SED"; then - as_fn_error "no acceptable sed could be found in \$PATH" "$LINENO" 5 + as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 fi else ac_cv_path_SED=$SED @@ -5821,7 +5829,7 @@ else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi -test -z "$LD" && as_fn_error "no acceptable ld found in \$PATH" "$LINENO" 5 +test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } if test "${lt_cv_prog_gnu_ld+set}" = set; then : @@ -6102,7 +6110,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_GNU_MAKE" >&5 $as_echo "$ac_cv_GNU_MAKE" >&6; } ; if test "x$ac_cv_GNU_MAKE" = "xNot Found" ; then - as_fn_error "*** Please install GNU make. It is required to build Asterisk!" "$LINENO" 5 + as_fn_error $? "*** Please install GNU make. It is required to build Asterisk!" "$LINENO" 5 exit 1 fi GNU_MAKE=$ac_cv_GNU_MAKE @@ -6162,7 +6170,7 @@ esac done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then - as_fn_error "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP @@ -7931,7 +7939,7 @@ if test "${enable_dev_mode+set}" = set; then : AST_DEVMODE=yes NOISY_BUILD=yes ;; - *) as_fn_error "bad value ${enableval} for --enable-dev-mode" "$LINENO" 5 ;; + *) as_fn_error $? "bad value ${enableval} for --enable-dev-mode" "$LINENO" 5 ;; esac fi @@ -7944,7 +7952,7 @@ if test "${enable_coverage+set}" = set; then : enableval=$enable_coverage; case "${enableval}" in y|ye|yes) AST_CODE_COVERAGE=yes ;; n|no) AST_CODE_COVERAGE=no ;; - *) as_fn_error "bad value ${enableval} for --enable-coverage" "$LINENO" 5 ;; + *) as_fn_error $? "bad value ${enableval} for --enable-coverage" "$LINENO" 5 ;; esac fi @@ -11092,8 +11100,7 @@ if test $ac_cv_os_cray = yes; then for ac_func in _getb67 GETB67 getb67; do as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" -eval as_val=\$$as_ac_var - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define CRAY_STACKSEG_END $ac_func @@ -11160,7 +11167,7 @@ for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do as_ac_Header=`$as_echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_hdr that defines DIR" >&5 $as_echo_n "checking for $ac_hdr that defines DIR... " >&6; } -if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Header+set}\"" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -11187,8 +11194,7 @@ fi eval ac_res=\$$as_ac_Header { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Header - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_hdr" | $as_tr_cpp` 1 _ACEOF @@ -11471,8 +11477,7 @@ for ac_header in arpa/inet.h fcntl.h inttypes.h libintl.h limits.h locale.h mall do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" -eval as_val=\$$as_ac_Header - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF @@ -11500,8 +11505,7 @@ for ac_header in winsock.h winsock2.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" -eval as_val=\$$as_ac_Header - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF @@ -12395,8 +12399,7 @@ for ac_func in fork vfork do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" -eval as_val=\$$as_ac_var - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF @@ -12779,8 +12782,7 @@ do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " -eval as_val=\$$as_ac_Header - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF @@ -12977,8 +12979,7 @@ for ac_header in sys/select.h sys/socket.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" -eval as_val=\$$as_ac_Header - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF @@ -13532,8 +13533,7 @@ for ac_func in asprintf atexit closefrom dup2 eaccess endpwent euidaccess ffsll do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" -eval as_val=\$$as_ac_var - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF @@ -13594,8 +13594,7 @@ for ac_func in exp2 log2 exp10 log10 sin cos tan asin acos atan atan2 pow rint e do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" -eval as_val=\$$as_ac_var - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF @@ -13611,8 +13610,7 @@ if test "x${ac_cv_type_long_double_wider}" = "xyes" ; then do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" -eval as_val=\$$as_ac_var - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF @@ -13727,7 +13725,7 @@ if test "${enable_internal_poll+set}" = set; then : enableval=$enable_internal_poll; case "${enableval}" in y|ye|yes) HAS_POLL="";; n|no) HAS_POLL="${HAS_POLL}" ;; - *) as_fn_error "bad value ${enableval} for --enable-internal-poll" "$LINENO" 5 ;; + *) as_fn_error $? "bad value ${enableval} for --enable-internal-poll" "$LINENO" 5 ;; esac fi @@ -13741,8 +13739,7 @@ for ac_func in funopen fopencookie do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" -eval as_val=\$$as_ac_var - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF @@ -13978,7 +13975,7 @@ if test "${ac_cv_file__dev_urandom+set}" = set; then : $as_echo_n "(cached) " >&6 else test "$cross_compiling" = yes && - as_fn_error "cannot check for file existence when cross compiling" "$LINENO" 5 + as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 if test -r "/dev/urandom"; then ac_cv_file__dev_urandom=yes else @@ -14516,8 +14513,8 @@ if test "${ac_cv_have_variable_fdset}x" = "0x"; then if test "$cross_compiling" = yes; then : { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error "cannot run test program while cross compiling -See \`config.log' for more details." "$LINENO" 5; } +as_fn_error $? "cannot run test program while cross compiling +See \`config.log' for more details" "$LINENO" 5 ; } else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -15818,9 +15815,8 @@ else if test "$ac_cv_type_int" = yes; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -{ as_fn_set_status 77 -as_fn_error "cannot compute sizeof (int) -See \`config.log' for more details." "$LINENO" 5; }; } +as_fn_error 77 "cannot compute sizeof (int) +See \`config.log' for more details" "$LINENO" 5 ; } else ac_cv_sizeof_int=0 fi @@ -15852,9 +15848,8 @@ else if test "$ac_cv_type_long" = yes; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -{ as_fn_set_status 77 -as_fn_error "cannot compute sizeof (long) -See \`config.log' for more details." "$LINENO" 5; }; } +as_fn_error 77 "cannot compute sizeof (long) +See \`config.log' for more details" "$LINENO" 5 ; } else ac_cv_sizeof_long=0 fi @@ -15886,9 +15881,8 @@ else if test "$ac_cv_type_long_long" = yes; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -{ as_fn_set_status 77 -as_fn_error "cannot compute sizeof (long long) -See \`config.log' for more details." "$LINENO" 5; }; } +as_fn_error 77 "cannot compute sizeof (long long) +See \`config.log' for more details" "$LINENO" 5 ; } else ac_cv_sizeof_long_long=0 fi @@ -15920,9 +15914,8 @@ else if test "$ac_cv_type_char_p" = yes; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -{ as_fn_set_status 77 -as_fn_error "cannot compute sizeof (char *) -See \`config.log' for more details." "$LINENO" 5; }; } +as_fn_error 77 "cannot compute sizeof (char *) +See \`config.log' for more details" "$LINENO" 5 ; } else ac_cv_sizeof_char_p=0 fi @@ -15954,9 +15947,8 @@ else if test "$ac_cv_type_long" = yes; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -{ as_fn_set_status 77 -as_fn_error "cannot compute sizeof (long) -See \`config.log' for more details." "$LINENO" 5; }; } +as_fn_error 77 "cannot compute sizeof (long) +See \`config.log' for more details" "$LINENO" 5 ; } else ac_cv_sizeof_long=0 fi @@ -15988,9 +15980,8 @@ else if test "$ac_cv_type_long_long" = yes; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -{ as_fn_set_status 77 -as_fn_error "cannot compute sizeof (long long) -See \`config.log' for more details." "$LINENO" 5; }; } +as_fn_error 77 "cannot compute sizeof (long long) +See \`config.log' for more details" "$LINENO" 5 ; } else ac_cv_sizeof_long_long=0 fi @@ -16029,9 +16020,8 @@ else if test "$ac_cv_type_fd_set_fds_bits" = yes; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -{ as_fn_set_status 77 -as_fn_error "cannot compute sizeof (fd_set.fds_bits) -See \`config.log' for more details." "$LINENO" 5; }; } +as_fn_error 77 "cannot compute sizeof (fd_set.fds_bits) +See \`config.log' for more details" "$LINENO" 5 ; } else ac_cv_sizeof_fd_set_fds_bits=0 fi @@ -16218,7 +16208,7 @@ if test "x${PBX_ALSA}" != "x1" -a "${USE_ALSA}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_asound_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lasound" >&5 $as_echo_n "checking for ${pbxfuncname} in -lasound... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -16253,8 +16243,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_ALSA_FOUND=yes else AST_ALSA_FOUND=no @@ -16324,7 +16313,7 @@ if test "x${PBX_BFD}" != "x1" -a "${USE_BFD}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_bfd_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lbfd" >&5 $as_echo_n "checking for ${pbxfuncname} in -lbfd... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -16359,8 +16348,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_BFD_FOUND=yes else AST_BFD_FOUND=no @@ -16430,7 +16418,7 @@ if test "x${PBX_CURSES}" != "x1" -a "${USE_CURSES}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_curses_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lcurses" >&5 $as_echo_n "checking for ${pbxfuncname} in -lcurses... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -16465,8 +16453,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_CURSES_FOUND=yes else AST_CURSES_FOUND=no @@ -16537,7 +16524,7 @@ if test "x${PBX_CAP}" != "x1" -a "${USE_CAP}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_cap_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lcap" >&5 $as_echo_n "checking for ${pbxfuncname} in -lcap... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -16572,8 +16559,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_CAP_FOUND=yes else AST_CAP_FOUND=no @@ -17065,8 +17051,7 @@ fi if test "x${GSM_DIR}" != "x" ; then as_ac_Header=`$as_echo "ac_cv_header_${GSM_DIR}/include/gsm.h" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "${GSM_DIR}/include/gsm.h" "$as_ac_Header" "$ac_includes_default" -eval as_val=\$$as_ac_Header - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : GSM_HEADER_FOUND=1 else GSM_HEADER_FOUND=0 @@ -17075,8 +17060,7 @@ fi as_ac_Header=`$as_echo "ac_cv_header_${GSM_DIR}/include/gsm/gsm.h" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "${GSM_DIR}/include/gsm/gsm.h" "$as_ac_Header" "$ac_includes_default" -eval as_val=\$$as_ac_Header - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : GSM_GSM_HEADER_FOUND=1 else GSM_GSM_HEADER_FOUND=0 @@ -17175,7 +17159,7 @@ if test "x${PBX_ICONV}" != "x1" -a "${USE_ICONV}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_iconv_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -liconv" >&5 $as_echo_n "checking for ${pbxfuncname} in -liconv... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -17210,8 +17194,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_ICONV_FOUND=yes else AST_ICONV_FOUND=no @@ -17281,7 +17264,7 @@ if test "x${PBX_ICONV}" != "x1" -a "${USE_ICONV}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_iconv_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -liconv" >&5 $as_echo_n "checking for ${pbxfuncname} in -liconv... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -17316,8 +17299,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_ICONV_FOUND=yes else AST_ICONV_FOUND=no @@ -17387,7 +17369,7 @@ if test "x${PBX_ICONV}" != "x1" -a "${USE_ICONV}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_c_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lc" >&5 $as_echo_n "checking for ${pbxfuncname} in -lc... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -17422,8 +17404,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_ICONV_FOUND=yes else AST_ICONV_FOUND=no @@ -17494,7 +17475,7 @@ if test "x${PBX_ICAL}" != "x1" -a "${USE_ICAL}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_ical_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lical" >&5 $as_echo_n "checking for ${pbxfuncname} in -lical... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -17529,8 +17510,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_ICAL_FOUND=yes else AST_ICAL_FOUND=no @@ -17600,7 +17580,7 @@ if test "x${PBX_IKSEMEL}" != "x1" -a "${USE_IKSEMEL}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_iksemel_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -liksemel" >&5 $as_echo_n "checking for ${pbxfuncname} in -liksemel... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -17635,8 +17615,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_IKSEMEL_FOUND=yes else AST_IKSEMEL_FOUND=no @@ -18334,7 +18313,7 @@ if test "x${PBX_IODBC}" != "x1" -a "${USE_IODBC}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_iodbc_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -liodbc" >&5 $as_echo_n "checking for ${pbxfuncname} in -liodbc... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -18369,8 +18348,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_IODBC_FOUND=yes else AST_IODBC_FOUND=no @@ -18440,7 +18418,7 @@ if test "x${PBX_INOTIFY}" != "x1" -a "${USE_INOTIFY}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_c_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lc" >&5 $as_echo_n "checking for ${pbxfuncname} in -lc... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -18475,8 +18453,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_INOTIFY_FOUND=yes else AST_INOTIFY_FOUND=no @@ -18546,7 +18523,7 @@ if test "x${PBX_JACK}" != "x1" -a "${USE_JACK}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_jack_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -ljack" >&5 $as_echo_n "checking for ${pbxfuncname} in -ljack... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -18581,8 +18558,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_JACK_FOUND=yes else AST_JACK_FOUND=no @@ -18653,7 +18629,7 @@ if test "x${PBX_KQUEUE}" != "x1" -a "${USE_KQUEUE}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_c_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lc" >&5 $as_echo_n "checking for ${pbxfuncname} in -lc... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -18688,8 +18664,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_KQUEUE_FOUND=yes else AST_KQUEUE_FOUND=no @@ -18773,7 +18748,7 @@ if test "x${PBX_LTDL}" != "x1" -a "${USE_LTDL}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_ltdl_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lltdl" >&5 $as_echo_n "checking for ${pbxfuncname} in -lltdl... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -18808,8 +18783,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_LTDL_FOUND=yes else AST_LTDL_FOUND=no @@ -18879,7 +18853,7 @@ if test "x${PBX_LDAP}" != "x1" -a "${USE_LDAP}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_ldap_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lldap" >&5 $as_echo_n "checking for ${pbxfuncname} in -lldap... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -18914,8 +18888,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_LDAP_FOUND=yes else AST_LDAP_FOUND=no @@ -18970,7 +18943,7 @@ if test "${enable_xmldoc+set}" = set; then : enableval=$enable_xmldoc; case "${enableval}" in y|ye|yes) disable_xmldoc=no ;; n|no) disable_xmldoc=yes ;; - *) as_fn_error "bad value ${enableval} for --disable-xmldoc" "$LINENO" 5 ;; + *) as_fn_error $? "bad value ${enableval} for --disable-xmldoc" "$LINENO" 5 ;; esac else disable_xmldoc=no @@ -19161,7 +19134,7 @@ if test "x${PBX_MISDN}" != "x1" -a "${USE_MISDN}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_mISDN_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lmISDN" >&5 $as_echo_n "checking for ${pbxfuncname} in -lmISDN... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -19196,8 +19169,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_MISDN_FOUND=yes else AST_MISDN_FOUND=no @@ -19268,7 +19240,7 @@ if test "x${PBX_ISDNNET}" != "x1" -a "${USE_ISDNNET}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_isdnnet_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lisdnnet" >&5 $as_echo_n "checking for ${pbxfuncname} in -lisdnnet... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -19303,8 +19275,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_ISDNNET_FOUND=yes else AST_ISDNNET_FOUND=no @@ -19373,7 +19344,7 @@ if test "x${PBX_SUPPSERV}" != "x1" -a "${USE_SUPPSERV}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_suppserv_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lsuppserv" >&5 $as_echo_n "checking for ${pbxfuncname} in -lsuppserv... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -19408,8 +19379,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_SUPPSERV_FOUND=yes else AST_SUPPSERV_FOUND=no @@ -19741,7 +19711,7 @@ if test "x${PBX_NBS}" != "x1" -a "${USE_NBS}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_nbs_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lnbs" >&5 $as_echo_n "checking for ${pbxfuncname} in -lnbs... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -19776,8 +19746,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_NBS_FOUND=yes else AST_NBS_FOUND=no @@ -19847,7 +19816,7 @@ if test "x${PBX_NCURSES}" != "x1" -a "${USE_NCURSES}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_ncurses_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lncurses" >&5 $as_echo_n "checking for ${pbxfuncname} in -lncurses... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -19882,8 +19851,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_NCURSES_FOUND=yes else AST_NCURSES_FOUND=no @@ -20412,7 +20380,7 @@ if test "x${PBX_NEWT}" != "x1" -a "${USE_NEWT}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_newt_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lnewt" >&5 $as_echo_n "checking for ${pbxfuncname} in -lnewt... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -20447,8 +20415,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_NEWT_FOUND=yes else AST_NEWT_FOUND=no @@ -20518,7 +20485,7 @@ if test "x${PBX_UNIXODBC}" != "x1" -a "${USE_UNIXODBC}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_odbc_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lodbc" >&5 $as_echo_n "checking for ${pbxfuncname} in -lodbc... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -20553,8 +20520,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_UNIXODBC_FOUND=yes else AST_UNIXODBC_FOUND=no @@ -20624,7 +20590,7 @@ if test "x${PBX_OGG}" != "x1" -a "${USE_OGG}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_ogg_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -logg" >&5 $as_echo_n "checking for ${pbxfuncname} in -logg... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -20659,8 +20625,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_OGG_FOUND=yes else AST_OGG_FOUND=no @@ -20731,7 +20696,7 @@ if test "x${PBX_BKTR}" != "x1" -a "${USE_BKTR}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_execinfo_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lexecinfo" >&5 $as_echo_n "checking for ${pbxfuncname} in -lexecinfo... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -20766,8 +20731,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_BKTR_FOUND=yes else AST_BKTR_FOUND=no @@ -20837,7 +20801,7 @@ if test "x${PBX_BKTR}" != "x1" -a "${USE_BKTR}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_c_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lc" >&5 $as_echo_n "checking for ${pbxfuncname} in -lc... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -20872,8 +20836,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_BKTR_FOUND=yes else AST_BKTR_FOUND=no @@ -20943,7 +20906,7 @@ if test "x${PBX_BLUETOOTH}" != "x1" -a "${USE_BLUETOOTH}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_bluetooth_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lbluetooth" >&5 $as_echo_n "checking for ${pbxfuncname} in -lbluetooth... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -20978,8 +20941,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_BLUETOOTH_FOUND=yes else AST_BLUETOOTH_FOUND=no @@ -21050,7 +21012,7 @@ if test "x${PBX_OSS}" != "x1" -a "${USE_OSS}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_ossaudio_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lossaudio" >&5 $as_echo_n "checking for ${pbxfuncname} in -lossaudio... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -21085,8 +21047,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_OSS_FOUND=yes else AST_OSS_FOUND=no @@ -21155,7 +21116,7 @@ if test "x${PBX_OSS}" != "x1" -a "${USE_OSS}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_ossaudio_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lossaudio" >&5 $as_echo_n "checking for ${pbxfuncname} in -lossaudio... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -21190,8 +21151,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_OSS_FOUND=yes else AST_OSS_FOUND=no @@ -21260,7 +21220,7 @@ if test "x${PBX_OSS}" != "x1" -a "${USE_OSS}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_ossaudio_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lossaudio" >&5 $as_echo_n "checking for ${pbxfuncname} in -lossaudio... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -21295,8 +21255,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_OSS_FOUND=yes else AST_OSS_FOUND=no @@ -21695,7 +21654,7 @@ if test "x${PBX_POPT}" != "x1" -a "${USE_POPT}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_popt_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lpopt" >&5 $as_echo_n "checking for ${pbxfuncname} in -lpopt... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -21730,8 +21689,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_POPT_FOUND=yes else AST_POPT_FOUND=no @@ -21801,7 +21759,7 @@ if test "x${PBX_PORTAUDIO}" != "x1" -a "${USE_PORTAUDIO}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_portaudio_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lportaudio" >&5 $as_echo_n "checking for ${pbxfuncname} in -lportaudio... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -21836,8 +21794,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_PORTAUDIO_FOUND=yes else AST_PORTAUDIO_FOUND=no @@ -21907,7 +21864,7 @@ if test "x${PBX_PRI}" != "x1" -a "${USE_PRI}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_pri_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lpri" >&5 $as_echo_n "checking for ${pbxfuncname} in -lpri... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -21942,8 +21899,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_PRI_FOUND=yes else AST_PRI_FOUND=no @@ -22012,7 +21968,7 @@ if test "x${PBX_PRI_DATETIME_SEND}" != "x1" -a "${USE_PRI_DATETIME_SEND}" != "no as_ac_Lib=`$as_echo "ac_cv_lib_pri_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lpri" >&5 $as_echo_n "checking for ${pbxfuncname} in -lpri... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -22047,8 +22003,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_PRI_DATETIME_SEND_FOUND=yes else AST_PRI_DATETIME_SEND_FOUND=no @@ -22117,7 +22072,7 @@ if test "x${PBX_PRI_MWI_V2}" != "x1" -a "${USE_PRI_MWI_V2}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_pri_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lpri" >&5 $as_echo_n "checking for ${pbxfuncname} in -lpri... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -22152,8 +22107,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_PRI_MWI_V2_FOUND=yes else AST_PRI_MWI_V2_FOUND=no @@ -22222,7 +22176,7 @@ if test "x${PBX_PRI_DISPLAY_TEXT}" != "x1" -a "${USE_PRI_DISPLAY_TEXT}" != "no"; as_ac_Lib=`$as_echo "ac_cv_lib_pri_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lpri" >&5 $as_echo_n "checking for ${pbxfuncname} in -lpri... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -22257,8 +22211,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_PRI_DISPLAY_TEXT_FOUND=yes else AST_PRI_DISPLAY_TEXT_FOUND=no @@ -22327,7 +22280,7 @@ if test "x${PBX_PRI_MWI}" != "x1" -a "${USE_PRI_MWI}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_pri_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lpri" >&5 $as_echo_n "checking for ${pbxfuncname} in -lpri... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -22362,8 +22315,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_PRI_MWI_FOUND=yes else AST_PRI_MWI_FOUND=no @@ -22432,7 +22384,7 @@ if test "x${PBX_PRI_MCID}" != "x1" -a "${USE_PRI_MCID}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_pri_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lpri" >&5 $as_echo_n "checking for ${pbxfuncname} in -lpri... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -22467,8 +22419,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_PRI_MCID_FOUND=yes else AST_PRI_MCID_FOUND=no @@ -22537,7 +22488,7 @@ if test "x${PBX_PRI_CALL_WAITING}" != "x1" -a "${USE_PRI_CALL_WAITING}" != "no"; as_ac_Lib=`$as_echo "ac_cv_lib_pri_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lpri" >&5 $as_echo_n "checking for ${pbxfuncname} in -lpri... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -22572,8 +22523,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_PRI_CALL_WAITING_FOUND=yes else AST_PRI_CALL_WAITING_FOUND=no @@ -22642,7 +22592,7 @@ if test "x${PBX_PRI_AOC_EVENTS}" != "x1" -a "${USE_PRI_AOC_EVENTS}" != "no"; the as_ac_Lib=`$as_echo "ac_cv_lib_pri_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lpri" >&5 $as_echo_n "checking for ${pbxfuncname} in -lpri... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -22677,8 +22627,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_PRI_AOC_EVENTS_FOUND=yes else AST_PRI_AOC_EVENTS_FOUND=no @@ -22747,7 +22696,7 @@ if test "x${PBX_PRI_TRANSFER}" != "x1" -a "${USE_PRI_TRANSFER}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_pri_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lpri" >&5 $as_echo_n "checking for ${pbxfuncname} in -lpri... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -22782,8 +22731,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_PRI_TRANSFER_FOUND=yes else AST_PRI_TRANSFER_FOUND=no @@ -22852,7 +22800,7 @@ if test "x${PBX_PRI_CCSS}" != "x1" -a "${USE_PRI_CCSS}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_pri_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lpri" >&5 $as_echo_n "checking for ${pbxfuncname} in -lpri... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -22887,8 +22835,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_PRI_CCSS_FOUND=yes else AST_PRI_CCSS_FOUND=no @@ -22957,7 +22904,7 @@ if test "x${PBX_PRI_HANGUP_FIX}" != "x1" -a "${USE_PRI_HANGUP_FIX}" != "no"; the as_ac_Lib=`$as_echo "ac_cv_lib_pri_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lpri" >&5 $as_echo_n "checking for ${pbxfuncname} in -lpri... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -22992,8 +22939,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_PRI_HANGUP_FIX_FOUND=yes else AST_PRI_HANGUP_FIX_FOUND=no @@ -23062,7 +23008,7 @@ if test "x${PBX_PRI_SUBADDR}" != "x1" -a "${USE_PRI_SUBADDR}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_pri_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lpri" >&5 $as_echo_n "checking for ${pbxfuncname} in -lpri... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -23097,8 +23043,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_PRI_SUBADDR_FOUND=yes else AST_PRI_SUBADDR_FOUND=no @@ -23167,7 +23112,7 @@ if test "x${PBX_PRI_CALL_HOLD}" != "x1" -a "${USE_PRI_CALL_HOLD}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_pri_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lpri" >&5 $as_echo_n "checking for ${pbxfuncname} in -lpri... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -23202,8 +23147,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_PRI_CALL_HOLD_FOUND=yes else AST_PRI_CALL_HOLD_FOUND=no @@ -23272,7 +23216,7 @@ if test "x${PBX_PRI_CALL_REROUTING}" != "x1" -a "${USE_PRI_CALL_REROUTING}" != " as_ac_Lib=`$as_echo "ac_cv_lib_pri_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lpri" >&5 $as_echo_n "checking for ${pbxfuncname} in -lpri... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -23307,8 +23251,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_PRI_CALL_REROUTING_FOUND=yes else AST_PRI_CALL_REROUTING_FOUND=no @@ -23377,7 +23320,7 @@ if test "x${PBX_PRI_SETUP_KEYPAD}" != "x1" -a "${USE_PRI_SETUP_KEYPAD}" != "no"; as_ac_Lib=`$as_echo "ac_cv_lib_pri_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lpri" >&5 $as_echo_n "checking for ${pbxfuncname} in -lpri... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -23412,8 +23355,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_PRI_SETUP_KEYPAD_FOUND=yes else AST_PRI_SETUP_KEYPAD_FOUND=no @@ -23486,7 +23428,7 @@ if test "x${PBX_PRI_PROG_W_CAUSE}" != "x1" -a "${USE_PRI_PROG_W_CAUSE}" != "no"; as_ac_Lib=`$as_echo "ac_cv_lib_pri_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lpri" >&5 $as_echo_n "checking for ${pbxfuncname} in -lpri... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -23521,8 +23463,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_PRI_PROG_W_CAUSE_FOUND=yes else AST_PRI_PROG_W_CAUSE_FOUND=no @@ -23591,7 +23532,7 @@ if test "x${PBX_PRI_INBANDDISCONNECT}" != "x1" -a "${USE_PRI_INBANDDISCONNECT}" as_ac_Lib=`$as_echo "ac_cv_lib_pri_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lpri" >&5 $as_echo_n "checking for ${pbxfuncname} in -lpri... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -23626,8 +23567,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_PRI_INBANDDISCONNECT_FOUND=yes else AST_PRI_INBANDDISCONNECT_FOUND=no @@ -23696,7 +23636,7 @@ if test "x${PBX_PRI_SERVICE_MESSAGES}" != "x1" -a "${USE_PRI_SERVICE_MESSAGES}" as_ac_Lib=`$as_echo "ac_cv_lib_pri_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lpri" >&5 $as_echo_n "checking for ${pbxfuncname} in -lpri... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -23731,8 +23671,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_PRI_SERVICE_MESSAGES_FOUND=yes else AST_PRI_SERVICE_MESSAGES_FOUND=no @@ -23801,7 +23740,7 @@ if test "x${PBX_PRI_REVERSE_CHARGE}" != "x1" -a "${USE_PRI_REVERSE_CHARGE}" != " as_ac_Lib=`$as_echo "ac_cv_lib_pri_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lpri" >&5 $as_echo_n "checking for ${pbxfuncname} in -lpri... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -23836,8 +23775,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_PRI_REVERSE_CHARGE_FOUND=yes else AST_PRI_REVERSE_CHARGE_FOUND=no @@ -23908,7 +23846,7 @@ if test "x${PBX_RESAMPLE}" != "x1" -a "${USE_RESAMPLE}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_resample_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lresample" >&5 $as_echo_n "checking for ${pbxfuncname} in -lresample... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -23943,8 +23881,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_RESAMPLE_FOUND=yes else AST_RESAMPLE_FOUND=no @@ -24076,7 +24013,7 @@ if test "x${PBX_SPANDSP}" != "x1" -a "${USE_SPANDSP}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_spandsp_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lspandsp" >&5 $as_echo_n "checking for ${pbxfuncname} in -lspandsp... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -24111,8 +24048,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_SPANDSP_FOUND=yes else AST_SPANDSP_FOUND=no @@ -24186,7 +24122,7 @@ if test "x${PBX_SPANDSP}" != "x1" -a "${USE_SPANDSP}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_spandsp_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lspandsp" >&5 $as_echo_n "checking for ${pbxfuncname} in -lspandsp... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -24221,8 +24157,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_SPANDSP_FOUND=yes else AST_SPANDSP_FOUND=no @@ -24293,7 +24228,7 @@ if test "x${PBX_SS7}" != "x1" -a "${USE_SS7}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_ss7_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lss7" >&5 $as_echo_n "checking for ${pbxfuncname} in -lss7... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -24328,8 +24263,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_SS7_FOUND=yes else AST_SS7_FOUND=no @@ -24399,7 +24333,7 @@ if test "x${PBX_OPENR2}" != "x1" -a "${USE_OPENR2}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_openr2_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lopenr2" >&5 $as_echo_n "checking for ${pbxfuncname} in -lopenr2... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -24434,8 +24368,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_OPENR2_FOUND=yes else AST_OPENR2_FOUND=no @@ -24503,8 +24436,7 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu if test "${PWLIBDIR:-unset}" != "unset" ; then as_ac_Header=`$as_echo "ac_cv_header_${PWLIBDIR}/version.h" | $as_tr_sh` ac_fn_cxx_check_header_mongrel "$LINENO" "${PWLIBDIR}/version.h" "$as_ac_Header" "$ac_includes_default" -eval as_val=\$$as_ac_Header - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : HAS_PWLIB=1 fi @@ -24514,8 +24446,7 @@ if test "${HAS_PWLIB:-unset}" = "unset" ; then if test "${OPENH323DIR:-unset}" != "unset"; then as_ac_Header=`$as_echo "ac_cv_header_${OPENH323DIR}/../pwlib/version.h" | $as_tr_sh` ac_fn_cxx_check_header_mongrel "$LINENO" "${OPENH323DIR}/../pwlib/version.h" "$as_ac_Header" "$ac_includes_default" -eval as_val=\$$as_ac_Header - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : HAS_PWLIB=1 fi @@ -24526,8 +24457,7 @@ fi else as_ac_Header=`$as_echo "ac_cv_header_${HOME}/pwlib/include/ptlib.h" | $as_tr_sh` ac_fn_cxx_check_header_mongrel "$LINENO" "${HOME}/pwlib/include/ptlib.h" "$as_ac_Header" "$ac_includes_default" -eval as_val=\$$as_ac_Header - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : HAS_PWLIB=1 fi @@ -24939,8 +24869,7 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu if test "${OPENH323DIR:-unset}" != "unset" ; then as_ac_Header=`$as_echo "ac_cv_header_${OPENH323DIR}/version.h" | $as_tr_sh` ac_fn_cxx_check_header_mongrel "$LINENO" "${OPENH323DIR}/version.h" "$as_ac_Header" "$ac_includes_default" -eval as_val=\$$as_ac_Header - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : HAS_OPENH323=1 fi @@ -24949,8 +24878,7 @@ fi if test "${HAS_OPENH323:-unset}" = "unset" ; then as_ac_Header=`$as_echo "ac_cv_header_${PWLIBDIR}/../openh323/version.h" | $as_tr_sh` ac_fn_cxx_check_header_mongrel "$LINENO" "${PWLIBDIR}/../openh323/version.h" "$as_ac_Header" "$ac_includes_default" -eval as_val=\$$as_ac_Header - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : OPENH323DIR="${PWLIBDIR}/../openh323"; HAS_OPENH323=1 fi @@ -24962,8 +24890,7 @@ fi as_ac_Header=`$as_echo "ac_cv_header_${OPENH323DIR}/include/h323.h" | $as_tr_sh` ac_fn_cxx_check_header_compile "$LINENO" "${OPENH323DIR}/include/h323.h" "$as_ac_Header" "#include " -eval as_val=\$$as_ac_Header - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : else OPENH323_INCDIR="${PWLIB_INCDIR}/openh323"; OPENH323_LIBDIR="${PWLIB_LIBDIR}" @@ -24977,8 +24904,7 @@ fi as_ac_Header=`$as_echo "ac_cv_header_${HOME}/openh323/include/h323.h" | $as_tr_sh` ac_fn_cxx_check_header_compile "$LINENO" "${HOME}/openh323/include/h323.h" "$as_ac_Header" "#include " -eval as_val=\$$as_ac_Header - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : HAS_OPENH323=1 fi @@ -25252,7 +25178,7 @@ if test "x${PBX_LUA}" != "x1" -a "${USE_LUA}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_lua5.1_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -llua5.1" >&5 $as_echo_n "checking for ${pbxfuncname} in -llua5.1... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -25287,8 +25213,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_LUA_FOUND=yes else AST_LUA_FOUND=no @@ -25366,7 +25291,7 @@ if test "x${PBX_LUA}" != "x1" -a "${USE_LUA}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_lua_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -llua" >&5 $as_echo_n "checking for ${pbxfuncname} in -llua... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -25401,8 +25326,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_LUA_FOUND=yes else AST_LUA_FOUND=no @@ -25472,7 +25396,7 @@ if test "x${PBX_RADIUS}" != "x1" -a "${USE_RADIUS}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_radiusclient-ng_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lradiusclient-ng" >&5 $as_echo_n "checking for ${pbxfuncname} in -lradiusclient-ng... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -25507,8 +25431,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_RADIUS_FOUND=yes else AST_RADIUS_FOUND=no @@ -25587,7 +25510,7 @@ if test "x${PBX_OPENAIS}" != "x1" -a "${USE_OPENAIS}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_SaClm_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lSaClm" >&5 $as_echo_n "checking for ${pbxfuncname} in -lSaClm... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -25622,8 +25545,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_OPENAIS_FOUND=yes else AST_OPENAIS_FOUND=no @@ -25708,7 +25630,7 @@ if test "x${PBX_SPEEX}" != "x1" -a "${USE_SPEEX}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_speex_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lspeex" >&5 $as_echo_n "checking for ${pbxfuncname} in -lspeex... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -25743,8 +25665,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_SPEEX_FOUND=yes else AST_SPEEX_FOUND=no @@ -25815,7 +25736,7 @@ if test "x${PBX_SPEEX_PREPROCESS}" != "x1" -a "${USE_SPEEX_PREPROCESS}" != "no"; as_ac_Lib=`$as_echo "ac_cv_lib_speex_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lspeex" >&5 $as_echo_n "checking for ${pbxfuncname} in -lspeex... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -25850,8 +25771,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_SPEEX_PREPROCESS_FOUND=yes else AST_SPEEX_PREPROCESS_FOUND=no @@ -25924,7 +25844,7 @@ if test "x${PBX_SPEEXDSP}" != "x1" -a "${USE_SPEEXDSP}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_speexdsp_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lspeexdsp" >&5 $as_echo_n "checking for ${pbxfuncname} in -lspeexdsp... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -25959,8 +25879,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_SPEEXDSP_FOUND=yes else AST_SPEEXDSP_FOUND=no @@ -26035,7 +25954,7 @@ if test "x${PBX_SQLITE}" != "x1" -a "${USE_SQLITE}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_sqlite_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lsqlite" >&5 $as_echo_n "checking for ${pbxfuncname} in -lsqlite... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -26070,8 +25989,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_SQLITE_FOUND=yes else AST_SQLITE_FOUND=no @@ -26141,7 +26059,7 @@ if test "x${PBX_SQLITE3}" != "x1" -a "${USE_SQLITE3}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_sqlite3_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lsqlite3" >&5 $as_echo_n "checking for ${pbxfuncname} in -lsqlite3... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -26176,8 +26094,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_SQLITE3_FOUND=yes else AST_SQLITE3_FOUND=no @@ -26227,6 +26144,14 @@ fi +if test "${PBX_SQLITE3}" != 1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** Asterisk now uses SQLite3 for the internal Asterisk database." >&5 +$as_echo "$as_me: WARNING: *** Asterisk now uses SQLite3 for the internal Asterisk database." >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** Please install the SQLite3 development package." >&5 +$as_echo "$as_me: WARNING: *** Please install the SQLite3 development package." >&2;} + exit 1 +fi + if test "x${PBX_CRYPTO}" != "x1" -a "${USE_CRYPTO}" != "no"; then pbxlibdir="" @@ -26247,7 +26172,7 @@ if test "x${PBX_CRYPTO}" != "x1" -a "${USE_CRYPTO}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_crypto_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lcrypto" >&5 $as_echo_n "checking for ${pbxfuncname} in -lcrypto... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -26282,8 +26207,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_CRYPTO_FOUND=yes else AST_CRYPTO_FOUND=no @@ -26355,7 +26279,7 @@ if test "x${PBX_OPENSSL}" != "x1" -a "${USE_OPENSSL}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_ssl_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lssl" >&5 $as_echo_n "checking for ${pbxfuncname} in -lssl... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -26390,8 +26314,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_OPENSSL_FOUND=yes else AST_OPENSSL_FOUND=no @@ -26526,8 +26449,8 @@ $as_echo_n "checking if OSP Toolkit version is compatible with app_osplookup... if test "$cross_compiling" = yes; then : { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error "cannot run test program while cross compiling -See \`config.log' for more details." "$LINENO" 5; } +as_fn_error $? "cannot run test program while cross compiling +See \`config.log' for more details" "$LINENO" 5 ; } else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -26593,7 +26516,7 @@ if test "x${PBX_SRTP}" != "x1" -a "${USE_SRTP}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_srtp_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lsrtp" >&5 $as_echo_n "checking for ${pbxfuncname} in -lsrtp... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -26628,8 +26551,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_SRTP_FOUND=yes else AST_SRTP_FOUND=no @@ -26924,7 +26846,7 @@ if test "x${PBX_HOARD}" != "x1" -a "${USE_HOARD}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_hoard_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lhoard" >&5 $as_echo_n "checking for ${pbxfuncname} in -lhoard... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -26959,8 +26881,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_HOARD_FOUND=yes else AST_HOARD_FOUND=no @@ -27030,7 +26951,7 @@ if test "x${PBX_FREETDS}" != "x1" -a "${USE_FREETDS}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_sybdb_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lsybdb" >&5 $as_echo_n "checking for ${pbxfuncname} in -lsybdb... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -27065,8 +26986,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_FREETDS_FOUND=yes else AST_FREETDS_FOUND=no @@ -27136,7 +27056,7 @@ if test "x${PBX_TERMCAP}" != "x1" -a "${USE_TERMCAP}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_termcap_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -ltermcap" >&5 $as_echo_n "checking for ${pbxfuncname} in -ltermcap... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -27171,8 +27091,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_TERMCAP_FOUND=yes else AST_TERMCAP_FOUND=no @@ -27242,7 +27161,7 @@ if test "x${PBX_TINFO}" != "x1" -a "${USE_TINFO}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_tinfo_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -ltinfo" >&5 $as_echo_n "checking for ${pbxfuncname} in -ltinfo... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -27277,8 +27196,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_TINFO_FOUND=yes else AST_TINFO_FOUND=no @@ -27395,7 +27313,7 @@ if test "x${PBX_TONEZONE}" != "x1" -a "${USE_TONEZONE}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_tonezone_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -ltonezone" >&5 $as_echo_n "checking for ${pbxfuncname} in -ltonezone... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -27430,8 +27348,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_TONEZONE_FOUND=yes else AST_TONEZONE_FOUND=no @@ -27501,7 +27418,7 @@ if test "x${PBX_USB}" != "x1" -a "${USE_USB}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_usb_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lusb" >&5 $as_echo_n "checking for ${pbxfuncname} in -lusb... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -27536,8 +27453,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_USB_FOUND=yes else AST_USB_FOUND=no @@ -27609,7 +27525,7 @@ if test "x${PBX_VORBIS}" != "x1" -a "${USE_VORBIS}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_vorbis_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lvorbis" >&5 $as_echo_n "checking for ${pbxfuncname} in -lvorbis... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -27644,8 +27560,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_VORBIS_FOUND=yes else AST_VORBIS_FOUND=no @@ -27715,7 +27630,7 @@ if test "x${PBX_VORBIS}" != "x1" -a "${USE_VORBIS}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_vorbis_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lvorbis" >&5 $as_echo_n "checking for ${pbxfuncname} in -lvorbis... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -27750,8 +27665,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_VORBIS_FOUND=yes else AST_VORBIS_FOUND=no @@ -27894,7 +27808,7 @@ if test "x${PBX_ZLIB}" != "x1" -a "${USE_ZLIB}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_z_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lz" >&5 $as_echo_n "checking for ${pbxfuncname} in -lz... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -27929,8 +27843,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_ZLIB_FOUND=yes else AST_ZLIB_FOUND=no @@ -27990,7 +27903,7 @@ elif test "x$CURSES_LIB" != "x" ; then elif test "x$NCURSES_LIB" != "x" ; then EDITLINE_LIB="$NCURSES_LIB" else - as_fn_error "*** termcap support not found (on modern systems, this typically means the ncurses development package is missing)" "$LINENO" 5 + as_fn_error $? "*** termcap support not found (on modern systems, this typically means the ncurses development package is missing)" "$LINENO" 5 fi @@ -28326,7 +28239,7 @@ if test "x${PBX_SDL_IMAGE}" != "x1" -a "${USE_SDL_IMAGE}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_SDL_image_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lSDL_image" >&5 $as_echo_n "checking for ${pbxfuncname} in -lSDL_image... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -28361,8 +28274,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_SDL_IMAGE_FOUND=yes else AST_SDL_IMAGE_FOUND=no @@ -28431,7 +28343,7 @@ if test "x${PBX_FFMPEG}" != "x1" -a "${USE_FFMPEG}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_avcodec_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lavcodec" >&5 $as_echo_n "checking for ${pbxfuncname} in -lavcodec... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -28466,8 +28378,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_FFMPEG_FOUND=yes else AST_FFMPEG_FOUND=no @@ -28550,7 +28461,7 @@ if test "x${PBX_X11}" != "x1" -a "${USE_X11}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_X11_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lX11" >&5 $as_echo_n "checking for ${pbxfuncname} in -lX11... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -28585,8 +28496,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_X11_FOUND=yes else AST_X11_FOUND=no @@ -28659,7 +28569,7 @@ if test "x${PBX_X11}" != "x1" -a "${USE_X11}" != "no"; then as_ac_Lib=`$as_echo "ac_cv_lib_X11_${pbxfuncname}" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lX11" >&5 $as_echo_n "checking for ${pbxfuncname} in -lX11... " >&6; } -if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval "test \"\${$as_ac_Lib+set}\"" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -28694,8 +28604,7 @@ fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Lib - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : AST_X11_FOUND=yes else AST_X11_FOUND=no @@ -28758,7 +28667,7 @@ if test "${ac_cv_file__sbin_launchd+set}" = set; then : $as_echo_n "(cached) " >&6 else test "$cross_compiling" = yes && - as_fn_error "cannot check for file existence when cross compiling" "$LINENO" 5 + as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 if test -r "/sbin/launchd"; then ac_cv_file__sbin_launchd=yes else @@ -29452,6 +29361,7 @@ DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= +U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' @@ -29613,19 +29523,19 @@ export LANGUAGE (unset CDPATH) >/dev/null 2>&1 && unset CDPATH -# as_fn_error ERROR [LINENO LOG_FD] -# --------------------------------- +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the -# script with status $?, using 1 if that was 0. +# script with STATUS, using 1 if that was 0. as_fn_error () { - as_status=$?; test $as_status -eq 0 && as_status=1 - if test "$3"; then - as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi - $as_echo "$as_me: error: $1" >&2 + $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error @@ -29821,7 +29731,7 @@ $as_echo X"$as_dir" | test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" - } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p @@ -29875,7 +29785,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # values after options handling. ac_log=" This file was extended by asterisk $as_me trunk, which was -generated by GNU Autoconf 2.65. Invocation command line was +generated by GNU Autoconf 2.67. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS @@ -29937,10 +29847,10 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ asterisk config.status trunk -configured by $0, generated by GNU Autoconf 2.65, +configured by $0, generated by GNU Autoconf 2.67, with options \\"\$ac_cs_config\\" -Copyright (C) 2009 Free Software Foundation, Inc. +Copyright (C) 2010 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." @@ -29957,11 +29867,16 @@ ac_need_defaults=: while test $# != 0 do case $1 in - --*=*) + --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; *) ac_option=$1 ac_optarg=$2 @@ -29983,6 +29898,7 @@ do $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; @@ -29995,7 +29911,7 @@ do ac_need_defaults=false;; --he | --h) # Conflict between --help and --header - as_fn_error "ambiguous option: \`$1' + as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; @@ -30004,7 +29920,7 @@ Try \`$0 --help' for more information.";; ac_cs_silent=: ;; # This is an error. - -*) as_fn_error "unrecognized option: \`$1' + -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" @@ -30058,7 +29974,7 @@ do "makeopts") CONFIG_FILES="$CONFIG_FILES makeopts" ;; "channels/h323/Makefile") CONFIG_FILES="$CONFIG_FILES channels/h323/Makefile" ;; - *) as_fn_error "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5 ;; esac done @@ -30095,7 +30011,7 @@ $debug || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") -} || as_fn_error "cannot create a temporary directory in ." "$LINENO" 5 +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. @@ -30112,7 +30028,7 @@ if test "x$ac_cr" = x; then fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then - ac_cs_awk_cr='\r' + ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi @@ -30126,18 +30042,18 @@ _ACEOF echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || - as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 -ac_delim_num=`echo "$ac_subst_vars" | grep -c '$'` + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || - as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then - as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi @@ -30226,20 +30142,28 @@ if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then else cat fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \ - || as_fn_error "could not setup config files machinery" "$LINENO" 5 + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF -# VPATH may cause trouble with some makes, so we remove $(srcdir), -# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then - ac_vpsub='/^[ ]*VPATH[ ]*=/{ -s/:*\$(srcdir):*/:/ -s/:*\${srcdir}:*/:/ -s/:*@srcdir@:*/:/ -s/^\([^=]*=[ ]*\):*/\1/ + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// s/^[^=]*=[ ]*$// }' fi @@ -30267,7 +30191,7 @@ for ac_last_try in false false :; do if test -z "$ac_t"; then break elif $ac_last_try; then - as_fn_error "could not make $CONFIG_HEADERS" "$LINENO" 5 + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi @@ -30352,7 +30276,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 - as_fn_error "could not setup config headers machinery" "$LINENO" 5 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" @@ -30365,7 +30289,7 @@ do esac case $ac_mode$ac_tag in :[FHL]*:*);; - :L* | :C*:*) as_fn_error "invalid tag \`$ac_tag'" "$LINENO" 5;; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5 ;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac @@ -30393,7 +30317,7 @@ do [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || - as_fn_error "cannot find input file: \`$ac_f'" "$LINENO" 5;; + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5 ;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" @@ -30420,7 +30344,7 @@ $as_echo "$as_me: creating $ac_file" >&6;} case $ac_tag in *:-:* | *:-) cat >"$tmp/stdin" \ - || as_fn_error "could not create $ac_file" "$LINENO" 5 ;; + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac @@ -30551,22 +30475,22 @@ s&@INSTALL@&$ac_INSTALL&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \ - || as_fn_error "could not create $ac_file" "$LINENO" 5 + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined." >&5 +which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined." >&2;} +which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$tmp/stdin" case $ac_file in -) cat "$tmp/out" && rm -f "$tmp/out";; *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";; esac \ - || as_fn_error "could not create $ac_file" "$LINENO" 5 + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # @@ -30577,19 +30501,19 @@ which seems to be undefined. Please make sure it is defined." >&2;} $as_echo "/* $configure_input */" \ && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" } >"$tmp/config.h" \ - || as_fn_error "could not create $ac_file" "$LINENO" 5 + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$tmp/config.h" "$ac_file" \ - || as_fn_error "could not create $ac_file" "$LINENO" 5 + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" \ - || as_fn_error "could not create -" "$LINENO" 5 + || as_fn_error $? "could not create -" "$LINENO" 5 fi ;; @@ -30604,7 +30528,7 @@ _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || - as_fn_error "write failure creating $CONFIG_STATUS" "$LINENO" 5 + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. @@ -30625,7 +30549,7 @@ if test "$no_create" != yes; then exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. - $ac_cs_success || as_fn_exit $? + $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 diff --git a/configure.ac b/configure.ac index afa079aff..cc3d73cb1 100644 --- a/configure.ac +++ b/configure.ac @@ -1970,6 +1970,12 @@ AST_EXT_LIB_CHECK([SQLITE], [sqlite], [sqlite_exec], [sqlite.h]) AST_EXT_LIB_CHECK([SQLITE3], [sqlite3], [sqlite3_open], [sqlite3.h], [${PTHREAD_LIBS}], [${PTHREAD_CFLAGS}]) +if test "${PBX_SQLITE3}" != 1; then + AC_MSG_WARN(*** Asterisk now uses SQLite3 for the internal Asterisk database.) + AC_MSG_WARN(*** Please install the SQLite3 development package.) + exit 1 +fi + AST_EXT_LIB_CHECK([CRYPTO], [crypto], [AES_encrypt], [openssl/aes.h]) if test "$PBX_CRYPTO" = "1"; diff --git a/main/Makefile b/main/Makefile index ad4d39c03..0b37aa3ef 100644 --- a/main/Makefile +++ b/main/Makefile @@ -33,6 +33,7 @@ endif AST_LIBS += $(OPENSSL_LIB) AST_LIBS += $(BKTR_LIB) AST_LIBS += $(LIBXML2_LIB) +AST_LIBS += $(SQLITE3_LIB) ifneq ($(findstring $(OSARCH), linux-gnu uclinux linux-uclibc linux-gnueabi kfreebsd-gnu),) ifneq ($(findstring LOADABLE_MODULES,$(MENUSELECT_CFLAGS)),) @@ -111,9 +112,6 @@ editline/libedit.a: CHECK_SUBDIR cd editline && test -f config.h || CFLAGS="$(PTHREAD_CFLAGS) $(subst $(ASTTOPDIR),../../,$(_ASTCFLAGS:-Werror=) $(ASTCFLAGS))" LDFLAGS="$(_ASTLDFLAGS) $(ASTLDFLAGS)" ./configure --build=$(BUILD_PLATFORM) --host=$(HOST_PLATFORM) --with-ncurses=$(NCURSES_DIR) --with-curses=$(CURSES_DIR) --with-termcap=$(TERMCAP_DIR) --with-tinfo=$(TINFO_DIR) $(MAKE) -C editline libedit.a -db1-ast/libdb1.a: CHECK_SUBDIR - _ASTCFLAGS="$(_ASTCFLAGS) -Wno-strict-aliasing" ASTCFLAGS="$(ASTCFLAGS)" $(MAKE) -C db1-ast libdb1.a - ifneq ($(findstring REBUILD_PARSERS,$(MENUSELECT_CFLAGS)),) ast_expr2.c ast_expr2.h: ast_expr2.y else @@ -143,6 +141,8 @@ testexpr2: ast_expr2f.c ast_expr2.c ast_expr2.h $(CC) -g -o testexpr2 ast_expr2f.o ast_expr2.o -lm rm ast_expr2.o ast_expr2f.o +db.o: _ASTCFLAGS+=$(SQLITE3_INCLUDE) + ifneq ($(findstring ENABLE_UPLOADS,$(MENUSELECT_CFLAGS)),) http.o: _ASTCFLAGS+=$(GMIME_INCLUDE) endif @@ -177,13 +177,13 @@ endif $(OBJS): _ASTCFLAGS+=-DAST_MODULE=\"core\" -$(MAIN_TGT): $(OBJS) editline/libedit.a db1-ast/libdb1.a $(AST_EMBED_LDSCRIPTS) +$(MAIN_TGT): $(OBJS) editline/libedit.a $(AST_EMBED_LDSCRIPTS) @$(CC) -c -o buildinfo.o $(_ASTCFLAGS) buildinfo.c $(ASTCFLAGS) - $(ECHO_PREFIX) echo " [LD] $(OBJS) editline/libedit.a db1-ast/libdb1.a $(AST_EMBED_LDSCRIPTS) -> $@" + $(ECHO_PREFIX) echo " [LD] $(OBJS) editline/libedit.a $(AST_EMBED_LDSCRIPTS) -> $@" ifneq ($(findstring chan_h323,$(MENUSELECT_CHANNELS)),) - $(CMD_PREFIX) $(CC) $(STATIC_BUILD) -o $@ $(ASTLINK) $(AST_EMBED_LDFLAGS) $(_ASTLDFLAGS) $(ASTLDFLAGS) $(OBJS) editline/libedit.a db1-ast/libdb1.a $(AST_EMBED_LDSCRIPTS) buildinfo.o $(AST_LIBS) $(AST_EMBED_LIBS) $(GMIMELDFLAGS) + $(CMD_PREFIX) $(CC) $(STATIC_BUILD) -o $@ $(ASTLINK) $(AST_EMBED_LDFLAGS) $(_ASTLDFLAGS) $(ASTLDFLAGS) $(OBJS) editline/libedit.a $(AST_EMBED_LDSCRIPTS) buildinfo.o $(AST_LIBS) $(AST_EMBED_LIBS) $(GMIMELDFLAGS) else - $(CMD_PREFIX) $(CXX) $(STATIC_BUILD) -o $@ $(ASTLINK) $(AST_EMBED_LDFLAGS) $(_ASTLDFLAGS) $(ASTLDFLAGS) $(H323LDFLAGS) $(OBJS) editline/libedit.a db1-ast/libdb1.a $(AST_EMBED_LDSCRIPTS) buildinfo.o $(AST_LIBS) $(AST_EMBED_LIBS) $(H323LDLIBS) $(GMIMELDFLAGS) + $(CMD_PREFIX) $(CXX) $(STATIC_BUILD) -o $@ $(ASTLINK) $(AST_EMBED_LDFLAGS) $(_ASTLDFLAGS) $(ASTLDFLAGS) $(H323LDFLAGS) $(OBJS) editline/libedit.a $(AST_EMBED_LDSCRIPTS) buildinfo.o $(AST_LIBS) $(AST_EMBED_LIBS) $(H323LDLIBS) $(GMIMELDFLAGS) endif ifeq ($(GNU_LD),1) @@ -194,9 +194,7 @@ endif clean:: rm -f asterisk - rm -f db1-ast/.*.d rm -f asterisk.exports @if [ -f editline/Makefile ]; then $(MAKE) -C editline distclean ; fi - @$(MAKE) -C db1-ast clean @$(MAKE) -C stdtime clean rm -f libresample/src/*.o diff --git a/main/asterisk.c b/main/asterisk.c index a325fec85..3572a526d 100644 --- a/main/asterisk.c +++ b/main/asterisk.c @@ -3759,6 +3759,11 @@ int main(int argc, char *argv[]) ast_xmldoc_load_documentation(); #endif + if (astdb_init()) { + printf("%s", term_quit()); + exit(1); + } + if (ast_msg_init()) { printf("%s", term_quit()); exit(1); @@ -3834,11 +3839,6 @@ int main(int argc, char *argv[]) exit(1); } - if (astdb_init()) { - printf("%s", term_quit()); - exit(1); - } - if (ast_enum_init()) { printf("%s", term_quit()); exit(1); diff --git a/main/db.c b/main/db.c index a0efc8c05..a1fff2146 100644 --- a/main/db.c +++ b/main/db.c @@ -20,11 +20,11 @@ * * \brief ASTdb Management * - * \author Mark Spencer + * \author Mark Spencer * * \note DB3 is licensed under Sleepycat Public License and is thus incompatible - * with GPL. To avoid having to make another exception (and complicate - * licensing even further) we elect to use DB1 which is BSD licensed + * with GPL. To avoid having to make another exception (and complicate + * licensing even further) we elect to use DB1 which is BSD licensed */ #include "asterisk.h" @@ -34,8 +34,12 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/_private.h" #include "asterisk/paths.h" /* use ast_config_AST_DB */ #include +#include +#include +#include #include #include +#include #include "asterisk/channel.h" #include "asterisk/file.h" @@ -44,9 +48,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/astdb.h" #include "asterisk/cli.h" #include "asterisk/utils.h" -#include "asterisk/lock.h" #include "asterisk/manager.h" -#include "db1-ast/include/db.h" /*** DOCUMENTATION @@ -101,242 +103,362 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") ***/ #define MAX_DB_FIELD 256 - -static DB *astdb; AST_MUTEX_DEFINE_STATIC(dblock); static ast_cond_t dbcond; -typedef int (*process_keys_cb)(DBT *key, DBT *value, const char *filter, void *data); +static sqlite3 *astdb; +static pthread_t syncthread; +static int doexit; static void db_sync(void); -static int dbinit(void) +#define DEFINE_SQL_STATEMENT(stmt,sql) static sqlite3_stmt *stmt; \ + const char stmt##_sql[] = sql; + +DEFINE_SQL_STATEMENT(put_stmt, "INSERT OR REPLACE INTO astdb (key, value) VALUES (?, ?)") +DEFINE_SQL_STATEMENT(get_stmt, "SELECT value FROM astdb WHERE key=?") +DEFINE_SQL_STATEMENT(del_stmt, "DELETE FROM astdb WHERE key=?") +DEFINE_SQL_STATEMENT(deltree_stmt, "DELETE FROM astdb WHERE key LIKE ? || '/' || '%'") +DEFINE_SQL_STATEMENT(deltree_all_stmt, "DELETE FROM astdb") +DEFINE_SQL_STATEMENT(gettree_stmt, "SELECT key, value FROM astdb WHERE key LIKE ? || '/' || '%'") +DEFINE_SQL_STATEMENT(gettree_all_stmt, "SELECT key, value FROM astdb") +DEFINE_SQL_STATEMENT(showkey_stmt, "SELECT key, value FROM astdb WHERE key LIKE '%' || '/' || ?") +DEFINE_SQL_STATEMENT(create_astdb_stmt, "CREATE TABLE IF NOT EXISTS astdb(key VARCHAR(256), value VARCHAR(256), PRIMARY KEY(key))") + +static int init_stmt(sqlite3_stmt **stmt, const char *sql, size_t len) { - if (!astdb && !(astdb = dbopen(ast_config_AST_DB, O_CREAT | O_RDWR, AST_FILE_MODE, DB_BTREE, NULL))) { - ast_log(LOG_WARNING, "Unable to open Asterisk database '%s': %s\n", ast_config_AST_DB, strerror(errno)); + ast_mutex_lock(&dblock); + if (sqlite3_prepare_v2(astdb, sql, len, stmt, NULL) != SQLITE_OK) { + ast_log(LOG_WARNING, "Couldn't prepare statement '%s': %s\n", sql, sqlite3_errmsg(astdb)); + ast_mutex_unlock(&dblock); return -1; } + ast_mutex_unlock(&dblock); + return 0; } - -static inline int keymatch(const char *key, const char *prefix) +static int init_statements(void) { - int preflen = strlen(prefix); - if (!preflen) - return 1; - if (!strcasecmp(key, prefix)) - return 1; - if ((strlen(key) > preflen) && !strncasecmp(key, prefix, preflen)) { - if (key[preflen] == '/') - return 1; - } - return 0; + /* Don't initialize create_astdb_statment here as the astdb table needs to exist + * brefore these statments can be initialized */ + return init_stmt(&get_stmt, get_stmt_sql, sizeof(get_stmt_sql)) + || init_stmt(&del_stmt, del_stmt_sql, sizeof(del_stmt_sql)) + || init_stmt(&deltree_stmt, deltree_stmt_sql, sizeof(deltree_stmt_sql)) + || init_stmt(&deltree_all_stmt, deltree_all_stmt_sql, sizeof(deltree_all_stmt_sql)) + || init_stmt(&gettree_stmt, gettree_stmt_sql, sizeof(gettree_stmt_sql)) + || init_stmt(&gettree_all_stmt, gettree_all_stmt_sql, sizeof(gettree_all_stmt_sql)) + || init_stmt(&showkey_stmt, showkey_stmt_sql, sizeof(showkey_stmt_sql)) + || init_stmt(&put_stmt, put_stmt_sql, sizeof(put_stmt_sql)); } -static inline int subkeymatch(const char *key, const char *suffix) +static int convert_bdb_to_sqlite3(void) { - int suffixlen = strlen(suffix); - if (suffixlen) { - const char *subkey = key + strlen(key) - suffixlen; - if (subkey < key) - return 0; - if (!strcasecmp(subkey, suffix)) - return 1; - } - return 0; + char *cmd; + int res; + + ast_asprintf(&cmd, "astdb2sqlite3 '%s'\n", ast_config_AST_DB); + res = ast_safe_system(cmd); + ast_free(cmd); + + return res; } -static const char *dbt_data2str(DBT *dbt) +static int db_create_astdb(void) { - char *data = ""; + int res = 0; - if (dbt->size) { - data = dbt->data; - data[dbt->size - 1] = '\0'; + if (!create_astdb_stmt) { + init_stmt(&create_astdb_stmt, create_astdb_stmt_sql, sizeof(create_astdb_stmt_sql)); } - return data; -} + ast_mutex_lock(&dblock); + if (sqlite3_step(create_astdb_stmt) != SQLITE_DONE) { + ast_log(LOG_WARNING, "Couldn't create astdb table: %s\n", sqlite3_errmsg(astdb)); + res = -1; + } + sqlite3_reset(create_astdb_stmt); + db_sync(); + ast_mutex_unlock(&dblock); -static inline const char *dbt_data2str_full(DBT *dbt, const char *def) -{ - return S_OR(dbt_data2str(dbt), def); + return res; } -static int process_db_keys(process_keys_cb cb, void *data, const char *filter, int sync) +static int db_open(void) { - DBT key = { 0, }, value = { 0, }, last_key = { 0, }; - int counter = 0; - int res, last = 0; - char last_key_s[MAX_DB_FIELD]; + char *dbname; + struct stat dont_care; + + if (!(dbname = alloca(strlen(ast_config_AST_DB) + sizeof(".sqlite3")))) { + return -1; + } + strcpy(dbname, ast_config_AST_DB); + strcat(dbname, ".sqlite3"); + + if (stat(dbname, &dont_care) && !stat(ast_config_AST_DB, &dont_care)) { + if (convert_bdb_to_sqlite3()) { + ast_log(LOG_ERROR, "*** Database conversion failed!\n"); + ast_log(LOG_ERROR, "*** Asterisk now uses SQLite3 for its internal\n"); + ast_log(LOG_ERROR, "*** database. Conversion from the old astdb\n"); + ast_log(LOG_ERROR, "*** failed. Most likely the astdb2sqlite3 utility\n"); + ast_log(LOG_ERROR, "*** was not selected for build. To convert the\n"); + ast_log(LOG_ERROR, "*** old astdb, please delete '%s'\n", dbname); + ast_log(LOG_ERROR, "*** and re-run 'make menuselect' and select astdb2sqlite3\n"); + ast_log(LOG_ERROR, "*** in the Utilities section, then 'make && make install'.\n"); + sleep(5); + } else { + ast_log(LOG_NOTICE, "Database conversion succeeded!\n"); + } + } ast_mutex_lock(&dblock); - if (dbinit()) { + if (sqlite3_open_v2(dbname, &astdb, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_NOMUTEX, NULL) != SQLITE_OK) { + ast_log(LOG_WARNING, "Unable to open Asterisk database '%s': %s\n", dbname, sqlite3_errmsg(astdb)); + sqlite3_close(astdb); ast_mutex_unlock(&dblock); return -1; } + ast_mutex_unlock(&dblock); - /* Somehow, the database can become corrupted such that astdb->seq will continue looping through - * the database indefinitely. The pointer to last_key.data ends up getting re-used by the BDB lib - * so this specifically queries for the last entry, makes a copy of the key, and then uses it as - * a sentinel to avoid repeatedly looping over the list. */ + return 0; +} - if (astdb->seq(astdb, &last_key, &value, R_LAST)) { - /* Empty database */ - ast_mutex_unlock(&dblock); +static int db_init(void) +{ + if (astdb) { return 0; } - memcpy(last_key_s, last_key.data, MIN(last_key.size - 1, sizeof(last_key_s))); - last_key_s[last_key.size - 1] = '\0'; - for (res = astdb->seq(astdb, &key, &value, R_FIRST); - !res; - res = astdb->seq(astdb, &key, &value, R_NEXT)) { - /* The callback might delete the key, so we have to check it before calling */ - last = !strcmp(dbt_data2str_full(&key, ""), last_key_s); - counter += cb(&key, &value, filter, data); - if (last) { - break; - } + if (db_open() || db_create_astdb() || init_statements()) { + return -1; } - if (sync) { - db_sync(); + return 0; +} + +/* We purposely don't lock around the sqlite3 call because the transaction + * calls will be called with the database lock held. For any other use, make + * sure to take the dblock yourself. */ +static int db_execute_sql(const char *sql, int (*callback)(void *, int, char **, char **), void *arg) +{ + char *errmsg = NULL; + int res =0; + + sqlite3_exec(astdb, sql, callback, arg, &errmsg); + if (errmsg) { + ast_log(LOG_WARNING, "Error executing SQL: %s\n", errmsg); + sqlite3_free(errmsg); + res = -1; } - ast_mutex_unlock(&dblock); + return res; +} - return counter; +static int ast_db_begin_transaction(void) +{ + return db_execute_sql("BEGIN TRANSACTION", NULL, NULL); } -static int db_deltree_cb(DBT *key, DBT *value, const char *filter, void *data) +static int ast_db_commit_transaction(void) { - int res = 0; + return db_execute_sql("COMMIT", NULL, NULL); +} - if (keymatch(dbt_data2str_full(key, ""), filter)) { - astdb->del(astdb, key, 0); - res = 1; - } - return res; +static int ast_db_rollback_transaction(void) +{ + return db_execute_sql("ROLLBACK", NULL, NULL); } -int ast_db_deltree(const char *family, const char *keytree) +int ast_db_put(const char *family, const char *key, const char *value) { - char prefix[MAX_DB_FIELD]; + char fullkey[MAX_DB_FIELD]; + size_t fullkey_len; + int res = 0; - if (family) { - if (keytree) { - snprintf(prefix, sizeof(prefix), "/%s/%s", family, keytree); - } else { - snprintf(prefix, sizeof(prefix), "/%s", family); - } - } else if (keytree) { + if (strlen(family) + strlen(key) + 2 > sizeof(fullkey) - 1) { + ast_log(LOG_WARNING, "Family and key length must be less than %zu bytes\n", sizeof(fullkey) - 3); return -1; - } else { - prefix[0] = '\0'; } - return process_db_keys(db_deltree_cb, NULL, prefix, 1); + fullkey_len = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, key); + + ast_mutex_lock(&dblock); + if (sqlite3_bind_text(put_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC) != SQLITE_OK) { + ast_log(LOG_WARNING, "Couldn't bind key to stmt: %s\n", sqlite3_errmsg(astdb)); + res = -1; + } else if (sqlite3_bind_text(put_stmt, 2, value, -1, SQLITE_STATIC) != SQLITE_OK) { + ast_log(LOG_WARNING, "Couldn't bind value to stmt: %s\n", sqlite3_errmsg(astdb)); + res = -1; + } else if (sqlite3_step(put_stmt) != SQLITE_DONE) { + ast_log(LOG_WARNING, "Couldn't execute statment: %s\n", sqlite3_errmsg(astdb)); + res = -1; + } + + sqlite3_reset(put_stmt); + db_sync(); + ast_mutex_unlock(&dblock); + + return res; } -int ast_db_put(const char *family, const char *keys, const char *value) +int ast_db_get(const char *family, const char *key, char *value, int valuelen) { + const unsigned char *result; char fullkey[MAX_DB_FIELD]; - DBT key, data; - int res, fullkeylen; + size_t fullkey_len; + int res = 0; - ast_mutex_lock(&dblock); - if (dbinit()) { - ast_mutex_unlock(&dblock); + if (strlen(family) + strlen(key) + 2 > sizeof(fullkey) - 1) { + ast_log(LOG_WARNING, "Family and key length must be less than %zu bytes\n", sizeof(fullkey) - 3); return -1; } - fullkeylen = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, keys); - memset(&key, 0, sizeof(key)); - memset(&data, 0, sizeof(data)); - key.data = fullkey; - key.size = fullkeylen + 1; - data.data = (char *) value; - data.size = strlen(value) + 1; - res = astdb->put(astdb, &key, &data, 0); - db_sync(); + fullkey_len = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, key); + + ast_mutex_lock(&dblock); + if (sqlite3_bind_text(get_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC) != SQLITE_OK) { + ast_log(LOG_WARNING, "Couldn't bind key to stmt: %s\n", sqlite3_errmsg(astdb)); + res = -1; + } else if (sqlite3_step(get_stmt) != SQLITE_ROW) { + ast_debug(1, "Unable to find key '%s' in family '%s'\n", key, family); + res = -1; + } else if (!(result = sqlite3_column_text(get_stmt, 0))) { + ast_log(LOG_WARNING, "Couldn't get value\n"); + res = -1; + } else { + strncpy(value, (const char *) result, valuelen); + } + sqlite3_reset(get_stmt); ast_mutex_unlock(&dblock); - if (res) - ast_log(LOG_WARNING, "Unable to put value '%s' for key '%s' in family '%s'\n", value, keys, family); return res; } -int ast_db_get(const char *family, const char *keys, char *value, int valuelen) +int ast_db_del(const char *family, const char *key) { - char fullkey[MAX_DB_FIELD] = ""; - DBT key, data; - int res, fullkeylen; + char fullkey[MAX_DB_FIELD]; + size_t fullkey_len; + int res = 0; - ast_mutex_lock(&dblock); - if (dbinit()) { - ast_mutex_unlock(&dblock); + if (strlen(family) + strlen(key) + 2 > sizeof(fullkey) - 1) { + ast_log(LOG_WARNING, "Family and key length must be less than %zu bytes\n", sizeof(fullkey) - 3); return -1; } - fullkeylen = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, keys); - memset(&key, 0, sizeof(key)); - memset(&data, 0, sizeof(data)); - memset(value, 0, valuelen); - key.data = fullkey; - key.size = fullkeylen + 1; + fullkey_len = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, key); - res = astdb->get(astdb, &key, &data, 0); + ast_mutex_lock(&dblock); + if (sqlite3_bind_text(del_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC) != SQLITE_OK) { + ast_log(LOG_WARNING, "Couldn't bind key to stmt: %s\n", sqlite3_errmsg(astdb)); + res = -1; + } else if (sqlite3_step(del_stmt) != SQLITE_DONE) { + ast_debug(1, "Unable to find key '%s' in family '%s'\n", key, family); + res = -1; + } + sqlite3_reset(del_stmt); + db_sync(); + ast_mutex_unlock(&dblock); - /* Be sure to NULL terminate our data either way */ - if (res) { - ast_debug(1, "Unable to find key '%s' in family '%s'\n", keys, family); - } else { -#if 0 - printf("Got value of size %d\n", data.size); -#endif - if (data.size) { - ((char *)data.data)[data.size - 1] = '\0'; - /* Make sure that we don't write too much to the dst pointer or we don't read too much from the source pointer */ - ast_copy_string(value, data.data, (valuelen > data.size) ? data.size : valuelen); + return res; +} + +int ast_db_deltree(const char *family, const char *subfamily) +{ + sqlite3_stmt *stmt = deltree_stmt; + char prefix[MAX_DB_FIELD]; + int res = 0; + + if (!ast_strlen_zero(family)) { + if (!ast_strlen_zero(subfamily)) { + /* Family and key tree */ + snprintf(prefix, sizeof(prefix), "/%s/%s", family, subfamily); } else { - ast_log(LOG_NOTICE, "Strange, empty value for /%s/%s\n", family, keys); + /* Family only */ + snprintf(prefix, sizeof(prefix), "/%s", family); } + } else { + prefix[0] = '\0'; + stmt = deltree_all_stmt; } - /* Data is not fully isolated for concurrency, so the lock must be extended - * to after the copy to the output buffer. */ + ast_mutex_lock(&dblock); + if (!ast_strlen_zero(prefix) && (sqlite3_bind_text(stmt, 1, prefix, -1, SQLITE_STATIC) != SQLITE_OK)) { + ast_log(LOG_WARNING, "Could bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb)); + res = -1; + } else if (sqlite3_step(stmt) != SQLITE_DONE) { + ast_log(LOG_WARNING, "Couldn't execute stmt: %s\n", sqlite3_errmsg(astdb)); + res = -1; + } + res = sqlite3_changes(astdb); + sqlite3_reset(stmt); + db_sync(); ast_mutex_unlock(&dblock); return res; } -int ast_db_del(const char *family, const char *keys) +struct ast_db_entry *ast_db_gettree(const char *family, const char *subfamily) { - char fullkey[MAX_DB_FIELD]; - DBT key; - int res, fullkeylen; + char prefix[MAX_DB_FIELD]; + sqlite3_stmt *stmt = gettree_stmt; + struct ast_db_entry *cur, *last = NULL, *ret = NULL; + + if (!ast_strlen_zero(family)) { + if (!ast_strlen_zero(subfamily)) { + /* Family and key tree */ + snprintf(prefix, sizeof(prefix), "/%s/%s", family, subfamily); + } else { + /* Family only */ + snprintf(prefix, sizeof(prefix), "/%s", family); + } + } else { + prefix[0] = '\0'; + stmt = gettree_all_stmt; + } ast_mutex_lock(&dblock); - if (dbinit()) { + if (!ast_strlen_zero(prefix) && (sqlite3_bind_text(stmt, 1, prefix, -1, SQLITE_STATIC) != SQLITE_OK)) { + ast_log(LOG_WARNING, "Could bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb)); + sqlite3_reset(stmt); ast_mutex_unlock(&dblock); - return -1; + return NULL; } - - fullkeylen = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, keys); - memset(&key, 0, sizeof(key)); - key.data = fullkey; - key.size = fullkeylen + 1; - - res = astdb->del(astdb, &key, 0); - db_sync(); - + + while (sqlite3_step(stmt) == SQLITE_ROW) { + const char *key_s, *value_s; + if (!(key_s = (const char *) sqlite3_column_text(stmt, 0))) { + break; + } + if (!(value_s = (const char *) sqlite3_column_text(stmt, 1))) { + break; + } + if (!(cur = ast_malloc(sizeof(*cur) + strlen(key_s) + strlen(value_s) + 2))) { + break; + } + cur->next = NULL; + cur->key = cur->data + strlen(value_s) + 1; + strcpy(cur->data, value_s); + strcpy(cur->key, key_s); + if (last) { + last->next = cur; + } else { + ret = cur; + } + last = cur; + } + sqlite3_reset(stmt); ast_mutex_unlock(&dblock); - if (res) { - ast_debug(1, "Unable to find key '%s' in family '%s'\n", keys, family); + return ret; +} + +void ast_db_freetree(struct ast_db_entry *dbe) +{ + struct ast_db_entry *last; + while (dbe) { + last = dbe; + dbe = dbe->next; + ast_free(last); } - return res; } static char *handle_cli_database_put(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) @@ -429,8 +551,8 @@ static char *handle_cli_database_deltree(struct ast_cli_entry *e, int cmd, struc case CLI_INIT: e->command = "database deltree"; e->usage = - "Usage: database deltree [keytree]\n" - " Deletes a family or specific keytree within a family\n" + "Usage: database deltree [subfamily]\n" + " Deletes a family or specific subfamily within a family\n" " in the Asterisk database.\n"; return NULL; case CLI_GENERATE: @@ -452,32 +574,19 @@ static char *handle_cli_database_deltree(struct ast_cli_entry *e, int cmd, struc return CLI_SUCCESS; } -static int db_show_cb(DBT *key, DBT *value, const char *filter, void *data) -{ - struct ast_cli_args *a = data; - const char *key_s = dbt_data2str_full(key, ""); - const char *value_s = dbt_data2str_full(value, ""); - - if (keymatch(key_s, filter)) { - ast_cli(a->fd, "%-50s: %-25s\n", key_s, value_s); - return 1; - } - - return 0; -} - static char *handle_cli_database_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { char prefix[MAX_DB_FIELD]; int counter = 0; + sqlite3_stmt *stmt = gettree_stmt; switch (cmd) { case CLI_INIT: e->command = "database show"; e->usage = - "Usage: database show [family [keytree]]\n" + "Usage: database show [family [subfamily]]\n" " Shows Asterisk database contents, optionally restricted\n" - " to a given family, or family and keytree.\n"; + " to a given family, or family and subfamily.\n"; return NULL; case CLI_GENERATE: return NULL; @@ -492,118 +601,123 @@ static char *handle_cli_database_show(struct ast_cli_entry *e, int cmd, struct a } else if (a->argc == 2) { /* Neither */ prefix[0] = '\0'; + stmt = gettree_all_stmt; + } else { return CLI_SHOWUSAGE; } - if((counter = process_db_keys(db_show_cb, a, prefix, 0)) < 0) { - ast_cli(a->fd, "Database unavailable\n"); - return CLI_SUCCESS; + ast_mutex_lock(&dblock); + if (!ast_strlen_zero(prefix) && (sqlite3_bind_text(stmt, 1, prefix, -1, SQLITE_STATIC) != SQLITE_OK)) { + ast_log(LOG_WARNING, "Could bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb)); + sqlite3_reset(stmt); + ast_mutex_unlock(&dblock); + return NULL; } - ast_cli(a->fd, "%d results found.\n", counter); - return CLI_SUCCESS; -} - -static int db_showkey_cb(DBT *key, DBT *value, const char *filter, void *data) -{ - struct ast_cli_args *a = data; - const char *key_s = dbt_data2str_full(key, ""); - const char *value_s = dbt_data2str_full(value, ""); - - if (subkeymatch(key_s, filter)) { + while (sqlite3_step(stmt) == SQLITE_ROW) { + const char *key_s, *value_s; + if (!(key_s = (const char *) sqlite3_column_text(stmt, 0))) { + ast_log(LOG_WARNING, "Skipping invalid key!\n"); + continue; + } + if (!(value_s = (const char *) sqlite3_column_text(stmt, 1))) { + ast_log(LOG_WARNING, "Skipping invalid value!\n"); + continue; + } + ++counter; ast_cli(a->fd, "%-50s: %-25s\n", key_s, value_s); - return 1; } - return 0; + sqlite3_reset(stmt); + ast_mutex_unlock(&dblock); + + ast_cli(a->fd, "%d results found.\n", counter); + return CLI_SUCCESS; } static char *handle_cli_database_showkey(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { - char suffix[MAX_DB_FIELD]; int counter = 0; switch (cmd) { case CLI_INIT: e->command = "database showkey"; e->usage = - "Usage: database showkey \n" + "Usage: database showkey \n" " Shows Asterisk database contents, restricted to a given key.\n"; return NULL; case CLI_GENERATE: return NULL; } - if (a->argc == 3) { - /* Key only */ - snprintf(suffix, sizeof(suffix), "/%s", a->argv[2]); - } else { + if (a->argc != 3) { return CLI_SHOWUSAGE; } - if ((counter = process_db_keys(db_showkey_cb, a, suffix, 0)) < 0) { - ast_cli(a->fd, "Database unavailable\n"); - return CLI_SUCCESS; + ast_mutex_lock(&dblock); + if (!ast_strlen_zero(a->argv[2]) && (sqlite3_bind_text(showkey_stmt, 1, a->argv[2], -1, SQLITE_STATIC) != SQLITE_OK)) { + ast_log(LOG_WARNING, "Could bind %s to stmt: %s\n", a->argv[2], sqlite3_errmsg(astdb)); + sqlite3_reset(showkey_stmt); + ast_mutex_unlock(&dblock); + return NULL; + } + + while (sqlite3_step(showkey_stmt) == SQLITE_ROW) { + const char *key_s, *value_s; + if (!(key_s = (const char *) sqlite3_column_text(showkey_stmt, 0))) { + break; + } + if (!(value_s = (const char *) sqlite3_column_text(showkey_stmt, 1))) { + break; + } + ++counter; + ast_cli(a->fd, "%-50s: %-25s\n", key_s, value_s); } + sqlite3_reset(showkey_stmt); + ast_mutex_unlock(&dblock); ast_cli(a->fd, "%d results found.\n", counter); return CLI_SUCCESS; } -static int db_gettree_cb(DBT *key, DBT *value, const char *filter, void *data) +static int display_results(void *arg, int columns, char **values, char **colnames) { - struct ast_db_entry **ret = data; - struct ast_db_entry *cur; - const char *key_s = dbt_data2str_full(key, ""); - const char *value_s = dbt_data2str_full(value, ""); - size_t key_slen = strlen(key_s) + 1, value_slen = strlen(value_s) + 1; + struct ast_cli_args *a = arg; + size_t x; - if (keymatch(key_s, filter) && (cur = ast_malloc(sizeof(*cur) + key_slen + value_slen))) { - cur->next = *ret; - cur->key = cur->data + value_slen; - strcpy(cur->data, value_s); - strcpy(cur->key, key_s); - *ret = cur; - return 1; + for (x = 0; x < columns; x++) { + ast_cli(a->fd, "%-5s: %-50s\n", colnames[x], values[x]); } + ast_cli(a->fd, "\n"); return 0; } -struct ast_db_entry *ast_db_gettree(const char *family, const char *keytree) +static char *handle_cli_database_query(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { - char prefix[MAX_DB_FIELD]; - struct ast_db_entry *ret = NULL; - if (!ast_strlen_zero(family)) { - if (!ast_strlen_zero(keytree)) { - /* Family and key tree */ - snprintf(prefix, sizeof(prefix), "/%s/%s", family, keytree); - } else { - /* Family only */ - snprintf(prefix, sizeof(prefix), "/%s", family); - } - } else { - prefix[0] = '\0'; + switch (cmd) { + case CLI_INIT: + e->command = "database query"; + e->usage = + "Usage: database query \"\"\n" + " Run a user-specified SQL query on the database. Be careful.\n"; + return NULL; + case CLI_GENERATE: + return NULL; } - if (process_db_keys(db_gettree_cb, &ret, prefix, 0) < 0) { - ast_log(LOG_WARNING, "Database unavailable\n"); - return NULL; + if (a->argc != 3) { + return CLI_SHOWUSAGE; } - return ret; -} + ast_mutex_lock(&dblock); + db_execute_sql(a->argv[2], display_results, a); + db_sync(); /* Go ahead and sync the db in case they write */ + ast_mutex_unlock(&dblock); -void ast_db_freetree(struct ast_db_entry *dbe) -{ - struct ast_db_entry *last; - while (dbe) { - last = dbe; - dbe = dbe->next; - ast_free(last); - } + return CLI_SUCCESS; } static struct ast_cli_entry cli_database[] = { @@ -612,7 +726,8 @@ static struct ast_cli_entry cli_database[] = { AST_CLI_DEFINE(handle_cli_database_get, "Gets database value"), AST_CLI_DEFINE(handle_cli_database_put, "Adds/updates database value"), AST_CLI_DEFINE(handle_cli_database_del, "Removes database key/value"), - AST_CLI_DEFINE(handle_cli_database_deltree, "Removes database keytree/values") + AST_CLI_DEFINE(handle_cli_database_deltree, "Removes database subfamily/values"), + AST_CLI_DEFINE(handle_cli_database_query, "Run a user-specified query on the astdb"), }; static int manager_dbput(struct mansession *s, const struct message *m) @@ -726,7 +841,7 @@ static int manager_dbdeltree(struct mansession *s, const struct message *m) astman_send_error(s, m, "Database entry not found"); else astman_send_ack(s, m, "Key tree deleted successfully"); - + return 0; } @@ -754,27 +869,48 @@ static void db_sync(void) static void *db_sync_thread(void *data) { ast_mutex_lock(&dblock); + ast_db_begin_transaction(); for (;;) { + /* We're ok with spurious wakeups, so we don't worry about a predicate */ ast_cond_wait(&dbcond, &dblock); + if (ast_db_commit_transaction()) { + ast_db_rollback_transaction(); + } + if (doexit) { + ast_mutex_unlock(&dblock); + break; + } + ast_db_begin_transaction(); ast_mutex_unlock(&dblock); sleep(1); ast_mutex_lock(&dblock); - astdb->sync(astdb, 0); } return NULL; } +static void astdb_atexit(void) +{ + doexit = 1; + db_sync(); + pthread_join(syncthread, NULL); + ast_mutex_lock(&dblock); + sqlite3_close(astdb); + ast_mutex_unlock(&dblock); +} + int astdb_init(void) { - pthread_t dont_care; + if (db_init()) { + return -1; + } ast_cond_init(&dbcond, NULL); - if (ast_pthread_create_background(&dont_care, NULL, db_sync_thread, NULL)) { + if (ast_pthread_create_background(&syncthread, NULL, db_sync_thread, NULL)) { return -1; } - dbinit(); + ast_register_atexit(astdb_atexit); ast_cli_register_multiple(cli_database, ARRAY_LEN(cli_database)); ast_manager_register_xml("DBGet", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_dbget); ast_manager_register_xml("DBPut", EVENT_FLAG_SYSTEM, manager_dbput); diff --git a/main/db1-ast/Makefile b/main/db1-ast/Makefile deleted file mode 100644 index a0f12e1c4..000000000 --- a/main/db1-ast/Makefile +++ /dev/null @@ -1,71 +0,0 @@ -# @(#)Makefile 8.9 (Berkeley) 7/14/94 - -LIBDB= libdb1.a -ARCH=$(shell uname -m) -ifeq ($(ARCH),alpha) -SOVER=2.1 -else -SOVER=2 -endif - -ifeq ($(OSARCH),Darwin) - OSARCH_DEFINE+=-D__Darwin__ -endif - -LIBDBSO=libdb.so.$(SOVER) -PROG= db_dump185 -OBJ1= hash/hash.o hash/hash_bigkey.o hash/hash_buf.o hash/hash_func.o hash/hash_log2.o hash/hash_page.o \ - hash/ndbm.o -OBJ2= btree/bt_close.o btree/bt_conv.o btree/bt_debug.o btree/bt_delete.o btree/bt_get.o btree/bt_open.o \ - btree/bt_overflow.o btree/bt_page.o btree/bt_put.o btree/bt_search.o btree/bt_seq.o btree/bt_split.o \ - btree/bt_utils.o -OBJ3= db/db.o -OBJ4= mpool/mpool.o -OBJ5= recno/rec_close.o recno/rec_delete.o recno/rec_get.o recno/rec_open.o recno/rec_put.o recno/rec_search.o \ - recno/rec_seq.o recno/rec_utils.o -MISC= -OBJS= $(OBJ1) $(OBJ2) $(OBJ3) $(OBJ4) $(OBJ5) $(MISC) -SHOBJS= $(patsubst %.o,%.os,$(OBJS)) - -include $(ASTTOPDIR)/Makefile.rules - -all: $(LIBDB) #$(LIBDBSO) $(PROG) - -$(LIBDB): $(OBJS) - $(ECHO_PREFIX) echo " [AR] $^ -> $@" - $(CMD_PREFIX) $(AR) cr $@ $^ - $(CMD_PREFIX) $(RANLIB) $@ - -$(LIBDBSO): $(SHOBJS) - $(CC) -Wl,-O1 -Wl,--version-script=libdb.map -Wl,-soname=$(LIBDBSO) -shared -o $@ $^ - ln -sf $@ libdb.so - -$(PROG): db_dump185.o $(LIBDBSO) - $(CC) -o $@ db_dump185.o -L. -ldb - -clean-depend: - -clean: - rm -f $(LIBDB) $(LIBDBSO) $(OBJS) $(SHOBJS) */*.s */*.i - -_ASTCFLAGS:=-Wall -D__DBINTERFACE_PRIVATE -I. -I.. -Iinclude -Ihash -Ibtree -Irecno $(_ASTCFLAGS) - -OSTYPE=$(shell uname -s) -ifeq ($(OSTYPE),SunOS) -_ASTCFLAGS+=-I../../include -I../../include/solaris-compat -DSOLARIS -endif - -db_dump185.o: db_dump185.c - $(CL) -o $@ $< -x%.o: hash/%.c - $(CL) -Ihash $(OSARCH_DEFINE) -o $@ $< -%.os: hash/%.c - $(CL) -Ihash -fPIC -o $@ $< -x%.o: btree/%.c - $(CL) -Ibtree -o $@ $< -%.os: btree/%.c - $(CL) -Ibtree -fPIC -o $@ $< -x%.o: recno/%.c - $(CL) -Irecno -o $@ $< -%.os: recno/%.c - $(CL) -Irecno -fPIC -o $@ $< diff --git a/main/db1-ast/btree/bt_close.c b/main/db1-ast/btree/bt_close.c deleted file mode 100644 index 67a6e5340..000000000 --- a/main/db1-ast/btree/bt_close.c +++ /dev/null @@ -1,182 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Mike Olson. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)bt_close.c 8.7 (Berkeley) 8/17/94"; -#endif /* LIBC_SCCS and not lint */ - -#include - -#include -#include -#include -#include -#include - -#include "../include/db.h" -#include "btree.h" - -static int bt_meta __P((BTREE *)); - -/* - * BT_CLOSE -- Close a btree. - * - * Parameters: - * dbp: pointer to access method - * - * Returns: - * RET_ERROR, RET_SUCCESS - */ -int -__bt_close(dbp) - DB *dbp; -{ - BTREE *t; - int fd; - - t = dbp->internal; - - /* Toss any page pinned across calls. */ - if (t->bt_pinned != NULL) { - mpool_put(t->bt_mp, t->bt_pinned, 0); - t->bt_pinned = NULL; - } - - /* Sync the tree. */ - if (__bt_sync(dbp, 0) == RET_ERROR) - return (RET_ERROR); - - /* Close the memory pool. */ - if (mpool_close(t->bt_mp) == RET_ERROR) - return (RET_ERROR); - - /* Free random memory. */ - if (t->bt_cursor.key.data != NULL) { - free(t->bt_cursor.key.data); - t->bt_cursor.key.size = 0; - t->bt_cursor.key.data = NULL; - } - if (t->bt_rkey.data) { - free(t->bt_rkey.data); - t->bt_rkey.size = 0; - t->bt_rkey.data = NULL; - } - if (t->bt_rdata.data) { - free(t->bt_rdata.data); - t->bt_rdata.size = 0; - t->bt_rdata.data = NULL; - } - - fd = t->bt_fd; - free(t); - free(dbp); - return (close(fd) ? RET_ERROR : RET_SUCCESS); -} - -/* - * BT_SYNC -- sync the btree to disk. - * - * Parameters: - * dbp: pointer to access method - * - * Returns: - * RET_SUCCESS, RET_ERROR. - */ -int -__bt_sync(dbp, flags) - const DB *dbp; - u_int flags; -{ - BTREE *t; - int status; - - t = dbp->internal; - - /* Toss any page pinned across calls. */ - if (t->bt_pinned != NULL) { - mpool_put(t->bt_mp, t->bt_pinned, 0); - t->bt_pinned = NULL; - } - - /* Sync doesn't currently take any flags. */ - if (flags != 0) { - errno = EINVAL; - return (RET_ERROR); - } - - if (F_ISSET(t, B_INMEM | B_RDONLY) || !F_ISSET(t, B_MODIFIED)) - return (RET_SUCCESS); - - if (F_ISSET(t, B_METADIRTY) && bt_meta(t) == RET_ERROR) - return (RET_ERROR); - - if ((status = mpool_sync(t->bt_mp)) == RET_SUCCESS) - F_CLR(t, B_MODIFIED); - - return (status); -} - -/* - * BT_META -- write the tree meta data to disk. - * - * Parameters: - * t: tree - * - * Returns: - * RET_ERROR, RET_SUCCESS - */ -static int -bt_meta(t) - BTREE *t; -{ - BTMETA m; - void *p; - - if ((p = mpool_get(t->bt_mp, P_META, 0)) == NULL) - return (RET_ERROR); - - /* Fill in metadata. */ - m.magic = BTREEMAGIC; - m.version = BTREEVERSION; - m.psize = t->bt_psize; - m.free = t->bt_free; - m.nrecs = t->bt_nrecs; - m.flags = F_ISSET(t, SAVEMETA); - - memmove(p, &m, sizeof(BTMETA)); - mpool_put(t->bt_mp, p, MPOOL_DIRTY); - return (RET_SUCCESS); -} diff --git a/main/db1-ast/btree/bt_conv.c b/main/db1-ast/btree/bt_conv.c deleted file mode 100644 index d2ebdc57b..000000000 --- a/main/db1-ast/btree/bt_conv.c +++ /dev/null @@ -1,221 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Mike Olson. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)bt_conv.c 8.5 (Berkeley) 8/17/94"; -#endif /* LIBC_SCCS and not lint */ - -#include - -#include - -#include "../include/db.h" -#include "btree.h" - -static void mswap __P((PAGE *)); - -/* - * __BT_BPGIN, __BT_BPGOUT -- - * Convert host-specific number layout to/from the host-independent - * format stored on disk. - * - * Parameters: - * t: tree - * pg: page number - * h: page to convert - */ -void -__bt_pgin(t, pg, pp) - void *t; - pgno_t pg; - void *pp; -{ - PAGE *h; - indx_t i, top; - u_char flags; - char *p; - - if (!F_ISSET(((BTREE *)t), B_NEEDSWAP)) - return; - if (pg == P_META) { - mswap(pp); - return; - } - - h = pp; - M_32_SWAP(h->pgno); - M_32_SWAP(h->prevpg); - M_32_SWAP(h->nextpg); - M_32_SWAP(h->flags); - M_16_SWAP(h->lower); - M_16_SWAP(h->upper); - - top = NEXTINDEX(h); - if ((h->flags & P_TYPE) == P_BINTERNAL) - for (i = 0; i < top; i++) { - M_16_SWAP(h->linp[i]); - p = (char *)GETBINTERNAL(h, i); - P_32_SWAP(p); - p += sizeof(u_int32_t); - P_32_SWAP(p); - p += sizeof(pgno_t); - if (*(u_char *)p & P_BIGKEY) { - p += sizeof(u_char); - P_32_SWAP(p); - p += sizeof(pgno_t); - P_32_SWAP(p); - } - } - else if ((h->flags & P_TYPE) == P_BLEAF) - for (i = 0; i < top; i++) { - M_16_SWAP(h->linp[i]); - p = (char *)GETBLEAF(h, i); - P_32_SWAP(p); - p += sizeof(u_int32_t); - P_32_SWAP(p); - p += sizeof(u_int32_t); - flags = *(u_char *)p; - if (flags & (P_BIGKEY | P_BIGDATA)) { - p += sizeof(u_char); - if (flags & P_BIGKEY) { - P_32_SWAP(p); - p += sizeof(pgno_t); - P_32_SWAP(p); - } - if (flags & P_BIGDATA) { - p += sizeof(u_int32_t); - P_32_SWAP(p); - p += sizeof(pgno_t); - P_32_SWAP(p); - } - } - } -} - -void -__bt_pgout(t, pg, pp) - void *t; - pgno_t pg; - void *pp; -{ - PAGE *h; - indx_t i, top; - u_char flags; - char *p; - - if (!F_ISSET(((BTREE *)t), B_NEEDSWAP)) - return; - if (pg == P_META) { - mswap(pp); - return; - } - - h = pp; - top = NEXTINDEX(h); - if ((h->flags & P_TYPE) == P_BINTERNAL) - for (i = 0; i < top; i++) { - p = (char *)GETBINTERNAL(h, i); - P_32_SWAP(p); - p += sizeof(u_int32_t); - P_32_SWAP(p); - p += sizeof(pgno_t); - if (*(u_char *)p & P_BIGKEY) { - p += sizeof(u_char); - P_32_SWAP(p); - p += sizeof(pgno_t); - P_32_SWAP(p); - } - M_16_SWAP(h->linp[i]); - } - else if ((h->flags & P_TYPE) == P_BLEAF) - for (i = 0; i < top; i++) { - p = (char *)GETBLEAF(h, i); - P_32_SWAP(p); - p += sizeof(u_int32_t); - P_32_SWAP(p); - p += sizeof(u_int32_t); - flags = *(u_char *)p; - if (flags & (P_BIGKEY | P_BIGDATA)) { - p += sizeof(u_char); - if (flags & P_BIGKEY) { - P_32_SWAP(p); - p += sizeof(pgno_t); - P_32_SWAP(p); - } - if (flags & P_BIGDATA) { - p += sizeof(u_int32_t); - P_32_SWAP(p); - p += sizeof(pgno_t); - P_32_SWAP(p); - } - } - M_16_SWAP(h->linp[i]); - } - - M_32_SWAP(h->pgno); - M_32_SWAP(h->prevpg); - M_32_SWAP(h->nextpg); - M_32_SWAP(h->flags); - M_16_SWAP(h->lower); - M_16_SWAP(h->upper); -} - -/* - * MSWAP -- Actually swap the bytes on the meta page. - * - * Parameters: - * p: page to convert - */ -static void -mswap(pg) - PAGE *pg; -{ - char *p; - - p = (char *)pg; - P_32_SWAP(p); /* magic */ - p += sizeof(u_int32_t); - P_32_SWAP(p); /* version */ - p += sizeof(u_int32_t); - P_32_SWAP(p); /* psize */ - p += sizeof(u_int32_t); - P_32_SWAP(p); /* free */ - p += sizeof(u_int32_t); - P_32_SWAP(p); /* nrecs */ - p += sizeof(u_int32_t); - P_32_SWAP(p); /* flags */ - p += sizeof(u_int32_t); -} diff --git a/main/db1-ast/btree/bt_debug.c b/main/db1-ast/btree/bt_debug.c deleted file mode 100644 index e035851a8..000000000 --- a/main/db1-ast/btree/bt_debug.c +++ /dev/null @@ -1,329 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Mike Olson. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)bt_debug.c 8.5 (Berkeley) 8/17/94"; -#endif /* LIBC_SCCS and not lint */ - -#ifdef DEBUG -#include - -#include -#include -#include - -#include "../include/db.h" -#include "btree.h" - -/* - * BT_DUMP -- Dump the tree - * - * Parameters: - * dbp: pointer to the DB - */ -void -__bt_dump(dbp) - DB *dbp; -{ - BTREE *t; - PAGE *h; - pgno_t i; - char *sep; - - t = dbp->internal; - (void)fprintf(stderr, "%s: pgsz %d", - F_ISSET(t, B_INMEM) ? "memory" : "disk", t->bt_psize); - if (F_ISSET(t, R_RECNO)) - (void)fprintf(stderr, " keys %lu", t->bt_nrecs); -#undef X -#define X(flag, name) \ - if (F_ISSET(t, flag)) { \ - (void)fprintf(stderr, "%s%s", sep, name); \ - sep = ", "; \ - } - if (t->flags != 0) { - sep = " flags ("; - X(R_FIXLEN, "FIXLEN"); - X(B_INMEM, "INMEM"); - X(B_NODUPS, "NODUPS"); - X(B_RDONLY, "RDONLY"); - X(R_RECNO, "RECNO"); - X(B_METADIRTY,"METADIRTY"); - (void)fprintf(stderr, ")\n"); - } -#undef X - - for (i = P_ROOT; (h = mpool_get(t->bt_mp, i, 0)) != NULL; ++i) { - __bt_dpage(h); - (void)mpool_put(t->bt_mp, h, 0); - } -} - -/* - * BT_DMPAGE -- Dump the meta page - * - * Parameters: - * h: pointer to the PAGE - */ -void -__bt_dmpage(h) - PAGE *h; -{ - BTMETA *m; - char *sep; - - m = (BTMETA *)h; - (void)fprintf(stderr, "magic %lx\n", m->magic); - (void)fprintf(stderr, "version %lu\n", m->version); - (void)fprintf(stderr, "psize %lu\n", m->psize); - (void)fprintf(stderr, "free %lu\n", m->free); - (void)fprintf(stderr, "nrecs %lu\n", m->nrecs); - (void)fprintf(stderr, "flags %lu", m->flags); -#undef X -#define X(flag, name) \ - if (m->flags & flag) { \ - (void)fprintf(stderr, "%s%s", sep, name); \ - sep = ", "; \ - } - if (m->flags) { - sep = " ("; - X(B_NODUPS, "NODUPS"); - X(R_RECNO, "RECNO"); - (void)fprintf(stderr, ")"); - } -} - -/* - * BT_DNPAGE -- Dump the page - * - * Parameters: - * n: page number to dump. - */ -void -__bt_dnpage(dbp, pgno) - DB *dbp; - pgno_t pgno; -{ - BTREE *t; - PAGE *h; - - t = dbp->internal; - if ((h = mpool_get(t->bt_mp, pgno, 0)) != NULL) { - __bt_dpage(h); - (void)mpool_put(t->bt_mp, h, 0); - } -} - -/* - * BT_DPAGE -- Dump the page - * - * Parameters: - * h: pointer to the PAGE - */ -void -__bt_dpage(h) - PAGE *h; -{ - BINTERNAL *bi; - BLEAF *bl; - RINTERNAL *ri; - RLEAF *rl; - indx_t cur, top; - char *sep; - - (void)fprintf(stderr, " page %d: (", h->pgno); -#undef X -#define X(flag, name) \ - if (h->flags & flag) { \ - (void)fprintf(stderr, "%s%s", sep, name); \ - sep = ", "; \ - } - sep = ""; - X(P_BINTERNAL, "BINTERNAL") /* types */ - X(P_BLEAF, "BLEAF") - X(P_RINTERNAL, "RINTERNAL") /* types */ - X(P_RLEAF, "RLEAF") - X(P_OVERFLOW, "OVERFLOW") - X(P_PRESERVE, "PRESERVE"); - (void)fprintf(stderr, ")\n"); -#undef X - - (void)fprintf(stderr, "\tprev %2d next %2d", h->prevpg, h->nextpg); - if (h->flags & P_OVERFLOW) - return; - - top = NEXTINDEX(h); - (void)fprintf(stderr, " lower %3d upper %3d nextind %d\n", - h->lower, h->upper, top); - for (cur = 0; cur < top; cur++) { - (void)fprintf(stderr, "\t[%03d] %4d ", cur, h->linp[cur]); - switch (h->flags & P_TYPE) { - case P_BINTERNAL: - bi = GETBINTERNAL(h, cur); - (void)fprintf(stderr, - "size %03d pgno %03d", bi->ksize, bi->pgno); - if (bi->flags & P_BIGKEY) - (void)fprintf(stderr, " (indirect)"); - else if (bi->ksize) - (void)fprintf(stderr, - " {%.*s}", (int)bi->ksize, bi->bytes); - break; - case P_RINTERNAL: - ri = GETRINTERNAL(h, cur); - (void)fprintf(stderr, "entries %03d pgno %03d", - ri->nrecs, ri->pgno); - break; - case P_BLEAF: - bl = GETBLEAF(h, cur); - if (bl->flags & P_BIGKEY) - (void)fprintf(stderr, - "big key page %lu size %u/", - *(pgno_t *)bl->bytes, - *(u_int32_t *)(bl->bytes + sizeof(pgno_t))); - else if (bl->ksize) - (void)fprintf(stderr, "%s/", bl->bytes); - if (bl->flags & P_BIGDATA) - (void)fprintf(stderr, - "big data page %lu size %u", - *(pgno_t *)(bl->bytes + bl->ksize), - *(u_int32_t *)(bl->bytes + bl->ksize + - sizeof(pgno_t))); - else if (bl->dsize) - (void)fprintf(stderr, "%.*s", - (int)bl->dsize, bl->bytes + bl->ksize); - break; - case P_RLEAF: - rl = GETRLEAF(h, cur); - if (rl->flags & P_BIGDATA) - (void)fprintf(stderr, - "big data page %lu size %u", - *(pgno_t *)rl->bytes, - *(u_int32_t *)(rl->bytes + sizeof(pgno_t))); - else if (rl->dsize) - (void)fprintf(stderr, - "%.*s", (int)rl->dsize, rl->bytes); - break; - } - (void)fprintf(stderr, "\n"); - } -} -#endif - -#ifdef STATISTICS -/* - * BT_STAT -- Gather/print the tree statistics - * - * Parameters: - * dbp: pointer to the DB - */ -void -__bt_stat(dbp) - DB *dbp; -{ - extern u_long bt_cache_hit, bt_cache_miss, bt_pfxsaved, bt_rootsplit; - extern u_long bt_sortsplit, bt_split; - BTREE *t; - PAGE *h; - pgno_t i, pcont, pinternal, pleaf; - u_long ifree, lfree, nkeys; - int levels; - - t = dbp->internal; - pcont = pinternal = pleaf = 0; - nkeys = ifree = lfree = 0; - for (i = P_ROOT; (h = mpool_get(t->bt_mp, i, 0)) != NULL; ++i) { - switch (h->flags & P_TYPE) { - case P_BINTERNAL: - case P_RINTERNAL: - ++pinternal; - ifree += h->upper - h->lower; - break; - case P_BLEAF: - case P_RLEAF: - ++pleaf; - lfree += h->upper - h->lower; - nkeys += NEXTINDEX(h); - break; - case P_OVERFLOW: - ++pcont; - break; - } - (void)mpool_put(t->bt_mp, h, 0); - } - - /* Count the levels of the tree. */ - for (i = P_ROOT, levels = 0 ;; ++levels) { - h = mpool_get(t->bt_mp, i, 0); - if (h->flags & (P_BLEAF|P_RLEAF)) { - if (levels == 0) - levels = 1; - (void)mpool_put(t->bt_mp, h, 0); - break; - } - i = F_ISSET(t, R_RECNO) ? - GETRINTERNAL(h, 0)->pgno : - GETBINTERNAL(h, 0)->pgno; - (void)mpool_put(t->bt_mp, h, 0); - } - - (void)fprintf(stderr, "%d level%s with %ld keys", - levels, levels == 1 ? "" : "s", nkeys); - if (F_ISSET(t, R_RECNO)) - (void)fprintf(stderr, " (%ld header count)", t->bt_nrecs); - (void)fprintf(stderr, - "\n%lu pages (leaf %ld, internal %ld, overflow %ld)\n", - pinternal + pleaf + pcont, pleaf, pinternal, pcont); - (void)fprintf(stderr, "%ld cache hits, %ld cache misses\n", - bt_cache_hit, bt_cache_miss); - (void)fprintf(stderr, "%ld splits (%ld root splits, %ld sort splits)\n", - bt_split, bt_rootsplit, bt_sortsplit); - pleaf *= t->bt_psize - BTDATAOFF; - if (pleaf) - (void)fprintf(stderr, - "%.0f%% leaf fill (%ld bytes used, %ld bytes free)\n", - ((double)(pleaf - lfree) / pleaf) * 100, - pleaf - lfree, lfree); - pinternal *= t->bt_psize - BTDATAOFF; - if (pinternal) - (void)fprintf(stderr, - "%.0f%% internal fill (%ld bytes used, %ld bytes free\n", - ((double)(pinternal - ifree) / pinternal) * 100, - pinternal - ifree, ifree); - if (bt_pfxsaved) - (void)fprintf(stderr, "prefix checking removed %lu bytes.\n", - bt_pfxsaved); -} -#endif diff --git a/main/db1-ast/btree/bt_delete.c b/main/db1-ast/btree/bt_delete.c deleted file mode 100644 index 6e3883db9..000000000 --- a/main/db1-ast/btree/bt_delete.c +++ /dev/null @@ -1,657 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Mike Olson. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)bt_delete.c 8.13 (Berkeley) 7/28/94"; -#endif /* LIBC_SCCS and not lint */ - -#include - -#include -#include -#include - -#include "../include/db.h" -#include "btree.h" - -static int __bt_bdelete __P((BTREE *, const DBT *)); -static int __bt_curdel __P((BTREE *, const DBT *, PAGE *, u_int)); -static int __bt_pdelete __P((BTREE *, PAGE *)); -static int __bt_relink __P((BTREE *, PAGE *)); -static int __bt_stkacq __P((BTREE *, PAGE **, CURSOR *)); - -/* - * __bt_delete - * Delete the item(s) referenced by a key. - * - * Return RET_SPECIAL if the key is not found. - */ -int -__bt_delete(dbp, key, flags) - const DB *dbp; - const DBT *key; - u_int flags; -{ - BTREE *t; - CURSOR *c; - PAGE *h; - int status; - - t = dbp->internal; - - /* Toss any page pinned across calls. */ - if (t->bt_pinned != NULL) { - mpool_put(t->bt_mp, t->bt_pinned, 0); - t->bt_pinned = NULL; - } - - /* Check for change to a read-only tree. */ - if (F_ISSET(t, B_RDONLY)) { - errno = EPERM; - return (RET_ERROR); - } - - switch (flags) { - case 0: - status = __bt_bdelete(t, key); - break; - case R_CURSOR: - /* - * If flags is R_CURSOR, delete the cursor. Must already - * have started a scan and not have already deleted it. - */ - c = &t->bt_cursor; - if (F_ISSET(c, CURS_INIT)) { - if (F_ISSET(c, CURS_ACQUIRE | CURS_AFTER | CURS_BEFORE)) - return (RET_SPECIAL); - if ((h = mpool_get(t->bt_mp, c->pg.pgno, 0)) == NULL) - return (RET_ERROR); - - /* - * If the page is about to be emptied, we'll need to - * delete it, which means we have to acquire a stack. - */ - if (NEXTINDEX(h) == 1) - if (__bt_stkacq(t, &h, &t->bt_cursor)) - return (RET_ERROR); - - status = __bt_dleaf(t, NULL, h, c->pg.index); - - if (NEXTINDEX(h) == 0 && status == RET_SUCCESS) { - if (__bt_pdelete(t, h)) - return (RET_ERROR); - } else - mpool_put(t->bt_mp, - h, status == RET_SUCCESS ? MPOOL_DIRTY : 0); - break; - } - /* FALLTHROUGH */ - default: - errno = EINVAL; - return (RET_ERROR); - } - if (status == RET_SUCCESS) - F_SET(t, B_MODIFIED); - return (status); -} - -/* - * __bt_stkacq -- - * Acquire a stack so we can delete a cursor entry. - * - * Parameters: - * t: tree - * hp: pointer to current, pinned PAGE pointer - * c: pointer to the cursor - * - * Returns: - * 0 on success, 1 on failure - */ -static int -__bt_stkacq(t, hp, c) - BTREE *t; - PAGE **hp; - CURSOR *c; -{ - BINTERNAL *bi; - EPG *e; - EPGNO *parent; - PAGE *h; - indx_t idx = 0; - pgno_t pgno; - recno_t nextpg, prevpg; - int exact, level; - - /* - * Find the first occurrence of the key in the tree. Toss the - * currently locked page so we don't hit an already-locked page. - */ - h = *hp; - mpool_put(t->bt_mp, h, 0); - if ((e = __bt_search(t, &c->key, &exact)) == NULL) - return (1); - h = e->page; - - /* See if we got it in one shot. */ - if (h->pgno == c->pg.pgno) - goto ret; - - /* - * Move right, looking for the page. At each move we have to move - * up the stack until we don't have to move to the next page. If - * we have to change pages at an internal level, we have to fix the - * stack back up. - */ - while (h->pgno != c->pg.pgno) { - if ((nextpg = h->nextpg) == P_INVALID) - break; - mpool_put(t->bt_mp, h, 0); - - /* Move up the stack. */ - for (level = 0; (parent = BT_POP(t)) != NULL; ++level) { - /* Get the parent page. */ - if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL) - return (1); - - /* Move to the next index. */ - if (parent->index != NEXTINDEX(h) - 1) { - idx = parent->index + 1; - BT_PUSH(t, h->pgno, idx); - break; - } - mpool_put(t->bt_mp, h, 0); - } - - /* Restore the stack. */ - while (level--) { - /* Push the next level down onto the stack. */ - bi = GETBINTERNAL(h, idx); - pgno = bi->pgno; - BT_PUSH(t, pgno, 0); - - /* Lose the currently pinned page. */ - mpool_put(t->bt_mp, h, 0); - - /* Get the next level down. */ - if ((h = mpool_get(t->bt_mp, pgno, 0)) == NULL) - return (1); - idx = 0; - } - mpool_put(t->bt_mp, h, 0); - if ((h = mpool_get(t->bt_mp, nextpg, 0)) == NULL) - return (1); - } - - if (h->pgno == c->pg.pgno) - goto ret; - - /* Reacquire the original stack. */ - mpool_put(t->bt_mp, h, 0); - if ((e = __bt_search(t, &c->key, &exact)) == NULL) - return (1); - h = e->page; - - /* - * Move left, looking for the page. At each move we have to move - * up the stack until we don't have to change pages to move to the - * next page. If we have to change pages at an internal level, we - * have to fix the stack back up. - */ - while (h->pgno != c->pg.pgno) { - if ((prevpg = h->prevpg) == P_INVALID) - break; - mpool_put(t->bt_mp, h, 0); - - /* Move up the stack. */ - for (level = 0; (parent = BT_POP(t)) != NULL; ++level) { - /* Get the parent page. */ - if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL) - return (1); - - /* Move to the next index. */ - if (parent->index != 0) { - idx = parent->index - 1; - BT_PUSH(t, h->pgno, idx); - break; - } - mpool_put(t->bt_mp, h, 0); - } - - /* Restore the stack. */ - while (level--) { - /* Push the next level down onto the stack. */ - bi = GETBINTERNAL(h, idx); - pgno = bi->pgno; - - /* Lose the currently pinned page. */ - mpool_put(t->bt_mp, h, 0); - - /* Get the next level down. */ - if ((h = mpool_get(t->bt_mp, pgno, 0)) == NULL) - return (1); - - idx = NEXTINDEX(h) - 1; - BT_PUSH(t, pgno, idx); - } - mpool_put(t->bt_mp, h, 0); - if ((h = mpool_get(t->bt_mp, prevpg, 0)) == NULL) - return (1); - } - - -ret: mpool_put(t->bt_mp, h, 0); - return ((*hp = mpool_get(t->bt_mp, c->pg.pgno, 0)) == NULL); -} - -/* - * __bt_bdelete -- - * Delete all key/data pairs matching the specified key. - * - * Parameters: - * t: tree - * key: key to delete - * - * Returns: - * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found. - */ -static int -__bt_bdelete(t, key) - BTREE *t; - const DBT *key; -{ - EPG *e; - PAGE *h; - int deleted, exact, redo; - - deleted = 0; - - /* Find any matching record; __bt_search pins the page. */ -loop: if ((e = __bt_search(t, key, &exact)) == NULL) - return (deleted ? RET_SUCCESS : RET_ERROR); - if (!exact) { - mpool_put(t->bt_mp, e->page, 0); - return (deleted ? RET_SUCCESS : RET_SPECIAL); - } - - /* - * Delete forward, then delete backward, from the found key. If - * there are duplicates and we reach either side of the page, do - * the key search again, so that we get them all. - */ - redo = 0; - h = e->page; - do { - if (__bt_dleaf(t, key, h, e->index)) { - mpool_put(t->bt_mp, h, 0); - return (RET_ERROR); - } - if (F_ISSET(t, B_NODUPS)) { - if (NEXTINDEX(h) == 0) { - if (__bt_pdelete(t, h)) - return (RET_ERROR); - } else - mpool_put(t->bt_mp, h, MPOOL_DIRTY); - return (RET_SUCCESS); - } - deleted = 1; - } while (e->index < NEXTINDEX(h) && __bt_cmp(t, key, e) == 0); - - /* Check for right-hand edge of the page. */ - if (e->index == NEXTINDEX(h)) - redo = 1; - - /* Delete from the key to the beginning of the page. */ - while (e->index-- > 0) { - if (__bt_cmp(t, key, e) != 0) - break; - if (__bt_dleaf(t, key, h, e->index) == RET_ERROR) { - mpool_put(t->bt_mp, h, 0); - return (RET_ERROR); - } - if (e->index == 0) - redo = 1; - } - - /* Check for an empty page. */ - if (NEXTINDEX(h) == 0) { - if (__bt_pdelete(t, h)) - return (RET_ERROR); - goto loop; - } - - /* Put the page. */ - mpool_put(t->bt_mp, h, MPOOL_DIRTY); - - if (redo) - goto loop; - return (RET_SUCCESS); -} - -/* - * __bt_pdelete -- - * Delete a single page from the tree. - * - * Parameters: - * t: tree - * h: leaf page - * - * Returns: - * RET_SUCCESS, RET_ERROR. - * - * Side-effects: - * mpool_put's the page - */ -static int -__bt_pdelete(t, h) - BTREE *t; - PAGE *h; -{ - BINTERNAL *bi; - PAGE *pg; - EPGNO *parent; - indx_t cnt, idx, *ip, offset; - u_int32_t nksize; - char *from; - - /* - * Walk the parent page stack -- a LIFO stack of the pages that were - * traversed when we searched for the page where the delete occurred. - * Each stack entry is a page number and a page index offset. The - * offset is for the page traversed on the search. We've just deleted - * a page, so we have to delete the key from the parent page. - * - * If the delete from the parent page makes it empty, this process may - * continue all the way up the tree. We stop if we reach the root page - * (which is never deleted, it's just not worth the effort) or if the - * delete does not empty the page. - */ - while ((parent = BT_POP(t)) != NULL) { - /* Get the parent page. */ - if ((pg = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL) - return (RET_ERROR); - - idx = parent->index; - bi = GETBINTERNAL(pg, idx); - - /* Free any overflow pages. */ - if (bi->flags & P_BIGKEY && - __ovfl_delete(t, bi->bytes) == RET_ERROR) { - mpool_put(t->bt_mp, pg, 0); - return (RET_ERROR); - } - - /* - * Free the parent if it has only the one key and it's not the - * root page. If it's the rootpage, turn it back into an empty - * leaf page. - */ - if (NEXTINDEX(pg) == 1) { - if (pg->pgno == P_ROOT) { - pg->lower = BTDATAOFF; - pg->upper = t->bt_psize; - pg->flags = P_BLEAF; - } else { - if (__bt_relink(t, pg) || __bt_free(t, pg)) - return (RET_ERROR); - continue; - } - } else { - /* Pack remaining key items at the end of the page. */ - nksize = NBINTERNAL(bi->ksize); - from = (char *)pg + pg->upper; - memmove(from + nksize, from, (char *)bi - from); - pg->upper += nksize; - - /* Adjust indices' offsets, shift the indices down. */ - offset = pg->linp[idx]; - for (cnt = idx, ip = &pg->linp[0]; cnt--; ++ip) - if (ip[0] < offset) - ip[0] += nksize; - for (cnt = NEXTINDEX(pg) - idx; --cnt; ++ip) - ip[0] = ip[1] < offset ? ip[1] + nksize : ip[1]; - pg->lower -= sizeof(indx_t); - } - - mpool_put(t->bt_mp, pg, MPOOL_DIRTY); - break; - } - - /* Free the leaf page, as long as it wasn't the root. */ - if (h->pgno == P_ROOT) { - mpool_put(t->bt_mp, h, MPOOL_DIRTY); - return (RET_SUCCESS); - } - return (__bt_relink(t, h) || __bt_free(t, h)); -} - -/* - * __bt_dleaf -- - * Delete a single record from a leaf page. - * - * Parameters: - * t: tree - * key: referenced key - * h: page - * index: index on page to delete - * - * Returns: - * RET_SUCCESS, RET_ERROR. - */ -int -__bt_dleaf(t, key, h, idx) - BTREE *t; - const DBT *key; - PAGE *h; - u_int idx; -{ - BLEAF *bl; - indx_t cnt, *ip, offset; - u_int32_t nbytes; - void *to; - char *from; - - /* If this record is referenced by the cursor, delete the cursor. */ - if (F_ISSET(&t->bt_cursor, CURS_INIT) && - !F_ISSET(&t->bt_cursor, CURS_ACQUIRE) && - t->bt_cursor.pg.pgno == h->pgno && t->bt_cursor.pg.index == idx && - __bt_curdel(t, key, h, idx)) - return (RET_ERROR); - - /* If the entry uses overflow pages, make them available for reuse. */ - to = bl = GETBLEAF(h, idx); - if (bl->flags & P_BIGKEY && __ovfl_delete(t, bl->bytes) == RET_ERROR) - return (RET_ERROR); - if (bl->flags & P_BIGDATA && - __ovfl_delete(t, bl->bytes + bl->ksize) == RET_ERROR) - return (RET_ERROR); - - /* Pack the remaining key/data items at the end of the page. */ - nbytes = NBLEAF(bl); - from = (char *)h + h->upper; - memmove(from + nbytes, from, (char *)to - from); - h->upper += nbytes; - - /* Adjust the indices' offsets, shift the indices down. */ - offset = h->linp[idx]; - for (cnt = idx, ip = &h->linp[0]; cnt--; ++ip) - if (ip[0] < offset) - ip[0] += nbytes; - for (cnt = NEXTINDEX(h) - idx; --cnt; ++ip) - ip[0] = ip[1] < offset ? ip[1] + nbytes : ip[1]; - h->lower -= sizeof(indx_t); - - /* If the cursor is on this page, adjust it as necessary. */ - if (F_ISSET(&t->bt_cursor, CURS_INIT) && - !F_ISSET(&t->bt_cursor, CURS_ACQUIRE) && - t->bt_cursor.pg.pgno == h->pgno && t->bt_cursor.pg.index > idx) - --t->bt_cursor.pg.index; - - return (RET_SUCCESS); -} - -/* - * __bt_curdel -- - * Delete the cursor. - * - * Parameters: - * t: tree - * key: referenced key (or NULL) - * h: page - * index: index on page to delete - * - * Returns: - * RET_SUCCESS, RET_ERROR. - */ -static int -__bt_curdel(t, key, h, idx) - BTREE *t; - const DBT *key; - PAGE *h; - u_int idx; -{ - CURSOR *c; - EPG e; - PAGE *pg; - int curcopy, status; - - /* - * If there are duplicates, move forward or backward to one. - * Otherwise, copy the key into the cursor area. - */ - c = &t->bt_cursor; - F_CLR(c, CURS_AFTER | CURS_BEFORE | CURS_ACQUIRE); - - curcopy = 0; - if (!F_ISSET(t, B_NODUPS)) { - /* - * We're going to have to do comparisons. If we weren't - * provided a copy of the key, i.e. the user is deleting - * the current cursor position, get one. - */ - if (key == NULL) { - e.page = h; - e.index = idx; - if ((status = __bt_ret(t, &e, - &c->key, &c->key, NULL, NULL, 1)) != RET_SUCCESS) - return (status); - curcopy = 1; - key = &c->key; - } - /* Check previous key, if not at the beginning of the page. */ - if (idx > 0) { - e.page = h; - e.index = idx - 1; - if (__bt_cmp(t, key, &e) == 0) { - F_SET(c, CURS_BEFORE); - goto dup2; - } - } - /* Check next key, if not at the end of the page. */ - if (idx < NEXTINDEX(h) - 1) { - e.page = h; - e.index = idx + 1; - if (__bt_cmp(t, key, &e) == 0) { - F_SET(c, CURS_AFTER); - goto dup2; - } - } - /* Check previous key if at the beginning of the page. */ - if (idx == 0 && h->prevpg != P_INVALID) { - if ((pg = mpool_get(t->bt_mp, h->prevpg, 0)) == NULL) - return (RET_ERROR); - e.page = pg; - e.index = NEXTINDEX(pg) - 1; - if (__bt_cmp(t, key, &e) == 0) { - F_SET(c, CURS_BEFORE); - goto dup1; - } - mpool_put(t->bt_mp, pg, 0); - } - /* Check next key if at the end of the page. */ - if (idx == NEXTINDEX(h) - 1 && h->nextpg != P_INVALID) { - if ((pg = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL) - return (RET_ERROR); - e.page = pg; - e.index = 0; - if (__bt_cmp(t, key, &e) == 0) { - F_SET(c, CURS_AFTER); -dup1: mpool_put(t->bt_mp, pg, 0); -dup2: c->pg.pgno = e.page->pgno; - c->pg.index = e.index; - return (RET_SUCCESS); - } - mpool_put(t->bt_mp, pg, 0); - } - } - e.page = h; - e.index = idx; - if (curcopy || (status = - __bt_ret(t, &e, &c->key, &c->key, NULL, NULL, 1)) == RET_SUCCESS) { - F_SET(c, CURS_ACQUIRE); - return (RET_SUCCESS); - } - return (status); -} - -/* - * __bt_relink -- - * Link around a deleted page. - * - * Parameters: - * t: tree - * h: page to be deleted - */ -static int -__bt_relink(t, h) - BTREE *t; - PAGE *h; -{ - PAGE *pg; - - if (h->nextpg != P_INVALID) { - if ((pg = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL) - return (RET_ERROR); - pg->prevpg = h->prevpg; - mpool_put(t->bt_mp, pg, MPOOL_DIRTY); - } - if (h->prevpg != P_INVALID) { - if ((pg = mpool_get(t->bt_mp, h->prevpg, 0)) == NULL) - return (RET_ERROR); - pg->nextpg = h->nextpg; - mpool_put(t->bt_mp, pg, MPOOL_DIRTY); - } - return (0); -} diff --git a/main/db1-ast/btree/bt_get.c b/main/db1-ast/btree/bt_get.c deleted file mode 100644 index b5e18022c..000000000 --- a/main/db1-ast/btree/bt_get.c +++ /dev/null @@ -1,105 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Mike Olson. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)bt_get.c 8.6 (Berkeley) 7/20/94"; -#endif /* LIBC_SCCS and not lint */ - -#include - -#include -#include -#include - -#include "../include/db.h" -#include "btree.h" - -/* - * __BT_GET -- Get a record from the btree. - * - * Parameters: - * dbp: pointer to access method - * key: key to find - * data: data to return - * flag: currently unused - * - * Returns: - * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found. - */ -int -__bt_get(dbp, key, data, flags) - const DB *dbp; - const DBT *key; - DBT *data; - u_int flags; -{ - BTREE *t; - EPG *e; - int exact, status; - - t = dbp->internal; - - /* Toss any page pinned across calls. */ - if (t->bt_pinned != NULL) { - mpool_put(t->bt_mp, t->bt_pinned, 0); - t->bt_pinned = NULL; - } - - /* Get currently doesn't take any flags. */ - if (flags) { - errno = EINVAL; - return (RET_ERROR); - } - - if ((e = __bt_search(t, key, &exact)) == NULL) - return (RET_ERROR); - if (!exact) { - mpool_put(t->bt_mp, e->page, 0); - return (RET_SPECIAL); - } - - status = __bt_ret(t, e, NULL, NULL, data, &t->bt_rdata, 0); - - /* - * If the user is doing concurrent access, we copied the - * key/data, toss the page. - */ - if (F_ISSET(t, B_DB_LOCK)) - mpool_put(t->bt_mp, e->page, 0); - else - t->bt_pinned = e->page; - return (status); -} diff --git a/main/db1-ast/btree/bt_open.c b/main/db1-ast/btree/bt_open.c deleted file mode 100644 index 5d40e4593..000000000 --- a/main/db1-ast/btree/bt_open.c +++ /dev/null @@ -1,458 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Mike Olson. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)bt_open.c 8.10 (Berkeley) 8/17/94"; -#endif /* LIBC_SCCS and not lint */ - -/* - * Implementation of btree access method for 4.4BSD. - * - * The design here was originally based on that of the btree access method - * used in the Postgres database system at UC Berkeley. This implementation - * is wholly independent of the Postgres code. - */ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../include/db.h" -#include "btree.h" - -#ifdef DEBUG -#undef MINPSIZE -#define MINPSIZE 128 -#endif - -static int byteorder __P((void)); -static int nroot __P((BTREE *)); -static int tmp __P((void)); - -/* - * __BT_OPEN -- Open a btree. - * - * Creates and fills a DB struct, and calls the routine that actually - * opens the btree. - * - * Parameters: - * fname: filename (NULL for in-memory trees) - * flags: open flag bits - * mode: open permission bits - * b: BTREEINFO pointer - * - * Returns: - * NULL on failure, pointer to DB on success. - * - */ -DB * -__bt_open(fname, flags, mode, openinfo, dflags) - const char *fname; - int flags, mode, dflags; - const BTREEINFO *openinfo; -{ - struct stat sb; - BTMETA m; - BTREE *t; - BTREEINFO b; - DB *dbp; - pgno_t ncache; - ssize_t nr; - int machine_lorder; - - t = NULL; - - /* - * Intention is to make sure all of the user's selections are okay - * here and then use them without checking. Can't be complete, since - * we don't know the right page size, lorder or flags until the backing - * file is opened. Also, the file's page size can cause the cachesize - * to change. - */ - machine_lorder = byteorder(); - if (openinfo) { - b = *openinfo; - - /* Flags: R_DUP. */ - if (b.flags & ~(R_DUP)) - goto einval; - - /* - * Page size must be indx_t aligned and >= MINPSIZE. Default - * page size is set farther on, based on the underlying file - * transfer size. - */ - if (b.psize && - (b.psize < MINPSIZE || b.psize > MAX_PAGE_OFFSET + 1 || - b.psize & (sizeof(indx_t) - 1))) - goto einval; - - /* Minimum number of keys per page; absolute minimum is 2. */ - if (b.minkeypage) { - if (b.minkeypage < 2) - goto einval; - } else - b.minkeypage = DEFMINKEYPAGE; - - /* If no comparison, use default comparison and prefix. */ - if (b.compare == NULL) { - b.compare = __bt_defcmp; - if (b.prefix == NULL) - b.prefix = __bt_defpfx; - } - - if (b.lorder == 0) - b.lorder = machine_lorder; - } else { - b.compare = __bt_defcmp; - b.cachesize = 0; - b.flags = 0; - b.lorder = machine_lorder; - b.minkeypage = DEFMINKEYPAGE; - b.prefix = __bt_defpfx; - b.psize = 0; - } - - /* Check for the ubiquitous PDP-11. */ - if (b.lorder != BIG_ENDIAN && b.lorder != LITTLE_ENDIAN) - goto einval; - - /* Allocate and initialize DB and BTREE structures. */ - if ((t = (BTREE *)malloc(sizeof(BTREE))) == NULL) - goto err; - memset(t, 0, sizeof(BTREE)); - t->bt_fd = -1; /* Don't close unopened fd on error. */ - t->bt_lorder = b.lorder; - t->bt_order = NOT; - t->bt_cmp = b.compare; - t->bt_pfx = b.prefix; - t->bt_rfd = -1; - - if ((t->bt_dbp = dbp = (DB *)malloc(sizeof(DB))) == NULL) - goto err; - memset(t->bt_dbp, 0, sizeof(DB)); - if (t->bt_lorder != machine_lorder) - F_SET(t, B_NEEDSWAP); - - dbp->type = DB_BTREE; - dbp->internal = t; - dbp->close = __bt_close; - dbp->del = __bt_delete; - dbp->fd = __bt_fd; - dbp->get = __bt_get; - dbp->put = __bt_put; - dbp->seq = __bt_seq; - dbp->sync = __bt_sync; - - /* - * If no file name was supplied, this is an in-memory btree and we - * open a backing temporary file. Otherwise, it's a disk-based tree. - */ - if (fname) { - switch (flags & O_ACCMODE) { - case O_RDONLY: - F_SET(t, B_RDONLY); - break; - case O_RDWR: - break; - case O_WRONLY: - default: - goto einval; - } - - if ((t->bt_fd = open(fname, flags, mode)) < 0) - goto err; - - } else { - if ((flags & O_ACCMODE) != O_RDWR) - goto einval; - if ((t->bt_fd = tmp()) == -1) - goto err; - F_SET(t, B_INMEM); - } - - if (fcntl(t->bt_fd, F_SETFD, 1) == -1) - goto err; - - if (fstat(t->bt_fd, &sb)) - goto err; - if (sb.st_size) { - if ((nr = read(t->bt_fd, &m, sizeof(BTMETA))) < 0) - goto err; - if (nr != sizeof(BTMETA)) - goto eftype; - - /* - * Read in the meta-data. This can change the notion of what - * the lorder, page size and flags are, and, when the page size - * changes, the cachesize value can change too. If the user - * specified the wrong byte order for an existing database, we - * don't bother to return an error, we just clear the NEEDSWAP - * bit. - */ - if (m.magic == BTREEMAGIC) - F_CLR(t, B_NEEDSWAP); - else { - F_SET(t, B_NEEDSWAP); - M_32_SWAP(m.magic); - M_32_SWAP(m.version); - M_32_SWAP(m.psize); - M_32_SWAP(m.free); - M_32_SWAP(m.nrecs); - M_32_SWAP(m.flags); - } - if (m.magic != BTREEMAGIC || m.version != BTREEVERSION) - goto eftype; - if (m.psize < MINPSIZE || m.psize > MAX_PAGE_OFFSET + 1 || - m.psize & (sizeof(indx_t) - 1)) - goto eftype; - if (m.flags & ~SAVEMETA) - goto eftype; - b.psize = m.psize; - F_SET(t, m.flags); - t->bt_free = m.free; - t->bt_nrecs = m.nrecs; - } else { - /* - * Set the page size to the best value for I/O to this file. - * Don't overflow the page offset type. - */ - if (b.psize == 0) { -#ifdef _STATBUF_ST_BLKSIZE - b.psize = sb.st_blksize; -#endif - if (b.psize < MINPSIZE) - b.psize = MINPSIZE; - if (b.psize > MAX_PAGE_OFFSET + 1) - b.psize = MAX_PAGE_OFFSET + 1; - } - - /* Set flag if duplicates permitted. */ - if (!(b.flags & R_DUP)) - F_SET(t, B_NODUPS); - - t->bt_free = P_INVALID; - t->bt_nrecs = 0; - F_SET(t, B_METADIRTY); - } - - t->bt_psize = b.psize; - - /* Set the cache size; must be a multiple of the page size. */ - if (b.cachesize && b.cachesize & (b.psize - 1)) - b.cachesize += (~b.cachesize & (b.psize - 1)) + 1; - if (b.cachesize < b.psize * MINCACHE) - b.cachesize = b.psize * MINCACHE; - - /* Calculate number of pages to cache. */ - ncache = (b.cachesize + t->bt_psize - 1) / t->bt_psize; - - /* - * The btree data structure requires that at least two keys can fit on - * a page, but other than that there's no fixed requirement. The user - * specified a minimum number per page, and we translated that into the - * number of bytes a key/data pair can use before being placed on an - * overflow page. This calculation includes the page header, the size - * of the index referencing the leaf item and the size of the leaf item - * structure. Also, don't let the user specify a minkeypage such that - * a key/data pair won't fit even if both key and data are on overflow - * pages. - */ - t->bt_ovflsize = (t->bt_psize - BTDATAOFF) / b.minkeypage - - (sizeof(indx_t) + NBLEAFDBT(0, 0)); - if (t->bt_ovflsize < NBLEAFDBT(NOVFLSIZE, NOVFLSIZE) + sizeof(indx_t)) - t->bt_ovflsize = - NBLEAFDBT(NOVFLSIZE, NOVFLSIZE) + sizeof(indx_t); - - /* Initialize the buffer pool. */ - if ((t->bt_mp = - mpool_open(NULL, t->bt_fd, t->bt_psize, ncache)) == NULL) - goto err; - if (!F_ISSET(t, B_INMEM)) - mpool_filter(t->bt_mp, __bt_pgin, __bt_pgout, t); - - /* Create a root page if new tree. */ - if (nroot(t) == RET_ERROR) - goto err; - - /* Global flags. */ - if (dflags & DB_LOCK) - F_SET(t, B_DB_LOCK); - if (dflags & DB_SHMEM) - F_SET(t, B_DB_SHMEM); - if (dflags & DB_TXN) - F_SET(t, B_DB_TXN); - - return (dbp); - -einval: errno = EINVAL; - goto err; - -eftype: errno = EFTYPE; - goto err; - -err: if (t) { - if (t->bt_dbp) - free(t->bt_dbp); - if (t->bt_fd != -1) - (void)close(t->bt_fd); - free(t); - } - return (NULL); -} - -/* - * NROOT -- Create the root of a new tree. - * - * Parameters: - * t: tree - * - * Returns: - * RET_ERROR, RET_SUCCESS - */ -static int -nroot(t) - BTREE *t; -{ - PAGE *meta, *root; - pgno_t npg; - - if ((meta = mpool_get(t->bt_mp, 0, 0)) != NULL) { - mpool_put(t->bt_mp, meta, 0); - return (RET_SUCCESS); - } - if (errno != EINVAL) /* It's OK to not exist. */ - return (RET_ERROR); - errno = 0; - - if ((meta = mpool_new(t->bt_mp, &npg)) == NULL) - return (RET_ERROR); - - if ((root = mpool_new(t->bt_mp, &npg)) == NULL) - return (RET_ERROR); - - if (npg != P_ROOT) - return (RET_ERROR); - root->pgno = npg; - root->prevpg = root->nextpg = P_INVALID; - root->lower = BTDATAOFF; - root->upper = t->bt_psize; - root->flags = P_BLEAF; - memset(meta, 0, t->bt_psize); - mpool_put(t->bt_mp, meta, MPOOL_DIRTY); - mpool_put(t->bt_mp, root, MPOOL_DIRTY); - return (RET_SUCCESS); -} - -static int -tmp() -{ - sigset_t set, oset; - int fd; - const char *envtmp; - char *path; - static const char fmt[] = "%s/bt.XXXXXX"; - size_t n; - - envtmp = getenv("TMPDIR"); - if (!envtmp) - envtmp = "/tmp"; - n = strlen (envtmp) + sizeof fmt; -#ifdef __GNUC__ - path = __builtin_alloca(n); -#else - path = malloc(n); -#endif - (void)snprintf(path, n, fmt, envtmp ? envtmp : "/tmp"); - - (void)sigfillset(&set); - (void)sigprocmask(SIG_BLOCK, &set, &oset); - if ((fd = mkstemp(path)) != -1) - (void)unlink(path); - (void)sigprocmask(SIG_SETMASK, &oset, NULL); -#ifndef __GNUC__ - free(path); -#endif - return(fd); -} - -static int -byteorder() -{ - u_int32_t x; - u_char *p; - - x = 0x01020304; - p = (u_char *)&x; - switch (*p) { - case 1: - return (BIG_ENDIAN); - case 4: - return (LITTLE_ENDIAN); - default: - return (0); - } -} - -int -__bt_fd(dbp) - const DB *dbp; -{ - BTREE *t; - - t = dbp->internal; - - /* Toss any page pinned across calls. */ - if (t->bt_pinned != NULL) { - mpool_put(t->bt_mp, t->bt_pinned, 0); - t->bt_pinned = NULL; - } - - /* In-memory database can't have a file descriptor. */ - if (F_ISSET(t, B_INMEM)) { - errno = ENOENT; - return (-1); - } - return (t->bt_fd); -} diff --git a/main/db1-ast/btree/bt_overflow.c b/main/db1-ast/btree/bt_overflow.c deleted file mode 100644 index d8f310d91..000000000 --- a/main/db1-ast/btree/bt_overflow.c +++ /dev/null @@ -1,228 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Mike Olson. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)bt_overflow.c 8.5 (Berkeley) 7/16/94"; -#endif /* LIBC_SCCS and not lint */ - -#include - -#include -#include -#include - -#include "../include/db.h" -#include "btree.h" - -/* - * Big key/data code. - * - * Big key and data entries are stored on linked lists of pages. The initial - * reference is byte string stored with the key or data and is the page number - * and size. The actual record is stored in a chain of pages linked by the - * nextpg field of the PAGE header. - * - * The first page of the chain has a special property. If the record is used - * by an internal page, it cannot be deleted and the P_PRESERVE bit will be set - * in the header. - * - * XXX - * A single DBT is written to each chain, so a lot of space on the last page - * is wasted. This is a fairly major bug for some data sets. - */ - -/* - * __OVFL_GET -- Get an overflow key/data item. - * - * Parameters: - * t: tree - * p: pointer to { pgno_t, u_int32_t } - * buf: storage address - * bufsz: storage size - * - * Returns: - * RET_ERROR, RET_SUCCESS - */ -int -__ovfl_get(t, p, ssz, buf, bufsz) - BTREE *t; - void *p; - size_t *ssz; - void **buf; - size_t *bufsz; -{ - PAGE *h; - pgno_t pg; - size_t nb, plen; - u_int32_t sz; - - memmove(&pg, p, sizeof(pgno_t)); - memmove(&sz, (char *)p + sizeof(pgno_t), sizeof(u_int32_t)); - *ssz = sz; - -#ifdef DEBUG - if (pg == P_INVALID || sz == 0) - abort(); -#endif - /* Make the buffer bigger as necessary. */ - if (*bufsz < sz) { - *buf = (char *)(*buf == NULL ? malloc(sz) : realloc(*buf, sz)); - if (*buf == NULL) - return (RET_ERROR); - *bufsz = sz; - } - - /* - * Step through the linked list of pages, copying the data on each one - * into the buffer. Never copy more than the data's length. - */ - plen = t->bt_psize - BTDATAOFF; - for (p = *buf;; p = (char *)p + nb, pg = h->nextpg) { - if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) - return (RET_ERROR); - - nb = MIN(sz, plen); - memmove(p, (char *)h + BTDATAOFF, nb); - mpool_put(t->bt_mp, h, 0); - - if ((sz -= nb) == 0) - break; - } - return (RET_SUCCESS); -} - -/* - * __OVFL_PUT -- Store an overflow key/data item. - * - * Parameters: - * t: tree - * data: DBT to store - * pgno: storage page number - * - * Returns: - * RET_ERROR, RET_SUCCESS - */ -int -__ovfl_put(t, dbt, pg) - BTREE *t; - const DBT *dbt; - pgno_t *pg; -{ - PAGE *h, *last; - void *p; - pgno_t npg; - size_t nb, plen; - u_int32_t sz; - - /* - * Allocate pages and copy the key/data record into them. Store the - * number of the first page in the chain. - */ - plen = t->bt_psize - BTDATAOFF; - for (last = NULL, p = dbt->data, sz = dbt->size;; - p = (char *)p + plen, last = h) { - if ((h = __bt_new(t, &npg)) == NULL) - return (RET_ERROR); - - h->pgno = npg; - h->nextpg = h->prevpg = P_INVALID; - h->flags = P_OVERFLOW; - h->lower = h->upper = 0; - - nb = MIN(sz, plen); - memmove((char *)h + BTDATAOFF, p, nb); - - if (last) { - last->nextpg = h->pgno; - mpool_put(t->bt_mp, last, MPOOL_DIRTY); - } else - *pg = h->pgno; - - if ((sz -= nb) == 0) { - mpool_put(t->bt_mp, h, MPOOL_DIRTY); - break; - } - } - return (RET_SUCCESS); -} - -/* - * __OVFL_DELETE -- Delete an overflow chain. - * - * Parameters: - * t: tree - * p: pointer to { pgno_t, u_int32_t } - * - * Returns: - * RET_ERROR, RET_SUCCESS - */ -int -__ovfl_delete(t, p) - BTREE *t; - void *p; -{ - PAGE *h; - pgno_t pg; - size_t plen; - u_int32_t sz; - - memmove(&pg, p, sizeof(pgno_t)); - memmove(&sz, (char *)p + sizeof(pgno_t), sizeof(u_int32_t)); - -#ifdef DEBUG - if (pg == P_INVALID || sz == 0) - abort(); -#endif - if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) - return (RET_ERROR); - - /* Don't delete chains used by internal pages. */ - if (h->flags & P_PRESERVE) { - mpool_put(t->bt_mp, h, 0); - return (RET_SUCCESS); - } - - /* Step through the chain, calling the free routine for each page. */ - for (plen = t->bt_psize - BTDATAOFF;; sz -= plen) { - pg = h->nextpg; - __bt_free(t, h); - if (sz <= plen) - break; - if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) - return (RET_ERROR); - } - return (RET_SUCCESS); -} diff --git a/main/db1-ast/btree/bt_page.c b/main/db1-ast/btree/bt_page.c deleted file mode 100644 index e77a1d6b5..000000000 --- a/main/db1-ast/btree/bt_page.c +++ /dev/null @@ -1,100 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)bt_page.c 8.3 (Berkeley) 7/14/94"; -#endif /* LIBC_SCCS and not lint */ - -#include - -#include - -#include "../include/db.h" -#include "btree.h" - -/* - * __bt_free -- - * Put a page on the freelist. - * - * Parameters: - * t: tree - * h: page to free - * - * Returns: - * RET_ERROR, RET_SUCCESS - * - * Side-effect: - * mpool_put's the page. - */ -int -__bt_free(t, h) - BTREE *t; - PAGE *h; -{ - /* Insert the page at the head of the free list. */ - h->prevpg = P_INVALID; - h->nextpg = t->bt_free; - t->bt_free = h->pgno; - F_SET(t, B_METADIRTY); - - /* Make sure the page gets written back. */ - return (mpool_put(t->bt_mp, h, MPOOL_DIRTY)); -} - -/* - * __bt_new -- - * Get a new page, preferably from the freelist. - * - * Parameters: - * t: tree - * npg: storage for page number. - * - * Returns: - * Pointer to a page, NULL on error. - */ -PAGE * -__bt_new(t, npg) - BTREE *t; - pgno_t *npg; -{ - PAGE *h; - - if (t->bt_free != P_INVALID && - (h = mpool_get(t->bt_mp, t->bt_free, 0)) != NULL) { - *npg = t->bt_free; - t->bt_free = h->nextpg; - F_SET(t, B_METADIRTY); - return (h); - } - return (mpool_new(t->bt_mp, npg)); -} diff --git a/main/db1-ast/btree/bt_put.c b/main/db1-ast/btree/bt_put.c deleted file mode 100644 index 604ff06a3..000000000 --- a/main/db1-ast/btree/bt_put.c +++ /dev/null @@ -1,321 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Mike Olson. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)bt_put.c 8.8 (Berkeley) 7/26/94"; -#endif /* LIBC_SCCS and not lint */ - -#include - -#include -#include -#include -#include - -#include "../include/db.h" -#include "btree.h" - -static EPG *bt_fast __P((BTREE *, const DBT *, const DBT *, int *)); - -/* - * __BT_PUT -- Add a btree item to the tree. - * - * Parameters: - * dbp: pointer to access method - * key: key - * data: data - * flag: R_NOOVERWRITE - * - * Returns: - * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key is already in the - * tree and R_NOOVERWRITE specified. - */ -int -__bt_put(dbp, key, data, flags) - const DB *dbp; - DBT *key; - const DBT *data; - u_int flags; -{ - BTREE *t; - DBT tkey, tdata; - EPG *e = 0; - PAGE *h; - indx_t idx, nxtindex; - pgno_t pg; - u_int32_t nbytes; - int dflags, exact, status; - char *dest, db[NOVFLSIZE], kb[NOVFLSIZE]; - - t = dbp->internal; - - /* Toss any page pinned across calls. */ - if (t->bt_pinned != NULL) { - mpool_put(t->bt_mp, t->bt_pinned, 0); - t->bt_pinned = NULL; - } - - /* Check for change to a read-only tree. */ - if (F_ISSET(t, B_RDONLY)) { - errno = EPERM; - return (RET_ERROR); - } - - switch (flags) { - case 0: - case R_NOOVERWRITE: - break; - case R_CURSOR: - /* - * If flags is R_CURSOR, put the cursor. Must already - * have started a scan and not have already deleted it. - */ - if (F_ISSET(&t->bt_cursor, CURS_INIT) && - !F_ISSET(&t->bt_cursor, - CURS_ACQUIRE | CURS_AFTER | CURS_BEFORE)) - break; - /* FALLTHROUGH */ - default: - errno = EINVAL; - return (RET_ERROR); - } - - /* - * If the key/data pair won't fit on a page, store it on overflow - * pages. Only put the key on the overflow page if the pair are - * still too big after moving the data to an overflow page. - * - * XXX - * If the insert fails later on, the overflow pages aren't recovered. - */ - dflags = 0; - if (key->size + data->size > t->bt_ovflsize) { - if (key->size > t->bt_ovflsize) { -storekey: if (__ovfl_put(t, key, &pg) == RET_ERROR) - return (RET_ERROR); - tkey.data = kb; - tkey.size = NOVFLSIZE; - memmove(kb, &pg, sizeof(pgno_t)); - memmove(kb + sizeof(pgno_t), - &key->size, sizeof(u_int32_t)); - dflags |= P_BIGKEY; - key = &tkey; - } - if (key->size + data->size > t->bt_ovflsize) { - if (__ovfl_put(t, data, &pg) == RET_ERROR) - return (RET_ERROR); - tdata.data = db; - tdata.size = NOVFLSIZE; - memmove(db, &pg, sizeof(pgno_t)); - memmove(db + sizeof(pgno_t), - &data->size, sizeof(u_int32_t)); - dflags |= P_BIGDATA; - data = &tdata; - } - if (key->size + data->size > t->bt_ovflsize) - goto storekey; - } - - /* Replace the cursor. */ - if (flags == R_CURSOR) { - if ((h = mpool_get(t->bt_mp, t->bt_cursor.pg.pgno, 0)) == NULL) - return (RET_ERROR); - idx = t->bt_cursor.pg.index; - goto delete; - } - - /* - * Find the key to delete, or, the location at which to insert. - * Bt_fast and __bt_search both pin the returned page. - */ - if (t->bt_order == NOT || (e = bt_fast(t, key, data, &exact)) == NULL) - if ((e = __bt_search(t, key, &exact)) == NULL) - return (RET_ERROR); - h = e->page; - idx = e->index; - - /* - * Add the key/data pair to the tree. If an identical key is already - * in the tree, and R_NOOVERWRITE is set, an error is returned. If - * R_NOOVERWRITE is not set, the key is either added (if duplicates are - * permitted) or an error is returned. - */ - switch (flags) { - case R_NOOVERWRITE: - if (!exact) - break; - mpool_put(t->bt_mp, h, 0); - return (RET_SPECIAL); - default: - if (!exact || !F_ISSET(t, B_NODUPS)) - break; - /* - * !!! - * Note, the delete may empty the page, so we need to put a - * new entry into the page immediately. - */ -delete: if (__bt_dleaf(t, key, h, idx) == RET_ERROR) { - mpool_put(t->bt_mp, h, 0); - return (RET_ERROR); - } - break; - } - - /* - * If not enough room, or the user has put a ceiling on the number of - * keys permitted in the page, split the page. The split code will - * insert the key and data and unpin the current page. If inserting - * into the offset array, shift the pointers up. - */ - nbytes = NBLEAFDBT(key->size, data->size); - if ((u_int32_t) (h->upper - h->lower) < nbytes + sizeof(indx_t)) { - if ((status = __bt_split(t, h, key, - data, dflags, nbytes, idx)) != RET_SUCCESS) - return (status); - goto success; - } - - if (idx < (nxtindex = NEXTINDEX(h))) - memmove(h->linp + idx + 1, h->linp + idx, - (nxtindex - idx) * sizeof(indx_t)); - h->lower += sizeof(indx_t); - - h->linp[idx] = h->upper -= nbytes; - dest = (char *)h + h->upper; - WR_BLEAF(dest, key, data, dflags); - - /* If the cursor is on this page, adjust it as necessary. */ - if (F_ISSET(&t->bt_cursor, CURS_INIT) && - !F_ISSET(&t->bt_cursor, CURS_ACQUIRE) && - t->bt_cursor.pg.pgno == h->pgno && t->bt_cursor.pg.index >= idx) - ++t->bt_cursor.pg.index; - - if (t->bt_order == NOT) { - if (h->nextpg == P_INVALID) { - if (idx == NEXTINDEX(h) - 1) { - t->bt_order = FORWARD; - t->bt_last.index = idx; - t->bt_last.pgno = h->pgno; - } - } else if (h->prevpg == P_INVALID) { - if (idx == 0) { - t->bt_order = BACK; - t->bt_last.index = 0; - t->bt_last.pgno = h->pgno; - } - } - } - - mpool_put(t->bt_mp, h, MPOOL_DIRTY); - -success: - if (flags == R_SETCURSOR) - __bt_setcur(t, e->page->pgno, e->index); - - F_SET(t, B_MODIFIED); - return (RET_SUCCESS); -} - -#ifdef STATISTICS -u_long bt_cache_hit, bt_cache_miss; -#endif - -/* - * BT_FAST -- Do a quick check for sorted data. - * - * Parameters: - * t: tree - * key: key to insert - * - * Returns: - * EPG for new record or NULL if not found. - */ -static EPG * -bt_fast(t, key, data, exactp) - BTREE *t; - const DBT *key, *data; - int *exactp; -{ - PAGE *h; - u_int32_t nbytes; - int cmp; - - if ((h = mpool_get(t->bt_mp, t->bt_last.pgno, 0)) == NULL) { - t->bt_order = NOT; - return (NULL); - } - t->bt_cur.page = h; - t->bt_cur.index = t->bt_last.index; - - /* - * If won't fit in this page or have too many keys in this page, - * have to search to get split stack. - */ - nbytes = NBLEAFDBT(key->size, data->size); - if ((u_int32_t) (h->upper - h->lower) < nbytes + sizeof(indx_t)) - goto miss; - - if (t->bt_order == FORWARD) { - if (t->bt_cur.page->nextpg != P_INVALID) - goto miss; - if (t->bt_cur.index != NEXTINDEX(h) - 1) - goto miss; - if ((cmp = __bt_cmp(t, key, &t->bt_cur)) < 0) - goto miss; - t->bt_last.index = cmp ? ++t->bt_cur.index : t->bt_cur.index; - } else { - if (t->bt_cur.page->prevpg != P_INVALID) - goto miss; - if (t->bt_cur.index != 0) - goto miss; - if ((cmp = __bt_cmp(t, key, &t->bt_cur)) > 0) - goto miss; - t->bt_last.index = 0; - } - *exactp = cmp == 0; -#ifdef STATISTICS - ++bt_cache_hit; -#endif - return (&t->bt_cur); - -miss: -#ifdef STATISTICS - ++bt_cache_miss; -#endif - t->bt_order = NOT; - mpool_put(t->bt_mp, h, 0); - return (NULL); -} diff --git a/main/db1-ast/btree/bt_search.c b/main/db1-ast/btree/bt_search.c deleted file mode 100644 index 623f43949..000000000 --- a/main/db1-ast/btree/bt_search.c +++ /dev/null @@ -1,213 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Mike Olson. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)bt_search.c 8.8 (Berkeley) 7/31/94"; -#endif /* LIBC_SCCS and not lint */ - -#include - -#include - -#include "../include/db.h" -#include "btree.h" - -static int __bt_snext __P((BTREE *, PAGE *, const DBT *, int *)); -static int __bt_sprev __P((BTREE *, PAGE *, const DBT *, int *)); - -/* - * __bt_search -- - * Search a btree for a key. - * - * Parameters: - * t: tree to search - * key: key to find - * exactp: pointer to exact match flag - * - * Returns: - * The EPG for matching record, if any, or the EPG for the location - * of the key, if it were inserted into the tree, is entered into - * the bt_cur field of the tree. A pointer to the field is returned. - */ -EPG * -__bt_search(t, key, exactp) - BTREE *t; - const DBT *key; - int *exactp; -{ - PAGE *h; - indx_t base, index, lim; - pgno_t pg; - int cmp; - - BT_CLR(t); - for (pg = P_ROOT;;) { - if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) - return (NULL); - - /* Do a binary search on the current page. */ - t->bt_cur.page = h; - for (base = 0, lim = NEXTINDEX(h); lim; lim >>= 1) { - t->bt_cur.index = index = base + (lim >> 1); - if ((cmp = __bt_cmp(t, key, &t->bt_cur)) == 0) { - if (h->flags & P_BLEAF) { - *exactp = 1; - return (&t->bt_cur); - } - goto next; - } - if (cmp > 0) { - base = index + 1; - --lim; - } - } - - /* - * If it's a leaf page, we're almost done. If no duplicates - * are allowed, or we have an exact match, we're done. Else, - * it's possible that there were matching keys on this page, - * which later deleted, and we're on a page with no matches - * while there are matches on other pages. If at the start or - * end of a page, check the adjacent page. - */ - if (h->flags & P_BLEAF) { - if (!F_ISSET(t, B_NODUPS)) { - if (base == 0 && - h->prevpg != P_INVALID && - __bt_sprev(t, h, key, exactp)) - return (&t->bt_cur); - if (base == NEXTINDEX(h) && - h->nextpg != P_INVALID && - __bt_snext(t, h, key, exactp)) - return (&t->bt_cur); - } - *exactp = 0; - t->bt_cur.index = base; - return (&t->bt_cur); - } - - /* - * No match found. Base is the smallest index greater than - * key and may be zero or a last + 1 index. If it's non-zero, - * decrement by one, and record the internal page which should - * be a parent page for the key. If a split later occurs, the - * inserted page will be to the right of the saved page. - */ - index = base ? base - 1 : base; - -next: BT_PUSH(t, h->pgno, index); - pg = GETBINTERNAL(h, index)->pgno; - mpool_put(t->bt_mp, h, 0); - } -} - -/* - * __bt_snext -- - * Check for an exact match after the key. - * - * Parameters: - * t: tree - * h: current page - * key: key - * exactp: pointer to exact match flag - * - * Returns: - * If an exact match found. - */ -static int -__bt_snext(t, h, key, exactp) - BTREE *t; - PAGE *h; - const DBT *key; - int *exactp; -{ - EPG e; - - /* - * Get the next page. The key is either an exact - * match, or not as good as the one we already have. - */ - if ((e.page = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL) - return (0); - e.index = 0; - if (__bt_cmp(t, key, &e) == 0) { - mpool_put(t->bt_mp, h, 0); - t->bt_cur = e; - *exactp = 1; - return (1); - } - mpool_put(t->bt_mp, e.page, 0); - return (0); -} - -/* - * __bt_sprev -- - * Check for an exact match before the key. - * - * Parameters: - * t: tree - * h: current page - * key: key - * exactp: pointer to exact match flag - * - * Returns: - * If an exact match found. - */ -static int -__bt_sprev(t, h, key, exactp) - BTREE *t; - PAGE *h; - const DBT *key; - int *exactp; -{ - EPG e; - - /* - * Get the previous page. The key is either an exact - * match, or not as good as the one we already have. - */ - if ((e.page = mpool_get(t->bt_mp, h->prevpg, 0)) == NULL) - return (0); - e.index = NEXTINDEX(e.page) - 1; - if (__bt_cmp(t, key, &e) == 0) { - mpool_put(t->bt_mp, h, 0); - t->bt_cur = e; - *exactp = 1; - return (1); - } - mpool_put(t->bt_mp, e.page, 0); - return (0); -} diff --git a/main/db1-ast/btree/bt_seq.c b/main/db1-ast/btree/bt_seq.c deleted file mode 100644 index 3f1724274..000000000 --- a/main/db1-ast/btree/bt_seq.c +++ /dev/null @@ -1,460 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Mike Olson. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)bt_seq.c 8.7 (Berkeley) 7/20/94"; -#endif /* LIBC_SCCS and not lint */ - -#include - -#include -#include -#include -#include - -#include "../include/db.h" -#include "btree.h" - -static int __bt_first __P((BTREE *, const DBT *, EPG *, int *)); -static int __bt_seqadv __P((BTREE *, EPG *, int)); -static int __bt_seqset __P((BTREE *, EPG *, DBT *, int)); - -/* - * Sequential scan support. - * - * The tree can be scanned sequentially, starting from either end of the - * tree or from any specific key. A scan request before any scanning is - * done is initialized as starting from the least node. - */ - -/* - * __bt_seq -- - * Btree sequential scan interface. - * - * Parameters: - * dbp: pointer to access method - * key: key for positioning and return value - * data: data return value - * flags: R_CURSOR, R_FIRST, R_LAST, R_NEXT, R_PREV. - * - * Returns: - * RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key. - */ -int -__bt_seq(dbp, key, data, flags) - const DB *dbp; - DBT *key, *data; - u_int flags; -{ - BTREE *t; - EPG e; - int status; - - t = dbp->internal; - - /* Toss any page pinned across calls. */ - if (t->bt_pinned != NULL) { - mpool_put(t->bt_mp, t->bt_pinned, 0); - t->bt_pinned = NULL; - } - - /* - * If scan uninitialized as yet, or starting at a specific record, set - * the scan to a specific key. Both __bt_seqset and __bt_seqadv pin - * the page the cursor references if they're successful. - */ - switch (flags) { - case R_NEXT: - case R_PREV: - if (F_ISSET(&t->bt_cursor, CURS_INIT)) { - status = __bt_seqadv(t, &e, flags); - break; - } - /* FALLTHROUGH */ - case R_FIRST: - case R_LAST: - case R_CURSOR: - status = __bt_seqset(t, &e, key, flags); - break; - default: - errno = EINVAL; - return (RET_ERROR); - } - - if (status == RET_SUCCESS) { - __bt_setcur(t, e.page->pgno, e.index); - - status = - __bt_ret(t, &e, key, &t->bt_rkey, data, &t->bt_rdata, 0); - - /* - * If the user is doing concurrent access, we copied the - * key/data, toss the page. - */ - if (F_ISSET(t, B_DB_LOCK)) - mpool_put(t->bt_mp, e.page, 0); - else - t->bt_pinned = e.page; - } - return (status); -} - -/* - * __bt_seqset -- - * Set the sequential scan to a specific key. - * - * Parameters: - * t: tree - * ep: storage for returned key - * key: key for initial scan position - * flags: R_CURSOR, R_FIRST, R_LAST, R_NEXT, R_PREV - * - * Side effects: - * Pins the page the cursor references. - * - * Returns: - * RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key. - */ -static int -__bt_seqset(t, ep, key, flags) - BTREE *t; - EPG *ep; - DBT *key; - int flags; -{ - PAGE *h; - pgno_t pg; - int exact; - - /* - * Find the first, last or specific key in the tree and point the - * cursor at it. The cursor may not be moved until a new key has - * been found. - */ - switch (flags) { - case R_CURSOR: /* Keyed scan. */ - /* - * Find the first instance of the key or the smallest key - * which is greater than or equal to the specified key. - */ - if (key->data == NULL || key->size == 0) { - errno = EINVAL; - return (RET_ERROR); - } - return (__bt_first(t, key, ep, &exact)); - case R_FIRST: /* First record. */ - case R_NEXT: - /* Walk down the left-hand side of the tree. */ - for (pg = P_ROOT;;) { - if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) - return (RET_ERROR); - - /* Check for an empty tree. */ - if (NEXTINDEX(h) == 0) { - mpool_put(t->bt_mp, h, 0); - return (RET_SPECIAL); - } - - if (h->flags & (P_BLEAF | P_RLEAF)) - break; - pg = GETBINTERNAL(h, 0)->pgno; - mpool_put(t->bt_mp, h, 0); - } - ep->page = h; - ep->index = 0; - break; - case R_LAST: /* Last record. */ - case R_PREV: - /* Walk down the right-hand side of the tree. */ - for (pg = P_ROOT;;) { - if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) - return (RET_ERROR); - - /* Check for an empty tree. */ - if (NEXTINDEX(h) == 0) { - mpool_put(t->bt_mp, h, 0); - return (RET_SPECIAL); - } - - if (h->flags & (P_BLEAF | P_RLEAF)) - break; - pg = GETBINTERNAL(h, NEXTINDEX(h) - 1)->pgno; - mpool_put(t->bt_mp, h, 0); - } - - ep->page = h; - ep->index = NEXTINDEX(h) - 1; - break; - } - return (RET_SUCCESS); -} - -/* - * __bt_seqadvance -- - * Advance the sequential scan. - * - * Parameters: - * t: tree - * flags: R_NEXT, R_PREV - * - * Side effects: - * Pins the page the new key/data record is on. - * - * Returns: - * RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key. - */ -static int -__bt_seqadv(t, ep, flags) - BTREE *t; - EPG *ep; - int flags; -{ - CURSOR *c; - PAGE *h; - indx_t index = 0; - pgno_t pg; - int exact; - - /* - * There are a couple of states that we can be in. The cursor has - * been initialized by the time we get here, but that's all we know. - */ - c = &t->bt_cursor; - - /* - * The cursor was deleted where there weren't any duplicate records, - * so the key was saved. Find out where that key would go in the - * current tree. It doesn't matter if the returned key is an exact - * match or not -- if it's an exact match, the record was added after - * the delete so we can just return it. If not, as long as there's - * a record there, return it. - */ - if (F_ISSET(c, CURS_ACQUIRE)) - return (__bt_first(t, &c->key, ep, &exact)); - - /* Get the page referenced by the cursor. */ - if ((h = mpool_get(t->bt_mp, c->pg.pgno, 0)) == NULL) - return (RET_ERROR); - - /* - * Find the next/previous record in the tree and point the cursor at - * it. The cursor may not be moved until a new key has been found. - */ - switch (flags) { - case R_NEXT: /* Next record. */ - /* - * The cursor was deleted in duplicate records, and moved - * forward to a record that has yet to be returned. Clear - * that flag, and return the record. - */ - if (F_ISSET(c, CURS_AFTER)) - goto usecurrent; - index = c->pg.index; - if (++index == NEXTINDEX(h)) { - pg = h->nextpg; - mpool_put(t->bt_mp, h, 0); - if (pg == P_INVALID) - return (RET_SPECIAL); - if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) - return (RET_ERROR); - index = 0; - } - break; - case R_PREV: /* Previous record. */ - /* - * The cursor was deleted in duplicate records, and moved - * backward to a record that has yet to be returned. Clear - * that flag, and return the record. - */ - if (F_ISSET(c, CURS_BEFORE)) { -usecurrent: F_CLR(c, CURS_AFTER | CURS_BEFORE); - ep->page = h; - ep->index = c->pg.index; - return (RET_SUCCESS); - } - index = c->pg.index; - if (index == 0) { - pg = h->prevpg; - mpool_put(t->bt_mp, h, 0); - if (pg == P_INVALID) - return (RET_SPECIAL); - if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) - return (RET_ERROR); - index = NEXTINDEX(h) - 1; - } else - --index; - break; - } - - ep->page = h; - ep->index = index; - return (RET_SUCCESS); -} - -/* - * __bt_first -- - * Find the first entry. - * - * Parameters: - * t: the tree - * key: the key - * erval: return EPG - * exactp: pointer to exact match flag - * - * Returns: - * The first entry in the tree greater than or equal to key, - * or RET_SPECIAL if no such key exists. - */ -static int -__bt_first(t, key, erval, exactp) - BTREE *t; - const DBT *key; - EPG *erval; - int *exactp; -{ - PAGE *h; - EPG *ep, save; - pgno_t pg; - - /* - * Find any matching record; __bt_search pins the page. - * - * If it's an exact match and duplicates are possible, walk backwards - * in the tree until we find the first one. Otherwise, make sure it's - * a valid key (__bt_search may return an index just past the end of a - * page) and return it. - */ - if ((ep = __bt_search(t, key, exactp)) == NULL) - return (RET_SPECIAL); - if (*exactp) { - if (F_ISSET(t, B_NODUPS)) { - *erval = *ep; - return (RET_SUCCESS); - } - - /* - * Walk backwards, as long as the entry matches and there are - * keys left in the tree. Save a copy of each match in case - * we go too far. - */ - save = *ep; - h = ep->page; - do { - if (save.page->pgno != ep->page->pgno) { - mpool_put(t->bt_mp, save.page, 0); - save = *ep; - } else - save.index = ep->index; - - /* - * Don't unpin the page the last (or original) match - * was on, but make sure it's unpinned if an error - * occurs. - */ - if (ep->index == 0) { - if (h->prevpg == P_INVALID) - break; - if (h->pgno != save.page->pgno) - mpool_put(t->bt_mp, h, 0); - if ((h = mpool_get(t->bt_mp, - h->prevpg, 0)) == NULL) { - if (h->pgno == save.page->pgno) - mpool_put(t->bt_mp, - save.page, 0); - return (RET_ERROR); - } - ep->page = h; - ep->index = NEXTINDEX(h); - } - --ep->index; - } while (__bt_cmp(t, key, ep) == 0); - - /* - * Reach here with the last page that was looked at pinned, - * which may or may not be the same as the last (or original) - * match page. If it's not useful, release it. - */ - if (h->pgno != save.page->pgno) - mpool_put(t->bt_mp, h, 0); - - *erval = save; - return (RET_SUCCESS); - } - - /* If at the end of a page, find the next entry. */ - if (ep->index == NEXTINDEX(ep->page)) { - h = ep->page; - pg = h->nextpg; - mpool_put(t->bt_mp, h, 0); - if (pg == P_INVALID) - return (RET_SPECIAL); - if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) - return (RET_ERROR); - ep->index = 0; - ep->page = h; - } - *erval = *ep; - return (RET_SUCCESS); -} - -/* - * __bt_setcur -- - * Set the cursor to an entry in the tree. - * - * Parameters: - * t: the tree - * pgno: page number - * index: page index - */ -void -__bt_setcur(t, pgno, index) - BTREE *t; - pgno_t pgno; - u_int index; -{ - /* Lose any already deleted key. */ - if (t->bt_cursor.key.data != NULL) { - free(t->bt_cursor.key.data); - t->bt_cursor.key.size = 0; - t->bt_cursor.key.data = NULL; - } - F_CLR(&t->bt_cursor, CURS_ACQUIRE | CURS_AFTER | CURS_BEFORE); - - /* Update the cursor. */ - t->bt_cursor.pg.pgno = pgno; - t->bt_cursor.pg.index = index; - F_SET(&t->bt_cursor, CURS_INIT); -} diff --git a/main/db1-ast/btree/bt_split.c b/main/db1-ast/btree/bt_split.c deleted file mode 100644 index 8fede1e45..000000000 --- a/main/db1-ast/btree/bt_split.c +++ /dev/null @@ -1,829 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Mike Olson. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)bt_split.c 8.9 (Berkeley) 7/26/94"; -#endif /* LIBC_SCCS and not lint */ - -#include - -#include -#include -#include -#include - -#include "../include/db.h" -#include "btree.h" - -static int bt_broot __P((BTREE *, PAGE *, PAGE *, PAGE *)); -static PAGE *bt_page - __P((BTREE *, PAGE *, PAGE **, PAGE **, indx_t *, size_t)); -static int bt_preserve __P((BTREE *, pgno_t)); -static PAGE *bt_psplit - __P((BTREE *, PAGE *, PAGE *, PAGE *, indx_t *, size_t)); -static PAGE *bt_root - __P((BTREE *, PAGE *, PAGE **, PAGE **, indx_t *, size_t)); -static int bt_rroot __P((BTREE *, PAGE *, PAGE *, PAGE *)); -static recno_t rec_total __P((PAGE *)); - -#ifdef STATISTICS -u_long bt_rootsplit, bt_split, bt_sortsplit, bt_pfxsaved; -#endif - -/* - * __BT_SPLIT -- Split the tree. - * - * Parameters: - * t: tree - * sp: page to split - * key: key to insert - * data: data to insert - * flags: BIGKEY/BIGDATA flags - * ilen: insert length - * skip: index to leave open - * - * Returns: - * RET_ERROR, RET_SUCCESS - */ -int -__bt_split(t, sp, key, data, flags, ilen, argskip) - BTREE *t; - PAGE *sp; - const DBT *key, *data; - int flags; - size_t ilen; - u_int32_t argskip; -{ - BINTERNAL *bi = 0; - BLEAF *bl = 0, *tbl; - DBT a, b; - EPGNO *parent; - PAGE *h, *l, *r, *lchild, *rchild; - indx_t nxtindex; - u_int16_t skip; - u_int32_t n, nbytes, nksize = 0; - int parentsplit; - char *dest; - - /* - * Split the page into two pages, l and r. The split routines return - * a pointer to the page into which the key should be inserted and with - * skip set to the offset which should be used. Additionally, l and r - * are pinned. - */ - skip = argskip; - h = sp->pgno == P_ROOT ? - bt_root(t, sp, &l, &r, &skip, ilen) : - bt_page(t, sp, &l, &r, &skip, ilen); - if (h == NULL) - return (RET_ERROR); - - /* - * Insert the new key/data pair into the leaf page. (Key inserts - * always cause a leaf page to split first.) - */ - h->linp[skip] = h->upper -= ilen; - dest = (char *)h + h->upper; - if (F_ISSET(t, R_RECNO)) - WR_RLEAF(dest, data, flags) - else - WR_BLEAF(dest, key, data, flags) - - /* If the root page was split, make it look right. */ - if (sp->pgno == P_ROOT && - (F_ISSET(t, R_RECNO) ? - bt_rroot(t, sp, l, r) : bt_broot(t, sp, l, r)) == RET_ERROR) - goto err2; - - /* - * Now we walk the parent page stack -- a LIFO stack of the pages that - * were traversed when we searched for the page that split. Each stack - * entry is a page number and a page index offset. The offset is for - * the page traversed on the search. We've just split a page, so we - * have to insert a new key into the parent page. - * - * If the insert into the parent page causes it to split, may have to - * continue splitting all the way up the tree. We stop if the root - * splits or the page inserted into didn't have to split to hold the - * new key. Some algorithms replace the key for the old page as well - * as the new page. We don't, as there's no reason to believe that the - * first key on the old page is any better than the key we have, and, - * in the case of a key being placed at index 0 causing the split, the - * key is unavailable. - * - * There are a maximum of 5 pages pinned at any time. We keep the left - * and right pages pinned while working on the parent. The 5 are the - * two children, left parent and right parent (when the parent splits) - * and the root page or the overflow key page when calling bt_preserve. - * This code must make sure that all pins are released other than the - * root page or overflow page which is unlocked elsewhere. - */ - while ((parent = BT_POP(t)) != NULL) { - lchild = l; - rchild = r; - - /* Get the parent page. */ - if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL) - goto err2; - - /* - * The new key goes ONE AFTER the index, because the split - * was to the right. - */ - skip = parent->index + 1; - - /* - * Calculate the space needed on the parent page. - * - * Prefix trees: space hack when inserting into BINTERNAL - * pages. Retain only what's needed to distinguish between - * the new entry and the LAST entry on the page to its left. - * If the keys compare equal, retain the entire key. Note, - * we don't touch overflow keys, and the entire key must be - * retained for the next-to-left most key on the leftmost - * page of each level, or the search will fail. Applicable - * ONLY to internal pages that have leaf pages as children. - * Further reduction of the key between pairs of internal - * pages loses too much information. - */ - switch (rchild->flags & P_TYPE) { - case P_BINTERNAL: - bi = GETBINTERNAL(rchild, 0); - nbytes = NBINTERNAL(bi->ksize); - break; - case P_BLEAF: - bl = GETBLEAF(rchild, 0); - nbytes = NBINTERNAL(bl->ksize); - if (t->bt_pfx && !(bl->flags & P_BIGKEY) && - (h->prevpg != P_INVALID || skip > 1)) { - tbl = GETBLEAF(lchild, NEXTINDEX(lchild) - 1); - a.size = tbl->ksize; - a.data = tbl->bytes; - b.size = bl->ksize; - b.data = bl->bytes; - nksize = t->bt_pfx(&a, &b); - n = NBINTERNAL(nksize); - if (n < nbytes) { -#ifdef STATISTICS - bt_pfxsaved += nbytes - n; -#endif - nbytes = n; - } else - nksize = 0; - } else - nksize = 0; - break; - case P_RINTERNAL: - case P_RLEAF: - nbytes = NRINTERNAL; - break; - default: - abort(); - } - - /* Split the parent page if necessary or shift the indices. */ - if ((u_int32_t) (h->upper - h->lower) - < nbytes + sizeof(indx_t)) { - sp = h; - h = h->pgno == P_ROOT ? - bt_root(t, h, &l, &r, &skip, nbytes) : - bt_page(t, h, &l, &r, &skip, nbytes); - if (h == NULL) - goto err1; - parentsplit = 1; - } else { - if (skip < (nxtindex = NEXTINDEX(h))) - memmove(h->linp + skip + 1, h->linp + skip, - (nxtindex - skip) * sizeof(indx_t)); - h->lower += sizeof(indx_t); - parentsplit = 0; - } - - /* Insert the key into the parent page. */ - switch (rchild->flags & P_TYPE) { - case P_BINTERNAL: - h->linp[skip] = h->upper -= nbytes; - dest = (char *)h + h->linp[skip]; - memmove(dest, bi, nbytes); - ((BINTERNAL *)dest)->pgno = rchild->pgno; - break; - case P_BLEAF: - h->linp[skip] = h->upper -= nbytes; - dest = (char *)h + h->linp[skip]; - WR_BINTERNAL(dest, nksize ? nksize : bl->ksize, - rchild->pgno, bl->flags & P_BIGKEY); - memmove(dest, bl->bytes, nksize ? nksize : bl->ksize); - if (bl->flags & P_BIGKEY && - bt_preserve(t, *(pgno_t *)bl->bytes) == RET_ERROR) - goto err1; - break; - case P_RINTERNAL: - /* - * Update the left page count. If split - * added at index 0, fix the correct page. - */ - if (skip > 0) - dest = (char *)h + h->linp[skip - 1]; - else - dest = (char *)l + l->linp[NEXTINDEX(l) - 1]; - ((RINTERNAL *)dest)->nrecs = rec_total(lchild); - ((RINTERNAL *)dest)->pgno = lchild->pgno; - - /* Update the right page count. */ - h->linp[skip] = h->upper -= nbytes; - dest = (char *)h + h->linp[skip]; - ((RINTERNAL *)dest)->nrecs = rec_total(rchild); - ((RINTERNAL *)dest)->pgno = rchild->pgno; - break; - case P_RLEAF: - /* - * Update the left page count. If split - * added at index 0, fix the correct page. - */ - if (skip > 0) - dest = (char *)h + h->linp[skip - 1]; - else - dest = (char *)l + l->linp[NEXTINDEX(l) - 1]; - ((RINTERNAL *)dest)->nrecs = NEXTINDEX(lchild); - ((RINTERNAL *)dest)->pgno = lchild->pgno; - - /* Update the right page count. */ - h->linp[skip] = h->upper -= nbytes; - dest = (char *)h + h->linp[skip]; - ((RINTERNAL *)dest)->nrecs = NEXTINDEX(rchild); - ((RINTERNAL *)dest)->pgno = rchild->pgno; - break; - default: - abort(); - } - - /* Unpin the held pages. */ - if (!parentsplit) { - mpool_put(t->bt_mp, h, MPOOL_DIRTY); - break; - } - - /* If the root page was split, make it look right. */ - if (sp->pgno == P_ROOT && - (F_ISSET(t, R_RECNO) ? - bt_rroot(t, sp, l, r) : bt_broot(t, sp, l, r)) == RET_ERROR) - goto err1; - - mpool_put(t->bt_mp, lchild, MPOOL_DIRTY); - mpool_put(t->bt_mp, rchild, MPOOL_DIRTY); - } - - /* Unpin the held pages. */ - mpool_put(t->bt_mp, l, MPOOL_DIRTY); - mpool_put(t->bt_mp, r, MPOOL_DIRTY); - - /* Clear any pages left on the stack. */ - return (RET_SUCCESS); - - /* - * If something fails in the above loop we were already walking back - * up the tree and the tree is now inconsistent. Nothing much we can - * do about it but release any memory we're holding. - */ -err1: mpool_put(t->bt_mp, lchild, MPOOL_DIRTY); - mpool_put(t->bt_mp, rchild, MPOOL_DIRTY); - -err2: mpool_put(t->bt_mp, l, 0); - mpool_put(t->bt_mp, r, 0); - __dbpanic(t->bt_dbp); - return (RET_ERROR); -} - -/* - * BT_PAGE -- Split a non-root page of a btree. - * - * Parameters: - * t: tree - * h: root page - * lp: pointer to left page pointer - * rp: pointer to right page pointer - * skip: pointer to index to leave open - * ilen: insert length - * - * Returns: - * Pointer to page in which to insert or NULL on error. - */ -static PAGE * -bt_page(t, h, lp, rp, skip, ilen) - BTREE *t; - PAGE *h, **lp, **rp; - indx_t *skip; - size_t ilen; -{ - PAGE *l, *r, *tp; - pgno_t npg; - -#ifdef STATISTICS - ++bt_split; -#endif - /* Put the new right page for the split into place. */ - if ((r = __bt_new(t, &npg)) == NULL) - return (NULL); - r->pgno = npg; - r->lower = BTDATAOFF; - r->upper = t->bt_psize; - r->nextpg = h->nextpg; - r->prevpg = h->pgno; - r->flags = h->flags & P_TYPE; - - /* - * If we're splitting the last page on a level because we're appending - * a key to it (skip is NEXTINDEX()), it's likely that the data is - * sorted. Adding an empty page on the side of the level is less work - * and can push the fill factor much higher than normal. If we're - * wrong it's no big deal, we'll just do the split the right way next - * time. It may look like it's equally easy to do a similar hack for - * reverse sorted data, that is, split the tree left, but it's not. - * Don't even try. - */ - if (h->nextpg == P_INVALID && *skip == NEXTINDEX(h)) { -#ifdef STATISTICS - ++bt_sortsplit; -#endif - h->nextpg = r->pgno; - r->lower = BTDATAOFF + sizeof(indx_t); - *skip = 0; - *lp = h; - *rp = r; - return (r); - } - - /* Put the new left page for the split into place. */ - if ((l = (PAGE *)malloc(t->bt_psize)) == NULL) { - mpool_put(t->bt_mp, r, 0); - return (NULL); - } -#ifdef PURIFY - memset(l, 0xff, t->bt_psize); -#endif - l->pgno = h->pgno; - l->nextpg = r->pgno; - l->prevpg = h->prevpg; - l->lower = BTDATAOFF; - l->upper = t->bt_psize; - l->flags = h->flags & P_TYPE; - - /* Fix up the previous pointer of the page after the split page. */ - if (h->nextpg != P_INVALID) { - if ((tp = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL) { - free(l); - /* XXX mpool_free(t->bt_mp, r->pgno); */ - return (NULL); - } - tp->prevpg = r->pgno; - mpool_put(t->bt_mp, tp, MPOOL_DIRTY); - } - - /* - * Split right. The key/data pairs aren't sorted in the btree page so - * it's simpler to copy the data from the split page onto two new pages - * instead of copying half the data to the right page and compacting - * the left page in place. Since the left page can't change, we have - * to swap the original and the allocated left page after the split. - */ - tp = bt_psplit(t, h, l, r, skip, ilen); - - /* Move the new left page onto the old left page. */ - memmove(h, l, t->bt_psize); - if (tp == l) - tp = h; - free(l); - - *lp = h; - *rp = r; - return (tp); -} - -/* - * BT_ROOT -- Split the root page of a btree. - * - * Parameters: - * t: tree - * h: root page - * lp: pointer to left page pointer - * rp: pointer to right page pointer - * skip: pointer to index to leave open - * ilen: insert length - * - * Returns: - * Pointer to page in which to insert or NULL on error. - */ -static PAGE * -bt_root(t, h, lp, rp, skip, ilen) - BTREE *t; - PAGE *h, **lp, **rp; - indx_t *skip; - size_t ilen; -{ - PAGE *l, *r, *tp; - pgno_t lnpg, rnpg; - -#ifdef STATISTICS - ++bt_split; - ++bt_rootsplit; -#endif - /* Put the new left and right pages for the split into place. */ - if ((l = __bt_new(t, &lnpg)) == NULL || - (r = __bt_new(t, &rnpg)) == NULL) - return (NULL); - l->pgno = lnpg; - r->pgno = rnpg; - l->nextpg = r->pgno; - r->prevpg = l->pgno; - l->prevpg = r->nextpg = P_INVALID; - l->lower = r->lower = BTDATAOFF; - l->upper = r->upper = t->bt_psize; - l->flags = r->flags = h->flags & P_TYPE; - - /* Split the root page. */ - tp = bt_psplit(t, h, l, r, skip, ilen); - - *lp = l; - *rp = r; - return (tp); -} - -/* - * BT_RROOT -- Fix up the recno root page after it has been split. - * - * Parameters: - * t: tree - * h: root page - * l: left page - * r: right page - * - * Returns: - * RET_ERROR, RET_SUCCESS - */ -static int -bt_rroot(t, h, l, r) - BTREE *t; - PAGE *h, *l, *r; -{ - char *dest; - - /* Insert the left and right keys, set the header information. */ - h->linp[0] = h->upper = t->bt_psize - NRINTERNAL; - dest = (char *)h + h->upper; - WR_RINTERNAL(dest, - l->flags & P_RLEAF ? NEXTINDEX(l) : rec_total(l), l->pgno); - - h->linp[1] = h->upper -= NRINTERNAL; - dest = (char *)h + h->upper; - WR_RINTERNAL(dest, - r->flags & P_RLEAF ? NEXTINDEX(r) : rec_total(r), r->pgno); - - h->lower = BTDATAOFF + 2 * sizeof(indx_t); - - /* Unpin the root page, set to recno internal page. */ - h->flags &= ~P_TYPE; - h->flags |= P_RINTERNAL; - mpool_put(t->bt_mp, h, MPOOL_DIRTY); - - return (RET_SUCCESS); -} - -/* - * BT_BROOT -- Fix up the btree root page after it has been split. - * - * Parameters: - * t: tree - * h: root page - * l: left page - * r: right page - * - * Returns: - * RET_ERROR, RET_SUCCESS - */ -static int -bt_broot(t, h, l, r) - BTREE *t; - PAGE *h, *l, *r; -{ - BINTERNAL *bi; - BLEAF *bl; - u_int32_t nbytes; - char *dest; - - /* - * If the root page was a leaf page, change it into an internal page. - * We copy the key we split on (but not the key's data, in the case of - * a leaf page) to the new root page. - * - * The btree comparison code guarantees that the left-most key on any - * level of the tree is never used, so it doesn't need to be filled in. - */ - nbytes = NBINTERNAL(0); - h->linp[0] = h->upper = t->bt_psize - nbytes; - dest = (char *)h + h->upper; - WR_BINTERNAL(dest, 0, l->pgno, 0); - - switch (h->flags & P_TYPE) { - case P_BLEAF: - bl = GETBLEAF(r, 0); - nbytes = NBINTERNAL(bl->ksize); - h->linp[1] = h->upper -= nbytes; - dest = (char *)h + h->upper; - WR_BINTERNAL(dest, bl->ksize, r->pgno, 0); - memmove(dest, bl->bytes, bl->ksize); - - /* - * If the key is on an overflow page, mark the overflow chain - * so it isn't deleted when the leaf copy of the key is deleted. - */ - if (bl->flags & P_BIGKEY && - bt_preserve(t, *(pgno_t *)bl->bytes) == RET_ERROR) - return (RET_ERROR); - break; - case P_BINTERNAL: - bi = GETBINTERNAL(r, 0); - nbytes = NBINTERNAL(bi->ksize); - h->linp[1] = h->upper -= nbytes; - dest = (char *)h + h->upper; - memmove(dest, bi, nbytes); - ((BINTERNAL *)dest)->pgno = r->pgno; - break; - default: - abort(); - } - - /* There are two keys on the page. */ - h->lower = BTDATAOFF + 2 * sizeof(indx_t); - - /* Unpin the root page, set to btree internal page. */ - h->flags &= ~P_TYPE; - h->flags |= P_BINTERNAL; - mpool_put(t->bt_mp, h, MPOOL_DIRTY); - - return (RET_SUCCESS); -} - -/* - * BT_PSPLIT -- Do the real work of splitting the page. - * - * Parameters: - * t: tree - * h: page to be split - * l: page to put lower half of data - * r: page to put upper half of data - * pskip: pointer to index to leave open - * ilen: insert length - * - * Returns: - * Pointer to page in which to insert. - */ -static PAGE * -bt_psplit(t, h, l, r, pskip, ilen) - BTREE *t; - PAGE *h, *l, *r; - indx_t *pskip; - size_t ilen; -{ - BINTERNAL *bi; - BLEAF *bl; - CURSOR *c; - RLEAF *rl; - PAGE *rval; - void *src = 0; - indx_t full, half, nxt, off, skip, top, used; - u_int32_t nbytes; - int bigkeycnt, isbigkey; - - /* - * Split the data to the left and right pages. Leave the skip index - * open. Additionally, make some effort not to split on an overflow - * key. This makes internal page processing faster and can save - * space as overflow keys used by internal pages are never deleted. - */ - bigkeycnt = 0; - skip = *pskip; - full = t->bt_psize - BTDATAOFF; - half = full / 2; - used = 0; - for (nxt = off = 0, top = NEXTINDEX(h); nxt < top; ++off) { - if (skip == off) { - nbytes = ilen; - isbigkey = 0; /* XXX: not really known. */ - } else - switch (h->flags & P_TYPE) { - case P_BINTERNAL: - src = bi = GETBINTERNAL(h, nxt); - nbytes = NBINTERNAL(bi->ksize); - isbigkey = bi->flags & P_BIGKEY; - break; - case P_BLEAF: - src = bl = GETBLEAF(h, nxt); - nbytes = NBLEAF(bl); - isbigkey = bl->flags & P_BIGKEY; - break; - case P_RINTERNAL: - src = GETRINTERNAL(h, nxt); - nbytes = NRINTERNAL; - isbigkey = 0; - break; - case P_RLEAF: - src = rl = GETRLEAF(h, nxt); - nbytes = NRLEAF(rl); - isbigkey = 0; - break; - default: - abort(); - } - - /* - * If the key/data pairs are substantial fractions of the max - * possible size for the page, it's possible to get situations - * where we decide to try and copy too much onto the left page. - * Make sure that doesn't happen. - */ - if ((skip <= off && used + nbytes + sizeof(indx_t) >= full) - || nxt == top - 1) { - --off; - break; - } - - /* Copy the key/data pair, if not the skipped index. */ - if (skip != off) { - ++nxt; - - l->linp[off] = l->upper -= nbytes; - memmove((char *)l + l->upper, src, nbytes); - } - - used += nbytes + sizeof(indx_t); - if (used >= half) { - if (!isbigkey || bigkeycnt == 3) - break; - else - ++bigkeycnt; - } - } - - /* - * Off is the last offset that's valid for the left page. - * Nxt is the first offset to be placed on the right page. - */ - l->lower += (off + 1) * sizeof(indx_t); - - /* - * If splitting the page that the cursor was on, the cursor has to be - * adjusted to point to the same record as before the split. If the - * cursor is at or past the skipped slot, the cursor is incremented by - * one. If the cursor is on the right page, it is decremented by the - * number of records split to the left page. - */ - c = &t->bt_cursor; - if (F_ISSET(c, CURS_INIT) && c->pg.pgno == h->pgno) { - if (c->pg.index >= skip) - ++c->pg.index; - if (c->pg.index < nxt) /* Left page. */ - c->pg.pgno = l->pgno; - else { /* Right page. */ - c->pg.pgno = r->pgno; - c->pg.index -= nxt; - } - } - - /* - * If the skipped index was on the left page, just return that page. - * Otherwise, adjust the skip index to reflect the new position on - * the right page. - */ - if (skip <= off) { - skip = 0; - rval = l; - } else { - rval = r; - *pskip -= nxt; - } - - for (off = 0; nxt < top; ++off) { - if (skip == nxt) { - ++off; - skip = 0; - } - switch (h->flags & P_TYPE) { - case P_BINTERNAL: - src = bi = GETBINTERNAL(h, nxt); - nbytes = NBINTERNAL(bi->ksize); - break; - case P_BLEAF: - src = bl = GETBLEAF(h, nxt); - nbytes = NBLEAF(bl); - break; - case P_RINTERNAL: - src = GETRINTERNAL(h, nxt); - nbytes = NRINTERNAL; - break; - case P_RLEAF: - src = rl = GETRLEAF(h, nxt); - nbytes = NRLEAF(rl); - break; - default: - abort(); - } - ++nxt; - r->linp[off] = r->upper -= nbytes; - memmove((char *)r + r->upper, src, nbytes); - } - r->lower += off * sizeof(indx_t); - - /* If the key is being appended to the page, adjust the index. */ - if (skip == top) - r->lower += sizeof(indx_t); - - return (rval); -} - -/* - * BT_PRESERVE -- Mark a chain of pages as used by an internal node. - * - * Chains of indirect blocks pointed to by leaf nodes get reclaimed when the - * record that references them gets deleted. Chains pointed to by internal - * pages never get deleted. This routine marks a chain as pointed to by an - * internal page. - * - * Parameters: - * t: tree - * pg: page number of first page in the chain. - * - * Returns: - * RET_SUCCESS, RET_ERROR. - */ -static int -bt_preserve(t, pg) - BTREE *t; - pgno_t pg; -{ - PAGE *h; - - if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) - return (RET_ERROR); - h->flags |= P_PRESERVE; - mpool_put(t->bt_mp, h, MPOOL_DIRTY); - return (RET_SUCCESS); -} - -/* - * REC_TOTAL -- Return the number of recno entries below a page. - * - * Parameters: - * h: page - * - * Returns: - * The number of recno entries below a page. - * - * XXX - * These values could be set by the bt_psplit routine. The problem is that the - * entry has to be popped off of the stack etc. or the values have to be passed - * all the way back to bt_split/bt_rroot and it's not very clean. - */ -static recno_t -rec_total(h) - PAGE *h; -{ - recno_t recs; - indx_t nxt, top; - - for (recs = 0, nxt = 0, top = NEXTINDEX(h); nxt < top; ++nxt) - recs += GETRINTERNAL(h, nxt)->nrecs; - return (recs); -} diff --git a/main/db1-ast/btree/bt_utils.c b/main/db1-ast/btree/bt_utils.c deleted file mode 100644 index 2ecb5e678..000000000 --- a/main/db1-ast/btree/bt_utils.c +++ /dev/null @@ -1,260 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Mike Olson. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)bt_utils.c 8.8 (Berkeley) 7/20/94"; -#endif /* LIBC_SCCS and not lint */ - -#include - -#include -#include -#include - -#include "../include/db.h" -#include "btree.h" - -/* - * __bt_ret -- - * Build return key/data pair. - * - * Parameters: - * t: tree - * e: key/data pair to be returned - * key: user's key structure (NULL if not to be filled in) - * rkey: memory area to hold key - * data: user's data structure (NULL if not to be filled in) - * rdata: memory area to hold data - * copy: always copy the key/data item - * - * Returns: - * RET_SUCCESS, RET_ERROR. - */ -int -__bt_ret(t, e, key, rkey, data, rdata, copy) - BTREE *t; - EPG *e; - DBT *key, *rkey, *data, *rdata; - int copy; -{ - BLEAF *bl; - void *p; - - bl = GETBLEAF(e->page, e->index); - - /* - * We must copy big keys/data to make them contiguous. Otherwise, - * leave the page pinned and don't copy unless the user specified - * concurrent access. - */ - if (key == NULL) - goto dataonly; - - if (bl->flags & P_BIGKEY) { - if (__ovfl_get(t, bl->bytes, - &key->size, &rkey->data, &rkey->size)) - return (RET_ERROR); - key->data = rkey->data; - } else if (copy || F_ISSET(t, B_DB_LOCK)) { - if (bl->ksize > rkey->size) { - p = (void *)(rkey->data == NULL ? - malloc(bl->ksize) : realloc(rkey->data, bl->ksize)); - if (p == NULL) - return (RET_ERROR); - rkey->data = p; - rkey->size = bl->ksize; - } - memmove(rkey->data, bl->bytes, bl->ksize); - key->size = bl->ksize; - key->data = rkey->data; - } else { - key->size = bl->ksize; - key->data = bl->bytes; - } - -dataonly: - if (data == NULL) - return (RET_SUCCESS); - - if (bl->flags & P_BIGDATA) { - if (__ovfl_get(t, bl->bytes + bl->ksize, - &data->size, &rdata->data, &rdata->size)) - return (RET_ERROR); - data->data = rdata->data; - } else if (copy || F_ISSET(t, B_DB_LOCK)) { - /* Use +1 in case the first record retrieved is 0 length. */ - if (bl->dsize + 1 > rdata->size) { - p = (void *)(rdata->data == NULL ? - malloc(bl->dsize + 1) : - realloc(rdata->data, bl->dsize + 1)); - if (p == NULL) - return (RET_ERROR); - rdata->data = p; - rdata->size = bl->dsize + 1; - } - memmove(rdata->data, bl->bytes + bl->ksize, bl->dsize); - data->size = bl->dsize; - data->data = rdata->data; - } else { - data->size = bl->dsize; - data->data = bl->bytes + bl->ksize; - } - - return (RET_SUCCESS); -} - -/* - * __BT_CMP -- Compare a key to a given record. - * - * Parameters: - * t: tree - * k1: DBT pointer of first arg to comparison - * e: pointer to EPG for comparison - * - * Returns: - * < 0 if k1 is < record - * = 0 if k1 is = record - * > 0 if k1 is > record - */ -int -__bt_cmp(t, k1, e) - BTREE *t; - const DBT *k1; - EPG *e; -{ - BINTERNAL *bi; - BLEAF *bl; - DBT k2; - PAGE *h; - void *bigkey; - - /* - * The left-most key on internal pages, at any level of the tree, is - * guaranteed by the following code to be less than any user key. - * This saves us from having to update the leftmost key on an internal - * page when the user inserts a new key in the tree smaller than - * anything we've yet seen. - */ - h = e->page; - if (e->index == 0 && h->prevpg == P_INVALID && !(h->flags & P_BLEAF)) - return (1); - - bigkey = NULL; - if (h->flags & P_BLEAF) { - bl = GETBLEAF(h, e->index); - if (bl->flags & P_BIGKEY) - bigkey = bl->bytes; - else { - k2.data = bl->bytes; - k2.size = bl->ksize; - } - } else { - bi = GETBINTERNAL(h, e->index); - if (bi->flags & P_BIGKEY) - bigkey = bi->bytes; - else { - k2.data = bi->bytes; - k2.size = bi->ksize; - } - } - - if (bigkey) { - if (__ovfl_get(t, bigkey, - &k2.size, &t->bt_rdata.data, &t->bt_rdata.size)) - return (RET_ERROR); - k2.data = t->bt_rdata.data; - } - return ((*t->bt_cmp)(k1, &k2)); -} - -/* - * __BT_DEFCMP -- Default comparison routine. - * - * Parameters: - * a: DBT #1 - * b: DBT #2 - * - * Returns: - * < 0 if a is < b - * = 0 if a is = b - * > 0 if a is > b - */ -int -__bt_defcmp(a, b) - const DBT *a, *b; -{ - register size_t len; - register u_char *p1, *p2; - - /* - * XXX - * If a size_t doesn't fit in an int, this routine can lose. - * What we need is a integral type which is guaranteed to be - * larger than a size_t, and there is no such thing. - */ - len = MIN(a->size, b->size); - for (p1 = a->data, p2 = b->data; len--; ++p1, ++p2) - if (*p1 != *p2) - return ((int)*p1 - (int)*p2); - return ((int)a->size - (int)b->size); -} - -/* - * __BT_DEFPFX -- Default prefix routine. - * - * Parameters: - * a: DBT #1 - * b: DBT #2 - * - * Returns: - * Number of bytes needed to distinguish b from a. - */ -size_t -__bt_defpfx(a, b) - const DBT *a, *b; -{ - register u_char *p1, *p2; - register size_t cnt, len; - - cnt = 1; - len = MIN(a->size, b->size); - for (p1 = a->data, p2 = b->data; len--; ++p1, ++p2, ++cnt) - if (*p1 != *p2) - return (cnt); - - /* a->size must be <= b->size, or they wouldn't be in this order. */ - return (a->size < b->size ? a->size + 1 : a->size); -} diff --git a/main/db1-ast/btree/btree.h b/main/db1-ast/btree/btree.h deleted file mode 100644 index 1f4a9ec91..000000000 --- a/main/db1-ast/btree/btree.h +++ /dev/null @@ -1,391 +0,0 @@ -/*- - * Copyright (c) 1991, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Mike Olson. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)btree.h 8.11 (Berkeley) 8/17/94 - */ - -/* Macros to set/clear/test flags. */ -#define F_SET(p, f) (p)->flags |= (f) -#define F_CLR(p, f) (p)->flags &= ~(f) -#define F_ISSET(p, f) ((p)->flags & (f)) - -#include - -#define mpool_open __mpool_open -#define mpool_filter __mpool_filter -#define mpool_new __mpool_new -#define mpool_get __mpool_get -#define mpool_put __mpool_put -#define mpool_sync __mpool_sync -#define mpool_close __mpool_close - -#define DEFMINKEYPAGE (2) /* Minimum keys per page */ -#define MINCACHE (5) /* Minimum cached pages */ -#define MINPSIZE (512) /* Minimum page size */ - -/* - * Page 0 of a btree file contains a copy of the meta-data. This page is also - * used as an out-of-band page, i.e. page pointers that point to nowhere point - * to page 0. Page 1 is the root of the btree. - */ -#define P_INVALID 0 /* Invalid tree page number. */ -#define P_META 0 /* Tree metadata page number. */ -#define P_ROOT 1 /* Tree root page number. */ - -/* - * There are five page layouts in the btree: btree internal pages (BINTERNAL), - * btree leaf pages (BLEAF), recno internal pages (RINTERNAL), recno leaf pages - * (RLEAF) and overflow pages. All five page types have a page header (PAGE). - * This implementation requires that values within structures NOT be padded. - * (ANSI C permits random padding.) If your compiler pads randomly you'll have - * to do some work to get this package to run. - */ -typedef struct _page { - pgno_t pgno; /* this page's page number */ - pgno_t prevpg; /* left sibling */ - pgno_t nextpg; /* right sibling */ - -#define P_BINTERNAL 0x01 /* btree internal page */ -#define P_BLEAF 0x02 /* leaf page */ -#define P_OVERFLOW 0x04 /* overflow page */ -#define P_RINTERNAL 0x08 /* recno internal page */ -#define P_RLEAF 0x10 /* leaf page */ -#define P_TYPE 0x1f /* type mask */ -#define P_PRESERVE 0x20 /* never delete this chain of pages */ - u_int32_t flags; - - indx_t lower; /* lower bound of free space on page */ - indx_t upper; /* upper bound of free space on page */ - indx_t linp[1]; /* indx_t-aligned VAR. LENGTH DATA */ -} PAGE; - -/* First and next index. */ -#define BTDATAOFF \ - (sizeof(pgno_t) + sizeof(pgno_t) + sizeof(pgno_t) + \ - sizeof(u_int32_t) + sizeof(indx_t) + sizeof(indx_t)) -#define NEXTINDEX(p) (((p)->lower - BTDATAOFF) / sizeof(indx_t)) - -/* - * For pages other than overflow pages, there is an array of offsets into the - * rest of the page immediately following the page header. Each offset is to - * an item which is unique to the type of page. The h_lower offset is just - * past the last filled-in index. The h_upper offset is the first item on the - * page. Offsets are from the beginning of the page. - * - * If an item is too big to store on a single page, a flag is set and the item - * is a { page, size } pair such that the page is the first page of an overflow - * chain with size bytes of item. Overflow pages are simply bytes without any - * external structure. - * - * The page number and size fields in the items are pgno_t-aligned so they can - * be manipulated without copying. (This presumes that 32 bit items can be - * manipulated on this system.) - */ -#define LALIGN(n) (((n) + sizeof(pgno_t) - 1) & ~(sizeof(pgno_t) - 1)) -#define NOVFLSIZE (sizeof(pgno_t) + sizeof(u_int32_t)) - -/* - * For the btree internal pages, the item is a key. BINTERNALs are {key, pgno} - * pairs, such that the key compares less than or equal to all of the records - * on that page. For a tree without duplicate keys, an internal page with two - * consecutive keys, a and b, will have all records greater than or equal to a - * and less than b stored on the page associated with a. Duplicate keys are - * somewhat special and can cause duplicate internal and leaf page records and - * some minor modifications of the above rule. - */ -typedef struct _binternal { - u_int32_t ksize; /* key size */ - pgno_t pgno; /* page number stored on */ -#define P_BIGDATA 0x01 /* overflow data */ -#define P_BIGKEY 0x02 /* overflow key */ - u_char flags; - char bytes[1]; /* data */ -} BINTERNAL; - -/* Get the page's BINTERNAL structure at index indx. */ -#define GETBINTERNAL(pg, indx) \ - ((BINTERNAL *)((char *)(pg) + (pg)->linp[indx])) - -/* Get the number of bytes in the entry. */ -#define NBINTERNAL(len) \ - LALIGN(sizeof(u_int32_t) + sizeof(pgno_t) + sizeof(u_char) + (len)) - -/* Copy a BINTERNAL entry to the page. */ -#define WR_BINTERNAL(p, size, pgno, flags) { \ - *(u_int32_t *)p = size; \ - p += sizeof(u_int32_t); \ - *(pgno_t *)p = pgno; \ - p += sizeof(pgno_t); \ - *(u_char *)p = flags; \ - p += sizeof(u_char); \ -} - -/* - * For the recno internal pages, the item is a page number with the number of - * keys found on that page and below. - */ -typedef struct _rinternal { - recno_t nrecs; /* number of records */ - pgno_t pgno; /* page number stored below */ -} RINTERNAL; - -/* Get the page's RINTERNAL structure at index indx. */ -#define GETRINTERNAL(pg, indx) \ - ((RINTERNAL *)((char *)(pg) + (pg)->linp[indx])) - -/* Get the number of bytes in the entry. */ -#define NRINTERNAL \ - LALIGN(sizeof(recno_t) + sizeof(pgno_t)) - -/* Copy a RINTERNAL entry to the page. */ -#define WR_RINTERNAL(p, nrecs, pgno) { \ - *(recno_t *)p = nrecs; \ - p += sizeof(recno_t); \ - *(pgno_t *)p = pgno; \ -} - -/* For the btree leaf pages, the item is a key and data pair. */ -typedef struct _bleaf { - u_int32_t ksize; /* size of key */ - u_int32_t dsize; /* size of data */ - u_char flags; /* P_BIGDATA, P_BIGKEY */ - char bytes[1]; /* data */ -} BLEAF; - -/* Get the page's BLEAF structure at index indx. */ -#define GETBLEAF(pg, indx) \ - ((BLEAF *)((char *)(pg) + (pg)->linp[indx])) - -/* Get the number of bytes in the entry. */ -#define NBLEAF(p) NBLEAFDBT((p)->ksize, (p)->dsize) - -/* Get the number of bytes in the user's key/data pair. */ -#define NBLEAFDBT(ksize, dsize) \ - LALIGN(sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(u_char) + \ - (ksize) + (dsize)) - -/* Copy a BLEAF entry to the page. */ -#define WR_BLEAF(p, key, data, flags) { \ - *(u_int32_t *)p = key->size; \ - p += sizeof(u_int32_t); \ - *(u_int32_t *)p = data->size; \ - p += sizeof(u_int32_t); \ - *(u_char *)p = flags; \ - p += sizeof(u_char); \ - memmove(p, key->data, key->size); \ - p += key->size; \ - memmove(p, data->data, data->size); \ -} - -/* For the recno leaf pages, the item is a data entry. */ -typedef struct _rleaf { - u_int32_t dsize; /* size of data */ - u_char flags; /* P_BIGDATA */ - char bytes[1]; -} RLEAF; - -/* Get the page's RLEAF structure at index indx. */ -#define GETRLEAF(pg, indx) \ - ((RLEAF *)((char *)(pg) + (pg)->linp[indx])) - -/* Get the number of bytes in the entry. */ -#define NRLEAF(p) NRLEAFDBT((p)->dsize) - -/* Get the number of bytes from the user's data. */ -#define NRLEAFDBT(dsize) \ - LALIGN(sizeof(u_int32_t) + sizeof(u_char) + (dsize)) - -/* Copy a RLEAF entry to the page. */ -#define WR_RLEAF(p, data, flags) { \ - *(u_int32_t *)p = data->size; \ - p += sizeof(u_int32_t); \ - *(u_char *)p = flags; \ - p += sizeof(u_char); \ - memmove(p, data->data, data->size); \ -} - -/* - * A record in the tree is either a pointer to a page and an index in the page - * or a page number and an index. These structures are used as a cursor, stack - * entry and search returns as well as to pass records to other routines. - * - * One comment about searches. Internal page searches must find the largest - * record less than key in the tree so that descents work. Leaf page searches - * must find the smallest record greater than key so that the returned index - * is the record's correct position for insertion. - */ -typedef struct _epgno { - pgno_t pgno; /* the page number */ - indx_t index; /* the index on the page */ -} EPGNO; - -typedef struct _epg { - PAGE *page; /* the (pinned) page */ - indx_t index; /* the index on the page */ -} EPG; - -/* - * About cursors. The cursor (and the page that contained the key/data pair - * that it referenced) can be deleted, which makes things a bit tricky. If - * there are no duplicates of the cursor key in the tree (i.e. B_NODUPS is set - * or there simply aren't any duplicates of the key) we copy the key that it - * referenced when it's deleted, and reacquire a new cursor key if the cursor - * is used again. If there are duplicates keys, we move to the next/previous - * key, and set a flag so that we know what happened. NOTE: if duplicate (to - * the cursor) keys are added to the tree during this process, it is undefined - * if they will be returned or not in a cursor scan. - * - * The flags determine the possible states of the cursor: - * - * CURS_INIT The cursor references *something*. - * CURS_ACQUIRE The cursor was deleted, and a key has been saved so that - * we can reacquire the right position in the tree. - * CURS_AFTER, CURS_BEFORE - * The cursor was deleted, and now references a key/data pair - * that has not yet been returned, either before or after the - * deleted key/data pair. - * XXX - * This structure is broken out so that we can eventually offer multiple - * cursors as part of the DB interface. - */ -typedef struct _cursor { - EPGNO pg; /* B: Saved tree reference. */ - DBT key; /* B: Saved key, or key.data == NULL. */ - recno_t rcursor; /* R: recno cursor (1-based) */ - -#define CURS_ACQUIRE 0x01 /* B: Cursor needs to be reacquired. */ -#define CURS_AFTER 0x02 /* B: Unreturned cursor after key. */ -#define CURS_BEFORE 0x04 /* B: Unreturned cursor before key. */ -#define CURS_INIT 0x08 /* RB: Cursor initialized. */ - u_int8_t flags; -} CURSOR; - -/* - * The metadata of the tree. The nrecs field is used only by the RECNO code. - * This is because the btree doesn't really need it and it requires that every - * put or delete call modify the metadata. - */ -typedef struct _btmeta { - u_int32_t magic; /* magic number */ - u_int32_t version; /* version */ - u_int32_t psize; /* page size */ - u_int32_t free; /* page number of first free page */ - u_int32_t nrecs; /* R: number of records */ - -#define SAVEMETA (B_NODUPS | R_RECNO) - u_int32_t flags; /* bt_flags & SAVEMETA */ -} BTMETA; - -/* The in-memory btree/recno data structure. */ -typedef struct _btree { - MPOOL *bt_mp; /* memory pool cookie */ - - DB *bt_dbp; /* pointer to enclosing DB */ - - EPG bt_cur; /* current (pinned) page */ - PAGE *bt_pinned; /* page pinned across calls */ - - CURSOR bt_cursor; /* cursor */ - -#define BT_PUSH(t, p, i) { \ - t->bt_sp->pgno = p; \ - t->bt_sp->index = i; \ - ++t->bt_sp; \ -} -#define BT_POP(t) (t->bt_sp == t->bt_stack ? NULL : --t->bt_sp) -#define BT_CLR(t) (t->bt_sp = t->bt_stack) - EPGNO bt_stack[50]; /* stack of parent pages */ - EPGNO *bt_sp; /* current stack pointer */ - - DBT bt_rkey; /* returned key */ - DBT bt_rdata; /* returned data */ - - int bt_fd; /* tree file descriptor */ - - pgno_t bt_free; /* next free page */ - u_int32_t bt_psize; /* page size */ - indx_t bt_ovflsize; /* cut-off for key/data overflow */ - int bt_lorder; /* byte order */ - /* sorted order */ - enum { NOT, BACK, FORWARD } bt_order; - EPGNO bt_last; /* last insert */ - - /* B: key comparison function */ - int (*bt_cmp) __P((const DBT *, const DBT *)); - /* B: prefix comparison function */ - size_t (*bt_pfx) __P((const DBT *, const DBT *)); - /* R: recno input function */ - int (*bt_irec) __P((struct _btree *, recno_t)); - - FILE *bt_rfp; /* R: record FILE pointer */ - int bt_rfd; /* R: record file descriptor */ - - caddr_t bt_cmap; /* R: current point in mapped space */ - caddr_t bt_smap; /* R: start of mapped space */ - caddr_t bt_emap; /* R: end of mapped space */ - size_t bt_msize; /* R: size of mapped region. */ - - recno_t bt_nrecs; /* R: number of records */ - size_t bt_reclen; /* R: fixed record length */ - u_char bt_bval; /* R: delimiting byte/pad character */ - -/* - * NB: - * B_NODUPS and R_RECNO are stored on disk, and may not be changed. - */ -#define B_INMEM 0x00001 /* in-memory tree */ -#define B_METADIRTY 0x00002 /* need to write metadata */ -#define B_MODIFIED 0x00004 /* tree modified */ -#define B_NEEDSWAP 0x00008 /* if byte order requires swapping */ -#define B_RDONLY 0x00010 /* read-only tree */ - -#define B_NODUPS 0x00020 /* no duplicate keys permitted */ -#define R_RECNO 0x00080 /* record oriented tree */ - -#define R_CLOSEFP 0x00040 /* opened a file pointer */ -#define R_EOF 0x00100 /* end of input file reached. */ -#define R_FIXLEN 0x00200 /* fixed length records */ -#define R_MEMMAPPED 0x00400 /* memory mapped file. */ -#define R_INMEM 0x00800 /* in-memory file */ -#define R_MODIFIED 0x01000 /* modified file */ -#define R_RDONLY 0x02000 /* read-only file */ - -#define B_DB_LOCK 0x04000 /* DB_LOCK specified. */ -#define B_DB_SHMEM 0x08000 /* DB_SHMEM specified. */ -#define B_DB_TXN 0x10000 /* DB_TXN specified. */ - u_int32_t flags; -} BTREE; - -#include "extern.h" diff --git a/main/db1-ast/btree/extern.h b/main/db1-ast/btree/extern.h deleted file mode 100644 index ebd9c5492..000000000 --- a/main/db1-ast/btree/extern.h +++ /dev/null @@ -1,70 +0,0 @@ -/*- - * Copyright (c) 1991, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)extern.h 8.10 (Berkeley) 7/20/94 - */ - -int __bt_close __P((DB *)); -int __bt_cmp __P((BTREE *, const DBT *, EPG *)); -int __bt_crsrdel __P((BTREE *, EPGNO *)); -int __bt_defcmp __P((const DBT *, const DBT *)); -size_t __bt_defpfx __P((const DBT *, const DBT *)); -int __bt_delete __P((const DB *, const DBT *, u_int)); -int __bt_dleaf __P((BTREE *, const DBT *, PAGE *, u_int)); -int __bt_fd __P((const DB *)); -int __bt_free __P((BTREE *, PAGE *)); -int __bt_get __P((const DB *, const DBT *, DBT *, u_int)); -PAGE *__bt_new __P((BTREE *, pgno_t *)); -void __bt_pgin __P((void *, pgno_t, void *)); -void __bt_pgout __P((void *, pgno_t, void *)); -int __bt_push __P((BTREE *, pgno_t, int)); -int __bt_put __P((const DB *dbp, DBT *, const DBT *, u_int)); -int __bt_ret __P((BTREE *, EPG *, DBT *, DBT *, DBT *, DBT *, int)); -EPG *__bt_search __P((BTREE *, const DBT *, int *)); -int __bt_seq __P((const DB *, DBT *, DBT *, u_int)); -void __bt_setcur __P((BTREE *, pgno_t, u_int)); -int __bt_split __P((BTREE *, PAGE *, - const DBT *, const DBT *, int, size_t, u_int32_t)); -int __bt_sync __P((const DB *, u_int)); - -int __ovfl_delete __P((BTREE *, void *)); -int __ovfl_get __P((BTREE *, void *, size_t *, void **, size_t *)); -int __ovfl_put __P((BTREE *, const DBT *, pgno_t *)); - -#ifdef DEBUG -void __bt_dnpage __P((DB *, pgno_t)); -void __bt_dpage __P((PAGE *)); -void __bt_dump __P((DB *)); -#endif -#ifdef STATISTICS -void __bt_stat __P((DB *)); -#endif diff --git a/main/db1-ast/db/db.c b/main/db1-ast/db/db.c deleted file mode 100644 index 8c0584d4c..000000000 --- a/main/db1-ast/db/db.c +++ /dev/null @@ -1,103 +0,0 @@ -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)db.c 8.4 (Berkeley) 2/21/94"; -#endif /* LIBC_SCCS and not lint */ - -#include - -#include -#include -#include -#include - -#include "../include/db.h" - -DB * -dbopen(fname, flags, mode, type, openinfo) - const char *fname; - int flags, mode; - DBTYPE type; - const void *openinfo; -{ - -#define DB_FLAGS (DB_LOCK | DB_SHMEM | DB_TXN) -#define USE_OPEN_FLAGS \ - (O_CREAT | O_EXCL | O_EXLOCK | O_NONBLOCK | O_RDONLY | \ - O_RDWR | O_SHLOCK | O_TRUNC) - - if ((flags & ~(USE_OPEN_FLAGS | DB_FLAGS)) == 0) - switch (type) { - case DB_BTREE: - return (__bt_open(fname, flags & USE_OPEN_FLAGS, - mode, openinfo, flags & DB_FLAGS)); - case DB_HASH: - return (__hash_open(fname, flags & USE_OPEN_FLAGS, - mode, openinfo, flags & DB_FLAGS)); - case DB_RECNO: - return (__rec_open(fname, flags & USE_OPEN_FLAGS, - mode, openinfo, flags & DB_FLAGS)); - } - errno = EINVAL; - return (NULL); -} - -static int -__dberr __P((void)) -{ - return (RET_ERROR); -} - -/* - * __DBPANIC -- Stop. - * - * Parameters: - * dbp: pointer to the DB structure. - */ -void -__dbpanic(dbp) - DB *dbp; -{ - /* The only thing that can succeed is a close. */ - dbp->del = (int (*)__P((const struct __db *, - const DBT *, u_int))) __dberr; - dbp->get = (int (*)__P((const struct __db *, - const DBT *, DBT *, u_int))) __dberr; - dbp->put = (int (*)__P((const struct __db *, - DBT *, const DBT *, u_int))) __dberr; - dbp->seq = (int (*)__P((const struct __db *, - DBT *, DBT *, u_int))) __dberr; - dbp->sync = (int (*)__P((const struct __db *, u_int))) __dberr; - dbp->fd = (int (*)__P((const struct __db *))) __dberr; -} diff --git a/main/db1-ast/hash/README b/main/db1-ast/hash/README deleted file mode 100644 index f29ccf7e1..000000000 --- a/main/db1-ast/hash/README +++ /dev/null @@ -1,72 +0,0 @@ -# @(#)README 8.1 (Berkeley) 6/4/93 - -This package implements a superset of the hsearch and dbm/ndbm libraries. - -Test Programs: - All test programs which need key/data pairs expect them entered - with key and data on separate lines - - tcreat3.c - Takes - bucketsize (bsize), - fill factor (ffactor), and - initial number of elements (nelem). - Creates a hash table named hashtest containing the - keys/data pairs entered from standard in. - thash4.c - Takes - bucketsize (bsize), - fill factor (ffactor), - initial number of elements (nelem) - bytes of cache (ncached), and - file from which to read data (fname) - Creates a table from the key/data pairs on standard in and - then does a read of each key/data in fname - tdel.c - Takes - bucketsize (bsize), and - fill factor (ffactor). - file from which to read data (fname) - Reads each key/data pair from fname and deletes the - key from the hash table hashtest - tseq.c - Reads the key/data pairs in the file hashtest and writes them - to standard out. - tread2.c - Takes - butes of cache (ncached). - Reads key/data pairs from standard in and looks them up - in the file hashtest. - tverify.c - Reads key/data pairs from standard in, looks them up - in the file hashtest, and verifies that the data is - correct. - -NOTES: - -The file search.h is provided for using the hsearch compatible interface -on BSD systems. On System V derived systems, search.h should appear in -/usr/include. - -The man page ../man/db.3 explains the interface to the hashing system. -The file hash.ps is a postscript copy of a paper explaining -the history, implementation, and performance of the hash package. - -"bugs" or idiosyncracies - -If you have a lot of overflows, it is possible to run out of overflow -pages. Currently, this will cause a message to be printed on stderr. -Eventually, this will be indicated by a return error code. - -If you are using the ndbm interface and exit without flushing or closing the -file, you may lose updates since the package buffers all writes. Also, -the db interface only creates a single database file. To avoid overwriting -the user's original file, the suffix ".db" is appended to the file name -passed to dbm_open. Additionally, if your code "knows" about the historic -.dir and .pag files, it will break. - -There is a fundamental difference between this package and the old hsearch. -Hsearch requires the user to maintain the keys and data in the application's -allocated memory while hash takes care of all storage management. The down -side is that the byte strings passed in the ENTRY structure must be null -terminated (both the keys and the data). diff --git a/main/db1-ast/hash/extern.h b/main/db1-ast/hash/extern.h deleted file mode 100644 index 4f1f23d67..000000000 --- a/main/db1-ast/hash/extern.h +++ /dev/null @@ -1,65 +0,0 @@ -/*- - * Copyright (c) 1991, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)extern.h 8.4 (Berkeley) 6/16/94 - */ - -BUFHEAD *__add_ovflpage __P((HTAB *, BUFHEAD *)); -int __addel __P((HTAB *, BUFHEAD *, const DBT *, const DBT *)); -int __big_delete __P((HTAB *, BUFHEAD *)); -int __big_insert __P((HTAB *, BUFHEAD *, const DBT *, const DBT *)); -int __big_keydata __P((HTAB *, BUFHEAD *, DBT *, DBT *, int)); -int __big_return __P((HTAB *, BUFHEAD *, int, DBT *, int)); -int __big_split __P((HTAB *, BUFHEAD *, BUFHEAD *, BUFHEAD *, - int, u_int32_t, SPLIT_RETURN *)); -int __buf_free __P((HTAB *, int, int)); -void __buf_init __P((HTAB *, int)); -u_int32_t __call_hash __P((HTAB *, char *, int)); -int __delpair __P((HTAB *, BUFHEAD *, int)); -int __expand_table __P((HTAB *)); -int __find_bigpair __P((HTAB *, BUFHEAD *, int, char *, int)); -u_int16_t __find_last_page __P((HTAB *, BUFHEAD **)); -void __free_ovflpage __P((HTAB *, BUFHEAD *)); -BUFHEAD *__get_buf __P((HTAB *, u_int32_t, BUFHEAD *, int)); -int __get_page __P((HTAB *, char *, u_int32_t, int, int, int)); -int __ibitmap __P((HTAB *, int, int, int)); -u_int32_t __hash_log2 __P((u_int32_t)); -int __put_page __P((HTAB *, char *, u_int32_t, int, int)); -void __reclaim_buf __P((HTAB *, BUFHEAD *)); -int __split_page __P((HTAB *, u_int32_t, u_int32_t)); - -/* Default hash routine. */ -extern u_int32_t (*__default_hash) __P((const void *, size_t)); - -#ifdef HASH_STATISTICS -extern int hash_accesses, hash_collisions, hash_expansions, hash_overflows; -#endif diff --git a/main/db1-ast/hash/hash.c b/main/db1-ast/hash/hash.c deleted file mode 100644 index 47dc52a0e..000000000 --- a/main/db1-ast/hash/hash.c +++ /dev/null @@ -1,999 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Margo Seltzer. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)hash.c 8.9 (Berkeley) 6/16/94"; -#endif /* LIBC_SCCS and not lint */ - -#include -#include - -#include -#include -#include -#include -#include -#include -#ifdef DEBUG -#include -#endif - -#include "../include/db.h" -#include "hash.h" -#include "page.h" -#include "extern.h" - -static int alloc_segs __P((HTAB *, int)); -static int flush_meta __P((HTAB *)); -static int hash_access __P((HTAB *, ACTION, DBT *, DBT *)); -static int hash_close __P((DB *)); -static int hash_delete __P((const DB *, const DBT *, u_int32_t)); -static int hash_fd __P((const DB *)); -static int hash_get __P((const DB *, const DBT *, DBT *, u_int32_t)); -static int hash_put __P((const DB *, DBT *, const DBT *, u_int32_t)); -static void *hash_realloc __P((SEGMENT **, int, int)); -static int hash_seq __P((const DB *, DBT *, DBT *, u_int32_t)); -static int hash_sync __P((const DB *, u_int32_t)); -static int hdestroy __P((HTAB *)); -static HTAB *init_hash __P((HTAB *, const char *, const HASHINFO *)); -static int init_htab __P((HTAB *, int)); -#if BYTE_ORDER == LITTLE_ENDIAN -static void swap_header __P((HTAB *)); -static void swap_header_copy __P((HASHHDR *, HASHHDR *)); -#endif - -/* Fast arithmetic, relying on powers of 2, */ -#define MOD(x, y) ((x) & ((y) - 1)) - -#define RETURN_ERROR(ERR, LOC) { save_errno = ERR; goto LOC; } - -/* Return values */ -#define SUCCESS (0) -#define ERROR (-1) -#define ABNORMAL (1) - -#ifdef HASH_STATISTICS -int hash_accesses, hash_collisions, hash_expansions, hash_overflows; -#endif - -/************************** INTERFACE ROUTINES ***************************/ -/* OPEN/CLOSE */ - -extern DB * -__hash_open(file, flags, mode, info, dflags) - const char *file; - int flags, mode, dflags; - const HASHINFO *info; /* Special directives for create */ -{ - HTAB *hashp; - struct stat statbuf; - DB *dbp; - int bpages, hdrsize, new_table, nsegs, save_errno; - - if ((flags & O_ACCMODE) == O_WRONLY) { - errno = EINVAL; - return (NULL); - } - - if (!(hashp = (HTAB *)calloc(1, sizeof(HTAB)))) - return (NULL); - hashp->fp = -1; - - /* - * Even if user wants write only, we need to be able to read - * the actual file, so we need to open it read/write. But, the - * field in the hashp structure needs to be accurate so that - * we can check accesses. - */ - hashp->flags = flags; - - new_table = 0; - if (!file || (flags & O_TRUNC) || - (stat(file, &statbuf) && (errno == ENOENT))) { - if (errno == ENOENT) - errno = 0; /* Just in case someone looks at errno */ - new_table = 1; - } - if (file) { - if ((hashp->fp = open(file, flags, mode)) == -1) - RETURN_ERROR(errno, error0); - (void)fcntl(hashp->fp, F_SETFD, 1); - } - if (new_table) { - if (!(hashp = init_hash(hashp, file, info))) - RETURN_ERROR(errno, error1); - } else { - /* Table already exists */ - if (info && info->hash) - hashp->hash = info->hash; - else - hashp->hash = __default_hash; - - hdrsize = read(hashp->fp, &hashp->hdr, sizeof(HASHHDR)); -#if BYTE_ORDER == LITTLE_ENDIAN - swap_header(hashp); -#endif - if (hdrsize == -1) - RETURN_ERROR(errno, error1); - if (hdrsize != sizeof(HASHHDR)) - RETURN_ERROR(EFTYPE, error1); - /* Verify file type, versions and hash function */ - if (hashp->MAGIC != HASHMAGIC) - RETURN_ERROR(EFTYPE, error1); -#define OLDHASHVERSION 1 - if (hashp->VERSION != HASHVERSION && - hashp->VERSION != OLDHASHVERSION) - RETURN_ERROR(EFTYPE, error1); - if (hashp->hash(CHARKEY, sizeof(CHARKEY)) - != (u_int32_t) hashp->H_CHARKEY) - RETURN_ERROR(EFTYPE, error1); - /* - * Figure out how many segments we need. Max_Bucket is the - * maximum bucket number, so the number of buckets is - * max_bucket + 1. - */ - nsegs = (hashp->MAX_BUCKET + 1 + hashp->SGSIZE - 1) / - hashp->SGSIZE; - hashp->nsegs = 0; - if (alloc_segs(hashp, nsegs)) - /* - * If alloc_segs fails, table will have been destroyed - * and errno will have been set. - */ - return (NULL); - /* Read in bitmaps */ - bpages = (hashp->SPARES[hashp->OVFL_POINT] + - (hashp->BSIZE << BYTE_SHIFT) - 1) >> - (hashp->BSHIFT + BYTE_SHIFT); - - hashp->nmaps = bpages; - (void)memset(&hashp->mapp[0], 0, bpages * sizeof(u_int32_t *)); - } - - /* Initialize Buffer Manager */ - if (info && info->cachesize) - __buf_init(hashp, info->cachesize); - else - __buf_init(hashp, DEF_BUFSIZE); - - hashp->new_file = new_table; - hashp->save_file = file && (hashp->flags & O_ACCMODE) != O_RDONLY; - hashp->cbucket = -1; - if (!(dbp = (DB *)malloc(sizeof(DB)))) { - save_errno = errno; - hdestroy(hashp); - errno = save_errno; - return (NULL); - } - dbp->internal = hashp; - dbp->close = hash_close; - dbp->del = hash_delete; - dbp->fd = hash_fd; - dbp->get = hash_get; - dbp->put = hash_put; - dbp->seq = hash_seq; - dbp->sync = hash_sync; - dbp->type = DB_HASH; - -#ifdef DEBUG - (void)fprintf(stderr, -"%s\n%s%x\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%x\n%s%x\n%s%d\n%s%d\n", - "init_htab:", - "TABLE POINTER ", hashp, - "BUCKET SIZE ", hashp->BSIZE, - "BUCKET SHIFT ", hashp->BSHIFT, - "DIRECTORY SIZE ", hashp->DSIZE, - "SEGMENT SIZE ", hashp->SGSIZE, - "SEGMENT SHIFT ", hashp->SSHIFT, - "FILL FACTOR ", hashp->FFACTOR, - "MAX BUCKET ", hashp->MAX_BUCKET, - "OVFL POINT ", hashp->OVFL_POINT, - "LAST FREED ", hashp->LAST_FREED, - "HIGH MASK ", hashp->HIGH_MASK, - "LOW MASK ", hashp->LOW_MASK, - "NSEGS ", hashp->nsegs, - "NKEYS ", hashp->NKEYS); -#endif -#ifdef HASH_STATISTICS - hash_overflows = hash_accesses = hash_collisions = hash_expansions = 0; -#endif - return (dbp); - -error1: - if (hashp != NULL) - (void)close(hashp->fp); - -error0: - free(hashp); - errno = save_errno; - return (NULL); -} - -static int -hash_close(dbp) - DB *dbp; -{ - HTAB *hashp; - int retval; - - if (!dbp) - return (ERROR); - - hashp = (HTAB *)dbp->internal; - retval = hdestroy(hashp); - free(dbp); - return (retval); -} - -static int -hash_fd(dbp) - const DB *dbp; -{ - HTAB *hashp; - - if (!dbp) - return (ERROR); - - hashp = (HTAB *)dbp->internal; - if (hashp->fp == -1) { - errno = ENOENT; - return (-1); - } - return (hashp->fp); -} - -/************************** LOCAL CREATION ROUTINES **********************/ -static HTAB * -init_hash(hashp, file, info) - HTAB *hashp; - const char *file; - const HASHINFO *info; -{ -#ifdef _STATBUF_ST_BLKSIZE - struct stat statbuf; -#endif - int nelem; - - nelem = 1; - hashp->NKEYS = 0; - hashp->LORDER = BYTE_ORDER; - hashp->BSIZE = DEF_BUCKET_SIZE; - hashp->BSHIFT = DEF_BUCKET_SHIFT; - hashp->SGSIZE = DEF_SEGSIZE; - hashp->SSHIFT = DEF_SEGSIZE_SHIFT; - hashp->DSIZE = DEF_DIRSIZE; - hashp->FFACTOR = DEF_FFACTOR; - hashp->hash = __default_hash; - memset(hashp->SPARES, 0, sizeof(hashp->SPARES)); - memset(hashp->BITMAPS, 0, sizeof (hashp->BITMAPS)); - - /* Fix bucket size to be optimal for file system */ -#ifdef _STATBUF_ST_BLKSIZE - if (file != NULL) { - if (stat(file, &statbuf)) - return (NULL); - hashp->BSIZE = statbuf.st_blksize; - hashp->BSHIFT = __hash_log2(hashp->BSIZE); - } -#endif - - if (info) { - if (info->bsize) { - /* Round pagesize up to power of 2 */ - hashp->BSHIFT = __hash_log2(info->bsize); - hashp->BSIZE = 1 << hashp->BSHIFT; - if (hashp->BSIZE > MAX_BSIZE) { - errno = EINVAL; - return (NULL); - } - } - if (info->ffactor) - hashp->FFACTOR = info->ffactor; - if (info->hash) - hashp->hash = info->hash; - if (info->nelem) - nelem = info->nelem; - if (info->lorder) { - if (info->lorder != BIG_ENDIAN && - info->lorder != LITTLE_ENDIAN) { - errno = EINVAL; - return (NULL); - } - hashp->LORDER = info->lorder; - } - } - /* init_htab should destroy the table and set errno if it fails */ - if (init_htab(hashp, nelem)) - return (NULL); - else - return (hashp); -} -/* - * This calls alloc_segs which may run out of memory. Alloc_segs will destroy - * the table and set errno, so we just pass the error information along. - * - * Returns 0 on No Error - */ -static int -init_htab(hashp, nelem) - HTAB *hashp; - int nelem; -{ - register int nbuckets, nsegs; - int l2; - - /* - * Divide number of elements by the fill factor and determine a - * desired number of buckets. Allocate space for the next greater - * power of two number of buckets. - */ - nelem = (nelem - 1) / hashp->FFACTOR + 1; - - l2 = __hash_log2(MAX(nelem, 2)); - nbuckets = 1 << l2; - - hashp->SPARES[l2] = l2 + 1; - hashp->SPARES[l2 + 1] = l2 + 1; - hashp->OVFL_POINT = l2; - hashp->LAST_FREED = 2; - - /* First bitmap page is at: splitpoint l2 page offset 1 */ - if (__ibitmap(hashp, OADDR_OF(l2, 1), l2 + 1, 0)) - return (-1); - - hashp->MAX_BUCKET = hashp->LOW_MASK = nbuckets - 1; - hashp->HIGH_MASK = (nbuckets << 1) - 1; - hashp->HDRPAGES = ((MAX(sizeof(HASHHDR), MINHDRSIZE) - 1) >> - hashp->BSHIFT) + 1; - - nsegs = (nbuckets - 1) / hashp->SGSIZE + 1; - nsegs = 1 << __hash_log2(nsegs); - - if (nsegs > hashp->DSIZE) - hashp->DSIZE = nsegs; - return (alloc_segs(hashp, nsegs)); -} - -/********************** DESTROY/CLOSE ROUTINES ************************/ - -/* - * Flushes any changes to the file if necessary and destroys the hashp - * structure, freeing all allocated space. - */ -static int -hdestroy(hashp) - HTAB *hashp; -{ - int i, save_errno; - - save_errno = 0; - -#ifdef HASH_STATISTICS - (void)fprintf(stderr, "hdestroy: accesses %ld collisions %ld\n", - hash_accesses, hash_collisions); - (void)fprintf(stderr, "hdestroy: expansions %ld\n", - hash_expansions); - (void)fprintf(stderr, "hdestroy: overflows %ld\n", - hash_overflows); - (void)fprintf(stderr, "keys %ld maxp %d segmentcount %d\n", - hashp->NKEYS, hashp->MAX_BUCKET, hashp->nsegs); - - for (i = 0; i < NCACHED; i++) - (void)fprintf(stderr, - "spares[%d] = %d\n", i, hashp->SPARES[i]); -#endif - /* - * Call on buffer manager to free buffers, and if required, - * write them to disk. - */ - if (__buf_free(hashp, 1, hashp->save_file)) - save_errno = errno; - if (hashp->dir) { - free(*hashp->dir); /* Free initial segments */ - /* Free extra segments */ - while (hashp->exsegs--) - free(hashp->dir[--hashp->nsegs]); - free(hashp->dir); - } - if (flush_meta(hashp) && !save_errno) - save_errno = errno; - /* Free Bigmaps */ - for (i = 0; i < hashp->nmaps; i++) - if (hashp->mapp[i]) - free(hashp->mapp[i]); - - if (hashp->fp != -1) - (void)close(hashp->fp); - - free(hashp); - - if (save_errno) { - errno = save_errno; - return (ERROR); - } - return (SUCCESS); -} -/* - * Write modified pages to disk - * - * Returns: - * 0 == OK - * -1 ERROR - */ -static int -hash_sync(dbp, flags) - const DB *dbp; - u_int32_t flags; -{ - HTAB *hashp; - - if (flags != 0) { - errno = EINVAL; - return (ERROR); - } - - if (!dbp) - return (ERROR); - - hashp = (HTAB *)dbp->internal; - if (!hashp->save_file) - return (0); - if (__buf_free(hashp, 0, 1) || flush_meta(hashp)) - return (ERROR); - hashp->new_file = 0; - return (0); -} - -/* - * Returns: - * 0 == OK - * -1 indicates that errno should be set - */ -static int -flush_meta(hashp) - HTAB *hashp; -{ - HASHHDR *whdrp; -#if BYTE_ORDER == LITTLE_ENDIAN - HASHHDR whdr; -#endif - int fp, i, wsize; - - if (!hashp->save_file) - return (0); - hashp->MAGIC = HASHMAGIC; - hashp->VERSION = HASHVERSION; - hashp->H_CHARKEY = hashp->hash(CHARKEY, sizeof(CHARKEY)); - - fp = hashp->fp; - whdrp = &hashp->hdr; -#if BYTE_ORDER == LITTLE_ENDIAN - whdrp = &whdr; - swap_header_copy(&hashp->hdr, whdrp); -#endif - if ((lseek(fp, (off_t)0, SEEK_SET) == -1) || - ((wsize = write(fp, whdrp, sizeof(HASHHDR))) == -1)) - return (-1); - else - if (wsize != sizeof(HASHHDR)) { - errno = EFTYPE; - hashp->errnum = errno; - return (-1); - } - for (i = 0; i < NCACHED; i++) - if (hashp->mapp[i]) - if (__put_page(hashp, (char *)hashp->mapp[i], - hashp->BITMAPS[i], 0, 1)) - return (-1); - return (0); -} - -/*******************************SEARCH ROUTINES *****************************/ -/* - * All the access routines return - * - * Returns: - * 0 on SUCCESS - * 1 to indicate an external ERROR (i.e. key not found, etc) - * -1 to indicate an internal ERROR (i.e. out of memory, etc) - */ -static int -hash_get(dbp, key, data, flag) - const DB *dbp; - const DBT *key; - DBT *data; - u_int32_t flag; -{ - HTAB *hashp; - - hashp = (HTAB *)dbp->internal; - if (flag) { - hashp->errnum = errno = EINVAL; - return (ERROR); - } - return (hash_access(hashp, HASH_GET, (DBT *)key, data)); -} - -static int -hash_put(dbp, key, data, flag) - const DB *dbp; - DBT *key; - const DBT *data; - u_int32_t flag; -{ - HTAB *hashp; - - hashp = (HTAB *)dbp->internal; - if (flag && flag != R_NOOVERWRITE) { - hashp->errnum = errno = EINVAL; - return (ERROR); - } - if ((hashp->flags & O_ACCMODE) == O_RDONLY) { - hashp->errnum = errno = EPERM; - return (ERROR); - } - return (hash_access(hashp, flag == R_NOOVERWRITE ? - HASH_PUTNEW : HASH_PUT, (DBT *)key, (DBT *)data)); -} - -static int -hash_delete(dbp, key, flag) - const DB *dbp; - const DBT *key; - u_int32_t flag; /* Ignored */ -{ - HTAB *hashp; - - hashp = (HTAB *)dbp->internal; - if (flag && flag != R_CURSOR) { - hashp->errnum = errno = EINVAL; - return (ERROR); - } - if ((hashp->flags & O_ACCMODE) == O_RDONLY) { - hashp->errnum = errno = EPERM; - return (ERROR); - } - return (hash_access(hashp, HASH_DELETE, (DBT *)key, NULL)); -} - -/* - * Assume that hashp has been set in wrapper routine. - */ -static int -hash_access(hashp, action, key, val) - HTAB *hashp; - ACTION action; - DBT *key, *val; -{ - register BUFHEAD *rbufp; - BUFHEAD *bufp, *save_bufp; - register u_int16_t *bp; - register int n, ndx, off, size; - register char *kp; - u_int16_t pageno; - -#ifdef HASH_STATISTICS - hash_accesses++; -#endif - - off = hashp->BSIZE; - size = key->size; - kp = (char *)key->data; - rbufp = __get_buf(hashp, __call_hash(hashp, kp, size), NULL, 0); - if (!rbufp) - return (ERROR); - save_bufp = rbufp; - - /* Pin the bucket chain */ - rbufp->flags |= BUF_PIN; - for (bp = (u_int16_t *)rbufp->page, n = *bp++, ndx = 1; ndx < n;) - if (bp[1] >= REAL_KEY) { - /* Real key/data pair */ - if (size == off - *bp && - memcmp(kp, rbufp->page + *bp, size) == 0) - goto found; - off = bp[1]; -#ifdef HASH_STATISTICS - hash_collisions++; -#endif - bp += 2; - ndx += 2; - } else if (bp[1] == OVFLPAGE) { - rbufp = __get_buf(hashp, *bp, rbufp, 0); - if (!rbufp) { - save_bufp->flags &= ~BUF_PIN; - return (ERROR); - } - /* FOR LOOP INIT */ - bp = (u_int16_t *)rbufp->page; - n = *bp++; - ndx = 1; - off = hashp->BSIZE; - } else if (bp[1] < REAL_KEY) { - if ((ndx = - __find_bigpair(hashp, rbufp, ndx, kp, size)) > 0) - goto found; - if (ndx == -2) { - bufp = rbufp; - if (!(pageno = - __find_last_page(hashp, &bufp))) { - ndx = 0; - rbufp = bufp; - break; /* FOR */ - } - rbufp = __get_buf(hashp, pageno, bufp, 0); - if (!rbufp) { - save_bufp->flags &= ~BUF_PIN; - return (ERROR); - } - /* FOR LOOP INIT */ - bp = (u_int16_t *)rbufp->page; - n = *bp++; - ndx = 1; - off = hashp->BSIZE; - } else { - save_bufp->flags &= ~BUF_PIN; - return (ERROR); - } - } - - /* Not found */ - switch (action) { - case HASH_PUT: - case HASH_PUTNEW: - if (__addel(hashp, rbufp, key, val)) { - save_bufp->flags &= ~BUF_PIN; - return (ERROR); - } else { - save_bufp->flags &= ~BUF_PIN; - return (SUCCESS); - } - case HASH_GET: - case HASH_DELETE: - default: - save_bufp->flags &= ~BUF_PIN; - return (ABNORMAL); - } - -found: - switch (action) { - case HASH_PUTNEW: - save_bufp->flags &= ~BUF_PIN; - return (ABNORMAL); - case HASH_GET: - bp = (u_int16_t *)rbufp->page; - if (bp[ndx + 1] < REAL_KEY) { - if (__big_return(hashp, rbufp, ndx, val, 0)) - return (ERROR); - } else { - val->data = (u_char *)rbufp->page + (int)bp[ndx + 1]; - val->size = bp[ndx] - bp[ndx + 1]; - } - break; - case HASH_PUT: - if ((__delpair(hashp, rbufp, ndx)) || - (__addel(hashp, rbufp, key, val))) { - save_bufp->flags &= ~BUF_PIN; - return (ERROR); - } - break; - case HASH_DELETE: - if (__delpair(hashp, rbufp, ndx)) - return (ERROR); - break; - default: - abort(); - } - save_bufp->flags &= ~BUF_PIN; - return (SUCCESS); -} - -static int -hash_seq(dbp, key, data, flag) - const DB *dbp; - DBT *key, *data; - u_int32_t flag; -{ - register u_int32_t bucket; - register BUFHEAD *bufp = NULL; - HTAB *hashp; - u_int16_t *bp, ndx; - - hashp = (HTAB *)dbp->internal; - if (flag && flag != R_FIRST && flag != R_NEXT) { - hashp->errnum = errno = EINVAL; - return (ERROR); - } -#ifdef HASH_STATISTICS - hash_accesses++; -#endif - if ((hashp->cbucket < 0) || (flag == R_FIRST)) { - hashp->cbucket = 0; - hashp->cndx = 1; - hashp->cpage = NULL; - } - - for (bp = NULL; !bp || !bp[0]; ) { - if (!(bufp = hashp->cpage)) { - for (bucket = hashp->cbucket; - bucket <= (u_int32_t) hashp->MAX_BUCKET; - bucket++, hashp->cndx = 1) { - bufp = __get_buf(hashp, bucket, NULL, 0); - if (!bufp) - return (ERROR); - hashp->cpage = bufp; - bp = (u_int16_t *)bufp->page; - if (bp[0]) - break; - } - hashp->cbucket = bucket; - if (hashp->cbucket > hashp->MAX_BUCKET) { - hashp->cbucket = -1; - return (ABNORMAL); - } - } else - bp = (u_int16_t *)hashp->cpage->page; - -#ifdef DEBUG - assert(bp); - assert(bufp); -#endif - while (bp[hashp->cndx + 1] == OVFLPAGE) { - bufp = hashp->cpage = - __get_buf(hashp, bp[hashp->cndx], bufp, 0); - if (!bufp) - return (ERROR); - bp = (u_int16_t *)(bufp->page); - hashp->cndx = 1; - } - if (!bp[0]) { - hashp->cpage = NULL; - ++hashp->cbucket; - } - } - ndx = hashp->cndx; - if (bp[ndx + 1] < REAL_KEY) { - if (__big_keydata(hashp, bufp, key, data, 1)) - return (ERROR); - } else { - key->data = (u_char *)hashp->cpage->page + bp[ndx]; - key->size = (ndx > 1 ? bp[ndx - 1] : hashp->BSIZE) - bp[ndx]; - data->data = (u_char *)hashp->cpage->page + bp[ndx + 1]; - data->size = bp[ndx] - bp[ndx + 1]; - ndx += 2; - if (ndx > bp[0]) { - hashp->cpage = NULL; - hashp->cbucket++; - hashp->cndx = 1; - } else - hashp->cndx = ndx; - } - return (SUCCESS); -} - -/********************************* UTILITIES ************************/ - -/* - * Returns: - * 0 ==> OK - * -1 ==> Error - */ -extern int -__expand_table(hashp) - HTAB *hashp; -{ - u_int32_t old_bucket, new_bucket; - int dirsize, new_segnum, spare_ndx; - -#ifdef HASH_STATISTICS - hash_expansions++; -#endif - new_bucket = ++hashp->MAX_BUCKET; - old_bucket = (hashp->MAX_BUCKET & hashp->LOW_MASK); - - new_segnum = new_bucket >> hashp->SSHIFT; - - /* Check if we need a new segment */ - if (new_segnum >= hashp->nsegs) { - /* Check if we need to expand directory */ - if (new_segnum >= hashp->DSIZE) { - /* Reallocate directory */ - dirsize = hashp->DSIZE * sizeof(SEGMENT *); - if (!hash_realloc(&hashp->dir, dirsize, dirsize << 1)) - return (-1); - hashp->DSIZE = dirsize << 1; - } - if ((hashp->dir[new_segnum] = - (SEGMENT)calloc(hashp->SGSIZE, sizeof(SEGMENT))) == NULL) - return (-1); - hashp->exsegs++; - hashp->nsegs++; - } - /* - * If the split point is increasing (MAX_BUCKET's log base 2 - * * increases), we need to copy the current contents of the spare - * split bucket to the next bucket. - */ - spare_ndx = __hash_log2(hashp->MAX_BUCKET + 1); - if (spare_ndx > hashp->OVFL_POINT) { - hashp->SPARES[spare_ndx] = hashp->SPARES[hashp->OVFL_POINT]; - hashp->OVFL_POINT = spare_ndx; - } - - if (new_bucket > (u_int32_t) hashp->HIGH_MASK) { - /* Starting a new doubling */ - hashp->LOW_MASK = hashp->HIGH_MASK; - hashp->HIGH_MASK = new_bucket | hashp->LOW_MASK; - } - /* Relocate records to the new bucket */ - return (__split_page(hashp, old_bucket, new_bucket)); -} - -/* - * If realloc guarantees that the pointer is not destroyed if the realloc - * fails, then this routine can go away. - */ -static void * -hash_realloc(p_ptr, oldsize, newsize) - SEGMENT **p_ptr; - int oldsize, newsize; -{ - register void *p; - - if ((p = malloc(newsize))) { - memmove(p, *p_ptr, oldsize); - memset((char *)p + oldsize, 0, newsize - oldsize); - free(*p_ptr); - *p_ptr = p; - } - return (p); -} - -extern u_int32_t -__call_hash(hashp, k, len) - HTAB *hashp; - char *k; - int len; -{ - int n, bucket; - - n = hashp->hash(k, len); - bucket = n & hashp->HIGH_MASK; - if (bucket > hashp->MAX_BUCKET) - bucket = bucket & hashp->LOW_MASK; - return (bucket); -} - -/* - * Allocate segment table. On error, destroy the table and set errno. - * - * Returns 0 on success - */ -static int -alloc_segs(hashp, nsegs) - HTAB *hashp; - int nsegs; -{ - register int i; - register SEGMENT store; - - int save_errno; - - if ((hashp->dir = - (SEGMENT *)calloc(hashp->DSIZE, sizeof(SEGMENT *))) == NULL) { - save_errno = errno; - (void)hdestroy(hashp); - errno = save_errno; - return (-1); - } - /* Allocate segments */ - if ((store = - (SEGMENT)calloc(nsegs << hashp->SSHIFT, sizeof(SEGMENT))) == NULL) { - save_errno = errno; - (void)hdestroy(hashp); - errno = save_errno; - return (-1); - } - for (i = 0; i < nsegs; i++, hashp->nsegs++) - hashp->dir[i] = &store[i << hashp->SSHIFT]; - return (0); -} - -#if BYTE_ORDER == LITTLE_ENDIAN -/* - * Hashp->hdr needs to be byteswapped. - */ -static void -swap_header_copy(srcp, destp) - HASHHDR *srcp, *destp; -{ - int i; - - P_32_COPY(srcp->magic, destp->magic); - P_32_COPY(srcp->version, destp->version); - P_32_COPY(srcp->lorder, destp->lorder); - P_32_COPY(srcp->bsize, destp->bsize); - P_32_COPY(srcp->bshift, destp->bshift); - P_32_COPY(srcp->dsize, destp->dsize); - P_32_COPY(srcp->ssize, destp->ssize); - P_32_COPY(srcp->sshift, destp->sshift); - P_32_COPY(srcp->ovfl_point, destp->ovfl_point); - P_32_COPY(srcp->last_freed, destp->last_freed); - P_32_COPY(srcp->max_bucket, destp->max_bucket); - P_32_COPY(srcp->high_mask, destp->high_mask); - P_32_COPY(srcp->low_mask, destp->low_mask); - P_32_COPY(srcp->ffactor, destp->ffactor); - P_32_COPY(srcp->nkeys, destp->nkeys); - P_32_COPY(srcp->hdrpages, destp->hdrpages); - P_32_COPY(srcp->h_charkey, destp->h_charkey); - for (i = 0; i < NCACHED; i++) { - P_32_COPY(srcp->spares[i], destp->spares[i]); - P_16_COPY(srcp->bitmaps[i], destp->bitmaps[i]); - } -} - -static void -swap_header(hashp) - HTAB *hashp; -{ - HASHHDR *hdrp; - int i; - - hdrp = &hashp->hdr; - - M_32_SWAP(hdrp->magic); - M_32_SWAP(hdrp->version); - M_32_SWAP(hdrp->lorder); - M_32_SWAP(hdrp->bsize); - M_32_SWAP(hdrp->bshift); - M_32_SWAP(hdrp->dsize); - M_32_SWAP(hdrp->ssize); - M_32_SWAP(hdrp->sshift); - M_32_SWAP(hdrp->ovfl_point); - M_32_SWAP(hdrp->last_freed); - M_32_SWAP(hdrp->max_bucket); - M_32_SWAP(hdrp->high_mask); - M_32_SWAP(hdrp->low_mask); - M_32_SWAP(hdrp->ffactor); - M_32_SWAP(hdrp->nkeys); - M_32_SWAP(hdrp->hdrpages); - M_32_SWAP(hdrp->h_charkey); - for (i = 0; i < NCACHED; i++) { - M_32_SWAP(hdrp->spares[i]); - M_16_SWAP(hdrp->bitmaps[i]); - } -} -#endif diff --git a/main/db1-ast/hash/hash.h b/main/db1-ast/hash/hash.h deleted file mode 100644 index d07db6f07..000000000 --- a/main/db1-ast/hash/hash.h +++ /dev/null @@ -1,293 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Margo Seltzer. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)hash.h 8.3 (Berkeley) 5/31/94 - */ - -/* Operations */ -typedef enum { - HASH_GET, HASH_PUT, HASH_PUTNEW, HASH_DELETE, HASH_FIRST, HASH_NEXT -} ACTION; - -/* Buffer Management structures */ -typedef struct _bufhead BUFHEAD; - -struct _bufhead { - BUFHEAD *prev; /* LRU links */ - BUFHEAD *next; /* LRU links */ - BUFHEAD *ovfl; /* Overflow page buffer header */ - u_int32_t addr; /* Address of this page */ - char *page; /* Actual page data */ - char flags; -#define BUF_MOD 0x0001 -#define BUF_DISK 0x0002 -#define BUF_BUCKET 0x0004 -#define BUF_PIN 0x0008 -}; - -#define IS_BUCKET(X) ((X) & BUF_BUCKET) - -typedef BUFHEAD **SEGMENT; - -/* Hash Table Information */ -typedef struct hashhdr { /* Disk resident portion */ - int magic; /* Magic NO for hash tables */ - int version; /* Version ID */ - u_int32_t lorder; /* Byte Order */ - int bsize; /* Bucket/Page Size */ - int bshift; /* Bucket shift */ - int dsize; /* Directory Size */ - int ssize; /* Segment Size */ - int sshift; /* Segment shift */ - int ovfl_point; /* Where overflow pages are being - * allocated */ - int last_freed; /* Last overflow page freed */ - int max_bucket; /* ID of Maximum bucket in use */ - int high_mask; /* Mask to modulo into entire table */ - int low_mask; /* Mask to modulo into lower half of - * table */ - int ffactor; /* Fill factor */ - int nkeys; /* Number of keys in hash table */ - int hdrpages; /* Size of table header */ - int h_charkey; /* value of hash(CHARKEY) */ -#define NCACHED 32 /* number of bit maps and spare - * points */ - int spares[NCACHED];/* spare pages for overflow */ - u_int16_t bitmaps[NCACHED]; /* address of overflow page - * bitmaps */ -} HASHHDR; - -typedef struct htab { /* Memory resident data structure */ - HASHHDR hdr; /* Header */ - int nsegs; /* Number of allocated segments */ - int exsegs; /* Number of extra allocated - * segments */ - u_int32_t /* Hash function */ - (*hash)__P((const void *, size_t)); - int flags; /* Flag values */ - int fp; /* File pointer */ - char *tmp_buf; /* Temporary Buffer for BIG data */ - char *tmp_key; /* Temporary Buffer for BIG keys */ - BUFHEAD *cpage; /* Current page */ - int cbucket; /* Current bucket */ - int cndx; /* Index of next item on cpage */ - int errnum; /* Error Number -- for DBM - * compatibility */ - int new_file; /* Indicates if fd is backing store - * or no */ - int save_file; /* Indicates whether we need to flush - * file at - * exit */ - u_int32_t *mapp[NCACHED]; /* Pointers to page maps */ - int nmaps; /* Initial number of bitmaps */ - int nbufs; /* Number of buffers left to - * allocate */ - BUFHEAD bufhead; /* Header of buffer lru list */ - SEGMENT *dir; /* Hash Bucket directory */ -} HTAB; - -/* - * Constants - */ -#define MAX_BSIZE 65536 /* 2^16 */ -#define MIN_BUFFERS 6 -#define MINHDRSIZE 512 -#define DEF_BUFSIZE 65536 /* 64 K */ -#define DEF_BUCKET_SIZE 4096 -#define DEF_BUCKET_SHIFT 12 /* log2(BUCKET) */ -#define DEF_SEGSIZE 256 -#define DEF_SEGSIZE_SHIFT 8 /* log2(SEGSIZE) */ -#define DEF_DIRSIZE 256 -#define DEF_FFACTOR 65536 -#define MIN_FFACTOR 4 -#define SPLTMAX 8 -#define CHARKEY "%$sniglet^&" -#define NUMKEY 1038583 -#define BYTE_SHIFT 3 -#define INT_TO_BYTE 2 -#define INT_BYTE_SHIFT 5 -#define ALL_SET ((u_int32_t)0xFFFFFFFF) -#define ALL_CLEAR 0 - -#define PTROF(X) ((BUFHEAD *)((ptrdiff_t)(X)&~0x3)) -#define ISMOD(X) ((u_int32_t)(ptrdiff_t)(X)&0x1) -#define DOMOD(X) ((X) = (char *)((ptrdiff_t)(X)|0x1)) -#define ISDISK(X) ((u_int32_t)(ptrdiff_t)(X)&0x2) -#define DODISK(X) ((X) = (char *)((ptrdiff_t)(X)|0x2)) - -#define BITS_PER_MAP 32 - -/* Given the address of the beginning of a big map, clear/set the nth bit */ -#define CLRBIT(A, N) ((A)[(N)/BITS_PER_MAP] &= ~(1<<((N)%BITS_PER_MAP))) -#define SETBIT(A, N) ((A)[(N)/BITS_PER_MAP] |= (1<<((N)%BITS_PER_MAP))) -#define ISSET(A, N) ((A)[(N)/BITS_PER_MAP] & (1<<((N)%BITS_PER_MAP))) - -/* Overflow management */ -/* - * Overflow page numbers are allocated per split point. At each doubling of - * the table, we can allocate extra pages. So, an overflow page number has - * the top 5 bits indicate which split point and the lower 11 bits indicate - * which page at that split point is indicated (pages within split points are - * numberered starting with 1). - */ - -#define SPLITSHIFT 11 -#define SPLITMASK 0x7FF -#define SPLITNUM(N) (((u_int32_t)(N)) >> SPLITSHIFT) -#define OPAGENUM(N) ((N) & SPLITMASK) -#define OADDR_OF(S,O) ((u_int32_t)((u_int32_t)(S) << SPLITSHIFT) + (O)) - -#define BUCKET_TO_PAGE(B) \ - (B) + hashp->HDRPAGES + ((B) ? hashp->SPARES[__hash_log2((B)+1)-1] : 0) -#define OADDR_TO_PAGE(B) \ - BUCKET_TO_PAGE ( (1 << SPLITNUM((B))) -1 ) + OPAGENUM((B)); - -/* - * page.h contains a detailed description of the page format. - * - * Normally, keys and data are accessed from offset tables in the top of - * each page which point to the beginning of the key and data. There are - * four flag values which may be stored in these offset tables which indicate - * the following: - * - * - * OVFLPAGE Rather than a key data pair, this pair contains - * the address of an overflow page. The format of - * the pair is: - * OVERFLOW_PAGE_NUMBER OVFLPAGE - * - * PARTIAL_KEY This must be the first key/data pair on a page - * and implies that page contains only a partial key. - * That is, the key is too big to fit on a single page - * so it starts on this page and continues on the next. - * The format of the page is: - * KEY_OFF PARTIAL_KEY OVFL_PAGENO OVFLPAGE - * - * KEY_OFF -- offset of the beginning of the key - * PARTIAL_KEY -- 1 - * OVFL_PAGENO - page number of the next overflow page - * OVFLPAGE -- 0 - * - * FULL_KEY This must be the first key/data pair on the page. It - * is used in two cases. - * - * Case 1: - * There is a complete key on the page but no data - * (because it wouldn't fit). The next page contains - * the data. - * - * Page format it: - * KEY_OFF FULL_KEY OVFL_PAGENO OVFL_PAGE - * - * KEY_OFF -- offset of the beginning of the key - * FULL_KEY -- 2 - * OVFL_PAGENO - page number of the next overflow page - * OVFLPAGE -- 0 - * - * Case 2: - * This page contains no key, but part of a large - * data field, which is continued on the next page. - * - * Page format it: - * DATA_OFF FULL_KEY OVFL_PAGENO OVFL_PAGE - * - * KEY_OFF -- offset of the beginning of the data on - * this page - * FULL_KEY -- 2 - * OVFL_PAGENO - page number of the next overflow page - * OVFLPAGE -- 0 - * - * FULL_KEY_DATA - * This must be the first key/data pair on the page. - * There are two cases: - * - * Case 1: - * This page contains a key and the beginning of the - * data field, but the data field is continued on the - * next page. - * - * Page format is: - * KEY_OFF FULL_KEY_DATA OVFL_PAGENO DATA_OFF - * - * KEY_OFF -- offset of the beginning of the key - * FULL_KEY_DATA -- 3 - * OVFL_PAGENO - page number of the next overflow page - * DATA_OFF -- offset of the beginning of the data - * - * Case 2: - * This page contains the last page of a big data pair. - * There is no key, only the tail end of the data - * on this page. - * - * Page format is: - * DATA_OFF FULL_KEY_DATA - * - * DATA_OFF -- offset of the beginning of the data on - * this page - * FULL_KEY_DATA -- 3 - * OVFL_PAGENO - page number of the next overflow page - * OVFLPAGE -- 0 - * - * OVFL_PAGENO and OVFLPAGE are optional (they are - * not present if there is no next page). - */ - -#define OVFLPAGE 0 -#define PARTIAL_KEY 1 -#define FULL_KEY 2 -#define FULL_KEY_DATA 3 -#define REAL_KEY 4 - -/* Short hands for accessing structure */ -#define BSIZE hdr.bsize -#define BSHIFT hdr.bshift -#define DSIZE hdr.dsize -#define SGSIZE hdr.ssize -#define SSHIFT hdr.sshift -#define LORDER hdr.lorder -#define OVFL_POINT hdr.ovfl_point -#define LAST_FREED hdr.last_freed -#define MAX_BUCKET hdr.max_bucket -#define FFACTOR hdr.ffactor -#define HIGH_MASK hdr.high_mask -#define LOW_MASK hdr.low_mask -#define NKEYS hdr.nkeys -#define HDRPAGES hdr.hdrpages -#define SPARES hdr.spares -#define BITMAPS hdr.bitmaps -#define VERSION hdr.version -#define MAGIC hdr.magic -#define NEXT_FREE hdr.next_free -#define H_CHARKEY hdr.h_charkey diff --git a/main/db1-ast/hash/hash_bigkey.c b/main/db1-ast/hash/hash_bigkey.c deleted file mode 100644 index daa8c1f17..000000000 --- a/main/db1-ast/hash/hash_bigkey.c +++ /dev/null @@ -1,668 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Margo Seltzer. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)hash_bigkey.c 8.3 (Berkeley) 5/31/94"; -#endif /* LIBC_SCCS and not lint */ - -/* - * PACKAGE: hash - * DESCRIPTION: - * Big key/data handling for the hashing package. - * - * ROUTINES: - * External - * __big_keydata - * __big_split - * __big_insert - * __big_return - * __big_delete - * __find_last_page - * Internal - * collect_key - * collect_data - */ - -#include - -#include -#include -#include -#include - -#ifdef DEBUG -#include -#endif - -#include "../include/db.h" -#include "hash.h" -#include "page.h" -#include "extern.h" - -static int collect_key __P((HTAB *, BUFHEAD *, int, DBT *, int)); -static int collect_data __P((HTAB *, BUFHEAD *, int, int)); - -/* - * Big_insert - * - * You need to do an insert and the key/data pair is too big - * - * Returns: - * 0 ==> OK - *-1 ==> ERROR - */ -extern int -__big_insert(hashp, bufp, key, val) - HTAB *hashp; - BUFHEAD *bufp; - const DBT *key, *val; -{ - register u_int16_t *p; - int key_size, n, val_size; - u_int16_t space, move_bytes, off; - char *cp, *key_data, *val_data; - - cp = bufp->page; /* Character pointer of p. */ - p = (u_int16_t *)cp; - - key_data = (char *)key->data; - key_size = key->size; - val_data = (char *)val->data; - val_size = val->size; - - /* First move the Key */ - for (space = FREESPACE(p) - BIGOVERHEAD; key_size; - space = FREESPACE(p) - BIGOVERHEAD) { - move_bytes = MIN(space, key_size); - off = OFFSET(p) - move_bytes; - memmove(cp + off, key_data, move_bytes); - key_size -= move_bytes; - key_data += move_bytes; - n = p[0]; - p[++n] = off; - p[0] = ++n; - FREESPACE(p) = off - PAGE_META(n); - OFFSET(p) = off; - p[n] = PARTIAL_KEY; - bufp = __add_ovflpage(hashp, bufp); - if (!bufp) - return (-1); - n = p[0]; - if (!key_size) { - if (FREESPACE(p)) { - move_bytes = MIN(FREESPACE(p), val_size); - off = OFFSET(p) - move_bytes; - p[n] = off; - memmove(cp + off, val_data, move_bytes); - val_data += move_bytes; - val_size -= move_bytes; - p[n - 2] = FULL_KEY_DATA; - FREESPACE(p) = FREESPACE(p) - move_bytes; - OFFSET(p) = off; - } else - p[n - 2] = FULL_KEY; - } - p = (u_int16_t *)bufp->page; - cp = bufp->page; - bufp->flags |= BUF_MOD; - } - - /* Now move the data */ - for (space = FREESPACE(p) - BIGOVERHEAD; val_size; - space = FREESPACE(p) - BIGOVERHEAD) { - move_bytes = MIN(space, val_size); - /* - * Here's the hack to make sure that if the data ends on the - * same page as the key ends, FREESPACE is at least one. - */ - if ((int) space == val_size && (size_t) val_size == val->size) - move_bytes--; - off = OFFSET(p) - move_bytes; - memmove(cp + off, val_data, move_bytes); - val_size -= move_bytes; - val_data += move_bytes; - n = p[0]; - p[++n] = off; - p[0] = ++n; - FREESPACE(p) = off - PAGE_META(n); - OFFSET(p) = off; - if (val_size) { - p[n] = FULL_KEY; - bufp = __add_ovflpage(hashp, bufp); - if (!bufp) - return (-1); - cp = bufp->page; - p = (u_int16_t *)cp; - } else - p[n] = FULL_KEY_DATA; - bufp->flags |= BUF_MOD; - } - return (0); -} - -/* - * Called when bufp's page contains a partial key (index should be 1) - * - * All pages in the big key/data pair except bufp are freed. We cannot - * free bufp because the page pointing to it is lost and we can't get rid - * of its pointer. - * - * Returns: - * 0 => OK - *-1 => ERROR - */ -extern int -__big_delete(hashp, bufp) - HTAB *hashp; - BUFHEAD *bufp; -{ - register BUFHEAD *last_bfp, *rbufp; - u_int16_t *bp, pageno; - int key_done, n; - - rbufp = bufp; - last_bfp = NULL; - bp = (u_int16_t *)bufp->page; - pageno = 0; - key_done = 0; - - while (!key_done || (bp[2] != FULL_KEY_DATA)) { - if (bp[2] == FULL_KEY || bp[2] == FULL_KEY_DATA) - key_done = 1; - - /* - * If there is freespace left on a FULL_KEY_DATA page, then - * the data is short and fits entirely on this page, and this - * is the last page. - */ - if (bp[2] == FULL_KEY_DATA && FREESPACE(bp)) - break; - pageno = bp[bp[0] - 1]; - rbufp->flags |= BUF_MOD; - rbufp = __get_buf(hashp, pageno, rbufp, 0); - if (last_bfp) - __free_ovflpage(hashp, last_bfp); - last_bfp = rbufp; - if (!rbufp) - return (-1); /* Error. */ - bp = (u_int16_t *)rbufp->page; - } - - /* - * If we get here then rbufp points to the last page of the big - * key/data pair. Bufp points to the first one -- it should now be - * empty pointing to the next page after this pair. Can't free it - * because we don't have the page pointing to it. - */ - - /* This is information from the last page of the pair. */ - n = bp[0]; - pageno = bp[n - 1]; - - /* Now, bp is the first page of the pair. */ - bp = (u_int16_t *)bufp->page; - if (n > 2) { - /* There is an overflow page. */ - bp[1] = pageno; - bp[2] = OVFLPAGE; - bufp->ovfl = rbufp->ovfl; - } else - /* This is the last page. */ - bufp->ovfl = NULL; - n -= 2; - bp[0] = n; - FREESPACE(bp) = hashp->BSIZE - PAGE_META(n); - OFFSET(bp) = hashp->BSIZE - 1; - - bufp->flags |= BUF_MOD; - if (rbufp) - __free_ovflpage(hashp, rbufp); - if (last_bfp && last_bfp != rbufp) - __free_ovflpage(hashp, last_bfp); - - hashp->NKEYS--; - return (0); -} -/* - * Returns: - * 0 = key not found - * -1 = get next overflow page - * -2 means key not found and this is big key/data - * -3 error - */ -extern int -__find_bigpair(hashp, bufp, ndx, key, size) - HTAB *hashp; - BUFHEAD *bufp; - int ndx; - char *key; - int size; -{ - register u_int16_t *bp; - register char *p; - int ksize; - u_int16_t bytes; - char *kkey; - - bp = (u_int16_t *)bufp->page; - p = bufp->page; - ksize = size; - kkey = key; - - for (bytes = hashp->BSIZE - bp[ndx]; - bytes <= size && bp[ndx + 1] == PARTIAL_KEY; - bytes = hashp->BSIZE - bp[ndx]) { - if (memcmp(p + bp[ndx], kkey, bytes)) - return (-2); - kkey += bytes; - ksize -= bytes; - bufp = __get_buf(hashp, bp[ndx + 2], bufp, 0); - if (!bufp) - return (-3); - p = bufp->page; - bp = (u_int16_t *)p; - ndx = 1; - } - - if (bytes != ksize || memcmp(p + bp[ndx], kkey, bytes)) { -#ifdef HASH_STATISTICS - ++hash_collisions; -#endif - return (-2); - } else - return (ndx); -} - -/* - * Given the buffer pointer of the first overflow page of a big pair, - * find the end of the big pair - * - * This will set bpp to the buffer header of the last page of the big pair. - * It will return the pageno of the overflow page following the last page - * of the pair; 0 if there isn't any (i.e. big pair is the last key in the - * bucket) - */ -extern u_int16_t -__find_last_page(hashp, bpp) - HTAB *hashp; - BUFHEAD **bpp; -{ - BUFHEAD *bufp; - u_int16_t *bp, pageno; - int n; - - bufp = *bpp; - bp = (u_int16_t *)bufp->page; - for (;;) { - n = bp[0]; - - /* - * This is the last page if: the tag is FULL_KEY_DATA and - * either only 2 entries OVFLPAGE marker is explicit there - * is freespace on the page. - */ - if (bp[2] == FULL_KEY_DATA && - ((n == 2) || (bp[n] == OVFLPAGE) || (FREESPACE(bp)))) - break; - - pageno = bp[n - 1]; - bufp = __get_buf(hashp, pageno, bufp, 0); - if (!bufp) - return (0); /* Need to indicate an error! */ - bp = (u_int16_t *)bufp->page; - } - - *bpp = bufp; - if (bp[0] > 2) - return (bp[3]); - else - return (0); -} - -/* - * Return the data for the key/data pair that begins on this page at this - * index (index should always be 1). - */ -extern int -__big_return(hashp, bufp, ndx, val, set_current) - HTAB *hashp; - BUFHEAD *bufp; - int ndx; - DBT *val; - int set_current; -{ - BUFHEAD *save_p; - u_int16_t *bp, len, off, save_addr; - char *tp; - - bp = (u_int16_t *)bufp->page; - while (bp[ndx + 1] == PARTIAL_KEY) { - bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0); - if (!bufp) - return (-1); - bp = (u_int16_t *)bufp->page; - ndx = 1; - } - - if (bp[ndx + 1] == FULL_KEY) { - bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0); - if (!bufp) - return (-1); - bp = (u_int16_t *)bufp->page; - save_p = bufp; - save_addr = save_p->addr; - off = bp[1]; - len = 0; - } else - if (!FREESPACE(bp)) { - /* - * This is a hack. We can't distinguish between - * FULL_KEY_DATA that contains complete data or - * incomplete data, so we require that if the data - * is complete, there is at least 1 byte of free - * space left. - */ - off = bp[bp[0]]; - len = bp[1] - off; - save_p = bufp; - save_addr = bufp->addr; - bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0); - if (!bufp) - return (-1); - bp = (u_int16_t *)bufp->page; - } else { - /* The data is all on one page. */ - tp = (char *)bp; - off = bp[bp[0]]; - val->data = (u_char *)tp + off; - val->size = bp[1] - off; - if (set_current) { - if (bp[0] == 2) { /* No more buckets in - * chain */ - hashp->cpage = NULL; - hashp->cbucket++; - hashp->cndx = 1; - } else { - hashp->cpage = __get_buf(hashp, - bp[bp[0] - 1], bufp, 0); - if (!hashp->cpage) - return (-1); - hashp->cndx = 1; - if (!((u_int16_t *) - hashp->cpage->page)[0]) { - hashp->cbucket++; - hashp->cpage = NULL; - } - } - } - return (0); - } - - val->size = collect_data(hashp, bufp, (int)len, set_current); - if (val->size == (size_t) -1) - return (-1); - if (save_p->addr != save_addr) { - /* We are pretty short on buffers. */ - errno = EINVAL; /* OUT OF BUFFERS */ - return (-1); - } - memmove(hashp->tmp_buf, (save_p->page) + off, len); - val->data = (u_char *)hashp->tmp_buf; - return (0); -} -/* - * Count how big the total datasize is by recursing through the pages. Then - * allocate a buffer and copy the data as you recurse up. - */ -static int -collect_data(hashp, bufp, len, set) - HTAB *hashp; - BUFHEAD *bufp; - int len, set; -{ - register u_int16_t *bp; - register char *p; - BUFHEAD *xbp; - u_int16_t save_addr; - int mylen, totlen; - - p = bufp->page; - bp = (u_int16_t *)p; - mylen = hashp->BSIZE - bp[1]; - save_addr = bufp->addr; - - if (bp[2] == FULL_KEY_DATA) { /* End of Data */ - totlen = len + mylen; - if (hashp->tmp_buf) - free(hashp->tmp_buf); - if ((hashp->tmp_buf = (char *)malloc(totlen)) == NULL) - return (-1); - if (set) { - hashp->cndx = 1; - if (bp[0] == 2) { /* No more buckets in chain */ - hashp->cpage = NULL; - hashp->cbucket++; - } else { - hashp->cpage = - __get_buf(hashp, bp[bp[0] - 1], bufp, 0); - if (!hashp->cpage) - return (-1); - else if (!((u_int16_t *)hashp->cpage->page)[0]) { - hashp->cbucket++; - hashp->cpage = NULL; - } - } - } - } else { - xbp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0); - if (!xbp || ((totlen = - collect_data(hashp, xbp, len + mylen, set)) < 1)) - return (-1); - } - if (bufp->addr != save_addr) { - errno = EINVAL; /* Out of buffers. */ - return (-1); - } - memmove(&hashp->tmp_buf[len], (bufp->page) + bp[1], mylen); - return (totlen); -} - -/* - * Fill in the key and data for this big pair. - */ -extern int -__big_keydata(hashp, bufp, key, val, set) - HTAB *hashp; - BUFHEAD *bufp; - DBT *key, *val; - int set; -{ - key->size = collect_key(hashp, bufp, 0, val, set); - if (key->size == (size_t) -1) - return (-1); - key->data = (u_char *)hashp->tmp_key; - return (0); -} - -/* - * Count how big the total key size is by recursing through the pages. Then - * collect the data, allocate a buffer and copy the key as you recurse up. - */ -static int -collect_key(hashp, bufp, len, val, set) - HTAB *hashp; - BUFHEAD *bufp; - int len; - DBT *val; - int set; -{ - BUFHEAD *xbp; - char *p; - int mylen, totlen; - u_int16_t *bp, save_addr; - - p = bufp->page; - bp = (u_int16_t *)p; - mylen = hashp->BSIZE - bp[1]; - - save_addr = bufp->addr; - totlen = len + mylen; - if (bp[2] == FULL_KEY || bp[2] == FULL_KEY_DATA) { /* End of Key. */ - if (hashp->tmp_key != NULL) - free(hashp->tmp_key); - if ((hashp->tmp_key = (char *)malloc(totlen)) == NULL) - return (-1); - if (__big_return(hashp, bufp, 1, val, set)) - return (-1); - } else { - xbp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0); - if (!xbp || ((totlen = - collect_key(hashp, xbp, totlen, val, set)) < 1)) - return (-1); - } - if (bufp->addr != save_addr) { - errno = EINVAL; /* MIS -- OUT OF BUFFERS */ - return (-1); - } - memmove(&hashp->tmp_key[len], (bufp->page) + bp[1], mylen); - return (totlen); -} - -/* - * Returns: - * 0 => OK - * -1 => error - */ -extern int -__big_split(hashp, op, np, big_keyp, addr, obucket, ret) - HTAB *hashp; - BUFHEAD *op; /* Pointer to where to put keys that go in old bucket */ - BUFHEAD *np; /* Pointer to new bucket page */ - /* Pointer to first page containing the big key/data */ - BUFHEAD *big_keyp; - int addr; /* Address of big_keyp */ - u_int32_t obucket;/* Old Bucket */ - SPLIT_RETURN *ret; -{ - register BUFHEAD *tmpp; - register u_int16_t *tp; - BUFHEAD *bp; - DBT key, val; - u_int32_t change; - u_int16_t free_space, n, off; - - bp = big_keyp; - - /* Now figure out where the big key/data goes */ - if (__big_keydata(hashp, big_keyp, &key, &val, 0)) - return (-1); - change = (__call_hash(hashp, key.data, key.size) != obucket); - - if ((ret->next_addr = __find_last_page(hashp, &big_keyp))) { - if (!(ret->nextp = - __get_buf(hashp, ret->next_addr, big_keyp, 0))) - return (-1);; - } else - ret->nextp = NULL; - - /* Now make one of np/op point to the big key/data pair */ -#ifdef DEBUG - assert(np->ovfl == NULL); -#endif - if (change) - tmpp = np; - else - tmpp = op; - - tmpp->flags |= BUF_MOD; -#ifdef DEBUG1 - (void)fprintf(stderr, - "BIG_SPLIT: %d->ovfl was %d is now %d\n", tmpp->addr, - (tmpp->ovfl ? tmpp->ovfl->addr : 0), (bp ? bp->addr : 0)); -#endif - tmpp->ovfl = bp; /* one of op/np point to big_keyp */ - tp = (u_int16_t *)tmpp->page; -#ifdef DEBUG - assert(FREESPACE(tp) >= OVFLSIZE); -#endif - n = tp[0]; - off = OFFSET(tp); - free_space = FREESPACE(tp); - tp[++n] = (u_int16_t)addr; - tp[++n] = OVFLPAGE; - tp[0] = n; - OFFSET(tp) = off; - FREESPACE(tp) = free_space - OVFLSIZE; - - /* - * Finally, set the new and old return values. BIG_KEYP contains a - * pointer to the last page of the big key_data pair. Make sure that - * big_keyp has no following page (2 elements) or create an empty - * following page. - */ - - ret->newp = np; - ret->oldp = op; - - tp = (u_int16_t *)big_keyp->page; - big_keyp->flags |= BUF_MOD; - if (tp[0] > 2) { - /* - * There may be either one or two offsets on this page. If - * there is one, then the overflow page is linked on normally - * and tp[4] is OVFLPAGE. If there are two, tp[4] contains - * the second offset and needs to get stuffed in after the - * next overflow page is added. - */ - n = tp[4]; - free_space = FREESPACE(tp); - off = OFFSET(tp); - tp[0] -= 2; - FREESPACE(tp) = free_space + OVFLSIZE; - OFFSET(tp) = off; - tmpp = __add_ovflpage(hashp, big_keyp); - if (!tmpp) - return (-1); - tp[4] = n; - } else - tmpp = big_keyp; - - if (change) - ret->newp = tmpp; - else - ret->oldp = tmpp; - return (0); -} diff --git a/main/db1-ast/hash/hash_buf.c b/main/db1-ast/hash/hash_buf.c deleted file mode 100644 index 063dd8229..000000000 --- a/main/db1-ast/hash/hash_buf.c +++ /dev/null @@ -1,355 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Margo Seltzer. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)hash_buf.c 8.5 (Berkeley) 7/15/94"; -#endif /* LIBC_SCCS and not lint */ - -/* - * PACKAGE: hash - * - * DESCRIPTION: - * Contains buffer management - * - * ROUTINES: - * External - * __buf_init - * __get_buf - * __buf_free - * __reclaim_buf - * Internal - * newbuf - */ - -#include - -#include -#include -#include -#include - -#ifdef DEBUG -#include -#endif - -#include "../include/db.h" -#include "hash.h" -#include "page.h" -#include "extern.h" - -static BUFHEAD *newbuf __P((HTAB *, u_int32_t, BUFHEAD *)); - -/* Unlink B from its place in the lru */ -#define BUF_REMOVE(B) { \ - (B)->prev->next = (B)->next; \ - (B)->next->prev = (B)->prev; \ -} - -/* Insert B after P */ -#define BUF_INSERT(B, P) { \ - (B)->next = (P)->next; \ - (B)->prev = (P); \ - (P)->next = (B); \ - (B)->next->prev = (B); \ -} - -#define MRU hashp->bufhead.next -#define LRU hashp->bufhead.prev - -#define MRU_INSERT(B) BUF_INSERT((B), &hashp->bufhead) -#define LRU_INSERT(B) BUF_INSERT((B), LRU) - -/* - * We are looking for a buffer with address "addr". If prev_bp is NULL, then - * address is a bucket index. If prev_bp is not NULL, then it points to the - * page previous to an overflow page that we are trying to find. - * - * CAVEAT: The buffer header accessed via prev_bp's ovfl field may no longer - * be valid. Therefore, you must always verify that its address matches the - * address you are seeking. - */ -extern BUFHEAD * -__get_buf(hashp, addr, prev_bp, newpage) - HTAB *hashp; - u_int32_t addr; - BUFHEAD *prev_bp; - int newpage; /* If prev_bp set, indicates a new overflow page. */ -{ - register BUFHEAD *bp; - register u_int32_t is_disk_mask; - register int is_disk, segment_ndx = 0; - SEGMENT segp = 0; - - is_disk = 0; - is_disk_mask = 0; - if (prev_bp) { - bp = prev_bp->ovfl; - if (!bp || (bp->addr != addr)) - bp = NULL; - if (!newpage) - is_disk = BUF_DISK; - } else { - /* Grab buffer out of directory */ - segment_ndx = addr & (hashp->SGSIZE - 1); - - /* valid segment ensured by __call_hash() */ - segp = hashp->dir[addr >> hashp->SSHIFT]; -#ifdef DEBUG - assert(segp != NULL); -#endif - bp = PTROF(segp[segment_ndx]); - is_disk_mask = ISDISK(segp[segment_ndx]); - is_disk = is_disk_mask || !hashp->new_file; - } - - if (!bp) { - bp = newbuf(hashp, addr, prev_bp); - if (!bp || - __get_page(hashp, bp->page, addr, !prev_bp, is_disk, 0)) - return (NULL); - if (!prev_bp) - segp[segment_ndx] = - (BUFHEAD *)((ptrdiff_t)bp | is_disk_mask); - } else { - BUF_REMOVE(bp); - MRU_INSERT(bp); - } - return (bp); -} - -/* - * We need a buffer for this page. Either allocate one, or evict a resident - * one (if we have as many buffers as we're allowed) and put this one in. - * - * If newbuf finds an error (returning NULL), it also sets errno. - */ -static BUFHEAD * -newbuf(hashp, addr, prev_bp) - HTAB *hashp; - u_int32_t addr; - BUFHEAD *prev_bp; -{ - register BUFHEAD *bp; /* The buffer we're going to use */ - register BUFHEAD *xbp; /* Temp pointer */ - register BUFHEAD *next_xbp; - SEGMENT segp; - int segment_ndx; - u_int16_t oaddr, *shortp; - - oaddr = 0; - bp = LRU; - /* - * If LRU buffer is pinned, the buffer pool is too small. We need to - * allocate more buffers. - */ - if (hashp->nbufs || (bp->flags & BUF_PIN)) { - /* Allocate a new one */ - if ((bp = (BUFHEAD *)malloc(sizeof(BUFHEAD))) == NULL) - return (NULL); -#ifdef PURIFY - memset(bp, 0xff, sizeof(BUFHEAD)); -#endif - if ((bp->page = (char *)malloc(hashp->BSIZE)) == NULL) { - free(bp); - return (NULL); - } -#ifdef PURIFY - memset(bp->page, 0xff, hashp->BSIZE); -#endif - if (hashp->nbufs) - hashp->nbufs--; - } else { - /* Kick someone out */ - BUF_REMOVE(bp); - /* - * If this is an overflow page with addr 0, it's already been - * flushed back in an overflow chain and initialized. - */ - if ((bp->addr != 0) || (bp->flags & BUF_BUCKET)) { - /* - * Set oaddr before __put_page so that you get it - * before bytes are swapped. - */ - shortp = (u_int16_t *)bp->page; - if (shortp[0]) - oaddr = shortp[shortp[0] - 1]; - if ((bp->flags & BUF_MOD) && __put_page(hashp, bp->page, - bp->addr, (int)IS_BUCKET(bp->flags), 0)) - return (NULL); - /* - * Update the pointer to this page (i.e. invalidate it). - * - * If this is a new file (i.e. we created it at open - * time), make sure that we mark pages which have been - * written to disk so we retrieve them from disk later, - * rather than allocating new pages. - */ - if (IS_BUCKET(bp->flags)) { - segment_ndx = bp->addr & (hashp->SGSIZE - 1); - segp = hashp->dir[bp->addr >> hashp->SSHIFT]; -#ifdef DEBUG - assert(segp != NULL); -#endif - - if (hashp->new_file && - ((bp->flags & BUF_MOD) || - ISDISK(segp[segment_ndx]))) - segp[segment_ndx] = (BUFHEAD *)BUF_DISK; - else - segp[segment_ndx] = NULL; - } - /* - * Since overflow pages can only be access by means of - * their bucket, free overflow pages associated with - * this bucket. - */ - for (xbp = bp; xbp->ovfl;) { - next_xbp = xbp->ovfl; - xbp->ovfl = 0; - xbp = next_xbp; - - /* Check that ovfl pointer is up date. */ - if (IS_BUCKET(xbp->flags) || - (oaddr != xbp->addr)) - break; - - shortp = (u_int16_t *)xbp->page; - if (shortp[0]) - /* set before __put_page */ - oaddr = shortp[shortp[0] - 1]; - if ((xbp->flags & BUF_MOD) && __put_page(hashp, - xbp->page, xbp->addr, 0, 0)) - return (NULL); - xbp->addr = 0; - xbp->flags = 0; - BUF_REMOVE(xbp); - LRU_INSERT(xbp); - } - } - } - - /* Now assign this buffer */ - bp->addr = addr; -#ifdef DEBUG1 - (void)fprintf(stderr, "NEWBUF1: %d->ovfl was %d is now %d\n", - bp->addr, (bp->ovfl ? bp->ovfl->addr : 0), 0); -#endif - bp->ovfl = NULL; - if (prev_bp) { - /* - * If prev_bp is set, this is an overflow page, hook it in to - * the buffer overflow links. - */ -#ifdef DEBUG1 - (void)fprintf(stderr, "NEWBUF2: %d->ovfl was %d is now %d\n", - prev_bp->addr, (prev_bp->ovfl ? bp->ovfl->addr : 0), - (bp ? bp->addr : 0)); -#endif - prev_bp->ovfl = bp; - bp->flags = 0; - } else - bp->flags = BUF_BUCKET; - MRU_INSERT(bp); - return (bp); -} - -extern void -__buf_init(hashp, nbytes) - HTAB *hashp; - int nbytes; -{ - BUFHEAD *bfp; - int npages; - - bfp = &(hashp->bufhead); - npages = (nbytes + hashp->BSIZE - 1) >> hashp->BSHIFT; - npages = MAX(npages, MIN_BUFFERS); - - hashp->nbufs = npages; - bfp->next = bfp; - bfp->prev = bfp; - /* - * This space is calloc'd so these are already null. - * - * bfp->ovfl = NULL; - * bfp->flags = 0; - * bfp->page = NULL; - * bfp->addr = 0; - */ -} - -extern int -__buf_free(hashp, do_free, to_disk) - HTAB *hashp; - int do_free, to_disk; -{ - BUFHEAD *bp; - - /* Need to make sure that buffer manager has been initialized */ - if (!LRU) - return (0); - for (bp = LRU; bp != &hashp->bufhead;) { - /* Check that the buffer is valid */ - if (bp->addr || IS_BUCKET(bp->flags)) { - if (to_disk && (bp->flags & BUF_MOD) && - __put_page(hashp, bp->page, - bp->addr, IS_BUCKET(bp->flags), 0)) - return (-1); - } - /* Check if we are freeing stuff */ - if (do_free) { - if (bp->page) - free(bp->page); - BUF_REMOVE(bp); - free(bp); - bp = LRU; - } else - bp = bp->prev; - } - return (0); -} - -extern void -__reclaim_buf(hashp, bp) - HTAB *hashp; - BUFHEAD *bp; -{ - bp->ovfl = 0; - bp->addr = 0; - bp->flags = 0; - BUF_REMOVE(bp); - LRU_INSERT(bp); -} diff --git a/main/db1-ast/hash/hash_func.c b/main/db1-ast/hash/hash_func.c deleted file mode 100644 index 4d7907b57..000000000 --- a/main/db1-ast/hash/hash_func.c +++ /dev/null @@ -1,225 +0,0 @@ -/*- - * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Margo Seltzer. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)hash_func.c 8.2 (Berkeley) 2/21/94"; -#endif /* LIBC_SCCS and not lint */ - -#include - -#include "../include/db.h" -#include "hash.h" -#include "page.h" -#include "extern.h" - -/* only one of these can be defined */ -/* #define HASH1_EJB 1 */ -/* #define HASH2_PHONG 1 */ -/* #define HASH3_SDBM 1 */ -#define HASH4_TOREK 1 - -static u_int32_t hashfunc __P((const void *, size_t)); - -/* Global default hash function */ -u_int32_t (*__default_hash) __P((const void *, size_t)) = hashfunc; - -/* - * HASH FUNCTIONS - * - * Assume that we've already split the bucket to which this key hashes, - * calculate that bucket, and check that in fact we did already split it. - * - * This came from ejb's hsearch. - */ - -#ifdef HASH1_EJB - -#define PRIME1 37 -#define PRIME2 1048583 - -static u_int32_t -hashfunc(keyarg, len) - const void *keyarg; - register size_t len; -{ - register const u_char *key; - register u_int32_t h; - - /* Convert string to integer */ - for (key = keyarg, h = 0; len--;) - h = h * PRIME1 ^ (*key++ - ' '); - h %= PRIME2; - return (h); -} - -#endif - -#ifdef HASH2_PHONG -/* - * Phong's linear congruential hash - */ -#define dcharhash(h, c) ((h) = 0x63c63cd9*(h) + 0x9c39c33d + (c)) - -static u_int32_t -hashfunc(keyarg, len) - const void *keyarg; - size_t len; -{ - register const u_char *e, *key; - register u_int32_t h; - register u_char c; - - key = keyarg; - e = key + len; - for (h = 0; key != e;) { - c = *key++; - if (!c && key > e) - break; - dcharhash(h, c); - } - return (h); -} -#endif - -#ifdef HASH3_SDBM -/* - * This is INCREDIBLY ugly, but fast. We break the string up into 8 byte - * units. On the first time through the loop we get the "leftover bytes" - * (strlen % 8). On every other iteration, we perform 8 HASHC's so we handle - * all 8 bytes. Essentially, this saves us 7 cmp & branch instructions. If - * this routine is heavily used enough, it's worth the ugly coding. - * - * OZ's original sdbm hash - */ -static u_int32_t -hashfunc(keyarg, len) - const void *keyarg; - register size_t len; -{ - register const u_char *key; - register size_t loop; - register u_int32_t h; - -#define HASHC h = *key++ + 65599 * h - - h = 0; - key = keyarg; - if (len > 0) { - loop = (len + 8 - 1) >> 3; - - switch (len & (8 - 1)) { - case 0: - do { - HASHC; - /* FALLTHROUGH */ - case 7: - HASHC; - /* FALLTHROUGH */ - case 6: - HASHC; - /* FALLTHROUGH */ - case 5: - HASHC; - /* FALLTHROUGH */ - case 4: - HASHC; - /* FALLTHROUGH */ - case 3: - HASHC; - /* FALLTHROUGH */ - case 2: - HASHC; - /* FALLTHROUGH */ - case 1: - HASHC; - } while (--loop); - } - } - return (h); -} -#endif - -#ifdef HASH4_TOREK -/* Hash function from Chris Torek. */ -static u_int32_t -hashfunc(keyarg, len) - const void *keyarg; - register size_t len; -{ - register const u_char *key; - register size_t loop; - register u_int32_t h; - -#define HASH4a h = (h << 5) - h + *key++; -#define HASH4b h = (h << 5) + h + *key++; -#define HASH4 HASH4b - - h = 0; - key = keyarg; - if (len > 0) { - loop = (len + 8 - 1) >> 3; - - switch (len & (8 - 1)) { - case 0: - do { - HASH4; - /* FALLTHROUGH */ - case 7: - HASH4; - /* FALLTHROUGH */ - case 6: - HASH4; - /* FALLTHROUGH */ - case 5: - HASH4; - /* FALLTHROUGH */ - case 4: - HASH4; - /* FALLTHROUGH */ - case 3: - HASH4; - /* FALLTHROUGH */ - case 2: - HASH4; - /* FALLTHROUGH */ - case 1: - HASH4; - } while (--loop); - } - } - return (h); -} -#endif diff --git a/main/db1-ast/hash/hash_log2.c b/main/db1-ast/hash/hash_log2.c deleted file mode 100644 index b86655d47..000000000 --- a/main/db1-ast/hash/hash_log2.c +++ /dev/null @@ -1,56 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Margo Seltzer. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)hash_log2.c 8.2 (Berkeley) 5/31/94"; -#endif /* LIBC_SCCS and not lint */ - -#include - -#include "../include/db.h" - -u_int32_t __hash_log2 __P((u_int32_t)); - -u_int32_t -__hash_log2(num) - u_int32_t num; -{ - register u_int32_t i, limit; - - limit = 1; - for (i = 0; limit < num; limit = limit << 1, i++); - return (i); -} diff --git a/main/db1-ast/hash/hash_page.c b/main/db1-ast/hash/hash_page.c deleted file mode 100644 index 52571c552..000000000 --- a/main/db1-ast/hash/hash_page.c +++ /dev/null @@ -1,946 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Margo Seltzer. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)hash_page.c 8.7 (Berkeley) 8/16/94"; -#endif /* LIBC_SCCS and not lint */ - -/* - * PACKAGE: hashing - * - * DESCRIPTION: - * Page manipulation for hashing package. - * - * ROUTINES: - * - * External - * __get_page - * __add_ovflpage - * Internal - * overflow_page - * open_temp - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#ifdef DEBUG -#include -#endif - -#include "../include/db.h" -#include "hash.h" -#include "page.h" -#include "extern.h" - -static u_int32_t *fetch_bitmap __P((HTAB *, int)); -static u_int32_t first_free __P((u_int32_t)); -static int open_temp __P((HTAB *)); -static u_int16_t overflow_page __P((HTAB *)); -static void putpair __P((char *, const DBT *, const DBT *)); -static void squeeze_key __P((u_int16_t *, const DBT *, const DBT *)); -static int ugly_split - __P((HTAB *, u_int32_t, BUFHEAD *, BUFHEAD *, int, int)); - -#define PAGE_INIT(P) { \ - ((u_int16_t *)(P))[0] = 0; \ - ((u_int16_t *)(P))[1] = hashp->BSIZE - 3 * sizeof(u_int16_t); \ - ((u_int16_t *)(P))[2] = hashp->BSIZE; \ -} - -/* - * This is called AFTER we have verified that there is room on the page for - * the pair (PAIRFITS has returned true) so we go right ahead and start moving - * stuff on. - */ -static void -putpair(p, key, val) - char *p; - const DBT *key, *val; -{ - register u_int16_t *bp, n, off; - - bp = (u_int16_t *)p; - - /* Enter the key first. */ - n = bp[0]; - - off = OFFSET(bp) - key->size; - memmove(p + off, key->data, key->size); - bp[++n] = off; - - /* Now the data. */ - off -= val->size; - memmove(p + off, val->data, val->size); - bp[++n] = off; - - /* Adjust page info. */ - bp[0] = n; - bp[n + 1] = off - ((n + 3) * sizeof(u_int16_t)); - bp[n + 2] = off; -} - -/* - * Returns: - * 0 OK - * -1 error - */ -extern int -__delpair(hashp, bufp, ndx) - HTAB *hashp; - BUFHEAD *bufp; - register int ndx; -{ - register u_int16_t *bp, newoff; - register int n; - u_int16_t pairlen; - - bp = (u_int16_t *)bufp->page; - n = bp[0]; - - if (bp[ndx + 1] < REAL_KEY) - return (__big_delete(hashp, bufp)); - if (ndx != 1) - newoff = bp[ndx - 1]; - else - newoff = hashp->BSIZE; - pairlen = newoff - bp[ndx + 1]; - - if (ndx != (n - 1)) { - /* Hard Case -- need to shuffle keys */ - register int i; - register char *src = bufp->page + (int)OFFSET(bp); - register char *dst = src + (int)pairlen; - memmove(dst, src, bp[ndx + 1] - OFFSET(bp)); - - /* Now adjust the pointers */ - for (i = ndx + 2; i <= n; i += 2) { - if (bp[i + 1] == OVFLPAGE) { - bp[i - 2] = bp[i]; - bp[i - 1] = bp[i + 1]; - } else { - bp[i - 2] = bp[i] + pairlen; - bp[i - 1] = bp[i + 1] + pairlen; - } - } - } - /* Finally adjust the page data */ - bp[n] = OFFSET(bp) + pairlen; - bp[n - 1] = bp[n + 1] + pairlen + 2 * sizeof(u_int16_t); - bp[0] = n - 2; - hashp->NKEYS--; - - bufp->flags |= BUF_MOD; - return (0); -} -/* - * Returns: - * 0 ==> OK - * -1 ==> Error - */ -extern int -__split_page(hashp, obucket, nbucket) - HTAB *hashp; - u_int32_t obucket, nbucket; -{ - register BUFHEAD *new_bufp, *old_bufp; - register u_int16_t *ino; - register char *np; - DBT key, val; - int n, ndx, retval; - u_int16_t copyto, diff, off, moved; - char *op; - - copyto = (u_int16_t)hashp->BSIZE; - off = (u_int16_t)hashp->BSIZE; - old_bufp = __get_buf(hashp, obucket, NULL, 0); - if (old_bufp == NULL) - return (-1); - new_bufp = __get_buf(hashp, nbucket, NULL, 0); - if (new_bufp == NULL) - return (-1); - - old_bufp->flags |= (BUF_MOD | BUF_PIN); - new_bufp->flags |= (BUF_MOD | BUF_PIN); - - ino = (u_int16_t *)(op = old_bufp->page); - np = new_bufp->page; - - moved = 0; - - for (n = 1, ndx = 1; n < ino[0]; n += 2) { - if (ino[n + 1] < REAL_KEY) { - retval = ugly_split(hashp, obucket, old_bufp, new_bufp, - (int)copyto, (int)moved); - old_bufp->flags &= ~BUF_PIN; - new_bufp->flags &= ~BUF_PIN; - return (retval); - - } - key.data = (u_char *)op + ino[n]; - key.size = off - ino[n]; - - if (__call_hash(hashp, key.data, key.size) == obucket) { - /* Don't switch page */ - diff = copyto - off; - if (diff) { - copyto = ino[n + 1] + diff; - memmove(op + copyto, op + ino[n + 1], - off - ino[n + 1]); - ino[ndx] = copyto + ino[n] - ino[n + 1]; - ino[ndx + 1] = copyto; - } else - copyto = ino[n + 1]; - ndx += 2; - } else { - /* Switch page */ - val.data = (u_char *)op + ino[n + 1]; - val.size = ino[n] - ino[n + 1]; - putpair(np, &key, &val); - moved += 2; - } - - off = ino[n + 1]; - } - - /* Now clean up the page */ - ino[0] -= moved; - FREESPACE(ino) = copyto - sizeof(u_int16_t) * (ino[0] + 3); - OFFSET(ino) = copyto; - -#ifdef DEBUG3 - (void)fprintf(stderr, "split %d/%d\n", - ((u_int16_t *)np)[0] / 2, - ((u_int16_t *)op)[0] / 2); -#endif - /* unpin both pages */ - old_bufp->flags &= ~BUF_PIN; - new_bufp->flags &= ~BUF_PIN; - return (0); -} - -/* - * Called when we encounter an overflow or big key/data page during split - * handling. This is special cased since we have to begin checking whether - * the key/data pairs fit on their respective pages and because we may need - * overflow pages for both the old and new pages. - * - * The first page might be a page with regular key/data pairs in which case - * we have a regular overflow condition and just need to go on to the next - * page or it might be a big key/data pair in which case we need to fix the - * big key/data pair. - * - * Returns: - * 0 ==> success - * -1 ==> failure - */ -static int -ugly_split(hashp, obucket, old_bufp, new_bufp, copyto, moved) - HTAB *hashp; - u_int32_t obucket; /* Same as __split_page. */ - BUFHEAD *old_bufp, *new_bufp; - int copyto; /* First byte on page which contains key/data values. */ - int moved; /* Number of pairs moved to new page. */ -{ - register BUFHEAD *bufp; /* Buffer header for ino */ - register u_int16_t *ino; /* Page keys come off of */ - register u_int16_t *np; /* New page */ - register u_int16_t *op; /* Page keys go on to if they aren't moving */ - - BUFHEAD *last_bfp; /* Last buf header OVFL needing to be freed */ - DBT key, val; - SPLIT_RETURN ret; - u_int16_t n, off, ov_addr, scopyto; - char *cino; /* Character value of ino */ - - bufp = old_bufp; - ino = (u_int16_t *)old_bufp->page; - np = (u_int16_t *)new_bufp->page; - op = (u_int16_t *)old_bufp->page; - last_bfp = NULL; - scopyto = (u_int16_t)copyto; /* ANSI */ - - n = ino[0] - 1; - while (n < ino[0]) { - if (ino[2] < REAL_KEY && ino[2] != OVFLPAGE) { - if (__big_split(hashp, old_bufp, - new_bufp, bufp, bufp->addr, obucket, &ret)) - return (-1); - old_bufp = ret.oldp; - if (!old_bufp) - return (-1); - op = (u_int16_t *)old_bufp->page; - new_bufp = ret.newp; - if (!new_bufp) - return (-1); - np = (u_int16_t *)new_bufp->page; - bufp = ret.nextp; - if (!bufp) - return (0); - cino = (char *)bufp->page; - ino = (u_int16_t *)cino; - last_bfp = ret.nextp; - } else if (ino[n + 1] == OVFLPAGE) { - ov_addr = ino[n]; - /* - * Fix up the old page -- the extra 2 are the fields - * which contained the overflow information. - */ - ino[0] -= (moved + 2); - FREESPACE(ino) = - scopyto - sizeof(u_int16_t) * (ino[0] + 3); - OFFSET(ino) = scopyto; - - bufp = __get_buf(hashp, ov_addr, bufp, 0); - if (!bufp) - return (-1); - - ino = (u_int16_t *)bufp->page; - n = 1; - scopyto = hashp->BSIZE; - moved = 0; - - if (last_bfp) - __free_ovflpage(hashp, last_bfp); - last_bfp = bufp; - } - /* Move regular sized pairs of there are any */ - off = hashp->BSIZE; - for (n = 1; (n < ino[0]) && (ino[n + 1] >= REAL_KEY); n += 2) { - cino = (char *)ino; - key.data = (u_char *)cino + ino[n]; - key.size = off - ino[n]; - val.data = (u_char *)cino + ino[n + 1]; - val.size = ino[n] - ino[n + 1]; - off = ino[n + 1]; - - if (__call_hash(hashp, key.data, key.size) == obucket) { - /* Keep on old page */ - if (PAIRFITS(op, (&key), (&val))) - putpair((char *)op, &key, &val); - else { - old_bufp = - __add_ovflpage(hashp, old_bufp); - if (!old_bufp) - return (-1); - op = (u_int16_t *)old_bufp->page; - putpair((char *)op, &key, &val); - } - old_bufp->flags |= BUF_MOD; - } else { - /* Move to new page */ - if (PAIRFITS(np, (&key), (&val))) - putpair((char *)np, &key, &val); - else { - new_bufp = - __add_ovflpage(hashp, new_bufp); - if (!new_bufp) - return (-1); - np = (u_int16_t *)new_bufp->page; - putpair((char *)np, &key, &val); - } - new_bufp->flags |= BUF_MOD; - } - } - } - if (last_bfp) - __free_ovflpage(hashp, last_bfp); - return (0); -} - -/* - * Add the given pair to the page - * - * Returns: - * 0 ==> OK - * 1 ==> failure - */ -extern int -__addel(hashp, bufp, key, val) - HTAB *hashp; - BUFHEAD *bufp; - const DBT *key, *val; -{ - register u_int16_t *bp, *sop; - int do_expand; - - bp = (u_int16_t *)bufp->page; - do_expand = 0; - while (bp[0] && (bp[2] < REAL_KEY || bp[bp[0]] < REAL_KEY)) - /* Exception case */ - if (bp[2] == FULL_KEY_DATA && bp[0] == 2) - /* This is the last page of a big key/data pair - and we need to add another page */ - break; - else if (bp[2] < REAL_KEY && bp[bp[0]] != OVFLPAGE) { - bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0); - if (!bufp) - return (-1); - bp = (u_int16_t *)bufp->page; - } else - /* Try to squeeze key on this page */ - if (FREESPACE(bp) > PAIRSIZE(key, val)) { - squeeze_key(bp, key, val); - return (0); - } else { - bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0); - if (!bufp) - return (-1); - bp = (u_int16_t *)bufp->page; - } - - if (PAIRFITS(bp, key, val)) - putpair(bufp->page, key, val); - else { - do_expand = 1; - bufp = __add_ovflpage(hashp, bufp); - if (!bufp) - return (-1); - sop = (u_int16_t *)bufp->page; - - if (PAIRFITS(sop, key, val)) - putpair((char *)sop, key, val); - else - if (__big_insert(hashp, bufp, key, val)) - return (-1); - } - bufp->flags |= BUF_MOD; - /* - * If the average number of keys per bucket exceeds the fill factor, - * expand the table. - */ - hashp->NKEYS++; - if (do_expand || - (hashp->NKEYS / (hashp->MAX_BUCKET + 1) > hashp->FFACTOR)) - return (__expand_table(hashp)); - return (0); -} - -/* - * - * Returns: - * pointer on success - * NULL on error - */ -extern BUFHEAD * -__add_ovflpage(hashp, bufp) - HTAB *hashp; - BUFHEAD *bufp; -{ - register u_int16_t *sp; - u_int16_t ndx, ovfl_num; -#ifdef DEBUG1 - int tmp1, tmp2; -#endif - sp = (u_int16_t *)bufp->page; - - /* Check if we are dynamically determining the fill factor */ - if (hashp->FFACTOR == DEF_FFACTOR) { - hashp->FFACTOR = sp[0] >> 1; - if (hashp->FFACTOR < MIN_FFACTOR) - hashp->FFACTOR = MIN_FFACTOR; - } - bufp->flags |= BUF_MOD; - ovfl_num = overflow_page(hashp); -#ifdef DEBUG1 - tmp1 = bufp->addr; - tmp2 = bufp->ovfl ? bufp->ovfl->addr : 0; -#endif - if (!ovfl_num || !(bufp->ovfl = __get_buf(hashp, ovfl_num, bufp, 1))) - return (NULL); - bufp->ovfl->flags |= BUF_MOD; -#ifdef DEBUG1 - (void)fprintf(stderr, "ADDOVFLPAGE: %d->ovfl was %d is now %d\n", - tmp1, tmp2, bufp->ovfl->addr); -#endif - ndx = sp[0]; - /* - * Since a pair is allocated on a page only if there's room to add - * an overflow page, we know that the OVFL information will fit on - * the page. - */ - sp[ndx + 4] = OFFSET(sp); - sp[ndx + 3] = FREESPACE(sp) - OVFLSIZE; - sp[ndx + 1] = ovfl_num; - sp[ndx + 2] = OVFLPAGE; - sp[0] = ndx + 2; -#ifdef HASH_STATISTICS - hash_overflows++; -#endif - return (bufp->ovfl); -} - -/* - * Returns: - * 0 indicates SUCCESS - * -1 indicates FAILURE - */ -extern int -__get_page(hashp, p, bucket, is_bucket, is_disk, is_bitmap) - HTAB *hashp; - char *p; - u_int32_t bucket; - int is_bucket, is_disk, is_bitmap; -{ - register int fd, page, size; - int rsize; - u_int16_t *bp; - - fd = hashp->fp; - size = hashp->BSIZE; - - if ((fd == -1) || !is_disk) { - PAGE_INIT(p); - return (0); - } - if (is_bucket) - page = BUCKET_TO_PAGE(bucket); - else - page = OADDR_TO_PAGE(bucket); - if ((lseek(fd, (off_t)page << hashp->BSHIFT, SEEK_SET) == -1) || - ((rsize = read(fd, p, size)) == -1)) - return (-1); - bp = (u_int16_t *)p; - if (!rsize) - bp[0] = 0; /* We hit the EOF, so initialize a new page */ - else - if (rsize != size) { - errno = EFTYPE; - return (-1); - } - if (!is_bitmap && !bp[0]) { - PAGE_INIT(p); - } else - if (hashp->LORDER != BYTE_ORDER) { - register int i, max; - - if (is_bitmap) { - max = hashp->BSIZE >> 2; /* divide by 4 */ - for (i = 0; i < max; i++) - M_32_SWAP(((int *)p)[i]); - } else { - M_16_SWAP(bp[0]); - max = bp[0] + 2; - for (i = 1; i <= max; i++) - M_16_SWAP(bp[i]); - } - } - return (0); -} - -/* - * Write page p to disk - * - * Returns: - * 0 ==> OK - * -1 ==>failure - */ -extern int -__put_page(hashp, p, bucket, is_bucket, is_bitmap) - HTAB *hashp; - char *p; - u_int32_t bucket; - int is_bucket, is_bitmap; -{ - register int fd, page, size; - int wsize; - - size = hashp->BSIZE; - if ((hashp->fp == -1) && open_temp(hashp)) - return (-1); - fd = hashp->fp; - - if (hashp->LORDER != BYTE_ORDER) { - register int i; - register int max; - - if (is_bitmap) { - max = hashp->BSIZE >> 2; /* divide by 4 */ - for (i = 0; i < max; i++) - M_32_SWAP(((int *)p)[i]); - } else { - max = ((u_int16_t *)p)[0] + 2; - for (i = 0; i <= max; i++) - M_16_SWAP(((u_int16_t *)p)[i]); - } - } - if (is_bucket) - page = BUCKET_TO_PAGE(bucket); - else - page = OADDR_TO_PAGE(bucket); - if ((lseek(fd, (off_t)page << hashp->BSHIFT, SEEK_SET) == -1) || - ((wsize = write(fd, p, size)) == -1)) - /* Errno is set */ - return (-1); - if (wsize != size) { - errno = EFTYPE; - return (-1); - } - return (0); -} - -#define BYTE_MASK ((1 << INT_BYTE_SHIFT) -1) -/* - * Initialize a new bitmap page. Bitmap pages are left in memory - * once they are read in. - */ -extern int -__ibitmap(hashp, pnum, nbits, ndx) - HTAB *hashp; - int pnum, nbits, ndx; -{ - u_int32_t *ip; - int clearbytes, clearints; - - if ((ip = (u_int32_t *)malloc(hashp->BSIZE)) == NULL) - return (1); - hashp->nmaps++; - clearints = ((nbits - 1) >> INT_BYTE_SHIFT) + 1; - clearbytes = clearints << INT_TO_BYTE; - (void)memset((char *)ip, 0, clearbytes); - (void)memset(((char *)ip) + clearbytes, 0xFF, - hashp->BSIZE - clearbytes); - ip[clearints - 1] = ALL_SET << (nbits & BYTE_MASK); - SETBIT(ip, 0); - hashp->BITMAPS[ndx] = (u_int16_t)pnum; - hashp->mapp[ndx] = ip; - return (0); -} - -static u_int32_t -first_free(map) - u_int32_t map; -{ - register u_int32_t i, mask; - - mask = 0x1; - for (i = 0; i < BITS_PER_MAP; i++) { - if (!(mask & map)) - return (i); - mask = mask << 1; - } - return (i); -} - -static u_int16_t -overflow_page(hashp) - HTAB *hashp; -{ - register u_int32_t *freep = 0; - register int max_free, offset, splitnum; - u_int16_t addr; - int bit, first_page, free_bit, free_page, i, in_use_bits, j; -#ifdef DEBUG2 - int tmp1, tmp2; -#endif - splitnum = hashp->OVFL_POINT; - max_free = hashp->SPARES[splitnum]; - - free_page = (max_free - 1) >> (hashp->BSHIFT + BYTE_SHIFT); - free_bit = (max_free - 1) & ((hashp->BSIZE << BYTE_SHIFT) - 1); - - /* Look through all the free maps to find the first free block */ - first_page = hashp->LAST_FREED >>(hashp->BSHIFT + BYTE_SHIFT); - for ( i = first_page; i <= free_page; i++ ) { - if (!(freep = (u_int32_t *)hashp->mapp[i]) && - !(freep = fetch_bitmap(hashp, i))) - return (0); - if (i == free_page) - in_use_bits = free_bit; - else - in_use_bits = (hashp->BSIZE << BYTE_SHIFT) - 1; - - if (i == first_page) { - bit = hashp->LAST_FREED & - ((hashp->BSIZE << BYTE_SHIFT) - 1); - j = bit / BITS_PER_MAP; - bit = bit & ~(BITS_PER_MAP - 1); - } else { - bit = 0; - j = 0; - } - for (; bit <= in_use_bits; j++, bit += BITS_PER_MAP) - if (freep[j] != ALL_SET) - goto found; - } - - /* No Free Page Found */ - hashp->LAST_FREED = hashp->SPARES[splitnum]; - hashp->SPARES[splitnum]++; - offset = hashp->SPARES[splitnum] - - (splitnum ? hashp->SPARES[splitnum - 1] : 0); - -#define OVMSG "HASH: Out of overflow pages. Increase page size\n" - if (offset > SPLITMASK) { - if (++splitnum >= NCACHED) { - if (write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1) < 0) { - } - return (0); - } - hashp->OVFL_POINT = splitnum; - hashp->SPARES[splitnum] = hashp->SPARES[splitnum-1]; - hashp->SPARES[splitnum-1]--; - offset = 1; - } - - /* Check if we need to allocate a new bitmap page */ - if (free_bit == (hashp->BSIZE << BYTE_SHIFT) - 1) { - free_page++; - if (free_page >= NCACHED) { - if (write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1) < 0) { - } - return (0); - } - /* - * This is tricky. The 1 indicates that you want the new page - * allocated with 1 clear bit. Actually, you are going to - * allocate 2 pages from this map. The first is going to be - * the map page, the second is the overflow page we were - * looking for. The init_bitmap routine automatically, sets - * the first bit of itself to indicate that the bitmap itself - * is in use. We would explicitly set the second bit, but - * don't have to if we tell init_bitmap not to leave it clear - * in the first place. - */ - if (__ibitmap(hashp, - (int)OADDR_OF(splitnum, offset), 1, free_page)) - return (0); - hashp->SPARES[splitnum]++; -#ifdef DEBUG2 - free_bit = 2; -#endif - offset++; - if (offset > SPLITMASK) { - if (++splitnum >= NCACHED) { - if (write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1) < 0) { - } - return (0); - } - hashp->OVFL_POINT = splitnum; - hashp->SPARES[splitnum] = hashp->SPARES[splitnum-1]; - hashp->SPARES[splitnum-1]--; - offset = 0; - } - } else { - /* - * Free_bit addresses the last used bit. Bump it to address - * the first available bit. - */ - free_bit++; - SETBIT(freep, free_bit); - } - - /* Calculate address of the new overflow page */ - addr = OADDR_OF(splitnum, offset); -#ifdef DEBUG2 - (void)fprintf(stderr, "OVERFLOW_PAGE: ADDR: %d BIT: %d PAGE %d\n", - addr, free_bit, free_page); -#endif - return (addr); - -found: - bit = bit + first_free(freep[j]); - SETBIT(freep, bit); -#ifdef DEBUG2 - tmp1 = bit; - tmp2 = i; -#endif - /* - * Bits are addressed starting with 0, but overflow pages are addressed - * beginning at 1. Bit is a bit addressnumber, so we need to increment - * it to convert it to a page number. - */ - bit = 1 + bit + (i * (hashp->BSIZE << BYTE_SHIFT)); - if (bit >= hashp->LAST_FREED) - hashp->LAST_FREED = bit - 1; - - /* Calculate the split number for this page */ - for (i = 0; (i < splitnum) && (bit > hashp->SPARES[i]); i++); - offset = (i ? bit - hashp->SPARES[i - 1] : bit); - if (offset >= SPLITMASK) - return (0); /* Out of overflow pages */ - addr = OADDR_OF(i, offset); -#ifdef DEBUG2 - (void)fprintf(stderr, "OVERFLOW_PAGE: ADDR: %d BIT: %d PAGE %d\n", - addr, tmp1, tmp2); -#endif - - /* Allocate and return the overflow page */ - return (addr); -} - -/* - * Mark this overflow page as free. - */ -extern void -__free_ovflpage(hashp, obufp) - HTAB *hashp; - BUFHEAD *obufp; -{ - register u_int16_t addr; - u_int32_t *freep; - int bit_address, free_page, free_bit; - u_int16_t ndx; - - addr = obufp->addr; -#ifdef DEBUG1 - (void)fprintf(stderr, "Freeing %d\n", addr); -#endif - ndx = (((u_int16_t)addr) >> SPLITSHIFT); - bit_address = - (ndx ? hashp->SPARES[ndx - 1] : 0) + (addr & SPLITMASK) - 1; - if (bit_address < hashp->LAST_FREED) - hashp->LAST_FREED = bit_address; - free_page = (bit_address >> (hashp->BSHIFT + BYTE_SHIFT)); - free_bit = bit_address & ((hashp->BSIZE << BYTE_SHIFT) - 1); - - if (!(freep = hashp->mapp[free_page])) - freep = fetch_bitmap(hashp, free_page); -#ifdef DEBUG - /* - * This had better never happen. It means we tried to read a bitmap - * that has already had overflow pages allocated off it, and we - * failed to read it from the file. - */ - if (!freep) - assert(0); -#endif - CLRBIT(freep, free_bit); -#ifdef DEBUG2 - (void)fprintf(stderr, "FREE_OVFLPAGE: ADDR: %d BIT: %d PAGE %d\n", - obufp->addr, free_bit, free_page); -#endif - __reclaim_buf(hashp, obufp); -} - -/* - * Returns: - * 0 success - * -1 failure - */ -static int -open_temp(hashp) - HTAB *hashp; -{ - sigset_t set, oset; - static char namestr[] = "_hashXXXXXX"; - - /* Block signals; make sure file goes away at process exit. */ - (void)sigfillset(&set); - (void)sigprocmask(SIG_BLOCK, &set, &oset); - if ((hashp->fp = mkstemp(namestr)) != -1) { - (void)unlink(namestr); - (void)fcntl(hashp->fp, F_SETFD, 1); - } - (void)sigprocmask(SIG_SETMASK, &oset, (sigset_t *)NULL); - return (hashp->fp != -1 ? 0 : -1); -} - -/* - * We have to know that the key will fit, but the last entry on the page is - * an overflow pair, so we need to shift things. - */ -static void -squeeze_key(sp, key, val) - u_int16_t *sp; - const DBT *key, *val; -{ - register char *p; - u_int16_t free_space, n, off, pageno; - - p = (char *)sp; - n = sp[0]; - free_space = FREESPACE(sp); - off = OFFSET(sp); - - pageno = sp[n - 1]; - off -= key->size; - sp[n - 1] = off; - memmove(p + off, key->data, key->size); - off -= val->size; - sp[n] = off; - memmove(p + off, val->data, val->size); - sp[0] = n + 2; - sp[n + 1] = pageno; - sp[n + 2] = OVFLPAGE; - FREESPACE(sp) = free_space - PAIRSIZE(key, val); - OFFSET(sp) = off; -} - -static u_int32_t * -fetch_bitmap(hashp, ndx) - HTAB *hashp; - int ndx; -{ - if (ndx >= hashp->nmaps) - return (NULL); - if ((hashp->mapp[ndx] = (u_int32_t *)malloc(hashp->BSIZE)) == NULL) - return (NULL); - if (__get_page(hashp, - (char *)hashp->mapp[ndx], hashp->BITMAPS[ndx], 0, 1, 1)) { - free(hashp->mapp[ndx]); - return (NULL); - } - return (hashp->mapp[ndx]); -} - -#ifdef DEBUG4 -int -print_chain(addr) - int addr; -{ - BUFHEAD *bufp; - short *bp, oaddr; - - (void)fprintf(stderr, "%d ", addr); - bufp = __get_buf(hashp, addr, NULL, 0); - bp = (short *)bufp->page; - while (bp[0] && ((bp[bp[0]] == OVFLPAGE) || - ((bp[0] > 2) && bp[2] < REAL_KEY))) { - oaddr = bp[bp[0] - 1]; - (void)fprintf(stderr, "%d ", (int)oaddr); - bufp = __get_buf(hashp, (int)oaddr, bufp, 0); - bp = (short *)bufp->page; - } - (void)fprintf(stderr, "\n"); -} -#endif diff --git a/main/db1-ast/hash/hsearch.c b/main/db1-ast/hash/hsearch.c deleted file mode 100644 index 2971f9308..000000000 --- a/main/db1-ast/hash/hsearch.c +++ /dev/null @@ -1,107 +0,0 @@ -/*- - * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Margo Seltzer. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)hsearch.c 8.4 (Berkeley) 7/21/94"; -#endif /* LIBC_SCCS and not lint */ - -#include - -#include -#include - -#include "../include/db.h" -#include "search.h" - -static DB *dbp = NULL; -static ENTRY retval; - -extern int -hcreate(nel) - u_int nel; -{ - HASHINFO info; - - info.nelem = nel; - info.bsize = 256; - info.ffactor = 8; - info.cachesize = 0; - info.hash = NULL; - info.lorder = 0; - dbp = (DB *)__hash_open(NULL, O_CREAT | O_RDWR, 0600, &info, 0); - return ((int)dbp); -} - -extern ENTRY * -hsearch(item, action) - ENTRY item; - ACTION action; -{ - DBT key, val; - int status; - - if (!dbp) - return (NULL); - key.data = (u_char *)item.key; - key.size = strlen(item.key) + 1; - - if (action == ENTER) { - val.data = (u_char *)item.data; - val.size = strlen(item.data) + 1; - status = (dbp->put)(dbp, &key, &val, R_NOOVERWRITE); - if (status) - return (NULL); - } else { - /* FIND */ - status = (dbp->get)(dbp, &key, &val, 0); - if (status) - return (NULL); - else - item.data = (char *)val.data; - } - retval.key = item.key; - retval.data = item.data; - return (&retval); -} - -extern void -hdestroy() -{ - if (dbp) { - (void)(dbp->close)(dbp); - dbp = NULL; - } -} diff --git a/main/db1-ast/hash/ndbm.c b/main/db1-ast/hash/ndbm.c deleted file mode 100644 index d702f737a..000000000 --- a/main/db1-ast/hash/ndbm.c +++ /dev/null @@ -1,235 +0,0 @@ -/*- - * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Margo Seltzer. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)ndbm.c 8.4 (Berkeley) 7/21/94"; -#endif /* LIBC_SCCS and not lint */ - -/* - * This package provides a dbm compatible interface to the new hashing - * package described in db(3). - */ - -#include - -#include -#include -#include - -#include -#include "hash.h" - -/* - * Returns: - * *DBM on success - * NULL on failure - */ -extern DBM * -dbm_open(file, flags, mode) - const char *file; - int flags, mode; -{ - DBM *db; - HASHINFO info; - const size_t len = strlen(file) + sizeof (DBM_SUFFIX); -#ifdef __GNUC__ - char path[len]; -#else - char *path = malloc(len); - if (path == NULL) - return NULL; -#endif - - info.bsize = 4096; - info.ffactor = 40; - info.nelem = 1; - info.cachesize = 0; - info.hash = NULL; - info.lorder = 0; - (void)strncpy(path, file, len - 1); - (void)strncat(path, DBM_SUFFIX, len - strlen(path) - 1); - db = (DBM *)__hash_open(path, flags, mode, &info, 0); -#ifndef __GNUC__ - free(path); -#endif - return db; -} - -extern void -dbm_close(db) - DBM *db; -{ - (void)(db->close)(db); -} - -/* - * Returns: - * DATUM on success - * NULL on failure - */ -extern datum -dbm_fetch(db, key) - DBM *db; - datum key; -{ - datum retdata; - int status; - DBT dbtkey, dbtretdata; - - dbtkey.data = key.dptr; - dbtkey.size = key.dsize; - status = (db->get)(db, &dbtkey, &dbtretdata, 0); - if (status) { - dbtretdata.data = NULL; - dbtretdata.size = 0; - } - retdata.dptr = dbtretdata.data; - retdata.dsize = dbtretdata.size; - return (retdata); -} - -/* - * Returns: - * DATUM on success - * NULL on failure - */ -extern datum -dbm_firstkey(db) - DBM *db; -{ - int status; - datum retkey; - DBT dbtretkey, dbtretdata; - - status = (db->seq)(db, &dbtretkey, &dbtretdata, R_FIRST); - if (status) - dbtretkey.data = NULL; - retkey.dptr = dbtretkey.data; - retkey.dsize = dbtretkey.size; - return (retkey); -} - -/* - * Returns: - * DATUM on success - * NULL on failure - */ -extern datum -dbm_nextkey(db) - DBM *db; -{ - int status; - datum retkey; - DBT dbtretkey, dbtretdata; - - status = (db->seq)(db, &dbtretkey, &dbtretdata, R_NEXT); - if (status) - dbtretkey.data = NULL; - retkey.dptr = dbtretkey.data; - retkey.dsize = dbtretkey.size; - return (retkey); -} -/* - * Returns: - * 0 on success - * <0 failure - */ -extern int -dbm_delete(db, key) - DBM *db; - datum key; -{ - int status; - DBT dbtkey; - - dbtkey.data = key.dptr; - dbtkey.size = key.dsize; - status = (db->del)(db, &dbtkey, 0); - if (status) - return (-1); - else - return (0); -} - -/* - * Returns: - * 0 on success - * <0 failure - * 1 if DBM_INSERT and entry exists - */ -extern int -dbm_store(db, key, data, flags) - DBM *db; - datum key, data; - int flags; -{ - DBT dbtkey, dbtdata; - - dbtkey.data = key.dptr; - dbtkey.size = key.dsize; - dbtdata.data = data.dptr; - dbtdata.size = data.dsize; - return ((db->put)(db, &dbtkey, &dbtdata, - (flags == DBM_INSERT) ? R_NOOVERWRITE : 0)); -} - -extern int -dbm_error(db) - DBM *db; -{ - HTAB *hp; - - hp = (HTAB *)db->internal; - return (hp->errnum); -} - -extern int -dbm_clearerr(db) - DBM *db; -{ - HTAB *hp; - - hp = (HTAB *)db->internal; - hp->errnum = 0; - return (0); -} - -extern int -dbm_dirfno(db) - DBM *db; -{ - return(((HTAB *)db->internal)->fp); -} diff --git a/main/db1-ast/hash/page.h b/main/db1-ast/hash/page.h deleted file mode 100644 index 0fc0d5a3e..000000000 --- a/main/db1-ast/hash/page.h +++ /dev/null @@ -1,92 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Margo Seltzer. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)page.h 8.2 (Berkeley) 5/31/94 - */ - -/* - * Definitions for hashing page file format. - */ - -/* - * routines dealing with a data page - * - * page format: - * +------------------------------+ - * p | n | keyoff | datoff | keyoff | - * +------------+--------+--------+ - * | datoff | free | ptr | --> | - * +--------+---------------------+ - * | F R E E A R E A | - * +--------------+---------------+ - * | <---- - - - | data | - * +--------+-----+----+----------+ - * | key | data | key | - * +--------+----------+----------+ - * - * Pointer to the free space is always: p[p[0] + 2] - * Amount of free space on the page is: p[p[0] + 1] - */ - -/* - * How many bytes required for this pair? - * 2 shorts in the table at the top of the page + room for the - * key and room for the data - * - * We prohibit entering a pair on a page unless there is also room to append - * an overflow page. The reason for this it that you can get in a situation - * where a single key/data pair fits on a page, but you can't append an - * overflow page and later you'd have to split the key/data and handle like - * a big pair. - * You might as well do this up front. - */ - -#define PAIRSIZE(K,D) (2*sizeof(u_int16_t) + (K)->size + (D)->size) -#define BIGOVERHEAD (4*sizeof(u_int16_t)) -#define KEYSIZE(K) (4*sizeof(u_int16_t) + (K)->size); -#define OVFLSIZE (2*sizeof(u_int16_t)) -#define FREESPACE(P) ((P)[(P)[0]+1]) -#define OFFSET(P) ((P)[(P)[0]+2]) -#define PAIRFITS(P,K,D) \ - (((P)[2] >= REAL_KEY) && \ - (PAIRSIZE((K),(D)) + OVFLSIZE) <= FREESPACE((P))) -#define PAGE_META(N) (((N)+3) * sizeof(u_int16_t)) - -typedef struct { - BUFHEAD *newp; - BUFHEAD *oldp; - BUFHEAD *nextp; - u_int16_t next_addr; -} SPLIT_RETURN; diff --git a/main/db1-ast/hash/search.h b/main/db1-ast/hash/search.h deleted file mode 100644 index 4d3b9143e..000000000 --- a/main/db1-ast/hash/search.h +++ /dev/null @@ -1,51 +0,0 @@ -/*- - * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Margo Seltzer. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)search.h 8.1 (Berkeley) 6/4/93 - */ - -/* Backward compatibility to hsearch interface. */ -typedef struct entry { - char *key; - char *data; -} ENTRY; - -typedef enum { - FIND, ENTER -} ACTION; - -int hcreate __P((unsigned int)); -void hdestroy __P((void)); -ENTRY *hsearch __P((ENTRY, ACTION)); diff --git a/main/db1-ast/include/circ-queue.h b/main/db1-ast/include/circ-queue.h deleted file mode 100644 index 33ba9115b..000000000 --- a/main/db1-ast/include/circ-queue.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)queue.h 8.5 (Berkeley) 8/20/94 - * $FreeBSD: ports/misc/44bsd-more/files/queue.h,v 1.1 2001/01/06 03:41:36 hoek Exp $ - */ - -/* - * Circular queue definitions. - */ -#define CIRCLEQ_HEAD(name, type) \ -struct name { \ - struct type *cqh_first; /* first element */ \ - struct type *cqh_last; /* last element */ \ -} - -#define CIRCLEQ_ENTRY(type) \ -struct { \ - struct type *cqe_next; /* next element */ \ - struct type *cqe_prev; /* previous element */ \ -} - -/* - * Circular queue functions. - */ -#define CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head)) - -#define CIRCLEQ_FIRST(head) ((head)->cqh_first) - -#define CIRCLEQ_FOREACH(var, head, field) \ - for((var) = (head)->cqh_first; \ - (var) != (void *)(head); \ - (var) = (var)->field.cqe_next) - -#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \ - for((var) = (head)->cqh_last; \ - (var) != (void *)(head); \ - (var) = (var)->field.cqe_prev) - -#define CIRCLEQ_INIT(head) do { \ - (head)->cqh_first = (void *)(head); \ - (head)->cqh_last = (void *)(head); \ -} while (0) - -#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ - (elm)->field.cqe_next = (listelm)->field.cqe_next; \ - (elm)->field.cqe_prev = (listelm); \ - if ((listelm)->field.cqe_next == (void *)(head)) \ - (head)->cqh_last = (elm); \ - else \ - (listelm)->field.cqe_next->field.cqe_prev = (elm); \ - (listelm)->field.cqe_next = (elm); \ -} while (0) - -#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ - (elm)->field.cqe_next = (listelm); \ - (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \ - if ((listelm)->field.cqe_prev == (void *)(head)) \ - (head)->cqh_first = (elm); \ - else \ - (listelm)->field.cqe_prev->field.cqe_next = (elm); \ - (listelm)->field.cqe_prev = (elm); \ -} while (0) - -#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \ - (elm)->field.cqe_next = (head)->cqh_first; \ - (elm)->field.cqe_prev = (void *)(head); \ - if ((head)->cqh_last == (void *)(head)) \ - (head)->cqh_last = (elm); \ - else \ - (head)->cqh_first->field.cqe_prev = (elm); \ - (head)->cqh_first = (elm); \ -} while (0) - -#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \ - (elm)->field.cqe_next = (void *)(head); \ - (elm)->field.cqe_prev = (head)->cqh_last; \ - if ((head)->cqh_first == (void *)(head)) \ - (head)->cqh_first = (elm); \ - else \ - (head)->cqh_last->field.cqe_next = (elm); \ - (head)->cqh_last = (elm); \ -} while (0) - -#define CIRCLEQ_LAST(head) ((head)->cqh_last) - -#define CIRCLEQ_NEXT(elm,field) ((elm)->field.cqe_next) - -#define CIRCLEQ_PREV(elm,field) ((elm)->field.cqe_prev) - -#define CIRCLEQ_REMOVE(head, elm, field) do { \ - if ((elm)->field.cqe_next == (void *)(head)) \ - (head)->cqh_last = (elm)->field.cqe_prev; \ - else \ - (elm)->field.cqe_next->field.cqe_prev = \ - (elm)->field.cqe_prev; \ - if ((elm)->field.cqe_prev == (void *)(head)) \ - (head)->cqh_first = (elm)->field.cqe_next; \ - else \ - (elm)->field.cqe_prev->field.cqe_next = \ - (elm)->field.cqe_next; \ -} while (0) diff --git a/main/db1-ast/include/compat.h b/main/db1-ast/include/compat.h deleted file mode 100644 index 706e58265..000000000 --- a/main/db1-ast/include/compat.h +++ /dev/null @@ -1,49 +0,0 @@ -/* Values for building 4.4 BSD db routines in the GNU C library. */ - -#ifndef _compat_h_ -#define _compat_h_ - -#include - -/* - * If you can't provide lock values in the open(2) call. Note, this - * allows races to happen. - */ -#ifndef O_EXLOCK /* 4.4BSD extension. */ -#define O_EXLOCK 0 -#endif - -#ifndef O_SHLOCK /* 4.4BSD extension. */ -#define O_SHLOCK 0 -#endif - -#include - -#ifndef EFTYPE -#define EFTYPE EINVAL /* POSIX 1003.1 format errno. */ -#endif - -#include -#include - -#ifndef _POSIX_VDISABLE /* POSIX 1003.1 disabling char. */ -#define _POSIX_VDISABLE 0 /* Some systems used 0. */ -#endif - -#include - -#ifndef TCSASOFT /* 4.4BSD extension. */ -#define TCSASOFT 0 -#endif - -#include - -#ifndef MAX /* Usually found in . */ -#define MAX(_a,_b) ((_a)<(_b)?(_b):(_a)) -#endif -#ifndef MIN /* Usually found in . */ -#define MIN(_a,_b) ((_a)<(_b)?(_a):(_b)) -#endif - - -#endif /* compat.h */ diff --git a/main/db1-ast/include/db.h b/main/db1-ast/include/db.h deleted file mode 100644 index a58724bdd..000000000 --- a/main/db1-ast/include/db.h +++ /dev/null @@ -1,250 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)db.h 8.7 (Berkeley) 6/16/94 - */ - -#ifndef _DB_H -#define _DB_H 1 - -#include -#include - -#include - -#ifdef __DBINTERFACE_PRIVATE -#include -#endif - -#ifdef SOLARIS -#include "solaris-compat/compat.h" -#endif - -#define RET_ERROR -1 /* Return values. */ -#define RET_SUCCESS 0 -#define RET_SPECIAL 1 - -#ifndef __BIT_TYPES_DEFINED__ -#define __BIT_TYPES_DEFINED__ -#if (!defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__APPLE__)) -typedef __signed char int8_t; -typedef short int16_t; -typedef int int32_t; -typedef unsigned char u_int8_t; -typedef unsigned short u_int16_t; -typedef unsigned int u_int32_t; -#ifdef WE_DONT_NEED_QUADS -typedef long long int64_t; -typedef unsigned long long u_int64_t; -#endif -#endif /* __FreeBSD__ */ -#endif - -#ifdef SOLARIS -#define __P(p) p -#define __BEGIN_DECLS -#define __END_DECLS -#endif - -#define MAX_PAGE_NUMBER 0xffffffff /* >= # of pages in a file */ -typedef u_int32_t pgno_t; -#define MAX_PAGE_OFFSET 65535 /* >= # of bytes in a page */ -typedef u_int16_t indx_t; -#define MAX_REC_NUMBER 0xffffffff /* >= # of records in a tree */ -typedef u_int32_t recno_t; - -/* Key/data structure -- a Data-Base Thang. */ -typedef struct { - void *data; /* data */ - size_t size; /* data length */ -} DBT; - -/* Routine flags. */ -#define R_CURSOR 1 /* del, put, seq */ -#define __R_UNUSED 2 /* UNUSED */ -#define R_FIRST 3 /* seq */ -#define R_IAFTER 4 /* put (RECNO) */ -#define R_IBEFORE 5 /* put (RECNO) */ -#define R_LAST 6 /* seq (BTREE, RECNO) */ -#define R_NEXT 7 /* seq */ -#define R_NOOVERWRITE 8 /* put */ -#define R_PREV 9 /* seq (BTREE, RECNO) */ -#define R_SETCURSOR 10 /* put (RECNO) */ -#define R_RECNOSYNC 11 /* sync (RECNO) */ - -typedef enum { DB_BTREE, DB_HASH, DB_RECNO } DBTYPE; - -/* - * !!! - * The following flags are included in the dbopen(3) call as part of the - * open(2) flags. In order to avoid conflicts with the open flags, start - * at the top of the 16 or 32-bit number space and work our way down. If - * the open flags were significantly expanded in the future, it could be - * a problem. Wish I'd left another flags word in the dbopen call. - * - * !!! - * None of this stuff is implemented yet. The only reason that it's here - * is so that the access methods can skip copying the key/data pair when - * the DB_LOCK flag isn't set. - */ -#if UINT_MAX > 65535 -#define DB_LOCK 0x20000000 /* Do locking. */ -#define DB_SHMEM 0x40000000 /* Use shared memory. */ -#define DB_TXN 0x80000000 /* Do transactions. */ -#else -#define DB_LOCK 0x2000 /* Do locking. */ -#define DB_SHMEM 0x4000 /* Use shared memory. */ -#define DB_TXN 0x8000 /* Do transactions. */ -#endif - -/* Access method description structure. */ -typedef struct __db { - DBTYPE type; /* Underlying db type. */ - int (*close) __P((struct __db *)); - int (*del) __P((const struct __db *, const DBT *, u_int)); - int (*get) __P((const struct __db *, const DBT *, DBT *, u_int)); - int (*put) __P((const struct __db *, DBT *, const DBT *, u_int)); - int (*seq) __P((const struct __db *, DBT *, DBT *, u_int)); - int (*sync) __P((const struct __db *, u_int)); - void *internal; /* Access method private. */ - int (*fd) __P((const struct __db *)); -} DB; - -#define BTREEMAGIC 0x053162 -#define BTREEVERSION 3 - -/* Structure used to pass parameters to the btree routines. */ -typedef struct { -#define R_DUP 0x01 /* duplicate keys */ - u_long flags; - u_int cachesize; /* bytes to cache */ - int maxkeypage; /* maximum keys per page */ - int minkeypage; /* minimum keys per page */ - u_int psize; /* page size */ - int (*compare) /* comparison function */ - __P((const DBT *, const DBT *)); - size_t (*prefix) /* prefix function */ - __P((const DBT *, const DBT *)); - int lorder; /* byte order */ -} BTREEINFO; - -#define HASHMAGIC 0x061561 -#define HASHVERSION 2 - -/* Structure used to pass parameters to the hashing routines. */ -typedef struct { - u_int bsize; /* bucket size */ - u_int ffactor; /* fill factor */ - u_int nelem; /* number of elements */ - u_int cachesize; /* bytes to cache */ - u_int32_t /* hash function */ - (*hash) __P((const void *, size_t)); - int lorder; /* byte order */ -} HASHINFO; - -/* Structure used to pass parameters to the record routines. */ -typedef struct { -#define R_FIXEDLEN 0x01 /* fixed-length records */ -#define R_NOKEY 0x02 /* key not required */ -#define R_SNAPSHOT 0x04 /* snapshot the input */ - u_long flags; - u_int cachesize; /* bytes to cache */ - u_int psize; /* page size */ - int lorder; /* byte order */ - size_t reclen; /* record length (fixed-length records) */ - u_char bval; /* delimiting byte (variable-length records */ - char *bfname; /* btree file name */ -} RECNOINFO; - -#ifdef __DBINTERFACE_PRIVATE -/* - * Little endian <==> big endian 32-bit swap macros. - * M_32_SWAP swap a memory location - * P_32_SWAP swap a referenced memory location - * P_32_COPY swap from one location to another - */ -#define M_32_SWAP(a) { \ - u_int32_t _tmp = a; \ - ((char *)&a)[0] = ((char *)&_tmp)[3]; \ - ((char *)&a)[1] = ((char *)&_tmp)[2]; \ - ((char *)&a)[2] = ((char *)&_tmp)[1]; \ - ((char *)&a)[3] = ((char *)&_tmp)[0]; \ -} -#define P_32_SWAP(a) { \ - u_int32_t _tmp = *(u_int32_t *)a; \ - ((char *)a)[0] = ((char *)&_tmp)[3]; \ - ((char *)a)[1] = ((char *)&_tmp)[2]; \ - ((char *)a)[2] = ((char *)&_tmp)[1]; \ - ((char *)a)[3] = ((char *)&_tmp)[0]; \ -} -#define P_32_COPY(a, b) { \ - ((char *)&(b))[0] = ((char *)&(a))[3]; \ - ((char *)&(b))[1] = ((char *)&(a))[2]; \ - ((char *)&(b))[2] = ((char *)&(a))[1]; \ - ((char *)&(b))[3] = ((char *)&(a))[0]; \ -} - -/* - * Little endian <==> big endian 16-bit swap macros. - * M_16_SWAP swap a memory location - * P_16_SWAP swap a referenced memory location - * P_16_COPY swap from one location to another - */ -#define M_16_SWAP(a) { \ - u_int16_t _tmp = a; \ - ((char *)&a)[0] = ((char *)&_tmp)[1]; \ - ((char *)&a)[1] = ((char *)&_tmp)[0]; \ -} -#define P_16_SWAP(a) { \ - u_int16_t _tmp = *(u_int16_t *)a; \ - ((char *)a)[0] = ((char *)&_tmp)[1]; \ - ((char *)a)[1] = ((char *)&_tmp)[0]; \ -} -#define P_16_COPY(a, b) { \ - ((char *)&(b))[0] = ((char *)&(a))[1]; \ - ((char *)&(b))[1] = ((char *)&(a))[0]; \ -} -#endif - -__BEGIN_DECLS -DB *__dbopen __P((const char *, int, int, DBTYPE, const void *)); -DB *dbopen __P((const char *, int, int, DBTYPE, const void *)); - -#ifdef __DBINTERFACE_PRIVATE -DB *__bt_open __P((const char *, int, int, const BTREEINFO *, int)); -DB *__hash_open __P((const char *, int, int, const HASHINFO *, int)); -DB *__rec_open __P((const char *, int, int, const RECNOINFO *, int)); -void __dbpanic __P((DB *dbp)); -#endif -__END_DECLS - -#endif /* db.h */ diff --git a/main/db1-ast/include/mpool.h b/main/db1-ast/include/mpool.h deleted file mode 100644 index 0cfc5741c..000000000 --- a/main/db1-ast/include/mpool.h +++ /dev/null @@ -1,115 +0,0 @@ -/*- - * Copyright (c) 1991, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)mpool.h 8.2 (Berkeley) 7/14/94 - */ - -#ifndef _MPOOL_H -#define _MPOOL_H 1 - -#include -#ifndef CIRCLEQ_HEAD -#include -#endif - -/* - * The memory pool scheme is a simple one. Each in-memory page is referenced - * by a bucket which is threaded in up to two of three ways. All active pages - * are threaded on a hash chain (hashed by page number) and an lru chain. - * Inactive pages are threaded on a free chain. Each reference to a memory - * pool is handed an opaque MPOOL cookie which stores all of this information. - */ -#define HASHSIZE 128 -#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE) - -/* The BKT structures are the elements of the queues. */ -typedef struct _bkt { - CIRCLEQ_ENTRY(_bkt) hq; /* hash queue */ - CIRCLEQ_ENTRY(_bkt) q; /* lru queue */ - void *page; /* page */ - pgno_t pgno; /* page number */ - -#define MPOOL_DIRTY 0x01 /* page needs to be written */ -#define MPOOL_PINNED 0x02 /* page is pinned into memory */ - u_int8_t flags; /* flags */ -} BKT; - -typedef struct MPOOL { - CIRCLEQ_HEAD(_lqh, _bkt) lqh; /* lru queue head */ - /* hash queue array */ - CIRCLEQ_HEAD(_hqh, _bkt) hqh[HASHSIZE]; - pgno_t curcache; /* current number of cached pages */ - pgno_t maxcache; /* max number of cached pages */ - pgno_t npages; /* number of pages in the file */ - u_long pagesize; /* file page size */ - int fd; /* file descriptor */ - /* page in conversion routine */ - void (*pgin) __P((void *, pgno_t, void *)); - /* page out conversion routine */ - void (*pgout) __P((void *, pgno_t, void *)); - void *pgcookie; /* cookie for page in/out routines */ -#ifdef STATISTICS - u_long cachehit; - u_long cachemiss; - u_long pagealloc; - u_long pageflush; - u_long pageget; - u_long pagenew; - u_long pageput; - u_long pageread; - u_long pagewrite; -#endif -} MPOOL; - -__BEGIN_DECLS -MPOOL *__mpool_open __P((void *, int, pgno_t, pgno_t)); -MPOOL *mpool_open __P((void *, int, pgno_t, pgno_t)); -void __mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), - void (*)(void *, pgno_t, void *), void *)); -void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), - void (*)(void *, pgno_t, void *), void *)); -void *__mpool_new __P((MPOOL *, pgno_t *)); -void *mpool_new __P((MPOOL *, pgno_t *)); -void *__mpool_get __P((MPOOL *, pgno_t, u_int)); -void *mpool_get __P((MPOOL *, pgno_t, u_int)); -int __mpool_put __P((MPOOL *, void *, u_int)); -int mpool_put __P((MPOOL *, void *, u_int)); -int __mpool_sync __P((MPOOL *)); -int mpool_sync __P((MPOOL *)); -int __mpool_close __P((MPOOL *)); -int mpool_close __P((MPOOL *)); -#ifdef STATISTICS -void mpool_stat __P((MPOOL *)); -#endif -__END_DECLS - -#endif /* mpool.h */ diff --git a/main/db1-ast/include/ndbm.h b/main/db1-ast/include/ndbm.h deleted file mode 100644 index d2079b0a5..000000000 --- a/main/db1-ast/include/ndbm.h +++ /dev/null @@ -1,79 +0,0 @@ -/*- - * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Margo Seltzer. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)ndbm.h 8.1 (Berkeley) 6/2/93 - */ - -#ifndef _NDBM_H -#define _NDBM_H 1 - -#include "db.h" - -/* Map dbm interface onto db(3). */ -#define DBM_RDONLY O_RDONLY - -/* Flags to dbm_store(). */ -#define DBM_INSERT 0 -#define DBM_REPLACE 1 - -/* - * The db(3) support for ndbm(3) always appends this suffix to the - * file name to avoid overwriting the user's original database. - */ -#define DBM_SUFFIX ".db" - -typedef struct { - char *dptr; - int dsize; -} datum; - -typedef DB DBM; -#define dbm_pagfno(a) DBM_PAGFNO_NOT_AVAILABLE - -__BEGIN_DECLS -void dbm_close __P((DBM *)); -int dbm_delete __P((DBM *, datum)); -datum dbm_fetch __P((DBM *, datum)); -datum dbm_firstkey __P((DBM *)); -long dbm_forder __P((DBM *, datum)); -datum dbm_nextkey __P((DBM *)); -DBM *dbm_open __P((const char *, int, int)); -int dbm_store __P((DBM *, datum, datum, int)); -int dbm_dirfno __P((DBM *)); -int dbm_error __P((DBM *)); -int dbm_clearerr __P((DBM *)); -__END_DECLS - -#endif /* ndbm.h */ diff --git a/main/db1-ast/libdb.map b/main/db1-ast/libdb.map deleted file mode 100644 index 87e34c430..000000000 --- a/main/db1-ast/libdb.map +++ /dev/null @@ -1,11 +0,0 @@ -GLIBC_2.0 { - global: - # the real DB entry point. - dbopen; __dbopen; - - # The compatibility functions. - dbm_clearerr; dbm_close; dbm_delete; dbm_dirfno; dbm_error; - dbm_fetch; dbm_firstkey; dbm_nextkey; dbm_open; dbm_store; - local: - *; -}; diff --git a/main/db1-ast/mpool/README b/main/db1-ast/mpool/README deleted file mode 100644 index 0f01fbcdb..000000000 --- a/main/db1-ast/mpool/README +++ /dev/null @@ -1,7 +0,0 @@ -# @(#)README 8.1 (Berkeley) 6/4/93 - -These are the current memory pool routines. -They aren't ready for prime time, yet, and -the interface is expected to change. - ---keith diff --git a/main/db1-ast/mpool/mpool.c b/main/db1-ast/mpool/mpool.c deleted file mode 100644 index 719136d7b..000000000 --- a/main/db1-ast/mpool/mpool.c +++ /dev/null @@ -1,502 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "asterisk.h" - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)mpool.c 8.5 (Berkeley) 7/26/94"; -#endif /* LIBC_SCCS and not lint */ - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "../include/db.h" - -#include "asterisk/utils.h" - -#define __MPOOLINTERFACE_PRIVATE -#include - -#undef __APPLE__ - -#ifndef __APPLE__ -#define mpool_open __mpool_open -#define mpool_filter __mpool_filter -#define mpool_new __mpool_new -#define mpool_get __mpool_get -#define mpool_put __mpool_put -#define mpool_sync __mpool_sync -#define mpool_close __mpool_close -#endif - -static BKT *mpool_bkt __P((MPOOL *)); -static BKT *mpool_look __P((MPOOL *, pgno_t)); -static int mpool_write __P((MPOOL *, BKT *)); - -/* - * mpool_open -- - * Initialize a memory pool. - */ -MPOOL * -mpool_open(key, fd, pagesize, maxcache) - void *key; - int fd; - pgno_t pagesize, maxcache; -{ - struct stat sb; - MPOOL *mp; - int entry; - - /* - * Get information about the file. - * - * XXX - * We don't currently handle pipes, although we should. - */ - if (fstat(fd, &sb)) - return (NULL); - if (!S_ISREG(sb.st_mode)) { - errno = ESPIPE; - return (NULL); - } - - /* Allocate and initialize the MPOOL cookie. */ - if ((mp = (MPOOL *)calloc(1, sizeof(MPOOL))) == NULL) - return (NULL); - CIRCLEQ_INIT(&mp->lqh); - for (entry = 0; entry < HASHSIZE; ++entry) - CIRCLEQ_INIT(&mp->hqh[entry]); - mp->maxcache = maxcache; - mp->npages = sb.st_size / pagesize; - mp->pagesize = pagesize; - mp->fd = fd; - return (mp); -} - -/* - * mpool_filter -- - * Initialize input/output filters. - */ -void -mpool_filter(mp, pgin, pgout, pgcookie) - MPOOL *mp; - void (*pgin) __P((void *, pgno_t, void *)); - void (*pgout) __P((void *, pgno_t, void *)); - void *pgcookie; -{ - mp->pgin = pgin; - mp->pgout = pgout; - mp->pgcookie = pgcookie; -} - -/* - * mpool_new -- - * Get a new page of memory. - */ -void * -mpool_new(mp, pgnoaddr) - MPOOL *mp; - pgno_t *pgnoaddr; -{ - struct _hqh *head; - BKT *bp; - - if (mp->npages == MAX_PAGE_NUMBER) { - (void)fprintf(stderr, "mpool_new: page allocation overflow.\n"); - abort(); - } -#ifdef STATISTICS - ++mp->pagenew; -#endif - /* - * Get a BKT from the cache. Assign a new page number, attach - * it to the head of the hash chain, the tail of the lru chain, - * and return. - */ - if ((bp = mpool_bkt(mp)) == NULL) - return (NULL); - *pgnoaddr = bp->pgno = mp->npages++; - bp->flags = MPOOL_PINNED; - - head = &mp->hqh[HASHKEY(bp->pgno)]; - CIRCLEQ_INSERT_HEAD(head, bp, hq); - CIRCLEQ_INSERT_TAIL(&mp->lqh, bp, q); - return (bp->page); -} - -/* - * mpool_get - * Get a page. - */ -void * -mpool_get(mp, pgno, flags) - MPOOL *mp; - pgno_t pgno; - u_int flags; /* XXX not used? */ -{ - struct _hqh *head; - BKT *bp; - off_t off; - int nr; - - /* Check for attempt to retrieve a non-existent page. */ - if (pgno >= mp->npages) { - errno = EINVAL; - return (NULL); - } - -#ifdef STATISTICS - ++mp->pageget; -#endif - - /* Check for a page that is cached. */ - if ((bp = mpool_look(mp, pgno)) != NULL) { -#ifdef DEBUG - if (bp->flags & MPOOL_PINNED) { - (void)fprintf(stderr, - "mpool_get: page %d already pinned\n", bp->pgno); - abort(); - } -#endif - /* - * Move the page to the head of the hash chain and the tail - * of the lru chain. - */ - head = &mp->hqh[HASHKEY(bp->pgno)]; - CIRCLEQ_REMOVE(head, bp, hq); - CIRCLEQ_INSERT_HEAD(head, bp, hq); - CIRCLEQ_REMOVE(&mp->lqh, bp, q); - CIRCLEQ_INSERT_TAIL(&mp->lqh, bp, q); - - /* Return a pinned page. */ - bp->flags |= MPOOL_PINNED; - return (bp->page); - } - - /* Get a page from the cache. */ - if ((bp = mpool_bkt(mp)) == NULL) - return (NULL); - - /* Read in the contents. */ -#ifdef STATISTICS - ++mp->pageread; -#endif - off = mp->pagesize * pgno; - if (lseek(mp->fd, off, SEEK_SET) != off) - return (NULL); - if ((u_long) (nr = read(mp->fd, bp->page, mp->pagesize)) - != mp->pagesize) { - if (nr >= 0) - errno = EFTYPE; - return (NULL); - } - - /* Set the page number, pin the page. */ - bp->pgno = pgno; - bp->flags = MPOOL_PINNED; - - /* - * Add the page to the head of the hash chain and the tail - * of the lru chain. - */ - head = &mp->hqh[HASHKEY(bp->pgno)]; - CIRCLEQ_INSERT_HEAD(head, bp, hq); - CIRCLEQ_INSERT_TAIL(&mp->lqh, bp, q); - - /* Run through the user's filter. */ - if (mp->pgin != NULL) - (mp->pgin)(mp->pgcookie, bp->pgno, bp->page); - - return (bp->page); -} - -/* - * mpool_put - * Return a page. - */ -int -mpool_put(mp, page, flags) - MPOOL *mp; - void *page; - u_int flags; -{ - BKT *bp; - -#ifdef STATISTICS - ++mp->pageput; -#endif - bp = (BKT *)((char *)page - sizeof(BKT)); -#ifdef DEBUG - if (!(bp->flags & MPOOL_PINNED)) { - (void)fprintf(stderr, - "mpool_put: page %d not pinned\n", bp->pgno); - abort(); - } -#endif - bp->flags &= ~MPOOL_PINNED; - bp->flags |= flags & MPOOL_DIRTY; - return (RET_SUCCESS); -} - -/* - * mpool_close - * Close the buffer pool. - */ -int -mpool_close(mp) - MPOOL *mp; -{ - BKT *bp; - - /* Free up any space allocated to the lru pages. */ - while ((bp = mp->lqh.cqh_first) != (void *)&mp->lqh) { - CIRCLEQ_REMOVE(&mp->lqh, mp->lqh.cqh_first, q); - free(bp); - } - - /* Free the MPOOL cookie. */ - free(mp); - return (RET_SUCCESS); -} - -/* - * mpool_sync - * Sync the pool to disk. - */ -int -mpool_sync(mp) - MPOOL *mp; -{ - BKT *bp; - - /* Walk the lru chain, flushing any dirty pages to disk. */ - for (bp = mp->lqh.cqh_first; - bp != (void *)&mp->lqh; bp = bp->q.cqe_next) - if (bp->flags & MPOOL_DIRTY && - mpool_write(mp, bp) == RET_ERROR) - return (RET_ERROR); - - /* Sync the file descriptor. */ - return (fsync(mp->fd) ? RET_ERROR : RET_SUCCESS); -} - -#define __APPLE__ - -#ifndef __APPLE__ -#undef mpool_open -#undef mpool_filter -#undef mpool_new -#undef mpool_get -#undef mpool_put -#undef mpool_close -#undef mpool_sync - -#define weak_alias(original, alias) \ - asm (".weak " #alias "\n" #alias " = " #original); -weak_alias (__mpool_open, mpool_open) -weak_alias (__mpool_filter, mpool_filter) -weak_alias (__mpool_new, mpool_new) -weak_alias (__mpool_get, mpool_get) -weak_alias (__mpool_put, mpool_put) -weak_alias (__mpool_close, mpool_close) -weak_alias (__mpool_sync, mpool_sync) -#endif - -/* - * mpool_bkt - * Get a page from the cache (or create one). - */ -static BKT * -mpool_bkt(mp) - MPOOL *mp; -{ - struct _hqh *head; - BKT *bp; - - /* If under the max cached, always create a new page. */ - if (mp->curcache < mp->maxcache) - goto new; - - /* - * If the cache is max'd out, walk the lru list for a buffer we - * can flush. If we find one, write it (if necessary) and take it - * off any lists. If we don't find anything we grow the cache anyway. - * The cache never shrinks. - */ - for (bp = mp->lqh.cqh_first; - bp != (void *)&mp->lqh; bp = bp->q.cqe_next) - if (!(bp->flags & MPOOL_PINNED)) { - /* Flush if dirty. */ - if (bp->flags & MPOOL_DIRTY && - mpool_write(mp, bp) == RET_ERROR) - return (NULL); -#ifdef STATISTICS - ++mp->pageflush; -#endif - /* Remove from the hash and lru queues. */ - head = &mp->hqh[HASHKEY(bp->pgno)]; - CIRCLEQ_REMOVE(head, bp, hq); - CIRCLEQ_REMOVE(&mp->lqh, bp, q); -#ifdef DEBUG - { void *spage; - spage = bp->page; - memset(bp, 0xff, sizeof(BKT) + mp->pagesize); - bp->page = spage; - } -#endif - return (bp); - } - -new: if ((bp = (BKT *) ast_calloc(1, sizeof(BKT) + mp->pagesize)) == NULL) - return (NULL); -#ifdef STATISTICS - ++mp->pagealloc; -#endif -#if defined(DEBUG) || defined(PURIFY) - memset(bp, 0xff, sizeof(BKT) + mp->pagesize); -#endif - bp->page = (char *)bp + sizeof(BKT); - ++mp->curcache; - return (bp); -} - -/* - * mpool_write - * Write a page to disk. - */ -static int -mpool_write(mp, bp) - MPOOL *mp; - BKT *bp; -{ - off_t off; - -#ifdef STATISTICS - ++mp->pagewrite; -#endif - - /* Run through the user's filter. */ - if (mp->pgout) - (mp->pgout)(mp->pgcookie, bp->pgno, bp->page); - - off = mp->pagesize * bp->pgno; - if (lseek(mp->fd, off, SEEK_SET) != off) - return (RET_ERROR); - if ((u_long) write(mp->fd, bp->page, mp->pagesize) != mp->pagesize) - return (RET_ERROR); - - bp->flags &= ~MPOOL_DIRTY; - return (RET_SUCCESS); -} - -/* - * mpool_look - * Lookup a page in the cache. - */ -static BKT * -mpool_look(mp, pgno) - MPOOL *mp; - pgno_t pgno; -{ - struct _hqh *head; - BKT *bp; - - head = &mp->hqh[HASHKEY(pgno)]; - for (bp = head->cqh_first; bp != (void *)head; bp = bp->hq.cqe_next) - if (bp->pgno == pgno) { -#ifdef STATISTICS - ++mp->cachehit; -#endif - return (bp); - } -#ifdef STATISTICS - ++mp->cachemiss; -#endif - return (NULL); -} - -#ifdef STATISTICS -/* - * mpool_stat - * Print out cache statistics. - */ -void -mpool_stat(mp) - MPOOL *mp; -{ - BKT *bp; - int cnt; - char *sep; - - (void)fprintf(stderr, "%lu pages in the file\n", mp->npages); - (void)fprintf(stderr, - "page size %lu, cacheing %lu pages of %lu page max cache\n", - mp->pagesize, mp->curcache, mp->maxcache); - (void)fprintf(stderr, "%lu page puts, %lu page gets, %lu page new\n", - mp->pageput, mp->pageget, mp->pagenew); - (void)fprintf(stderr, "%lu page allocs, %lu page flushes\n", - mp->pagealloc, mp->pageflush); - if (mp->cachehit + mp->cachemiss) - (void)fprintf(stderr, - "%.0f%% cache hit rate (%lu hits, %lu misses)\n", - ((double)mp->cachehit / (mp->cachehit + mp->cachemiss)) - * 100, mp->cachehit, mp->cachemiss); - (void)fprintf(stderr, "%lu page reads, %lu page writes\n", - mp->pageread, mp->pagewrite); - - sep = ""; - cnt = 0; - for (bp = mp->lqh.cqh_first; - bp != (void *)&mp->lqh; bp = bp->q.cqe_next) { - (void)fprintf(stderr, "%s%d", sep, bp->pgno); - if (bp->flags & MPOOL_DIRTY) - (void)fprintf(stderr, "d"); - if (bp->flags & MPOOL_PINNED) - (void)fprintf(stderr, "P"); - if (++cnt == 10) { - sep = "\n"; - cnt = 0; - } else - sep = ", "; - - } - (void)fprintf(stderr, "\n"); -} -#endif diff --git a/main/db1-ast/recno/extern.h b/main/db1-ast/recno/extern.h deleted file mode 100644 index feed43445..000000000 --- a/main/db1-ast/recno/extern.h +++ /dev/null @@ -1,54 +0,0 @@ -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)extern.h 8.3 (Berkeley) 6/4/94 - */ - -#include "../btree/extern.h" - -int __rec_close __P((DB *)); -int __rec_delete __P((const DB *, const DBT *, u_int)); -int __rec_dleaf __P((BTREE *, PAGE *, u_int32_t)); -int __rec_fd __P((const DB *)); -int __rec_fmap __P((BTREE *, recno_t)); -int __rec_fout __P((BTREE *)); -int __rec_fpipe __P((BTREE *, recno_t)); -int __rec_get __P((const DB *, const DBT *, DBT *, u_int)); -int __rec_iput __P((BTREE *, recno_t, const DBT *, u_int)); -int __rec_put __P((const DB *dbp, DBT *, const DBT *, u_int)); -int __rec_ret __P((BTREE *, EPG *, recno_t, DBT *, DBT *)); -EPG *__rec_search __P((BTREE *, recno_t, enum SRCHOP)); -int __rec_seq __P((const DB *, DBT *, DBT *, u_int)); -int __rec_sync __P((const DB *, u_int)); -int __rec_vmap __P((BTREE *, recno_t)); -int __rec_vout __P((BTREE *)); -int __rec_vpipe __P((BTREE *, recno_t)); diff --git a/main/db1-ast/recno/rec_close.c b/main/db1-ast/recno/rec_close.c deleted file mode 100644 index 20b00f52c..000000000 --- a/main/db1-ast/recno/rec_close.c +++ /dev/null @@ -1,183 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)rec_close.c 8.6 (Berkeley) 8/18/94"; -#endif /* LIBC_SCCS and not lint */ - -#include -#include -#include - -#include -#include -#include -#include - -#include "../include/db.h" -#include "recno.h" - -/* - * __REC_CLOSE -- Close a recno tree. - * - * Parameters: - * dbp: pointer to access method - * - * Returns: - * RET_ERROR, RET_SUCCESS - */ -int -__rec_close(dbp) - DB *dbp; -{ - BTREE *t; - int status; - - t = dbp->internal; - - /* Toss any page pinned across calls. */ - if (t->bt_pinned != NULL) { - mpool_put(t->bt_mp, t->bt_pinned, 0); - t->bt_pinned = NULL; - } - - if (__rec_sync(dbp, 0) == RET_ERROR) - return (RET_ERROR); - - /* Committed to closing. */ - status = RET_SUCCESS; - if (F_ISSET(t, R_MEMMAPPED) && munmap(t->bt_smap, t->bt_msize)) - status = RET_ERROR; - - if (!F_ISSET(t, R_INMEM)) { - if (F_ISSET(t, R_CLOSEFP)) { - if (fclose(t->bt_rfp)) - status = RET_ERROR; - } else - if (close(t->bt_rfd)) - status = RET_ERROR; - } - - if (__bt_close(dbp) == RET_ERROR) - status = RET_ERROR; - - return (status); -} - -/* - * __REC_SYNC -- sync the recno tree to disk. - * - * Parameters: - * dbp: pointer to access method - * - * Returns: - * RET_SUCCESS, RET_ERROR. - */ -int -__rec_sync(dbp, flags) - const DB *dbp; - u_int flags; -{ - struct iovec iov[2]; - BTREE *t; - DBT data, key; - off_t off; - recno_t scursor, trec; - int status; - - t = dbp->internal; - - /* Toss any page pinned across calls. */ - if (t->bt_pinned != NULL) { - mpool_put(t->bt_mp, t->bt_pinned, 0); - t->bt_pinned = NULL; - } - - if (flags == R_RECNOSYNC) - return (__bt_sync(dbp, 0)); - - if (F_ISSET(t, R_RDONLY | R_INMEM) || !F_ISSET(t, R_MODIFIED)) - return (RET_SUCCESS); - - /* Read any remaining records into the tree. */ - if (!F_ISSET(t, R_EOF) && t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR) - return (RET_ERROR); - - /* Rewind the file descriptor. */ - if (lseek(t->bt_rfd, (off_t)0, SEEK_SET) != 0) - return (RET_ERROR); - - /* Save the cursor. */ - scursor = t->bt_cursor.rcursor; - - key.size = sizeof(recno_t); - key.data = &trec; - - if (F_ISSET(t, R_FIXLEN)) { - /* - * We assume that fixed length records are all fixed length. - * Any that aren't are either EINVAL'd or corrected by the - * record put code. - */ - status = (dbp->seq)(dbp, &key, &data, R_FIRST); - while (status == RET_SUCCESS) { - if ((size_t) write(t->bt_rfd, data.data, data.size) != data.size) - return (RET_ERROR); - status = (dbp->seq)(dbp, &key, &data, R_NEXT); - } - } else { - iov[1].iov_base = &t->bt_bval; - iov[1].iov_len = 1; - - status = (dbp->seq)(dbp, &key, &data, R_FIRST); - while (status == RET_SUCCESS) { - iov[0].iov_base = data.data; - iov[0].iov_len = data.size; - if ((size_t) writev(t->bt_rfd, iov, 2) != data.size + 1) - return (RET_ERROR); - status = (dbp->seq)(dbp, &key, &data, R_NEXT); - } - } - - /* Restore the cursor. */ - t->bt_cursor.rcursor = scursor; - - if (status == RET_ERROR) - return (RET_ERROR); - if ((off = lseek(t->bt_rfd, (off_t)0, SEEK_CUR)) == -1) - return (RET_ERROR); - if (ftruncate(t->bt_rfd, off)) - return (RET_ERROR); - F_CLR(t, R_MODIFIED); - return (RET_SUCCESS); -} diff --git a/main/db1-ast/recno/rec_delete.c b/main/db1-ast/recno/rec_delete.c deleted file mode 100644 index f40b5caed..000000000 --- a/main/db1-ast/recno/rec_delete.c +++ /dev/null @@ -1,197 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Mike Olson. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)rec_delete.c 8.7 (Berkeley) 7/14/94"; -#endif /* LIBC_SCCS and not lint */ - -#include - -#include -#include -#include - -#include "../include/db.h" -#include "recno.h" - -static int rec_rdelete __P((BTREE *, recno_t)); - -/* - * __REC_DELETE -- Delete the item(s) referenced by a key. - * - * Parameters: - * dbp: pointer to access method - * key: key to delete - * flags: R_CURSOR if deleting what the cursor references - * - * Returns: - * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found. - */ -int -__rec_delete(dbp, key, flags) - const DB *dbp; - const DBT *key; - u_int flags; -{ - BTREE *t; - recno_t nrec; - int status; - - t = dbp->internal; - - /* Toss any page pinned across calls. */ - if (t->bt_pinned != NULL) { - mpool_put(t->bt_mp, t->bt_pinned, 0); - t->bt_pinned = NULL; - } - - switch(flags) { - case 0: - if ((nrec = *(recno_t *)key->data) == 0) - goto einval; - if (nrec > t->bt_nrecs) - return (RET_SPECIAL); - --nrec; - status = rec_rdelete(t, nrec); - break; - case R_CURSOR: - if (!F_ISSET(&t->bt_cursor, CURS_INIT)) - goto einval; - if (t->bt_nrecs == 0) - return (RET_SPECIAL); - status = rec_rdelete(t, t->bt_cursor.rcursor - 1); - if (status == RET_SUCCESS) - --t->bt_cursor.rcursor; - break; - default: -einval: errno = EINVAL; - return (RET_ERROR); - } - - if (status == RET_SUCCESS) - F_SET(t, B_MODIFIED | R_MODIFIED); - return (status); -} - -/* - * REC_RDELETE -- Delete the data matching the specified key. - * - * Parameters: - * tree: tree - * nrec: record to delete - * - * Returns: - * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found. - */ -static int -rec_rdelete(t, nrec) - BTREE *t; - recno_t nrec; -{ - EPG *e; - PAGE *h; - int status; - - /* Find the record; __rec_search pins the page. */ - if ((e = __rec_search(t, nrec, SDELETE)) == NULL) - return (RET_ERROR); - - /* Delete the record. */ - h = e->page; - status = __rec_dleaf(t, h, e->index); - if (status != RET_SUCCESS) { - mpool_put(t->bt_mp, h, 0); - return (status); - } - mpool_put(t->bt_mp, h, MPOOL_DIRTY); - return (RET_SUCCESS); -} - -/* - * __REC_DLEAF -- Delete a single record from a recno leaf page. - * - * Parameters: - * t: tree - * index: index on current page to delete - * - * Returns: - * RET_SUCCESS, RET_ERROR. - */ -int -__rec_dleaf(t, h, idx) - BTREE *t; - PAGE *h; - u_int32_t idx; -{ - RLEAF *rl; - indx_t *ip, cnt, offset; - u_int32_t nbytes; - char *from; - void *to; - - /* - * Delete a record from a recno leaf page. Internal records are never - * deleted from internal pages, regardless of the records that caused - * them to be added being deleted. Pages made empty by deletion are - * not reclaimed. They are, however, made available for reuse. - * - * Pack the remaining entries at the end of the page, shift the indices - * down, overwriting the deleted record and its index. If the record - * uses overflow pages, make them available for reuse. - */ - to = rl = GETRLEAF(h, idx); - if (rl->flags & P_BIGDATA && __ovfl_delete(t, rl->bytes) == RET_ERROR) - return (RET_ERROR); - nbytes = NRLEAF(rl); - - /* - * Compress the key/data pairs. Compress and adjust the [BR]LEAF - * offsets. Reset the headers. - */ - from = (char *)h + h->upper; - memmove(from + nbytes, from, (char *)to - from); - h->upper += nbytes; - - offset = h->linp[idx]; - for (cnt = &h->linp[idx] - (ip = &h->linp[0]); cnt--; ++ip) - if (ip[0] < offset) - ip[0] += nbytes; - for (cnt = &h->linp[NEXTINDEX(h)] - ip; --cnt; ++ip) - ip[0] = ip[1] < offset ? ip[1] + nbytes : ip[1]; - h->lower -= sizeof(indx_t); - --t->bt_nrecs; - return (RET_SUCCESS); -} diff --git a/main/db1-ast/recno/rec_get.c b/main/db1-ast/recno/rec_get.c deleted file mode 100644 index 7038cc81a..000000000 --- a/main/db1-ast/recno/rec_get.c +++ /dev/null @@ -1,311 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)rec_get.c 8.9 (Berkeley) 8/18/94"; -#endif /* LIBC_SCCS and not lint */ - -#include - -#include -#include -#include -#include -#include -#include - -#include "../include/db.h" -#include "recno.h" - -/* - * __REC_GET -- Get a record from the btree. - * - * Parameters: - * dbp: pointer to access method - * key: key to find - * data: data to return - * flag: currently unused - * - * Returns: - * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found. - */ -int -__rec_get(dbp, key, data, flags) - const DB *dbp; - const DBT *key; - DBT *data; - u_int flags; -{ - BTREE *t; - EPG *e; - recno_t nrec; - int status; - - t = dbp->internal; - - /* Toss any page pinned across calls. */ - if (t->bt_pinned != NULL) { - mpool_put(t->bt_mp, t->bt_pinned, 0); - t->bt_pinned = NULL; - } - - /* Get currently doesn't take any flags, and keys of 0 are illegal. */ - if (flags || (nrec = *(recno_t *)key->data) == 0) { - errno = EINVAL; - return (RET_ERROR); - } - - /* - * If we haven't seen this record yet, try to find it in the - * original file. - */ - if (nrec > t->bt_nrecs) { - if (F_ISSET(t, R_EOF | R_INMEM)) - return (RET_SPECIAL); - if ((status = t->bt_irec(t, nrec)) != RET_SUCCESS) - return (status); - } - - --nrec; - if ((e = __rec_search(t, nrec, SEARCH)) == NULL) - return (RET_ERROR); - - status = __rec_ret(t, e, 0, NULL, data); - if (F_ISSET(t, B_DB_LOCK)) - mpool_put(t->bt_mp, e->page, 0); - else - t->bt_pinned = e->page; - return (status); -} - -/* - * __REC_FPIPE -- Get fixed length records from a pipe. - * - * Parameters: - * t: tree - * cnt: records to read - * - * Returns: - * RET_ERROR, RET_SUCCESS - */ -int -__rec_fpipe(t, top) - BTREE *t; - recno_t top; -{ - DBT data; - recno_t nrec; - size_t len; - int ch; - u_char *p; - - if (t->bt_rdata.size < t->bt_reclen) { - t->bt_rdata.data = t->bt_rdata.data == NULL ? - malloc(t->bt_reclen) : - realloc(t->bt_rdata.data, t->bt_reclen); - if (t->bt_rdata.data == NULL) - return (RET_ERROR); - t->bt_rdata.size = t->bt_reclen; - } - data.data = t->bt_rdata.data; - data.size = t->bt_reclen; - - for (nrec = t->bt_nrecs; nrec < top;) { - len = t->bt_reclen; - for (p = t->bt_rdata.data;; *p++ = ch) - if ((ch = getc(t->bt_rfp)) == EOF || !--len) { - if (ch != EOF) - *p = ch; - if (len != 0) - memset(p, t->bt_bval, len); - if (__rec_iput(t, - nrec, &data, 0) != RET_SUCCESS) - return (RET_ERROR); - ++nrec; - break; - } - if (ch == EOF) - break; - } - if (nrec < top) { - F_SET(t, R_EOF); - return (RET_SPECIAL); - } - return (RET_SUCCESS); -} - -/* - * __REC_VPIPE -- Get variable length records from a pipe. - * - * Parameters: - * t: tree - * cnt: records to read - * - * Returns: - * RET_ERROR, RET_SUCCESS - */ -int -__rec_vpipe(t, top) - BTREE *t; - recno_t top; -{ - DBT data; - recno_t nrec; - indx_t len; - size_t sz; - int bval, ch; - u_char *p; - - bval = t->bt_bval; - for (nrec = t->bt_nrecs; nrec < top; ++nrec) { - for (p = t->bt_rdata.data, - sz = t->bt_rdata.size;; *p++ = ch, --sz) { - if ((ch = getc(t->bt_rfp)) == EOF || ch == bval) { - data.data = t->bt_rdata.data; - data.size = p - (u_char *)t->bt_rdata.data; - if (ch == EOF && data.size == 0) - break; - if (__rec_iput(t, nrec, &data, 0) - != RET_SUCCESS) - return (RET_ERROR); - break; - } - if (sz == 0) { - len = p - (u_char *)t->bt_rdata.data; - t->bt_rdata.size += (sz = 256); - t->bt_rdata.data = t->bt_rdata.data == NULL ? - malloc(t->bt_rdata.size) : - realloc(t->bt_rdata.data, t->bt_rdata.size); - if (t->bt_rdata.data == NULL) - return (RET_ERROR); - p = (u_char *)t->bt_rdata.data + len; - } - } - if (ch == EOF) - break; - } - if (nrec < top) { - F_SET(t, R_EOF); - return (RET_SPECIAL); - } - return (RET_SUCCESS); -} - -/* - * __REC_FMAP -- Get fixed length records from a file. - * - * Parameters: - * t: tree - * cnt: records to read - * - * Returns: - * RET_ERROR, RET_SUCCESS - */ -int -__rec_fmap(t, top) - BTREE *t; - recno_t top; -{ - DBT data; - recno_t nrec; - u_char *sp, *ep, *p; - size_t len; - - if (t->bt_rdata.size < t->bt_reclen) { - t->bt_rdata.data = t->bt_rdata.data == NULL ? - malloc(t->bt_reclen) : - realloc(t->bt_rdata.data, t->bt_reclen); - if (t->bt_rdata.data == NULL) - return (RET_ERROR); - t->bt_rdata.size = t->bt_reclen; - } - data.data = t->bt_rdata.data; - data.size = t->bt_reclen; - - sp = (u_char *)t->bt_cmap; - ep = (u_char *)t->bt_emap; - for (nrec = t->bt_nrecs; nrec < top; ++nrec) { - if (sp >= ep) { - F_SET(t, R_EOF); - return (RET_SPECIAL); - } - len = t->bt_reclen; - for (p = t->bt_rdata.data; - sp < ep && len > 0; *p++ = *sp++, --len); - if (len != 0) - memset(p, t->bt_bval, len); - if (__rec_iput(t, nrec, &data, 0) != RET_SUCCESS) - return (RET_ERROR); - } - t->bt_cmap = (caddr_t)sp; - return (RET_SUCCESS); -} - -/* - * __REC_VMAP -- Get variable length records from a file. - * - * Parameters: - * t: tree - * cnt: records to read - * - * Returns: - * RET_ERROR, RET_SUCCESS - */ -int -__rec_vmap(t, top) - BTREE *t; - recno_t top; -{ - DBT data; - u_char *sp, *ep; - recno_t nrec; - int bval; - - sp = (u_char *)t->bt_cmap; - ep = (u_char *)t->bt_emap; - bval = t->bt_bval; - - for (nrec = t->bt_nrecs; nrec < top; ++nrec) { - if (sp >= ep) { - F_SET(t, R_EOF); - return (RET_SPECIAL); - } - for (data.data = sp; sp < ep && *sp != bval; ++sp); - data.size = sp - (u_char *)data.data; - if (__rec_iput(t, nrec, &data, 0) != RET_SUCCESS) - return (RET_ERROR); - ++sp; - } - t->bt_cmap = (caddr_t)sp; - return (RET_SUCCESS); -} diff --git a/main/db1-ast/recno/rec_open.c b/main/db1-ast/recno/rec_open.c deleted file mode 100644 index 0fb08258c..000000000 --- a/main/db1-ast/recno/rec_open.c +++ /dev/null @@ -1,241 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Mike Olson. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)rec_open.c 8.10 (Berkeley) 9/1/94"; -#endif /* LIBC_SCCS and not lint */ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "../include/db.h" -#include "recno.h" - -DB * -__rec_open(fname, flags, mode, openinfo, dflags) - const char *fname; - int flags, mode, dflags; - const RECNOINFO *openinfo; -{ - BTREE *t; - BTREEINFO btopeninfo; - DB *dbp; - PAGE *h; - struct stat sb; - int rfd = 0, sverrno; - - /* Open the user's file -- if this fails, we're done. */ - if (fname != NULL && (rfd = open(fname, flags, mode)) < 0) - return (NULL); - - /* Create a btree in memory (backed by disk). */ - dbp = NULL; - if (openinfo) { - if (openinfo->flags & ~(R_FIXEDLEN | R_NOKEY | R_SNAPSHOT)) - goto einval; - btopeninfo.flags = 0; - btopeninfo.cachesize = openinfo->cachesize; - btopeninfo.maxkeypage = 0; - btopeninfo.minkeypage = 0; - btopeninfo.psize = openinfo->psize; - btopeninfo.compare = NULL; - btopeninfo.prefix = NULL; - btopeninfo.lorder = openinfo->lorder; - dbp = __bt_open(openinfo->bfname, - O_RDWR, S_IRUSR | S_IWUSR, &btopeninfo, dflags); - } else - dbp = __bt_open(NULL, O_RDWR, S_IRUSR | S_IWUSR, NULL, dflags); - if (dbp == NULL) - goto err; - - /* - * Some fields in the tree structure are recno specific. Fill them - * in and make the btree structure look like a recno structure. We - * don't change the bt_ovflsize value, it's close enough and slightly - * bigger. - */ - t = dbp->internal; - if (openinfo) { - if (openinfo->flags & R_FIXEDLEN) { - F_SET(t, R_FIXLEN); - t->bt_reclen = openinfo->reclen; - if (t->bt_reclen == 0) - goto einval; - } - t->bt_bval = openinfo->bval; - } else - t->bt_bval = '\n'; - - F_SET(t, R_RECNO); - if (fname == NULL) - F_SET(t, R_EOF | R_INMEM); - else - t->bt_rfd = rfd; - - if (fname != NULL) { - /* - * In 4.4BSD, stat(2) returns true for ISSOCK on pipes. - * Unfortunately, that's not portable, so we use lseek - * and check the errno values. - */ - errno = 0; - if (lseek(rfd, (off_t)0, SEEK_CUR) == -1 && errno == ESPIPE) { - switch (flags & O_ACCMODE) { - case O_RDONLY: - F_SET(t, R_RDONLY); - break; - default: - goto einval; - } -slow: if ((t->bt_rfp = fdopen(rfd, "r")) == NULL) - goto err; - F_SET(t, R_CLOSEFP); - t->bt_irec = - F_ISSET(t, R_FIXLEN) ? __rec_fpipe : __rec_vpipe; - } else { - switch (flags & O_ACCMODE) { - case O_RDONLY: - F_SET(t, R_RDONLY); - break; - case O_RDWR: - break; - default: - goto einval; - } - - if (fstat(rfd, &sb)) - goto err; - /* - * Kluge -- we'd like to test to see if the file is too - * big to mmap. Since, we don't know what size or type - * off_t's or size_t's are, what the largest unsigned - * integral type is, or what random insanity the local - * C compiler will perpetrate, doing the comparison in - * a portable way is flatly impossible. Hope that mmap - * fails if the file is too large. - */ - if (sb.st_size == 0) - F_SET(t, R_EOF); - else { -#ifdef MMAP_NOT_AVAILABLE - /* - * XXX - * Mmap doesn't work correctly on many current - * systems. In particular, it can fail subtly, - * with cache coherency problems. Don't use it - * for now. - */ - t->bt_msize = sb.st_size; - if ((t->bt_smap = mmap(NULL, t->bt_msize, - PROT_READ, MAP_PRIVATE, rfd, - (off_t)0)) == MAP_FAILED - goto slow; - t->bt_cmap = t->bt_smap; - t->bt_emap = t->bt_smap + sb.st_size; - t->bt_irec = F_ISSET(t, R_FIXLEN) ? - __rec_fmap : __rec_vmap; - F_SET(t, R_MEMMAPPED); -#else - goto slow; -#endif - } - } - } - - /* Use the recno routines. */ - dbp->close = __rec_close; - dbp->del = __rec_delete; - dbp->fd = __rec_fd; - dbp->get = __rec_get; - dbp->put = __rec_put; - dbp->seq = __rec_seq; - dbp->sync = __rec_sync; - - /* If the root page was created, reset the flags. */ - if ((h = mpool_get(t->bt_mp, P_ROOT, 0)) == NULL) - goto err; - if ((h->flags & P_TYPE) == P_BLEAF) { - F_CLR(h, P_TYPE); - F_SET(h, P_RLEAF); - mpool_put(t->bt_mp, h, MPOOL_DIRTY); - } else - mpool_put(t->bt_mp, h, 0); - - if (openinfo && openinfo->flags & R_SNAPSHOT && - !F_ISSET(t, R_EOF | R_INMEM) && - t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR) - goto err; - return (dbp); - -einval: errno = EINVAL; -err: sverrno = errno; - if (dbp != NULL) - (void)__bt_close(dbp); - if (fname != NULL) - (void)close(rfd); - errno = sverrno; - return (NULL); -} - -int -__rec_fd(dbp) - const DB *dbp; -{ - BTREE *t; - - t = dbp->internal; - - /* Toss any page pinned across calls. */ - if (t->bt_pinned != NULL) { - mpool_put(t->bt_mp, t->bt_pinned, 0); - t->bt_pinned = NULL; - } - - /* In-memory database can't have a file descriptor. */ - if (F_ISSET(t, R_INMEM)) { - errno = ENOENT; - return (-1); - } - return (t->bt_rfd); -} diff --git a/main/db1-ast/recno/rec_put.c b/main/db1-ast/recno/rec_put.c deleted file mode 100644 index ba8861297..000000000 --- a/main/db1-ast/recno/rec_put.c +++ /dev/null @@ -1,280 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)rec_put.c 8.7 (Berkeley) 8/18/94"; -#endif /* LIBC_SCCS and not lint */ - -#include - -#include -#include -#include -#include - -#include "../include/db.h" -#include "recno.h" - -/* - * __REC_PUT -- Add a recno item to the tree. - * - * Parameters: - * dbp: pointer to access method - * key: key - * data: data - * flag: R_CURSOR, R_IAFTER, R_IBEFORE, R_NOOVERWRITE - * - * Returns: - * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key is - * already in the tree and R_NOOVERWRITE specified. - */ -int -__rec_put(dbp, key, data, flags) - const DB *dbp; - DBT *key; - const DBT *data; - u_int flags; -{ - BTREE *t; - DBT fdata, tdata; - recno_t nrec; - int status; - - t = dbp->internal; - - /* Toss any page pinned across calls. */ - if (t->bt_pinned != NULL) { - mpool_put(t->bt_mp, t->bt_pinned, 0); - t->bt_pinned = NULL; - } - - /* - * If using fixed-length records, and the record is long, return - * EINVAL. If it's short, pad it out. Use the record data return - * memory, it's only short-term. - */ - if (F_ISSET(t, R_FIXLEN) && data->size != t->bt_reclen) { - if (data->size > t->bt_reclen) - goto einval; - - if (t->bt_rdata.size < t->bt_reclen) { - t->bt_rdata.data = t->bt_rdata.data == NULL ? - malloc(t->bt_reclen) : - realloc(t->bt_rdata.data, t->bt_reclen); - if (t->bt_rdata.data == NULL) - return (RET_ERROR); - t->bt_rdata.size = t->bt_reclen; - } - memmove(t->bt_rdata.data, data->data, data->size); - memset((char *)t->bt_rdata.data + data->size, - t->bt_bval, t->bt_reclen - data->size); - fdata.data = t->bt_rdata.data; - fdata.size = t->bt_reclen; - } else { - fdata.data = data->data; - fdata.size = data->size; - } - - switch (flags) { - case R_CURSOR: - if (!F_ISSET(&t->bt_cursor, CURS_INIT)) - goto einval; - nrec = t->bt_cursor.rcursor; - break; - case R_SETCURSOR: - if ((nrec = *(recno_t *)key->data) == 0) - goto einval; - break; - case R_IAFTER: - if ((nrec = *(recno_t *)key->data) == 0) { - nrec = 1; - flags = R_IBEFORE; - } - break; - case 0: - case R_IBEFORE: - if ((nrec = *(recno_t *)key->data) == 0) - goto einval; - break; - case R_NOOVERWRITE: - if ((nrec = *(recno_t *)key->data) == 0) - goto einval; - if (nrec <= t->bt_nrecs) - return (RET_SPECIAL); - break; - default: -einval: errno = EINVAL; - return (RET_ERROR); - } - - /* - * Make sure that records up to and including the put record are - * already in the database. If skipping records, create empty ones. - */ - if (nrec > t->bt_nrecs) { - if (!F_ISSET(t, R_EOF | R_INMEM) && - t->bt_irec(t, nrec) == RET_ERROR) - return (RET_ERROR); - if (nrec > t->bt_nrecs + 1) { - if (F_ISSET(t, R_FIXLEN)) { - if ((tdata.data = - (void *)malloc(t->bt_reclen)) == NULL) - return (RET_ERROR); - tdata.size = t->bt_reclen; - memset(tdata.data, t->bt_bval, tdata.size); - } else { - tdata.data = NULL; - tdata.size = 0; - } - while (nrec > t->bt_nrecs + 1) - if (__rec_iput(t, - t->bt_nrecs, &tdata, 0) != RET_SUCCESS) - return (RET_ERROR); - if (F_ISSET(t, R_FIXLEN)) - free(tdata.data); - } - } - - if ((status = __rec_iput(t, nrec - 1, &fdata, flags)) != RET_SUCCESS) - return (status); - - if (flags == R_SETCURSOR) - t->bt_cursor.rcursor = nrec; - - F_SET(t, R_MODIFIED); - return (__rec_ret(t, NULL, nrec, key, NULL)); -} - -/* - * __REC_IPUT -- Add a recno item to the tree. - * - * Parameters: - * t: tree - * nrec: record number - * data: data - * - * Returns: - * RET_ERROR, RET_SUCCESS - */ -int -__rec_iput(t, nrec, data, flags) - BTREE *t; - recno_t nrec; - const DBT *data; - u_int flags; -{ - DBT tdata; - EPG *e; - PAGE *h; - indx_t idx, nxtindex; - pgno_t pg; - u_int32_t nbytes; - int dflags, status; - char *dest, db[NOVFLSIZE]; - - /* - * If the data won't fit on a page, store it on indirect pages. - * - * XXX - * If the insert fails later on, these pages aren't recovered. - */ - if (data->size > t->bt_ovflsize) { - if (__ovfl_put(t, data, &pg) == RET_ERROR) - return (RET_ERROR); - tdata.data = db; - tdata.size = NOVFLSIZE; - *(pgno_t *)db = pg; - *(u_int32_t *)(db + sizeof(pgno_t)) = data->size; - dflags = P_BIGDATA; - data = &tdata; - } else - dflags = 0; - - /* __rec_search pins the returned page. */ - if ((e = __rec_search(t, nrec, - nrec > t->bt_nrecs || flags == R_IAFTER || flags == R_IBEFORE ? - SINSERT : SEARCH)) == NULL) - return (RET_ERROR); - - h = e->page; - idx = e->index; - - /* - * Add the specified key/data pair to the tree. The R_IAFTER and - * R_IBEFORE flags insert the key after/before the specified key. - * - * Pages are split as required. - */ - switch (flags) { - case R_IAFTER: - ++idx; - break; - case R_IBEFORE: - break; - default: - if (nrec < t->bt_nrecs && - __rec_dleaf(t, h, idx) == RET_ERROR) { - mpool_put(t->bt_mp, h, 0); - return (RET_ERROR); - } - break; - } - - /* - * If not enough room, split the page. The split code will insert - * the key and data and unpin the current page. If inserting into - * the offset array, shift the pointers up. - */ - nbytes = NRLEAFDBT(data->size); - if ((u_int32_t) (h->upper - h->lower) < nbytes + sizeof(indx_t)) { - status = __bt_split(t, h, NULL, data, dflags, nbytes, idx); - if (status == RET_SUCCESS) - ++t->bt_nrecs; - return (status); - } - - if (idx < (nxtindex = NEXTINDEX(h))) - memmove(h->linp + idx + 1, h->linp + idx, - (nxtindex - idx) * sizeof(indx_t)); - h->lower += sizeof(indx_t); - - h->linp[idx] = h->upper -= nbytes; - dest = (char *)h + h->upper; - WR_RLEAF(dest, data, dflags); - - ++t->bt_nrecs; - F_SET(t, B_MODIFIED); - mpool_put(t->bt_mp, h, MPOOL_DIRTY); - - return (RET_SUCCESS); -} diff --git a/main/db1-ast/recno/rec_search.c b/main/db1-ast/recno/rec_search.c deleted file mode 100644 index e70fe4c13..000000000 --- a/main/db1-ast/recno/rec_search.c +++ /dev/null @@ -1,126 +0,0 @@ -/*- - * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)rec_search.c 8.4 (Berkeley) 7/14/94"; -#endif /* LIBC_SCCS and not lint */ - -#include - -#include -#include - -#include "../include/db.h" -#include "recno.h" - -/* - * __REC_SEARCH -- Search a btree for a key. - * - * Parameters: - * t: tree to search - * recno: key to find - * op: search operation - * - * Returns: - * EPG for matching record, if any, or the EPG for the location of the - * key, if it were inserted into the tree. - * - * Returns: - * The EPG for matching record, if any, or the EPG for the location - * of the key, if it were inserted into the tree, is entered into - * the bt_cur field of the tree. A pointer to the field is returned. - */ -EPG * -__rec_search(t, recno, op) - BTREE *t; - recno_t recno; - enum SRCHOP op; -{ - register indx_t index; - register PAGE *h; - EPGNO *parent; - RINTERNAL *r; - pgno_t pg; - indx_t top; - recno_t total; - int sverrno; - - BT_CLR(t); - for (pg = P_ROOT, total = 0;;) { - if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) - goto err; - if (h->flags & P_RLEAF) { - t->bt_cur.page = h; - t->bt_cur.index = recno - total; - return (&t->bt_cur); - } - for (index = 0, top = NEXTINDEX(h);;) { - r = GETRINTERNAL(h, index); - if (++index == top || total + r->nrecs > recno) - break; - total += r->nrecs; - } - - BT_PUSH(t, pg, index - 1); - - pg = r->pgno; - switch (op) { - case SDELETE: - --GETRINTERNAL(h, (index - 1))->nrecs; - mpool_put(t->bt_mp, h, MPOOL_DIRTY); - break; - case SINSERT: - ++GETRINTERNAL(h, (index - 1))->nrecs; - mpool_put(t->bt_mp, h, MPOOL_DIRTY); - break; - case SEARCH: - mpool_put(t->bt_mp, h, 0); - break; - } - - } - /* Try and recover the tree. */ -err: sverrno = errno; - if (op != SEARCH) - while ((parent = BT_POP(t)) != NULL) { - if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL) - break; - if (op == SINSERT) - --GETRINTERNAL(h, parent->index)->nrecs; - else - ++GETRINTERNAL(h, parent->index)->nrecs; - mpool_put(t->bt_mp, h, MPOOL_DIRTY); - } - errno = sverrno; - return (NULL); -} diff --git a/main/db1-ast/recno/rec_seq.c b/main/db1-ast/recno/rec_seq.c deleted file mode 100644 index ca3451ca6..000000000 --- a/main/db1-ast/recno/rec_seq.c +++ /dev/null @@ -1,131 +0,0 @@ -/*- - * Copyright (c) 1991, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)rec_seq.c 8.3 (Berkeley) 7/14/94"; -#endif /* not lint */ - -#include - -#include -#include -#include -#include - -#include "../include/db.h" -#include "recno.h" - -/* - * __REC_SEQ -- Recno sequential scan interface. - * - * Parameters: - * dbp: pointer to access method - * key: key for positioning and return value - * data: data return value - * flags: R_CURSOR, R_FIRST, R_LAST, R_NEXT, R_PREV. - * - * Returns: - * RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key. - */ -int -__rec_seq(dbp, key, data, flags) - const DB *dbp; - DBT *key, *data; - u_int flags; -{ - BTREE *t; - EPG *e; - recno_t nrec; - int status; - - t = dbp->internal; - - /* Toss any page pinned across calls. */ - if (t->bt_pinned != NULL) { - mpool_put(t->bt_mp, t->bt_pinned, 0); - t->bt_pinned = NULL; - } - - switch(flags) { - case R_CURSOR: - if ((nrec = *(recno_t *)key->data) == 0) - goto einval; - break; - case R_NEXT: - if (F_ISSET(&t->bt_cursor, CURS_INIT)) { - nrec = t->bt_cursor.rcursor + 1; - break; - } - /* FALLTHROUGH */ - case R_FIRST: - nrec = 1; - break; - case R_PREV: - if (F_ISSET(&t->bt_cursor, CURS_INIT)) { - if ((nrec = t->bt_cursor.rcursor - 1) == 0) - return (RET_SPECIAL); - break; - } - /* FALLTHROUGH */ - case R_LAST: - if (!F_ISSET(t, R_EOF | R_INMEM) && - t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR) - return (RET_ERROR); - nrec = t->bt_nrecs; - break; - default: -einval: errno = EINVAL; - return (RET_ERROR); - } - - if (t->bt_nrecs == 0 || nrec > t->bt_nrecs) { - if (!F_ISSET(t, R_EOF | R_INMEM) && - (status = t->bt_irec(t, nrec)) != RET_SUCCESS) - return (status); - if (t->bt_nrecs == 0 || nrec > t->bt_nrecs) - return (RET_SPECIAL); - } - - if ((e = __rec_search(t, nrec - 1, SEARCH)) == NULL) - return (RET_ERROR); - - F_SET(&t->bt_cursor, CURS_INIT); - t->bt_cursor.rcursor = nrec; - - status = __rec_ret(t, e, nrec, key, data); - if (F_ISSET(t, B_DB_LOCK)) - mpool_put(t->bt_mp, e->page, 0); - else - t->bt_pinned = e->page; - return (status); -} diff --git a/main/db1-ast/recno/rec_utils.c b/main/db1-ast/recno/rec_utils.c deleted file mode 100644 index ddc309712..000000000 --- a/main/db1-ast/recno/rec_utils.c +++ /dev/null @@ -1,122 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)rec_utils.c 8.6 (Berkeley) 7/16/94"; -#endif /* LIBC_SCCS and not lint */ - -#include - -#include -#include -#include - -#include "../include/db.h" -#include "recno.h" - -/* - * __rec_ret -- - * Build return data. - * - * Parameters: - * t: tree - * e: key/data pair to be returned - * nrec: record number - * key: user's key structure - * data: user's data structure - * - * Returns: - * RET_SUCCESS, RET_ERROR. - */ -int -__rec_ret(t, e, nrec, key, data) - BTREE *t; - EPG *e; - recno_t nrec; - DBT *key, *data; -{ - RLEAF *rl; - void *p; - - if (key == NULL) - goto dataonly; - - /* We have to copy the key, it's not on the page. */ - if (sizeof(recno_t) > t->bt_rkey.size) { - p = (void *)(t->bt_rkey.data == NULL ? - malloc(sizeof(recno_t)) : - realloc(t->bt_rkey.data, sizeof(recno_t))); - if (p == NULL) - return (RET_ERROR); - t->bt_rkey.data = p; - t->bt_rkey.size = sizeof(recno_t); - } - memmove(t->bt_rkey.data, &nrec, sizeof(recno_t)); - key->size = sizeof(recno_t); - key->data = t->bt_rkey.data; - -dataonly: - if (data == NULL) - return (RET_SUCCESS); - - /* - * We must copy big keys/data to make them contiguous. Otherwise, - * leave the page pinned and don't copy unless the user specified - * concurrent access. - */ - rl = GETRLEAF(e->page, e->index); - if (rl->flags & P_BIGDATA) { - if (__ovfl_get(t, rl->bytes, - &data->size, &t->bt_rdata.data, &t->bt_rdata.size)) - return (RET_ERROR); - data->data = t->bt_rdata.data; - } else if (F_ISSET(t, B_DB_LOCK)) { - /* Use +1 in case the first record retrieved is 0 length. */ - if (rl->dsize + 1 > t->bt_rdata.size) { - p = (void *)(t->bt_rdata.data == NULL ? - malloc(rl->dsize + 1) : - realloc(t->bt_rdata.data, rl->dsize + 1)); - if (p == NULL) - return (RET_ERROR); - t->bt_rdata.data = p; - t->bt_rdata.size = rl->dsize + 1; - } - memmove(t->bt_rdata.data, rl->bytes, rl->dsize); - data->size = rl->dsize; - data->data = t->bt_rdata.data; - } else { - data->size = rl->dsize; - data->data = rl->bytes; - } - return (RET_SUCCESS); -} diff --git a/main/db1-ast/recno/recno.h b/main/db1-ast/recno/recno.h deleted file mode 100644 index bec772c2f..000000000 --- a/main/db1-ast/recno/recno.h +++ /dev/null @@ -1,39 +0,0 @@ -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)recno.h 8.1 (Berkeley) 6/4/93 - */ - -enum SRCHOP { SDELETE, SINSERT, SEARCH}; /* Rec_search operation. */ - -#include "../btree/btree.h" -#include "extern.h" diff --git a/tests/test_db.c b/tests/test_db.c index 105a6ab1e..95532c780 100644 --- a/tests/test_db.c +++ b/tests/test_db.c @@ -205,10 +205,37 @@ AST_TEST_DEFINE(gettree_deltree) return res; } +AST_TEST_DEFINE(perftest) +{ + int res = AST_TEST_PASS; + size_t x; + char buf[10]; + + switch (cmd) { + case TEST_INIT: + info->name = "perftest"; + info->category = "/main/astdb/"; + info->summary = "astdb performance unit test"; + info->description = + "Measure astdb performance"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + for (x = 0; x < 100000; x++) { + sprintf(buf, "%zu", x); + ast_db_put("astdbtest", buf, buf); + } + ast_db_deltree("astdbtest", NULL); + + return res; +} static int unload_module(void) { AST_TEST_UNREGISTER(put_get_del); AST_TEST_UNREGISTER(gettree_deltree); + AST_TEST_UNREGISTER(perftest); return 0; } @@ -216,6 +243,7 @@ static int load_module(void) { AST_TEST_REGISTER(put_get_del); AST_TEST_REGISTER(gettree_deltree); + AST_TEST_REGISTER(perftest); return AST_MODULE_LOAD_SUCCESS; } diff --git a/utils/Makefile b/utils/Makefile index 1981fb2e2..d80a488d9 100644 --- a/utils/Makefile +++ b/utils/Makefile @@ -89,6 +89,8 @@ clean: rm -f md5.c strcompat.c ast_expr2.c ast_expr2.h ast_expr2f.c pbx_ael.c pval.c hashtab.c lock.c rm -f aelparse.c aelbison.c conf2ael rm -f utils.c strings.c threadstorage.c sha1.c astobj2.c hashtest2 hashtest refcounter + rm -f db1-ast/.*.d + @$(MAKE) -C db1-ast clean md5.c: $(ASTTOPDIR)/main/md5.c $(ECHO_PREFIX) echo " [CP] $(subst $(ASTTOPDIR)/,,$<) -> $@" @@ -206,6 +208,14 @@ muted: muted.o muted: LIBS+=$(AUDIO_LIBS) muted: _ASTCFLAGS:=$(filter-out -Werror,$(_ASTCFLAGS)) +CHECK_SUBDIR: # do nothing, just make sure that we recurse in the subdir/ +db1-ast/libdb1.a: CHECK_SUBDIR + _ASTCFLAGS="$(_ASTCFLAGS) -Wno-strict-aliasing" ASTCFLAGS="$(ASTCFLAGS)" $(MAKE) -C db1-ast libdb1.a + +astdb2sqlite3: LIBS+=$(SQLITE3_LIB) +astdb2sqlite3: _ASTCFLAGS+=$(SQLITE3_INCLUDE) +astdb2sqlite3: db1-ast/libdb1.a + ifneq ($(wildcard .*.d),) include .*.d endif diff --git a/utils/astdb2sqlite3.c b/utils/astdb2sqlite3.c new file mode 100644 index 000000000..254141744 --- /dev/null +++ b/utils/astdb2sqlite3.c @@ -0,0 +1,231 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 1999 - 2005, Digium, Inc. + * + * Mark Spencer + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! \file + * + * \brief Berekeley DB to SQLite3 converter + * + * \author Terry Wilson + */ + +#include "asterisk.h" + +//ASTERISK_FILE_VERSION(__FILE__, "$Revision$") + +#include +#include +#include +#include +#include +#include /* OS X doesn't have the basename function in strings.h */ + +#include "db1-ast/include/db.h" + +#define MAX_DB_FIELD 256 +#define MIN(a,b) \ +({ typeof (a) _a = (a); \ + typeof (b) _b = (b); \ + a < _b ? _a : _b; }) + +static sqlite3 *astdb; + +#define DEFINE_SQL_STATEMENT(stmt,sql) static sqlite3_stmt *stmt; \ + const char stmt##_sql[] = sql; + +DEFINE_SQL_STATEMENT(put_stmt, "INSERT OR REPLACE INTO astdb (key, value) VALUES (?, ?)") +DEFINE_SQL_STATEMENT(create_astdb_stmt, "CREATE TABLE IF NOT EXISTS astdb(key VARCHAR(256), value VARCHAR(256), PRIMARY KEY(key))") + +static int db_execute_transaction_sql(const char *sql) +{ + char *errmsg = NULL; + int res =0; + + sqlite3_exec(astdb, sql, NULL, NULL, &errmsg); + if (errmsg) { + fprintf(stderr, "Error executing SQL: %s\n", errmsg); + sqlite3_free(errmsg); + res = -1; + } + + return res; +} + +static int ast_db_begin_transaction(void) +{ + return db_execute_transaction_sql("BEGIN TRANSACTION"); +} + +static int ast_db_commit_transaction(void) +{ + return db_execute_transaction_sql("COMMIT"); +} + +static int ast_db_rollback_transaction(void) +{ + return db_execute_transaction_sql("ROLLBACK"); +} + +static int db_put_raw(const char *key, size_t keylen, const char *value, size_t valuelen) +{ + int res = 0; + + if (sqlite3_bind_text(put_stmt, 1, key, keylen, SQLITE_STATIC) != SQLITE_OK) { + fprintf(stderr, "Couldn't bind key to stmt: %s\n", sqlite3_errmsg(astdb)); + res = -1; + } else if (sqlite3_bind_text(put_stmt, 2, value, valuelen, SQLITE_STATIC) != SQLITE_OK) { + fprintf(stderr, "Couldn't bind value to stmt: %s\n", sqlite3_errmsg(astdb)); + res = -1; + } else if (sqlite3_step(put_stmt) != SQLITE_DONE) { + fprintf(stderr, "Couldn't execute statment: %s\n", sqlite3_errmsg(astdb)); + res = -1; + } + sqlite3_reset(put_stmt); + + return res; +} + +static int convert_bdb_to_sqlite3(const char *bdb_dbname) +{ + DB *bdb; + DBT key = { 0, }, value = { 0, }, last_key = { 0, }; + int res, last = 0; + char last_key_s[MAX_DB_FIELD]; + + if (!(bdb = dbopen(bdb_dbname, O_RDONLY, AST_FILE_MODE, DB_BTREE, NULL))) { + fprintf(stderr, "Unable to open Asterisk database '%s'\n", bdb_dbname); + return -1; + } + + if (bdb->seq(bdb, &last_key, &value, R_LAST)) { + /* Empty database */ + return 0; + } + + memcpy(last_key_s, last_key.data, MIN(last_key.size - 1, sizeof(last_key_s))); + last_key_s[last_key.size - 1] = '\0'; + for (res = bdb->seq(bdb, &key, &value, R_FIRST); + !res; res = bdb->seq(bdb, &key, &value, R_NEXT)) { + last = !strcmp(key.data, last_key_s); + db_put_raw((const char *) key.data, key.size - 1, (const char *) value.data, value.size - 1); + if (last) { + break; + } + } + + bdb->close(bdb); + + return 0; +} + +static int init_stmt(sqlite3_stmt **stmt, const char *sql, size_t len) +{ + if (sqlite3_prepare_v2(astdb, sql, len, stmt, NULL) != SQLITE_OK) { + fprintf(stderr, "Couldn't prepare statement '%s': %s\n", sql, sqlite3_errmsg(astdb)); + return -1; + } + + return 0; +} + +static int db_create_astdb(void) +{ + if (init_stmt(&create_astdb_stmt, create_astdb_stmt_sql, sizeof(create_astdb_stmt_sql))) { + return -1; + } + + ast_db_begin_transaction(); + if (sqlite3_step(create_astdb_stmt) != SQLITE_DONE) { + fprintf(stderr, "Couldn't create astdb table: %s\n", sqlite3_errmsg(astdb)); + ast_db_rollback_transaction(); + sqlite3_reset(create_astdb_stmt); + return -1; + } + + ast_db_commit_transaction(); + sqlite3_reset(create_astdb_stmt); + + return 0; +} + +static int init_statements(void) +{ + /* Don't initialize create_astdb_statment here as the astdb table needs to exist + * brefore these statments can be initialized */ + return init_stmt(&put_stmt, put_stmt_sql, sizeof(put_stmt_sql)); +} + +static int db_open(const char *dbname) +{ + if (sqlite3_open_v2(dbname, &astdb, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_NOMUTEX, NULL) != SQLITE_OK) { + fprintf(stderr, "Unable to open Asterisk database '%s': %s\n", dbname, sqlite3_errmsg(astdb)); + sqlite3_close(astdb); + return -1; + } + + return 0; +} + +static int sql_db_init(const char *dbname) +{ + if (db_open(dbname) || db_create_astdb() || init_statements()) { + return -1; + } + + return 0; +} + +int main(int argc, char *argv[]) +{ + char *dbname; + struct stat dont_care; + + if (argc != 2) { + fprintf(stderr, "%s takes the path of astdb as its only argument\n", basename(argv[0])); + exit(-1); + } + + if (stat(argv[1], &dont_care)) { + fprintf(stderr, "Unable to open %s: %s\n", argv[1], strerror(errno)); + exit(-1); + } + + if (!(dbname = alloca(strlen(argv[1]) + sizeof(".sqlite3")))) { + exit(-1); + } + + strcpy(dbname, argv[1]); + strcat(dbname, ".sqlite3"); + + if (!stat(dbname, &dont_care)) { + fprintf(stderr, "%s already exists!\n", dbname); + exit(-1); + } + + if (sql_db_init(dbname)) { + exit(-1); + } + + if (convert_bdb_to_sqlite3(argv[1])) { + fprintf(stderr, "Database conversion failed!\n"); + exit(-1); + sqlite3_close(astdb); + } + + sqlite3_close(astdb); + return 0; +} diff --git a/utils/db1-ast/Makefile b/utils/db1-ast/Makefile new file mode 100644 index 000000000..a0f12e1c4 --- /dev/null +++ b/utils/db1-ast/Makefile @@ -0,0 +1,71 @@ +# @(#)Makefile 8.9 (Berkeley) 7/14/94 + +LIBDB= libdb1.a +ARCH=$(shell uname -m) +ifeq ($(ARCH),alpha) +SOVER=2.1 +else +SOVER=2 +endif + +ifeq ($(OSARCH),Darwin) + OSARCH_DEFINE+=-D__Darwin__ +endif + +LIBDBSO=libdb.so.$(SOVER) +PROG= db_dump185 +OBJ1= hash/hash.o hash/hash_bigkey.o hash/hash_buf.o hash/hash_func.o hash/hash_log2.o hash/hash_page.o \ + hash/ndbm.o +OBJ2= btree/bt_close.o btree/bt_conv.o btree/bt_debug.o btree/bt_delete.o btree/bt_get.o btree/bt_open.o \ + btree/bt_overflow.o btree/bt_page.o btree/bt_put.o btree/bt_search.o btree/bt_seq.o btree/bt_split.o \ + btree/bt_utils.o +OBJ3= db/db.o +OBJ4= mpool/mpool.o +OBJ5= recno/rec_close.o recno/rec_delete.o recno/rec_get.o recno/rec_open.o recno/rec_put.o recno/rec_search.o \ + recno/rec_seq.o recno/rec_utils.o +MISC= +OBJS= $(OBJ1) $(OBJ2) $(OBJ3) $(OBJ4) $(OBJ5) $(MISC) +SHOBJS= $(patsubst %.o,%.os,$(OBJS)) + +include $(ASTTOPDIR)/Makefile.rules + +all: $(LIBDB) #$(LIBDBSO) $(PROG) + +$(LIBDB): $(OBJS) + $(ECHO_PREFIX) echo " [AR] $^ -> $@" + $(CMD_PREFIX) $(AR) cr $@ $^ + $(CMD_PREFIX) $(RANLIB) $@ + +$(LIBDBSO): $(SHOBJS) + $(CC) -Wl,-O1 -Wl,--version-script=libdb.map -Wl,-soname=$(LIBDBSO) -shared -o $@ $^ + ln -sf $@ libdb.so + +$(PROG): db_dump185.o $(LIBDBSO) + $(CC) -o $@ db_dump185.o -L. -ldb + +clean-depend: + +clean: + rm -f $(LIBDB) $(LIBDBSO) $(OBJS) $(SHOBJS) */*.s */*.i + +_ASTCFLAGS:=-Wall -D__DBINTERFACE_PRIVATE -I. -I.. -Iinclude -Ihash -Ibtree -Irecno $(_ASTCFLAGS) + +OSTYPE=$(shell uname -s) +ifeq ($(OSTYPE),SunOS) +_ASTCFLAGS+=-I../../include -I../../include/solaris-compat -DSOLARIS +endif + +db_dump185.o: db_dump185.c + $(CL) -o $@ $< +x%.o: hash/%.c + $(CL) -Ihash $(OSARCH_DEFINE) -o $@ $< +%.os: hash/%.c + $(CL) -Ihash -fPIC -o $@ $< +x%.o: btree/%.c + $(CL) -Ibtree -o $@ $< +%.os: btree/%.c + $(CL) -Ibtree -fPIC -o $@ $< +x%.o: recno/%.c + $(CL) -Irecno -o $@ $< +%.os: recno/%.c + $(CL) -Irecno -fPIC -o $@ $< diff --git a/utils/db1-ast/btree/bt_close.c b/utils/db1-ast/btree/bt_close.c new file mode 100644 index 000000000..67a6e5340 --- /dev/null +++ b/utils/db1-ast/btree/bt_close.c @@ -0,0 +1,182 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Mike Olson. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)bt_close.c 8.7 (Berkeley) 8/17/94"; +#endif /* LIBC_SCCS and not lint */ + +#include + +#include +#include +#include +#include +#include + +#include "../include/db.h" +#include "btree.h" + +static int bt_meta __P((BTREE *)); + +/* + * BT_CLOSE -- Close a btree. + * + * Parameters: + * dbp: pointer to access method + * + * Returns: + * RET_ERROR, RET_SUCCESS + */ +int +__bt_close(dbp) + DB *dbp; +{ + BTREE *t; + int fd; + + t = dbp->internal; + + /* Toss any page pinned across calls. */ + if (t->bt_pinned != NULL) { + mpool_put(t->bt_mp, t->bt_pinned, 0); + t->bt_pinned = NULL; + } + + /* Sync the tree. */ + if (__bt_sync(dbp, 0) == RET_ERROR) + return (RET_ERROR); + + /* Close the memory pool. */ + if (mpool_close(t->bt_mp) == RET_ERROR) + return (RET_ERROR); + + /* Free random memory. */ + if (t->bt_cursor.key.data != NULL) { + free(t->bt_cursor.key.data); + t->bt_cursor.key.size = 0; + t->bt_cursor.key.data = NULL; + } + if (t->bt_rkey.data) { + free(t->bt_rkey.data); + t->bt_rkey.size = 0; + t->bt_rkey.data = NULL; + } + if (t->bt_rdata.data) { + free(t->bt_rdata.data); + t->bt_rdata.size = 0; + t->bt_rdata.data = NULL; + } + + fd = t->bt_fd; + free(t); + free(dbp); + return (close(fd) ? RET_ERROR : RET_SUCCESS); +} + +/* + * BT_SYNC -- sync the btree to disk. + * + * Parameters: + * dbp: pointer to access method + * + * Returns: + * RET_SUCCESS, RET_ERROR. + */ +int +__bt_sync(dbp, flags) + const DB *dbp; + u_int flags; +{ + BTREE *t; + int status; + + t = dbp->internal; + + /* Toss any page pinned across calls. */ + if (t->bt_pinned != NULL) { + mpool_put(t->bt_mp, t->bt_pinned, 0); + t->bt_pinned = NULL; + } + + /* Sync doesn't currently take any flags. */ + if (flags != 0) { + errno = EINVAL; + return (RET_ERROR); + } + + if (F_ISSET(t, B_INMEM | B_RDONLY) || !F_ISSET(t, B_MODIFIED)) + return (RET_SUCCESS); + + if (F_ISSET(t, B_METADIRTY) && bt_meta(t) == RET_ERROR) + return (RET_ERROR); + + if ((status = mpool_sync(t->bt_mp)) == RET_SUCCESS) + F_CLR(t, B_MODIFIED); + + return (status); +} + +/* + * BT_META -- write the tree meta data to disk. + * + * Parameters: + * t: tree + * + * Returns: + * RET_ERROR, RET_SUCCESS + */ +static int +bt_meta(t) + BTREE *t; +{ + BTMETA m; + void *p; + + if ((p = mpool_get(t->bt_mp, P_META, 0)) == NULL) + return (RET_ERROR); + + /* Fill in metadata. */ + m.magic = BTREEMAGIC; + m.version = BTREEVERSION; + m.psize = t->bt_psize; + m.free = t->bt_free; + m.nrecs = t->bt_nrecs; + m.flags = F_ISSET(t, SAVEMETA); + + memmove(p, &m, sizeof(BTMETA)); + mpool_put(t->bt_mp, p, MPOOL_DIRTY); + return (RET_SUCCESS); +} diff --git a/utils/db1-ast/btree/bt_conv.c b/utils/db1-ast/btree/bt_conv.c new file mode 100644 index 000000000..d2ebdc57b --- /dev/null +++ b/utils/db1-ast/btree/bt_conv.c @@ -0,0 +1,221 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Mike Olson. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)bt_conv.c 8.5 (Berkeley) 8/17/94"; +#endif /* LIBC_SCCS and not lint */ + +#include + +#include + +#include "../include/db.h" +#include "btree.h" + +static void mswap __P((PAGE *)); + +/* + * __BT_BPGIN, __BT_BPGOUT -- + * Convert host-specific number layout to/from the host-independent + * format stored on disk. + * + * Parameters: + * t: tree + * pg: page number + * h: page to convert + */ +void +__bt_pgin(t, pg, pp) + void *t; + pgno_t pg; + void *pp; +{ + PAGE *h; + indx_t i, top; + u_char flags; + char *p; + + if (!F_ISSET(((BTREE *)t), B_NEEDSWAP)) + return; + if (pg == P_META) { + mswap(pp); + return; + } + + h = pp; + M_32_SWAP(h->pgno); + M_32_SWAP(h->prevpg); + M_32_SWAP(h->nextpg); + M_32_SWAP(h->flags); + M_16_SWAP(h->lower); + M_16_SWAP(h->upper); + + top = NEXTINDEX(h); + if ((h->flags & P_TYPE) == P_BINTERNAL) + for (i = 0; i < top; i++) { + M_16_SWAP(h->linp[i]); + p = (char *)GETBINTERNAL(h, i); + P_32_SWAP(p); + p += sizeof(u_int32_t); + P_32_SWAP(p); + p += sizeof(pgno_t); + if (*(u_char *)p & P_BIGKEY) { + p += sizeof(u_char); + P_32_SWAP(p); + p += sizeof(pgno_t); + P_32_SWAP(p); + } + } + else if ((h->flags & P_TYPE) == P_BLEAF) + for (i = 0; i < top; i++) { + M_16_SWAP(h->linp[i]); + p = (char *)GETBLEAF(h, i); + P_32_SWAP(p); + p += sizeof(u_int32_t); + P_32_SWAP(p); + p += sizeof(u_int32_t); + flags = *(u_char *)p; + if (flags & (P_BIGKEY | P_BIGDATA)) { + p += sizeof(u_char); + if (flags & P_BIGKEY) { + P_32_SWAP(p); + p += sizeof(pgno_t); + P_32_SWAP(p); + } + if (flags & P_BIGDATA) { + p += sizeof(u_int32_t); + P_32_SWAP(p); + p += sizeof(pgno_t); + P_32_SWAP(p); + } + } + } +} + +void +__bt_pgout(t, pg, pp) + void *t; + pgno_t pg; + void *pp; +{ + PAGE *h; + indx_t i, top; + u_char flags; + char *p; + + if (!F_ISSET(((BTREE *)t), B_NEEDSWAP)) + return; + if (pg == P_META) { + mswap(pp); + return; + } + + h = pp; + top = NEXTINDEX(h); + if ((h->flags & P_TYPE) == P_BINTERNAL) + for (i = 0; i < top; i++) { + p = (char *)GETBINTERNAL(h, i); + P_32_SWAP(p); + p += sizeof(u_int32_t); + P_32_SWAP(p); + p += sizeof(pgno_t); + if (*(u_char *)p & P_BIGKEY) { + p += sizeof(u_char); + P_32_SWAP(p); + p += sizeof(pgno_t); + P_32_SWAP(p); + } + M_16_SWAP(h->linp[i]); + } + else if ((h->flags & P_TYPE) == P_BLEAF) + for (i = 0; i < top; i++) { + p = (char *)GETBLEAF(h, i); + P_32_SWAP(p); + p += sizeof(u_int32_t); + P_32_SWAP(p); + p += sizeof(u_int32_t); + flags = *(u_char *)p; + if (flags & (P_BIGKEY | P_BIGDATA)) { + p += sizeof(u_char); + if (flags & P_BIGKEY) { + P_32_SWAP(p); + p += sizeof(pgno_t); + P_32_SWAP(p); + } + if (flags & P_BIGDATA) { + p += sizeof(u_int32_t); + P_32_SWAP(p); + p += sizeof(pgno_t); + P_32_SWAP(p); + } + } + M_16_SWAP(h->linp[i]); + } + + M_32_SWAP(h->pgno); + M_32_SWAP(h->prevpg); + M_32_SWAP(h->nextpg); + M_32_SWAP(h->flags); + M_16_SWAP(h->lower); + M_16_SWAP(h->upper); +} + +/* + * MSWAP -- Actually swap the bytes on the meta page. + * + * Parameters: + * p: page to convert + */ +static void +mswap(pg) + PAGE *pg; +{ + char *p; + + p = (char *)pg; + P_32_SWAP(p); /* magic */ + p += sizeof(u_int32_t); + P_32_SWAP(p); /* version */ + p += sizeof(u_int32_t); + P_32_SWAP(p); /* psize */ + p += sizeof(u_int32_t); + P_32_SWAP(p); /* free */ + p += sizeof(u_int32_t); + P_32_SWAP(p); /* nrecs */ + p += sizeof(u_int32_t); + P_32_SWAP(p); /* flags */ + p += sizeof(u_int32_t); +} diff --git a/utils/db1-ast/btree/bt_debug.c b/utils/db1-ast/btree/bt_debug.c new file mode 100644 index 000000000..e035851a8 --- /dev/null +++ b/utils/db1-ast/btree/bt_debug.c @@ -0,0 +1,329 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Mike Olson. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)bt_debug.c 8.5 (Berkeley) 8/17/94"; +#endif /* LIBC_SCCS and not lint */ + +#ifdef DEBUG +#include + +#include +#include +#include + +#include "../include/db.h" +#include "btree.h" + +/* + * BT_DUMP -- Dump the tree + * + * Parameters: + * dbp: pointer to the DB + */ +void +__bt_dump(dbp) + DB *dbp; +{ + BTREE *t; + PAGE *h; + pgno_t i; + char *sep; + + t = dbp->internal; + (void)fprintf(stderr, "%s: pgsz %d", + F_ISSET(t, B_INMEM) ? "memory" : "disk", t->bt_psize); + if (F_ISSET(t, R_RECNO)) + (void)fprintf(stderr, " keys %lu", t->bt_nrecs); +#undef X +#define X(flag, name) \ + if (F_ISSET(t, flag)) { \ + (void)fprintf(stderr, "%s%s", sep, name); \ + sep = ", "; \ + } + if (t->flags != 0) { + sep = " flags ("; + X(R_FIXLEN, "FIXLEN"); + X(B_INMEM, "INMEM"); + X(B_NODUPS, "NODUPS"); + X(B_RDONLY, "RDONLY"); + X(R_RECNO, "RECNO"); + X(B_METADIRTY,"METADIRTY"); + (void)fprintf(stderr, ")\n"); + } +#undef X + + for (i = P_ROOT; (h = mpool_get(t->bt_mp, i, 0)) != NULL; ++i) { + __bt_dpage(h); + (void)mpool_put(t->bt_mp, h, 0); + } +} + +/* + * BT_DMPAGE -- Dump the meta page + * + * Parameters: + * h: pointer to the PAGE + */ +void +__bt_dmpage(h) + PAGE *h; +{ + BTMETA *m; + char *sep; + + m = (BTMETA *)h; + (void)fprintf(stderr, "magic %lx\n", m->magic); + (void)fprintf(stderr, "version %lu\n", m->version); + (void)fprintf(stderr, "psize %lu\n", m->psize); + (void)fprintf(stderr, "free %lu\n", m->free); + (void)fprintf(stderr, "nrecs %lu\n", m->nrecs); + (void)fprintf(stderr, "flags %lu", m->flags); +#undef X +#define X(flag, name) \ + if (m->flags & flag) { \ + (void)fprintf(stderr, "%s%s", sep, name); \ + sep = ", "; \ + } + if (m->flags) { + sep = " ("; + X(B_NODUPS, "NODUPS"); + X(R_RECNO, "RECNO"); + (void)fprintf(stderr, ")"); + } +} + +/* + * BT_DNPAGE -- Dump the page + * + * Parameters: + * n: page number to dump. + */ +void +__bt_dnpage(dbp, pgno) + DB *dbp; + pgno_t pgno; +{ + BTREE *t; + PAGE *h; + + t = dbp->internal; + if ((h = mpool_get(t->bt_mp, pgno, 0)) != NULL) { + __bt_dpage(h); + (void)mpool_put(t->bt_mp, h, 0); + } +} + +/* + * BT_DPAGE -- Dump the page + * + * Parameters: + * h: pointer to the PAGE + */ +void +__bt_dpage(h) + PAGE *h; +{ + BINTERNAL *bi; + BLEAF *bl; + RINTERNAL *ri; + RLEAF *rl; + indx_t cur, top; + char *sep; + + (void)fprintf(stderr, " page %d: (", h->pgno); +#undef X +#define X(flag, name) \ + if (h->flags & flag) { \ + (void)fprintf(stderr, "%s%s", sep, name); \ + sep = ", "; \ + } + sep = ""; + X(P_BINTERNAL, "BINTERNAL") /* types */ + X(P_BLEAF, "BLEAF") + X(P_RINTERNAL, "RINTERNAL") /* types */ + X(P_RLEAF, "RLEAF") + X(P_OVERFLOW, "OVERFLOW") + X(P_PRESERVE, "PRESERVE"); + (void)fprintf(stderr, ")\n"); +#undef X + + (void)fprintf(stderr, "\tprev %2d next %2d", h->prevpg, h->nextpg); + if (h->flags & P_OVERFLOW) + return; + + top = NEXTINDEX(h); + (void)fprintf(stderr, " lower %3d upper %3d nextind %d\n", + h->lower, h->upper, top); + for (cur = 0; cur < top; cur++) { + (void)fprintf(stderr, "\t[%03d] %4d ", cur, h->linp[cur]); + switch (h->flags & P_TYPE) { + case P_BINTERNAL: + bi = GETBINTERNAL(h, cur); + (void)fprintf(stderr, + "size %03d pgno %03d", bi->ksize, bi->pgno); + if (bi->flags & P_BIGKEY) + (void)fprintf(stderr, " (indirect)"); + else if (bi->ksize) + (void)fprintf(stderr, + " {%.*s}", (int)bi->ksize, bi->bytes); + break; + case P_RINTERNAL: + ri = GETRINTERNAL(h, cur); + (void)fprintf(stderr, "entries %03d pgno %03d", + ri->nrecs, ri->pgno); + break; + case P_BLEAF: + bl = GETBLEAF(h, cur); + if (bl->flags & P_BIGKEY) + (void)fprintf(stderr, + "big key page %lu size %u/", + *(pgno_t *)bl->bytes, + *(u_int32_t *)(bl->bytes + sizeof(pgno_t))); + else if (bl->ksize) + (void)fprintf(stderr, "%s/", bl->bytes); + if (bl->flags & P_BIGDATA) + (void)fprintf(stderr, + "big data page %lu size %u", + *(pgno_t *)(bl->bytes + bl->ksize), + *(u_int32_t *)(bl->bytes + bl->ksize + + sizeof(pgno_t))); + else if (bl->dsize) + (void)fprintf(stderr, "%.*s", + (int)bl->dsize, bl->bytes + bl->ksize); + break; + case P_RLEAF: + rl = GETRLEAF(h, cur); + if (rl->flags & P_BIGDATA) + (void)fprintf(stderr, + "big data page %lu size %u", + *(pgno_t *)rl->bytes, + *(u_int32_t *)(rl->bytes + sizeof(pgno_t))); + else if (rl->dsize) + (void)fprintf(stderr, + "%.*s", (int)rl->dsize, rl->bytes); + break; + } + (void)fprintf(stderr, "\n"); + } +} +#endif + +#ifdef STATISTICS +/* + * BT_STAT -- Gather/print the tree statistics + * + * Parameters: + * dbp: pointer to the DB + */ +void +__bt_stat(dbp) + DB *dbp; +{ + extern u_long bt_cache_hit, bt_cache_miss, bt_pfxsaved, bt_rootsplit; + extern u_long bt_sortsplit, bt_split; + BTREE *t; + PAGE *h; + pgno_t i, pcont, pinternal, pleaf; + u_long ifree, lfree, nkeys; + int levels; + + t = dbp->internal; + pcont = pinternal = pleaf = 0; + nkeys = ifree = lfree = 0; + for (i = P_ROOT; (h = mpool_get(t->bt_mp, i, 0)) != NULL; ++i) { + switch (h->flags & P_TYPE) { + case P_BINTERNAL: + case P_RINTERNAL: + ++pinternal; + ifree += h->upper - h->lower; + break; + case P_BLEAF: + case P_RLEAF: + ++pleaf; + lfree += h->upper - h->lower; + nkeys += NEXTINDEX(h); + break; + case P_OVERFLOW: + ++pcont; + break; + } + (void)mpool_put(t->bt_mp, h, 0); + } + + /* Count the levels of the tree. */ + for (i = P_ROOT, levels = 0 ;; ++levels) { + h = mpool_get(t->bt_mp, i, 0); + if (h->flags & (P_BLEAF|P_RLEAF)) { + if (levels == 0) + levels = 1; + (void)mpool_put(t->bt_mp, h, 0); + break; + } + i = F_ISSET(t, R_RECNO) ? + GETRINTERNAL(h, 0)->pgno : + GETBINTERNAL(h, 0)->pgno; + (void)mpool_put(t->bt_mp, h, 0); + } + + (void)fprintf(stderr, "%d level%s with %ld keys", + levels, levels == 1 ? "" : "s", nkeys); + if (F_ISSET(t, R_RECNO)) + (void)fprintf(stderr, " (%ld header count)", t->bt_nrecs); + (void)fprintf(stderr, + "\n%lu pages (leaf %ld, internal %ld, overflow %ld)\n", + pinternal + pleaf + pcont, pleaf, pinternal, pcont); + (void)fprintf(stderr, "%ld cache hits, %ld cache misses\n", + bt_cache_hit, bt_cache_miss); + (void)fprintf(stderr, "%ld splits (%ld root splits, %ld sort splits)\n", + bt_split, bt_rootsplit, bt_sortsplit); + pleaf *= t->bt_psize - BTDATAOFF; + if (pleaf) + (void)fprintf(stderr, + "%.0f%% leaf fill (%ld bytes used, %ld bytes free)\n", + ((double)(pleaf - lfree) / pleaf) * 100, + pleaf - lfree, lfree); + pinternal *= t->bt_psize - BTDATAOFF; + if (pinternal) + (void)fprintf(stderr, + "%.0f%% internal fill (%ld bytes used, %ld bytes free\n", + ((double)(pinternal - ifree) / pinternal) * 100, + pinternal - ifree, ifree); + if (bt_pfxsaved) + (void)fprintf(stderr, "prefix checking removed %lu bytes.\n", + bt_pfxsaved); +} +#endif diff --git a/utils/db1-ast/btree/bt_delete.c b/utils/db1-ast/btree/bt_delete.c new file mode 100644 index 000000000..6e3883db9 --- /dev/null +++ b/utils/db1-ast/btree/bt_delete.c @@ -0,0 +1,657 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Mike Olson. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)bt_delete.c 8.13 (Berkeley) 7/28/94"; +#endif /* LIBC_SCCS and not lint */ + +#include + +#include +#include +#include + +#include "../include/db.h" +#include "btree.h" + +static int __bt_bdelete __P((BTREE *, const DBT *)); +static int __bt_curdel __P((BTREE *, const DBT *, PAGE *, u_int)); +static int __bt_pdelete __P((BTREE *, PAGE *)); +static int __bt_relink __P((BTREE *, PAGE *)); +static int __bt_stkacq __P((BTREE *, PAGE **, CURSOR *)); + +/* + * __bt_delete + * Delete the item(s) referenced by a key. + * + * Return RET_SPECIAL if the key is not found. + */ +int +__bt_delete(dbp, key, flags) + const DB *dbp; + const DBT *key; + u_int flags; +{ + BTREE *t; + CURSOR *c; + PAGE *h; + int status; + + t = dbp->internal; + + /* Toss any page pinned across calls. */ + if (t->bt_pinned != NULL) { + mpool_put(t->bt_mp, t->bt_pinned, 0); + t->bt_pinned = NULL; + } + + /* Check for change to a read-only tree. */ + if (F_ISSET(t, B_RDONLY)) { + errno = EPERM; + return (RET_ERROR); + } + + switch (flags) { + case 0: + status = __bt_bdelete(t, key); + break; + case R_CURSOR: + /* + * If flags is R_CURSOR, delete the cursor. Must already + * have started a scan and not have already deleted it. + */ + c = &t->bt_cursor; + if (F_ISSET(c, CURS_INIT)) { + if (F_ISSET(c, CURS_ACQUIRE | CURS_AFTER | CURS_BEFORE)) + return (RET_SPECIAL); + if ((h = mpool_get(t->bt_mp, c->pg.pgno, 0)) == NULL) + return (RET_ERROR); + + /* + * If the page is about to be emptied, we'll need to + * delete it, which means we have to acquire a stack. + */ + if (NEXTINDEX(h) == 1) + if (__bt_stkacq(t, &h, &t->bt_cursor)) + return (RET_ERROR); + + status = __bt_dleaf(t, NULL, h, c->pg.index); + + if (NEXTINDEX(h) == 0 && status == RET_SUCCESS) { + if (__bt_pdelete(t, h)) + return (RET_ERROR); + } else + mpool_put(t->bt_mp, + h, status == RET_SUCCESS ? MPOOL_DIRTY : 0); + break; + } + /* FALLTHROUGH */ + default: + errno = EINVAL; + return (RET_ERROR); + } + if (status == RET_SUCCESS) + F_SET(t, B_MODIFIED); + return (status); +} + +/* + * __bt_stkacq -- + * Acquire a stack so we can delete a cursor entry. + * + * Parameters: + * t: tree + * hp: pointer to current, pinned PAGE pointer + * c: pointer to the cursor + * + * Returns: + * 0 on success, 1 on failure + */ +static int +__bt_stkacq(t, hp, c) + BTREE *t; + PAGE **hp; + CURSOR *c; +{ + BINTERNAL *bi; + EPG *e; + EPGNO *parent; + PAGE *h; + indx_t idx = 0; + pgno_t pgno; + recno_t nextpg, prevpg; + int exact, level; + + /* + * Find the first occurrence of the key in the tree. Toss the + * currently locked page so we don't hit an already-locked page. + */ + h = *hp; + mpool_put(t->bt_mp, h, 0); + if ((e = __bt_search(t, &c->key, &exact)) == NULL) + return (1); + h = e->page; + + /* See if we got it in one shot. */ + if (h->pgno == c->pg.pgno) + goto ret; + + /* + * Move right, looking for the page. At each move we have to move + * up the stack until we don't have to move to the next page. If + * we have to change pages at an internal level, we have to fix the + * stack back up. + */ + while (h->pgno != c->pg.pgno) { + if ((nextpg = h->nextpg) == P_INVALID) + break; + mpool_put(t->bt_mp, h, 0); + + /* Move up the stack. */ + for (level = 0; (parent = BT_POP(t)) != NULL; ++level) { + /* Get the parent page. */ + if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL) + return (1); + + /* Move to the next index. */ + if (parent->index != NEXTINDEX(h) - 1) { + idx = parent->index + 1; + BT_PUSH(t, h->pgno, idx); + break; + } + mpool_put(t->bt_mp, h, 0); + } + + /* Restore the stack. */ + while (level--) { + /* Push the next level down onto the stack. */ + bi = GETBINTERNAL(h, idx); + pgno = bi->pgno; + BT_PUSH(t, pgno, 0); + + /* Lose the currently pinned page. */ + mpool_put(t->bt_mp, h, 0); + + /* Get the next level down. */ + if ((h = mpool_get(t->bt_mp, pgno, 0)) == NULL) + return (1); + idx = 0; + } + mpool_put(t->bt_mp, h, 0); + if ((h = mpool_get(t->bt_mp, nextpg, 0)) == NULL) + return (1); + } + + if (h->pgno == c->pg.pgno) + goto ret; + + /* Reacquire the original stack. */ + mpool_put(t->bt_mp, h, 0); + if ((e = __bt_search(t, &c->key, &exact)) == NULL) + return (1); + h = e->page; + + /* + * Move left, looking for the page. At each move we have to move + * up the stack until we don't have to change pages to move to the + * next page. If we have to change pages at an internal level, we + * have to fix the stack back up. + */ + while (h->pgno != c->pg.pgno) { + if ((prevpg = h->prevpg) == P_INVALID) + break; + mpool_put(t->bt_mp, h, 0); + + /* Move up the stack. */ + for (level = 0; (parent = BT_POP(t)) != NULL; ++level) { + /* Get the parent page. */ + if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL) + return (1); + + /* Move to the next index. */ + if (parent->index != 0) { + idx = parent->index - 1; + BT_PUSH(t, h->pgno, idx); + break; + } + mpool_put(t->bt_mp, h, 0); + } + + /* Restore the stack. */ + while (level--) { + /* Push the next level down onto the stack. */ + bi = GETBINTERNAL(h, idx); + pgno = bi->pgno; + + /* Lose the currently pinned page. */ + mpool_put(t->bt_mp, h, 0); + + /* Get the next level down. */ + if ((h = mpool_get(t->bt_mp, pgno, 0)) == NULL) + return (1); + + idx = NEXTINDEX(h) - 1; + BT_PUSH(t, pgno, idx); + } + mpool_put(t->bt_mp, h, 0); + if ((h = mpool_get(t->bt_mp, prevpg, 0)) == NULL) + return (1); + } + + +ret: mpool_put(t->bt_mp, h, 0); + return ((*hp = mpool_get(t->bt_mp, c->pg.pgno, 0)) == NULL); +} + +/* + * __bt_bdelete -- + * Delete all key/data pairs matching the specified key. + * + * Parameters: + * t: tree + * key: key to delete + * + * Returns: + * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found. + */ +static int +__bt_bdelete(t, key) + BTREE *t; + const DBT *key; +{ + EPG *e; + PAGE *h; + int deleted, exact, redo; + + deleted = 0; + + /* Find any matching record; __bt_search pins the page. */ +loop: if ((e = __bt_search(t, key, &exact)) == NULL) + return (deleted ? RET_SUCCESS : RET_ERROR); + if (!exact) { + mpool_put(t->bt_mp, e->page, 0); + return (deleted ? RET_SUCCESS : RET_SPECIAL); + } + + /* + * Delete forward, then delete backward, from the found key. If + * there are duplicates and we reach either side of the page, do + * the key search again, so that we get them all. + */ + redo = 0; + h = e->page; + do { + if (__bt_dleaf(t, key, h, e->index)) { + mpool_put(t->bt_mp, h, 0); + return (RET_ERROR); + } + if (F_ISSET(t, B_NODUPS)) { + if (NEXTINDEX(h) == 0) { + if (__bt_pdelete(t, h)) + return (RET_ERROR); + } else + mpool_put(t->bt_mp, h, MPOOL_DIRTY); + return (RET_SUCCESS); + } + deleted = 1; + } while (e->index < NEXTINDEX(h) && __bt_cmp(t, key, e) == 0); + + /* Check for right-hand edge of the page. */ + if (e->index == NEXTINDEX(h)) + redo = 1; + + /* Delete from the key to the beginning of the page. */ + while (e->index-- > 0) { + if (__bt_cmp(t, key, e) != 0) + break; + if (__bt_dleaf(t, key, h, e->index) == RET_ERROR) { + mpool_put(t->bt_mp, h, 0); + return (RET_ERROR); + } + if (e->index == 0) + redo = 1; + } + + /* Check for an empty page. */ + if (NEXTINDEX(h) == 0) { + if (__bt_pdelete(t, h)) + return (RET_ERROR); + goto loop; + } + + /* Put the page. */ + mpool_put(t->bt_mp, h, MPOOL_DIRTY); + + if (redo) + goto loop; + return (RET_SUCCESS); +} + +/* + * __bt_pdelete -- + * Delete a single page from the tree. + * + * Parameters: + * t: tree + * h: leaf page + * + * Returns: + * RET_SUCCESS, RET_ERROR. + * + * Side-effects: + * mpool_put's the page + */ +static int +__bt_pdelete(t, h) + BTREE *t; + PAGE *h; +{ + BINTERNAL *bi; + PAGE *pg; + EPGNO *parent; + indx_t cnt, idx, *ip, offset; + u_int32_t nksize; + char *from; + + /* + * Walk the parent page stack -- a LIFO stack of the pages that were + * traversed when we searched for the page where the delete occurred. + * Each stack entry is a page number and a page index offset. The + * offset is for the page traversed on the search. We've just deleted + * a page, so we have to delete the key from the parent page. + * + * If the delete from the parent page makes it empty, this process may + * continue all the way up the tree. We stop if we reach the root page + * (which is never deleted, it's just not worth the effort) or if the + * delete does not empty the page. + */ + while ((parent = BT_POP(t)) != NULL) { + /* Get the parent page. */ + if ((pg = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL) + return (RET_ERROR); + + idx = parent->index; + bi = GETBINTERNAL(pg, idx); + + /* Free any overflow pages. */ + if (bi->flags & P_BIGKEY && + __ovfl_delete(t, bi->bytes) == RET_ERROR) { + mpool_put(t->bt_mp, pg, 0); + return (RET_ERROR); + } + + /* + * Free the parent if it has only the one key and it's not the + * root page. If it's the rootpage, turn it back into an empty + * leaf page. + */ + if (NEXTINDEX(pg) == 1) { + if (pg->pgno == P_ROOT) { + pg->lower = BTDATAOFF; + pg->upper = t->bt_psize; + pg->flags = P_BLEAF; + } else { + if (__bt_relink(t, pg) || __bt_free(t, pg)) + return (RET_ERROR); + continue; + } + } else { + /* Pack remaining key items at the end of the page. */ + nksize = NBINTERNAL(bi->ksize); + from = (char *)pg + pg->upper; + memmove(from + nksize, from, (char *)bi - from); + pg->upper += nksize; + + /* Adjust indices' offsets, shift the indices down. */ + offset = pg->linp[idx]; + for (cnt = idx, ip = &pg->linp[0]; cnt--; ++ip) + if (ip[0] < offset) + ip[0] += nksize; + for (cnt = NEXTINDEX(pg) - idx; --cnt; ++ip) + ip[0] = ip[1] < offset ? ip[1] + nksize : ip[1]; + pg->lower -= sizeof(indx_t); + } + + mpool_put(t->bt_mp, pg, MPOOL_DIRTY); + break; + } + + /* Free the leaf page, as long as it wasn't the root. */ + if (h->pgno == P_ROOT) { + mpool_put(t->bt_mp, h, MPOOL_DIRTY); + return (RET_SUCCESS); + } + return (__bt_relink(t, h) || __bt_free(t, h)); +} + +/* + * __bt_dleaf -- + * Delete a single record from a leaf page. + * + * Parameters: + * t: tree + * key: referenced key + * h: page + * index: index on page to delete + * + * Returns: + * RET_SUCCESS, RET_ERROR. + */ +int +__bt_dleaf(t, key, h, idx) + BTREE *t; + const DBT *key; + PAGE *h; + u_int idx; +{ + BLEAF *bl; + indx_t cnt, *ip, offset; + u_int32_t nbytes; + void *to; + char *from; + + /* If this record is referenced by the cursor, delete the cursor. */ + if (F_ISSET(&t->bt_cursor, CURS_INIT) && + !F_ISSET(&t->bt_cursor, CURS_ACQUIRE) && + t->bt_cursor.pg.pgno == h->pgno && t->bt_cursor.pg.index == idx && + __bt_curdel(t, key, h, idx)) + return (RET_ERROR); + + /* If the entry uses overflow pages, make them available for reuse. */ + to = bl = GETBLEAF(h, idx); + if (bl->flags & P_BIGKEY && __ovfl_delete(t, bl->bytes) == RET_ERROR) + return (RET_ERROR); + if (bl->flags & P_BIGDATA && + __ovfl_delete(t, bl->bytes + bl->ksize) == RET_ERROR) + return (RET_ERROR); + + /* Pack the remaining key/data items at the end of the page. */ + nbytes = NBLEAF(bl); + from = (char *)h + h->upper; + memmove(from + nbytes, from, (char *)to - from); + h->upper += nbytes; + + /* Adjust the indices' offsets, shift the indices down. */ + offset = h->linp[idx]; + for (cnt = idx, ip = &h->linp[0]; cnt--; ++ip) + if (ip[0] < offset) + ip[0] += nbytes; + for (cnt = NEXTINDEX(h) - idx; --cnt; ++ip) + ip[0] = ip[1] < offset ? ip[1] + nbytes : ip[1]; + h->lower -= sizeof(indx_t); + + /* If the cursor is on this page, adjust it as necessary. */ + if (F_ISSET(&t->bt_cursor, CURS_INIT) && + !F_ISSET(&t->bt_cursor, CURS_ACQUIRE) && + t->bt_cursor.pg.pgno == h->pgno && t->bt_cursor.pg.index > idx) + --t->bt_cursor.pg.index; + + return (RET_SUCCESS); +} + +/* + * __bt_curdel -- + * Delete the cursor. + * + * Parameters: + * t: tree + * key: referenced key (or NULL) + * h: page + * index: index on page to delete + * + * Returns: + * RET_SUCCESS, RET_ERROR. + */ +static int +__bt_curdel(t, key, h, idx) + BTREE *t; + const DBT *key; + PAGE *h; + u_int idx; +{ + CURSOR *c; + EPG e; + PAGE *pg; + int curcopy, status; + + /* + * If there are duplicates, move forward or backward to one. + * Otherwise, copy the key into the cursor area. + */ + c = &t->bt_cursor; + F_CLR(c, CURS_AFTER | CURS_BEFORE | CURS_ACQUIRE); + + curcopy = 0; + if (!F_ISSET(t, B_NODUPS)) { + /* + * We're going to have to do comparisons. If we weren't + * provided a copy of the key, i.e. the user is deleting + * the current cursor position, get one. + */ + if (key == NULL) { + e.page = h; + e.index = idx; + if ((status = __bt_ret(t, &e, + &c->key, &c->key, NULL, NULL, 1)) != RET_SUCCESS) + return (status); + curcopy = 1; + key = &c->key; + } + /* Check previous key, if not at the beginning of the page. */ + if (idx > 0) { + e.page = h; + e.index = idx - 1; + if (__bt_cmp(t, key, &e) == 0) { + F_SET(c, CURS_BEFORE); + goto dup2; + } + } + /* Check next key, if not at the end of the page. */ + if (idx < NEXTINDEX(h) - 1) { + e.page = h; + e.index = idx + 1; + if (__bt_cmp(t, key, &e) == 0) { + F_SET(c, CURS_AFTER); + goto dup2; + } + } + /* Check previous key if at the beginning of the page. */ + if (idx == 0 && h->prevpg != P_INVALID) { + if ((pg = mpool_get(t->bt_mp, h->prevpg, 0)) == NULL) + return (RET_ERROR); + e.page = pg; + e.index = NEXTINDEX(pg) - 1; + if (__bt_cmp(t, key, &e) == 0) { + F_SET(c, CURS_BEFORE); + goto dup1; + } + mpool_put(t->bt_mp, pg, 0); + } + /* Check next key if at the end of the page. */ + if (idx == NEXTINDEX(h) - 1 && h->nextpg != P_INVALID) { + if ((pg = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL) + return (RET_ERROR); + e.page = pg; + e.index = 0; + if (__bt_cmp(t, key, &e) == 0) { + F_SET(c, CURS_AFTER); +dup1: mpool_put(t->bt_mp, pg, 0); +dup2: c->pg.pgno = e.page->pgno; + c->pg.index = e.index; + return (RET_SUCCESS); + } + mpool_put(t->bt_mp, pg, 0); + } + } + e.page = h; + e.index = idx; + if (curcopy || (status = + __bt_ret(t, &e, &c->key, &c->key, NULL, NULL, 1)) == RET_SUCCESS) { + F_SET(c, CURS_ACQUIRE); + return (RET_SUCCESS); + } + return (status); +} + +/* + * __bt_relink -- + * Link around a deleted page. + * + * Parameters: + * t: tree + * h: page to be deleted + */ +static int +__bt_relink(t, h) + BTREE *t; + PAGE *h; +{ + PAGE *pg; + + if (h->nextpg != P_INVALID) { + if ((pg = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL) + return (RET_ERROR); + pg->prevpg = h->prevpg; + mpool_put(t->bt_mp, pg, MPOOL_DIRTY); + } + if (h->prevpg != P_INVALID) { + if ((pg = mpool_get(t->bt_mp, h->prevpg, 0)) == NULL) + return (RET_ERROR); + pg->nextpg = h->nextpg; + mpool_put(t->bt_mp, pg, MPOOL_DIRTY); + } + return (0); +} diff --git a/utils/db1-ast/btree/bt_get.c b/utils/db1-ast/btree/bt_get.c new file mode 100644 index 000000000..b5e18022c --- /dev/null +++ b/utils/db1-ast/btree/bt_get.c @@ -0,0 +1,105 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Mike Olson. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)bt_get.c 8.6 (Berkeley) 7/20/94"; +#endif /* LIBC_SCCS and not lint */ + +#include + +#include +#include +#include + +#include "../include/db.h" +#include "btree.h" + +/* + * __BT_GET -- Get a record from the btree. + * + * Parameters: + * dbp: pointer to access method + * key: key to find + * data: data to return + * flag: currently unused + * + * Returns: + * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found. + */ +int +__bt_get(dbp, key, data, flags) + const DB *dbp; + const DBT *key; + DBT *data; + u_int flags; +{ + BTREE *t; + EPG *e; + int exact, status; + + t = dbp->internal; + + /* Toss any page pinned across calls. */ + if (t->bt_pinned != NULL) { + mpool_put(t->bt_mp, t->bt_pinned, 0); + t->bt_pinned = NULL; + } + + /* Get currently doesn't take any flags. */ + if (flags) { + errno = EINVAL; + return (RET_ERROR); + } + + if ((e = __bt_search(t, key, &exact)) == NULL) + return (RET_ERROR); + if (!exact) { + mpool_put(t->bt_mp, e->page, 0); + return (RET_SPECIAL); + } + + status = __bt_ret(t, e, NULL, NULL, data, &t->bt_rdata, 0); + + /* + * If the user is doing concurrent access, we copied the + * key/data, toss the page. + */ + if (F_ISSET(t, B_DB_LOCK)) + mpool_put(t->bt_mp, e->page, 0); + else + t->bt_pinned = e->page; + return (status); +} diff --git a/utils/db1-ast/btree/bt_open.c b/utils/db1-ast/btree/bt_open.c new file mode 100644 index 000000000..5d40e4593 --- /dev/null +++ b/utils/db1-ast/btree/bt_open.c @@ -0,0 +1,458 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Mike Olson. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)bt_open.c 8.10 (Berkeley) 8/17/94"; +#endif /* LIBC_SCCS and not lint */ + +/* + * Implementation of btree access method for 4.4BSD. + * + * The design here was originally based on that of the btree access method + * used in the Postgres database system at UC Berkeley. This implementation + * is wholly independent of the Postgres code. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../include/db.h" +#include "btree.h" + +#ifdef DEBUG +#undef MINPSIZE +#define MINPSIZE 128 +#endif + +static int byteorder __P((void)); +static int nroot __P((BTREE *)); +static int tmp __P((void)); + +/* + * __BT_OPEN -- Open a btree. + * + * Creates and fills a DB struct, and calls the routine that actually + * opens the btree. + * + * Parameters: + * fname: filename (NULL for in-memory trees) + * flags: open flag bits + * mode: open permission bits + * b: BTREEINFO pointer + * + * Returns: + * NULL on failure, pointer to DB on success. + * + */ +DB * +__bt_open(fname, flags, mode, openinfo, dflags) + const char *fname; + int flags, mode, dflags; + const BTREEINFO *openinfo; +{ + struct stat sb; + BTMETA m; + BTREE *t; + BTREEINFO b; + DB *dbp; + pgno_t ncache; + ssize_t nr; + int machine_lorder; + + t = NULL; + + /* + * Intention is to make sure all of the user's selections are okay + * here and then use them without checking. Can't be complete, since + * we don't know the right page size, lorder or flags until the backing + * file is opened. Also, the file's page size can cause the cachesize + * to change. + */ + machine_lorder = byteorder(); + if (openinfo) { + b = *openinfo; + + /* Flags: R_DUP. */ + if (b.flags & ~(R_DUP)) + goto einval; + + /* + * Page size must be indx_t aligned and >= MINPSIZE. Default + * page size is set farther on, based on the underlying file + * transfer size. + */ + if (b.psize && + (b.psize < MINPSIZE || b.psize > MAX_PAGE_OFFSET + 1 || + b.psize & (sizeof(indx_t) - 1))) + goto einval; + + /* Minimum number of keys per page; absolute minimum is 2. */ + if (b.minkeypage) { + if (b.minkeypage < 2) + goto einval; + } else + b.minkeypage = DEFMINKEYPAGE; + + /* If no comparison, use default comparison and prefix. */ + if (b.compare == NULL) { + b.compare = __bt_defcmp; + if (b.prefix == NULL) + b.prefix = __bt_defpfx; + } + + if (b.lorder == 0) + b.lorder = machine_lorder; + } else { + b.compare = __bt_defcmp; + b.cachesize = 0; + b.flags = 0; + b.lorder = machine_lorder; + b.minkeypage = DEFMINKEYPAGE; + b.prefix = __bt_defpfx; + b.psize = 0; + } + + /* Check for the ubiquitous PDP-11. */ + if (b.lorder != BIG_ENDIAN && b.lorder != LITTLE_ENDIAN) + goto einval; + + /* Allocate and initialize DB and BTREE structures. */ + if ((t = (BTREE *)malloc(sizeof(BTREE))) == NULL) + goto err; + memset(t, 0, sizeof(BTREE)); + t->bt_fd = -1; /* Don't close unopened fd on error. */ + t->bt_lorder = b.lorder; + t->bt_order = NOT; + t->bt_cmp = b.compare; + t->bt_pfx = b.prefix; + t->bt_rfd = -1; + + if ((t->bt_dbp = dbp = (DB *)malloc(sizeof(DB))) == NULL) + goto err; + memset(t->bt_dbp, 0, sizeof(DB)); + if (t->bt_lorder != machine_lorder) + F_SET(t, B_NEEDSWAP); + + dbp->type = DB_BTREE; + dbp->internal = t; + dbp->close = __bt_close; + dbp->del = __bt_delete; + dbp->fd = __bt_fd; + dbp->get = __bt_get; + dbp->put = __bt_put; + dbp->seq = __bt_seq; + dbp->sync = __bt_sync; + + /* + * If no file name was supplied, this is an in-memory btree and we + * open a backing temporary file. Otherwise, it's a disk-based tree. + */ + if (fname) { + switch (flags & O_ACCMODE) { + case O_RDONLY: + F_SET(t, B_RDONLY); + break; + case O_RDWR: + break; + case O_WRONLY: + default: + goto einval; + } + + if ((t->bt_fd = open(fname, flags, mode)) < 0) + goto err; + + } else { + if ((flags & O_ACCMODE) != O_RDWR) + goto einval; + if ((t->bt_fd = tmp()) == -1) + goto err; + F_SET(t, B_INMEM); + } + + if (fcntl(t->bt_fd, F_SETFD, 1) == -1) + goto err; + + if (fstat(t->bt_fd, &sb)) + goto err; + if (sb.st_size) { + if ((nr = read(t->bt_fd, &m, sizeof(BTMETA))) < 0) + goto err; + if (nr != sizeof(BTMETA)) + goto eftype; + + /* + * Read in the meta-data. This can change the notion of what + * the lorder, page size and flags are, and, when the page size + * changes, the cachesize value can change too. If the user + * specified the wrong byte order for an existing database, we + * don't bother to return an error, we just clear the NEEDSWAP + * bit. + */ + if (m.magic == BTREEMAGIC) + F_CLR(t, B_NEEDSWAP); + else { + F_SET(t, B_NEEDSWAP); + M_32_SWAP(m.magic); + M_32_SWAP(m.version); + M_32_SWAP(m.psize); + M_32_SWAP(m.free); + M_32_SWAP(m.nrecs); + M_32_SWAP(m.flags); + } + if (m.magic != BTREEMAGIC || m.version != BTREEVERSION) + goto eftype; + if (m.psize < MINPSIZE || m.psize > MAX_PAGE_OFFSET + 1 || + m.psize & (sizeof(indx_t) - 1)) + goto eftype; + if (m.flags & ~SAVEMETA) + goto eftype; + b.psize = m.psize; + F_SET(t, m.flags); + t->bt_free = m.free; + t->bt_nrecs = m.nrecs; + } else { + /* + * Set the page size to the best value for I/O to this file. + * Don't overflow the page offset type. + */ + if (b.psize == 0) { +#ifdef _STATBUF_ST_BLKSIZE + b.psize = sb.st_blksize; +#endif + if (b.psize < MINPSIZE) + b.psize = MINPSIZE; + if (b.psize > MAX_PAGE_OFFSET + 1) + b.psize = MAX_PAGE_OFFSET + 1; + } + + /* Set flag if duplicates permitted. */ + if (!(b.flags & R_DUP)) + F_SET(t, B_NODUPS); + + t->bt_free = P_INVALID; + t->bt_nrecs = 0; + F_SET(t, B_METADIRTY); + } + + t->bt_psize = b.psize; + + /* Set the cache size; must be a multiple of the page size. */ + if (b.cachesize && b.cachesize & (b.psize - 1)) + b.cachesize += (~b.cachesize & (b.psize - 1)) + 1; + if (b.cachesize < b.psize * MINCACHE) + b.cachesize = b.psize * MINCACHE; + + /* Calculate number of pages to cache. */ + ncache = (b.cachesize + t->bt_psize - 1) / t->bt_psize; + + /* + * The btree data structure requires that at least two keys can fit on + * a page, but other than that there's no fixed requirement. The user + * specified a minimum number per page, and we translated that into the + * number of bytes a key/data pair can use before being placed on an + * overflow page. This calculation includes the page header, the size + * of the index referencing the leaf item and the size of the leaf item + * structure. Also, don't let the user specify a minkeypage such that + * a key/data pair won't fit even if both key and data are on overflow + * pages. + */ + t->bt_ovflsize = (t->bt_psize - BTDATAOFF) / b.minkeypage - + (sizeof(indx_t) + NBLEAFDBT(0, 0)); + if (t->bt_ovflsize < NBLEAFDBT(NOVFLSIZE, NOVFLSIZE) + sizeof(indx_t)) + t->bt_ovflsize = + NBLEAFDBT(NOVFLSIZE, NOVFLSIZE) + sizeof(indx_t); + + /* Initialize the buffer pool. */ + if ((t->bt_mp = + mpool_open(NULL, t->bt_fd, t->bt_psize, ncache)) == NULL) + goto err; + if (!F_ISSET(t, B_INMEM)) + mpool_filter(t->bt_mp, __bt_pgin, __bt_pgout, t); + + /* Create a root page if new tree. */ + if (nroot(t) == RET_ERROR) + goto err; + + /* Global flags. */ + if (dflags & DB_LOCK) + F_SET(t, B_DB_LOCK); + if (dflags & DB_SHMEM) + F_SET(t, B_DB_SHMEM); + if (dflags & DB_TXN) + F_SET(t, B_DB_TXN); + + return (dbp); + +einval: errno = EINVAL; + goto err; + +eftype: errno = EFTYPE; + goto err; + +err: if (t) { + if (t->bt_dbp) + free(t->bt_dbp); + if (t->bt_fd != -1) + (void)close(t->bt_fd); + free(t); + } + return (NULL); +} + +/* + * NROOT -- Create the root of a new tree. + * + * Parameters: + * t: tree + * + * Returns: + * RET_ERROR, RET_SUCCESS + */ +static int +nroot(t) + BTREE *t; +{ + PAGE *meta, *root; + pgno_t npg; + + if ((meta = mpool_get(t->bt_mp, 0, 0)) != NULL) { + mpool_put(t->bt_mp, meta, 0); + return (RET_SUCCESS); + } + if (errno != EINVAL) /* It's OK to not exist. */ + return (RET_ERROR); + errno = 0; + + if ((meta = mpool_new(t->bt_mp, &npg)) == NULL) + return (RET_ERROR); + + if ((root = mpool_new(t->bt_mp, &npg)) == NULL) + return (RET_ERROR); + + if (npg != P_ROOT) + return (RET_ERROR); + root->pgno = npg; + root->prevpg = root->nextpg = P_INVALID; + root->lower = BTDATAOFF; + root->upper = t->bt_psize; + root->flags = P_BLEAF; + memset(meta, 0, t->bt_psize); + mpool_put(t->bt_mp, meta, MPOOL_DIRTY); + mpool_put(t->bt_mp, root, MPOOL_DIRTY); + return (RET_SUCCESS); +} + +static int +tmp() +{ + sigset_t set, oset; + int fd; + const char *envtmp; + char *path; + static const char fmt[] = "%s/bt.XXXXXX"; + size_t n; + + envtmp = getenv("TMPDIR"); + if (!envtmp) + envtmp = "/tmp"; + n = strlen (envtmp) + sizeof fmt; +#ifdef __GNUC__ + path = __builtin_alloca(n); +#else + path = malloc(n); +#endif + (void)snprintf(path, n, fmt, envtmp ? envtmp : "/tmp"); + + (void)sigfillset(&set); + (void)sigprocmask(SIG_BLOCK, &set, &oset); + if ((fd = mkstemp(path)) != -1) + (void)unlink(path); + (void)sigprocmask(SIG_SETMASK, &oset, NULL); +#ifndef __GNUC__ + free(path); +#endif + return(fd); +} + +static int +byteorder() +{ + u_int32_t x; + u_char *p; + + x = 0x01020304; + p = (u_char *)&x; + switch (*p) { + case 1: + return (BIG_ENDIAN); + case 4: + return (LITTLE_ENDIAN); + default: + return (0); + } +} + +int +__bt_fd(dbp) + const DB *dbp; +{ + BTREE *t; + + t = dbp->internal; + + /* Toss any page pinned across calls. */ + if (t->bt_pinned != NULL) { + mpool_put(t->bt_mp, t->bt_pinned, 0); + t->bt_pinned = NULL; + } + + /* In-memory database can't have a file descriptor. */ + if (F_ISSET(t, B_INMEM)) { + errno = ENOENT; + return (-1); + } + return (t->bt_fd); +} diff --git a/utils/db1-ast/btree/bt_overflow.c b/utils/db1-ast/btree/bt_overflow.c new file mode 100644 index 000000000..d8f310d91 --- /dev/null +++ b/utils/db1-ast/btree/bt_overflow.c @@ -0,0 +1,228 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Mike Olson. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)bt_overflow.c 8.5 (Berkeley) 7/16/94"; +#endif /* LIBC_SCCS and not lint */ + +#include + +#include +#include +#include + +#include "../include/db.h" +#include "btree.h" + +/* + * Big key/data code. + * + * Big key and data entries are stored on linked lists of pages. The initial + * reference is byte string stored with the key or data and is the page number + * and size. The actual record is stored in a chain of pages linked by the + * nextpg field of the PAGE header. + * + * The first page of the chain has a special property. If the record is used + * by an internal page, it cannot be deleted and the P_PRESERVE bit will be set + * in the header. + * + * XXX + * A single DBT is written to each chain, so a lot of space on the last page + * is wasted. This is a fairly major bug for some data sets. + */ + +/* + * __OVFL_GET -- Get an overflow key/data item. + * + * Parameters: + * t: tree + * p: pointer to { pgno_t, u_int32_t } + * buf: storage address + * bufsz: storage size + * + * Returns: + * RET_ERROR, RET_SUCCESS + */ +int +__ovfl_get(t, p, ssz, buf, bufsz) + BTREE *t; + void *p; + size_t *ssz; + void **buf; + size_t *bufsz; +{ + PAGE *h; + pgno_t pg; + size_t nb, plen; + u_int32_t sz; + + memmove(&pg, p, sizeof(pgno_t)); + memmove(&sz, (char *)p + sizeof(pgno_t), sizeof(u_int32_t)); + *ssz = sz; + +#ifdef DEBUG + if (pg == P_INVALID || sz == 0) + abort(); +#endif + /* Make the buffer bigger as necessary. */ + if (*bufsz < sz) { + *buf = (char *)(*buf == NULL ? malloc(sz) : realloc(*buf, sz)); + if (*buf == NULL) + return (RET_ERROR); + *bufsz = sz; + } + + /* + * Step through the linked list of pages, copying the data on each one + * into the buffer. Never copy more than the data's length. + */ + plen = t->bt_psize - BTDATAOFF; + for (p = *buf;; p = (char *)p + nb, pg = h->nextpg) { + if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) + return (RET_ERROR); + + nb = MIN(sz, plen); + memmove(p, (char *)h + BTDATAOFF, nb); + mpool_put(t->bt_mp, h, 0); + + if ((sz -= nb) == 0) + break; + } + return (RET_SUCCESS); +} + +/* + * __OVFL_PUT -- Store an overflow key/data item. + * + * Parameters: + * t: tree + * data: DBT to store + * pgno: storage page number + * + * Returns: + * RET_ERROR, RET_SUCCESS + */ +int +__ovfl_put(t, dbt, pg) + BTREE *t; + const DBT *dbt; + pgno_t *pg; +{ + PAGE *h, *last; + void *p; + pgno_t npg; + size_t nb, plen; + u_int32_t sz; + + /* + * Allocate pages and copy the key/data record into them. Store the + * number of the first page in the chain. + */ + plen = t->bt_psize - BTDATAOFF; + for (last = NULL, p = dbt->data, sz = dbt->size;; + p = (char *)p + plen, last = h) { + if ((h = __bt_new(t, &npg)) == NULL) + return (RET_ERROR); + + h->pgno = npg; + h->nextpg = h->prevpg = P_INVALID; + h->flags = P_OVERFLOW; + h->lower = h->upper = 0; + + nb = MIN(sz, plen); + memmove((char *)h + BTDATAOFF, p, nb); + + if (last) { + last->nextpg = h->pgno; + mpool_put(t->bt_mp, last, MPOOL_DIRTY); + } else + *pg = h->pgno; + + if ((sz -= nb) == 0) { + mpool_put(t->bt_mp, h, MPOOL_DIRTY); + break; + } + } + return (RET_SUCCESS); +} + +/* + * __OVFL_DELETE -- Delete an overflow chain. + * + * Parameters: + * t: tree + * p: pointer to { pgno_t, u_int32_t } + * + * Returns: + * RET_ERROR, RET_SUCCESS + */ +int +__ovfl_delete(t, p) + BTREE *t; + void *p; +{ + PAGE *h; + pgno_t pg; + size_t plen; + u_int32_t sz; + + memmove(&pg, p, sizeof(pgno_t)); + memmove(&sz, (char *)p + sizeof(pgno_t), sizeof(u_int32_t)); + +#ifdef DEBUG + if (pg == P_INVALID || sz == 0) + abort(); +#endif + if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) + return (RET_ERROR); + + /* Don't delete chains used by internal pages. */ + if (h->flags & P_PRESERVE) { + mpool_put(t->bt_mp, h, 0); + return (RET_SUCCESS); + } + + /* Step through the chain, calling the free routine for each page. */ + for (plen = t->bt_psize - BTDATAOFF;; sz -= plen) { + pg = h->nextpg; + __bt_free(t, h); + if (sz <= plen) + break; + if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) + return (RET_ERROR); + } + return (RET_SUCCESS); +} diff --git a/utils/db1-ast/btree/bt_page.c b/utils/db1-ast/btree/bt_page.c new file mode 100644 index 000000000..e77a1d6b5 --- /dev/null +++ b/utils/db1-ast/btree/bt_page.c @@ -0,0 +1,100 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)bt_page.c 8.3 (Berkeley) 7/14/94"; +#endif /* LIBC_SCCS and not lint */ + +#include + +#include + +#include "../include/db.h" +#include "btree.h" + +/* + * __bt_free -- + * Put a page on the freelist. + * + * Parameters: + * t: tree + * h: page to free + * + * Returns: + * RET_ERROR, RET_SUCCESS + * + * Side-effect: + * mpool_put's the page. + */ +int +__bt_free(t, h) + BTREE *t; + PAGE *h; +{ + /* Insert the page at the head of the free list. */ + h->prevpg = P_INVALID; + h->nextpg = t->bt_free; + t->bt_free = h->pgno; + F_SET(t, B_METADIRTY); + + /* Make sure the page gets written back. */ + return (mpool_put(t->bt_mp, h, MPOOL_DIRTY)); +} + +/* + * __bt_new -- + * Get a new page, preferably from the freelist. + * + * Parameters: + * t: tree + * npg: storage for page number. + * + * Returns: + * Pointer to a page, NULL on error. + */ +PAGE * +__bt_new(t, npg) + BTREE *t; + pgno_t *npg; +{ + PAGE *h; + + if (t->bt_free != P_INVALID && + (h = mpool_get(t->bt_mp, t->bt_free, 0)) != NULL) { + *npg = t->bt_free; + t->bt_free = h->nextpg; + F_SET(t, B_METADIRTY); + return (h); + } + return (mpool_new(t->bt_mp, npg)); +} diff --git a/utils/db1-ast/btree/bt_put.c b/utils/db1-ast/btree/bt_put.c new file mode 100644 index 000000000..604ff06a3 --- /dev/null +++ b/utils/db1-ast/btree/bt_put.c @@ -0,0 +1,321 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Mike Olson. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)bt_put.c 8.8 (Berkeley) 7/26/94"; +#endif /* LIBC_SCCS and not lint */ + +#include + +#include +#include +#include +#include + +#include "../include/db.h" +#include "btree.h" + +static EPG *bt_fast __P((BTREE *, const DBT *, const DBT *, int *)); + +/* + * __BT_PUT -- Add a btree item to the tree. + * + * Parameters: + * dbp: pointer to access method + * key: key + * data: data + * flag: R_NOOVERWRITE + * + * Returns: + * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key is already in the + * tree and R_NOOVERWRITE specified. + */ +int +__bt_put(dbp, key, data, flags) + const DB *dbp; + DBT *key; + const DBT *data; + u_int flags; +{ + BTREE *t; + DBT tkey, tdata; + EPG *e = 0; + PAGE *h; + indx_t idx, nxtindex; + pgno_t pg; + u_int32_t nbytes; + int dflags, exact, status; + char *dest, db[NOVFLSIZE], kb[NOVFLSIZE]; + + t = dbp->internal; + + /* Toss any page pinned across calls. */ + if (t->bt_pinned != NULL) { + mpool_put(t->bt_mp, t->bt_pinned, 0); + t->bt_pinned = NULL; + } + + /* Check for change to a read-only tree. */ + if (F_ISSET(t, B_RDONLY)) { + errno = EPERM; + return (RET_ERROR); + } + + switch (flags) { + case 0: + case R_NOOVERWRITE: + break; + case R_CURSOR: + /* + * If flags is R_CURSOR, put the cursor. Must already + * have started a scan and not have already deleted it. + */ + if (F_ISSET(&t->bt_cursor, CURS_INIT) && + !F_ISSET(&t->bt_cursor, + CURS_ACQUIRE | CURS_AFTER | CURS_BEFORE)) + break; + /* FALLTHROUGH */ + default: + errno = EINVAL; + return (RET_ERROR); + } + + /* + * If the key/data pair won't fit on a page, store it on overflow + * pages. Only put the key on the overflow page if the pair are + * still too big after moving the data to an overflow page. + * + * XXX + * If the insert fails later on, the overflow pages aren't recovered. + */ + dflags = 0; + if (key->size + data->size > t->bt_ovflsize) { + if (key->size > t->bt_ovflsize) { +storekey: if (__ovfl_put(t, key, &pg) == RET_ERROR) + return (RET_ERROR); + tkey.data = kb; + tkey.size = NOVFLSIZE; + memmove(kb, &pg, sizeof(pgno_t)); + memmove(kb + sizeof(pgno_t), + &key->size, sizeof(u_int32_t)); + dflags |= P_BIGKEY; + key = &tkey; + } + if (key->size + data->size > t->bt_ovflsize) { + if (__ovfl_put(t, data, &pg) == RET_ERROR) + return (RET_ERROR); + tdata.data = db; + tdata.size = NOVFLSIZE; + memmove(db, &pg, sizeof(pgno_t)); + memmove(db + sizeof(pgno_t), + &data->size, sizeof(u_int32_t)); + dflags |= P_BIGDATA; + data = &tdata; + } + if (key->size + data->size > t->bt_ovflsize) + goto storekey; + } + + /* Replace the cursor. */ + if (flags == R_CURSOR) { + if ((h = mpool_get(t->bt_mp, t->bt_cursor.pg.pgno, 0)) == NULL) + return (RET_ERROR); + idx = t->bt_cursor.pg.index; + goto delete; + } + + /* + * Find the key to delete, or, the location at which to insert. + * Bt_fast and __bt_search both pin the returned page. + */ + if (t->bt_order == NOT || (e = bt_fast(t, key, data, &exact)) == NULL) + if ((e = __bt_search(t, key, &exact)) == NULL) + return (RET_ERROR); + h = e->page; + idx = e->index; + + /* + * Add the key/data pair to the tree. If an identical key is already + * in the tree, and R_NOOVERWRITE is set, an error is returned. If + * R_NOOVERWRITE is not set, the key is either added (if duplicates are + * permitted) or an error is returned. + */ + switch (flags) { + case R_NOOVERWRITE: + if (!exact) + break; + mpool_put(t->bt_mp, h, 0); + return (RET_SPECIAL); + default: + if (!exact || !F_ISSET(t, B_NODUPS)) + break; + /* + * !!! + * Note, the delete may empty the page, so we need to put a + * new entry into the page immediately. + */ +delete: if (__bt_dleaf(t, key, h, idx) == RET_ERROR) { + mpool_put(t->bt_mp, h, 0); + return (RET_ERROR); + } + break; + } + + /* + * If not enough room, or the user has put a ceiling on the number of + * keys permitted in the page, split the page. The split code will + * insert the key and data and unpin the current page. If inserting + * into the offset array, shift the pointers up. + */ + nbytes = NBLEAFDBT(key->size, data->size); + if ((u_int32_t) (h->upper - h->lower) < nbytes + sizeof(indx_t)) { + if ((status = __bt_split(t, h, key, + data, dflags, nbytes, idx)) != RET_SUCCESS) + return (status); + goto success; + } + + if (idx < (nxtindex = NEXTINDEX(h))) + memmove(h->linp + idx + 1, h->linp + idx, + (nxtindex - idx) * sizeof(indx_t)); + h->lower += sizeof(indx_t); + + h->linp[idx] = h->upper -= nbytes; + dest = (char *)h + h->upper; + WR_BLEAF(dest, key, data, dflags); + + /* If the cursor is on this page, adjust it as necessary. */ + if (F_ISSET(&t->bt_cursor, CURS_INIT) && + !F_ISSET(&t->bt_cursor, CURS_ACQUIRE) && + t->bt_cursor.pg.pgno == h->pgno && t->bt_cursor.pg.index >= idx) + ++t->bt_cursor.pg.index; + + if (t->bt_order == NOT) { + if (h->nextpg == P_INVALID) { + if (idx == NEXTINDEX(h) - 1) { + t->bt_order = FORWARD; + t->bt_last.index = idx; + t->bt_last.pgno = h->pgno; + } + } else if (h->prevpg == P_INVALID) { + if (idx == 0) { + t->bt_order = BACK; + t->bt_last.index = 0; + t->bt_last.pgno = h->pgno; + } + } + } + + mpool_put(t->bt_mp, h, MPOOL_DIRTY); + +success: + if (flags == R_SETCURSOR) + __bt_setcur(t, e->page->pgno, e->index); + + F_SET(t, B_MODIFIED); + return (RET_SUCCESS); +} + +#ifdef STATISTICS +u_long bt_cache_hit, bt_cache_miss; +#endif + +/* + * BT_FAST -- Do a quick check for sorted data. + * + * Parameters: + * t: tree + * key: key to insert + * + * Returns: + * EPG for new record or NULL if not found. + */ +static EPG * +bt_fast(t, key, data, exactp) + BTREE *t; + const DBT *key, *data; + int *exactp; +{ + PAGE *h; + u_int32_t nbytes; + int cmp; + + if ((h = mpool_get(t->bt_mp, t->bt_last.pgno, 0)) == NULL) { + t->bt_order = NOT; + return (NULL); + } + t->bt_cur.page = h; + t->bt_cur.index = t->bt_last.index; + + /* + * If won't fit in this page or have too many keys in this page, + * have to search to get split stack. + */ + nbytes = NBLEAFDBT(key->size, data->size); + if ((u_int32_t) (h->upper - h->lower) < nbytes + sizeof(indx_t)) + goto miss; + + if (t->bt_order == FORWARD) { + if (t->bt_cur.page->nextpg != P_INVALID) + goto miss; + if (t->bt_cur.index != NEXTINDEX(h) - 1) + goto miss; + if ((cmp = __bt_cmp(t, key, &t->bt_cur)) < 0) + goto miss; + t->bt_last.index = cmp ? ++t->bt_cur.index : t->bt_cur.index; + } else { + if (t->bt_cur.page->prevpg != P_INVALID) + goto miss; + if (t->bt_cur.index != 0) + goto miss; + if ((cmp = __bt_cmp(t, key, &t->bt_cur)) > 0) + goto miss; + t->bt_last.index = 0; + } + *exactp = cmp == 0; +#ifdef STATISTICS + ++bt_cache_hit; +#endif + return (&t->bt_cur); + +miss: +#ifdef STATISTICS + ++bt_cache_miss; +#endif + t->bt_order = NOT; + mpool_put(t->bt_mp, h, 0); + return (NULL); +} diff --git a/utils/db1-ast/btree/bt_search.c b/utils/db1-ast/btree/bt_search.c new file mode 100644 index 000000000..623f43949 --- /dev/null +++ b/utils/db1-ast/btree/bt_search.c @@ -0,0 +1,213 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Mike Olson. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)bt_search.c 8.8 (Berkeley) 7/31/94"; +#endif /* LIBC_SCCS and not lint */ + +#include + +#include + +#include "../include/db.h" +#include "btree.h" + +static int __bt_snext __P((BTREE *, PAGE *, const DBT *, int *)); +static int __bt_sprev __P((BTREE *, PAGE *, const DBT *, int *)); + +/* + * __bt_search -- + * Search a btree for a key. + * + * Parameters: + * t: tree to search + * key: key to find + * exactp: pointer to exact match flag + * + * Returns: + * The EPG for matching record, if any, or the EPG for the location + * of the key, if it were inserted into the tree, is entered into + * the bt_cur field of the tree. A pointer to the field is returned. + */ +EPG * +__bt_search(t, key, exactp) + BTREE *t; + const DBT *key; + int *exactp; +{ + PAGE *h; + indx_t base, index, lim; + pgno_t pg; + int cmp; + + BT_CLR(t); + for (pg = P_ROOT;;) { + if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) + return (NULL); + + /* Do a binary search on the current page. */ + t->bt_cur.page = h; + for (base = 0, lim = NEXTINDEX(h); lim; lim >>= 1) { + t->bt_cur.index = index = base + (lim >> 1); + if ((cmp = __bt_cmp(t, key, &t->bt_cur)) == 0) { + if (h->flags & P_BLEAF) { + *exactp = 1; + return (&t->bt_cur); + } + goto next; + } + if (cmp > 0) { + base = index + 1; + --lim; + } + } + + /* + * If it's a leaf page, we're almost done. If no duplicates + * are allowed, or we have an exact match, we're done. Else, + * it's possible that there were matching keys on this page, + * which later deleted, and we're on a page with no matches + * while there are matches on other pages. If at the start or + * end of a page, check the adjacent page. + */ + if (h->flags & P_BLEAF) { + if (!F_ISSET(t, B_NODUPS)) { + if (base == 0 && + h->prevpg != P_INVALID && + __bt_sprev(t, h, key, exactp)) + return (&t->bt_cur); + if (base == NEXTINDEX(h) && + h->nextpg != P_INVALID && + __bt_snext(t, h, key, exactp)) + return (&t->bt_cur); + } + *exactp = 0; + t->bt_cur.index = base; + return (&t->bt_cur); + } + + /* + * No match found. Base is the smallest index greater than + * key and may be zero or a last + 1 index. If it's non-zero, + * decrement by one, and record the internal page which should + * be a parent page for the key. If a split later occurs, the + * inserted page will be to the right of the saved page. + */ + index = base ? base - 1 : base; + +next: BT_PUSH(t, h->pgno, index); + pg = GETBINTERNAL(h, index)->pgno; + mpool_put(t->bt_mp, h, 0); + } +} + +/* + * __bt_snext -- + * Check for an exact match after the key. + * + * Parameters: + * t: tree + * h: current page + * key: key + * exactp: pointer to exact match flag + * + * Returns: + * If an exact match found. + */ +static int +__bt_snext(t, h, key, exactp) + BTREE *t; + PAGE *h; + const DBT *key; + int *exactp; +{ + EPG e; + + /* + * Get the next page. The key is either an exact + * match, or not as good as the one we already have. + */ + if ((e.page = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL) + return (0); + e.index = 0; + if (__bt_cmp(t, key, &e) == 0) { + mpool_put(t->bt_mp, h, 0); + t->bt_cur = e; + *exactp = 1; + return (1); + } + mpool_put(t->bt_mp, e.page, 0); + return (0); +} + +/* + * __bt_sprev -- + * Check for an exact match before the key. + * + * Parameters: + * t: tree + * h: current page + * key: key + * exactp: pointer to exact match flag + * + * Returns: + * If an exact match found. + */ +static int +__bt_sprev(t, h, key, exactp) + BTREE *t; + PAGE *h; + const DBT *key; + int *exactp; +{ + EPG e; + + /* + * Get the previous page. The key is either an exact + * match, or not as good as the one we already have. + */ + if ((e.page = mpool_get(t->bt_mp, h->prevpg, 0)) == NULL) + return (0); + e.index = NEXTINDEX(e.page) - 1; + if (__bt_cmp(t, key, &e) == 0) { + mpool_put(t->bt_mp, h, 0); + t->bt_cur = e; + *exactp = 1; + return (1); + } + mpool_put(t->bt_mp, e.page, 0); + return (0); +} diff --git a/utils/db1-ast/btree/bt_seq.c b/utils/db1-ast/btree/bt_seq.c new file mode 100644 index 000000000..3f1724274 --- /dev/null +++ b/utils/db1-ast/btree/bt_seq.c @@ -0,0 +1,460 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Mike Olson. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)bt_seq.c 8.7 (Berkeley) 7/20/94"; +#endif /* LIBC_SCCS and not lint */ + +#include + +#include +#include +#include +#include + +#include "../include/db.h" +#include "btree.h" + +static int __bt_first __P((BTREE *, const DBT *, EPG *, int *)); +static int __bt_seqadv __P((BTREE *, EPG *, int)); +static int __bt_seqset __P((BTREE *, EPG *, DBT *, int)); + +/* + * Sequential scan support. + * + * The tree can be scanned sequentially, starting from either end of the + * tree or from any specific key. A scan request before any scanning is + * done is initialized as starting from the least node. + */ + +/* + * __bt_seq -- + * Btree sequential scan interface. + * + * Parameters: + * dbp: pointer to access method + * key: key for positioning and return value + * data: data return value + * flags: R_CURSOR, R_FIRST, R_LAST, R_NEXT, R_PREV. + * + * Returns: + * RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key. + */ +int +__bt_seq(dbp, key, data, flags) + const DB *dbp; + DBT *key, *data; + u_int flags; +{ + BTREE *t; + EPG e; + int status; + + t = dbp->internal; + + /* Toss any page pinned across calls. */ + if (t->bt_pinned != NULL) { + mpool_put(t->bt_mp, t->bt_pinned, 0); + t->bt_pinned = NULL; + } + + /* + * If scan uninitialized as yet, or starting at a specific record, set + * the scan to a specific key. Both __bt_seqset and __bt_seqadv pin + * the page the cursor references if they're successful. + */ + switch (flags) { + case R_NEXT: + case R_PREV: + if (F_ISSET(&t->bt_cursor, CURS_INIT)) { + status = __bt_seqadv(t, &e, flags); + break; + } + /* FALLTHROUGH */ + case R_FIRST: + case R_LAST: + case R_CURSOR: + status = __bt_seqset(t, &e, key, flags); + break; + default: + errno = EINVAL; + return (RET_ERROR); + } + + if (status == RET_SUCCESS) { + __bt_setcur(t, e.page->pgno, e.index); + + status = + __bt_ret(t, &e, key, &t->bt_rkey, data, &t->bt_rdata, 0); + + /* + * If the user is doing concurrent access, we copied the + * key/data, toss the page. + */ + if (F_ISSET(t, B_DB_LOCK)) + mpool_put(t->bt_mp, e.page, 0); + else + t->bt_pinned = e.page; + } + return (status); +} + +/* + * __bt_seqset -- + * Set the sequential scan to a specific key. + * + * Parameters: + * t: tree + * ep: storage for returned key + * key: key for initial scan position + * flags: R_CURSOR, R_FIRST, R_LAST, R_NEXT, R_PREV + * + * Side effects: + * Pins the page the cursor references. + * + * Returns: + * RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key. + */ +static int +__bt_seqset(t, ep, key, flags) + BTREE *t; + EPG *ep; + DBT *key; + int flags; +{ + PAGE *h; + pgno_t pg; + int exact; + + /* + * Find the first, last or specific key in the tree and point the + * cursor at it. The cursor may not be moved until a new key has + * been found. + */ + switch (flags) { + case R_CURSOR: /* Keyed scan. */ + /* + * Find the first instance of the key or the smallest key + * which is greater than or equal to the specified key. + */ + if (key->data == NULL || key->size == 0) { + errno = EINVAL; + return (RET_ERROR); + } + return (__bt_first(t, key, ep, &exact)); + case R_FIRST: /* First record. */ + case R_NEXT: + /* Walk down the left-hand side of the tree. */ + for (pg = P_ROOT;;) { + if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) + return (RET_ERROR); + + /* Check for an empty tree. */ + if (NEXTINDEX(h) == 0) { + mpool_put(t->bt_mp, h, 0); + return (RET_SPECIAL); + } + + if (h->flags & (P_BLEAF | P_RLEAF)) + break; + pg = GETBINTERNAL(h, 0)->pgno; + mpool_put(t->bt_mp, h, 0); + } + ep->page = h; + ep->index = 0; + break; + case R_LAST: /* Last record. */ + case R_PREV: + /* Walk down the right-hand side of the tree. */ + for (pg = P_ROOT;;) { + if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) + return (RET_ERROR); + + /* Check for an empty tree. */ + if (NEXTINDEX(h) == 0) { + mpool_put(t->bt_mp, h, 0); + return (RET_SPECIAL); + } + + if (h->flags & (P_BLEAF | P_RLEAF)) + break; + pg = GETBINTERNAL(h, NEXTINDEX(h) - 1)->pgno; + mpool_put(t->bt_mp, h, 0); + } + + ep->page = h; + ep->index = NEXTINDEX(h) - 1; + break; + } + return (RET_SUCCESS); +} + +/* + * __bt_seqadvance -- + * Advance the sequential scan. + * + * Parameters: + * t: tree + * flags: R_NEXT, R_PREV + * + * Side effects: + * Pins the page the new key/data record is on. + * + * Returns: + * RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key. + */ +static int +__bt_seqadv(t, ep, flags) + BTREE *t; + EPG *ep; + int flags; +{ + CURSOR *c; + PAGE *h; + indx_t index = 0; + pgno_t pg; + int exact; + + /* + * There are a couple of states that we can be in. The cursor has + * been initialized by the time we get here, but that's all we know. + */ + c = &t->bt_cursor; + + /* + * The cursor was deleted where there weren't any duplicate records, + * so the key was saved. Find out where that key would go in the + * current tree. It doesn't matter if the returned key is an exact + * match or not -- if it's an exact match, the record was added after + * the delete so we can just return it. If not, as long as there's + * a record there, return it. + */ + if (F_ISSET(c, CURS_ACQUIRE)) + return (__bt_first(t, &c->key, ep, &exact)); + + /* Get the page referenced by the cursor. */ + if ((h = mpool_get(t->bt_mp, c->pg.pgno, 0)) == NULL) + return (RET_ERROR); + + /* + * Find the next/previous record in the tree and point the cursor at + * it. The cursor may not be moved until a new key has been found. + */ + switch (flags) { + case R_NEXT: /* Next record. */ + /* + * The cursor was deleted in duplicate records, and moved + * forward to a record that has yet to be returned. Clear + * that flag, and return the record. + */ + if (F_ISSET(c, CURS_AFTER)) + goto usecurrent; + index = c->pg.index; + if (++index == NEXTINDEX(h)) { + pg = h->nextpg; + mpool_put(t->bt_mp, h, 0); + if (pg == P_INVALID) + return (RET_SPECIAL); + if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) + return (RET_ERROR); + index = 0; + } + break; + case R_PREV: /* Previous record. */ + /* + * The cursor was deleted in duplicate records, and moved + * backward to a record that has yet to be returned. Clear + * that flag, and return the record. + */ + if (F_ISSET(c, CURS_BEFORE)) { +usecurrent: F_CLR(c, CURS_AFTER | CURS_BEFORE); + ep->page = h; + ep->index = c->pg.index; + return (RET_SUCCESS); + } + index = c->pg.index; + if (index == 0) { + pg = h->prevpg; + mpool_put(t->bt_mp, h, 0); + if (pg == P_INVALID) + return (RET_SPECIAL); + if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) + return (RET_ERROR); + index = NEXTINDEX(h) - 1; + } else + --index; + break; + } + + ep->page = h; + ep->index = index; + return (RET_SUCCESS); +} + +/* + * __bt_first -- + * Find the first entry. + * + * Parameters: + * t: the tree + * key: the key + * erval: return EPG + * exactp: pointer to exact match flag + * + * Returns: + * The first entry in the tree greater than or equal to key, + * or RET_SPECIAL if no such key exists. + */ +static int +__bt_first(t, key, erval, exactp) + BTREE *t; + const DBT *key; + EPG *erval; + int *exactp; +{ + PAGE *h; + EPG *ep, save; + pgno_t pg; + + /* + * Find any matching record; __bt_search pins the page. + * + * If it's an exact match and duplicates are possible, walk backwards + * in the tree until we find the first one. Otherwise, make sure it's + * a valid key (__bt_search may return an index just past the end of a + * page) and return it. + */ + if ((ep = __bt_search(t, key, exactp)) == NULL) + return (RET_SPECIAL); + if (*exactp) { + if (F_ISSET(t, B_NODUPS)) { + *erval = *ep; + return (RET_SUCCESS); + } + + /* + * Walk backwards, as long as the entry matches and there are + * keys left in the tree. Save a copy of each match in case + * we go too far. + */ + save = *ep; + h = ep->page; + do { + if (save.page->pgno != ep->page->pgno) { + mpool_put(t->bt_mp, save.page, 0); + save = *ep; + } else + save.index = ep->index; + + /* + * Don't unpin the page the last (or original) match + * was on, but make sure it's unpinned if an error + * occurs. + */ + if (ep->index == 0) { + if (h->prevpg == P_INVALID) + break; + if (h->pgno != save.page->pgno) + mpool_put(t->bt_mp, h, 0); + if ((h = mpool_get(t->bt_mp, + h->prevpg, 0)) == NULL) { + if (h->pgno == save.page->pgno) + mpool_put(t->bt_mp, + save.page, 0); + return (RET_ERROR); + } + ep->page = h; + ep->index = NEXTINDEX(h); + } + --ep->index; + } while (__bt_cmp(t, key, ep) == 0); + + /* + * Reach here with the last page that was looked at pinned, + * which may or may not be the same as the last (or original) + * match page. If it's not useful, release it. + */ + if (h->pgno != save.page->pgno) + mpool_put(t->bt_mp, h, 0); + + *erval = save; + return (RET_SUCCESS); + } + + /* If at the end of a page, find the next entry. */ + if (ep->index == NEXTINDEX(ep->page)) { + h = ep->page; + pg = h->nextpg; + mpool_put(t->bt_mp, h, 0); + if (pg == P_INVALID) + return (RET_SPECIAL); + if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) + return (RET_ERROR); + ep->index = 0; + ep->page = h; + } + *erval = *ep; + return (RET_SUCCESS); +} + +/* + * __bt_setcur -- + * Set the cursor to an entry in the tree. + * + * Parameters: + * t: the tree + * pgno: page number + * index: page index + */ +void +__bt_setcur(t, pgno, index) + BTREE *t; + pgno_t pgno; + u_int index; +{ + /* Lose any already deleted key. */ + if (t->bt_cursor.key.data != NULL) { + free(t->bt_cursor.key.data); + t->bt_cursor.key.size = 0; + t->bt_cursor.key.data = NULL; + } + F_CLR(&t->bt_cursor, CURS_ACQUIRE | CURS_AFTER | CURS_BEFORE); + + /* Update the cursor. */ + t->bt_cursor.pg.pgno = pgno; + t->bt_cursor.pg.index = index; + F_SET(&t->bt_cursor, CURS_INIT); +} diff --git a/utils/db1-ast/btree/bt_split.c b/utils/db1-ast/btree/bt_split.c new file mode 100644 index 000000000..8fede1e45 --- /dev/null +++ b/utils/db1-ast/btree/bt_split.c @@ -0,0 +1,829 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Mike Olson. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)bt_split.c 8.9 (Berkeley) 7/26/94"; +#endif /* LIBC_SCCS and not lint */ + +#include + +#include +#include +#include +#include + +#include "../include/db.h" +#include "btree.h" + +static int bt_broot __P((BTREE *, PAGE *, PAGE *, PAGE *)); +static PAGE *bt_page + __P((BTREE *, PAGE *, PAGE **, PAGE **, indx_t *, size_t)); +static int bt_preserve __P((BTREE *, pgno_t)); +static PAGE *bt_psplit + __P((BTREE *, PAGE *, PAGE *, PAGE *, indx_t *, size_t)); +static PAGE *bt_root + __P((BTREE *, PAGE *, PAGE **, PAGE **, indx_t *, size_t)); +static int bt_rroot __P((BTREE *, PAGE *, PAGE *, PAGE *)); +static recno_t rec_total __P((PAGE *)); + +#ifdef STATISTICS +u_long bt_rootsplit, bt_split, bt_sortsplit, bt_pfxsaved; +#endif + +/* + * __BT_SPLIT -- Split the tree. + * + * Parameters: + * t: tree + * sp: page to split + * key: key to insert + * data: data to insert + * flags: BIGKEY/BIGDATA flags + * ilen: insert length + * skip: index to leave open + * + * Returns: + * RET_ERROR, RET_SUCCESS + */ +int +__bt_split(t, sp, key, data, flags, ilen, argskip) + BTREE *t; + PAGE *sp; + const DBT *key, *data; + int flags; + size_t ilen; + u_int32_t argskip; +{ + BINTERNAL *bi = 0; + BLEAF *bl = 0, *tbl; + DBT a, b; + EPGNO *parent; + PAGE *h, *l, *r, *lchild, *rchild; + indx_t nxtindex; + u_int16_t skip; + u_int32_t n, nbytes, nksize = 0; + int parentsplit; + char *dest; + + /* + * Split the page into two pages, l and r. The split routines return + * a pointer to the page into which the key should be inserted and with + * skip set to the offset which should be used. Additionally, l and r + * are pinned. + */ + skip = argskip; + h = sp->pgno == P_ROOT ? + bt_root(t, sp, &l, &r, &skip, ilen) : + bt_page(t, sp, &l, &r, &skip, ilen); + if (h == NULL) + return (RET_ERROR); + + /* + * Insert the new key/data pair into the leaf page. (Key inserts + * always cause a leaf page to split first.) + */ + h->linp[skip] = h->upper -= ilen; + dest = (char *)h + h->upper; + if (F_ISSET(t, R_RECNO)) + WR_RLEAF(dest, data, flags) + else + WR_BLEAF(dest, key, data, flags) + + /* If the root page was split, make it look right. */ + if (sp->pgno == P_ROOT && + (F_ISSET(t, R_RECNO) ? + bt_rroot(t, sp, l, r) : bt_broot(t, sp, l, r)) == RET_ERROR) + goto err2; + + /* + * Now we walk the parent page stack -- a LIFO stack of the pages that + * were traversed when we searched for the page that split. Each stack + * entry is a page number and a page index offset. The offset is for + * the page traversed on the search. We've just split a page, so we + * have to insert a new key into the parent page. + * + * If the insert into the parent page causes it to split, may have to + * continue splitting all the way up the tree. We stop if the root + * splits or the page inserted into didn't have to split to hold the + * new key. Some algorithms replace the key for the old page as well + * as the new page. We don't, as there's no reason to believe that the + * first key on the old page is any better than the key we have, and, + * in the case of a key being placed at index 0 causing the split, the + * key is unavailable. + * + * There are a maximum of 5 pages pinned at any time. We keep the left + * and right pages pinned while working on the parent. The 5 are the + * two children, left parent and right parent (when the parent splits) + * and the root page or the overflow key page when calling bt_preserve. + * This code must make sure that all pins are released other than the + * root page or overflow page which is unlocked elsewhere. + */ + while ((parent = BT_POP(t)) != NULL) { + lchild = l; + rchild = r; + + /* Get the parent page. */ + if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL) + goto err2; + + /* + * The new key goes ONE AFTER the index, because the split + * was to the right. + */ + skip = parent->index + 1; + + /* + * Calculate the space needed on the parent page. + * + * Prefix trees: space hack when inserting into BINTERNAL + * pages. Retain only what's needed to distinguish between + * the new entry and the LAST entry on the page to its left. + * If the keys compare equal, retain the entire key. Note, + * we don't touch overflow keys, and the entire key must be + * retained for the next-to-left most key on the leftmost + * page of each level, or the search will fail. Applicable + * ONLY to internal pages that have leaf pages as children. + * Further reduction of the key between pairs of internal + * pages loses too much information. + */ + switch (rchild->flags & P_TYPE) { + case P_BINTERNAL: + bi = GETBINTERNAL(rchild, 0); + nbytes = NBINTERNAL(bi->ksize); + break; + case P_BLEAF: + bl = GETBLEAF(rchild, 0); + nbytes = NBINTERNAL(bl->ksize); + if (t->bt_pfx && !(bl->flags & P_BIGKEY) && + (h->prevpg != P_INVALID || skip > 1)) { + tbl = GETBLEAF(lchild, NEXTINDEX(lchild) - 1); + a.size = tbl->ksize; + a.data = tbl->bytes; + b.size = bl->ksize; + b.data = bl->bytes; + nksize = t->bt_pfx(&a, &b); + n = NBINTERNAL(nksize); + if (n < nbytes) { +#ifdef STATISTICS + bt_pfxsaved += nbytes - n; +#endif + nbytes = n; + } else + nksize = 0; + } else + nksize = 0; + break; + case P_RINTERNAL: + case P_RLEAF: + nbytes = NRINTERNAL; + break; + default: + abort(); + } + + /* Split the parent page if necessary or shift the indices. */ + if ((u_int32_t) (h->upper - h->lower) + < nbytes + sizeof(indx_t)) { + sp = h; + h = h->pgno == P_ROOT ? + bt_root(t, h, &l, &r, &skip, nbytes) : + bt_page(t, h, &l, &r, &skip, nbytes); + if (h == NULL) + goto err1; + parentsplit = 1; + } else { + if (skip < (nxtindex = NEXTINDEX(h))) + memmove(h->linp + skip + 1, h->linp + skip, + (nxtindex - skip) * sizeof(indx_t)); + h->lower += sizeof(indx_t); + parentsplit = 0; + } + + /* Insert the key into the parent page. */ + switch (rchild->flags & P_TYPE) { + case P_BINTERNAL: + h->linp[skip] = h->upper -= nbytes; + dest = (char *)h + h->linp[skip]; + memmove(dest, bi, nbytes); + ((BINTERNAL *)dest)->pgno = rchild->pgno; + break; + case P_BLEAF: + h->linp[skip] = h->upper -= nbytes; + dest = (char *)h + h->linp[skip]; + WR_BINTERNAL(dest, nksize ? nksize : bl->ksize, + rchild->pgno, bl->flags & P_BIGKEY); + memmove(dest, bl->bytes, nksize ? nksize : bl->ksize); + if (bl->flags & P_BIGKEY && + bt_preserve(t, *(pgno_t *)bl->bytes) == RET_ERROR) + goto err1; + break; + case P_RINTERNAL: + /* + * Update the left page count. If split + * added at index 0, fix the correct page. + */ + if (skip > 0) + dest = (char *)h + h->linp[skip - 1]; + else + dest = (char *)l + l->linp[NEXTINDEX(l) - 1]; + ((RINTERNAL *)dest)->nrecs = rec_total(lchild); + ((RINTERNAL *)dest)->pgno = lchild->pgno; + + /* Update the right page count. */ + h->linp[skip] = h->upper -= nbytes; + dest = (char *)h + h->linp[skip]; + ((RINTERNAL *)dest)->nrecs = rec_total(rchild); + ((RINTERNAL *)dest)->pgno = rchild->pgno; + break; + case P_RLEAF: + /* + * Update the left page count. If split + * added at index 0, fix the correct page. + */ + if (skip > 0) + dest = (char *)h + h->linp[skip - 1]; + else + dest = (char *)l + l->linp[NEXTINDEX(l) - 1]; + ((RINTERNAL *)dest)->nrecs = NEXTINDEX(lchild); + ((RINTERNAL *)dest)->pgno = lchild->pgno; + + /* Update the right page count. */ + h->linp[skip] = h->upper -= nbytes; + dest = (char *)h + h->linp[skip]; + ((RINTERNAL *)dest)->nrecs = NEXTINDEX(rchild); + ((RINTERNAL *)dest)->pgno = rchild->pgno; + break; + default: + abort(); + } + + /* Unpin the held pages. */ + if (!parentsplit) { + mpool_put(t->bt_mp, h, MPOOL_DIRTY); + break; + } + + /* If the root page was split, make it look right. */ + if (sp->pgno == P_ROOT && + (F_ISSET(t, R_RECNO) ? + bt_rroot(t, sp, l, r) : bt_broot(t, sp, l, r)) == RET_ERROR) + goto err1; + + mpool_put(t->bt_mp, lchild, MPOOL_DIRTY); + mpool_put(t->bt_mp, rchild, MPOOL_DIRTY); + } + + /* Unpin the held pages. */ + mpool_put(t->bt_mp, l, MPOOL_DIRTY); + mpool_put(t->bt_mp, r, MPOOL_DIRTY); + + /* Clear any pages left on the stack. */ + return (RET_SUCCESS); + + /* + * If something fails in the above loop we were already walking back + * up the tree and the tree is now inconsistent. Nothing much we can + * do about it but release any memory we're holding. + */ +err1: mpool_put(t->bt_mp, lchild, MPOOL_DIRTY); + mpool_put(t->bt_mp, rchild, MPOOL_DIRTY); + +err2: mpool_put(t->bt_mp, l, 0); + mpool_put(t->bt_mp, r, 0); + __dbpanic(t->bt_dbp); + return (RET_ERROR); +} + +/* + * BT_PAGE -- Split a non-root page of a btree. + * + * Parameters: + * t: tree + * h: root page + * lp: pointer to left page pointer + * rp: pointer to right page pointer + * skip: pointer to index to leave open + * ilen: insert length + * + * Returns: + * Pointer to page in which to insert or NULL on error. + */ +static PAGE * +bt_page(t, h, lp, rp, skip, ilen) + BTREE *t; + PAGE *h, **lp, **rp; + indx_t *skip; + size_t ilen; +{ + PAGE *l, *r, *tp; + pgno_t npg; + +#ifdef STATISTICS + ++bt_split; +#endif + /* Put the new right page for the split into place. */ + if ((r = __bt_new(t, &npg)) == NULL) + return (NULL); + r->pgno = npg; + r->lower = BTDATAOFF; + r->upper = t->bt_psize; + r->nextpg = h->nextpg; + r->prevpg = h->pgno; + r->flags = h->flags & P_TYPE; + + /* + * If we're splitting the last page on a level because we're appending + * a key to it (skip is NEXTINDEX()), it's likely that the data is + * sorted. Adding an empty page on the side of the level is less work + * and can push the fill factor much higher than normal. If we're + * wrong it's no big deal, we'll just do the split the right way next + * time. It may look like it's equally easy to do a similar hack for + * reverse sorted data, that is, split the tree left, but it's not. + * Don't even try. + */ + if (h->nextpg == P_INVALID && *skip == NEXTINDEX(h)) { +#ifdef STATISTICS + ++bt_sortsplit; +#endif + h->nextpg = r->pgno; + r->lower = BTDATAOFF + sizeof(indx_t); + *skip = 0; + *lp = h; + *rp = r; + return (r); + } + + /* Put the new left page for the split into place. */ + if ((l = (PAGE *)malloc(t->bt_psize)) == NULL) { + mpool_put(t->bt_mp, r, 0); + return (NULL); + } +#ifdef PURIFY + memset(l, 0xff, t->bt_psize); +#endif + l->pgno = h->pgno; + l->nextpg = r->pgno; + l->prevpg = h->prevpg; + l->lower = BTDATAOFF; + l->upper = t->bt_psize; + l->flags = h->flags & P_TYPE; + + /* Fix up the previous pointer of the page after the split page. */ + if (h->nextpg != P_INVALID) { + if ((tp = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL) { + free(l); + /* XXX mpool_free(t->bt_mp, r->pgno); */ + return (NULL); + } + tp->prevpg = r->pgno; + mpool_put(t->bt_mp, tp, MPOOL_DIRTY); + } + + /* + * Split right. The key/data pairs aren't sorted in the btree page so + * it's simpler to copy the data from the split page onto two new pages + * instead of copying half the data to the right page and compacting + * the left page in place. Since the left page can't change, we have + * to swap the original and the allocated left page after the split. + */ + tp = bt_psplit(t, h, l, r, skip, ilen); + + /* Move the new left page onto the old left page. */ + memmove(h, l, t->bt_psize); + if (tp == l) + tp = h; + free(l); + + *lp = h; + *rp = r; + return (tp); +} + +/* + * BT_ROOT -- Split the root page of a btree. + * + * Parameters: + * t: tree + * h: root page + * lp: pointer to left page pointer + * rp: pointer to right page pointer + * skip: pointer to index to leave open + * ilen: insert length + * + * Returns: + * Pointer to page in which to insert or NULL on error. + */ +static PAGE * +bt_root(t, h, lp, rp, skip, ilen) + BTREE *t; + PAGE *h, **lp, **rp; + indx_t *skip; + size_t ilen; +{ + PAGE *l, *r, *tp; + pgno_t lnpg, rnpg; + +#ifdef STATISTICS + ++bt_split; + ++bt_rootsplit; +#endif + /* Put the new left and right pages for the split into place. */ + if ((l = __bt_new(t, &lnpg)) == NULL || + (r = __bt_new(t, &rnpg)) == NULL) + return (NULL); + l->pgno = lnpg; + r->pgno = rnpg; + l->nextpg = r->pgno; + r->prevpg = l->pgno; + l->prevpg = r->nextpg = P_INVALID; + l->lower = r->lower = BTDATAOFF; + l->upper = r->upper = t->bt_psize; + l->flags = r->flags = h->flags & P_TYPE; + + /* Split the root page. */ + tp = bt_psplit(t, h, l, r, skip, ilen); + + *lp = l; + *rp = r; + return (tp); +} + +/* + * BT_RROOT -- Fix up the recno root page after it has been split. + * + * Parameters: + * t: tree + * h: root page + * l: left page + * r: right page + * + * Returns: + * RET_ERROR, RET_SUCCESS + */ +static int +bt_rroot(t, h, l, r) + BTREE *t; + PAGE *h, *l, *r; +{ + char *dest; + + /* Insert the left and right keys, set the header information. */ + h->linp[0] = h->upper = t->bt_psize - NRINTERNAL; + dest = (char *)h + h->upper; + WR_RINTERNAL(dest, + l->flags & P_RLEAF ? NEXTINDEX(l) : rec_total(l), l->pgno); + + h->linp[1] = h->upper -= NRINTERNAL; + dest = (char *)h + h->upper; + WR_RINTERNAL(dest, + r->flags & P_RLEAF ? NEXTINDEX(r) : rec_total(r), r->pgno); + + h->lower = BTDATAOFF + 2 * sizeof(indx_t); + + /* Unpin the root page, set to recno internal page. */ + h->flags &= ~P_TYPE; + h->flags |= P_RINTERNAL; + mpool_put(t->bt_mp, h, MPOOL_DIRTY); + + return (RET_SUCCESS); +} + +/* + * BT_BROOT -- Fix up the btree root page after it has been split. + * + * Parameters: + * t: tree + * h: root page + * l: left page + * r: right page + * + * Returns: + * RET_ERROR, RET_SUCCESS + */ +static int +bt_broot(t, h, l, r) + BTREE *t; + PAGE *h, *l, *r; +{ + BINTERNAL *bi; + BLEAF *bl; + u_int32_t nbytes; + char *dest; + + /* + * If the root page was a leaf page, change it into an internal page. + * We copy the key we split on (but not the key's data, in the case of + * a leaf page) to the new root page. + * + * The btree comparison code guarantees that the left-most key on any + * level of the tree is never used, so it doesn't need to be filled in. + */ + nbytes = NBINTERNAL(0); + h->linp[0] = h->upper = t->bt_psize - nbytes; + dest = (char *)h + h->upper; + WR_BINTERNAL(dest, 0, l->pgno, 0); + + switch (h->flags & P_TYPE) { + case P_BLEAF: + bl = GETBLEAF(r, 0); + nbytes = NBINTERNAL(bl->ksize); + h->linp[1] = h->upper -= nbytes; + dest = (char *)h + h->upper; + WR_BINTERNAL(dest, bl->ksize, r->pgno, 0); + memmove(dest, bl->bytes, bl->ksize); + + /* + * If the key is on an overflow page, mark the overflow chain + * so it isn't deleted when the leaf copy of the key is deleted. + */ + if (bl->flags & P_BIGKEY && + bt_preserve(t, *(pgno_t *)bl->bytes) == RET_ERROR) + return (RET_ERROR); + break; + case P_BINTERNAL: + bi = GETBINTERNAL(r, 0); + nbytes = NBINTERNAL(bi->ksize); + h->linp[1] = h->upper -= nbytes; + dest = (char *)h + h->upper; + memmove(dest, bi, nbytes); + ((BINTERNAL *)dest)->pgno = r->pgno; + break; + default: + abort(); + } + + /* There are two keys on the page. */ + h->lower = BTDATAOFF + 2 * sizeof(indx_t); + + /* Unpin the root page, set to btree internal page. */ + h->flags &= ~P_TYPE; + h->flags |= P_BINTERNAL; + mpool_put(t->bt_mp, h, MPOOL_DIRTY); + + return (RET_SUCCESS); +} + +/* + * BT_PSPLIT -- Do the real work of splitting the page. + * + * Parameters: + * t: tree + * h: page to be split + * l: page to put lower half of data + * r: page to put upper half of data + * pskip: pointer to index to leave open + * ilen: insert length + * + * Returns: + * Pointer to page in which to insert. + */ +static PAGE * +bt_psplit(t, h, l, r, pskip, ilen) + BTREE *t; + PAGE *h, *l, *r; + indx_t *pskip; + size_t ilen; +{ + BINTERNAL *bi; + BLEAF *bl; + CURSOR *c; + RLEAF *rl; + PAGE *rval; + void *src = 0; + indx_t full, half, nxt, off, skip, top, used; + u_int32_t nbytes; + int bigkeycnt, isbigkey; + + /* + * Split the data to the left and right pages. Leave the skip index + * open. Additionally, make some effort not to split on an overflow + * key. This makes internal page processing faster and can save + * space as overflow keys used by internal pages are never deleted. + */ + bigkeycnt = 0; + skip = *pskip; + full = t->bt_psize - BTDATAOFF; + half = full / 2; + used = 0; + for (nxt = off = 0, top = NEXTINDEX(h); nxt < top; ++off) { + if (skip == off) { + nbytes = ilen; + isbigkey = 0; /* XXX: not really known. */ + } else + switch (h->flags & P_TYPE) { + case P_BINTERNAL: + src = bi = GETBINTERNAL(h, nxt); + nbytes = NBINTERNAL(bi->ksize); + isbigkey = bi->flags & P_BIGKEY; + break; + case P_BLEAF: + src = bl = GETBLEAF(h, nxt); + nbytes = NBLEAF(bl); + isbigkey = bl->flags & P_BIGKEY; + break; + case P_RINTERNAL: + src = GETRINTERNAL(h, nxt); + nbytes = NRINTERNAL; + isbigkey = 0; + break; + case P_RLEAF: + src = rl = GETRLEAF(h, nxt); + nbytes = NRLEAF(rl); + isbigkey = 0; + break; + default: + abort(); + } + + /* + * If the key/data pairs are substantial fractions of the max + * possible size for the page, it's possible to get situations + * where we decide to try and copy too much onto the left page. + * Make sure that doesn't happen. + */ + if ((skip <= off && used + nbytes + sizeof(indx_t) >= full) + || nxt == top - 1) { + --off; + break; + } + + /* Copy the key/data pair, if not the skipped index. */ + if (skip != off) { + ++nxt; + + l->linp[off] = l->upper -= nbytes; + memmove((char *)l + l->upper, src, nbytes); + } + + used += nbytes + sizeof(indx_t); + if (used >= half) { + if (!isbigkey || bigkeycnt == 3) + break; + else + ++bigkeycnt; + } + } + + /* + * Off is the last offset that's valid for the left page. + * Nxt is the first offset to be placed on the right page. + */ + l->lower += (off + 1) * sizeof(indx_t); + + /* + * If splitting the page that the cursor was on, the cursor has to be + * adjusted to point to the same record as before the split. If the + * cursor is at or past the skipped slot, the cursor is incremented by + * one. If the cursor is on the right page, it is decremented by the + * number of records split to the left page. + */ + c = &t->bt_cursor; + if (F_ISSET(c, CURS_INIT) && c->pg.pgno == h->pgno) { + if (c->pg.index >= skip) + ++c->pg.index; + if (c->pg.index < nxt) /* Left page. */ + c->pg.pgno = l->pgno; + else { /* Right page. */ + c->pg.pgno = r->pgno; + c->pg.index -= nxt; + } + } + + /* + * If the skipped index was on the left page, just return that page. + * Otherwise, adjust the skip index to reflect the new position on + * the right page. + */ + if (skip <= off) { + skip = 0; + rval = l; + } else { + rval = r; + *pskip -= nxt; + } + + for (off = 0; nxt < top; ++off) { + if (skip == nxt) { + ++off; + skip = 0; + } + switch (h->flags & P_TYPE) { + case P_BINTERNAL: + src = bi = GETBINTERNAL(h, nxt); + nbytes = NBINTERNAL(bi->ksize); + break; + case P_BLEAF: + src = bl = GETBLEAF(h, nxt); + nbytes = NBLEAF(bl); + break; + case P_RINTERNAL: + src = GETRINTERNAL(h, nxt); + nbytes = NRINTERNAL; + break; + case P_RLEAF: + src = rl = GETRLEAF(h, nxt); + nbytes = NRLEAF(rl); + break; + default: + abort(); + } + ++nxt; + r->linp[off] = r->upper -= nbytes; + memmove((char *)r + r->upper, src, nbytes); + } + r->lower += off * sizeof(indx_t); + + /* If the key is being appended to the page, adjust the index. */ + if (skip == top) + r->lower += sizeof(indx_t); + + return (rval); +} + +/* + * BT_PRESERVE -- Mark a chain of pages as used by an internal node. + * + * Chains of indirect blocks pointed to by leaf nodes get reclaimed when the + * record that references them gets deleted. Chains pointed to by internal + * pages never get deleted. This routine marks a chain as pointed to by an + * internal page. + * + * Parameters: + * t: tree + * pg: page number of first page in the chain. + * + * Returns: + * RET_SUCCESS, RET_ERROR. + */ +static int +bt_preserve(t, pg) + BTREE *t; + pgno_t pg; +{ + PAGE *h; + + if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) + return (RET_ERROR); + h->flags |= P_PRESERVE; + mpool_put(t->bt_mp, h, MPOOL_DIRTY); + return (RET_SUCCESS); +} + +/* + * REC_TOTAL -- Return the number of recno entries below a page. + * + * Parameters: + * h: page + * + * Returns: + * The number of recno entries below a page. + * + * XXX + * These values could be set by the bt_psplit routine. The problem is that the + * entry has to be popped off of the stack etc. or the values have to be passed + * all the way back to bt_split/bt_rroot and it's not very clean. + */ +static recno_t +rec_total(h) + PAGE *h; +{ + recno_t recs; + indx_t nxt, top; + + for (recs = 0, nxt = 0, top = NEXTINDEX(h); nxt < top; ++nxt) + recs += GETRINTERNAL(h, nxt)->nrecs; + return (recs); +} diff --git a/utils/db1-ast/btree/bt_utils.c b/utils/db1-ast/btree/bt_utils.c new file mode 100644 index 000000000..2ecb5e678 --- /dev/null +++ b/utils/db1-ast/btree/bt_utils.c @@ -0,0 +1,260 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Mike Olson. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)bt_utils.c 8.8 (Berkeley) 7/20/94"; +#endif /* LIBC_SCCS and not lint */ + +#include + +#include +#include +#include + +#include "../include/db.h" +#include "btree.h" + +/* + * __bt_ret -- + * Build return key/data pair. + * + * Parameters: + * t: tree + * e: key/data pair to be returned + * key: user's key structure (NULL if not to be filled in) + * rkey: memory area to hold key + * data: user's data structure (NULL if not to be filled in) + * rdata: memory area to hold data + * copy: always copy the key/data item + * + * Returns: + * RET_SUCCESS, RET_ERROR. + */ +int +__bt_ret(t, e, key, rkey, data, rdata, copy) + BTREE *t; + EPG *e; + DBT *key, *rkey, *data, *rdata; + int copy; +{ + BLEAF *bl; + void *p; + + bl = GETBLEAF(e->page, e->index); + + /* + * We must copy big keys/data to make them contiguous. Otherwise, + * leave the page pinned and don't copy unless the user specified + * concurrent access. + */ + if (key == NULL) + goto dataonly; + + if (bl->flags & P_BIGKEY) { + if (__ovfl_get(t, bl->bytes, + &key->size, &rkey->data, &rkey->size)) + return (RET_ERROR); + key->data = rkey->data; + } else if (copy || F_ISSET(t, B_DB_LOCK)) { + if (bl->ksize > rkey->size) { + p = (void *)(rkey->data == NULL ? + malloc(bl->ksize) : realloc(rkey->data, bl->ksize)); + if (p == NULL) + return (RET_ERROR); + rkey->data = p; + rkey->size = bl->ksize; + } + memmove(rkey->data, bl->bytes, bl->ksize); + key->size = bl->ksize; + key->data = rkey->data; + } else { + key->size = bl->ksize; + key->data = bl->bytes; + } + +dataonly: + if (data == NULL) + return (RET_SUCCESS); + + if (bl->flags & P_BIGDATA) { + if (__ovfl_get(t, bl->bytes + bl->ksize, + &data->size, &rdata->data, &rdata->size)) + return (RET_ERROR); + data->data = rdata->data; + } else if (copy || F_ISSET(t, B_DB_LOCK)) { + /* Use +1 in case the first record retrieved is 0 length. */ + if (bl->dsize + 1 > rdata->size) { + p = (void *)(rdata->data == NULL ? + malloc(bl->dsize + 1) : + realloc(rdata->data, bl->dsize + 1)); + if (p == NULL) + return (RET_ERROR); + rdata->data = p; + rdata->size = bl->dsize + 1; + } + memmove(rdata->data, bl->bytes + bl->ksize, bl->dsize); + data->size = bl->dsize; + data->data = rdata->data; + } else { + data->size = bl->dsize; + data->data = bl->bytes + bl->ksize; + } + + return (RET_SUCCESS); +} + +/* + * __BT_CMP -- Compare a key to a given record. + * + * Parameters: + * t: tree + * k1: DBT pointer of first arg to comparison + * e: pointer to EPG for comparison + * + * Returns: + * < 0 if k1 is < record + * = 0 if k1 is = record + * > 0 if k1 is > record + */ +int +__bt_cmp(t, k1, e) + BTREE *t; + const DBT *k1; + EPG *e; +{ + BINTERNAL *bi; + BLEAF *bl; + DBT k2; + PAGE *h; + void *bigkey; + + /* + * The left-most key on internal pages, at any level of the tree, is + * guaranteed by the following code to be less than any user key. + * This saves us from having to update the leftmost key on an internal + * page when the user inserts a new key in the tree smaller than + * anything we've yet seen. + */ + h = e->page; + if (e->index == 0 && h->prevpg == P_INVALID && !(h->flags & P_BLEAF)) + return (1); + + bigkey = NULL; + if (h->flags & P_BLEAF) { + bl = GETBLEAF(h, e->index); + if (bl->flags & P_BIGKEY) + bigkey = bl->bytes; + else { + k2.data = bl->bytes; + k2.size = bl->ksize; + } + } else { + bi = GETBINTERNAL(h, e->index); + if (bi->flags & P_BIGKEY) + bigkey = bi->bytes; + else { + k2.data = bi->bytes; + k2.size = bi->ksize; + } + } + + if (bigkey) { + if (__ovfl_get(t, bigkey, + &k2.size, &t->bt_rdata.data, &t->bt_rdata.size)) + return (RET_ERROR); + k2.data = t->bt_rdata.data; + } + return ((*t->bt_cmp)(k1, &k2)); +} + +/* + * __BT_DEFCMP -- Default comparison routine. + * + * Parameters: + * a: DBT #1 + * b: DBT #2 + * + * Returns: + * < 0 if a is < b + * = 0 if a is = b + * > 0 if a is > b + */ +int +__bt_defcmp(a, b) + const DBT *a, *b; +{ + register size_t len; + register u_char *p1, *p2; + + /* + * XXX + * If a size_t doesn't fit in an int, this routine can lose. + * What we need is a integral type which is guaranteed to be + * larger than a size_t, and there is no such thing. + */ + len = MIN(a->size, b->size); + for (p1 = a->data, p2 = b->data; len--; ++p1, ++p2) + if (*p1 != *p2) + return ((int)*p1 - (int)*p2); + return ((int)a->size - (int)b->size); +} + +/* + * __BT_DEFPFX -- Default prefix routine. + * + * Parameters: + * a: DBT #1 + * b: DBT #2 + * + * Returns: + * Number of bytes needed to distinguish b from a. + */ +size_t +__bt_defpfx(a, b) + const DBT *a, *b; +{ + register u_char *p1, *p2; + register size_t cnt, len; + + cnt = 1; + len = MIN(a->size, b->size); + for (p1 = a->data, p2 = b->data; len--; ++p1, ++p2, ++cnt) + if (*p1 != *p2) + return (cnt); + + /* a->size must be <= b->size, or they wouldn't be in this order. */ + return (a->size < b->size ? a->size + 1 : a->size); +} diff --git a/utils/db1-ast/btree/btree.h b/utils/db1-ast/btree/btree.h new file mode 100644 index 000000000..1f4a9ec91 --- /dev/null +++ b/utils/db1-ast/btree/btree.h @@ -0,0 +1,391 @@ +/*- + * Copyright (c) 1991, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Mike Olson. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)btree.h 8.11 (Berkeley) 8/17/94 + */ + +/* Macros to set/clear/test flags. */ +#define F_SET(p, f) (p)->flags |= (f) +#define F_CLR(p, f) (p)->flags &= ~(f) +#define F_ISSET(p, f) ((p)->flags & (f)) + +#include + +#define mpool_open __mpool_open +#define mpool_filter __mpool_filter +#define mpool_new __mpool_new +#define mpool_get __mpool_get +#define mpool_put __mpool_put +#define mpool_sync __mpool_sync +#define mpool_close __mpool_close + +#define DEFMINKEYPAGE (2) /* Minimum keys per page */ +#define MINCACHE (5) /* Minimum cached pages */ +#define MINPSIZE (512) /* Minimum page size */ + +/* + * Page 0 of a btree file contains a copy of the meta-data. This page is also + * used as an out-of-band page, i.e. page pointers that point to nowhere point + * to page 0. Page 1 is the root of the btree. + */ +#define P_INVALID 0 /* Invalid tree page number. */ +#define P_META 0 /* Tree metadata page number. */ +#define P_ROOT 1 /* Tree root page number. */ + +/* + * There are five page layouts in the btree: btree internal pages (BINTERNAL), + * btree leaf pages (BLEAF), recno internal pages (RINTERNAL), recno leaf pages + * (RLEAF) and overflow pages. All five page types have a page header (PAGE). + * This implementation requires that values within structures NOT be padded. + * (ANSI C permits random padding.) If your compiler pads randomly you'll have + * to do some work to get this package to run. + */ +typedef struct _page { + pgno_t pgno; /* this page's page number */ + pgno_t prevpg; /* left sibling */ + pgno_t nextpg; /* right sibling */ + +#define P_BINTERNAL 0x01 /* btree internal page */ +#define P_BLEAF 0x02 /* leaf page */ +#define P_OVERFLOW 0x04 /* overflow page */ +#define P_RINTERNAL 0x08 /* recno internal page */ +#define P_RLEAF 0x10 /* leaf page */ +#define P_TYPE 0x1f /* type mask */ +#define P_PRESERVE 0x20 /* never delete this chain of pages */ + u_int32_t flags; + + indx_t lower; /* lower bound of free space on page */ + indx_t upper; /* upper bound of free space on page */ + indx_t linp[1]; /* indx_t-aligned VAR. LENGTH DATA */ +} PAGE; + +/* First and next index. */ +#define BTDATAOFF \ + (sizeof(pgno_t) + sizeof(pgno_t) + sizeof(pgno_t) + \ + sizeof(u_int32_t) + sizeof(indx_t) + sizeof(indx_t)) +#define NEXTINDEX(p) (((p)->lower - BTDATAOFF) / sizeof(indx_t)) + +/* + * For pages other than overflow pages, there is an array of offsets into the + * rest of the page immediately following the page header. Each offset is to + * an item which is unique to the type of page. The h_lower offset is just + * past the last filled-in index. The h_upper offset is the first item on the + * page. Offsets are from the beginning of the page. + * + * If an item is too big to store on a single page, a flag is set and the item + * is a { page, size } pair such that the page is the first page of an overflow + * chain with size bytes of item. Overflow pages are simply bytes without any + * external structure. + * + * The page number and size fields in the items are pgno_t-aligned so they can + * be manipulated without copying. (This presumes that 32 bit items can be + * manipulated on this system.) + */ +#define LALIGN(n) (((n) + sizeof(pgno_t) - 1) & ~(sizeof(pgno_t) - 1)) +#define NOVFLSIZE (sizeof(pgno_t) + sizeof(u_int32_t)) + +/* + * For the btree internal pages, the item is a key. BINTERNALs are {key, pgno} + * pairs, such that the key compares less than or equal to all of the records + * on that page. For a tree without duplicate keys, an internal page with two + * consecutive keys, a and b, will have all records greater than or equal to a + * and less than b stored on the page associated with a. Duplicate keys are + * somewhat special and can cause duplicate internal and leaf page records and + * some minor modifications of the above rule. + */ +typedef struct _binternal { + u_int32_t ksize; /* key size */ + pgno_t pgno; /* page number stored on */ +#define P_BIGDATA 0x01 /* overflow data */ +#define P_BIGKEY 0x02 /* overflow key */ + u_char flags; + char bytes[1]; /* data */ +} BINTERNAL; + +/* Get the page's BINTERNAL structure at index indx. */ +#define GETBINTERNAL(pg, indx) \ + ((BINTERNAL *)((char *)(pg) + (pg)->linp[indx])) + +/* Get the number of bytes in the entry. */ +#define NBINTERNAL(len) \ + LALIGN(sizeof(u_int32_t) + sizeof(pgno_t) + sizeof(u_char) + (len)) + +/* Copy a BINTERNAL entry to the page. */ +#define WR_BINTERNAL(p, size, pgno, flags) { \ + *(u_int32_t *)p = size; \ + p += sizeof(u_int32_t); \ + *(pgno_t *)p = pgno; \ + p += sizeof(pgno_t); \ + *(u_char *)p = flags; \ + p += sizeof(u_char); \ +} + +/* + * For the recno internal pages, the item is a page number with the number of + * keys found on that page and below. + */ +typedef struct _rinternal { + recno_t nrecs; /* number of records */ + pgno_t pgno; /* page number stored below */ +} RINTERNAL; + +/* Get the page's RINTERNAL structure at index indx. */ +#define GETRINTERNAL(pg, indx) \ + ((RINTERNAL *)((char *)(pg) + (pg)->linp[indx])) + +/* Get the number of bytes in the entry. */ +#define NRINTERNAL \ + LALIGN(sizeof(recno_t) + sizeof(pgno_t)) + +/* Copy a RINTERNAL entry to the page. */ +#define WR_RINTERNAL(p, nrecs, pgno) { \ + *(recno_t *)p = nrecs; \ + p += sizeof(recno_t); \ + *(pgno_t *)p = pgno; \ +} + +/* For the btree leaf pages, the item is a key and data pair. */ +typedef struct _bleaf { + u_int32_t ksize; /* size of key */ + u_int32_t dsize; /* size of data */ + u_char flags; /* P_BIGDATA, P_BIGKEY */ + char bytes[1]; /* data */ +} BLEAF; + +/* Get the page's BLEAF structure at index indx. */ +#define GETBLEAF(pg, indx) \ + ((BLEAF *)((char *)(pg) + (pg)->linp[indx])) + +/* Get the number of bytes in the entry. */ +#define NBLEAF(p) NBLEAFDBT((p)->ksize, (p)->dsize) + +/* Get the number of bytes in the user's key/data pair. */ +#define NBLEAFDBT(ksize, dsize) \ + LALIGN(sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(u_char) + \ + (ksize) + (dsize)) + +/* Copy a BLEAF entry to the page. */ +#define WR_BLEAF(p, key, data, flags) { \ + *(u_int32_t *)p = key->size; \ + p += sizeof(u_int32_t); \ + *(u_int32_t *)p = data->size; \ + p += sizeof(u_int32_t); \ + *(u_char *)p = flags; \ + p += sizeof(u_char); \ + memmove(p, key->data, key->size); \ + p += key->size; \ + memmove(p, data->data, data->size); \ +} + +/* For the recno leaf pages, the item is a data entry. */ +typedef struct _rleaf { + u_int32_t dsize; /* size of data */ + u_char flags; /* P_BIGDATA */ + char bytes[1]; +} RLEAF; + +/* Get the page's RLEAF structure at index indx. */ +#define GETRLEAF(pg, indx) \ + ((RLEAF *)((char *)(pg) + (pg)->linp[indx])) + +/* Get the number of bytes in the entry. */ +#define NRLEAF(p) NRLEAFDBT((p)->dsize) + +/* Get the number of bytes from the user's data. */ +#define NRLEAFDBT(dsize) \ + LALIGN(sizeof(u_int32_t) + sizeof(u_char) + (dsize)) + +/* Copy a RLEAF entry to the page. */ +#define WR_RLEAF(p, data, flags) { \ + *(u_int32_t *)p = data->size; \ + p += sizeof(u_int32_t); \ + *(u_char *)p = flags; \ + p += sizeof(u_char); \ + memmove(p, data->data, data->size); \ +} + +/* + * A record in the tree is either a pointer to a page and an index in the page + * or a page number and an index. These structures are used as a cursor, stack + * entry and search returns as well as to pass records to other routines. + * + * One comment about searches. Internal page searches must find the largest + * record less than key in the tree so that descents work. Leaf page searches + * must find the smallest record greater than key so that the returned index + * is the record's correct position for insertion. + */ +typedef struct _epgno { + pgno_t pgno; /* the page number */ + indx_t index; /* the index on the page */ +} EPGNO; + +typedef struct _epg { + PAGE *page; /* the (pinned) page */ + indx_t index; /* the index on the page */ +} EPG; + +/* + * About cursors. The cursor (and the page that contained the key/data pair + * that it referenced) can be deleted, which makes things a bit tricky. If + * there are no duplicates of the cursor key in the tree (i.e. B_NODUPS is set + * or there simply aren't any duplicates of the key) we copy the key that it + * referenced when it's deleted, and reacquire a new cursor key if the cursor + * is used again. If there are duplicates keys, we move to the next/previous + * key, and set a flag so that we know what happened. NOTE: if duplicate (to + * the cursor) keys are added to the tree during this process, it is undefined + * if they will be returned or not in a cursor scan. + * + * The flags determine the possible states of the cursor: + * + * CURS_INIT The cursor references *something*. + * CURS_ACQUIRE The cursor was deleted, and a key has been saved so that + * we can reacquire the right position in the tree. + * CURS_AFTER, CURS_BEFORE + * The cursor was deleted, and now references a key/data pair + * that has not yet been returned, either before or after the + * deleted key/data pair. + * XXX + * This structure is broken out so that we can eventually offer multiple + * cursors as part of the DB interface. + */ +typedef struct _cursor { + EPGNO pg; /* B: Saved tree reference. */ + DBT key; /* B: Saved key, or key.data == NULL. */ + recno_t rcursor; /* R: recno cursor (1-based) */ + +#define CURS_ACQUIRE 0x01 /* B: Cursor needs to be reacquired. */ +#define CURS_AFTER 0x02 /* B: Unreturned cursor after key. */ +#define CURS_BEFORE 0x04 /* B: Unreturned cursor before key. */ +#define CURS_INIT 0x08 /* RB: Cursor initialized. */ + u_int8_t flags; +} CURSOR; + +/* + * The metadata of the tree. The nrecs field is used only by the RECNO code. + * This is because the btree doesn't really need it and it requires that every + * put or delete call modify the metadata. + */ +typedef struct _btmeta { + u_int32_t magic; /* magic number */ + u_int32_t version; /* version */ + u_int32_t psize; /* page size */ + u_int32_t free; /* page number of first free page */ + u_int32_t nrecs; /* R: number of records */ + +#define SAVEMETA (B_NODUPS | R_RECNO) + u_int32_t flags; /* bt_flags & SAVEMETA */ +} BTMETA; + +/* The in-memory btree/recno data structure. */ +typedef struct _btree { + MPOOL *bt_mp; /* memory pool cookie */ + + DB *bt_dbp; /* pointer to enclosing DB */ + + EPG bt_cur; /* current (pinned) page */ + PAGE *bt_pinned; /* page pinned across calls */ + + CURSOR bt_cursor; /* cursor */ + +#define BT_PUSH(t, p, i) { \ + t->bt_sp->pgno = p; \ + t->bt_sp->index = i; \ + ++t->bt_sp; \ +} +#define BT_POP(t) (t->bt_sp == t->bt_stack ? NULL : --t->bt_sp) +#define BT_CLR(t) (t->bt_sp = t->bt_stack) + EPGNO bt_stack[50]; /* stack of parent pages */ + EPGNO *bt_sp; /* current stack pointer */ + + DBT bt_rkey; /* returned key */ + DBT bt_rdata; /* returned data */ + + int bt_fd; /* tree file descriptor */ + + pgno_t bt_free; /* next free page */ + u_int32_t bt_psize; /* page size */ + indx_t bt_ovflsize; /* cut-off for key/data overflow */ + int bt_lorder; /* byte order */ + /* sorted order */ + enum { NOT, BACK, FORWARD } bt_order; + EPGNO bt_last; /* last insert */ + + /* B: key comparison function */ + int (*bt_cmp) __P((const DBT *, const DBT *)); + /* B: prefix comparison function */ + size_t (*bt_pfx) __P((const DBT *, const DBT *)); + /* R: recno input function */ + int (*bt_irec) __P((struct _btree *, recno_t)); + + FILE *bt_rfp; /* R: record FILE pointer */ + int bt_rfd; /* R: record file descriptor */ + + caddr_t bt_cmap; /* R: current point in mapped space */ + caddr_t bt_smap; /* R: start of mapped space */ + caddr_t bt_emap; /* R: end of mapped space */ + size_t bt_msize; /* R: size of mapped region. */ + + recno_t bt_nrecs; /* R: number of records */ + size_t bt_reclen; /* R: fixed record length */ + u_char bt_bval; /* R: delimiting byte/pad character */ + +/* + * NB: + * B_NODUPS and R_RECNO are stored on disk, and may not be changed. + */ +#define B_INMEM 0x00001 /* in-memory tree */ +#define B_METADIRTY 0x00002 /* need to write metadata */ +#define B_MODIFIED 0x00004 /* tree modified */ +#define B_NEEDSWAP 0x00008 /* if byte order requires swapping */ +#define B_RDONLY 0x00010 /* read-only tree */ + +#define B_NODUPS 0x00020 /* no duplicate keys permitted */ +#define R_RECNO 0x00080 /* record oriented tree */ + +#define R_CLOSEFP 0x00040 /* opened a file pointer */ +#define R_EOF 0x00100 /* end of input file reached. */ +#define R_FIXLEN 0x00200 /* fixed length records */ +#define R_MEMMAPPED 0x00400 /* memory mapped file. */ +#define R_INMEM 0x00800 /* in-memory file */ +#define R_MODIFIED 0x01000 /* modified file */ +#define R_RDONLY 0x02000 /* read-only file */ + +#define B_DB_LOCK 0x04000 /* DB_LOCK specified. */ +#define B_DB_SHMEM 0x08000 /* DB_SHMEM specified. */ +#define B_DB_TXN 0x10000 /* DB_TXN specified. */ + u_int32_t flags; +} BTREE; + +#include "extern.h" diff --git a/utils/db1-ast/btree/extern.h b/utils/db1-ast/btree/extern.h new file mode 100644 index 000000000..ebd9c5492 --- /dev/null +++ b/utils/db1-ast/btree/extern.h @@ -0,0 +1,70 @@ +/*- + * Copyright (c) 1991, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)extern.h 8.10 (Berkeley) 7/20/94 + */ + +int __bt_close __P((DB *)); +int __bt_cmp __P((BTREE *, const DBT *, EPG *)); +int __bt_crsrdel __P((BTREE *, EPGNO *)); +int __bt_defcmp __P((const DBT *, const DBT *)); +size_t __bt_defpfx __P((const DBT *, const DBT *)); +int __bt_delete __P((const DB *, const DBT *, u_int)); +int __bt_dleaf __P((BTREE *, const DBT *, PAGE *, u_int)); +int __bt_fd __P((const DB *)); +int __bt_free __P((BTREE *, PAGE *)); +int __bt_get __P((const DB *, const DBT *, DBT *, u_int)); +PAGE *__bt_new __P((BTREE *, pgno_t *)); +void __bt_pgin __P((void *, pgno_t, void *)); +void __bt_pgout __P((void *, pgno_t, void *)); +int __bt_push __P((BTREE *, pgno_t, int)); +int __bt_put __P((const DB *dbp, DBT *, const DBT *, u_int)); +int __bt_ret __P((BTREE *, EPG *, DBT *, DBT *, DBT *, DBT *, int)); +EPG *__bt_search __P((BTREE *, const DBT *, int *)); +int __bt_seq __P((const DB *, DBT *, DBT *, u_int)); +void __bt_setcur __P((BTREE *, pgno_t, u_int)); +int __bt_split __P((BTREE *, PAGE *, + const DBT *, const DBT *, int, size_t, u_int32_t)); +int __bt_sync __P((const DB *, u_int)); + +int __ovfl_delete __P((BTREE *, void *)); +int __ovfl_get __P((BTREE *, void *, size_t *, void **, size_t *)); +int __ovfl_put __P((BTREE *, const DBT *, pgno_t *)); + +#ifdef DEBUG +void __bt_dnpage __P((DB *, pgno_t)); +void __bt_dpage __P((PAGE *)); +void __bt_dump __P((DB *)); +#endif +#ifdef STATISTICS +void __bt_stat __P((DB *)); +#endif diff --git a/utils/db1-ast/db/db.c b/utils/db1-ast/db/db.c new file mode 100644 index 000000000..8c0584d4c --- /dev/null +++ b/utils/db1-ast/db/db.c @@ -0,0 +1,103 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)db.c 8.4 (Berkeley) 2/21/94"; +#endif /* LIBC_SCCS and not lint */ + +#include + +#include +#include +#include +#include + +#include "../include/db.h" + +DB * +dbopen(fname, flags, mode, type, openinfo) + const char *fname; + int flags, mode; + DBTYPE type; + const void *openinfo; +{ + +#define DB_FLAGS (DB_LOCK | DB_SHMEM | DB_TXN) +#define USE_OPEN_FLAGS \ + (O_CREAT | O_EXCL | O_EXLOCK | O_NONBLOCK | O_RDONLY | \ + O_RDWR | O_SHLOCK | O_TRUNC) + + if ((flags & ~(USE_OPEN_FLAGS | DB_FLAGS)) == 0) + switch (type) { + case DB_BTREE: + return (__bt_open(fname, flags & USE_OPEN_FLAGS, + mode, openinfo, flags & DB_FLAGS)); + case DB_HASH: + return (__hash_open(fname, flags & USE_OPEN_FLAGS, + mode, openinfo, flags & DB_FLAGS)); + case DB_RECNO: + return (__rec_open(fname, flags & USE_OPEN_FLAGS, + mode, openinfo, flags & DB_FLAGS)); + } + errno = EINVAL; + return (NULL); +} + +static int +__dberr __P((void)) +{ + return (RET_ERROR); +} + +/* + * __DBPANIC -- Stop. + * + * Parameters: + * dbp: pointer to the DB structure. + */ +void +__dbpanic(dbp) + DB *dbp; +{ + /* The only thing that can succeed is a close. */ + dbp->del = (int (*)__P((const struct __db *, + const DBT *, u_int))) __dberr; + dbp->get = (int (*)__P((const struct __db *, + const DBT *, DBT *, u_int))) __dberr; + dbp->put = (int (*)__P((const struct __db *, + DBT *, const DBT *, u_int))) __dberr; + dbp->seq = (int (*)__P((const struct __db *, + DBT *, DBT *, u_int))) __dberr; + dbp->sync = (int (*)__P((const struct __db *, u_int))) __dberr; + dbp->fd = (int (*)__P((const struct __db *))) __dberr; +} diff --git a/utils/db1-ast/hash/README b/utils/db1-ast/hash/README new file mode 100644 index 000000000..f29ccf7e1 --- /dev/null +++ b/utils/db1-ast/hash/README @@ -0,0 +1,72 @@ +# @(#)README 8.1 (Berkeley) 6/4/93 + +This package implements a superset of the hsearch and dbm/ndbm libraries. + +Test Programs: + All test programs which need key/data pairs expect them entered + with key and data on separate lines + + tcreat3.c + Takes + bucketsize (bsize), + fill factor (ffactor), and + initial number of elements (nelem). + Creates a hash table named hashtest containing the + keys/data pairs entered from standard in. + thash4.c + Takes + bucketsize (bsize), + fill factor (ffactor), + initial number of elements (nelem) + bytes of cache (ncached), and + file from which to read data (fname) + Creates a table from the key/data pairs on standard in and + then does a read of each key/data in fname + tdel.c + Takes + bucketsize (bsize), and + fill factor (ffactor). + file from which to read data (fname) + Reads each key/data pair from fname and deletes the + key from the hash table hashtest + tseq.c + Reads the key/data pairs in the file hashtest and writes them + to standard out. + tread2.c + Takes + butes of cache (ncached). + Reads key/data pairs from standard in and looks them up + in the file hashtest. + tverify.c + Reads key/data pairs from standard in, looks them up + in the file hashtest, and verifies that the data is + correct. + +NOTES: + +The file search.h is provided for using the hsearch compatible interface +on BSD systems. On System V derived systems, search.h should appear in +/usr/include. + +The man page ../man/db.3 explains the interface to the hashing system. +The file hash.ps is a postscript copy of a paper explaining +the history, implementation, and performance of the hash package. + +"bugs" or idiosyncracies + +If you have a lot of overflows, it is possible to run out of overflow +pages. Currently, this will cause a message to be printed on stderr. +Eventually, this will be indicated by a return error code. + +If you are using the ndbm interface and exit without flushing or closing the +file, you may lose updates since the package buffers all writes. Also, +the db interface only creates a single database file. To avoid overwriting +the user's original file, the suffix ".db" is appended to the file name +passed to dbm_open. Additionally, if your code "knows" about the historic +.dir and .pag files, it will break. + +There is a fundamental difference between this package and the old hsearch. +Hsearch requires the user to maintain the keys and data in the application's +allocated memory while hash takes care of all storage management. The down +side is that the byte strings passed in the ENTRY structure must be null +terminated (both the keys and the data). diff --git a/utils/db1-ast/hash/extern.h b/utils/db1-ast/hash/extern.h new file mode 100644 index 000000000..4f1f23d67 --- /dev/null +++ b/utils/db1-ast/hash/extern.h @@ -0,0 +1,65 @@ +/*- + * Copyright (c) 1991, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)extern.h 8.4 (Berkeley) 6/16/94 + */ + +BUFHEAD *__add_ovflpage __P((HTAB *, BUFHEAD *)); +int __addel __P((HTAB *, BUFHEAD *, const DBT *, const DBT *)); +int __big_delete __P((HTAB *, BUFHEAD *)); +int __big_insert __P((HTAB *, BUFHEAD *, const DBT *, const DBT *)); +int __big_keydata __P((HTAB *, BUFHEAD *, DBT *, DBT *, int)); +int __big_return __P((HTAB *, BUFHEAD *, int, DBT *, int)); +int __big_split __P((HTAB *, BUFHEAD *, BUFHEAD *, BUFHEAD *, + int, u_int32_t, SPLIT_RETURN *)); +int __buf_free __P((HTAB *, int, int)); +void __buf_init __P((HTAB *, int)); +u_int32_t __call_hash __P((HTAB *, char *, int)); +int __delpair __P((HTAB *, BUFHEAD *, int)); +int __expand_table __P((HTAB *)); +int __find_bigpair __P((HTAB *, BUFHEAD *, int, char *, int)); +u_int16_t __find_last_page __P((HTAB *, BUFHEAD **)); +void __free_ovflpage __P((HTAB *, BUFHEAD *)); +BUFHEAD *__get_buf __P((HTAB *, u_int32_t, BUFHEAD *, int)); +int __get_page __P((HTAB *, char *, u_int32_t, int, int, int)); +int __ibitmap __P((HTAB *, int, int, int)); +u_int32_t __hash_log2 __P((u_int32_t)); +int __put_page __P((HTAB *, char *, u_int32_t, int, int)); +void __reclaim_buf __P((HTAB *, BUFHEAD *)); +int __split_page __P((HTAB *, u_int32_t, u_int32_t)); + +/* Default hash routine. */ +extern u_int32_t (*__default_hash) __P((const void *, size_t)); + +#ifdef HASH_STATISTICS +extern int hash_accesses, hash_collisions, hash_expansions, hash_overflows; +#endif diff --git a/utils/db1-ast/hash/hash.c b/utils/db1-ast/hash/hash.c new file mode 100644 index 000000000..47dc52a0e --- /dev/null +++ b/utils/db1-ast/hash/hash.c @@ -0,0 +1,999 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)hash.c 8.9 (Berkeley) 6/16/94"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#ifdef DEBUG +#include +#endif + +#include "../include/db.h" +#include "hash.h" +#include "page.h" +#include "extern.h" + +static int alloc_segs __P((HTAB *, int)); +static int flush_meta __P((HTAB *)); +static int hash_access __P((HTAB *, ACTION, DBT *, DBT *)); +static int hash_close __P((DB *)); +static int hash_delete __P((const DB *, const DBT *, u_int32_t)); +static int hash_fd __P((const DB *)); +static int hash_get __P((const DB *, const DBT *, DBT *, u_int32_t)); +static int hash_put __P((const DB *, DBT *, const DBT *, u_int32_t)); +static void *hash_realloc __P((SEGMENT **, int, int)); +static int hash_seq __P((const DB *, DBT *, DBT *, u_int32_t)); +static int hash_sync __P((const DB *, u_int32_t)); +static int hdestroy __P((HTAB *)); +static HTAB *init_hash __P((HTAB *, const char *, const HASHINFO *)); +static int init_htab __P((HTAB *, int)); +#if BYTE_ORDER == LITTLE_ENDIAN +static void swap_header __P((HTAB *)); +static void swap_header_copy __P((HASHHDR *, HASHHDR *)); +#endif + +/* Fast arithmetic, relying on powers of 2, */ +#define MOD(x, y) ((x) & ((y) - 1)) + +#define RETURN_ERROR(ERR, LOC) { save_errno = ERR; goto LOC; } + +/* Return values */ +#define SUCCESS (0) +#define ERROR (-1) +#define ABNORMAL (1) + +#ifdef HASH_STATISTICS +int hash_accesses, hash_collisions, hash_expansions, hash_overflows; +#endif + +/************************** INTERFACE ROUTINES ***************************/ +/* OPEN/CLOSE */ + +extern DB * +__hash_open(file, flags, mode, info, dflags) + const char *file; + int flags, mode, dflags; + const HASHINFO *info; /* Special directives for create */ +{ + HTAB *hashp; + struct stat statbuf; + DB *dbp; + int bpages, hdrsize, new_table, nsegs, save_errno; + + if ((flags & O_ACCMODE) == O_WRONLY) { + errno = EINVAL; + return (NULL); + } + + if (!(hashp = (HTAB *)calloc(1, sizeof(HTAB)))) + return (NULL); + hashp->fp = -1; + + /* + * Even if user wants write only, we need to be able to read + * the actual file, so we need to open it read/write. But, the + * field in the hashp structure needs to be accurate so that + * we can check accesses. + */ + hashp->flags = flags; + + new_table = 0; + if (!file || (flags & O_TRUNC) || + (stat(file, &statbuf) && (errno == ENOENT))) { + if (errno == ENOENT) + errno = 0; /* Just in case someone looks at errno */ + new_table = 1; + } + if (file) { + if ((hashp->fp = open(file, flags, mode)) == -1) + RETURN_ERROR(errno, error0); + (void)fcntl(hashp->fp, F_SETFD, 1); + } + if (new_table) { + if (!(hashp = init_hash(hashp, file, info))) + RETURN_ERROR(errno, error1); + } else { + /* Table already exists */ + if (info && info->hash) + hashp->hash = info->hash; + else + hashp->hash = __default_hash; + + hdrsize = read(hashp->fp, &hashp->hdr, sizeof(HASHHDR)); +#if BYTE_ORDER == LITTLE_ENDIAN + swap_header(hashp); +#endif + if (hdrsize == -1) + RETURN_ERROR(errno, error1); + if (hdrsize != sizeof(HASHHDR)) + RETURN_ERROR(EFTYPE, error1); + /* Verify file type, versions and hash function */ + if (hashp->MAGIC != HASHMAGIC) + RETURN_ERROR(EFTYPE, error1); +#define OLDHASHVERSION 1 + if (hashp->VERSION != HASHVERSION && + hashp->VERSION != OLDHASHVERSION) + RETURN_ERROR(EFTYPE, error1); + if (hashp->hash(CHARKEY, sizeof(CHARKEY)) + != (u_int32_t) hashp->H_CHARKEY) + RETURN_ERROR(EFTYPE, error1); + /* + * Figure out how many segments we need. Max_Bucket is the + * maximum bucket number, so the number of buckets is + * max_bucket + 1. + */ + nsegs = (hashp->MAX_BUCKET + 1 + hashp->SGSIZE - 1) / + hashp->SGSIZE; + hashp->nsegs = 0; + if (alloc_segs(hashp, nsegs)) + /* + * If alloc_segs fails, table will have been destroyed + * and errno will have been set. + */ + return (NULL); + /* Read in bitmaps */ + bpages = (hashp->SPARES[hashp->OVFL_POINT] + + (hashp->BSIZE << BYTE_SHIFT) - 1) >> + (hashp->BSHIFT + BYTE_SHIFT); + + hashp->nmaps = bpages; + (void)memset(&hashp->mapp[0], 0, bpages * sizeof(u_int32_t *)); + } + + /* Initialize Buffer Manager */ + if (info && info->cachesize) + __buf_init(hashp, info->cachesize); + else + __buf_init(hashp, DEF_BUFSIZE); + + hashp->new_file = new_table; + hashp->save_file = file && (hashp->flags & O_ACCMODE) != O_RDONLY; + hashp->cbucket = -1; + if (!(dbp = (DB *)malloc(sizeof(DB)))) { + save_errno = errno; + hdestroy(hashp); + errno = save_errno; + return (NULL); + } + dbp->internal = hashp; + dbp->close = hash_close; + dbp->del = hash_delete; + dbp->fd = hash_fd; + dbp->get = hash_get; + dbp->put = hash_put; + dbp->seq = hash_seq; + dbp->sync = hash_sync; + dbp->type = DB_HASH; + +#ifdef DEBUG + (void)fprintf(stderr, +"%s\n%s%x\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%x\n%s%x\n%s%d\n%s%d\n", + "init_htab:", + "TABLE POINTER ", hashp, + "BUCKET SIZE ", hashp->BSIZE, + "BUCKET SHIFT ", hashp->BSHIFT, + "DIRECTORY SIZE ", hashp->DSIZE, + "SEGMENT SIZE ", hashp->SGSIZE, + "SEGMENT SHIFT ", hashp->SSHIFT, + "FILL FACTOR ", hashp->FFACTOR, + "MAX BUCKET ", hashp->MAX_BUCKET, + "OVFL POINT ", hashp->OVFL_POINT, + "LAST FREED ", hashp->LAST_FREED, + "HIGH MASK ", hashp->HIGH_MASK, + "LOW MASK ", hashp->LOW_MASK, + "NSEGS ", hashp->nsegs, + "NKEYS ", hashp->NKEYS); +#endif +#ifdef HASH_STATISTICS + hash_overflows = hash_accesses = hash_collisions = hash_expansions = 0; +#endif + return (dbp); + +error1: + if (hashp != NULL) + (void)close(hashp->fp); + +error0: + free(hashp); + errno = save_errno; + return (NULL); +} + +static int +hash_close(dbp) + DB *dbp; +{ + HTAB *hashp; + int retval; + + if (!dbp) + return (ERROR); + + hashp = (HTAB *)dbp->internal; + retval = hdestroy(hashp); + free(dbp); + return (retval); +} + +static int +hash_fd(dbp) + const DB *dbp; +{ + HTAB *hashp; + + if (!dbp) + return (ERROR); + + hashp = (HTAB *)dbp->internal; + if (hashp->fp == -1) { + errno = ENOENT; + return (-1); + } + return (hashp->fp); +} + +/************************** LOCAL CREATION ROUTINES **********************/ +static HTAB * +init_hash(hashp, file, info) + HTAB *hashp; + const char *file; + const HASHINFO *info; +{ +#ifdef _STATBUF_ST_BLKSIZE + struct stat statbuf; +#endif + int nelem; + + nelem = 1; + hashp->NKEYS = 0; + hashp->LORDER = BYTE_ORDER; + hashp->BSIZE = DEF_BUCKET_SIZE; + hashp->BSHIFT = DEF_BUCKET_SHIFT; + hashp->SGSIZE = DEF_SEGSIZE; + hashp->SSHIFT = DEF_SEGSIZE_SHIFT; + hashp->DSIZE = DEF_DIRSIZE; + hashp->FFACTOR = DEF_FFACTOR; + hashp->hash = __default_hash; + memset(hashp->SPARES, 0, sizeof(hashp->SPARES)); + memset(hashp->BITMAPS, 0, sizeof (hashp->BITMAPS)); + + /* Fix bucket size to be optimal for file system */ +#ifdef _STATBUF_ST_BLKSIZE + if (file != NULL) { + if (stat(file, &statbuf)) + return (NULL); + hashp->BSIZE = statbuf.st_blksize; + hashp->BSHIFT = __hash_log2(hashp->BSIZE); + } +#endif + + if (info) { + if (info->bsize) { + /* Round pagesize up to power of 2 */ + hashp->BSHIFT = __hash_log2(info->bsize); + hashp->BSIZE = 1 << hashp->BSHIFT; + if (hashp->BSIZE > MAX_BSIZE) { + errno = EINVAL; + return (NULL); + } + } + if (info->ffactor) + hashp->FFACTOR = info->ffactor; + if (info->hash) + hashp->hash = info->hash; + if (info->nelem) + nelem = info->nelem; + if (info->lorder) { + if (info->lorder != BIG_ENDIAN && + info->lorder != LITTLE_ENDIAN) { + errno = EINVAL; + return (NULL); + } + hashp->LORDER = info->lorder; + } + } + /* init_htab should destroy the table and set errno if it fails */ + if (init_htab(hashp, nelem)) + return (NULL); + else + return (hashp); +} +/* + * This calls alloc_segs which may run out of memory. Alloc_segs will destroy + * the table and set errno, so we just pass the error information along. + * + * Returns 0 on No Error + */ +static int +init_htab(hashp, nelem) + HTAB *hashp; + int nelem; +{ + register int nbuckets, nsegs; + int l2; + + /* + * Divide number of elements by the fill factor and determine a + * desired number of buckets. Allocate space for the next greater + * power of two number of buckets. + */ + nelem = (nelem - 1) / hashp->FFACTOR + 1; + + l2 = __hash_log2(MAX(nelem, 2)); + nbuckets = 1 << l2; + + hashp->SPARES[l2] = l2 + 1; + hashp->SPARES[l2 + 1] = l2 + 1; + hashp->OVFL_POINT = l2; + hashp->LAST_FREED = 2; + + /* First bitmap page is at: splitpoint l2 page offset 1 */ + if (__ibitmap(hashp, OADDR_OF(l2, 1), l2 + 1, 0)) + return (-1); + + hashp->MAX_BUCKET = hashp->LOW_MASK = nbuckets - 1; + hashp->HIGH_MASK = (nbuckets << 1) - 1; + hashp->HDRPAGES = ((MAX(sizeof(HASHHDR), MINHDRSIZE) - 1) >> + hashp->BSHIFT) + 1; + + nsegs = (nbuckets - 1) / hashp->SGSIZE + 1; + nsegs = 1 << __hash_log2(nsegs); + + if (nsegs > hashp->DSIZE) + hashp->DSIZE = nsegs; + return (alloc_segs(hashp, nsegs)); +} + +/********************** DESTROY/CLOSE ROUTINES ************************/ + +/* + * Flushes any changes to the file if necessary and destroys the hashp + * structure, freeing all allocated space. + */ +static int +hdestroy(hashp) + HTAB *hashp; +{ + int i, save_errno; + + save_errno = 0; + +#ifdef HASH_STATISTICS + (void)fprintf(stderr, "hdestroy: accesses %ld collisions %ld\n", + hash_accesses, hash_collisions); + (void)fprintf(stderr, "hdestroy: expansions %ld\n", + hash_expansions); + (void)fprintf(stderr, "hdestroy: overflows %ld\n", + hash_overflows); + (void)fprintf(stderr, "keys %ld maxp %d segmentcount %d\n", + hashp->NKEYS, hashp->MAX_BUCKET, hashp->nsegs); + + for (i = 0; i < NCACHED; i++) + (void)fprintf(stderr, + "spares[%d] = %d\n", i, hashp->SPARES[i]); +#endif + /* + * Call on buffer manager to free buffers, and if required, + * write them to disk. + */ + if (__buf_free(hashp, 1, hashp->save_file)) + save_errno = errno; + if (hashp->dir) { + free(*hashp->dir); /* Free initial segments */ + /* Free extra segments */ + while (hashp->exsegs--) + free(hashp->dir[--hashp->nsegs]); + free(hashp->dir); + } + if (flush_meta(hashp) && !save_errno) + save_errno = errno; + /* Free Bigmaps */ + for (i = 0; i < hashp->nmaps; i++) + if (hashp->mapp[i]) + free(hashp->mapp[i]); + + if (hashp->fp != -1) + (void)close(hashp->fp); + + free(hashp); + + if (save_errno) { + errno = save_errno; + return (ERROR); + } + return (SUCCESS); +} +/* + * Write modified pages to disk + * + * Returns: + * 0 == OK + * -1 ERROR + */ +static int +hash_sync(dbp, flags) + const DB *dbp; + u_int32_t flags; +{ + HTAB *hashp; + + if (flags != 0) { + errno = EINVAL; + return (ERROR); + } + + if (!dbp) + return (ERROR); + + hashp = (HTAB *)dbp->internal; + if (!hashp->save_file) + return (0); + if (__buf_free(hashp, 0, 1) || flush_meta(hashp)) + return (ERROR); + hashp->new_file = 0; + return (0); +} + +/* + * Returns: + * 0 == OK + * -1 indicates that errno should be set + */ +static int +flush_meta(hashp) + HTAB *hashp; +{ + HASHHDR *whdrp; +#if BYTE_ORDER == LITTLE_ENDIAN + HASHHDR whdr; +#endif + int fp, i, wsize; + + if (!hashp->save_file) + return (0); + hashp->MAGIC = HASHMAGIC; + hashp->VERSION = HASHVERSION; + hashp->H_CHARKEY = hashp->hash(CHARKEY, sizeof(CHARKEY)); + + fp = hashp->fp; + whdrp = &hashp->hdr; +#if BYTE_ORDER == LITTLE_ENDIAN + whdrp = &whdr; + swap_header_copy(&hashp->hdr, whdrp); +#endif + if ((lseek(fp, (off_t)0, SEEK_SET) == -1) || + ((wsize = write(fp, whdrp, sizeof(HASHHDR))) == -1)) + return (-1); + else + if (wsize != sizeof(HASHHDR)) { + errno = EFTYPE; + hashp->errnum = errno; + return (-1); + } + for (i = 0; i < NCACHED; i++) + if (hashp->mapp[i]) + if (__put_page(hashp, (char *)hashp->mapp[i], + hashp->BITMAPS[i], 0, 1)) + return (-1); + return (0); +} + +/*******************************SEARCH ROUTINES *****************************/ +/* + * All the access routines return + * + * Returns: + * 0 on SUCCESS + * 1 to indicate an external ERROR (i.e. key not found, etc) + * -1 to indicate an internal ERROR (i.e. out of memory, etc) + */ +static int +hash_get(dbp, key, data, flag) + const DB *dbp; + const DBT *key; + DBT *data; + u_int32_t flag; +{ + HTAB *hashp; + + hashp = (HTAB *)dbp->internal; + if (flag) { + hashp->errnum = errno = EINVAL; + return (ERROR); + } + return (hash_access(hashp, HASH_GET, (DBT *)key, data)); +} + +static int +hash_put(dbp, key, data, flag) + const DB *dbp; + DBT *key; + const DBT *data; + u_int32_t flag; +{ + HTAB *hashp; + + hashp = (HTAB *)dbp->internal; + if (flag && flag != R_NOOVERWRITE) { + hashp->errnum = errno = EINVAL; + return (ERROR); + } + if ((hashp->flags & O_ACCMODE) == O_RDONLY) { + hashp->errnum = errno = EPERM; + return (ERROR); + } + return (hash_access(hashp, flag == R_NOOVERWRITE ? + HASH_PUTNEW : HASH_PUT, (DBT *)key, (DBT *)data)); +} + +static int +hash_delete(dbp, key, flag) + const DB *dbp; + const DBT *key; + u_int32_t flag; /* Ignored */ +{ + HTAB *hashp; + + hashp = (HTAB *)dbp->internal; + if (flag && flag != R_CURSOR) { + hashp->errnum = errno = EINVAL; + return (ERROR); + } + if ((hashp->flags & O_ACCMODE) == O_RDONLY) { + hashp->errnum = errno = EPERM; + return (ERROR); + } + return (hash_access(hashp, HASH_DELETE, (DBT *)key, NULL)); +} + +/* + * Assume that hashp has been set in wrapper routine. + */ +static int +hash_access(hashp, action, key, val) + HTAB *hashp; + ACTION action; + DBT *key, *val; +{ + register BUFHEAD *rbufp; + BUFHEAD *bufp, *save_bufp; + register u_int16_t *bp; + register int n, ndx, off, size; + register char *kp; + u_int16_t pageno; + +#ifdef HASH_STATISTICS + hash_accesses++; +#endif + + off = hashp->BSIZE; + size = key->size; + kp = (char *)key->data; + rbufp = __get_buf(hashp, __call_hash(hashp, kp, size), NULL, 0); + if (!rbufp) + return (ERROR); + save_bufp = rbufp; + + /* Pin the bucket chain */ + rbufp->flags |= BUF_PIN; + for (bp = (u_int16_t *)rbufp->page, n = *bp++, ndx = 1; ndx < n;) + if (bp[1] >= REAL_KEY) { + /* Real key/data pair */ + if (size == off - *bp && + memcmp(kp, rbufp->page + *bp, size) == 0) + goto found; + off = bp[1]; +#ifdef HASH_STATISTICS + hash_collisions++; +#endif + bp += 2; + ndx += 2; + } else if (bp[1] == OVFLPAGE) { + rbufp = __get_buf(hashp, *bp, rbufp, 0); + if (!rbufp) { + save_bufp->flags &= ~BUF_PIN; + return (ERROR); + } + /* FOR LOOP INIT */ + bp = (u_int16_t *)rbufp->page; + n = *bp++; + ndx = 1; + off = hashp->BSIZE; + } else if (bp[1] < REAL_KEY) { + if ((ndx = + __find_bigpair(hashp, rbufp, ndx, kp, size)) > 0) + goto found; + if (ndx == -2) { + bufp = rbufp; + if (!(pageno = + __find_last_page(hashp, &bufp))) { + ndx = 0; + rbufp = bufp; + break; /* FOR */ + } + rbufp = __get_buf(hashp, pageno, bufp, 0); + if (!rbufp) { + save_bufp->flags &= ~BUF_PIN; + return (ERROR); + } + /* FOR LOOP INIT */ + bp = (u_int16_t *)rbufp->page; + n = *bp++; + ndx = 1; + off = hashp->BSIZE; + } else { + save_bufp->flags &= ~BUF_PIN; + return (ERROR); + } + } + + /* Not found */ + switch (action) { + case HASH_PUT: + case HASH_PUTNEW: + if (__addel(hashp, rbufp, key, val)) { + save_bufp->flags &= ~BUF_PIN; + return (ERROR); + } else { + save_bufp->flags &= ~BUF_PIN; + return (SUCCESS); + } + case HASH_GET: + case HASH_DELETE: + default: + save_bufp->flags &= ~BUF_PIN; + return (ABNORMAL); + } + +found: + switch (action) { + case HASH_PUTNEW: + save_bufp->flags &= ~BUF_PIN; + return (ABNORMAL); + case HASH_GET: + bp = (u_int16_t *)rbufp->page; + if (bp[ndx + 1] < REAL_KEY) { + if (__big_return(hashp, rbufp, ndx, val, 0)) + return (ERROR); + } else { + val->data = (u_char *)rbufp->page + (int)bp[ndx + 1]; + val->size = bp[ndx] - bp[ndx + 1]; + } + break; + case HASH_PUT: + if ((__delpair(hashp, rbufp, ndx)) || + (__addel(hashp, rbufp, key, val))) { + save_bufp->flags &= ~BUF_PIN; + return (ERROR); + } + break; + case HASH_DELETE: + if (__delpair(hashp, rbufp, ndx)) + return (ERROR); + break; + default: + abort(); + } + save_bufp->flags &= ~BUF_PIN; + return (SUCCESS); +} + +static int +hash_seq(dbp, key, data, flag) + const DB *dbp; + DBT *key, *data; + u_int32_t flag; +{ + register u_int32_t bucket; + register BUFHEAD *bufp = NULL; + HTAB *hashp; + u_int16_t *bp, ndx; + + hashp = (HTAB *)dbp->internal; + if (flag && flag != R_FIRST && flag != R_NEXT) { + hashp->errnum = errno = EINVAL; + return (ERROR); + } +#ifdef HASH_STATISTICS + hash_accesses++; +#endif + if ((hashp->cbucket < 0) || (flag == R_FIRST)) { + hashp->cbucket = 0; + hashp->cndx = 1; + hashp->cpage = NULL; + } + + for (bp = NULL; !bp || !bp[0]; ) { + if (!(bufp = hashp->cpage)) { + for (bucket = hashp->cbucket; + bucket <= (u_int32_t) hashp->MAX_BUCKET; + bucket++, hashp->cndx = 1) { + bufp = __get_buf(hashp, bucket, NULL, 0); + if (!bufp) + return (ERROR); + hashp->cpage = bufp; + bp = (u_int16_t *)bufp->page; + if (bp[0]) + break; + } + hashp->cbucket = bucket; + if (hashp->cbucket > hashp->MAX_BUCKET) { + hashp->cbucket = -1; + return (ABNORMAL); + } + } else + bp = (u_int16_t *)hashp->cpage->page; + +#ifdef DEBUG + assert(bp); + assert(bufp); +#endif + while (bp[hashp->cndx + 1] == OVFLPAGE) { + bufp = hashp->cpage = + __get_buf(hashp, bp[hashp->cndx], bufp, 0); + if (!bufp) + return (ERROR); + bp = (u_int16_t *)(bufp->page); + hashp->cndx = 1; + } + if (!bp[0]) { + hashp->cpage = NULL; + ++hashp->cbucket; + } + } + ndx = hashp->cndx; + if (bp[ndx + 1] < REAL_KEY) { + if (__big_keydata(hashp, bufp, key, data, 1)) + return (ERROR); + } else { + key->data = (u_char *)hashp->cpage->page + bp[ndx]; + key->size = (ndx > 1 ? bp[ndx - 1] : hashp->BSIZE) - bp[ndx]; + data->data = (u_char *)hashp->cpage->page + bp[ndx + 1]; + data->size = bp[ndx] - bp[ndx + 1]; + ndx += 2; + if (ndx > bp[0]) { + hashp->cpage = NULL; + hashp->cbucket++; + hashp->cndx = 1; + } else + hashp->cndx = ndx; + } + return (SUCCESS); +} + +/********************************* UTILITIES ************************/ + +/* + * Returns: + * 0 ==> OK + * -1 ==> Error + */ +extern int +__expand_table(hashp) + HTAB *hashp; +{ + u_int32_t old_bucket, new_bucket; + int dirsize, new_segnum, spare_ndx; + +#ifdef HASH_STATISTICS + hash_expansions++; +#endif + new_bucket = ++hashp->MAX_BUCKET; + old_bucket = (hashp->MAX_BUCKET & hashp->LOW_MASK); + + new_segnum = new_bucket >> hashp->SSHIFT; + + /* Check if we need a new segment */ + if (new_segnum >= hashp->nsegs) { + /* Check if we need to expand directory */ + if (new_segnum >= hashp->DSIZE) { + /* Reallocate directory */ + dirsize = hashp->DSIZE * sizeof(SEGMENT *); + if (!hash_realloc(&hashp->dir, dirsize, dirsize << 1)) + return (-1); + hashp->DSIZE = dirsize << 1; + } + if ((hashp->dir[new_segnum] = + (SEGMENT)calloc(hashp->SGSIZE, sizeof(SEGMENT))) == NULL) + return (-1); + hashp->exsegs++; + hashp->nsegs++; + } + /* + * If the split point is increasing (MAX_BUCKET's log base 2 + * * increases), we need to copy the current contents of the spare + * split bucket to the next bucket. + */ + spare_ndx = __hash_log2(hashp->MAX_BUCKET + 1); + if (spare_ndx > hashp->OVFL_POINT) { + hashp->SPARES[spare_ndx] = hashp->SPARES[hashp->OVFL_POINT]; + hashp->OVFL_POINT = spare_ndx; + } + + if (new_bucket > (u_int32_t) hashp->HIGH_MASK) { + /* Starting a new doubling */ + hashp->LOW_MASK = hashp->HIGH_MASK; + hashp->HIGH_MASK = new_bucket | hashp->LOW_MASK; + } + /* Relocate records to the new bucket */ + return (__split_page(hashp, old_bucket, new_bucket)); +} + +/* + * If realloc guarantees that the pointer is not destroyed if the realloc + * fails, then this routine can go away. + */ +static void * +hash_realloc(p_ptr, oldsize, newsize) + SEGMENT **p_ptr; + int oldsize, newsize; +{ + register void *p; + + if ((p = malloc(newsize))) { + memmove(p, *p_ptr, oldsize); + memset((char *)p + oldsize, 0, newsize - oldsize); + free(*p_ptr); + *p_ptr = p; + } + return (p); +} + +extern u_int32_t +__call_hash(hashp, k, len) + HTAB *hashp; + char *k; + int len; +{ + int n, bucket; + + n = hashp->hash(k, len); + bucket = n & hashp->HIGH_MASK; + if (bucket > hashp->MAX_BUCKET) + bucket = bucket & hashp->LOW_MASK; + return (bucket); +} + +/* + * Allocate segment table. On error, destroy the table and set errno. + * + * Returns 0 on success + */ +static int +alloc_segs(hashp, nsegs) + HTAB *hashp; + int nsegs; +{ + register int i; + register SEGMENT store; + + int save_errno; + + if ((hashp->dir = + (SEGMENT *)calloc(hashp->DSIZE, sizeof(SEGMENT *))) == NULL) { + save_errno = errno; + (void)hdestroy(hashp); + errno = save_errno; + return (-1); + } + /* Allocate segments */ + if ((store = + (SEGMENT)calloc(nsegs << hashp->SSHIFT, sizeof(SEGMENT))) == NULL) { + save_errno = errno; + (void)hdestroy(hashp); + errno = save_errno; + return (-1); + } + for (i = 0; i < nsegs; i++, hashp->nsegs++) + hashp->dir[i] = &store[i << hashp->SSHIFT]; + return (0); +} + +#if BYTE_ORDER == LITTLE_ENDIAN +/* + * Hashp->hdr needs to be byteswapped. + */ +static void +swap_header_copy(srcp, destp) + HASHHDR *srcp, *destp; +{ + int i; + + P_32_COPY(srcp->magic, destp->magic); + P_32_COPY(srcp->version, destp->version); + P_32_COPY(srcp->lorder, destp->lorder); + P_32_COPY(srcp->bsize, destp->bsize); + P_32_COPY(srcp->bshift, destp->bshift); + P_32_COPY(srcp->dsize, destp->dsize); + P_32_COPY(srcp->ssize, destp->ssize); + P_32_COPY(srcp->sshift, destp->sshift); + P_32_COPY(srcp->ovfl_point, destp->ovfl_point); + P_32_COPY(srcp->last_freed, destp->last_freed); + P_32_COPY(srcp->max_bucket, destp->max_bucket); + P_32_COPY(srcp->high_mask, destp->high_mask); + P_32_COPY(srcp->low_mask, destp->low_mask); + P_32_COPY(srcp->ffactor, destp->ffactor); + P_32_COPY(srcp->nkeys, destp->nkeys); + P_32_COPY(srcp->hdrpages, destp->hdrpages); + P_32_COPY(srcp->h_charkey, destp->h_charkey); + for (i = 0; i < NCACHED; i++) { + P_32_COPY(srcp->spares[i], destp->spares[i]); + P_16_COPY(srcp->bitmaps[i], destp->bitmaps[i]); + } +} + +static void +swap_header(hashp) + HTAB *hashp; +{ + HASHHDR *hdrp; + int i; + + hdrp = &hashp->hdr; + + M_32_SWAP(hdrp->magic); + M_32_SWAP(hdrp->version); + M_32_SWAP(hdrp->lorder); + M_32_SWAP(hdrp->bsize); + M_32_SWAP(hdrp->bshift); + M_32_SWAP(hdrp->dsize); + M_32_SWAP(hdrp->ssize); + M_32_SWAP(hdrp->sshift); + M_32_SWAP(hdrp->ovfl_point); + M_32_SWAP(hdrp->last_freed); + M_32_SWAP(hdrp->max_bucket); + M_32_SWAP(hdrp->high_mask); + M_32_SWAP(hdrp->low_mask); + M_32_SWAP(hdrp->ffactor); + M_32_SWAP(hdrp->nkeys); + M_32_SWAP(hdrp->hdrpages); + M_32_SWAP(hdrp->h_charkey); + for (i = 0; i < NCACHED; i++) { + M_32_SWAP(hdrp->spares[i]); + M_16_SWAP(hdrp->bitmaps[i]); + } +} +#endif diff --git a/utils/db1-ast/hash/hash.h b/utils/db1-ast/hash/hash.h new file mode 100644 index 000000000..d07db6f07 --- /dev/null +++ b/utils/db1-ast/hash/hash.h @@ -0,0 +1,293 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)hash.h 8.3 (Berkeley) 5/31/94 + */ + +/* Operations */ +typedef enum { + HASH_GET, HASH_PUT, HASH_PUTNEW, HASH_DELETE, HASH_FIRST, HASH_NEXT +} ACTION; + +/* Buffer Management structures */ +typedef struct _bufhead BUFHEAD; + +struct _bufhead { + BUFHEAD *prev; /* LRU links */ + BUFHEAD *next; /* LRU links */ + BUFHEAD *ovfl; /* Overflow page buffer header */ + u_int32_t addr; /* Address of this page */ + char *page; /* Actual page data */ + char flags; +#define BUF_MOD 0x0001 +#define BUF_DISK 0x0002 +#define BUF_BUCKET 0x0004 +#define BUF_PIN 0x0008 +}; + +#define IS_BUCKET(X) ((X) & BUF_BUCKET) + +typedef BUFHEAD **SEGMENT; + +/* Hash Table Information */ +typedef struct hashhdr { /* Disk resident portion */ + int magic; /* Magic NO for hash tables */ + int version; /* Version ID */ + u_int32_t lorder; /* Byte Order */ + int bsize; /* Bucket/Page Size */ + int bshift; /* Bucket shift */ + int dsize; /* Directory Size */ + int ssize; /* Segment Size */ + int sshift; /* Segment shift */ + int ovfl_point; /* Where overflow pages are being + * allocated */ + int last_freed; /* Last overflow page freed */ + int max_bucket; /* ID of Maximum bucket in use */ + int high_mask; /* Mask to modulo into entire table */ + int low_mask; /* Mask to modulo into lower half of + * table */ + int ffactor; /* Fill factor */ + int nkeys; /* Number of keys in hash table */ + int hdrpages; /* Size of table header */ + int h_charkey; /* value of hash(CHARKEY) */ +#define NCACHED 32 /* number of bit maps and spare + * points */ + int spares[NCACHED];/* spare pages for overflow */ + u_int16_t bitmaps[NCACHED]; /* address of overflow page + * bitmaps */ +} HASHHDR; + +typedef struct htab { /* Memory resident data structure */ + HASHHDR hdr; /* Header */ + int nsegs; /* Number of allocated segments */ + int exsegs; /* Number of extra allocated + * segments */ + u_int32_t /* Hash function */ + (*hash)__P((const void *, size_t)); + int flags; /* Flag values */ + int fp; /* File pointer */ + char *tmp_buf; /* Temporary Buffer for BIG data */ + char *tmp_key; /* Temporary Buffer for BIG keys */ + BUFHEAD *cpage; /* Current page */ + int cbucket; /* Current bucket */ + int cndx; /* Index of next item on cpage */ + int errnum; /* Error Number -- for DBM + * compatibility */ + int new_file; /* Indicates if fd is backing store + * or no */ + int save_file; /* Indicates whether we need to flush + * file at + * exit */ + u_int32_t *mapp[NCACHED]; /* Pointers to page maps */ + int nmaps; /* Initial number of bitmaps */ + int nbufs; /* Number of buffers left to + * allocate */ + BUFHEAD bufhead; /* Header of buffer lru list */ + SEGMENT *dir; /* Hash Bucket directory */ +} HTAB; + +/* + * Constants + */ +#define MAX_BSIZE 65536 /* 2^16 */ +#define MIN_BUFFERS 6 +#define MINHDRSIZE 512 +#define DEF_BUFSIZE 65536 /* 64 K */ +#define DEF_BUCKET_SIZE 4096 +#define DEF_BUCKET_SHIFT 12 /* log2(BUCKET) */ +#define DEF_SEGSIZE 256 +#define DEF_SEGSIZE_SHIFT 8 /* log2(SEGSIZE) */ +#define DEF_DIRSIZE 256 +#define DEF_FFACTOR 65536 +#define MIN_FFACTOR 4 +#define SPLTMAX 8 +#define CHARKEY "%$sniglet^&" +#define NUMKEY 1038583 +#define BYTE_SHIFT 3 +#define INT_TO_BYTE 2 +#define INT_BYTE_SHIFT 5 +#define ALL_SET ((u_int32_t)0xFFFFFFFF) +#define ALL_CLEAR 0 + +#define PTROF(X) ((BUFHEAD *)((ptrdiff_t)(X)&~0x3)) +#define ISMOD(X) ((u_int32_t)(ptrdiff_t)(X)&0x1) +#define DOMOD(X) ((X) = (char *)((ptrdiff_t)(X)|0x1)) +#define ISDISK(X) ((u_int32_t)(ptrdiff_t)(X)&0x2) +#define DODISK(X) ((X) = (char *)((ptrdiff_t)(X)|0x2)) + +#define BITS_PER_MAP 32 + +/* Given the address of the beginning of a big map, clear/set the nth bit */ +#define CLRBIT(A, N) ((A)[(N)/BITS_PER_MAP] &= ~(1<<((N)%BITS_PER_MAP))) +#define SETBIT(A, N) ((A)[(N)/BITS_PER_MAP] |= (1<<((N)%BITS_PER_MAP))) +#define ISSET(A, N) ((A)[(N)/BITS_PER_MAP] & (1<<((N)%BITS_PER_MAP))) + +/* Overflow management */ +/* + * Overflow page numbers are allocated per split point. At each doubling of + * the table, we can allocate extra pages. So, an overflow page number has + * the top 5 bits indicate which split point and the lower 11 bits indicate + * which page at that split point is indicated (pages within split points are + * numberered starting with 1). + */ + +#define SPLITSHIFT 11 +#define SPLITMASK 0x7FF +#define SPLITNUM(N) (((u_int32_t)(N)) >> SPLITSHIFT) +#define OPAGENUM(N) ((N) & SPLITMASK) +#define OADDR_OF(S,O) ((u_int32_t)((u_int32_t)(S) << SPLITSHIFT) + (O)) + +#define BUCKET_TO_PAGE(B) \ + (B) + hashp->HDRPAGES + ((B) ? hashp->SPARES[__hash_log2((B)+1)-1] : 0) +#define OADDR_TO_PAGE(B) \ + BUCKET_TO_PAGE ( (1 << SPLITNUM((B))) -1 ) + OPAGENUM((B)); + +/* + * page.h contains a detailed description of the page format. + * + * Normally, keys and data are accessed from offset tables in the top of + * each page which point to the beginning of the key and data. There are + * four flag values which may be stored in these offset tables which indicate + * the following: + * + * + * OVFLPAGE Rather than a key data pair, this pair contains + * the address of an overflow page. The format of + * the pair is: + * OVERFLOW_PAGE_NUMBER OVFLPAGE + * + * PARTIAL_KEY This must be the first key/data pair on a page + * and implies that page contains only a partial key. + * That is, the key is too big to fit on a single page + * so it starts on this page and continues on the next. + * The format of the page is: + * KEY_OFF PARTIAL_KEY OVFL_PAGENO OVFLPAGE + * + * KEY_OFF -- offset of the beginning of the key + * PARTIAL_KEY -- 1 + * OVFL_PAGENO - page number of the next overflow page + * OVFLPAGE -- 0 + * + * FULL_KEY This must be the first key/data pair on the page. It + * is used in two cases. + * + * Case 1: + * There is a complete key on the page but no data + * (because it wouldn't fit). The next page contains + * the data. + * + * Page format it: + * KEY_OFF FULL_KEY OVFL_PAGENO OVFL_PAGE + * + * KEY_OFF -- offset of the beginning of the key + * FULL_KEY -- 2 + * OVFL_PAGENO - page number of the next overflow page + * OVFLPAGE -- 0 + * + * Case 2: + * This page contains no key, but part of a large + * data field, which is continued on the next page. + * + * Page format it: + * DATA_OFF FULL_KEY OVFL_PAGENO OVFL_PAGE + * + * KEY_OFF -- offset of the beginning of the data on + * this page + * FULL_KEY -- 2 + * OVFL_PAGENO - page number of the next overflow page + * OVFLPAGE -- 0 + * + * FULL_KEY_DATA + * This must be the first key/data pair on the page. + * There are two cases: + * + * Case 1: + * This page contains a key and the beginning of the + * data field, but the data field is continued on the + * next page. + * + * Page format is: + * KEY_OFF FULL_KEY_DATA OVFL_PAGENO DATA_OFF + * + * KEY_OFF -- offset of the beginning of the key + * FULL_KEY_DATA -- 3 + * OVFL_PAGENO - page number of the next overflow page + * DATA_OFF -- offset of the beginning of the data + * + * Case 2: + * This page contains the last page of a big data pair. + * There is no key, only the tail end of the data + * on this page. + * + * Page format is: + * DATA_OFF FULL_KEY_DATA + * + * DATA_OFF -- offset of the beginning of the data on + * this page + * FULL_KEY_DATA -- 3 + * OVFL_PAGENO - page number of the next overflow page + * OVFLPAGE -- 0 + * + * OVFL_PAGENO and OVFLPAGE are optional (they are + * not present if there is no next page). + */ + +#define OVFLPAGE 0 +#define PARTIAL_KEY 1 +#define FULL_KEY 2 +#define FULL_KEY_DATA 3 +#define REAL_KEY 4 + +/* Short hands for accessing structure */ +#define BSIZE hdr.bsize +#define BSHIFT hdr.bshift +#define DSIZE hdr.dsize +#define SGSIZE hdr.ssize +#define SSHIFT hdr.sshift +#define LORDER hdr.lorder +#define OVFL_POINT hdr.ovfl_point +#define LAST_FREED hdr.last_freed +#define MAX_BUCKET hdr.max_bucket +#define FFACTOR hdr.ffactor +#define HIGH_MASK hdr.high_mask +#define LOW_MASK hdr.low_mask +#define NKEYS hdr.nkeys +#define HDRPAGES hdr.hdrpages +#define SPARES hdr.spares +#define BITMAPS hdr.bitmaps +#define VERSION hdr.version +#define MAGIC hdr.magic +#define NEXT_FREE hdr.next_free +#define H_CHARKEY hdr.h_charkey diff --git a/utils/db1-ast/hash/hash_bigkey.c b/utils/db1-ast/hash/hash_bigkey.c new file mode 100644 index 000000000..daa8c1f17 --- /dev/null +++ b/utils/db1-ast/hash/hash_bigkey.c @@ -0,0 +1,668 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)hash_bigkey.c 8.3 (Berkeley) 5/31/94"; +#endif /* LIBC_SCCS and not lint */ + +/* + * PACKAGE: hash + * DESCRIPTION: + * Big key/data handling for the hashing package. + * + * ROUTINES: + * External + * __big_keydata + * __big_split + * __big_insert + * __big_return + * __big_delete + * __find_last_page + * Internal + * collect_key + * collect_data + */ + +#include + +#include +#include +#include +#include + +#ifdef DEBUG +#include +#endif + +#include "../include/db.h" +#include "hash.h" +#include "page.h" +#include "extern.h" + +static int collect_key __P((HTAB *, BUFHEAD *, int, DBT *, int)); +static int collect_data __P((HTAB *, BUFHEAD *, int, int)); + +/* + * Big_insert + * + * You need to do an insert and the key/data pair is too big + * + * Returns: + * 0 ==> OK + *-1 ==> ERROR + */ +extern int +__big_insert(hashp, bufp, key, val) + HTAB *hashp; + BUFHEAD *bufp; + const DBT *key, *val; +{ + register u_int16_t *p; + int key_size, n, val_size; + u_int16_t space, move_bytes, off; + char *cp, *key_data, *val_data; + + cp = bufp->page; /* Character pointer of p. */ + p = (u_int16_t *)cp; + + key_data = (char *)key->data; + key_size = key->size; + val_data = (char *)val->data; + val_size = val->size; + + /* First move the Key */ + for (space = FREESPACE(p) - BIGOVERHEAD; key_size; + space = FREESPACE(p) - BIGOVERHEAD) { + move_bytes = MIN(space, key_size); + off = OFFSET(p) - move_bytes; + memmove(cp + off, key_data, move_bytes); + key_size -= move_bytes; + key_data += move_bytes; + n = p[0]; + p[++n] = off; + p[0] = ++n; + FREESPACE(p) = off - PAGE_META(n); + OFFSET(p) = off; + p[n] = PARTIAL_KEY; + bufp = __add_ovflpage(hashp, bufp); + if (!bufp) + return (-1); + n = p[0]; + if (!key_size) { + if (FREESPACE(p)) { + move_bytes = MIN(FREESPACE(p), val_size); + off = OFFSET(p) - move_bytes; + p[n] = off; + memmove(cp + off, val_data, move_bytes); + val_data += move_bytes; + val_size -= move_bytes; + p[n - 2] = FULL_KEY_DATA; + FREESPACE(p) = FREESPACE(p) - move_bytes; + OFFSET(p) = off; + } else + p[n - 2] = FULL_KEY; + } + p = (u_int16_t *)bufp->page; + cp = bufp->page; + bufp->flags |= BUF_MOD; + } + + /* Now move the data */ + for (space = FREESPACE(p) - BIGOVERHEAD; val_size; + space = FREESPACE(p) - BIGOVERHEAD) { + move_bytes = MIN(space, val_size); + /* + * Here's the hack to make sure that if the data ends on the + * same page as the key ends, FREESPACE is at least one. + */ + if ((int) space == val_size && (size_t) val_size == val->size) + move_bytes--; + off = OFFSET(p) - move_bytes; + memmove(cp + off, val_data, move_bytes); + val_size -= move_bytes; + val_data += move_bytes; + n = p[0]; + p[++n] = off; + p[0] = ++n; + FREESPACE(p) = off - PAGE_META(n); + OFFSET(p) = off; + if (val_size) { + p[n] = FULL_KEY; + bufp = __add_ovflpage(hashp, bufp); + if (!bufp) + return (-1); + cp = bufp->page; + p = (u_int16_t *)cp; + } else + p[n] = FULL_KEY_DATA; + bufp->flags |= BUF_MOD; + } + return (0); +} + +/* + * Called when bufp's page contains a partial key (index should be 1) + * + * All pages in the big key/data pair except bufp are freed. We cannot + * free bufp because the page pointing to it is lost and we can't get rid + * of its pointer. + * + * Returns: + * 0 => OK + *-1 => ERROR + */ +extern int +__big_delete(hashp, bufp) + HTAB *hashp; + BUFHEAD *bufp; +{ + register BUFHEAD *last_bfp, *rbufp; + u_int16_t *bp, pageno; + int key_done, n; + + rbufp = bufp; + last_bfp = NULL; + bp = (u_int16_t *)bufp->page; + pageno = 0; + key_done = 0; + + while (!key_done || (bp[2] != FULL_KEY_DATA)) { + if (bp[2] == FULL_KEY || bp[2] == FULL_KEY_DATA) + key_done = 1; + + /* + * If there is freespace left on a FULL_KEY_DATA page, then + * the data is short and fits entirely on this page, and this + * is the last page. + */ + if (bp[2] == FULL_KEY_DATA && FREESPACE(bp)) + break; + pageno = bp[bp[0] - 1]; + rbufp->flags |= BUF_MOD; + rbufp = __get_buf(hashp, pageno, rbufp, 0); + if (last_bfp) + __free_ovflpage(hashp, last_bfp); + last_bfp = rbufp; + if (!rbufp) + return (-1); /* Error. */ + bp = (u_int16_t *)rbufp->page; + } + + /* + * If we get here then rbufp points to the last page of the big + * key/data pair. Bufp points to the first one -- it should now be + * empty pointing to the next page after this pair. Can't free it + * because we don't have the page pointing to it. + */ + + /* This is information from the last page of the pair. */ + n = bp[0]; + pageno = bp[n - 1]; + + /* Now, bp is the first page of the pair. */ + bp = (u_int16_t *)bufp->page; + if (n > 2) { + /* There is an overflow page. */ + bp[1] = pageno; + bp[2] = OVFLPAGE; + bufp->ovfl = rbufp->ovfl; + } else + /* This is the last page. */ + bufp->ovfl = NULL; + n -= 2; + bp[0] = n; + FREESPACE(bp) = hashp->BSIZE - PAGE_META(n); + OFFSET(bp) = hashp->BSIZE - 1; + + bufp->flags |= BUF_MOD; + if (rbufp) + __free_ovflpage(hashp, rbufp); + if (last_bfp && last_bfp != rbufp) + __free_ovflpage(hashp, last_bfp); + + hashp->NKEYS--; + return (0); +} +/* + * Returns: + * 0 = key not found + * -1 = get next overflow page + * -2 means key not found and this is big key/data + * -3 error + */ +extern int +__find_bigpair(hashp, bufp, ndx, key, size) + HTAB *hashp; + BUFHEAD *bufp; + int ndx; + char *key; + int size; +{ + register u_int16_t *bp; + register char *p; + int ksize; + u_int16_t bytes; + char *kkey; + + bp = (u_int16_t *)bufp->page; + p = bufp->page; + ksize = size; + kkey = key; + + for (bytes = hashp->BSIZE - bp[ndx]; + bytes <= size && bp[ndx + 1] == PARTIAL_KEY; + bytes = hashp->BSIZE - bp[ndx]) { + if (memcmp(p + bp[ndx], kkey, bytes)) + return (-2); + kkey += bytes; + ksize -= bytes; + bufp = __get_buf(hashp, bp[ndx + 2], bufp, 0); + if (!bufp) + return (-3); + p = bufp->page; + bp = (u_int16_t *)p; + ndx = 1; + } + + if (bytes != ksize || memcmp(p + bp[ndx], kkey, bytes)) { +#ifdef HASH_STATISTICS + ++hash_collisions; +#endif + return (-2); + } else + return (ndx); +} + +/* + * Given the buffer pointer of the first overflow page of a big pair, + * find the end of the big pair + * + * This will set bpp to the buffer header of the last page of the big pair. + * It will return the pageno of the overflow page following the last page + * of the pair; 0 if there isn't any (i.e. big pair is the last key in the + * bucket) + */ +extern u_int16_t +__find_last_page(hashp, bpp) + HTAB *hashp; + BUFHEAD **bpp; +{ + BUFHEAD *bufp; + u_int16_t *bp, pageno; + int n; + + bufp = *bpp; + bp = (u_int16_t *)bufp->page; + for (;;) { + n = bp[0]; + + /* + * This is the last page if: the tag is FULL_KEY_DATA and + * either only 2 entries OVFLPAGE marker is explicit there + * is freespace on the page. + */ + if (bp[2] == FULL_KEY_DATA && + ((n == 2) || (bp[n] == OVFLPAGE) || (FREESPACE(bp)))) + break; + + pageno = bp[n - 1]; + bufp = __get_buf(hashp, pageno, bufp, 0); + if (!bufp) + return (0); /* Need to indicate an error! */ + bp = (u_int16_t *)bufp->page; + } + + *bpp = bufp; + if (bp[0] > 2) + return (bp[3]); + else + return (0); +} + +/* + * Return the data for the key/data pair that begins on this page at this + * index (index should always be 1). + */ +extern int +__big_return(hashp, bufp, ndx, val, set_current) + HTAB *hashp; + BUFHEAD *bufp; + int ndx; + DBT *val; + int set_current; +{ + BUFHEAD *save_p; + u_int16_t *bp, len, off, save_addr; + char *tp; + + bp = (u_int16_t *)bufp->page; + while (bp[ndx + 1] == PARTIAL_KEY) { + bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0); + if (!bufp) + return (-1); + bp = (u_int16_t *)bufp->page; + ndx = 1; + } + + if (bp[ndx + 1] == FULL_KEY) { + bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0); + if (!bufp) + return (-1); + bp = (u_int16_t *)bufp->page; + save_p = bufp; + save_addr = save_p->addr; + off = bp[1]; + len = 0; + } else + if (!FREESPACE(bp)) { + /* + * This is a hack. We can't distinguish between + * FULL_KEY_DATA that contains complete data or + * incomplete data, so we require that if the data + * is complete, there is at least 1 byte of free + * space left. + */ + off = bp[bp[0]]; + len = bp[1] - off; + save_p = bufp; + save_addr = bufp->addr; + bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0); + if (!bufp) + return (-1); + bp = (u_int16_t *)bufp->page; + } else { + /* The data is all on one page. */ + tp = (char *)bp; + off = bp[bp[0]]; + val->data = (u_char *)tp + off; + val->size = bp[1] - off; + if (set_current) { + if (bp[0] == 2) { /* No more buckets in + * chain */ + hashp->cpage = NULL; + hashp->cbucket++; + hashp->cndx = 1; + } else { + hashp->cpage = __get_buf(hashp, + bp[bp[0] - 1], bufp, 0); + if (!hashp->cpage) + return (-1); + hashp->cndx = 1; + if (!((u_int16_t *) + hashp->cpage->page)[0]) { + hashp->cbucket++; + hashp->cpage = NULL; + } + } + } + return (0); + } + + val->size = collect_data(hashp, bufp, (int)len, set_current); + if (val->size == (size_t) -1) + return (-1); + if (save_p->addr != save_addr) { + /* We are pretty short on buffers. */ + errno = EINVAL; /* OUT OF BUFFERS */ + return (-1); + } + memmove(hashp->tmp_buf, (save_p->page) + off, len); + val->data = (u_char *)hashp->tmp_buf; + return (0); +} +/* + * Count how big the total datasize is by recursing through the pages. Then + * allocate a buffer and copy the data as you recurse up. + */ +static int +collect_data(hashp, bufp, len, set) + HTAB *hashp; + BUFHEAD *bufp; + int len, set; +{ + register u_int16_t *bp; + register char *p; + BUFHEAD *xbp; + u_int16_t save_addr; + int mylen, totlen; + + p = bufp->page; + bp = (u_int16_t *)p; + mylen = hashp->BSIZE - bp[1]; + save_addr = bufp->addr; + + if (bp[2] == FULL_KEY_DATA) { /* End of Data */ + totlen = len + mylen; + if (hashp->tmp_buf) + free(hashp->tmp_buf); + if ((hashp->tmp_buf = (char *)malloc(totlen)) == NULL) + return (-1); + if (set) { + hashp->cndx = 1; + if (bp[0] == 2) { /* No more buckets in chain */ + hashp->cpage = NULL; + hashp->cbucket++; + } else { + hashp->cpage = + __get_buf(hashp, bp[bp[0] - 1], bufp, 0); + if (!hashp->cpage) + return (-1); + else if (!((u_int16_t *)hashp->cpage->page)[0]) { + hashp->cbucket++; + hashp->cpage = NULL; + } + } + } + } else { + xbp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0); + if (!xbp || ((totlen = + collect_data(hashp, xbp, len + mylen, set)) < 1)) + return (-1); + } + if (bufp->addr != save_addr) { + errno = EINVAL; /* Out of buffers. */ + return (-1); + } + memmove(&hashp->tmp_buf[len], (bufp->page) + bp[1], mylen); + return (totlen); +} + +/* + * Fill in the key and data for this big pair. + */ +extern int +__big_keydata(hashp, bufp, key, val, set) + HTAB *hashp; + BUFHEAD *bufp; + DBT *key, *val; + int set; +{ + key->size = collect_key(hashp, bufp, 0, val, set); + if (key->size == (size_t) -1) + return (-1); + key->data = (u_char *)hashp->tmp_key; + return (0); +} + +/* + * Count how big the total key size is by recursing through the pages. Then + * collect the data, allocate a buffer and copy the key as you recurse up. + */ +static int +collect_key(hashp, bufp, len, val, set) + HTAB *hashp; + BUFHEAD *bufp; + int len; + DBT *val; + int set; +{ + BUFHEAD *xbp; + char *p; + int mylen, totlen; + u_int16_t *bp, save_addr; + + p = bufp->page; + bp = (u_int16_t *)p; + mylen = hashp->BSIZE - bp[1]; + + save_addr = bufp->addr; + totlen = len + mylen; + if (bp[2] == FULL_KEY || bp[2] == FULL_KEY_DATA) { /* End of Key. */ + if (hashp->tmp_key != NULL) + free(hashp->tmp_key); + if ((hashp->tmp_key = (char *)malloc(totlen)) == NULL) + return (-1); + if (__big_return(hashp, bufp, 1, val, set)) + return (-1); + } else { + xbp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0); + if (!xbp || ((totlen = + collect_key(hashp, xbp, totlen, val, set)) < 1)) + return (-1); + } + if (bufp->addr != save_addr) { + errno = EINVAL; /* MIS -- OUT OF BUFFERS */ + return (-1); + } + memmove(&hashp->tmp_key[len], (bufp->page) + bp[1], mylen); + return (totlen); +} + +/* + * Returns: + * 0 => OK + * -1 => error + */ +extern int +__big_split(hashp, op, np, big_keyp, addr, obucket, ret) + HTAB *hashp; + BUFHEAD *op; /* Pointer to where to put keys that go in old bucket */ + BUFHEAD *np; /* Pointer to new bucket page */ + /* Pointer to first page containing the big key/data */ + BUFHEAD *big_keyp; + int addr; /* Address of big_keyp */ + u_int32_t obucket;/* Old Bucket */ + SPLIT_RETURN *ret; +{ + register BUFHEAD *tmpp; + register u_int16_t *tp; + BUFHEAD *bp; + DBT key, val; + u_int32_t change; + u_int16_t free_space, n, off; + + bp = big_keyp; + + /* Now figure out where the big key/data goes */ + if (__big_keydata(hashp, big_keyp, &key, &val, 0)) + return (-1); + change = (__call_hash(hashp, key.data, key.size) != obucket); + + if ((ret->next_addr = __find_last_page(hashp, &big_keyp))) { + if (!(ret->nextp = + __get_buf(hashp, ret->next_addr, big_keyp, 0))) + return (-1);; + } else + ret->nextp = NULL; + + /* Now make one of np/op point to the big key/data pair */ +#ifdef DEBUG + assert(np->ovfl == NULL); +#endif + if (change) + tmpp = np; + else + tmpp = op; + + tmpp->flags |= BUF_MOD; +#ifdef DEBUG1 + (void)fprintf(stderr, + "BIG_SPLIT: %d->ovfl was %d is now %d\n", tmpp->addr, + (tmpp->ovfl ? tmpp->ovfl->addr : 0), (bp ? bp->addr : 0)); +#endif + tmpp->ovfl = bp; /* one of op/np point to big_keyp */ + tp = (u_int16_t *)tmpp->page; +#ifdef DEBUG + assert(FREESPACE(tp) >= OVFLSIZE); +#endif + n = tp[0]; + off = OFFSET(tp); + free_space = FREESPACE(tp); + tp[++n] = (u_int16_t)addr; + tp[++n] = OVFLPAGE; + tp[0] = n; + OFFSET(tp) = off; + FREESPACE(tp) = free_space - OVFLSIZE; + + /* + * Finally, set the new and old return values. BIG_KEYP contains a + * pointer to the last page of the big key_data pair. Make sure that + * big_keyp has no following page (2 elements) or create an empty + * following page. + */ + + ret->newp = np; + ret->oldp = op; + + tp = (u_int16_t *)big_keyp->page; + big_keyp->flags |= BUF_MOD; + if (tp[0] > 2) { + /* + * There may be either one or two offsets on this page. If + * there is one, then the overflow page is linked on normally + * and tp[4] is OVFLPAGE. If there are two, tp[4] contains + * the second offset and needs to get stuffed in after the + * next overflow page is added. + */ + n = tp[4]; + free_space = FREESPACE(tp); + off = OFFSET(tp); + tp[0] -= 2; + FREESPACE(tp) = free_space + OVFLSIZE; + OFFSET(tp) = off; + tmpp = __add_ovflpage(hashp, big_keyp); + if (!tmpp) + return (-1); + tp[4] = n; + } else + tmpp = big_keyp; + + if (change) + ret->newp = tmpp; + else + ret->oldp = tmpp; + return (0); +} diff --git a/utils/db1-ast/hash/hash_buf.c b/utils/db1-ast/hash/hash_buf.c new file mode 100644 index 000000000..063dd8229 --- /dev/null +++ b/utils/db1-ast/hash/hash_buf.c @@ -0,0 +1,355 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)hash_buf.c 8.5 (Berkeley) 7/15/94"; +#endif /* LIBC_SCCS and not lint */ + +/* + * PACKAGE: hash + * + * DESCRIPTION: + * Contains buffer management + * + * ROUTINES: + * External + * __buf_init + * __get_buf + * __buf_free + * __reclaim_buf + * Internal + * newbuf + */ + +#include + +#include +#include +#include +#include + +#ifdef DEBUG +#include +#endif + +#include "../include/db.h" +#include "hash.h" +#include "page.h" +#include "extern.h" + +static BUFHEAD *newbuf __P((HTAB *, u_int32_t, BUFHEAD *)); + +/* Unlink B from its place in the lru */ +#define BUF_REMOVE(B) { \ + (B)->prev->next = (B)->next; \ + (B)->next->prev = (B)->prev; \ +} + +/* Insert B after P */ +#define BUF_INSERT(B, P) { \ + (B)->next = (P)->next; \ + (B)->prev = (P); \ + (P)->next = (B); \ + (B)->next->prev = (B); \ +} + +#define MRU hashp->bufhead.next +#define LRU hashp->bufhead.prev + +#define MRU_INSERT(B) BUF_INSERT((B), &hashp->bufhead) +#define LRU_INSERT(B) BUF_INSERT((B), LRU) + +/* + * We are looking for a buffer with address "addr". If prev_bp is NULL, then + * address is a bucket index. If prev_bp is not NULL, then it points to the + * page previous to an overflow page that we are trying to find. + * + * CAVEAT: The buffer header accessed via prev_bp's ovfl field may no longer + * be valid. Therefore, you must always verify that its address matches the + * address you are seeking. + */ +extern BUFHEAD * +__get_buf(hashp, addr, prev_bp, newpage) + HTAB *hashp; + u_int32_t addr; + BUFHEAD *prev_bp; + int newpage; /* If prev_bp set, indicates a new overflow page. */ +{ + register BUFHEAD *bp; + register u_int32_t is_disk_mask; + register int is_disk, segment_ndx = 0; + SEGMENT segp = 0; + + is_disk = 0; + is_disk_mask = 0; + if (prev_bp) { + bp = prev_bp->ovfl; + if (!bp || (bp->addr != addr)) + bp = NULL; + if (!newpage) + is_disk = BUF_DISK; + } else { + /* Grab buffer out of directory */ + segment_ndx = addr & (hashp->SGSIZE - 1); + + /* valid segment ensured by __call_hash() */ + segp = hashp->dir[addr >> hashp->SSHIFT]; +#ifdef DEBUG + assert(segp != NULL); +#endif + bp = PTROF(segp[segment_ndx]); + is_disk_mask = ISDISK(segp[segment_ndx]); + is_disk = is_disk_mask || !hashp->new_file; + } + + if (!bp) { + bp = newbuf(hashp, addr, prev_bp); + if (!bp || + __get_page(hashp, bp->page, addr, !prev_bp, is_disk, 0)) + return (NULL); + if (!prev_bp) + segp[segment_ndx] = + (BUFHEAD *)((ptrdiff_t)bp | is_disk_mask); + } else { + BUF_REMOVE(bp); + MRU_INSERT(bp); + } + return (bp); +} + +/* + * We need a buffer for this page. Either allocate one, or evict a resident + * one (if we have as many buffers as we're allowed) and put this one in. + * + * If newbuf finds an error (returning NULL), it also sets errno. + */ +static BUFHEAD * +newbuf(hashp, addr, prev_bp) + HTAB *hashp; + u_int32_t addr; + BUFHEAD *prev_bp; +{ + register BUFHEAD *bp; /* The buffer we're going to use */ + register BUFHEAD *xbp; /* Temp pointer */ + register BUFHEAD *next_xbp; + SEGMENT segp; + int segment_ndx; + u_int16_t oaddr, *shortp; + + oaddr = 0; + bp = LRU; + /* + * If LRU buffer is pinned, the buffer pool is too small. We need to + * allocate more buffers. + */ + if (hashp->nbufs || (bp->flags & BUF_PIN)) { + /* Allocate a new one */ + if ((bp = (BUFHEAD *)malloc(sizeof(BUFHEAD))) == NULL) + return (NULL); +#ifdef PURIFY + memset(bp, 0xff, sizeof(BUFHEAD)); +#endif + if ((bp->page = (char *)malloc(hashp->BSIZE)) == NULL) { + free(bp); + return (NULL); + } +#ifdef PURIFY + memset(bp->page, 0xff, hashp->BSIZE); +#endif + if (hashp->nbufs) + hashp->nbufs--; + } else { + /* Kick someone out */ + BUF_REMOVE(bp); + /* + * If this is an overflow page with addr 0, it's already been + * flushed back in an overflow chain and initialized. + */ + if ((bp->addr != 0) || (bp->flags & BUF_BUCKET)) { + /* + * Set oaddr before __put_page so that you get it + * before bytes are swapped. + */ + shortp = (u_int16_t *)bp->page; + if (shortp[0]) + oaddr = shortp[shortp[0] - 1]; + if ((bp->flags & BUF_MOD) && __put_page(hashp, bp->page, + bp->addr, (int)IS_BUCKET(bp->flags), 0)) + return (NULL); + /* + * Update the pointer to this page (i.e. invalidate it). + * + * If this is a new file (i.e. we created it at open + * time), make sure that we mark pages which have been + * written to disk so we retrieve them from disk later, + * rather than allocating new pages. + */ + if (IS_BUCKET(bp->flags)) { + segment_ndx = bp->addr & (hashp->SGSIZE - 1); + segp = hashp->dir[bp->addr >> hashp->SSHIFT]; +#ifdef DEBUG + assert(segp != NULL); +#endif + + if (hashp->new_file && + ((bp->flags & BUF_MOD) || + ISDISK(segp[segment_ndx]))) + segp[segment_ndx] = (BUFHEAD *)BUF_DISK; + else + segp[segment_ndx] = NULL; + } + /* + * Since overflow pages can only be access by means of + * their bucket, free overflow pages associated with + * this bucket. + */ + for (xbp = bp; xbp->ovfl;) { + next_xbp = xbp->ovfl; + xbp->ovfl = 0; + xbp = next_xbp; + + /* Check that ovfl pointer is up date. */ + if (IS_BUCKET(xbp->flags) || + (oaddr != xbp->addr)) + break; + + shortp = (u_int16_t *)xbp->page; + if (shortp[0]) + /* set before __put_page */ + oaddr = shortp[shortp[0] - 1]; + if ((xbp->flags & BUF_MOD) && __put_page(hashp, + xbp->page, xbp->addr, 0, 0)) + return (NULL); + xbp->addr = 0; + xbp->flags = 0; + BUF_REMOVE(xbp); + LRU_INSERT(xbp); + } + } + } + + /* Now assign this buffer */ + bp->addr = addr; +#ifdef DEBUG1 + (void)fprintf(stderr, "NEWBUF1: %d->ovfl was %d is now %d\n", + bp->addr, (bp->ovfl ? bp->ovfl->addr : 0), 0); +#endif + bp->ovfl = NULL; + if (prev_bp) { + /* + * If prev_bp is set, this is an overflow page, hook it in to + * the buffer overflow links. + */ +#ifdef DEBUG1 + (void)fprintf(stderr, "NEWBUF2: %d->ovfl was %d is now %d\n", + prev_bp->addr, (prev_bp->ovfl ? bp->ovfl->addr : 0), + (bp ? bp->addr : 0)); +#endif + prev_bp->ovfl = bp; + bp->flags = 0; + } else + bp->flags = BUF_BUCKET; + MRU_INSERT(bp); + return (bp); +} + +extern void +__buf_init(hashp, nbytes) + HTAB *hashp; + int nbytes; +{ + BUFHEAD *bfp; + int npages; + + bfp = &(hashp->bufhead); + npages = (nbytes + hashp->BSIZE - 1) >> hashp->BSHIFT; + npages = MAX(npages, MIN_BUFFERS); + + hashp->nbufs = npages; + bfp->next = bfp; + bfp->prev = bfp; + /* + * This space is calloc'd so these are already null. + * + * bfp->ovfl = NULL; + * bfp->flags = 0; + * bfp->page = NULL; + * bfp->addr = 0; + */ +} + +extern int +__buf_free(hashp, do_free, to_disk) + HTAB *hashp; + int do_free, to_disk; +{ + BUFHEAD *bp; + + /* Need to make sure that buffer manager has been initialized */ + if (!LRU) + return (0); + for (bp = LRU; bp != &hashp->bufhead;) { + /* Check that the buffer is valid */ + if (bp->addr || IS_BUCKET(bp->flags)) { + if (to_disk && (bp->flags & BUF_MOD) && + __put_page(hashp, bp->page, + bp->addr, IS_BUCKET(bp->flags), 0)) + return (-1); + } + /* Check if we are freeing stuff */ + if (do_free) { + if (bp->page) + free(bp->page); + BUF_REMOVE(bp); + free(bp); + bp = LRU; + } else + bp = bp->prev; + } + return (0); +} + +extern void +__reclaim_buf(hashp, bp) + HTAB *hashp; + BUFHEAD *bp; +{ + bp->ovfl = 0; + bp->addr = 0; + bp->flags = 0; + BUF_REMOVE(bp); + LRU_INSERT(bp); +} diff --git a/utils/db1-ast/hash/hash_func.c b/utils/db1-ast/hash/hash_func.c new file mode 100644 index 000000000..4d7907b57 --- /dev/null +++ b/utils/db1-ast/hash/hash_func.c @@ -0,0 +1,225 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)hash_func.c 8.2 (Berkeley) 2/21/94"; +#endif /* LIBC_SCCS and not lint */ + +#include + +#include "../include/db.h" +#include "hash.h" +#include "page.h" +#include "extern.h" + +/* only one of these can be defined */ +/* #define HASH1_EJB 1 */ +/* #define HASH2_PHONG 1 */ +/* #define HASH3_SDBM 1 */ +#define HASH4_TOREK 1 + +static u_int32_t hashfunc __P((const void *, size_t)); + +/* Global default hash function */ +u_int32_t (*__default_hash) __P((const void *, size_t)) = hashfunc; + +/* + * HASH FUNCTIONS + * + * Assume that we've already split the bucket to which this key hashes, + * calculate that bucket, and check that in fact we did already split it. + * + * This came from ejb's hsearch. + */ + +#ifdef HASH1_EJB + +#define PRIME1 37 +#define PRIME2 1048583 + +static u_int32_t +hashfunc(keyarg, len) + const void *keyarg; + register size_t len; +{ + register const u_char *key; + register u_int32_t h; + + /* Convert string to integer */ + for (key = keyarg, h = 0; len--;) + h = h * PRIME1 ^ (*key++ - ' '); + h %= PRIME2; + return (h); +} + +#endif + +#ifdef HASH2_PHONG +/* + * Phong's linear congruential hash + */ +#define dcharhash(h, c) ((h) = 0x63c63cd9*(h) + 0x9c39c33d + (c)) + +static u_int32_t +hashfunc(keyarg, len) + const void *keyarg; + size_t len; +{ + register const u_char *e, *key; + register u_int32_t h; + register u_char c; + + key = keyarg; + e = key + len; + for (h = 0; key != e;) { + c = *key++; + if (!c && key > e) + break; + dcharhash(h, c); + } + return (h); +} +#endif + +#ifdef HASH3_SDBM +/* + * This is INCREDIBLY ugly, but fast. We break the string up into 8 byte + * units. On the first time through the loop we get the "leftover bytes" + * (strlen % 8). On every other iteration, we perform 8 HASHC's so we handle + * all 8 bytes. Essentially, this saves us 7 cmp & branch instructions. If + * this routine is heavily used enough, it's worth the ugly coding. + * + * OZ's original sdbm hash + */ +static u_int32_t +hashfunc(keyarg, len) + const void *keyarg; + register size_t len; +{ + register const u_char *key; + register size_t loop; + register u_int32_t h; + +#define HASHC h = *key++ + 65599 * h + + h = 0; + key = keyarg; + if (len > 0) { + loop = (len + 8 - 1) >> 3; + + switch (len & (8 - 1)) { + case 0: + do { + HASHC; + /* FALLTHROUGH */ + case 7: + HASHC; + /* FALLTHROUGH */ + case 6: + HASHC; + /* FALLTHROUGH */ + case 5: + HASHC; + /* FALLTHROUGH */ + case 4: + HASHC; + /* FALLTHROUGH */ + case 3: + HASHC; + /* FALLTHROUGH */ + case 2: + HASHC; + /* FALLTHROUGH */ + case 1: + HASHC; + } while (--loop); + } + } + return (h); +} +#endif + +#ifdef HASH4_TOREK +/* Hash function from Chris Torek. */ +static u_int32_t +hashfunc(keyarg, len) + const void *keyarg; + register size_t len; +{ + register const u_char *key; + register size_t loop; + register u_int32_t h; + +#define HASH4a h = (h << 5) - h + *key++; +#define HASH4b h = (h << 5) + h + *key++; +#define HASH4 HASH4b + + h = 0; + key = keyarg; + if (len > 0) { + loop = (len + 8 - 1) >> 3; + + switch (len & (8 - 1)) { + case 0: + do { + HASH4; + /* FALLTHROUGH */ + case 7: + HASH4; + /* FALLTHROUGH */ + case 6: + HASH4; + /* FALLTHROUGH */ + case 5: + HASH4; + /* FALLTHROUGH */ + case 4: + HASH4; + /* FALLTHROUGH */ + case 3: + HASH4; + /* FALLTHROUGH */ + case 2: + HASH4; + /* FALLTHROUGH */ + case 1: + HASH4; + } while (--loop); + } + } + return (h); +} +#endif diff --git a/utils/db1-ast/hash/hash_log2.c b/utils/db1-ast/hash/hash_log2.c new file mode 100644 index 000000000..b86655d47 --- /dev/null +++ b/utils/db1-ast/hash/hash_log2.c @@ -0,0 +1,56 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)hash_log2.c 8.2 (Berkeley) 5/31/94"; +#endif /* LIBC_SCCS and not lint */ + +#include + +#include "../include/db.h" + +u_int32_t __hash_log2 __P((u_int32_t)); + +u_int32_t +__hash_log2(num) + u_int32_t num; +{ + register u_int32_t i, limit; + + limit = 1; + for (i = 0; limit < num; limit = limit << 1, i++); + return (i); +} diff --git a/utils/db1-ast/hash/hash_page.c b/utils/db1-ast/hash/hash_page.c new file mode 100644 index 000000000..52571c552 --- /dev/null +++ b/utils/db1-ast/hash/hash_page.c @@ -0,0 +1,946 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)hash_page.c 8.7 (Berkeley) 8/16/94"; +#endif /* LIBC_SCCS and not lint */ + +/* + * PACKAGE: hashing + * + * DESCRIPTION: + * Page manipulation for hashing package. + * + * ROUTINES: + * + * External + * __get_page + * __add_ovflpage + * Internal + * overflow_page + * open_temp + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#ifdef DEBUG +#include +#endif + +#include "../include/db.h" +#include "hash.h" +#include "page.h" +#include "extern.h" + +static u_int32_t *fetch_bitmap __P((HTAB *, int)); +static u_int32_t first_free __P((u_int32_t)); +static int open_temp __P((HTAB *)); +static u_int16_t overflow_page __P((HTAB *)); +static void putpair __P((char *, const DBT *, const DBT *)); +static void squeeze_key __P((u_int16_t *, const DBT *, const DBT *)); +static int ugly_split + __P((HTAB *, u_int32_t, BUFHEAD *, BUFHEAD *, int, int)); + +#define PAGE_INIT(P) { \ + ((u_int16_t *)(P))[0] = 0; \ + ((u_int16_t *)(P))[1] = hashp->BSIZE - 3 * sizeof(u_int16_t); \ + ((u_int16_t *)(P))[2] = hashp->BSIZE; \ +} + +/* + * This is called AFTER we have verified that there is room on the page for + * the pair (PAIRFITS has returned true) so we go right ahead and start moving + * stuff on. + */ +static void +putpair(p, key, val) + char *p; + const DBT *key, *val; +{ + register u_int16_t *bp, n, off; + + bp = (u_int16_t *)p; + + /* Enter the key first. */ + n = bp[0]; + + off = OFFSET(bp) - key->size; + memmove(p + off, key->data, key->size); + bp[++n] = off; + + /* Now the data. */ + off -= val->size; + memmove(p + off, val->data, val->size); + bp[++n] = off; + + /* Adjust page info. */ + bp[0] = n; + bp[n + 1] = off - ((n + 3) * sizeof(u_int16_t)); + bp[n + 2] = off; +} + +/* + * Returns: + * 0 OK + * -1 error + */ +extern int +__delpair(hashp, bufp, ndx) + HTAB *hashp; + BUFHEAD *bufp; + register int ndx; +{ + register u_int16_t *bp, newoff; + register int n; + u_int16_t pairlen; + + bp = (u_int16_t *)bufp->page; + n = bp[0]; + + if (bp[ndx + 1] < REAL_KEY) + return (__big_delete(hashp, bufp)); + if (ndx != 1) + newoff = bp[ndx - 1]; + else + newoff = hashp->BSIZE; + pairlen = newoff - bp[ndx + 1]; + + if (ndx != (n - 1)) { + /* Hard Case -- need to shuffle keys */ + register int i; + register char *src = bufp->page + (int)OFFSET(bp); + register char *dst = src + (int)pairlen; + memmove(dst, src, bp[ndx + 1] - OFFSET(bp)); + + /* Now adjust the pointers */ + for (i = ndx + 2; i <= n; i += 2) { + if (bp[i + 1] == OVFLPAGE) { + bp[i - 2] = bp[i]; + bp[i - 1] = bp[i + 1]; + } else { + bp[i - 2] = bp[i] + pairlen; + bp[i - 1] = bp[i + 1] + pairlen; + } + } + } + /* Finally adjust the page data */ + bp[n] = OFFSET(bp) + pairlen; + bp[n - 1] = bp[n + 1] + pairlen + 2 * sizeof(u_int16_t); + bp[0] = n - 2; + hashp->NKEYS--; + + bufp->flags |= BUF_MOD; + return (0); +} +/* + * Returns: + * 0 ==> OK + * -1 ==> Error + */ +extern int +__split_page(hashp, obucket, nbucket) + HTAB *hashp; + u_int32_t obucket, nbucket; +{ + register BUFHEAD *new_bufp, *old_bufp; + register u_int16_t *ino; + register char *np; + DBT key, val; + int n, ndx, retval; + u_int16_t copyto, diff, off, moved; + char *op; + + copyto = (u_int16_t)hashp->BSIZE; + off = (u_int16_t)hashp->BSIZE; + old_bufp = __get_buf(hashp, obucket, NULL, 0); + if (old_bufp == NULL) + return (-1); + new_bufp = __get_buf(hashp, nbucket, NULL, 0); + if (new_bufp == NULL) + return (-1); + + old_bufp->flags |= (BUF_MOD | BUF_PIN); + new_bufp->flags |= (BUF_MOD | BUF_PIN); + + ino = (u_int16_t *)(op = old_bufp->page); + np = new_bufp->page; + + moved = 0; + + for (n = 1, ndx = 1; n < ino[0]; n += 2) { + if (ino[n + 1] < REAL_KEY) { + retval = ugly_split(hashp, obucket, old_bufp, new_bufp, + (int)copyto, (int)moved); + old_bufp->flags &= ~BUF_PIN; + new_bufp->flags &= ~BUF_PIN; + return (retval); + + } + key.data = (u_char *)op + ino[n]; + key.size = off - ino[n]; + + if (__call_hash(hashp, key.data, key.size) == obucket) { + /* Don't switch page */ + diff = copyto - off; + if (diff) { + copyto = ino[n + 1] + diff; + memmove(op + copyto, op + ino[n + 1], + off - ino[n + 1]); + ino[ndx] = copyto + ino[n] - ino[n + 1]; + ino[ndx + 1] = copyto; + } else + copyto = ino[n + 1]; + ndx += 2; + } else { + /* Switch page */ + val.data = (u_char *)op + ino[n + 1]; + val.size = ino[n] - ino[n + 1]; + putpair(np, &key, &val); + moved += 2; + } + + off = ino[n + 1]; + } + + /* Now clean up the page */ + ino[0] -= moved; + FREESPACE(ino) = copyto - sizeof(u_int16_t) * (ino[0] + 3); + OFFSET(ino) = copyto; + +#ifdef DEBUG3 + (void)fprintf(stderr, "split %d/%d\n", + ((u_int16_t *)np)[0] / 2, + ((u_int16_t *)op)[0] / 2); +#endif + /* unpin both pages */ + old_bufp->flags &= ~BUF_PIN; + new_bufp->flags &= ~BUF_PIN; + return (0); +} + +/* + * Called when we encounter an overflow or big key/data page during split + * handling. This is special cased since we have to begin checking whether + * the key/data pairs fit on their respective pages and because we may need + * overflow pages for both the old and new pages. + * + * The first page might be a page with regular key/data pairs in which case + * we have a regular overflow condition and just need to go on to the next + * page or it might be a big key/data pair in which case we need to fix the + * big key/data pair. + * + * Returns: + * 0 ==> success + * -1 ==> failure + */ +static int +ugly_split(hashp, obucket, old_bufp, new_bufp, copyto, moved) + HTAB *hashp; + u_int32_t obucket; /* Same as __split_page. */ + BUFHEAD *old_bufp, *new_bufp; + int copyto; /* First byte on page which contains key/data values. */ + int moved; /* Number of pairs moved to new page. */ +{ + register BUFHEAD *bufp; /* Buffer header for ino */ + register u_int16_t *ino; /* Page keys come off of */ + register u_int16_t *np; /* New page */ + register u_int16_t *op; /* Page keys go on to if they aren't moving */ + + BUFHEAD *last_bfp; /* Last buf header OVFL needing to be freed */ + DBT key, val; + SPLIT_RETURN ret; + u_int16_t n, off, ov_addr, scopyto; + char *cino; /* Character value of ino */ + + bufp = old_bufp; + ino = (u_int16_t *)old_bufp->page; + np = (u_int16_t *)new_bufp->page; + op = (u_int16_t *)old_bufp->page; + last_bfp = NULL; + scopyto = (u_int16_t)copyto; /* ANSI */ + + n = ino[0] - 1; + while (n < ino[0]) { + if (ino[2] < REAL_KEY && ino[2] != OVFLPAGE) { + if (__big_split(hashp, old_bufp, + new_bufp, bufp, bufp->addr, obucket, &ret)) + return (-1); + old_bufp = ret.oldp; + if (!old_bufp) + return (-1); + op = (u_int16_t *)old_bufp->page; + new_bufp = ret.newp; + if (!new_bufp) + return (-1); + np = (u_int16_t *)new_bufp->page; + bufp = ret.nextp; + if (!bufp) + return (0); + cino = (char *)bufp->page; + ino = (u_int16_t *)cino; + last_bfp = ret.nextp; + } else if (ino[n + 1] == OVFLPAGE) { + ov_addr = ino[n]; + /* + * Fix up the old page -- the extra 2 are the fields + * which contained the overflow information. + */ + ino[0] -= (moved + 2); + FREESPACE(ino) = + scopyto - sizeof(u_int16_t) * (ino[0] + 3); + OFFSET(ino) = scopyto; + + bufp = __get_buf(hashp, ov_addr, bufp, 0); + if (!bufp) + return (-1); + + ino = (u_int16_t *)bufp->page; + n = 1; + scopyto = hashp->BSIZE; + moved = 0; + + if (last_bfp) + __free_ovflpage(hashp, last_bfp); + last_bfp = bufp; + } + /* Move regular sized pairs of there are any */ + off = hashp->BSIZE; + for (n = 1; (n < ino[0]) && (ino[n + 1] >= REAL_KEY); n += 2) { + cino = (char *)ino; + key.data = (u_char *)cino + ino[n]; + key.size = off - ino[n]; + val.data = (u_char *)cino + ino[n + 1]; + val.size = ino[n] - ino[n + 1]; + off = ino[n + 1]; + + if (__call_hash(hashp, key.data, key.size) == obucket) { + /* Keep on old page */ + if (PAIRFITS(op, (&key), (&val))) + putpair((char *)op, &key, &val); + else { + old_bufp = + __add_ovflpage(hashp, old_bufp); + if (!old_bufp) + return (-1); + op = (u_int16_t *)old_bufp->page; + putpair((char *)op, &key, &val); + } + old_bufp->flags |= BUF_MOD; + } else { + /* Move to new page */ + if (PAIRFITS(np, (&key), (&val))) + putpair((char *)np, &key, &val); + else { + new_bufp = + __add_ovflpage(hashp, new_bufp); + if (!new_bufp) + return (-1); + np = (u_int16_t *)new_bufp->page; + putpair((char *)np, &key, &val); + } + new_bufp->flags |= BUF_MOD; + } + } + } + if (last_bfp) + __free_ovflpage(hashp, last_bfp); + return (0); +} + +/* + * Add the given pair to the page + * + * Returns: + * 0 ==> OK + * 1 ==> failure + */ +extern int +__addel(hashp, bufp, key, val) + HTAB *hashp; + BUFHEAD *bufp; + const DBT *key, *val; +{ + register u_int16_t *bp, *sop; + int do_expand; + + bp = (u_int16_t *)bufp->page; + do_expand = 0; + while (bp[0] && (bp[2] < REAL_KEY || bp[bp[0]] < REAL_KEY)) + /* Exception case */ + if (bp[2] == FULL_KEY_DATA && bp[0] == 2) + /* This is the last page of a big key/data pair + and we need to add another page */ + break; + else if (bp[2] < REAL_KEY && bp[bp[0]] != OVFLPAGE) { + bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0); + if (!bufp) + return (-1); + bp = (u_int16_t *)bufp->page; + } else + /* Try to squeeze key on this page */ + if (FREESPACE(bp) > PAIRSIZE(key, val)) { + squeeze_key(bp, key, val); + return (0); + } else { + bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0); + if (!bufp) + return (-1); + bp = (u_int16_t *)bufp->page; + } + + if (PAIRFITS(bp, key, val)) + putpair(bufp->page, key, val); + else { + do_expand = 1; + bufp = __add_ovflpage(hashp, bufp); + if (!bufp) + return (-1); + sop = (u_int16_t *)bufp->page; + + if (PAIRFITS(sop, key, val)) + putpair((char *)sop, key, val); + else + if (__big_insert(hashp, bufp, key, val)) + return (-1); + } + bufp->flags |= BUF_MOD; + /* + * If the average number of keys per bucket exceeds the fill factor, + * expand the table. + */ + hashp->NKEYS++; + if (do_expand || + (hashp->NKEYS / (hashp->MAX_BUCKET + 1) > hashp->FFACTOR)) + return (__expand_table(hashp)); + return (0); +} + +/* + * + * Returns: + * pointer on success + * NULL on error + */ +extern BUFHEAD * +__add_ovflpage(hashp, bufp) + HTAB *hashp; + BUFHEAD *bufp; +{ + register u_int16_t *sp; + u_int16_t ndx, ovfl_num; +#ifdef DEBUG1 + int tmp1, tmp2; +#endif + sp = (u_int16_t *)bufp->page; + + /* Check if we are dynamically determining the fill factor */ + if (hashp->FFACTOR == DEF_FFACTOR) { + hashp->FFACTOR = sp[0] >> 1; + if (hashp->FFACTOR < MIN_FFACTOR) + hashp->FFACTOR = MIN_FFACTOR; + } + bufp->flags |= BUF_MOD; + ovfl_num = overflow_page(hashp); +#ifdef DEBUG1 + tmp1 = bufp->addr; + tmp2 = bufp->ovfl ? bufp->ovfl->addr : 0; +#endif + if (!ovfl_num || !(bufp->ovfl = __get_buf(hashp, ovfl_num, bufp, 1))) + return (NULL); + bufp->ovfl->flags |= BUF_MOD; +#ifdef DEBUG1 + (void)fprintf(stderr, "ADDOVFLPAGE: %d->ovfl was %d is now %d\n", + tmp1, tmp2, bufp->ovfl->addr); +#endif + ndx = sp[0]; + /* + * Since a pair is allocated on a page only if there's room to add + * an overflow page, we know that the OVFL information will fit on + * the page. + */ + sp[ndx + 4] = OFFSET(sp); + sp[ndx + 3] = FREESPACE(sp) - OVFLSIZE; + sp[ndx + 1] = ovfl_num; + sp[ndx + 2] = OVFLPAGE; + sp[0] = ndx + 2; +#ifdef HASH_STATISTICS + hash_overflows++; +#endif + return (bufp->ovfl); +} + +/* + * Returns: + * 0 indicates SUCCESS + * -1 indicates FAILURE + */ +extern int +__get_page(hashp, p, bucket, is_bucket, is_disk, is_bitmap) + HTAB *hashp; + char *p; + u_int32_t bucket; + int is_bucket, is_disk, is_bitmap; +{ + register int fd, page, size; + int rsize; + u_int16_t *bp; + + fd = hashp->fp; + size = hashp->BSIZE; + + if ((fd == -1) || !is_disk) { + PAGE_INIT(p); + return (0); + } + if (is_bucket) + page = BUCKET_TO_PAGE(bucket); + else + page = OADDR_TO_PAGE(bucket); + if ((lseek(fd, (off_t)page << hashp->BSHIFT, SEEK_SET) == -1) || + ((rsize = read(fd, p, size)) == -1)) + return (-1); + bp = (u_int16_t *)p; + if (!rsize) + bp[0] = 0; /* We hit the EOF, so initialize a new page */ + else + if (rsize != size) { + errno = EFTYPE; + return (-1); + } + if (!is_bitmap && !bp[0]) { + PAGE_INIT(p); + } else + if (hashp->LORDER != BYTE_ORDER) { + register int i, max; + + if (is_bitmap) { + max = hashp->BSIZE >> 2; /* divide by 4 */ + for (i = 0; i < max; i++) + M_32_SWAP(((int *)p)[i]); + } else { + M_16_SWAP(bp[0]); + max = bp[0] + 2; + for (i = 1; i <= max; i++) + M_16_SWAP(bp[i]); + } + } + return (0); +} + +/* + * Write page p to disk + * + * Returns: + * 0 ==> OK + * -1 ==>failure + */ +extern int +__put_page(hashp, p, bucket, is_bucket, is_bitmap) + HTAB *hashp; + char *p; + u_int32_t bucket; + int is_bucket, is_bitmap; +{ + register int fd, page, size; + int wsize; + + size = hashp->BSIZE; + if ((hashp->fp == -1) && open_temp(hashp)) + return (-1); + fd = hashp->fp; + + if (hashp->LORDER != BYTE_ORDER) { + register int i; + register int max; + + if (is_bitmap) { + max = hashp->BSIZE >> 2; /* divide by 4 */ + for (i = 0; i < max; i++) + M_32_SWAP(((int *)p)[i]); + } else { + max = ((u_int16_t *)p)[0] + 2; + for (i = 0; i <= max; i++) + M_16_SWAP(((u_int16_t *)p)[i]); + } + } + if (is_bucket) + page = BUCKET_TO_PAGE(bucket); + else + page = OADDR_TO_PAGE(bucket); + if ((lseek(fd, (off_t)page << hashp->BSHIFT, SEEK_SET) == -1) || + ((wsize = write(fd, p, size)) == -1)) + /* Errno is set */ + return (-1); + if (wsize != size) { + errno = EFTYPE; + return (-1); + } + return (0); +} + +#define BYTE_MASK ((1 << INT_BYTE_SHIFT) -1) +/* + * Initialize a new bitmap page. Bitmap pages are left in memory + * once they are read in. + */ +extern int +__ibitmap(hashp, pnum, nbits, ndx) + HTAB *hashp; + int pnum, nbits, ndx; +{ + u_int32_t *ip; + int clearbytes, clearints; + + if ((ip = (u_int32_t *)malloc(hashp->BSIZE)) == NULL) + return (1); + hashp->nmaps++; + clearints = ((nbits - 1) >> INT_BYTE_SHIFT) + 1; + clearbytes = clearints << INT_TO_BYTE; + (void)memset((char *)ip, 0, clearbytes); + (void)memset(((char *)ip) + clearbytes, 0xFF, + hashp->BSIZE - clearbytes); + ip[clearints - 1] = ALL_SET << (nbits & BYTE_MASK); + SETBIT(ip, 0); + hashp->BITMAPS[ndx] = (u_int16_t)pnum; + hashp->mapp[ndx] = ip; + return (0); +} + +static u_int32_t +first_free(map) + u_int32_t map; +{ + register u_int32_t i, mask; + + mask = 0x1; + for (i = 0; i < BITS_PER_MAP; i++) { + if (!(mask & map)) + return (i); + mask = mask << 1; + } + return (i); +} + +static u_int16_t +overflow_page(hashp) + HTAB *hashp; +{ + register u_int32_t *freep = 0; + register int max_free, offset, splitnum; + u_int16_t addr; + int bit, first_page, free_bit, free_page, i, in_use_bits, j; +#ifdef DEBUG2 + int tmp1, tmp2; +#endif + splitnum = hashp->OVFL_POINT; + max_free = hashp->SPARES[splitnum]; + + free_page = (max_free - 1) >> (hashp->BSHIFT + BYTE_SHIFT); + free_bit = (max_free - 1) & ((hashp->BSIZE << BYTE_SHIFT) - 1); + + /* Look through all the free maps to find the first free block */ + first_page = hashp->LAST_FREED >>(hashp->BSHIFT + BYTE_SHIFT); + for ( i = first_page; i <= free_page; i++ ) { + if (!(freep = (u_int32_t *)hashp->mapp[i]) && + !(freep = fetch_bitmap(hashp, i))) + return (0); + if (i == free_page) + in_use_bits = free_bit; + else + in_use_bits = (hashp->BSIZE << BYTE_SHIFT) - 1; + + if (i == first_page) { + bit = hashp->LAST_FREED & + ((hashp->BSIZE << BYTE_SHIFT) - 1); + j = bit / BITS_PER_MAP; + bit = bit & ~(BITS_PER_MAP - 1); + } else { + bit = 0; + j = 0; + } + for (; bit <= in_use_bits; j++, bit += BITS_PER_MAP) + if (freep[j] != ALL_SET) + goto found; + } + + /* No Free Page Found */ + hashp->LAST_FREED = hashp->SPARES[splitnum]; + hashp->SPARES[splitnum]++; + offset = hashp->SPARES[splitnum] - + (splitnum ? hashp->SPARES[splitnum - 1] : 0); + +#define OVMSG "HASH: Out of overflow pages. Increase page size\n" + if (offset > SPLITMASK) { + if (++splitnum >= NCACHED) { + if (write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1) < 0) { + } + return (0); + } + hashp->OVFL_POINT = splitnum; + hashp->SPARES[splitnum] = hashp->SPARES[splitnum-1]; + hashp->SPARES[splitnum-1]--; + offset = 1; + } + + /* Check if we need to allocate a new bitmap page */ + if (free_bit == (hashp->BSIZE << BYTE_SHIFT) - 1) { + free_page++; + if (free_page >= NCACHED) { + if (write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1) < 0) { + } + return (0); + } + /* + * This is tricky. The 1 indicates that you want the new page + * allocated with 1 clear bit. Actually, you are going to + * allocate 2 pages from this map. The first is going to be + * the map page, the second is the overflow page we were + * looking for. The init_bitmap routine automatically, sets + * the first bit of itself to indicate that the bitmap itself + * is in use. We would explicitly set the second bit, but + * don't have to if we tell init_bitmap not to leave it clear + * in the first place. + */ + if (__ibitmap(hashp, + (int)OADDR_OF(splitnum, offset), 1, free_page)) + return (0); + hashp->SPARES[splitnum]++; +#ifdef DEBUG2 + free_bit = 2; +#endif + offset++; + if (offset > SPLITMASK) { + if (++splitnum >= NCACHED) { + if (write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1) < 0) { + } + return (0); + } + hashp->OVFL_POINT = splitnum; + hashp->SPARES[splitnum] = hashp->SPARES[splitnum-1]; + hashp->SPARES[splitnum-1]--; + offset = 0; + } + } else { + /* + * Free_bit addresses the last used bit. Bump it to address + * the first available bit. + */ + free_bit++; + SETBIT(freep, free_bit); + } + + /* Calculate address of the new overflow page */ + addr = OADDR_OF(splitnum, offset); +#ifdef DEBUG2 + (void)fprintf(stderr, "OVERFLOW_PAGE: ADDR: %d BIT: %d PAGE %d\n", + addr, free_bit, free_page); +#endif + return (addr); + +found: + bit = bit + first_free(freep[j]); + SETBIT(freep, bit); +#ifdef DEBUG2 + tmp1 = bit; + tmp2 = i; +#endif + /* + * Bits are addressed starting with 0, but overflow pages are addressed + * beginning at 1. Bit is a bit addressnumber, so we need to increment + * it to convert it to a page number. + */ + bit = 1 + bit + (i * (hashp->BSIZE << BYTE_SHIFT)); + if (bit >= hashp->LAST_FREED) + hashp->LAST_FREED = bit - 1; + + /* Calculate the split number for this page */ + for (i = 0; (i < splitnum) && (bit > hashp->SPARES[i]); i++); + offset = (i ? bit - hashp->SPARES[i - 1] : bit); + if (offset >= SPLITMASK) + return (0); /* Out of overflow pages */ + addr = OADDR_OF(i, offset); +#ifdef DEBUG2 + (void)fprintf(stderr, "OVERFLOW_PAGE: ADDR: %d BIT: %d PAGE %d\n", + addr, tmp1, tmp2); +#endif + + /* Allocate and return the overflow page */ + return (addr); +} + +/* + * Mark this overflow page as free. + */ +extern void +__free_ovflpage(hashp, obufp) + HTAB *hashp; + BUFHEAD *obufp; +{ + register u_int16_t addr; + u_int32_t *freep; + int bit_address, free_page, free_bit; + u_int16_t ndx; + + addr = obufp->addr; +#ifdef DEBUG1 + (void)fprintf(stderr, "Freeing %d\n", addr); +#endif + ndx = (((u_int16_t)addr) >> SPLITSHIFT); + bit_address = + (ndx ? hashp->SPARES[ndx - 1] : 0) + (addr & SPLITMASK) - 1; + if (bit_address < hashp->LAST_FREED) + hashp->LAST_FREED = bit_address; + free_page = (bit_address >> (hashp->BSHIFT + BYTE_SHIFT)); + free_bit = bit_address & ((hashp->BSIZE << BYTE_SHIFT) - 1); + + if (!(freep = hashp->mapp[free_page])) + freep = fetch_bitmap(hashp, free_page); +#ifdef DEBUG + /* + * This had better never happen. It means we tried to read a bitmap + * that has already had overflow pages allocated off it, and we + * failed to read it from the file. + */ + if (!freep) + assert(0); +#endif + CLRBIT(freep, free_bit); +#ifdef DEBUG2 + (void)fprintf(stderr, "FREE_OVFLPAGE: ADDR: %d BIT: %d PAGE %d\n", + obufp->addr, free_bit, free_page); +#endif + __reclaim_buf(hashp, obufp); +} + +/* + * Returns: + * 0 success + * -1 failure + */ +static int +open_temp(hashp) + HTAB *hashp; +{ + sigset_t set, oset; + static char namestr[] = "_hashXXXXXX"; + + /* Block signals; make sure file goes away at process exit. */ + (void)sigfillset(&set); + (void)sigprocmask(SIG_BLOCK, &set, &oset); + if ((hashp->fp = mkstemp(namestr)) != -1) { + (void)unlink(namestr); + (void)fcntl(hashp->fp, F_SETFD, 1); + } + (void)sigprocmask(SIG_SETMASK, &oset, (sigset_t *)NULL); + return (hashp->fp != -1 ? 0 : -1); +} + +/* + * We have to know that the key will fit, but the last entry on the page is + * an overflow pair, so we need to shift things. + */ +static void +squeeze_key(sp, key, val) + u_int16_t *sp; + const DBT *key, *val; +{ + register char *p; + u_int16_t free_space, n, off, pageno; + + p = (char *)sp; + n = sp[0]; + free_space = FREESPACE(sp); + off = OFFSET(sp); + + pageno = sp[n - 1]; + off -= key->size; + sp[n - 1] = off; + memmove(p + off, key->data, key->size); + off -= val->size; + sp[n] = off; + memmove(p + off, val->data, val->size); + sp[0] = n + 2; + sp[n + 1] = pageno; + sp[n + 2] = OVFLPAGE; + FREESPACE(sp) = free_space - PAIRSIZE(key, val); + OFFSET(sp) = off; +} + +static u_int32_t * +fetch_bitmap(hashp, ndx) + HTAB *hashp; + int ndx; +{ + if (ndx >= hashp->nmaps) + return (NULL); + if ((hashp->mapp[ndx] = (u_int32_t *)malloc(hashp->BSIZE)) == NULL) + return (NULL); + if (__get_page(hashp, + (char *)hashp->mapp[ndx], hashp->BITMAPS[ndx], 0, 1, 1)) { + free(hashp->mapp[ndx]); + return (NULL); + } + return (hashp->mapp[ndx]); +} + +#ifdef DEBUG4 +int +print_chain(addr) + int addr; +{ + BUFHEAD *bufp; + short *bp, oaddr; + + (void)fprintf(stderr, "%d ", addr); + bufp = __get_buf(hashp, addr, NULL, 0); + bp = (short *)bufp->page; + while (bp[0] && ((bp[bp[0]] == OVFLPAGE) || + ((bp[0] > 2) && bp[2] < REAL_KEY))) { + oaddr = bp[bp[0] - 1]; + (void)fprintf(stderr, "%d ", (int)oaddr); + bufp = __get_buf(hashp, (int)oaddr, bufp, 0); + bp = (short *)bufp->page; + } + (void)fprintf(stderr, "\n"); +} +#endif diff --git a/utils/db1-ast/hash/hsearch.c b/utils/db1-ast/hash/hsearch.c new file mode 100644 index 000000000..2971f9308 --- /dev/null +++ b/utils/db1-ast/hash/hsearch.c @@ -0,0 +1,107 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)hsearch.c 8.4 (Berkeley) 7/21/94"; +#endif /* LIBC_SCCS and not lint */ + +#include + +#include +#include + +#include "../include/db.h" +#include "search.h" + +static DB *dbp = NULL; +static ENTRY retval; + +extern int +hcreate(nel) + u_int nel; +{ + HASHINFO info; + + info.nelem = nel; + info.bsize = 256; + info.ffactor = 8; + info.cachesize = 0; + info.hash = NULL; + info.lorder = 0; + dbp = (DB *)__hash_open(NULL, O_CREAT | O_RDWR, 0600, &info, 0); + return ((int)dbp); +} + +extern ENTRY * +hsearch(item, action) + ENTRY item; + ACTION action; +{ + DBT key, val; + int status; + + if (!dbp) + return (NULL); + key.data = (u_char *)item.key; + key.size = strlen(item.key) + 1; + + if (action == ENTER) { + val.data = (u_char *)item.data; + val.size = strlen(item.data) + 1; + status = (dbp->put)(dbp, &key, &val, R_NOOVERWRITE); + if (status) + return (NULL); + } else { + /* FIND */ + status = (dbp->get)(dbp, &key, &val, 0); + if (status) + return (NULL); + else + item.data = (char *)val.data; + } + retval.key = item.key; + retval.data = item.data; + return (&retval); +} + +extern void +hdestroy() +{ + if (dbp) { + (void)(dbp->close)(dbp); + dbp = NULL; + } +} diff --git a/utils/db1-ast/hash/ndbm.c b/utils/db1-ast/hash/ndbm.c new file mode 100644 index 000000000..d702f737a --- /dev/null +++ b/utils/db1-ast/hash/ndbm.c @@ -0,0 +1,235 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)ndbm.c 8.4 (Berkeley) 7/21/94"; +#endif /* LIBC_SCCS and not lint */ + +/* + * This package provides a dbm compatible interface to the new hashing + * package described in db(3). + */ + +#include + +#include +#include +#include + +#include +#include "hash.h" + +/* + * Returns: + * *DBM on success + * NULL on failure + */ +extern DBM * +dbm_open(file, flags, mode) + const char *file; + int flags, mode; +{ + DBM *db; + HASHINFO info; + const size_t len = strlen(file) + sizeof (DBM_SUFFIX); +#ifdef __GNUC__ + char path[len]; +#else + char *path = malloc(len); + if (path == NULL) + return NULL; +#endif + + info.bsize = 4096; + info.ffactor = 40; + info.nelem = 1; + info.cachesize = 0; + info.hash = NULL; + info.lorder = 0; + (void)strncpy(path, file, len - 1); + (void)strncat(path, DBM_SUFFIX, len - strlen(path) - 1); + db = (DBM *)__hash_open(path, flags, mode, &info, 0); +#ifndef __GNUC__ + free(path); +#endif + return db; +} + +extern void +dbm_close(db) + DBM *db; +{ + (void)(db->close)(db); +} + +/* + * Returns: + * DATUM on success + * NULL on failure + */ +extern datum +dbm_fetch(db, key) + DBM *db; + datum key; +{ + datum retdata; + int status; + DBT dbtkey, dbtretdata; + + dbtkey.data = key.dptr; + dbtkey.size = key.dsize; + status = (db->get)(db, &dbtkey, &dbtretdata, 0); + if (status) { + dbtretdata.data = NULL; + dbtretdata.size = 0; + } + retdata.dptr = dbtretdata.data; + retdata.dsize = dbtretdata.size; + return (retdata); +} + +/* + * Returns: + * DATUM on success + * NULL on failure + */ +extern datum +dbm_firstkey(db) + DBM *db; +{ + int status; + datum retkey; + DBT dbtretkey, dbtretdata; + + status = (db->seq)(db, &dbtretkey, &dbtretdata, R_FIRST); + if (status) + dbtretkey.data = NULL; + retkey.dptr = dbtretkey.data; + retkey.dsize = dbtretkey.size; + return (retkey); +} + +/* + * Returns: + * DATUM on success + * NULL on failure + */ +extern datum +dbm_nextkey(db) + DBM *db; +{ + int status; + datum retkey; + DBT dbtretkey, dbtretdata; + + status = (db->seq)(db, &dbtretkey, &dbtretdata, R_NEXT); + if (status) + dbtretkey.data = NULL; + retkey.dptr = dbtretkey.data; + retkey.dsize = dbtretkey.size; + return (retkey); +} +/* + * Returns: + * 0 on success + * <0 failure + */ +extern int +dbm_delete(db, key) + DBM *db; + datum key; +{ + int status; + DBT dbtkey; + + dbtkey.data = key.dptr; + dbtkey.size = key.dsize; + status = (db->del)(db, &dbtkey, 0); + if (status) + return (-1); + else + return (0); +} + +/* + * Returns: + * 0 on success + * <0 failure + * 1 if DBM_INSERT and entry exists + */ +extern int +dbm_store(db, key, data, flags) + DBM *db; + datum key, data; + int flags; +{ + DBT dbtkey, dbtdata; + + dbtkey.data = key.dptr; + dbtkey.size = key.dsize; + dbtdata.data = data.dptr; + dbtdata.size = data.dsize; + return ((db->put)(db, &dbtkey, &dbtdata, + (flags == DBM_INSERT) ? R_NOOVERWRITE : 0)); +} + +extern int +dbm_error(db) + DBM *db; +{ + HTAB *hp; + + hp = (HTAB *)db->internal; + return (hp->errnum); +} + +extern int +dbm_clearerr(db) + DBM *db; +{ + HTAB *hp; + + hp = (HTAB *)db->internal; + hp->errnum = 0; + return (0); +} + +extern int +dbm_dirfno(db) + DBM *db; +{ + return(((HTAB *)db->internal)->fp); +} diff --git a/utils/db1-ast/hash/page.h b/utils/db1-ast/hash/page.h new file mode 100644 index 000000000..0fc0d5a3e --- /dev/null +++ b/utils/db1-ast/hash/page.h @@ -0,0 +1,92 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)page.h 8.2 (Berkeley) 5/31/94 + */ + +/* + * Definitions for hashing page file format. + */ + +/* + * routines dealing with a data page + * + * page format: + * +------------------------------+ + * p | n | keyoff | datoff | keyoff | + * +------------+--------+--------+ + * | datoff | free | ptr | --> | + * +--------+---------------------+ + * | F R E E A R E A | + * +--------------+---------------+ + * | <---- - - - | data | + * +--------+-----+----+----------+ + * | key | data | key | + * +--------+----------+----------+ + * + * Pointer to the free space is always: p[p[0] + 2] + * Amount of free space on the page is: p[p[0] + 1] + */ + +/* + * How many bytes required for this pair? + * 2 shorts in the table at the top of the page + room for the + * key and room for the data + * + * We prohibit entering a pair on a page unless there is also room to append + * an overflow page. The reason for this it that you can get in a situation + * where a single key/data pair fits on a page, but you can't append an + * overflow page and later you'd have to split the key/data and handle like + * a big pair. + * You might as well do this up front. + */ + +#define PAIRSIZE(K,D) (2*sizeof(u_int16_t) + (K)->size + (D)->size) +#define BIGOVERHEAD (4*sizeof(u_int16_t)) +#define KEYSIZE(K) (4*sizeof(u_int16_t) + (K)->size); +#define OVFLSIZE (2*sizeof(u_int16_t)) +#define FREESPACE(P) ((P)[(P)[0]+1]) +#define OFFSET(P) ((P)[(P)[0]+2]) +#define PAIRFITS(P,K,D) \ + (((P)[2] >= REAL_KEY) && \ + (PAIRSIZE((K),(D)) + OVFLSIZE) <= FREESPACE((P))) +#define PAGE_META(N) (((N)+3) * sizeof(u_int16_t)) + +typedef struct { + BUFHEAD *newp; + BUFHEAD *oldp; + BUFHEAD *nextp; + u_int16_t next_addr; +} SPLIT_RETURN; diff --git a/utils/db1-ast/hash/search.h b/utils/db1-ast/hash/search.h new file mode 100644 index 000000000..4d3b9143e --- /dev/null +++ b/utils/db1-ast/hash/search.h @@ -0,0 +1,51 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)search.h 8.1 (Berkeley) 6/4/93 + */ + +/* Backward compatibility to hsearch interface. */ +typedef struct entry { + char *key; + char *data; +} ENTRY; + +typedef enum { + FIND, ENTER +} ACTION; + +int hcreate __P((unsigned int)); +void hdestroy __P((void)); +ENTRY *hsearch __P((ENTRY, ACTION)); diff --git a/utils/db1-ast/include/circ-queue.h b/utils/db1-ast/include/circ-queue.h new file mode 100644 index 000000000..33ba9115b --- /dev/null +++ b/utils/db1-ast/include/circ-queue.h @@ -0,0 +1,131 @@ +/* + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)queue.h 8.5 (Berkeley) 8/20/94 + * $FreeBSD: ports/misc/44bsd-more/files/queue.h,v 1.1 2001/01/06 03:41:36 hoek Exp $ + */ + +/* + * Circular queue definitions. + */ +#define CIRCLEQ_HEAD(name, type) \ +struct name { \ + struct type *cqh_first; /* first element */ \ + struct type *cqh_last; /* last element */ \ +} + +#define CIRCLEQ_ENTRY(type) \ +struct { \ + struct type *cqe_next; /* next element */ \ + struct type *cqe_prev; /* previous element */ \ +} + +/* + * Circular queue functions. + */ +#define CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head)) + +#define CIRCLEQ_FIRST(head) ((head)->cqh_first) + +#define CIRCLEQ_FOREACH(var, head, field) \ + for((var) = (head)->cqh_first; \ + (var) != (void *)(head); \ + (var) = (var)->field.cqe_next) + +#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \ + for((var) = (head)->cqh_last; \ + (var) != (void *)(head); \ + (var) = (var)->field.cqe_prev) + +#define CIRCLEQ_INIT(head) do { \ + (head)->cqh_first = (void *)(head); \ + (head)->cqh_last = (void *)(head); \ +} while (0) + +#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ + (elm)->field.cqe_next = (listelm)->field.cqe_next; \ + (elm)->field.cqe_prev = (listelm); \ + if ((listelm)->field.cqe_next == (void *)(head)) \ + (head)->cqh_last = (elm); \ + else \ + (listelm)->field.cqe_next->field.cqe_prev = (elm); \ + (listelm)->field.cqe_next = (elm); \ +} while (0) + +#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ + (elm)->field.cqe_next = (listelm); \ + (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \ + if ((listelm)->field.cqe_prev == (void *)(head)) \ + (head)->cqh_first = (elm); \ + else \ + (listelm)->field.cqe_prev->field.cqe_next = (elm); \ + (listelm)->field.cqe_prev = (elm); \ +} while (0) + +#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \ + (elm)->field.cqe_next = (head)->cqh_first; \ + (elm)->field.cqe_prev = (void *)(head); \ + if ((head)->cqh_last == (void *)(head)) \ + (head)->cqh_last = (elm); \ + else \ + (head)->cqh_first->field.cqe_prev = (elm); \ + (head)->cqh_first = (elm); \ +} while (0) + +#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.cqe_next = (void *)(head); \ + (elm)->field.cqe_prev = (head)->cqh_last; \ + if ((head)->cqh_first == (void *)(head)) \ + (head)->cqh_first = (elm); \ + else \ + (head)->cqh_last->field.cqe_next = (elm); \ + (head)->cqh_last = (elm); \ +} while (0) + +#define CIRCLEQ_LAST(head) ((head)->cqh_last) + +#define CIRCLEQ_NEXT(elm,field) ((elm)->field.cqe_next) + +#define CIRCLEQ_PREV(elm,field) ((elm)->field.cqe_prev) + +#define CIRCLEQ_REMOVE(head, elm, field) do { \ + if ((elm)->field.cqe_next == (void *)(head)) \ + (head)->cqh_last = (elm)->field.cqe_prev; \ + else \ + (elm)->field.cqe_next->field.cqe_prev = \ + (elm)->field.cqe_prev; \ + if ((elm)->field.cqe_prev == (void *)(head)) \ + (head)->cqh_first = (elm)->field.cqe_next; \ + else \ + (elm)->field.cqe_prev->field.cqe_next = \ + (elm)->field.cqe_next; \ +} while (0) diff --git a/utils/db1-ast/include/compat.h b/utils/db1-ast/include/compat.h new file mode 100644 index 000000000..706e58265 --- /dev/null +++ b/utils/db1-ast/include/compat.h @@ -0,0 +1,49 @@ +/* Values for building 4.4 BSD db routines in the GNU C library. */ + +#ifndef _compat_h_ +#define _compat_h_ + +#include + +/* + * If you can't provide lock values in the open(2) call. Note, this + * allows races to happen. + */ +#ifndef O_EXLOCK /* 4.4BSD extension. */ +#define O_EXLOCK 0 +#endif + +#ifndef O_SHLOCK /* 4.4BSD extension. */ +#define O_SHLOCK 0 +#endif + +#include + +#ifndef EFTYPE +#define EFTYPE EINVAL /* POSIX 1003.1 format errno. */ +#endif + +#include +#include + +#ifndef _POSIX_VDISABLE /* POSIX 1003.1 disabling char. */ +#define _POSIX_VDISABLE 0 /* Some systems used 0. */ +#endif + +#include + +#ifndef TCSASOFT /* 4.4BSD extension. */ +#define TCSASOFT 0 +#endif + +#include + +#ifndef MAX /* Usually found in . */ +#define MAX(_a,_b) ((_a)<(_b)?(_b):(_a)) +#endif +#ifndef MIN /* Usually found in . */ +#define MIN(_a,_b) ((_a)<(_b)?(_a):(_b)) +#endif + + +#endif /* compat.h */ diff --git a/utils/db1-ast/include/db.h b/utils/db1-ast/include/db.h new file mode 100644 index 000000000..a58724bdd --- /dev/null +++ b/utils/db1-ast/include/db.h @@ -0,0 +1,250 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)db.h 8.7 (Berkeley) 6/16/94 + */ + +#ifndef _DB_H +#define _DB_H 1 + +#include +#include + +#include + +#ifdef __DBINTERFACE_PRIVATE +#include +#endif + +#ifdef SOLARIS +#include "solaris-compat/compat.h" +#endif + +#define RET_ERROR -1 /* Return values. */ +#define RET_SUCCESS 0 +#define RET_SPECIAL 1 + +#ifndef __BIT_TYPES_DEFINED__ +#define __BIT_TYPES_DEFINED__ +#if (!defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__APPLE__)) +typedef __signed char int8_t; +typedef short int16_t; +typedef int int32_t; +typedef unsigned char u_int8_t; +typedef unsigned short u_int16_t; +typedef unsigned int u_int32_t; +#ifdef WE_DONT_NEED_QUADS +typedef long long int64_t; +typedef unsigned long long u_int64_t; +#endif +#endif /* __FreeBSD__ */ +#endif + +#ifdef SOLARIS +#define __P(p) p +#define __BEGIN_DECLS +#define __END_DECLS +#endif + +#define MAX_PAGE_NUMBER 0xffffffff /* >= # of pages in a file */ +typedef u_int32_t pgno_t; +#define MAX_PAGE_OFFSET 65535 /* >= # of bytes in a page */ +typedef u_int16_t indx_t; +#define MAX_REC_NUMBER 0xffffffff /* >= # of records in a tree */ +typedef u_int32_t recno_t; + +/* Key/data structure -- a Data-Base Thang. */ +typedef struct { + void *data; /* data */ + size_t size; /* data length */ +} DBT; + +/* Routine flags. */ +#define R_CURSOR 1 /* del, put, seq */ +#define __R_UNUSED 2 /* UNUSED */ +#define R_FIRST 3 /* seq */ +#define R_IAFTER 4 /* put (RECNO) */ +#define R_IBEFORE 5 /* put (RECNO) */ +#define R_LAST 6 /* seq (BTREE, RECNO) */ +#define R_NEXT 7 /* seq */ +#define R_NOOVERWRITE 8 /* put */ +#define R_PREV 9 /* seq (BTREE, RECNO) */ +#define R_SETCURSOR 10 /* put (RECNO) */ +#define R_RECNOSYNC 11 /* sync (RECNO) */ + +typedef enum { DB_BTREE, DB_HASH, DB_RECNO } DBTYPE; + +/* + * !!! + * The following flags are included in the dbopen(3) call as part of the + * open(2) flags. In order to avoid conflicts with the open flags, start + * at the top of the 16 or 32-bit number space and work our way down. If + * the open flags were significantly expanded in the future, it could be + * a problem. Wish I'd left another flags word in the dbopen call. + * + * !!! + * None of this stuff is implemented yet. The only reason that it's here + * is so that the access methods can skip copying the key/data pair when + * the DB_LOCK flag isn't set. + */ +#if UINT_MAX > 65535 +#define DB_LOCK 0x20000000 /* Do locking. */ +#define DB_SHMEM 0x40000000 /* Use shared memory. */ +#define DB_TXN 0x80000000 /* Do transactions. */ +#else +#define DB_LOCK 0x2000 /* Do locking. */ +#define DB_SHMEM 0x4000 /* Use shared memory. */ +#define DB_TXN 0x8000 /* Do transactions. */ +#endif + +/* Access method description structure. */ +typedef struct __db { + DBTYPE type; /* Underlying db type. */ + int (*close) __P((struct __db *)); + int (*del) __P((const struct __db *, const DBT *, u_int)); + int (*get) __P((const struct __db *, const DBT *, DBT *, u_int)); + int (*put) __P((const struct __db *, DBT *, const DBT *, u_int)); + int (*seq) __P((const struct __db *, DBT *, DBT *, u_int)); + int (*sync) __P((const struct __db *, u_int)); + void *internal; /* Access method private. */ + int (*fd) __P((const struct __db *)); +} DB; + +#define BTREEMAGIC 0x053162 +#define BTREEVERSION 3 + +/* Structure used to pass parameters to the btree routines. */ +typedef struct { +#define R_DUP 0x01 /* duplicate keys */ + u_long flags; + u_int cachesize; /* bytes to cache */ + int maxkeypage; /* maximum keys per page */ + int minkeypage; /* minimum keys per page */ + u_int psize; /* page size */ + int (*compare) /* comparison function */ + __P((const DBT *, const DBT *)); + size_t (*prefix) /* prefix function */ + __P((const DBT *, const DBT *)); + int lorder; /* byte order */ +} BTREEINFO; + +#define HASHMAGIC 0x061561 +#define HASHVERSION 2 + +/* Structure used to pass parameters to the hashing routines. */ +typedef struct { + u_int bsize; /* bucket size */ + u_int ffactor; /* fill factor */ + u_int nelem; /* number of elements */ + u_int cachesize; /* bytes to cache */ + u_int32_t /* hash function */ + (*hash) __P((const void *, size_t)); + int lorder; /* byte order */ +} HASHINFO; + +/* Structure used to pass parameters to the record routines. */ +typedef struct { +#define R_FIXEDLEN 0x01 /* fixed-length records */ +#define R_NOKEY 0x02 /* key not required */ +#define R_SNAPSHOT 0x04 /* snapshot the input */ + u_long flags; + u_int cachesize; /* bytes to cache */ + u_int psize; /* page size */ + int lorder; /* byte order */ + size_t reclen; /* record length (fixed-length records) */ + u_char bval; /* delimiting byte (variable-length records */ + char *bfname; /* btree file name */ +} RECNOINFO; + +#ifdef __DBINTERFACE_PRIVATE +/* + * Little endian <==> big endian 32-bit swap macros. + * M_32_SWAP swap a memory location + * P_32_SWAP swap a referenced memory location + * P_32_COPY swap from one location to another + */ +#define M_32_SWAP(a) { \ + u_int32_t _tmp = a; \ + ((char *)&a)[0] = ((char *)&_tmp)[3]; \ + ((char *)&a)[1] = ((char *)&_tmp)[2]; \ + ((char *)&a)[2] = ((char *)&_tmp)[1]; \ + ((char *)&a)[3] = ((char *)&_tmp)[0]; \ +} +#define P_32_SWAP(a) { \ + u_int32_t _tmp = *(u_int32_t *)a; \ + ((char *)a)[0] = ((char *)&_tmp)[3]; \ + ((char *)a)[1] = ((char *)&_tmp)[2]; \ + ((char *)a)[2] = ((char *)&_tmp)[1]; \ + ((char *)a)[3] = ((char *)&_tmp)[0]; \ +} +#define P_32_COPY(a, b) { \ + ((char *)&(b))[0] = ((char *)&(a))[3]; \ + ((char *)&(b))[1] = ((char *)&(a))[2]; \ + ((char *)&(b))[2] = ((char *)&(a))[1]; \ + ((char *)&(b))[3] = ((char *)&(a))[0]; \ +} + +/* + * Little endian <==> big endian 16-bit swap macros. + * M_16_SWAP swap a memory location + * P_16_SWAP swap a referenced memory location + * P_16_COPY swap from one location to another + */ +#define M_16_SWAP(a) { \ + u_int16_t _tmp = a; \ + ((char *)&a)[0] = ((char *)&_tmp)[1]; \ + ((char *)&a)[1] = ((char *)&_tmp)[0]; \ +} +#define P_16_SWAP(a) { \ + u_int16_t _tmp = *(u_int16_t *)a; \ + ((char *)a)[0] = ((char *)&_tmp)[1]; \ + ((char *)a)[1] = ((char *)&_tmp)[0]; \ +} +#define P_16_COPY(a, b) { \ + ((char *)&(b))[0] = ((char *)&(a))[1]; \ + ((char *)&(b))[1] = ((char *)&(a))[0]; \ +} +#endif + +__BEGIN_DECLS +DB *__dbopen __P((const char *, int, int, DBTYPE, const void *)); +DB *dbopen __P((const char *, int, int, DBTYPE, const void *)); + +#ifdef __DBINTERFACE_PRIVATE +DB *__bt_open __P((const char *, int, int, const BTREEINFO *, int)); +DB *__hash_open __P((const char *, int, int, const HASHINFO *, int)); +DB *__rec_open __P((const char *, int, int, const RECNOINFO *, int)); +void __dbpanic __P((DB *dbp)); +#endif +__END_DECLS + +#endif /* db.h */ diff --git a/utils/db1-ast/include/mpool.h b/utils/db1-ast/include/mpool.h new file mode 100644 index 000000000..0cfc5741c --- /dev/null +++ b/utils/db1-ast/include/mpool.h @@ -0,0 +1,115 @@ +/*- + * Copyright (c) 1991, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)mpool.h 8.2 (Berkeley) 7/14/94 + */ + +#ifndef _MPOOL_H +#define _MPOOL_H 1 + +#include +#ifndef CIRCLEQ_HEAD +#include +#endif + +/* + * The memory pool scheme is a simple one. Each in-memory page is referenced + * by a bucket which is threaded in up to two of three ways. All active pages + * are threaded on a hash chain (hashed by page number) and an lru chain. + * Inactive pages are threaded on a free chain. Each reference to a memory + * pool is handed an opaque MPOOL cookie which stores all of this information. + */ +#define HASHSIZE 128 +#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE) + +/* The BKT structures are the elements of the queues. */ +typedef struct _bkt { + CIRCLEQ_ENTRY(_bkt) hq; /* hash queue */ + CIRCLEQ_ENTRY(_bkt) q; /* lru queue */ + void *page; /* page */ + pgno_t pgno; /* page number */ + +#define MPOOL_DIRTY 0x01 /* page needs to be written */ +#define MPOOL_PINNED 0x02 /* page is pinned into memory */ + u_int8_t flags; /* flags */ +} BKT; + +typedef struct MPOOL { + CIRCLEQ_HEAD(_lqh, _bkt) lqh; /* lru queue head */ + /* hash queue array */ + CIRCLEQ_HEAD(_hqh, _bkt) hqh[HASHSIZE]; + pgno_t curcache; /* current number of cached pages */ + pgno_t maxcache; /* max number of cached pages */ + pgno_t npages; /* number of pages in the file */ + u_long pagesize; /* file page size */ + int fd; /* file descriptor */ + /* page in conversion routine */ + void (*pgin) __P((void *, pgno_t, void *)); + /* page out conversion routine */ + void (*pgout) __P((void *, pgno_t, void *)); + void *pgcookie; /* cookie for page in/out routines */ +#ifdef STATISTICS + u_long cachehit; + u_long cachemiss; + u_long pagealloc; + u_long pageflush; + u_long pageget; + u_long pagenew; + u_long pageput; + u_long pageread; + u_long pagewrite; +#endif +} MPOOL; + +__BEGIN_DECLS +MPOOL *__mpool_open __P((void *, int, pgno_t, pgno_t)); +MPOOL *mpool_open __P((void *, int, pgno_t, pgno_t)); +void __mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), + void (*)(void *, pgno_t, void *), void *)); +void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), + void (*)(void *, pgno_t, void *), void *)); +void *__mpool_new __P((MPOOL *, pgno_t *)); +void *mpool_new __P((MPOOL *, pgno_t *)); +void *__mpool_get __P((MPOOL *, pgno_t, u_int)); +void *mpool_get __P((MPOOL *, pgno_t, u_int)); +int __mpool_put __P((MPOOL *, void *, u_int)); +int mpool_put __P((MPOOL *, void *, u_int)); +int __mpool_sync __P((MPOOL *)); +int mpool_sync __P((MPOOL *)); +int __mpool_close __P((MPOOL *)); +int mpool_close __P((MPOOL *)); +#ifdef STATISTICS +void mpool_stat __P((MPOOL *)); +#endif +__END_DECLS + +#endif /* mpool.h */ diff --git a/utils/db1-ast/include/ndbm.h b/utils/db1-ast/include/ndbm.h new file mode 100644 index 000000000..d2079b0a5 --- /dev/null +++ b/utils/db1-ast/include/ndbm.h @@ -0,0 +1,79 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ndbm.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _NDBM_H +#define _NDBM_H 1 + +#include "db.h" + +/* Map dbm interface onto db(3). */ +#define DBM_RDONLY O_RDONLY + +/* Flags to dbm_store(). */ +#define DBM_INSERT 0 +#define DBM_REPLACE 1 + +/* + * The db(3) support for ndbm(3) always appends this suffix to the + * file name to avoid overwriting the user's original database. + */ +#define DBM_SUFFIX ".db" + +typedef struct { + char *dptr; + int dsize; +} datum; + +typedef DB DBM; +#define dbm_pagfno(a) DBM_PAGFNO_NOT_AVAILABLE + +__BEGIN_DECLS +void dbm_close __P((DBM *)); +int dbm_delete __P((DBM *, datum)); +datum dbm_fetch __P((DBM *, datum)); +datum dbm_firstkey __P((DBM *)); +long dbm_forder __P((DBM *, datum)); +datum dbm_nextkey __P((DBM *)); +DBM *dbm_open __P((const char *, int, int)); +int dbm_store __P((DBM *, datum, datum, int)); +int dbm_dirfno __P((DBM *)); +int dbm_error __P((DBM *)); +int dbm_clearerr __P((DBM *)); +__END_DECLS + +#endif /* ndbm.h */ diff --git a/utils/db1-ast/libdb.map b/utils/db1-ast/libdb.map new file mode 100644 index 000000000..87e34c430 --- /dev/null +++ b/utils/db1-ast/libdb.map @@ -0,0 +1,11 @@ +GLIBC_2.0 { + global: + # the real DB entry point. + dbopen; __dbopen; + + # The compatibility functions. + dbm_clearerr; dbm_close; dbm_delete; dbm_dirfno; dbm_error; + dbm_fetch; dbm_firstkey; dbm_nextkey; dbm_open; dbm_store; + local: + *; +}; diff --git a/utils/db1-ast/mpool/README b/utils/db1-ast/mpool/README new file mode 100644 index 000000000..0f01fbcdb --- /dev/null +++ b/utils/db1-ast/mpool/README @@ -0,0 +1,7 @@ +# @(#)README 8.1 (Berkeley) 6/4/93 + +These are the current memory pool routines. +They aren't ready for prime time, yet, and +the interface is expected to change. + +--keith diff --git a/utils/db1-ast/mpool/mpool.c b/utils/db1-ast/mpool/mpool.c new file mode 100644 index 000000000..f095b27f5 --- /dev/null +++ b/utils/db1-ast/mpool/mpool.c @@ -0,0 +1,498 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)mpool.c 8.5 (Berkeley) 7/26/94"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "../include/db.h" + +#define __MPOOLINTERFACE_PRIVATE +#include + +#undef __APPLE__ + +#ifndef __APPLE__ +#define mpool_open __mpool_open +#define mpool_filter __mpool_filter +#define mpool_new __mpool_new +#define mpool_get __mpool_get +#define mpool_put __mpool_put +#define mpool_sync __mpool_sync +#define mpool_close __mpool_close +#endif + +static BKT *mpool_bkt __P((MPOOL *)); +static BKT *mpool_look __P((MPOOL *, pgno_t)); +static int mpool_write __P((MPOOL *, BKT *)); + +/* + * mpool_open -- + * Initialize a memory pool. + */ +MPOOL * +mpool_open(key, fd, pagesize, maxcache) + void *key; + int fd; + pgno_t pagesize, maxcache; +{ + struct stat sb; + MPOOL *mp; + int entry; + + /* + * Get information about the file. + * + * XXX + * We don't currently handle pipes, although we should. + */ + if (fstat(fd, &sb)) + return (NULL); + if (!S_ISREG(sb.st_mode)) { + errno = ESPIPE; + return (NULL); + } + + /* Allocate and initialize the MPOOL cookie. */ + if ((mp = (MPOOL *)calloc(1, sizeof(MPOOL))) == NULL) + return (NULL); + CIRCLEQ_INIT(&mp->lqh); + for (entry = 0; entry < HASHSIZE; ++entry) + CIRCLEQ_INIT(&mp->hqh[entry]); + mp->maxcache = maxcache; + mp->npages = sb.st_size / pagesize; + mp->pagesize = pagesize; + mp->fd = fd; + return (mp); +} + +/* + * mpool_filter -- + * Initialize input/output filters. + */ +void +mpool_filter(mp, pgin, pgout, pgcookie) + MPOOL *mp; + void (*pgin) __P((void *, pgno_t, void *)); + void (*pgout) __P((void *, pgno_t, void *)); + void *pgcookie; +{ + mp->pgin = pgin; + mp->pgout = pgout; + mp->pgcookie = pgcookie; +} + +/* + * mpool_new -- + * Get a new page of memory. + */ +void * +mpool_new(mp, pgnoaddr) + MPOOL *mp; + pgno_t *pgnoaddr; +{ + struct _hqh *head; + BKT *bp; + + if (mp->npages == MAX_PAGE_NUMBER) { + (void)fprintf(stderr, "mpool_new: page allocation overflow.\n"); + abort(); + } +#ifdef STATISTICS + ++mp->pagenew; +#endif + /* + * Get a BKT from the cache. Assign a new page number, attach + * it to the head of the hash chain, the tail of the lru chain, + * and return. + */ + if ((bp = mpool_bkt(mp)) == NULL) + return (NULL); + *pgnoaddr = bp->pgno = mp->npages++; + bp->flags = MPOOL_PINNED; + + head = &mp->hqh[HASHKEY(bp->pgno)]; + CIRCLEQ_INSERT_HEAD(head, bp, hq); + CIRCLEQ_INSERT_TAIL(&mp->lqh, bp, q); + return (bp->page); +} + +/* + * mpool_get + * Get a page. + */ +void * +mpool_get(mp, pgno, flags) + MPOOL *mp; + pgno_t pgno; + u_int flags; /* XXX not used? */ +{ + struct _hqh *head; + BKT *bp; + off_t off; + int nr; + + /* Check for attempt to retrieve a non-existent page. */ + if (pgno >= mp->npages) { + errno = EINVAL; + return (NULL); + } + +#ifdef STATISTICS + ++mp->pageget; +#endif + + /* Check for a page that is cached. */ + if ((bp = mpool_look(mp, pgno)) != NULL) { +#ifdef DEBUG + if (bp->flags & MPOOL_PINNED) { + (void)fprintf(stderr, + "mpool_get: page %d already pinned\n", bp->pgno); + abort(); + } +#endif + /* + * Move the page to the head of the hash chain and the tail + * of the lru chain. + */ + head = &mp->hqh[HASHKEY(bp->pgno)]; + CIRCLEQ_REMOVE(head, bp, hq); + CIRCLEQ_INSERT_HEAD(head, bp, hq); + CIRCLEQ_REMOVE(&mp->lqh, bp, q); + CIRCLEQ_INSERT_TAIL(&mp->lqh, bp, q); + + /* Return a pinned page. */ + bp->flags |= MPOOL_PINNED; + return (bp->page); + } + + /* Get a page from the cache. */ + if ((bp = mpool_bkt(mp)) == NULL) + return (NULL); + + /* Read in the contents. */ +#ifdef STATISTICS + ++mp->pageread; +#endif + off = mp->pagesize * pgno; + if (lseek(mp->fd, off, SEEK_SET) != off) + return (NULL); + if ((u_long) (nr = read(mp->fd, bp->page, mp->pagesize)) + != mp->pagesize) { + if (nr >= 0) + errno = EFTYPE; + return (NULL); + } + + /* Set the page number, pin the page. */ + bp->pgno = pgno; + bp->flags = MPOOL_PINNED; + + /* + * Add the page to the head of the hash chain and the tail + * of the lru chain. + */ + head = &mp->hqh[HASHKEY(bp->pgno)]; + CIRCLEQ_INSERT_HEAD(head, bp, hq); + CIRCLEQ_INSERT_TAIL(&mp->lqh, bp, q); + + /* Run through the user's filter. */ + if (mp->pgin != NULL) + (mp->pgin)(mp->pgcookie, bp->pgno, bp->page); + + return (bp->page); +} + +/* + * mpool_put + * Return a page. + */ +int +mpool_put(mp, page, flags) + MPOOL *mp; + void *page; + u_int flags; +{ + BKT *bp; + +#ifdef STATISTICS + ++mp->pageput; +#endif + bp = (BKT *)((char *)page - sizeof(BKT)); +#ifdef DEBUG + if (!(bp->flags & MPOOL_PINNED)) { + (void)fprintf(stderr, + "mpool_put: page %d not pinned\n", bp->pgno); + abort(); + } +#endif + bp->flags &= ~MPOOL_PINNED; + bp->flags |= flags & MPOOL_DIRTY; + return (RET_SUCCESS); +} + +/* + * mpool_close + * Close the buffer pool. + */ +int +mpool_close(mp) + MPOOL *mp; +{ + BKT *bp; + + /* Free up any space allocated to the lru pages. */ + while ((bp = mp->lqh.cqh_first) != (void *)&mp->lqh) { + CIRCLEQ_REMOVE(&mp->lqh, mp->lqh.cqh_first, q); + free(bp); + } + + /* Free the MPOOL cookie. */ + free(mp); + return (RET_SUCCESS); +} + +/* + * mpool_sync + * Sync the pool to disk. + */ +int +mpool_sync(mp) + MPOOL *mp; +{ + BKT *bp; + + /* Walk the lru chain, flushing any dirty pages to disk. */ + for (bp = mp->lqh.cqh_first; + bp != (void *)&mp->lqh; bp = bp->q.cqe_next) + if (bp->flags & MPOOL_DIRTY && + mpool_write(mp, bp) == RET_ERROR) + return (RET_ERROR); + + /* Sync the file descriptor. */ + return (fsync(mp->fd) ? RET_ERROR : RET_SUCCESS); +} + +#define __APPLE__ + +#ifndef __APPLE__ +#undef mpool_open +#undef mpool_filter +#undef mpool_new +#undef mpool_get +#undef mpool_put +#undef mpool_close +#undef mpool_sync + +#define weak_alias(original, alias) \ + asm (".weak " #alias "\n" #alias " = " #original); +weak_alias (__mpool_open, mpool_open) +weak_alias (__mpool_filter, mpool_filter) +weak_alias (__mpool_new, mpool_new) +weak_alias (__mpool_get, mpool_get) +weak_alias (__mpool_put, mpool_put) +weak_alias (__mpool_close, mpool_close) +weak_alias (__mpool_sync, mpool_sync) +#endif + +/* + * mpool_bkt + * Get a page from the cache (or create one). + */ +static BKT * +mpool_bkt(mp) + MPOOL *mp; +{ + struct _hqh *head; + BKT *bp; + + /* If under the max cached, always create a new page. */ + if (mp->curcache < mp->maxcache) + goto new; + + /* + * If the cache is max'd out, walk the lru list for a buffer we + * can flush. If we find one, write it (if necessary) and take it + * off any lists. If we don't find anything we grow the cache anyway. + * The cache never shrinks. + */ + for (bp = mp->lqh.cqh_first; + bp != (void *)&mp->lqh; bp = bp->q.cqe_next) + if (!(bp->flags & MPOOL_PINNED)) { + /* Flush if dirty. */ + if (bp->flags & MPOOL_DIRTY && + mpool_write(mp, bp) == RET_ERROR) + return (NULL); +#ifdef STATISTICS + ++mp->pageflush; +#endif + /* Remove from the hash and lru queues. */ + head = &mp->hqh[HASHKEY(bp->pgno)]; + CIRCLEQ_REMOVE(head, bp, hq); + CIRCLEQ_REMOVE(&mp->lqh, bp, q); +#ifdef DEBUG + { void *spage; + spage = bp->page; + memset(bp, 0xff, sizeof(BKT) + mp->pagesize); + bp->page = spage; + } +#endif + return (bp); + } + +new: if ((bp = (BKT *) calloc(1, sizeof(BKT) + mp->pagesize)) == NULL) + return (NULL); +#ifdef STATISTICS + ++mp->pagealloc; +#endif +#if defined(DEBUG) || defined(PURIFY) + memset(bp, 0xff, sizeof(BKT) + mp->pagesize); +#endif + bp->page = (char *)bp + sizeof(BKT); + ++mp->curcache; + return (bp); +} + +/* + * mpool_write + * Write a page to disk. + */ +static int +mpool_write(mp, bp) + MPOOL *mp; + BKT *bp; +{ + off_t off; + +#ifdef STATISTICS + ++mp->pagewrite; +#endif + + /* Run through the user's filter. */ + if (mp->pgout) + (mp->pgout)(mp->pgcookie, bp->pgno, bp->page); + + off = mp->pagesize * bp->pgno; + if (lseek(mp->fd, off, SEEK_SET) != off) + return (RET_ERROR); + if ((u_long) write(mp->fd, bp->page, mp->pagesize) != mp->pagesize) + return (RET_ERROR); + + bp->flags &= ~MPOOL_DIRTY; + return (RET_SUCCESS); +} + +/* + * mpool_look + * Lookup a page in the cache. + */ +static BKT * +mpool_look(mp, pgno) + MPOOL *mp; + pgno_t pgno; +{ + struct _hqh *head; + BKT *bp; + + head = &mp->hqh[HASHKEY(pgno)]; + for (bp = head->cqh_first; bp != (void *)head; bp = bp->hq.cqe_next) + if (bp->pgno == pgno) { +#ifdef STATISTICS + ++mp->cachehit; +#endif + return (bp); + } +#ifdef STATISTICS + ++mp->cachemiss; +#endif + return (NULL); +} + +#ifdef STATISTICS +/* + * mpool_stat + * Print out cache statistics. + */ +void +mpool_stat(mp) + MPOOL *mp; +{ + BKT *bp; + int cnt; + char *sep; + + (void)fprintf(stderr, "%lu pages in the file\n", mp->npages); + (void)fprintf(stderr, + "page size %lu, cacheing %lu pages of %lu page max cache\n", + mp->pagesize, mp->curcache, mp->maxcache); + (void)fprintf(stderr, "%lu page puts, %lu page gets, %lu page new\n", + mp->pageput, mp->pageget, mp->pagenew); + (void)fprintf(stderr, "%lu page allocs, %lu page flushes\n", + mp->pagealloc, mp->pageflush); + if (mp->cachehit + mp->cachemiss) + (void)fprintf(stderr, + "%.0f%% cache hit rate (%lu hits, %lu misses)\n", + ((double)mp->cachehit / (mp->cachehit + mp->cachemiss)) + * 100, mp->cachehit, mp->cachemiss); + (void)fprintf(stderr, "%lu page reads, %lu page writes\n", + mp->pageread, mp->pagewrite); + + sep = ""; + cnt = 0; + for (bp = mp->lqh.cqh_first; + bp != (void *)&mp->lqh; bp = bp->q.cqe_next) { + (void)fprintf(stderr, "%s%d", sep, bp->pgno); + if (bp->flags & MPOOL_DIRTY) + (void)fprintf(stderr, "d"); + if (bp->flags & MPOOL_PINNED) + (void)fprintf(stderr, "P"); + if (++cnt == 10) { + sep = "\n"; + cnt = 0; + } else + sep = ", "; + + } + (void)fprintf(stderr, "\n"); +} +#endif diff --git a/utils/db1-ast/recno/extern.h b/utils/db1-ast/recno/extern.h new file mode 100644 index 000000000..feed43445 --- /dev/null +++ b/utils/db1-ast/recno/extern.h @@ -0,0 +1,54 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)extern.h 8.3 (Berkeley) 6/4/94 + */ + +#include "../btree/extern.h" + +int __rec_close __P((DB *)); +int __rec_delete __P((const DB *, const DBT *, u_int)); +int __rec_dleaf __P((BTREE *, PAGE *, u_int32_t)); +int __rec_fd __P((const DB *)); +int __rec_fmap __P((BTREE *, recno_t)); +int __rec_fout __P((BTREE *)); +int __rec_fpipe __P((BTREE *, recno_t)); +int __rec_get __P((const DB *, const DBT *, DBT *, u_int)); +int __rec_iput __P((BTREE *, recno_t, const DBT *, u_int)); +int __rec_put __P((const DB *dbp, DBT *, const DBT *, u_int)); +int __rec_ret __P((BTREE *, EPG *, recno_t, DBT *, DBT *)); +EPG *__rec_search __P((BTREE *, recno_t, enum SRCHOP)); +int __rec_seq __P((const DB *, DBT *, DBT *, u_int)); +int __rec_sync __P((const DB *, u_int)); +int __rec_vmap __P((BTREE *, recno_t)); +int __rec_vout __P((BTREE *)); +int __rec_vpipe __P((BTREE *, recno_t)); diff --git a/utils/db1-ast/recno/rec_close.c b/utils/db1-ast/recno/rec_close.c new file mode 100644 index 000000000..20b00f52c --- /dev/null +++ b/utils/db1-ast/recno/rec_close.c @@ -0,0 +1,183 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)rec_close.c 8.6 (Berkeley) 8/18/94"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include + +#include +#include +#include +#include + +#include "../include/db.h" +#include "recno.h" + +/* + * __REC_CLOSE -- Close a recno tree. + * + * Parameters: + * dbp: pointer to access method + * + * Returns: + * RET_ERROR, RET_SUCCESS + */ +int +__rec_close(dbp) + DB *dbp; +{ + BTREE *t; + int status; + + t = dbp->internal; + + /* Toss any page pinned across calls. */ + if (t->bt_pinned != NULL) { + mpool_put(t->bt_mp, t->bt_pinned, 0); + t->bt_pinned = NULL; + } + + if (__rec_sync(dbp, 0) == RET_ERROR) + return (RET_ERROR); + + /* Committed to closing. */ + status = RET_SUCCESS; + if (F_ISSET(t, R_MEMMAPPED) && munmap(t->bt_smap, t->bt_msize)) + status = RET_ERROR; + + if (!F_ISSET(t, R_INMEM)) { + if (F_ISSET(t, R_CLOSEFP)) { + if (fclose(t->bt_rfp)) + status = RET_ERROR; + } else + if (close(t->bt_rfd)) + status = RET_ERROR; + } + + if (__bt_close(dbp) == RET_ERROR) + status = RET_ERROR; + + return (status); +} + +/* + * __REC_SYNC -- sync the recno tree to disk. + * + * Parameters: + * dbp: pointer to access method + * + * Returns: + * RET_SUCCESS, RET_ERROR. + */ +int +__rec_sync(dbp, flags) + const DB *dbp; + u_int flags; +{ + struct iovec iov[2]; + BTREE *t; + DBT data, key; + off_t off; + recno_t scursor, trec; + int status; + + t = dbp->internal; + + /* Toss any page pinned across calls. */ + if (t->bt_pinned != NULL) { + mpool_put(t->bt_mp, t->bt_pinned, 0); + t->bt_pinned = NULL; + } + + if (flags == R_RECNOSYNC) + return (__bt_sync(dbp, 0)); + + if (F_ISSET(t, R_RDONLY | R_INMEM) || !F_ISSET(t, R_MODIFIED)) + return (RET_SUCCESS); + + /* Read any remaining records into the tree. */ + if (!F_ISSET(t, R_EOF) && t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR) + return (RET_ERROR); + + /* Rewind the file descriptor. */ + if (lseek(t->bt_rfd, (off_t)0, SEEK_SET) != 0) + return (RET_ERROR); + + /* Save the cursor. */ + scursor = t->bt_cursor.rcursor; + + key.size = sizeof(recno_t); + key.data = &trec; + + if (F_ISSET(t, R_FIXLEN)) { + /* + * We assume that fixed length records are all fixed length. + * Any that aren't are either EINVAL'd or corrected by the + * record put code. + */ + status = (dbp->seq)(dbp, &key, &data, R_FIRST); + while (status == RET_SUCCESS) { + if ((size_t) write(t->bt_rfd, data.data, data.size) != data.size) + return (RET_ERROR); + status = (dbp->seq)(dbp, &key, &data, R_NEXT); + } + } else { + iov[1].iov_base = &t->bt_bval; + iov[1].iov_len = 1; + + status = (dbp->seq)(dbp, &key, &data, R_FIRST); + while (status == RET_SUCCESS) { + iov[0].iov_base = data.data; + iov[0].iov_len = data.size; + if ((size_t) writev(t->bt_rfd, iov, 2) != data.size + 1) + return (RET_ERROR); + status = (dbp->seq)(dbp, &key, &data, R_NEXT); + } + } + + /* Restore the cursor. */ + t->bt_cursor.rcursor = scursor; + + if (status == RET_ERROR) + return (RET_ERROR); + if ((off = lseek(t->bt_rfd, (off_t)0, SEEK_CUR)) == -1) + return (RET_ERROR); + if (ftruncate(t->bt_rfd, off)) + return (RET_ERROR); + F_CLR(t, R_MODIFIED); + return (RET_SUCCESS); +} diff --git a/utils/db1-ast/recno/rec_delete.c b/utils/db1-ast/recno/rec_delete.c new file mode 100644 index 000000000..f40b5caed --- /dev/null +++ b/utils/db1-ast/recno/rec_delete.c @@ -0,0 +1,197 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Mike Olson. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)rec_delete.c 8.7 (Berkeley) 7/14/94"; +#endif /* LIBC_SCCS and not lint */ + +#include + +#include +#include +#include + +#include "../include/db.h" +#include "recno.h" + +static int rec_rdelete __P((BTREE *, recno_t)); + +/* + * __REC_DELETE -- Delete the item(s) referenced by a key. + * + * Parameters: + * dbp: pointer to access method + * key: key to delete + * flags: R_CURSOR if deleting what the cursor references + * + * Returns: + * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found. + */ +int +__rec_delete(dbp, key, flags) + const DB *dbp; + const DBT *key; + u_int flags; +{ + BTREE *t; + recno_t nrec; + int status; + + t = dbp->internal; + + /* Toss any page pinned across calls. */ + if (t->bt_pinned != NULL) { + mpool_put(t->bt_mp, t->bt_pinned, 0); + t->bt_pinned = NULL; + } + + switch(flags) { + case 0: + if ((nrec = *(recno_t *)key->data) == 0) + goto einval; + if (nrec > t->bt_nrecs) + return (RET_SPECIAL); + --nrec; + status = rec_rdelete(t, nrec); + break; + case R_CURSOR: + if (!F_ISSET(&t->bt_cursor, CURS_INIT)) + goto einval; + if (t->bt_nrecs == 0) + return (RET_SPECIAL); + status = rec_rdelete(t, t->bt_cursor.rcursor - 1); + if (status == RET_SUCCESS) + --t->bt_cursor.rcursor; + break; + default: +einval: errno = EINVAL; + return (RET_ERROR); + } + + if (status == RET_SUCCESS) + F_SET(t, B_MODIFIED | R_MODIFIED); + return (status); +} + +/* + * REC_RDELETE -- Delete the data matching the specified key. + * + * Parameters: + * tree: tree + * nrec: record to delete + * + * Returns: + * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found. + */ +static int +rec_rdelete(t, nrec) + BTREE *t; + recno_t nrec; +{ + EPG *e; + PAGE *h; + int status; + + /* Find the record; __rec_search pins the page. */ + if ((e = __rec_search(t, nrec, SDELETE)) == NULL) + return (RET_ERROR); + + /* Delete the record. */ + h = e->page; + status = __rec_dleaf(t, h, e->index); + if (status != RET_SUCCESS) { + mpool_put(t->bt_mp, h, 0); + return (status); + } + mpool_put(t->bt_mp, h, MPOOL_DIRTY); + return (RET_SUCCESS); +} + +/* + * __REC_DLEAF -- Delete a single record from a recno leaf page. + * + * Parameters: + * t: tree + * index: index on current page to delete + * + * Returns: + * RET_SUCCESS, RET_ERROR. + */ +int +__rec_dleaf(t, h, idx) + BTREE *t; + PAGE *h; + u_int32_t idx; +{ + RLEAF *rl; + indx_t *ip, cnt, offset; + u_int32_t nbytes; + char *from; + void *to; + + /* + * Delete a record from a recno leaf page. Internal records are never + * deleted from internal pages, regardless of the records that caused + * them to be added being deleted. Pages made empty by deletion are + * not reclaimed. They are, however, made available for reuse. + * + * Pack the remaining entries at the end of the page, shift the indices + * down, overwriting the deleted record and its index. If the record + * uses overflow pages, make them available for reuse. + */ + to = rl = GETRLEAF(h, idx); + if (rl->flags & P_BIGDATA && __ovfl_delete(t, rl->bytes) == RET_ERROR) + return (RET_ERROR); + nbytes = NRLEAF(rl); + + /* + * Compress the key/data pairs. Compress and adjust the [BR]LEAF + * offsets. Reset the headers. + */ + from = (char *)h + h->upper; + memmove(from + nbytes, from, (char *)to - from); + h->upper += nbytes; + + offset = h->linp[idx]; + for (cnt = &h->linp[idx] - (ip = &h->linp[0]); cnt--; ++ip) + if (ip[0] < offset) + ip[0] += nbytes; + for (cnt = &h->linp[NEXTINDEX(h)] - ip; --cnt; ++ip) + ip[0] = ip[1] < offset ? ip[1] + nbytes : ip[1]; + h->lower -= sizeof(indx_t); + --t->bt_nrecs; + return (RET_SUCCESS); +} diff --git a/utils/db1-ast/recno/rec_get.c b/utils/db1-ast/recno/rec_get.c new file mode 100644 index 000000000..7038cc81a --- /dev/null +++ b/utils/db1-ast/recno/rec_get.c @@ -0,0 +1,311 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)rec_get.c 8.9 (Berkeley) 8/18/94"; +#endif /* LIBC_SCCS and not lint */ + +#include + +#include +#include +#include +#include +#include +#include + +#include "../include/db.h" +#include "recno.h" + +/* + * __REC_GET -- Get a record from the btree. + * + * Parameters: + * dbp: pointer to access method + * key: key to find + * data: data to return + * flag: currently unused + * + * Returns: + * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found. + */ +int +__rec_get(dbp, key, data, flags) + const DB *dbp; + const DBT *key; + DBT *data; + u_int flags; +{ + BTREE *t; + EPG *e; + recno_t nrec; + int status; + + t = dbp->internal; + + /* Toss any page pinned across calls. */ + if (t->bt_pinned != NULL) { + mpool_put(t->bt_mp, t->bt_pinned, 0); + t->bt_pinned = NULL; + } + + /* Get currently doesn't take any flags, and keys of 0 are illegal. */ + if (flags || (nrec = *(recno_t *)key->data) == 0) { + errno = EINVAL; + return (RET_ERROR); + } + + /* + * If we haven't seen this record yet, try to find it in the + * original file. + */ + if (nrec > t->bt_nrecs) { + if (F_ISSET(t, R_EOF | R_INMEM)) + return (RET_SPECIAL); + if ((status = t->bt_irec(t, nrec)) != RET_SUCCESS) + return (status); + } + + --nrec; + if ((e = __rec_search(t, nrec, SEARCH)) == NULL) + return (RET_ERROR); + + status = __rec_ret(t, e, 0, NULL, data); + if (F_ISSET(t, B_DB_LOCK)) + mpool_put(t->bt_mp, e->page, 0); + else + t->bt_pinned = e->page; + return (status); +} + +/* + * __REC_FPIPE -- Get fixed length records from a pipe. + * + * Parameters: + * t: tree + * cnt: records to read + * + * Returns: + * RET_ERROR, RET_SUCCESS + */ +int +__rec_fpipe(t, top) + BTREE *t; + recno_t top; +{ + DBT data; + recno_t nrec; + size_t len; + int ch; + u_char *p; + + if (t->bt_rdata.size < t->bt_reclen) { + t->bt_rdata.data = t->bt_rdata.data == NULL ? + malloc(t->bt_reclen) : + realloc(t->bt_rdata.data, t->bt_reclen); + if (t->bt_rdata.data == NULL) + return (RET_ERROR); + t->bt_rdata.size = t->bt_reclen; + } + data.data = t->bt_rdata.data; + data.size = t->bt_reclen; + + for (nrec = t->bt_nrecs; nrec < top;) { + len = t->bt_reclen; + for (p = t->bt_rdata.data;; *p++ = ch) + if ((ch = getc(t->bt_rfp)) == EOF || !--len) { + if (ch != EOF) + *p = ch; + if (len != 0) + memset(p, t->bt_bval, len); + if (__rec_iput(t, + nrec, &data, 0) != RET_SUCCESS) + return (RET_ERROR); + ++nrec; + break; + } + if (ch == EOF) + break; + } + if (nrec < top) { + F_SET(t, R_EOF); + return (RET_SPECIAL); + } + return (RET_SUCCESS); +} + +/* + * __REC_VPIPE -- Get variable length records from a pipe. + * + * Parameters: + * t: tree + * cnt: records to read + * + * Returns: + * RET_ERROR, RET_SUCCESS + */ +int +__rec_vpipe(t, top) + BTREE *t; + recno_t top; +{ + DBT data; + recno_t nrec; + indx_t len; + size_t sz; + int bval, ch; + u_char *p; + + bval = t->bt_bval; + for (nrec = t->bt_nrecs; nrec < top; ++nrec) { + for (p = t->bt_rdata.data, + sz = t->bt_rdata.size;; *p++ = ch, --sz) { + if ((ch = getc(t->bt_rfp)) == EOF || ch == bval) { + data.data = t->bt_rdata.data; + data.size = p - (u_char *)t->bt_rdata.data; + if (ch == EOF && data.size == 0) + break; + if (__rec_iput(t, nrec, &data, 0) + != RET_SUCCESS) + return (RET_ERROR); + break; + } + if (sz == 0) { + len = p - (u_char *)t->bt_rdata.data; + t->bt_rdata.size += (sz = 256); + t->bt_rdata.data = t->bt_rdata.data == NULL ? + malloc(t->bt_rdata.size) : + realloc(t->bt_rdata.data, t->bt_rdata.size); + if (t->bt_rdata.data == NULL) + return (RET_ERROR); + p = (u_char *)t->bt_rdata.data + len; + } + } + if (ch == EOF) + break; + } + if (nrec < top) { + F_SET(t, R_EOF); + return (RET_SPECIAL); + } + return (RET_SUCCESS); +} + +/* + * __REC_FMAP -- Get fixed length records from a file. + * + * Parameters: + * t: tree + * cnt: records to read + * + * Returns: + * RET_ERROR, RET_SUCCESS + */ +int +__rec_fmap(t, top) + BTREE *t; + recno_t top; +{ + DBT data; + recno_t nrec; + u_char *sp, *ep, *p; + size_t len; + + if (t->bt_rdata.size < t->bt_reclen) { + t->bt_rdata.data = t->bt_rdata.data == NULL ? + malloc(t->bt_reclen) : + realloc(t->bt_rdata.data, t->bt_reclen); + if (t->bt_rdata.data == NULL) + return (RET_ERROR); + t->bt_rdata.size = t->bt_reclen; + } + data.data = t->bt_rdata.data; + data.size = t->bt_reclen; + + sp = (u_char *)t->bt_cmap; + ep = (u_char *)t->bt_emap; + for (nrec = t->bt_nrecs; nrec < top; ++nrec) { + if (sp >= ep) { + F_SET(t, R_EOF); + return (RET_SPECIAL); + } + len = t->bt_reclen; + for (p = t->bt_rdata.data; + sp < ep && len > 0; *p++ = *sp++, --len); + if (len != 0) + memset(p, t->bt_bval, len); + if (__rec_iput(t, nrec, &data, 0) != RET_SUCCESS) + return (RET_ERROR); + } + t->bt_cmap = (caddr_t)sp; + return (RET_SUCCESS); +} + +/* + * __REC_VMAP -- Get variable length records from a file. + * + * Parameters: + * t: tree + * cnt: records to read + * + * Returns: + * RET_ERROR, RET_SUCCESS + */ +int +__rec_vmap(t, top) + BTREE *t; + recno_t top; +{ + DBT data; + u_char *sp, *ep; + recno_t nrec; + int bval; + + sp = (u_char *)t->bt_cmap; + ep = (u_char *)t->bt_emap; + bval = t->bt_bval; + + for (nrec = t->bt_nrecs; nrec < top; ++nrec) { + if (sp >= ep) { + F_SET(t, R_EOF); + return (RET_SPECIAL); + } + for (data.data = sp; sp < ep && *sp != bval; ++sp); + data.size = sp - (u_char *)data.data; + if (__rec_iput(t, nrec, &data, 0) != RET_SUCCESS) + return (RET_ERROR); + ++sp; + } + t->bt_cmap = (caddr_t)sp; + return (RET_SUCCESS); +} diff --git a/utils/db1-ast/recno/rec_open.c b/utils/db1-ast/recno/rec_open.c new file mode 100644 index 000000000..0fb08258c --- /dev/null +++ b/utils/db1-ast/recno/rec_open.c @@ -0,0 +1,241 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Mike Olson. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)rec_open.c 8.10 (Berkeley) 9/1/94"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "../include/db.h" +#include "recno.h" + +DB * +__rec_open(fname, flags, mode, openinfo, dflags) + const char *fname; + int flags, mode, dflags; + const RECNOINFO *openinfo; +{ + BTREE *t; + BTREEINFO btopeninfo; + DB *dbp; + PAGE *h; + struct stat sb; + int rfd = 0, sverrno; + + /* Open the user's file -- if this fails, we're done. */ + if (fname != NULL && (rfd = open(fname, flags, mode)) < 0) + return (NULL); + + /* Create a btree in memory (backed by disk). */ + dbp = NULL; + if (openinfo) { + if (openinfo->flags & ~(R_FIXEDLEN | R_NOKEY | R_SNAPSHOT)) + goto einval; + btopeninfo.flags = 0; + btopeninfo.cachesize = openinfo->cachesize; + btopeninfo.maxkeypage = 0; + btopeninfo.minkeypage = 0; + btopeninfo.psize = openinfo->psize; + btopeninfo.compare = NULL; + btopeninfo.prefix = NULL; + btopeninfo.lorder = openinfo->lorder; + dbp = __bt_open(openinfo->bfname, + O_RDWR, S_IRUSR | S_IWUSR, &btopeninfo, dflags); + } else + dbp = __bt_open(NULL, O_RDWR, S_IRUSR | S_IWUSR, NULL, dflags); + if (dbp == NULL) + goto err; + + /* + * Some fields in the tree structure are recno specific. Fill them + * in and make the btree structure look like a recno structure. We + * don't change the bt_ovflsize value, it's close enough and slightly + * bigger. + */ + t = dbp->internal; + if (openinfo) { + if (openinfo->flags & R_FIXEDLEN) { + F_SET(t, R_FIXLEN); + t->bt_reclen = openinfo->reclen; + if (t->bt_reclen == 0) + goto einval; + } + t->bt_bval = openinfo->bval; + } else + t->bt_bval = '\n'; + + F_SET(t, R_RECNO); + if (fname == NULL) + F_SET(t, R_EOF | R_INMEM); + else + t->bt_rfd = rfd; + + if (fname != NULL) { + /* + * In 4.4BSD, stat(2) returns true for ISSOCK on pipes. + * Unfortunately, that's not portable, so we use lseek + * and check the errno values. + */ + errno = 0; + if (lseek(rfd, (off_t)0, SEEK_CUR) == -1 && errno == ESPIPE) { + switch (flags & O_ACCMODE) { + case O_RDONLY: + F_SET(t, R_RDONLY); + break; + default: + goto einval; + } +slow: if ((t->bt_rfp = fdopen(rfd, "r")) == NULL) + goto err; + F_SET(t, R_CLOSEFP); + t->bt_irec = + F_ISSET(t, R_FIXLEN) ? __rec_fpipe : __rec_vpipe; + } else { + switch (flags & O_ACCMODE) { + case O_RDONLY: + F_SET(t, R_RDONLY); + break; + case O_RDWR: + break; + default: + goto einval; + } + + if (fstat(rfd, &sb)) + goto err; + /* + * Kluge -- we'd like to test to see if the file is too + * big to mmap. Since, we don't know what size or type + * off_t's or size_t's are, what the largest unsigned + * integral type is, or what random insanity the local + * C compiler will perpetrate, doing the comparison in + * a portable way is flatly impossible. Hope that mmap + * fails if the file is too large. + */ + if (sb.st_size == 0) + F_SET(t, R_EOF); + else { +#ifdef MMAP_NOT_AVAILABLE + /* + * XXX + * Mmap doesn't work correctly on many current + * systems. In particular, it can fail subtly, + * with cache coherency problems. Don't use it + * for now. + */ + t->bt_msize = sb.st_size; + if ((t->bt_smap = mmap(NULL, t->bt_msize, + PROT_READ, MAP_PRIVATE, rfd, + (off_t)0)) == MAP_FAILED + goto slow; + t->bt_cmap = t->bt_smap; + t->bt_emap = t->bt_smap + sb.st_size; + t->bt_irec = F_ISSET(t, R_FIXLEN) ? + __rec_fmap : __rec_vmap; + F_SET(t, R_MEMMAPPED); +#else + goto slow; +#endif + } + } + } + + /* Use the recno routines. */ + dbp->close = __rec_close; + dbp->del = __rec_delete; + dbp->fd = __rec_fd; + dbp->get = __rec_get; + dbp->put = __rec_put; + dbp->seq = __rec_seq; + dbp->sync = __rec_sync; + + /* If the root page was created, reset the flags. */ + if ((h = mpool_get(t->bt_mp, P_ROOT, 0)) == NULL) + goto err; + if ((h->flags & P_TYPE) == P_BLEAF) { + F_CLR(h, P_TYPE); + F_SET(h, P_RLEAF); + mpool_put(t->bt_mp, h, MPOOL_DIRTY); + } else + mpool_put(t->bt_mp, h, 0); + + if (openinfo && openinfo->flags & R_SNAPSHOT && + !F_ISSET(t, R_EOF | R_INMEM) && + t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR) + goto err; + return (dbp); + +einval: errno = EINVAL; +err: sverrno = errno; + if (dbp != NULL) + (void)__bt_close(dbp); + if (fname != NULL) + (void)close(rfd); + errno = sverrno; + return (NULL); +} + +int +__rec_fd(dbp) + const DB *dbp; +{ + BTREE *t; + + t = dbp->internal; + + /* Toss any page pinned across calls. */ + if (t->bt_pinned != NULL) { + mpool_put(t->bt_mp, t->bt_pinned, 0); + t->bt_pinned = NULL; + } + + /* In-memory database can't have a file descriptor. */ + if (F_ISSET(t, R_INMEM)) { + errno = ENOENT; + return (-1); + } + return (t->bt_rfd); +} diff --git a/utils/db1-ast/recno/rec_put.c b/utils/db1-ast/recno/rec_put.c new file mode 100644 index 000000000..ba8861297 --- /dev/null +++ b/utils/db1-ast/recno/rec_put.c @@ -0,0 +1,280 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)rec_put.c 8.7 (Berkeley) 8/18/94"; +#endif /* LIBC_SCCS and not lint */ + +#include + +#include +#include +#include +#include + +#include "../include/db.h" +#include "recno.h" + +/* + * __REC_PUT -- Add a recno item to the tree. + * + * Parameters: + * dbp: pointer to access method + * key: key + * data: data + * flag: R_CURSOR, R_IAFTER, R_IBEFORE, R_NOOVERWRITE + * + * Returns: + * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key is + * already in the tree and R_NOOVERWRITE specified. + */ +int +__rec_put(dbp, key, data, flags) + const DB *dbp; + DBT *key; + const DBT *data; + u_int flags; +{ + BTREE *t; + DBT fdata, tdata; + recno_t nrec; + int status; + + t = dbp->internal; + + /* Toss any page pinned across calls. */ + if (t->bt_pinned != NULL) { + mpool_put(t->bt_mp, t->bt_pinned, 0); + t->bt_pinned = NULL; + } + + /* + * If using fixed-length records, and the record is long, return + * EINVAL. If it's short, pad it out. Use the record data return + * memory, it's only short-term. + */ + if (F_ISSET(t, R_FIXLEN) && data->size != t->bt_reclen) { + if (data->size > t->bt_reclen) + goto einval; + + if (t->bt_rdata.size < t->bt_reclen) { + t->bt_rdata.data = t->bt_rdata.data == NULL ? + malloc(t->bt_reclen) : + realloc(t->bt_rdata.data, t->bt_reclen); + if (t->bt_rdata.data == NULL) + return (RET_ERROR); + t->bt_rdata.size = t->bt_reclen; + } + memmove(t->bt_rdata.data, data->data, data->size); + memset((char *)t->bt_rdata.data + data->size, + t->bt_bval, t->bt_reclen - data->size); + fdata.data = t->bt_rdata.data; + fdata.size = t->bt_reclen; + } else { + fdata.data = data->data; + fdata.size = data->size; + } + + switch (flags) { + case R_CURSOR: + if (!F_ISSET(&t->bt_cursor, CURS_INIT)) + goto einval; + nrec = t->bt_cursor.rcursor; + break; + case R_SETCURSOR: + if ((nrec = *(recno_t *)key->data) == 0) + goto einval; + break; + case R_IAFTER: + if ((nrec = *(recno_t *)key->data) == 0) { + nrec = 1; + flags = R_IBEFORE; + } + break; + case 0: + case R_IBEFORE: + if ((nrec = *(recno_t *)key->data) == 0) + goto einval; + break; + case R_NOOVERWRITE: + if ((nrec = *(recno_t *)key->data) == 0) + goto einval; + if (nrec <= t->bt_nrecs) + return (RET_SPECIAL); + break; + default: +einval: errno = EINVAL; + return (RET_ERROR); + } + + /* + * Make sure that records up to and including the put record are + * already in the database. If skipping records, create empty ones. + */ + if (nrec > t->bt_nrecs) { + if (!F_ISSET(t, R_EOF | R_INMEM) && + t->bt_irec(t, nrec) == RET_ERROR) + return (RET_ERROR); + if (nrec > t->bt_nrecs + 1) { + if (F_ISSET(t, R_FIXLEN)) { + if ((tdata.data = + (void *)malloc(t->bt_reclen)) == NULL) + return (RET_ERROR); + tdata.size = t->bt_reclen; + memset(tdata.data, t->bt_bval, tdata.size); + } else { + tdata.data = NULL; + tdata.size = 0; + } + while (nrec > t->bt_nrecs + 1) + if (__rec_iput(t, + t->bt_nrecs, &tdata, 0) != RET_SUCCESS) + return (RET_ERROR); + if (F_ISSET(t, R_FIXLEN)) + free(tdata.data); + } + } + + if ((status = __rec_iput(t, nrec - 1, &fdata, flags)) != RET_SUCCESS) + return (status); + + if (flags == R_SETCURSOR) + t->bt_cursor.rcursor = nrec; + + F_SET(t, R_MODIFIED); + return (__rec_ret(t, NULL, nrec, key, NULL)); +} + +/* + * __REC_IPUT -- Add a recno item to the tree. + * + * Parameters: + * t: tree + * nrec: record number + * data: data + * + * Returns: + * RET_ERROR, RET_SUCCESS + */ +int +__rec_iput(t, nrec, data, flags) + BTREE *t; + recno_t nrec; + const DBT *data; + u_int flags; +{ + DBT tdata; + EPG *e; + PAGE *h; + indx_t idx, nxtindex; + pgno_t pg; + u_int32_t nbytes; + int dflags, status; + char *dest, db[NOVFLSIZE]; + + /* + * If the data won't fit on a page, store it on indirect pages. + * + * XXX + * If the insert fails later on, these pages aren't recovered. + */ + if (data->size > t->bt_ovflsize) { + if (__ovfl_put(t, data, &pg) == RET_ERROR) + return (RET_ERROR); + tdata.data = db; + tdata.size = NOVFLSIZE; + *(pgno_t *)db = pg; + *(u_int32_t *)(db + sizeof(pgno_t)) = data->size; + dflags = P_BIGDATA; + data = &tdata; + } else + dflags = 0; + + /* __rec_search pins the returned page. */ + if ((e = __rec_search(t, nrec, + nrec > t->bt_nrecs || flags == R_IAFTER || flags == R_IBEFORE ? + SINSERT : SEARCH)) == NULL) + return (RET_ERROR); + + h = e->page; + idx = e->index; + + /* + * Add the specified key/data pair to the tree. The R_IAFTER and + * R_IBEFORE flags insert the key after/before the specified key. + * + * Pages are split as required. + */ + switch (flags) { + case R_IAFTER: + ++idx; + break; + case R_IBEFORE: + break; + default: + if (nrec < t->bt_nrecs && + __rec_dleaf(t, h, idx) == RET_ERROR) { + mpool_put(t->bt_mp, h, 0); + return (RET_ERROR); + } + break; + } + + /* + * If not enough room, split the page. The split code will insert + * the key and data and unpin the current page. If inserting into + * the offset array, shift the pointers up. + */ + nbytes = NRLEAFDBT(data->size); + if ((u_int32_t) (h->upper - h->lower) < nbytes + sizeof(indx_t)) { + status = __bt_split(t, h, NULL, data, dflags, nbytes, idx); + if (status == RET_SUCCESS) + ++t->bt_nrecs; + return (status); + } + + if (idx < (nxtindex = NEXTINDEX(h))) + memmove(h->linp + idx + 1, h->linp + idx, + (nxtindex - idx) * sizeof(indx_t)); + h->lower += sizeof(indx_t); + + h->linp[idx] = h->upper -= nbytes; + dest = (char *)h + h->upper; + WR_RLEAF(dest, data, dflags); + + ++t->bt_nrecs; + F_SET(t, B_MODIFIED); + mpool_put(t->bt_mp, h, MPOOL_DIRTY); + + return (RET_SUCCESS); +} diff --git a/utils/db1-ast/recno/rec_search.c b/utils/db1-ast/recno/rec_search.c new file mode 100644 index 000000000..e70fe4c13 --- /dev/null +++ b/utils/db1-ast/recno/rec_search.c @@ -0,0 +1,126 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)rec_search.c 8.4 (Berkeley) 7/14/94"; +#endif /* LIBC_SCCS and not lint */ + +#include + +#include +#include + +#include "../include/db.h" +#include "recno.h" + +/* + * __REC_SEARCH -- Search a btree for a key. + * + * Parameters: + * t: tree to search + * recno: key to find + * op: search operation + * + * Returns: + * EPG for matching record, if any, or the EPG for the location of the + * key, if it were inserted into the tree. + * + * Returns: + * The EPG for matching record, if any, or the EPG for the location + * of the key, if it were inserted into the tree, is entered into + * the bt_cur field of the tree. A pointer to the field is returned. + */ +EPG * +__rec_search(t, recno, op) + BTREE *t; + recno_t recno; + enum SRCHOP op; +{ + register indx_t index; + register PAGE *h; + EPGNO *parent; + RINTERNAL *r; + pgno_t pg; + indx_t top; + recno_t total; + int sverrno; + + BT_CLR(t); + for (pg = P_ROOT, total = 0;;) { + if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) + goto err; + if (h->flags & P_RLEAF) { + t->bt_cur.page = h; + t->bt_cur.index = recno - total; + return (&t->bt_cur); + } + for (index = 0, top = NEXTINDEX(h);;) { + r = GETRINTERNAL(h, index); + if (++index == top || total + r->nrecs > recno) + break; + total += r->nrecs; + } + + BT_PUSH(t, pg, index - 1); + + pg = r->pgno; + switch (op) { + case SDELETE: + --GETRINTERNAL(h, (index - 1))->nrecs; + mpool_put(t->bt_mp, h, MPOOL_DIRTY); + break; + case SINSERT: + ++GETRINTERNAL(h, (index - 1))->nrecs; + mpool_put(t->bt_mp, h, MPOOL_DIRTY); + break; + case SEARCH: + mpool_put(t->bt_mp, h, 0); + break; + } + + } + /* Try and recover the tree. */ +err: sverrno = errno; + if (op != SEARCH) + while ((parent = BT_POP(t)) != NULL) { + if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL) + break; + if (op == SINSERT) + --GETRINTERNAL(h, parent->index)->nrecs; + else + ++GETRINTERNAL(h, parent->index)->nrecs; + mpool_put(t->bt_mp, h, MPOOL_DIRTY); + } + errno = sverrno; + return (NULL); +} diff --git a/utils/db1-ast/recno/rec_seq.c b/utils/db1-ast/recno/rec_seq.c new file mode 100644 index 000000000..ca3451ca6 --- /dev/null +++ b/utils/db1-ast/recno/rec_seq.c @@ -0,0 +1,131 @@ +/*- + * Copyright (c) 1991, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)rec_seq.c 8.3 (Berkeley) 7/14/94"; +#endif /* not lint */ + +#include + +#include +#include +#include +#include + +#include "../include/db.h" +#include "recno.h" + +/* + * __REC_SEQ -- Recno sequential scan interface. + * + * Parameters: + * dbp: pointer to access method + * key: key for positioning and return value + * data: data return value + * flags: R_CURSOR, R_FIRST, R_LAST, R_NEXT, R_PREV. + * + * Returns: + * RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key. + */ +int +__rec_seq(dbp, key, data, flags) + const DB *dbp; + DBT *key, *data; + u_int flags; +{ + BTREE *t; + EPG *e; + recno_t nrec; + int status; + + t = dbp->internal; + + /* Toss any page pinned across calls. */ + if (t->bt_pinned != NULL) { + mpool_put(t->bt_mp, t->bt_pinned, 0); + t->bt_pinned = NULL; + } + + switch(flags) { + case R_CURSOR: + if ((nrec = *(recno_t *)key->data) == 0) + goto einval; + break; + case R_NEXT: + if (F_ISSET(&t->bt_cursor, CURS_INIT)) { + nrec = t->bt_cursor.rcursor + 1; + break; + } + /* FALLTHROUGH */ + case R_FIRST: + nrec = 1; + break; + case R_PREV: + if (F_ISSET(&t->bt_cursor, CURS_INIT)) { + if ((nrec = t->bt_cursor.rcursor - 1) == 0) + return (RET_SPECIAL); + break; + } + /* FALLTHROUGH */ + case R_LAST: + if (!F_ISSET(t, R_EOF | R_INMEM) && + t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR) + return (RET_ERROR); + nrec = t->bt_nrecs; + break; + default: +einval: errno = EINVAL; + return (RET_ERROR); + } + + if (t->bt_nrecs == 0 || nrec > t->bt_nrecs) { + if (!F_ISSET(t, R_EOF | R_INMEM) && + (status = t->bt_irec(t, nrec)) != RET_SUCCESS) + return (status); + if (t->bt_nrecs == 0 || nrec > t->bt_nrecs) + return (RET_SPECIAL); + } + + if ((e = __rec_search(t, nrec - 1, SEARCH)) == NULL) + return (RET_ERROR); + + F_SET(&t->bt_cursor, CURS_INIT); + t->bt_cursor.rcursor = nrec; + + status = __rec_ret(t, e, nrec, key, data); + if (F_ISSET(t, B_DB_LOCK)) + mpool_put(t->bt_mp, e->page, 0); + else + t->bt_pinned = e->page; + return (status); +} diff --git a/utils/db1-ast/recno/rec_utils.c b/utils/db1-ast/recno/rec_utils.c new file mode 100644 index 000000000..ddc309712 --- /dev/null +++ b/utils/db1-ast/recno/rec_utils.c @@ -0,0 +1,122 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)rec_utils.c 8.6 (Berkeley) 7/16/94"; +#endif /* LIBC_SCCS and not lint */ + +#include + +#include +#include +#include + +#include "../include/db.h" +#include "recno.h" + +/* + * __rec_ret -- + * Build return data. + * + * Parameters: + * t: tree + * e: key/data pair to be returned + * nrec: record number + * key: user's key structure + * data: user's data structure + * + * Returns: + * RET_SUCCESS, RET_ERROR. + */ +int +__rec_ret(t, e, nrec, key, data) + BTREE *t; + EPG *e; + recno_t nrec; + DBT *key, *data; +{ + RLEAF *rl; + void *p; + + if (key == NULL) + goto dataonly; + + /* We have to copy the key, it's not on the page. */ + if (sizeof(recno_t) > t->bt_rkey.size) { + p = (void *)(t->bt_rkey.data == NULL ? + malloc(sizeof(recno_t)) : + realloc(t->bt_rkey.data, sizeof(recno_t))); + if (p == NULL) + return (RET_ERROR); + t->bt_rkey.data = p; + t->bt_rkey.size = sizeof(recno_t); + } + memmove(t->bt_rkey.data, &nrec, sizeof(recno_t)); + key->size = sizeof(recno_t); + key->data = t->bt_rkey.data; + +dataonly: + if (data == NULL) + return (RET_SUCCESS); + + /* + * We must copy big keys/data to make them contiguous. Otherwise, + * leave the page pinned and don't copy unless the user specified + * concurrent access. + */ + rl = GETRLEAF(e->page, e->index); + if (rl->flags & P_BIGDATA) { + if (__ovfl_get(t, rl->bytes, + &data->size, &t->bt_rdata.data, &t->bt_rdata.size)) + return (RET_ERROR); + data->data = t->bt_rdata.data; + } else if (F_ISSET(t, B_DB_LOCK)) { + /* Use +1 in case the first record retrieved is 0 length. */ + if (rl->dsize + 1 > t->bt_rdata.size) { + p = (void *)(t->bt_rdata.data == NULL ? + malloc(rl->dsize + 1) : + realloc(t->bt_rdata.data, rl->dsize + 1)); + if (p == NULL) + return (RET_ERROR); + t->bt_rdata.data = p; + t->bt_rdata.size = rl->dsize + 1; + } + memmove(t->bt_rdata.data, rl->bytes, rl->dsize); + data->size = rl->dsize; + data->data = t->bt_rdata.data; + } else { + data->size = rl->dsize; + data->data = rl->bytes; + } + return (RET_SUCCESS); +} diff --git a/utils/db1-ast/recno/recno.h b/utils/db1-ast/recno/recno.h new file mode 100644 index 000000000..bec772c2f --- /dev/null +++ b/utils/db1-ast/recno/recno.h @@ -0,0 +1,39 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)recno.h 8.1 (Berkeley) 6/4/93 + */ + +enum SRCHOP { SDELETE, SINSERT, SEARCH}; /* Rec_search operation. */ + +#include "../btree/btree.h" +#include "extern.h" diff --git a/utils/utils.xml b/utils/utils.xml index ec455c9da..fea5f3197 100644 --- a/utils/utils.xml +++ b/utils/utils.xml @@ -5,6 +5,9 @@ yes + + yes + no newt -- cgit v1.2.3 From 8d66c8fe0c8f117b6628edafdaa166145356dd87 Mon Sep 17 00:00:00 2001 From: tzafrir Date: Thu, 7 Jul 2011 09:49:54 +0000 Subject: live_ast: valgrind: run asterisk under valgrind Adds a new sub-command, "valgrind" to live_ast. It runs asterisk under valgrind. The extra command-line parameters are passed to Asterisk as usual, and parameters to valgrind are passed through LIVE_AST_VALGRIND_ARGS in live.conf . Review: https://reviewboard.asterisk.org/r/1109/ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@326636 f38db490-d61c-443f-a65b-d21fe96a405b --- contrib/scripts/live_ast | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/contrib/scripts/live_ast b/contrib/scripts/live_ast index c1e7fade1..c5195c3d8 100755 --- a/contrib/scripts/live_ast +++ b/contrib/scripts/live_ast @@ -99,6 +99,10 @@ # is run. #LIVE_AST_BRISTUFFED_LIBPRI=yes # +# LIVE_AST_VALGRIND_ARGS: +# Parameters to pass to valgrind if using the 'valgrind' command. +#LIVE_AST_VALGRIND_ARGS="-v --leak-check=full --suppressions=contrib/valgrind.supp --log-file=valgrind.log" +# # LIVE_AST_FOR_SYSTEM # When generating asterisk.conf, use most components from the installed # system. Also provide a sane var-run directory for those of us who want @@ -235,6 +239,10 @@ run) set_ld_env $AST_BIN -C $AST_CONF "$@" ;; +valgrind) + set_ld_env + valgrind $LIVE_AST_VALGRIND_ARGS $AST_BIN -C $AST_CONF "$@" + ;; rsync) remote_host="$1" remote_dir="$2" @@ -262,6 +270,7 @@ gdb) echo "$0 samples make samples" echo "$0 run [params] asterisk [params]" echo "$0 gdb gdb asterisk" + echo "$0 valgrind valgrind asterisk" echo "$0 rsync [user@]host dir copy files over to [user@]host:dir" echo "$0 gen-live-asterisk regenerate the wrapper ./live/asterisk" echo "$0 conf-file create live.conf if it does not exist" -- cgit v1.2.3 From bdc36711b2373e8fc696a53922c7a4deb790f103 Mon Sep 17 00:00:00 2001 From: mnicholson Date: Thu, 7 Jul 2011 15:26:42 +0000 Subject: Merged revisions 326681 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.8 ........ r326681 | mnicholson | 2011-07-07 10:25:49 -0500 (Thu, 07 Jul 2011) | 3 lines make the uri parameter used in reply digests more standards compliant in certain cases by prepending "sip:" or "sips:" to it ........ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@326682 f38db490-d61c-443f-a65b-d21fe96a405b --- channels/chan_sip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 1f2c72379..ab7600f7b 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -19137,7 +19137,7 @@ static int build_reply_digest(struct sip_pvt *p, int method, char* digest, int d struct sip_auth_container *credentials; if (!ast_strlen_zero(p->domain)) - ast_copy_string(uri, p->domain, sizeof(uri)); + snprintf(uri, sizeof(uri), "%s:%s", p->socket.type == SIP_TRANSPORT_TLS ? "sips" : "sip", p->domain); else if (!ast_strlen_zero(p->uri)) ast_copy_string(uri, p->uri, sizeof(uri)); else -- cgit v1.2.3 From f5c8c790feacc50d817970fef24491469a008710 Mon Sep 17 00:00:00 2001 From: mnicholson Date: Thu, 7 Jul 2011 15:28:47 +0000 Subject: Merged revisions 326683 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.8 ........ r326683 | mnicholson | 2011-07-07 10:28:25 -0500 (Thu, 07 Jul 2011) | 3 lines use sips: or sip: depending on the transport in use when building reply digest URIs ........ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@326684 f38db490-d61c-443f-a65b-d21fe96a405b --- channels/chan_sip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/channels/chan_sip.c b/channels/chan_sip.c index ab7600f7b..9e2ddf7ed 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -19141,7 +19141,7 @@ static int build_reply_digest(struct sip_pvt *p, int method, char* digest, int d else if (!ast_strlen_zero(p->uri)) ast_copy_string(uri, p->uri, sizeof(uri)); else - snprintf(uri, sizeof(uri), "sip:%s@%s", p->username, ast_sockaddr_stringify_host_remote(&p->sa)); + snprintf(uri, sizeof(uri), "%s:%s@%s", p->socket.type == SIP_TRANSPORT_TLS ? "sips" : "sip", p->username, ast_sockaddr_stringify_host_remote(&p->sa)); snprintf(cnonce, sizeof(cnonce), "%08lx", ast_random()); -- cgit v1.2.3 From 6663fbe8c7826bbf50f7ed0eac5d8e4f0b07f106 Mon Sep 17 00:00:00 2001 From: jrose Date: Thu, 7 Jul 2011 16:18:18 +0000 Subject: Merged revisions 326689 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.8 ........ r326689 | jrose | 2011-07-07 11:04:51 -0500 (Thu, 07 Jul 2011) | 10 lines res_odbc patch by tilghman to fix integers with null values Addresses some improper sql statements in res_odbc that would cause an update to fail on realtime peers due to trying to set as "(NULL)" rather than an actual NULL. (closes issue #1922STERISK-17791) Reported by: marcelloceschia Patches: 20110505__issue19223.diff.txt uploaded by tilghman (license 14) ........ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@326694 f38db490-d61c-443f-a65b-d21fe96a405b --- res/res_config_odbc.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/res/res_config_odbc.c b/res/res_config_odbc.c index 8154ecc2b..f52f941be 100644 --- a/res/res_config_odbc.c +++ b/res/res_config_odbc.c @@ -481,7 +481,7 @@ static int update_odbc(const char *database, const char *table, const char *keyf va_list aq; struct custom_prepare_struct cps = { .sql = sql, .extra = lookup }; struct odbc_cache_tables *tableptr; - struct odbc_cache_columns *column; + struct odbc_cache_columns *column = NULL; struct ast_flags connected_flag = { RES_ODBC_CONNECTED }; if (!table) { @@ -519,7 +519,16 @@ static int update_odbc(const char *database, const char *table, const char *keyf while((newparam = va_arg(aq, const char *))) { va_arg(aq, const char *); if ((tableptr && (column = ast_odbc_find_column(tableptr, newparam))) || count > 63) { - snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), ", %s=?", newparam); + /* NULL test for integer-based columns */ + if (ast_strlen_zero(newparam) && tableptr && column && column->nullable && count < 64 && + (column->type == SQL_INTEGER || column->type == SQL_BIGINT || + column->type == SQL_SMALLINT || column->type == SQL_TINYINT || + column->type == SQL_NUMERIC || column->type == SQL_DECIMAL)) { + snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), ", %s=NULL", newparam); + cps.skip |= (1LL << count); + } else { + snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), ", %s=?", newparam); + } } else { /* the column does not exist in the table */ cps.skip |= (1LL << count); } -- cgit v1.2.3 From 66f9db6d03e6736e088ff354d99c5ee3efedec29 Mon Sep 17 00:00:00 2001 From: twilson Date: Thu, 7 Jul 2011 16:50:54 +0000 Subject: Use older functions out of deference to older distros git-svn-id: http://svn.digium.com/svn/asterisk/trunk@326750 f38db490-d61c-443f-a65b-d21fe96a405b --- main/db.c | 4 ++-- utils/astdb2sqlite3.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/main/db.c b/main/db.c index a1fff2146..6a48b331f 100644 --- a/main/db.c +++ b/main/db.c @@ -127,7 +127,7 @@ DEFINE_SQL_STATEMENT(create_astdb_stmt, "CREATE TABLE IF NOT EXISTS astdb(key VA static int init_stmt(sqlite3_stmt **stmt, const char *sql, size_t len) { ast_mutex_lock(&dblock); - if (sqlite3_prepare_v2(astdb, sql, len, stmt, NULL) != SQLITE_OK) { + if (sqlite3_prepare(astdb, sql, len, stmt, NULL) != SQLITE_OK) { ast_log(LOG_WARNING, "Couldn't prepare statement '%s': %s\n", sql, sqlite3_errmsg(astdb)); ast_mutex_unlock(&dblock); return -1; @@ -211,7 +211,7 @@ static int db_open(void) } ast_mutex_lock(&dblock); - if (sqlite3_open_v2(dbname, &astdb, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_NOMUTEX, NULL) != SQLITE_OK) { + if (sqlite3_open(dbname, &astdb) != SQLITE_OK) { ast_log(LOG_WARNING, "Unable to open Asterisk database '%s': %s\n", dbname, sqlite3_errmsg(astdb)); sqlite3_close(astdb); ast_mutex_unlock(&dblock); diff --git a/utils/astdb2sqlite3.c b/utils/astdb2sqlite3.c index 254141744..b0751dc3b 100644 --- a/utils/astdb2sqlite3.c +++ b/utils/astdb2sqlite3.c @@ -134,7 +134,7 @@ static int convert_bdb_to_sqlite3(const char *bdb_dbname) static int init_stmt(sqlite3_stmt **stmt, const char *sql, size_t len) { - if (sqlite3_prepare_v2(astdb, sql, len, stmt, NULL) != SQLITE_OK) { + if (sqlite3_prepare(astdb, sql, len, stmt, NULL) != SQLITE_OK) { fprintf(stderr, "Couldn't prepare statement '%s': %s\n", sql, sqlite3_errmsg(astdb)); return -1; } @@ -171,7 +171,7 @@ static int init_statements(void) static int db_open(const char *dbname) { - if (sqlite3_open_v2(dbname, &astdb, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_NOMUTEX, NULL) != SQLITE_OK) { + if (sqlite3_open(dbname, &astdb) != SQLITE_OK) { fprintf(stderr, "Unable to open Asterisk database '%s': %s\n", dbname, sqlite3_errmsg(astdb)); sqlite3_close(astdb); return -1; -- cgit v1.2.3 From 2db968139e780b63e6d11b52e11b125ddfc2ae8b Mon Sep 17 00:00:00 2001 From: dvossel Date: Thu, 7 Jul 2011 17:24:57 +0000 Subject: Updates confbridge.conf video documentation and adds dtmf action for releasing video src. git-svn-id: http://svn.digium.com/svn/asterisk/trunk@326782 f38db490-d61c-443f-a65b-d21fe96a405b --- apps/app_confbridge.c | 39 +++++++++++++++++++++++------------- apps/confbridge/conf_config_parser.c | 6 ++++++ apps/confbridge/include/confbridge.h | 1 + configs/confbridge.conf.sample | 23 +++++++++++++++++++-- 4 files changed, 53 insertions(+), 16 deletions(-) diff --git a/apps/app_confbridge.c b/apps/app_confbridge.c index d046c489f..80c84ed47 100644 --- a/apps/app_confbridge.c +++ b/apps/app_confbridge.c @@ -632,10 +632,10 @@ static int play_prompt_to_channel(struct conference_bridge *conference_bridge, s return res; } -static void handle_video_on_join(struct conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user) +static void handle_video_on_join(struct conference_bridge *conference_bridge, struct ast_channel *chan, int marked) { - /* only automatically set video source for marked users */ - if (!ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_MARKEDUSER)) { + /* Right now, only marked users are automatically set as the single src of video.*/ + if (!marked) { return; } @@ -645,7 +645,7 @@ static void handle_video_on_join(struct conference_bridge *conference_bridge, st ao2_lock(conference_bridge); /* see if anyone is already the video src */ AST_LIST_TRAVERSE(&conference_bridge->users_list, tmp_user, list) { - if (tmp_user == conference_bridge_user) { + if (tmp_user->chan == chan) { continue; } if (ast_bridge_is_video_src(conference_bridge->bridge, tmp_user->chan)) { @@ -655,24 +655,31 @@ static void handle_video_on_join(struct conference_bridge *conference_bridge, st } ao2_unlock(conference_bridge); if (set) { - ast_bridge_set_single_src_video_mode(conference_bridge->bridge, conference_bridge_user->chan); + ast_bridge_set_single_src_video_mode(conference_bridge->bridge, chan); } } else if (ast_test_flag(&conference_bridge->b_profile, BRIDGE_OPT_VIDEO_SRC_LAST_MARKED)) { /* we joined and are video capable, we override anyone else that may have already been the video feed */ - ast_bridge_set_single_src_video_mode(conference_bridge->bridge, conference_bridge_user->chan); + ast_bridge_set_single_src_video_mode(conference_bridge->bridge, chan); } } -static void handle_video_on_exit(struct conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user) +static void handle_video_on_exit(struct conference_bridge *conference_bridge, struct ast_channel *chan) { struct conference_bridge_user *tmp_user = NULL; /* if this isn't a video source, nothing to update */ - if (!ast_bridge_is_video_src(conference_bridge->bridge, conference_bridge_user->chan)) { + if (!ast_bridge_is_video_src(conference_bridge->bridge, chan)) { return; } - ast_bridge_remove_video_src(conference_bridge->bridge, conference_bridge_user->chan); + ast_bridge_remove_video_src(conference_bridge->bridge, chan); + + /* If in follow talker mode, make sure to restore this mode on the + * bridge when a source is removed. It is possible this channel was + * only set temporarily as a video source by an AMI or DTMF action. */ + if (ast_test_flag(&conference_bridge->b_profile, BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER)) { + ast_bridge_set_talker_src_video_mode(conference_bridge->bridge); + } /* if the video_mode isn't set to automatically pick the video source, do nothing on exit. */ if (!ast_test_flag(&conference_bridge->b_profile, BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED) && @@ -680,10 +687,10 @@ static void handle_video_on_exit(struct conference_bridge *conference_bridge, st return; } - /* Make the next avaliable marked user the video src. */ + /* Make the next available marked user the video src. */ ao2_lock(conference_bridge); AST_LIST_TRAVERSE(&conference_bridge->users_list, tmp_user, list) { - if (tmp_user == conference_bridge_user) { + if (tmp_user->chan == chan) { continue; } if (ast_test_flag(&tmp_user->u_profile, USER_OPT_MARKEDUSER)) { @@ -1454,7 +1461,8 @@ static int confbridge_exec(struct ast_channel *chan, const char *data) } } - handle_video_on_join(conference_bridge, &conference_bridge_user); + /* See if we need to automatically set this user as a video source or not */ + handle_video_on_join(conference_bridge, conference_bridge_user.chan, ast_test_flag(&conference_bridge_user.u_profile, USER_OPT_MARKEDUSER)); /* Join our conference bridge for real */ send_join_event(conference_bridge_user.chan, conference_bridge->name); @@ -1465,8 +1473,8 @@ static int confbridge_exec(struct ast_channel *chan, const char *data) &conference_bridge_user.tech_args); send_leave_event(conference_bridge_user.chan, conference_bridge->name); - - handle_video_on_exit(conference_bridge, &conference_bridge_user); + /* If this user was a video source, we need to clean up and possibly pick a new source. */ + handle_video_on_exit(conference_bridge, conference_bridge_user.chan); /* if this user has a intro, play it when leaving */ if (!quiet && !ast_strlen_zero(conference_bridge_user.name_rec_location)) { @@ -1775,6 +1783,9 @@ static int execute_menu_entry(struct conference_bridge *conference_bridge, ast_bridge_set_single_src_video_mode(conference_bridge->bridge, bridge_channel->chan); ao2_unlock(conference_bridge); break; + case MENU_ACTION_RELEASE_SINGLE_VIDEO_SRC: + handle_video_on_exit(conference_bridge, bridge_channel->chan); + break; } } return res; diff --git a/apps/confbridge/conf_config_parser.c b/apps/confbridge/conf_config_parser.c index 8864f52bc..d11b82582 100644 --- a/apps/confbridge/conf_config_parser.c +++ b/apps/confbridge/conf_config_parser.c @@ -543,6 +543,7 @@ static int add_action_to_menu_entry(struct conf_menu_entry *menu_entry, enum con case MENU_ACTION_ADMIN_KICK_LAST: case MENU_ACTION_LEAVE: case MENU_ACTION_SET_SINGLE_VIDEO_SRC: + case MENU_ACTION_RELEASE_SINGLE_VIDEO_SRC: break; case MENU_ACTION_PLAYBACK: case MENU_ACTION_PLAYBACK_AND_CONTINUE: @@ -660,6 +661,8 @@ static int add_menu_entry(struct conf_menu *menu, const char *dtmf, const char * res |= add_action_to_menu_entry(menu_entry, MENU_ACTION_LEAVE, NULL); } else if (!strcasecmp(action, "set_as_single_video_src")) { res |= add_action_to_menu_entry(menu_entry, MENU_ACTION_SET_SINGLE_VIDEO_SRC, NULL); + } else if (!strcasecmp(action, "release_as_single_video_src")) { + res |= add_action_to_menu_entry(menu_entry, MENU_ACTION_RELEASE_SINGLE_VIDEO_SRC, NULL); } else if (!strncasecmp(action, "dialplan_exec(", 14)) { ast_copy_string(buf, action, sizeof(buf)); action_args = buf; @@ -1166,6 +1169,9 @@ static char *handle_cli_confbridge_show_menu(struct ast_cli_entry *e, int cmd, s case MENU_ACTION_SET_SINGLE_VIDEO_SRC: ast_cli(a->fd, "set_as_single_video_src"); break; + case MENU_ACTION_RELEASE_SINGLE_VIDEO_SRC: + ast_cli(a->fd, "release_as_single_video_src"); + break; } action_num++; } diff --git a/apps/confbridge/include/confbridge.h b/apps/confbridge/include/confbridge.h index 7a2f6bb07..ab4a8c4b0 100644 --- a/apps/confbridge/include/confbridge.h +++ b/apps/confbridge/include/confbridge.h @@ -82,6 +82,7 @@ enum conf_menu_action_id { MENU_ACTION_LEAVE, MENU_ACTION_NOOP, MENU_ACTION_SET_SINGLE_VIDEO_SRC, + MENU_ACTION_RELEASE_SINGLE_VIDEO_SRC, }; /*! The conference menu action contains both diff --git a/configs/confbridge.conf.sample b/configs/confbridge.conf.sample index 408387012..e60ba73be 100644 --- a/configs/confbridge.conf.sample +++ b/configs/confbridge.conf.sample @@ -168,9 +168,13 @@ type=bridge ; larger amounts of delay into the bridge. Valid values here are 10, 20, 40, ; or 80. By default 20ms is used. -;video_mode = follow_talker ; Sets how confbridge handles video distribution to the conference participants. +;video_mode = follow_talker; Sets how confbridge handles video distribution to the conference participants. ; Note that participants wanting to view and be the source of a video feed - ; _MUST_ be sharing the same video codec. + ; _MUST_ be sharing the same video codec. Also, using video in conjunction with + ; with the jitterbuffer currently results in the audio being slightly out of sync + ; with the video. This is a result of the jitterbuffer only working on the audio + ; stream. It is recommended to disable the jitterbuffer when video is used. + ; ; --- MODES --- ; none: No video sources are set by default in the conference. It is still ; possible for a user to be set as a video source via AMI or DTMF action @@ -284,8 +288,23 @@ type=bridge ; admin_toggle_conference_lock ; This action allows an Admin to toggle locking and ; unlocking the conference. Non admins can not use ; this action even if it is in their menu. + ; set_as_single_video_src ; This action allows any user to set themselves as the ; single video source distributed to all participants. + ; This will make the video feed stick to them regardless + ; of what the video_mode is set to. + +; release_as_single_video_src ; This action allows a user to release themselves as + ; the video source. If video_mode is not set to "none" + ; this action will result in the conference returning to + ; whatever video mode the bridge profile is using. + ; + ; Note that this action will have no effect if the user + ; is not currently the video source. Also, the user is + ; not guaranteed by using this action that they will not + ; become the video source again. The bridge will return + ; to whatever operation the video_mode option is set to + ; upon release of the video src. [sample_user_menu] type=menu -- cgit v1.2.3 From 0847f36c973247c1f2db1463fdc013708bf071b7 Mon Sep 17 00:00:00 2001 From: tilghman Date: Thu, 7 Jul 2011 19:20:38 +0000 Subject: Merged revisions 326830 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.8 ........ r326830 | tilghman | 2011-07-07 14:17:19 -0500 (Thu, 07 Jul 2011) | 1 line libgen.h is also needed on Darwin for basename(3) ........ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@326842 f38db490-d61c-443f-a65b-d21fe96a405b --- res/res_http_post.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/res_http_post.c b/res/res_http_post.c index 0f2373730..c0719b6da 100644 --- a/res/res_http_post.c +++ b/res/res_http_post.c @@ -37,7 +37,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include #include #include -#if defined (__OpenBSD__) || defined(__FreeBSD__) +#if defined (__OpenBSD__) || defined(__FreeBSD__) || defined(__Darwin__) #include #endif -- cgit v1.2.3 From d94bb98beca8a6eaf31ed889a172eca06045fedc Mon Sep 17 00:00:00 2001 From: dvossel Date: Thu, 7 Jul 2011 19:39:17 +0000 Subject: Adds pass-through support for codec CELT. This patch adds pass-through support for CELT. CELT formats are defined in codecs.conf and can be configured to any sample rate a CELT endpoint supports. This patch also addresses a crash in channel.c resulting from a frame list being freed incorrectly. This crash was discovered while testing a CELT translator which had to split encoded audio into multiple frames. The codec translator is not a part of this patch, but may be contributed in the future. Review: https://reviewboard.asterisk.org/r/1294/ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@326855 f38db490-d61c-443f-a65b-d21fe96a405b --- channels/chan_sip.c | 54 +++++++++++++++++++++++++--------------------- configs/codecs.conf.sample | 19 +++++++++++++++- include/asterisk/format.h | 2 ++ main/channel.c | 12 +++++++---- main/format.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++ main/frame.c | 4 ++++ main/rtp_engine.c | 4 ++++ res/res_rtp_asterisk.c | 1 + 8 files changed, 120 insertions(+), 30 deletions(-) diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 9e2ddf7ed..9ab409265 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -9468,6 +9468,7 @@ static int process_sdp_a_audio(const char *a, struct sip_pvt *p, struct ast_rtp_ if ((format = ast_rtp_codecs_get_payload_format(newaudiortp, codec))) { unsigned int bit_rate; + int val = 0; switch ((int) format->id) { case AST_FORMAT_SIREN7: @@ -9500,20 +9501,21 @@ static int process_sdp_a_audio(const char *a, struct sip_pvt *p, struct ast_rtp_ } } break; + case AST_FORMAT_CELT: + if (sscanf(fmtp_string, "framesize=%30u", &val) == 1) { + ast_format_append(format, CELT_ATTR_KEY_FRAME_SIZE, val, AST_FORMAT_ATTR_END); + } case AST_FORMAT_SILK: - { - int val = 0; - if (sscanf(fmtp_string, "maxaveragebitrate=%30u", &val) == 1) { - ast_format_append(format, SILK_ATTR_KEY_MAX_BITRATE, val, AST_FORMAT_ATTR_END); - } - if (sscanf(fmtp_string, "usedtx=%30u", &val) == 1) { - ast_format_append(format, SILK_ATTR_KEY_DTX, val ? 1 : 0, AST_FORMAT_ATTR_END); - } - if (sscanf(fmtp_string, "useinbandfec=%30u", &val) == 1) { - ast_format_append(format, SILK_ATTR_KEY_FEC, val ? 1 : 0, AST_FORMAT_ATTR_END); - } - break; + if (sscanf(fmtp_string, "maxaveragebitrate=%30u", &val) == 1) { + ast_format_append(format, SILK_ATTR_KEY_MAX_BITRATE, val, AST_FORMAT_ATTR_END); + } + if (sscanf(fmtp_string, "usedtx=%30u", &val) == 1) { + ast_format_append(format, SILK_ATTR_KEY_DTX, val ? 1 : 0, AST_FORMAT_ATTR_END); + } + if (sscanf(fmtp_string, "useinbandfec=%30u", &val) == 1) { + ast_format_append(format, SILK_ATTR_KEY_FEC, val ? 1 : 0, AST_FORMAT_ATTR_END); } + break; } } } @@ -10829,7 +10831,7 @@ static void add_codec_to_sdp(const struct sip_pvt *p, { int rtp_code; struct ast_format_list fmt; - + int val = 0; if (debug) ast_verbose("Adding codec %d (%s) to SDP\n", format->id, ast_getformatname(format)); @@ -10872,20 +10874,22 @@ static void add_codec_to_sdp(const struct sip_pvt *p, /* Indicate that we only expect 64Kbps */ ast_str_append(a_buf, 0, "a=fmtp:%d bitrate=64000\r\n", rtp_code); break; + case AST_FORMAT_CELT: + if (!ast_format_get_value(format, CELT_ATTR_KEY_FRAME_SIZE, &val) && val > 0) { + ast_str_append(a_buf, 0, "a=fmtp:%d framesize=%u\r\n", rtp_code, val); + } + break; case AST_FORMAT_SILK: - { - int val = 0; - if (!ast_format_get_value(format, SILK_ATTR_KEY_MAX_BITRATE, &val) && val > 5000 && val < 40000) { - ast_str_append(a_buf, 0, "a=fmtp:%d maxaveragebitrate=%u\r\n", rtp_code, val); - } - if (!ast_format_get_value(format, SILK_ATTR_KEY_DTX, &val)) { - ast_str_append(a_buf, 0, "a=fmtp:%d usedtx=%u\r\n", rtp_code, val ? 1 : 0); - } - if (!ast_format_get_value(format, SILK_ATTR_KEY_FEC, &val)) { - ast_str_append(a_buf, 0, "a=fmtp:%d useinbandfec=%u\r\n", rtp_code, val ? 1 : 0); - } - break; + if (!ast_format_get_value(format, SILK_ATTR_KEY_MAX_BITRATE, &val) && val > 5000 && val < 40000) { + ast_str_append(a_buf, 0, "a=fmtp:%d maxaveragebitrate=%u\r\n", rtp_code, val); + } + if (!ast_format_get_value(format, SILK_ATTR_KEY_DTX, &val)) { + ast_str_append(a_buf, 0, "a=fmtp:%d usedtx=%u\r\n", rtp_code, val ? 1 : 0); } + if (!ast_format_get_value(format, SILK_ATTR_KEY_FEC, &val)) { + ast_str_append(a_buf, 0, "a=fmtp:%d useinbandfec=%u\r\n", rtp_code, val ? 1 : 0); + } + break; } if (fmt.cur_ms && (fmt.cur_ms < *min_packet_size)) diff --git a/configs/codecs.conf.sample b/configs/codecs.conf.sample index 4404d4a0c..9b5738577 100644 --- a/configs/codecs.conf.sample +++ b/configs/codecs.conf.sample @@ -126,7 +126,6 @@ maxbitrate=20000 fec=true packetloss_percentage=10; - [silk24] type=silk samprate=24000 @@ -134,3 +133,21 @@ maxbitrate=30000 fec=true packetloss_percentage=10; + +; Default custom CELT codec definitions. Only one custom CELT definition is allowed +; per a sample rate. +;[celt44] +;type=celt +;samprate=44100 ; The samplerate in hz. This option is required. +;framesize=480 ; The framesize option represents the duration of each frame in samples. + ; This must be a factor of 2. This option is only advertised in an SDP + ; when it is set. Otherwise a default of framesize of 480 is assumed + ; internally + +;[celt48] +;type=celt +;samprate=48000 + +;[celt32] +;type=celt +;samprate=32000 diff --git a/include/asterisk/format.h b/include/asterisk/format.h index 67e4178a2..d0f1021d5 100644 --- a/include/asterisk/format.h +++ b/include/asterisk/format.h @@ -28,6 +28,7 @@ #include "asterisk/astobj2.h" #include "asterisk/silk.h" +#include "asterisk/celt.h" #define AST_FORMAT_ATTR_SIZE 128 #define AST_FORMAT_INC 100000 @@ -99,6 +100,7 @@ enum ast_format_id { /*! Raw 16-bit Signed Linear (192000 Hz) PCM. maybe we're taking this too far. */ AST_FORMAT_SLINEAR192 = 27 + AST_FORMAT_TYPE_AUDIO, AST_FORMAT_SPEEX32 = 28 + AST_FORMAT_TYPE_AUDIO, + AST_FORMAT_CELT = 29 + AST_FORMAT_TYPE_AUDIO, /*! H.261 Video */ AST_FORMAT_H261 = 1 + AST_FORMAT_TYPE_VIDEO, diff --git a/main/channel.c b/main/channel.c index ed84da1e6..902c79d85 100644 --- a/main/channel.c +++ b/main/channel.c @@ -1081,6 +1081,8 @@ struct ast_format *ast_best_codec(struct ast_format_cap *cap, struct ast_format AST_FORMAT_SPEEX, /*! SILK is pretty awesome. */ AST_FORMAT_SILK, + /*! CELT supports crazy high sample rates */ + AST_FORMAT_CELT, /*! Ick, LPC10 sounds terrible, but at least we have code for it, if you're tacky enough to use it */ AST_FORMAT_LPC10, @@ -5019,12 +5021,13 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr) from the single frame we passed in; if so, feed each one of them to the channel, freeing each one after it has been written */ if ((f != fr) && AST_LIST_NEXT(f, frame_list)) { - struct ast_frame *cur, *next; + struct ast_frame *cur, *next = NULL; unsigned int skip = 0; - for (cur = f, next = AST_LIST_NEXT(cur, frame_list); - cur; - cur = next, next = cur ? AST_LIST_NEXT(cur, frame_list) : NULL) { + cur = f; + while (cur) { + next = AST_LIST_NEXT(cur, frame_list); + AST_LIST_NEXT(cur, frame_list) = NULL; if (!skip) { if ((res = chan->tech->write(chan, cur)) < 0) { chan->_softhangup |= AST_SOFTHANGUP_DEV; @@ -5037,6 +5040,7 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr) } } ast_frfree(cur); + cur = next; } /* reset f so the code below doesn't attempt to free it */ diff --git a/main/format.c b/main/format.c index 28b15ae21..1c60ab770 100644 --- a/main/format.c +++ b/main/format.c @@ -748,6 +748,15 @@ int ast_format_rate(const struct ast_format *format) } else { return 8000; } + case AST_FORMAT_CELT: + { + int samplerate; + if (!(ast_format_get_value(format, + CELT_ATTR_KEY_SAMP_RATE, + &samplerate))) { + return samplerate; + } + } default: return 8000; } @@ -1085,6 +1094,32 @@ init_cleanup: return -1; } +static int custom_celt_format(struct ast_format_list *entry, unsigned int maxbitrate, unsigned int framesize) +{ + if (!entry->samplespersecond) { + ast_log(LOG_WARNING, "Custom CELT format definition '%s' requires sample rate to be defined.\n", entry->name); + } + ast_format_set(&entry->format, AST_FORMAT_CELT, 0); + if (!has_interface(&entry->format)) { + return -1; + } + + snprintf(entry->desc, sizeof(entry->desc), "CELT Custom Format %dkhz", entry->samplespersecond/1000); + + ast_format_append(&entry->format, + CELT_ATTR_KEY_SAMP_RATE, entry->samplespersecond, + CELT_ATTR_KEY_MAX_BITRATE, maxbitrate, + CELT_ATTR_KEY_FRAME_SIZE, framesize, + AST_FORMAT_ATTR_END); + + entry->fr_len = 80; + entry->min_ms = 20; + entry->max_ms = 20; + entry->inc_ms = 20; + entry->def_ms = 20; + return 0; +} + static int custom_silk_format(struct ast_format_list *entry, unsigned int maxbitrate, int usedtx, int usefec, int packetloss_percentage) { if (!entry->samplespersecond) { @@ -1144,6 +1179,8 @@ static int conf_process_format_name(const char *name, enum ast_format_id *id) { if (!strcasecmp(name, "silk")) { *id = AST_FORMAT_SILK; + } else if (!strcasecmp(name, "celt")) { + *id = AST_FORMAT_CELT; } else { *id = 0; return -1; @@ -1163,8 +1200,14 @@ static int conf_process_sample_rate(const char *rate, unsigned int *result) *result = 24000; } else if (!strcasecmp(rate, "32000")) { *result = 32000; + } else if (!strcasecmp(rate, "44100")) { + *result = 44100; } else if (!strcasecmp(rate, "48000")) { *result = 48000; + } else if (!strcasecmp(rate, "96000")) { + *result = 96000; + } else if (!strcasecmp(rate, "192000")) { + *result = 192000; } else { *result = 0; return -1; @@ -1184,6 +1227,7 @@ static int load_format_config(void) struct { enum ast_format_id id; unsigned int maxbitrate; + unsigned int framesize; unsigned int packetloss_percentage; int usefec; int usedtx; @@ -1221,6 +1265,11 @@ static int load_format_config(void) ast_log(LOG_WARNING, "maxbitrate '%s' at line %d of %s is not supported.\n", var->value, var->lineno, FORMAT_CONFIG); } + } else if (!strcasecmp(var->name, "framesize")) { + if (sscanf(var->value, "%30u", &settings.framesize) != 1) { + ast_log(LOG_WARNING, "framesize '%s' at line %d of %s is not supported.\n", + var->value, var->lineno, FORMAT_CONFIG); + } } else if (!strcasecmp(var->name, "dtx")) { settings.usedtx = ast_true(var->value) ? 1 : 0; } else if (!strcasecmp(var->name, "fec")) { @@ -1239,6 +1288,11 @@ static int load_format_config(void) add_it = 1; } break; + case AST_FORMAT_CELT: + if (!(custom_celt_format(&entry, settings.maxbitrate, settings.framesize))) { + add_it = 1; + } + break; default: ast_log(LOG_WARNING, "Can not create custom format %s\n", entry.name); } diff --git a/main/frame.c b/main/frame.c index bb32386ca..b664e2e84 100644 --- a/main/frame.c +++ b/main/frame.c @@ -1011,6 +1011,10 @@ int ast_codec_get_samples(struct ast_frame *f) } else { return 160; } + case AST_FORMAT_CELT: + /* TODO The assumes 20ms delivery right now, which is incorrect */ + samples = ast_format_rate(&f->subclass.format) / 50; + break; default: ast_log(LOG_WARNING, "Unable to calculate samples for format %s\n", ast_getformatname(&f->subclass.format)); } diff --git a/main/rtp_engine.c b/main/rtp_engine.c index a3d9c4d8e..4ad3c9024 100644 --- a/main/rtp_engine.c +++ b/main/rtp_engine.c @@ -1931,6 +1931,10 @@ int ast_rtp_engine_load_format(const struct ast_format *format) set_next_mime_type(format, 0, "audio", "SILK", ast_format_rate(format)); add_static_payload(-1, format, 0); break; + case AST_FORMAT_CELT: + set_next_mime_type(format, 0, "audio", "CELT", ast_format_rate(format)); + add_static_payload(-1, format, 0); + break; default: break; } diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c index 60f7edacf..5948e664c 100644 --- a/res/res_rtp_asterisk.c +++ b/res/res_rtp_asterisk.c @@ -1254,6 +1254,7 @@ static int ast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *fr case AST_FORMAT_SPEEX16: case AST_FORMAT_SPEEX32: case AST_FORMAT_SILK: + case AST_FORMAT_CELT: case AST_FORMAT_G723_1: case AST_FORMAT_SIREN7: case AST_FORMAT_SIREN14: -- cgit v1.2.3 From 49352ad47d741f2f0d56aeaf85df13ccc0a18ca3 Mon Sep 17 00:00:00 2001 From: dvossel Date: Thu, 7 Jul 2011 19:57:06 +0000 Subject: Fixes spelling errors in CHANGES as well as adding a few entries for CELT and confbridge. git-svn-id: http://svn.digium.com/svn/asterisk/trunk@326856 f38db490-d61c-443f-a65b-d21fe96a405b --- CHANGES | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 7241a7652..a47f1cd03 100644 --- a/CHANGES +++ b/CHANGES @@ -75,6 +75,8 @@ CODECS -------------------------- * Ability to define custom SILK formats in codecs.conf. * Addition of speex32 audio format with translation. + * CELT codec pass-through support and ability to define + custom CELT formats in codecs.conf. ConfBridge -------------------------- @@ -82,11 +84,14 @@ ConfBridge mixing audio at sample rates ranging from 8khz-96khz. * CONFBRIDGE dialplan function capable of creating dynamic ConfBridge user and bridge profiles on a channel. - * CONFBRIDGE_INFO dialplan function capable of retreiving information + * CONFBRIDGE_INFO dialplan function capable of retrieving information about a conference such as locked status and number of parties, admins, and marked users. * Addition of video_mode option in confbridge.conf for adding video support into a bridge profile. + * Addition of the follow_talker video_mode in confbridge.conf. This video + mode dynamically switches the video feed to always display the loudest talker + supplying video in the conference. Dialplan Variables ------------------ @@ -148,7 +153,7 @@ pbx_lua in the sample extensions.lua file for syntax details. * Applications that perform jumps in the dialplan such as Goto will now execute properly. When pbx_lua detects that the context, extension, or - priority we are executing on has changed it will immediatly return control + priority we are executing on has changed it will immediately return control to the asterisk PBX engine. Currently the engine cannot detect a Goto to the priority after the currently executing priority. * An autoservice is now started by default for pbx_lua channels. It can be -- cgit v1.2.3 From 9bf02656507672dabcc06c6beb221af3e35b5ea8 Mon Sep 17 00:00:00 2001 From: dvossel Date: Thu, 7 Jul 2011 22:16:10 +0000 Subject: Adds missing celt.h file from celt pass-through support patch. git-svn-id: http://svn.digium.com/svn/asterisk/trunk@326900 f38db490-d61c-443f-a65b-d21fe96a405b --- include/asterisk/celt.h | 74 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 include/asterisk/celt.h diff --git a/include/asterisk/celt.h b/include/asterisk/celt.h new file mode 100644 index 000000000..f4ba032f4 --- /dev/null +++ b/include/asterisk/celt.h @@ -0,0 +1,74 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2011, Digium, Inc. + * + * David Vossel + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! + * \file + * \brief CELT Format Attributes + * + * \author David Vossel + */ +#ifndef _AST_FORMAT_CELT_H_ +#define _AST_FORMAT_CELT_H_ + +#define AST_CELT_DEFAULT_FRAME_SIZE 480 + +/*! CELT format attribute key value pairs, all are accessible through ast_format_get_value()*/ +enum celt_attr_keys { + CELT_ATTR_KEY_SAMP_RATE, /*!< value is an unsigned integer representing sample rate */ + CELT_ATTR_KEY_MAX_BITRATE, /*!< value is an int */ + CELT_ATTR_KEY_FRAME_SIZE, /*!< value is an int */ +}; + +#endif /* _AST_FORMAT_CELT_H */ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2011, Digium, Inc. + * + * David Vossel + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! + * \file + * \brief CELT Format Attributes + * + * \author David Vossel + */ +#ifndef _AST_FORMAT_CELT_H_ +#define _AST_FORMAT_CELT_H_ + +#define AST_CELT_DEFAULT_FRAME_SIZE 480 + +/*! CELT format attribute key value pairs, all are accessible through ast_format_get_value()*/ +enum celt_attr_keys { + CELT_ATTR_KEY_SAMP_RATE, /*!< value is an unsigned integer representing sample rate */ + CELT_ATTR_KEY_MAX_BITRATE, /*!< value is an int */ + CELT_ATTR_KEY_FRAME_SIZE, /*!< value is an int */ +}; + +#endif /* _AST_FORMAT_CELT_H */ -- cgit v1.2.3 From f034a6ef27149860892b706a1e4b24836895cb29 Mon Sep 17 00:00:00 2001 From: dvossel Date: Thu, 7 Jul 2011 22:17:47 +0000 Subject: Adds the format_attr_celt file which was also missing from the CELT pass through patch. git-svn-id: http://svn.digium.com/svn/asterisk/trunk@326904 f38db490-d61c-443f-a65b-d21fe96a405b --- formats/format_attr_celt.c | 181 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 181 insertions(+) create mode 100644 formats/format_attr_celt.c diff --git a/formats/format_attr_celt.c b/formats/format_attr_celt.c new file mode 100644 index 000000000..de3de8c40 --- /dev/null +++ b/formats/format_attr_celt.c @@ -0,0 +1,181 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2011, Digium, Inc. + * + * David Vossel + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! + * \file + * \brief CELT format attribute interface + * + * \author David Vossel + */ + +#include "asterisk.h" + +ASTERISK_FILE_VERSION(__FILE__, "$Revision$") + +#include "asterisk/module.h" +#include "asterisk/format.h" + +/*! + * \brief CELT attribute structure. + * + * \note The only attribute that affects compatibility here is the sample rate. + */ +struct celt_attr { + unsigned int samplerate; + unsigned int maxbitrate; + unsigned int framesize; +}; + +static enum ast_format_cmp_res celt_cmp(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2) +{ + struct celt_attr *attr1 = (struct celt_attr *) fattr1; + struct celt_attr *attr2 = (struct celt_attr *) fattr2; + + if (attr1->samplerate == attr2->samplerate) { + return AST_FORMAT_CMP_EQUAL; + } + return AST_FORMAT_CMP_NOT_EQUAL; +} + +static int celt_get_val(const struct ast_format_attr *fattr, int key, void *result) +{ + const struct celt_attr *attr = (struct celt_attr *) fattr; + int *val = result; + + switch (key) { + case CELT_ATTR_KEY_SAMP_RATE: + *val = attr->samplerate; + break; + case CELT_ATTR_KEY_MAX_BITRATE: + *val = attr->maxbitrate; + break; + case CELT_ATTR_KEY_FRAME_SIZE: + *val = attr->framesize; + break; + default: + return -1; + ast_log(LOG_WARNING, "unknown attribute type %d\n", key); + } + return 0; +} + +static int celt_isset(const struct ast_format_attr *fattr, va_list ap) +{ + enum celt_attr_keys key; + const struct celt_attr *attr = (struct celt_attr *) fattr; + + for (key = va_arg(ap, int); + key != AST_FORMAT_ATTR_END; + key = va_arg(ap, int)) + { + switch (key) { + case CELT_ATTR_KEY_SAMP_RATE: + if (attr->samplerate != (va_arg(ap, int))) { + return -1; + } + break; + case CELT_ATTR_KEY_MAX_BITRATE: + if (attr->maxbitrate != (va_arg(ap, int))) { + return -1; + } + break; + case CELT_ATTR_KEY_FRAME_SIZE: + if (attr->framesize != (va_arg(ap, int))) { + return -1; + } + break; + default: + return -1; + ast_log(LOG_WARNING, "unknown attribute type %d\n", key); + } + } + return 0; +} +static int celt_getjoint(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2, struct ast_format_attr *result) +{ + struct celt_attr *attr1 = (struct celt_attr *) fattr1; + struct celt_attr *attr2 = (struct celt_attr *) fattr2; + struct celt_attr *attr_res = (struct celt_attr *) result; + + /* sample rate is the only attribute that has any bearing on if joint capabilities exist or not */ + if (attr1->samplerate != attr2->samplerate) { + return -1; + } + /* either would work, they are guaranteed the same at this point. */ + attr_res->samplerate = attr1->samplerate; + /* Take the lowest max bitrate */ + attr_res->maxbitrate = MIN(attr1->maxbitrate, attr2->maxbitrate); + + attr_res->framesize = attr2->framesize; /* TODO figure out what joint framesize means */ + return 0; +} + +static void celt_set(struct ast_format_attr *fattr, va_list ap) +{ + enum celt_attr_keys key; + struct celt_attr *attr = (struct celt_attr *) fattr; + + for (key = va_arg(ap, int); + key != AST_FORMAT_ATTR_END; + key = va_arg(ap, int)) + { + switch (key) { + case CELT_ATTR_KEY_SAMP_RATE: + attr->samplerate = (va_arg(ap, int)); + break; + case CELT_ATTR_KEY_MAX_BITRATE: + attr->maxbitrate = (va_arg(ap, int)); + break; + case CELT_ATTR_KEY_FRAME_SIZE: + attr->framesize = (va_arg(ap, int)); + break; + default: + ast_log(LOG_WARNING, "unknown attribute type %d\n", key); + } + } +} + +static struct ast_format_attr_interface celt_interface = { + .id = AST_FORMAT_CELT, + .format_attr_cmp = celt_cmp, + .format_attr_get_joint = celt_getjoint, + .format_attr_set = celt_set, + .format_attr_isset = celt_isset, + .format_attr_get_val = celt_get_val, +}; + +static int load_module(void) +{ + if (ast_format_attr_reg_interface(&celt_interface)) { + return AST_MODULE_LOAD_DECLINE; + } + + return AST_MODULE_LOAD_SUCCESS; +} + +static int unload_module(void) +{ + ast_format_attr_unreg_interface(&celt_interface); + return 0; +} + +AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "CELT Format Attribute Module", + .load = load_module, + .unload = unload_module, + .load_pri = AST_MODPRI_CHANNEL_DEPEND, +); -- cgit v1.2.3 From 41711d591d5f8f916a5afcb2dc0a517c4327fbfd Mon Sep 17 00:00:00 2001 From: qwell Date: Thu, 7 Jul 2011 22:39:54 +0000 Subject: I think reviewboard broke this. The whole file was doubled. git-svn-id: http://svn.digium.com/svn/asterisk/trunk@326943 f38db490-d61c-443f-a65b-d21fe96a405b --- include/asterisk/celt.h | 37 ------------------------------------- 1 file changed, 37 deletions(-) diff --git a/include/asterisk/celt.h b/include/asterisk/celt.h index f4ba032f4..815525a7b 100644 --- a/include/asterisk/celt.h +++ b/include/asterisk/celt.h @@ -35,40 +35,3 @@ enum celt_attr_keys { }; #endif /* _AST_FORMAT_CELT_H */ -/* - * Asterisk -- An open source telephony toolkit. - * - * Copyright (C) 2011, Digium, Inc. - * - * David Vossel - * - * See http://www.asterisk.org for more information about - * the Asterisk project. Please do not directly contact - * any of the maintainers of this project for assistance; - * the project provides a web site, mailing lists and IRC - * channels for your use. - * - * This program is free software, distributed under the terms of - * the GNU General Public License Version 2. See the LICENSE file - * at the top of the source tree. - */ - -/*! - * \file - * \brief CELT Format Attributes - * - * \author David Vossel - */ -#ifndef _AST_FORMAT_CELT_H_ -#define _AST_FORMAT_CELT_H_ - -#define AST_CELT_DEFAULT_FRAME_SIZE 480 - -/*! CELT format attribute key value pairs, all are accessible through ast_format_get_value()*/ -enum celt_attr_keys { - CELT_ATTR_KEY_SAMP_RATE, /*!< value is an unsigned integer representing sample rate */ - CELT_ATTR_KEY_MAX_BITRATE, /*!< value is an int */ - CELT_ATTR_KEY_FRAME_SIZE, /*!< value is an int */ -}; - -#endif /* _AST_FORMAT_CELT_H */ -- cgit v1.2.3 From bcec07369712e22b9fc38ea2c6a402d32543453e Mon Sep 17 00:00:00 2001 From: rmudgett Date: Fri, 8 Jul 2011 01:26:01 +0000 Subject: Merged revisions 326985 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.8 ........ r326985 | rmudgett | 2011-07-07 20:08:05 -0500 (Thu, 07 Jul 2011) | 12 lines Some code cleanup in pbx.c * Mostly comment and format changes. * ast_context_remove_extension_callerid() and ast_add_extension_nolock() will write lock the found specific context. * ast_context_find() will now tolerate a NULL name. * Eliminated some inlined versions of find_context() and find_context_locked(). ........ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@327000 f38db490-d61c-443f-a65b-d21fe96a405b --- main/pbx.c | 261 +++++++++++++++++++++++++++++-------------------------------- 1 file changed, 124 insertions(+), 137 deletions(-) diff --git a/main/pbx.c b/main/pbx.c index 821fdbfad..0059cbd0b 100644 --- a/main/pbx.c +++ b/main/pbx.c @@ -12,7 +12,7 @@ * channels for your use. * * This program is free software, distributed under the terms of -* the GNU General Public License Version 2. See the LICENSE file + * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. */ @@ -921,15 +921,18 @@ struct ast_state_cb { int id; void *data; ast_state_cb_type callback; + /*! \note Only used by ast_merge_contexts_and_delete */ AST_LIST_ENTRY(ast_state_cb) entry; }; -/*! \brief Structure for dial plan hints - - \note Hints are pointers from an extension in the dialplan to one or - more devices (tech/name) - - See \ref AstExtState -*/ +/*! + * \brief Structure for dial plan hints + * + * \note Hints are pointers from an extension in the dialplan to + * one or more devices (tech/name) + * + * See \ref AstExtState + */ struct ast_hint { struct ast_exten *exten; /*!< Extension */ int laststate; /*!< Last known state */ @@ -1114,12 +1117,12 @@ static void __ast_internal_context_destroy( struct ast_context *con); static int ast_add_extension_nolock(const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void (*datad)(void *), const char *registrar); -static int add_pri_lockopt(struct ast_context *con, struct ast_exten *tmp, - struct ast_exten *el, struct ast_exten *e, int replace, int lockhints); static int ast_add_extension2_lockopt(struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void (*datad)(void *), - const char *registrar, int lockconts, int lockhints); + const char *registrar, int lock_context); +static struct ast_context *find_context_locked(const char *context); +static struct ast_context *find_context(const char *context); /* a func for qsort to use to sort a char array */ static int compare_char(const void *a, const void *b) @@ -1263,7 +1266,9 @@ static struct pbx_builtin { static struct ast_context *contexts; static struct ast_hashtab *contexts_table = NULL; -/*!\brief Lock for the ast_context list +/*! + * \brief Lock for the ast_context list + * \note * This lock MUST be recursive, or a deadlock on reload may result. See * https://issues.asterisk.org/view.php?id=17643 */ @@ -1274,11 +1279,13 @@ static AST_RWLIST_HEAD_STATIC(apps, ast_app); static AST_RWLIST_HEAD_STATIC(switches, ast_switch); static int stateid = 1; -/*! - * \brief When holding this container's lock, do _not_ do anything that will cause conlock - * to be taken, unless you _already_ hold it. The ast_merge_contexts_and_delete - * function will take the locks in conlock/hints order, so any other - * paths that require both locks must also take them in that order. +/*! + * \note When holding this container's lock, do _not_ do + * anything that will cause conlock to be taken, unless you + * _already_ hold it. The ast_merge_contexts_and_delete function + * will take the locks in conlock/hints order, so any other + * paths that require both locks must also take them in that + * order. */ static struct ao2_container *hints; @@ -1306,8 +1313,6 @@ void check_contexts_trouble(void) x = 2; } -static struct ast_context *find_context_locked(const char *context); -static struct ast_context *find_context(const char *context); int check_contexts(char *, int); int check_contexts(char *file, int line ) @@ -1353,9 +1358,7 @@ int check_contexts(char *file, int line ) hashtab structure */ for(c2=contexts;c2;c2=c2->next) { c1 = find_context_locked(c2->name); - if (c1) - { - + if (c1) { ast_unlock_contexts(); /* is every entry in the root list also in the root_table? */ @@ -2602,17 +2605,20 @@ struct fake_context /* this struct is purely for matching in the hashtab */ struct ast_context *ast_context_find(const char *name) { - struct ast_context *tmp = NULL; + struct ast_context *tmp; struct fake_context item; - ast_copy_string(item.name, name, sizeof(item.name)); - + if (!name) { + return NULL; + } ast_rdlock_contexts(); - if( contexts_table ) { - tmp = ast_hashtab_lookup(contexts_table,&item); + if (contexts_table) { + ast_copy_string(item.name, name, sizeof(item.name)); + tmp = ast_hashtab_lookup(contexts_table, &item); } else { - while ( (tmp = ast_walk_contexts(tmp)) ) { - if (!name || !strcasecmp(name, tmp->name)) { + tmp = NULL; + while ((tmp = ast_walk_contexts(tmp))) { + if (!strcasecmp(name, tmp->name)) { break; } } @@ -2679,11 +2685,7 @@ struct ast_exten *pbx_find_extension(struct ast_channel *chan, if (bypass) { /* bypass means we only look there */ tmp = bypass; } else { /* look in contexts */ - struct fake_context item; - - ast_copy_string(item.name, context, sizeof(item.name)); - - tmp = ast_hashtab_lookup(contexts_table, &item); + tmp = find_context(context); if (!tmp) { return NULL; } @@ -4387,9 +4389,9 @@ static int handle_statechange(void *datap) continue; } hint = device->hint; + /* Get device state for this hint */ state = ast_extension_state2(hint->exten); - if ((state == -1) || (state == hint->laststate)) { ao2_t_ref(device, -1, "no statechange for device"); continue; @@ -4439,7 +4441,7 @@ static int handle_statechange(void *datap) /*! \brief Add watcher for extension states */ int ast_extension_state_add(const char *context, const char *exten, - ast_state_cb_type callback, void *data) + ast_state_cb_type callback, void *data) { struct ast_hint *hint; struct ast_state_cb *state_cb; @@ -5276,36 +5278,33 @@ void pbx_set_overrideswitch(const char *newval) /*! * \brief lookup for a context with a given name, * \retval found context or NULL if not found. -*/ + */ static struct ast_context *find_context(const char *context) { - struct ast_context *c = NULL; struct fake_context item; ast_copy_string(item.name, context, sizeof(item.name)); - c = ast_hashtab_lookup(contexts_table,&item); - - return c; + return ast_hashtab_lookup(contexts_table, &item); } /*! * \brief lookup for a context with a given name, * \retval with conlock held if found. * \retval NULL if not found. -*/ + */ static struct ast_context *find_context_locked(const char *context) { - struct ast_context *c = NULL; + struct ast_context *c; struct fake_context item; ast_copy_string(item.name, context, sizeof(item.name)); ast_rdlock_contexts(); - c = ast_hashtab_lookup(contexts_table,&item); - - if (!c) + c = ast_hashtab_lookup(contexts_table, &item); + if (!c) { ast_unlock_contexts(); + } return c; } @@ -5315,12 +5314,13 @@ static struct ast_context *find_context_locked(const char *context) * This function locks contexts list by &conlist, search for the right context * structure, leave context list locked and call ast_context_remove_include2 * which removes include, unlock contexts list and return ... -*/ + */ int ast_context_remove_include(const char *context, const char *include, const char *registrar) { int ret = -1; - struct ast_context *c = find_context_locked(context); + struct ast_context *c; + c = find_context_locked(context); if (c) { /* found, remove include from this context ... */ ret = ast_context_remove_include2(c, include, registrar); @@ -5376,8 +5376,9 @@ int ast_context_remove_include2(struct ast_context *con, const char *include, co int ast_context_remove_switch(const char *context, const char *sw, const char *data, const char *registrar) { int ret = -1; /* default error return */ - struct ast_context *c = find_context_locked(context); + struct ast_context *c; + c = find_context_locked(context); if (c) { /* remove switch from this context ... */ ret = ast_context_remove_switch2(c, sw, data, registrar); @@ -5420,11 +5421,7 @@ int ast_context_remove_switch2(struct ast_context *con, const char *sw, const ch return ret; } -/* - * \note This functions lock contexts list, search for the right context, - * call ast_context_remove_extension2, unlock contexts list and return. - * In this function we are using - */ +/*! \note This function will lock conlock. */ int ast_context_remove_extension(const char *context, const char *extension, int priority, const char *registrar) { return ast_context_remove_extension_callerid(context, extension, priority, NULL, 0, registrar); @@ -5433,12 +5430,15 @@ int ast_context_remove_extension(const char *context, const char *extension, int int ast_context_remove_extension_callerid(const char *context, const char *extension, int priority, const char *callerid, int matchcallerid, const char *registrar) { int ret = -1; /* default error return */ - struct ast_context *c = find_context_locked(context); + struct ast_context *c; + c = find_context_locked(context); if (c) { /* ... remove extension ... */ - ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid, matchcallerid, registrar, 1); + ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid, + matchcallerid, registrar, 0); ast_unlock_contexts(); } + return ret; } @@ -5619,21 +5619,14 @@ int ast_context_remove_extension_callerid2(struct ast_context *con, const char * */ int ast_context_lockmacro(const char *context) { - struct ast_context *c = NULL; + struct ast_context *c; int ret = -1; - struct fake_context item; - - ast_rdlock_contexts(); - - ast_copy_string(item.name, context, sizeof(item.name)); - c = ast_hashtab_lookup(contexts_table,&item); - if (c) - ret = 0; - ast_unlock_contexts(); + c = find_context_locked(context); + if (c) { + ast_unlock_contexts(); - /* if we found context, lock macrolock */ - if (ret == 0) { + /* if we found context, lock macrolock */ ret = ast_mutex_lock(&c->macrolock); } @@ -5647,21 +5640,14 @@ int ast_context_lockmacro(const char *context) */ int ast_context_unlockmacro(const char *context) { - struct ast_context *c = NULL; + struct ast_context *c; int ret = -1; - struct fake_context item; - ast_rdlock_contexts(); - - ast_copy_string(item.name, context, sizeof(item.name)); - - c = ast_hashtab_lookup(contexts_table,&item); - if (c) - ret = 0; - ast_unlock_contexts(); + c = find_context_locked(context); + if (c) { + ast_unlock_contexts(); - /* if we found context, unlock macrolock */ - if (ret == 0) { + /* if we found context, unlock macrolock */ ret = ast_mutex_unlock(&c->macrolock); } @@ -5955,8 +5941,8 @@ static char *handle_show_hints(struct ast_cli_entry *e, int cmd, struct ast_cli_ ast_extension_state2str(hint->laststate), watchers); num++; } - ao2_iterator_destroy(&i); + ast_cli(a->fd, "----------------\n"); ast_cli(a->fd, "- %d hints registered\n", num); return CLI_SUCCESS; @@ -7214,7 +7200,8 @@ static void context_merge(struct ast_context **extcontexts, struct ast_hashtab * void ast_merge_contexts_and_delete(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *registrar) { double ft; - struct ast_context *tmp, *oldcontextslist; + struct ast_context *tmp; + struct ast_context *oldcontextslist; struct ast_hashtab *oldtable; struct store_hints store = AST_LIST_HEAD_INIT_VALUE; struct store_hint *this; @@ -7224,17 +7211,22 @@ void ast_merge_contexts_and_delete(struct ast_context **extcontexts, struct ast_ struct ast_state_cb *thiscb; struct ast_hashtab_iter *iter; struct ao2_iterator i; + struct timeval begintime; + struct timeval writelocktime; + struct timeval endlocktime; + struct timeval enddeltime; - /* it is very important that this function hold the hint list lock _and_ the conlock - during its operation; not only do we need to ensure that the list of contexts - and extensions does not change, but also that no hint callbacks (watchers) are - added or removed during the merge/delete process - - in addition, the locks _must_ be taken in this order, because there are already - other code paths that use this order - */ - - struct timeval begintime, writelocktime, endlocktime, enddeltime; + /* + * It is very important that this function hold the hints + * container lock _and_ the conlock during its operation; not + * only do we need to ensure that the list of contexts and + * extensions does not change, but also that no hint callbacks + * (watchers) are added or removed during the merge/delete + * process + * + * In addition, the locks _must_ be taken in this order, because + * there are already other code paths that use this order + */ begintime = ast_tvnow(); ast_rdlock_contexts(); @@ -7330,13 +7322,17 @@ void ast_merge_contexts_and_delete(struct ast_context **extcontexts, struct ast_ ast_unlock_contexts(); endlocktime = ast_tvnow(); - /* the old list and hashtab no longer are relevant, delete them while the rest of asterisk - is now freely using the new stuff instead */ + /* + * The old list and hashtab no longer are relevant, delete them + * while the rest of asterisk is now freely using the new stuff + * instead. + */ ast_hashtab_destroy(oldtable, NULL); for (tmp = oldcontextslist; tmp; ) { struct ast_context *next; /* next starting point */ + next = tmp->next; __ast_internal_context_destroy(tmp); tmp = next; @@ -7358,7 +7354,6 @@ void ast_merge_contexts_and_delete(struct ast_context **extcontexts, struct ast_ ft = ast_tvdiff_us(enddeltime, begintime); ft /= 1000000.0; ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft); - return; } /* @@ -7369,8 +7364,9 @@ void ast_merge_contexts_and_delete(struct ast_context **extcontexts, struct ast_ int ast_context_add_include(const char *context, const char *include, const char *registrar) { int ret = -1; - struct ast_context *c = find_context_locked(context); + struct ast_context *c; + c = find_context_locked(context); if (c) { ret = ast_context_add_include2(c, include, registrar); ast_unlock_contexts(); @@ -7700,8 +7696,9 @@ int ast_context_add_include2(struct ast_context *con, const char *value, int ast_context_add_switch(const char *context, const char *sw, const char *data, int eval, const char *registrar) { int ret = -1; - struct ast_context *c = find_context_locked(context); + struct ast_context *c; + c = find_context_locked(context); if (c) { /* found, add switch to this context */ ret = ast_context_add_switch2(c, sw, data, eval, registrar); ast_unlock_contexts(); @@ -7779,8 +7776,9 @@ int ast_context_add_switch2(struct ast_context *con, const char *value, int ast_context_remove_ignorepat(const char *context, const char *ignorepat, const char *registrar) { int ret = -1; - struct ast_context *c = find_context_locked(context); + struct ast_context *c; + c = find_context_locked(context); if (c) { ret = ast_context_remove_ignorepat2(c, ignorepat, registrar); ast_unlock_contexts(); @@ -7822,8 +7820,9 @@ int ast_context_remove_ignorepat2(struct ast_context *con, const char *ignorepat int ast_context_add_ignorepat(const char *context, const char *value, const char *registrar) { int ret = -1; - struct ast_context *c = find_context_locked(context); + struct ast_context *c; + c = find_context_locked(context); if (c) { ret = ast_context_add_ignorepat2(c, value, registrar); ast_unlock_contexts(); @@ -7872,8 +7871,10 @@ int ast_context_add_ignorepat2(struct ast_context *con, const char *value, const int ast_ignore_pattern(const char *context, const char *pattern) { struct ast_context *con = ast_context_find(context); + if (con) { struct ast_ignorepat *pat; + for (pat = con->ignorepats; pat; pat = pat->next) { if (ast_extension_match(pat->pattern, pattern)) return 1; @@ -7893,11 +7894,12 @@ static int ast_add_extension_nolock(const char *context, int replace, const char const char *application, void *data, void (*datad)(void *), const char *registrar) { int ret = -1; - struct ast_context *c = find_context(context); + struct ast_context *c; + c = find_context(context); if (c) { ret = ast_add_extension2_lockopt(c, replace, extension, priority, label, callerid, - application, data, datad, registrar, 0, 0); + application, data, datad, registrar, 1); } return ret; @@ -7912,8 +7914,9 @@ int ast_add_extension(const char *context, int replace, const char *extension, const char *application, void *data, void (*datad)(void *), const char *registrar) { int ret = -1; - struct ast_context *c = find_context_locked(context); + struct ast_context *c; + c = find_context_locked(context); if (c) { ret = ast_add_extension2(c, replace, extension, priority, label, callerid, application, data, datad, registrar); @@ -8071,19 +8074,8 @@ static int ext_strncpy(char *dst, const char *src, int len) * \retval 0 on success. * \retval -1 on failure. */ -static int add_pri(struct ast_context *con, struct ast_exten *tmp, +static int add_priority(struct ast_context *con, struct ast_exten *tmp, struct ast_exten *el, struct ast_exten *e, int replace) -{ - return add_pri_lockopt(con, tmp, el, e, replace, 1); -} - -/*! - * \brief add the extension in the priority chain. - * \retval 0 on success. - * \retval -1 on failure. -*/ -static int add_pri_lockopt(struct ast_context *con, struct ast_exten *tmp, - struct ast_exten *el, struct ast_exten *e, int replace, int lockhints) { struct ast_exten *ep; struct ast_exten *eh=e; @@ -8220,11 +8212,7 @@ static int add_pri_lockopt(struct ast_context *con, struct ast_exten *tmp, } /* And immediately return success. */ if (tmp->priority == PRIORITY_HINT) { - if (lockhints) { - ast_add_hint(tmp); - } else { - ast_add_hint(tmp); - } + ast_add_hint(tmp); } } return 0; @@ -8260,18 +8248,21 @@ int ast_add_extension2(struct ast_context *con, const char *application, void *data, void (*datad)(void *), const char *registrar) { - return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid, application, data, datad, registrar, 1, 1); + return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid, + application, data, datad, registrar, 1); } -/*! \brief - * Does all the work of ast_add_extension2, but adds two args, to determine if - * context and hint locking should be done. In merge_and_delete, we need to do - * this without locking, as the locks are already held. +/*! + * \brief Same as ast_add_extension2() but controls the context locking. + * + * \details + * Does all the work of ast_add_extension2, but adds an arg to + * determine if context locking should be done. */ static int ast_add_extension2_lockopt(struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void (*datad)(void *), - const char *registrar, int lockconts, int lockhints) + const char *registrar, int lock_context) { /* * Sort extensions (or patterns) according to the rules indicated above. @@ -8348,7 +8339,7 @@ static int ast_add_extension2_lockopt(struct ast_context *con, tmp->datad = datad; tmp->registrar = registrar; - if (lockconts) { + if (lock_context) { ast_wrlock_context(con); } @@ -8381,9 +8372,9 @@ static int ast_add_extension2_lockopt(struct ast_context *con, if (res >= 0) break; } - if (e && res == 0) { /* exact match, insert in the pri chain */ - res = add_pri(con, tmp, el, e, replace); - if (lockconts) { + if (e && res == 0) { /* exact match, insert in the priority chain */ + res = add_priority(con, tmp, el, e, replace); + if (lock_context) { ast_unlock_context(con); } if (res < 0) { @@ -8442,15 +8433,11 @@ static int ast_add_extension2_lockopt(struct ast_context *con, } ast_hashtab_insert_safe(con->root_table, tmp); - if (lockconts) { + if (lock_context) { ast_unlock_context(con); } if (tmp->priority == PRIORITY_HINT) { - if (lockhints) { - ast_add_hint(tmp); - } else { - ast_add_hint(tmp); - } + ast_add_hint(tmp); } } if (option_debug) { @@ -10102,17 +10089,17 @@ int load_pbx(void) /* * Lock context list functions ... */ -int ast_wrlock_contexts() +int ast_wrlock_contexts(void) { return ast_mutex_lock(&conlock); } -int ast_rdlock_contexts() +int ast_rdlock_contexts(void) { return ast_mutex_lock(&conlock); } -int ast_unlock_contexts() +int ast_unlock_contexts(void) { return ast_mutex_unlock(&conlock); } -- cgit v1.2.3 From 2ac04b0c3d1e25317fc3da0e37034a04ef87bb93 Mon Sep 17 00:00:00 2001 From: russell Date: Fri, 8 Jul 2011 15:39:42 +0000 Subject: Merged revisions 327044 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.8 ........ r327044 | russell | 2011-07-08 10:28:44 -0500 (Fri, 08 Jul 2011) | 2 lines Resolve some set-but-unused-variable warnings. ........ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@327045 f38db490-d61c-443f-a65b-d21fe96a405b --- channels/chan_dahdi.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c index 321be6625..b94889ef4 100644 --- a/channels/chan_dahdi.c +++ b/channels/chan_dahdi.c @@ -3072,9 +3072,9 @@ static int sig_pri_tone_to_dahditone(enum sig_pri_tone tone) #if defined(HAVE_PRI) static void my_handle_dchan_exception(struct sig_pri_span *pri, int index) { - int x, res; + int x; - res = ioctl(pri->fds[index], DAHDI_GETEVENT, &x); + ioctl(pri->fds[index], DAHDI_GETEVENT, &x); if (x) { ast_log(LOG_NOTICE, "PRI got event: %s (%d) on D-channel of span %d\n", event2str(x), x, pri->span); } @@ -11075,7 +11075,7 @@ quit_no_clean: */ static int mwi_send_init(struct dahdi_pvt * pvt) { - int x, res; + int x; struct ast_format tmpfmt; #ifdef HAVE_DAHDI_LINEREVERSE_VMWI @@ -11112,7 +11112,7 @@ static int mwi_send_init(struct dahdi_pvt * pvt) return -1; } x = DAHDI_FLUSH_BOTH; - res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x); + ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x); x = 3000; ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x); #ifdef HAVE_DAHDI_LINEREVERSE_VMWI -- cgit v1.2.3 From 94bbe2a70165acb7af61ceab57ac1e3c4989f971 Mon Sep 17 00:00:00 2001 From: russell Date: Fri, 8 Jul 2011 16:00:46 +0000 Subject: Merged revisions 327046 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.8 ........ r327046 | russell | 2011-07-08 11:00:05 -0500 (Fri, 08 Jul 2011) | 2 lines Fix an error and add more log message info to help see why this fails on FreeBSD. ........ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@327047 f38db490-d61c-443f-a65b-d21fe96a405b --- tests/test_netsock2.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/test_netsock2.c b/tests/test_netsock2.c index 3bbf25770..f759ed2ce 100644 --- a/tests/test_netsock2.c +++ b/tests/test_netsock2.c @@ -101,7 +101,9 @@ AST_TEST_DEFINE(parsing) tmp = ast_sockaddr_stringify(&addr); ast_sockaddr_parse(&tmp_addr, tmp, 0); if (ast_sockaddr_cmp_addr(&addr, &tmp_addr)) { - ast_test_status_update(test, "Re-parsed stringification did not match: '%s' vs '%s'\n", ast_sockaddr_stringify(&addr), ast_sockaddr_stringify(&tmp_addr)); + char buf[64]; + ast_copy_string(buf, ast_sockaddr_stringify(&addr), sizeof(buf)); + ast_test_status_update(test, "Re-parsed stringification of '%s' did not match: '%s' vs '%s'\n", test_vals[x].address, buf, ast_sockaddr_stringify(&tmp_addr)); res = AST_TEST_FAIL; } } -- cgit v1.2.3 From 66a5c9a88c736b368b0eeae4a8f9bb6f90ee4495 Mon Sep 17 00:00:00 2001 From: mnicholson Date: Fri, 8 Jul 2011 19:54:23 +0000 Subject: Merged revisions 327106 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.8 ........ r327106 | mnicholson | 2011-07-08 14:52:51 -0500 (Fri, 08 Jul 2011) | 11 lines Reset our ast_str before passing it on to dialplan function backends. It is possible for a dialplan backend to not modify the given buffer or ast_str and still return success. This causes any previous value stored in the buffer to be used as if the new function call provided it. Some functions also append to the given buffer assuming it is empty. The test_substitution unit test has also been modified to detect this problem. (closes issue ASTERISK-17878) ........ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@327107 f38db490-d61c-443f-a65b-d21fe96a405b --- main/pbx.c | 2 +- tests/test_substitution.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/main/pbx.c b/main/pbx.c index 0059cbd0b..3cb9affeb 100644 --- a/main/pbx.c +++ b/main/pbx.c @@ -3663,9 +3663,9 @@ int ast_func_read2(struct ast_channel *chan, const char *function, struct ast_st if (acfptr->mod) { u = __ast_module_user_add(acfptr->mod, chan); } + ast_str_reset(*str); if (acfptr->read2) { /* ast_str enabled */ - ast_str_reset(*str); res = acfptr->read2(chan, copy, args, str, maxlen); } else { /* Legacy function pointer, allocate buffer for result */ diff --git a/tests/test_substitution.c b/tests/test_substitution.c index aa7d14f91..98e1ed191 100644 --- a/tests/test_substitution.c +++ b/tests/test_substitution.c @@ -261,6 +261,8 @@ AST_TEST_DEFINE(test_substitution) TEST(test_expected_result(test, c, "A${${baz}o:-2:-1}A", "A2A")); pbx_builtin_setvar_helper(c, "list1", "ab&cd&ef"); TEST(test_expected_result(test, c, "${LISTFILTER(list1,&,cd)}", "ab&ef")); + TEST(test_expected_result(test, c, "${SHELL(echo -n 123)},${SHELL(echo -n 456)}", "123,456")); + TEST(test_expected_result(test, c, "${foo},${CDR(answer)},${SHELL(echo -n 456)}", "123,,456")); #undef TEST /* For testing dialplan functions */ -- cgit v1.2.3 From 4308ba0308f55efd1c507fcff830e472236692cb Mon Sep 17 00:00:00 2001 From: dvossel Date: Fri, 8 Jul 2011 20:18:39 +0000 Subject: Moves celt and silk format attribute files into res folder. It was inconsistent to have the silk and celt format attribute modules in the format file interpreter folder. git-svn-id: http://svn.digium.com/svn/asterisk/trunk@327116 f38db490-d61c-443f-a65b-d21fe96a405b --- formats/format_attr_celt.c | 181 -------------------------------------- formats/format_attr_silk.c | 215 --------------------------------------------- res/res_format_attr_celt.c | 181 ++++++++++++++++++++++++++++++++++++++ res/res_format_attr_silk.c | 215 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 396 insertions(+), 396 deletions(-) delete mode 100644 formats/format_attr_celt.c delete mode 100644 formats/format_attr_silk.c create mode 100644 res/res_format_attr_celt.c create mode 100644 res/res_format_attr_silk.c diff --git a/formats/format_attr_celt.c b/formats/format_attr_celt.c deleted file mode 100644 index de3de8c40..000000000 --- a/formats/format_attr_celt.c +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Asterisk -- An open source telephony toolkit. - * - * Copyright (C) 2011, Digium, Inc. - * - * David Vossel - * - * See http://www.asterisk.org for more information about - * the Asterisk project. Please do not directly contact - * any of the maintainers of this project for assistance; - * the project provides a web site, mailing lists and IRC - * channels for your use. - * - * This program is free software, distributed under the terms of - * the GNU General Public License Version 2. See the LICENSE file - * at the top of the source tree. - */ - -/*! - * \file - * \brief CELT format attribute interface - * - * \author David Vossel - */ - -#include "asterisk.h" - -ASTERISK_FILE_VERSION(__FILE__, "$Revision$") - -#include "asterisk/module.h" -#include "asterisk/format.h" - -/*! - * \brief CELT attribute structure. - * - * \note The only attribute that affects compatibility here is the sample rate. - */ -struct celt_attr { - unsigned int samplerate; - unsigned int maxbitrate; - unsigned int framesize; -}; - -static enum ast_format_cmp_res celt_cmp(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2) -{ - struct celt_attr *attr1 = (struct celt_attr *) fattr1; - struct celt_attr *attr2 = (struct celt_attr *) fattr2; - - if (attr1->samplerate == attr2->samplerate) { - return AST_FORMAT_CMP_EQUAL; - } - return AST_FORMAT_CMP_NOT_EQUAL; -} - -static int celt_get_val(const struct ast_format_attr *fattr, int key, void *result) -{ - const struct celt_attr *attr = (struct celt_attr *) fattr; - int *val = result; - - switch (key) { - case CELT_ATTR_KEY_SAMP_RATE: - *val = attr->samplerate; - break; - case CELT_ATTR_KEY_MAX_BITRATE: - *val = attr->maxbitrate; - break; - case CELT_ATTR_KEY_FRAME_SIZE: - *val = attr->framesize; - break; - default: - return -1; - ast_log(LOG_WARNING, "unknown attribute type %d\n", key); - } - return 0; -} - -static int celt_isset(const struct ast_format_attr *fattr, va_list ap) -{ - enum celt_attr_keys key; - const struct celt_attr *attr = (struct celt_attr *) fattr; - - for (key = va_arg(ap, int); - key != AST_FORMAT_ATTR_END; - key = va_arg(ap, int)) - { - switch (key) { - case CELT_ATTR_KEY_SAMP_RATE: - if (attr->samplerate != (va_arg(ap, int))) { - return -1; - } - break; - case CELT_ATTR_KEY_MAX_BITRATE: - if (attr->maxbitrate != (va_arg(ap, int))) { - return -1; - } - break; - case CELT_ATTR_KEY_FRAME_SIZE: - if (attr->framesize != (va_arg(ap, int))) { - return -1; - } - break; - default: - return -1; - ast_log(LOG_WARNING, "unknown attribute type %d\n", key); - } - } - return 0; -} -static int celt_getjoint(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2, struct ast_format_attr *result) -{ - struct celt_attr *attr1 = (struct celt_attr *) fattr1; - struct celt_attr *attr2 = (struct celt_attr *) fattr2; - struct celt_attr *attr_res = (struct celt_attr *) result; - - /* sample rate is the only attribute that has any bearing on if joint capabilities exist or not */ - if (attr1->samplerate != attr2->samplerate) { - return -1; - } - /* either would work, they are guaranteed the same at this point. */ - attr_res->samplerate = attr1->samplerate; - /* Take the lowest max bitrate */ - attr_res->maxbitrate = MIN(attr1->maxbitrate, attr2->maxbitrate); - - attr_res->framesize = attr2->framesize; /* TODO figure out what joint framesize means */ - return 0; -} - -static void celt_set(struct ast_format_attr *fattr, va_list ap) -{ - enum celt_attr_keys key; - struct celt_attr *attr = (struct celt_attr *) fattr; - - for (key = va_arg(ap, int); - key != AST_FORMAT_ATTR_END; - key = va_arg(ap, int)) - { - switch (key) { - case CELT_ATTR_KEY_SAMP_RATE: - attr->samplerate = (va_arg(ap, int)); - break; - case CELT_ATTR_KEY_MAX_BITRATE: - attr->maxbitrate = (va_arg(ap, int)); - break; - case CELT_ATTR_KEY_FRAME_SIZE: - attr->framesize = (va_arg(ap, int)); - break; - default: - ast_log(LOG_WARNING, "unknown attribute type %d\n", key); - } - } -} - -static struct ast_format_attr_interface celt_interface = { - .id = AST_FORMAT_CELT, - .format_attr_cmp = celt_cmp, - .format_attr_get_joint = celt_getjoint, - .format_attr_set = celt_set, - .format_attr_isset = celt_isset, - .format_attr_get_val = celt_get_val, -}; - -static int load_module(void) -{ - if (ast_format_attr_reg_interface(&celt_interface)) { - return AST_MODULE_LOAD_DECLINE; - } - - return AST_MODULE_LOAD_SUCCESS; -} - -static int unload_module(void) -{ - ast_format_attr_unreg_interface(&celt_interface); - return 0; -} - -AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "CELT Format Attribute Module", - .load = load_module, - .unload = unload_module, - .load_pri = AST_MODPRI_CHANNEL_DEPEND, -); diff --git a/formats/format_attr_silk.c b/formats/format_attr_silk.c deleted file mode 100644 index 49122fe80..000000000 --- a/formats/format_attr_silk.c +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Asterisk -- An open source telephony toolkit. - * - * Copyright (C) 2011, Digium, Inc. - * - * David Vossel - * - * See http://www.asterisk.org for more information about - * the Asterisk project. Please do not directly contact - * any of the maintainers of this project for assistance; - * the project provides a web site, mailing lists and IRC - * channels for your use. - * - * This program is free software, distributed under the terms of - * the GNU General Public License Version 2. See the LICENSE file - * at the top of the source tree. - */ - -/*! - * \file - * \brief SILK format attribute interface - * - * \author David Vossel - */ - -#include "asterisk.h" - -ASTERISK_FILE_VERSION(__FILE__, "$Revision$") - -#include "asterisk/module.h" -#include "asterisk/format.h" - -/*! - * \brief SILK attribute structure. - * - * \note The only attribute that affects compatibility here is the sample rate. - */ -struct silk_attr { - unsigned int samplerate; - unsigned int maxbitrate; - unsigned int dtx; - unsigned int fec; - unsigned int packetloss_percentage; -}; - -static enum ast_format_cmp_res silk_cmp(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2) -{ - struct silk_attr *attr1 = (struct silk_attr *) fattr1; - struct silk_attr *attr2 = (struct silk_attr *) fattr2; - - if (attr1->samplerate == attr2->samplerate) { - return AST_FORMAT_CMP_EQUAL; - } - return AST_FORMAT_CMP_NOT_EQUAL; -} - -static int silk_get_val(const struct ast_format_attr *fattr, int key, void *result) -{ - const struct silk_attr *attr = (struct silk_attr *) fattr; - int *val = result; - - switch (key) { - case SILK_ATTR_KEY_SAMP_RATE: - *val = attr->samplerate; - break; - case SILK_ATTR_KEY_MAX_BITRATE: - *val = attr->maxbitrate; - break; - case SILK_ATTR_KEY_DTX: - *val = attr->dtx; - break; - case SILK_ATTR_KEY_FEC: - *val = attr->fec; - break; - case SILK_ATTR_KEY_PACKETLOSS_PERCENTAGE: - *val = attr->packetloss_percentage; - break; - default: - return -1; - ast_log(LOG_WARNING, "unknown attribute type %d\n", key); - } - return 0; -} - -static int silk_isset(const struct ast_format_attr *fattr, va_list ap) -{ - enum silk_attr_keys key; - const struct silk_attr *attr = (struct silk_attr *) fattr; - - for (key = va_arg(ap, int); - key != AST_FORMAT_ATTR_END; - key = va_arg(ap, int)) - { - switch (key) { - case SILK_ATTR_KEY_SAMP_RATE: - if (attr->samplerate != (va_arg(ap, int))) { - return -1; - } - break; - case SILK_ATTR_KEY_MAX_BITRATE: - if (attr->maxbitrate != (va_arg(ap, int))) { - return -1; - } - break; - case SILK_ATTR_KEY_DTX: - if (attr->dtx != (va_arg(ap, int))) { - return -1; - } - break; - case SILK_ATTR_KEY_FEC: - if (attr->fec != (va_arg(ap, int))) { - return -1; - } - break; - case SILK_ATTR_KEY_PACKETLOSS_PERCENTAGE: - if (attr->packetloss_percentage != (va_arg(ap, int))) { - return -1; - } - break; - default: - return -1; - ast_log(LOG_WARNING, "unknown attribute type %d\n", key); - } - } - return 0; -} -static int silk_getjoint(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2, struct ast_format_attr *result) -{ - struct silk_attr *attr1 = (struct silk_attr *) fattr1; - struct silk_attr *attr2 = (struct silk_attr *) fattr2; - struct silk_attr *attr_res = (struct silk_attr *) result; - int joint = -1; - - attr_res->samplerate = attr1->samplerate & attr2->samplerate; - /* sample rate is the only attribute that has any bearing on if joint capabilities exist or not */ - if (attr_res->samplerate) { - joint = 0; - } - /* Take the lowest max bitrate */ - attr_res->maxbitrate = MIN(attr1->maxbitrate, attr2->maxbitrate); - - /* Only do dtx if both sides want it. DTX is a trade off between - * computational complexity and bandwidth. */ - attr_res->dtx = attr1->dtx && attr2->dtx ? 1 : 0; - - /* Only do FEC if both sides want it. If a peer specifically requests not - * to receive with FEC, it may be a waste of bandwidth. */ - attr_res->fec = attr1->fec && attr2->fec ? 1 : 0; - - /* Use the maximum packetloss percentage between the two attributes. This affects how - * much redundancy is used in the FEC. */ - attr_res->packetloss_percentage = MAX(attr1->packetloss_percentage, attr2->packetloss_percentage); - return joint; -} - -static void silk_set(struct ast_format_attr *fattr, va_list ap) -{ - enum silk_attr_keys key; - struct silk_attr *attr = (struct silk_attr *) fattr; - - for (key = va_arg(ap, int); - key != AST_FORMAT_ATTR_END; - key = va_arg(ap, int)) - { - switch (key) { - case SILK_ATTR_KEY_SAMP_RATE: - attr->samplerate = (va_arg(ap, int)); - break; - case SILK_ATTR_KEY_MAX_BITRATE: - attr->maxbitrate = (va_arg(ap, int)); - break; - case SILK_ATTR_KEY_DTX: - attr->dtx = (va_arg(ap, int)); - break; - case SILK_ATTR_KEY_FEC: - attr->fec = (va_arg(ap, int)); - break; - case SILK_ATTR_KEY_PACKETLOSS_PERCENTAGE: - attr->packetloss_percentage = (va_arg(ap, int)); - break; - default: - ast_log(LOG_WARNING, "unknown attribute type %d\n", key); - } - } -} - -static struct ast_format_attr_interface silk_interface = { - .id = AST_FORMAT_SILK, - .format_attr_cmp = silk_cmp, - .format_attr_get_joint = silk_getjoint, - .format_attr_set = silk_set, - .format_attr_isset = silk_isset, - .format_attr_get_val = silk_get_val, -}; - -static int load_module(void) -{ - if (ast_format_attr_reg_interface(&silk_interface)) { - return AST_MODULE_LOAD_DECLINE; - } - - return AST_MODULE_LOAD_SUCCESS; -} - -static int unload_module(void) -{ - ast_format_attr_unreg_interface(&silk_interface); - return 0; -} - -AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "SILK Format Attribute Module", - .load = load_module, - .unload = unload_module, - .load_pri = AST_MODPRI_CHANNEL_DEPEND, -); diff --git a/res/res_format_attr_celt.c b/res/res_format_attr_celt.c new file mode 100644 index 000000000..de3de8c40 --- /dev/null +++ b/res/res_format_attr_celt.c @@ -0,0 +1,181 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2011, Digium, Inc. + * + * David Vossel + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! + * \file + * \brief CELT format attribute interface + * + * \author David Vossel + */ + +#include "asterisk.h" + +ASTERISK_FILE_VERSION(__FILE__, "$Revision$") + +#include "asterisk/module.h" +#include "asterisk/format.h" + +/*! + * \brief CELT attribute structure. + * + * \note The only attribute that affects compatibility here is the sample rate. + */ +struct celt_attr { + unsigned int samplerate; + unsigned int maxbitrate; + unsigned int framesize; +}; + +static enum ast_format_cmp_res celt_cmp(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2) +{ + struct celt_attr *attr1 = (struct celt_attr *) fattr1; + struct celt_attr *attr2 = (struct celt_attr *) fattr2; + + if (attr1->samplerate == attr2->samplerate) { + return AST_FORMAT_CMP_EQUAL; + } + return AST_FORMAT_CMP_NOT_EQUAL; +} + +static int celt_get_val(const struct ast_format_attr *fattr, int key, void *result) +{ + const struct celt_attr *attr = (struct celt_attr *) fattr; + int *val = result; + + switch (key) { + case CELT_ATTR_KEY_SAMP_RATE: + *val = attr->samplerate; + break; + case CELT_ATTR_KEY_MAX_BITRATE: + *val = attr->maxbitrate; + break; + case CELT_ATTR_KEY_FRAME_SIZE: + *val = attr->framesize; + break; + default: + return -1; + ast_log(LOG_WARNING, "unknown attribute type %d\n", key); + } + return 0; +} + +static int celt_isset(const struct ast_format_attr *fattr, va_list ap) +{ + enum celt_attr_keys key; + const struct celt_attr *attr = (struct celt_attr *) fattr; + + for (key = va_arg(ap, int); + key != AST_FORMAT_ATTR_END; + key = va_arg(ap, int)) + { + switch (key) { + case CELT_ATTR_KEY_SAMP_RATE: + if (attr->samplerate != (va_arg(ap, int))) { + return -1; + } + break; + case CELT_ATTR_KEY_MAX_BITRATE: + if (attr->maxbitrate != (va_arg(ap, int))) { + return -1; + } + break; + case CELT_ATTR_KEY_FRAME_SIZE: + if (attr->framesize != (va_arg(ap, int))) { + return -1; + } + break; + default: + return -1; + ast_log(LOG_WARNING, "unknown attribute type %d\n", key); + } + } + return 0; +} +static int celt_getjoint(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2, struct ast_format_attr *result) +{ + struct celt_attr *attr1 = (struct celt_attr *) fattr1; + struct celt_attr *attr2 = (struct celt_attr *) fattr2; + struct celt_attr *attr_res = (struct celt_attr *) result; + + /* sample rate is the only attribute that has any bearing on if joint capabilities exist or not */ + if (attr1->samplerate != attr2->samplerate) { + return -1; + } + /* either would work, they are guaranteed the same at this point. */ + attr_res->samplerate = attr1->samplerate; + /* Take the lowest max bitrate */ + attr_res->maxbitrate = MIN(attr1->maxbitrate, attr2->maxbitrate); + + attr_res->framesize = attr2->framesize; /* TODO figure out what joint framesize means */ + return 0; +} + +static void celt_set(struct ast_format_attr *fattr, va_list ap) +{ + enum celt_attr_keys key; + struct celt_attr *attr = (struct celt_attr *) fattr; + + for (key = va_arg(ap, int); + key != AST_FORMAT_ATTR_END; + key = va_arg(ap, int)) + { + switch (key) { + case CELT_ATTR_KEY_SAMP_RATE: + attr->samplerate = (va_arg(ap, int)); + break; + case CELT_ATTR_KEY_MAX_BITRATE: + attr->maxbitrate = (va_arg(ap, int)); + break; + case CELT_ATTR_KEY_FRAME_SIZE: + attr->framesize = (va_arg(ap, int)); + break; + default: + ast_log(LOG_WARNING, "unknown attribute type %d\n", key); + } + } +} + +static struct ast_format_attr_interface celt_interface = { + .id = AST_FORMAT_CELT, + .format_attr_cmp = celt_cmp, + .format_attr_get_joint = celt_getjoint, + .format_attr_set = celt_set, + .format_attr_isset = celt_isset, + .format_attr_get_val = celt_get_val, +}; + +static int load_module(void) +{ + if (ast_format_attr_reg_interface(&celt_interface)) { + return AST_MODULE_LOAD_DECLINE; + } + + return AST_MODULE_LOAD_SUCCESS; +} + +static int unload_module(void) +{ + ast_format_attr_unreg_interface(&celt_interface); + return 0; +} + +AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "CELT Format Attribute Module", + .load = load_module, + .unload = unload_module, + .load_pri = AST_MODPRI_CHANNEL_DEPEND, +); diff --git a/res/res_format_attr_silk.c b/res/res_format_attr_silk.c new file mode 100644 index 000000000..49122fe80 --- /dev/null +++ b/res/res_format_attr_silk.c @@ -0,0 +1,215 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2011, Digium, Inc. + * + * David Vossel + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! + * \file + * \brief SILK format attribute interface + * + * \author David Vossel + */ + +#include "asterisk.h" + +ASTERISK_FILE_VERSION(__FILE__, "$Revision$") + +#include "asterisk/module.h" +#include "asterisk/format.h" + +/*! + * \brief SILK attribute structure. + * + * \note The only attribute that affects compatibility here is the sample rate. + */ +struct silk_attr { + unsigned int samplerate; + unsigned int maxbitrate; + unsigned int dtx; + unsigned int fec; + unsigned int packetloss_percentage; +}; + +static enum ast_format_cmp_res silk_cmp(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2) +{ + struct silk_attr *attr1 = (struct silk_attr *) fattr1; + struct silk_attr *attr2 = (struct silk_attr *) fattr2; + + if (attr1->samplerate == attr2->samplerate) { + return AST_FORMAT_CMP_EQUAL; + } + return AST_FORMAT_CMP_NOT_EQUAL; +} + +static int silk_get_val(const struct ast_format_attr *fattr, int key, void *result) +{ + const struct silk_attr *attr = (struct silk_attr *) fattr; + int *val = result; + + switch (key) { + case SILK_ATTR_KEY_SAMP_RATE: + *val = attr->samplerate; + break; + case SILK_ATTR_KEY_MAX_BITRATE: + *val = attr->maxbitrate; + break; + case SILK_ATTR_KEY_DTX: + *val = attr->dtx; + break; + case SILK_ATTR_KEY_FEC: + *val = attr->fec; + break; + case SILK_ATTR_KEY_PACKETLOSS_PERCENTAGE: + *val = attr->packetloss_percentage; + break; + default: + return -1; + ast_log(LOG_WARNING, "unknown attribute type %d\n", key); + } + return 0; +} + +static int silk_isset(const struct ast_format_attr *fattr, va_list ap) +{ + enum silk_attr_keys key; + const struct silk_attr *attr = (struct silk_attr *) fattr; + + for (key = va_arg(ap, int); + key != AST_FORMAT_ATTR_END; + key = va_arg(ap, int)) + { + switch (key) { + case SILK_ATTR_KEY_SAMP_RATE: + if (attr->samplerate != (va_arg(ap, int))) { + return -1; + } + break; + case SILK_ATTR_KEY_MAX_BITRATE: + if (attr->maxbitrate != (va_arg(ap, int))) { + return -1; + } + break; + case SILK_ATTR_KEY_DTX: + if (attr->dtx != (va_arg(ap, int))) { + return -1; + } + break; + case SILK_ATTR_KEY_FEC: + if (attr->fec != (va_arg(ap, int))) { + return -1; + } + break; + case SILK_ATTR_KEY_PACKETLOSS_PERCENTAGE: + if (attr->packetloss_percentage != (va_arg(ap, int))) { + return -1; + } + break; + default: + return -1; + ast_log(LOG_WARNING, "unknown attribute type %d\n", key); + } + } + return 0; +} +static int silk_getjoint(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2, struct ast_format_attr *result) +{ + struct silk_attr *attr1 = (struct silk_attr *) fattr1; + struct silk_attr *attr2 = (struct silk_attr *) fattr2; + struct silk_attr *attr_res = (struct silk_attr *) result; + int joint = -1; + + attr_res->samplerate = attr1->samplerate & attr2->samplerate; + /* sample rate is the only attribute that has any bearing on if joint capabilities exist or not */ + if (attr_res->samplerate) { + joint = 0; + } + /* Take the lowest max bitrate */ + attr_res->maxbitrate = MIN(attr1->maxbitrate, attr2->maxbitrate); + + /* Only do dtx if both sides want it. DTX is a trade off between + * computational complexity and bandwidth. */ + attr_res->dtx = attr1->dtx && attr2->dtx ? 1 : 0; + + /* Only do FEC if both sides want it. If a peer specifically requests not + * to receive with FEC, it may be a waste of bandwidth. */ + attr_res->fec = attr1->fec && attr2->fec ? 1 : 0; + + /* Use the maximum packetloss percentage between the two attributes. This affects how + * much redundancy is used in the FEC. */ + attr_res->packetloss_percentage = MAX(attr1->packetloss_percentage, attr2->packetloss_percentage); + return joint; +} + +static void silk_set(struct ast_format_attr *fattr, va_list ap) +{ + enum silk_attr_keys key; + struct silk_attr *attr = (struct silk_attr *) fattr; + + for (key = va_arg(ap, int); + key != AST_FORMAT_ATTR_END; + key = va_arg(ap, int)) + { + switch (key) { + case SILK_ATTR_KEY_SAMP_RATE: + attr->samplerate = (va_arg(ap, int)); + break; + case SILK_ATTR_KEY_MAX_BITRATE: + attr->maxbitrate = (va_arg(ap, int)); + break; + case SILK_ATTR_KEY_DTX: + attr->dtx = (va_arg(ap, int)); + break; + case SILK_ATTR_KEY_FEC: + attr->fec = (va_arg(ap, int)); + break; + case SILK_ATTR_KEY_PACKETLOSS_PERCENTAGE: + attr->packetloss_percentage = (va_arg(ap, int)); + break; + default: + ast_log(LOG_WARNING, "unknown attribute type %d\n", key); + } + } +} + +static struct ast_format_attr_interface silk_interface = { + .id = AST_FORMAT_SILK, + .format_attr_cmp = silk_cmp, + .format_attr_get_joint = silk_getjoint, + .format_attr_set = silk_set, + .format_attr_isset = silk_isset, + .format_attr_get_val = silk_get_val, +}; + +static int load_module(void) +{ + if (ast_format_attr_reg_interface(&silk_interface)) { + return AST_MODULE_LOAD_DECLINE; + } + + return AST_MODULE_LOAD_SUCCESS; +} + +static int unload_module(void) +{ + ast_format_attr_unreg_interface(&silk_interface); + return 0; +} + +AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "SILK Format Attribute Module", + .load = load_module, + .unload = unload_module, + .load_pri = AST_MODPRI_CHANNEL_DEPEND, +); -- cgit v1.2.3 From 95f945f442778334fb19b9c114f3a64892ede944 Mon Sep 17 00:00:00 2001 From: dvossel Date: Fri, 8 Jul 2011 20:23:37 +0000 Subject: Support for writing and reading raw slin files 8khz-192khz. git-svn-id: http://svn.digium.com/svn/asterisk/trunk@327137 f38db490-d61c-443f-a65b-d21fe96a405b --- formats/format_sln.c | 168 ++++++++++++++++++++++++++++++++++++++++++++----- formats/format_sln16.c | 142 ----------------------------------------- 2 files changed, 152 insertions(+), 158 deletions(-) delete mode 100644 formats/format_sln16.c diff --git a/formats/format_sln.c b/formats/format_sln.c index 0cb27949d..91cb4584a 100644 --- a/formats/format_sln.c +++ b/formats/format_sln.c @@ -17,11 +17,10 @@ /*! \file * - * \brief RAW SLINEAR Format - * \arg File name extensions: sln, raw + * \brief RAW SLINEAR Formats * \ingroup formats */ - + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") @@ -30,18 +29,15 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/module.h" #include "asterisk/endian.h" -#define BUF_SIZE 320 /* 320 bytes, 160 samples */ -#define SLIN_SAMPLES 160 - -static struct ast_frame *slinear_read(struct ast_filestream *s, int *whennext) +static struct ast_frame *generic_read(struct ast_filestream *s, int *whennext, unsigned int buf_size, enum ast_format_id id) { int res; /* Send a frame from the file to the appropriate channel */ s->fr.frametype = AST_FRAME_VOICE; - ast_format_set(&s->fr.subclass.format, AST_FORMAT_SLINEAR, 0); + ast_format_set(&s->fr.subclass.format, id, 0); s->fr.mallocd = 0; - AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, BUF_SIZE); + AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, buf_size); if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) < 1) { if (res) ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno)); @@ -52,14 +48,14 @@ static struct ast_frame *slinear_read(struct ast_filestream *s, int *whennext) return &s->fr; } -static int slinear_write(struct ast_filestream *fs, struct ast_frame *f) +static int generic_write(struct ast_filestream *fs, struct ast_frame *f, enum ast_format_id id) { int res; if (f->frametype != AST_FRAME_VOICE) { ast_log(LOG_WARNING, "Asked to write non-voice frame!\n"); return -1; } - if (f->subclass.format.id != AST_FORMAT_SLINEAR) { + if (f->subclass.format.id != id) { ast_log(LOG_WARNING, "Asked to write non-slinear frame (%s)!\n", ast_getformatname(&f->subclass.format)); return -1; } @@ -103,6 +99,8 @@ static off_t slinear_tell(struct ast_filestream *fs) return ftello(fs->f) / 2; } +static int slinear_write(struct ast_filestream *fs, struct ast_frame *f){return generic_write(fs, f, AST_FORMAT_SLINEAR);} +static struct ast_frame *slinear_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 320, AST_FORMAT_SLINEAR);} static struct ast_format_def slin_f = { .name = "sln", .exts = "sln|raw", @@ -111,23 +109,161 @@ static struct ast_format_def slin_f = { .trunc = slinear_trunc, .tell = slinear_tell, .read = slinear_read, - .buf_size = BUF_SIZE + AST_FRIENDLY_OFFSET, + .buf_size = 320 + AST_FRIENDLY_OFFSET, +}; + +static int slinear12_write(struct ast_filestream *fs, struct ast_frame *f){return generic_write(fs, f, AST_FORMAT_SLINEAR12);} +static struct ast_frame *slinear12_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 480, AST_FORMAT_SLINEAR12);} +static struct ast_format_def slin12_f = { + .name = "sln12", + .exts = "sln12", + .write = slinear12_write, + .seek = slinear_seek, + .trunc = slinear_trunc, + .tell = slinear_tell, + .read = slinear12_read, + .buf_size = 480 + AST_FRIENDLY_OFFSET, +}; + +static int slinear16_write(struct ast_filestream *fs, struct ast_frame *f){return generic_write(fs, f, AST_FORMAT_SLINEAR16);} +static struct ast_frame *slinear16_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 640, AST_FORMAT_SLINEAR16);} +static struct ast_format_def slin16_f = { + .name = "sln16", + .exts = "sln16", + .write = slinear16_write, + .seek = slinear_seek, + .trunc = slinear_trunc, + .tell = slinear_tell, + .read = slinear16_read, + .buf_size = 640 + AST_FRIENDLY_OFFSET, +}; + +static int slinear24_write(struct ast_filestream *fs, struct ast_frame *f){return generic_write(fs, f, AST_FORMAT_SLINEAR24);} +static struct ast_frame *slinear24_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 960, AST_FORMAT_SLINEAR24);} +static struct ast_format_def slin24_f = { + .name = "sln24", + .exts = "sln24", + .write = slinear24_write, + .seek = slinear_seek, + .trunc = slinear_trunc, + .tell = slinear_tell, + .read = slinear24_read, + .buf_size = 960 + AST_FRIENDLY_OFFSET, +}; + +static int slinear32_write(struct ast_filestream *fs, struct ast_frame *f){return generic_write(fs, f, AST_FORMAT_SLINEAR32);} +static struct ast_frame *slinear32_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 1280, AST_FORMAT_SLINEAR32);} +static struct ast_format_def slin32_f = { + .name = "sln32", + .exts = "sln32", + .write = slinear32_write, + .seek = slinear_seek, + .trunc = slinear_trunc, + .tell = slinear_tell, + .read = slinear32_read, + .buf_size = 1280 + AST_FRIENDLY_OFFSET, +}; + +static int slinear44_write(struct ast_filestream *fs, struct ast_frame *f){return generic_write(fs, f, AST_FORMAT_SLINEAR44);} +static struct ast_frame *slinear44_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 1764, AST_FORMAT_SLINEAR44);} +static struct ast_format_def slin44_f = { + .name = "sln44", + .exts = "sln44", + .write = slinear44_write, + .seek = slinear_seek, + .trunc = slinear_trunc, + .tell = slinear_tell, + .read = slinear44_read, + .buf_size = 1764 + AST_FRIENDLY_OFFSET, +}; + +static int slinear48_write(struct ast_filestream *fs, struct ast_frame *f){return generic_write(fs, f, AST_FORMAT_SLINEAR48);} +static struct ast_frame *slinear48_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 1920, AST_FORMAT_SLINEAR48);} +static struct ast_format_def slin48_f = { + .name = "sln48", + .exts = "sln48", + .write = slinear48_write, + .seek = slinear_seek, + .trunc = slinear_trunc, + .tell = slinear_tell, + .read = slinear48_read, + .buf_size = 1920 + AST_FRIENDLY_OFFSET, +}; + +static int slinear96_write(struct ast_filestream *fs, struct ast_frame *f){return generic_write(fs, f, AST_FORMAT_SLINEAR96);} +static struct ast_frame *slinear96_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 3840, AST_FORMAT_SLINEAR96);} +static struct ast_format_def slin96_f = { + .name = "sln96", + .exts = "sln96", + .write = slinear96_write, + .seek = slinear_seek, + .trunc = slinear_trunc, + .tell = slinear_tell, + .read = slinear96_read, + .buf_size = 3840 + AST_FRIENDLY_OFFSET, +}; + +static int slinear192_write(struct ast_filestream *fs, struct ast_frame *f){return generic_write(fs, f, AST_FORMAT_SLINEAR192);} +static struct ast_frame *slinear192_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 7680, AST_FORMAT_SLINEAR192);} +static struct ast_format_def slin192_f = { + .name = "sln192", + .exts = "sln192", + .write = slinear192_write, + .seek = slinear_seek, + .trunc = slinear_trunc, + .tell = slinear_tell, + .read = slinear192_read, + .buf_size = 7680 + AST_FRIENDLY_OFFSET, +}; + +static struct ast_format_def *slin_list[] = { + &slin_f, + &slin12_f, + &slin16_f, + &slin24_f, + &slin32_f, + &slin44_f, + &slin48_f, + &slin96_f, + &slin192_f, }; static int load_module(void) { + int i; ast_format_set(&slin_f.format, AST_FORMAT_SLINEAR, 0); - if (ast_format_def_register(&slin_f)) - return AST_MODULE_LOAD_FAILURE; + ast_format_set(&slin12_f.format, AST_FORMAT_SLINEAR12, 0); + ast_format_set(&slin16_f.format, AST_FORMAT_SLINEAR16, 0); + ast_format_set(&slin24_f.format, AST_FORMAT_SLINEAR24, 0); + ast_format_set(&slin32_f.format, AST_FORMAT_SLINEAR32, 0); + ast_format_set(&slin44_f.format, AST_FORMAT_SLINEAR44, 0); + ast_format_set(&slin48_f.format, AST_FORMAT_SLINEAR48, 0); + ast_format_set(&slin96_f.format, AST_FORMAT_SLINEAR96, 0); + ast_format_set(&slin192_f.format, AST_FORMAT_SLINEAR192, 0); + + for (i = 0; i < ARRAY_LEN(slin_list); i++) { + if (ast_format_def_register(slin_list[i])) { + return AST_MODULE_LOAD_FAILURE; + } + } + return AST_MODULE_LOAD_SUCCESS; } static int unload_module(void) { - return ast_format_def_unregister(slin_f.name); + int res = 0; + int i = 0; + + for (i = 0; i < ARRAY_LEN(slin_list); i++) { + if (ast_format_def_unregister(slin_list[i]->name)) { + res |= AST_MODULE_LOAD_FAILURE; + } + } + return res; } -AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Raw Signed Linear Audio support (SLN)", +AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Raw Signed Linear Audio support (SLN) 8khz-192khz", .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_APP_DEPEND diff --git a/formats/format_sln16.c b/formats/format_sln16.c deleted file mode 100644 index cac019615..000000000 --- a/formats/format_sln16.c +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Asterisk -- An open source telephony toolkit. - * - * Copyright (C) 1999 - 2008, Anthony Minessale and Digium, Inc. - * Anthony Minessale (anthmct@yahoo.com) - * Kevin P. Fleming - * - * See http://www.asterisk.org for more information about - * the Asterisk project. Please do not directly contact - * any of the maintainers of this project for assistance; - * the project provides a web site, mailing lists and IRC - * channels for your use. - * - * This program is free software, distributed under the terms of - * the GNU General Public License Version 2. See the LICENSE file - * at the top of the source tree. - */ - -/*! \file - * - * \brief RAW SLINEAR 16 Format - * \arg File name extensions: sln16 - * \ingroup formats - */ - -#include "asterisk.h" - -ASTERISK_FILE_VERSION(__FILE__, "$Revision$") - -#include "asterisk/mod_format.h" -#include "asterisk/module.h" -#include "asterisk/endian.h" - -#define BUF_SIZE 640 /* 640 bytes, 320 samples */ -#define SLIN_SAMPLES 320 - -static struct ast_frame *slinear_read(struct ast_filestream *s, int *whennext) -{ - int res; - /* Send a frame from the file to the appropriate channel */ - - s->fr.frametype = AST_FRAME_VOICE; - ast_format_set(&s->fr.subclass.format, AST_FORMAT_SLINEAR16, 0); - s->fr.mallocd = 0; - AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, BUF_SIZE); - if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) < 1) { - if (res) - ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno)); - return NULL; - } - *whennext = s->fr.samples = res/2; - s->fr.datalen = res; - return &s->fr; -} - -static int slinear_write(struct ast_filestream *fs, struct ast_frame *f) -{ - int res; - - if (f->frametype != AST_FRAME_VOICE) { - ast_log(LOG_WARNING, "Asked to write non-voice frame!\n"); - return -1; - } - if (f->subclass.format.id != AST_FORMAT_SLINEAR16) { - ast_log(LOG_WARNING, "Asked to write non-slinear16 frame (%s)!\n", ast_getformatname(&f->subclass.format)); - return -1; - } - if ((res = fwrite(f->data.ptr, 1, f->datalen, fs->f)) != f->datalen) { - ast_log(LOG_WARNING, "Bad write (%d/%d): %s\n", res, f->datalen, strerror(errno)); - return -1; - } - return 0; -} - -static int slinear_seek(struct ast_filestream *fs, off_t sample_offset, int whence) -{ - off_t offset = 0, min = 0, cur, max; - - sample_offset <<= 1; - - cur = ftello(fs->f); - - fseeko(fs->f, 0, SEEK_END); - - max = ftello(fs->f); - - if (whence == SEEK_SET) - offset = sample_offset; - else if (whence == SEEK_CUR || whence == SEEK_FORCECUR) - offset = sample_offset + cur; - else if (whence == SEEK_END) - offset = max - sample_offset; - - if (whence != SEEK_FORCECUR) - offset = (offset > max) ? max : offset; - - /* always protect against seeking past begining. */ - offset = (offset < min) ? min : offset; - - return fseeko(fs->f, offset, SEEK_SET); -} - -static int slinear_trunc(struct ast_filestream *fs) -{ - return ftruncate(fileno(fs->f), ftello(fs->f)); -} - -static off_t slinear_tell(struct ast_filestream *fs) -{ - return ftello(fs->f) / 2; -} - -static struct ast_format_def slin_f = { - .name = "sln16", - .exts = "sln16", - .write = slinear_write, - .seek = slinear_seek, - .trunc = slinear_trunc, - .tell = slinear_tell, - .read = slinear_read, - .buf_size = BUF_SIZE + AST_FRIENDLY_OFFSET, -}; - -static int load_module(void) -{ - ast_format_set(&slin_f.format, AST_FORMAT_SLINEAR16, 0); - if (ast_format_def_register(&slin_f)) - return AST_MODULE_LOAD_FAILURE; - - return AST_MODULE_LOAD_SUCCESS; -} - -static int unload_module(void) -{ - return ast_format_def_unregister(slin_f.name); -} - -AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Raw Signed Linear 16KHz Audio support (SLN16)", - .load = load_module, - .unload = unload_module, - .load_pri = AST_MODPRI_APP_DEPEND -); -- cgit v1.2.3 From be5ddbfe3244f2783f655b496a1ff6a2b8344102 Mon Sep 17 00:00:00 2001 From: dvossel Date: Fri, 8 Jul 2011 20:26:07 +0000 Subject: Updates CHANGES log to reflect new slinear read/write file interpreters. git-svn-id: http://svn.digium.com/svn/asterisk/trunk@327148 f38db490-d61c-443f-a65b-d21fe96a405b --- CHANGES | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES b/CHANGES index a47f1cd03..d5997fcf4 100644 --- a/CHANGES +++ b/CHANGES @@ -77,6 +77,9 @@ CODECS * Addition of speex32 audio format with translation. * CELT codec pass-through support and ability to define custom CELT formats in codecs.conf. + * Ability to read raw signed linear files with sample rates + ranging from 8khz - 192khz. The new file extensions introduced + are .sln12, .sln24, .slin32, .slin44, .slin48, .slin96, .slin192. ConfBridge -------------------------- -- cgit v1.2.3 From 644c8745fe8b6323eedb50ad784b818633a69df5 Mon Sep 17 00:00:00 2001 From: dvossel Date: Fri, 8 Jul 2011 20:33:49 +0000 Subject: Adds entry in UPDATES.txt for removal of formats/format_sln16.c. Fixes typo in CHANGES as well. git-svn-id: http://svn.digium.com/svn/asterisk/trunk@327168 f38db490-d61c-443f-a65b-d21fe96a405b --- CHANGES | 2 +- UPGRADE.txt | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index d5997fcf4..85a1ea11f 100644 --- a/CHANGES +++ b/CHANGES @@ -79,7 +79,7 @@ CODECS custom CELT formats in codecs.conf. * Ability to read raw signed linear files with sample rates ranging from 8khz - 192khz. The new file extensions introduced - are .sln12, .sln24, .slin32, .slin44, .slin48, .slin96, .slin192. + are .sln12, .sln24, .sln32, .sln44, .sln48, .sln96, .sln192. ConfBridge -------------------------- diff --git a/UPGRADE.txt b/UPGRADE.txt index 6f111eff0..87413cf3b 100644 --- a/UPGRADE.txt +++ b/UPGRADE.txt @@ -29,6 +29,12 @@ ConfBridge - ConfBridge's dialplan arguments have changed and are not backwards compatible. +File Interpreters + - The format interpreter formats/format_sln16.c for the file extension + '.sln16' has been removed. The '.sln16' file interpreter now exists + in the formats/format_sln.c module along with new support for sln12, + sln24, sln32, sln44, sln48, sln96, and sln192 file extensions. + HTTP: - A bindaddr must be specified in order for the HTTP server to run. Previous versions would default to 0.0.0.0 if no -- cgit v1.2.3 From 786d3a9c16744a85ae7c559504bfa23594a51ea5 Mon Sep 17 00:00:00 2001 From: rmudgett Date: Fri, 8 Jul 2011 21:43:49 +0000 Subject: Merged revisions 327211 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.8 ........ r327211 | rmudgett | 2011-07-08 16:41:58 -0500 (Fri, 08 Jul 2011) | 9 lines INVITE 403 Forbidden response always retransmits the maximum times. Asterisk sends a 403 Forbidden response if authentication fails for an INVITE as required. However, it ignores the ACK and keeps retransmitting the response. * Made not delete the to-tag in the dialog so the expected ACK can be matched with the dialog and stop the retransmissions. ........ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@327212 f38db490-d61c-443f-a65b-d21fe96a405b --- channels/chan_sip.c | 1 - 1 file changed, 1 deletion(-) diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 9ab409265..2e7b6f7f9 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -22523,7 +22523,6 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int } p->invitestate = INV_COMPLETED; sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); - ast_string_field_set(p, theirtag, NULL); res = 0; goto request_invite_cleanup; } -- cgit v1.2.3 -- cgit v1.2.3 From c611b5cf37ec4b788e56e4a954bc4d5efd351b34 Mon Sep 17 00:00:00 2001 From: may Date: Sun, 10 Jul 2011 01:37:58 +0000 Subject: Full T.38 handshaking and fax detection Add full t.38 handshaking for OOH323 that are required for newest T.38 gateway codes. Add fax detection (cng tone, t38) and dialplan redirection to fax ext on fax event detected. Add OOH323() function to set/get t38support and faxdetect parameters. (closes issue ASTERISK-17754) Reported by: irroot Patches: ooh323_faxdetect.patch uploaded by irroot (license 52) issue19183-final.patch uploaded by may213 (license 454) Tested by: may213, irroot Review: https://reviewboard.asterisk.org/r/1174/ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@327359 f38db490-d61c-443f-a65b-d21fe96a405b --- addons/chan_ooh323.c | 770 ++++++++++++++++++++++++++++------------ configs/chan_ooh323.conf.sample | 12 + 2 files changed, 564 insertions(+), 218 deletions(-) diff --git a/addons/chan_ooh323.c b/addons/chan_ooh323.c index 5c2131c93..552b8f22c 100644 --- a/addons/chan_ooh323.c +++ b/addons/chan_ooh323.c @@ -24,6 +24,42 @@ #include "chan_ooh323.h" #include +/*** DOCUMENTATION + + + Allow Setting / Reading OOH323 Settings + + + + + + Fax Detect [R/W] + Returns 0 or 1 + Write yes or no + + + + + t38support [R/W] + Returns 0 or 1 + Write yes or no + + + + + Returns h323id [R] + + + + + + Read and set channel parameters in the dialplan. + name is one of the above only those with a [W] can be writen to. + + + +***/ + #define FORMAT_STRING_SIZE 512 /* Defaults */ @@ -49,6 +85,9 @@ #define T38_ENABLED 1 #define T38_FAXGW 1 +#define FAXDETECT_CNG 1 +#define FAXDETECT_T38 2 + /* Channel description */ static const char type[] = "OOH323"; static const char tdesc[] = "Objective Systems H323 Channel Driver"; @@ -138,6 +177,8 @@ static struct ooh323_pvt { struct ast_rtp_instance *vrtp; /* Placeholder for now */ int t38support; /* T.38 mode - disable, transparent, faxgw */ + int faxdetect; + int faxdetected; int rtptimeout; struct ast_udptl *udptl; int faxmode; @@ -199,25 +240,26 @@ AST_MUTEX_DEFINE_STATIC(iflock); /* Profile of H.323 user registered with PBX*/ struct ooh323_user{ ast_mutex_t lock; - char name[256]; - char context[AST_MAX_EXTENSION]; - int incominglimit; - unsigned inUse; - char accountcode[20]; - int amaflags; + char name[256]; + char context[AST_MAX_EXTENSION]; + int incominglimit; + unsigned inUse; + char accountcode[20]; + int amaflags; struct ast_format_cap *cap; struct ast_codec_pref prefs; - int dtmfmode; - int dtmfcodec; - int t38support; - int rtptimeout; - int mUseIP; /* Use IP address or H323-ID to search user */ - char mIP[4*8+7+2]; /* Max for IPv6 - 2 brackets, 8 4hex, 7 - : */ - struct OOH323Regex *rtpmask; - char rtpmaskstr[120]; - int rtdrcount, rtdrinterval; - int faststart, h245tunneling; - int g729onlyA; + int dtmfmode; + int dtmfcodec; + int faxdetect; + int t38support; + int rtptimeout; + int mUseIP; /* Use IP address or H323-ID to search user */ + char mIP[4*8+7+2]; /* Max for IPv6 - 2 brackets, 8 4hex, 7 - : */ + struct OOH323Regex *rtpmask; + char rtpmaskstr[120]; + int rtdrcount, rtdrinterval; + int faststart, h245tunneling; + int g729onlyA; struct ooh323_user *next; }; @@ -233,6 +275,7 @@ struct ooh323_peer{ int amaflags; int dtmfmode; int dtmfcodec; + int faxdetect; int t38support; int mFriend; /* indicates defined as friend */ char ip[4*8+7+2]; /* Max for IPv6 - 2 brackets, 8 4hex, 7 - : */ @@ -295,6 +338,7 @@ static struct ast_format_cap *gCap; static struct ast_codec_pref gPrefs; static int gDTMFMode = H323_DTMF_RFC2833; static int gDTMFCodec = 101; +static int gFAXdetect = FAXDETECT_CNG; static int gT38Support = T38_FAXGW; static char gGatekeeper[100]; static enum RasGatekeeperMode gRasGkMode = RasNoGatekeeper; @@ -343,10 +387,12 @@ static pthread_t monitor_thread = AST_PTHREADT_NULL; static struct ast_channel *ooh323_new(struct ooh323_pvt *i, int state, - const char *host, struct ast_format_cap *cap, const char *linkedid) + const char *host, struct ast_format_cap *cap, const char *linkedid) { struct ast_channel *ch = NULL; struct ast_format tmpfmt; + int features = 0; + if (gH323Debug) ast_verbose("--- ooh323_new - %s\n", host); @@ -388,16 +434,27 @@ static struct ast_channel *ooh323_new(struct ooh323_pvt *i, int state, ast_module_ref(myself); /* Allocate dsp for in-band DTMF support */ - if (i->dtmfmode & H323_DTMF_INBAND) { + if ((i->dtmfmode & H323_DTMF_INBAND) || (i->faxdetect & FAXDETECT_CNG)) { i->vad = ast_dsp_new(); - ast_dsp_set_features(i->vad, DSP_FEATURE_DIGIT_DETECT); - ast_dsp_set_features(i->vad, - DSP_FEATURE_DIGIT_DETECT | DSP_FEATURE_FAX_DETECT); - ast_dsp_set_faxmode(i->vad, - DSP_FAXMODE_DETECT_CNG | DSP_FAXMODE_DETECT_CED); + } - if (i->dtmfmode & H323_DTMF_INBANDRELAX) + /* inband DTMF*/ + if (i->dtmfmode & H323_DTMF_INBAND) { + features |= DSP_FEATURE_DIGIT_DETECT; + if (i->dtmfmode & H323_DTMF_INBANDRELAX) { ast_dsp_set_digitmode(i->vad, DSP_DIGITMODE_DTMF | DSP_DIGITMODE_RELAXDTMF); + } + } + + /* fax detection*/ + if (i->faxdetect & FAXDETECT_CNG) { + features |= DSP_FEATURE_FAX_DETECT; + ast_dsp_set_faxmode(i->vad, + DSP_FAXMODE_DETECT_CNG | DSP_FAXMODE_DETECT_CED); + } + + if (features) { + ast_dsp_set_features(i->vad, features); } ast_mutex_lock(&usecnt_lock); @@ -484,6 +541,9 @@ static struct ooh323_pvt *ooh323_alloc(int callref, char *callToken) ast_mutex_lock(&pvt->lock); pvt->faxmode = 0; + pvt->chmodepend = 0; + pvt->faxdetected = 0; + pvt->faxdetect = gFAXdetect; pvt->t38support = gT38Support; pvt->rtptimeout = gRTPTimeout; pvt->rtdrinterval = gRTDRInterval; @@ -610,6 +670,7 @@ static struct ast_channel *ooh323_request(const char *type, struct ast_format_ca p->g729onlyA = peer->g729onlyA; p->dtmfmode |= peer->dtmfmode; p->dtmfcodec = peer->dtmfcodec; + p->faxdetect = peer->faxdetect; p->t38support = peer->t38support; p->rtptimeout = peer->rtptimeout; p->faststart = peer->faststart; @@ -639,6 +700,7 @@ static struct ast_channel *ooh323_request(const char *type, struct ast_format_ca p->g729onlyA = g729onlyA; p->dtmfmode = gDTMFMode; p->dtmfcodec = gDTMFCodec; + p->faxdetect = gFAXdetect; p->t38support = gT38Support; p->rtptimeout = gRTPTimeout; ast_format_cap_copy(p->cap, gCap); @@ -828,17 +890,7 @@ static int ooh323_digit_begin(struct ast_channel *chan, char digit) } ast_mutex_lock(&p->lock); - - if (digit == 'e' && !p->faxmode && p->t38support != T38_DISABLED) { - if (!p->chmodepend) { - if (gH323Debug) - ast_verbose("request to change %s to t.38 because fax cng\n", - p->callToken); - p->chmodepend = 1; - ooRequestChangeMode(p->callToken, 1); - } - - } else if (p->rtp && ((p->dtmfmode & H323_DTMF_RFC2833) || (p->dtmfmode & H323_DTMF_CISCO))) { + if (p->rtp && ((p->dtmfmode & H323_DTMF_RFC2833) || (p->dtmfmode & H323_DTMF_CISCO))) { ast_rtp_instance_dtmf_begin(p->rtp, digit); } else if (((p->dtmfmode & H323_DTMF_Q931) || (p->dtmfmode & H323_DTMF_H245ALPHANUMERIC) || @@ -1270,27 +1322,50 @@ static int ooh323_indicate(struct ast_channel *ast, int condition, const void *d (int)sizeof(enum ast_control_t38), (int)datalen); } else { const struct ast_control_t38_parameters *parameters = data; + struct ast_control_t38_parameters our_parameters; enum ast_control_t38 message = parameters->request_response; switch (message) { + case AST_T38_NEGOTIATED: + if (p->faxmode) { + res = 0; + break; + } case AST_T38_REQUEST_NEGOTIATE: - if (!p->chmodepend && !p->faxmode) { - ooRequestChangeMode(p->callToken, 1); + if (p->faxmode) { + /* T.38 already negotiated */ + our_parameters.request_response = AST_T38_NEGOTIATED; + our_parameters.max_ifp = ast_udptl_get_far_max_ifp(p->udptl); + our_parameters.rate = AST_T38_RATE_14400; + ast_queue_control_data(p->owner, AST_CONTROL_T38_PARAMETERS, &our_parameters, sizeof(our_parameters)); + } else if (!p->chmodepend) { p->chmodepend = 1; + ooRequestChangeMode(p->callToken, 1); res = 0; } break; case AST_T38_REQUEST_TERMINATE: - if (!p->chmodepend && p->faxmode) { - ooRequestChangeMode(p->callToken, 0); + if (!p->faxmode) { + /* T.38 already terminated */ + our_parameters.request_response = AST_T38_TERMINATED; + ast_queue_control_data(p->owner, AST_CONTROL_T38_PARAMETERS, &our_parameters, sizeof(our_parameters)); + } else if (!p->chmodepend) { p->chmodepend = 1; + ooRequestChangeMode(p->callToken, 0); res = 0; } break; + case AST_T38_REQUEST_PARMS: + our_parameters.request_response = AST_T38_REQUEST_PARMS; + our_parameters.max_ifp = ast_udptl_get_far_max_ifp(p->udptl); + our_parameters.rate = AST_T38_RATE_14400; + ast_queue_control_data(p->owner, AST_CONTROL_T38_PARAMETERS, &our_parameters, sizeof(our_parameters)); + res = AST_T38_REQUEST_PARMS; + break; default: ; @@ -1336,17 +1411,18 @@ static int ooh323_queryoption(struct ast_channel *ast, int option, void *data, i case AST_OPTION_T38_STATE: if (*datalen != sizeof(enum ast_t38_state)) { - ast_log(LOG_ERROR, "Invalid datalen for AST_OPTION_T38_STATE option." + ast_log(LOG_ERROR, "Invalid datalen for AST_OPTION_T38_STATE option." " Expected %d, got %d\n", (int)sizeof(enum ast_t38_state), *datalen); break; } - if (p->t38support != T38_DISABLED) - state = T38_STATE_UNKNOWN; - if (p->faxmode) - state = (p->chmodepend) ? T38_STATE_UNKNOWN : T38_STATE_NEGOTIATED; - else if (p->chmodepend) - state = T38_STATE_NEGOTIATING; + if (p->t38support != T38_DISABLED) { + if (p->faxmode) { + state = (p->chmodepend) ? T38_STATE_NEGOTIATING : T38_STATE_NEGOTIATED; + } else { + state = T38_STATE_UNKNOWN; + } + } *((enum ast_t38_state *) data) = state; res = 0; @@ -1762,6 +1838,7 @@ int ooh323_onReceivedSetup(ooCallData *call, Q931Message *pmsg) memcpy(&p->prefs, &user->prefs, sizeof(struct ast_codec_pref)); p->dtmfmode |= user->dtmfmode; p->dtmfcodec = user->dtmfcodec; + p->faxdetect = user->faxdetect; p->t38support = user->t38support; p->rtptimeout = user->rtptimeout; p->h245tunneling = user->h245tunneling; @@ -2202,6 +2279,7 @@ static struct ooh323_user *build_user(const char *name, struct ast_variable *v) user->rtptimeout = gRTPTimeout; user->dtmfmode = gDTMFMode; user->dtmfcodec = gDTMFCodec; + user->faxdetect = gFAXdetect; user->t38support = gT38Support; user->faststart = gFastStart; user->h245tunneling = gTunneling; @@ -2279,7 +2357,27 @@ static struct ooh323_user *build_user(const char *name, struct ast_variable *v) user->dtmfmode |= ast_true(v->value) ? H323_DTMF_INBANDRELAX : 0; } else if (!strcasecmp(v->name, "dtmfcodec") && atoi(v->value)) { user->dtmfcodec = atoi(v->value); - } else if (!strcasecmp(v->name, "t38support")) { + } else if (!strcasecmp(v->name, "faxdetect")) { + if (ast_true(v->value)) { + user->faxdetect = FAXDETECT_CNG | FAXDETECT_T38; + } else if (ast_false(v->value)) { + user->faxdetect = 0; + } else { + char *buf = ast_strdupa(v->value); + char *word, *next = buf; + user->faxdetect = 0; + while ((word = strsep(&next, ","))) { + if (!strcasecmp(word, "cng")) { + user->faxdetect |= FAXDETECT_CNG; + } else if (!strcasecmp(word, "t38")) { + user->faxdetect |= FAXDETECT_T38; + } else { + ast_log(LOG_WARNING, "Unknown faxdetect mode '%s' on line %d.\n", word, v->lineno); + } + } + + } + } else if (!strcasecmp(v->name, "t38support")) { if (!strcasecmp(v->value, "disabled")) user->t38support = T38_DISABLED; if (!strcasecmp(v->value, "no")) @@ -2322,11 +2420,12 @@ static struct ooh323_peer *build_peer(const char *name, struct ast_variable *v, peer->amaflags = gAMAFLAGS; peer->dtmfmode = gDTMFMode; peer->dtmfcodec = gDTMFCodec; + peer->faxdetect = gFAXdetect; peer->t38support = gT38Support; peer->faststart = gFastStart; peer->h245tunneling = gTunneling; peer->g729onlyA = g729onlyA; - peer->port = 1720; + peer->port = 1720; if (0 == friend_type) { peer->mFriend = 1; } @@ -2426,7 +2525,27 @@ static struct ooh323_peer *build_peer(const char *name, struct ast_variable *v, peer->dtmfmode |= ast_true(v->value) ? H323_DTMF_INBANDRELAX : 0; } else if (!strcasecmp(v->name, "dtmfcodec") && atoi(v->value)) { peer->dtmfcodec = atoi(v->value); - } else if (!strcasecmp(v->name, "t38support")) { + } else if (!strcasecmp(v->name, "faxdetect")) { + if (ast_true(v->value)) { + peer->faxdetect = FAXDETECT_CNG | FAXDETECT_T38; + } else if (ast_false(v->value)) { + peer->faxdetect = 0; + } else { + char *buf = ast_strdupa(v->value); + char *word, *next = buf; + peer->faxdetect = 0; + while ((word = strsep(&next, ","))) { + if (!strcasecmp(word, "cng")) { + peer->faxdetect |= FAXDETECT_CNG; + } else if (!strcasecmp(word, "t38")) { + peer->faxdetect |= FAXDETECT_T38; + } else { + ast_log(LOG_WARNING, "Unknown faxdetect mode '%s' on line %d.\n", word, v->lineno); + } + } + + } + } else if (!strcasecmp(v->name, "t38support")) { if (!strcasecmp(v->value, "disabled")) peer->t38support = T38_DISABLED; if (!strcasecmp(v->value, "no")) @@ -2548,6 +2667,7 @@ int reload_config(int reload) memset(&gPrefs, 0, sizeof(struct ast_codec_pref)); gDTMFMode = H323_DTMF_RFC2833; gDTMFCodec = 101; + gFAXdetect = FAXDETECT_CNG; gT38Support = T38_FAXGW; gTRCLVL = OOTRCLVLERR; gRasGkMode = RasNoGatekeeper; @@ -2751,7 +2871,27 @@ int reload_config(int reload) gDTMFMode |= ast_true(v->value) ? H323_DTMF_INBANDRELAX : 0; } else if (!strcasecmp(v->name, "dtmfcodec") && atoi(v->value)) { gDTMFCodec = atoi(v->value); - } else if (!strcasecmp(v->name, "t38support")) { + } else if (!strcasecmp(v->name, "faxdetect")) { + if (ast_true(v->value)) { + gFAXdetect = FAXDETECT_CNG | FAXDETECT_T38; + } else if (ast_false(v->value)) { + gFAXdetect = 0; + } else { + char *buf = ast_strdupa(v->value); + char *word, *next = buf; + gFAXdetect = 0; + while ((word = strsep(&next, ","))) { + if (!strcasecmp(word, "cng")) { + gFAXdetect |= FAXDETECT_CNG; + } else if (!strcasecmp(word, "t38")) { + gFAXdetect |= FAXDETECT_T38; + } else { + ast_log(LOG_WARNING, "Unknown faxdetect mode '%s' on line %d.\n", word, v->lineno); + } + } + + } + } else if (!strcasecmp(v->name, "t38support")) { if (!strcasecmp(v->value, "disabled")) gT38Support = T38_DISABLED; if (!strcasecmp(v->value, "no")) @@ -2838,14 +2978,13 @@ static char *handle_cli_ooh323_show_peer(struct ast_cli_entry *e, int cmd, struc if (a->argc != 4) return CLI_SHOWUSAGE; - ast_mutex_lock(&peerl.lock); peer = peerl.peers; while (peer) { ast_mutex_lock(&peer->lock); - if(!strcmp(peer->name, a->argv[3])) + if (!strcmp(peer->name, a->argv[3])) { break; - else { + } else { prev = peer; peer = peer->next; ast_mutex_unlock(&prev->lock); @@ -2853,53 +2992,64 @@ static char *handle_cli_ooh323_show_peer(struct ast_cli_entry *e, int cmd, struc } if (peer) { - sprintf(ip_port, "%s:%d", peer->ip, peer->port); - ast_cli(a->fd, "%-15.15s%s\n", "Name: ", peer->name); - ast_cli(a->fd, "%s:%s,%s\n", "FastStart/H.245 Tunneling", peer->faststart?"yes":"no", + sprintf(ip_port, "%s:%d", peer->ip, peer->port); + ast_cli(a->fd, "%-15.15s%s\n", "Name: ", peer->name); + ast_cli(a->fd, "%s:%s,%s\n", "FastStart/H.245 Tunneling", peer->faststart?"yes":"no", peer->h245tunneling?"yes":"no"); - ast_cli(a->fd, "%-15.15s%s", "Format Prefs: ", "("); - print_codec_to_cli(a->fd, &peer->prefs); - ast_cli(a->fd, ")\n"); - ast_cli(a->fd, "%-15.15s", "DTMF Mode: "); + ast_cli(a->fd, "%-15.15s%s", "Format Prefs: ", "("); + print_codec_to_cli(a->fd, &peer->prefs); + ast_cli(a->fd, ")\n"); + ast_cli(a->fd, "%-15.15s", "DTMF Mode: "); if (peer->dtmfmode & H323_DTMF_CISCO) { - ast_cli(a->fd, "%s\n", "cisco"); - ast_cli(a->fd, "%-15.15s%d\n", "DTMF Codec: ", peer->dtmfcodec); + ast_cli(a->fd, "%s\n", "cisco"); + ast_cli(a->fd, "%-15.15s%d\n", "DTMF Codec: ", peer->dtmfcodec); } else if (peer->dtmfmode & H323_DTMF_RFC2833) { - ast_cli(a->fd, "%s\n", "rfc2833"); - ast_cli(a->fd, "%-15.15s%d\n", "DTMF Codec: ", peer->dtmfcodec); - } else if (peer->dtmfmode & H323_DTMF_Q931) - ast_cli(a->fd, "%s\n", "q931keypad"); - else if (peer->dtmfmode & H323_DTMF_H245ALPHANUMERIC) - ast_cli(a->fd, "%s\n", "h245alphanumeric"); - else if (peer->dtmfmode & H323_DTMF_H245SIGNAL) - ast_cli(a->fd, "%s\n", "h245signal"); - else if (peer->dtmfmode & H323_DTMF_INBAND && peer->dtmfmode & H323_DTMF_INBANDRELAX) - ast_cli(a->fd, "%s\n", "inband-relaxed"); - else if (peer->dtmfmode & H323_DTMF_INBAND) - ast_cli(a->fd, "%s\n", "inband"); - else - ast_cli(a->fd, "%s\n", "unknown"); - - ast_cli(a->fd,"%-15s", "T.38 Mode: "); - if (peer->t38support == T38_DISABLED) - ast_cli(a->fd, "%s\n", "disabled"); - else if (peer->t38support == T38_FAXGW) - ast_cli(a->fd, "%s\n", "faxgw/chan_sip compatible"); + ast_cli(a->fd, "%s\n", "rfc2833"); + ast_cli(a->fd, "%-15.15s%d\n", "DTMF Codec: ", peer->dtmfcodec); + } else if (peer->dtmfmode & H323_DTMF_Q931) { + ast_cli(a->fd, "%s\n", "q931keypad"); + } else if (peer->dtmfmode & H323_DTMF_H245ALPHANUMERIC) { + ast_cli(a->fd, "%s\n", "h245alphanumeric"); + } else if (peer->dtmfmode & H323_DTMF_H245SIGNAL) { + ast_cli(a->fd, "%s\n", "h245signal"); + } else if (peer->dtmfmode & H323_DTMF_INBAND && peer->dtmfmode & H323_DTMF_INBANDRELAX) { + ast_cli(a->fd, "%s\n", "inband-relaxed"); + } else if (peer->dtmfmode & H323_DTMF_INBAND) { + ast_cli(a->fd, "%s\n", "inband"); + } else { + ast_cli(a->fd, "%s\n", "unknown"); + } + ast_cli(a->fd,"%-15s", "T.38 Mode: "); + if (peer->t38support == T38_DISABLED) { + ast_cli(a->fd, "%s\n", "disabled"); + } else if (peer->t38support == T38_FAXGW) { + ast_cli(a->fd, "%s\n", "faxgw/chan_sip compatible"); + } + if (peer->faxdetect == (FAXDETECT_CNG | FAXDETECT_T38)) { + ast_cli(a->fd,"%-20s%s\n", "FAX Detect:", "Yes"); + } else if (peer->faxdetect & FAXDETECT_CNG) { + ast_cli(a->fd,"%-20s%s\n", "FAX Detect:", "Cng"); + } else if (peer->faxdetect & FAXDETECT_T38) { + ast_cli(a->fd,"%-20s%s\n", "FAX Detect:", "T.38"); + } else { + ast_cli(a->fd,"%-20s%s\n", "FAX Detect:", "No"); + } - ast_cli(a->fd, "%-15.15s%s\n", "AccountCode: ", peer->accountcode); - ast_cli(a->fd, "%-15.15s%s\n", "AMA flags: ", - ast_cdr_flags2str(peer->amaflags)); - ast_cli(a->fd, "%-15.15s%s\n", "IP:Port: ", ip_port); - ast_cli(a->fd, "%-15.15s%d\n", "OutgoingLimit: ", peer->outgoinglimit); - ast_cli(a->fd, "%-15.15s%d\n", "rtptimeout: ", peer->rtptimeout); - if (peer->rtpmaskstr[0]) - ast_cli(a->fd, "%-15.15s%s\n", "rtpmask: ", peer->rtpmaskstr); - if (peer->rtdrcount && peer->rtdrinterval) - ast_cli(a->fd, "%-15.15s%d,%d\n", "RoundTrip: ", peer->rtdrcount, peer->rtdrinterval); - ast_mutex_unlock(&peer->lock); + ast_cli(a->fd, "%-15.15s%s\n", "AccountCode: ", peer->accountcode); + ast_cli(a->fd, "%-15.15s%s\n", "AMA flags: ", ast_cdr_flags2str(peer->amaflags)); + ast_cli(a->fd, "%-15.15s%s\n", "IP:Port: ", ip_port); + ast_cli(a->fd, "%-15.15s%d\n", "OutgoingLimit: ", peer->outgoinglimit); + ast_cli(a->fd, "%-15.15s%d\n", "rtptimeout: ", peer->rtptimeout); + if (peer->rtpmaskstr[0]) { + ast_cli(a->fd, "%-15.15s%s\n", "rtpmask: ", peer->rtpmaskstr); + } + if (peer->rtdrcount && peer->rtdrinterval) { + ast_cli(a->fd, "%-15.15s%d,%d\n", "RoundTrip: ", peer->rtdrcount, peer->rtdrinterval); + } + ast_mutex_unlock(&peer->lock); } else { - ast_cli(a->fd, "Peer %s not found\n", a->argv[3]); - ast_cli(a->fd, "\n"); + ast_cli(a->fd, "Peer %s not found\n", a->argv[3]); + ast_cli(a->fd, "\n"); } ast_mutex_unlock(&peerl.lock); @@ -2989,9 +3139,9 @@ static char *handle_cli_ooh323_show_user(struct ast_cli_entry *e, int cmd, struc user = userl.users; while (user) { ast_mutex_lock(&user->lock); - if(!strcmp(user->name, a->argv[3])) { + if (!strcmp(user->name, a->argv[3])) { break; - } else { + } else { prev = user; user = user->next; ast_mutex_unlock(&prev->lock); @@ -2999,53 +3149,64 @@ static char *handle_cli_ooh323_show_user(struct ast_cli_entry *e, int cmd, struc } if (user) { - ast_cli(a->fd, "%-15.15s%s\n", "Name: ", user->name); - ast_cli(a->fd, "%s:%s,%s\n", "FastStart/H.245 Tunneling", user->faststart?"yes":"no", + ast_cli(a->fd, "%-15.15s%s\n", "Name: ", user->name); + ast_cli(a->fd, "%s:%s,%s\n", "FastStart/H.245 Tunneling", user->faststart?"yes":"no", user->h245tunneling?"yes":"no"); - ast_cli(a->fd, "%-15.15s%s", "Format Prefs: ", "("); - print_codec_to_cli(a->fd, &user->prefs); - ast_cli(a->fd, ")\n"); - ast_cli(a->fd, "%-15.15s", "DTMF Mode: "); + ast_cli(a->fd, "%-15.15s%s", "Format Prefs: ", "("); + print_codec_to_cli(a->fd, &user->prefs); + ast_cli(a->fd, ")\n"); + ast_cli(a->fd, "%-15.15s", "DTMF Mode: "); if (user->dtmfmode & H323_DTMF_CISCO) { - ast_cli(a->fd, "%s\n", "cisco"); - ast_cli(a->fd, "%-15.15s%d\n", "DTMF Codec: ", user->dtmfcodec); + ast_cli(a->fd, "%s\n", "cisco"); + ast_cli(a->fd, "%-15.15s%d\n", "DTMF Codec: ", user->dtmfcodec); } else if (user->dtmfmode & H323_DTMF_RFC2833) { - ast_cli(a->fd, "%s\n", "rfc2833"); - ast_cli(a->fd, "%-15.15s%d\n", "DTMF Codec: ", user->dtmfcodec); - } else if (user->dtmfmode & H323_DTMF_Q931) - ast_cli(a->fd, "%s\n", "q931keypad"); - else if (user->dtmfmode & H323_DTMF_H245ALPHANUMERIC) - ast_cli(a->fd, "%s\n", "h245alphanumeric"); - else if (user->dtmfmode & H323_DTMF_H245SIGNAL) - ast_cli(a->fd, "%s\n", "h245signal"); - else if (user->dtmfmode & H323_DTMF_INBAND && user->dtmfmode & H323_DTMF_INBANDRELAX) - ast_cli(a->fd, "%s\n", "inband-relaxed"); - else if (user->dtmfmode & H323_DTMF_INBAND) - ast_cli(a->fd, "%s\n", "inband"); - else - ast_cli(a->fd, "%s\n", "unknown"); - - ast_cli(a->fd,"%-15s", "T.38 Mode: "); - if (user->t38support == T38_DISABLED) - ast_cli(a->fd, "%s\n", "disabled"); - else if (user->t38support == T38_FAXGW) - ast_cli(a->fd, "%s\n", "faxgw/chan_sip compatible"); + ast_cli(a->fd, "%s\n", "rfc2833"); + ast_cli(a->fd, "%-15.15s%d\n", "DTMF Codec: ", user->dtmfcodec); + } else if (user->dtmfmode & H323_DTMF_Q931) { + ast_cli(a->fd, "%s\n", "q931keypad"); + } else if (user->dtmfmode & H323_DTMF_H245ALPHANUMERIC) { + ast_cli(a->fd, "%s\n", "h245alphanumeric"); + } else if (user->dtmfmode & H323_DTMF_H245SIGNAL) { + ast_cli(a->fd, "%s\n", "h245signal"); + } else if (user->dtmfmode & H323_DTMF_INBAND && user->dtmfmode & H323_DTMF_INBANDRELAX) { + ast_cli(a->fd, "%s\n", "inband-relaxed"); + } else if (user->dtmfmode & H323_DTMF_INBAND) { + ast_cli(a->fd, "%s\n", "inband"); + } else { + ast_cli(a->fd, "%s\n", "unknown"); + } + ast_cli(a->fd,"%-15s", "T.38 Mode: "); + if (user->t38support == T38_DISABLED) { + ast_cli(a->fd, "%s\n", "disabled"); + } else if (user->t38support == T38_FAXGW) { + ast_cli(a->fd, "%s\n", "faxgw/chan_sip compatible"); + } + if (user->faxdetect == (FAXDETECT_CNG | FAXDETECT_T38)) { + ast_cli(a->fd,"%-20s%s\n", "FAX Detect:", "Yes"); + } else if (user->faxdetect & FAXDETECT_CNG) { + ast_cli(a->fd,"%-20s%s\n", "FAX Detect:", "Cng"); + } else if (user->faxdetect & FAXDETECT_T38) { + ast_cli(a->fd,"%-20s%s\n", "FAX Detect:", "T.38"); + } else { + ast_cli(a->fd,"%-20s%s\n", "FAX Detect:", "No"); + } - ast_cli(a->fd, "%-15.15s%s\n", "AccountCode: ", user->accountcode); - ast_cli(a->fd, "%-15.15s%s\n", "AMA flags: ", - ast_cdr_flags2str(user->amaflags)); - ast_cli(a->fd, "%-15.15s%s\n", "Context: ", user->context); - ast_cli(a->fd, "%-15.15s%d\n", "IncomingLimit: ", user->incominglimit); - ast_cli(a->fd, "%-15.15s%d\n", "InUse: ", user->inUse); - ast_cli(a->fd, "%-15.15s%d\n", "rtptimeout: ", user->rtptimeout); - if (user->rtpmaskstr[0]) - ast_cli(a->fd, "%-15.15s%s\n", "rtpmask: ", user->rtpmaskstr); + ast_cli(a->fd, "%-15.15s%s\n", "AccountCode: ", user->accountcode); + ast_cli(a->fd, "%-15.15s%s\n", "AMA flags: ", ast_cdr_flags2str(user->amaflags)); + ast_cli(a->fd, "%-15.15s%s\n", "Context: ", user->context); + ast_cli(a->fd, "%-15.15s%d\n", "IncomingLimit: ", user->incominglimit); + ast_cli(a->fd, "%-15.15s%d\n", "InUse: ", user->inUse); + ast_cli(a->fd, "%-15.15s%d\n", "rtptimeout: ", user->rtptimeout); + if (user->rtpmaskstr[0]) { + ast_cli(a->fd, "%-15.15s%s\n", "rtpmask: ", user->rtpmaskstr); + } ast_mutex_unlock(&user->lock); - if (user->rtdrcount && user->rtdrinterval) - ast_cli(a->fd, "%-15.15s%d,%d\n", "RoundTrip: ", user->rtdrcount, user->rtdrinterval); + if (user->rtdrcount && user->rtdrinterval) { + ast_cli(a->fd, "%-15.15s%d,%d\n", "RoundTrip: ", user->rtdrcount, user->rtdrinterval); + } } else { - ast_cli(a->fd, "User %s not found\n", a->argv[3]); - ast_cli(a->fd, "\n"); + ast_cli(a->fd, "User %s not found\n", a->argv[3]); + ast_cli(a->fd, "\n"); } ast_mutex_unlock(&userl.lock); @@ -3144,91 +3305,93 @@ static char *handle_cli_ooh323_show_config(struct ast_cli_entry *e, int cmd, str if (a->argc != 3) return CLI_SHOWUSAGE; - - - ast_cli(a->fd, "\nObjective Open H.323 Channel Driver's Config:\n"); + ast_cli(a->fd, "\nObjective Open H.323 Channel Driver's Config:\n"); snprintf(value, sizeof(value), "%s:%d", gIP, gPort); - ast_cli(a->fd, "%-20s%s\n", "IP:Port: ", value); - ast_cli(a->fd, "%-20s%d-%d\n", "H.225 port range: ", - ooconfig.mTCPPortStart, ooconfig.mTCPPortEnd); - ast_cli(a->fd, "%-20s%s\n", "FastStart", gFastStart?"yes":"no"); - ast_cli(a->fd, "%-20s%s\n", "Tunneling", gTunneling?"yes":"no"); - ast_cli(a->fd, "%-20s%s\n", "CallerId", gCallerID); - ast_cli(a->fd, "%-20s%s\n", "MediaWaitForConnect", - gMediaWaitForConnect?"yes":"no"); + ast_cli(a->fd, "%-20s%s\n", "IP:Port: ", value); + ast_cli(a->fd, "%-20s%d-%d\n", "H.225 port range: ", ooconfig.mTCPPortStart, ooconfig.mTCPPortEnd); + ast_cli(a->fd, "%-20s%s\n", "FastStart", gFastStart?"yes":"no"); + ast_cli(a->fd, "%-20s%s\n", "Tunneling", gTunneling?"yes":"no"); + ast_cli(a->fd, "%-20s%s\n", "CallerId", gCallerID); + ast_cli(a->fd, "%-20s%s\n", "MediaWaitForConnect", gMediaWaitForConnect?"yes":"no"); #if (0) extern OOH323EndPoint gH323ep; - ast_cli(a->fd, "%-20s%s\n", "FASTSTART", - (OO_TESTFLAG(gH323ep.flags, OO_M_FASTSTART) != 0) ? "yes" : "no"); - ast_cli(a->fd, "%-20s%s\n", "TUNNELING", - (OO_TESTFLAG(gH323ep.flags, OO_M_TUNNELING) != 0) ? "yes" : "no"); - ast_cli(a->fd, "%-20s%s\n", "MEDIAWAITFORCONN", - (OO_TESTFLAG(gH323ep.flags, OO_M_MEDIAWAITFORCONN) != 0) ? "yes" : "no"); + ast_cli(a->fd, "%-20s%s\n", "FASTSTART", + (OO_TESTFLAG(gH323ep.flags, OO_M_FASTSTART) != 0) ? "yes" : "no"); + ast_cli(a->fd, "%-20s%s\n", "TUNNELING", + (OO_TESTFLAG(gH323ep.flags, OO_M_TUNNELING) != 0) ? "yes" : "no"); + ast_cli(a->fd, "%-20s%s\n", "MEDIAWAITFORCONN", + (OO_TESTFLAG(gH323ep.flags, OO_M_MEDIAWAITFORCONN) != 0) ? "yes" : "no"); #endif - if (gRasGkMode == RasNoGatekeeper) + if (gRasGkMode == RasNoGatekeeper) { snprintf(value, sizeof(value), "%s", "No Gatekeeper"); - else if (gRasGkMode == RasDiscoverGatekeeper) + } else if (gRasGkMode == RasDiscoverGatekeeper) { snprintf(value, sizeof(value), "%s", "Discover"); - else + } else { snprintf(value, sizeof(value), "%s", gGatekeeper); - - ast_cli(a->fd, "%-20s%s\n", "Gatekeeper:", value); - - ast_cli(a->fd, "%-20s%s\n", "H.323 LogFile:", gLogFile); - - ast_cli(a->fd, "%-20s%s\n", "Context:", gContext); - - ast_cli(a->fd, "%-20s%s\n", "Capability:", - ast_getformatname_multiple(value,FORMAT_STRING_SIZE,gCap)); - - ast_cli(a->fd, "%-20s", "DTMF Mode: "); + } + ast_cli(a->fd, "%-20s%s\n", "Gatekeeper:", value); + ast_cli(a->fd, "%-20s%s\n", "H.323 LogFile:", gLogFile); + ast_cli(a->fd, "%-20s%s\n", "Context:", gContext); + ast_cli(a->fd, "%-20s%s\n", "Capability:", + ast_getformatname_multiple(value,FORMAT_STRING_SIZE,gCap)); + ast_cli(a->fd, "%-20s", "DTMF Mode: "); if (gDTMFMode & H323_DTMF_CISCO) { - ast_cli(a->fd, "%s\n", "cisco"); - ast_cli(a->fd, "%-15.15s%d\n", "DTMF Codec: ", gDTMFCodec); + ast_cli(a->fd, "%s\n", "cisco"); + ast_cli(a->fd, "%-20.15s%d\n", "DTMF Codec: ", gDTMFCodec); } else if (gDTMFMode & H323_DTMF_RFC2833) { - ast_cli(a->fd, "%s\n", "rfc2833"); - ast_cli(a->fd, "%-15.15s%d\n", "DTMF Codec: ", gDTMFCodec); - } else if (gDTMFMode & H323_DTMF_Q931) - ast_cli(a->fd, "%s\n", "q931keypad"); - else if (gDTMFMode & H323_DTMF_H245ALPHANUMERIC) - ast_cli(a->fd, "%s\n", "h245alphanumeric"); - else if (gDTMFMode & H323_DTMF_H245SIGNAL) - ast_cli(a->fd, "%s\n", "h245signal"); - else if (gDTMFMode & H323_DTMF_INBAND && gDTMFMode & H323_DTMF_INBANDRELAX) - ast_cli(a->fd, "%s\n", "inband-relaxed"); - else if (gDTMFMode & H323_DTMF_INBAND) - ast_cli(a->fd, "%s\n", "inband"); - else + ast_cli(a->fd, "%s\n", "rfc2833"); + ast_cli(a->fd, "%-20.15s%d\n", "DTMF Codec: ", gDTMFCodec); + } else if (gDTMFMode & H323_DTMF_Q931) { + ast_cli(a->fd, "%s\n", "q931keypad"); + } else if (gDTMFMode & H323_DTMF_H245ALPHANUMERIC) { + ast_cli(a->fd, "%s\n", "h245alphanumeric"); + } else if (gDTMFMode & H323_DTMF_H245SIGNAL) { + ast_cli(a->fd, "%s\n", "h245signal"); + } else if (gDTMFMode & H323_DTMF_INBAND && gDTMFMode & H323_DTMF_INBANDRELAX) { + ast_cli(a->fd, "%s\n", "inband-relaxed"); + } else if (gDTMFMode & H323_DTMF_INBAND) { + ast_cli(a->fd, "%s\n", "inband"); + } else { ast_cli(a->fd, "%s\n", "unknown"); + } - ast_cli(a->fd,"%-20s", "T.38 Mode: "); - if (gT38Support == T38_DISABLED) + ast_cli(a->fd,"%-20s", "T.38 Mode: "); + if (gT38Support == T38_DISABLED) { ast_cli(a->fd, "%s\n", "disabled"); - else if (gT38Support == T38_FAXGW) + } else if (gT38Support == T38_FAXGW) { ast_cli(a->fd, "%s\n", "faxgw/chan_sip compatible"); + } + if (gFAXdetect == (FAXDETECT_CNG | FAXDETECT_T38)) { + ast_cli(a->fd,"%-20s%s\n", "FAX Detect:", "Yes"); + } else if (gFAXdetect & FAXDETECT_CNG) { + ast_cli(a->fd,"%-20s%s\n", "FAX Detect:", "Cng"); + } else if (gFAXdetect & FAXDETECT_T38) { + ast_cli(a->fd,"%-20s%s\n", "FAX Detect:", "T.38"); + } else { + ast_cli(a->fd,"%-20s%s\n", "FAX Detect:", "No"); + } - if (gRTDRCount && gRTDRInterval) - ast_cli(a->fd, "%-15.15s%d,%d\n", "RoundTrip: ", gRTDRCount, gRTDRInterval); - - ast_cli(a->fd, "%-20s%ld\n", "Call counter: ", callnumber); - ast_cli(a->fd, "%-20s%s\n", "AccountCode: ", gAccountcode); + if (gRTDRCount && gRTDRInterval) { + ast_cli(a->fd, "%-20.15s%d,%d\n", "RoundTrip: ", gRTDRCount, gRTDRInterval); + } - ast_cli(a->fd, "%-20s%s\n", "AMA flags: ", ast_cdr_flags2str(gAMAFLAGS)); + ast_cli(a->fd, "%-20s%ld\n", "Call counter: ", callnumber); + ast_cli(a->fd, "%-20s%s\n", "AccountCode: ", gAccountcode); + ast_cli(a->fd, "%-20s%s\n", "AMA flags: ", ast_cdr_flags2str(gAMAFLAGS)); pAlias = gAliasList; - if(pAlias) { - ast_cli(a->fd, "%-20s\n", "Aliases: "); - } + if(pAlias) { + ast_cli(a->fd, "%-20s\n", "Aliases: "); + } while (pAlias) { pAliasNext = pAlias->next; if (pAliasNext) { - ast_cli(a->fd,"\t%-30s\t%-30s\n",pAlias->value, pAliasNext->value); + ast_cli(a->fd,"\t%-30s\t%-30s\n",pAlias->value, pAliasNext->value); pAlias = pAliasNext->next; - } - else{ - ast_cli(a->fd,"\t%-30s\n",pAlias->value); + } else { + ast_cli(a->fd,"\t%-30s\n",pAlias->value); pAlias = pAlias->next; } } @@ -3245,6 +3408,115 @@ static struct ast_cli_entry cli_ooh323[] = { AST_CLI_DEFINE(handle_cli_ooh323_reload, "reload ooh323 config") }; +/*! \brief OOH323 Dialplan function - reads ooh323 settings */ +static int function_ooh323_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) +{ + struct ooh323_pvt *p = chan->tech_pvt; + + ast_channel_lock(chan); + if (!p) { + ast_channel_unlock(chan); + return -1; + } + + if (strcmp(chan->tech->type, "OOH323")) { + ast_log(LOG_ERROR, "This function is only supported on OOH323 channels, Channel is %s\n", chan->tech->type); + ast_channel_unlock(chan); + return -1; + } + + ast_mutex_lock(&p->lock); + if (!strcasecmp(data, "faxdetect")) { + ast_copy_string(buf, p->faxdetect ? "1" : "0", len); + } else if (!strcasecmp(data, "t38support")) { + ast_copy_string(buf, p->t38support ? "1" : "0", len); + } else if (!strcasecmp(data, "caller_h323id")) { + ast_copy_string(buf, p->caller_h323id, len); + } else if (!strcasecmp(data, "caller_dialeddigits")) { + ast_copy_string(buf, p->caller_dialedDigits, len); + } else if (!strcasecmp(data, "caller_email")) { + ast_copy_string(buf, p->caller_email, len); + } else if (!strcasecmp(data, "h323id_url")) { + ast_copy_string(buf, p->caller_url, len); + } else if (!strcasecmp(data, "callee_h323id")) { + ast_copy_string(buf, p->callee_h323id, len); + } else if (!strcasecmp(data, "callee_dialeddigits")) { + ast_copy_string(buf, p->callee_dialedDigits, len); + } else if (!strcasecmp(data, "callee_email")) { + ast_copy_string(buf, p->callee_email, len); + } else if (!strcasecmp(data, "callee_url")) { + ast_copy_string(buf, p->callee_url, len); + } + ast_mutex_unlock(&p->lock); + + ast_channel_unlock(chan); + return 0; +} + +/*! \brief OOH323 Dialplan function - writes ooh323 settings */ +static int function_ooh323_write(struct ast_channel *chan, const char *cmd, char *data, const char *value) +{ + struct ooh323_pvt *p = chan->tech_pvt; + int res = -1; + + ast_channel_lock(chan); + if (!p) { + ast_channel_unlock(chan); + return -1; + } + + if (strcmp(chan->tech->type, "OOH323")) { + ast_log(LOG_ERROR, "This function is only supported on OOH323 channels, Channel is %s\n", chan->tech->type); + ast_channel_unlock(chan); + return -1; + } + + ast_mutex_lock(&p->lock); + if (!strcasecmp(data, "faxdetect")) { + if (ast_true(value)) { + p->faxdetect = 1; + res = 0; + } else if (ast_false(value)) { + p->faxdetect = 0; + res = 0; + } else { + char *buf = ast_strdupa(value); + char *word, *next = buf; + p->faxdetect = 0; + res = 0; + while ((word = strsep(&next, ","))) { + if (!strcasecmp(word, "cng")) { + p->faxdetect |= FAXDETECT_CNG; + } else if (!strcasecmp(word, "t38")) { + p->faxdetect |= FAXDETECT_T38; + } else { + ast_log(LOG_WARNING, "Unknown faxdetect mode '%s'.\n", word); + res = -1; + } + } + + } + } else if (!strcasecmp(data, "t38support")) { + if (ast_true(value)) { + p->t38support = 1; + res = 0; + } else { + p->t38support = 0; + res = 0; + } + } + ast_mutex_unlock(&p->lock); + ast_channel_unlock(chan); + + return res; +} + +/*! \brief Structure to declare a dialplan function: OOH323 */ +static struct ast_custom_function ooh323_function = { + .name = "OOH323", + .read = function_ooh323_read, + .write = function_ooh323_write, +}; static int load_module(void) { @@ -3414,6 +3686,9 @@ static int load_module(void) restart_monitor(); } + /* Register dialplan functions */ + ast_custom_function_register(&ooh323_function); + return 0; } @@ -3689,7 +3964,7 @@ int delete_users() ast_mutex_unlock(&userl.lock); return 0; } - + static int unload_module(void) { struct ooh323_pvt *p; @@ -3804,8 +4079,11 @@ static int unload_module(void) } ooH323EpDestroy(); + /* Unregister dial plan functions */ + ast_custom_function_unregister(&ooh323_function); + if (gH323Debug) { - ast_verbose("+++ ooh323 unload_module \n"); + ast_verbose("+++ ooh323 unload_module \n"); } gCap = ast_format_cap_destroy(gCap); @@ -4310,6 +4588,7 @@ struct ast_frame *ooh323_rtp_read(struct ast_channel *ast, struct ooh323_pvt *p) { /* Retrieve audio/etc from channel. Assumes p->lock is already held. */ struct ast_frame *f; + struct ast_frame *dfr = NULL; static struct ast_frame null_frame = { AST_FRAME_NULL, }; switch (ast->fdno) { case 0: @@ -4336,25 +4615,59 @@ struct ast_frame *ooh323_rtp_read(struct ast_channel *ast, struct ooh323_pvt *p) f = &null_frame; } - if (p->owner) { + if (p->owner && !p->faxmode && (f->frametype == AST_FRAME_VOICE)) { /* We already hold the channel lock */ - if (f->frametype == AST_FRAME_VOICE && !p->faxmode) { - if (!(ast_format_cap_iscompatible(p->owner->nativeformats, &f->subclass.format))) { - ast_debug(1, "Oooh, voice format changed to %s\n", ast_getformatname(&f->subclass.format)); - ast_format_cap_set(p->owner->nativeformats, &f->subclass.format); - ast_set_read_format(p->owner, &p->owner->readformat); - ast_set_write_format(p->owner, &p->owner->writeformat); - } + if (!(ast_format_cap_iscompatible(p->owner->nativeformats, &f->subclass.format))) { + ast_debug(1, "Oooh, voice format changed to %s\n", ast_getformatname(&f->subclass.format)); + ast_format_cap_set(p->owner->nativeformats, &f->subclass.format); + ast_set_read_format(p->owner, &p->owner->readformat); + ast_set_write_format(p->owner, &p->owner->writeformat); + } + if (((p->dtmfmode & H323_DTMF_INBAND) || (p->faxdetect & FAXDETECT_CNG)) && p->vad && + (f->subclass.format.id == AST_FORMAT_SLINEAR || f->subclass.format.id == AST_FORMAT_ALAW || + f->subclass.format.id == AST_FORMAT_ULAW)) { + dfr = ast_frdup(f); + dfr = ast_dsp_process(p->owner, p->vad, dfr); + } + } else { + return f; + } - if ((p->dtmfmode & H323_DTMF_INBAND) && p->vad && - (f->subclass.format.id == AST_FORMAT_SLINEAR || f->subclass.format.id == AST_FORMAT_ALAW || - f->subclass.format.id == AST_FORMAT_ULAW)) { - f = ast_dsp_process(p->owner, p->vad, f); - if (f && (f->frametype == AST_FRAME_DTMF)) { - ast_debug(1, "* Detected inband DTMF '%c'\n", f->subclass.integer); + /* process INBAND DTMF*/ + if (dfr && (dfr->frametype == AST_FRAME_DTMF) && ((dfr->subclass.integer == 'f') || (dfr->subclass.integer == 'e'))) { + ast_debug(1, "* Detected FAX Tone %s\n", (dfr->subclass.integer == 'e') ? "CED" : "CNG"); + /* Switch to T.38 ON CED*/ + if (!p->faxmode && !p->chmodepend && (dfr->subclass.integer == 'e') && (p->t38support != T38_DISABLED)) { + if (gH323Debug) + ast_verbose("request to change %s to t.38 because fax ced\n", p->callToken); + p->chmodepend = 1; + p->faxdetected = 1; + ooRequestChangeMode(p->callToken, 1); + } else if ((dfr->subclass.integer == 'f') && !p->faxdetected) { + const char *target_context = S_OR(p->owner->macrocontext, p->owner->context); + if ((strcmp(p->owner->exten, "fax")) && + (ast_exists_extension(p->owner, target_context, "fax", 1, + S_COR(p->owner->caller.id.number.valid, p->owner->caller.id.number.str, NULL)))) { + ast_verb(2, "Redirecting '%s' to fax extension due to CNG detection\n", p->owner->name); + pbx_builtin_setvar_helper(p->owner, "FAXEXTEN", p->owner->exten); + if (ast_async_goto(p->owner, target_context, "fax", 1)) { + ast_log(LOG_NOTICE, "Failed to async goto '%s' into fax of '%s'\n", p->owner->name,target_context); + } + p->faxdetected = 1; + if (dfr) { + ast_frfree(dfr); } + return &ast_null_frame; } } + } else if (dfr && dfr->frametype == AST_FRAME_DTMF) { + ast_debug(1, "* Detected inband DTMF '%c'\n", f->subclass.integer); + ast_frfree(f); + return dfr; + } + + if (dfr) { + ast_frfree(dfr); } return f; } @@ -4377,6 +4690,7 @@ void onModeChanged(ooCallData *call, int t38mode) { if (gH323Debug) ast_debug(1, "mode for %s is already %d\n", call->callToken, t38mode); + p->chmodepend = 0; ast_mutex_unlock(&p->lock); return; } @@ -4387,11 +4701,13 @@ void onModeChanged(ooCallData *call, int t38mode) { DEADLOCK_AVOIDANCE(&p->lock); } if (!p->owner) { + p->chmodepend = 0; ast_mutex_unlock(&p->lock); ast_log(LOG_ERROR, "Channel has no owner\n"); return; } } else { + p->chmodepend = 0; ast_mutex_unlock(&p->lock); ast_log(LOG_ERROR, "Channel has no owner\n"); return; @@ -4401,10 +4717,26 @@ void onModeChanged(ooCallData *call, int t38mode) { if (p->t38support == T38_ENABLED) { + struct ast_control_t38_parameters parameters = { .request_response = 0 }; + + if ((p->faxdetect & FAXDETECT_T38) && !p->faxdetected) { + const char *target_context; + ast_debug(1, "* Detected T.38 Request\n"); + target_context = S_OR(p->owner->macrocontext, p->owner->context); + if ((strcmp(p->owner->exten, "fax")) && + (ast_exists_extension(p->owner, target_context, "fax", 1, + S_COR(p->owner->caller.id.number.valid, p->owner->caller.id.number.str, NULL)))) { + ast_verb(2, "Redirecting '%s' to fax extension due to CNG detection\n", p->owner->name); + pbx_builtin_setvar_helper(p->owner, "FAXEXTEN", p->owner->exten); + if (ast_async_goto(p->owner, target_context, "fax", 1)) { + ast_log(LOG_NOTICE, "Failed to async goto '%s' into fax of '%s'\n", p->owner->name,target_context); + } + } + p->faxdetected = 1; + } /* AST_T38_CONTROL mode */ - struct ast_control_t38_parameters parameters = { .request_response = 0 }; parameters.request_response = AST_T38_REQUEST_NEGOTIATE; if (call->T38FarMaxDatagram) { ast_udptl_set_far_max_datagram(p->udptl, call->T38FarMaxDatagram); @@ -4420,6 +4752,7 @@ void onModeChanged(ooCallData *call, int t38mode) { ¶meters, sizeof(parameters)); p->faxmode = 1; + } } else { if (p->t38support == T38_ENABLED) { @@ -4431,6 +4764,7 @@ void onModeChanged(ooCallData *call, int t38mode) { ¶meters, sizeof(parameters)); } p->faxmode = 0; + p->faxdetected = 0; p->t38_init = 0; } diff --git a/configs/chan_ooh323.conf.sample b/configs/chan_ooh323.conf.sample index 8dbdafc73..20ccf73ec 100644 --- a/configs/chan_ooh323.conf.sample +++ b/configs/chan_ooh323.conf.sample @@ -122,6 +122,18 @@ dtmfmode=rfc2833 ; ;roundtrip=x,y +; +; FAX detection will cause the OOH323 channel to jump to the 'fax' extension (if it exists) +; based one or more events being detected. The events that can be detected are an incoming +; CNG tone or an incoming T.38 RequestMode packet +; +; yes - enable both detection (CNG & T.38) +; no - disable both +; cng - enable CNG detection (default) +; t38 - enable T.38 request detection +; +faxdetect = cng + ; User/peer/friend definitions: ; User config options Peer config options ; ------------------ ------------------- -- cgit v1.2.3 From 4788d10f12b1c122efbf7bc9561d0e580d3464de Mon Sep 17 00:00:00 2001 From: tzafrir Date: Mon, 11 Jul 2011 10:57:26 +0000 Subject: Merged revisions 327411 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ........ r327411 | tzafrir | 2011-07-11 13:46:34 +0300 (ב', 11 יול 2011) | 5 lines fix building the Debian armhf (HardFloat) port Fixes http://buildd.debian-ports.org/status/fetch.php?pkg=asterisk&arch=armhf&ver=1%3A1.8.4.4~dfsg-2&stamp=1309935385 (Missing pthreads) ........ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@327413 f38db490-d61c-443f-a65b-d21fe96a405b --- main/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/Makefile b/main/Makefile index 0b37aa3ef..9533163e3 100644 --- a/main/Makefile +++ b/main/Makefile @@ -35,7 +35,7 @@ AST_LIBS += $(BKTR_LIB) AST_LIBS += $(LIBXML2_LIB) AST_LIBS += $(SQLITE3_LIB) -ifneq ($(findstring $(OSARCH), linux-gnu uclinux linux-uclibc linux-gnueabi kfreebsd-gnu),) +ifneq ($(findstring $(OSARCH), linux-gnu uclinux linux-uclibc linux-gnueabi kfreebsd-gnu linux-gnueabihf),) ifneq ($(findstring LOADABLE_MODULES,$(MENUSELECT_CFLAGS)),) AST_LIBS+=-ldl endif -- cgit v1.2.3 From fdee0340a69817e159e22a01f5ce9a3590f0313a Mon Sep 17 00:00:00 2001 From: mnicholson Date: Mon, 11 Jul 2011 12:58:50 +0000 Subject: fixed wording in a comment git-svn-id: http://svn.digium.com/svn/asterisk/trunk@327469 f38db490-d61c-443f-a65b-d21fe96a405b --- res/res_fax.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/res_fax.c b/res/res_fax.c index 431e7086a..06b39e05c 100644 --- a/res/res_fax.c +++ b/res/res_fax.c @@ -2925,7 +2925,7 @@ static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct /* in gateway mode, gateway some packets */ if (gateway->t38_state == T38_STATE_NEGOTIATED) { /* framehooks are called in __ast_read() before frame format - * translation is does, so we need to translate here */ + * translation is done, so we need to translate here */ if ((f->frametype == AST_FRAME_VOICE) && (f->subclass.format.id != AST_FORMAT_SLINEAR)) { if (active->readtrans && (f = ast_translate(active->readtrans, f, 1)) == NULL) { f = &ast_null_frame; -- cgit v1.2.3 From 30177298c63c914a1180aef905305b2a570453b1 Mon Sep 17 00:00:00 2001 From: mnicholson Date: Mon, 11 Jul 2011 13:29:13 +0000 Subject: Delay sending an CED tone generated T.38 reinvite to give the CED tone generating party time to send its own T.38 reinvite. Also don't forward frames through the gateway if we are negotiating T.38. git-svn-id: http://svn.digium.com/svn/asterisk/trunk@327511 f38db490-d61c-443f-a65b-d21fe96a405b --- res/res_fax.c | 105 ++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 72 insertions(+), 33 deletions(-) diff --git a/res/res_fax.c b/res/res_fax.c index 06b39e05c..5202e6323 100644 --- a/res/res_fax.c +++ b/res/res_fax.c @@ -246,6 +246,8 @@ struct fax_gateway { struct ast_fax_tech_token *token; /*! \brief the start of our timeout counter */ struct timeval timeout_start; + /*! \brief the start of our ced timeout */ + struct timeval ced_timeout_start; /*! \brief DSP Processor */ struct ast_dsp *chan_dsp; struct ast_dsp *peer_dsp; @@ -253,6 +255,8 @@ struct fax_gateway { int framehook; /*! \brief bridged */ int bridged:1; + /*! \brief 1 if the ced tone came from chan, 0 if it came from peer */ + int ced_chan:1; /*! \brief a flag to track the state of our negotiation */ enum ast_t38_state t38_state; /*! \brief original audio formats */ @@ -269,6 +273,7 @@ static int fax_logger_level = -1; #define RES_FAX_TIMEOUT 10000 #define FAX_GATEWAY_TIMEOUT RES_FAX_TIMEOUT +#define FAX_GATEWAY_CED_TIMEOUT 3000 /*! \brief The faxregistry is used to manage information and statistics for all FAX sessions. */ static struct { @@ -2465,6 +2470,46 @@ static int fax_gateway_start(struct fax_gateway *gateway, struct ast_fax_session return 0; } +static struct ast_frame *fax_gateway_send_ced(struct fax_gateway *gateway, struct ast_channel *chan, struct ast_frame *f) +{ + struct ast_frame *fp; + struct ast_control_t38_parameters t38_parameters = { + .request_response = AST_T38_REQUEST_NEGOTIATE, + }; + struct ast_frame control_frame = { + .src = "res_fax", + .frametype = AST_FRAME_CONTROL, + .datalen = sizeof(t38_parameters), + .subclass.integer = AST_CONTROL_T38_PARAMETERS, + .data.ptr = &t38_parameters, + }; + + struct ast_fax_session_details *details = find_details(chan); + + if (!details) { + ast_log(LOG_ERROR, "no FAX session details found on chan %s for T.38 gateway session, odd\n", chan->name); + ast_framehook_detach(chan, gateway->framehook); + return f; + } + + t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters); + ao2_ref(details, -1); + + if (!(fp = ast_frisolate(&control_frame))) { + ast_log(LOG_ERROR, "error generating T.38 request control frame on chan %s for T.38 gateway session\n", chan->name); + return f; + } + + gateway->t38_state = T38_STATE_NEGOTIATING; + gateway->timeout_start = ast_tvnow(); + + gateway->ced_timeout_start.tv_sec = 0; + gateway->ced_timeout_start.tv_usec = 0; + + ast_debug(1, "detected CED tone; requesting T.38 for gateway session for %s\n", chan->name); + return fp; +} + static struct ast_frame *fax_gateway_detect_ced(struct fax_gateway *gateway, struct ast_channel *chan, struct ast_channel *peer, struct ast_channel *active, struct ast_frame *f) { struct ast_frame *dfr = ast_frdup(f); @@ -2480,40 +2525,13 @@ static struct ast_frame *fax_gateway_detect_ced(struct fax_gateway *gateway, str } if (dfr->frametype == AST_FRAME_DTMF && dfr->subclass.integer == 'e') { - if (ast_channel_get_t38_state(other) == T38_STATE_UNKNOWN) { - struct ast_control_t38_parameters t38_parameters = { - .request_response = AST_T38_REQUEST_NEGOTIATE, - }; - struct ast_frame control_frame = { - .src = "res_fax", - .frametype = AST_FRAME_CONTROL, - .datalen = sizeof(t38_parameters), - .subclass.integer = AST_CONTROL_T38_PARAMETERS, - .data.ptr = &t38_parameters, - }; - - struct ast_fax_session_details *details = find_details(chan); - ast_frfree(dfr); - - if (!details) { - ast_log(LOG_ERROR, "no FAX session details found on chan %s for T.38 gateway session, odd\n", chan->name); - ast_framehook_detach(chan, gateway->framehook); - return f; - } - - t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters); - ao2_ref(details, -1); - - if (!(dfr = ast_frisolate(&control_frame))) { - ast_log(LOG_ERROR, "error generating T.38 request control frame on chan %s for T.38 gateway session\n", chan->name); - return f; + if (ast_channel_get_t38_state(other) == T38_STATE_UNKNOWN && ast_tvzero(gateway->ced_timeout_start)) { + if (ast_channel_get_t38_state(active) == T38_STATE_UNKNOWN) { + gateway->ced_timeout_start = ast_tvnow(); + gateway->ced_chan = (active == chan); + } else { + return fax_gateway_send_ced(gateway, chan, f); } - - gateway->t38_state = T38_STATE_NEGOTIATING; - gateway->timeout_start = ast_tvnow(); - - ast_debug(1, "detected CED tone on %s, requesting T.38 on %s for T.38 gateway session\n", active->name, other->name); - return dfr; } else { ast_debug(1, "detected CED tone on %s, but %s does not support T.38 for T.38 gateway session\n", active->name, other->name); } @@ -2568,6 +2586,10 @@ static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, str if (control_params->request_response == AST_T38_REQUEST_NEGOTIATE) { enum ast_t38_state state = ast_channel_get_t38_state(other); + + gateway->ced_timeout_start.tv_sec = 0; + gateway->ced_timeout_start.tv_usec = 0; + if (state == T38_STATE_UNKNOWN) { /* we detected a request to negotiate T.38 and the * other channel appears to support T.38, we'll pass @@ -2922,6 +2944,17 @@ static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct return fax_gateway_detect_ced(gateway, chan, peer, active, f); } + /* handle the ced timeout delay */ + if (!ast_tvzero(gateway->ced_timeout_start)) { + if (ast_tvdiff_ms(ast_tvnow(), gateway->ced_timeout_start) > FAX_GATEWAY_CED_TIMEOUT) { + if (gateway->ced_chan && chan == active) { + return fax_gateway_send_ced(gateway, chan, f); + } else if (!gateway->ced_chan && peer == active) { + return fax_gateway_send_ced(gateway, chan, f); + } + } + } + /* in gateway mode, gateway some packets */ if (gateway->t38_state == T38_STATE_NEGOTIATED) { /* framehooks are called in __ast_read() before frame format @@ -2942,6 +2975,12 @@ static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct return f; } + /* force silence on the line if T.38 negotiation might be taking place */ + if (!ast_tvzero(gateway->ced_timeout_start) || (gateway->t38_state != T38_STATE_UNAVAILABLE && gateway->t38_state != T38_STATE_REJECTED)) { + /* XXX may need to return a silence frame here */ + return &ast_null_frame; + } + return f; } -- cgit v1.2.3 From 959deafb08b36e7a7ee52493e048c751b646dc9b Mon Sep 17 00:00:00 2001 From: mnicholson Date: Mon, 11 Jul 2011 13:55:28 +0000 Subject: Merged revisions 327512 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.8 ........ r327512 | mnicholson | 2011-07-11 08:53:59 -0500 (Mon, 11 Jul 2011) | 2 lines reset our buffer each iteration when doing variable substitution ........ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@327513 f38db490-d61c-443f-a65b-d21fe96a405b --- main/pbx.c | 3 +++ tests/test_substitution.c | 1 + 2 files changed, 4 insertions(+) diff --git a/main/pbx.c b/main/pbx.c index 3cb9affeb..e625a873a 100644 --- a/main/pbx.c +++ b/main/pbx.c @@ -3732,6 +3732,9 @@ void ast_str_substitute_variables_full(struct ast_str **buf, ssize_t maxlen, str ast_str_reset(*buf); whereweare = tmp = templ; while (!ast_strlen_zero(whereweare)) { + /* reset our buffer */ + ast_str_reset(substr3); + /* Assume we're copying the whole remaining string */ pos = strlen(whereweare); nextvar = NULL; diff --git a/tests/test_substitution.c b/tests/test_substitution.c index 98e1ed191..366b9371c 100644 --- a/tests/test_substitution.c +++ b/tests/test_substitution.c @@ -263,6 +263,7 @@ AST_TEST_DEFINE(test_substitution) TEST(test_expected_result(test, c, "${LISTFILTER(list1,&,cd)}", "ab&ef")); TEST(test_expected_result(test, c, "${SHELL(echo -n 123)},${SHELL(echo -n 456)}", "123,456")); TEST(test_expected_result(test, c, "${foo},${CDR(answer)},${SHELL(echo -n 456)}", "123,,456")); + TEST(test_expected_result(test, c, "${foo},${this_does_not_exist},${THIS_DOES_NOT_EXIST(either)}", "123,,")); #undef TEST /* For testing dialplan functions */ -- cgit v1.2.3 From 9374cf84f9beb1adb4daa1a8cebe4cb6dc7f5c51 Mon Sep 17 00:00:00 2001 From: mnicholson Date: Mon, 11 Jul 2011 14:13:24 +0000 Subject: write silence on the channel during t.38 negotiation git-svn-id: http://svn.digium.com/svn/asterisk/trunk@327514 f38db490-d61c-443f-a65b-d21fe96a405b --- res/res_fax.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/res/res_fax.c b/res/res_fax.c index 5202e6323..2b3fec194 100644 --- a/res/res_fax.c +++ b/res/res_fax.c @@ -2977,8 +2977,21 @@ static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct /* force silence on the line if T.38 negotiation might be taking place */ if (!ast_tvzero(gateway->ced_timeout_start) || (gateway->t38_state != T38_STATE_UNAVAILABLE && gateway->t38_state != T38_STATE_REJECTED)) { - /* XXX may need to return a silence frame here */ - return &ast_null_frame; + if (f->frametype == AST_FRAME_VOICE && f->subclass.format.id == AST_FORMAT_SLINEAR) { + short silence_buf[f->samples]; + struct ast_frame silence_frame = { + .frametype = AST_FRAME_VOICE, + .data.ptr = silence_buf, + .samples = f->samples, + .datalen = sizeof(silence_buf), + }; + ast_format_set(&silence_frame.subclass.format, AST_FORMAT_SLINEAR, 0); + memset(silence_buf, 0, sizeof(silence_buf)); + + return ast_frisolate(&silence_frame); + } else { + return &ast_null_frame; + } } return f; -- cgit v1.2.3 From f14aa92f10bec4a05b4a92d4c30a8b946896a105 Mon Sep 17 00:00:00 2001 From: mnicholson Date: Mon, 11 Jul 2011 16:27:08 +0000 Subject: actually do something with the ced timeout, also added more debug output git-svn-id: http://svn.digium.com/svn/asterisk/trunk@327570 f38db490-d61c-443f-a65b-d21fe96a405b --- res/res_fax.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/res/res_fax.c b/res/res_fax.c index 2b3fec194..7cbcaa8b7 100644 --- a/res/res_fax.c +++ b/res/res_fax.c @@ -2516,6 +2516,11 @@ static struct ast_frame *fax_gateway_detect_ced(struct fax_gateway *gateway, str struct ast_dsp *active_dsp = (active == chan) ? gateway->chan_dsp : gateway->peer_dsp; struct ast_channel *other = (active == chan) ? peer : chan; + /* if we have already detected a CED tone, don't waste time here */ + if (!ast_tvzero(gateway->ced_timeout_start)) { + return f; + } + if (!dfr) { return f; } @@ -2525,10 +2530,11 @@ static struct ast_frame *fax_gateway_detect_ced(struct fax_gateway *gateway, str } if (dfr->frametype == AST_FRAME_DTMF && dfr->subclass.integer == 'e') { - if (ast_channel_get_t38_state(other) == T38_STATE_UNKNOWN && ast_tvzero(gateway->ced_timeout_start)) { + if (ast_channel_get_t38_state(other) == T38_STATE_UNKNOWN) { if (ast_channel_get_t38_state(active) == T38_STATE_UNKNOWN) { gateway->ced_timeout_start = ast_tvnow(); gateway->ced_chan = (active == chan); + ast_debug(1, "detected CED tone from %s; will schedule T.38 request on %s\n", active->name, other->name); } else { return fax_gateway_send_ced(gateway, chan, f); } @@ -2938,12 +2944,6 @@ static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct return fax_gateway_detect_t38(gateway, chan, peer, active, f); } - /* not in gateway mode yet, listen for CED */ - /* XXX this should detect a v21 preamble instead of CED */ - if (gateway->t38_state == T38_STATE_UNAVAILABLE && f->frametype == AST_FRAME_VOICE) { - return fax_gateway_detect_ced(gateway, chan, peer, active, f); - } - /* handle the ced timeout delay */ if (!ast_tvzero(gateway->ced_timeout_start)) { if (ast_tvdiff_ms(ast_tvnow(), gateway->ced_timeout_start) > FAX_GATEWAY_CED_TIMEOUT) { @@ -2953,6 +2953,11 @@ static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct return fax_gateway_send_ced(gateway, chan, f); } } + } else if (gateway->t38_state == T38_STATE_UNAVAILABLE && f->frametype == AST_FRAME_VOICE) { + /* not in gateway mode and have not detected CED yet, listen + * for CED */ + /* XXX this should detect a v21 preamble instead of CED */ + return fax_gateway_detect_ced(gateway, chan, peer, active, f); } /* in gateway mode, gateway some packets */ -- cgit v1.2.3 From 2b37cbc87b7954dac455b48260fe9eaf07305640 Mon Sep 17 00:00:00 2001 From: mnicholson Date: Mon, 11 Jul 2011 17:23:54 +0000 Subject: renamed fax_gateway_send_ced() to fax_gateway_request_t38() git-svn-id: http://svn.digium.com/svn/asterisk/trunk@327598 f38db490-d61c-443f-a65b-d21fe96a405b --- res/res_fax.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/res/res_fax.c b/res/res_fax.c index 7cbcaa8b7..18f3fa133 100644 --- a/res/res_fax.c +++ b/res/res_fax.c @@ -2470,7 +2470,7 @@ static int fax_gateway_start(struct fax_gateway *gateway, struct ast_fax_session return 0; } -static struct ast_frame *fax_gateway_send_ced(struct fax_gateway *gateway, struct ast_channel *chan, struct ast_frame *f) +static struct ast_frame *fax_gateway_request_t38(struct fax_gateway *gateway, struct ast_channel *chan, struct ast_frame *f) { struct ast_frame *fp; struct ast_control_t38_parameters t38_parameters = { @@ -2506,7 +2506,7 @@ static struct ast_frame *fax_gateway_send_ced(struct fax_gateway *gateway, struc gateway->ced_timeout_start.tv_sec = 0; gateway->ced_timeout_start.tv_usec = 0; - ast_debug(1, "detected CED tone; requesting T.38 for gateway session for %s\n", chan->name); + ast_debug(1, "requesting T.38 for gateway session for %s\n", chan->name); return fp; } @@ -2536,7 +2536,7 @@ static struct ast_frame *fax_gateway_detect_ced(struct fax_gateway *gateway, str gateway->ced_chan = (active == chan); ast_debug(1, "detected CED tone from %s; will schedule T.38 request on %s\n", active->name, other->name); } else { - return fax_gateway_send_ced(gateway, chan, f); + return fax_gateway_request_t38(gateway, chan, f); } } else { ast_debug(1, "detected CED tone on %s, but %s does not support T.38 for T.38 gateway session\n", active->name, other->name); @@ -2948,9 +2948,9 @@ static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct if (!ast_tvzero(gateway->ced_timeout_start)) { if (ast_tvdiff_ms(ast_tvnow(), gateway->ced_timeout_start) > FAX_GATEWAY_CED_TIMEOUT) { if (gateway->ced_chan && chan == active) { - return fax_gateway_send_ced(gateway, chan, f); + return fax_gateway_request_t38(gateway, chan, f); } else if (!gateway->ced_chan && peer == active) { - return fax_gateway_send_ced(gateway, chan, f); + return fax_gateway_request_t38(gateway, chan, f); } } } else if (gateway->t38_state == T38_STATE_UNAVAILABLE && f->frametype == AST_FRAME_VOICE) { -- cgit v1.2.3 From d4998689668ee1f03f2c4daf2dbee2aefc1a070a Mon Sep 17 00:00:00 2001 From: dvossel Date: Mon, 11 Jul 2011 18:44:06 +0000 Subject: Updates follow_talker video_mode in confbridge application. follow_talker mode originally echoed the same video stream to all participants. As the primary talker switched around, the video stream would result in the talker seeing themselves. Now the primary talker sees the last person who was talking rather than themselves. git-svn-id: http://svn.digium.com/svn/asterisk/trunk@327640 f38db490-d61c-443f-a65b-d21fe96a405b --- bridges/bridge_softmix.c | 33 ++++++++++++++++++++++++++----- include/asterisk/bridging.h | 13 ++++++++++++ main/bridging.c | 48 +++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 87 insertions(+), 7 deletions(-) diff --git a/bridges/bridge_softmix.c b/bridges/bridge_softmix.c index 8828d640a..00b0556d0 100644 --- a/bridges/bridge_softmix.c +++ b/bridges/bridge_softmix.c @@ -435,13 +435,30 @@ static void softmix_pass_dtmf(struct ast_bridge *bridge, struct ast_bridge_chann } } -static void softmix_pass_video(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame) +static void softmix_pass_video_top_priority(struct ast_bridge *bridge, struct ast_frame *frame) { struct ast_bridge_channel *tmp; AST_LIST_TRAVERSE(&bridge->channels, tmp, entry) { if (tmp->suspended) { continue; } + if (ast_bridge_is_video_src(bridge, tmp->chan) == 1) { + ast_write(tmp->chan, frame); + break; + } + } +} + +static void softmix_pass_video_all(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame, int echo) +{ + struct ast_bridge_channel *tmp; + AST_LIST_TRAVERSE(&bridge->channels, tmp, entry) { + if (tmp->suspended) { + continue; + } + if ((tmp->chan == bridge_channel->chan) && !echo) { + continue; + } ast_write(tmp->chan, frame); } } @@ -472,20 +489,26 @@ static enum ast_bridge_write_result softmix_bridge_write(struct ast_bridge *brid /* Determine if this video frame should be distributed or not */ if (frame->frametype == AST_FRAME_VIDEO) { + int num_src = ast_bridge_number_video_src(bridge); + int video_src_priority = ast_bridge_is_video_src(bridge, bridge_channel->chan); + switch (bridge->video_mode.mode) { case AST_BRIDGE_VIDEO_MODE_NONE: break; case AST_BRIDGE_VIDEO_MODE_SINGLE_SRC: - if (ast_bridge_is_video_src(bridge, bridge_channel->chan)) { - softmix_pass_video(bridge, bridge_channel, frame); + if (video_src_priority == 1) { + softmix_pass_video_all(bridge, bridge_channel, frame, 1); } break; case AST_BRIDGE_VIDEO_MODE_TALKER_SRC: ast_mutex_lock(&sc->lock); ast_bridge_update_talker_src_video_mode(bridge, bridge_channel->chan, sc->video_talker.energy_average, ast_format_get_video_mark(&frame->subclass.format)); ast_mutex_unlock(&sc->lock); - if (ast_bridge_is_video_src(bridge, bridge_channel->chan)) { - softmix_pass_video(bridge, bridge_channel, frame); + if (video_src_priority == 1) { + int echo = num_src > 1 ? 0 : 1; + softmix_pass_video_all(bridge, bridge_channel, frame, echo); + } else if (video_src_priority == 2) { + softmix_pass_video_top_priority(bridge, frame); } break; } diff --git a/include/asterisk/bridging.h b/include/asterisk/bridging.h index 849f88741..54137b028 100644 --- a/include/asterisk/bridging.h +++ b/include/asterisk/bridging.h @@ -190,6 +190,9 @@ struct ast_bridge_video_talker_src_data { /*! Only accept video coming from this channel */ struct ast_channel *chan_vsrc; int average_talking_energy; + + /*! Current talker see's this person */ + struct ast_channel *chan_old_vsrc; }; struct ast_bridge_video_mode { @@ -527,8 +530,18 @@ void ast_bridge_set_talker_src_video_mode(struct ast_bridge *bridge); */ void ast_bridge_update_talker_src_video_mode(struct ast_bridge *bridge, struct ast_channel *chan, int talker_energy, int is_keyfame); +/*! + * \brief Returns the number of video sources currently active in the bridge + */ +int ast_bridge_number_video_src(struct ast_bridge *bridge); + /*! * \brief Determine if a channel is a video src for the bridge + * + * \retval 0 Not a current video source of the bridge. + * \retval None 0, is a video source of the bridge, The number + * returned represents the priority this video stream has + * on the bridge where 1 is the highest priority. */ int ast_bridge_is_video_src(struct ast_bridge *bridge, struct ast_channel *chan); diff --git a/main/bridging.c b/main/bridging.c index 1563e4789..835a849fb 100644 --- a/main/bridging.c +++ b/main/bridging.c @@ -1489,6 +1489,9 @@ static void cleanup_video_mode(struct ast_bridge *bridge) if (bridge->video_mode.mode_data.talker_src_data.chan_vsrc) { ast_channel_unref(bridge->video_mode.mode_data.talker_src_data.chan_vsrc); } + if (bridge->video_mode.mode_data.talker_src_data.chan_old_vsrc) { + ast_channel_unref(bridge->video_mode.mode_data.talker_src_data.chan_old_vsrc); + } } memset(&bridge->video_mode, 0, sizeof(bridge->video_mode)); } @@ -1525,20 +1528,51 @@ void ast_bridge_update_talker_src_video_mode(struct ast_bridge *bridge, struct a if (data->chan_vsrc == chan) { data->average_talking_energy = talker_energy; } else if ((data->average_talking_energy < talker_energy) && is_keyframe) { + if (data->chan_old_vsrc) { + ast_channel_unref(data->chan_old_vsrc); + } if (data->chan_vsrc) { - ast_channel_unref(data->chan_vsrc); + data->chan_old_vsrc = data->chan_vsrc; + ast_indicate(data->chan_old_vsrc, AST_CONTROL_VIDUPDATE); } data->chan_vsrc = ast_channel_ref(chan); data->average_talking_energy = talker_energy; - ast_indicate(chan, AST_CONTROL_VIDUPDATE); } else if ((data->average_talking_energy < talker_energy) && !is_keyframe) { ast_indicate(chan, AST_CONTROL_VIDUPDATE); } else if (!data->chan_vsrc && is_keyframe) { data->chan_vsrc = ast_channel_ref(chan); data->average_talking_energy = talker_energy; ast_indicate(chan, AST_CONTROL_VIDUPDATE); + } else if (!data->chan_old_vsrc && is_keyframe) { + data->chan_old_vsrc = ast_channel_ref(chan); + ast_indicate(chan, AST_CONTROL_VIDUPDATE); + } + ao2_unlock(bridge); +} + +int ast_bridge_number_video_src(struct ast_bridge *bridge) +{ + int res = 0; + + ao2_lock(bridge); + switch (bridge->video_mode.mode) { + case AST_BRIDGE_VIDEO_MODE_NONE: + break; + case AST_BRIDGE_VIDEO_MODE_SINGLE_SRC: + if (bridge->video_mode.mode_data.single_src_data.chan_vsrc) { + res = 1; + } + break; + case AST_BRIDGE_VIDEO_MODE_TALKER_SRC: + if (bridge->video_mode.mode_data.talker_src_data.chan_vsrc) { + res++; + } + if (bridge->video_mode.mode_data.talker_src_data.chan_old_vsrc) { + res++; + } } ao2_unlock(bridge); + return res; } int ast_bridge_is_video_src(struct ast_bridge *bridge, struct ast_channel *chan) @@ -1557,7 +1591,10 @@ int ast_bridge_is_video_src(struct ast_bridge *bridge, struct ast_channel *chan) case AST_BRIDGE_VIDEO_MODE_TALKER_SRC: if (bridge->video_mode.mode_data.talker_src_data.chan_vsrc == chan) { res = 1; + } else if (bridge->video_mode.mode_data.talker_src_data.chan_old_vsrc == chan) { + res = 2; } + } ao2_unlock(bridge); return res; @@ -1583,6 +1620,13 @@ void ast_bridge_remove_video_src(struct ast_bridge *bridge, struct ast_channel * ast_channel_unref(bridge->video_mode.mode_data.talker_src_data.chan_vsrc); } bridge->video_mode.mode_data.talker_src_data.chan_vsrc = NULL; + bridge->video_mode.mode_data.talker_src_data.average_talking_energy = 0; + } + if (bridge->video_mode.mode_data.talker_src_data.chan_old_vsrc == chan) { + if (bridge->video_mode.mode_data.talker_src_data.chan_old_vsrc) { + ast_channel_unref(bridge->video_mode.mode_data.talker_src_data.chan_old_vsrc); + } + bridge->video_mode.mode_data.talker_src_data.chan_old_vsrc = NULL; } } ao2_unlock(bridge); -- cgit v1.2.3 From f422ffb34848fa66d8291d618694c1612a527e23 Mon Sep 17 00:00:00 2001 From: twilson Date: Mon, 11 Jul 2011 19:49:35 +0000 Subject: Merged revisions 327682 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.8 ........ r327682 | twilson | 2011-07-11 12:41:59 -0700 (Mon, 11 Jul 2011) | 9 lines Update chan_gtalk to work with changed GMail-based calls The messages sent by the GMail client have changed, but include the old-style messages as well. This patch checks for this case and uses the old-style offer. (closes issue ASTERISK-18084) Review: https://reviewboard.asterisk.org/r/1312/ ........ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@327683 f38db490-d61c-443f-a65b-d21fe96a405b --- channels/chan_gtalk.c | 9 ++++++++- include/asterisk/jingle.h | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/channels/chan_gtalk.c b/channels/chan_gtalk.c index 3b08d8ce4..326cb69db 100644 --- a/channels/chan_gtalk.c +++ b/channels/chan_gtalk.c @@ -1336,7 +1336,7 @@ static int gtalk_newcall(struct gtalk *client, ikspak *pak) ast_copy_string(p->sid, sid, sizeof(p->sid)); /* codec points to the first tag */ - codec = iks_first_tag(iks_first_tag(iks_first_tag(pak->x))); + codec = iks_first_tag(iks_first_tag(pak->query)); while (codec) { char *codec_id = iks_find_attrib(codec, "id"); @@ -2049,6 +2049,12 @@ static int gtalk_parser(void *data, ikspak *pak) { struct gtalk *client = ASTOBJ_REF((struct gtalk *) data); int res; + iks *tmp; + + if (!strcasecmp(iks_name(pak->query), "jin:jingle") && (tmp = iks_next(pak->query)) && !strcasecmp(iks_name(tmp), "ses:session")) { + ast_debug(1, "New method detected. Skipping jingle offer and using old gtalk method.\n"); + pak->query = tmp; + } if (!strcmp(S_OR(iks_find_attrib(pak->x, "type"), ""), "error")) { ast_log(LOG_NOTICE, "Remote peer reported an error, trying to establish the call anyway\n"); @@ -2233,6 +2239,7 @@ static int gtalk_load_config(void) ASTOBJ_WRLOCK(member); member->connection = NULL; iks_filter_add_rule(iterator->f, gtalk_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_NS, GOOGLE_NS, IKS_RULE_DONE); + iks_filter_add_rule(iterator->f, gtalk_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_NS, GOOGLE_JINGLE_NS, IKS_RULE_DONE); iks_filter_add_rule(iterator->f, gtalk_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_NS, "http://jabber.org/protocol/gtalk", IKS_RULE_DONE); ASTOBJ_UNLOCK(member); ASTOBJ_UNLOCK(iterator); diff --git a/include/asterisk/jingle.h b/include/asterisk/jingle.h index bbe86c8f2..77820654c 100644 --- a/include/asterisk/jingle.h +++ b/include/asterisk/jingle.h @@ -44,6 +44,7 @@ #define JINGLE_DTMF_NS "urn:xmpp:tmp:jingle:dtmf" #define GOOGLE_NS "http://www.google.com/session" +#define GOOGLE_JINGLE_NS "urn:xmpp:jingle:1" #define GOOGLE_AUDIO_NS "http://www.google.com/session/phone" #define GOOGLE_VIDEO_NS "http://www.google.com/session/video" #define GOOGLE_TRANSPORT_NS "http://www.google.com/transport/p2p" -- cgit v1.2.3 From bdb6e57e72a435d52535de1067426024560574e8 Mon Sep 17 00:00:00 2001 From: mnicholson Date: Mon, 11 Jul 2011 20:06:28 +0000 Subject: use printf instead of echo -n in substitution test git-svn-id: http://svn.digium.com/svn/asterisk/trunk@327684 f38db490-d61c-443f-a65b-d21fe96a405b --- tests/test_substitution.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_substitution.c b/tests/test_substitution.c index 366b9371c..b335d50ba 100644 --- a/tests/test_substitution.c +++ b/tests/test_substitution.c @@ -261,8 +261,8 @@ AST_TEST_DEFINE(test_substitution) TEST(test_expected_result(test, c, "A${${baz}o:-2:-1}A", "A2A")); pbx_builtin_setvar_helper(c, "list1", "ab&cd&ef"); TEST(test_expected_result(test, c, "${LISTFILTER(list1,&,cd)}", "ab&ef")); - TEST(test_expected_result(test, c, "${SHELL(echo -n 123)},${SHELL(echo -n 456)}", "123,456")); - TEST(test_expected_result(test, c, "${foo},${CDR(answer)},${SHELL(echo -n 456)}", "123,,456")); + TEST(test_expected_result(test, c, "${SHELL(printf 123)},${SHELL(printf 456)}", "123,456")); + TEST(test_expected_result(test, c, "${foo},${CDR(answer)},${SHELL(printf 456)}", "123,,456")); TEST(test_expected_result(test, c, "${foo},${this_does_not_exist},${THIS_DOES_NOT_EXIST(either)}", "123,,")); #undef TEST -- cgit v1.2.3 From d8b274bfd0efdc0763231701da7cc148a4f36d33 Mon Sep 17 00:00:00 2001 From: kmoore Date: Tue, 12 Jul 2011 14:40:16 +0000 Subject: Segfault on shutdown when confbridge is active When undergoing a shutdown and channels are kicked out of a bridge, a segfault occurs because ConfBridge tries to play sounds on the bridge after the underlying channels have been blown away due to the shutdown. (closes ASTERISK-18040) Review: https://reviewboard.asterisk.org/r/1283/ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@327748 f38db490-d61c-443f-a65b-d21fe96a405b --- apps/app_confbridge.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/apps/app_confbridge.c b/apps/app_confbridge.c index 80c84ed47..0ca2c6e8d 100644 --- a/apps/app_confbridge.c +++ b/apps/app_confbridge.c @@ -1473,6 +1473,13 @@ static int confbridge_exec(struct ast_channel *chan, const char *data) &conference_bridge_user.tech_args); send_leave_event(conference_bridge_user.chan, conference_bridge->name); + /* if we're shutting down, don't attempt to do further processing */ + if (ast_shutting_down()) { + leave_conference_bridge(conference_bridge, &conference_bridge_user); + conference_bridge = NULL; + goto confbridge_cleanup; + } + /* If this user was a video source, we need to clean up and possibly pick a new source. */ handle_video_on_exit(conference_bridge, conference_bridge_user.chan); -- cgit v1.2.3 From d75b0b09d3af66e24923107f91c8f4cbc50f0d39 Mon Sep 17 00:00:00 2001 From: dvossel Date: Tue, 12 Jul 2011 14:55:51 +0000 Subject: Send video update frame to new video source in follow_talker correctly. git-svn-id: http://svn.digium.com/svn/asterisk/trunk@327749 f38db490-d61c-443f-a65b-d21fe96a405b --- main/bridging.c | 1 + 1 file changed, 1 insertion(+) diff --git a/main/bridging.c b/main/bridging.c index 835a849fb..dea4f77a0 100644 --- a/main/bridging.c +++ b/main/bridging.c @@ -1537,6 +1537,7 @@ void ast_bridge_update_talker_src_video_mode(struct ast_bridge *bridge, struct a } data->chan_vsrc = ast_channel_ref(chan); data->average_talking_energy = talker_energy; + ast_indicate(data->chan_vsrc, AST_CONTROL_VIDUPDATE); } else if ((data->average_talking_energy < talker_energy) && !is_keyframe) { ast_indicate(chan, AST_CONTROL_VIDUPDATE); } else if (!data->chan_vsrc && is_keyframe) { -- cgit v1.2.3 From f4348dccf22bedc458d060f20a269a11a004485d Mon Sep 17 00:00:00 2001 From: mnicholson Date: Tue, 12 Jul 2011 15:23:24 +0000 Subject: do v21 detection instead of CED detection for the fax gateway git-svn-id: http://svn.digium.com/svn/asterisk/trunk@327769 f38db490-d61c-443f-a65b-d21fe96a405b --- include/asterisk/dsp.h | 3 +- main/dsp.c | 147 +++++++++++++++++++++++++++++++++++++++++++++++++ res/res_fax.c | 65 +++++++--------------- 3 files changed, 170 insertions(+), 45 deletions(-) diff --git a/include/asterisk/dsp.h b/include/asterisk/dsp.h index 333415200..78c9a74ac 100644 --- a/include/asterisk/dsp.h +++ b/include/asterisk/dsp.h @@ -45,7 +45,8 @@ #define DSP_FAXMODE_DETECT_CNG (1 << 0) #define DSP_FAXMODE_DETECT_CED (1 << 1) -#define DSP_FAXMODE_DETECT_ALL (DSP_FAXMODE_DETECT_CNG | DSP_FAXMODE_DETECT_CED) +#define DSP_FAXMODE_DETECT_V21 (1 << 2) +#define DSP_FAXMODE_DETECT_ALL (DSP_FAXMODE_DETECT_CNG | DSP_FAXMODE_DETECT_CED | DSP_FAXMODE_DETECT_V21) #define DSP_TONE_STATE_SILENCE 0 #define DSP_TONE_STATE_RINGING 1 diff --git a/main/dsp.c b/main/dsp.c index ee1891823..02cdc9d73 100644 --- a/main/dsp.c +++ b/main/dsp.c @@ -244,6 +244,20 @@ typedef struct } tone_detect_state_t; +typedef struct +{ + int block_size; + goertzel_state_t tone; + float energy; /* Accumulated energy of the current block */ + int samples_pending; /* Samples remain to complete the current block */ + + float threshold; /* Energy of the tone relative to energy from all other signals to consider a hit */ + + int hit_count; + int miss_count; + +} v21_detect_state_t; + typedef struct { goertzel_state_t row_out[4]; @@ -391,6 +405,7 @@ struct ast_dsp { digit_detect_state_t digit_state; tone_detect_state_t cng_tone_state; tone_detect_state_t ced_tone_state; + v21_detect_state_t v21_state; }; static void mute_fragment(struct ast_dsp *dsp, fragment_t *fragment) @@ -463,10 +478,55 @@ static void ast_tone_detect_init(tone_detect_state_t *s, int freq, int duration, ast_debug(1, "Setup tone %d Hz, %d ms, block_size=%d, hits_required=%d\n", freq, duration, s->block_size, s->hits_required); } +static void ast_v21_detect_init(v21_detect_state_t *s, unsigned int sample_rate) +{ + float x; + int periods_in_block; + + /* If we want to remove tone, it is important to have block size not + to exceed frame size. Otherwise by the moment tone is detected it is too late + to squelch it from previous frames. Block size is 20ms at the given sample rate.*/ + s->block_size = (20 * sample_rate) / 1000; + + periods_in_block = s->block_size * 1850 / sample_rate; + + /* Make sure we will have at least 5 periods at target frequency for analisys. + This may make block larger than expected packet and will make squelching impossible + but at least we will be detecting the tone */ + if (periods_in_block < 5) + periods_in_block = 5; + + /* Now calculate final block size. It will contain integer number of periods */ + s->block_size = periods_in_block * sample_rate / 1850; + + goertzel_init(&s->tone, 1850.0, s->block_size, sample_rate); + + s->samples_pending = s->block_size; + s->hit_count = 0; + s->miss_count = 0; + s->energy = 0.0; + + /* We want tone energy to be amp decibels above the rest of the signal (the noise). + According to Parseval's theorem the energy computed in time domain equals to energy + computed in frequency domain. So subtracting energy in the frequency domain (Goertzel result) + from the energy in the time domain we will get energy of the remaining signal (without the tone + we are detecting). We will be checking that + 10*log(Ew / (Et - Ew)) > amp + Calculate threshold so that we will be actually checking + Ew > Et * threshold + */ + + x = pow(10.0, 16 / 10.0); + s->threshold = x / (x + 1); + + ast_debug(1, "Setup v21 detector, block_size=%d\n", s->block_size); +} + static void ast_fax_detect_init(struct ast_dsp *s) { ast_tone_detect_init(&s->cng_tone_state, FAX_TONE_CNG_FREQ, FAX_TONE_CNG_DURATION, FAX_TONE_CNG_DB, s->sample_rate); ast_tone_detect_init(&s->ced_tone_state, FAX_TONE_CED_FREQ, FAX_TONE_CED_DURATION, FAX_TONE_CED_DB, s->sample_rate); + ast_v21_detect_init(&s->v21_state, s->sample_rate); } static void ast_dtmf_detect_init (dtmf_detect_state_t *s, unsigned int sample_rate) @@ -513,6 +573,89 @@ static void ast_digit_detect_init(digit_detect_state_t *s, int mf, unsigned int } } +/*! \brief Detect a v21 preamble. + * This code is derived from the tone_detect code and detects a pattern of 1850 + * Hz tone found in a v21 preamble. + */ +static int v21_detect(struct ast_dsp *dsp, v21_detect_state_t *s, int16_t *amp, int samples) +{ + float tone_energy; + int i; + int hit = 0; + int limit; + int res = 0; + int16_t *ptr; + int start, end; + + for (start = 0; start < samples; start = end) { + /* Process in blocks. */ + limit = samples - start; + if (limit > s->samples_pending) { + limit = s->samples_pending; + } + end = start + limit; + + for (i = limit, ptr = amp ; i > 0; i--, ptr++) { + /* signed 32 bit int should be enough to suqare any possible signed 16 bit value */ + s->energy += (int32_t) *ptr * (int32_t) *ptr; + + goertzel_sample(&s->tone, *ptr); + } + + s->samples_pending -= limit; + + if (s->samples_pending) { + /* Finished incomplete (last) block */ + break; + } + + tone_energy = goertzel_result(&s->tone); + + /* Scale to make comparable */ + tone_energy *= 2.0; + s->energy *= s->block_size; + + ast_debug(10, "v21 1850 Ew=%.2E, Et=%.2E, s/n=%10.2f\n", tone_energy, s->energy, tone_energy / (s->energy - tone_energy)); + + hit = 0; + if (tone_energy > s->energy * s->threshold) { + ast_debug(10, "Hit! count=%d; miss_count=%d\n", s->hit_count, s->miss_count); + hit = 1; + } + + if (hit) { + if (s->hit_count == 0 || s->miss_count == 3) { + s->hit_count++; + } else { + s->hit_count = 0; + } + + s->miss_count = 0; + } else { + s->miss_count++; + if (s->miss_count > 3) { + s->hit_count = 0; + } + } + + if (s->hit_count == 4) { + ast_debug(1, "v21 preamble detected\n"); + res = 1; + } + + /* Reinitialise the detector for the next block */ + goertzel_reset(&s->tone); + + /* Advance to the next block */ + s->energy = 0.0; + s->samples_pending = s->block_size; + + amp += limit; + } + + return res; +} + static int tone_detect(struct ast_dsp *dsp, tone_detect_state_t *s, int16_t *amp, int samples) { float tone_energy; @@ -1441,6 +1584,10 @@ struct ast_frame *ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp, if ((dsp->faxmode & DSP_FAXMODE_DETECT_CED) && tone_detect(dsp, &dsp->ced_tone_state, shortdata, len)) { fax_digit = 'e'; } + + if ((dsp->faxmode & DSP_FAXMODE_DETECT_V21) && v21_detect(dsp, &dsp->v21_state, shortdata, len)) { + fax_digit = 'g'; + } } if (dsp->features & (DSP_FEATURE_DIGIT_DETECT | DSP_FEATURE_BUSY_DETECT)) { diff --git a/res/res_fax.c b/res/res_fax.c index 18f3fa133..31aede8a6 100644 --- a/res/res_fax.c +++ b/res/res_fax.c @@ -246,8 +246,6 @@ struct fax_gateway { struct ast_fax_tech_token *token; /*! \brief the start of our timeout counter */ struct timeval timeout_start; - /*! \brief the start of our ced timeout */ - struct timeval ced_timeout_start; /*! \brief DSP Processor */ struct ast_dsp *chan_dsp; struct ast_dsp *peer_dsp; @@ -255,8 +253,8 @@ struct fax_gateway { int framehook; /*! \brief bridged */ int bridged:1; - /*! \brief 1 if the ced tone came from chan, 0 if it came from peer */ - int ced_chan:1; + /*! \brief 1 if a v21 preamble has been detected */ + int detected_v21:1; /*! \brief a flag to track the state of our negotiation */ enum ast_t38_state t38_state; /*! \brief original audio formats */ @@ -273,7 +271,6 @@ static int fax_logger_level = -1; #define RES_FAX_TIMEOUT 10000 #define FAX_GATEWAY_TIMEOUT RES_FAX_TIMEOUT -#define FAX_GATEWAY_CED_TIMEOUT 3000 /*! \brief The faxregistry is used to manage information and statistics for all FAX sessions. */ static struct { @@ -2412,10 +2409,10 @@ static struct fax_gateway *fax_gateway_new(struct ast_fax_session_details *detai gateway->framehook = -1; ast_dsp_set_features(gateway->chan_dsp, DSP_FEATURE_FAX_DETECT); - ast_dsp_set_faxmode(gateway->chan_dsp, DSP_FAXMODE_DETECT_CED); + ast_dsp_set_faxmode(gateway->chan_dsp, DSP_FAXMODE_DETECT_V21); ast_dsp_set_features(gateway->peer_dsp, DSP_FEATURE_FAX_DETECT); - ast_dsp_set_faxmode(gateway->peer_dsp, DSP_FAXMODE_DETECT_CED); + ast_dsp_set_faxmode(gateway->peer_dsp, DSP_FAXMODE_DETECT_V21); details->caps = AST_FAX_TECH_GATEWAY; if (!(gateway->s = fax_session_reserve(details, &gateway->token))) { @@ -2503,21 +2500,17 @@ static struct ast_frame *fax_gateway_request_t38(struct fax_gateway *gateway, st gateway->t38_state = T38_STATE_NEGOTIATING; gateway->timeout_start = ast_tvnow(); - gateway->ced_timeout_start.tv_sec = 0; - gateway->ced_timeout_start.tv_usec = 0; - ast_debug(1, "requesting T.38 for gateway session for %s\n", chan->name); return fp; } -static struct ast_frame *fax_gateway_detect_ced(struct fax_gateway *gateway, struct ast_channel *chan, struct ast_channel *peer, struct ast_channel *active, struct ast_frame *f) +static struct ast_frame *fax_gateway_detect_v21(struct fax_gateway *gateway, struct ast_channel *chan, struct ast_channel *peer, struct ast_channel *active, struct ast_frame *f) { struct ast_frame *dfr = ast_frdup(f); struct ast_dsp *active_dsp = (active == chan) ? gateway->chan_dsp : gateway->peer_dsp; struct ast_channel *other = (active == chan) ? peer : chan; - /* if we have already detected a CED tone, don't waste time here */ - if (!ast_tvzero(gateway->ced_timeout_start)) { + if (gateway->detected_v21) { return f; } @@ -2529,17 +2522,13 @@ static struct ast_frame *fax_gateway_detect_ced(struct fax_gateway *gateway, str return f; } - if (dfr->frametype == AST_FRAME_DTMF && dfr->subclass.integer == 'e') { + if (dfr->frametype == AST_FRAME_DTMF && dfr->subclass.integer == 'g') { + gateway->detected_v21 = 1; if (ast_channel_get_t38_state(other) == T38_STATE_UNKNOWN) { - if (ast_channel_get_t38_state(active) == T38_STATE_UNKNOWN) { - gateway->ced_timeout_start = ast_tvnow(); - gateway->ced_chan = (active == chan); - ast_debug(1, "detected CED tone from %s; will schedule T.38 request on %s\n", active->name, other->name); - } else { - return fax_gateway_request_t38(gateway, chan, f); - } + ast_debug(1, "detected v21 preamble from %s\n", active->name); + return fax_gateway_request_t38(gateway, chan, f); } else { - ast_debug(1, "detected CED tone on %s, but %s does not support T.38 for T.38 gateway session\n", active->name, other->name); + ast_debug(1, "detected v21 preamble on %s, but %s does not support T.38 for T.38 gateway session\n", active->name, other->name); } } @@ -2593,9 +2582,6 @@ static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, str if (control_params->request_response == AST_T38_REQUEST_NEGOTIATE) { enum ast_t38_state state = ast_channel_get_t38_state(other); - gateway->ced_timeout_start.tv_sec = 0; - gateway->ced_timeout_start.tv_usec = 0; - if (state == T38_STATE_UNKNOWN) { /* we detected a request to negotiate T.38 and the * other channel appears to support T.38, we'll pass @@ -2635,7 +2621,7 @@ static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, str return &ast_null_frame; } else if (gateway->t38_state == T38_STATE_NEGOTIATING) { /* we got a request to negotiate T.38 after we already - * sent one to the other party based on CED tone + * sent one to the other party based on v21 preamble * detection. We'll just pretend we passed this request * through in the first place. */ @@ -2643,12 +2629,12 @@ static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, str gateway->t38_state = T38_STATE_UNKNOWN; gateway->timeout_start = ast_tvnow(); - ast_debug(1, "%s is attempting to negotiate T.38 after we already sent a negotiation request based on CED detection\n", active->name); + ast_debug(1, "%s is attempting to negotiate T.38 after we already sent a negotiation request based on v21 preamble detection\n", active->name); ao2_ref(details, -1); return &ast_null_frame; } else if (gateway->t38_state == T38_STATE_NEGOTIATED) { /* we got a request to negotiate T.38 after we already - * sent one to the other party based on CED tone + * sent one to the other party based on v21 preamble * detection and received a response. We need to * respond to this and shut down the gateway. */ @@ -2869,7 +2855,8 @@ static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct gateway->timeout_start = ast_tvnow(); - /* we are bridged, change r/w formats to SLIN for CED detection and T.30 */ + /* we are bridged, change r/w formats to SLIN for v21 preamble + * detection and T.30 */ ast_format_copy(&gateway->chan_read_format, &chan->readformat); ast_format_copy(&gateway->chan_write_format, &chan->readformat); @@ -2944,20 +2931,10 @@ static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct return fax_gateway_detect_t38(gateway, chan, peer, active, f); } - /* handle the ced timeout delay */ - if (!ast_tvzero(gateway->ced_timeout_start)) { - if (ast_tvdiff_ms(ast_tvnow(), gateway->ced_timeout_start) > FAX_GATEWAY_CED_TIMEOUT) { - if (gateway->ced_chan && chan == active) { - return fax_gateway_request_t38(gateway, chan, f); - } else if (!gateway->ced_chan && peer == active) { - return fax_gateway_request_t38(gateway, chan, f); - } - } - } else if (gateway->t38_state == T38_STATE_UNAVAILABLE && f->frametype == AST_FRAME_VOICE) { - /* not in gateway mode and have not detected CED yet, listen - * for CED */ - /* XXX this should detect a v21 preamble instead of CED */ - return fax_gateway_detect_ced(gateway, chan, peer, active, f); + if (!gateway->detected_v21 && gateway->t38_state == T38_STATE_UNAVAILABLE && f->frametype == AST_FRAME_VOICE) { + /* not in gateway mode and have not detected v21 yet, listen + * for v21 */ + return fax_gateway_detect_v21(gateway, chan, peer, active, f); } /* in gateway mode, gateway some packets */ @@ -2981,7 +2958,7 @@ static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct } /* force silence on the line if T.38 negotiation might be taking place */ - if (!ast_tvzero(gateway->ced_timeout_start) || (gateway->t38_state != T38_STATE_UNAVAILABLE && gateway->t38_state != T38_STATE_REJECTED)) { + if (gateway->t38_state != T38_STATE_UNAVAILABLE && gateway->t38_state != T38_STATE_REJECTED) { if (f->frametype == AST_FRAME_VOICE && f->subclass.format.id == AST_FORMAT_SLINEAR) { short silence_buf[f->samples]; struct ast_frame silence_frame = { -- cgit v1.2.3 From 9b87fa23c7836284f1945f620a105573471af0a1 Mon Sep 17 00:00:00 2001 From: tilghman Date: Tue, 12 Jul 2011 15:38:47 +0000 Subject: Merged revisions 327793 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.8 ........ r327793 | tilghman | 2011-07-12 10:35:46 -0500 (Tue, 12 Jul 2011) | 14 lines Use 'printf' (POSIX issue 4) instead of 'echo -n', for portability. The problem with using 'echo -n' is that it is not portable. While BSD systems required that the '-n' option be removed and interpreted, System V required that all strings should be echoed with no interpretation of options. This fundamental difference of behavior means that it is never possible to use the '-n' flag to echo in tests which are meant to be portable. In this case, on Mac OS X 10.6, the /bin/sh shell builtin 'echo' uses the System V semantics of the command, and thus the SHELL test failed on that platform. http://pubs.opengroup.org/onlinepubs/009695399/utilities/echo.html#tag_04_41_16 ........ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@327794 f38db490-d61c-443f-a65b-d21fe96a405b --- tests/test_substitution.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_substitution.c b/tests/test_substitution.c index b335d50ba..cb3161691 100644 --- a/tests/test_substitution.c +++ b/tests/test_substitution.c @@ -261,8 +261,8 @@ AST_TEST_DEFINE(test_substitution) TEST(test_expected_result(test, c, "A${${baz}o:-2:-1}A", "A2A")); pbx_builtin_setvar_helper(c, "list1", "ab&cd&ef"); TEST(test_expected_result(test, c, "${LISTFILTER(list1,&,cd)}", "ab&ef")); - TEST(test_expected_result(test, c, "${SHELL(printf 123)},${SHELL(printf 456)}", "123,456")); - TEST(test_expected_result(test, c, "${foo},${CDR(answer)},${SHELL(printf 456)}", "123,,456")); + TEST(test_expected_result(test, c, "${SHELL(printf '%d' 123)},${SHELL(printf '%d' 456)}", "123,456")); + TEST(test_expected_result(test, c, "${foo},${CDR(answer)},${SHELL(printf '%d' 456)}", "123,,456")); TEST(test_expected_result(test, c, "${foo},${this_does_not_exist},${THIS_DOES_NOT_EXIST(either)}", "123,,")); #undef TEST -- cgit v1.2.3 From b7bcb3bd7a67cb9e1341c35fe13a1838b9c170af Mon Sep 17 00:00:00 2001 From: mjordan Date: Tue, 12 Jul 2011 19:18:08 +0000 Subject: Merged revisions 327852 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.8 ........ r327852 | mjordan | 2011-07-12 14:10:34 -0500 (Tue, 12 Jul 2011) | 12 lines Added additional checks for mailbox / password beginning with '*' character A bug existed such that if a user entered a password with '*', and the extension 'a' did not exist, an invalid mailbox would be created and the user authenticated. The code was changed to prevent this from occurring, and to prevent users from having mailboxes or passwords defined that begin with the '*' character. (closes issue ASTERISK-17443) Reported by: Kevin Scott Adams Tested by: Matt Jordan Review: https://reviewboard.asterisk.org/r/1316/ ........ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@327856 f38db490-d61c-443f-a65b-d21fe96a405b --- apps/app_voicemail.c | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c index 971e1879d..1f72ee1d9 100644 --- a/apps/app_voicemail.c +++ b/apps/app_voicemail.c @@ -1215,6 +1215,9 @@ static int check_password(struct ast_vm_user *vmu, char *password) /* check minimum length */ if (strlen(password) < minpassword) return 1; + /* check that password does not contain '*' character */ + if (!ast_strlen_zero(password) && password[0] == '*') + return 1; if (!ast_strlen_zero(ext_pass_check_cmd)) { char cmd[255], buf[255]; @@ -1294,8 +1297,14 @@ static void apply_options_full(struct ast_vm_user *retval, struct ast_variable * if (!strcasecmp(var->name, "vmsecret")) { ast_copy_string(retval->password, var->value, sizeof(retval->password)); } else if (!strcasecmp(var->name, "secret") || !strcasecmp(var->name, "password")) { /* don't overwrite vmsecret if it exists */ - if (ast_strlen_zero(retval->password)) - ast_copy_string(retval->password, var->value, sizeof(retval->password)); + if (ast_strlen_zero(retval->password)) { + if (!ast_strlen_zero(var->value) && var->value[0] == '*') { + ast_log(LOG_WARNING, "Invalid password detected for mailbox %s. The password" + "\n\tmust be reset in voicemail.conf.\n", retval->mailbox); + } else { + ast_copy_string(retval->password, var->value, sizeof(retval->password)); + } + } } else if (!strcasecmp(var->name, "uniqueid")) { ast_copy_string(retval->uniqueid, var->value, sizeof(retval->uniqueid)); } else if (!strcasecmp(var->name, "pager")) { @@ -9662,10 +9671,12 @@ static int vm_authenticate(struct ast_channel *chan, char *mailbox, int mailbox_ } } else if (mailbox[0] == '*') { /* user entered '*' */ + ast_verb(4, "Mailbox begins with '*', attempting jump to extension 'a'\n"); if (ast_exists_extension(chan, chan->context, "a", 1, S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) { return -1; } + ast_verb(4, "Jump to extension 'a' failed; setting mailbox to NULL\n"); mailbox[0] = '\0'; } @@ -9694,12 +9705,16 @@ static int vm_authenticate(struct ast_channel *chan, char *mailbox, int mailbox_ return -1; } else if (password[0] == '*') { /* user entered '*' */ + ast_verb(4, "Password begins with '*', attempting jump to extension 'a'\n"); if (ast_exists_extension(chan, chan->context, "a", 1, S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) { mailbox[0] = '*'; return -1; } + ast_verb(4, "Jump to extension 'a' failed; setting mailbox and user to NULL\n"); mailbox[0] = '\0'; + /* if the password entered was '*', do not let a user mailbox be created if the extension 'a' is not defined */ + vmu = NULL; } } @@ -10546,6 +10561,14 @@ static struct ast_vm_user *find_or_create(const char *context, const char *box) { struct ast_vm_user *vmu; + if (!ast_strlen_zero(box) && box[0] == '*') { + ast_log(LOG_WARNING, "Mailbox %s in context %s begins with '*' character. The '*' character," + "\n\twhen it is the first character in a mailbox or password, is used to jump to a" + "\n\tpredefined extension 'a'. A mailbox or password beginning with '*' is not valid" + "\n\tand will be ignored.\n", box, context); + return NULL; + } + AST_LIST_TRAVERSE(&users, vmu, list) { if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(box, vmu->mailbox)) { if (strcasecmp(vmu->context, context)) { @@ -10594,6 +10617,11 @@ static int append_mailbox(const char *context, const char *box, const char *data stringp = tmp; if ((s = strsep(&stringp, ","))) { + if (!ast_strlen_zero(s) && s[0] == '*') { + ast_log(LOG_WARNING, "Invalid password detected for mailbox %s. The password" + "\n\tmust be reset in voicemail.conf.\n", box); + } + /* assign password regardless of validity to prevent NULL password from being assigned */ ast_copy_string(vmu->password, s, sizeof(vmu->password)); } if (stringp && (s = strsep(&stringp, ","))) { -- cgit v1.2.3 From 8af76f640fdb4ce9de93fb02beaf07b5cdf7a463 Mon Sep 17 00:00:00 2001 From: qwell Date: Tue, 12 Jul 2011 19:39:04 +0000 Subject: Merged revisions 327888 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.8 ........ r327888 | qwell | 2011-07-12 14:38:44 -0500 (Tue, 12 Jul 2011) | 1 line Fix uninstall target, so that modules dir gets cleared again. ........ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@327889 f38db490-d61c-443f-a65b-d21fe96a405b --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 85149c94a..fda715702 100644 --- a/Makefile +++ b/Makefile @@ -844,7 +844,7 @@ $(SUBDIRS_UNINSTALL): +@$(SUBMAKE) -C $(@:-uninstall=) uninstall _uninstall: $(SUBDIRS_UNINSTALL) - rm -f "$(DESTDIR)$(MODULES_DIR)/*" + rm -f "$(DESTDIR)$(MODULES_DIR)/"* rm -f $(DESTDIR)$(ASTSBINDIR)/*asterisk* rm -f $(DESTDIR)$(ASTSBINDIR)/astgenkey rm -f $(DESTDIR)$(ASTSBINDIR)/autosupport -- cgit v1.2.3 From 6324f36910aa179dae8faa835ebf0a160f42daf8 Mon Sep 17 00:00:00 2001 From: mnicholson Date: Tue, 12 Jul 2011 20:08:04 +0000 Subject: Merged revisions 327890 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.8 ........ r327890 | mnicholson | 2011-07-12 15:07:20 -0500 (Tue, 12 Jul 2011) | 2 lines search in the current context for 'a' and 'o' instead of 'default' ........ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@327891 f38db490-d61c-443f-a65b-d21fe96a405b --- apps/app_directory.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/apps/app_directory.c b/apps/app_directory.c index 305bcdd7b..8451eea08 100644 --- a/apps/app_directory.c +++ b/apps/app_directory.c @@ -57,7 +57,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") This is the dialplan context to use when looking for an extension that the user has selected, or when jumping to the - o or a extension. + o or a extension. If not + specified, the current context will be used. @@ -246,7 +247,7 @@ static int compare(const char *text, const char *template) static int goto_exten(struct ast_channel *chan, const char *dialcontext, char *ext) { - if (!ast_goto_if_exists(chan, dialcontext, ext, 1) || + if (!ast_goto_if_exists(chan, S_OR(dialcontext, chan->context), ext, 1) || (!ast_strlen_zero(chan->macrocontext) && !ast_goto_if_exists(chan, chan->macrocontext, ext, 1))) { return 0; @@ -685,11 +686,11 @@ static int do_directory(struct ast_channel *chan, struct ast_config *vmcfg, stru int count, i; char ext[10] = ""; - if (digit == '0' && !goto_exten(chan, S_OR(dialcontext, "default"), "o")) { + if (digit == '0' && !goto_exten(chan, dialcontext, "o")) { return digit; } - if (digit == '*' && !goto_exten(chan, S_OR(dialcontext, "default"), "a")) { + if (digit == '*' && !goto_exten(chan, dialcontext, "a")) { return digit; } -- cgit v1.2.3 From ef8cbd877102c8fe70cf3cd682f262086c9dfdeb Mon Sep 17 00:00:00 2001 From: kpfleming Date: Tue, 12 Jul 2011 23:02:31 +0000 Subject: Merged revisions 327950 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.8 ........ r327950 | kpfleming | 2011-07-12 17:53:53 -0500 (Tue, 12 Jul 2011) | 14 lines Correct double-free situation in manager output processing. The process_output() function calls ast_str_append() and xml_translate() on its 'out' parameter, which is a pointer to an ast_str buffer. If either of these functions need to reallocate the ast_str so it will have more space, they will free the existing buffer and allocate a new one, returning the address of the new one. However, because process_output only receives a pointer to the ast_str, not a pointer to its caller's variable holding the pointer, if the original ast_str is freed, the caller will not know, and will continue to use it (and later attempt to free it). (reported by jkroon on #asterisk-dev) ........ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@327953 f38db490-d61c-443f-a65b-d21fe96a405b --- main/manager.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/main/manager.c b/main/manager.c index 5b3da313d..edaad357f 100644 --- a/main/manager.c +++ b/main/manager.c @@ -5621,7 +5621,7 @@ static void xml_translate(struct ast_str **out, char *in, struct ast_variable *g } } -static void process_output(struct mansession *s, struct ast_str *out, struct ast_variable *params, enum output_format format) +static void process_output(struct mansession *s, struct ast_str **out, struct ast_variable *params, enum output_format format) { char *buf; size_t l; @@ -5638,14 +5638,14 @@ static void process_output(struct mansession *s, struct ast_str *out, struct ast ast_log(LOG_WARNING, "mmap failed. Manager output was not processed\n"); } else { if (format == FORMAT_XML || format == FORMAT_HTML) { - xml_translate(&out, buf, params, format); + xml_translate(out, buf, params, format); } else { - ast_str_append(&out, 0, "%s", buf); + ast_str_append(out, 0, "%s", buf); } munmap(buf, l); } } else if (format == FORMAT_XML || format == FORMAT_HTML) { - xml_translate(&out, "", params, format); + xml_translate(out, "", params, format); } fclose(s->f); @@ -5803,7 +5803,7 @@ static int generic_http_callback(struct ast_tcptls_session_instance *ser, ast_str_append(&out, 0, ROW_FMT, TEST_STRING); } - process_output(&s, out, params, format); + process_output(&s, &out, params, format); if (format == FORMAT_XML) { ast_str_append(&out, 0, "\n"); @@ -6115,7 +6115,7 @@ static int auth_http_callback(struct ast_tcptls_session_instance *ser, "\r\n"); } - process_output(&s, out, params, format); + process_output(&s, &out, params, format); if (format == FORMAT_XML) { ast_str_append(&out, 0, "\n"); -- cgit v1.2.3 From d7d1aee4e34a236aaee8ad6c973ce3af327010d5 Mon Sep 17 00:00:00 2001 From: rmudgett Date: Wed, 13 Jul 2011 18:47:16 +0000 Subject: Merged revisions 328014 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.8 ........ r328014 | rmudgett | 2011-07-13 13:46:38 -0500 (Wed, 13 Jul 2011) | 1 line Add ATXFER_NULL_TECH note in features.conf.sample. ........ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@328016 f38db490-d61c-443f-a65b-d21fe96a405b --- configs/features.conf.sample | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/configs/features.conf.sample b/configs/features.conf.sample index f9d9dd45d..dfeec1757 100644 --- a/configs/features.conf.sample +++ b/configs/features.conf.sample @@ -73,6 +73,10 @@ context => parkedcalls ; Which context parked calls are in (default parking lot ; caller is connected, then by default, the system will try to call back the ; person that did the transfer. If this is set to "yes", the callback will ; not be attempted and the transfer will just fail. + ; For atxferdropcall=no to work properly, you also need to + ; define ATXFER_NULL_TECH in main/features.c. The reason the + ; code is not enabled by default is spelled out in the comment + ; block near the top of main/features.c describing ATXFER_NULL_TECH. ;atxferloopdelay = 10 ; Number of seconds to sleep between retries (if atxferdropcall = no) ;atxfercallbackretries = 2 ; Number of times to attempt to send the call back to the transferer. ; By default, this is 2. -- cgit v1.2.3 -- cgit v1.2.3 -- cgit v1.2.3 From 53890401acc42a53661375686ca1c1ee2c18aa2c Mon Sep 17 00:00:00 2001 From: lmadsen Date: Wed, 13 Jul 2011 21:06:23 +0000 Subject: Add UPGRADE-1.10.txt file from UPGRADE.txt. git-svn-id: http://svn.digium.com/svn/asterisk/trunk@328079 f38db490-d61c-443f-a65b-d21fe96a405b --- BUGS | 2 +- UPGRADE-1.10.txt | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ UPGRADE.txt | 5 ++++ 3 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 UPGRADE-1.10.txt diff --git a/BUGS b/BUGS index 86fbb76fd..624459ea5 100644 --- a/BUGS +++ b/BUGS @@ -4,7 +4,7 @@ Asterisk Bug Tracking Information To learn about and report Asterisk bugs, please visit the official Asterisk Bug Tracker at: - https://issues.asterisk.org + https://issues.asterisk.org/jira For more information on using the bug tracker, or to learn how you can contribute by acting as a bug marshal diff --git a/UPGRADE-1.10.txt b/UPGRADE-1.10.txt new file mode 100644 index 000000000..87413cf3b --- /dev/null +++ b/UPGRADE-1.10.txt @@ -0,0 +1,71 @@ +=========================================================== +=== +=== Information for upgrading between Asterisk versions +=== +=== These files document all the changes that MUST be taken +=== into account when upgrading between the Asterisk +=== versions listed below. These changes may require that +=== you modify your configuration files, dialplan or (in +=== some cases) source code if you have your own Asterisk +=== modules or patches. These files also include advance +=== notice of any functionality that has been marked as +=== 'deprecated' and may be removed in a future release, +=== along with the suggested replacement functionality. +=== +=== UPGRADE-1.2.txt -- Upgrade info for 1.0 to 1.2 +=== UPGRADE-1.4.txt -- Upgrade info for 1.2 to 1.4 +=== UPGRADE-1.6.txt -- Upgrade info for 1.4 to 1.6 +=== UPGRADE-1.8.txt -- Upgrade info for 1.6 to 1.8 +=== +=========================================================== + +From 1.8 to 1.10: + +cel_pgsql: + - This module now expects an 'extra' column in the database for data added + using the CELGenUserEvent() application. + +ConfBridge + - ConfBridge's dialplan arguments have changed and are not + backwards compatible. + +File Interpreters + - The format interpreter formats/format_sln16.c for the file extension + '.sln16' has been removed. The '.sln16' file interpreter now exists + in the formats/format_sln.c module along with new support for sln12, + sln24, sln32, sln44, sln48, sln96, and sln192 file extensions. + +HTTP: + - A bindaddr must be specified in order for the HTTP server + to run. Previous versions would default to 0.0.0.0 if no + bindaddr was specified. + +Gtalk: + - The default value for 'context' and 'parkinglots' in gtalk.conf has + been changed to 'default', previously they were empty. + +chan_dahdi: + - The mohinterpret=passthrough setting is deprecated in favor of + moh_signaling=notify. + +pbx_lua: + - Execution no longer continues after applications that do dialplan jumps + (such as app.goto). Now when an application such as app.goto() is called, + control is returned back to the pbx engine and the current extension + function stops executing. + - the autoservice now defaults to being on by default + - autoservice_start() and autoservice_start() no longer return a value. + +Queue: + - Mark QUEUE_MEMBER_PENALTY Deprecated it never worked for realtime members + - QUEUE_MEMBER is now R/W supporting setting paused, ignorebusy and penalty. + + Asterisk Database: + - The internal Asterisk database has been switched from Berkeley DB 1.86 to + SQLite 3. An existing Berkeley astdb file can be converted with the astdb2sqlite3 + utility in the UTILS section of menuselect. If an existing astdb is found and no + astdb.sqlite3 exists, astdb2sqlite3 will be compiled automatically. Asterisk will + convert an existing astdb to the SQLite3 version automatically at runtime. + +=========================================================== +=========================================================== diff --git a/UPGRADE.txt b/UPGRADE.txt index 87413cf3b..a5500f203 100644 --- a/UPGRADE.txt +++ b/UPGRADE.txt @@ -16,9 +16,14 @@ === UPGRADE-1.4.txt -- Upgrade info for 1.2 to 1.4 === UPGRADE-1.6.txt -- Upgrade info for 1.4 to 1.6 === UPGRADE-1.8.txt -- Upgrade info for 1.6 to 1.8 +=== UPGRADE-1.10.txt -- Upgrade info for 1.8 to 1.10 === =========================================================== +From 1.10 to 1.12: + +* No significant changes as of yet. + From 1.8 to 1.10: cel_pgsql: -- cgit v1.2.3 From fb85b967191258fa96fceef1b6ee99b203a021b7 Mon Sep 17 00:00:00 2001 From: dvossel Date: Wed, 13 Jul 2011 22:10:26 +0000 Subject: Merged revisions 328120 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.10 ........ r328120 | dvossel | 2011-07-13 17:09:34 -0500 (Wed, 13 Jul 2011) | 15 lines Preserve sample rate quality of wideband mixmonitor recordings. MixMonitor has the ability to record in any file format Asterisk supports, but the quality of wideband audio is not preserved. This is because regardless of the sample rate the call is being recorded in, the audio is always downsampled to 8khz and then upsampled to whatever wideband format it is being written as. This patch resolves this by requesting the audio from the audiohook in the signed linear format closest to the sample rate of the format we are writing. This fix is only possible for Asterisk 1.10 because audio hooks in 1.8 are not capable of wideband audio. Review: https://reviewboard.asterisk.org/r/1314/ ........ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@328121 f38db490-d61c-443f-a65b-d21fe96a405b --- apps/app_mixmonitor.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/apps/app_mixmonitor.c b/apps/app_mixmonitor.c index 29463e253..05798ffa3 100644 --- a/apps/app_mixmonitor.c +++ b/apps/app_mixmonitor.c @@ -47,6 +47,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/channel.h" #include "asterisk/autochan.h" #include "asterisk/manager.h" +#include "asterisk/mod_format.h" /*** DOCUMENTATION @@ -225,6 +226,8 @@ struct mixmonitor_ds { struct ast_filestream *fs_write; struct ast_audiohook *audiohook; + + unsigned int samp_rate; }; /*! @@ -334,7 +337,7 @@ static void mixmonitor_save_prep(struct mixmonitor *mixmonitor, char *filename, if (!*fs && !*errflag && !mixmonitor->mixmonitor_ds->fs_quit) { *oflags = O_CREAT | O_WRONLY; *oflags |= ast_test_flag(mixmonitor, MUXFLAG_APPEND) ? O_APPEND : O_TRUNC; - + last_slash = strrchr(filename, '/'); if ((ext = strrchr(filename, '.')) && (ext > last_slash)) { @@ -346,6 +349,9 @@ static void mixmonitor_save_prep(struct mixmonitor *mixmonitor, char *filename, if (!(*fs = ast_writefile(filename, ext, NULL, *oflags, 0, 0666))) { ast_log(LOG_ERROR, "Cannot open %s.%s\n", filename, ext); *errflag = 1; + } else { + struct ast_filestream *tmp = *fs; + mixmonitor->mixmonitor_ds->samp_rate = MAX(mixmonitor->mixmonitor_ds->samp_rate, ast_format_rate(&tmp->fmt->format)); } } } @@ -363,13 +369,22 @@ static void *mixmonitor_thread(void *obj) int errflag = 0; struct ast_format format_slin; - ast_format_set(&format_slin, AST_FORMAT_SLINEAR, 0); ast_verb(2, "Begin MixMonitor Recording %s\n", mixmonitor->name); fs = &mixmonitor->mixmonitor_ds->fs; fs_read = &mixmonitor->mixmonitor_ds->fs_read; fs_write = &mixmonitor->mixmonitor_ds->fs_write; + ast_mutex_lock(&mixmonitor->mixmonitor_ds->lock); + mixmonitor_save_prep(mixmonitor, mixmonitor->filename, fs, &oflags, &errflag); + mixmonitor_save_prep(mixmonitor, mixmonitor->filename_read, fs_read, &oflags, &errflag); + mixmonitor_save_prep(mixmonitor, mixmonitor->filename_write, fs_write, &oflags, &errflag); + + ast_format_set(&format_slin, ast_format_slin_by_rate(mixmonitor->mixmonitor_ds->samp_rate), 0); + + ast_mutex_unlock(&mixmonitor->mixmonitor_ds->lock); + + /* The audiohook must enter and exit the loop locked */ ast_audiohook_lock(&mixmonitor->audiohook); while (mixmonitor->audiohook.status == AST_AUDIOHOOK_STATUS_RUNNING && !mixmonitor->mixmonitor_ds->fs_quit) { @@ -393,9 +408,6 @@ static void *mixmonitor_thread(void *obj) if (!ast_test_flag(mixmonitor, MUXFLAG_BRIDGED) || (mixmonitor->autochan->chan && ast_bridged_channel(mixmonitor->autochan->chan))) { ast_mutex_lock(&mixmonitor->mixmonitor_ds->lock); - mixmonitor_save_prep(mixmonitor, mixmonitor->filename, fs, &oflags, &errflag); - mixmonitor_save_prep(mixmonitor, mixmonitor->filename_read, fs_read, &oflags, &errflag); - mixmonitor_save_prep(mixmonitor, mixmonitor->filename_write, fs_write, &oflags, &errflag); /* Write out the frame(s) */ if ((*fs_read) && (fr_read)) { @@ -484,6 +496,8 @@ static int setup_mixmonitor_ds(struct mixmonitor *mixmonitor, struct ast_channel return -1; } + + mixmonitor_ds->samp_rate = 8000; mixmonitor_ds->audiohook = &mixmonitor->audiohook; datastore->data = mixmonitor_ds; -- cgit v1.2.3 From 5911bed3161fa69c67919a669d2522e7bb569fbb Mon Sep 17 00:00:00 2001 From: mnicholson Date: Thu, 14 Jul 2011 17:47:40 +0000 Subject: Merged revisions 328162 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.10 ........ r328162 | mnicholson | 2011-07-14 12:46:32 -0500 (Thu, 14 Jul 2011) | 3 lines tune the v21 preamble detector to properly detect the desired sequence of hits and misses ........ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@328163 f38db490-d61c-443f-a65b-d21fe96a405b --- main/dsp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main/dsp.c b/main/dsp.c index 02cdc9d73..da982d0c1 100644 --- a/main/dsp.c +++ b/main/dsp.c @@ -624,10 +624,10 @@ static int v21_detect(struct ast_dsp *dsp, v21_detect_state_t *s, int16_t *amp, } if (hit) { - if (s->hit_count == 0 || s->miss_count == 3) { + if (s->miss_count == 3) { s->hit_count++; } else { - s->hit_count = 0; + s->hit_count = 1; } s->miss_count = 0; -- cgit v1.2.3 From 8e91a16c45cbfb0bc8ea6fcc7426867c71c79fc7 Mon Sep 17 00:00:00 2001 From: jrose Date: Thu, 14 Jul 2011 19:56:19 +0000 Subject: Merged revisions 328207 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.10 ................ r328207 | jrose | 2011-07-14 14:45:18 -0500 (Thu, 14 Jul 2011) | 13 lines Merged revisions 328205 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.8 ........ r328205 | jrose | 2011-07-14 14:21:02 -0500 (Thu, 14 Jul 2011) | 6 lines Monitor application arguments requirements fixed. Monitor was requiring options in spite of no individual option on Monitor being required. Review: https://reviewboard.asterisk.org/r/1320/ ........ ................ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@328208 f38db490-d61c-443f-a65b-d21fe96a405b --- res/res_monitor.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/res/res_monitor.c b/res/res_monitor.c index d508da13a..86d1d1e02 100644 --- a/res/res_monitor.c +++ b/res/res_monitor.c @@ -650,12 +650,6 @@ static int start_monitor_exec(struct ast_channel *chan, const char *data) AST_APP_ARG(fname_base); AST_APP_ARG(options); ); - - /* Parse arguments. */ - if (ast_strlen_zero(data)) { - ast_log(LOG_ERROR, "Monitor requires an argument\n"); - return 0; - } parse = ast_strdupa(data); AST_STANDARD_APP_ARGS(args, parse); @@ -671,7 +665,9 @@ static int start_monitor_exec(struct ast_channel *chan, const char *data) stream_action &= ~X_REC_OUT; } - arg = strchr(args.format, ':'); + if (args.format) { + arg = strchr(args.format, ':'); + } if (arg) { *arg++ = 0; urlprefix = arg; -- cgit v1.2.3 From e73cab2f3f7846300e1d8a340f8261b16c718226 Mon Sep 17 00:00:00 2001 From: lmadsen Date: Thu, 14 Jul 2011 20:28:54 +0000 Subject: Merged revisions 328247 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.10 ................ r328247 | lmadsen | 2011-07-14 16:25:31 -0400 (Thu, 14 Jul 2011) | 14 lines Merged revisions 328209 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.8 ........ r328209 | lmadsen | 2011-07-14 16:13:06 -0400 (Thu, 14 Jul 2011) | 6 lines Introduce tags in MODULEINFO. This change introduces MODULEINFO into many modules in Asterisk in order to show the community support level for those modules. This is used by changes committed to menuselect by Russell Bryant recently (r917 in menuselect). More information about the support level types and what they mean is available on the wiki at https://wiki.asterisk.org/wiki/display/AST/Asterisk+Module+Support+States ........ ................ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@328259 f38db490-d61c-443f-a65b-d21fe96a405b --- addons/app_mysql.c | 2 ++ addons/app_saycountpl.c | 2 ++ addons/cdr_mysql.c | 2 ++ addons/chan_mobile.c | 1 + addons/chan_ooh323.c | 1 + addons/format_mp3.c | 1 + addons/res_config_mysql.c | 1 + agi/eagi-test.c | 4 ++++ apps/app_adsiprog.c | 1 + apps/app_alarmreceiver.c | 4 ++++ apps/app_amd.c | 3 +++ apps/app_authenticate.c | 4 ++++ apps/app_cdr.c | 4 ++++ apps/app_chanisavail.c | 4 ++++ apps/app_channelredirect.c | 4 ++++ apps/app_chanspy.c | 4 ++++ apps/app_confbridge.c | 4 ++++ apps/app_controlplayback.c | 4 ++++ apps/app_dahdibarge.c | 3 +++ apps/app_dahdiras.c | 1 + apps/app_db.c | 4 ++++ apps/app_dial.c | 1 + apps/app_dictate.c | 4 ++++ apps/app_directed_pickup.c | 4 ++++ apps/app_directory.c | 1 + apps/app_disa.c | 4 ++++ apps/app_dumpchan.c | 4 ++++ apps/app_echo.c | 4 ++++ apps/app_exec.c | 3 +++ apps/app_externalivr.c | 4 ++++ apps/app_fax.c | 1 + apps/app_festival.c | 4 ++++ apps/app_flash.c | 1 + apps/app_followme.c | 1 + apps/app_forkcdr.c | 4 ++++ apps/app_getcpeid.c | 4 ++++ apps/app_ices.c | 4 ++++ apps/app_image.c | 4 ++++ apps/app_ivrdemo.c | 1 + apps/app_jack.c | 1 + apps/app_macro.c | 6 ++++++ apps/app_meetme.c | 3 +++ apps/app_milliwatt.c | 4 ++++ apps/app_minivm.c | 4 ++++ apps/app_mixmonitor.c | 4 ++++ apps/app_morsecode.c | 4 ++++ apps/app_mp3.c | 4 ++++ apps/app_nbscat.c | 4 ++++ apps/app_originate.c | 4 ++++ apps/app_osplookup.c | 1 + apps/app_page.c | 1 + apps/app_parkandannounce.c | 4 ++++ apps/app_playback.c | 6 +++++- apps/app_playtones.c | 4 ++++ apps/app_privacy.c | 4 ++++ apps/app_queue.c | 1 + apps/app_read.c | 4 ++++ apps/app_readexten.c | 4 ++++ apps/app_readfile.c | 6 ++++++ apps/app_record.c | 4 ++++ apps/app_rpt.c | 1 + apps/app_saycounted.c | 1 + apps/app_sayunixtime.c | 4 ++++ apps/app_senddtmf.c | 4 ++++ apps/app_sendtext.c | 4 ++++ apps/app_setcallerid.c | 8 +++++++- apps/app_skel.c | 1 + apps/app_sms.c | 4 ++++ apps/app_softhangup.c | 4 ++++ apps/app_speech_utils.c | 4 ++++ apps/app_stack.c | 1 + apps/app_talkdetect.c | 6 +++++- apps/app_test.c | 4 ++++ apps/app_transfer.c | 4 ++++ apps/app_url.c | 4 ++++ apps/app_userevent.c | 4 ++++ apps/app_verbose.c | 4 ++++ apps/app_voicemail.c | 1 + apps/app_waitforring.c | 4 ++++ apps/app_waitforsilence.c | 4 ++++ apps/app_waituntil.c | 4 ++++ apps/app_while.c | 4 ++++ apps/app_zapateller.c | 4 ++++ bridges/bridge_builtin_features.c | 4 ++++ bridges/bridge_multiplexed.c | 4 ++++ bridges/bridge_simple.c | 4 ++++ bridges/bridge_softmix.c | 4 ++++ cdr/cdr_adaptive_odbc.c | 1 + cdr/cdr_csv.c | 4 ++++ cdr/cdr_custom.c | 4 ++++ cdr/cdr_manager.c | 4 ++++ cdr/cdr_odbc.c | 1 + cdr/cdr_pgsql.c | 1 + cdr/cdr_radius.c | 1 + cdr/cdr_sqlite.c | 3 +++ cdr/cdr_sqlite3_custom.c | 1 + cdr/cdr_syslog.c | 3 ++- cdr/cdr_tds.c | 1 + cel/cel_custom.c | 4 ++++ cel/cel_manager.c | 4 ++++ cel/cel_odbc.c | 1 + cel/cel_pgsql.c | 1 + cel/cel_radius.c | 1 + cel/cel_sqlite3_custom.c | 1 + cel/cel_tds.c | 1 + channels/chan_agent.c | 1 + channels/chan_alsa.c | 1 + channels/chan_bridge.c | 4 ++++ channels/chan_console.c | 1 + channels/chan_dahdi.c | 1 + channels/chan_gtalk.c | 1 + channels/chan_h323.c | 4 +++- channels/chan_iax2.c | 1 + channels/chan_jingle.c | 2 ++ channels/chan_local.c | 4 ++++ channels/chan_mgcp.c | 1 + channels/chan_misdn.c | 1 + channels/chan_multicast_rtp.c | 4 ++++ channels/chan_nbs.c | 1 + channels/chan_oss.c | 1 + channels/chan_phone.c | 1 + channels/chan_sip.c | 1 + channels/chan_skinny.c | 3 +++ channels/chan_unistim.c | 4 ++++ channels/chan_usbradio.c | 1 + channels/chan_vpb.cc | 2 ++ codecs/codec_a_mu.c | 4 ++++ codecs/codec_adpcm.c | 4 ++++ codecs/codec_alaw.c | 4 ++++ codecs/codec_g722.c | 4 ++++ codecs/codec_g726.c | 4 ++++ codecs/codec_gsm.c | 1 + codecs/codec_ilbc.c | 1 + codecs/codec_lpc10.c | 4 ++++ codecs/codec_resample.c | 5 +++++ codecs/codec_speex.c | 1 + codecs/codec_ulaw.c | 4 ++++ formats/format_g719.c | 4 ++++ formats/format_g723.c | 4 ++++ formats/format_g726.c | 4 ++++ formats/format_g729.c | 4 ++++ formats/format_gsm.c | 4 ++++ formats/format_h263.c | 4 ++++ formats/format_h264.c | 4 ++++ formats/format_ilbc.c | 4 ++++ formats/format_jpeg.c | 4 ++++ formats/format_ogg_vorbis.c | 1 + formats/format_pcm.c | 4 ++++ formats/format_siren14.c | 4 ++++ formats/format_siren7.c | 4 ++++ formats/format_sln.c | 4 ++++ formats/format_vox.c | 4 ++++ formats/format_wav.c | 4 ++++ formats/format_wav_gsm.c | 4 ++++ funcs/func_aes.c | 1 + funcs/func_audiohookinherit.c | 4 ++++ funcs/func_base64.c | 4 ++++ funcs/func_blacklist.c | 4 ++++ funcs/func_callcompletion.c | 4 ++++ funcs/func_callerid.c | 4 ++++ funcs/func_cdr.c | 4 ++++ funcs/func_channel.c | 4 ++++ funcs/func_config.c | 4 ++++ funcs/func_curl.c | 1 + funcs/func_cut.c | 4 ++++ funcs/func_db.c | 4 ++++ funcs/func_devstate.c | 4 ++++ funcs/func_dialgroup.c | 4 ++++ funcs/func_dialplan.c | 4 ++++ funcs/func_enum.c | 4 ++++ funcs/func_env.c | 4 ++++ funcs/func_extstate.c | 4 ++++ funcs/func_frame_trace.c | 4 ++++ funcs/func_global.c | 4 ++++ funcs/func_groupcount.c | 4 ++++ funcs/func_iconv.c | 3 ++- funcs/func_lock.c | 4 ++++ funcs/func_logic.c | 4 ++++ funcs/func_math.c | 4 ++++ funcs/func_md5.c | 4 ++++ funcs/func_module.c | 5 +++++ funcs/func_odbc.c | 1 + funcs/func_pitchshift.c | 4 ++++ funcs/func_rand.c | 4 ++++ funcs/func_sha1.c | 4 ++++ funcs/func_shell.c | 4 ++++ funcs/func_speex.c | 1 + funcs/func_sprintf.c | 4 ++++ funcs/func_srv.c | 4 ++++ funcs/func_strings.c | 4 ++++ funcs/func_sysinfo.c | 4 ++++ funcs/func_timeout.c | 4 ++++ funcs/func_uri.c | 4 ++++ funcs/func_version.c | 4 ++++ funcs/func_vmcount.c | 4 ++++ funcs/func_volume.c | 4 ++++ main/features.c | 4 ++++ main/http.c | 4 ++++ main/manager.c | 4 ++++ pbx/pbx_ael.c | 1 + pbx/pbx_config.c | 4 ++++ pbx/pbx_dundi.c | 1 + pbx/pbx_loopback.c | 4 ++++ pbx/pbx_lua.c | 1 + pbx/pbx_realtime.c | 4 ++++ pbx/pbx_spool.c | 4 ++++ res/res_adsi.c | 4 ++++ res/res_ael_share.c | 4 ++++ res/res_agi.c | 4 ++++ res/res_ais.c | 1 + res/res_calendar.c | 4 ++++ res/res_calendar_caldav.c | 2 ++ res/res_calendar_ews.c | 2 ++ res/res_calendar_exchange.c | 2 ++ res/res_calendar_icalendar.c | 2 ++ res/res_clialiases.c | 3 +++ res/res_clioriginate.c | 4 ++++ res/res_config_curl.c | 1 + res/res_config_ldap.c | 1 + res/res_config_odbc.c | 1 + res/res_config_pgsql.c | 1 + res/res_config_sqlite.c | 1 + res/res_convert.c | 4 ++++ res/res_crypto.c | 1 + res/res_fax.c | 4 ++++ res/res_fax_spandsp.c | 1 + res/res_http_post.c | 1 + res/res_jabber.c | 1 + res/res_limit.c | 3 +++ res/res_monitor.c | 14 +++++++++++--- res/res_musiconhold.c | 1 + res/res_mutestream.c | 4 ++++ res/res_odbc.c | 1 + res/res_phoneprov.c | 4 ++++ res/res_pktccops.c | 1 + res/res_realtime.c | 4 ++++ res/res_rtp_asterisk.c | 4 ++++ res/res_rtp_multicast.c | 4 ++++ res/res_security_log.c | 4 ++++ res/res_smdi.c | 4 ++++ res/res_snmp.c | 1 + res/res_speech.c | 4 ++++ res/res_srtp.c | 3 ++- res/res_stun_monitor.c | 4 ++++ res/res_timing_dahdi.c | 1 + res/res_timing_kqueue.c | 1 + res/res_timing_pthread.c | 4 ++++ res/res_timing_timerfd.c | 1 + tests/test_acl.c | 1 + tests/test_amihooks.c | 1 + tests/test_aoc.c | 1 + tests/test_app.c | 1 + tests/test_ast_format_str_reduce.c | 1 + tests/test_astobj2.c | 1 + tests/test_devicestate.c | 1 + tests/test_dlinklists.c | 1 + tests/test_event.c | 1 + tests/test_expr.c | 1 + tests/test_func_file.c | 1 + tests/test_gosub.c | 1 + tests/test_heap.c | 1 + tests/test_locale.c | 1 + tests/test_logger.c | 1 + tests/test_pbx.c | 1 + tests/test_poll.c | 1 + tests/test_sched.c | 1 + tests/test_security_events.c | 1 + tests/test_skel.c | 1 + tests/test_stringfields.c | 1 + tests/test_strings.c | 1 + tests/test_substitution.c | 1 + tests/test_time.c | 1 + tests/test_utils.c | 1 + utils/ael_main.c | 5 +++++ utils/astcanary.c | 4 ++++ utils/astman.c | 4 ++++ utils/check_expr.c | 4 ++++ utils/conf2ael.c | 1 + utils/extconf.c | 5 +++++ utils/hashtest.c | 4 ++++ utils/hashtest2.c | 4 ++++ utils/muted.c | 4 ++++ utils/refcounter.c | 4 ++++ utils/smsq.c | 4 ++++ utils/stereorize.c | 4 ++++ utils/streamplayer.c | 4 ++++ 286 files changed, 834 insertions(+), 10 deletions(-) diff --git a/addons/app_mysql.c b/addons/app_mysql.c index 589b23823..5649166a7 100644 --- a/addons/app_mysql.c +++ b/addons/app_mysql.c @@ -26,6 +26,8 @@ /*** MODULEINFO mysqlclient no + deprecated + func_odbc ***/ #include "asterisk.h" diff --git a/addons/app_saycountpl.c b/addons/app_saycountpl.c index 915779899..b4441f24f 100644 --- a/addons/app_saycountpl.c +++ b/addons/app_saycountpl.c @@ -22,6 +22,8 @@ /*** MODULEINFO no + deprecated + say.conf ***/ #include "asterisk.h" diff --git a/addons/cdr_mysql.c b/addons/cdr_mysql.c index 60abae2d9..ecdfaea0b 100644 --- a/addons/cdr_mysql.c +++ b/addons/cdr_mysql.c @@ -36,6 +36,8 @@ /*** MODULEINFO mysqlclient no + deprecated + cdr_adaptive_odbc ***/ #include "asterisk.h" diff --git a/addons/chan_mobile.c b/addons/chan_mobile.c index 5495c7f22..7c1492729 100644 --- a/addons/chan_mobile.c +++ b/addons/chan_mobile.c @@ -28,6 +28,7 @@ /*** MODULEINFO bluetooth no + extended ***/ #include "asterisk.h" diff --git a/addons/chan_ooh323.c b/addons/chan_ooh323.c index 552b8f22c..32d1cf7d4 100644 --- a/addons/chan_ooh323.c +++ b/addons/chan_ooh323.c @@ -19,6 +19,7 @@ /*** MODULEINFO no + extended ***/ #include "chan_ooh323.h" diff --git a/addons/format_mp3.c b/addons/format_mp3.c index d59411d6c..5584f3e06 100644 --- a/addons/format_mp3.c +++ b/addons/format_mp3.c @@ -29,6 +29,7 @@ /*** MODULEINFO no + extended ***/ #include "asterisk.h" diff --git a/addons/res_config_mysql.c b/addons/res_config_mysql.c index eaf7209f9..d393de6c1 100644 --- a/addons/res_config_mysql.c +++ b/addons/res_config_mysql.c @@ -25,6 +25,7 @@ /*** MODULEINFO mysqlclient no + extended ***/ #include "asterisk.h" diff --git a/agi/eagi-test.c b/agi/eagi-test.c index dc2d7fa1a..7f24d1f23 100644 --- a/agi/eagi-test.c +++ b/agi/eagi-test.c @@ -5,6 +5,10 @@ * with no warranty of any kind */ +/*** MODULEINFO + extended + ***/ + #include "asterisk.h" #define AUDIO_FILENO (STDERR_FILENO + 1) diff --git a/apps/app_adsiprog.c b/apps/app_adsiprog.c index c138f0429..430d8258d 100644 --- a/apps/app_adsiprog.c +++ b/apps/app_adsiprog.c @@ -27,6 +27,7 @@ /*** MODULEINFO res_adsi + extended ***/ #include "asterisk.h" diff --git a/apps/app_alarmreceiver.c b/apps/app_alarmreceiver.c index 6936cb5a0..1a4f9220f 100644 --- a/apps/app_alarmreceiver.c +++ b/apps/app_alarmreceiver.c @@ -29,6 +29,10 @@ * \ingroup applications */ +/*** MODULEINFO + extended + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_amd.c b/apps/app_amd.c index 7c4e2a47a..35c5005f7 100644 --- a/apps/app_amd.c +++ b/apps/app_amd.c @@ -26,6 +26,9 @@ * \author Claude Klimos (claude.klimos@aheeva.com) */ +/*** MODULEINFO + extended + ***/ #include "asterisk.h" diff --git a/apps/app_authenticate.c b/apps/app_authenticate.c index 416ea432d..8b5fa11a6 100644 --- a/apps/app_authenticate.c +++ b/apps/app_authenticate.c @@ -25,6 +25,10 @@ * \ingroup applications */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_cdr.c b/apps/app_cdr.c index 70036ad82..2f227b049 100644 --- a/apps/app_cdr.c +++ b/apps/app_cdr.c @@ -25,6 +25,10 @@ * \ingroup applications */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_chanisavail.c b/apps/app_chanisavail.c index 5dd4a1f60..86ce34177 100644 --- a/apps/app_chanisavail.c +++ b/apps/app_chanisavail.c @@ -27,6 +27,10 @@ * \ingroup applications */ +/*** MODULEINFO + extended + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_channelredirect.c b/apps/app_channelredirect.c index 57c9234ef..8fe543dab 100644 --- a/apps/app_channelredirect.c +++ b/apps/app_channelredirect.c @@ -23,6 +23,10 @@ * \ingroup applications */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_chanspy.c b/apps/app_chanspy.c index c90a7907a..92e0ba513 100644 --- a/apps/app_chanspy.c +++ b/apps/app_chanspy.c @@ -29,6 +29,10 @@ * \ingroup applications */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_confbridge.c b/apps/app_confbridge.c index 0ca2c6e8d..4897d065e 100644 --- a/apps/app_confbridge.c +++ b/apps/app_confbridge.c @@ -28,6 +28,10 @@ * \ingroup applications */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_controlplayback.c b/apps/app_controlplayback.c index bbeea3037..1e2e6fbc2 100644 --- a/apps/app_controlplayback.c +++ b/apps/app_controlplayback.c @@ -25,6 +25,10 @@ * \ingroup applications */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_dahdibarge.c b/apps/app_dahdibarge.c index 082405e80..bb0120cbc 100644 --- a/apps/app_dahdibarge.c +++ b/apps/app_dahdibarge.c @@ -33,6 +33,9 @@ /*** MODULEINFO dahdi + no + deprecated + app_chanspy ***/ #include "asterisk.h" diff --git a/apps/app_dahdiras.c b/apps/app_dahdiras.c index b467b16b8..fbaf98450 100644 --- a/apps/app_dahdiras.c +++ b/apps/app_dahdiras.c @@ -27,6 +27,7 @@ /*** MODULEINFO dahdi + extended ***/ #include "asterisk.h" diff --git a/apps/app_db.c b/apps/app_db.c index 99679e71b..1fa24088e 100644 --- a/apps/app_db.c +++ b/apps/app_db.c @@ -28,6 +28,10 @@ * \ingroup applications */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_dial.c b/apps/app_dial.c index d3b8009de..f144d48ea 100644 --- a/apps/app_dial.c +++ b/apps/app_dial.c @@ -27,6 +27,7 @@ /*** MODULEINFO chan_local + core ***/ diff --git a/apps/app_dictate.c b/apps/app_dictate.c index 5bf439d16..b50fbb044 100644 --- a/apps/app_dictate.c +++ b/apps/app_dictate.c @@ -27,6 +27,10 @@ * \ingroup applications */ +/*** MODULEINFO + extended + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_directed_pickup.c b/apps/app_directed_pickup.c index 63a7621ff..c2bdf5131 100644 --- a/apps/app_directed_pickup.c +++ b/apps/app_directed_pickup.c @@ -29,6 +29,10 @@ * \ingroup applications */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_directory.c b/apps/app_directory.c index 8451eea08..dccae948b 100644 --- a/apps/app_directory.c +++ b/apps/app_directory.c @@ -27,6 +27,7 @@ /*** MODULEINFO app_voicemail + core ***/ #include "asterisk.h" diff --git a/apps/app_disa.c b/apps/app_disa.c index 20c9ce48c..3ca080009 100644 --- a/apps/app_disa.c +++ b/apps/app_disa.c @@ -26,6 +26,10 @@ * \ingroup applications */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_dumpchan.c b/apps/app_dumpchan.c index f9e657201..0a9fa6888 100644 --- a/apps/app_dumpchan.c +++ b/apps/app_dumpchan.c @@ -28,6 +28,10 @@ * \ingroup applications */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_echo.c b/apps/app_echo.c index ab991427d..48e6714e2 100644 --- a/apps/app_echo.c +++ b/apps/app_echo.c @@ -25,6 +25,10 @@ * \ingroup applications */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_exec.c b/apps/app_exec.c index 2a4da1e2f..ab9a9aece 100644 --- a/apps/app_exec.c +++ b/apps/app_exec.c @@ -26,6 +26,9 @@ * \ingroup applications */ +/*** MODULEINFO + core + ***/ #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_externalivr.c b/apps/app_externalivr.c index 258a1e5c7..4eb99c1bb 100644 --- a/apps/app_externalivr.c +++ b/apps/app_externalivr.c @@ -31,6 +31,10 @@ * \ingroup applications */ +/*** MODULEINFO + extended + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_fax.c b/apps/app_fax.c index 0d59dfa3a..e2085cbbb 100644 --- a/apps/app_fax.c +++ b/apps/app_fax.c @@ -16,6 +16,7 @@ no spandsp res_fax + extended ***/ #include "asterisk.h" diff --git a/apps/app_festival.c b/apps/app_festival.c index a30302fa7..d609b3fe4 100644 --- a/apps/app_festival.c +++ b/apps/app_festival.c @@ -27,6 +27,10 @@ * \ingroup applications */ +/*** MODULEINFO + extended + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_flash.c b/apps/app_flash.c index dedadfeab..3273b5b0a 100644 --- a/apps/app_flash.c +++ b/apps/app_flash.c @@ -27,6 +27,7 @@ /*** MODULEINFO dahdi + core ***/ #include "asterisk.h" diff --git a/apps/app_followme.c b/apps/app_followme.c index 7ed874928..a72ef307a 100644 --- a/apps/app_followme.c +++ b/apps/app_followme.c @@ -30,6 +30,7 @@ /*** MODULEINFO chan_local + core ***/ #include "asterisk.h" diff --git a/apps/app_forkcdr.c b/apps/app_forkcdr.c index 12d504914..ffeeca8ec 100644 --- a/apps/app_forkcdr.c +++ b/apps/app_forkcdr.c @@ -26,6 +26,10 @@ * \ingroup applications */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_getcpeid.c b/apps/app_getcpeid.c index 220708156..7f59976eb 100644 --- a/apps/app_getcpeid.c +++ b/apps/app_getcpeid.c @@ -25,6 +25,10 @@ * \ingroup applications */ +/*** MODULEINFO + extended + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_ices.c b/apps/app_ices.c index 729375313..52c03ae09 100644 --- a/apps/app_ices.c +++ b/apps/app_ices.c @@ -26,6 +26,10 @@ * * \ingroup applications */ + +/*** MODULEINFO + extended + ***/ #include "asterisk.h" diff --git a/apps/app_image.c b/apps/app_image.c index af4abd7e9..160a28569 100644 --- a/apps/app_image.c +++ b/apps/app_image.c @@ -24,6 +24,10 @@ * * \ingroup applications */ + +/*** MODULEINFO + extended + ***/ #include "asterisk.h" diff --git a/apps/app_ivrdemo.c b/apps/app_ivrdemo.c index a9c61209a..d035df91f 100644 --- a/apps/app_ivrdemo.c +++ b/apps/app_ivrdemo.c @@ -27,6 +27,7 @@ /*** MODULEINFO no + extended ***/ #include "asterisk.h" diff --git a/apps/app_jack.c b/apps/app_jack.c index 07ab8da79..893a5dec0 100644 --- a/apps/app_jack.c +++ b/apps/app_jack.c @@ -37,6 +37,7 @@ /*** MODULEINFO jack resample + extended ***/ #include "asterisk.h" diff --git a/apps/app_macro.c b/apps/app_macro.c index aecc0327e..3bbfe20d6 100644 --- a/apps/app_macro.c +++ b/apps/app_macro.c @@ -25,6 +25,12 @@ * \ingroup applications */ +/*** MODULEINFO + no + deprecated + app_stack (GoSub) + */ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_meetme.c b/apps/app_meetme.c index 40f5b0ee4..73aaefc0e 100644 --- a/apps/app_meetme.c +++ b/apps/app_meetme.c @@ -31,6 +31,9 @@ /*** MODULEINFO dahdi + no + deprecated + app_confbridge ***/ #include "asterisk.h" diff --git a/apps/app_milliwatt.c b/apps/app_milliwatt.c index 26cba3c40..dc37e7e89 100644 --- a/apps/app_milliwatt.c +++ b/apps/app_milliwatt.c @@ -25,6 +25,10 @@ * \ingroup applications */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_minivm.c b/apps/app_minivm.c index 124a04d4f..3445b7ec6 100644 --- a/apps/app_minivm.c +++ b/apps/app_minivm.c @@ -141,6 +141,10 @@ * Back: \ref App_minivm */ +/*** MODULEINFO + extended + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_mixmonitor.c b/apps/app_mixmonitor.c index 05798ffa3..c263b1445 100644 --- a/apps/app_mixmonitor.c +++ b/apps/app_mixmonitor.c @@ -33,6 +33,10 @@ * Anthony Minessale II */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_morsecode.c b/apps/app_morsecode.c index a234cd431..67e242f7b 100644 --- a/apps/app_morsecode.c +++ b/apps/app_morsecode.c @@ -24,6 +24,10 @@ * \ingroup applications */ +/*** MODULEINFO + extended + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_mp3.c b/apps/app_mp3.c index f8c5a0578..922d42a5b 100644 --- a/apps/app_mp3.c +++ b/apps/app_mp3.c @@ -27,6 +27,10 @@ * * \ingroup applications */ + +/*** MODULEINFO + extended + ***/ #include "asterisk.h" diff --git a/apps/app_nbscat.c b/apps/app_nbscat.c index 2bbde630e..093653495 100644 --- a/apps/app_nbscat.c +++ b/apps/app_nbscat.c @@ -24,6 +24,10 @@ * * \ingroup applications */ + +/*** MODULEINFO + extended + ***/ #include "asterisk.h" diff --git a/apps/app_originate.c b/apps/app_originate.c index bc811d958..5cfd41386 100644 --- a/apps/app_originate.c +++ b/apps/app_originate.c @@ -32,6 +32,10 @@ * Set options for call files. */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_osplookup.c b/apps/app_osplookup.c index 239d6d501..9dbf39752 100644 --- a/apps/app_osplookup.c +++ b/apps/app_osplookup.c @@ -31,6 +31,7 @@ /*** MODULEINFO osptk openssl + extended ***/ #include "asterisk.h" diff --git a/apps/app_page.c b/apps/app_page.c index 656dcf571..cf2101446 100644 --- a/apps/app_page.c +++ b/apps/app_page.c @@ -28,6 +28,7 @@ /*** MODULEINFO dahdi app_meetme + core ***/ #include "asterisk.h" diff --git a/apps/app_parkandannounce.c b/apps/app_parkandannounce.c index fb3e713e1..70633745b 100644 --- a/apps/app_parkandannounce.c +++ b/apps/app_parkandannounce.c @@ -29,6 +29,10 @@ * \ingroup applications */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_playback.c b/apps/app_playback.c index 1e198470e..ea4d90b19 100644 --- a/apps/app_playback.c +++ b/apps/app_playback.c @@ -24,7 +24,11 @@ * * \ingroup applications */ - + +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_playtones.c b/apps/app_playtones.c index c9c0fbb99..1e142de23 100644 --- a/apps/app_playtones.c +++ b/apps/app_playtones.c @@ -25,6 +25,10 @@ * \ingroup applications */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_privacy.c b/apps/app_privacy.c index 6a6c1a437..6b191771c 100644 --- a/apps/app_privacy.c +++ b/apps/app_privacy.c @@ -25,6 +25,10 @@ * \ingroup applications */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_queue.c b/apps/app_queue.c index 9442ce649..fdb36fed1 100644 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -58,6 +58,7 @@ /*** MODULEINFO res_monitor + core ***/ #include "asterisk.h" diff --git a/apps/app_read.c b/apps/app_read.c index a5e4a6434..813d37565 100644 --- a/apps/app_read.c +++ b/apps/app_read.c @@ -24,6 +24,10 @@ * * \ingroup applications */ + +/*** MODULEINFO + core + ***/ #include "asterisk.h" diff --git a/apps/app_readexten.c b/apps/app_readexten.c index 5e8159b35..94dc1e1f8 100644 --- a/apps/app_readexten.c +++ b/apps/app_readexten.c @@ -23,6 +23,10 @@ * * \ingroup applications */ + +/*** MODULEINFO + core + ***/ #include "asterisk.h" diff --git a/apps/app_readfile.c b/apps/app_readfile.c index 8c3bcae64..d031406c2 100644 --- a/apps/app_readfile.c +++ b/apps/app_readfile.c @@ -25,6 +25,12 @@ * \ingroup applications */ +/*** MODULEINFO + no + deprecated + func_env (FILE()) + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_record.c b/apps/app_record.c index a192b1adc..6098ca729 100644 --- a/apps/app_record.c +++ b/apps/app_record.c @@ -24,6 +24,10 @@ * * \ingroup applications */ + +/*** MODULEINFO + core + ***/ #include "asterisk.h" diff --git a/apps/app_rpt.c b/apps/app_rpt.c index 990f05423..f37083695 100644 --- a/apps/app_rpt.c +++ b/apps/app_rpt.c @@ -155,6 +155,7 @@ dahdi tonezone no + extended ***/ /* Un-comment the following to include support for MDC-1200 digital tone diff --git a/apps/app_saycounted.c b/apps/app_saycounted.c index c840d8bb0..be3ac65ef 100644 --- a/apps/app_saycounted.c +++ b/apps/app_saycounted.c @@ -26,6 +26,7 @@ /*** MODULEINFO no + extended ***/ /*** DOCUMENTATION diff --git a/apps/app_sayunixtime.c b/apps/app_sayunixtime.c index 55afdf463..fc1b238dd 100644 --- a/apps/app_sayunixtime.c +++ b/apps/app_sayunixtime.c @@ -25,6 +25,10 @@ * \ingroup applications */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_senddtmf.c b/apps/app_senddtmf.c index 2af67a299..5c8425a0f 100644 --- a/apps/app_senddtmf.c +++ b/apps/app_senddtmf.c @@ -24,6 +24,10 @@ * * \ingroup applications */ + +/*** MODULEINFO + core + ***/ #include "asterisk.h" diff --git a/apps/app_sendtext.c b/apps/app_sendtext.c index 2624fe505..a723de5b9 100644 --- a/apps/app_sendtext.c +++ b/apps/app_sendtext.c @@ -26,6 +26,10 @@ * * \ingroup applications */ + +/*** MODULEINFO + core + ***/ #include "asterisk.h" diff --git a/apps/app_setcallerid.c b/apps/app_setcallerid.c index 666e46ff4..cfcd2b47d 100644 --- a/apps/app_setcallerid.c +++ b/apps/app_setcallerid.c @@ -24,7 +24,13 @@ * * \ingroup applications */ - + +/*** MODULEINFO + no + deprecated + func_callerid + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_skel.c b/apps/app_skel.c index c58d451e4..bd3b546e0 100644 --- a/apps/app_skel.c +++ b/apps/app_skel.c @@ -31,6 +31,7 @@ /*** MODULEINFO no + core ***/ #include "asterisk.h" diff --git a/apps/app_sms.c b/apps/app_sms.c index 07af71d1c..e3f8c5260 100644 --- a/apps/app_sms.c +++ b/apps/app_sms.c @@ -34,6 +34,10 @@ * Not fully tested, under development */ +/*** MODULEINFO + extended + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_softhangup.c b/apps/app_softhangup.c index 1c880b4e8..cdfd7c147 100644 --- a/apps/app_softhangup.c +++ b/apps/app_softhangup.c @@ -25,6 +25,10 @@ * \ingroup applications */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_speech_utils.c b/apps/app_speech_utils.c index fe99157e9..637aac613 100644 --- a/apps/app_speech_utils.c +++ b/apps/app_speech_utils.c @@ -25,6 +25,10 @@ * \ingroup applications */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$"); diff --git a/apps/app_stack.c b/apps/app_stack.c index 10a1af48d..c5f0b6aff 100644 --- a/apps/app_stack.c +++ b/apps/app_stack.c @@ -27,6 +27,7 @@ /*** MODULEINFO res_agi + core ***/ #include "asterisk.h" diff --git a/apps/app_talkdetect.c b/apps/app_talkdetect.c index 545261c72..9eb800287 100644 --- a/apps/app_talkdetect.c +++ b/apps/app_talkdetect.c @@ -24,7 +24,11 @@ * * \ingroup applications */ - + +/*** MODULEINFO + extended + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_test.c b/apps/app_test.c index 7d0214a59..32b6fc02b 100644 --- a/apps/app_test.c +++ b/apps/app_test.c @@ -27,6 +27,10 @@ * \ingroup applications */ +/*** MODULEINFO + extended + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_transfer.c b/apps/app_transfer.c index ad6e8011e..f072eb27f 100644 --- a/apps/app_transfer.c +++ b/apps/app_transfer.c @@ -27,6 +27,10 @@ * \ingroup applications */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_url.c b/apps/app_url.c index 533c11212..f33890c76 100644 --- a/apps/app_url.c +++ b/apps/app_url.c @@ -24,6 +24,10 @@ * * \ingroup applications */ + +/*** MODULEINFO + extended + ***/ #include "asterisk.h" diff --git a/apps/app_userevent.c b/apps/app_userevent.c index 1e1e4a9cd..59bea65df 100644 --- a/apps/app_userevent.c +++ b/apps/app_userevent.c @@ -21,6 +21,10 @@ * \ingroup applications */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_verbose.c b/apps/app_verbose.c index 85f79f892..ca1a010cc 100644 --- a/apps/app_verbose.c +++ b/apps/app_verbose.c @@ -24,6 +24,10 @@ * \ingroup applications */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c index 1f72ee1d9..764a44520 100644 --- a/apps/app_voicemail.c +++ b/apps/app_voicemail.c @@ -40,6 +40,7 @@ /*** MODULEINFO res_adsi res_smdi + core ***/ /*** MAKEOPTS diff --git a/apps/app_waitforring.c b/apps/app_waitforring.c index 7ddc9db12..bd0353b07 100644 --- a/apps/app_waitforring.c +++ b/apps/app_waitforring.c @@ -25,6 +25,10 @@ * \ingroup applications */ +/*** MODULEINFO + extended + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_waitforsilence.c b/apps/app_waitforsilence.c index fe4b1e14d..a920e11a8 100644 --- a/apps/app_waitforsilence.c +++ b/apps/app_waitforsilence.c @@ -38,6 +38,10 @@ * \ingroup applications */ +/*** MODULEINFO + extended + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_waituntil.c b/apps/app_waituntil.c index 04905edc5..d1f4bb103 100644 --- a/apps/app_waituntil.c +++ b/apps/app_waituntil.c @@ -25,6 +25,10 @@ * \ingroup applications */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_while.c b/apps/app_while.c index 80359359e..45bd65594 100644 --- a/apps/app_while.c +++ b/apps/app_while.c @@ -25,6 +25,10 @@ * \ingroup applications */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/apps/app_zapateller.c b/apps/app_zapateller.c index 6af9b963c..b102ea426 100644 --- a/apps/app_zapateller.c +++ b/apps/app_zapateller.c @@ -24,6 +24,10 @@ * * \ingroup applications */ + +/*** MODULEINFO + extended + ***/ #include "asterisk.h" diff --git a/bridges/bridge_builtin_features.c b/bridges/bridge_builtin_features.c index 2b21933e2..802e9ae30 100644 --- a/bridges/bridge_builtin_features.c +++ b/bridges/bridge_builtin_features.c @@ -25,6 +25,10 @@ * \ingroup bridges */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/bridges/bridge_multiplexed.c b/bridges/bridge_multiplexed.c index 5a3de43d8..e004dfd40 100644 --- a/bridges/bridge_multiplexed.c +++ b/bridges/bridge_multiplexed.c @@ -25,6 +25,10 @@ * \ingroup bridges */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/bridges/bridge_simple.c b/bridges/bridge_simple.c index 72b91087a..14864df4d 100644 --- a/bridges/bridge_simple.c +++ b/bridges/bridge_simple.c @@ -25,6 +25,10 @@ * \ingroup bridges */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/bridges/bridge_softmix.c b/bridges/bridge_softmix.c index 00b0556d0..7632f36ee 100644 --- a/bridges/bridge_softmix.c +++ b/bridges/bridge_softmix.c @@ -27,6 +27,10 @@ * \ingroup bridges */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/cdr/cdr_adaptive_odbc.c b/cdr/cdr_adaptive_odbc.c index db19896f2..cb9bd0d52 100644 --- a/cdr/cdr_adaptive_odbc.c +++ b/cdr/cdr_adaptive_odbc.c @@ -26,6 +26,7 @@ /*** MODULEINFO res_odbc + core ***/ #include "asterisk.h" diff --git a/cdr/cdr_csv.c b/cdr/cdr_csv.c index 60b965880..068b7a9a2 100644 --- a/cdr/cdr_csv.c +++ b/cdr/cdr_csv.c @@ -28,6 +28,10 @@ * \ingroup cdr_drivers */ +/*** MODULEINFO + extended + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/cdr/cdr_custom.c b/cdr/cdr_custom.c index c834814e8..6a2751d1f 100644 --- a/cdr/cdr_custom.c +++ b/cdr/cdr_custom.c @@ -30,6 +30,10 @@ * \ingroup cdr_drivers */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/cdr/cdr_manager.c b/cdr/cdr_manager.c index 4cc818365..d5106b158 100644 --- a/cdr/cdr_manager.c +++ b/cdr/cdr_manager.c @@ -25,6 +25,10 @@ * \ingroup cdr_drivers */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/cdr/cdr_odbc.c b/cdr/cdr_odbc.c index f77d60b2c..45f8bca79 100644 --- a/cdr/cdr_odbc.c +++ b/cdr/cdr_odbc.c @@ -30,6 +30,7 @@ /*** MODULEINFO res_odbc + extended ***/ #include "asterisk.h" diff --git a/cdr/cdr_pgsql.c b/cdr/cdr_pgsql.c index 826b09f3f..e857baa87 100644 --- a/cdr/cdr_pgsql.c +++ b/cdr/cdr_pgsql.c @@ -35,6 +35,7 @@ /*** MODULEINFO pgsql + extended ***/ #include "asterisk.h" diff --git a/cdr/cdr_radius.c b/cdr/cdr_radius.c index bf613284d..140e7a01c 100644 --- a/cdr/cdr_radius.c +++ b/cdr/cdr_radius.c @@ -29,6 +29,7 @@ /*** MODULEINFO radius + extended ***/ #include "asterisk.h" diff --git a/cdr/cdr_sqlite.c b/cdr/cdr_sqlite.c index 2dcdf96a4..47d1a5192 100644 --- a/cdr/cdr_sqlite.c +++ b/cdr/cdr_sqlite.c @@ -36,6 +36,9 @@ /*** MODULEINFO sqlite + no + deprecated + sqlite3_custom ***/ #include "asterisk.h" diff --git a/cdr/cdr_sqlite3_custom.c b/cdr/cdr_sqlite3_custom.c index c2dae7a7b..97d1a309e 100644 --- a/cdr/cdr_sqlite3_custom.c +++ b/cdr/cdr_sqlite3_custom.c @@ -34,6 +34,7 @@ /*** MODULEINFO sqlite3 + extended ***/ #include "asterisk.h" diff --git a/cdr/cdr_syslog.c b/cdr/cdr_syslog.c index 63545208e..b6fc90e0d 100644 --- a/cdr/cdr_syslog.c +++ b/cdr/cdr_syslog.c @@ -28,7 +28,8 @@ */ /*** MODULEINFO - syslog + syslog + core ***/ #include "asterisk.h" diff --git a/cdr/cdr_tds.c b/cdr/cdr_tds.c index fca815fd8..eead023fb 100644 --- a/cdr/cdr_tds.c +++ b/cdr/cdr_tds.c @@ -59,6 +59,7 @@ CREATE TABLE [dbo].[cdr] ( /*** MODULEINFO freetds + extended ***/ #include "asterisk.h" diff --git a/cel/cel_custom.c b/cel/cel_custom.c index 9f7d589b4..54b1e4f5e 100644 --- a/cel/cel_custom.c +++ b/cel/cel_custom.c @@ -29,6 +29,10 @@ * \ingroup cel_drivers */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/cel/cel_manager.c b/cel/cel_manager.c index fcf20766f..551b861d0 100644 --- a/cel/cel_manager.c +++ b/cel/cel_manager.c @@ -29,6 +29,10 @@ * \ingroup cel_drivers */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/cel/cel_odbc.c b/cel/cel_odbc.c index d298f1ba2..f0c70f53c 100644 --- a/cel/cel_odbc.c +++ b/cel/cel_odbc.c @@ -28,6 +28,7 @@ /*** MODULEINFO res_odbc + core ***/ #include "asterisk.h" diff --git a/cel/cel_pgsql.c b/cel/cel_pgsql.c index 62438d856..4a67edd85 100644 --- a/cel/cel_pgsql.c +++ b/cel/cel_pgsql.c @@ -39,6 +39,7 @@ /*** MODULEINFO pgsql + extended ***/ #include "asterisk.h" diff --git a/cel/cel_radius.c b/cel/cel_radius.c index f5ccb5f8a..7cd7726e1 100644 --- a/cel/cel_radius.c +++ b/cel/cel_radius.c @@ -28,6 +28,7 @@ /*** MODULEINFO radius + extended ***/ #include "asterisk.h" diff --git a/cel/cel_sqlite3_custom.c b/cel/cel_sqlite3_custom.c index 18e2a9f1a..2906ed9ee 100644 --- a/cel/cel_sqlite3_custom.c +++ b/cel/cel_sqlite3_custom.c @@ -36,6 +36,7 @@ /*** MODULEINFO sqlite3 + extended ***/ #include "asterisk.h" diff --git a/cel/cel_tds.c b/cel/cel_tds.c index 37992bf5e..f5686c9b0 100644 --- a/cel/cel_tds.c +++ b/cel/cel_tds.c @@ -56,6 +56,7 @@ CREATE TABLE [dbo].[cdr] ( /*** MODULEINFO freetds + extended ***/ #include "asterisk.h" diff --git a/channels/chan_agent.c b/channels/chan_agent.c index 0dc930f9d..044524669 100644 --- a/channels/chan_agent.c +++ b/channels/chan_agent.c @@ -33,6 +33,7 @@ /*** MODULEINFO chan_local res_monitor + core ***/ #include "asterisk.h" diff --git a/channels/chan_alsa.c b/channels/chan_alsa.c index b1e7c30e5..b51c942af 100644 --- a/channels/chan_alsa.c +++ b/channels/chan_alsa.c @@ -29,6 +29,7 @@ /*** MODULEINFO alsa + extended ***/ #include "asterisk.h" diff --git a/channels/chan_bridge.c b/channels/chan_bridge.c index 7b01909ae..36f23a500 100644 --- a/channels/chan_bridge.c +++ b/channels/chan_bridge.c @@ -25,6 +25,10 @@ * \ingroup channel_drivers */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/channels/chan_console.c b/channels/chan_console.c index a5f22be2d..a0eddbeae 100644 --- a/channels/chan_console.c +++ b/channels/chan_console.c @@ -49,6 +49,7 @@ /*** MODULEINFO portaudio + extended ***/ #include "asterisk.h" diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c index b94889ef4..079831340 100644 --- a/channels/chan_dahdi.c +++ b/channels/chan_dahdi.c @@ -44,6 +44,7 @@ pri ss7 openr2 + core ***/ #include "asterisk.h" diff --git a/channels/chan_gtalk.c b/channels/chan_gtalk.c index 326cb69db..a15fca975 100644 --- a/channels/chan_gtalk.c +++ b/channels/chan_gtalk.c @@ -35,6 +35,7 @@ iksemel res_jabber openssl + extended ***/ #include "asterisk.h" diff --git a/channels/chan_h323.c b/channels/chan_h323.c index 07646652f..e90bee18c 100644 --- a/channels/chan_h323.c +++ b/channels/chan_h323.c @@ -36,7 +36,9 @@ /*** MODULEINFO openh323 - yes + no + deprecated + chan_ooh323 ***/ #ifdef __cplusplus diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index 9f5f32deb..dff1bfda2 100644 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -33,6 +33,7 @@ /*** MODULEINFO crypto + core ***/ #include "asterisk.h" diff --git a/channels/chan_jingle.c b/channels/chan_jingle.c index 53b1a85e4..86a6410db 100644 --- a/channels/chan_jingle.c +++ b/channels/chan_jingle.c @@ -31,6 +31,8 @@ iksemel res_jabber openssl + no + extended ***/ #include "asterisk.h" diff --git a/channels/chan_local.c b/channels/chan_local.c index 3c16fc51a..937ede4c2 100644 --- a/channels/chan_local.c +++ b/channels/chan_local.c @@ -25,6 +25,10 @@ * \ingroup channel_drivers */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/channels/chan_mgcp.c b/channels/chan_mgcp.c index bd92fe9b0..dfd5a310f 100644 --- a/channels/chan_mgcp.c +++ b/channels/chan_mgcp.c @@ -31,6 +31,7 @@ /*** MODULEINFO res_pktccops + extended ***/ #include "asterisk.h" diff --git a/channels/chan_misdn.c b/channels/chan_misdn.c index d6e10aebe..e9fa80010 100644 --- a/channels/chan_misdn.c +++ b/channels/chan_misdn.c @@ -53,6 +53,7 @@ isdnnet misdn suppserv + extended ***/ #include "asterisk.h" diff --git a/channels/chan_multicast_rtp.c b/channels/chan_multicast_rtp.c index b398abb21..929525ffb 100644 --- a/channels/chan_multicast_rtp.c +++ b/channels/chan_multicast_rtp.c @@ -27,6 +27,10 @@ * \ingroup channel_drivers */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/channels/chan_nbs.c b/channels/chan_nbs.c index fdfbd8eb3..3ff97dde7 100644 --- a/channels/chan_nbs.c +++ b/channels/chan_nbs.c @@ -27,6 +27,7 @@ /*** MODULEINFO nbs + extended ***/ #include "asterisk.h" diff --git a/channels/chan_oss.c b/channels/chan_oss.c index 67c55c592..a8ca79a3e 100644 --- a/channels/chan_oss.c +++ b/channels/chan_oss.c @@ -35,6 +35,7 @@ /*** MODULEINFO oss + extended ***/ #include "asterisk.h" diff --git a/channels/chan_phone.c b/channels/chan_phone.c index 4b7ec9721..6acb7a184 100644 --- a/channels/chan_phone.c +++ b/channels/chan_phone.c @@ -27,6 +27,7 @@ /*** MODULEINFO ixjuser + extended ***/ #include "asterisk.h" diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 2e7b6f7f9..fec843627 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -164,6 +164,7 @@ /*** MODULEINFO res_crypto chan_local + core ***/ /*! \page sip_session_timers SIP Session Timers in Asterisk Chan_sip diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c index ea7d16c9e..80338c7d0 100644 --- a/channels/chan_skinny.c +++ b/channels/chan_skinny.c @@ -25,6 +25,9 @@ * \ingroup channel_drivers */ +/*** MODULEINFO + extended + ***/ #include "asterisk.h" diff --git a/channels/chan_unistim.c b/channels/chan_unistim.c index f4b92330e..8f0cfa59e 100644 --- a/channels/chan_unistim.c +++ b/channels/chan_unistim.c @@ -32,6 +32,10 @@ * \ingroup channel_drivers */ +/*** MODULEINFO + extended + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/channels/chan_usbradio.c b/channels/chan_usbradio.c index 925629f85..62a26de7f 100644 --- a/channels/chan_usbradio.c +++ b/channels/chan_usbradio.c @@ -38,6 +38,7 @@ alsa usb no + extended ***/ /*** MAKEOPTS diff --git a/channels/chan_vpb.cc b/channels/chan_vpb.cc index 0215ab82f..b4e9858ee 100644 --- a/channels/chan_vpb.cc +++ b/channels/chan_vpb.cc @@ -31,6 +31,8 @@ /*** MODULEINFO vpb + no + extended ***/ #include diff --git a/codecs/codec_a_mu.c b/codecs/codec_a_mu.c index a7d86e2c4..470f363e7 100644 --- a/codecs/codec_a_mu.c +++ b/codecs/codec_a_mu.c @@ -23,6 +23,10 @@ * \ingroup codecs */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/codecs/codec_adpcm.c b/codecs/codec_adpcm.c index 63745c170..96e19f0d3 100644 --- a/codecs/codec_adpcm.c +++ b/codecs/codec_adpcm.c @@ -27,6 +27,10 @@ * \ingroup codecs */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/codecs/codec_alaw.c b/codecs/codec_alaw.c index 3d2fc92ae..34a71388e 100644 --- a/codecs/codec_alaw.c +++ b/codecs/codec_alaw.c @@ -23,6 +23,10 @@ * \ingroup codecs */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/codecs/codec_g722.c b/codecs/codec_g722.c index 9c3a01846..89641f175 100644 --- a/codecs/codec_g722.c +++ b/codecs/codec_g722.c @@ -33,6 +33,10 @@ * \ingroup codecs */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/codecs/codec_g726.c b/codecs/codec_g726.c index f8a57f740..d92b9b642 100644 --- a/codecs/codec_g726.c +++ b/codecs/codec_g726.c @@ -27,6 +27,10 @@ * \ingroup codecs */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/codecs/codec_gsm.c b/codecs/codec_gsm.c index 46c1c84fb..f42a5f1bd 100644 --- a/codecs/codec_gsm.c +++ b/codecs/codec_gsm.c @@ -28,6 +28,7 @@ /*** MODULEINFO gsm + core ***/ #include "asterisk.h" diff --git a/codecs/codec_ilbc.c b/codecs/codec_ilbc.c index 7229b434d..ac6ccbb43 100644 --- a/codecs/codec_ilbc.c +++ b/codecs/codec_ilbc.c @@ -27,6 +27,7 @@ /*** MODULEINFO no + core ***/ #include "asterisk.h" diff --git a/codecs/codec_lpc10.c b/codecs/codec_lpc10.c index 7d1739203..5f2047a3f 100644 --- a/codecs/codec_lpc10.c +++ b/codecs/codec_lpc10.c @@ -27,6 +27,10 @@ * \ingroup codecs */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/codecs/codec_resample.c b/codecs/codec_resample.c index 66ef584bd..a3e7d6f26 100644 --- a/codecs/codec_resample.c +++ b/codecs/codec_resample.c @@ -25,6 +25,11 @@ * \ingroup codecs */ +/*** MODULEINFO + resample + core + ***/ + #include "asterisk.h" #include "speex/speex_resampler.h" diff --git a/codecs/codec_speex.c b/codecs/codec_speex.c index 6554ee000..d298f2379 100644 --- a/codecs/codec_speex.c +++ b/codecs/codec_speex.c @@ -34,6 +34,7 @@ speex speex_preprocess speexdsp + core ***/ #include "asterisk.h" diff --git a/codecs/codec_ulaw.c b/codecs/codec_ulaw.c index b5211a585..86a0706c4 100644 --- a/codecs/codec_ulaw.c +++ b/codecs/codec_ulaw.c @@ -23,6 +23,10 @@ * \ingroup codecs */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/formats/format_g719.c b/formats/format_g719.c index b679122f8..aace0edc7 100644 --- a/formats/format_g719.c +++ b/formats/format_g719.c @@ -22,6 +22,10 @@ * \arg File name extensions: g719 * \ingroup formats */ + +/*** MODULEINFO + core + ***/ #include "asterisk.h" diff --git a/formats/format_g723.c b/formats/format_g723.c index 6dab66a86..7eba74147 100644 --- a/formats/format_g723.c +++ b/formats/format_g723.c @@ -24,6 +24,10 @@ * \arg Extensions: g723, g723sf * \ingroup formats */ + +/*** MODULEINFO + core + ***/ #include "asterisk.h" diff --git a/formats/format_g726.c b/formats/format_g726.c index 73a57c8ee..636aff091 100644 --- a/formats/format_g726.c +++ b/formats/format_g726.c @@ -27,6 +27,10 @@ * \arg 16 kbps: g726-16 * \ingroup formats */ + +/*** MODULEINFO + core + ***/ #include "asterisk.h" diff --git a/formats/format_g729.c b/formats/format_g729.c index 22b3c3282..042977728 100644 --- a/formats/format_g729.c +++ b/formats/format_g729.c @@ -25,6 +25,10 @@ * \arg Extensions: g729 * \ingroup formats */ + +/*** MODULEINFO + core + ***/ #include "asterisk.h" diff --git a/formats/format_gsm.c b/formats/format_gsm.c index 26257c39f..03419c2f6 100644 --- a/formats/format_gsm.c +++ b/formats/format_gsm.c @@ -22,6 +22,10 @@ * \arg File name extension: gsm * \ingroup formats */ + +/*** MODULEINFO + core + ***/ #include "asterisk.h" diff --git a/formats/format_h263.c b/formats/format_h263.c index 76555a67c..77c1229c3 100644 --- a/formats/format_h263.c +++ b/formats/format_h263.c @@ -23,6 +23,10 @@ * \ingroup formats * \arg See \ref AstVideo */ + +/*** MODULEINFO + core + ***/ #include "asterisk.h" diff --git a/formats/format_h264.c b/formats/format_h264.c index ea82454f3..155f46975 100644 --- a/formats/format_h264.c +++ b/formats/format_h264.c @@ -23,6 +23,10 @@ * \ingroup formats * \arg See \ref AstVideo */ + +/*** MODULEINFO + core + ***/ #include "asterisk.h" diff --git a/formats/format_ilbc.c b/formats/format_ilbc.c index a60b585d7..7a08ca515 100644 --- a/formats/format_ilbc.c +++ b/formats/format_ilbc.c @@ -25,6 +25,10 @@ * \ingroup formats */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/formats/format_jpeg.c b/formats/format_jpeg.c index 99de8dac1..d6733020e 100644 --- a/formats/format_jpeg.c +++ b/formats/format_jpeg.c @@ -23,6 +23,10 @@ * \arg File name extension: jpeg, jpg * \ingroup formats */ + +/*** MODULEINFO + extended + ***/ #include "asterisk.h" diff --git a/formats/format_ogg_vorbis.c b/formats/format_ogg_vorbis.c index 949a13f78..46056b894 100644 --- a/formats/format_ogg_vorbis.c +++ b/formats/format_ogg_vorbis.c @@ -28,6 +28,7 @@ /*** MODULEINFO vorbis ogg + core ***/ #include "asterisk.h" diff --git a/formats/format_pcm.c b/formats/format_pcm.c index ec628c5b3..3bf27388c 100644 --- a/formats/format_pcm.c +++ b/formats/format_pcm.c @@ -23,6 +23,10 @@ * * \ingroup formats */ + +/*** MODULEINFO + core + ***/ #include "asterisk.h" diff --git a/formats/format_siren14.c b/formats/format_siren14.c index 53c9ea922..1ce50fad4 100644 --- a/formats/format_siren14.c +++ b/formats/format_siren14.c @@ -22,6 +22,10 @@ * \arg File name extensions: siren14 * \ingroup formats */ + +/*** MODULEINFO + core + ***/ #include "asterisk.h" diff --git a/formats/format_siren7.c b/formats/format_siren7.c index 16eca5df5..2e5182d3c 100644 --- a/formats/format_siren7.c +++ b/formats/format_siren7.c @@ -22,6 +22,10 @@ * \arg File name extensions: siren7 * \ingroup formats */ + +/*** MODULEINFO + core + ***/ #include "asterisk.h" diff --git a/formats/format_sln.c b/formats/format_sln.c index 91cb4584a..1a73cdfbb 100644 --- a/formats/format_sln.c +++ b/formats/format_sln.c @@ -21,6 +21,10 @@ * \ingroup formats */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/formats/format_vox.c b/formats/format_vox.c index 05ecdeeaf..7d34df99c 100644 --- a/formats/format_vox.c +++ b/formats/format_vox.c @@ -23,6 +23,10 @@ * * \ingroup formats */ + +/*** MODULEINFO + extended + ***/ #include "asterisk.h" diff --git a/formats/format_wav.c b/formats/format_wav.c index f35fd5278..f311522e5 100644 --- a/formats/format_wav.c +++ b/formats/format_wav.c @@ -24,6 +24,10 @@ * \ingroup formats */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/formats/format_wav_gsm.c b/formats/format_wav_gsm.c index ae1f11ed8..35d4339f9 100644 --- a/formats/format_wav_gsm.c +++ b/formats/format_wav_gsm.c @@ -26,6 +26,10 @@ * e-mail attachments mainly. * \ingroup formats */ + +/*** MODULEINFO + core + ***/ #include "asterisk.h" diff --git a/funcs/func_aes.c b/funcs/func_aes.c index 891106b6f..c176f4863 100644 --- a/funcs/func_aes.c +++ b/funcs/func_aes.c @@ -24,6 +24,7 @@ /*** MODULEINFO crypto + core ***/ #include "asterisk.h" diff --git a/funcs/func_audiohookinherit.c b/funcs/func_audiohookinherit.c index 528aed51f..59faa9019 100644 --- a/funcs/func_audiohookinherit.c +++ b/funcs/func_audiohookinherit.c @@ -28,6 +28,10 @@ * \ingroup functions */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" #include "asterisk/datastore.h" #include "asterisk/channel.h" diff --git a/funcs/func_base64.c b/funcs/func_base64.c index 274e291ce..1a7619d91 100644 --- a/funcs/func_base64.c +++ b/funcs/func_base64.c @@ -22,6 +22,10 @@ * \ingroup functions */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/funcs/func_blacklist.c b/funcs/func_blacklist.c index b940b5891..be3bbc5fb 100644 --- a/funcs/func_blacklist.c +++ b/funcs/func_blacklist.c @@ -26,6 +26,10 @@ * */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/funcs/func_callcompletion.c b/funcs/func_callcompletion.c index b3fab310f..cee06faa4 100644 --- a/funcs/func_callcompletion.c +++ b/funcs/func_callcompletion.c @@ -21,6 +21,10 @@ * \author Mark Michelson */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/funcs/func_callerid.c b/funcs/func_callerid.c index a653d8660..bb631fe4e 100644 --- a/funcs/func_callerid.c +++ b/funcs/func_callerid.c @@ -24,6 +24,10 @@ * \arg \ref AstCREDITS */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/funcs/func_cdr.c b/funcs/func_cdr.c index 3d0c846f9..34fdd6736 100644 --- a/funcs/func_cdr.c +++ b/funcs/func_cdr.c @@ -25,6 +25,10 @@ * \ingroup functions */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/funcs/func_channel.c b/funcs/func_channel.c index 202036e84..7baf2485e 100644 --- a/funcs/func_channel.c +++ b/funcs/func_channel.c @@ -24,6 +24,10 @@ * \ingroup functions */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/funcs/func_config.c b/funcs/func_config.c index 21d291c2e..cbc51aaae 100644 --- a/funcs/func_config.c +++ b/funcs/func_config.c @@ -27,6 +27,10 @@ * \ingroup functions */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/funcs/func_curl.c b/funcs/func_curl.c index 24f6fd923..7e97eb56e 100644 --- a/funcs/func_curl.c +++ b/funcs/func_curl.c @@ -32,6 +32,7 @@ /*** MODULEINFO curl + core ***/ #include "asterisk.h" diff --git a/funcs/func_cut.c b/funcs/func_cut.c index 10bca0a9f..762dd61fe 100644 --- a/funcs/func_cut.c +++ b/funcs/func_cut.c @@ -24,6 +24,10 @@ * \ingroup functions */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/funcs/func_db.c b/funcs/func_db.c index a932cf5b1..20c8829a6 100644 --- a/funcs/func_db.c +++ b/funcs/func_db.c @@ -27,6 +27,10 @@ * \ingroup functions */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/funcs/func_devstate.c b/funcs/func_devstate.c index 396657768..274f1ac03 100644 --- a/funcs/func_devstate.c +++ b/funcs/func_devstate.c @@ -30,6 +30,10 @@ * when I couldn't sleep. :) */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/funcs/func_dialgroup.c b/funcs/func_dialgroup.c index b1fa78017..4a789d627 100644 --- a/funcs/func_dialgroup.c +++ b/funcs/func_dialgroup.c @@ -25,6 +25,10 @@ * \ingroup functions */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/funcs/func_dialplan.c b/funcs/func_dialplan.c index 4e1ab3bed..c39b3e376 100644 --- a/funcs/func_dialplan.c +++ b/funcs/func_dialplan.c @@ -24,6 +24,10 @@ * \ingroup functions */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/funcs/func_enum.c b/funcs/func_enum.c index d8c8b252d..cc4d47a78 100644 --- a/funcs/func_enum.c +++ b/funcs/func_enum.c @@ -33,6 +33,10 @@ * \ingroup functions */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/funcs/func_env.c b/funcs/func_env.c index aa0abb4b3..c7b431dca 100644 --- a/funcs/func_env.c +++ b/funcs/func_env.c @@ -21,6 +21,10 @@ * \ingroup functions */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/funcs/func_extstate.c b/funcs/func_extstate.c index d3c7ba4b7..940c455c2 100644 --- a/funcs/func_extstate.c +++ b/funcs/func_extstate.c @@ -26,6 +26,10 @@ * \ingroup functions */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/funcs/func_frame_trace.c b/funcs/func_frame_trace.c index 03711ee7d..681f151fc 100644 --- a/funcs/func_frame_trace.c +++ b/funcs/func_frame_trace.c @@ -25,6 +25,10 @@ * \ingroup functions */ +/*** MODULEINFO + extended + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/funcs/func_global.c b/funcs/func_global.c index a501aee58..6b158aafb 100644 --- a/funcs/func_global.c +++ b/funcs/func_global.c @@ -25,6 +25,10 @@ * \ingroup functions */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/funcs/func_groupcount.c b/funcs/func_groupcount.c index 70c396436..609d01fef 100644 --- a/funcs/func_groupcount.c +++ b/funcs/func_groupcount.c @@ -21,6 +21,10 @@ * \ingroup functions */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/funcs/func_iconv.c b/funcs/func_iconv.c index 231b4880f..4c4f65f1a 100644 --- a/funcs/func_iconv.c +++ b/funcs/func_iconv.c @@ -25,7 +25,8 @@ */ /*** MODULEINFO - iconv + iconv + core ***/ #include "asterisk.h" diff --git a/funcs/func_lock.c b/funcs/func_lock.c index 27d199e36..c3cf7a987 100644 --- a/funcs/func_lock.c +++ b/funcs/func_lock.c @@ -26,6 +26,10 @@ * */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/funcs/func_logic.c b/funcs/func_logic.c index 27734ed78..21f08a13f 100644 --- a/funcs/func_logic.c +++ b/funcs/func_logic.c @@ -24,6 +24,10 @@ * \ingroup functions */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/funcs/func_math.c b/funcs/func_math.c index f3a690c5d..e7217c7b3 100644 --- a/funcs/func_math.c +++ b/funcs/func_math.c @@ -28,6 +28,10 @@ * \ingroup functions */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/funcs/func_md5.c b/funcs/func_md5.c index 7c61d9f8c..2e6018586 100644 --- a/funcs/func_md5.c +++ b/funcs/func_md5.c @@ -26,6 +26,10 @@ * \ingroup functions */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/funcs/func_module.c b/funcs/func_module.c index 44ec08e4d..b0b346116 100644 --- a/funcs/func_module.c +++ b/funcs/func_module.c @@ -21,6 +21,11 @@ * * \ingroup functions */ + +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/funcs/func_odbc.c b/funcs/func_odbc.c index fad548a92..6cef946df 100644 --- a/funcs/func_odbc.c +++ b/funcs/func_odbc.c @@ -29,6 +29,7 @@ /*** MODULEINFO res_odbc + core ***/ #include "asterisk.h" diff --git a/funcs/func_pitchshift.c b/funcs/func_pitchshift.c index b14894712..ca441f985 100644 --- a/funcs/func_pitchshift.c +++ b/funcs/func_pitchshift.c @@ -58,6 +58,10 @@ * *****************************************************************************/ +/*** MODULEINFO + extended + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/funcs/func_rand.c b/funcs/func_rand.c index 2d4e02fcf..6491b371d 100644 --- a/funcs/func_rand.c +++ b/funcs/func_rand.c @@ -24,6 +24,10 @@ * \ingroup functions */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/funcs/func_sha1.c b/funcs/func_sha1.c index 985e11a38..c6b757545 100644 --- a/funcs/func_sha1.c +++ b/funcs/func_sha1.c @@ -24,6 +24,10 @@ * \ingroup functions */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/funcs/func_shell.c b/funcs/func_shell.c index df7164d5f..1f274b83d 100644 --- a/funcs/func_shell.c +++ b/funcs/func_shell.c @@ -25,6 +25,10 @@ * \ingroup functions */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/funcs/func_speex.c b/funcs/func_speex.c index e17e8ca9c..2b29271f3 100644 --- a/funcs/func_speex.c +++ b/funcs/func_speex.c @@ -34,6 +34,7 @@ speex speex_preprocess speexdsp + core ***/ #include "asterisk.h" diff --git a/funcs/func_sprintf.c b/funcs/func_sprintf.c index 4e3fbb99c..4d5fc7a6c 100644 --- a/funcs/func_sprintf.c +++ b/funcs/func_sprintf.c @@ -25,6 +25,10 @@ * \ingroup functions */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/funcs/func_srv.c b/funcs/func_srv.c index de48f0d06..deb94835f 100644 --- a/funcs/func_srv.c +++ b/funcs/func_srv.c @@ -23,6 +23,10 @@ * \ingroup functions */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/funcs/func_strings.c b/funcs/func_strings.c index 0d2b95efc..055fd0c4e 100644 --- a/funcs/func_strings.c +++ b/funcs/func_strings.c @@ -25,6 +25,10 @@ * \ingroup functions */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/funcs/func_sysinfo.c b/funcs/func_sysinfo.c index 2d9a8dd24..a7e358bb8 100644 --- a/funcs/func_sysinfo.c +++ b/funcs/func_sysinfo.c @@ -25,6 +25,10 @@ * \ingroup functions */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision: 87233 $") diff --git a/funcs/func_timeout.c b/funcs/func_timeout.c index 79d908d18..53bbab753 100644 --- a/funcs/func_timeout.c +++ b/funcs/func_timeout.c @@ -24,6 +24,10 @@ * \ingroup functions */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/funcs/func_uri.c b/funcs/func_uri.c index ecf23d8ff..f4ecf3d67 100644 --- a/funcs/func_uri.c +++ b/funcs/func_uri.c @@ -28,6 +28,10 @@ * \ingroup functions */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/funcs/func_version.c b/funcs/func_version.c index 8ed6c218f..d8ba757a4 100644 --- a/funcs/func_version.c +++ b/funcs/func_version.c @@ -22,6 +22,10 @@ * \ingroup functions */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/funcs/func_vmcount.c b/funcs/func_vmcount.c index f409e75ce..c4d80d499 100644 --- a/funcs/func_vmcount.c +++ b/funcs/func_vmcount.c @@ -25,6 +25,10 @@ * \ingroup functions */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/funcs/func_volume.c b/funcs/func_volume.c index 938fbba38..806564bee 100644 --- a/funcs/func_volume.c +++ b/funcs/func_volume.c @@ -26,6 +26,10 @@ * */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/main/features.c b/main/features.c index 06ec1b698..7f8444c17 100644 --- a/main/features.c +++ b/main/features.c @@ -23,6 +23,10 @@ * \author Mark Spencer */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/main/http.c b/main/http.c index 63d91c2b2..724a58fdc 100644 --- a/main/http.c +++ b/main/http.c @@ -30,6 +30,10 @@ * \ref AstHTTP - AMI over the http protocol */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/main/manager.c b/main/manager.c index edaad357f..98daad084 100644 --- a/main/manager.c +++ b/main/manager.c @@ -41,6 +41,10 @@ /*! @{ Doxygen group */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/pbx/pbx_ael.c b/pbx/pbx_ael.c index 96c65ff6d..94a6212fa 100644 --- a/pbx/pbx_ael.c +++ b/pbx/pbx_ael.c @@ -24,6 +24,7 @@ /*** MODULEINFO res_ael_share + extended ***/ #include "asterisk.h" diff --git a/pbx/pbx_config.c b/pbx/pbx_config.c index e02ef9de6..f0da2e87a 100644 --- a/pbx/pbx_config.c +++ b/pbx/pbx_config.c @@ -23,6 +23,10 @@ * */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/pbx/pbx_dundi.c b/pbx/pbx_dundi.c index 26418d760..f2f556915 100644 --- a/pbx/pbx_dundi.c +++ b/pbx/pbx_dundi.c @@ -24,6 +24,7 @@ /*** MODULEINFO zlib crypto + extended ***/ #include "asterisk.h" diff --git a/pbx/pbx_loopback.c b/pbx/pbx_loopback.c index e283127a0..915a0cb10 100644 --- a/pbx/pbx_loopback.c +++ b/pbx/pbx_loopback.c @@ -22,6 +22,10 @@ * */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/pbx/pbx_lua.c b/pbx/pbx_lua.c index cae82adba..c1088629b 100644 --- a/pbx/pbx_lua.c +++ b/pbx/pbx_lua.c @@ -26,6 +26,7 @@ /*** MODULEINFO lua + extended ***/ #include "asterisk.h" diff --git a/pbx/pbx_realtime.c b/pbx/pbx_realtime.c index f183c867b..51254a871 100644 --- a/pbx/pbx_realtime.c +++ b/pbx/pbx_realtime.c @@ -23,6 +23,10 @@ * \arg See also: \ref AstARA */ +/*** MODULEINFO + extended + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/pbx/pbx_spool.c b/pbx/pbx_spool.c index b90866357..b45ff6a59 100644 --- a/pbx/pbx_spool.c +++ b/pbx/pbx_spool.c @@ -22,6 +22,10 @@ * */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/res/res_adsi.c b/res/res_adsi.c index 0a1f623a5..778752495 100644 --- a/res/res_adsi.c +++ b/res/res_adsi.c @@ -30,6 +30,10 @@ * res_adsi to load */ +/*** MODULEINFO + extended + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/res/res_ael_share.c b/res/res_ael_share.c index 805dfd9a8..f1ae9f33f 100644 --- a/res/res_ael_share.c +++ b/res/res_ael_share.c @@ -25,6 +25,10 @@ * \ingroup applications */ +/*** MODULEINFO + extended + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/res/res_agi.c b/res/res_agi.c index b57c498df..87ae21a6d 100644 --- a/res/res_agi.c +++ b/res/res_agi.c @@ -25,6 +25,10 @@ * \todo Convert the rest of the AGI commands over to XML documentation */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/res/res_ais.c b/res/res_ais.c index 9bcceeade..c64e8e674 100644 --- a/res/res_ais.c +++ b/res/res_ais.c @@ -34,6 +34,7 @@ /*** MODULEINFO ais + extended ***/ #include "asterisk.h" diff --git a/res/res_calendar.c b/res/res_calendar.c index e6b724baf..b77553781 100644 --- a/res/res_calendar.c +++ b/res/res_calendar.c @@ -23,6 +23,10 @@ * \todo Support writing attendees */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/res/res_calendar_caldav.c b/res/res_calendar_caldav.c index dd150afd6..14fce0ca7 100644 --- a/res/res_calendar_caldav.c +++ b/res/res_calendar_caldav.c @@ -24,7 +24,9 @@ neon ical libxml2 + core ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/res/res_calendar_ews.c b/res/res_calendar_ews.c index 31df35312..51761127e 100644 --- a/res/res_calendar_ews.c +++ b/res/res_calendar_ews.c @@ -22,7 +22,9 @@ /*** MODULEINFO neon29 + core ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/res/res_calendar_exchange.c b/res/res_calendar_exchange.c index 2238124db..4a2df1822 100644 --- a/res/res_calendar_exchange.c +++ b/res/res_calendar_exchange.c @@ -24,7 +24,9 @@ neon ical iksemel + core ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/res/res_calendar_icalendar.c b/res/res_calendar_icalendar.c index d503eac35..8ef269e4f 100644 --- a/res/res_calendar_icalendar.c +++ b/res/res_calendar_icalendar.c @@ -23,7 +23,9 @@ /*** MODULEINFO neon ical + core ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/res/res_clialiases.c b/res/res_clialiases.c index e2558f274..d67f3ba39 100644 --- a/res/res_clialiases.c +++ b/res/res_clialiases.c @@ -26,6 +26,9 @@ * CLI commands. */ +/*** MODULEINFO + core + ***/ #include "asterisk.h" diff --git a/res/res_clioriginate.c b/res/res_clioriginate.c index f244c165d..8a30be073 100644 --- a/res/res_clioriginate.c +++ b/res/res_clioriginate.c @@ -24,6 +24,10 @@ * */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$"); diff --git a/res/res_config_curl.c b/res/res_config_curl.c index 8488d9bdc..bb8d9b39b 100644 --- a/res/res_config_curl.c +++ b/res/res_config_curl.c @@ -28,6 +28,7 @@ /*** MODULEINFO curl + core ***/ #include "asterisk.h" diff --git a/res/res_config_ldap.c b/res/res_config_ldap.c index adfdacb28..55e1526d5 100644 --- a/res/res_config_ldap.c +++ b/res/res_config_ldap.c @@ -33,6 +33,7 @@ /*** MODULEINFO ldap + extended ***/ #include "asterisk.h" diff --git a/res/res_config_odbc.c b/res/res_config_odbc.c index f52f941be..86cc25c86 100644 --- a/res/res_config_odbc.c +++ b/res/res_config_odbc.c @@ -30,6 +30,7 @@ /*** MODULEINFO res_odbc + core ***/ #include "asterisk.h" diff --git a/res/res_config_pgsql.c b/res/res_config_pgsql.c index bbc683a47..6ed6bd294 100644 --- a/res/res_config_pgsql.c +++ b/res/res_config_pgsql.c @@ -24,6 +24,7 @@ /*** MODULEINFO pgsql + extended ***/ #include "asterisk.h" diff --git a/res/res_config_sqlite.c b/res/res_config_sqlite.c index 75d353cd5..fbeeac275 100644 --- a/res/res_config_sqlite.c +++ b/res/res_config_sqlite.c @@ -73,6 +73,7 @@ /*** MODULEINFO sqlite + extended ***/ #include "asterisk.h" diff --git a/res/res_convert.c b/res/res_convert.c index 94d6e1e59..c2966a85f 100644 --- a/res/res_convert.c +++ b/res/res_convert.c @@ -26,6 +26,10 @@ * */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/res/res_crypto.c b/res/res_crypto.c index e25b8a4d6..4ae0851d6 100644 --- a/res/res_crypto.c +++ b/res/res_crypto.c @@ -28,6 +28,7 @@ /*** MODULEINFO openssl + core ***/ #include "asterisk.h" diff --git a/res/res_fax.c b/res/res_fax.c index 31aede8a6..8073f2d6e 100644 --- a/res/res_fax.c +++ b/res/res_fax.c @@ -53,6 +53,10 @@ * \ingroup applications */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/res/res_fax_spandsp.c b/res/res_fax_spandsp.c index 02657583d..296dd07a6 100644 --- a/res/res_fax_spandsp.c +++ b/res/res_fax_spandsp.c @@ -45,6 +45,7 @@ /*** MODULEINFO spandsp res_fax + extended ***/ #include "asterisk.h" diff --git a/res/res_http_post.c b/res/res_http_post.c index c0719b6da..3dde6484d 100644 --- a/res/res_http_post.c +++ b/res/res_http_post.c @@ -27,6 +27,7 @@ /*** MODULEINFO gmime + core ***/ diff --git a/res/res_jabber.c b/res/res_jabber.c index 61d436a92..46229520a 100644 --- a/res/res_jabber.c +++ b/res/res_jabber.c @@ -33,6 +33,7 @@ /*** MODULEINFO iksemel openssl + extended ***/ #include "asterisk.h" diff --git a/res/res_limit.c b/res/res_limit.c index a6b4fef64..dc07a4caf 100644 --- a/res/res_limit.c +++ b/res/res_limit.c @@ -18,6 +18,9 @@ * \author Tilghman Lesher */ +/*** MODULEINFO + core + ***/ #include "asterisk.h" diff --git a/res/res_monitor.c b/res/res_monitor.c index 86d1d1e02..61dc4a2d0 100644 --- a/res/res_monitor.c +++ b/res/res_monitor.c @@ -22,6 +22,10 @@ * * \author Mark Spencer */ + +/*** MODULEINFO + core + ***/ #include "asterisk.h" @@ -650,6 +654,12 @@ static int start_monitor_exec(struct ast_channel *chan, const char *data) AST_APP_ARG(fname_base); AST_APP_ARG(options); ); + + /* Parse arguments. */ + if (ast_strlen_zero(data)) { + ast_log(LOG_ERROR, "Monitor requires an argument\n"); + return 0; + } parse = ast_strdupa(data); AST_STANDARD_APP_ARGS(args, parse); @@ -665,9 +675,7 @@ static int start_monitor_exec(struct ast_channel *chan, const char *data) stream_action &= ~X_REC_OUT; } - if (args.format) { - arg = strchr(args.format, ':'); - } + arg = strchr(args.format, ':'); if (arg) { *arg++ = 0; urlprefix = arg; diff --git a/res/res_musiconhold.c b/res/res_musiconhold.c index cc98543c6..4a052d43d 100644 --- a/res/res_musiconhold.c +++ b/res/res_musiconhold.c @@ -27,6 +27,7 @@ /*** MODULEINFO win32 + core ***/ #include "asterisk.h" diff --git a/res/res_mutestream.c b/res/res_mutestream.c index 41b2fd831..92d01c7c7 100644 --- a/res/res_mutestream.c +++ b/res/res_mutestream.c @@ -29,6 +29,10 @@ * When we know and understands what happens if we zero out video, we can do that too. */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision: 89545 $") diff --git a/res/res_odbc.c b/res/res_odbc.c index b1e72ac8d..1770bb303 100644 --- a/res/res_odbc.c +++ b/res/res_odbc.c @@ -33,6 +33,7 @@ /*** MODULEINFO generic_odbc ltdl + core ***/ #include "asterisk.h" diff --git a/res/res_phoneprov.c b/res/res_phoneprov.c index 24d7b6505..c6dc009ea 100644 --- a/res/res_phoneprov.c +++ b/res/res_phoneprov.c @@ -26,6 +26,10 @@ * \author Terry Wilson */ +/*** MODULEINFO + extended + ***/ + #include "asterisk.h" #include diff --git a/res/res_pktccops.c b/res/res_pktccops.c index 33ecc3817..0572658ac 100644 --- a/res/res_pktccops.c +++ b/res/res_pktccops.c @@ -32,6 +32,7 @@ /*** MODULEINFO no + extended ***/ #include "asterisk.h" diff --git a/res/res_realtime.c b/res/res_realtime.c index 1bafe52b7..8b1488fe4 100644 --- a/res/res_realtime.c +++ b/res/res_realtime.c @@ -27,6 +27,10 @@ * \ingroup applications */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c index 5948e664c..a520cdb16 100644 --- a/res/res_rtp_asterisk.c +++ b/res/res_rtp_asterisk.c @@ -28,6 +28,10 @@ * \ingroup rtp_engines */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/res/res_rtp_multicast.c b/res/res_rtp_multicast.c index 0e930d61f..18256e90e 100644 --- a/res/res_rtp_multicast.c +++ b/res/res_rtp_multicast.c @@ -28,6 +28,10 @@ * \ingroup rtp_engines */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/res/res_security_log.c b/res/res_security_log.c index 2e3d4af52..3e8c48a24 100644 --- a/res/res_security_log.c +++ b/res/res_security_log.c @@ -27,6 +27,10 @@ * \todo Escape quotes in string payload IE contents */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$"); diff --git a/res/res_smdi.c b/res/res_smdi.c index 3c1ce4c97..e0bde6959 100644 --- a/res/res_smdi.c +++ b/res/res_smdi.c @@ -31,6 +31,10 @@ * polling thread handle it. */ +/*** MODULEINFO + extended + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/res/res_snmp.c b/res/res_snmp.c index 4bf81a2f0..f717cead0 100644 --- a/res/res_snmp.c +++ b/res/res_snmp.c @@ -19,6 +19,7 @@ /*** MODULEINFO netsnmp + extended ***/ #include "asterisk.h" diff --git a/res/res_speech.c b/res/res_speech.c index 7a8d17e5a..de0c41e08 100644 --- a/res/res_speech.c +++ b/res/res_speech.c @@ -23,6 +23,10 @@ * \author Joshua Colp */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$"); diff --git a/res/res_srtp.c b/res/res_srtp.c index 3e9525afd..223b79bbb 100644 --- a/res/res_srtp.c +++ b/res/res_srtp.c @@ -29,7 +29,8 @@ */ /*** MODULEINFO - srtp + srtp + core ***/ /* See https://wiki.asterisk.org/wiki/display/AST/Secure+Calling */ diff --git a/res/res_stun_monitor.c b/res/res_stun_monitor.c index 8ce77141d..64ca73eda 100644 --- a/res/res_stun_monitor.c +++ b/res/res_stun_monitor.c @@ -23,6 +23,10 @@ * \author David Vossel */ +/*** MODULEINFO + core + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/res/res_timing_dahdi.c b/res/res_timing_dahdi.c index 41f74f6c9..61dda6a44 100644 --- a/res/res_timing_dahdi.c +++ b/res/res_timing_dahdi.c @@ -25,6 +25,7 @@ /*** MODULEINFO dahdi + core ***/ #include "asterisk.h" diff --git a/res/res_timing_kqueue.c b/res/res_timing_kqueue.c index 1fef5fb99..57091bf41 100644 --- a/res/res_timing_kqueue.c +++ b/res/res_timing_kqueue.c @@ -26,6 +26,7 @@ /*** MODULEINFO kqueue launchd + extended ***/ #include "asterisk.h" diff --git a/res/res_timing_pthread.c b/res/res_timing_pthread.c index 8cb2898d9..e89ded2d6 100644 --- a/res/res_timing_pthread.c +++ b/res/res_timing_pthread.c @@ -23,6 +23,10 @@ * \brief pthread timing interface */ +/*** MODULEINFO + extended + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$"); diff --git a/res/res_timing_timerfd.c b/res/res_timing_timerfd.c index ae5d2b411..80e5ca8a5 100644 --- a/res/res_timing_timerfd.c +++ b/res/res_timing_timerfd.c @@ -25,6 +25,7 @@ /*** MODULEINFO timerfd + core ***/ #include "asterisk.h" diff --git a/tests/test_acl.c b/tests/test_acl.c index 693c8054d..b84ca4364 100644 --- a/tests/test_acl.c +++ b/tests/test_acl.c @@ -26,6 +26,7 @@ /*** MODULEINFO TEST_FRAMEWORK + extended ***/ #include "asterisk.h" diff --git a/tests/test_amihooks.c b/tests/test_amihooks.c index 2fd23a476..dfb64866b 100644 --- a/tests/test_amihooks.c +++ b/tests/test_amihooks.c @@ -28,6 +28,7 @@ /*** MODULEINFO no + extended ***/ #include "asterisk.h" diff --git a/tests/test_aoc.c b/tests/test_aoc.c index 23663ee02..2a4294300 100644 --- a/tests/test_aoc.c +++ b/tests/test_aoc.c @@ -27,6 +27,7 @@ /*** MODULEINFO TEST_FRAMEWORK + extended ***/ #include "asterisk.h" diff --git a/tests/test_app.c b/tests/test_app.c index b4b2c22e1..75992f30f 100644 --- a/tests/test_app.c +++ b/tests/test_app.c @@ -26,6 +26,7 @@ /*** MODULEINFO TEST_FRAMEWORK + extended ***/ #include "asterisk.h" diff --git a/tests/test_ast_format_str_reduce.c b/tests/test_ast_format_str_reduce.c index c92245213..6723513b8 100644 --- a/tests/test_ast_format_str_reduce.c +++ b/tests/test_ast_format_str_reduce.c @@ -36,6 +36,7 @@ format_sln format_wav format_wav_gsm + extended ***/ #include "asterisk.h" diff --git a/tests/test_astobj2.c b/tests/test_astobj2.c index 12632c63a..9466f3384 100644 --- a/tests/test_astobj2.c +++ b/tests/test_astobj2.c @@ -25,6 +25,7 @@ /*** MODULEINFO TEST_FRAMEWORK + extended ***/ #include "asterisk.h" diff --git a/tests/test_devicestate.c b/tests/test_devicestate.c index 415cda271..77e718bd2 100644 --- a/tests/test_devicestate.c +++ b/tests/test_devicestate.c @@ -27,6 +27,7 @@ /*** MODULEINFO TEST_FRAMEWORK + extended ***/ #include "asterisk.h" diff --git a/tests/test_dlinklists.c b/tests/test_dlinklists.c index 45a34eaf7..2af251f71 100644 --- a/tests/test_dlinklists.c +++ b/tests/test_dlinklists.c @@ -28,6 +28,7 @@ /*** MODULEINFO no + extended ***/ #include "asterisk.h" diff --git a/tests/test_event.c b/tests/test_event.c index e6f345133..01bb9ee4c 100644 --- a/tests/test_event.c +++ b/tests/test_event.c @@ -44,6 +44,7 @@ /*** MODULEINFO TEST_FRAMEWORK + extended ***/ #include "asterisk.h" diff --git a/tests/test_expr.c b/tests/test_expr.c index b4adc4aac..b7f416446 100644 --- a/tests/test_expr.c +++ b/tests/test_expr.c @@ -28,6 +28,7 @@ /*** MODULEINFO TEST_FRAMEWORK + extended ***/ #include "asterisk.h" diff --git a/tests/test_func_file.c b/tests/test_func_file.c index 4e8823ba9..6e35fe921 100644 --- a/tests/test_func_file.c +++ b/tests/test_func_file.c @@ -27,6 +27,7 @@ /*** MODULEINFO TEST_FRAMEWORK + extended ***/ #include "asterisk.h" diff --git a/tests/test_gosub.c b/tests/test_gosub.c index e69acfb17..f8b7482fd 100644 --- a/tests/test_gosub.c +++ b/tests/test_gosub.c @@ -27,6 +27,7 @@ /*** MODULEINFO TEST_FRAMEWORK + extended ***/ #include "asterisk.h" diff --git a/tests/test_heap.c b/tests/test_heap.c index 3e70848d1..d14f1620f 100644 --- a/tests/test_heap.c +++ b/tests/test_heap.c @@ -25,6 +25,7 @@ /*** MODULEINFO TEST_FRAMEWORK + extended ***/ #include "asterisk.h" diff --git a/tests/test_locale.c b/tests/test_locale.c index 46271c232..89148d17a 100644 --- a/tests/test_locale.c +++ b/tests/test_locale.c @@ -27,6 +27,7 @@ /*** MODULEINFO no + extended ***/ #include "asterisk.h" diff --git a/tests/test_logger.c b/tests/test_logger.c index 04b5a1058..41467ee6e 100644 --- a/tests/test_logger.c +++ b/tests/test_logger.c @@ -27,6 +27,7 @@ /*** MODULEINFO no + extended ***/ #include "asterisk.h" diff --git a/tests/test_pbx.c b/tests/test_pbx.c index 3ecc9e937..a86ba36b8 100644 --- a/tests/test_pbx.c +++ b/tests/test_pbx.c @@ -28,6 +28,7 @@ /*** MODULEINFO TEST_FRAMEWORK + extended ***/ #include "asterisk.h" diff --git a/tests/test_poll.c b/tests/test_poll.c index 815e0c6c4..bdab29142 100644 --- a/tests/test_poll.c +++ b/tests/test_poll.c @@ -28,6 +28,7 @@ /*** MODULEINFO TEST_FRAMEWORK + extended ***/ #include "asterisk.h" diff --git a/tests/test_sched.c b/tests/test_sched.c index 0062afb09..bcd501aa0 100644 --- a/tests/test_sched.c +++ b/tests/test_sched.c @@ -25,6 +25,7 @@ /*** MODULEINFO TEST_FRAMEWORK + extended ***/ #include "asterisk.h" diff --git a/tests/test_security_events.c b/tests/test_security_events.c index 33b40e877..c2c7c2921 100644 --- a/tests/test_security_events.c +++ b/tests/test_security_events.c @@ -25,6 +25,7 @@ /*** MODULEINFO no + extended ***/ #include "asterisk.h" diff --git a/tests/test_skel.c b/tests/test_skel.c index 609e399a7..98d604012 100644 --- a/tests/test_skel.c +++ b/tests/test_skel.c @@ -28,6 +28,7 @@ /*** MODULEINFO TEST_FRAMEWORK + extended ***/ #include "asterisk.h" diff --git a/tests/test_stringfields.c b/tests/test_stringfields.c index dd3f0aaa1..2cd51ddae 100644 --- a/tests/test_stringfields.c +++ b/tests/test_stringfields.c @@ -29,6 +29,7 @@ /*** MODULEINFO TEST_FRAMEWORK + extended ***/ #include "asterisk.h" diff --git a/tests/test_strings.c b/tests/test_strings.c index 34062f04d..b1d1205e6 100644 --- a/tests/test_strings.c +++ b/tests/test_strings.c @@ -29,6 +29,7 @@ /*** MODULEINFO TEST_FRAMEWORK + extended ***/ #include "asterisk.h" diff --git a/tests/test_substitution.c b/tests/test_substitution.c index cb3161691..eb3bb54e2 100644 --- a/tests/test_substitution.c +++ b/tests/test_substitution.c @@ -28,6 +28,7 @@ /*** MODULEINFO TEST_FRAMEWORK func_curl + extended ***/ #include "asterisk.h" diff --git a/tests/test_time.c b/tests/test_time.c index c81c9bb12..ae8834d94 100644 --- a/tests/test_time.c +++ b/tests/test_time.c @@ -27,6 +27,7 @@ /*** MODULEINFO TEST_FRAMEWORK + extended ***/ #include "asterisk.h" diff --git a/tests/test_utils.c b/tests/test_utils.c index fd9d3bc4a..3e7df97e2 100644 --- a/tests/test_utils.c +++ b/tests/test_utils.c @@ -27,6 +27,7 @@ /*** MODULEINFO TEST_FRAMEWORK + extended ***/ #include "asterisk.h" diff --git a/utils/ael_main.c b/utils/ael_main.c index e5a7346ed..52aa47993 100644 --- a/utils/ael_main.c +++ b/utils/ael_main.c @@ -6,6 +6,11 @@ * it was copied from; * - fixing the formatting */ + +/*** MODULEINFO + extended + ***/ + #include "asterisk.h" #include diff --git a/utils/astcanary.c b/utils/astcanary.c index 8cfa3feb7..9432c57a7 100644 --- a/utils/astcanary.c +++ b/utils/astcanary.c @@ -16,6 +16,10 @@ * at the top of the source tree. */ +/*** MODULEINFO + core + ***/ + #include #include #include diff --git a/utils/astman.c b/utils/astman.c index 6bb4c4c6f..459eeee71 100644 --- a/utils/astman.c +++ b/utils/astman.c @@ -22,6 +22,10 @@ * */ +/*** MODULEINFO + extended + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk.h" diff --git a/utils/check_expr.c b/utils/check_expr.c index b904b4824..556b0f9f8 100644 --- a/utils/check_expr.c +++ b/utils/check_expr.c @@ -16,6 +16,10 @@ * at the top of the source tree. */ +/*** MODULEINFO + extended + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/utils/conf2ael.c b/utils/conf2ael.c index 538818b25..020dbe3af 100644 --- a/utils/conf2ael.c +++ b/utils/conf2ael.c @@ -24,6 +24,7 @@ /*** MODULEINFO res_ael_share + extended ***/ #include "asterisk.h" diff --git a/utils/extconf.c b/utils/extconf.c index 22df962e7..54e11a0ad 100644 --- a/utils/extconf.c +++ b/utils/extconf.c @@ -23,6 +23,11 @@ * for operations outside of asterisk. A huge, awful hack. * */ + +/*** MODULEINFO + extended + ***/ + #include "asterisk.h" #undef DEBUG_THREADS diff --git a/utils/hashtest.c b/utils/hashtest.c index 9ec597f4e..390e331e0 100644 --- a/utils/hashtest.c +++ b/utils/hashtest.c @@ -28,6 +28,10 @@ * \author Steve Murphy */ +/*** MODULEINFO + extended + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/utils/hashtest2.c b/utils/hashtest2.c index 7953decf6..5bc628061 100644 --- a/utils/hashtest2.c +++ b/utils/hashtest2.c @@ -28,6 +28,10 @@ * \author Steve Murphy */ +/*** MODULEINFO + extended + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/utils/muted.c b/utils/muted.c index 211766e53..18f55d73f 100644 --- a/utils/muted.c +++ b/utils/muted.c @@ -35,6 +35,10 @@ * */ +/*** MODULEINFO + extended + ***/ + #include "asterisk/autoconfig.h" #ifdef __Darwin__ diff --git a/utils/refcounter.c b/utils/refcounter.c index 1c679e822..b45680e0d 100644 --- a/utils/refcounter.c +++ b/utils/refcounter.c @@ -39,6 +39,10 @@ * \author Steve Murphy */ +/*** MODULEINFO + extended + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/utils/smsq.c b/utils/smsq.c index c6aaff8e2..fab32f086 100644 --- a/utils/smsq.c +++ b/utils/smsq.c @@ -17,6 +17,10 @@ * at the top of the source tree. */ +/*** MODULEINFO + extended + ***/ + #include "asterisk.h" #include diff --git a/utils/stereorize.c b/utils/stereorize.c index 31f1b1fbe..484304037 100644 --- a/utils/stereorize.c +++ b/utils/stereorize.c @@ -10,6 +10,10 @@ * ****************************************************************************/ +/*** MODULEINFO + extended + ***/ + #include #include #include diff --git a/utils/streamplayer.c b/utils/streamplayer.c index ebb12e54b..6c70b0840 100644 --- a/utils/streamplayer.c +++ b/utils/streamplayer.c @@ -42,6 +42,10 @@ * not work. :) */ +/*** MODULEINFO + extended + ***/ + #include #include #include -- cgit v1.2.3 From 567a2cc04c62038e0dae89abece069437f1c48bb Mon Sep 17 00:00:00 2001 From: rmudgett Date: Thu, 14 Jul 2011 23:34:43 +0000 Subject: Merged revisions 328317 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.10 ................ r328317 | rmudgett | 2011-07-14 18:28:49 -0500 (Thu, 14 Jul 2011) | 13 lines Merged revisions 328302 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.8 ........ r328302 | rmudgett | 2011-07-14 18:12:06 -0500 (Thu, 14 Jul 2011) | 6 lines Missing SIP pvt and channel unlock in sip_set_rtp_peer(). Regression introduced by -r326144. Add missing SIP pvt and channel unlock in sip_set_rtp_peer(). ........ ................ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@328318 f38db490-d61c-443f-a65b-d21fe96a405b --- channels/chan_sip.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/channels/chan_sip.c b/channels/chan_sip.c index fec843627..a8d24797f 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -29075,7 +29075,9 @@ static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *i if ((instance || vinstance || tinstance) && !ast_bridged_channel(chan) && !sip_cfg.directrtpsetup) { - return 0; + sip_pvt_unlock(p); + ast_channel_unlock(chan); + return 0; } if (p->alreadygone) { -- cgit v1.2.3 From 2abe989c60aa7892a23f95eebaadb6163e70a866 Mon Sep 17 00:00:00 2001 From: rmudgett Date: Fri, 15 Jul 2011 00:23:14 +0000 Subject: Merged revisions 328329 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.10 ........ r328329 | rmudgett | 2011-07-14 19:19:32 -0500 (Thu, 14 Jul 2011) | 2 lines Make hint watcher callback take const strings for context and exten parameters. ........ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@328344 f38db490-d61c-443f-a65b-d21fe96a405b --- apps/app_queue.c | 2 +- channels/chan_sip.c | 4 ++-- channels/chan_skinny.c | 4 ++-- include/asterisk/extconf.h | 2 +- include/asterisk/pbx.h | 2 +- main/manager.c | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/app_queue.c b/apps/app_queue.c index fdb36fed1..025c84cac 100644 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -1573,7 +1573,7 @@ static int extensionstate2devicestate(int state) return state; } -static int extension_state_cb(char *context, char *exten, enum ast_extension_states state, void *data) +static int extension_state_cb(const char *context, const char *exten, enum ast_extension_states state, void *data) { struct ao2_iterator miter, qiter; struct member *m; diff --git a/channels/chan_sip.c b/channels/chan_sip.c index a8d24797f..603d86953 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -1351,7 +1351,7 @@ static int attempt_transfer(struct sip_dual *transferer, struct sip_dual *target static int do_magic_pickup(struct ast_channel *channel, const char *extension, const char *context); /*--- Device monitoring and Device/extension state/event handling */ -static int cb_extensionstate(char *context, char* exten, int state, void *data); +static int cb_extensionstate(const char *context, const char *exten, enum ast_extension_states state, void *data); static int sip_devicestate(void *data); static int sip_poke_noanswer(const void *data); static int sip_poke_peer(struct sip_peer *peer, int force); @@ -14346,7 +14346,7 @@ static void network_change_event_cb(const struct ast_event *event, void *userdat /*! \brief Callback for the devicestate notification (SUBSCRIBE) support subsystem \note If you add an "hint" priority to the extension in the dial plan, you will get notifications on device state changes */ -static int cb_extensionstate(char *context, char* exten, int state, void *data) +static int cb_extensionstate(const char *context, const char *exten, enum ast_extension_states state, void *data) { struct sip_pvt *p = data; diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c index 80338c7d0..38640915c 100644 --- a/channels/chan_skinny.c +++ b/channels/chan_skinny.c @@ -1423,7 +1423,7 @@ static struct ast_channel_tech skinny_tech = { .bridge = ast_rtp_instance_bridge, }; -static int skinny_extensionstate_cb(char *context, char* exten, int state, void *data); +static int skinny_extensionstate_cb(const char *context, const char *exten, enum ast_extension_states state, void *data); static int skinny_transfer(struct skinny_subchannel *sub); static struct skinny_line *skinny_line_alloc(void) @@ -2796,7 +2796,7 @@ static void transmit_capabilitiesreq(struct skinny_device *d) transmit_response(d, req); } -static int skinny_extensionstate_cb(char *context, char *exten, int state, void *data) +static int skinny_extensionstate_cb(const char *context, const char *exten, enum ast_extension_states state, void *data) { struct skinny_speeddial *sd = data; struct skinny_device *d = sd->parent; diff --git a/include/asterisk/extconf.h b/include/asterisk/extconf.h index a5d36ad23..1a04b01bf 100644 --- a/include/asterisk/extconf.h +++ b/include/asterisk/extconf.h @@ -111,7 +111,7 @@ struct ast_exten { char stuff[0]; }; /* from pbx.h */ -typedef int (*ast_state_cb_type)(char *context, char* id, enum ast_extension_states state, void *data); +typedef int (*ast_state_cb_type)(const char *context, const char *exten, enum ast_extension_states state, void *data); struct ast_timing { int hastime; /*!< If time construct exists */ unsigned int monthmask; /*!< Mask for month */ diff --git a/include/asterisk/pbx.h b/include/asterisk/pbx.h index 1489ee2d6..36bc0724c 100644 --- a/include/asterisk/pbx.h +++ b/include/asterisk/pbx.h @@ -76,7 +76,7 @@ struct ast_ignorepat; struct ast_sw; /*! \brief Typedef for devicestate and hint callbacks */ -typedef int (*ast_state_cb_type)(char *context, char* id, enum ast_extension_states state, void *data); +typedef int (*ast_state_cb_type)(const char *context, const char *exten, enum ast_extension_states state, void *data); /*! \brief Data structure associated with a custom dialplan function */ struct ast_custom_function { diff --git a/main/manager.c b/main/manager.c index 98daad084..94782418c 100644 --- a/main/manager.c +++ b/main/manager.c @@ -5140,7 +5140,7 @@ int ast_manager_unregister(char *action) return 0; } -static int manager_state_cb(char *context, char *exten, int state, void *data) +static int manager_state_cb(const char *context, const char *exten, enum ast_extension_states state, void *data) { /* Notify managers of change */ char hint[512]; -- cgit v1.2.3 From f63908a68ac93f2954f7ff8f0d958ee4e13a48ad Mon Sep 17 00:00:00 2001 From: wedhorn Date: Fri, 15 Jul 2011 08:19:46 +0000 Subject: Add SLA to skinny. Adds sublines to skinny lines. Each subline can be attached to an SLA station/trunk combo. Includes the following functionality: Callid is persistent for both in/out calls on all skinny devices. Can join, hold, resume. All sublines appear under a single line button. See: https://wiki.asterisk.org/wiki/display/~wedhorn/Skinny+SLA for doc. (closes issue ASTERISK-17947) Review: https://reviewboard.asterisk.org/r/1239/ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@328381 f38db490-d61c-443f-a65b-d21fe96a405b --- channels/chan_skinny.c | 748 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 630 insertions(+), 118 deletions(-) diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c index 38640915c..dad151ea1 100644 --- a/channels/chan_skinny.c +++ b/channels/chan_skinny.c @@ -255,6 +255,9 @@ AST_THREADSTORAGE(control2str_threadbuf); AST_THREADSTORAGE(substate2str_threadbuf); #define SUBSTATE2STR_BUFSIZE 15 +AST_THREADSTORAGE(callstate2str_threadbuf); +#define CALLSTATE2STR_BUFSIZE 15 + /********************* * Protocol Messages * *********************/ @@ -639,6 +642,8 @@ struct soft_key_template_definition { #define KEYDEF_RINGOUT 8 #define KEYDEF_OFFHOOKWITHFEAT 9 #define KEYDEF_UNKNOWN 10 +#define KEYDEF_SLAHOLD 11 +#define KEYDEF_SLACONNECTEDNOTACTIVE 12 #define SOFTKEY_NONE 0x00 #define SOFTKEY_REDIAL 0x01 @@ -898,6 +903,18 @@ static const uint8_t soft_key_default_unknown[] = { SOFTKEY_NONE, }; +static const uint8_t soft_key_default_SLAhold[] = { + SOFTKEY_REDIAL, + SOFTKEY_NEWCALL, + SOFTKEY_RESUME, +}; + +static const uint8_t soft_key_default_SLAconnectednotactive[] = { + SOFTKEY_REDIAL, + SOFTKEY_NEWCALL, + SOFTKEY_JOIN, +}; + static const struct soft_key_definitions soft_key_default_definitions[] = { {KEYDEF_ONHOOK, soft_key_default_onhook, sizeof(soft_key_default_onhook) / sizeof(uint8_t)}, {KEYDEF_CONNECTED, soft_key_default_connected, sizeof(soft_key_default_connected) / sizeof(uint8_t)}, @@ -909,7 +926,9 @@ static const struct soft_key_definitions soft_key_default_definitions[] = { {KEYDEF_CONNWITHCONF, soft_key_default_connwithconf, sizeof(soft_key_default_connwithconf) / sizeof(uint8_t)}, {KEYDEF_RINGOUT, soft_key_default_ringout, sizeof(soft_key_default_ringout) / sizeof(uint8_t)}, {KEYDEF_OFFHOOKWITHFEAT, soft_key_default_offhookwithfeat, sizeof(soft_key_default_offhookwithfeat) / sizeof(uint8_t)}, - {KEYDEF_UNKNOWN, soft_key_default_unknown, sizeof(soft_key_default_unknown) / sizeof(uint8_t)} + {KEYDEF_UNKNOWN, soft_key_default_unknown, sizeof(soft_key_default_unknown) / sizeof(uint8_t)}, + {KEYDEF_SLAHOLD, soft_key_default_SLAhold, sizeof(soft_key_default_SLAhold) / sizeof(uint8_t)}, + {KEYDEF_SLACONNECTEDNOTACTIVE, soft_key_default_SLAconnectednotactive, sizeof(soft_key_default_SLAconnectednotactive) / sizeof(uint8_t)} }; struct soft_key_template_res_message { @@ -1221,6 +1240,7 @@ struct skinny_subchannel { AST_LIST_ENTRY(skinny_subchannel) list; struct skinny_subchannel *related; struct skinny_line *line; + struct skinny_subline *subline; }; #define SKINNY_LINE_OPTIONS \ @@ -1245,6 +1265,8 @@ struct skinny_subchannel { char mohinterpret[MAX_MUSICCLASS]; \ char mohsuggest[MAX_MUSICCLASS]; \ char lastnumberdialed[AST_MAX_EXTENSION]; \ + char dialoutexten[AST_MAX_EXTENSION]; \ + char dialoutcontext[AST_MAX_CONTEXT]; \ ast_group_t callgroup; \ ast_group_t pickupgroup; \ int callwaiting; \ @@ -1271,9 +1293,11 @@ struct skinny_subchannel { struct skinny_line { SKINNY_LINE_OPTIONS ast_mutex_t lock; + struct skinny_container *container; struct ast_event_sub *mwi_event_sub; /* Event based MWI */ struct skinny_subchannel *activesub; AST_LIST_HEAD(, skinny_subchannel) sub; + AST_LIST_HEAD(, skinny_subline) sublines; AST_LIST_ENTRY(skinny_line) list; AST_LIST_ENTRY(skinny_line) all; struct skinny_device *device; @@ -1300,8 +1324,29 @@ static struct skinny_line_options *default_line = &default_line_struct; static AST_LIST_HEAD_STATIC(lines, skinny_line); +struct skinny_subline { + struct skinny_container *container; + struct skinny_line *line; + struct skinny_subchannel *sub; + AST_LIST_ENTRY(skinny_subline) list; + char name[80]; + char context[AST_MAX_CONTEXT]; + char exten[AST_MAX_EXTENSION]; + char stname[AST_MAX_EXTENSION]; + char lnname[AST_MAX_EXTENSION]; + char ourName[40]; + char ourNum[24]; + char theirName[40]; + char theirNum[24]; + int calldirection; + int substate; + int extenstate; + unsigned int callid; +}; + struct skinny_speeddial { ast_mutex_t lock; + struct skinny_container *container; char label[42]; char context[AST_MAX_CONTEXT]; char exten[AST_MAX_EXTENSION]; @@ -1314,6 +1359,16 @@ struct skinny_speeddial { struct skinny_device *parent; }; +#define SKINNY_DEVICECONTAINER 1 +#define SKINNY_LINECONTAINER 2 +#define SKINNY_SUBLINECONTAINER 3 +#define SKINNY_SDCONTAINER 4 + +struct skinny_container { + int type; + void *data; +}; + struct skinny_addon { ast_mutex_t lock; char type[10]; @@ -1447,6 +1502,7 @@ static struct skinny_line *skinny_line_destroy(struct skinny_line *l) { l->cap = ast_format_cap_destroy(l->cap); l->confcap = ast_format_cap_destroy(l->confcap); + ast_free(l->container); ast_free(l); return NULL; } @@ -1695,6 +1751,47 @@ static struct skinny_line *find_line_by_name(const char *dest) return tmpl; } +static struct skinny_subline *find_subline_by_name(const char *dest) +{ + struct skinny_line *l; + struct skinny_subline *subline; + struct skinny_subline *tmpsubline = NULL; + struct skinny_device *d; + + AST_LIST_LOCK(&devices); + AST_LIST_TRAVERSE(&devices, d, list){ + AST_LIST_TRAVERSE(&d->lines, l, list){ + AST_LIST_TRAVERSE(&l->sublines, subline, list){ + if (!strcasecmp(subline->name, dest)) { + if (tmpsubline) { + ast_verb(2, "Ambiguous subline name: %s\n", dest); + AST_LIST_UNLOCK(&devices); + return NULL; + } else + tmpsubline = subline; + } + } + } + } + AST_LIST_UNLOCK(&devices); + return tmpsubline; +} + +static struct skinny_subline *find_subline_by_callid(struct skinny_device *d, int callid) +{ + struct skinny_subline *subline; + struct skinny_line *l; + + AST_LIST_TRAVERSE(&d->lines, l, list){ + AST_LIST_TRAVERSE(&l->sublines, subline, list){ + if (subline->callid == callid) { + return subline; + } + } + } + return NULL; +} + /*! * implement the setvar config line */ @@ -1946,6 +2043,7 @@ static int skinny_register(struct skinny_req *req, struct skinnysession *s) { struct skinny_device *d; struct skinny_line *l; + struct skinny_subline *subline; struct skinny_speeddial *sd; struct sockaddr_in sin; socklen_t slen; @@ -1973,7 +2071,7 @@ static int skinny_register(struct skinny_req *req, struct skinnysession *s) d->ourip = sin.sin_addr; AST_LIST_TRAVERSE(&d->speeddials, sd, list) { - sd->stateid = ast_extension_state_add(sd->context, sd->exten, skinny_extensionstate_cb, sd); + sd->stateid = ast_extension_state_add(sd->context, sd->exten, skinny_extensionstate_cb, sd->container); } instance = 0; AST_LIST_TRAVERSE(&d->lines, l, list) { @@ -2000,6 +2098,9 @@ static int skinny_register(struct skinny_req *req, struct skinnysession *s) register_exten(l); /* initialize MWI on line and device */ mwi_event_cb(0, l); + AST_LIST_TRAVERSE(&l->sublines, subline, list) { + ast_extension_state_add(subline->context, subline->exten, skinny_extensionstate_cb, subline->container); + } ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Skinny/%s", l->name); } --instance; @@ -2175,6 +2276,40 @@ static char *message2str(int type) return tmp; } } + +static char *callstate2str(int ind) +{ + char *tmp; + + switch (ind) { + case SUBSTATE_OFFHOOK: + return "SKINNY_OFFHOOK"; + case SKINNY_ONHOOK: + return "SKINNY_ONHOOK"; + case SKINNY_RINGOUT: + return "SKINNY_RINGOUT"; + case SKINNY_RINGIN: + return "SKINNY_RINGIN"; + case SKINNY_CONNECTED: + return "SKINNY_CONNECTED"; + case SKINNY_BUSY: + return "SKINNY_BUSY"; + case SKINNY_CONGESTION: + return "SKINNY_CONGESTION"; + case SKINNY_PROGRESS: + return "SKINNY_PROGRESS"; + case SKINNY_HOLD: + return "SKINNY_HOLD"; + case SKINNY_CALLWAIT: + return "SKINNY_CALLWAIT"; + default: + if (!(tmp = ast_threadstorage_get(&callstate2str_threadbuf, CALLSTATE2STR_BUFSIZE))) + return "Unknown"; + snprintf(tmp, CALLSTATE2STR_BUFSIZE, "UNKNOWN-%d", ind); + return tmp; + } +} + #endif static int transmit_response_bysession(struct skinnysession *s, struct skinny_req *req) @@ -2258,24 +2393,46 @@ static void transmit_microphone_mode(struct skinny_device *d, int mode) transmit_response(d, req); } -static void transmit_callinfo(struct skinny_subchannel *sub) +//static void transmit_callinfo(struct skinny_subchannel *sub) +static void transmit_callinfo(struct skinny_device *d, int instance, int callid, char *fromname, char *fromnum, char *toname, char *tonum, int calldirection) { - struct skinny_device *d; - struct skinny_line *l; struct skinny_req *req; + + if (!(req = req_alloc(sizeof(struct call_info_message), CALL_INFO_MESSAGE))) + return; + + if (skinnydebug) { + ast_verb(1, "Setting Callinfo to %s(%s) from %s(%s) (dir=%d) on %s(%d)\n", toname, tonum, fromname, fromnum, calldirection, d->name, instance); + } + + ast_copy_string(req->data.callinfo.callingPartyName, fromname, sizeof(req->data.callinfo.callingPartyName)); + ast_copy_string(req->data.callinfo.callingParty, fromnum, sizeof(req->data.callinfo.callingParty)); + ast_copy_string(req->data.callinfo.calledPartyName, toname, sizeof(req->data.callinfo.calledPartyName)); + ast_copy_string(req->data.callinfo.calledParty, tonum, sizeof(req->data.callinfo.calledParty)); + req->data.callinfo.instance = htolel(instance); + req->data.callinfo.reference = htolel(callid); + req->data.callinfo.type = htolel(calldirection); + transmit_response(d, req); +} + +static void send_callinfo(struct skinny_subchannel *sub) +{ struct ast_channel *ast; + struct skinny_device *d; + struct skinny_line *l; char *fromname; char *fromnum; char *toname; char *tonum; - if (!sub || !(l=sub->line) || !(d=l->device) || !(ast=sub->owner)) { + if (!sub || !sub->owner || !sub->line || !sub->line->device) { return; } - - if (!(req = req_alloc(sizeof(struct call_info_message), CALL_INFO_MESSAGE))) - return; - + + ast = sub->owner; + l = sub->line; + d = l->device; + if (sub->calldirection == SKINNY_INCOMING) { fromname = S_COR(ast->connected.id.name.valid, ast->connected.id.name.str, ""); fromnum = S_COR(ast->connected.id.number.valid, ast->connected.id.number.str, ""); @@ -2290,19 +2447,42 @@ static void transmit_callinfo(struct skinny_subchannel *sub) ast_verb(1, "Error sending Callinfo to %s(%d) - No call direction in sub\n", d->name, l->instance); return; } + transmit_callinfo(d, l->instance, sub->callid, fromname, fromnum, toname, tonum, sub->calldirection); +} - if (skinnydebug) { - ast_verb(1, "Setting Callinfo to %s(%s) from %s(%s) (dir=%d) on %s(%d)\n", toname, tonum, fromname, fromnum, sub->calldirection, d->name, l->instance); +static void push_callinfo(struct skinny_subline *subline, struct skinny_subchannel *sub) +{ + struct ast_channel *ast; + struct skinny_device *d; + struct skinny_line *l; + char *fromname; + char *fromnum; + char *toname; + char *tonum; + + if (!sub || !sub->owner || !sub->line || !sub->line->device) { + return; } - ast_copy_string(req->data.callinfo.callingPartyName, fromname, sizeof(req->data.callinfo.callingPartyName)); - ast_copy_string(req->data.callinfo.callingParty, fromnum, sizeof(req->data.callinfo.callingParty)); - ast_copy_string(req->data.callinfo.calledPartyName, toname, sizeof(req->data.callinfo.calledPartyName)); - ast_copy_string(req->data.callinfo.calledParty, tonum, sizeof(req->data.callinfo.calledParty)); - req->data.callinfo.instance = htolel(l->instance); - req->data.callinfo.reference = htolel(sub->callid); - req->data.callinfo.type = htolel(sub->calldirection); - transmit_response(d, req); + ast = sub->owner; + l = sub->line; + d = l->device; + + if (sub->calldirection == SKINNY_INCOMING) { + fromname = S_COR(ast->connected.id.name.valid, ast->connected.id.name.str, ""); + fromnum = S_COR(ast->connected.id.number.valid, ast->connected.id.number.str, ""); + toname = S_COR(ast->caller.id.name.valid, ast->caller.id.name.str, ""); + tonum = S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, ""); + } else if (sub->calldirection == SKINNY_OUTGOING) { + fromname = S_COR(ast->caller.id.name.valid, ast->caller.id.name.str, ""); + fromnum = S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, ""); + toname = S_COR(ast->connected.id.name.valid, ast->connected.id.name.str, l->lastnumberdialed); + tonum = S_COR(ast->connected.id.number.valid, ast->connected.id.number.str, l->lastnumberdialed); + } else { + ast_verb(1, "Error sending Callinfo to %s(%d) - No call direction in sub\n", d->name, l->instance); + return; + } + transmit_callinfo(subline->line->device, subline->line->instance, subline->callid, fromname, fromnum, toname, tonum, sub->calldirection); } static void transmit_connect(struct skinny_device *d, struct skinny_subchannel *sub) @@ -2559,6 +2739,12 @@ static void transmit_callstate(struct skinny_device *d, int buttonInstance, unsi if (!(req = req_alloc(sizeof(struct call_state_message), CALL_STATE_MESSAGE))) return; + +#ifdef SKINNY_DEVMODE + if (skinnydebug) { + ast_verb(3, "Transmitting CALL_STATE_MESSAGE to %s - line %d, callid %d, state %s\n", d->name, buttonInstance, callid, callstate2str(state)); + } +#endif req->data.callstate.callState = htolel(state); req->data.callstate.lineInstance = htolel(buttonInstance); @@ -2703,8 +2889,8 @@ static void transmit_softkeysetres(struct skinny_device *d) return; req->data.softkeysets.softKeySetOffset = htolel(0); - req->data.softkeysets.softKeySetCount = htolel(11); - req->data.softkeysets.totalSoftKeySetCount = htolel(11); + req->data.softkeysets.softKeySetCount = htolel(13); + req->data.softkeysets.totalSoftKeySetCount = htolel(13); for (x = 0; x < sizeof(soft_key_default_definitions) / sizeof(struct soft_key_definitions); x++) { const uint8_t *defaults = softkeymode->defaults; /* XXX I wanted to get the size of the array dynamically, but that wasn't wanting to work. @@ -2798,49 +2984,109 @@ static void transmit_capabilitiesreq(struct skinny_device *d) static int skinny_extensionstate_cb(const char *context, const char *exten, enum ast_extension_states state, void *data) { - struct skinny_speeddial *sd = data; - struct skinny_device *d = sd->parent; + struct skinny_container *container = data; + struct skinny_device *d = NULL; char hint[AST_MAX_EXTENSION]; - if (ast_get_hint(hint, sizeof(hint), NULL, 0, NULL, sd->context, sd->exten)) { - /* If they are not registered, we will override notification and show no availability */ - if (ast_device_state(hint) == AST_DEVICE_UNAVAILABLE) { - transmit_lamp_indication(d, STIMULUS_LINE, sd->instance, SKINNY_LAMP_FLASH); - transmit_callstate(d, sd->instance, 0, SKINNY_ONHOOK); + if (container->type == SKINNY_SDCONTAINER) { + struct skinny_speeddial *sd = container->data; + d = sd->parent; + + if (skinnydebug) { + ast_verb(2, "Got hint %s on speeddial %s\n", ast_extension_state2str(state), sd->label); + } + + if (ast_get_hint(hint, sizeof(hint), NULL, 0, NULL, sd->context, sd->exten)) { + /* If they are not registered, we will override notification and show no availability */ + if (ast_device_state(hint) == AST_DEVICE_UNAVAILABLE) { + transmit_lamp_indication(d, STIMULUS_LINE, sd->instance, SKINNY_LAMP_FLASH); + transmit_callstate(d, sd->instance, 0, SKINNY_ONHOOK); + return 0; + } + switch (state) { + case AST_EXTENSION_DEACTIVATED: /* Retry after a while */ + case AST_EXTENSION_REMOVED: /* Extension is gone */ + ast_verb(2, "Extension state: Watcher for hint %s %s. Notify Device %s\n", exten, state == AST_EXTENSION_DEACTIVATED ? "deactivated" : "removed", d->name); + sd->stateid = -1; + transmit_lamp_indication(d, STIMULUS_LINE, sd->instance, SKINNY_LAMP_OFF); + transmit_callstate(d, sd->instance, 0, SKINNY_ONHOOK); + break; + case AST_EXTENSION_RINGING: + case AST_EXTENSION_UNAVAILABLE: + transmit_lamp_indication(d, STIMULUS_LINE, sd->instance, SKINNY_LAMP_BLINK); + transmit_callstate(d, sd->instance, 0, SKINNY_RINGIN); + break; + case AST_EXTENSION_BUSY: /* callstate = SKINNY_BUSY wasn't wanting to work - I'll settle for this */ + case AST_EXTENSION_INUSE: + transmit_lamp_indication(d, STIMULUS_LINE, sd->instance, SKINNY_LAMP_ON); + transmit_callstate(d, sd->instance, 0, SKINNY_CALLREMOTEMULTILINE); + break; + case AST_EXTENSION_ONHOLD: + transmit_lamp_indication(d, STIMULUS_LINE, sd->instance, SKINNY_LAMP_WINK); + transmit_callstate(d, sd->instance, 0, SKINNY_HOLD); + break; + case AST_EXTENSION_NOT_INUSE: + default: + transmit_lamp_indication(d, STIMULUS_LINE, sd->instance, SKINNY_LAMP_OFF); + transmit_callstate(d, sd->instance, 0, SKINNY_ONHOOK); + break; + } + } + sd->laststate = state; + } else if (container->type == SKINNY_SUBLINECONTAINER) { + struct skinny_subline *subline = container->data; + struct skinny_line *l = subline->line; + d = l->device; + + if (skinnydebug) { + ast_verb(2, "Got hint %s on subline %s (%s@%s)\n", ast_extension_state2str(state), subline->name, exten, context); + } + + subline->extenstate = state; + + if (subline->callid == 0) { return 0; } + switch (state) { - case AST_EXTENSION_DEACTIVATED: /* Retry after a while */ - case AST_EXTENSION_REMOVED: /* Extension is gone */ - ast_verb(2, "Extension state: Watcher for hint %s %s. Notify Device %s\n", exten, state == AST_EXTENSION_DEACTIVATED ? "deactivated" : "removed", d->name); - sd->stateid = -1; - transmit_lamp_indication(d, STIMULUS_LINE, sd->instance, SKINNY_LAMP_OFF); - transmit_callstate(d, sd->instance, 0, SKINNY_ONHOOK); + case AST_EXTENSION_RINGING: /* Handled by normal ringin */ break; - case AST_EXTENSION_RINGING: - case AST_EXTENSION_UNAVAILABLE: - transmit_lamp_indication(d, STIMULUS_LINE, sd->instance, SKINNY_LAMP_BLINK); - transmit_callstate(d, sd->instance, 0, SKINNY_RINGIN); - break; - case AST_EXTENSION_BUSY: /* callstate = SKINNY_BUSY wasn't wanting to work - I'll settle for this */ case AST_EXTENSION_INUSE: - transmit_lamp_indication(d, STIMULUS_LINE, sd->instance, SKINNY_LAMP_ON); - transmit_callstate(d, sd->instance, 0, SKINNY_CALLREMOTEMULTILINE); + if (subline->sub && (subline->sub->substate == SKINNY_CONNECTED)) { /* Device has a real call */ + transmit_callstate(d, l->instance, subline->callid, SKINNY_CONNECTED); + transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_CONNECTED); + transmit_displaypromptstatus(d, "Connected", 0, l->instance, subline->callid); + } else { /* Some other device has active call */ + transmit_callstate(d, l->instance, subline->callid, SKINNY_CALLREMOTEMULTILINE); + transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_SLACONNECTEDNOTACTIVE); + transmit_displaypromptstatus(d, "In Use", 0, l->instance, subline->callid); + } + transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_ON); + transmit_ringer_mode(d, SKINNY_RING_OFF); + transmit_activatecallplane(d, l); break; case AST_EXTENSION_ONHOLD: - transmit_lamp_indication(d, STIMULUS_LINE, sd->instance, SKINNY_LAMP_WINK); - transmit_callstate(d, sd->instance, 0, SKINNY_HOLD); + transmit_callstate(d, l->instance, subline->callid, SKINNY_HOLD); + transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_SLAHOLD); + transmit_displaypromptstatus(d, "Hold", 0, l->instance, subline->callid); + transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_BLINK); + transmit_activatecallplane(d, l); break; case AST_EXTENSION_NOT_INUSE: - default: - transmit_lamp_indication(d, STIMULUS_LINE, sd->instance, SKINNY_LAMP_OFF); - transmit_callstate(d, sd->instance, 0, SKINNY_ONHOOK); + transmit_callstate(d, l->instance, subline->callid, SKINNY_ONHOOK); + transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_ONHOOK); + transmit_clearpromptmessage(d, l->instance, subline->callid); + transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_OFF); + transmit_activatecallplane(d, l); + subline->callid = 0; break; + default: + ast_log(LOG_WARNING, "AST_EXTENSION_STATE %s not configured\n", ast_extension_state2str(state)); } + } else { + ast_log(LOG_WARNING, "Invalid data supplied to skinny_extensionstate_cb\n"); } - sd->laststate = state; - return 0; } @@ -2860,7 +3106,7 @@ static void update_connectedline(struct skinny_subchannel *sub, const void *data ast_verb(3,"Sub %d - Updating\n", sub->callid); } - transmit_callinfo(sub); + send_callinfo(sub); if (sub->owner->_state == AST_STATE_UP) { transmit_callstate(d, l->instance, sub->callid, SKINNY_CONNECTED); transmit_displaypromptstatus(d, "Connected", 0, l->instance, sub->callid); @@ -3657,6 +3903,7 @@ static char *_skinny_show_line(int type, int fd, struct mansession *s, const str { struct skinny_device *d; struct skinny_line *l; + struct skinny_subline *subline; struct ast_codec_pref *pref; int x = 0; char codec_buf[512]; @@ -3727,6 +3974,12 @@ static char *_skinny_show_line(int type, int fd, struct mansession *s, const str ast_cli(fd, "Codec Order: ("); print_codec_to_cli(fd, &l->prefs); ast_cli(fd, ")\n"); + if (AST_LIST_FIRST(&l->sublines)) { + ast_cli(fd, "Sublines:\n"); + AST_LIST_TRAVERSE(&l->sublines, subline, list) { + ast_cli(fd, " %s, %s@%s\n", subline->name, subline->exten, subline->context); + } + } ast_cli(fd, "\n"); } else { /* manager */ astman_append(s, "Channeltype: SKINNY\r\n"); @@ -3927,7 +4180,6 @@ static void *skinny_newcall(void *data) struct skinny_device *d = l->device; int res = 0; - ast_copy_string(l->lastnumberdialed, c->exten, sizeof(l->lastnumberdialed)); ast_set_callerid(c, l->hidecallerid ? "" : l->cid_num, l->hidecallerid ? "" : l->cid_name, @@ -3944,6 +4196,7 @@ static void *skinny_newcall(void *data) if (!sub->rtp) { start_rtp(sub); } + ast_verb(3, "Sub %d - Calling %s@%s\n", sub->callid, c->exten, c->context); res = ast_pbx_run(c); if (res) { ast_log(LOG_WARNING, "PBX exited non-zero\n"); @@ -4523,7 +4776,7 @@ static int skinny_indicate(struct ast_channel *ast, int ind, const void *data, s return 0; } -static struct ast_channel *skinny_new(struct skinny_line *l, int state, const char *linkedid, int direction) +static struct ast_channel *skinny_new(struct skinny_line *l, struct skinny_subline *subline, int state, const char *linkedid, int direction) { struct ast_channel *tmp; struct skinny_subchannel *sub; @@ -4560,6 +4813,13 @@ static struct ast_channel *skinny_new(struct skinny_line *l, int state, const ch sub->related = NULL; sub->calldirection = direction; + if (subline) { + sub->subline = subline; + subline->sub = sub; + } else { + sub->subline = NULL; + } + AST_LIST_INSERT_HEAD(&l->sub, sub, list); //l->activesub = sub; } @@ -4610,7 +4870,11 @@ static struct ast_channel *skinny_new(struct skinny_line *l, int state, const ch } } - ast_copy_string(tmp->context, l->context, sizeof(tmp->context)); + if (subline) { + ast_copy_string(tmp->context, subline->context, sizeof(tmp->context)); + } else { + ast_copy_string(tmp->context, l->context, sizeof(tmp->context)); + } ast_copy_string(tmp->exten, l->exten, sizeof(tmp->exten)); /* Don't use ast_set_callerid() here because it will @@ -4679,6 +4943,7 @@ static char *substate2str(int ind) { static void setsubstate(struct skinny_subchannel *sub, int state) { struct skinny_line *l = sub->line; + struct skinny_subline *subline = sub->subline; struct skinny_device *d = l->device; struct ast_channel *c = sub->owner; pthread_t t; @@ -4698,7 +4963,118 @@ static void setsubstate(struct skinny_subchannel *sub, int state) if ((state == SUBSTATE_RINGIN) && ((d->hookstate == SKINNY_OFFHOOK) || (AST_LIST_NEXT(AST_LIST_FIRST(&l->sub), list)))) { actualstate = SUBSTATE_CALLWAIT; } - + + if ((state == SUBSTATE_CONNECTED) && (!subline) && (AST_LIST_FIRST(&l->sublines))) { + const char *slastation; + struct skinny_subline *tmpsubline; + slastation = pbx_builtin_getvar_helper(c, "SLASTATION"); + ast_verb(3, "Connecting %s to subline\n", slastation); + if (slastation) { + AST_LIST_TRAVERSE(&l->sublines, tmpsubline, list) { + if (!strcasecmp(tmpsubline->stname, slastation)) { + subline = tmpsubline; + break; + } + } + if (subline) { + struct skinny_line *tmpline; + subline->sub = sub; + sub->subline = subline; + subline->callid = sub->callid; + send_callinfo(sub); + AST_LIST_TRAVERSE(&lines, tmpline, all) { + AST_LIST_TRAVERSE(&tmpline->sublines, tmpsubline, list) { + if (!(subline == tmpsubline)) { + if (!strcasecmp(subline->lnname, tmpsubline->lnname)) { + tmpsubline->callid = callnums++; + transmit_callstate(tmpsubline->line->device, tmpsubline->line->instance, tmpsubline->callid, SKINNY_OFFHOOK); + push_callinfo(tmpsubline, sub); + skinny_extensionstate_cb(NULL, NULL, tmpsubline->extenstate, tmpsubline->container); + } + } + } + } + } + } + } + + if (subline) { /* Different handling for subs under a subline, indications come through hints */ + switch (actualstate) { + case SUBSTATE_ONHOOK: + AST_LIST_REMOVE(&l->sub, sub, list); + if (sub->related) { + sub->related->related = NULL; + } + + if (sub == l->activesub) { + l->activesub = NULL; + transmit_closereceivechannel(d, sub); + transmit_stopmediatransmission(d, sub); + } + + if (subline->callid) { + transmit_stop_tone(d, l->instance, sub->callid); + transmit_callstate(d, l->instance, subline->callid, SKINNY_CALLREMOTEMULTILINE); + transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_SLACONNECTEDNOTACTIVE); + transmit_displaypromptstatus(d, "In Use", 0, l->instance, subline->callid); + } + + sub->cxmode = SKINNY_CX_RECVONLY; + sub->substate = SUBSTATE_ONHOOK; + if (sub->rtp) { + ast_rtp_instance_destroy(sub->rtp); + sub->rtp = NULL; + } + sub->substate = SUBSTATE_ONHOOK; + if (sub->owner) { + ast_queue_hangup(sub->owner); + } + return; + case SUBSTATE_CONNECTED: + transmit_activatecallplane(d, l); + transmit_stop_tone(d, l->instance, sub->callid); + transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_CONNECTED); + transmit_callstate(d, l->instance, subline->callid, SKINNY_CONNECTED); + if (!sub->rtp) { + start_rtp(sub); + } + if (sub->substate == SUBSTATE_RINGIN || sub->substate == SUBSTATE_CALLWAIT) { + ast_queue_control(sub->owner, AST_CONTROL_ANSWER); + } + if (sub->substate == SUBSTATE_DIALING || sub->substate == SUBSTATE_RINGOUT) { + transmit_dialednumber(d, l->lastnumberdialed, l->instance, sub->callid); + } + if (sub->owner->_state != AST_STATE_UP) { + ast_setstate(sub->owner, AST_STATE_UP); + } + sub->substate = SUBSTATE_CONNECTED; + l->activesub = sub; + return; + case SUBSTATE_HOLD: + if (sub->substate != SUBSTATE_CONNECTED) { + ast_log(LOG_WARNING, "Cannot set substate to SUBSTATE_HOLD from %s (on call-%d)\n", substate2str(sub->substate), sub->callid); + return; + } + transmit_activatecallplane(d, l); + transmit_closereceivechannel(d, sub); + transmit_stopmediatransmission(d, sub); + + transmit_callstate(d, l->instance, subline->callid, SKINNY_CALLREMOTEMULTILINE); + transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_SLACONNECTEDNOTACTIVE); + transmit_displaypromptstatus(d, "In Use", 0, l->instance, subline->callid); + + sub->substate = SUBSTATE_HOLD; + + ast_queue_control_data(sub->owner, AST_CONTROL_HOLD, + S_OR(l->mohsuggest, NULL), + !ast_strlen_zero(l->mohsuggest) ? strlen(l->mohsuggest) + 1 : 0); + + return; + default: + ast_log(LOG_WARNING, "Substate handling under subline for state %d not implemented on Sub-%d\n", state, sub->callid); + } + } + if ((d->hookstate == SKINNY_ONHOOK) && ((actualstate == SUBSTATE_OFFHOOK) || (actualstate == SUBSTATE_DIALING) || (actualstate == SUBSTATE_RINGOUT) || (actualstate == SUBSTATE_CONNECTED) || (actualstate == SUBSTATE_BUSY) || (actualstate == SUBSTATE_CONGESTION) || (actualstate == SUBSTATE_PROGRESS))) { @@ -4711,7 +5087,7 @@ static void setsubstate(struct skinny_subchannel *sub, int state) } if (actualstate == sub->substate) { - transmit_callinfo(sub); + send_callinfo(sub); transmit_callstate(d, l->instance, sub->callid, SKINNY_HOLD); return; } @@ -4769,24 +5145,40 @@ static void setsubstate(struct skinny_subchannel *sub, int state) break; case SUBSTATE_DIALING: if (ast_strlen_zero(sub->exten) || !ast_exists_extension(c, c->context, sub->exten, 1, l->cid_num)) { - ast_log(LOG_WARNING, "Exten (%s) does not exist, unable to set substate DIALING on sub %d\n", sub->exten, sub->callid); + ast_log(LOG_WARNING, "Exten (%s)@(%s) does not exist, unable to set substate DIALING on sub %d\n", sub->exten, c->context, sub->callid); return; } if (d->hookstate == SKINNY_ONHOOK) { d->hookstate = SKINNY_OFFHOOK; transmit_speaker_mode(d, SKINNY_SPEAKERON); - transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK); transmit_activatecallplane(d, l); } - transmit_stop_tone(d, l->instance, sub->callid); - transmit_clear_display_message(d, l->instance, sub->callid); - transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGOUT); - transmit_displaypromptstatus(d, "Dialing", 0, l->instance, sub->callid); - ast_copy_string(c->exten, sub->exten, sizeof(c->exten)); - ast_copy_string(l->lastnumberdialed, sub->exten, sizeof(l->lastnumberdialed)); + if (!sub->subline) { + transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK); + transmit_stop_tone(d, l->instance, sub->callid); + transmit_clear_display_message(d, l->instance, sub->callid); + transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGOUT); + transmit_displaypromptstatus(d, "Dialing", 0, l->instance, sub->callid); + } + if (AST_LIST_FIRST(&l->sublines)) { + if (subline) { + ast_copy_string(c->exten, subline->exten, sizeof(c->exten)); + ast_copy_string(c->context, "sla_stations", sizeof(c->context)); + } else { + pbx_builtin_setvar_helper(c, "_DESTEXTEN", sub->exten); + pbx_builtin_setvar_helper(c, "_DESTCONTEXT", c->context); + ast_copy_string(c->exten, l->dialoutexten, sizeof(c->exten)); + ast_copy_string(c->context, l->dialoutcontext, sizeof(c->context)); + ast_copy_string(l->lastnumberdialed, sub->exten, sizeof(l->lastnumberdialed)); + } + } else { + ast_copy_string(c->exten, sub->exten, sizeof(c->exten)); + ast_copy_string(l->lastnumberdialed, sub->exten, sizeof(l->lastnumberdialed)); + } + sub->substate = SUBSTATE_DIALING; if (ast_pthread_create(&t, NULL, skinny_newcall, c)) { @@ -4806,14 +5198,14 @@ static void setsubstate(struct skinny_subchannel *sub, int state) transmit_callstate(d, l->instance, sub->callid, SKINNY_RINGOUT); transmit_dialednumber(d, l->lastnumberdialed, l->instance, sub->callid); transmit_displaypromptstatus(d, "Ring Out", 0, l->instance, sub->callid); - transmit_callinfo(sub); + send_callinfo(sub); sub->substate = SUBSTATE_RINGOUT; break; case SUBSTATE_RINGIN: transmit_callstate(d, l->instance, sub->callid, SKINNY_RINGIN); transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGIN); transmit_displaypromptstatus(d, "Ring-In", 0, l->instance, sub->callid); - transmit_callinfo(sub); + send_callinfo(sub); transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_BLINK); transmit_ringer_mode(d, SKINNY_RING_INSIDE); transmit_activatecallplane(d, l); @@ -4833,7 +5225,7 @@ static void setsubstate(struct skinny_subchannel *sub, int state) transmit_callstate(d, l->instance, sub->callid, SKINNY_CALLWAIT); transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGIN); transmit_displaypromptstatus(d, "Callwaiting", 0, l->instance, sub->callid); - transmit_callinfo(sub); + send_callinfo(sub); transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_BLINK); transmit_start_tone(d, SKINNY_CALLWAITTONE, l->instance, sub->callid); @@ -4849,7 +5241,7 @@ static void setsubstate(struct skinny_subchannel *sub, int state) transmit_ringer_mode(d, SKINNY_RING_OFF); transmit_activatecallplane(d, l); transmit_stop_tone(d, l->instance, sub->callid); - transmit_callinfo(sub); + send_callinfo(sub); transmit_callstate(d, l->instance, sub->callid, SKINNY_CONNECTED); transmit_displaypromptstatus(d, "Connected", 0, l->instance, sub->callid); transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_CONNECTED); @@ -4883,7 +5275,7 @@ static void setsubstate(struct skinny_subchannel *sub, int state) if (!d->earlyrtp) { transmit_start_tone(d, SKINNY_BUSYTONE, l->instance, sub->callid); } - transmit_callinfo(sub); + send_callinfo(sub); transmit_callstate(d, l->instance, sub->callid, SKINNY_BUSY); transmit_displaypromptstatus(d, "Busy", 0, l->instance, sub->callid); sub->substate = SUBSTATE_BUSY; @@ -4897,7 +5289,7 @@ static void setsubstate(struct skinny_subchannel *sub, int state) if (!d->earlyrtp) { transmit_start_tone(d, SKINNY_REORDER, l->instance, sub->callid); } - transmit_callinfo(sub); + send_callinfo(sub); transmit_callstate(d, l->instance, sub->callid, SKINNY_CONGESTION); transmit_displaypromptstatus(d, "Congestion", 0, l->instance, sub->callid); sub->substate = SUBSTATE_CONGESTION; @@ -4911,7 +5303,7 @@ static void setsubstate(struct skinny_subchannel *sub, int state) if (!d->earlyrtp) { transmit_start_tone(d, SKINNY_ALERT, l->instance, sub->callid); } - transmit_callinfo(sub); + send_callinfo(sub); transmit_callstate(d, l->instance, sub->callid, SKINNY_PROGRESS); transmit_displaypromptstatus(d, "Call Progress", 0, l->instance, sub->callid); sub->substate = SUBSTATE_PROGRESS; @@ -5063,7 +5455,7 @@ static int handle_transfer_button(struct skinny_subchannel *sub) if (!(sub->substate == SUBSTATE_HOLD)) { setsubstate(sub, SUBSTATE_HOLD); } - c = skinny_new(l, AST_STATE_DOWN, NULL, SKINNY_OUTGOING); + c = skinny_new(l, NULL, AST_STATE_DOWN, NULL, SKINNY_OUTGOING); if (c) { newsub = c->tech_pvt; /* point the sub and newsub at each other so we know they are related */ @@ -5251,7 +5643,7 @@ static int handle_stimulus_message(struct skinny_req *req, struct skinnysession break; } - c = skinny_new(l, AST_STATE_DOWN, NULL, SKINNY_OUTGOING); + c = skinny_new(l, NULL, AST_STATE_DOWN, NULL, SKINNY_OUTGOING); if (!c) { ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name); } else { @@ -5271,7 +5663,7 @@ static int handle_stimulus_message(struct skinny_req *req, struct skinnysession } if (!sub || !sub->owner) - c = skinny_new(l, AST_STATE_DOWN, NULL, SKINNY_OUTGOING); + c = skinny_new(l, NULL, AST_STATE_DOWN, NULL, SKINNY_OUTGOING); else c = sub->owner; @@ -5307,7 +5699,7 @@ static int handle_stimulus_message(struct skinny_req *req, struct skinnysession } if (!sub || !sub->owner) { - c = skinny_new(l, AST_STATE_DOWN, NULL, SKINNY_OUTGOING); + c = skinny_new(l, NULL, AST_STATE_DOWN, NULL, SKINNY_OUTGOING); } else { c = sub->owner; } @@ -5369,7 +5761,7 @@ static int handle_stimulus_message(struct skinny_req *req, struct skinnysession ast_verb(1, "Received Stimulus: Forward All(%d/%d)\n", instance, callreference); if (!sub || !sub->owner) { - c = skinny_new(l, AST_STATE_DOWN, NULL, SKINNY_OUTGOING); + c = skinny_new(l, NULL, AST_STATE_DOWN, NULL, SKINNY_OUTGOING); } else { c = sub->owner; } @@ -5386,7 +5778,7 @@ static int handle_stimulus_message(struct skinny_req *req, struct skinnysession ast_verb(1, "Received Stimulus: Forward Busy (%d/%d)\n", instance, callreference); if (!sub || !sub->owner) { - c = skinny_new(l, AST_STATE_DOWN, NULL, SKINNY_OUTGOING); + c = skinny_new(l, NULL, AST_STATE_DOWN, NULL, SKINNY_OUTGOING); } else { c = sub->owner; } @@ -5404,7 +5796,7 @@ static int handle_stimulus_message(struct skinny_req *req, struct skinnysession #if 0 /* Not sure how to handle this yet */ if (!sub || !sub->owner) { - c = skinny_new(l, AST_STATE_DOWN, NULL, SKINNY_OUTGOING); + c = skinny_new(l, NULL, AST_STATE_DOWN, NULL, SKINNY_OUTGOING); } else { c = sub->owner; } @@ -5447,7 +5839,7 @@ static int handle_stimulus_message(struct skinny_req *req, struct skinnysession if (sub && sub->owner) { ast_debug(1, "Current subchannel [%s] already has owner\n", sub->owner->name); } else { - c = skinny_new(l, AST_STATE_DOWN, NULL, SKINNY_OUTGOING); + c = skinny_new(l, NULL, AST_STATE_DOWN, NULL, SKINNY_OUTGOING); if (c) { setsubstate(c->tech_pvt, SUBSTATE_OFFHOOK); } else { @@ -5520,7 +5912,7 @@ static int handle_offhook_message(struct skinny_req *req, struct skinnysession * if (sub && sub->owner) { ast_debug(1, "Current sub [%s] already has owner\n", sub->owner->name); } else { - c = skinny_new(l, AST_STATE_DOWN, NULL, SKINNY_OUTGOING); + c = skinny_new(l, NULL, AST_STATE_DOWN, NULL, SKINNY_OUTGOING); if (c) { setsubstate(c->tech_pvt, SUBSTATE_OFFHOOK); } else { @@ -5854,7 +6246,7 @@ static int handle_enbloc_call_message(struct skinny_req *req, struct skinnysessi l = sub->line; } - c = skinny_new(l, AST_STATE_DOWN, NULL, SKINNY_OUTGOING); + c = skinny_new(l, NULL, AST_STATE_DOWN, NULL, SKINNY_OUTGOING); if(!c) { ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name); @@ -5917,7 +6309,7 @@ static int handle_soft_key_event_message(struct skinny_req *req, struct skinnyse } if (!sub || !sub->owner) { - c = skinny_new(l, AST_STATE_DOWN, NULL, SKINNY_OUTGOING); + c = skinny_new(l, NULL, AST_STATE_DOWN, NULL, SKINNY_OUTGOING); } else { c = sub->owner; } @@ -5934,9 +6326,9 @@ static int handle_soft_key_event_message(struct skinny_req *req, struct skinnyse ast_verb(1, "Received Softkey Event: New Call(%d/%d)\n", instance, callreference); /* New Call ALWAYS gets a new sub-channel */ - c = skinny_new(l, AST_STATE_DOWN, NULL, SKINNY_OUTGOING); + c = skinny_new(l, NULL, AST_STATE_DOWN, NULL, SKINNY_OUTGOING); sub = c->tech_pvt; - + if (!c) { ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name); } else { @@ -5946,7 +6338,16 @@ static int handle_soft_key_event_message(struct skinny_req *req, struct skinnyse case SOFTKEY_HOLD: if (skinnydebug) ast_verb(1, "Received Softkey Event: Hold(%d/%d)\n", instance, callreference); - setsubstate(sub, SUBSTATE_HOLD); + + if (sub) { + setsubstate(sub, SUBSTATE_HOLD); + } else { /* No sub, maybe an SLA call */ + struct skinny_subline *subline; + if ((subline = find_subline_by_callid(d, callreference))) { + setsubstate(subline->sub, SUBSTATE_HOLD); + } + } + break; case SOFTKEY_TRNSFER: if (skinnydebug) @@ -5979,7 +6380,7 @@ static int handle_soft_key_event_message(struct skinny_req *req, struct skinnyse ast_verb(1, "Received Softkey Event: Forward All(%d/%d)\n", instance, callreference); if (!sub || !sub->owner) { - c = skinny_new(l, AST_STATE_DOWN, NULL, SKINNY_OUTGOING); + c = skinny_new(l, NULL, AST_STATE_DOWN, NULL, SKINNY_OUTGOING); } else { c = sub->owner; } @@ -5997,7 +6398,7 @@ static int handle_soft_key_event_message(struct skinny_req *req, struct skinnyse ast_verb(1, "Received Softkey Event: Forward Busy (%d/%d)\n", instance, callreference); if (!sub || !sub->owner) { - c = skinny_new(l, AST_STATE_DOWN, NULL, SKINNY_OUTGOING); + c = skinny_new(l, NULL, AST_STATE_DOWN, NULL, SKINNY_OUTGOING); } else { c = sub->owner; } @@ -6016,7 +6417,7 @@ static int handle_soft_key_event_message(struct skinny_req *req, struct skinnyse #if 0 /* Not sure how to handle this yet */ if (!sub || !sub->owner) { - c = skinny_new(l, AST_STATE_DOWN, NULL, SKINNY_OUTGOING); + c = skinny_new(l, NULL, AST_STATE_DOWN, NULL, SKINNY_OUTGOING); } else { c = sub->owner; } @@ -6045,7 +6446,7 @@ static int handle_soft_key_event_message(struct skinny_req *req, struct skinnyse return 0; } - if (l->transfer && sub->xferor && sub->owner->_state >= AST_STATE_RING) { + if (l->transfer && sub && sub->xferor && sub->owner->_state >= AST_STATE_RING) { /* We're allowed to transfer, we have two active calls and we made at least one of the calls. Let's try and transfer */ handle_transfer_button(sub); @@ -6054,7 +6455,14 @@ static int handle_soft_key_event_message(struct skinny_req *req, struct skinnyse ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Skinny/%s", l->name); - dumpsub(sub, 1); + if (sub) { + dumpsub(sub, 1); + } else { /* No sub, maybe an SLA call */ + struct skinny_subline *subline; + if ((subline = find_subline_by_callid(d, callreference))) { + dumpsub(subline->sub, 1); + } + } d->hookstate = SKINNY_ONHOOK; @@ -6065,8 +6473,20 @@ static int handle_soft_key_event_message(struct skinny_req *req, struct skinnyse case SOFTKEY_RESUME: if (skinnydebug) ast_verb(1, "Received Softkey Event: Resume(%d/%d)\n", instance, callreference); - - activatesub(sub, SUBSTATE_CONNECTED); + + if (sub) { + activatesub(sub, SUBSTATE_CONNECTED); + } else { /* No sub, maybe an inactive SLA call */ + struct skinny_subline *subline; + subline = find_subline_by_callid(d, callreference); + c = skinny_new(l, subline, AST_STATE_DOWN, NULL, SKINNY_OUTGOING); + if (!c) { + ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name); + } else { + sub = c->tech_pvt; + dialandactivatesub(sub, subline->exten); + } + } break; case SOFTKEY_ANSWER: if (skinnydebug) @@ -6120,6 +6540,18 @@ static int handle_soft_key_event_message(struct skinny_req *req, struct skinnyse case SOFTKEY_JOIN: if (skinnydebug) ast_verb(1, "Received Softkey Event: Join(%d/%d)\n", instance, callreference); + /* this is SLA territory, should not get here unless there is a meetme at subline */ + { + struct skinny_subline *subline; + subline = find_subline_by_callid(d, callreference); + c = skinny_new(l, subline, AST_STATE_DOWN, NULL, SKINNY_OUTGOING); + if (!c) { + ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name); + } else { + sub = c->tech_pvt; + dialandactivatesub(sub, subline->exten); + } + } break; case SOFTKEY_MEETME: /* XXX How is this different from CONFRN? */ @@ -6578,6 +7010,7 @@ static int skinny_devicestate(void *data) static struct ast_channel *skinny_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause) { struct skinny_line *l; + struct skinny_subline *subline = NULL; struct ast_channel *tmpc = NULL; char tmp[256]; char *dest = data; @@ -6594,13 +7027,24 @@ static struct ast_channel *skinny_request(const char *type, struct ast_format_ca } l = find_line_by_name(tmp); if (!l) { - ast_log(LOG_NOTICE, "No available lines on: %s\n", dest); - return NULL; + subline = find_subline_by_name(tmp); + if (!subline) { + ast_log(LOG_NOTICE, "No available lines on: %s\n", dest); + return NULL; + } + l = subline->line; } ast_verb(3, "skinny_request(%s)\n", tmp); - tmpc = skinny_new(l, AST_STATE_DOWN, requestor ? requestor->linkedid : NULL, SKINNY_INCOMING); + tmpc = skinny_new(l, subline, AST_STATE_DOWN, requestor ? requestor->linkedid : NULL, SKINNY_INCOMING); if (!tmpc) { ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp); + } else if (subline) { + struct skinny_subchannel *sub = tmpc->tech_pvt; + subline->sub = sub; + subline->calldirection = SKINNY_INCOMING; + subline->substate = SUBSTATE_UNSET; + subline->callid = sub->callid; + sub->subline = subline; } return tmpc; } @@ -6950,36 +7394,92 @@ static struct ast_channel *skinny_request(const char *type, struct ast_format_ca } continue; } + } else if (!strcasecmp(v->name, "subline")) { + if (type & (TYPE_LINE)) { + struct skinny_subline *subline; + struct skinny_container *container; + char buf[256]; + char *stringp = buf, *exten, *stname, *context; + + if (!(subline = ast_calloc(1, sizeof(*subline)))) { + ast_log(LOG_WARNING, "Unable to allocate memory for subline %s. Ignoring subline.\n", v->value); + continue; + } + if (!(container = ast_calloc(1, sizeof(*container)))) { + ast_log(LOG_WARNING, "Unable to allocate memory for subline %s container. Ignoring subline.\n", v->value); + ast_free(subline); + continue; + } + + ast_copy_string(buf, v->value, sizeof(buf)); + exten = strsep(&stringp, "@"); + ast_copy_string(subline->exten, ast_strip(exten), sizeof(subline->exten)); + stname = strsep(&exten, "_"); + ast_copy_string(subline->stname, ast_strip(stname), sizeof(subline->stname)); + ast_copy_string(subline->lnname, ast_strip(exten), sizeof(subline->lnname)); + context = strsep(&stringp, ","); + ast_copy_string(subline->name, ast_strip(stringp), sizeof(subline->name)); + ast_copy_string(subline->context, ast_strip(context), sizeof(subline->context)); + + subline->line = CLINE; + subline->sub = NULL; + + container->type = SKINNY_SUBLINECONTAINER; + container->data = subline; + subline->container = container; + AST_LIST_INSERT_HEAD(&CLINE->sublines, subline, list); + continue; + } + } else if (!strcasecmp(v->name, "dialoutcontext")) { + if (type & (TYPE_LINE)) { + ast_copy_string(CLINE_OPTS->dialoutcontext, v->value, sizeof(CLINE_OPTS->dialoutcontext)); + continue; + } + } else if (!strcasecmp(v->name, "dialoutexten")) { + if (type & (TYPE_LINE)) { + ast_copy_string(CLINE_OPTS->dialoutexten, v->value, sizeof(CLINE_OPTS->dialoutexten)); + continue; + } } else if (!strcasecmp(v->name, "speeddial")) { if (type & (TYPE_DEVICE)) { struct skinny_speeddial *sd; + struct skinny_container *container; + char buf[256]; + char *stringp = buf, *exten, *context, *label; + if (!(sd = ast_calloc(1, sizeof(*sd)))) { ast_log(LOG_WARNING, "Unable to allocate memory for speeddial %s. Ignoring speeddial.\n", v->name); continue; - } else { - char buf[256]; - char *stringp = buf, *exten, *context, *label; - ast_copy_string(buf, v->value, sizeof(buf)); - exten = strsep(&stringp, ","); - if ((context = strchr(exten, '@'))) { - *context++ = '\0'; - } - label = stringp; - ast_mutex_init(&sd->lock); - ast_copy_string(sd->exten, exten, sizeof(sd->exten)); - if (!ast_strlen_zero(context)) { - sd->isHint = 1; - sd->instance = lineInstance++; - ast_copy_string(sd->context, context, sizeof(sd->context)); - } else { - sd->isHint = 0; - sd->instance = speeddialInstance++; - sd->context[0] = '\0'; - } - ast_copy_string(sd->label, S_OR(label, exten), sizeof(sd->label)); - sd->parent = CDEV; - AST_LIST_INSERT_HEAD(&CDEV->speeddials, sd, list); } + if (!(container = ast_calloc(1, sizeof(*container)))) { + ast_log(LOG_WARNING, "Unable to allocate memory for speeddial %s container. Ignoring speeddial.\n", v->name); + ast_free(sd); + continue; + } + + ast_copy_string(buf, v->value, sizeof(buf)); + exten = strsep(&stringp, ","); + if ((context = strchr(exten, '@'))) { + *context++ = '\0'; + } + label = stringp; + ast_mutex_init(&sd->lock); + ast_copy_string(sd->exten, exten, sizeof(sd->exten)); + if (!ast_strlen_zero(context)) { + sd->isHint = 1; + sd->instance = lineInstance++; + ast_copy_string(sd->context, context, sizeof(sd->context)); + } else { + sd->isHint = 0; + sd->instance = speeddialInstance++; + sd->context[0] = '\0'; + } + ast_copy_string(sd->label, S_OR(label, exten), sizeof(sd->label)); + sd->parent = CDEV; + container->type = SKINNY_SDCONTAINER; + container->data = sd; + sd->container = container; + AST_LIST_INSERT_HEAD(&CDEV->speeddials, sd, list); continue; } } else if (!strcasecmp(v->name, "addon")) { @@ -7008,6 +7508,7 @@ static struct ast_channel *skinny_request(const char *type, struct ast_format_ca { struct skinny_line *l, *temp; int update = 0; + struct skinny_container *container; ast_log(LOG_NOTICE, "Configuring skinny line %s.\n", lname); @@ -7026,7 +7527,17 @@ static struct ast_channel *skinny_request(const char *type, struct ast_format_ca AST_LIST_UNLOCK(&lines); return NULL; } + if (!(container = ast_calloc(1, sizeof(*container)))) { + ast_log(LOG_WARNING, "Unable to allocate memory for line %s container.\n", lname); + skinny_line_destroy(l); + AST_LIST_UNLOCK(&lines); + return NULL; + } + container->type = SKINNY_LINECONTAINER; + container->data = l; + l->container = container; + memcpy(l, default_line, sizeof(*default_line)); ast_mutex_init(&l->lock); ast_copy_string(l->name, lname, sizeof(l->name)); @@ -7284,6 +7795,7 @@ static void delete_devices(void) } /* Delete all speeddials for this device */ while ((sd = AST_LIST_REMOVE_HEAD(&d->speeddials, list))) { + free(sd->container); free(sd); } /* Delete all addons for this device */ -- cgit v1.2.3 From ca43a479c83ba54d27b0d822a63c0288822a5f57 Mon Sep 17 00:00:00 2001 From: lmadsen Date: Fri, 15 Jul 2011 21:01:41 +0000 Subject: Merged revisions 328448 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.10 ........ r328448 | lmadsen | 2011-07-15 16:57:15 -0400 (Fri, 15 Jul 2011) | 2 lines Update UPGRADE.txt and CHANGES files. Update documentation files stating that deprecated modules are no longer built by default. ........ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@328449 f38db490-d61c-443f-a65b-d21fe96a405b --- CHANGES | 5 +++++ UPGRADE-1.10.txt | 12 +++++++++++- UPGRADE.txt | 12 +++++++++++- 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 85a1ea11f..87a351fb6 100644 --- a/CHANGES +++ b/CHANGES @@ -204,6 +204,11 @@ Asterisk Database astdb.sqlite3 exists, astdb2sqlite3 will be compiled automatically. Asterisk will convert an existing astdb to the SQLite3 version automatically at runtime. +Asterisk Modules +---------------- + * Modules marked as deprecated are no longer marked as building by default. Enabling + these modules is still available via menuselect. + ------------------------------------------------------------------------------ --- Functionality changes from Asterisk 1.6.2 to Asterisk 1.8 ---------------- ------------------------------------------------------------------------------ diff --git a/UPGRADE-1.10.txt b/UPGRADE-1.10.txt index 87413cf3b..c1c1cd24c 100644 --- a/UPGRADE-1.10.txt +++ b/UPGRADE-1.10.txt @@ -60,12 +60,22 @@ Queue: - Mark QUEUE_MEMBER_PENALTY Deprecated it never worked for realtime members - QUEUE_MEMBER is now R/W supporting setting paused, ignorebusy and penalty. - Asterisk Database: +Asterisk Database: - The internal Asterisk database has been switched from Berkeley DB 1.86 to SQLite 3. An existing Berkeley astdb file can be converted with the astdb2sqlite3 utility in the UTILS section of menuselect. If an existing astdb is found and no astdb.sqlite3 exists, astdb2sqlite3 will be compiled automatically. Asterisk will convert an existing astdb to the SQLite3 version automatically at runtime. +Module Support Level + - All modules in the addons, apps, bridge, cdr, cel, channels, codecs, + formats, funcs, pbx, and res have been updated to include MODULEINFO data + that includes tags with a value of core, extended, or deprecated. + More information is available on the Asterisk wiki at + https://wiki.asterisk.org/wiki/display/AST/Asterisk+Module+Support+States + + Deprecated modules are now marked to not build by default and must be explicitly + enabled in menuselect. + =========================================================== =========================================================== diff --git a/UPGRADE.txt b/UPGRADE.txt index a5500f203..e98559f65 100644 --- a/UPGRADE.txt +++ b/UPGRADE.txt @@ -65,12 +65,22 @@ Queue: - Mark QUEUE_MEMBER_PENALTY Deprecated it never worked for realtime members - QUEUE_MEMBER is now R/W supporting setting paused, ignorebusy and penalty. - Asterisk Database: +Asterisk Database: - The internal Asterisk database has been switched from Berkeley DB 1.86 to SQLite 3. An existing Berkeley astdb file can be converted with the astdb2sqlite3 utility in the UTILS section of menuselect. If an existing astdb is found and no astdb.sqlite3 exists, astdb2sqlite3 will be compiled automatically. Asterisk will convert an existing astdb to the SQLite3 version automatically at runtime. +Module Support Level + - All modules in the addons, apps, bridge, cdr, cel, channels, codecs, + formats, funcs, pbx, and res have been updated to include MODULEINFO data + that includes tags with a value of core, extended, or deprecated. + More information is available on the Asterisk wiki at + https://wiki.asterisk.org/wiki/display/AST/Asterisk+Module+Support+States + + Deprecated modules are now marked to not build by default and must be explicitly + enabled in menuselect. + =========================================================== =========================================================== -- cgit v1.2.3 From d44b47240bebcefc202b43c36672e3c2dd563791 Mon Sep 17 00:00:00 2001 From: lmadsen Date: Fri, 15 Jul 2011 21:19:08 +0000 Subject: Merged revisions 328451 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.10 ........ r328451 | lmadsen | 2011-07-15 16:17:25 -0500 (Fri, 15 Jul 2011) | 1 line Build app_macro by default because things depend on it. ........ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@328459 f38db490-d61c-443f-a65b-d21fe96a405b --- apps/app_macro.c | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/app_macro.c b/apps/app_macro.c index 3bbfe20d6..651fac50d 100644 --- a/apps/app_macro.c +++ b/apps/app_macro.c @@ -26,7 +26,6 @@ */ /*** MODULEINFO - no deprecated app_stack (GoSub) */ -- cgit v1.2.3 From 7f5a82e677ddd9c75d49dfb62add997316e57ba3 Mon Sep 17 00:00:00 2001 From: may Date: Fri, 15 Jul 2011 21:41:46 +0000 Subject: Merged revisions 328428-328429 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.10 ................ r328428 | may | 2011-07-15 23:31:09 +0400 (Fri, 15 Jul 2011) | 13 lines Merged revisions 328427 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.8 ........ r328427 | may | 2011-07-15 23:22:24 +0400 (Fri, 15 Jul 2011) | 7 lines small gk processing fixes: - decrease for 1 second registration ttl for very low expirations (some providers expire few earlier than TTL) - delete rrq and registration expire timers on URQ received as we make new registration. ........ ................ r328429 | may | 2011-07-15 23:35:50 +0400 (Fri, 15 Jul 2011) | 2 lines delete unproperly changed svn props ................ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@328502 f38db490-d61c-443f-a65b-d21fe96a405b --- addons/ooh323c/src/ooGkClient.c | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/addons/ooh323c/src/ooGkClient.c b/addons/ooh323c/src/ooGkClient.c index 04359998a..33d7df019 100644 --- a/addons/ooh323c/src/ooGkClient.c +++ b/addons/ooh323c/src/ooGkClient.c @@ -1211,8 +1211,11 @@ int ooGkClientHandleRegistrationConfirm if(pGkClient->regTimeout > DEFAULT_TTL_OFFSET) regTTL = pGkClient->regTimeout - DEFAULT_TTL_OFFSET; - else - regTTL = pGkClient->regTimeout; + else { + regTTL = pGkClient->regTimeout - 1; /* -1 due to some ops expire us few earlier */ + if (regTTL <= 0) + regTTL = 1; + } cbData = (ooGkClientTimerCb*) memAlloc (&pGkClient->ctxt, sizeof(ooGkClientTimerCb)); @@ -1260,7 +1263,6 @@ int ooGkClientHandleRegistrationConfirm memFreePtr(&pGkClient->ctxt, pTimer->cbData); ooTimerDelete(&pGkClient->ctxt, &pGkClient->timerList, pTimer); OOTRACEDBGA1("Deleted RRQ Timer.\n"); - break; } } pGkClient->state = GkClientRegistered; @@ -1505,8 +1507,10 @@ int ooGkClientSendURQ(ooGkClient *pGkClient, ooAliases *aliases) int ooGkClientHandleUnregistrationRequest (ooGkClient *pGkClient, H225UnregistrationRequest * punregistrationRequest) { - int iRet=0; - + int iRet=0, x; + OOTimer *pTimer = NULL; + DListNode *pNode = NULL; + /* Lets first send unregistration confirm message back to gatekeeper*/ ooGkClientSendUnregistrationConfirm(pGkClient, punregistrationRequest->requestSeqNum); @@ -1528,6 +1532,24 @@ int ooGkClientHandleUnregistrationRequest pGkClient->rrqRetries = 0; pGkClient->state = GkClientDiscovered; + + /* delete the corresponding RRQ & REG timers */ + pNode = NULL; + for(x=0; xtimerList.count; x++) { + pNode = dListFindByIndex(&pGkClient->timerList, x); + pTimer = (OOTimer*)pNode->data; + if(((ooGkClientTimerCb*)pTimer->cbData)->timerType & OO_RRQ_TIMER) { + memFreePtr(&pGkClient->ctxt, pTimer->cbData); + ooTimerDelete(&pGkClient->ctxt, &pGkClient->timerList, pTimer); + OOTRACEDBGA1("Deleted RRQ Timer.\n"); + } + if(((ooGkClientTimerCb*)pTimer->cbData)->timerType & OO_REG_TIMER) { + memFreePtr(&pGkClient->ctxt, pTimer->cbData); + ooTimerDelete(&pGkClient->ctxt, &pGkClient->timerList, pTimer); + OOTRACEDBGA1("Deleted REG Timer.\n"); + } + } + iRet = ooGkClientSendRRQ(pGkClient, 0); if(iRet != OO_OK) { -- cgit v1.2.3 From 8fcfd897230e9fe512d2bd770aa092dc77f6e532 Mon Sep 17 00:00:00 2001 From: tilghman Date: Mon, 18 Jul 2011 07:12:22 +0000 Subject: Merged revisions 328541 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.10 ................ r328541 | tilghman | 2011-07-18 02:11:26 -0500 (Mon, 18 Jul 2011) | 9 lines Merged revisions 328540 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.8 ........ r328540 | tilghman | 2011-07-18 02:10:15 -0500 (Mon, 18 Jul 2011) | 2 lines Typo ........ ................ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@328542 f38db490-d61c-443f-a65b-d21fe96a405b --- funcs/func_odbc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/funcs/func_odbc.c b/funcs/func_odbc.c index 6cef946df..e940021a3 100644 --- a/funcs/func_odbc.c +++ b/funcs/func_odbc.c @@ -1131,7 +1131,7 @@ static char *cli_odbc_read(struct ast_cli_entry *e, int cmd, struct ast_cli_args } if (ast_strlen_zero(query->sql_read)) { - ast_cli(a->fd, "The function %s has no writesql parameter.\n", a->argv[2]); + ast_cli(a->fd, "The function %s has no readsql parameter.\n", a->argv[2]); AST_RWLIST_UNLOCK(&queries); return CLI_SUCCESS; } -- cgit v1.2.3 From 79206e605228129478a5707e801229c3d47ffd76 Mon Sep 17 00:00:00 2001 From: markm Date: Mon, 18 Jul 2011 12:54:29 +0000 Subject: Merged revisions 328609 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.10 ................ r328609 | markm | 2011-07-18 08:37:53 -0400 (Mon, 18 Jul 2011) | 15 lines Merged revisions 328593 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.8 ........ r328593 | markm | 2011-07-18 08:06:50 -0400 (Mon, 18 Jul 2011) | 8 lines Fixed invalid read and null pointer deref on asterisk shutdown. In some cases when starting asterisk with -c and hitting control-c to shutdown, there will be an invalid read and null pointer deref causing a crash. (closes issue ASTERISK-17927) Reported by: Mark Murawski Tested by: Mark Murawski, Kinsey Moore, Tilghman Lesher ........ ................ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@328610 f38db490-d61c-443f-a65b-d21fe96a405b --- main/asterisk.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/main/asterisk.c b/main/asterisk.c index 3572a526d..e23bf9bcb 100644 --- a/main/asterisk.c +++ b/main/asterisk.c @@ -291,6 +291,7 @@ static int sig_alert_pipe[2] = { -1, -1 }; static struct { unsigned int need_reload:1; unsigned int need_quit:1; + unsigned int need_quit_handler:1; } sig_flags; #if !defined(LOW_MEMORY) @@ -1657,21 +1658,24 @@ static void quit_handler(int num, int niceness, int safeshutdown, int restart) ast_module_shutdown(); } if (ast_opt_console || (ast_opt_remote && !ast_opt_exec)) { - pthread_t thisthread = pthread_self(); if (getenv("HOME")) { snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME")); } if (!ast_strlen_zero(filename)) { ast_el_write_history(filename); } - if (consolethread == AST_PTHREADT_NULL || consolethread == thisthread || mon_sig_flags == thisthread) { - /* Only end if we are the consolethread or signal handler, otherwise there's a race with that thread. */ + if (consolethread == AST_PTHREADT_NULL || consolethread == pthread_self()) { + /* Only end if we are the consolethread, otherwise there's a race with that thread. */ if (el != NULL) { el_end(el); } if (el_hist != NULL) { history_end(el_hist); } + } else if (mon_sig_flags == pthread_self()) { + if (consolethread != AST_PTHREADT_NULL) { + pthread_kill(consolethread, SIGURG); + } } } if (option_verbose) @@ -2150,7 +2154,7 @@ static int ast_el_read_char(EditLine *editline, char *cp) } res = ast_poll(fds, max, -1); if (res < 0) { - if (sig_flags.need_quit) + if (sig_flags.need_quit || sig_flags.need_quit_handler) break; if (errno == EINTR) continue; @@ -2707,7 +2711,7 @@ static void ast_remotecontrol(char *data) sprintf(tmp, "%s%s", prefix, data); if (write(ast_consock, tmp, strlen(tmp) + 1) < 0) { ast_log(LOG_ERROR, "write() failed: %s\n", strerror(errno)); - if (sig_flags.need_quit == 1) { + if (sig_flags.need_quit || sig_flags.need_quit_handler) { return; } } @@ -2745,7 +2749,7 @@ static void ast_remotecontrol(char *data) char buffer[512] = "", *curline = buffer, *nextline; int not_written = 1; - if (sig_flags.need_quit == 1) { + if (sig_flags.need_quit || sig_flags.need_quit_handler) { break; } @@ -2793,7 +2797,7 @@ static void ast_remotecontrol(char *data) for (;;) { ebuf = (char *)el_gets(el, &num); - if (sig_flags.need_quit == 1) { + if (sig_flags.need_quit || sig_flags.need_quit_handler) { break; } @@ -3115,7 +3119,12 @@ static void *monitor_sig_flags(void *unused) } if (sig_flags.need_quit) { sig_flags.need_quit = 0; - quit_handler(0, 0, 1, 0); + if (consolethread != AST_PTHREADT_NULL) { + sig_flags.need_quit_handler = 1; + pthread_kill(consolethread, SIGURG); + } else { + quit_handler(0, 0, 1, 0); + } } if (read(sig_alert_pipe[0], &a, sizeof(a)) != sizeof(a)) { } @@ -3900,7 +3909,13 @@ int main(int argc, char *argv[]) snprintf(title, sizeof(title), "Asterisk Console on '%s' (pid %ld)", hostname, (long)ast_mainpid); set_title(title); + el_set(el, EL_GETCFN, ast_el_read_char); + for (;;) { + if (sig_flags.need_quit || sig_flags.need_quit_handler) { + quit_handler(0, 0, 0, 0); + break; + } buf = (char *) el_gets(el, &num); if (!buf && write(1, "", 1) < 0) -- cgit v1.2.3 From 36b69d0c2caf73f401c93024b19d0e8c3e465f8e Mon Sep 17 00:00:00 2001 From: markm Date: Mon, 18 Jul 2011 12:58:02 +0000 Subject: Merged revisions 328611 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.10 ................ r328611 | markm | 2011-07-18 08:56:49 -0400 (Mon, 18 Jul 2011) | 15 lines Merged revisions 328608 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.8 ........ r328608 | markm | 2011-07-18 08:35:57 -0400 (Mon, 18 Jul 2011) | 9 lines If the sip private structure is null, sip_setoption() will defref the null pointer and crash. Ideally, sip_setoption shouldn't be called if there is a lack of a sip private structure. But this will fix a crash. (closes issue ASTERISK-17909) Reported by: Mark Murawski Tested by: Mark Murawski ........ ................ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@328612 f38db490-d61c-443f-a65b-d21fe96a405b --- channels/chan_sip.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 603d86953..74d328694 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -4266,6 +4266,11 @@ static int sip_setoption(struct ast_channel *chan, int option, void *data, int d int res = -1; struct sip_pvt *p = chan->tech_pvt; + if (!p) { + ast_log(LOG_ERROR, "Attempt to Ref a null pointer. sip private structure is gone!\n"); + return -1; + } + sip_pvt_lock(p); switch (option) { -- cgit v1.2.3 From 8084274becd2d795a3dd759a7cb94fb2ae525dbb Mon Sep 17 00:00:00 2001 From: markm Date: Mon, 18 Jul 2011 20:51:47 +0000 Subject: Merged revisions 328664 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.10 ................ r328664 | markm | 2011-07-18 16:50:13 -0400 (Mon, 18 Jul 2011) | 15 lines Merged revisions 328663 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.8 ........ r328663 | markm | 2011-07-18 16:47:04 -0400 (Mon, 18 Jul 2011) | 9 lines app_dial may double free a channel datastore When starting a call with originate, and having the callee channel run Bridge() on pickup, we will double free the dialed_interface_info datastore, causing a crash. Make sure to check if the datastore still exists before trying to free it. (closes issue ASTERISK-17917) Reported by: Mark Murawski Tested by: Mark Murawski ........ ................ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@328665 f38db490-d61c-443f-a65b-d21fe96a405b --- apps/app_dial.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/app_dial.c b/apps/app_dial.c index f144d48ea..65f5666f2 100644 --- a/apps/app_dial.c +++ b/apps/app_dial.c @@ -2409,7 +2409,8 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast * datastore again, causing a crash */ ast_channel_lock(chan); - if (!ast_channel_datastore_remove(chan, datastore)) { + datastore = ast_channel_datastore_find(chan, &dialed_interface_info, NULL); /* make sure we weren't cleaned up already */ + if (datastore && !ast_channel_datastore_remove(chan, datastore)) { ast_datastore_free(datastore); } ast_channel_unlock(chan); -- cgit v1.2.3 From ce69aa8bf49ec77f2c0ba83825c3d79f6591359d Mon Sep 17 00:00:00 2001 From: twilson Date: Tue, 19 Jul 2011 02:00:56 +0000 Subject: Merged revisions 328717 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.10 ................ r328717 | twilson | 2011-07-18 20:55:32 -0500 (Mon, 18 Jul 2011) | 14 lines Merged revisions 328716 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.8 ........ r328716 | twilson | 2011-07-18 20:35:53 -0500 (Mon, 18 Jul 2011) | 7 lines Make AST_LIST_REMOVE safer AST_LIST_REMOVE shouldn't modify the element passed in if it isn't found. This commit also adds linked list unit tests. Review: https://reviewboard.asterisk.org/r/1321/ ........ ................ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@328718 f38db490-d61c-443f-a65b-d21fe96a405b --- include/asterisk/linkedlists.h | 9 +- tests/test_linkedlists.c | 215 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 222 insertions(+), 2 deletions(-) create mode 100644 tests/test_linkedlists.c diff --git a/include/asterisk/linkedlists.h b/include/asterisk/linkedlists.h index 8e86470f5..4c9e27b28 100644 --- a/include/asterisk/linkedlists.h +++ b/include/asterisk/linkedlists.h @@ -838,7 +838,10 @@ struct { \ */ #define AST_LIST_REMOVE(head, elm, field) ({ \ __typeof(elm) __res = NULL; \ - if ((head)->first == (elm)) { \ + __typeof(elm) __tmp = elm; \ + if (!__tmp) { \ + __res = NULL; \ + } else if ((head)->first == (elm)) { \ __res = (head)->first; \ (head)->first = (elm)->field.next; \ if ((head)->last == (elm)) \ @@ -854,7 +857,9 @@ struct { \ (head)->last = curelm; \ } \ } \ - (elm)->field.next = NULL; \ + if (__res) { \ + (__res)->field.next = NULL; \ + } \ (__res); \ }) diff --git a/tests/test_linkedlists.c b/tests/test_linkedlists.c new file mode 100644 index 000000000..55944570b --- /dev/null +++ b/tests/test_linkedlists.c @@ -0,0 +1,215 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2011, Terry Wilson + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! \file + * + * \brief Linked List Tests + * + * \author Terry Wilson + * + * \ingroup tests + */ + +/*** MODULEINFO + no + extended + ***/ + +#include "asterisk.h" + +ASTERISK_FILE_VERSION(__FILE__, "$Revision$") + +#include "asterisk/module.h" +#include "asterisk/test.h" +#include "asterisk/strings.h" +#include "asterisk/logger.h" +#include "asterisk/linkedlists.h" + +struct test_val { + const char *name; + AST_LIST_ENTRY(test_val) list; +}; + +static struct test_val a = { "A" }; +static struct test_val b = { "B" }; +static struct test_val c = { "C" }; +static struct test_val d = { "D" }; + +AST_LIST_HEAD_NOLOCK(test_list, test_val); + +static int list_expect(struct test_list *test_list, char *expect, struct ast_str **buf) +{ + struct test_val *i; + + ast_str_reset(*buf); + AST_LIST_TRAVERSE(test_list, i, list) { + ast_str_append(buf, 0, "%s", i->name); + } + + return strcmp(expect, ast_str_buffer(*buf)); +} + +#define MATCH_OR_FAIL(list, val, retbuf) \ + if (list_expect(list, val, &retbuf)) { \ + ast_test_status_update(test, "Expected: %s, Got: %s\n", val, ast_str_buffer(retbuf)); \ + ast_free(retbuf); \ + return AST_TEST_FAIL; \ + } + +#define ELEM_OR_FAIL(x,y) \ + if ((x) != (y)) { \ + ast_test_status_update(test, "Expected: %s, Got: %s\n", (x)->name, (y)->name); \ + return AST_TEST_FAIL; \ + } + +AST_TEST_DEFINE(ll_tests) +{ + struct ast_str *buf; + struct test_list test_list = { 0, }; + struct test_val *bogus; + + switch (cmd) { + case TEST_INIT: + info->name = "ll_tests"; + info->category = "/main/linkedlists"; + info->summary = "linked list unit test"; + info->description = + "Test the linked list API"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + if (!(buf = ast_str_create(16))) { + return AST_TEST_FAIL; + } + + if (!(bogus = alloca(sizeof(*bogus)))) { + return AST_TEST_FAIL; + } + + if (AST_LIST_REMOVE(&test_list, bogus, list)) { + ast_test_status_update(test, "AST_LIST_REMOVE should safely return NULL for missing element from empty list\n"); + return AST_TEST_FAIL; + } + + /* INSERT_HEAD and REMOVE_HEAD tests */ + AST_LIST_INSERT_HEAD(&test_list, &a, list); + MATCH_OR_FAIL(&test_list, "A", buf); + AST_LIST_INSERT_HEAD(&test_list, &b, list); + MATCH_OR_FAIL(&test_list, "BA", buf); + AST_LIST_INSERT_HEAD(&test_list, &c, list); + MATCH_OR_FAIL(&test_list, "CBA", buf); + AST_LIST_INSERT_HEAD(&test_list, &d, list); + MATCH_OR_FAIL(&test_list, "DCBA", buf); + AST_LIST_REMOVE_HEAD(&test_list, list); + MATCH_OR_FAIL(&test_list, "CBA", buf); + AST_LIST_REMOVE_HEAD(&test_list, list); + MATCH_OR_FAIL(&test_list, "BA", buf); + AST_LIST_REMOVE_HEAD(&test_list, list); + MATCH_OR_FAIL(&test_list, "A", buf); + AST_LIST_REMOVE_HEAD(&test_list, list); + MATCH_OR_FAIL(&test_list, "", buf); + + if (AST_LIST_REMOVE_HEAD(&test_list, list)) { + ast_test_status_update(test, "Somehow removed an item from the head of a list that didn't exist\n"); + return AST_TEST_FAIL; + } + + if (!AST_LIST_EMPTY(&test_list)) { + ast_test_status_update(test, "List should be empty\n"); + return AST_TEST_FAIL; + } + + AST_LIST_INSERT_TAIL(&test_list, &a, list); + MATCH_OR_FAIL(&test_list, "A", buf); + AST_LIST_INSERT_TAIL(&test_list, &b, list); + MATCH_OR_FAIL(&test_list, "AB", buf); + AST_LIST_INSERT_TAIL(&test_list, &c, list); + MATCH_OR_FAIL(&test_list, "ABC", buf); + AST_LIST_INSERT_TAIL(&test_list, &d, list); + MATCH_OR_FAIL(&test_list, "ABCD", buf); + + if (AST_LIST_REMOVE(&test_list, bogus, list)) { + ast_test_status_update(test, "AST_LIST_REMOVE should safely return NULL for missing element\n"); + return AST_TEST_FAIL; + } + + bogus = NULL; + + if (AST_LIST_REMOVE(&test_list, bogus, list)) { + ast_test_status_update(test, "AST_LIST_REMOVE should safely return NULL for element set to NULL\n"); + return AST_TEST_FAIL; + } + + AST_LIST_REMOVE(&test_list, &b, list); + MATCH_OR_FAIL(&test_list, "ACD", buf); + AST_LIST_REMOVE(&test_list, &d, list); + MATCH_OR_FAIL(&test_list, "AC", buf); + AST_LIST_REMOVE(&test_list, &a, list); + MATCH_OR_FAIL(&test_list, "C", buf); + AST_LIST_REMOVE(&test_list, &c, list); + MATCH_OR_FAIL(&test_list, "", buf); + + if (!AST_LIST_EMPTY(&test_list)) { + ast_test_status_update(test, "List should be empty\n"); + return AST_TEST_FAIL; + } + + if (AST_LIST_REMOVE(&test_list, bogus, list)) { + ast_test_status_update(test, "AST_LIST_REMOVE should safely return NULL asked to remove a NULL pointer from an empty list\n"); + return AST_TEST_FAIL; + } + + AST_LIST_INSERT_HEAD(&test_list, &a, list); + MATCH_OR_FAIL(&test_list, "A", buf); + AST_LIST_INSERT_TAIL(&test_list, &b, list); + MATCH_OR_FAIL(&test_list, "AB", buf); + AST_LIST_INSERT_AFTER(&test_list, &a, &c, list); + MATCH_OR_FAIL(&test_list, "ACB", buf); + AST_LIST_INSERT_AFTER(&test_list, &b, &d, list); + MATCH_OR_FAIL(&test_list, "ACBD", buf); + + ELEM_OR_FAIL(AST_LIST_FIRST(&test_list), &a); + ELEM_OR_FAIL(AST_LIST_LAST(&test_list), &d); + ELEM_OR_FAIL(AST_LIST_NEXT(&a, list), &c); + + AST_LIST_TRAVERSE_SAFE_BEGIN(&test_list, bogus, list) { + AST_LIST_REMOVE_CURRENT(list); + } + AST_LIST_TRAVERSE_SAFE_END; + + if (!AST_LIST_EMPTY(&test_list)) { + ast_test_status_update(test, "List should be empty after traversing and removal. It wasn't.\n"); + return AST_TEST_FAIL; + } + + return AST_TEST_PASS; +} + +static int unload_module(void) +{ + AST_TEST_UNREGISTER(ll_tests); + return 0; +} + +static int load_module(void) +{ + AST_TEST_REGISTER(ll_tests); + return AST_MODULE_LOAD_SUCCESS; +} + +AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Test Linked Lists"); -- cgit v1.2.3 From b7854890e0bf54421cc02e811299f85a6cd27143 Mon Sep 17 00:00:00 2001 From: kmoore Date: Tue, 19 Jul 2011 15:49:55 +0000 Subject: Merged revisions 328771 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.10 ................ r328771 | kmoore | 2011-07-19 10:46:54 -0500 (Tue, 19 Jul 2011) | 18 lines Merged revisions 328770 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.8 ........ r328770 | kmoore | 2011-07-19 10:43:32 -0500 (Tue, 19 Jul 2011) | 11 lines MeetMe requests a PIN twice in some circumstances If a call to MeetMe includes both the dynamic(D) and always request PIN(P) options, MeetMe will ask for the PIN two times: once for creating the conference and once for entering the conference. This behavior was introduced in rev 311616 when adding the CONFFLAG_ALWAYSPROMPT option to the logic branch controlling PIN entry for joining a conference. (closes AST-601) Review: https://reviewboard.asterisk.org/r/1305/ ........ ................ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@328772 f38db490-d61c-443f-a65b-d21fe96a405b --- apps/app_meetme.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/apps/app_meetme.c b/apps/app_meetme.c index 73aaefc0e..f0ab25903 100644 --- a/apps/app_meetme.c +++ b/apps/app_meetme.c @@ -4419,15 +4419,13 @@ static int conf_exec(struct ast_channel *chan, const char *data) res = -1; } } else { - if (((!ast_strlen_zero(cnf->pin) && - !ast_test_flag64(&confflags, CONFFLAG_ADMIN)) || - (!ast_strlen_zero(cnf->pinadmin) && - ast_test_flag64(&confflags, CONFFLAG_ADMIN)) || - (!ast_strlen_zero(cnf->pin) && - ast_strlen_zero(cnf->pinadmin) && - ast_test_flag64(&confflags, CONFFLAG_ADMIN))) && - ((!(cnf->users == 0 && cnf->isdynamic)) || - ast_test_flag64(&confflags, CONFFLAG_ALWAYSPROMPT))) { + /* Check to see if the conference requires a pin + * and we ALWAYS prompt or no pin was provided */ + if ((!ast_strlen_zero(cnf->pin) || + (!ast_strlen_zero(cnf->pinadmin) && + ast_test_flag64(&confflags, CONFFLAG_ADMIN))) && + (ast_test_flag64(&confflags, CONFFLAG_ALWAYSPROMPT) || + ast_strlen_zero(args.pin))) { char pin[MAX_PIN] = ""; int j; -- cgit v1.2.3 From 4b03897207848035c13ad20f8f69b3c264f0c448 Mon Sep 17 00:00:00 2001 From: kmoore Date: Tue, 19 Jul 2011 18:07:22 +0000 Subject: Merged revisions 328824 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.10 ................ r328824 | kmoore | 2011-07-19 13:05:21 -0500 (Tue, 19 Jul 2011) | 18 lines Merged revisions 328823 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.8 ........ r328823 | kmoore | 2011-07-19 12:57:18 -0500 (Tue, 19 Jul 2011) | 11 lines RTP bridge away with inband DTMF and feature detection When deciding whether Asterisk was allowed to bridge the call away from the core, chan_sip did not take into account the usage of features on dialed channels that require monitoring of DTMF on channels utilizing inband DTMF. This would cause Asterisk to allow the call to be locally or remotely bridged, preventing access to the data required to detect activations of such features. (closes 17237) Review: https://reviewboard.asterisk.org/r/1302/ ........ ................ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@328825 f38db490-d61c-443f-a65b-d21fe96a405b --- channels/chan_sip.c | 13 +++++++------ include/asterisk/rtp_engine.h | 2 ++ main/rtp_engine.c | 19 +++++++------------ res/res_rtp_asterisk.c | 18 ++++++++++++++++++ 4 files changed, 34 insertions(+), 18 deletions(-) diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 74d328694..0e5d27f79 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -4228,10 +4228,11 @@ static void enable_dsp_detect(struct sip_pvt *p) } if ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) || - (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) { - if (!p->rtp || ast_rtp_instance_dtmf_mode_set(p->rtp, AST_RTP_DTMF_MODE_INBAND)) { - features |= DSP_FEATURE_DIGIT_DETECT; - } + (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) { + if (p->rtp) { + ast_rtp_instance_dtmf_mode_set(p->rtp, AST_RTP_DTMF_MODE_INBAND); + } + features |= DSP_FEATURE_DIGIT_DETECT; } if (ast_test_flag(&p->flags[1], SIP_PAGE2_FAX_DETECT_CNG)) { @@ -6932,8 +6933,8 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit if ((ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) || (ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) { - if (!i->rtp || ast_rtp_instance_dtmf_mode_set(i->rtp, AST_RTP_DTMF_MODE_INBAND)) { - enable_dsp_detect(i); + if (i->rtp) { + ast_rtp_instance_dtmf_mode_set(i->rtp, AST_RTP_DTMF_MODE_INBAND); } } else if (ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) { if (i->rtp) { diff --git a/include/asterisk/rtp_engine.h b/include/asterisk/rtp_engine.h index e04303ca6..30270ec4a 100644 --- a/include/asterisk/rtp_engine.h +++ b/include/asterisk/rtp_engine.h @@ -349,6 +349,8 @@ struct ast_rtp_engine { void (*alt_remote_address_set)(struct ast_rtp_instance *instance, struct ast_sockaddr *sa); /*! Callback for changing DTMF mode */ int (*dtmf_mode_set)(struct ast_rtp_instance *instance, enum ast_rtp_dtmf_mode dtmf_mode); + /*! Callback for getting DTMF mode */ + enum ast_rtp_dtmf_mode (*dtmf_mode_get)(struct ast_rtp_instance *instance); /*! Callback for retrieving statistics */ int (*get_stat)(struct ast_rtp_instance *instance, struct ast_rtp_instance_stats *stats, enum ast_rtp_instance_stat stat); /*! Callback for setting QoS values */ diff --git a/main/rtp_engine.c b/main/rtp_engine.c index 4ad3c9024..c7d77f809 100644 --- a/main/rtp_engine.c +++ b/main/rtp_engine.c @@ -69,8 +69,6 @@ struct ast_rtp_instance { int holdtimeout; /*! RTP keepalive interval */ int keepalive; - /*! DTMF mode in use */ - enum ast_rtp_dtmf_mode dtmf_mode; /*! Glue currently in use */ struct ast_rtp_glue *glue; /*! Channel associated with the instance */ @@ -745,18 +743,12 @@ int ast_rtp_instance_dtmf_end_with_duration(struct ast_rtp_instance *instance, c int ast_rtp_instance_dtmf_mode_set(struct ast_rtp_instance *instance, enum ast_rtp_dtmf_mode dtmf_mode) { - if (!instance->engine->dtmf_mode_set || instance->engine->dtmf_mode_set(instance, dtmf_mode)) { - return -1; - } - - instance->dtmf_mode = dtmf_mode; - - return 0; + return (!instance->engine->dtmf_mode_set || instance->engine->dtmf_mode_set(instance, dtmf_mode)) ? -1 : 0; } enum ast_rtp_dtmf_mode ast_rtp_instance_dtmf_mode_get(struct ast_rtp_instance *instance) { - return instance->dtmf_mode; + return instance->engine->dtmf_mode_get ? instance->engine->dtmf_mode_get(instance) : 0; } void ast_rtp_instance_update_source(struct ast_rtp_instance *instance) @@ -1291,6 +1283,7 @@ enum ast_bridge_result ast_rtp_instance_bridge(struct ast_channel *c0, struct as enum ast_rtp_glue_result audio_glue0_res = AST_RTP_GLUE_RESULT_FORBID, video_glue0_res = AST_RTP_GLUE_RESULT_FORBID; enum ast_rtp_glue_result audio_glue1_res = AST_RTP_GLUE_RESULT_FORBID, video_glue1_res = AST_RTP_GLUE_RESULT_FORBID; enum ast_bridge_result res = AST_BRIDGE_FAILED; + enum ast_rtp_dtmf_mode dmode; struct ast_format_cap *cap0 = ast_format_cap_alloc_nolock(); struct ast_format_cap *cap1 = ast_format_cap_alloc_nolock(); int unlock_chans = 1; @@ -1352,11 +1345,13 @@ enum ast_bridge_result ast_rtp_instance_bridge(struct ast_channel *c0, struct as } /* If we need to get DTMF see if we can do it outside of the RTP stream itself */ - if ((flags & AST_BRIDGE_DTMF_CHANNEL_0) && instance0->properties[AST_RTP_PROPERTY_DTMF]) { + dmode = ast_rtp_instance_dtmf_mode_get(instance0); + if ((flags & AST_BRIDGE_DTMF_CHANNEL_0) && dmode) { res = AST_BRIDGE_FAILED_NOWARN; goto done; } - if ((flags & AST_BRIDGE_DTMF_CHANNEL_1) && instance1->properties[AST_RTP_PROPERTY_DTMF]) { + dmode = ast_rtp_instance_dtmf_mode_get(instance1); + if ((flags & AST_BRIDGE_DTMF_CHANNEL_1) && dmode) { res = AST_BRIDGE_FAILED_NOWARN; goto done; } diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c index a520cdb16..06af4832d 100644 --- a/res/res_rtp_asterisk.c +++ b/res/res_rtp_asterisk.c @@ -147,6 +147,7 @@ struct ast_rtp { unsigned int dtmf_duration; /*!< Total duration in samples since the digit start event */ unsigned int dtmf_timeout; /*!< When this timestamp is reached we consider END frame lost and forcibly abort digit */ unsigned int dtmfsamples; + enum ast_rtp_dtmf_mode dtmfmode;/*!< The current DTMF mode of the RTP stream */ /* DTMF Transmission Variables */ unsigned int lastdigitts; char sending_digit; /*!< boolean - are we sending digits */ @@ -260,6 +261,8 @@ static int ast_rtp_destroy(struct ast_rtp_instance *instance); static int ast_rtp_dtmf_begin(struct ast_rtp_instance *instance, char digit); static int ast_rtp_dtmf_end(struct ast_rtp_instance *instance, char digit); static int ast_rtp_dtmf_end_with_duration(struct ast_rtp_instance *instance, char digit, unsigned int duration); +static int ast_rtp_dtmf_mode_set(struct ast_rtp_instance *instance, enum ast_rtp_dtmf_mode dtmf_mode); +static enum ast_rtp_dtmf_mode ast_rtp_dtmf_mode_get(struct ast_rtp_instance *instance); static void ast_rtp_update_source(struct ast_rtp_instance *instance); static void ast_rtp_change_source(struct ast_rtp_instance *instance); static int ast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *frame); @@ -286,6 +289,8 @@ static struct ast_rtp_engine asterisk_rtp_engine = { .dtmf_begin = ast_rtp_dtmf_begin, .dtmf_end = ast_rtp_dtmf_end, .dtmf_end_with_duration = ast_rtp_dtmf_end_with_duration, + .dtmf_mode_set = ast_rtp_dtmf_mode_set, + .dtmf_mode_get = ast_rtp_dtmf_mode_get, .update_source = ast_rtp_update_source, .change_source = ast_rtp_change_source, .write = ast_rtp_write, @@ -534,6 +539,19 @@ static int ast_rtp_destroy(struct ast_rtp_instance *instance) return 0; } +static int ast_rtp_dtmf_mode_set(struct ast_rtp_instance *instance, enum ast_rtp_dtmf_mode dtmf_mode) +{ + struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); + rtp->dtmfmode = dtmf_mode; + return 0; +} + +static enum ast_rtp_dtmf_mode ast_rtp_dtmf_mode_get(struct ast_rtp_instance *instance) +{ + struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); + return rtp->dtmfmode; +} + static int ast_rtp_dtmf_begin(struct ast_rtp_instance *instance, char digit) { struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); -- cgit v1.2.3 -- cgit v1.2.3 -- cgit v1.2.3 From d271a946b1e43455c178fbf1c2dd6cbbecc7b023 Mon Sep 17 00:00:00 2001 From: kpfleming Date: Tue, 19 Jul 2011 21:32:54 +0000 Subject: Merged revisions 328879 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/2.0 ................ r328879 | kpfleming | 2011-07-19 16:31:16 -0500 (Tue, 19 Jul 2011) | 23 lines Merged revisions 328878 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.8 ........ r328878 | kpfleming | 2011-07-19 16:29:07 -0500 (Tue, 19 Jul 2011) | 17 lines Revert partial attempt at handling pathnames with spaces. Revision 299794 attempted to improve the build system to be able to handle pathnames (primarily DESTDIR) with spaces in them, since this is common on some platforms (including Mac OSX). Unfortunately, the changes were incomplete and did not actually provide the desired behavior, and as a side effect the functionality that ensured that stale headers in the Asterisk 'include' directory were removed got broken. In addition, the check for stale (and possibly incompatible) modules in the Asterisk 'modules' directory also got broken, and would never report any stale modules. Users upgrading to this version or later versions would then see unexpected module load errors. Since there are few users who actually want to install Asterisk into paths that contain spaces, and a proper fix for the build system would take many hours, the best solution for now is to just revert the partial solution. ........ ................ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@328881 f38db490-d61c-443f-a65b-d21fe96a405b --- Makefile | 52 +++++++++++++++++++++++++-------------------------- Makefile.moddir_rules | 2 +- sounds/Makefile | 23 ++++------------------- 3 files changed, 31 insertions(+), 46 deletions(-) diff --git a/Makefile b/Makefile index fda715702..87139c118 100644 --- a/Makefile +++ b/Makefile @@ -467,9 +467,9 @@ datafiles: _all doc/core-en_US.xml # improved a lot. I'll put it here for now. for x in static-http/*; do \ - $(INSTALL) -m 644 $$x "$(DESTDIR)$(ASTDATADIR)/static-http" ; \ + $(INSTALL) -m 644 $$x $(DESTDIR)$(ASTDATADIR)/static-http ; \ done - $(INSTALL) -m 644 doc/core-en_US.xml "$(DESTDIR)$(ASTDATADIR)/static-http"; + $(INSTALL) -m 644 doc/core-en_US.xml $(DESTDIR)$(ASTDATADIR)/static-http; if [ -d doc/tex/asterisk ] ; then \ $(INSTALL) -d "$(DESTDIR)$(ASTDATADIR)/static-http/docs" ; \ for n in doc/tex/asterisk/* ; do \ @@ -477,7 +477,7 @@ datafiles: _all doc/core-en_US.xml done \ fi for x in images/*.jpg; do \ - $(INSTALL) -m 644 $$x "$(DESTDIR)$(ASTDATADIR)/images" ; \ + $(INSTALL) -m 644 $$x $(DESTDIR)$(ASTDATADIR)/images ; \ done $(MAKE) -C sounds install @@ -576,21 +576,21 @@ bininstall: _all installdirs $(SUBDIRS_INSTALL) rm -f $(addprefix $(DESTDIR)$(ASTHEADERDIR)/,$(OLDHEADERS)) ;\ fi - $(INSTALL) -m 644 doc/core-*.xml "$(DESTDIR)$(ASTDATADIR)/documentation" - $(INSTALL) -m 644 doc/appdocsxml.dtd "$(DESTDIR)$(ASTDATADIR)/documentation" - $(INSTALL) -m 644 doc/asterisk.8 "$(DESTDIR)$(ASTMANDIR)/man8" - $(INSTALL) -m 644 contrib/scripts/astgenkey.8 "$(DESTDIR)$(ASTMANDIR)/man8" - $(INSTALL) -m 644 contrib/scripts/autosupport.8 "$(DESTDIR)$(ASTMANDIR)/man8" - $(INSTALL) -m 644 contrib/scripts/safe_asterisk.8 "$(DESTDIR)$(ASTMANDIR)/man8" + $(INSTALL) -m 644 doc/core-*.xml $(DESTDIR)$(ASTDATADIR)/documentation + $(INSTALL) -m 644 doc/appdocsxml.dtd $(DESTDIR)$(ASTDATADIR)/documentation + $(INSTALL) -m 644 doc/asterisk.8 $(DESTDIR)$(ASTMANDIR)/man8 + $(INSTALL) -m 644 contrib/scripts/astgenkey.8 $(DESTDIR)$(ASTMANDIR)/man8 + $(INSTALL) -m 644 contrib/scripts/autosupport.8 $(DESTDIR)$(ASTMANDIR)/man8 + $(INSTALL) -m 644 contrib/scripts/safe_asterisk.8 $(DESTDIR)$(ASTMANDIR)/man8 if [ -f contrib/firmware/iax/iaxy.bin ] ; then \ - $(INSTALL) -m 644 contrib/firmware/iax/iaxy.bin "$(DESTDIR)$(ASTDATADIR)/firmware/iax/iaxy.bin"; \ + $(INSTALL) -m 644 contrib/firmware/iax/iaxy.bin $(DESTDIR)$(ASTDATADIR)/firmware/iax/iaxy.bin; \ fi $(SUBDIRS_INSTALL): +@DESTDIR="$(DESTDIR)" ASTSBINDIR="$(ASTSBINDIR)" $(SUBMAKE) -C $(@:-install=) install NEWMODS:=$(foreach d,$(MOD_SUBDIRS),$(notdir $(wildcard $(d)/*.so))) -OLDMODS=$(filter-out $(NEWMODS),$(notdir $(wildcard "$(DESTDIR)$(MODULES_DIR)/*.so"))) +OLDMODS=$(filter-out $(NEWMODS),$(notdir $(wildcard $(DESTDIR)$(MODULES_DIR)/*.so))) oldmodcheck: @if [ -n "$(OLDMODS)" ]; then \ @@ -698,33 +698,33 @@ samples: adsi rm -f $(DESTDIR)$(ASTCONFPATH).tmp ; \ fi ; \ $(INSTALL) -d $(DESTDIR)$(ASTSPOOLDIR)/voicemail/default/1234/INBOX - build_tools/make_sample_voicemail "$(DESTDIR)$(ASTDATADIR)" "$(DESTDIR)$(ASTSPOOLDIR)" + build_tools/make_sample_voicemail $(DESTDIR)/$(ASTDATADIR) $(DESTDIR)/$(ASTSPOOLDIR) @for x in phoneprov/*; do \ dst="$(DESTDIR)$(ASTDATADIR)/$$x" ; \ - if [ -f "$${dst}" ]; then \ + if [ -f $${dst} ]; then \ if [ "$(OVERWRITE)" = "y" ]; then \ - if cmp -s "$${dst}" $$x ; then \ + if cmp -s $${dst} $$x ; then \ echo "Config file $$x is unchanged"; \ continue; \ fi ; \ - mv -f "$${dst}" "$${dst}.old" ; \ + mv -f $${dst} $${dst}.old ; \ else \ echo "Skipping config file $$x"; \ continue; \ fi ;\ fi ; \ echo "Installing file $$x"; \ - $(INSTALL) -m 644 $$x "$${dst}" ;\ + $(INSTALL) -m 644 $$x $${dst} ;\ done webvmail: @[ -d $(DESTDIR)$(HTTP_DOCSDIR)/ ] || ( printf "http docs directory not found.\nUpdate assignment of variable HTTP_DOCSDIR in Makefile!\n" && exit 1 ) @[ -d $(DESTDIR)$(HTTP_CGIDIR) ] || ( printf "cgi-bin directory not found.\nUpdate assignment of variable HTTP_CGIDIR in Makefile!\n" && exit 1 ) - $(INSTALL) -m 4755 contrib/scripts/vmail.cgi "$(DESTDIR)$(HTTP_CGIDIR)/vmail.cgi" + $(INSTALL) -m 4755 contrib/scripts/vmail.cgi $(DESTDIR)$(HTTP_CGIDIR)/vmail.cgi $(INSTALL) -d $(DESTDIR)$(HTTP_DOCSDIR)/_asterisk for x in images/*.gif; do \ - $(INSTALL) -m 644 $$x "$(DESTDIR)$(HTTP_DOCSDIR)/_asterisk/"; \ + $(INSTALL) -m 644 $$x $(DESTDIR)$(HTTP_DOCSDIR)/_asterisk/; \ done @echo " +--------- Asterisk Web Voicemail ----------+" @echo " + +" @@ -844,12 +844,12 @@ $(SUBDIRS_UNINSTALL): +@$(SUBMAKE) -C $(@:-uninstall=) uninstall _uninstall: $(SUBDIRS_UNINSTALL) - rm -f "$(DESTDIR)$(MODULES_DIR)/"* + rm -f $(DESTDIR)$(MODULES_DIR)/* rm -f $(DESTDIR)$(ASTSBINDIR)/*asterisk* rm -f $(DESTDIR)$(ASTSBINDIR)/astgenkey rm -f $(DESTDIR)$(ASTSBINDIR)/autosupport rm -rf $(DESTDIR)$(ASTHEADERDIR) - rm -rf "$(DESTDIR)$(ASTDATADIR)/firmware" + rm -rf $(DESTDIR)$(ASTDATADIR)/firmware rm -f $(DESTDIR)$(ASTMANDIR)/man8/asterisk.8 rm -f $(DESTDIR)$(ASTMANDIR)/man8/astgenkey.8 rm -f $(DESTDIR)$(ASTMANDIR)/man8/autosupport.8 @@ -871,12 +871,12 @@ uninstall: _uninstall @echo " +-------------------------------------------+" uninstall-all: _uninstall - rm -rf "$(DESTDIR)$(ASTLIBDIR)" - rm -rf "$(DESTDIR)$(ASTVARLIBDIR)" - rm -rf "$(DESTDIR)$(ASTDATADIR)" - rm -rf "$(DESTDIR)$(ASTSPOOLDIR)" - rm -rf "$(DESTDIR)$(ASTETCDIR)" - rm -rf "$(DESTDIR)$(ASTLOGDIR)" + rm -rf $(DESTDIR)$(ASTLIBDIR) + rm -rf $(DESTDIR)$(ASTVARLIBDIR) + rm -rf $(DESTDIR)$(ASTDATADIR) + rm -rf $(DESTDIR)$(ASTSPOOLDIR) + rm -rf $(DESTDIR)$(ASTETCDIR) + rm -rf $(DESTDIR)$(ASTLOGDIR) menuconfig: menuselect diff --git a/Makefile.moddir_rules b/Makefile.moddir_rules index b0bc148ac..b883548af 100644 --- a/Makefile.moddir_rules +++ b/Makefile.moddir_rules @@ -122,7 +122,7 @@ clean:: install:: all @echo "Installing modules from `basename $(CURDIR)`..." - @for x in $(LOADABLE_MODS:%=%.so); do $(INSTALL) -m 755 $$x "$(DESTDIR)$(MODULES_DIR)" ; done + @for x in $(LOADABLE_MODS:%=%.so); do $(INSTALL) -m 755 $$x $(DESTDIR)$(MODULES_DIR) ; done uninstall:: diff --git a/sounds/Makefile b/sounds/Makefile index 178c30c7b..9826d9fb8 100644 --- a/sounds/Makefile +++ b/sounds/Makefile @@ -15,19 +15,10 @@ -include $(ASTTOPDIR)/menuselect.makeopts $(ASTTOPDIR)/makeopts -# Make doesn't tolerate spaces in pathnames well. I hate to hardcode the OS X -# path, but Make doesn't allow spaces as arguments, either. -ifneq ($(findstring Application Support,$(ASTDATADIR)),) -TMPDATADIR=/tmp/astdatadir -PREFIXCMD=ln -sf "$(ASTDATADIR)/" /tmp/astdatadir -else -TMPDATADIR=$(ASTDATADIR) -endif - CMD_PREFIX?=@ -SOUNDS_DIR:=$(DESTDIR)$(TMPDATADIR)/sounds +SOUNDS_DIR:=$(DESTDIR)$(ASTDATADIR)/sounds SOUNDS_CACHE_DIR?= -MOH_DIR:=$(DESTDIR)$(TMPDATADIR)/moh +MOH_DIR:=$(DESTDIR)$(ASTDATADIR)/moh CORE_SOUNDS_VERSION:=1.4.21 EXTRA_SOUNDS_VERSION:=1.4.11 MOH_VERSION:=2.03 @@ -142,13 +133,7 @@ endef endif -all: prefixcmd $(SOUNDS_CACHE_DIR) $(CORE_SOUNDS) $(EXTRA_SOUNDS) $(MOH) - -prefixcmd: - if [ -d /tmp/astdatadir ] ; then \ - rm -rf /tmp/astdatadir ; \ - fi - @$(PREFIXCMD) +all: $(SOUNDS_CACHE_DIR) $(CORE_SOUNDS) $(EXTRA_SOUNDS) $(MOH) have_download: @if test "$(DOWNLOAD)" = ":" ; then \ @@ -196,7 +181,7 @@ dist-clean: $(SOUNDS_DIR)/en $(MOH_DIR) $(SOUNDS_DIR)/en_AU $(SOUNDS_DIR)/es $(SOUNDS_DIR)/fr $(SOUNDS_DIR)/ru $(SOUNDS_CACHE_DIR): mkdir -p $@ -install: prefixcmd $(SOUNDS_CACHE_DIR) $(SOUNDS_DIR)/en $(SOUNDS_DIR)/en_AU $(SOUNDS_DIR)/es $(SOUNDS_DIR)/fr $(SOUNDS_DIR)/ru $(MOH_DIR) $(CORE_SOUND_TAGS) $(EXTRA_SOUND_TAGS) $(MOH_TAGS) +install: $(SOUNDS_CACHE_DIR) $(SOUNDS_DIR)/en $(SOUNDS_DIR)/en_AU $(SOUNDS_DIR)/es $(SOUNDS_DIR)/fr $(MOH_DIR) $(CORE_SOUND_TAGS) $(EXTRA_SOUND_TAGS) $(MOH_TAGS) uninstall: rm -rf $(SOUNDS_DIR) -- cgit v1.2.3 From 9b58d1a3daa400ce4b0003e812449695acd8c56f Mon Sep 17 00:00:00 2001 From: kmoore Date: Wed, 20 Jul 2011 19:03:17 +0000 Subject: Merged revisions 328936 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/2.0 ................ r328936 | kmoore | 2011-07-20 14:01:37 -0500 (Wed, 20 Jul 2011) | 15 lines Merged revisions 328935 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.8 ........ r328935 | kmoore | 2011-07-20 14:00:23 -0500 (Wed, 20 Jul 2011) | 8 lines Inband DTMF regression The functionality of inband DTMF in chan_sip relied upon ast_rtp_instance_dtmf_mode_get/set not working properly to avoid calling ast_rtp_instance_dtmf_begin/end on RTP streams with inband DTMF. According to documentation, ast_rtp_instance_dtmf_begin/end is meant only for RFC2833 DTMF, never inband. This fixes the regression introduced in revision 328823. ........ ................ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@328937 f38db490-d61c-443f-a65b-d21fe96a405b --- channels/chan_sip.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 0e5d27f79..a0b9cb037 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -6536,11 +6536,7 @@ static int sip_senddigit_begin(struct ast_channel *ast, char digit) sip_pvt_lock(p); switch (ast_test_flag(&p->flags[0], SIP_DTMF)) { case SIP_DTMF_INBAND: - if (p->rtp && ast_rtp_instance_dtmf_mode_get(p->rtp) == AST_RTP_DTMF_MODE_INBAND) { - ast_rtp_instance_dtmf_begin(p->rtp, digit); - } else { - res = -1; /* Tell Asterisk to generate inband indications */ - } + res = -1; /* Tell Asterisk to generate inband indications */ break; case SIP_DTMF_RFC2833: if (p->rtp) @@ -6572,11 +6568,7 @@ static int sip_senddigit_end(struct ast_channel *ast, char digit, unsigned int d ast_rtp_instance_dtmf_end_with_duration(p->rtp, digit, duration); break; case SIP_DTMF_INBAND: - if (p->rtp && ast_rtp_instance_dtmf_mode_get(p->rtp) == AST_RTP_DTMF_MODE_INBAND) { - ast_rtp_instance_dtmf_end(p->rtp, digit); - } else { - res = -1; /* Tell Asterisk to stop inband indications */ - } + res = -1; /* Tell Asterisk to stop inband indications */ break; } sip_pvt_unlock(p); -- cgit v1.2.3 From b8c96cbf21f203e87181e243516de53130165ca5 Mon Sep 17 00:00:00 2001 From: twilson Date: Wed, 20 Jul 2011 20:19:16 +0000 Subject: Merged revisions 328992 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/2.0 ................ r328992 | twilson | 2011-07-20 15:18:25 -0500 (Wed, 20 Jul 2011) | 12 lines Merged revisions 328987 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.8 ........ r328987 | twilson | 2011-07-20 15:16:58 -0500 (Wed, 20 Jul 2011) | 5 lines We can't guarantee an eth0 is present FreeBSD test fails on this case presumably because there is no eth0 on the test machine. Better to just remove this test for now. ........ ................ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@328996 f38db490-d61c-443f-a65b-d21fe96a405b --- tests/test_netsock2.c | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_netsock2.c b/tests/test_netsock2.c index f759ed2ce..8d7e1ebd8 100644 --- a/tests/test_netsock2.c +++ b/tests/test_netsock2.c @@ -69,7 +69,6 @@ AST_TEST_DEFINE(parsing) { "[2001::1]", 1 }, { "[2001:0000:4136:e378:8000:63bf:3fff:fdd2]:5060", 1 }, { "2001:0000:4136:e378:8000:63bf:3fff:fdd2:5060", 0 }, /* port, but no brackets */ - { "[fe80::200:5aee:feaa:20a2%eth0]", 1 }, /* link-local with scope id */ { "[fe80::200::abcd", 0 }, /* multiple zero expansions */ }; -- cgit v1.2.3 From 6c19532b0455b3beebacc9147b23bd22ba6b2f28 Mon Sep 17 00:00:00 2001 From: pabelanger Date: Wed, 20 Jul 2011 21:31:29 +0000 Subject: Merged revisions 329055 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/2.0 ................ r329055 | pabelanger | 2011-07-20 17:27:50 -0400 (Wed, 20 Jul 2011) | 9 lines Merged revisions 329027 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.8 ........ r329027 | pabelanger | 2011-07-20 17:20:36 -0400 (Wed, 20 Jul 2011) | 2 lines Asterisk now requires libpri 1.4.11+ for PRI support. ........ ................ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@329056 f38db490-d61c-443f-a65b-d21fe96a405b --- UPGRADE-1.8.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/UPGRADE-1.8.txt b/UPGRADE-1.8.txt index 5d40e2eb1..b70ff07f6 100644 --- a/UPGRADE-1.8.txt +++ b/UPGRADE-1.8.txt @@ -20,6 +20,8 @@ From 1.6.2 to 1.8: +* Asterisk now requires libpri 1.4.11+ for PRI support. + * A couple of CLI commands in res_ais were changed back to their original form: "ais show clm members" --> "ais clm show members" "ais show evt event channels" --> "ais evt show event channels" -- cgit v1.2.3 -- cgit v1.2.3 -- cgit v1.2.3 From c3f386fc6bdcc0dcf3849bbe868c258dcf4a4588 Mon Sep 17 00:00:00 2001 From: qwell Date: Thu, 21 Jul 2011 16:22:58 +0000 Subject: Fix UPGRADE.txt files for Asterisk 10. git-svn-id: http://svn.digium.com/svn/asterisk/trunk@329130 f38db490-d61c-443f-a65b-d21fe96a405b --- UPGRADE-1.10.txt | 81 -------------------------------------------------------- UPGRADE-10.txt | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ UPGRADE.txt | 6 ++--- 3 files changed, 84 insertions(+), 84 deletions(-) delete mode 100644 UPGRADE-1.10.txt create mode 100644 UPGRADE-10.txt diff --git a/UPGRADE-1.10.txt b/UPGRADE-1.10.txt deleted file mode 100644 index c1c1cd24c..000000000 --- a/UPGRADE-1.10.txt +++ /dev/null @@ -1,81 +0,0 @@ -=========================================================== -=== -=== Information for upgrading between Asterisk versions -=== -=== These files document all the changes that MUST be taken -=== into account when upgrading between the Asterisk -=== versions listed below. These changes may require that -=== you modify your configuration files, dialplan or (in -=== some cases) source code if you have your own Asterisk -=== modules or patches. These files also include advance -=== notice of any functionality that has been marked as -=== 'deprecated' and may be removed in a future release, -=== along with the suggested replacement functionality. -=== -=== UPGRADE-1.2.txt -- Upgrade info for 1.0 to 1.2 -=== UPGRADE-1.4.txt -- Upgrade info for 1.2 to 1.4 -=== UPGRADE-1.6.txt -- Upgrade info for 1.4 to 1.6 -=== UPGRADE-1.8.txt -- Upgrade info for 1.6 to 1.8 -=== -=========================================================== - -From 1.8 to 1.10: - -cel_pgsql: - - This module now expects an 'extra' column in the database for data added - using the CELGenUserEvent() application. - -ConfBridge - - ConfBridge's dialplan arguments have changed and are not - backwards compatible. - -File Interpreters - - The format interpreter formats/format_sln16.c for the file extension - '.sln16' has been removed. The '.sln16' file interpreter now exists - in the formats/format_sln.c module along with new support for sln12, - sln24, sln32, sln44, sln48, sln96, and sln192 file extensions. - -HTTP: - - A bindaddr must be specified in order for the HTTP server - to run. Previous versions would default to 0.0.0.0 if no - bindaddr was specified. - -Gtalk: - - The default value for 'context' and 'parkinglots' in gtalk.conf has - been changed to 'default', previously they were empty. - -chan_dahdi: - - The mohinterpret=passthrough setting is deprecated in favor of - moh_signaling=notify. - -pbx_lua: - - Execution no longer continues after applications that do dialplan jumps - (such as app.goto). Now when an application such as app.goto() is called, - control is returned back to the pbx engine and the current extension - function stops executing. - - the autoservice now defaults to being on by default - - autoservice_start() and autoservice_start() no longer return a value. - -Queue: - - Mark QUEUE_MEMBER_PENALTY Deprecated it never worked for realtime members - - QUEUE_MEMBER is now R/W supporting setting paused, ignorebusy and penalty. - -Asterisk Database: - - The internal Asterisk database has been switched from Berkeley DB 1.86 to - SQLite 3. An existing Berkeley astdb file can be converted with the astdb2sqlite3 - utility in the UTILS section of menuselect. If an existing astdb is found and no - astdb.sqlite3 exists, astdb2sqlite3 will be compiled automatically. Asterisk will - convert an existing astdb to the SQLite3 version automatically at runtime. - -Module Support Level - - All modules in the addons, apps, bridge, cdr, cel, channels, codecs, - formats, funcs, pbx, and res have been updated to include MODULEINFO data - that includes tags with a value of core, extended, or deprecated. - More information is available on the Asterisk wiki at - https://wiki.asterisk.org/wiki/display/AST/Asterisk+Module+Support+States - - Deprecated modules are now marked to not build by default and must be explicitly - enabled in menuselect. - -=========================================================== -=========================================================== diff --git a/UPGRADE-10.txt b/UPGRADE-10.txt new file mode 100644 index 000000000..c5d927b51 --- /dev/null +++ b/UPGRADE-10.txt @@ -0,0 +1,81 @@ +=========================================================== +=== +=== Information for upgrading between Asterisk versions +=== +=== These files document all the changes that MUST be taken +=== into account when upgrading between the Asterisk +=== versions listed below. These changes may require that +=== you modify your configuration files, dialplan or (in +=== some cases) source code if you have your own Asterisk +=== modules or patches. These files also include advance +=== notice of any functionality that has been marked as +=== 'deprecated' and may be removed in a future release, +=== along with the suggested replacement functionality. +=== +=== UPGRADE-1.2.txt -- Upgrade info for 1.0 to 1.2 +=== UPGRADE-1.4.txt -- Upgrade info for 1.2 to 1.4 +=== UPGRADE-1.6.txt -- Upgrade info for 1.4 to 1.6 +=== UPGRADE-1.8.txt -- Upgrade info for 1.6 to 1.8 +=== +=========================================================== + +From 1.8 to 10: + +cel_pgsql: + - This module now expects an 'extra' column in the database for data added + using the CELGenUserEvent() application. + +ConfBridge + - ConfBridge's dialplan arguments have changed and are not + backwards compatible. + +File Interpreters + - The format interpreter formats/format_sln16.c for the file extension + '.sln16' has been removed. The '.sln16' file interpreter now exists + in the formats/format_sln.c module along with new support for sln12, + sln24, sln32, sln44, sln48, sln96, and sln192 file extensions. + +HTTP: + - A bindaddr must be specified in order for the HTTP server + to run. Previous versions would default to 0.0.0.0 if no + bindaddr was specified. + +Gtalk: + - The default value for 'context' and 'parkinglots' in gtalk.conf has + been changed to 'default', previously they were empty. + +chan_dahdi: + - The mohinterpret=passthrough setting is deprecated in favor of + moh_signaling=notify. + +pbx_lua: + - Execution no longer continues after applications that do dialplan jumps + (such as app.goto). Now when an application such as app.goto() is called, + control is returned back to the pbx engine and the current extension + function stops executing. + - the autoservice now defaults to being on by default + - autoservice_start() and autoservice_start() no longer return a value. + +Queue: + - Mark QUEUE_MEMBER_PENALTY Deprecated it never worked for realtime members + - QUEUE_MEMBER is now R/W supporting setting paused, ignorebusy and penalty. + +Asterisk Database: + - The internal Asterisk database has been switched from Berkeley DB 1.86 to + SQLite 3. An existing Berkeley astdb file can be converted with the astdb2sqlite3 + utility in the UTILS section of menuselect. If an existing astdb is found and no + astdb.sqlite3 exists, astdb2sqlite3 will be compiled automatically. Asterisk will + convert an existing astdb to the SQLite3 version automatically at runtime. + +Module Support Level + - All modules in the addons, apps, bridge, cdr, cel, channels, codecs, + formats, funcs, pbx, and res have been updated to include MODULEINFO data + that includes tags with a value of core, extended, or deprecated. + More information is available on the Asterisk wiki at + https://wiki.asterisk.org/wiki/display/AST/Asterisk+Module+Support+States + + Deprecated modules are now marked to not build by default and must be explicitly + enabled in menuselect. + +=========================================================== +=========================================================== diff --git a/UPGRADE.txt b/UPGRADE.txt index e98559f65..d7803b4d3 100644 --- a/UPGRADE.txt +++ b/UPGRADE.txt @@ -16,15 +16,15 @@ === UPGRADE-1.4.txt -- Upgrade info for 1.2 to 1.4 === UPGRADE-1.6.txt -- Upgrade info for 1.4 to 1.6 === UPGRADE-1.8.txt -- Upgrade info for 1.6 to 1.8 -=== UPGRADE-1.10.txt -- Upgrade info for 1.8 to 1.10 +=== UPGRADE-10.txt -- Upgrade info for 1.8 to 10 === =========================================================== -From 1.10 to 1.12: +From 10 to 12: * No significant changes as of yet. -From 1.8 to 1.10: +From 1.8 to 10: cel_pgsql: - This module now expects an 'extra' column in the database for data added -- cgit v1.2.3 From ce2f61013b364080d7ddabfcb48ac297d5758fbc Mon Sep 17 00:00:00 2001 From: rmudgett Date: Thu, 21 Jul 2011 16:59:38 +0000 Subject: Merged revisions 329145 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/10 ................ r329145 | rmudgett | 2011-07-21 11:52:17 -0500 (Thu, 21 Jul 2011) | 16 lines Merged revisions 329144 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.8 ........ r329144 | rmudgett | 2011-07-21 11:46:21 -0500 (Thu, 21 Jul 2011) | 9 lines Dialplan bridge() app mutex 'current_dest_chan' freed more times than we've locked! This appears to be a leftover from when ast_channel was converted to ao2 objects. Simply removed the extraneous unlock. (closes issue ASTERISK-17772) ........ ................ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@329146 f38db490-d61c-443f-a65b-d21fe96a405b --- main/features.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/main/features.c b/main/features.c index 7f8444c17..5d3eda616 100644 --- a/main/features.c +++ b/main/features.c @@ -6149,8 +6149,6 @@ static int bridge_exec(struct ast_channel *chan, const char *data) "Channel2: %s\r\n", chan->name, args.dest_chan); } - ast_channel_unlock(current_dest_chan); - do_bridge_masquerade(current_dest_chan, final_dest_chan); chans[0] = current_dest_chan; -- cgit v1.2.3 From 42df093d7a08aaab59f8a0cc5f73456d45fa3f9d Mon Sep 17 00:00:00 2001 From: rmudgett Date: Thu, 21 Jul 2011 17:33:06 +0000 Subject: Merged revisions 329200 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/10 ................ r329200 | rmudgett | 2011-07-21 12:32:02 -0500 (Thu, 21 Jul 2011) | 24 lines Merged revisions 329199 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.8 ........ r329199 | rmudgett | 2011-07-21 12:30:57 -0500 (Thu, 21 Jul 2011) | 17 lines Update PickupChan documentation. The PickupChan uses the ampersand as the argument separator. Was documented as: PickupChan(channel[,channel2[,...][,options]]) Fixed documentation to: PickupChan(Technology/Resource[&Technology2/Resource2[&...]][,options]) This is a continuation of ASTERISK-17494 for v1.8 and later. (closes issue ASTERISK-18144) Reported by: Erik Smith Patches: pickupchan_ducumentation-v2.patch (License #6263) patch uploaded by Erik Smith Tested by: Erik Smith ........ ................ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@329201 f38db490-d61c-443f-a65b-d21fe96a405b --- apps/app_directed_pickup.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/apps/app_directed_pickup.c b/apps/app_directed_pickup.c index c2bdf5131..1b47d011a 100644 --- a/apps/app_directed_pickup.c +++ b/apps/app_directed_pickup.c @@ -80,9 +80,11 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") Pickup a ringing channel. - - - + + + + +