Module: sip-router Branch: master Commit: 99da07de696c1f5368bf74ea82fe7df7f8db61a0 URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=99da07de...
Author: Daniel-Constantin Mierla miconda@gmail.com Committer: Daniel-Constantin Mierla miconda@gmail.com Date: Tue Jul 22 13:33:24 2014 +0200
uac: new rpc command - uac.reg_reload
- reload the records from database - old records are kept for at least 150sec more to be sure no active registration process is using them - therefore reload cannot executed more often than 150sec
---
modules/uac/uac_reg.c | 164 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 154 insertions(+), 10 deletions(-)
diff --git a/modules/uac/uac_reg.c b/modules/uac/uac_reg.c index da3fdd0..f1344be 100644 --- a/modules/uac/uac_reg.c +++ b/modules/uac/uac_reg.c @@ -50,6 +50,7 @@ #define UAC_REG_AUTHSENT (1<<3)
#define MAX_UACH_SIZE 2048 +#define UAC_REG_GC_INTERVAL 150
typedef struct _reg_uac { @@ -88,10 +89,13 @@ typedef struct _reg_entry typedef struct _reg_ht { unsigned int htsize; + time_t stime; reg_entry_t *entries; } reg_ht_t;
static reg_ht_t *_reg_htable = NULL; +static reg_ht_t *_reg_htable_gc = NULL; +static gen_lock_t *_reg_htable_gc_lock = NULL;
int reg_use_domain = 0; int reg_timer_interval = 90; @@ -168,10 +172,50 @@ int uac_reg_init_ht(unsigned int sz) { int i;
+ _reg_htable_gc_lock = (gen_lock_t*)shm_malloc(sizeof(gen_lock_t)); + if(_reg_htable_gc_lock == NULL) + { + LM_ERR("no more shm for lock\n"); + return -1; + } + if(lock_init(_reg_htable_gc_lock)==0) + { + LM_ERR("cannot init global lock\n"); + shm_free((void*)_reg_htable_gc_lock); + return -1; + } + _reg_htable_gc = (reg_ht_t*)shm_malloc(sizeof(reg_ht_t)); + if(_reg_htable_gc==NULL) + { + LM_ERR("no more shm\n"); + lock_destroy(_reg_htable_gc_lock); + shm_free((void*)_reg_htable_gc_lock); + return -1; + } + memset(_reg_htable_gc, 0, sizeof(reg_ht_t)); + _reg_htable_gc->htsize = sz; + + _reg_htable_gc->entries = + (reg_entry_t*)shm_malloc(_reg_htable_gc->htsize*sizeof(reg_entry_t)); + if(_reg_htable_gc->entries==NULL) + { + LM_ERR("no more shm.\n"); + shm_free(_reg_htable_gc); + lock_destroy(_reg_htable_gc_lock); + shm_free((void*)_reg_htable_gc_lock); + return -1; + } + memset(_reg_htable_gc->entries, 0, _reg_htable_gc->htsize*sizeof(reg_entry_t)); + + _reg_htable = (reg_ht_t*)shm_malloc(sizeof(reg_ht_t)); if(_reg_htable==NULL) { LM_ERR("no more shm\n"); + shm_free(_reg_htable_gc->entries); + shm_free(_reg_htable_gc); + lock_destroy(_reg_htable_gc_lock); + shm_free((void*)_reg_htable_gc_lock); return -1; } memset(_reg_htable, 0, sizeof(reg_ht_t)); @@ -182,7 +226,11 @@ int uac_reg_init_ht(unsigned int sz) if(_reg_htable->entries==NULL) { LM_ERR("no more shm.\n"); + shm_free(_reg_htable_gc->entries); + shm_free(_reg_htable_gc); shm_free(_reg_htable); + lock_destroy(_reg_htable_gc_lock); + shm_free((void*)_reg_htable_gc_lock); return -1; } memset(_reg_htable->entries, 0, _reg_htable->htsize*sizeof(reg_entry_t)); @@ -199,6 +247,10 @@ int uac_reg_init_ht(unsigned int sz) } shm_free(_reg_htable->entries); shm_free(_reg_htable); + shm_free(_reg_htable_gc->entries); + shm_free(_reg_htable_gc); + lock_destroy(_reg_htable_gc_lock); + shm_free((void*)_reg_htable_gc_lock); return -1; } } @@ -215,6 +267,37 @@ int uac_reg_free_ht(void) reg_item_t *it = NULL; reg_item_t *it0 = NULL;
+ if(_reg_htable_gc_lock != NULL) + { + lock_destroy(_reg_htable_gc_lock); + shm_free((void*)_reg_htable_gc_lock); + _reg_htable_gc_lock = NULL; + } + if(_reg_htable_gc!=NULL) + { + for(i=0; i<_reg_htable_gc->htsize; i++) + { + it = _reg_htable_gc->entries[i].byuuid; + while(it) + { + it0 = it; + it = it->next; + shm_free(it0); + } + it = _reg_htable_gc->entries[i].byuser; + while(it) + { + it0 = it; + it = it->next; + shm_free(it0->r); + shm_free(it0); + } + } + shm_free(_reg_htable_gc->entries); + shm_free(_reg_htable_gc); + _reg_htable_gc = NULL; + } + if(_reg_htable==NULL) { LM_DBG("no hash table\n"); @@ -250,31 +333,30 @@ int uac_reg_free_ht(void) /** * */ -int uac_reg_reset_ht(void) +int uac_reg_reset_ht_gc(void) { int i; reg_item_t *it = NULL; reg_item_t *it0 = NULL;
- if(_reg_htable==NULL) + if(_reg_htable_gc==NULL) { LM_DBG("no hash table\n"); return -1; } - for(i=0; i<_reg_htable->htsize; i++) + for(i=0; i<_reg_htable_gc->htsize; i++) { - lock_get(&_reg_htable->entries[i].lock); /* free entries */ - it = _reg_htable->entries[i].byuuid; + it = _reg_htable_gc->entries[i].byuuid; while(it) { it0 = it; it = it->next; shm_free(it0); } - _reg_htable->entries[i].byuuid = NULL; - _reg_htable->entries[i].isize=0; - it = _reg_htable->entries[i].byuser; + _reg_htable_gc->entries[i].byuuid = NULL; + _reg_htable_gc->entries[i].isize=0; + it = _reg_htable_gc->entries[i].byuser; while(it) { it0 = it; @@ -282,10 +364,48 @@ int uac_reg_reset_ht(void) shm_free(it0->r); shm_free(it0); } + _reg_htable_gc->entries[i].byuser = NULL; + _reg_htable_gc->entries[i].usize = 0; + } + return 0; +} + +/** + * + */ +int uac_reg_ht_shift(void) +{ + time_t tn; + int i; + + if(_reg_htable==NULL || _reg_htable_gc==NULL) + { + LM_ERR("data struct invalid\n"); + return -1; + } + tn = time(NULL); + + lock_get(_reg_htable_gc_lock); + if(_reg_htable_gc->stime > tn-UAC_REG_GC_INTERVAL) { + lock_release(_reg_htable_gc_lock); + LM_ERR("shifting the memory table is not possible in less than %d\n", UAC_REG_GC_INTERVAL); + return -1; + } + uac_reg_reset_ht_gc(); + for(i=0; i<_reg_htable->htsize; i++) + { + /* shift entries */ + _reg_htable_gc->entries[i].byuuid = _reg_htable->entries[i].byuuid; + _reg_htable_gc->entries[i].byuser = _reg_htable->entries[i].byuser; + _reg_htable_gc->stime = time(NULL); + + /* reset active table entries */ + _reg_htable->entries[i].byuuid = NULL; + _reg_htable->entries[i].isize=0; _reg_htable->entries[i].byuser = NULL; _reg_htable->entries[i].usize = 0; - lock_release(&_reg_htable->entries[i].lock); } + lock_release(_reg_htable_gc_lock); return 0; }
@@ -989,12 +1109,16 @@ int uac_reg_load_db(void) } } while(RES_ROW_N(db_res)>0); reg_dbf.free_result(reg_db_con, db_res); + reg_dbf.close(reg_db_con);
done: return 0;
error: - reg_dbf.free_result(reg_db_con, db_res); + if (reg_db_con) { + reg_dbf.free_result(reg_db_con, db_res); + reg_dbf.close(reg_db_con); + } return -1; }
@@ -1385,13 +1509,33 @@ static void rpc_uac_reg_disable(rpc_t* rpc, void* ctx) rpc_uac_reg_update_flag(rpc, ctx, 0, UAC_REG_DISABLED); }
+static const char* rpc_uac_reg_reload_doc[2] = { + "Reload records from database.", + 0 +};
+static void rpc_uac_reg_reload(rpc_t* rpc, void* ctx) +{ + int ret; + if(uac_reg_ht_shift()<0) { + rpc->fault(ctx, 500, "Failed to shift records - check log messages"); + return; + } + lock_get(_reg_htable_gc_lock); + ret = uac_reg_load_db(); + lock_release(_reg_htable_gc_lock); + if(ret<0) { + rpc->fault(ctx, 500, "Failed to reload records - check log messages"); + return; + } +}
rpc_export_t uac_reg_rpc[] = { {"uac.reg_dump", rpc_uac_reg_dump, rpc_uac_reg_dump_doc, 0}, {"uac.reg_info", rpc_uac_reg_info, rpc_uac_reg_info_doc, 0}, {"uac.reg_enable", rpc_uac_reg_enable, rpc_uac_reg_enable_doc, 0}, {"uac.reg_disable", rpc_uac_reg_disable, rpc_uac_reg_disable_doc, 0}, + {"uac.reg_reload", rpc_uac_reg_reload, rpc_uac_reg_reload_doc, 0}, {0, 0, 0, 0} };