Module: sip-router
Branch: master
Commit: fcd61b36e044a560432fc150170aba3a04b06b7c
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=fcd61b3…
Author: Juha Heinanen <jh(a)tutpro.com>
Committer: Juha Heinanen <jh(a)tutpro.com>
Date: Mon Oct 4 18:04:02 2010 +0300
modules/lcr: added note about 'kamctl eval_weights' command
---
modules/lcr/README | 7 ++++---
modules/lcr/doc/lcr_admin.xml | 3 ++-
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/modules/lcr/README b/modules/lcr/README
index 8fa8a98..617c0e0 100644
--- a/modules/lcr/README
+++ b/modules/lcr/README
@@ -235,9 +235,10 @@ Chapter 1. Admin Guide
Weight is an integer value from 1 to 254. Weight implementation is
fast, but unfair favoring larger weight values at the expense smaller
ones. For example, if two gateways have weights 1 and 2, probability
- that the gateway with weight 1 is tried first is 1/4, not 1/3. A script
- is provided in lcr/utils directory that can be used to check the
- probabilities resulting from a given set of weight values.
+ that the gateway with weight 1 is tried first is 1/4, not 1/3. Two
+ scripts are provided in lcr/utils directory that can be used to check
+ the probabilities resulting from a given set of weight values. Same can
+ be done with command 'kamctl eval_weights'.
The function next_gw() can then be used to select one gateway at a time
for forwarding. Upon each call, unless "dont_strip_of_tag" flag is set,
diff --git a/modules/lcr/doc/lcr_admin.xml b/modules/lcr/doc/lcr_admin.xml
index 562a7c0..12f2d09 100644
--- a/modules/lcr/doc/lcr_admin.xml
+++ b/modules/lcr/doc/lcr_admin.xml
@@ -73,8 +73,9 @@
fast, but unfair favoring larger weight values at the expense smaller
ones. For example, if two gateways have weights 1 and 2, probability
that the gateway with weight 1 is tried first is 1/4, not 1/3.
- A script is provided in lcr/utils directory that can be used to
+ Two scripts are provided in lcr/utils directory that can be used to
check the probabilities resulting from a given set of weight values.
+ Same can be done with command 'kamctl eval_weights'.
</para>
<para>
The function <emphasis>next_gw()</emphasis> can then be used to
Hi, according to kamailio-devel-guide child_init function is just
called for kamailio workers:
16.10.6. Module Child Init Function
This is the function called just after KAMAILIO (OPENSER) forks
its worker processes.
but later it says:
The function gets as parameter the rank of the child process. The rank
is a positive number if it is a worker process and negative for special
processes like timer processes or TCP attendant.
So my question is: should I check the rank parameter in child_init
function just to run the code for real workers?
For example, in modules_k/alias_db module I see:
-----------------------------------------------
static int child_init(int rank)
{
if (rank==PROC_INIT || rank==PROC_MAIN || rank==PROC_TCP_MAIN)
return 0; /* do nothing for the main process */
db_handle = adbf.init(&db_url);
if (!db_handle)
{
LM_ERR("unable to connect database\n");
return -1;
}
return 0;
}
---------------------------------------------
But in modules/db_flatstore I see:
---------------------------------------------
/*
* FIXME: We should check whether just calling km_child_init would really work
* here. This function comes from kamailio and since the core of sip-router is
* based on SER 2.0, the way how child_init is called and values of the rank
* variable could be incompatible with km_child_init function. A solution here
* would be to rewrite km_child_init with ser 2.0 init stuff in mind.
*/
static int child_init(int rank)
{
char* tmp;
unsigned int v;
km_child_init(rank);
if (rank <= 0) {
v = -rank;
} else {
v = rank - PROC_MIN;
}
[...]
---------------------------------------------
I just want child_init to be run for workers, and no por other special
processes. Also I'm writting the module under modules/ so, what should
I do to achieve it?
Thanks a lot.
--
Iñaki Baz Castillo
<ibc(a)aliax.net>
Module: sip-router
Branch: tirpi/cfg_framework_multivalue
Commit: b062f42f4353802b03dba4cee41909657b4a5ffe
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=b062f42…
Author: Miklos Tirpak <miklos(a)iptel.org>
Committer: Miklos Tirpak <miklos(a)iptel.org>
Date: Mon Oct 4 15:26:58 2010 +0200
cfg framework: group handle can be moved runtime
Added support for moving the group handles between the default
configuration and different group instances runtime. The handles are
reset when cfg_update() is called the next time, or it can be
reset explicitely.
---
cfg/cfg_struct.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
cfg/cfg_struct.h | 52 +++++++++++++++++++++++++++++
2 files changed, 148 insertions(+), 1 deletions(-)
diff --git a/cfg/cfg_struct.c b/cfg/cfg_struct.c
index 358e4eb..30bd101 100644
--- a/cfg/cfg_struct.c
+++ b/cfg/cfg_struct.c
@@ -32,6 +32,7 @@
#include "../mem/shm_mem.h"
#include "../ut.h"
#include "../locking.h"
+#include "../bit_scan.h"
#include "cfg_ctx.h"
#include "cfg_script.h"
#include "cfg_select.h"
@@ -42,7 +43,7 @@ cfg_block_t **cfg_global = NULL; /* pointer to the active cfg block */
cfg_block_t *cfg_local = NULL; /* per-process pointer to the active cfg block.
Updated only when the child process
finishes working on the SIP message */
-static int cfg_block_size = 0; /* size of the cfg block including the meta-data (constant) */
+int cfg_block_size = 0; /* size of the cfg block including the meta-data (constant) */
gen_lock_t *cfg_global_lock = 0; /* protects *cfg_global */
gen_lock_t *cfg_writer_lock = 0; /* This lock makes sure that two processes do not
try to clone *cfg_global at the same time.
@@ -55,6 +56,7 @@ cfg_child_cb_t **cfg_child_cb_first = NULL; /* first item of the per-child proce
callback list */
cfg_child_cb_t **cfg_child_cb_last = NULL; /* last item of the above list */
cfg_child_cb_t *cfg_child_cb = NULL; /* pointer to the previously executed cb */
+int cfg_ginst_count = 0; /* number of group instances set within the child process */
/* forward declarations */
@@ -1057,3 +1059,96 @@ error:
shm_free(new_array);
return -1;
}
+
+/* Move the group handle to the specified group instance pointed by dst_ginst.
+ * src_ginst shall point to the active group instance.
+ * Both parameters can be NULL meaning that the src/dst config is the default,
+ * not an additional group instance.
+ * The function executes all the per-child process callbacks which are different
+ * in the two instaces.
+ */
+void cfg_move_handle(cfg_group_t *group, cfg_group_inst_t *src_ginst, cfg_group_inst_t *dst_ginst)
+{
+ cfg_mapping_t *var;
+ unsigned int bitmap;
+ int i, pos;
+ str gname, vname;
+
+ if (src_ginst == dst_ginst)
+ return; /* nothing to do */
+
+ /* move the handle to the variables of the dst group instance,
+ or to the local config if no dst group instance is specified */
+ *(group->handle) = dst_ginst ?
+ dst_ginst->vars
+ : CFG_GROUP_DATA(cfg_local, group);
+
+ /* call the per child process callback of those variables
+ that have different value in the two group instances */
+ /* TODO: performance optimization: this entire loop can be
+ skipped if the group does not have any variable with
+ per-child process callback. Use some flag in the group
+ structure for this purpose. */
+ gname.s = group->name;
+ gname.len = group->name_len;
+ for (i = 0; i < CFG_MAX_VAR_NUM/(sizeof(int)*8); i++) {
+ bitmap = ((src_ginst) ? src_ginst->set[i] : 0U)
+ | ((dst_ginst) ? dst_ginst->set[i] : 0U);
+ while (bitmap) {
+ pos = bit_scan_forward32(bitmap);
+ var = &group->mapping[pos + i*sizeof(int)*8];
+ if (var->def->on_set_child_cb) {
+ vname.s = var->def->name;
+ vname.len = var->name_len;
+ var->def->on_set_child_cb(&gname, &vname);
+ }
+ bitmap -= (1U << pos);
+ }
+ }
+ /* keep track of how many group instences are set in the child process */
+ if (!src_ginst && dst_ginst)
+ cfg_ginst_count++;
+ else if (!dst_ginst)
+ cfg_ginst_count--;
+#ifdef EXTRA_DEBUG
+ if (cfg_ginst_count < 0)
+ LOG(L_ERR, "ERROR: cfg_select(): BUG, cfg_ginst_count is negative: %d. group=%.*s\n",
+ cfg_ginst_count, group->name_len, group->name);
+#endif
+ return;
+}
+
+/* Move the group handle to the specified group instance. */
+int cfg_select(cfg_group_t *group, unsigned int id)
+{
+ cfg_group_inst_t *ginst;
+
+ if (!(ginst = cfg_find_group(CFG_GROUP_META(cfg_local, group),
+ group->size,
+ id))
+ ) {
+ LOG(L_ERR, "ERROR: cfg_select(): group instance '%.*s[%u]' does not exist\n",
+ group->name_len, group->name, id);
+ return -1;
+ }
+
+ cfg_move_handle(group,
+ CFG_HANDLE_TO_GINST(*(group->handle)), /* the active group instance */
+ ginst);
+
+ LOG(L_DBG, "DEBUG: cfg_select(): group instance '%.*s[%u]' has been selected\n",
+ group->name_len, group->name, id);
+ return 0;
+}
+
+/* Reset the group handle to the default, local configuration */
+int cfg_reset(cfg_group_t *group)
+{
+ cfg_move_handle(group,
+ CFG_HANDLE_TO_GINST(*(group->handle)), /* the active group instance */
+ NULL);
+
+ LOG(L_DBG, "DEBUG: cfg_reset(): default group '%.*s' has been selected\n",
+ group->name_len, group->name);
+ return 0;
+}
diff --git a/cfg/cfg_struct.h b/cfg/cfg_struct.h
index 545554c..0c62a3d 100644
--- a/cfg/cfg_struct.h
+++ b/cfg/cfg_struct.h
@@ -163,12 +163,14 @@ typedef struct _cfg_child_cb {
extern cfg_group_t *cfg_group;
extern cfg_block_t **cfg_global;
extern cfg_block_t *cfg_local;
+extern int cfg_block_size;
extern gen_lock_t *cfg_global_lock;
extern gen_lock_t *cfg_writer_lock;
extern int cfg_shmized;
extern cfg_child_cb_t **cfg_child_cb_first;
extern cfg_child_cb_t **cfg_child_cb_last;
extern cfg_child_cb_t *cfg_child_cb;
+extern int cfg_ginst_count;
/* magic value for cfg_child_cb for processes that do not want to
execute per-child callbacks */
@@ -196,6 +198,15 @@ extern cfg_child_cb_t *cfg_child_cb;
#define CFG_VAR_TEST_AND_SET(group_inst, var) \
bit_test_and_set((var)->pos % (sizeof(int)*8), (group_inst)->set + (var)->pos/(sizeof(int)*8))
+/* Return the group instance pointer from a handle,
+ * or NULL if the handle points to the default configuration block */
+#define CFG_HANDLE_TO_GINST(h) \
+ ( (((unsigned char*)(h) < cfg_local->vars) \
+ || ((unsigned char*)(h) > cfg_local->vars + cfg_block_size) \
+ ) ? \
+ (cfg_group_inst_t*)((char*)(h) - (unsigned long)&((cfg_group_inst_t *)0)->vars) \
+ : NULL )
+
/* initiate the cfg framework */
int sr_cfg_init(void);
@@ -268,6 +279,16 @@ static inline void cfg_block_free(cfg_block_t *block)
shm_free(block);
}
+/* Move the group handle to the specified group instance pointed by dst_ginst.
+ * src_ginst shall point to the active group instance.
+ * Both parameters can be NULL meaning that the src/dst config is the default,
+ * not an additional group instance.
+ * The function executes all the per-child process callbacks which are different
+ * in the two instaces.
+ */
+void cfg_move_handle(cfg_group_t *group, cfg_group_inst_t *src_ginst, cfg_group_inst_t *dst_ginst);
+
+
/* lock and unlock the global cfg block -- used only at the
* very last step when the block is replaced */
#define CFG_LOCK() lock_get(cfg_global_lock);
@@ -352,6 +373,29 @@ static inline void cfg_update_local(int no_cbs)
}
}
+/* Reset all the group handles to the default, local configuration */
+static inline void cfg_reset_handles(void)
+{
+ cfg_group_t *group;
+
+ if (!cfg_local)
+ return;
+
+ for ( group = cfg_group;
+ group && cfg_ginst_count; /* cfg_ginst_count is decreased every time
+ a group handle is reset. When it reaches 0,
+ needless to continue the loop */
+ group = group->next
+ ) {
+ if (((unsigned char*)*(group->handle) < cfg_local->vars)
+ || ((unsigned char*)*(group->handle) > cfg_local->vars + cfg_block_size)
+ )
+ cfg_move_handle(group,
+ CFG_HANDLE_TO_GINST(*(group->handle)),
+ NULL);
+ }
+}
+
/* sets the local cfg block to the active block
*
* If your module forks a new process that implements
@@ -361,6 +405,8 @@ static inline void cfg_update_local(int no_cbs)
*/
#define cfg_update() \
do { \
+ if (unlikely(cfg_ginst_count)) \
+ cfg_reset_handles(); \
if (unlikely(cfg_local != *cfg_global)) \
cfg_update_local(0); \
} while(0)
@@ -446,4 +492,10 @@ void cfg_child_cb_free(cfg_child_cb_t *child_cb_first);
int new_add_var(str *group_name, unsigned int group_id, str *var_name,
void *val, unsigned int type);
+/* Move the group handle to the specified group instance. */
+int cfg_select(cfg_group_t *group, unsigned int id);
+
+/* Reset the group handle to the default, local configuration */
+int cfg_reset(cfg_group_t *group);
+
#endif /* _CFG_STRUCT_H */
Module: sip-router
Branch: tirpi/cfg_framework_multivalue
Commit: 58829230eec1efba3cd1b217d6d55127fec152d6
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=5882923…
Author: Miklos Tirpak <miklos(a)iptel.org>
Committer: Miklos Tirpak <miklos(a)iptel.org>
Date: Mon Oct 4 16:27:24 2010 +0200
cfg framework: timer must reset the handles more frequently
The timer processes must reset the cfg group handles after
each registered timer function is executed, otherwise cfg_select()
in one function may influence another function.
---
cfg/cfg_struct.h | 10 ++++++++++
timer.c | 4 ++++
2 files changed, 14 insertions(+), 0 deletions(-)
diff --git a/cfg/cfg_struct.h b/cfg/cfg_struct.h
index 0c62a3d..adde858 100644
--- a/cfg/cfg_struct.h
+++ b/cfg/cfg_struct.h
@@ -421,6 +421,16 @@ static inline void cfg_reset_handles(void)
cfg_update_local(1); \
} while(0)
+/* Reset all the group handles in the child process,
+ * i.e. move them back to the default local configuration.
+ */
+#define cfg_reset_all() \
+ do { \
+ if (unlikely(cfg_ginst_count)) \
+ cfg_reset_handles(); \
+ } while(0)
+
+
/* searches a group by name */
cfg_group_t *cfg_lookup_group(char *name, int len);
diff --git a/timer.c b/timer.c
index ddce7e2..efba92d 100644
--- a/timer.c
+++ b/timer.c
@@ -892,6 +892,8 @@ inline static void timer_list_expire(ticks_t t, struct timer_head* h
#endif
UNLOCK_TIMER_LIST(); /* acts also as write barrier */
ret=tl->f(t, tl, tl->data);
+ /* reset the configuration group handles */
+ cfg_reset_all();
if (ret==0){
UNSET_RUNNING();
LOCK_TIMER_LIST();
@@ -1147,6 +1149,8 @@ void slow_timer_main()
SET_RUNNING_SLOW(tl);
UNLOCK_SLOW_TIMER_LIST();
ret=tl->f(*ticks, tl, tl->data);
+ /* reset the configuration group handles */
+ cfg_reset_all();
if (ret==0){
/* one shot */
UNSET_RUNNING_SLOW();