Преглед изворни кода

core: pv - new parameters to control the size of pv cache

- pv_cache_limit - the limit how many pv declarations in the cache
  after which an action is taken. Default value is 2048
- pv_cache_action - specify what action to be done when the size
  of pv cache is exceeded. If 0, print an warning log message when
  the limit is exceeded. If 1, warning log messages is printed and
  the cache systems tries to drop a $sht(...) declaration. Default is 0

This tries to cope better with the situation of declaring too many
variables when using kemi scripts

(cherry picked from commit 6dc9ee1701019c8db994710c11f7e05447cbae92)
Daniel-Constantin Mierla пре 7 година
родитељ
комит
efe8504652
5 измењених фајлова са 97 додато и 4 уклоњено
  1. 6 0
      src/core/cfg.lex
  2. 7 1
      src/core/cfg.y
  3. 9 3
      src/core/cfg_core.c
  4. 2 0
      src/core/cfg_core.h
  5. 73 0
      src/core/pvapi.c

+ 6 - 0
src/core/cfg.lex

@@ -437,6 +437,8 @@ KILL_TIMEOUT	"exit_timeout"|"ser_kill_timeout"
 MAX_WLOOPS		"max_while_loops"
 PVBUFSIZE		"pv_buffer_size"
 PVBUFSLOTS		"pv_buffer_slots"
+PVCACHELIMIT	"pv_cache_limit"
+PVCACHEACTION	"pv_cache_action"
 HTTP_REPLY_PARSE	"http_reply_hack"|"http_reply_parse"
 VERSION_TABLE_CFG	"version_table"
 VERBOSE_STARTUP		"verbose_startup"
@@ -917,6 +919,10 @@ IMPORTFILE      "import_file"
 									return PVBUFSIZE; }
 <INITIAL>{PVBUFSLOTS}			{	count(); yylval.strval=yytext;
 									return PVBUFSLOTS; }
+<INITIAL>{PVCACHELIMIT}			{	count(); yylval.strval=yytext;
+									return PVCACHELIMIT; }
+<INITIAL>{PVCACHEACTION}		{	count(); yylval.strval=yytext;
+									return PVCACHEACTION; }
 <INITIAL>{HTTP_REPLY_PARSE}		{	count(); yylval.strval=yytext;
 									return HTTP_REPLY_PARSE; }
 <INITIAL>{VERSION_TABLE_CFG}  { count(); yylval.strval=yytext; return VERSION_TABLE_CFG;}

+ 7 - 1
src/core/cfg.y

@@ -475,6 +475,8 @@ extern char *default_routename;
 %token MAX_WLOOPS
 %token PVBUFSIZE
 %token PVBUFSLOTS
+%token PVCACHELIMIT
+%token PVCACHEACTION
 %token HTTP_REPLY_PARSE
 %token VERSION_TABLE_CFG
 %token VERBOSE_STARTUP
@@ -1554,8 +1556,12 @@ assign_stm:
 	| MAX_WLOOPS EQUAL error { yyerror("number expected"); }
 	| PVBUFSIZE EQUAL NUMBER { pv_set_buffer_size($3); }
 	| PVBUFSIZE EQUAL error { yyerror("number expected"); }
-	| PVBUFSLOTS EQUAL NUMBER { pv_set_buffer_slots($3); }
+	| PVBUFSLOTS EQUAL NUMBER { default_core_cfg.pv_cache_limit=$3; }
 	| PVBUFSLOTS EQUAL error { yyerror("number expected"); }
+	| PVCACHELIMIT EQUAL NUMBER { default_core_cfg.pv_cache_action=$3; }
+	| PVCACHELIMIT EQUAL error { yyerror("number expected"); }
+	| PVCACHEACTION EQUAL NUMBER { pv_set_buffer_slots($3); }
+	| PVCACHEACTION EQUAL error { yyerror("number expected"); }
 	| HTTP_REPLY_PARSE EQUAL NUMBER { http_reply_parse=$3; }
 	| HTTP_REPLY_PARSE EQUAL error { yyerror("boolean value expected"); }
 	| VERBOSE_STARTUP EQUAL NUMBER { ksr_verbose_startup=$3; }

+ 9 - 3
src/core/cfg_core.c

@@ -120,7 +120,9 @@ struct cfg_group_core default_core_cfg = {
 	L_DBG, /*!< latency cfg log */
 	L_ERR, /*!< latency log */
 	0, /*!< latency limit db */
-	0 /*!< latency limit action */
+	0, /*!< latency limit action */
+	2048,  /*!< pv_cache_limit */
+	0  /*!< pv_cache_action */
 };
 
 void	*core_cfg = &default_core_cfg;
