Module: sip-router
Branch: master
Commit: ebf12d93251124d619e6d12093181eab5bab5818
URL:
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=ebf12d9…
Author: Elena-Ramona Modroiu <ramona(a)asipto.com>
Committer: Elena-Ramona Modroiu <ramona(a)asipto.com>
Date: Tue Feb 8 12:18:10 2011 +0100
htable: option to save content of htable to db at shutdown
- new 'dbmode' attribute for hash table definition
- if dbmode=1, the content fo hash table will be saved back to databse
table when the sip server is stopped
- default value is 0 - no sync back to database table
- example:
modparam("htable", "htable",
"a=>size=8;dbtable=htable;dbmode=1;")
---
modules_k/htable/ht_api.c | 36 ++++++++++++++-
modules_k/htable/ht_api.h | 4 +-
modules_k/htable/ht_db.c | 107 +++++++++++++++++++++++++++++++++++++++++++++
modules_k/htable/ht_db.h | 2 +
modules_k/htable/htable.c | 12 +++++
5 files changed, 158 insertions(+), 3 deletions(-)
diff --git a/modules_k/htable/ht_api.c b/modules_k/htable/ht_api.c
index 5951167..fe9a66e 100644
--- a/modules_k/htable/ht_api.c
+++ b/modules_k/htable/ht_api.c
@@ -117,7 +117,7 @@ ht_t* ht_get_table(str *name)
return NULL;
}
-int ht_pkg_init(str *name, int autoexp, str *dbtable, int size)
+int ht_pkg_init(str *name, int autoexp, str *dbtable, int size, int dbmode)
{
unsigned int htid;
ht_t *ht;
@@ -155,6 +155,7 @@ int ht_pkg_init(str *name, int autoexp, str *dbtable, int size)
ht->name = *name;
if(dbtable!=NULL && dbtable->len>0)
ht->dbtable = *dbtable;
+ ht->dbmode = dbmode;
ht->next = _ht_pkg_root;
_ht_pkg_root = ht;
@@ -516,6 +517,7 @@ int ht_table_spec(char *spec)
unsigned int autoexpire = 0;
unsigned int size = 4;
int type = 0;
+ unsigned int dbmode = 0;
str in;
str tok;
char *p;
@@ -570,6 +572,8 @@ next_token:
type = 2;
else if(tok.len==4 && strncmp(tok.s, "size", 4)==0)
type = 3;
+ else if(tok.len==6 && strncmp(tok.s, "dbmode", 6)==0)
+ type = 4;
else goto error;
if(*p!='=')
@@ -613,6 +617,12 @@ next_token:
LM_DBG("htable [%.*s] - size [%u]\n", name.len, name.s,
size);
break;
+ case 4:
+ if(str2int(&tok, &dbmode)!=0)
+ goto error;
+ LM_DBG("htable [%.*s] - dbmode [%u]\n", name.len, name.s,
+ dbmode);
+ break;
}
while(p<in.s+in.len && (*p==';' || *p==' ' ||
*p=='\t'
|| *p=='\n' || *p=='\r'))
@@ -620,7 +630,7 @@ next_token:
if(p<in.s+in.len)
goto next_token;
- return ht_pkg_init(&name, autoexpire, &dbtable, size);
+ return ht_pkg_init(&name, autoexpire, &dbtable, size, dbmode);
error:
LM_ERR("invalid htable parameter [%.*s] at [%d]\n", in.len, in.s,
@@ -648,6 +658,28 @@ int ht_db_load_tables(void)
return 0;
}
+int ht_db_sync_tables(void)
+{
+ ht_t *ht;
+
+ ht = _ht_root;
+ while(ht)
+ {
+ if(ht->dbtable.len>0 && ht->dbmode!=0)
+ {
+ LM_DBG("sync db table [%.*s] from ht [%.*s]\n",
+ ht->dbtable.len, ht->dbtable.s,
+ ht->name.len, ht->name.s);
+ ht_db_delete_records(&ht->dbtable);
+ if(ht_db_save_table(ht, &ht->dbtable)!=0)
+ LM_ERR("failed sync'ing hash table [%.*s] to db\n",
+ ht->name.len, ht->name.s);
+ }
+ ht = ht->next;
+ }
+ return 0;
+}
+
int ht_has_autoexpire(void)
{
ht_t *ht;
diff --git a/modules_k/htable/ht_api.h b/modules_k/htable/ht_api.h
index 99ff84a..71c8e21 100644
--- a/modules_k/htable/ht_api.h
+++ b/modules_k/htable/ht_api.h
@@ -54,6 +54,7 @@ typedef struct _ht
unsigned int htid;
unsigned int htexpire;
str dbtable;
+ int dbmode;
unsigned int htsize;
ht_entry_t *entries;
struct _ht *next;
@@ -65,7 +66,7 @@ typedef struct _ht_pv {
pv_elem_t *pve;
} ht_pv_t, *ht_pv_p;
-int ht_pkg_init(str *name, int autoexp, str *dbtable, int size);
+int ht_pkg_init(str *name, int autoexp, str *dbtable, int size, int dbmode);
int ht_shm_init(void);
int ht_destroy(void);
int ht_set_cell(ht_t *ht, str *name, int type, int_str *val, int mode);
@@ -79,6 +80,7 @@ int ht_cell_free(ht_cell_t *cell);
int ht_table_spec(char *spec);
ht_t* ht_get_table(str *name);
int ht_db_load_tables(void);
+int ht_db_sync_tables(void);
int ht_has_autoexpire(void);
void ht_timer(unsigned int ticks, void *param);
diff --git a/modules_k/htable/ht_db.c b/modules_k/htable/ht_db.c
index 0f88500..7addf81 100644
--- a/modules_k/htable/ht_db.c
+++ b/modules_k/htable/ht_db.c
@@ -43,6 +43,9 @@ str ht_db_vtype_column = str_init("value_type");
str ht_db_value_column = str_init("key_value");
int ht_fetch_rows = 100;
+/**
+ * init module parameters
+ */
int ht_db_init_params(void)
{
if(ht_db_url.s==0)
@@ -62,6 +65,9 @@ int ht_db_init_params(void)
return 0;
}
+/**
+ * initialize database connection
+ */
int ht_db_init_con(void)
{
/* binding to DB module */
@@ -79,6 +85,10 @@ int ht_db_init_con(void)
}
return 0;
}
+
+/**
+ * open database connection
+ */
int ht_db_open_con(void)
{
/* open a connection with the database */
@@ -93,6 +103,9 @@ int ht_db_open_con(void)
return 0;
}
+/**
+ * close database connection
+ */
int ht_db_close_con(void)
{
if (ht_db_con!=NULL && ht_dbf.close!=NULL)
@@ -104,6 +117,9 @@ int ht_db_close_con(void)
#define HT_NAME_BUF_SIZE 256
static char ht_name_buf[HT_NAME_BUF_SIZE];
+/**
+ * load content of a db table in hash table
+ */
int ht_db_load_table(ht_t *ht, str *dbtable, int mode)
{
db_key_t db_cols[4] = {&ht_db_name_column, &ht_db_ktype_column,
@@ -290,3 +306,94 @@ error:
}
+/**
+ * save hash table content back to database
+ */
+int ht_db_save_table(ht_t *ht, str *dbtable)
+{
+ db_key_t db_cols[4] = {&ht_db_name_column, &ht_db_ktype_column,
+ &ht_db_vtype_column, &ht_db_value_column};
+ db_val_t db_vals[4];
+ ht_cell_t *it;
+ str tmp;
+ int i;
+
+ if(ht_db_con==NULL)
+ {
+ LM_ERR("no db connection\n");
+ return -1;
+ }
+
+ if (ht_dbf.use_table(ht_db_con, dbtable) < 0)
+ {
+ LM_ERR("failed to use_table\n");
+ return -1;
+ }
+
+ LM_DBG("save the content of hash table [%.*s] to database in [%.*s]\n",
+ ht->name.len, ht->name.s, dbtable->len, dbtable->s);
+
+ for(i=0; i<ht->htsize; i++)
+ {
+ lock_get(&ht->entries[i].lock);
+ it = ht->entries[i].first;
+ while(it)
+ {
+ db_vals[0].type = DB1_STR;
+ db_vals[0].nul = 0;
+ db_vals[0].val.str_val.s = it->name.s;
+ db_vals[0].val.str_val.len = it->name.len;
+
+ db_vals[1].type = DB1_INT;
+ db_vals[1].nul = 0;
+ db_vals[1].val.int_val = 0;
+
+ db_vals[2].type = DB1_INT;
+ db_vals[2].nul = 0;
+ db_vals[2].val.int_val = 0;
+
+ db_vals[3].type = DB1_STR;
+ db_vals[3].nul = 0;
+ if(it->flags&AVP_VAL_STR) {
+ db_vals[3].val.str_val.s = it->value.s.s;
+ db_vals[3].val.str_val.len = it->value.s.len;
+ } else {
+ tmp.s = sint2str((long)it->value.n, &tmp.len);
+ db_vals[3].val.str_val.s = tmp.s;
+ db_vals[3].val.str_val.len = tmp.len;
+ }
+ if(ht_dbf.insert(ht_db_con, db_cols, db_vals, 4) < 0)
+ {
+ LM_ERR("failed to store key [%.*s] in table [%.*s]\n",
+ it->name.len, it->name.s,
+ dbtable->len, dbtable->s);
+ }
+ it = it->next;
+ }
+ }
+ return 0;
+}
+
+
+/**
+ * delete databse table
+ */
+int ht_db_delete_records(str *dbtable)
+{
+ if(ht_db_con==NULL)
+ {
+ LM_ERR("no db connection\n");
+ return -1;
+ }
+
+ if (ht_dbf.use_table(ht_db_con, dbtable) < 0)
+ {
+ LM_ERR("failed to use_table\n");
+ return -1;
+ }
+
+ if(ht_dbf.delete(ht_db_con, NULL, NULL, NULL, 0) < 0)
+ LM_ERR("failed to detele db records in [%.*s]\n",
+ dbtable->len, dbtable->s);
+ return 0;
+}
diff --git a/modules_k/htable/ht_db.h b/modules_k/htable/ht_db.h
index 14802bd..1edb345 100644
--- a/modules_k/htable/ht_db.h
+++ b/modules_k/htable/ht_db.h
@@ -38,5 +38,7 @@ int ht_db_init_con(void);
int ht_db_open_con(void);
int ht_db_close_con(void);
int ht_db_load_table(ht_t *ht, str *dbtable, int mode);
+int ht_db_save_table(ht_t *ht, str *dbtable);
+int ht_db_delete_records(str *dbtable);
#endif
diff --git a/modules_k/htable/htable.c b/modules_k/htable/htable.c
index ac01e32..f7af1d9 100644
--- a/modules_k/htable/htable.c
+++ b/modules_k/htable/htable.c
@@ -212,6 +212,18 @@ static int child_init(int rank)
*/
static void destroy(void)
{
+ /* sync back to db */
+ if(ht_db_url.len>0)
+ {
+ if(ht_db_init_con()==0)
+ {
+ if(ht_db_open_con()==0)
+ {
+ ht_db_sync_tables();
+ ht_db_close_con();
+ }
+ }
+ }
ht_destroy();
}