Module: sip-router Branch: master Commit: ebf12d93251124d619e6d12093181eab5bab5818 URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=ebf12d93...
Author: Elena-Ramona Modroiu ramona@asipto.com Committer: Elena-Ramona Modroiu ramona@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(); }