mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-22 20:56:39 +00:00
This commits the performance mods that give the priority processing engine in the pbx, a 25-30% speed boost. The two updates used, are, first, to merge the ast_exists_extension() and the ast_spawn_extension() where they are called sequentially in a loop in the code, into a slightly upgraded version of ast_spawn_extension(), with a few extra args; and, second, I modified the substitute_variables_helper_full, so it zeroes out the byte after the evaluated string instead of demanding you pre-zero the buffer; I also went thru the code and removed the code that zeroed this buffer before every call to the substitute_variables_helper_full. The first fix provides about a 9% speedup, and the second the rest. These figures come from the 'PIPS' benchmark I describe in blogs, conf. reports, etc.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@88166 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -505,7 +505,7 @@ static int rotate_file(const char *filename)
|
||||
|
||||
if (!ast_strlen_zero(exec_after_rotate)) {
|
||||
struct ast_channel *c = ast_channel_alloc(0, 0, "", "", "", "", "", 0, "Logger/rotate");
|
||||
char buf[512] = "";
|
||||
char buf[512];
|
||||
pbx_builtin_setvar_helper(c, "filename", filename);
|
||||
pbx_substitute_variables_helper(c, exec_after_rotate, buf, sizeof(buf));
|
||||
system(buf);
|
||||
|
145
main/pbx.c
145
main/pbx.c
@@ -1618,8 +1618,7 @@ int ast_func_write(struct ast_channel *chan, const char *function, const char *v
|
||||
|
||||
static void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count)
|
||||
{
|
||||
/* Substitutes variables into cp2, based on string cp1, and assuming cp2 to be
|
||||
zero-filled */
|
||||
/* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!! */
|
||||
char *cp4;
|
||||
const char *tmp, *whereweare;
|
||||
int length, offset, offset2, isfunction;
|
||||
@@ -1628,7 +1627,8 @@ static void pbx_substitute_variables_helper_full(struct ast_channel *c, struct v
|
||||
char *nextvar, *nextexp, *nextthing;
|
||||
char *vars, *vare;
|
||||
int pos, brackets, needsub, len;
|
||||
|
||||
|
||||
*cp2 = 0; /* just in case nothing ends up there */
|
||||
whereweare=tmp=cp1;
|
||||
while (!ast_strlen_zero(whereweare) && count) {
|
||||
/* Assume we're copying the whole remaining string */
|
||||
@@ -1662,6 +1662,7 @@ static void pbx_substitute_variables_helper_full(struct ast_channel *c, struct v
|
||||
count -= pos;
|
||||
cp2 += pos;
|
||||
whereweare += pos;
|
||||
*cp2 = 0;
|
||||
}
|
||||
|
||||
if (nextvar) {
|
||||
@@ -1702,7 +1703,6 @@ static void pbx_substitute_variables_helper_full(struct ast_channel *c, struct v
|
||||
if (!ltmp)
|
||||
ltmp = alloca(VAR_BUF_SIZE);
|
||||
|
||||
memset(ltmp, 0, VAR_BUF_SIZE);
|
||||
pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1);
|
||||
vars = ltmp;
|
||||
} else {
|
||||
@@ -1746,6 +1746,7 @@ static void pbx_substitute_variables_helper_full(struct ast_channel *c, struct v
|
||||
memcpy(cp2, cp4, length);
|
||||
count -= length;
|
||||
cp2 += length;
|
||||
*cp2 = 0;
|
||||
}
|
||||
} else if (nextexp) {
|
||||
/* We have an expression. Find the start and end, and determine
|
||||
@@ -1789,7 +1790,6 @@ static void pbx_substitute_variables_helper_full(struct ast_channel *c, struct v
|
||||
if (!ltmp)
|
||||
ltmp = alloca(VAR_BUF_SIZE);
|
||||
|
||||
memset(ltmp, 0, VAR_BUF_SIZE);
|
||||
pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1);
|
||||
vars = ltmp;
|
||||
} else {
|
||||
@@ -1802,6 +1802,7 @@ static void pbx_substitute_variables_helper_full(struct ast_channel *c, struct v
|
||||
ast_debug(1, "Expression result is '%s'\n", cp2);
|
||||
count -= length;
|
||||
cp2 += length;
|
||||
*cp2 = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1820,7 +1821,6 @@ void pbx_substitute_variables_varshead(struct varshead *headp, const char *cp1,
|
||||
static void pbx_substitute_variables(char *passdata, int datalen, struct ast_channel *c, struct ast_exten *e)
|
||||
{
|
||||
const char *tmp;
|
||||
memset(passdata, 0, datalen);
|
||||
|
||||
/* Nothing more to do */
|
||||
if (!e->data)
|
||||
@@ -1847,8 +1847,8 @@ static void pbx_substitute_variables(char *passdata, int datalen, struct ast_cha
|
||||
* \retval -1 on failure.
|
||||
*/
|
||||
static int pbx_extension_helper(struct ast_channel *c, struct ast_context *con,
|
||||
const char *context, const char *exten, int priority,
|
||||
const char *label, const char *callerid, enum ext_match_t action)
|
||||
const char *context, const char *exten, int priority,
|
||||
const char *label, const char *callerid, enum ext_match_t action, int *found, int combined_find_spawn)
|
||||
{
|
||||
struct ast_exten *e;
|
||||
struct ast_app *app;
|
||||
@@ -1857,10 +1857,14 @@ static int pbx_extension_helper(struct ast_channel *c, struct ast_context *con,
|
||||
char passdata[EXT_DATA_SIZE];
|
||||
|
||||
int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE);
|
||||
|
||||
|
||||
ast_rdlock_contexts();
|
||||
if (found)
|
||||
*found = 0;
|
||||
e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action);
|
||||
if (e) {
|
||||
if (found)
|
||||
*found = 1;
|
||||
if (matching_action) {
|
||||
ast_unlock_contexts();
|
||||
return -1; /* success, we found it */
|
||||
@@ -1927,19 +1931,19 @@ static int pbx_extension_helper(struct ast_channel *c, struct ast_context *con,
|
||||
ast_unlock_contexts();
|
||||
switch (q.status) {
|
||||
case STATUS_NO_CONTEXT:
|
||||
if (!matching_action)
|
||||
if (!matching_action && !combined_find_spawn)
|
||||
ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", context);
|
||||
break;
|
||||
case STATUS_NO_EXTENSION:
|
||||
if (!matching_action)
|
||||
if (!matching_action && !combined_find_spawn)
|
||||
ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, context);
|
||||
break;
|
||||
case STATUS_NO_PRIORITY:
|
||||
if (!matching_action)
|
||||
if (!matching_action && !combined_find_spawn)
|
||||
ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, context);
|
||||
break;
|
||||
case STATUS_NO_LABEL:
|
||||
if (context)
|
||||
if (context && !combined_find_spawn)
|
||||
ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, context);
|
||||
break;
|
||||
default:
|
||||
@@ -2376,32 +2380,32 @@ int ast_get_hint(char *hint, int hintsize, char *name, int namesize, struct ast_
|
||||
|
||||
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
|
||||
{
|
||||
return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH);
|
||||
return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0);
|
||||
}
|
||||
|
||||
int ast_findlabel_extension(struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid)
|
||||
{
|
||||
return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL);
|
||||
return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
|
||||
}
|
||||
|
||||
int ast_findlabel_extension2(struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid)
|
||||
{
|
||||
return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL);
|
||||
return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
|
||||
}
|
||||
|
||||
int ast_canmatch_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
|
||||
{
|
||||
return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH);
|
||||
return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0);
|
||||
}
|
||||
|
||||
int ast_matchmore_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
|
||||
{
|
||||
return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE);
|
||||
return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0);
|
||||
}
|
||||
|
||||
int ast_spawn_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
|
||||
int ast_spawn_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid, int *found, int combined_find_spawn)
|
||||
{
|
||||
return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN);
|
||||
return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn);
|
||||
}
|
||||
|
||||
/*! helper function to set extension and priority */
|
||||
@@ -2498,50 +2502,7 @@ static int __ast_pbx_run(struct ast_channel *c)
|
||||
int digit = 0;
|
||||
|
||||
/* loop on priorities in this context/exten */
|
||||
while (ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
|
||||
found = 1;
|
||||
if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num))) {
|
||||
/* Something bad happened, or a hangup has been requested. */
|
||||
if (strchr("0123456789ABCDEF*#", res)) {
|
||||
ast_debug(1, "Oooh, got something to jump out with ('%c')!\n", res);
|
||||
pos = 0;
|
||||
dst_exten[pos++] = digit = res;
|
||||
dst_exten[pos] = '\0';
|
||||
break;
|
||||
}
|
||||
if (res == AST_PBX_KEEPALIVE) {
|
||||
ast_debug(1, "Spawn extension (%s,%s,%d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
|
||||
ast_verb(2, "Spawn extension (%s, %s, %d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
|
||||
ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
|
||||
|
||||
if ((res == AST_PBX_ERROR) && ast_exists_extension(c, c->context, "e", 1, c->cid.cid_num)) {
|
||||
/* if we are already on the 'e' exten, don't jump to it again */
|
||||
if (!strcmp(c->exten, "e")) {
|
||||
if (option_verbose > 1)
|
||||
ast_verbose(VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited ERROR while already on 'e' exten on '%s'\n", c->context, c->exten, c->priority, c->name);
|
||||
error = 1;
|
||||
break;
|
||||
} else {
|
||||
pbx_builtin_raise_exception(c, "ERROR");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
|
||||
c->_softhangup = 0;
|
||||
} else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
|
||||
/* atimeout, nothing bad */
|
||||
} else {
|
||||
if (c->cdr)
|
||||
ast_cdr_update(c);
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
while ( !(res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num, &found,1))) {
|
||||
if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT && ast_exists_extension(c, c->context, "T", 1, c->cid.cid_num)) {
|
||||
set_ext_pri(c, "T", 0); /* 0 will become 1 with the c->priority++; at the end */
|
||||
/* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
|
||||
@@ -2560,6 +2521,45 @@ static int __ast_pbx_run(struct ast_channel *c)
|
||||
}
|
||||
c->priority++;
|
||||
} /* end while - from here on we can use 'break' to go out */
|
||||
if (found && res) {
|
||||
/* Something bad happened, or a hangup has been requested. */
|
||||
if (strchr("0123456789ABCDEF*#", res)) {
|
||||
ast_debug(1, "Oooh, got something to jump out with ('%c')!\n", res);
|
||||
pos = 0;
|
||||
dst_exten[pos++] = digit = res;
|
||||
dst_exten[pos] = '\0';
|
||||
}
|
||||
if (res == AST_PBX_KEEPALIVE) {
|
||||
ast_debug(1, "Spawn extension (%s,%s,%d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
|
||||
ast_verb(2, "Spawn extension (%s, %s, %d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
|
||||
error = 1;
|
||||
}
|
||||
ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
|
||||
ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
|
||||
|
||||
if ((res == AST_PBX_ERROR) && ast_exists_extension(c, c->context, "e", 1, c->cid.cid_num)) {
|
||||
/* if we are already on the 'e' exten, don't jump to it again */
|
||||
if (!strcmp(c->exten, "e")) {
|
||||
if (option_verbose > 1)
|
||||
ast_verbose(VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited ERROR while already on 'e' exten on '%s'\n", c->context, c->exten, c->priority, c->name);
|
||||
error = 1;
|
||||
} else {
|
||||
pbx_builtin_raise_exception(c, "ERROR");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
|
||||
c->_softhangup = 0;
|
||||
} else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
|
||||
/* atimeout, nothing bad */
|
||||
} else {
|
||||
if (c->cdr)
|
||||
ast_cdr_update(c);
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (error)
|
||||
break;
|
||||
|
||||
@@ -2657,15 +2657,14 @@ static int __ast_pbx_run(struct ast_channel *c)
|
||||
if (c->cdr && ast_opt_end_cdr_before_h_exten)
|
||||
ast_cdr_end(c->cdr);
|
||||
set_ext_pri(c, "h", 1);
|
||||
while (ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
|
||||
if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num))) {
|
||||
/* Something bad happened, or a hangup has been requested. */
|
||||
ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
|
||||
ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
|
||||
break;
|
||||
}
|
||||
while ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num, &found,1))) {
|
||||
c->priority++;
|
||||
}
|
||||
if (found && res) {
|
||||
/* Something bad happened, or a hangup has been requested. */
|
||||
ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
|
||||
ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
|
||||
}
|
||||
}
|
||||
ast_set2_flag(c, autoloopflag, AST_FLAG_IN_AUTOLOOP);
|
||||
|
||||
@@ -4930,7 +4929,7 @@ int ast_add_extension2(struct ast_context *con,
|
||||
int res;
|
||||
int length;
|
||||
char *p;
|
||||
char expand_buf[VAR_BUF_SIZE] = { 0, };
|
||||
char expand_buf[VAR_BUF_SIZE];
|
||||
|
||||
/* if we are adding a hint, and there are global variables, and the hint
|
||||
contains variable references, then expand them
|
||||
@@ -6078,7 +6077,7 @@ int pbx_builtin_importvar(struct ast_channel *chan, void *data)
|
||||
char *name;
|
||||
char *value;
|
||||
char *channel;
|
||||
char tmp[VAR_BUF_SIZE]="";
|
||||
char tmp[VAR_BUF_SIZE];
|
||||
static int deprecation_warning = 0;
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
|
Reference in New Issue
Block a user