瀏覽代碼

ndb_redis: added parameters to control connect and command timeouts

Morten Isaksen 9 年之前
父節點
當前提交
8992021f25

+ 39 - 34
modules/ndb_redis/doc/ndb_redis.xml

@@ -9,38 +9,43 @@
 ]>
 
 <book xmlns:xi="http://www.w3.org/2001/XInclude">
-    <bookinfo>
-	<title>NDB_REDIS Module</title>
-	<productname class="trade">sip-router.org</productname>
-	<authorgroup>
-	    <author>
-		<firstname>Daniel-Constantin</firstname>
-		<surname>Mierla</surname>
-		<email>[email protected]</email>
-	    </author>
-	    <editor>
-		<firstname>Daniel-Constantin</firstname>
-		<surname>Mierla</surname>
-		<email>[email protected]</email>
-	    </editor>
-	    <author>
-		<firstname>Vicente</firstname>
-		<surname>Hernando</surname>
-		<email>[email protected]</email>
-	    </author>
-	</authorgroup>
-	<copyright>
-	    <year>2011</year>
-	    <holder>asipto.com</holder>
-	</copyright>
-	<copyright>
-	    <year>2012</year>
-	    <holder>www.systemonenoc.com</holder>
-	</copyright>
-    </bookinfo>
-    <toc></toc>
-    
-    <xi:include href="ndb_redis_admin.xml"/>
-    
-    
+	<bookinfo>
+		<title>NDB_REDIS Module</title>
+		<productname class="trade">sip-router.org</productname>
+		<authorgroup>
+			<author>
+				<firstname>Daniel-Constantin</firstname>
+				<surname>Mierla</surname>
+				<email>[email protected]</email>
+			</author>
+			<editor>
+				<firstname>Daniel-Constantin</firstname>
+				<surname>Mierla</surname>
+				<email>[email protected]</email>
+			</editor>
+			<author>
+				<firstname>Vicente</firstname>
+				<surname>Hernando</surname>
+				<email>[email protected]</email>
+			</author>
+			<author>
+				<firstname>Morten</firstname>
+				<surname>Isaksen</surname>
+				<email>[email protected]</email>
+			</author>
+		</authorgroup>
+		<copyright>
+			<year>2011</year>
+			<holder>asipto.com</holder>
+		</copyright>
+		<copyright>
+			<year>2012</year>
+			<holder>www.systemonenoc.com</holder>
+		</copyright>
+	</bookinfo>
+	<toc></toc>
+
+	<xi:include href="ndb_redis_admin.xml"/>
+
+
 </book>

+ 46 - 6
modules/ndb_redis/doc/ndb_redis_admin.xml

@@ -10,9 +10,9 @@
 <!-- Module User's Guide -->
 
 <chapter>
-	
+
 	<title>&adminguide;</title>
-	
+
 	<section>
 	<title>Overview</title>
 	<para>
@@ -108,6 +108,46 @@ modparam("ndb_redis", "server", "name=srvY;unix=/tmp/redis.sock;db=3")
 			<programlisting format="linespecific">
 ...
 modparam("ndb_redis", "init_without_redis", 1)
+...
+			</programlisting>
+		</example>
+	</section>
+	<section id="ndb_redis.p.connect_timeout">
+		<title><varname>connect_timeout</varname> (int)</title>
+		<para>
+			The timeout when connecting to the redis server
+		</para>
+		<para>
+		<emphasis>
+			Default value is 1000 ms.
+		</emphasis>
+		</para>
+		<example>
+			<title>Set <varname>connect_timeout</varname> parameter</title>
+			<programlisting format="linespecific">
+...
+modparam("ndb_redis", "connect_timeout", 500)
+...
+			</programlisting>
+		</example>
+	</section>
+	<section id="ndb_redis.p.cmd_timeout">
+		<title><varname>cmd_timeout</varname> (int)</title>
+		<para>
+			The timeout for each query to the redis server. If the redis server does
+			not reply within the timeout value, the command will fail and kamailio will
+			continue executing the cfg file.
+		</para>
+		<para>
+		<emphasis>
+			Default value is 1000 ms.
+		</emphasis>
+		</para>
+		<example>
+			<title>Set <varname>cmd_timeout</varname> parameter</title>
+			<programlisting format="linespecific">
+...
+modparam("ndb_redis", "cmd_timeout", 500)
 ...
 			</programlisting>
 		</example>
@@ -117,10 +157,10 @@ modparam("ndb_redis", "init_without_redis", 1)
 	<section>
 	<title>Functions</title>
 	<section id="ndb_redis.f.redis_cmd">
