[svn-commits] murf: branch murf/bug6002 r104973 - in /team/murf/bug6002: apps/ channels/ in...
SVN commits to the Digium repositories
svn-commits at lists.digium.com
Thu Feb 28 07:59:49 CST 2008
Author: murf
Date: Thu Feb 28 07:59:48 2008
New Revision: 104973
URL: http://svn.digium.com/view/asterisk?view=rev&rev=104973
Log:
an initial checkpoint; things compile, but I have still have some higher level cleanup to do
Modified:
team/murf/bug6002/apps/app_dial.c
team/murf/bug6002/apps/app_meetme.c
team/murf/bug6002/apps/app_queue.c
team/murf/bug6002/channels/chan_iax2.c
team/murf/bug6002/channels/chan_sip.c
team/murf/bug6002/channels/chan_skinny.c
team/murf/bug6002/include/asterisk/pbx.h
team/murf/bug6002/include/asterisk/pval.h
team/murf/bug6002/main/features.c
team/murf/bug6002/main/pbx.c
team/murf/bug6002/pbx/pbx_ael.c
team/murf/bug6002/pbx/pbx_config.c
team/murf/bug6002/res/ael/ael.flex
team/murf/bug6002/res/ael/ael.tab.c
team/murf/bug6002/res/ael/ael.tab.h
team/murf/bug6002/res/ael/ael.y
team/murf/bug6002/res/ael/ael_lex.c
team/murf/bug6002/res/ael/pval.c
team/murf/bug6002/utils/Makefile
team/murf/bug6002/utils/ael_main.c
team/murf/bug6002/utils/conf2ael.c
team/murf/bug6002/utils/extconf.c
Modified: team/murf/bug6002/apps/app_dial.c
URL: http://svn.digium.com/view/asterisk/team/murf/bug6002/apps/app_dial.c?view=diff&rev=104973&r1=104972&r2=104973
==============================================================================
--- team/murf/bug6002/apps/app_dial.c (original)
+++ team/murf/bug6002/apps/app_dial.c Thu Feb 28 07:59:48 2008
@@ -2024,9 +2024,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/murf/bug6002/apps/app_meetme.c
URL: http://svn.digium.com/view/asterisk/team/murf/bug6002/apps/app_meetme.c?view=diff&rev=104973&r1=104972&r2=104973
==============================================================================
--- team/murf/bug6002/apps/app_meetme.c (original)
+++ team/murf/bug6002/apps/app_meetme.c Thu Feb 28 07:59:48 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);
Modified: team/murf/bug6002/apps/app_queue.c
URL: http://svn.digium.com/view/asterisk/team/murf/bug6002/apps/app_queue.c?view=diff&rev=104973&r1=104972&r2=104973
==============================================================================
--- team/murf/bug6002/apps/app_queue.c (original)
+++ team/murf/bug6002/apps/app_queue.c Thu Feb 28 07:59:48 2008
@@ -6144,9 +6144,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/murf/bug6002/channels/chan_iax2.c
URL: http://svn.digium.com/view/asterisk/team/murf/bug6002/channels/chan_iax2.c?view=diff&rev=104973&r1=104972&r2=104973
==============================================================================
--- team/murf/bug6002/channels/chan_iax2.c (original)
+++ team/murf/bug6002/channels/chan_iax2.c Thu Feb 28 07:59:48 2008
@@ -10755,8 +10755,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/murf/bug6002/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/murf/bug6002/channels/chan_sip.c?view=diff&rev=104973&r1=104972&r2=104973
==============================================================================
--- team/murf/bug6002/channels/chan_sip.c (original)
+++ team/murf/bug6002/channels/chan_sip.c Thu Feb 28 07:59:48 2008
@@ -20280,8 +20280,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/murf/bug6002/channels/chan_skinny.c
URL: http://svn.digium.com/view/asterisk/team/murf/bug6002/channels/chan_skinny.c?view=diff&rev=104973&r1=104972&r2=104973
==============================================================================
--- team/murf/bug6002/channels/chan_skinny.c (original)
+++ team/murf/bug6002/channels/chan_skinny.c Thu Feb 28 07:59:48 2008
@@ -5798,8 +5798,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/murf/bug6002/include/asterisk/pbx.h
URL: http://svn.digium.com/view/asterisk/team/murf/bug6002/include/asterisk/pbx.h?view=diff&rev=104973&r1=104972&r2=104973
==============================================================================
--- team/murf/bug6002/include/asterisk/pbx.h (original)
+++ team/murf/bug6002/include/asterisk/pbx.h Thu Feb 28 07:59:48 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)
@@ -975,6 +967,9 @@
const char *label, const char *callerid, enum ext_match_t action);
+/* 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/murf/bug6002/include/asterisk/pval.h
URL: http://svn.digium.com/view/asterisk/team/murf/bug6002/include/asterisk/pval.h?view=diff&rev=104973&r1=104972&r2=104973
==============================================================================
--- team/murf/bug6002/include/asterisk/pval.h (original)
+++ team/murf/bug6002/include/asterisk/pval.h Thu Feb 28 07:59:48 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/murf/bug6002/main/features.c
URL: http://svn.digium.com/view/asterisk/team/murf/bug6002/main/features.c?view=diff&rev=104973&r1=104972&r2=104973
==============================================================================
--- team/murf/bug6002/main/features.c (original)
+++ team/murf/bug6002/main/features.c Thu Feb 28 07:59:48 2008
@@ -487,9 +487,7 @@
ast_adsi_unload_session(peer);
}
- con = ast_context_find(parking_con);
- if (!con)
- con = ast_context_create(NULL, parking_con, registrar);
+ con = ast_context_find_or_create(NULL, NULL, parking_con, registrar);
if (!con) /* Still no context? Bad */
ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
/* Tell the peer channel the number of the parking space */
@@ -2224,12 +2222,9 @@
if (peername_flat[i] == '/')
peername_flat[i]= '0';
}
- con = ast_context_find(parking_con_dial);
- if (!con) {
- con = ast_context_create(NULL, parking_con_dial, registrar);
- if (!con)
- ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", parking_con_dial);
- }
+ con = ast_context_find_or_create(NULL, NULL, parking_con_dial, registrar);
+ if (!con)
+ ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", parking_con_dial);
if (con) {
char returnexten[AST_MAX_EXTENSION];
snprintf(returnexten, sizeof(returnexten), "%s,,t", peername);
@@ -2804,7 +2799,7 @@
ast_debug(1, "Removed old parking extension %s@%s\n", old_parking_ext, old_parking_con);
}
- if (!(con = ast_context_find(parking_con)) && !(con = ast_context_create(NULL, parking_con, registrar))) {
+ if (!(con = ast_context_find_or_create(NULL, NULL, parking_con, registrar))) {
ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
return -1;
}
Modified: team/murf/bug6002/main/pbx.c
URL: http://svn.digium.com/view/asterisk/team/murf/bug6002/main/pbx.c?view=diff&rev=104973&r1=104972&r2=104973
==============================================================================
--- team/murf/bug6002/main/pbx.c (original)
+++ team/murf/bug6002/main/pbx.c Thu Feb 28 07:59:48 2008
@@ -140,8 +140,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 peer list -- 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 +203,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 +328,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 +378,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 +686,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 +1254,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,7 +1584,7 @@
{
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;
@@ -1599,8 +1601,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 +1670,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 +1692,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 +1752,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 +1788,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)) ) {
@@ -3527,10 +3529,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);
@@ -3625,7 +3627,7 @@
struct fake_context item;
strncpy(item.name, context, 256);
ast_rdlock_contexts();
- c = ast_hashtab_lookup(contexts_tree,&item);
+ c = ast_hashtab_lookup(contexts_table,&item);
#ifdef NOTNOW
@@ -3792,13 +3794,13 @@
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);
@@ -3812,24 +3814,24 @@
}
} 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 (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 */
@@ -3845,7 +3847,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
@@ -3902,10 +3904,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;
@@ -3943,7 +3945,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;
@@ -3981,7 +3983,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
@@ -5124,42 +5126,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;
}
}
@@ -5168,19 +5165,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);
@@ -5188,15 +5192,6 @@
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);
struct store_hint {
@@ -5210,17 +5205,87 @@
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 */
+
+ 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.
+ but, if this is because of some sort of registrar conflict, we ought to say something... */
+ res1 = ast_add_extension2(new, 0, prio_item->exten, prio_item->priority, prio_item->label,
+ prio_item->cidmatch, prio_item->app, prio_item->data, prio_item->datad, prio_item->registrar);
+
+ if (!res1 && new_exten_item && new_prio_item){
+ ast_log(LOG_NOTICE,"Dropping old dialplan item %s/%s/%d [%s(%s)] (registrar=%s) due to conflict with new dialplan\n",
+ context->name, prio_item->exten, prio_item->priority, prio_item->app, (char*)prio_item->data, prio_item->registrar);
+ } else {
+ insert_count++;
+ }
+ }
+ ast_hashtab_end_traversal(prio_iter);
+ }
+ ast_hashtab_end_traversal(exten_iter);
+
+ if (!insert_count && !new && (strcmp(context->registrar, registrar) != 0 ||
+ (strcmp(context->registrar, registrar) == 0 && context->refcount > 1))) {
+
+ /* we could have given it the registrar of the other module who incremented the refcount,
+ but that's not available, so we give it the registrar we know about */
+ new = ast_context_find_or_create(extcontexts, exttable, context->name, context->registrar);
+ }
+}
+
+
/* XXX this does not check that multiple contexts are merged */
-void ast_merge_contexts_and_delete(struct ast_context **extcontexts, const char *registrar)
-{
- struct ast_context *tmp, *lasttmp = NULL;
+void ast_merge_contexts_and_delete(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *registrar)
+{
+ struct ast_context *tmp, *oldcontextslist;
+ struct ast_hashtab *oldtable;
struct store_hints store = AST_LIST_HEAD_INIT_VALUE;
struct store_hint *this;
struct ast_hint *hint;
struct ast_exten *exten;
int length;
struct ast_state_cb *thiscb, *prevcb;
-
+ struct ast_hashtab_iter *iter;
+
/* 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
@@ -5229,6 +5294,14 @@
in addition, the locks _must_ be taken in this order, because there are already
other code paths that use this order
*/
+
+ ast_rdlock_contexts();
+ iter = ast_hashtab_start_traversal(contexts_table);
+ while ((tmp=ast_hashtab_next(iter))) {
+ context_merge(extcontexts, exttable, tmp, registrar);
+ }
+ ast_hashtab_end_traversal(iter);
+
ast_wrlock_contexts();
AST_RWLIST_WRLOCK(&hints);
@@ -5249,36 +5322,14 @@
}
}
- tmp = *extcontexts;
- if (registrar) {
- /* XXX remove previous contexts from same registrar */
- ast_debug(1, "must remove any reg %s\n", registrar);
- __ast_context_destroy(NULL,registrar);
- while (tmp) {
- lasttmp = tmp;
- tmp = tmp->next;
- }
- } else {
- /* XXX remove contexts with the same name */
- while (tmp) {
- ast_log(LOG_WARNING, "must remove %s reg %s\n", tmp->name, tmp->registrar);
- __ast_context_destroy(tmp,tmp->registrar);
- lasttmp = tmp;
- tmp = tmp->next;
- }
- }
- tmp = *extcontexts;
- while (tmp) {
- ast_hashtab_insert_safe(contexts_tree, tmp); /*put this context into the tree */
- tmp = tmp->next;
- }
- if (lasttmp) {
- lasttmp->next = contexts;
- contexts = *extcontexts;
- *extcontexts = NULL;
- } else
- ast_log(LOG_WARNING, "Requested contexts didn't get merged\n");
-
+ /* save the old table and list */
+ oldtable = contexts_table;
+ oldcontextslist = contexts;
+
+ /* move in the new table and list */
+ contexts_table = exttable;
+ contexts = *extcontexts;
+
/* restore the watchers for hints that can be found; notify those that
cannot be restored
*/
@@ -5313,7 +5364,18 @@
AST_RWLIST_UNLOCK(&hints);
ast_unlock_contexts();
-
+
+ /* 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;
+ }
return;
}
@@ -5977,9 +6039,9 @@
break;
}
if (!e) { /* go at the end, and ep is surely set because the list is not empty */
- ast_hashtab_insert_safe(eh->peer_tree, tmp);
+ ast_hashtab_insert_safe(eh->peer_table, tmp);
if (tmp->label)
- ast_hashtab_insert_safe(eh->peer_label_tree, tmp);
+ ast_hashtab_insert_safe(eh->peer_label_table, tmp);
ep->peer = tmp;
return 0; /* success */
}
@@ -5999,25 +6061,25 @@
tmp->next = e->next; /* not meaningful if we are not first in the peer list */
tmp->peer = e->peer; /* always meaningful */
if (ep) { /* We're in the peer list, just insert ourselves */
- ast_hashtab_remove_object_via_lookup(eh->peer_tree,e);
+ ast_hashtab_remove_object_via_lookup(eh->peer_table,e);
if (e->label)
- ast_hashtab_remove_object_via_lookup(eh->peer_label_tree,e);
- ast_hashtab_insert_safe(eh->peer_tree,tmp);
+ ast_hashtab_remove_object_via_lookup(eh->peer_label_table,e);
+ ast_hashtab_insert_safe(eh->peer_table,tmp);
if (tmp->label)
- ast_hashtab_insert_safe(eh->peer_label_tree,tmp);
+ ast_hashtab_insert_safe(eh->peer_label_table,tmp);
ep->peer = tmp;
} else if (el) { /* We're the first extension. Take over e's functions */
struct match_char *x = add_exten_to_pattern_tree(con, e, 1);
- tmp->peer_tree = e->peer_tree;
- tmp->peer_label_tree = e->peer_label_tree;
- ast_hashtab_remove_object_via_lookup(tmp->peer_tree,e);
- ast_hashtab_insert_safe(tmp->peer_tree,tmp);
+ tmp->peer_table = e->peer_table;
+ tmp->peer_label_table = e->peer_label_table;
+ ast_hashtab_remove_object_via_lookup(tmp->peer_table,e);
+ ast_hashtab_insert_safe(tmp->peer_table,tmp);
if (e->label)
- ast_hashtab_remove_object_via_lookup(tmp->peer_label_tree,e);
+ ast_hashtab_remove_object_via_lookup(tmp->peer_label_table,e);
if (tmp->label)
- ast_hashtab_insert_safe(tmp->peer_label_tree,tmp);
- ast_hashtab_remove_object_via_lookup(con->root_tree, e);
- ast_hashtab_insert_safe(con->root_tree, tmp);
+ ast_hashtab_insert_safe(tmp->peer_label_table,tmp);
+ ast_hashtab_remove_object_via_lookup(con->root_table, e);
+ ast_hashtab_insert_safe(con->root_table, tmp);
el->next = tmp;
/* The pattern trie points to this exten; replace the pointer,
and all will be well */
@@ -6029,18 +6091,18 @@
}
} else { /* We're the very first extension. */
struct match_char *x = add_exten_to_pattern_tree(con, e, 1);
- ast_hashtab_remove_object_via_lookup(con->root_tree,e);
- ast_hashtab_insert_safe(con->root_tree,tmp);
- tmp->peer_tree = e->peer_tree;
- tmp->peer_label_tree = e->peer_label_tree;
- ast_hashtab_remove_object_via_lookup(tmp->peer_tree,e);
- ast_hashtab_insert_safe(tmp->peer_tree,tmp);
+ ast_hashtab_remove_object_via_lookup(con->root_table,e);
+ ast_hashtab_insert_safe(con->root_table,tmp);
+ tmp->peer_table = e->peer_table;
+ tmp->peer_label_table = e->peer_label_table;
+ ast_hashtab_remove_object_via_lookup(tmp->peer_table,e);
+ ast_hashtab_insert_safe(tmp->peer_table,tmp);
if (e->label)
- ast_hashtab_remove_object_via_lookup(tmp->peer_label_tree,e);
+ ast_hashtab_remove_object_via_lookup(tmp->peer_label_table,e);
if (tmp->label)
- ast_hashtab_insert_safe(tmp->peer_label_tree,tmp);
- ast_hashtab_remove_object_via_lookup(con->root_tree, e);
- ast_hashtab_insert_safe(con->root_tree, tmp);
+ ast_hashtab_insert_safe(tmp->peer_label_table,tmp);
+ ast_hashtab_remove_object_via_lookup(con->root_table, e);
+ ast_hashtab_insert_safe(con->root_table, tmp);
con->root = tmp;
/* The pattern trie points to this exten; replace the pointer,
and all will be well */
@@ -6061,20 +6123,20 @@
tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */
if (ep) { /* Easy enough, we're just in the peer list */
if (tmp->label)
- ast_hashtab_insert_safe(eh->peer_label_tree, tmp);
- ast_hashtab_insert_safe(eh->peer_tree, tmp);
+ ast_hashtab_insert_safe(eh->peer_label_table, tmp);
+ ast_hashtab_insert_safe(eh->peer_table, tmp);
ep->peer = tmp;
} else { /* we are the first in some peer list, so link in the ext list */
- tmp->peer_tree = e->peer_tree;
- tmp->peer_label_tree = e ->peer_label_tree;
- e->peer_tree = 0;
- e->peer_label_tree = 0;
- ast_hashtab_insert_safe(tmp->peer_tree,tmp);
+ tmp->peer_table = e->peer_table;
+ tmp->peer_label_table = e ->peer_label_table;
+ e->peer_table = 0;
+ e->peer_label_table = 0;
+ ast_hashtab_insert_safe(tmp->peer_table,tmp);
if (tmp->label) {
- ast_hashtab_insert_safe(tmp->peer_label_tree,tmp);
- }
- ast_hashtab_remove_object_via_lookup(con->root_tree,e);
- ast_hashtab_insert_safe(con->root_tree,tmp);
+ ast_hashtab_insert_safe(tmp->peer_label_table,tmp);
+ }
+ ast_hashtab_remove_object_via_lookup(con->root_table,e);
+ ast_hashtab_insert_safe(con->root_table,tmp);
if (el)
el->next = tmp; /* in the middle... */
else
@@ -6189,11 +6251,11 @@
dummy_exten.exten = dummy_name;
dummy_exten.matchcid = 0;
dummy_exten.cidmatch = 0;
[... 3995 lines stripped ...]
More information about the svn-commits
mailing list