Skip to content

Commit 35bb59e

Browse files
committed
Migrate from index to references when pointing to a script route
The idx are hard to work with in the context of script reload, as they cannot be upated or checked (if still valid). So, instead of pointing to the route by its idx, use an intermediary structure that holds: name of the route, the idx of the route, the version of the script. Now, such intermediary structs (or route refs) may operate in 2 ways: * they are per process, in pkg; all such refs are linked in a single list and automatically updated (their idx) upon reload. * they are shared (like attached to data structs in shm), in shm; if so, before using it, the version is checked, and if old, the idx is updated on spot.
1 parent 63309e5 commit 35bb59e

13 files changed

+351
-171
lines changed

action.c

+12-9
Original file line numberDiff line numberDiff line change
@@ -1058,13 +1058,13 @@ int do_action(struct action* a, struct sip_msg* msg)
10581058
break;
10591059
case ASYNC_T:
10601060
/* first param - an ACTIONS_ST containing an ACMD_ST
1061-
* second param - a NUMBER_ST pointing to resume route
1061+
* second param - a ROUTE_REF_ST pointing to resume route
10621062
* third param - an optional NUMBER_ST with a timeout */
10631063
aitem = (struct action *)(a->elem[0].u.data);
10641064
acmd = (const acmd_export_t *)aitem->elem[0].u.data_const;
10651065

10661066
if (async_script_start_f==NULL || a->elem[0].type!=ACTIONS_ST ||
1067-
a->elem[1].type!=NUMBER_ST || aitem->type!=AMODULE_T) {
1067+
a->elem[1].type!=ROUTE_REF_ST || aitem->type!=AMODULE_T) {
10681068
LM_ALERT("BUG in async expression "
10691069
"(is the 'tm' module loaded?)\n");
10701070
} else {
@@ -1077,7 +1077,8 @@ int do_action(struct action* a, struct sip_msg* msg)
10771077
break;
10781078
}
10791079

