[svn-commits] mvanbaak: branch group/multiparking r107013 - in /team/group/multiparking: ./...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Sun Mar 9 08:48:27 CDT 2008


Author: mvanbaak
Date: Sun Mar  9 08:48:27 2008
New Revision: 107013

URL: http://svn.digium.com/view/asterisk?view=rev&rev=107013
Log:
merge, resolve conflicts, compile, reset automerge, go!

Modified:
    team/group/multiparking/   (props changed)
    team/group/multiparking/apps/app_dial.c
    team/group/multiparking/apps/app_meetme.c
    team/group/multiparking/apps/app_queue.c
    team/group/multiparking/channels/chan_iax2.c
    team/group/multiparking/channels/chan_sip.c
    team/group/multiparking/channels/chan_skinny.c
    team/group/multiparking/channels/chan_zap.c
    team/group/multiparking/include/asterisk/pbx.h
    team/group/multiparking/include/asterisk/pval.h
    team/group/multiparking/main/channel.c
    team/group/multiparking/main/editline/Makefile.in
    team/group/multiparking/main/features.c
    team/group/multiparking/main/pbx.c
    team/group/multiparking/pbx/pbx_ael.c
    team/group/multiparking/pbx/pbx_config.c
    team/group/multiparking/res/ael/ael.flex
    team/group/multiparking/res/ael/ael.tab.c
    team/group/multiparking/res/ael/ael.tab.h
    team/group/multiparking/res/ael/ael.y
    team/group/multiparking/res/ael/ael_lex.c
    team/group/multiparking/res/ael/pval.c
    team/group/multiparking/utils/Makefile
    team/group/multiparking/utils/ael_main.c
    team/group/multiparking/utils/conf2ael.c
    team/group/multiparking/utils/extconf.c

Propchange: team/group/multiparking/
------------------------------------------------------------------------------
    automerge = yes

Propchange: team/group/multiparking/
------------------------------------------------------------------------------
Binary property 'branch-1.4-merged' - no diff available.

Propchange: team/group/multiparking/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Sun Mar  9 08:48:27 2008
@@ -1,1 +1,1 @@
-/trunk:1-106717
+/trunk:1-107012

Modified: team/group/multiparking/apps/app_dial.c
URL: http://svn.digium.com/view/asterisk/team/group/multiparking/apps/app_dial.c?view=diff&rev=107013&r1=107012&r2=107013
==============================================================================
--- team/group/multiparking/apps/app_dial.c (original)
+++ team/group/multiparking/apps/app_dial.c Sun Mar  9 08:48:27 2008
@@ -2096,9 +2096,7 @@
 	int res;
 	struct ast_context *con;
 
-	con = ast_context_find("app_dial_gosub_virtual_context");
-	if (!con)
-		con = ast_context_create(NULL, "app_dial_gosub_virtual_context", "app_dial");
+	con = ast_context_find_or_create(NULL, NULL, "app_dial_gosub_virtual_context", "app_dial");
 	if (!con)
 		ast_log(LOG_ERROR, "Dial virtual context 'app_dial_gosub_virtual_context' does not exist and unable to create\n");
 	else

