Browse code

dispatcher: remove destination from in-memory dispatcher set

- add dispatcher.remove call to remove entry from in-memory dispatcher
list
- allow arguments to callback in ds_iter_set()

Timmo Verlaan authored on 08/03/2019 20:19:22
Showing 4 changed files
... ...
@@ -176,7 +176,7 @@ int ds_hash_load_destroy(void)
176 176
 /**
177 177
  * Recursivly iterate over ds_set and execute callback
178 178
  */
179
-void ds_iter_set(ds_set_t *node, void (*ds_action_cb)(ds_set_t *node, int i))
179
+void ds_iter_set(ds_set_t *node, void (*ds_action_cb)(ds_set_t *node, int i, void *arg), void *ds_action_arg)
180 180
 {
181 181
 	if(!node)
182 182
 		return;
... ...
@@ -184,16 +184,16 @@ void ds_iter_set(ds_set_t *node, void (*ds_action_cb)(ds_set_t *node, int i))
184 184
 	int i;
185 185
 
186 186
 	for(i = 0; i < 2; ++i)
187
-		ds_iter_set(node->next[i], ds_action_cb);
187
+		ds_iter_set(node->next[i], ds_action_cb, ds_action_arg);
188 188
 
189 189
 	for(i = 0; i < node->nr; i++) {
190
-		ds_action_cb(node, i);
190
+		ds_action_cb(node, i, ds_action_arg);
191 191
 	}
192 192
 
193 193
 	return;
194 194
 }
195 195
 
