aboutsummaryrefslogtreecommitdiffstats
path: root/main/pbx.c
diff options
context:
space:
mode:
authormurf <murf@f38db490-d61c-443f-a65b-d21fe96a405b>2007-11-21 20:38:00 +0000
committermurf <murf@f38db490-d61c-443f-a65b-d21fe96a405b>2007-11-21 20:38:00 +0000
commita1c19a6b5c854f7f4682fd7856639a541a50c9a5 (patch)
treedcb3d663b129ff4b8b60c9722f832528bbcf29db /main/pbx.c
parent6177217d806447d7b1db9a5c1045ce1363164296 (diff)
closes issue #11290; the proposed patch was a good guess, and would solve the bug to some extent, but was really masking the real issue, that there were bad entries in the table. This fix removes the condition that the hashtab updates be done on exten removal only when the pattern_tree was present, which is silly. The operations that apply to the pattern tree are instead made conditional. Also, threw back in routines that kpfleming deleted because of probs in the 64-bit world. Tested on both 32 and 64-bit machines (compile). Tested the reload problem with over 20 reloads, and no problems. If you find more problems, please reopen 11290.
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@89505 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'main/pbx.c')
-rw-r--r--main/pbx.c136
1 files changed, 93 insertions, 43 deletions
diff --git a/main/pbx.c b/main/pbx.c
index d72607579..48f56fba0 100644
--- a/main/pbx.c
+++ b/main/pbx.c
@@ -316,9 +316,10 @@ static int pbx_builtin_saydigits(struct ast_channel *, void *);
static int pbx_builtin_saycharacters(struct ast_channel *, void *);
static int pbx_builtin_sayphonetic(struct ast_channel *, void *);
int pbx_builtin_setvar(struct ast_channel *, void *);
+void log_match_char_tree(struct match_char *node, char *prefix); /* for use anywhere */
static int pbx_builtin_setvar_multiple(struct ast_channel *, void *);
static int pbx_builtin_importvar(struct ast_channel *, void *);
-static void set_ext_pri(struct ast_channel *c, const char *exten, int pri);
+static void set_ext_pri(struct ast_channel *c, const char *exten, int pri);
static void new_find_extension(const char *str, struct scoreboard *score, struct match_char *tree, int length, int spec, const char *callerid);
static struct match_char *already_in_tree(struct match_char *current, char *pat);
static struct match_char *add_exten_to_pattern_tree(struct ast_context *con, struct ast_exten *e1, int findonly);
@@ -851,6 +852,48 @@ static void update_scoreboard(struct scoreboard *board, int length, int spec, st
}
}
+void log_match_char_tree(struct match_char *node, char *prefix)
+{
+ char my_prefix[1024];
+ char extenstr[40];
+
+ extenstr[0] = 0;
+ if (node && node->exten && node->exten)
+ sprintf(extenstr,"(%p)",node->exten);
+
+ if (strlen(node->x) > 1 )
+ ast_log(LOG_DEBUG,"%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y':'N', node->deleted? 'D':'-', node->specificity, node->exten? "EXTEN:":"", node->exten ? node->exten->exten : "", extenstr);
+ else
+ ast_log(LOG_DEBUG,"%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y':'N', node->deleted? 'D':'-', node->specificity, node->exten? "EXTEN:":"", node->exten ? node->exten->exten : "", extenstr);
+ strcpy(my_prefix,prefix);
+ strcat(my_prefix,"+ ");
+ if (node->next_char)
+ log_match_char_tree(node->next_char, my_prefix);
+ if (node->alt_char)
+ log_match_char_tree(node->alt_char, prefix);
+}
+
+static void cli_match_char_tree(struct match_char *node, char *prefix, int fd)
+{
+ char my_prefix[1024];
+ char extenstr[40];
+
+ extenstr[0] = 0;
+ if (node && node->exten && node->exten)
+ sprintf(extenstr,"(%p)",node->exten);
+
+ if (strlen(node->x) > 1)
+ ast_cli(fd, "%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y':'N', node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:":"", node->exten ? node->exten->exten : "", extenstr);
+ else
+ ast_cli(fd, "%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y':'N', node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:":"", node->exten ? node->exten->exten : "", extenstr);
+ strcpy(my_prefix,prefix);
+ strcat(my_prefix,"+ ");
+ if (node->next_char)
+ cli_match_char_tree(node->next_char, my_prefix, fd);
+ if (node->alt_char)
+ cli_match_char_tree(node->alt_char, prefix, fd);
+}
+
static struct ast_exten *get_canmatch_exten(struct match_char *node)
{
/* find the exten at the end of the rope */
@@ -3618,76 +3661,82 @@ int ast_context_remove_extension2(struct ast_context *con, const char *extension
{
struct ast_exten *exten, *prev_exten = NULL;
struct ast_exten *peer;
+ struct ast_exten ex, *exten2, *exten3;
+ char dummy_name[1024];
ast_wrlock_context(con);
/* Handle this is in the new world */
- if (con->pattern_tree) {
- struct ast_exten ex, *exten2, *exten3;
- char dummy_name[1024];
-
#ifdef NEED_DEBUG
- ast_log(LOG_NOTICE,"Removing %s/%s/%d from trees, registrar=%s\n", con->name, extension, priority, registrar);
+ ast_log(LOG_NOTICE,"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);
- if (exten) {
- if (priority == 0)
- {
- /* success, this exten is in this pattern tree. */
+ /* 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);
+ if (exten) {
+ if (priority == 0)
+ {
+ exten2 = ast_hashtab_remove_this_object(con->root_tree, 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);
+ if (con->pattern_tree) {
+
struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
+
if (x->exten) { /* this test for safety purposes */
x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
x->exten = 0; /* get rid of what will become a bad pointer */
- exten2 = ast_hashtab_remove_this_object(con->root_tree, exten);
} else {
ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n");
}
- } else {
- ex.priority = priority;
- exten2 = ast_hashtab_lookup(exten->peer_tree, &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);
- 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);
- }
-
- exten3 = ast_hashtab_remove_this_object(exten->peer_tree, exten2);
+ }
+ } else {
+ ex.priority = priority;
+ exten2 = ast_hashtab_lookup(exten->peer_tree, &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);
+ 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);
+ }
+
+ exten3 = ast_hashtab_remove_this_object(exten->peer_tree, 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) {
+ /* 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);
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) {
- /* well, if the last priority of an exten is to be removed,
- then, the extension is removed, too! */
+ ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_tree (%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 */
x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
x->exten = 0; /* get rid of what will become a bad pointer */
- exten3 = ast_hashtab_remove_this_object(con->root_tree, 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);
}
}
- } else {
- ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n",
- priority, exten->exten, con->name);
}
+ } else {
+ ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n",
+ priority, exten->exten, con->name);
}
- } else {
- /* hmmm? this exten is not in this pattern tree? */
- ast_log(LOG_WARNING,"Cannot find extension %s in pattern tree in context %s\n",
- extension, con->name);
}
+ } 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",
+ extension, con->name);
+ }
#ifdef NEED_DEBUG
+ if (con->pattern_tree) {
ast_log(LOG_NOTICE,"match char tree after exten removal:\n");
log_match_char_tree(con->pattern_tree, " ");
-#endif
}
+#endif
/* scan the extension list to find matching extension-registrar */
@@ -4389,6 +4438,7 @@ static int show_dialplan_helper(int fd, const char *context, const char *exten,
ast_cli(fd, " [matched exten]: If all chars matched to this point, which extension this matches. In form: EXTEN:<exten string> \r\n");
ast_cli(fd, " In general, you match a trie node to a string character, from left to right. All possible matching chars\r\n");
ast_cli(fd, " are in a string vertically, separated by an unbroken string of '+' characters.\r\n\r\n");
+ cli_match_char_tree(c->pattern_tree, " ", fd);
}
ast_unlock_context(c);