From 1682c6bcc1d653757f1c7cea304d6996a73d8e0b Mon Sep 17 00:00:00 2001
From: Sergey Poznyakoff <gray@Pirx.gnu.org.ua>
Date: Sat, 13 Jun 2009 18:50:28 +0300
Subject: [PATCH] Fix reloading sequence maps

* include/sm/map.h (sm_map_initopt, sm_map_addopt): New prototypes.
* libsmmap/mapconfopen.c (sm_mapconfopen): Properly handle
MST_SEQUENCE type: use sm_map_addopt instead of sm_map_setopt.
* libsmmap/mapopt.c (collect_options_from): New auxiliary finction.
(sm_map_initopt, sm_map_addopt): New functions.
(sm_map_setopt): Use collect_options_from.
---
 include/sm/map.h       |    2 +
 libsmmap/mapconfopen.c |   97 ++++++++++++++++++++++++++++++++++++++-
 libsmmap/mapopt.c      |  117 +++++++++++++++++++++++++++++++++++-------------
 3 files changed, 181 insertions(+), 35 deletions(-)

diff --git a/include/sm/map.h b/include/sm/map.h
index e9e2a35..ec40c43 100644
--- a/include/sm/map.h
+++ b/include/sm/map.h
@@ -130,7 +130,9 @@ sm_ret_T sm_map_open(sm_maps_P _maps, const sm_cstr_P _name, const sm_cstr_P _ty
 sm_ret_T sm_map_close(sm_map_P _map, uint32_t _flags);
 sm_ret_T sm_map_destroy(sm_map_P _map, uint32_t flags);
 sm_ret_T sm_map_reopen(sm_map_P _map, uint32_t flags, ...);
+void sm_map_initopt(sm_map_P map);
 sm_ret_T sm_map_setopt(sm_map_P _map, ...);
+sm_ret_T sm_map_addopt(sm_map_P map, ...);
 sm_ret_T sm_map_getopt(sm_map_P _map, int _which, void *_valp);
 
 sm_ret_T sm_map_lookup(sm_map_P _map, uint32_t _flags, sm_map_key_P _key, sm_map_data_P _data);
diff --git a/libsmmap/mapconfopen.c b/libsmmap/mapconfopen.c
index 8216a68..e14eccd 100644
--- a/libsmmap/mapconfopen.c
+++ b/libsmmap/mapconfopen.c
@@ -8,7 +8,7 @@
  */
 
 #include "sm/generic.h"
-SM_RCSID("@(#)$Id: mapconfopen.c,v 1.13 2009/07/03 04:47:35 ca Exp $")
+SM_RCSID("@(#)$Id: mapconfopen.c,v 1.12 2007/01/11 17:51:20 ca Exp $")
 
 #include "sm/error.h"
 #include "sm/string.h"
@@ -38,22 +38,113 @@ SM_RCSID("@(#)$Id: mapconfopen.c,v 1.13 2009/07/03 04:47:35 ca Exp $")
 sm_ret_T
 sm_mapconfopen(map_decl_P mapdef, sm_maps_P maps, const char *confdir)
 {
-	uint n;
+	uint n, i;
 	sm_ret_T ret;
 	mapspec_P md_maps;
+	sm_map_P map;
+	sm_cstr_P mtype, mname, sname;
 
 	SM_REQUIRE(mapdef != NULL);
 	SM_REQUIRE(maps != NULL);
+	mtype = mname = sname = NULL;
 	for (n = 0; n < mapdef->mapdecl_n; n++) {
 		md_maps = mapdef->mapdecl_maps + n;
 		if (NULL == md_maps)
 			continue;
-		ret = sm_mapcnfopen(mapdef, maps, confdir, md_maps);
+		mname = NULL;
+		mtype = sm_cstr_scpyn0((const uchar *)md_maps->mst_type,
+				strlen(md_maps->mst_type));
+		ret = sm_error_temp(SM_EM_MAP, ENOMEM);
+		if (NULL == mtype)
+			goto error;
+		mname = sm_cstr_scpyn0((const uchar *)md_maps->mst_name,
+				strlen(md_maps->mst_name));
+		if (NULL == mname)
+			goto error;
+		map = NULL;
+		ret = sm_map_create(maps, mtype, 0, &map);
+		if (sm_is_err(ret))
+			goto error;
+
+		switch (md_maps->mst_kind) {
+		  case MST_HASH:
+			if (md_maps->mst_hash.mst_hash_fn == NULL ||
+			    *md_maps->mst_hash.mst_hash_fn == '\0')
+			{
+				ret = sm_error_temp(SM_EM_MAP, EINVAL);
+				goto error;
+			}
+			else {
+				const char *mpath;
+
+				SM_GEN_MAP_PATH(mpath,
+					md_maps->mst_hash.mst_hash_path,
+					confdir, md_maps->mst_hash.mst_hash_fn,
+					NULL, error);
+				ret = sm_map_open(maps, mname, mtype, 0, mpath,
+					SMAP_MODE_RDONLY, &map, SMPO_END);
+			}
+			break;
+
+		  case MST_PASSWD:
+			ret = sm_map_open(maps, mname, mtype, 0, NULL,
+				SMAP_MODE_RDONLY, &map, SMPO_END);
+			break;
+
+		  case MST_SOCKET:
+			ret = sm_map_open(maps, mname, mtype, 0,
+				md_maps->mst_socket.mst_socket_mapname,
+				SMAP_MODE_RDONLY, &map,
+				SMPO_SOCKPATH,
+					md_maps->mst_socket.mst_socket_path,
+				SMPO_PORT, md_maps->mst_socket.mst_socket_port,
+				SMPO_IPV4, md_maps->mst_socket.mst_socket_ipv4,
+				SMPO_MIN_OCONN, md_maps->mst_socket.mst_socket_min_oconn,
+				SMPO_MAX_OCONN, md_maps->mst_socket.mst_socket_max_oconn,	  
+				SMPO_END);
+			break;
+
+		  case MST_SEQUENCE:
+			sm_map_initopt(map);
+			for (i = 0;
+			     md_maps->mst_seq.mst_seq_maps[i] != NULL && ret == SM_SUCCESS;
+			     i++)
+			{
+				char *mn;
+
+				mn = md_maps->mst_seq.mst_seq_maps[i];
+				sname = sm_cstr_scpyn0((const uchar *)mn,
+						strlen(mn));
+				if (NULL == sname) {
+					ret = sm_error_temp(SM_EM_MAP, ENOMEM);
+					goto error;
+				}
+				ret = sm_map_addopt(map, SMPO_MAPNAME, sname,
+						    SMPO_END);
+			}
+			if (sm_is_err(ret))
+				break;
+			ret = sm_map_open(maps, mname, mtype, 0, NULL, SMAP_MODE_RDONLY,
+					&map, SMPO_END);
+			break;
+
+		  default:
+			ret = sm_error_perm(SM_EM_MAP, EINVAL);
+			break;
+		}
+		if (sm_is_err(ret))
+			goto error;
+		SM_CSTR_FREE(mtype);
+		SM_CSTR_FREE(mname);
+		ret = sm_mapname_add(maps, map);
 		if (sm_is_err(ret))
 			goto error;
 	}
 	return SM_SUCCESS;
 
   error:
+	SM_CSTR_FREE(mtype);
+	SM_CSTR_FREE(mname);
+	SM_CSTR_FREE(sname);
 	return ret;
 }
diff --git a/libsmmap/mapopt.c b/libsmmap/mapopt.c
index 3acaf6f..6ea4970 100644
--- a/libsmmap/mapopt.c
+++ b/libsmmap/mapopt.c
@@ -17,6 +17,44 @@ SM_RCSID("@(#)$Id: mapopt.c,v 1.12 2009/08/15 15:29:20 ca Exp $")
 #include "sm/map.h"
 #include "sm/mapc.h"
 
+static sm_ret_T
+collect_options_from(sm_map_P map, int i, va_list ap)
+{
+	int opttype;
+	
+	for (; i < SM_MAP_MAX_OPT; i++)
+	{
+		opttype = va_arg(ap, int);
+		map->sm_map_opts[i].sm_map_opt_type = opttype;
+		if (opttype == SMPO_END)
+			break;
+		switch (SMPO_GET_TYPE(opttype))
+		{
+		  case SMPO_INT:
+			map->sm_map_opts[i].sm_map_opt_int = va_arg(ap, int);
+			break;
+		  case SMPO_PTR:
+			map->sm_map_opts[i].sm_map_opt_ptr = va_arg(ap,
+								    void *);
+			break;
+		  default:
+			/* crash and burn */
+			SM_ASSERT(opttype == SMPO_END);
+			break;
+		}
+	}
+	if (i >= SM_MAP_MAX_OPT)
+		return sm_error_perm(SM_EM_MAP, SM_E_FULL);
+	return SM_SUCCESS;
+}
+
+void
+sm_map_initopt(sm_map_P map)
+{
+	SM_IS_MAP(map);
+	sm_memzero(&map->sm_map_opts, sizeof(map->sm_map_opts));
+}
+
 /*
 **  MAP_SETOPT -- set options for map
 **
@@ -41,39 +79,54 @@ sm_map_setopt(sm_map_P map, ...)
 	SM_IS_MAPC(mapc);
 	sm_memzero(&map->sm_map_opts, sizeof(map->sm_map_opts));
 	va_start(ap, map);
-	i = 0;
-	while (i < SM_MAP_MAX_OPT) {
-		opttype = va_arg(ap, int);
-		if (opttype == SMPO_END)
-			break;
-		if (SMPO_SET_FLAGS == opttype) {
-			mapc->sm_mapc_flags |= va_arg(ap, int);
-			continue;
-		}
-		if (SMPO_CLR_FLAGS == opttype) {
-			mapc->sm_mapc_flags &= ~(va_arg(ap, int));
-			continue;
-		}
-		map->sm_map_opts[i].sm_map_opt_type = opttype;
-		switch (SMPO_GET_TYPE(opttype)) {
-		  case SMPO_INT:
-			map->sm_map_opts[i].sm_map_opt_int = va_arg(ap, int);
-			break;
-		  case SMPO_PTR:
-			map->sm_map_opts[i].sm_map_opt_ptr = va_arg(ap, void *);
-			break;
-		  default:
-			/* crash and burn */
-			SM_ASSERT(opttype == SMPO_END);
-			break;
-		}
-		++i;
-	}
+	ret = collect_options_from(map, 0, ap);
 	va_end(ap);
