Bladeren bron

htable: init tables directly in shm

- initial developed version didn't have access to shared memory during
  parameter setting, starting with 3.0 shm is initialized before module
  parameter section, thus code was simplified getting rid of the
  temporary clone in pkg
- helper structure and functions to store and parse 'key=>value' strings
  added
- parsing of 'htable' parameter format was simplified reusing the
  parse_params() function
Daniel-Constantin Mierla 14 jaren geleden
bovenliggende
commit
eef79d7f5e
3 gewijzigde bestanden met toevoegingen van 136 en 121 verwijderingen
  1. 133 118
      modules_k/htable/ht_api.c
  2. 2 2
      modules_k/htable/ht_api.h
  3. 1 1
      modules_k/htable/htable.c

+ 133 - 118
modules_k/htable/ht_api.c

@@ -24,7 +24,9 @@
 
 #include "../../mem/shm_mem.h"
 #include "../../mem/mem.h"
+#include "../../shm_init.h"
 #include "../../dprint.h"
+#include "../../parser/parse_param.h"
 #include "../../lib/kcore/hash_func.h"
 #include "../../ut.h"
 #include "../../re.h"
@@ -38,8 +40,104 @@
 
 
 ht_t *_ht_root = NULL;
-ht_t *_ht_pkg_root = NULL;
 
