mqueue: Added MI command to get current size of mqueue.
authorAlex Balashov <abalashov@evaristesys.com>
Mon, 23 Jul 2012 23:53:41 +0000 (19:53 -0400)
committerAlex Balashov <abalashov@evaristesys.com>
Mon, 23 Jul 2012 23:53:41 +0000 (19:53 -0400)
There is currently no runtime visibility into the size of a given mqueue.
To address this, added an MI command 'mq_get_size' that can return the size
of an mqueue by name.  Example:

   diminuendo-1:~/sip-router/modules/mqueue# kamctl fifo mq_get_size r_write
   mqueue::  name=r_write size=1

modules/mqueue/Makefile
modules/mqueue/mqueue_api.c
modules/mqueue/mqueue_api.h
modules/mqueue/mqueue_mod.c

index bbf4862..02a5329 100644 (file)
@@ -10,6 +10,7 @@ LIBS=
 DEFS+=-DOPENSER_MOD_INTERFACE
 
 SERLIBPATH=../../lib
+SER_LIBS+=$(SERLIBPATH)/kmi/kmi
 SER_LIBS+=$(SERLIBPATH)/kcore/kcore
 
 include ../../Makefile.modules
index 7f856f4..4a36909 100644 (file)
@@ -456,3 +456,19 @@ int pv_get_mqv(struct sip_msg *msg, pv_param_t *param,
        return pv_get_strval(msg, param, res, &mp->item->val);
 }
 
+/* Return head->csize for a given queue */
+
+int _mq_get_csize(str *name) 
+{
+       mq_head_t *mh = mq_head_get(name);
+       int mqueue_size = 0;
+
+       if(mh == NULL)
+               return -1;
+
+       lock_get(&mh->lock);
+       mqueue_size = mh->csize;
+       lock_release(&mh->lock);
+
+       return mqueue_size;
+}
index 04ad1e4..cb695f1 100644 (file)
@@ -41,5 +41,7 @@ int mq_head_fetch(str *name);
 void mq_pv_free(str *name);
 int mq_item_add(str *qname, str *key, str *val);
 
+int _mq_get_csize(str *);
+
 #endif
 
index 458701c..1559c51 100644 (file)
@@ -32,6 +32,7 @@
 #include "../../ut.h"
 #include "../../pvar.h"
 #include "../../mod_fix.h"
+#include "../../lib/kmi/mi.h"
 #include "../../parser/parse_param.h"
 #include "../../shm_init.h"
 
@@ -50,6 +51,8 @@ int mq_param(modparam_t type, void *val);
 static int fixup_mq_add(void** param, int param_no);
 static int bind_mq(mq_api_t* api);
 
+static struct mi_root *mq_mi_get_size(struct mi_root *, void *);
+
 static pv_export_t mod_pvs[] = {
        { {"mqk", sizeof("mqk")-1}, PVT_OTHER, pv_get_mqk, 0,
                pv_parse_mq_name, 0, 0, 0 },
@@ -58,6 +61,10 @@ static pv_export_t mod_pvs[] = {
        { {0, 0}, 0, 0, 0, 0, 0, 0, 0 }
 };
 
+static mi_export_t mi_cmds[] = {
+       { "mq_get_size",        mq_mi_get_size, 0, 0, 0},
+       { 0, 0, 0, 0, 0}
+};
 
 static cmd_export_t cmds[]={
        {"mq_fetch", (cmd_function)w_mq_fetch, 1, fixup_spve_null,
@@ -82,7 +89,7 @@ struct module_exports exports = {
        cmds,
        params,
        0,
-       0,              /* exported MI functions */
+       mi_cmds,        /* exported MI functions */
        mod_pvs,        /* exported pseudo-variables */
        0,              /* extra processes */
        mod_init,       /* module initialization function */
@@ -100,6 +107,12 @@ static int mod_init(void)
 {
        if(!mq_head_defined())
                LM_WARN("no mqueue defined\n");
+
+       if(register_mi_mod(exports.name, mi_cmds) != 0) {
+               LM_ERR("failed to register MI commands\n");
+               return 1;
+       }
+
        return 0;
 }
 
@@ -237,3 +250,70 @@ static int bind_mq(mq_api_t* api)
        api->add = mq_item_add;
        return 0;
 }
+
+/* Return the size of the specified mqueue */
+
+static struct mi_root *mq_mi_get_size(struct mi_root *cmd_tree, 
+                                     void *param)
+{
+       static struct mi_node   *node = NULL, *rpl = NULL;
+       static struct mi_root   *rpl_tree = NULL;
+       static struct mi_attr   *attr = NULL;
+       str                     mqueue_name;
+       int                     mqueue_sz = 0;
+       char                    *p = NULL;
+       int                     len = 0;
+
+       if((node = cmd_tree->node.kids) == NULL) {
+               return init_mi_tree(400, MI_MISSING_PARM_S, 
+                                        MI_MISSING_PARM_LEN);
+       }
+
+       mqueue_name = node->value;
+
+       if(mqueue_name.len <= 0 || mqueue_name.s == NULL) {
+               LM_ERR("bad mqueue name\n");
+               return init_mi_tree(500, MI_SSTR("bad mqueue name"));
+       }
+
+       mqueue_sz = _mq_get_csize(&mqueue_name);
+
+       if(mqueue_sz < 0) {
+               LM_ERR("no such mqueue\n");
+               return init_mi_tree(404, MI_SSTR("no such mqueue"));
+       }
+
+       rpl_tree = init_mi_tree(200, MI_OK_S, MI_OK_LEN);
+
+       if(rpl_tree == NULL) 
+               return 0;
+
+       rpl = &rpl_tree->node;
+
+       node = add_mi_node_child(rpl, MI_DUP_VALUE, "mqueue", strlen("mqueue"),
+                                NULL, 0);
+
+       if(node == NULL) {
+               free_mi_tree(rpl_tree);
+               return NULL;
+       }
+
+       attr = add_mi_attr(node, MI_DUP_VALUE, "name", strlen("name"),
+                          mqueue_name.s, mqueue_name.len);
+
+       if(attr == NULL) goto error;
+
+       p = int2str((unsigned long) mqueue_sz, &len);   
+
+       attr = add_mi_attr(node, MI_DUP_VALUE, "size", strlen("size"), 
+                          p, len);
+
+       if(attr == NULL) goto error;
+
+       return rpl_tree;
+
+error:
+       free_mi_tree(rpl_tree);
+       return NULL;
+}
+