Modified: team/group/multiparking/apps/app_meetme.c
URL: http://svn.digium.com/view/asterisk/team/group/multiparking/apps/app_meetme.c?view=diff&rev=107013&r1=107012&r2=107013
==============================================================================
--- team/group/multiparking/apps/app_meetme.c (original)
+++ team/group/multiparking/apps/app_meetme.c Sun Mar  9 08:48:27 2008
@@ -5280,7 +5280,7 @@
 
 	if (!ast_strlen_zero(trunk->autocontext)) {
 		struct ast_context *context;
-		context = ast_context_find_or_create(NULL, trunk->autocontext, sla_registrar);
+		context = ast_context_find_or_create(NULL, NULL, trunk->autocontext, sla_registrar);
 		if (!context) {
 			ast_log(LOG_ERROR, "Failed to automatically find or create "
 				"context '%s' for SLA!\n", trunk->autocontext);
@@ -5417,7 +5417,7 @@
 	if (!ast_strlen_zero(station->autocontext)) {
 		struct ast_context *context;
 		struct sla_trunk_ref *trunk_ref;
-		context = ast_context_find_or_create(NULL, station->autocontext, sla_registrar);
+		context = ast_context_find_or_create(NULL, NULL, station->autocontext, sla_registrar);
 		if (!context) {
 			ast_log(LOG_ERROR, "Failed to automatically find or create "
 				"context '%s' for SLA!\n", station->autocontext);
@@ -5510,7 +5510,7 @@
 
 	ast_config_destroy(cfg);
 
-	if (!reload)
+	if (!reload && (!AST_LIST_EMPTY(&sla_stations) || !AST_LIST_EMPTY(&sla_stations)))
 		ast_pthread_create(&sla.thread, NULL, sla_thread, NULL);
 
 	return res;

Modified: team/group/multiparking/apps/app_queue.c
URL: http://svn.digium.com/view/asterisk/team/group/multiparking/apps/app_queue.c?view=diff&rev=107013&r1=107012&r2=107013
==============================================================================
--- team/group/multiparking/apps/app_queue.c (original)
+++ team/group/multiparking/apps/app_queue.c Sun Mar  9 08:48:27 2008
@@ -6147,9 +6147,7 @@
 	if (!reload_queues(0))
 		return AST_MODULE_LOAD_DECLINE;
 
-	con = ast_context_find("app_queue_gosub_virtual_context");
-	if (!con)
-		con = ast_context_create(NULL, "app_queue_gosub_virtual_context", "app_queue");
+	con = ast_context_find_or_create(NULL, NULL, "app_queue_gosub_virtual_context", "app_queue");
 	if (!con)
 		ast_log(LOG_ERROR, "Queue virtual context 'app_queue_gosub_virtual_context' does not exist and unable to create\n");
 	else

Modified: team/group/multiparking/channels/chan_iax2.c
URL: http://svn.digium.com/view/asterisk/team/group/multiparking/channels/chan_iax2.c?view=diff&rev=107013&r1=107012&r2=107013
==============================================================================
--- team/group/multiparking/channels/chan_iax2.c (original)
+++ team/group/multiparking/channels/chan_iax2.c Sun Mar  9 08:48:27 2008
@@ -10788,8 +10788,7 @@
 		} else if (!strcasecmp(v->name, "regcontext")) {
 			ast_copy_string(regcontext, v->value, sizeof(regcontext));
 			/* Create context if it doesn't exist already */
-			if (!ast_context_find(regcontext))
-				ast_context_create(NULL, regcontext, "IAX2");
+			ast_context_find_or_create(NULL, NULL, regcontext, "IAX2");
 		} else if (!strcasecmp(v->name, "tos")) {
 			if (ast_str2tos(v->value, &tos))
 				ast_log(LOG_WARNING, "Invalid tos value at line %d, refer to QoS documentation\n", v->lineno);

Modified: team/group/multiparking/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/group/multiparking/channels/chan_sip.c?view=diff&rev=107013&r1=107012&r2=107013
==============================================================================
--- team/group/multiparking/channels/chan_sip.c (original)
+++ team/group/multiparking/channels/chan_sip.c Sun Mar  9 08:48:27 2008
@@ -3388,6 +3388,7 @@
 {
 	char multi[256];
 	char *stringp, *ext, *context;
+	struct pbx_find_info q = { .stacklen = 0 };
 
 	/* XXX note that global_regcontext is both a global 'enable' flag and
 	 * the name of the global regexten context, if not specified
@@ -3408,11 +3409,12 @@
 		} else {
 			context = global_regcontext;
 		}
-		if (onoff)
+		if (onoff) {
 			ast_add_extension(context, 1, ext, 1, NULL, NULL, "Noop",
 				 ast_strdup(peer->name), ast_free_ptr, "SIP");
-		else
+		} else if (pbx_find_extension(NULL, NULL, &q, context, ext, 1, NULL, "", E_MATCH)) {
 			ast_context_remove_extension(context, ext, 1, NULL);
+		}
 	}
 }
 
@@ -20297,8 +20299,7 @@
 			/* Create contexts if they don't exist already */
 			while ((context = strsep(&stringp, "&"))) {
 				ast_copy_string(used_context, context, sizeof(used_context));
-				if (!ast_context_find(context))
-					ast_context_create(NULL, context, "SIP");
+				ast_context_find_or_create(NULL, NULL, context, "SIP");
 			}
 			ast_copy_string(global_regcontext, v->value, sizeof(global_regcontext));
 		} else if (!strcasecmp(v->name, "regextenonqualify")) {

Modified: team/group/multiparking/channels/chan_skinny.c
URL: http://svn.digium.com/view/asterisk/team/group/multiparking/channels/chan_skinny.c?view=diff&rev=107013&r1=107012&r2=107013
==============================================================================
--- team/group/multiparking/channels/chan_skinny.c (original)
+++ team/group/multiparking/channels/chan_skinny.c Sun Mar  9 08:48:27 2008
@@ -5801,8 +5801,7 @@
 			/* Create contexts if they don't exist already */
 			while ((context = strsep(&stringp, "&"))) {
 				ast_copy_string(used_context, context, sizeof(used_context));
-				if (!ast_context_find(context))
-					ast_context_create(NULL, context, "Skinny");
+				ast_context_find_or_create(NULL, NULL, context, "Skinny");
 			}
 			ast_copy_string(regcontext, v->value, sizeof(regcontext));
 		} else if (!strcasecmp(v->name, "dateformat")) {

Modified: team/group/multiparking/channels/chan_zap.c
URL: http://svn.digium.com/view/asterisk/team/group/multiparking/channels/chan_zap.c?view=diff&rev=107013&r1=107012&r2=107013
==============================================================================
--- team/group/multiparking/channels/chan_zap.c (original)
+++ team/group/multiparking/channels/chan_zap.c Sun Mar  9 08:48:27 2008
@@ -9514,9 +9514,11 @@
 				}
 				p = linkset->pvts[chanpos];
 
-				zt_loopback(p, 0);
-				
-				ss7_start_call(p, linkset);
+				if (p->loopedback) {
+					zt_loopback(p, 0);
+					ss7_start_call(p, linkset);
+				}
+
 				break;
 			case ISUP_EVENT_CCR:
 				ast_debug(1, "Got CCR request on CIC %d\n", e->ccr.cic);
@@ -10307,8 +10309,18 @@
 		if (e) {
 			if (pri->debug)
 				pri_dump_event(pri->dchans[which], e);
-			if (e->e != PRI_EVENT_DCHAN_DOWN)
+
+			if (e->e != PRI_EVENT_DCHAN_DOWN) {
+				if (!(pri->dchanavail[which] & DCHAN_UP)) {
+					ast_verb(2, "%s D-Channel on span %d up\n", pri_order(which), pri->span);
+				}
 				pri->dchanavail[which] |= DCHAN_UP;
+			} else {
+				if (pri->dchanavail[which] & DCHAN_UP) {
+					ast_verb(2, "%s D-Channel on span %d down\n", pri_order(which), pri->span);
+				}
+				pri->dchanavail[which] &= ~DCHAN_UP;
+			}
 
 			if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
 				/* Must be an NFAS group that has the secondary dchan active */
@@ -10316,8 +10328,6 @@
 
 			switch (e->e) {
 			case PRI_EVENT_DCHAN_UP:
-				ast_verb(2, "%s D-Channel on span %d up\n", pri_order(which), pri->span);
-				pri->dchanavail[which] |= DCHAN_UP;
 				if (!pri->pri) pri_find_dchan(pri);
 
 				/* Note presense of D-channel */
@@ -10336,8 +10346,6 @@
 					}
 				break;
 			case PRI_EVENT_DCHAN_DOWN:
-				ast_verb(2, "%s D-Channel on span %d down\n", pri_order(which), pri->span);
-				pri->dchanavail[which] &= ~DCHAN_UP;
 				pri_find_dchan(pri);
 				if (!pri_is_up(pri)) {
 					pri->resetting = 0;

Modified: team/group/multiparking/include/asterisk/pbx.h
URL: http://svn.digium.com/view/asterisk/team/group/multiparking/include/asterisk/pbx.h?view=diff&rev=107013&r1=107012&r2=107013
==============================================================================
--- team/group/multiparking/include/asterisk/pbx.h (original)
+++ team/group/multiparking/include/asterisk/pbx.h Sun Mar  9 08:48:27 2008
@@ -25,6 +25,7 @@
 
 #include "asterisk/sched.h"
 #include "asterisk/chanvars.h"
+#include "asterisk/hashtab.h"
 
 #if defined(__cplusplus) || defined(c_plusplus)
 extern "C" {
@@ -167,11 +168,16 @@
 int pbx_exec(struct ast_channel *c, struct ast_app *app, void *data);
 
 /*!
- * \brief Register a new context
+ * \brief Register a new context or find an existing one
  *
  * \param extcontexts pointer to the ast_context structure pointer
+ * \param exttable pointer to the hashtable that contains all the elements in extcontexts
  * \param name name of the new context
  * \param registrar registrar of the context
+ *
+ * This function allows you to play in two environments: the global contexts (active dialplan)
+ * or an external context set of your choosing. To act on the external set, make sure extcontexts
+ * and exttable are set; for the globals, make sure both extcontexts and exttable are NULL.
  *
  * This will first search for a context with your name.  If it exists already, it will not
  * create a new one.  If it does not exist, it will create a new one with the given name
@@ -179,33 +185,19 @@
  *
  * \return NULL on failure, and an ast_context structure on success
  */
-struct ast_context *ast_context_create(struct ast_context **extcontexts, const char *name, const char *registrar);
-
-/*!
- * \brief Register a new context or find an existing one
- *
- * \param extcontexts pointer to the ast_context structure pointer
- * \param name name of the new context
- * \param registrar registrar of the context
- *
- * This will first search for a context with your name.  If it exists already, it will not
- * create a new one.  If it does not exist, it will create a new one with the given name
- * and registrar.
- *
- * \return NULL on failure, and an ast_context structure on success
- */
-struct ast_context *ast_context_find_or_create(struct ast_context **extcontexts, const char *name, const char *registrar);
+struct ast_context *ast_context_find_or_create(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar);
 
 /*!
  * \brief Merge the temporary contexts into a global contexts list and delete from the 
  *        global list the ones that are being added
  *
- * \param extcontexts pointer to the ast_context structure pointer
+ * \param extcontexts pointer to the ast_context structure
+ * \param exttable pointer to the ast_hashtab structure that contains all the elements in extcontexts
  * \param registrar of the context; if it's set the routine will delete all contexts 
  *        that belong to that registrar; if NULL only the contexts that are specified 
  *        in extcontexts
  */
-void ast_merge_contexts_and_delete(struct ast_context **extcontexts, const char *registrar);
+void ast_merge_contexts_and_delete(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *registrar);
 
 /*!
  * \brief Destroy a context (matches the specified context (or ANY context if NULL)
@@ -973,8 +965,18 @@
 									 struct ast_context *bypass, struct pbx_find_info *q,
 									 const char *context, const char *exten, int priority,
 									 const char *label, const char *callerid, enum ext_match_t action);
+
+
+/* every time a write lock is obtained for contexts,
+   a counter is incremented. You can check this via the
+   following func */
+
+int ast_wrlock_contexts_version(void);
 	
 
+/* hashtable functions for contexts */
+int ast_hashtab_compare_contexts(const void *ah_a, const void *ah_b);
+unsigned int ast_hashtab_hash_contexts(const void *obj);
 
 #if defined(__cplusplus) || defined(c_plusplus)
 }

Modified: team/group/multiparking/include/asterisk/pval.h
URL: http://svn.digium.com/view/asterisk/team/group/multiparking/include/asterisk/pval.h?view=diff&rev=107013&r1=107012&r2=107013
==============================================================================
--- team/group/multiparking/include/asterisk/pval.h (original)
+++ team/group/multiparking/include/asterisk/pval.h Sun Mar  9 08:48:27 2008
@@ -1,6 +1,7 @@
 #ifndef _ASTERISK_PVAL_H
 #define _ASTERISK_PVAL_H
 
+/* whatever includes this, better include asterisk/lock.h and asterisk/hashtab.h */
 
 typedef enum 
 {
@@ -143,7 +144,7 @@
    static void gen_prios(struct ael_extension *exten, char *label, pval *statement, struct ael_extension *mother_exten, struct ast_context *context ); */
 void set_priorities(struct ael_extension *exten);
 void add_extensions(struct ael_extension *exten);
-void ast_compile_ael2(struct ast_context **local_contexts, struct pval *root);
+void ast_compile_ael2(struct ast_context **local_contexts, struct ast_hashtab *local_table, struct pval *root);
 void destroy_pval(pval *item);
 void destroy_pval_item(pval *item);
 int is_float(char *arg );

Modified: team/group/multiparking/main/channel.c
URL: http://svn.digium.com/view/asterisk/team/group/multiparking/main/channel.c?view=diff&rev=107013&r1=107012&r2=107013
==============================================================================
--- team/group/multiparking/main/channel.c (original)
+++ team/group/multiparking/main/channel.c Sun Mar  9 08:48:27 2008
@@ -2203,6 +2203,7 @@
 					return -1;
 				case AST_CONTROL_RINGING:
 				case AST_CONTROL_ANSWER:
+				case AST_CONTROL_SRCUPDATE:
 					/* Unimportant */
 					break;
 				default:

Modified: team/group/multiparking/main/editline/Makefile.in
URL: http://svn.digium.com/view/asterisk/team/group/multiparking/main/editline/Makefile.in?view=diff&rev=107013&r1=107012&r2=107013
==============================================================================
--- team/group/multiparking/main/editline/Makefile.in (original)
+++ team/group/multiparking/main/editline/Makefile.in Sun Mar  9 08:48:27 2008
@@ -4,7 +4,7 @@
 
 OSTYPE=$(shell uname -s)
 define cyg_subst_sys
-	if uname -s | grep -qi cygwin; then \
+	if uname -s | ${GREP} -qi cygwin; then \
 	cat $@ | sed -e s/"sys\.h"/"config.h"/g > $@.copy; \
 	mv --force $@.copy $@; \
 	fi

Modified: team/group/multiparking/main/features.c
URL: http://svn.digium.com/view/asterisk/team/group/multiparking/main/features.c?view=diff&rev=107013&r1=107012&r2=107013
==============================================================================
--- team/group/multiparking/main/features.c (original)
+++ team/group/multiparking/main/features.c Sun Mar  9 08:48:27 2008
@@ -567,9 +567,7 @@
 		ast_adsi_unload_session(peer);
 	}
 
-	con = ast_context_find(parkinglot->parking_con);
-	if (!con) 
-		con = ast_context_create(NULL, parkinglot->parking_con, registrar);
+	con = ast_context_find_or_create(NULL, NULL, parkinglot->parking_con, registrar);
 	if (!con)	/* Still no context? Bad */
 		ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parkinglot->parking_con);
 	/* Tell the peer channel the number of the parking space */
@@ -2299,11 +2297,9 @@
 					if (peername_flat[i] == '/') 
 						peername_flat[i]= '0';
 				}
-				con = ast_context_find(pu->parkinglot->parking_con_dial);
+				con = ast_context_find_or_create(NULL, NULL, pu->parkinglot->parking_con_dial, registrar);
 				if (!con) {
-					con = ast_context_create(NULL, pu->parkinglot->parking_con_dial, registrar);
-					if (!con)
-						ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", pu->parkinglot->parking_con_dial);
+					ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", pu->parkinglot->parking_con_dial);
 				}
 				if (con) {
 					char returnexten[AST_MAX_EXTENSION];
@@ -2772,11 +2768,9 @@
 	}
 
 	/* Create context */
-	if (!error && !(con = ast_context_find(parkinglot->parking_con))) {
-		if (!(con = ast_context_create(NULL, parkinglot->parking_con, registrar))) {
-			ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parkinglot->parking_con);
-			error = 1;
-		}
+	if (!error && !(con = ast_context_find_or_create(NULL, NULL, parkinglot->parking_con, registrar))) {
+		ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parkinglot->parking_con);
+		error = 1;
 	}
 
 	/* Add a parking extension into the context */
@@ -3123,11 +3117,9 @@
 		ast_debug(1, "Removed old parking extension %s@%s\n", old_parking_ext, old_parking_con);
 	}
 	
-	if (!(con = ast_context_find(default_parkinglot->parking_con))) {
-		if (!(con = ast_context_create(NULL, default_parkinglot->parking_con, registrar))) {
-			ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", default_parkinglot->parking_con);
-			return -1;
-		}
+	if (!(con = ast_context_find_or_create(NULL, NULL, default_parkinglot->parking_con, registrar))) {
+		ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", default_parkinglot->parking_con);
+		return -1;
 	}
 	res = ast_add_extension2(con, 1, ast_parking_ext(), 1, NULL, NULL, parkcall, NULL, NULL, registrar);
 	if (parkaddhints)

Modified: team/group/multiparking/main/pbx.c
URL: http://svn.digium.com/view/asterisk/team/group/multiparking/main/pbx.c?view=diff&rev=107013&r1=107012&r2=107013
==============================================================================
--- team/group/multiparking/main/pbx.c (original)
+++ team/group/multiparking/main/pbx.c Sun Mar  9 08:48:27 2008
@@ -48,6 +48,7 @@
 #include "asterisk/cdr.h"
 #include "asterisk/config.h"
 #include "asterisk/term.h"
+#include "asterisk/time.h"
 #include "asterisk/manager.h"
 #include "asterisk/ast_expr.h"
 #include "asterisk/linkedlists.h"
@@ -140,8 +141,8 @@
 	void *data;			/*!< Data to use (arguments) */
 	void (*datad)(void *);		/*!< Data destructor */
 	struct ast_exten *peer;		/*!< Next higher priority with our extension */
-	struct ast_hashtab *peer_tree;    /*!< Priorities list in tree form -- only on the head of the peer list */
-	struct ast_hashtab *peer_label_tree; /*!< labeled priorities in the peer list -- only on the head of the peer list */
+	struct ast_hashtab *peer_table;    /*!< Priorities list in hashtab form -- only on the head of the peer list */
+	struct ast_hashtab *peer_label_table; /*!< labeled priorities in the peers -- only on the head of the peer list */
 	const char *registrar;		/*!< Registrar */
 	struct ast_exten *next;		/*!< Extension with a greater ID */
 	char stuff[0];
@@ -203,12 +204,13 @@
 struct ast_context {
 	ast_rwlock_t lock; 			/*!< A lock to prevent multiple threads from clobbering the context */
 	struct ast_exten *root;			/*!< The root of the list of extensions */
-	struct ast_hashtab *root_tree;            /*!< For exact matches on the extensions in the pattern tree, and for traversals of the pattern_tree  */
+	struct ast_hashtab *root_table;            /*!< For exact matches on the extensions in the pattern tree, and for traversals of the pattern_tree  */
  	struct match_char *pattern_tree;        /*!< A tree to speed up extension pattern matching */
 	struct ast_context *next;		/*!< Link them together */
 	struct ast_include *includes;		/*!< Include other contexts */
 	struct ast_ignorepat *ignorepats;	/*!< Patterns for which to continue playing dialtone */
 	const char *registrar;			/*!< Registrar */
+	int refcount;                   /*!< each module that would have created this context should inc/dec this as appropriate */
 	AST_LIST_HEAD_NOLOCK(, ast_sw) alts;	/*!< Alternative switches */
 	ast_mutex_t macrolock;			/*!< A lock to implement "exclusive" macros - held whilst a call is executing in the macro */
 	char name[0];				/*!< Name of the context */
@@ -327,17 +329,18 @@
 static void create_match_char_tree(struct ast_context *con);
 static struct ast_exten *get_canmatch_exten(struct match_char *node);
 static void destroy_pattern_tree(struct match_char *pattern_tree);
-static int hashtab_compare_contexts(const void *ah_a, const void *ah_b);
+int ast_hashtab_compare_contexts(const void *ah_a, const void *ah_b);
 static int hashtab_compare_extens(const void *ha_a, const void *ah_b);
 static int hashtab_compare_exten_numbers(const void *ah_a, const void *ah_b);
 static int hashtab_compare_exten_labels(const void *ah_a, const void *ah_b);
-static unsigned int hashtab_hash_contexts(const void *obj);
+unsigned int ast_hashtab_hash_contexts(const void *obj);
 static unsigned int hashtab_hash_extens(const void *obj);
 static unsigned int hashtab_hash_priority(const void *obj);
 static unsigned int hashtab_hash_labels(const void *obj);
+static void __ast_internal_context_destroy( struct ast_context *con);
 
 /* labels, contexts are case sensitive  priority numbers are ints */
-static int hashtab_compare_contexts(const void *ah_a, const void *ah_b)
+int ast_hashtab_compare_contexts(const void *ah_a, const void *ah_b)
 {
 	const struct ast_context *ac = ah_a;
 	const struct ast_context *bc = ah_b;
@@ -376,7 +379,7 @@
 	return strcmp(ac->label, bc->label);
 }
 
-static unsigned int hashtab_hash_contexts(const void *obj)
+unsigned int ast_hashtab_hash_contexts(const void *obj)
 {
 	const struct ast_context *ac = obj;
 	return ast_hashtab_hash_string(ac->name);
@@ -684,7 +687,7 @@
 };
 
 static struct ast_context *contexts;
-static struct ast_hashtab *contexts_tree = NULL;
+static struct ast_hashtab *contexts_table = NULL;
 
 AST_RWLOCK_DEFINE_STATIC(conlock); 		/*!< Lock for the ast_context list */
 
@@ -1252,11 +1255,11 @@
 	int biggest_bucket, resizes, numobjs, numbucks;
 	
 	ast_log(LOG_DEBUG,"Creating Extension Trie for context %s\n", con->name);
-	ast_hashtab_get_stats(con->root_tree, &biggest_bucket, &resizes, &numobjs, &numbucks);
+	ast_hashtab_get_stats(con->root_table, &biggest_bucket, &resizes, &numobjs, &numbucks);
 	ast_log(LOG_DEBUG,"This tree has %d objects in %d bucket lists, longest list=%d objects, and has resized %d times\n",
 			numobjs, numbucks, biggest_bucket, resizes);
 #endif
-	t1 = ast_hashtab_start_traversal(con->root_tree);
+	t1 = ast_hashtab_start_traversal(con->root_table);
 	while( (e1 = ast_hashtab_next(t1)) ) {
 		if (e1->exten)
 			add_exten_to_pattern_tree(con, e1, 0);
@@ -1582,12 +1585,13 @@
 {
 	ast_rwlock_t lock; 			
 	struct ast_exten *root;		
-	struct ast_hashtab *root_tree;            
+	struct ast_hashtab *root_table;            
 	struct match_char *pattern_tree;       
 	struct ast_context *next;	
 	struct ast_include *includes;		
 	struct ast_ignorepat *ignorepats;	
-	const char *registrar;	
+	const char *registrar;
+	int refcount;
 	AST_LIST_HEAD_NOLOCK(, ast_sw) alts;	
 	ast_mutex_t macrolock;		
 	char name[256];		
@@ -1599,8 +1603,8 @@
 	struct fake_context item;
 	strncpy(item.name,name,256);
 	ast_rdlock_contexts();
-	if( contexts_tree ) {
-		tmp = ast_hashtab_lookup(contexts_tree,&item);
+	if( contexts_table ) {
+		tmp = ast_hashtab_lookup(contexts_table,&item);
 	} else {
 		while ( (tmp = ast_walk_contexts(tmp)) ) {
 			if (!name || !strcasecmp(name, tmp->name))
@@ -1668,7 +1672,7 @@
 	else {	/* look in contexts */
 		struct fake_context item;
 		strncpy(item.name,context,256);
-		tmp = ast_hashtab_lookup(contexts_tree,&item);
+		tmp = ast_hashtab_lookup(contexts_table,&item);
 #ifdef NOTNOW
 		tmp = NULL;
 		while ((tmp = ast_walk_contexts(tmp)) ) {
@@ -1690,7 +1694,7 @@
 	score.total_specificity = 0;
 	score.exten = 0;
 	score.total_length = 0;
-	if (!tmp->pattern_tree && tmp->root_tree)
+	if (!tmp->pattern_tree && tmp->root_table)
 	{
 		create_match_char_tree(tmp);
 #ifdef NEED_DEBUG
@@ -1750,9 +1754,9 @@
 			if (action == E_FINDLABEL && label ) {
 				if (q->status < STATUS_NO_LABEL)
 					q->status = STATUS_NO_LABEL;
-				e = ast_hashtab_lookup(eroot->peer_label_tree, &pattern);
+				e = ast_hashtab_lookup(eroot->peer_label_table, &pattern);
 			} else {
-				e = ast_hashtab_lookup(eroot->peer_tree, &pattern);
+				e = ast_hashtab_lookup(eroot->peer_table, &pattern);
 			}
 			if (e) {	/* found a valid match */
 				q->status = STATUS_SUCCESS;
@@ -1786,9 +1790,9 @@
 			if (action == E_FINDLABEL && label ) {
 				if (q->status < STATUS_NO_LABEL)
 					q->status = STATUS_NO_LABEL;
-				e = ast_hashtab_lookup(eroot->peer_label_tree, &pattern);
+				e = ast_hashtab_lookup(eroot->peer_label_table, &pattern);
 			} else {
-				e = ast_hashtab_lookup(eroot->peer_tree, &pattern);
+				e = ast_hashtab_lookup(eroot->peer_table, &pattern);
 			}
 #ifdef NOTNOW
 			while ( (e = ast_walk_extension_priorities(eroot, e)) ) {
@@ -2465,7 +2469,7 @@
 				vare++;
 			}
 			if (brackets)
-				ast_log(LOG_NOTICE, "Error in extension logic (missing '}')\n");
+				ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
 			len = vare - vars - 1;
 
 			/* Skip totally over variable string */
@@ -2552,7 +2556,7 @@
 				vare++;
 			}
 			if (brackets)
-				ast_log(LOG_NOTICE, "Error in extension logic (missing ']')\n");
+				ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
 			len = vare - vars - 1;
 
 			/* Skip totally over expression */
@@ -3479,14 +3483,14 @@
 	ast_mutex_lock(&maxcalllock);
 	if (option_maxcalls) {
 		if (countcalls >= option_maxcalls) {
-			ast_log(LOG_NOTICE, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name);
+			ast_log(LOG_WARNING, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name);
 			failed = -1;
 		}
 	}
 	if (option_maxload) {
 		getloadavg(&curloadavg, 1);
 		if (curloadavg >= option_maxload) {
-			ast_log(LOG_NOTICE, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg);
+			ast_log(LOG_WARNING, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg);
 			failed = -1;
 		}
 	}
@@ -3527,10 +3531,10 @@
 	if (e->priority == PRIORITY_HINT)
 		ast_remove_hint(e);
 
-	if (e->peer_tree)
-		ast_hashtab_destroy(e->peer_tree,0);
-	if (e->peer_label_tree)
-		ast_hashtab_destroy(e->peer_label_tree, 0);
+	if (e->peer_table)
+		ast_hashtab_destroy(e->peer_table,0);
+	if (e->peer_label_table)
+		ast_hashtab_destroy(e->peer_label_table, 0);
 	if (e->datad)
 		e->datad(e->data);
 	ast_free(e);
@@ -3627,8 +3631,7 @@
 	ast_copy_string(item.name, context, sizeof(item.name));
 
 	ast_rdlock_contexts();
-
-	c = ast_hashtab_lookup(contexts_tree,&item);
+	c = ast_hashtab_lookup(contexts_table,&item);
 
 #ifdef NOTNOW
 
@@ -3789,19 +3792,19 @@
 	/* Handle this is in the new world */
 
 #ifdef NEED_DEBUG
-	ast_log(LOG_NOTICE,"Removing %s/%s/%d from trees, registrar=%s\n", con->name, extension, priority, registrar);
+	ast_verb(3,"Removing %s/%s/%d from trees, registrar=%s\n", con->name, extension, priority, registrar);
 #endif
 	/* find this particular extension */
 	ex.exten = dummy_name;
 	ex.matchcid = 0;
 	ast_copy_string(dummy_name,extension, sizeof(dummy_name));
-	exten = ast_hashtab_lookup(con->root_tree, &ex);
+	exten = ast_hashtab_lookup(con->root_table, &ex);
 	if (exten) {
 		if (priority == 0)
 		{
-			exten2 = ast_hashtab_remove_this_object(con->root_tree, exten);
+			exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
 			if (!exten2)
-				ast_log(LOG_ERROR,"Trying to delete the exten %s from context %s, but could not remove from the root_tree\n", extension, con->name);
+				ast_log(LOG_ERROR,"Trying to delete the exten %s from context %s, but could not remove from the root_table\n", extension, con->name);
 			if (con->pattern_tree) {
 				
 				struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
@@ -3815,24 +3818,28 @@
 			}
 		} else {
 			ex.priority = priority;
-			exten2 = ast_hashtab_lookup(exten->peer_tree, &ex);
+			exten2 = ast_hashtab_lookup(exten->peer_table, &ex);
 			if (exten2) {
 				
 				if (exten2->label) { /* if this exten has a label, remove that, too */
-					exten3 = ast_hashtab_remove_this_object(exten->peer_label_tree,exten2);
+					exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2);
 					if (!exten3)
-						ast_log(LOG_ERROR,"Did not remove this priority label (%d/%s) from the peer_label_tree of context %s, extension %s!\n", priority, exten2->label, con->name, exten2->exten);
+						ast_log(LOG_ERROR,"Did not remove this priority label (%d/%s) from the peer_label_table of context %s, extension %s!\n", priority, exten2->label, con->name, exten2->exten);
 				}
 				
-				exten3 = ast_hashtab_remove_this_object(exten->peer_tree, exten2);
+				exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2);
 				if (!exten3)
-					ast_log(LOG_ERROR,"Did not remove this priority (%d) from the peer_tree of context %s, extension %s!\n", priority, con->name, exten2->exten);
-				if (ast_hashtab_size(exten->peer_tree) == 0) {
+					ast_log(LOG_ERROR,"Did not remove this priority (%d) from the peer_table of context %s, extension %s!\n", priority, con->name, exten2->exten);
+				if (exten2 == exten && exten2->peer) {
+					exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
+					ast_hashtab_insert_immediate(con->root_table, exten2->peer);
+				}
+				if (ast_hashtab_size(exten->peer_table) == 0) {
 					/* well, if the last priority of an exten is to be removed,
 					   then, the extension is removed, too! */
-					exten3 = ast_hashtab_remove_this_object(con->root_tree, exten);
+					exten3 = ast_hashtab_remove_this_object(con->root_table, exten);
 					if (!exten3)
-						ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_tree (%s) (priority %d)\n", exten->exten, con->name, priority);
+						ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority);
 					if (con->pattern_tree) {
 						struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
 						if (x->exten) { /* this test for safety purposes */
@@ -3848,7 +3855,7 @@
 		}
 	} else {
 		/* hmmm? this exten is not in this pattern tree? */
-		ast_log(LOG_WARNING,"Cannot find extension %s in root_tree in context %s\n",
+		ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n",
 				extension, con->name);
 	}
 #ifdef NEED_DEBUG
@@ -3905,10 +3912,10 @@
 			 */
 			struct ast_exten *next_node = peer->peer ? peer->peer : peer->next;
 			if (next_node && next_node == peer->peer) {
-				next_node->peer_tree = exten->peer_tree; /* move the priority hash tabs over */
-				exten->peer_tree = 0;
-				next_node->peer_label_tree = exten->peer_label_tree;
-				exten->peer_label_tree = 0;
+				next_node->peer_table = exten->peer_table; /* move the priority hash tabs over */
+				exten->peer_table = 0;
+				next_node->peer_label_table = exten->peer_label_table;
+				exten->peer_label_table = 0;
 			}
 			if (!prev_exten) {	/* change the root... */
 				con->root = next_node;
@@ -3946,7 +3953,7 @@
 	ast_rdlock_contexts();
 
 	strncpy(item.name,context,256);
-	c = ast_hashtab_lookup(contexts_tree,&item);
+	c = ast_hashtab_lookup(contexts_table,&item);
 	if (c)
 		ret = 0;
 
@@ -3984,7 +3991,7 @@
 	ast_rdlock_contexts();
 
 	strncpy(item.name, context, 256);
-	c = ast_hashtab_lookup(contexts_tree,&item);
+	c = ast_hashtab_lookup(contexts_table,&item);
 	if (c)
 		ret = 0;
 #ifdef NOTNOW
@@ -4578,7 +4585,7 @@
 			if (exten) {
 				/* Check all includes for the requested extension */
 				if (includecount >= AST_PBX_MAX_STACK) {
-					ast_log(LOG_NOTICE, "Maximum include depth exceeded!\n");
+					ast_log(LOG_WARNING, "Maximum include depth exceeded!\n");
 				} else {
 					int dupe = 0;
 					int x;
@@ -5127,42 +5134,37 @@
 	return tmp ? 0 : -1;
 }
 
-static struct ast_context *__ast_context_create(struct ast_context **extcontexts, const char *name, const char *registrar, int existsokay)
+struct ast_context *ast_context_find_or_create(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar)
 {
 	struct ast_context *tmp, **local_contexts;
 	struct fake_context search;
 	int length = sizeof(struct ast_context) + strlen(name) + 1;
 
-	if (!contexts_tree) {
-		contexts_tree = ast_hashtab_create(17,
-										   hashtab_compare_contexts, 
+	if (!contexts_table) {
+		contexts_table = ast_hashtab_create(17,
+										   ast_hashtab_compare_contexts, 
 										   ast_hashtab_resize_java,
 										   ast_hashtab_newsize_java,
-										   hashtab_hash_contexts,
+										   ast_hashtab_hash_contexts,
 										   0);
 	}
 	
+	strncpy(search.name,name,sizeof(search.name));
 	if (!extcontexts) {
 		ast_rdlock_contexts();
 		local_contexts = &contexts;
-		strncpy(search.name,name,sizeof(search.name));
-		tmp = ast_hashtab_lookup(contexts_tree, &search);
-		if (!existsokay && tmp) {
-			ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name);
-		}
+		tmp = ast_hashtab_lookup(contexts_table, &search);
 		ast_unlock_contexts();
-		if (tmp)
+		if (tmp) {
+			tmp->refcount++;
 			return tmp;
+		}
 	} else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */
 		local_contexts = extcontexts;
-		for (tmp = *local_contexts; tmp; tmp = tmp->next) {
-			if (!strcasecmp(tmp->name, name)) {
-				if (!existsokay) {
-					ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name);
-					tmp = NULL;
-				}
-				return tmp;
-			}
+		tmp = ast_hashtab_lookup(exttable, &search);
+		if (tmp) {
+			tmp->refcount++;
+			return tmp;
 		}
 	}
 	
@@ -5171,19 +5173,26 @@
 		ast_mutex_init(&tmp->macrolock);
 		strcpy(tmp->name, name);
 		tmp->root = NULL;
-		tmp->root_tree = NULL;
+		tmp->root_table = NULL;
 		tmp->registrar = registrar;
 		tmp->includes = NULL;
 		tmp->ignorepats = NULL;
-	}
+		tmp->refcount = 1;
+	} else {
+		ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name);
+		return NULL;
+	}
+	
 	if (!extcontexts) {
 		ast_wrlock_contexts();
 		tmp->next = *local_contexts;
 		*local_contexts = tmp;
-		ast_hashtab_insert_safe(contexts_tree, tmp); /*put this context into the tree */
+		ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */
 		ast_unlock_contexts();
 	} else {
 		tmp->next = *local_contexts;
+		if (exttable)
+			ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */
 		*local_contexts = tmp;
 	}
 	ast_debug(1, "Registered context '%s'\n", tmp->name);
@@ -5191,16 +5200,7 @@
 	return tmp;
 }
 
-struct ast_context *ast_context_create(struct ast_context **extcontexts, const char *name, const char *registrar)
-{
-	return __ast_context_create(extcontexts, name, registrar, 0);
-}
-
-struct ast_context *ast_context_find_or_create(struct ast_context **extcontexts, const char *name, const char *registrar)
-{
-	return __ast_context_create(extcontexts, name, registrar, 1);
-}
-void __ast_context_destroy(struct ast_context *con, const char *registrar);
+void __ast_context_destroy(struct ast_context *list, struct ast_hashtab *contexttab, struct ast_context *con, const char *registrar);
 
 struct store_hint {
 	char *context;
@@ -5213,17 +5213,89 @@
 
 AST_LIST_HEAD(store_hints, store_hint);
 
+/* the purpose of this routine is to duplicate a context, with all its substructure,
+   except for any extens that have a matching registrar */
+static void context_merge(struct ast_context **extcontexts, struct ast_hashtab *exttable, struct ast_context *context, const char *registrar)
+{
+	struct ast_context *new = ast_hashtab_lookup(exttable, context); /* is there a match in the new set? */
+	struct ast_exten *exten_item, *prio_item, *new_exten_item, *new_prio_item;
+	struct ast_hashtab_iter *exten_iter;
+	struct ast_hashtab_iter *prio_iter;
+	int insert_count = 0;
+	
+	/* We'll traverse all the extensions/prios, and see which are not registrar'd with
+	   the current registrar, and copy them to the new context. If the new context does not
+	   exist, we'll create it "on demand". If no items are in this context to copy, then we'll
+	   only create the empty matching context if the old one meets the criteria */
+	if (context->root_table) {
+		exten_iter = ast_hashtab_start_traversal(context->root_table);
+		while ((exten_item=ast_hashtab_next(exten_iter))) {
+			if (new) {
+				new_exten_item = ast_hashtab_lookup(new->root_table, exten_item);
+			} else {
+				new_exten_item = NULL;
+			}
+			prio_iter = ast_hashtab_start_traversal(exten_item->peer_table);
+			while ((prio_item=ast_hashtab_next(prio_iter))) {
+				int res1;
+				
+				if (new_exten_item) {
+					new_prio_item = ast_hashtab_lookup(new_exten_item->peer_table, prio_item);
+				} else {
+					new_prio_item = NULL;
+				}
+				if (strcmp(prio_item->registrar,registrar) == 0) {
+					continue;
+				}
+				/* make sure the new context exists, so we have somewhere to stick this exten/prio */
+				if (!new) {
+					new = ast_context_find_or_create(extcontexts, exttable, context->name, prio_item->registrar); /* a new context created via priority from a different context in the old dialplan, gets its registrar from the prio's registrar */
+				}
+				if (!new) {
+					ast_log(LOG_ERROR,"Could not allocate a new context for %s in merge_and_delete! Danger!\n", context->name);
+					return; /* no sense continuing. */
+				}
+				/* we will not replace existing entries in the new context with stuff from the old context.

[... 4485 lines stripped ...]



More information about the svn-commits mailing list