@@ -323,8 +325,12 @@ cfg_def_t core_cfg_def[] = {
 	{"latency_log",		CFG_VAR_INT|CFG_ATOMIC,	0, 0, 0, 0,
 		"log level for latency limits alert messages"},
 	{"latency_limit_db",		CFG_VAR_INT|CFG_ATOMIC,	0, 0, 0, 0,
-		"limit is ms for alerting on time consuming db commands"},
+		"limit in ms for alerting on time consuming db commands"},
 	{"latency_limit_action",		CFG_VAR_INT|CFG_ATOMIC,	0, 0, 0, 0,
-		"limit is ms for alerting on time consuming config actions"},
+		"limit in ms for alerting on time consuming config actions"},
+	{"pv_cache_limit",		CFG_VAR_INT|CFG_ATOMIC,	0, 0, 0, 0,
+		"limit to alert if too many vars in pv cache"},
+	{"pv_cache_action",		CFG_VAR_INT|CFG_ATOMIC,	0, 0, 0, 0,
+		"action to do if too many vars in pv cache"},
 	{0, 0, 0, 0, 0, 0}
 };

+ 2 - 0
src/core/cfg_core.h

@@ -109,6 +109,8 @@ struct cfg_group_core {
 	int latency_log; /*!< log level for latency limits messages */
 	int latency_limit_db; /*!< alert limit of running db commands */
 	int latency_limit_action; /*!< alert limit of running cfg actions */
+	int pv_cache_limit; /*!< alert limit of having too many vars in pv cache */
+	int pv_cache_action; /*!< action to be taken on pv cache limit */
 };
 
 extern struct cfg_group_core default_core_cfg;

+ 73 - 0
src/core/pvapi.c

@@ -59,6 +59,8 @@ static int _pv_table_set = 0;
 
 static pv_cache_t* _pv_cache[PV_CACHE_SIZE];
 static int _pv_cache_set = 0;
+static int _pv_cache_counter = 0;
+static int _pv_cache_drop_index = 0;
 
 /**
  *
@@ -254,6 +256,67 @@ done:
 	return 0;
 }
 
+/**
+ *
+ */
+int pv_cache_drop(void)
+{
+	int i;
+	pv_cache_t *pvp;
+	pv_cache_t *pvi;
+
+	if(_pv_cache_set==0) {
+		LM_DBG("PV cache not initialized\n");
+		return 0;
+	}
+	/* round-robin on slots to find a $sht(...) to drop */
+	_pv_cache_drop_index = (_pv_cache_drop_index + 1) % PV_CACHE_SIZE;
+	for(i=_pv_cache_drop_index; i<PV_CACHE_SIZE; i++) {
+		pvi = _pv_cache[i];
+		pvp = NULL;
+		while(pvi) {
+			if(pvi->pvname.len>5 && strncmp(pvi->pvname.s, "$sht(", 5)==0) {
+				LM_DBG("dropping from pv cache [%d]: %.*s\n", i,
+						pvi->pvname.len, pvi->pvname.s);
+				if(pvp) {
+					pvp->next = pvi->next;
+				} else {
+					_pv_cache[i] = pvi->next;
+				}
+				if(pvi->spec.pvp.pvn.nfree) {
+					pvi->spec.pvp.pvn.nfree((void*)(&pvi->spec.pvp.pvn));
+				}
+				pkg_free(pvi);
+				return 1;
+			}
+			pvi = pvi->next;
+		}
+	}
+	for(i=0; i<_pv_cache_drop_index; i++) {
+		pvi = _pv_cache[i];
+		pvp = NULL;
+		while(pvi) {
+			if(pvi->pvname.len>5 && strncmp(pvi->pvname.s, "$sht(", 5)==0) {
+				LM_DBG("dropping from pv cache [%d]: %.*s\n", i,
+						pvi->pvname.len, pvi->pvname.s);
+				if(pvp) {
+					pvp->next = pvi->next;
+				} else {
+					_pv_cache[i] = pvi->next;
+				}
+				if(pvi->spec.pvp.pvn.nfree) {
+					pvi->spec.pvp.pvn.nfree((void*)(&pvi->spec.pvp.pvn));
+				}
+				pkg_free(pvi);
+				return 1;
+			}
+			pvi = pvi->next;
+		}
+	}
+	LM_WARN("no suitable variable found to drop from pv cache\n");
+	return 0;
+}
+
 /**
  *
  */
@@ -268,6 +331,16 @@ pv_spec_t* pv_cache_add(str *name)
 		LM_DBG("PV cache not initialized, doing it now\n");
 		pv_init_cache();
 	}
+	if(_pv_cache_counter+1>=cfg_get(core, core_cfg, pv_cache_limit)) {
+		if(_pv_cache_counter+1==cfg_get(core, core_cfg, pv_cache_limit)) {
+			LM_WARN("pv cache limit is going to be exceeded"
+					" - pkg memory may get filled with pv declarations\n");
+		} else {
+			if(cfg_get(core, core_cfg, pv_cache_action)==1) {
+				pv_cache_drop();
+			}
+		}
+	}
 	pvid = get_hash1_raw(name->s, name->len);
 	pvn = (pv_cache_t*)pkg_malloc(sizeof(pv_cache_t) + name->len + 1);
 	if(pvn==0)