summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
authorSteve Murphy <murf@digium.com>2007-11-21 01:09:47 +0000
committerSteve Murphy <murf@digium.com>2007-11-21 01:09:47 +0000
commit8e90425a6c67a22ceafc1326271a28acb33c7a41 (patch)
tree069a1cd5b6dfdc42a5abea8c99faa0ae010c7077 /main
parent04e1e0069f88f3b7de517af4bc7e6eff15243c74 (diff)
A free in add_pri was ultimately the source of the grief we were having with parking. This set of changes fixes that problem, and introduces some more error messages, and puts debugs into ifdefs for what could be short-term usage. Txs to Terry W. for his help, guidance, and especially patience.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@89474 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main')
-rw-r--r--main/pbx.c99
1 files changed, 78 insertions, 21 deletions
diff --git a/main/pbx.c b/main/pbx.c
index 62994c7f8..a61d90792 100644
--- a/main/pbx.c
+++ b/main/pbx.c
@@ -324,6 +324,7 @@ struct match_char *already_in_tree(struct match_char *current, char *pat);
struct match_char *add_exten_to_pattern_tree(struct ast_context *con, struct ast_exten *e1, int findonly);
struct match_char *add_pattern_node(struct ast_context *con, struct match_char *current, char *pattern, int is_pattern, int already, int specificity);
void create_match_char_tree(struct ast_context *con);
+void log_match_char_tree(struct match_char *node, char *prefix);
struct ast_exten *get_canmatch_exten(struct match_char *node);
void destroy_pattern_tree(struct match_char *pattern_tree);
static int hashtab_compare_contexts(const void *ah_a, const void *ah_b);
@@ -851,28 +852,40 @@ static void update_scoreboard(struct scoreboard *board, int length, int spec, st
}
}
-#ifdef NEED_DEBUG
-static void log_match_char_tree(struct match_char *node, char *prefix)
+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,"(%x)",(unsigned int)node->exten);
- ast_log(LOG_DEBUG,"%s%s:%c:%d:%s\n", prefix, node->x, node->is_pattern ? 'Y':'N', node->specificity, node->exten? "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)
- print_match_char_tree(node->next_char, my_prefix);
+ log_match_char_tree(node->next_char, my_prefix);
if (node->alt_char)
- print_match_char_tree(node->alt_char, prefix);
+ log_match_char_tree(node->alt_char, prefix);
}
-#endif
static void cli_match_char_tree(struct match_char *node, char *prefix, int fd)
{
char my_prefix[1024];
- if (strlen(node->x) > 1 )
- ast_cli(fd, "%s[%s]:%c:%d:%s%s\n", prefix, node->x, node->is_pattern ? 'Y':'N', node->specificity, node->exten? "EXTEN:":"", node->exten ? node->exten->exten : "");
+ char extenstr[40];
+
+ extenstr[0] = 0;
+ if (node && node->exten && node->exten)
+ sprintf(extenstr,"(%x)",(unsigned int)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:%d:%s%s\n", prefix, node->x, node->is_pattern ? 'Y':'N', node->specificity, node->exten? "EXTEN:":"", node->exten ? node->exten->exten : "");
+ 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)
@@ -1153,9 +1166,11 @@ struct match_char *add_exten_to_pattern_tree(struct ast_context *con, struct ast
}
m2 = 0;
if (already && (m2=already_in_tree(m1,buf)) && m2->next_char) {
- if (!(*(s1+1))) /* if this is the end of the pattern, but not the end of the tree, then mark this node with the exten...
+ if (!(*(s1+1))) { /* if this is the end of the pattern, but not the end of the tree, then mark this node with the exten...
a shorter pattern might win if the longer one doesn't match */
m2->exten = e1;
+ m2->deleted = 0;
+ }
m1 = m2->next_char; /* m1 points to the node to compare against */
} else {
if (m2) {
@@ -1168,8 +1183,11 @@ struct match_char *add_exten_to_pattern_tree(struct ast_context *con, struct ast
m1 = add_pattern_node(con, m1, buf, pattern, already,specif); /* m1 is the node just added */
}
- if (!(*(s1+1)))
+ if (!(*(s1+1))) {
+ m1->deleted = 0;
m1->exten = e1;
+ }
+
already = 0;
}
s1++; /* advance to next char */
@@ -1565,7 +1583,9 @@ struct ast_exten *pbx_find_extension(struct ast_channel *chan,
pattern.label = label;
pattern.priority = priority;
-
+#ifdef NEED_DEBUG
+ ast_log(LOG_NOTICE,"Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int)action);
+#endif
/* Initialize status if appropriate */
if (q->stacklen == 0) {
q->status = STATUS_NO_CONTEXT;
@@ -1615,10 +1635,13 @@ struct ast_exten *pbx_find_extension(struct ast_channel *chan,
create_match_char_tree(tmp);
#ifdef NEED_DEBUG
ast_log(LOG_DEBUG,"Tree Created in context %s:\n", context);
- print_match_char_tree(tmp->pattern_tree," ");
+ log_match_char_tree(tmp->pattern_tree," ");
#endif
}
-
+#ifdef NEED_DEBUG
+ ast_log(LOG_NOTICE,"The Trie we are searching in:\n");
+ log_match_char_tree(tmp->pattern_tree, ":: ");
+#endif
new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid);
eroot = score.exten;
@@ -3647,9 +3670,13 @@ int ast_context_remove_extension2(struct ast_context *con, const char *extension
/* Handle this is in the new world */
if (con->pattern_tree) {
- /* find this particular extension */
- struct ast_exten ex, *exten2;
+ 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);
+#endif
+ /* find this particular extension */
ex.exten = dummy_name;
ex.matchcid = 0;
ast_copy_string(dummy_name,extension, sizeof(dummy_name));
@@ -3662,7 +3689,7 @@ int ast_context_remove_extension2(struct ast_context *con, const char *extension
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 */
- ast_hashtab_remove_this_object(con->root_tree, exten);
+ 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");
}
@@ -3670,9 +3697,16 @@ int ast_context_remove_extension2(struct ast_context *con, const char *extension
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 */
- ast_hashtab_remove_this_object(exten->peer_label_tree,exten2);
- ast_hashtab_remove_this_object(exten->peer_tree, 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! */
@@ -3680,7 +3714,9 @@ int ast_context_remove_extension2(struct ast_context *con, const char *extension
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 */
- ast_hashtab_remove_this_object(con->root_tree, exten);
+ 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 {
@@ -3693,6 +3729,10 @@ int ast_context_remove_extension2(struct ast_context *con, const char *extension
ast_log(LOG_WARNING,"Cannot find extension %s in pattern tree in context %s\n",
extension, con->name);
}
+#ifdef NEED_DEBUG
+ ast_log(LOG_NOTICE,"match char tree after exten removal:\n");
+ log_match_char_tree(con->pattern_tree, " ");
+#endif
}
@@ -5666,6 +5706,7 @@ static int add_pri(struct ast_context *con, struct ast_exten *tmp,
ast_hashtab_insert_safe(eh->peer_label_tree,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);
@@ -5677,7 +5718,16 @@ static int add_pri(struct ast_context *con, struct ast_exten *tmp,
ast_hashtab_remove_object_via_lookup(con->root_tree, e);
ast_hashtab_insert_safe(con->root_tree, tmp);
el->next = tmp;
+ /* The pattern trie points to this exten; replace the pointer,
+ and all will be well */
+
+ if (x->exten) { /* this test for safety purposes */
+ x->exten = tmp; /* replace what would become a bad pointer */
+ } else {
+ ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n");
+ }
} 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;
@@ -5691,6 +5741,13 @@ static int add_pri(struct ast_context *con, struct ast_exten *tmp,
ast_hashtab_remove_object_via_lookup(con->root_tree, e);
ast_hashtab_insert_safe(con->root_tree, tmp);
con->root = tmp;
+ /* The pattern trie points to this exten; replace the pointer,
+ and all will be well */
+ if (x->exten) { /* this test for safety purposes */
+ x->exten = tmp; /* replace what would become a bad pointer */
+ } else {
+ ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n");
+ }
}
if (tmp->priority == PRIORITY_HINT)
ast_change_hint(e,tmp);