+typedef struct _keyvalue {
+	str key;
+	str value;
+	int type;
+	union {
+		param_t *params;
+	} u;
+} keyvalue_t;
+
+
+#define KEYVALUE_TYPE_NONE		0
+#define KEYVALUE_TYPE_PARAMS	1
+
+/**
+ * parse a string like: 'key=>value'
+ *   - the value can be parameter list: 'name1=value1;...;nameX=valueX'
+ */
+int keyvalue_parse_str(str *data, int type, keyvalue_t *res)
+{
+	char *p;
+	str s;
+	str in;
+	param_hooks_t phooks;
+
+	if(data==NULL || data->s==NULL || data->len<=0 || res==NULL)
+	{
+		LM_ERR("invalid parameters\n");
+		return -1;
+	}
+
+	memset(res, 0, sizeof(keyvalue_t));
+
+	in.s = data->s;
+	in.len = data->len;
+
+	p = in.s;
+	while(p<in.s+in.len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r'))
+		p++;
+	if(p>in.s+in.len || *p=='\0')
+		goto error;
+	res->key.s = p;
+	while(p < in.s + in.len)
+	{
+		if(*p=='=' || *p==' ' || *p=='\t' || *p=='\n' || *p=='\r')
+			break;
+		p++;
+	}
+	if(p>in.s+in.len || *p=='\0')
+		goto error;
+	res->key.len = (int)(p - res->key.s);
+	if(*p!='=')
+	{
+		while(p<in.s+in.len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r'))
+			p++;
+		if(p>in.s+in.len || *p=='\0' || *p!='=')
+			goto error;
+	}
+	p++;
+	if(*p!='>')
+		goto error;
+	p++;
+	while(p<in.s+in.len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r'))
+		p++;
+
+	s.s = p;
+	s.len = in.s + in.len - p;
+	res->value.s = s.s;
+	res->value.len = s.len;
+	res->type = type;
+	if(type==KEYVALUE_TYPE_PARAMS)
+	{
+		if(s.s[s.len-1]==';')
+			s.len--;
+		if (parse_params(&s, CLASS_ANY, &phooks, &res->u.params)<0)
+		{
+			LM_ERR("failed parsing params value\n");
+			goto error;
+		}
+	}
+	return 0;
+error:
+	LM_ERR("invalid input parameter [%.*s] at [%d]\n", in.len, in.s,
+			(int)(p-in.s));
+	return -1;
+}
+
+void keyvalue_destroy(keyvalue_t *res)
+{
+	if(res==NULL)
+		return;
+	if(res->type==KEYVALUE_TYPE_PARAMS)
+	{
+		if(res->u.params!=NULL)
+			free_params(res->u.params);
+	}
+	memset(res, 0, sizeof(keyvalue_t));
+}
 
 ht_cell_t* ht_cell_new(str *name, int type, int_str *val, unsigned int cellid)
 {
@@ -86,7 +184,6 @@ int ht_cell_free(ht_cell_t *cell)
 	return 0;
 }
 
-
 int ht_cell_pkg_free(ht_cell_t *cell)
 {
 	if(cell==NULL)
@@ -95,6 +192,7 @@ int ht_cell_pkg_free(ht_cell_t *cell)
 	return 0;
 }
 
+
 ht_t* ht_get_table(str *name)
 {
 	unsigned int htid;
@@ -117,7 +215,7 @@ ht_t* ht_get_table(str *name)
 	return NULL;
 }
 
-int ht_pkg_init(str *name, int autoexp, str *dbtable, int size, int dbmode)
+int ht_add_table(str *name, int autoexp, str *dbtable, int size, int dbmode)
 {
 	unsigned int htid;
 	ht_t *ht;
@@ -125,7 +223,7 @@ int ht_pkg_init(str *name, int autoexp, str *dbtable, int size, int dbmode)
 	htid = ht_compute_hash(name);
 
 	/* does it exist */
-	ht = _ht_pkg_root;
+	ht = _ht_root;
 	while(ht!=NULL)
 	{
 		if(htid == ht->htid && name->len==ht->name.len 
@@ -137,10 +235,10 @@ int ht_pkg_init(str *name, int autoexp, str *dbtable, int size, int dbmode)
 		ht = ht->next;
 	}
 
-	ht = (ht_t*)pkg_malloc(sizeof(ht_t));
+	ht = (ht_t*)shm_malloc(sizeof(ht_t));
 	if(ht==NULL)
 	{
-		LM_ERR("no more pkg\n");
+		LM_ERR("no more shared memory\n");
 		return -1;
 	}
 	memset(ht, 0, sizeof(ht_t));
@@ -157,35 +255,24 @@ int ht_pkg_init(str *name, int autoexp, str *dbtable, int size, int dbmode)
 		ht->dbtable = *dbtable;
 	ht->dbmode = dbmode;
 
-	ht->next = _ht_pkg_root;
-	_ht_pkg_root = ht;
+	ht->next = _ht_root;
+	_ht_root = ht;
 	return 0;
 }
 
-int ht_shm_init(void)
+int ht_init_tables(void)
 {
-	ht_t *htp;
-	ht_t *htp0;
 	ht_t *ht;
 	int i;
 
-	htp = _ht_pkg_root;
+	ht = _ht_root;
 
-	while(htp)
+	while(ht)
 	{
-		htp0 = htp->next;
-		ht = (ht_t*)shm_malloc(sizeof(ht_t));
-		if(ht==NULL)
-		{
-			LM_ERR("no more shm\n");
-			return -1;
-		}
-		memcpy(ht, htp, sizeof(ht_t));
-
 		ht->entries = (ht_entry_t*)shm_malloc(ht->htsize*sizeof(ht_entry_t));
 		if(ht->entries==NULL)
 		{
-			LM_ERR("no more shm.\n");
+			LM_ERR("no more shm for [%.*s]\n", ht->name.len, ht->name.s);
 			shm_free(ht);
 			return -1;
 		}
@@ -195,7 +282,8 @@ int ht_shm_init(void)
 		{
 			if(lock_init(&ht->entries[i].lock)==0)
 			{
-				LM_ERR("cannot initalize lock[%d]\n", i);
+				LM_ERR("cannot initalize lock[%d] in [%.*s]\n", i,
+						ht->name.len, ht->name.s);
 				i--;
 				while(i>=0)
 				{
@@ -208,12 +296,8 @@ int ht_shm_init(void)
 
 			}
 		}
-		ht->next = _ht_root;
-		_ht_root = ht;
-		pkg_free(htp);
-		htp = htp0;
+		ht = ht->next;
 	}
-	_ht_pkg_root = NULL;
 
 	return 0;
 }
@@ -512,129 +596,60 @@ int ht_dbg(void)
 
 int ht_table_spec(char *spec)
 {
+	keyvalue_t kval;
 	str name;
 	str dbtable = {0, 0};
 	unsigned int autoexpire = 0;
 	unsigned int size = 4;
-	int type = 0;
 	unsigned int dbmode = 0;
 	str in;
 	str tok;
-	char *p;
+	param_t *pit=NULL;
 
+	if(!shm_initialized())
+	{
+		LM_ERR("shared memory was not initialized\n");
+		return -1;
+	}
 	/* parse: name=>dbtable=abc;autoexpire=123;size=123*/
 	in.s = spec;
 	in.len = strlen(in.s);
-
-	p = in.s;
-	while(p<in.s+in.len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r'))
-		p++;
-	if(p>in.s+in.len || *p=='\0')
-		goto error;
-	name.s = p;
-	while(p < in.s + in.len)
-	{
-		if(*p=='=' || *p==' ' || *p=='\t' || *p=='\n' || *p=='\r')
-			break;
-		p++;
-	}
-	if(p>in.s+in.len || *p=='\0')
-		goto error;
-	name.len = p - name.s;
-	if(*p!='=')
-	{
-		while(p<in.s+in.len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r'))
-			p++;
-		if(p>in.s+in.len || *p=='\0' || *p!='=')
-			goto error;
-	}
-	p++;
-	if(*p!='>')
-		goto error;
-	p++;
-	while(p<in.s+in.len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r'))
-		p++;
-
-next_token:
-	tok.s = p;
-	while(p < in.s + in.len)
+	if(keyvalue_parse_str(&in, KEYVALUE_TYPE_PARAMS, &kval)<0)
 	{
-		if(*p=='=' || *p==' ' || *p=='\t' || *p=='\n' || *p=='\r')
-			break;
-		p++;
+		LM_ERR("failed parsing: %.*s\n", in.len, in.s);
+		return -1;
 	}
-	if(p>in.s+in.len || *p=='\0')
-		goto error;
-	tok.len = p - tok.s;
-	if(tok.len==7 && strncmp(tok.s, "dbtable", 7)==0)
-		type = 1;
-	else if(tok.len==10 && strncmp(tok.s, "autoexpire", 10)==0)
-		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;
+	name = kval.key;
 
-	if(*p!='=')
+	for (pit = kval.u.params; pit; pit=pit->next)
 	{
-		while(p<in.s+in.len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r'))
-			p++;
-		if(p>in.s+in.len || *p=='\0' || *p!='=')
-			goto error;
-	}
-	p++;
-	while(p<in.s+in.len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r'))
-		p++;
-	if(p>in.s+in.len || *p=='\0')
-		goto error;
-	tok.s = p;
-	while(p < in.s + in.len)
-	{
-		if(*p==';' || *p==' ' || *p=='\t' || *p=='\n' || *p=='\r')
-			break;
-		p++;
-	}
-	if(p>in.s+in.len || *p=='\0')
-		goto error;
-	tok.len = p - tok.s;
-	switch(type)
-	{
-		case 1:
+		tok = pit->body;
+		if(pit->name.len==7 && strncmp(pit->name.s, "dbtable", 7)==0) {
 			dbtable = tok;
 			LM_DBG("htable [%.*s] - dbtable [%.*s]\n", name.len, name.s,
 					dbtable.len, dbtable.s);
-			break;
-		case 2:
+		} else if(pit->name.len==10 && strncmp(pit->name.s, "autoexpire", 10)==0) {
 			if(str2int(&tok, &autoexpire)!=0)
 				goto error;
 			LM_DBG("htable [%.*s] - expire [%u]\n", name.len, name.s,
 					autoexpire);
-			break;
-		case 3:
+		} else if(pit->name.len==4 && strncmp(pit->name.s, "size", 4)==0) {
 			if(str2int(&tok, &size)!=0)
 				goto error;
 			LM_DBG("htable [%.*s] - size [%u]\n", name.len, name.s,
 					size);
-			break;
-		case 4:
+		} else if(pit->name.len==6 && strncmp(pit->name.s, "dbmode", 6)==0) {
 			if(str2int(&tok, &dbmode)!=0)
 				goto error;
 			LM_DBG("htable [%.*s] - dbmode [%u]\n", name.len, name.s,
 					dbmode);
-			break;
+		} else { goto error; }
 	}
-	while(p<in.s+in.len && (*p==';' || *p==' ' || *p=='\t'
-				|| *p=='\n' || *p=='\r'))
-		p++;
-	if(p<in.s+in.len)
-		goto next_token;
 
-	return ht_pkg_init(&name, autoexpire, &dbtable, size, dbmode);
+	return ht_add_table(&name, autoexpire, &dbtable, size, dbmode);
 
 error:
-	LM_ERR("invalid htable parameter [%.*s] at [%d]\n", in.len, in.s,
-			(int)(p-in.s));
+	LM_ERR("invalid htable parameter [%.*s]\n", in.len, in.s);
 	return -1;
 }
 

+ 2 - 2
modules_k/htable/ht_api.h

@@ -66,8 +66,8 @@ 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 dbmode);
-int ht_shm_init(void);
+int ht_add_table(str *name, int autoexp, str *dbtable, int size, int dbmode);
+int ht_init_tables(void);
 int ht_destroy(void);
 int ht_set_cell(ht_t *ht, str *name, int type, int_str *val, int mode);
 int ht_del_cell(ht_t *ht, str *name);

+ 1 - 1
modules_k/htable/htable.c

@@ -144,7 +144,7 @@ static int mod_init(void)
 		return -1;
 	}
 
-	if(ht_shm_init()!=0)
+	if(ht_init_tables()!=0)
 		return -1;
 	ht_db_init_params();