[sr-dev] git:master: htable: option to save content of htable to db at shutdown

Elena-Ramona Modroiu ramona at rosdev.ro
Tue Feb 8 12:24:58 CET 2011


Module: sip-router
Branch: master
Commit: ebf12d93251124d619e6d12093181eab5bab5818
URL:    http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=ebf12d93251124d619e6d12093181eab5bab5818

Author: Elena-Ramona Modroiu <ramona at asipto.com>
Committer: Elena-Ramona Modroiu <ramona at 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();
 }
 




More information about the sr-dev mailing list