-	    <title>
+		<title>
 		<function moreinfo="none">redis_cmd(srvname, command, ..., replyid)</function>
-	    </title>
-	    <para>
+		</title>
+		<para>
 			Send a command to REDIS server identified by srvname. The reply will
 			be stored in a local container identified by replyid. All the
 			parameters can be strings with pseudo-variables that are evaluated
@@ -194,7 +234,7 @@ if(redis_cmd("srvN", "HMGET foo_key field1 field3", "r")) {
 }
 ...
 </programlisting>
-	    </example>
+		</example>
 	</section>
 	<section id="ndb_redis.f.redis_free">
 	<title>

+ 14 - 9
modules/ndb_redis/ndb_redis_mod.c

@@ -43,6 +43,8 @@ MODULE_VERSION
 
 int redis_srv_param(modparam_t type, void *val);
 int init_without_redis = 0;
+int redis_connect_timeout_param = 1000;
+int redis_cmd_timeout_param = 1000;
 
 static int w_redis_cmd3(struct sip_msg* msg, char* ssrv, char* scmd,
 		char* sres);
@@ -87,6 +89,8 @@ static cmd_export_t cmds[]={
 static param_export_t params[]={
 	{"server",         PARAM_STRING|USE_FUNC_PARAM, (void*)redis_srv_param},
 	{"init_without_redis", INT_PARAM, &init_without_redis},
+	{"connect_timeout", INT_PARAM, &redis_connect_timeout_param},
+	{"cmd_timeout", INT_PARAM, &redis_cmd_timeout_param},
 	{0, 0, 0}
 };
 
@@ -114,10 +118,9 @@ static int child_init(int rank)
 	if (rank==PROC_INIT || rank==PROC_MAIN || rank==PROC_TCP_MAIN)
 		return 0;
 
-	if(redisc_init()<0)
-	{
-	  LM_ERR("failed to initialize redis connections\n");
-	  return -1;
+	if(redisc_init()<0) {
+		LM_ERR("failed to initialize redis connections\n");
+		return -1;
 	}
 	return 0;
 }
@@ -553,7 +556,7 @@ static int pv_get_redisc(struct sip_msg *msg,  pv_param_t *param,
 					if(pos!=-1)
 						return pv_get_null(msg, param, res);
 					return pv_get_sintval(msg, param, res,
-										  (int)rpv->reply->rplRedis->integer);
+									(int)rpv->reply->rplRedis->integer);
 				case REDIS_REPLY_ARRAY:
 					if(pos<0 || pos>=(int)rpv->reply->rplRedis->elements)
 						return pv_get_null(msg, param, res);
@@ -566,7 +569,7 @@ static int pv_get_redisc(struct sip_msg *msg,  pv_param_t *param,
 							return pv_get_strval(msg, param, res, &s);
 						case REDIS_REPLY_INTEGER:
 							return pv_get_sintval(msg, param, res,
-												  (int)rpv->reply->rplRedis->element[pos]->integer);
+										(int)rpv->reply->rplRedis->element[pos]->integer);
 						default:
 							return pv_get_null(msg, param, res);
 					}