1080-
ret = async_script_start_f(msg, aitem, a->elem[1].u.number,
1080+
ret = async_script_start_f(msg, aitem,
1081+
(struct script_route_ref*)a->elem[1].u.data,
10811082
(unsigned int)a->elem[2].u.number, cmdp);
10821083
if (ret>=0)
10831084
action_flags |= ACT_FL_TBCONT;
@@ -1092,17 +1093,17 @@ int do_action(struct action* a, struct sip_msg* msg)
10921093
break;
10931094
case LAUNCH_T:
10941095
/* first param - an ACTIONS_ST containing an ACMD_ST
1095-
* second param - an optional NUMBER_ST pointing to an end route */
1096+
* second param - an optional ROUTE_REF_ST pointing to an end route */
10961097
aitem = (struct action *)(a->elem[0].u.data);
10971098
acmd = (const acmd_export_t *)aitem->elem[0].u.data_const;
10981099

10991100
if (async_script_start_f==NULL || a->elem[0].type!=ACTIONS_ST ||
1100-
a->elem[1].type!=NUMBER_ST || aitem->type!=AMODULE_T) {
1101+
a->elem[1].type!=ROUTE_REF_ST || aitem->type!=AMODULE_T) {
11011102
LM_ALERT("BUG in launch expression\n");
11021103
} else {
11031104
script_trace("launch", acmd->name, msg, a->file, a->line);
1104-
/* NOTE that the routeID (a->elem[1].u.number) is set to
1105-
* -1 if no reporting route is set */
1105+
/* NOTE that the routeID (a->elem[1].u.data) is set to
1106+
* NULL if no reporting route is set */
11061107

11071108
if ((ret = get_cmd_fixups(msg, acmd->params, aitem->elem,
11081109
cmdp, tmp_vals)) < 0) {
@@ -1117,10 +1118,12 @@ int do_action(struct action* a, struct sip_msg* msg)
11171118
break;
11181119
}
11191120

1120-
ret = async_script_launch( msg, aitem, a->elem[1].u.number,
1121+
ret = async_script_launch( msg, aitem,
1122+
(struct script_route_ref*)a->elem[1].u.data,
11211123
&sval, cmdp);
11221124
} else {
1123-
ret = async_script_launch( msg, aitem, a->elem[1].u.number,
1125+
ret = async_script_launch( msg, aitem,
1126+
(struct script_route_ref*)a->elem[1].u.data,
11241127
NULL, cmdp);
11251128
}
11261129

async.c

+20-10
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ async_script_resume_function *async_script_resume_f = NULL;
4545
typedef struct _async_launch_ctx {
4646
/* generic async context - MUST BE FIRST */
4747
async_ctx async;
48-
/* the ID of the report script route (-1 if none) */
49-
int report_route;
48+
/* ref to the report script route (NULL if none) */
49+
struct script_route_ref *report_route;
5050
str report_route_param;
5151
} async_launch_ctx;
5252

@@ -240,18 +240,18 @@ int async_launch_resume(int fd, void *param)
240240
if (async_status == ASYNC_DONE_CLOSE_FD)
241241
close(fd);
242242

243-
if (ctx->report_route!=-1) {
243+
if (ref_script_route_check_and_update(ctx->report_route)) {
244244
LM_DBG("runinng report route for a launch job,"
245245
" route <%s>, param [%.*s]\n",
246-
sroutes->request[ctx->report_route].name,
246+
ctx->report_route->name.s,
247247
ctx->report_route_param.len, ctx->report_route_param.s);
248248
if (ctx->report_route_param.s)
249249
route_params_push_level(
250-
sroutes->request[ctx->report_route].name,
250+
sroutes->request[ctx->report_route->idx].name,
251251
&ctx->report_route_param, NULL,
252252
launch_route_param_get);
253253
swap_route_type( bk_rt, REQUEST_ROUTE);
254-
run_top_route( sroutes->request[ctx->report_route], req);
254+
run_top_route( sroutes->request[ctx->report_route->idx], req);
255255
set_route_type( bk_rt );
256256
if (ctx->report_route_param.s)
257257
route_params_pop_level();
@@ -261,6 +261,8 @@ int async_launch_resume(int fd, void *param)
261261
}
262262

263263
/* no need for the context anymore */
264+
if (ctx->report_route)
265+
shm_free(ctx->report_route);
264266
shm_free(ctx);
265267
LM_DBG("done with a launch job\n");
266268

@@ -273,7 +275,8 @@ int async_launch_resume(int fd, void *param)
273275

274276

275277
int async_script_launch(struct sip_msg *msg, struct action* a,
276-
int report_route, str *report_route_param, void **params)
278+
struct script_route_ref *report_route,
279+
str *report_route_param, void **params)
277280
{
278281
struct sip_msg *req;
279282
struct usr_avp *report_avps = NULL, **bak_avps = NULL;
@@ -331,7 +334,12 @@ int async_script_launch(struct sip_msg *msg, struct action* a,
331334
}
332335

333336
/* ctx is to be used from this point further */
334-
ctx->report_route = report_route;
337+
338+
ctx->report_route = dup_ref_script_route_in_shm( report_route, 0);
339+
if (!ref_script_route_is_valid(ctx->report_route)) {
340+
LM_ERR("failed dup resume route -> act in sync mode\n");
341+
goto sync;
342+
}
335343

336344
if (report_route_param) {
337345
ctx->report_route_param.s = (char *)(ctx+1);
@@ -366,8 +374,10 @@ int async_script_launch(struct sip_msg *msg, struct action* a,
366374
} while(async_status==ASYNC_CONTINUE||async_status==ASYNC_CHANGE_FD);
367375
/* the IO completed, so report now */
368376
report:
377+
if (ctx->report_route)
378+
shm_free(ctx->report_route);
369379
shm_free(ctx);
370-
if (report_route==-1)
380+
if (report_route==NULL)
371381
return 1;
372382

373383
/* run the report route inline */
@@ -380,7 +390,7 @@ int async_script_launch(struct sip_msg *msg, struct action* a,
380390
bak_avps = set_avp_list(&report_avps);
381391
swap_route_type( bk_rt, REQUEST_ROUTE);
382392

383-
run_top_route( sroutes->request[report_route], req);
393+
run_top_route( sroutes->request[report_route->idx], req);
384394

385395
set_route_type( bk_rt );
386396
destroy_avp_list(&report_avps);

async.h

+5-2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#ifndef _ASYNC_H_
2828
#define _ASYNC_H_
2929

30+
#include "route.h"
3031
#include "route_struct.h"
3132
#include "parser/msg_parser.h"
3233

@@ -74,7 +75,8 @@ extern int async_status;
7475
-1 some error happened and the async call did not happened.
7576
*/
7677
typedef int (async_script_start_function)
77-
(struct sip_msg *msg, struct action* a , int resume_route,
78+
(struct sip_msg *msg, struct action* a,
79+
struct script_route_ref *resume_route,
7880
unsigned int timeout, void **params);
7981

8082
/* Handles periodic progress (data arrival) on behalf of the contained,
@@ -140,7 +142,8 @@ int async_fd_resume(int fd, void *param);
140142
/******** functions related to async launch *******/
141143

142144
int async_script_launch(struct sip_msg *msg, struct action* a,
143-
int report_route, str *report_route_param, void **params);
145+
struct script_route_ref *report_route,
146+
str *report_route_param, void **params);
144147

145148
/* @fd is always valid */
146149
int async_launch_resume(int fd, void *param);

cfg.y

+23-18
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ static pv_spec_t *spec;
141141
static pv_elem_t *elem;
142142
static struct bl_rule *bl_head = 0;
143143
static struct bl_rule *bl_tail = 0;
144+
static struct script_route_ref *rt_ref = NULL;
144145

145146
action_elem_t elems[MAX_ACTION_ELEMS];
146147
static action_elem_t route_elems[MAX_ACTION_ELEMS];
@@ -2474,32 +2475,36 @@ cmd: ASSERT LPAREN exp COMMA STRING RPAREN {
24742475
| XLOG LPAREN STRING COMMA folded_string RPAREN {
24752476
mk_action2($$, XLOG_T, STR_ST, STR_ST, $3, $5); }
24762477
| ASYNC_TOKEN LPAREN async_func COMMA route_name RPAREN {
2477-
i_tmp = get_script_route_idx( $5, sroutes->request, RT_NO, 0);
2478-
if (i_tmp==-1) yyerror("too many script routes");
2479-
mk_action2($$, ASYNC_T, ACTIONS_ST, NUMBER_ST,
2480-
$3, (void*)(long)i_tmp);
2478+
rt_ref = ref_script_route_by_name( $5, sroutes->request,
2479+
RT_NO, REQUEST_ROUTE, 0);
2480+
if (rt_ref==NULL) yyerror("fail to create route reference");
2481+
mk_action2($$, ASYNC_T, ACTIONS_ST, ROUTE_REF_ST,
2482+
$3, (void*)rt_ref);
24812483
}
24822484
| ASYNC_TOKEN LPAREN async_func COMMA route_name COMMA NUMBER RPAREN {
2483-
i_tmp = get_script_route_idx( $5, sroutes->request, RT_NO, 0);
2484-
if (i_tmp==-1) yyerror("too many script routes");
2485-
mk_action3($$, ASYNC_T, ACTIONS_ST, NUMBER_ST, NUMBER_ST,
2486-
$3, (void*)(long)i_tmp, (void*)(long)$7);
2485+
rt_ref = ref_script_route_by_name( $5, sroutes->request,
2486+
RT_NO, REQUEST_ROUTE, 0);
2487+
if (rt_ref==NULL) yyerror("fail to create route reference");
2488+
mk_action3($$, ASYNC_T, ACTIONS_ST, ROUTE_REF_ST, NUMBER_ST,
2489+
$3, (void*)rt_ref, (void*)(long)$7);
24872490
}
24882491
| LAUNCH_TOKEN LPAREN async_func COMMA route_name COMMA STRING RPAREN {
2489-
i_tmp = get_script_route_idx( $5, sroutes->request, RT_NO, 0);
2490-
if (i_tmp==-1) yyerror("too many script routes");
2491-
mk_action3($$, LAUNCH_T, ACTIONS_ST, NUMBER_ST, STRING_ST,
2492-
$3, (void*)(long)i_tmp, $7);
2492+
rt_ref = ref_script_route_by_name( $5, sroutes->request,
2493+
RT_NO, REQUEST_ROUTE, 0);
2494+
if (rt_ref==NULL) yyerror("fail to create route reference");
2495+
mk_action3($$, LAUNCH_T, ACTIONS_ST, ROUTE_REF_ST, STRING_ST,
2496+
$3, (void*)rt_ref, $7);
24932497
}
24942498
| LAUNCH_TOKEN LPAREN async_func COMMA route_name RPAREN {
2495-
i_tmp = get_script_route_idx( $5, sroutes->request, RT_NO, 0);
2496-
if (i_tmp==-1) yyerror("too many script routes");
2497-
mk_action2($$, LAUNCH_T, ACTIONS_ST, NUMBER_ST,
2498-
$3, (void*)(long)i_tmp);
2499+
rt_ref = ref_script_route_by_name( $5, sroutes->request,
2500+
RT_NO, REQUEST_ROUTE, 0);
2501+
if (rt_ref==NULL) yyerror("fail to create route reference");
2502+
mk_action2($$, LAUNCH_T, ACTIONS_ST, ROUTE_REF_ST,
2503+
$3, (void*)rt_ref);
24992504
}
25002505
| LAUNCH_TOKEN LPAREN async_func RPAREN {
2501-
mk_action2($$, LAUNCH_T, ACTIONS_ST, NUMBER_ST,
2502-
$3, (void*)(long)-1);
2506+
mk_action2($$, LAUNCH_T, ACTIONS_ST, ROUTE_REF_ST,
2507+
$3, (void*)NULL);
25032508
}
25042509
;
25052510

cfg_reload.c

+4-116
Original file line numberDiff line numberDiff line change
@@ -154,117 +154,6 @@ static inline void reset_script_reload_ctx(void)
154154
}
155155

156156

157-
static int reindex_new_sroutes(struct script_route *new_sr,
158-
struct script_route *old_sr, int size, int has_zero)
159-
{
160-
static char *deleted_route_name = "_X_deleted_Y_";
161-
struct script_route *my_sr;
162-
int i, n, adding_idx;
163-
164-
/* devel only
165-
for(i=0+(has_zero?0:1) ; i<size && old_sr[i].name ; i++)
166-
LM_DBG("OLD [%d] is [%s]\n",i,old_sr[i].name);
167-
for(i=0+(has_zero?0:1) ; i<size && new_sr[i].name ; i++)
168-
LM_DBG("NEW [%d] is [%s]\n",i,new_sr[i].name);*/
169-
170-
my_sr = (struct script_route*)pkg_malloc(size*sizeof(struct script_route));
171-
if (my_sr==NULL) {
172-
LM_ERR("failed to allocate pkg mem (needing %zu)\n",
173-
size*sizeof(struct script_route));
174-
return -1;
175-
}
176-
memset( my_sr, 0, size*sizeof(struct script_route));
177-
/* iterate the old set of route and try to correlate the entries with the
178-
* new set of routes - the idea is to try to preserv the indexes */
179-
if (has_zero) {
180-
my_sr[0] = new_sr[0];
181-
new_sr[0].name = NULL;
182-
new_sr[0].a = NULL;
183-
}
184-
for ( i=1 ; i<size && old_sr[i].name ; i++) {
185-
if (old_sr[i].name == deleted_route_name) {
186-
/* simply preserve the index of old deleted routes */
187-
my_sr[i] = old_sr[i];
188-
} else {
189-
n = get_script_route_ID_by_name( old_sr[i].name, new_sr, size);
190-
if (n==-1) {
191-
/* route was removed in the new set , set the dummy one here */
192-
my_sr[i].name = deleted_route_name;
193-
my_sr[i].a = pkg_malloc( sizeof(struct action) );
194-
if (my_sr[i].a==NULL) {
195-
LM_ERR("failed to allocate dummy EXIT action\n");
196-
pkg_free(my_sr);
197-
return -1;
198-
}
199-
my_sr[i].a->type = EXIT_T;
200-
} else {
201-
/* copy new route definition over the original index*/
202-
my_sr[i] = new_sr[n];
203-
new_sr[n].name = deleted_route_name;
204-
new_sr[n].a = NULL;
205-
}
206-
}
207-
}
208-
adding_idx = i;
209-
210-
/* now see what is left in new set and not re-mapped to the old set
211-
* (basically the newly defined routes */
212-
for ( i=1 ; i<size ; i++) {
213-
if (new_sr[i].name==deleted_route_name || new_sr[i].name==NULL)
214-
continue;
215-
if (adding_idx==size) {
216-
LM_ERR("too many routes, cannot re-index newly defined routes "
217-
"after reload\n");
218-
pkg_free(my_sr);
219-
return -1;
220-
}
221-
my_sr[adding_idx++] = new_sr[i];
222-
}
223-
224-
/* copy the re-indexed set of routes as the new set of routes */
225-
memcpy( new_sr, my_sr, size*sizeof(struct script_route));
226-
pkg_free(my_sr);
227-
/* devel only
228-
for(i=0+(has_zero?0:1) ; i<size && new_sr[i].name ; i++)
229-
LM_DBG("END NEW [%d] is [%s]\n",i,new_sr[i].name);
230-
*/
231-
return 0;
232-
}
233-
234-
235-
static int reindex_all_new_sroutes(struct os_script_routes *new_srs,
236-
struct os_script_routes *old_srs)
237-
{
238-
if (reindex_new_sroutes( new_srs->request, old_srs->request,
239-
RT_NO, 1)<0) {
240-
LM_ERR("failed to re-index the request routes\n");
241-
return -1;
242-
}
243-
if (reindex_new_sroutes( new_srs->onreply, old_srs->onreply,
244-
ONREPLY_RT_NO, 1)<0) {
245-
LM_ERR("failed to re-index the on_reply routes\n");
246-
return -1;
247-
}
248-
if (reindex_new_sroutes( new_srs->failure, old_srs->failure,
249-
FAILURE_RT_NO, 0)<0) {
250-
LM_ERR("failed to re-index the on_failure routes\n");
251-
return -1;
252-
}
253-
if (reindex_new_sroutes( new_srs->branch, old_srs->branch,
254-
BRANCH_RT_NO, 0)<0) {
255-
LM_ERR("failed to re-index the branch routes\n");
256-
return -1;
257-
}
258-
if (reindex_new_sroutes( new_srs->event, old_srs->event,
259-
EVENT_RT_NO, 0)<0) {
260-
LM_ERR("failed to re-index the branch routes\n");
261-
return -1;
262-
}
263-
264-
return 0;
265-
}
266-
267-
268157
static inline void send_cmd_to_all_procs(ipc_rpc_f *rpc)
269158
{
270159
int i;
@@ -392,11 +281,6 @@ static void routes_reload_per_proc(int sender, void *param)
392281
fclose(cfg);
393282
cfg_parse_only_routes = 0;
394283

395-
if (reindex_all_new_sroutes( sroutes, sr_bk)<0) {
396-
LM_ERR("re-indexing routes failed, abording\n");
397-
goto error;
398-
}
399-
400284
if (fix_rls()<0) {
401285
LM_ERR("fixing routes failed, abording\n");
402286
goto error;
@@ -462,6 +346,10 @@ static void routes_switch_per_proc(int sender, void *param)
462346
/* swap the old route set with the new parsed set */
463347
sroutes = parsed_sr;
464348
parsed_sr = NULL;
349+
350+
/* update all the ref to script routes */
351+
update_all_script_route_refs();
352+
print_script_route_refs();
465353
}
466354

467355

0 commit comments

Comments
 (0)