196
-void ds_log_dst_cb(ds_set_t *node, int i)
196
+void ds_log_dst_cb(ds_set_t *node, int i, void *arg)
197 197
 {
198 198
 	LM_DBG("dst>> %d %.*s %d %d (%.*s,%d,%d,%d)\n", node->id,
199 199
 		node->dlist[i].uri.len, node->dlist[i].uri.s,
... ...
@@ -208,7 +208,7 @@ void ds_log_dst_cb(ds_set_t *node, int i)
208 208
  */
209 209
 void ds_log_set(ds_set_t *node)
210 210
 {
211
-	ds_iter_set(node, &ds_log_dst_cb);
211
+	ds_iter_set(node, &ds_log_dst_cb, NULL);
212 212
 
213 213
 	return;
214 214
 }
... ...
@@ -2350,7 +2350,7 @@ int ds_update_dst(struct sip_msg *msg, int upos, int mode)
2350 2350
 }
2351 2351
 
2352 2352
 /* callback for adding nodes based on index */
2353
-void ds_add_dest_cb(ds_set_t *node, int i)
2353
+void ds_add_dest_cb(ds_set_t *node, int i, void *arg)
2354 2354
 {
2355 2355
 	int setn;
2356 2356
 
... ...
@@ -2378,7 +2378,7 @@ int ds_add_dst(int group, str *address, int flags)
2378 2378
 	ds_avl_destroy(&ds_lists[*next_idx]);
2379 2379
 
2380 2380
 	// add all existing destinations
2381
-	ds_iter_set(_ds_list, &ds_add_dest_cb);
2381
+	ds_iter_set(_ds_list, &ds_add_dest_cb, NULL);
2382 2382
 
2383 2383
 	// add new destination
2384 2384
 	if(add_dest2list(group, *address, flags, priority, &attrs,
... ...
@@ -2406,6 +2406,61 @@ error:
2406 2406
 	return -1;
2407 2407
 }
2408 2408
 
2409
+/* callback for removing nodes based on setid & address */
2410
+void ds_filter_dest_cb(ds_set_t *node, int i, void *arg)
2411
+{
2412
+	struct ds_filter_dest_cb_arg *filter_arg = (typeof(filter_arg)) arg;
2413
+
2414
+	if(node->id == filter_arg->setid && node->dlist[i].uri.len == filter_arg->dest->uri.len &&
2415
+		strncmp(node->dlist[i].uri.s, filter_arg->dest->uri.s, filter_arg->dest->uri.len) == 0)
2416
+		return;
2417
+
2418
+	if(add_dest2list(node->id, node->dlist[i].uri, node->dlist[i].flags,
2419
+			node->dlist[i].priority, &node->dlist[i].attrs.body, *next_idx,
2420
+			filter_arg->setn) != 0) {
2421
+		LM_WARN("failed to add destination in group %d - %.*s\n",
2422
+				node->id, node->dlist[i].uri.len, node->dlist[i].uri.s);
2423
+	}
2424
+	return;
2425
+}
2426
+
2427
+/* remove dispatcher entry from in-memory dispatcher list */
2428
+int ds_remove_dst(int group, str *address)
2429
+{
2430
+	int setn;
2431
+	struct ds_filter_dest_cb_arg filter_arg;
2432
+	ds_dest_t *dp = NULL;
2433
+
2434
+	setn = 0;
2435
+
2436
+	dp = pack_dest(*address, 0, 0, NULL);
2437
+	filter_arg.setid = group;
2438
+	filter_arg.dest = dp;
2439
+	filter_arg.setn = &setn;
2440
+
2441
+	*next_idx = (*crt_idx + 1) % 2;
2442
+	ds_avl_destroy(&ds_lists[*next_idx]);
2443
+
2444
+	// add existing destinations except destination that matches group & address
2445
+	ds_iter_set(_ds_list, &ds_filter_dest_cb, &filter_arg);
2446
+
2447
+	if(reindex_dests(ds_lists[*next_idx]) != 0) {
2448
+		LM_ERR("error on reindex\n");
2449
+		goto error;
2450
+	}
2451
+
2452
+	_ds_list_nr = setn;
2453
+	*crt_idx = *next_idx;
2454
+	ds_ht_clear_slots(_dsht_load);
2455
+	ds_log_sets();
2456
+	return 0;
2457
+
2458
+error:
2459
+	ds_avl_destroy(&ds_lists[*next_idx]);
2460
+	*next_idx = *crt_idx;
2461
+	return -1;
2462
+}
2463
+
2409 2464
 int ds_mark_dst(struct sip_msg *msg, int state)
2410 2465
 {
2411 2466
 	sr_xavp_t *rxavp = NULL;
... ...
@@ -130,6 +130,7 @@ int ds_select_dst_limit(sip_msg_t *msg, int set, int alg, uint32_t limit,
130 130
 int ds_select_dst(struct sip_msg *msg, int set, int alg, int mode);
131 131
 int ds_update_dst(struct sip_msg *msg, int upos, int mode);
132 132
 int ds_add_dst(int group, str *address, int flags);
133
+int ds_remove_dst(int group, str *address);
133 134
 int ds_update_state(sip_msg_t *msg, int group, str *address, int state);
134 135
 int ds_reinit_state(int group, str *address, int state);
135 136
 int ds_reinit_state_all(int group, int state);
... ...
@@ -228,6 +229,12 @@ typedef struct _ds_select_state {
228 229
 	sr_xavp_t *lxavp;
229 230
 } ds_select_state_t;
230 231
 
232
+struct ds_filter_dest_cb_arg {
233
+	int setid;
234
+	ds_dest_t *dest;
235
+	int *setn;
236
+};
237
+
231 238
 /* clang-format on */
232 239
 
233 240
 #define AVL_LEFT 0
... ...
@@ -1668,6 +1668,31 @@ static void dispatcher_rpc_add(rpc_t *rpc, void *ctx)
1668 1668
 	return;
1669 1669
 }
1670 1670
 
1671
+static const char *dispatcher_rpc_remove_doc[2] = {
1672
+		"Remove a destination address from memory", 0};
1673
+
1674
+
1675
+/*
1676
+ * RPC command to remove a destination address from memory
1677
+ */
1678
+static void dispatcher_rpc_remove(rpc_t *rpc, void *ctx)
1679
+{
1680
+	int group;
1681
+	str dest;
1682
+
1683
+	if(rpc->scan(ctx, "dS", &group, &dest) < 2) {
1684
+		rpc->fault(ctx, 500, "Invalid Parameters");
1685
+		return;
1686
+	}
1687
+
1688
+	if(ds_remove_dst(group, &dest) != 0) {
1689
+		rpc->fault(ctx, 500, "Removing dispatcher dst failed");
1690
+		return;
1691
+	}
1692
+
1693
+	return;
1694
+}
1695
+
1671 1696
 /* clang-format off */
1672 1697
 rpc_export_t dispatcher_rpc_cmds[] = {
1673 1698
 	{"dispatcher.reload", dispatcher_rpc_reload,
... ...
@@ -1680,6 +1705,8 @@ rpc_export_t dispatcher_rpc_cmds[] = {
1680 1705
 		dispatcher_rpc_ping_active_doc, 0},
1681 1706
 	{"dispatcher.add",   dispatcher_rpc_add,
1682 1707
 		dispatcher_rpc_add_doc, 0},
1708
+	{"dispatcher.remove",   dispatcher_rpc_remove,
1709
+		dispatcher_rpc_remove_doc, 0},
1683 1710
 	{0, 0, 0, 0}
1684 1711
 };
1685 1712
 /* clang-format on */
... ...
@@ -1831,6 +1831,39 @@ DEST: {
1831 1831
 &sercmd; dispatcher.add 2 sip:127.0.0.1:5080
1832 1832
 &sercmd; dispatcher.add 3 sip:127.0.0.1:5075 8
1833 1833
 ...
1834
+</programlisting>
1835
+    </section>
1836
+		<section id="dispatcher.r.remove">
1837
+		<title>
1838
+		<function moreinfo="none">dispatcher.remove</function>
1839
+		</title>
1840
+		<para>
1841
+		Remove a destination address from the in-memory dispatcher list. Reloading
1842
+		the dispatcher from file or database will re-add destinations that are
1843
+		removed using this command.
1844
+		</para>
1845
+		<para>
1846
+		This command will remove all entries that match the group and address.
1847
+		</para>
1848
+		<para>
1849
+		Name: <emphasis>dispatcher.remove</emphasis>
1850
+		</para>
1851
+		<para>Parameters:</para>
1852
+		<itemizedlist>
1853
+			<listitem><para>_group_: destination group id</para></listitem>
1854
+
1855
+			<listitem><para>_address_: address of the destination in the _group_</para></listitem>
1856
+
1857
+		</itemizedlist>
1858
+		<para>
1859
+		Example:
1860
+		</para>
1861
+<programlisting  format="linespecific">
1862
+...
1863
+# prototype: &sercmd; dispatcher.remove _group_ _address_
1864
+&sercmd; dispatcher.remove 2 sip:127.0.0.1:5080
1865
+&sercmd; dispatcher.remove 3 sip:127.0.0.1:5075;transport=udp
1866
+...
1834 1867
 </programlisting>
1835 1868
     </section>
1836 1869