@@ -583,7 +586,8 @@ static int pv_get_redisc(struct sip_msg *msg,  pv_param_t *param,
 		case 3:
 			/* size */
 			if(rpv->reply->rplRedis->type == REDIS_REPLY_ARRAY) {
-				return pv_get_uintval(msg, param, res, (unsigned int)rpv->reply->rplRedis->elements);
+				return pv_get_uintval(msg, param, res,
+						(unsigned int)rpv->reply->rplRedis->elements);
 			} else {
 				return pv_get_null(msg, param, res);
 			}
@@ -591,14 +595,15 @@ static int pv_get_redisc(struct sip_msg *msg,  pv_param_t *param,
 			/* type */
 			if(pos==-1)
 				return pv_get_sintval(msg, param, res,
-									  rpv->reply->rplRedis->type);
+								rpv->reply->rplRedis->type);
 			if(rpv->reply->rplRedis->type != REDIS_REPLY_ARRAY)
 				return pv_get_null(msg, param, res);
 			if(pos<0 || pos>=(int)rpv->reply->rplRedis->elements)
 				return pv_get_null(msg, param, res);
 			if(rpv->reply->rplRedis->element[pos]==NULL)
 				return pv_get_null(msg, param, res);
-			return pv_get_sintval(msg, param, res, rpv->reply->rplRedis->element[pos]->type);
+			return pv_get_sintval(msg, param, res,
+					rpv->reply->rplRedis->element[pos]->type);
 		default:
 			/* We do nothing. */
 			return pv_get_null(msg, param, res);

+ 38 - 22
modules/ndb_redis/redis_client.c

@@ -42,6 +42,9 @@ static redisc_server_t *_redisc_srv_list=NULL;
 static redisc_reply_t *_redisc_rpl_list=NULL;
 
 extern int init_without_redis;
+extern int redis_connect_timeout_param;
+extern int redis_cmd_timeout_param;
+
 
 /**
  *
@@ -52,10 +55,14 @@ int redisc_init(void)
 	unsigned int port, db;
 	redisc_server_t *rsrv=NULL;
 	param_t *pit = NULL;
-	struct timeval tv;
+	struct timeval tv_conn;
+	struct timeval tv_cmd;
+
+	tv_conn.tv_sec = (int) redis_connect_timeout_param / 1000;
+	tv_conn.tv_usec = (int) (redis_connect_timeout_param % 1000) * 1000;
 
-	tv.tv_sec = 1;
-	tv.tv_usec = 0;
+	tv_cmd.tv_sec = (int) redis_cmd_timeout_param / 1000;
+	tv_cmd.tv_usec = (int) (redis_cmd_timeout_param % 1000) * 1000;
 
 	if(_redisc_srv_list==NULL)
 	{
@@ -92,9 +99,9 @@ int redisc_init(void)
 
 		if(unix_sock_path != NULL) {
 			LM_DBG("Connecting to unix socket: %s\n", unix_sock_path);
-			rsrv->ctxRedis = redisConnectUnixWithTimeout(unix_sock_path, tv);
+			rsrv->ctxRedis = redisConnectUnixWithTimeout(unix_sock_path, tv_conn);
 		} else {
-			rsrv->ctxRedis = redisConnectWithTimeout(addr, port, tv);
+			rsrv->ctxRedis = redisConnectWithTimeout(addr, port, tv_conn);
 		}
 
 		if(!rsrv->ctxRedis)
@@ -103,6 +110,8 @@ int redisc_init(void)
 			goto err2;
 		if ((pass != NULL) && redisc_check_auth(rsrv, pass))
 			goto err2;
+		if (redisSetTimeout(rsrv->ctxRedis, tv_cmd))
+			goto err2;
 		if (redisCommandNR(rsrv->ctxRedis, "PING"))
 			goto err2;
 		if (redisCommandNR(rsrv->ctxRedis, "SELECT %i", db))
@@ -115,10 +124,10 @@ int redisc_init(void)
 err2:
 	if (unix_sock_path != NULL) {
 		LM_ERR("error communicating with redis server [%.*s] (unix:%s db:%d): %s\n",
-			   rsrv->sname->len, rsrv->sname->s, unix_sock_path, db, rsrv->ctxRedis->errstr);
+				rsrv->sname->len, rsrv->sname->s, unix_sock_path, db, rsrv->ctxRedis->errstr);
 	} else {
 		LM_ERR("error communicating with redis server [%.*s] (%s:%d/%d): %s\n",
-			   rsrv->sname->len, rsrv->sname->s, addr, port, db, rsrv->ctxRedis->errstr);
+				rsrv->sname->len, rsrv->sname->s, addr, port, db, rsrv->ctxRedis->errstr);
 	}
 	if (init_without_redis==1)
 	{
@@ -130,10 +139,10 @@ err2:
 err:
 	if (unix_sock_path != NULL) {
 		LM_ERR("failed to connect to redis server [%.*s] (unix:%s db:%d)\n",
-			   rsrv->sname->len, rsrv->sname->s, unix_sock_path, db);
+				rsrv->sname->len, rsrv->sname->s, unix_sock_path, db);
 	} else {
 		LM_ERR("failed to connect to redis server [%.*s] (%s:%d/%d)\n",
-			   rsrv->sname->len, rsrv->sname->s, addr, port, db);
+				rsrv->sname->len, rsrv->sname->s, addr, port, db);
 	}
 	if (init_without_redis==1)
 	{
@@ -266,10 +275,15 @@ int redisc_reconnect_server(redisc_server_t *rsrv)
 	char *addr, *pass, *unix_sock_path = NULL;
 	unsigned int port, db;
 	param_t *pit = NULL;
-	struct timeval tv;
+	struct timeval tv_conn;
+	struct timeval tv_cmd;
+
+	tv_conn.tv_sec = (int) redis_connect_timeout_param / 1000;
+	tv_conn.tv_usec = (int) (redis_connect_timeout_param % 1000) * 1000;
+
+	tv_cmd.tv_sec = (int) redis_cmd_timeout_param / 1000;
+	tv_cmd.tv_usec = (int) (redis_cmd_timeout_param % 1000) * 1000;
 
-	tv.tv_sec = 1;
-	tv.tv_usec = 0;
 	addr = "127.0.0.1";
 	port = 6379;
 	db = 0;
@@ -299,9 +313,9 @@ int redisc_reconnect_server(redisc_server_t *rsrv)
 	}
 
 	if(unix_sock_path != NULL) {
-		rsrv->ctxRedis = redisConnectUnixWithTimeout(unix_sock_path, tv);
+		rsrv->ctxRedis = redisConnectUnixWithTimeout(unix_sock_path, tv_conn);
 	} else {
-		rsrv->ctxRedis = redisConnectWithTimeout(addr, port, tv);
+		rsrv->ctxRedis = redisConnectWithTimeout(addr, port, tv_conn);
 	}
 	if(!rsrv->ctxRedis)
 		goto err;
@@ -309,6 +323,8 @@ int redisc_reconnect_server(redisc_server_t *rsrv)
 		goto err2;
 	if ((pass != NULL) && redisc_check_auth(rsrv, pass))
 		goto err2;
+	if (redisSetTimeout(rsrv->ctxRedis, tv_cmd))
+		goto err2;
 	if (redisCommandNR(rsrv->ctxRedis, "PING"))
 		goto err2;
 	if (redisCommandNR(rsrv->ctxRedis, "SELECT %i", db))
@@ -319,18 +335,18 @@ int redisc_reconnect_server(redisc_server_t *rsrv)
 err2:
 	if (unix_sock_path != NULL) {
 		LM_ERR("error communicating with redis server [%.*s] (unix:%s db:%d): %s\n",
-			   rsrv->sname->len, rsrv->sname->s, unix_sock_path, db, rsrv->ctxRedis->errstr);
+				rsrv->sname->len, rsrv->sname->s, unix_sock_path, db, rsrv->ctxRedis->errstr);
 	} else {
 		LM_ERR("error communicating with redis server [%.*s] (%s:%d/%d): %s\n",
-			   rsrv->sname->len, rsrv->sname->s, addr, port, db, rsrv->ctxRedis->errstr);
+				rsrv->sname->len, rsrv->sname->s, addr, port, db, rsrv->ctxRedis->errstr);
 	}
 err:
 	if (unix_sock_path != NULL) {
 		LM_ERR("failed to connect to redis server [%.*s] (unix:%s db:%d)\n",
-			   rsrv->sname->len, rsrv->sname->s, unix_sock_path, db);
+				rsrv->sname->len, rsrv->sname->s, unix_sock_path, db);
 	} else {
 		LM_ERR("failed to connect to redis server [%.*s] (%s:%d/%d)\n",
-			   rsrv->sname->len, rsrv->sname->s, addr, port, db);
+				rsrv->sname->len, rsrv->sname->s, addr, port, db);
 	}
 	return -1;
 }
@@ -429,8 +445,8 @@ void * redisc_exec_argv(redisc_server_t *rsrv, int argc, const char **argv, cons
 	if(rsrv==NULL || rsrv->ctxRedis==NULL)
 	{
 		LM_ERR("no redis context found for server %.*s\n",
-			  (rsrv)?rsrv->sname->len:0,
-			  (rsrv)?rsrv->sname->s:"");
+				(rsrv)?rsrv->sname->len:0,
+				(rsrv)?rsrv->sname->s:"");
 		return NULL;
 	}
 	if(argc<=0)
@@ -461,7 +477,7 @@ void * redisc_exec_argv(redisc_server_t *rsrv, int argc, const char **argv, cons
 	else
 	{
 		LM_ERR("Unable to reconnect to server: %.*s\n",
-			   rsrv->sname->len, rsrv->sname->s);
+				rsrv->sname->len, rsrv->sname->s);
 		return NULL;
 	}
 
@@ -528,7 +544,7 @@ int redisc_free_reply(str *name)
 	while(rpl) {
 
 		if(rpl->hname==hid && rpl->rname.len==name->len
-		   && strncmp(rpl->rname.s, name->s, name->len)==0) {
+				&& strncmp(rpl->rname.s, name->s, name->len)==0) {
 			if(rpl->rplRedis) {
 				freeReplyObject(rpl->rplRedis);
 				rpl->rplRedis = NULL;