-	if (i >= SM_MAP_MAX_OPT)
-		return sm_error_perm(SM_EM_MAP, SM_E_FULL);
+	if (sm_is_error(ret))
+		return ret;
+	
+	if (mapc->sm_mapc_setoptf != NULL)
+	{
+		va_start(ap, map);
+		ret = mapc->sm_mapc_setoptf(map, ap);
+		va_end(ap);
+	}
+	else
+		ret = sm_error_perm(SM_EM_MAP, EINVAL);	/* XXX */
+	return ret;
+}	
 
-	if (mapc->sm_mapc_setoptf != NULL) {
+/*
+**  MAP_ADDOPT -- add options to map
+**
+**	Parameters:
+**		map -- map
+**		... -- options
+**
+**	Returns:
+**		usual sm_error code
+*/
+sm_ret_T
+sm_map_addopt(sm_map_P map, ...)
+{
+	sm_ret_T ret;
+	sm_mapc_P mapc;
+	int i, opttype;
+	va_list ap;
+
+	SM_IS_MAP(map);
+	mapc = map->sm_map_class;
+	SM_IS_MAPC(mapc);
+	for (i = 0; i < SM_MAP_MAX_OPT
+		     && map->sm_map_opts[i].sm_map_opt_type != SMPO_END; i++)
+		;
+	va_start(ap, map);
+	ret = collect_options_from(map, i, ap);
+	va_end(ap);
+	if (sm_is_error(ret))
+		return ret;
+	
+	if (mapc->sm_mapc_setoptf != NULL)
+	{
 		va_start(ap, map);
 		ret = mapc->sm_mapc_setoptf(map, ap);
 		va_end(ap);
@@ -82,7 +135,7 @@ sm_map_setopt(sm_map_P map, ...)
 		ret = sm_error_perm(SM_EM_MAP, EINVAL);	/* XXX */
 	return ret;
 }
-
+	
 /*
 **  MAP_SETONEOPT -- set one option for a map
 **
-- 
1.6.0.3

