Explorar o código

imc: db_mode support

Support db_mode. if db_mode is 2, synch all operations to DB, otherwise use only memory.
Joey Golan %!s(int64=2) %!d(string=hai) anos
pai
achega
b94e158e0f

+ 21 - 0
src/modules/imc/doc/imc_admin.xml

@@ -88,6 +88,27 @@
 ...
 modparam("imc", "db_url", "&exampledb;")
 ...
+</programlisting>
+		</example>
+	</section>
+	<section id="imc.p.db_mode">
+		<title><varname>db_mode</varname>(integer)</title>
+		<para>
+		The module supports 2 modes of operation, high speed memory
+		based storage (mode 0), and database only (mode 2) where all 
+		data is stored in a database, allowing scalability at the
+		expense of speed. Mode 1 is reserved.
+		</para>
+		<para>
+		<emphasis>	Default value is <quote>0</quote> 	
+		</emphasis>
+		</para>
+		<example>
+		<title>Set <varname>db_mode</varname> parameter</title>
+		<programlisting format="linespecific">
+...
+modparam("imc", "db_mode", 2)
+...
 </programlisting>
 		</example>
 	</section>

+ 65 - 246
src/modules/imc/imc.c

@@ -30,14 +30,12 @@
 #include <fcntl.h>
 #include <time.h>
 #include "../../lib/srdb1/db.h"
-#include "../../lib/srdb1/db_res.h"
 #include "../../core/sr_module.h"
 #include "../../core/dprint.h"
 #include "../../core/ut.h"
 #include "../../core/timer.h"
 #include "../../core/str.h"
 #include "../../core/mem/shm_mem.h"
-#include "../../lib/srdb1/db.h"
 #include "../../core/parser/parse_from.h"
 #include "../../core/parser/parse_content.h"
 #include "../../core/parser/contact/parse_contact.h"
@@ -61,20 +59,22 @@ char hdr_buf[1024];
 str all_hdrs;
 
 /** parameters */
-
 db1_con_t *imc_db = NULL;
 db_func_t imc_dbf;
+
 static str db_url  = str_init(DEFAULT_DB_URL);
-str outbound_proxy = {NULL, 0};
+int db_mode = 0;
 
-static str rooms_table   = str_init("imc_rooms");
-static str members_table = str_init("imc_members");
+str rooms_table   = str_init("imc_rooms");
+str members_table = str_init("imc_members");
 
-static str imc_col_username = str_init("username");
-static str imc_col_domain   = str_init("domain");
-static str imc_col_flag     = str_init("flag");
-static str imc_col_room     = str_init("room");
-static str imc_col_name     = str_init("name");
+str imc_col_username = str_init("username");
+str imc_col_domain   = str_init("domain");
+str imc_col_flag     = str_init("flag");
+str imc_col_room     = str_init("room");
+str imc_col_name     = str_init("name");
+
+str outbound_proxy = {NULL, 0};
 
 imc_hentry_p _imc_htable = NULL;
 int imc_hash_size = 4;
@@ -108,11 +108,12 @@ static cmd_export_t cmds[]={
 
 static param_export_t params[]={
 	{"db_url",				PARAM_STR, &db_url},
+	{"db_mode", 			INT_PARAM, &db_mode},
 	{"hash_size",			INT_PARAM, &imc_hash_size},
 	{"imc_cmd_start_char",	PARAM_STR, &imc_cmd_start_str},
 	{"rooms_table",			PARAM_STR, &rooms_table},
 	{"members_table",		PARAM_STR, &members_table},
-	{"outbound_proxy",		PARAM_STR, &outbound_proxy},
+	{"outbound_proxy",		PARAM_STR, &outbound_proxy},	
 	{"extra_hdrs",        PARAM_STR, &extra_hdrs},
 	{"create_on_join", INT_PARAM, &imc_create_on_join},
 	{"check_on_create", INT_PARAM, &imc_check_on_create},
@@ -146,183 +147,6 @@ struct module_exports exports= {
 	destroy     /* module destroy function */
 };
 
-/**
- * the initiating function
- */
-int add_from_db(void)
-{
-	imc_member_p member = NULL;
-	int i, j, flag;
-	db_key_t mq_result_cols[4], mquery_cols[2];
-	db_key_t rq_result_cols[4];
-	db_val_t mquery_vals[2];
-	db1_res_t *r_res= NULL;
-	db1_res_t *m_res= NULL;
-	db_row_t *m_row = NULL, *r_row = NULL;
-	db_val_t *m_row_vals, *r_row_vals = NULL;
-	str name, domain;
-	imc_room_p room = NULL;
-	int er_ret = -1;
-
-	rq_result_cols[0] = &imc_col_name;
-	rq_result_cols[1] = &imc_col_domain;
-	rq_result_cols[2] = &imc_col_flag;
-
-	mq_result_cols[0] = &imc_col_username;
-	mq_result_cols[1] = &imc_col_domain;
-	mq_result_cols[2] = &imc_col_flag;
-
-	mquery_cols[0] = &imc_col_room;
-	mquery_vals[0].type = DB1_STR;
-	mquery_vals[0].nul = 0;
-
-	if(imc_dbf.use_table(imc_db, &rooms_table)< 0)
-	{
-		LM_ERR("use_table failed\n");
-		return -1;
-	}
-
-	if(imc_dbf.query(imc_db,0, 0, 0, rq_result_cols,0, 3, 0,&r_res)< 0)
-	{
-		LM_ERR("failed to querry table\n");
-		return -1;
-	}
-	if(r_res==NULL || r_res->n<=0)
-	{
-		LM_INFO("the query returned no result\n");
-		if(r_res) imc_dbf.free_result(imc_db, r_res);
-		r_res = NULL;
-		return 0;
-	}
-
-	LM_DBG("found %d rooms\n", r_res->n);
-
-	for(i =0 ; i< r_res->n ; i++)
-	{
-		/*add rooms*/
-		r_row = &r_res->rows[i];
-		r_row_vals = ROW_VALUES(r_row);
-
-		name.s = 	r_row_vals[0].val.str_val.s;
-		name.len = strlen(name.s);
-
-		domain.s = 	r_row_vals[1].val.str_val.s;
-		domain.len = strlen(domain.s);
-
-		flag = 	r_row_vals[2].val.int_val;
-
-		room = imc_add_room(&name, &domain, flag);
-		if(room == NULL)
-		{
-			LM_ERR("failed to add room\n ");
-			goto error;
-		}
-
-		/* add members */
-		if(imc_dbf.use_table(imc_db, &members_table)< 0)
-		{
-			LM_ERR("use_table failed\n ");
-			goto error;
-		}
-
-		mquery_vals[0].val.str_val= room->uri;
-
-		if(imc_dbf.query(imc_db, mquery_cols, 0, mquery_vals, mq_result_cols,
-					1, 3, 0, &m_res)< 0)
-		{
-			LM_ERR("failed to querry table\n");
-			goto error;
-		}
-
-		if(m_res==NULL || m_res->n<=0)
-		{
-			LM_INFO("the query returned no result\n");
-			er_ret = 0;
-			goto error; /* each room must have at least one member*/
-		}
-		for(j =0; j< m_res->n; j++)
-		{
-			m_row = &m_res->rows[j];
-			m_row_vals = ROW_VALUES(m_row);
-
-			name.s = m_row_vals[0].val.str_val.s;
-			name.len = strlen(name.s);
-
-			domain.s = m_row_vals[1].val.str_val.s;
-			domain.len = strlen(domain.s);
-
-			flag = m_row_vals[2].val.int_val;
-
-			LM_DBG("adding memeber: [name]=%.*s [domain]=%.*s"
-					" in [room]= %.*s\n", STR_FMT(&name), STR_FMT(&domain),
-					STR_FMT(&room->uri));
-
-			member = imc_add_member(room, &name, &domain, flag);
-			if(member == NULL)
-			{
-				LM_ERR("failed to adding member\n ");
-				goto error;
-			}
-			imc_release_room(room);
-		}
-
-		if(m_res)
-		{
-			imc_dbf.free_result(imc_db, m_res);
-			m_res = NULL;
-		}
-	}
-
-	if(imc_dbf.use_table(imc_db, &members_table)< 0)
-	{
-		LM_ERR("use table failed\n ");
-		goto error;
-	}
-
-	if(imc_dbf.delete(imc_db, 0, 0 , 0, 0) < 0)
-	{
-		LM_ERR("failed to delete information from db\n");
-		goto error;
-	}
-
-	if(imc_dbf.use_table(imc_db, &rooms_table)< 0)
-	{
-		LM_ERR("use table failed\n ");
-		goto error;
-	}
-
-	if(imc_dbf.delete(imc_db, 0, 0 , 0, 0) < 0)
-	{
-		LM_ERR("failed to delete information from db\n");
-		goto error;
-	}
-
-	if(r_res)
-	{
-		imc_dbf.free_result(imc_db, r_res);
-		r_res = NULL;
-	}
-
-	return 0;
-
-error:
-	if(r_res)
-	{
-		imc_dbf.free_result(imc_db, r_res);
-		r_res = NULL;
-	}
-	if(m_res)
-	{
-		imc_dbf.free_result(imc_db, m_res);
-		m_res = NULL;
-	}
-	if(room)
-		imc_release_room(room);
-	return er_ret;
-
-}
-
-
 static int mod_init(void)
 {
 #ifdef STATISTICS
@@ -333,22 +157,19 @@ static int mod_init(void)
 	}
 #endif
 
-	if(imc_rpc_init()<0)
-	{
+	if(imc_rpc_init()<0) {
 		LM_ERR("failed to register RPC commands\n");
 		return -1;
 	}
 
-	if(imc_hash_size <= 0)
-	{
+	if(imc_hash_size <= 0) {
 		LM_ERR("invalid hash size\n");
 		return -1;
 	}
 
 	imc_hash_size = 1 << imc_hash_size;
 
-	if(imc_htable_init() < 0)
-	{
+	if(imc_htable_init() < 0) {
 		LM_ERR("initializing hash table\n");
 		return -1;
 	}
@@ -365,29 +186,34 @@ static int mod_init(void)
 		all_hdrs.len = extra_hdrs.len + imc_hdrs.len;
 	} else {
 		all_hdrs = imc_hdrs;
-	}
+	}	
 
-	/*  binding to mysql module */
-	LM_DBG("db_url=%s/%d/%p\n", ZSW(db_url.s), db_url.len, db_url.s);
+	if(db_mode == 2) {
+		/*  binding to mysql module */
+		LM_DBG("db_url=%s/%d/%p\n", ZSW(db_url.s), db_url.len, db_url.s);
 
-	if (db_bind_mod(&db_url, &imc_dbf))
-	{
-		LM_DBG("database module not found\n");
-		return -1;
-	}
+		if (db_bind_mod(&db_url, &imc_dbf)) {
+			LM_DBG("database module not found\n");
+			return -1;
+		}
 
-	imc_db = imc_dbf.init(&db_url);
-	if (!imc_db)
-	{
-		LM_ERR("failed to connect to the database\n");
-		return -1;
-	}
-	/* read the informations stored in db */
-	if(add_from_db() <0)
-	{
-		LM_ERR("failed to get information from db\n");
-		return -1;
-	}
+		imc_db = imc_dbf.init(&db_url);
+		if (!imc_db) {
+			LM_ERR("failed to connect to the database\n");
+			return -1;
+		}
+
+		/* read the informations stored in db */
+		if (load_rooms_from_db() < 0) {
+			LM_ERR("failed to get information from db\n");
+			return -1;
+		}
+
+		if(imc_db)
+			imc_dbf.close(imc_db);
+
+		imc_db = NULL;
+	}	
 
 	/* load TM API */
 	if (load_tm_api(&tmb)!=0) {
@@ -395,11 +221,7 @@ static int mod_init(void)
 		return -1;
 	}
 
-	imc_cmd_start_char = imc_cmd_start_str.s[0];
-
-	if(imc_db)
-		imc_dbf.close(imc_db);
-	imc_db = NULL;
+	imc_cmd_start_char = imc_cmd_start_str.s[0];	
 
 	return 0;
 }
@@ -412,32 +234,30 @@ static int child_init(int rank)
 	if (rank==PROC_INIT || rank==PROC_TCP_MAIN)
 		return 0; /* do nothing for the main process */
 
-	if (imc_dbf.init==0)
-	{
-		LM_ERR("database not bound\n");
-		return -1;
-	}
-	imc_db = imc_dbf.init(&db_url);
-	if (!imc_db)
-	{
-		LM_ERR("child %d: Error while connecting database\n", rank);
-		return -1;
-	}
-	else
-	{
-		if (imc_dbf.use_table(imc_db, &rooms_table) < 0)
-		{
-			LM_ERR("child %d: Error in use_table '%.*s'\n", rank, STR_FMT(&rooms_table));
+	if (db_mode == 2) {
+		if (imc_dbf.init == 0) {
+			LM_ERR("database not bound\n");
 			return -1;
 		}
-		if (imc_dbf.use_table(imc_db, &members_table) < 0)
-		{
-			LM_ERR("child %d: Error in use_table '%.*s'\n", rank, STR_FMT(&members_table));
+		
+		imc_db = imc_dbf.init(&db_url);		
+		if (!imc_db) {
+			LM_ERR("child %d: Error while connecting database\n", rank);
 			return -1;
 		}
+		else {
+			if (imc_dbf.use_table(imc_db, &rooms_table) < 0) {
+				LM_ERR("child %d: Error in use_table '%.*s'\n", rank, STR_FMT(&rooms_table));
+				return -1;
+			}
+			if (imc_dbf.use_table(imc_db, &members_table) < 0) {
+				LM_ERR("child %d: Error in use_table '%.*s'\n", rank, STR_FMT(&members_table));
+				return -1;
+			}
 
-		LM_DBG("child %d: Database connection opened successfully\n", rank);
-	}
+			LM_DBG("child %d: Database connection opened successfully\n", rank);
+		}
+	}	
 
 	return 0;
 }
@@ -451,8 +271,7 @@ static int ki_imc_manager(struct sip_msg* msg)
 	int ret = -1;
 
 	body.s = get_body( msg );
-	if (body.s==0)
-	{
+	if (body.s==0) {
 		LM_ERR("cannot extract body from msg\n");
 		goto error;
 	}
@@ -508,7 +327,7 @@ static int ki_imc_manager(struct sip_msg* msg)
 				LM_ERR("failed to handle 'create'\n");
 				ret = -30;
 				goto error;
-			}
+			}			
 		break;
 		case IMC_CMDID_JOIN:
 			if(imc_handle_join(msg, &cmd, &src, &dst)<0)
@@ -532,7 +351,7 @@ static int ki_imc_manager(struct sip_msg* msg)
 				LM_ERR("failed to handle 'add'\n");
 				ret = -50;
 				goto error;
-			}
+			}			
 		break;
 		case IMC_CMDID_ACCEPT:
 			if(imc_handle_accept(msg, &cmd, &src, &dst)<0)
@@ -556,7 +375,7 @@ static int ki_imc_manager(struct sip_msg* msg)
 				LM_ERR("failed to handle 'remove'\n");
 				ret = -80;
 				goto error;
-			}
+			}			
 		break;
 		case IMC_CMDID_LEAVE:
 			if(imc_handle_leave(msg, &cmd, &src, &dst)<0)

+ 1 - 0
src/modules/imc/imc.h

@@ -33,6 +33,7 @@ extern str imc_cmd_start_str;
 extern char imc_cmd_start_char;
 extern struct tm_binds tmb;
 extern str outbound_proxy;
+extern int db_mode;
 extern str all_hdrs;
 extern str extra_hdrs;
 extern int imc_create_on_join;

+ 113 - 9
src/modules/imc/imc_cmd.c

@@ -62,6 +62,7 @@ static str msg_join_attempt_bcast = STR_STATIC_INIT(PREFIX "%.*s attempted to jo
 static str msg_join_attempt_ucast = STR_STATIC_INIT(PREFIX "Private rooms are by invitation only. Room owners have been notified.");
 static str msg_invite             = STR_STATIC_INIT(PREFIX "%.*s invites you to join the room (send '%.*saccept' or '%.*sreject')");
 static str msg_add_reject         = STR_STATIC_INIT(PREFIX "You don't have the permmission to add members to this room");
+static str msg_user_modified      = STR_STATIC_INIT(PREFIX "%.*s is now %.*s");
 static str msg_modify_reject      = STR_STATIC_INIT(PREFIX "You don't have the permmission to modify members in this room");
 #if 0
 static str msg_rejected           = STR_STATIC_INIT(PREFIX "%.*s has rejected invitation");
@@ -415,6 +416,14 @@ int imc_handle_create(struct sip_msg* msg, imc_cmd_t *cmd,
 		}
 		LM_DBG("Added room [%.*s]\n", STR_FMT(&rm->uri));
 
+		if (db_mode == 2) {
+			if (add_room_to_db(rm) < 0) {
+				LM_ERR("failed to add room to db\n");
+				goto error;
+			}
+			LM_DBG("Add room [%.*s] to db\n", STR_FMT(&rm->uri));
+		}
+
 		flag_member |= IMC_MEMBER_OWNER;
 		/* adding the owner as the first member*/
 		member = imc_add_member(rm, &src->parsed.user, &src->parsed.host, flag_member);
@@ -425,6 +434,13 @@ int imc_handle_create(struct sip_msg* msg, imc_cmd_t *cmd,
 		LM_DBG("Added [%.*s] as the first member in room [%.*s]\n",
 			   STR_FMT(&member->uri), STR_FMT(&rm->uri));
 
+		if (db_mode == 2) {
+			if (add_room_member_to_db(member, rm, flag_member) < 0) {
+				LM_ERR("failed to add room member [%.*s] to db\n", STR_FMT(&member->uri));
+				goto error;
+			}
+		}
+
 		imc_send_message(&rm->uri, &member->uri, build_headers(msg), &msg_room_created);
 		goto done;
 	}
@@ -457,6 +473,13 @@ int imc_handle_create(struct sip_msg* msg, imc_cmd_t *cmd,
 	LM_DBG("Added [%.*s] as member to room [%.*s]\n", STR_FMT(&member->uri),
 			STR_FMT(&rm->uri));
 
+	if (db_mode == 2) {
+		if (add_room_member_to_db(member, rm, flag_member) < 0) {
+			LM_ERR("failed to add room member [%.*s] to db\n", STR_FMT(&member->uri));
+			goto error;
+		}
+	}
+
 	body.s = imc_body_buf;
 	body.len = snprintf(body.s, sizeof(imc_body_buf), msg_user_joined.s,
 			STR_FMT(format_uri(member->uri)));
@@ -501,6 +524,7 @@ int imc_handle_join(struct sip_msg* msg, imc_cmd_t *cmd,
 		goto error;
 
 	rm = imc_get_room(&room.parsed.user, &room.parsed.host);
+	
 	if (rm == NULL || (rm->flags & IMC_ROOM_DELETED)) {
 		LM_DBG("Room [%.*s] not found\n", STR_FMT(&room.uri));
 
@@ -516,12 +540,28 @@ int imc_handle_join(struct sip_msg* msg, imc_cmd_t *cmd,
 			goto error;
 		}
 		LM_DBG("Created a new room [%.*s]\n", STR_FMT(&rm->uri));
+
+		if (db_mode == 2) {
+			if (add_room_to_db(rm) < 0) {
+				LM_ERR("failed to add room to db\n");
+				goto error;
+			}
+			LM_DBG("Add room [%.*s] to db\n", STR_FMT(&rm->uri));
+		}
+
 		flag_member |= IMC_MEMBER_OWNER;
 		member = imc_add_member(rm, &src->parsed.user, &src->parsed.host, flag_member);
 		if (member == NULL) {
 			LM_ERR("Failed to add new member [%.*s]\n", STR_FMT(&src->uri));
 			goto error;
 		}
+
+		if (db_mode == 2) {
+			if (add_room_member_to_db(member, rm, flag_member) < 0) {
+				LM_ERR("failed to add room member [%.*s] to db\n", STR_FMT(&member->uri));
+				goto error;
+			}
+		}
 		/* send info message */
 		imc_send_message(&rm->uri, &member->uri, build_headers(msg), &msg_room_created);
 		goto done;
@@ -545,6 +585,13 @@ int imc_handle_join(struct sip_msg* msg, imc_cmd_t *cmd,
 			goto error;
 		}
 
+		if (db_mode == 2) {
+			if (add_room_member_to_db(member, rm, flag_member) < 0) {
+				LM_ERR("failed to add room member [%.*s] to db\n", STR_FMT(&member->uri));
+				goto error;
+			}
+		}
+
 		body.len = snprintf(body.s, sizeof(imc_body_buf), msg_user_joined.s,
 				STR_FMT(format_uri(src->uri)));
 	} else {
@@ -638,6 +685,13 @@ int imc_handle_invite(struct sip_msg* msg, imc_cmd_t *cmd,
 		goto error;
 	}
 
+	if (db_mode == 2) {
+		if (add_room_member_to_db(member, rm, flag_member) < 0) {
+			LM_ERR("failed to add room member [%.*s] to db\n", STR_FMT(&member->uri));
+			goto error;
+		}
+	}
+
 	body.s = imc_body_buf;
 	body.len = snprintf(body.s, sizeof(imc_body_buf), msg_invite.s, STR_FMT(format_uri(src->uri)),
 		STR_FMT(&imc_cmd_start_str), STR_FMT(&imc_cmd_start_str));
@@ -743,6 +797,13 @@ int imc_handle_add(struct sip_msg* msg, imc_cmd_t *cmd,
 		goto error;
 	}
 
+	if (db_mode == 2) {
+		if (add_room_member_to_db(member, rm, 0) < 0) {
+			LM_ERR("failed to add room member [%.*s] to db\n", STR_FMT(&member->uri));
+			goto error;
+		}
+	}
+
 	body.s = imc_body_buf;
 	body.len = snprintf(body.s, sizeof(imc_body_buf), msg_user_joined.s, STR_FMT(format_uri(member->uri)));
 
@@ -796,6 +857,13 @@ int imc_handle_accept(struct sip_msg* msg, imc_cmd_t *cmd,
 
 	member->flags &= ~IMC_MEMBER_INVITED;
 
+	if (db_mode == 2) {
+		if (modify_room_member_in_db(member, rm, member->flags) < 0) {
+			LM_ERR("failed to modify room member [%.*s] in db\n", STR_FMT(&member->uri));
+			goto error;
+		}
+	}
+
 	body.s = imc_body_buf;
 	body.len = snprintf(body.s, sizeof(imc_body_buf), msg_user_joined.s, STR_FMT(format_uri(member->uri)));
 
@@ -879,6 +947,13 @@ int imc_handle_remove(struct sip_msg* msg, imc_cmd_t *cmd,
 	member->flags |= IMC_MEMBER_DELETED;
 	imc_del_member(rm, &user.parsed.user, &user.parsed.host);
 
+	if (db_mode == 2) {
+		if (remove_room_member_from_db(member, rm) < 0) {
+			LM_ERR("failed to remove room member\n");
+			goto error;
+		}
+	}
+
 	body.s = imc_body_buf;
 	body.len = snprintf(body.s, sizeof(imc_body_buf), msg_user_left.s, STR_FMT(format_uri(member->uri)));
 
@@ -940,6 +1015,13 @@ int imc_handle_reject(struct sip_msg* msg, imc_cmd_t *cmd,
 
 	imc_del_member(rm, &src->parsed.user, &src->parsed.host);
 
+	if (db_mode == 2) {
+		if( remove_room_member_from_db(member, rm) < 0) {
+			LM_ERR("failed to remove room member\n");
+			goto error;
+		}
+	}
+
 	rv = 0;
 error:
 	if (room.uri.s != NULL) pkg_free(room.uri.s);
@@ -1146,6 +1228,13 @@ int imc_handle_leave(struct sip_msg* msg, imc_cmd_t *cmd,
 	member->flags |= IMC_MEMBER_DELETED;
 	imc_del_member(rm, &src->parsed.user, &src->parsed.host);
 
+	if (db_mode == 2) {
+		if (remove_room_member_from_db(member, rm) < 0) {
+			LM_ERR("failed to remove room member\n");
+			goto error;
+		}
+	}
+
 done:
 	rv = 0;
 error:
@@ -1189,14 +1278,22 @@ int imc_handle_destroy(struct sip_msg* msg, imc_cmd_t *cmd,
 	rm->flags |= IMC_ROOM_DELETED;
 
 	/* braodcast message */
-	imc_room_broadcast(rm, build_headers(msg), &msg_room_destroyed);
+	imc_room_broadcast(rm, build_headers(msg), &msg_room_destroyed);	
+
+	if (db_mode == 2) {
+		LM_DBG("Deleting room [%.*s] from db\n", STR_FMT(&room.uri));
+		if (remove_room_from_db(rm) < 0) {
+			LM_ERR("Failed to delete room [%.*s] from db\n", STR_FMT(&room.uri));
+			goto error;
+		}
+	}
+
+	LM_DBG("Deleting room [%.*s] from htable\n", STR_FMT(&room.uri));
+	imc_del_room(&room.parsed.user, &room.parsed.host);	
 
 	imc_release_room(rm);
 	rm = NULL;
 
-	LM_DBG("Deleting room [%.*s]\n", STR_FMT(&room.uri));
-	imc_del_room(&room.parsed.user, &room.parsed.host);
-
 	rv = 0;
 error:
 	if (room.uri.s != NULL) pkg_free(room.uri.s);
@@ -1341,10 +1438,10 @@ int imc_handle_modify(struct sip_msg* msg, imc_cmd_t *cmd,
 				&& !strncasecmp(cmd->param[1].s, IMC_MEMBER_ADMIN_STR, cmd->param[1].len))
 		{
 			flag_member |= IMC_MEMBER_ADMIN;
-		} else if(cmd->param[1].len==(sizeof(IMC_MEMBER_INVITED_STR)-1)
-				&& !strncasecmp(cmd->param[1].s, IMC_MEMBER_INVITED_STR, cmd->param[1].len))
+		} else if(cmd->param[1].len==(sizeof(IMC_MEMBER_STR)-1)
+				&& !strncasecmp(cmd->param[1].s, IMC_MEMBER_STR, cmd->param[1].len))
 		{
-			flag_member |= IMC_MEMBER_INVITED;
+			flag_member = 0;
 		} else {
 			LM_INFO("Modify command with unknown argument role [%.*s]\n", STR_FMT(&cmd->param[1]));
 			goto error;
@@ -1386,15 +1483,22 @@ int imc_handle_modify(struct sip_msg* msg, imc_cmd_t *cmd,
 		goto error;
 	}
 
-	rv = imc_modify_member(rm, &src->parsed.user, &src->parsed.host, flag_member);
+	rv = imc_modify_member(rm, &member->user, &member->domain, flag_member);
 	
 	if (rv == -1) {
 		LM_ERR("Failed to modify member [%.*s] role [%.*s]\n", STR_FMT(&member->uri), STR_FMT(&cmd->param[1]));
 		goto error;
 	}
 
+	if (db_mode == 2) {
+		if (modify_room_member_in_db(member, rm, flag_member) < 0){
+			LM_ERR("Failed to modify member [%.*s] role [%.*s] in db\n", STR_FMT(&member->uri), STR_FMT(&cmd->param[1]));
+			goto error;
+		}
+	}
+
 	body.s = imc_body_buf;
-	body.len = snprintf(body.s, sizeof(imc_body_buf), msg_user_joined.s, STR_FMT(format_uri(member->uri)));
+	body.len = snprintf(body.s, sizeof(imc_body_buf), msg_user_modified.s, STR_FMT(&member->uri), STR_FMT(&cmd->param[1]));
 
 	if (body.len < 0) {
 		LM_ERR("Error while building response\n");

+ 372 - 3
src/modules/imc/imc_mng.c

@@ -26,12 +26,15 @@
 #include <unistd.h>
 #include <stdio.h>
 
+#include "../../lib/srdb1/db_res.h"
 #include "../../core/mem/mem.h"
 #include "../../core/mem/shm_mem.h"
 #include "../../core/dprint.h"
 #include "../../core/hashes.h"
 
 #include "imc_mng.h"
+#include "imc.h"
+
 /* imc hash table */
 extern imc_hentry_p _imc_htable;
 extern int imc_hash_size;
@@ -65,7 +68,7 @@ int imc_htable_init(void)
 			goto error;
 		}
 	}
-	
+
 	return 0;
 
 error:
@@ -106,6 +109,370 @@ int imc_htable_destroy(void)
 	return 0;
 }
 
+int load_rooms_from_db()
+{
+	imc_member_p member = NULL;
+	int i, j, flag;
+	db_key_t mq_result_cols[4], mquery_cols[2];
+	db_key_t rq_result_cols[4];
+	db_val_t mquery_vals[2];
+	db1_res_t *r_res= NULL;
+	db1_res_t *m_res= NULL;
+	db_row_t *m_row = NULL, *r_row = NULL;
+	db_val_t *m_row_vals, *r_row_vals = NULL;
+	str name, domain;
+	imc_room_p room = NULL;
+	int er_ret = -1;
+
+	rq_result_cols[0] = &imc_col_name;
+	rq_result_cols[1] = &imc_col_domain;
+	rq_result_cols[2] = &imc_col_flag;
+
+	mq_result_cols[0] = &imc_col_username;
+	mq_result_cols[1] = &imc_col_domain;
+	mq_result_cols[2] = &imc_col_flag;
+
+	mquery_cols[0] = &imc_col_room;
+	mquery_vals[0].type = DB1_STR;
+	mquery_vals[0].nul = 0;
+
+	if(imc_dbf.use_table(imc_db, &rooms_table)< 0)
+	{
+		LM_ERR("use_table failed\n");
+		return -1;
+	}
+
+	if(imc_dbf.query(imc_db,0, 0, 0, rq_result_cols,0, 3, 0,&r_res)< 0)
+	{
+		LM_ERR("failed to query table\n");
+		return -1;
+	}
+	if(r_res==NULL || r_res->n<=0)
+	{
+		LM_INFO("the query returned no result\n");
+		if(r_res) imc_dbf.free_result(imc_db, r_res);
+		r_res = NULL;
+		return 0;
+	}
+
+	LM_DBG("found %d rooms\n", r_res->n);
+
+	for(i =0 ; i< r_res->n ; i++)
+	{
+		/*add rooms*/
+		r_row = &r_res->rows[i];
+		r_row_vals = ROW_VALUES(r_row);
+
+		name.s = 	r_row_vals[0].val.str_val.s;
+		name.len = strlen(name.s);
+
+		domain.s = 	r_row_vals[1].val.str_val.s;
+		domain.len = strlen(domain.s);
+
+		flag = 	r_row_vals[2].val.int_val;
+
+		room = imc_add_room(&name, &domain, flag);
+		if(room == NULL)
+		{
+			LM_ERR("failed to add room\n ");
+			goto error;
+		}
+
+		/* add members */
+		if(imc_dbf.use_table(imc_db, &members_table)< 0)
+		{
+			LM_ERR("use_table failed\n ");
+			goto error;
+		}
+
+		mquery_vals[0].val.str_val= room->uri;
+
+		if(imc_dbf.query(imc_db, mquery_cols, 0, mquery_vals, mq_result_cols,
+					1, 3, 0, &m_res)< 0)
+		{
+			LM_ERR("failed to query table\n");
+			goto error;
+		}
+
+		if(m_res==NULL || m_res->n<=0)
+		{
+			LM_INFO("the query returned no result\n");
+			er_ret = 0;
+			goto error; /* each room must have at least one member*/
+		}
+		for(j =0; j< m_res->n; j++)
+		{
+			m_row = &m_res->rows[j];
+			m_row_vals = ROW_VALUES(m_row);
+
+			name.s = m_row_vals[0].val.str_val.s;
+			name.len = strlen(name.s);
+
+			domain.s = m_row_vals[1].val.str_val.s;
+			domain.len = strlen(domain.s);
+
+			flag = m_row_vals[2].val.int_val;
+
+			LM_DBG("adding memeber: [name]=%.*s [domain]=%.*s"
+					" in [room]= %.*s\n", STR_FMT(&name), STR_FMT(&domain),
+					STR_FMT(&room->uri));
+
+			member = imc_add_member(room, &name, &domain, flag);
+			if(member == NULL)
+			{
+				LM_ERR("failed to adding member\n ");
+				goto error;
+			}
+			imc_release_room(room);
+		}
+
+		if(m_res)
+		{
+			imc_dbf.free_result(imc_db, m_res);
+			m_res = NULL;
+		}
+	}
+
+	return 0;
+
+error:
+	if(r_res)
+	{
+		imc_dbf.free_result(imc_db, r_res);
+		r_res = NULL;
+	}
+	if(m_res)
+	{
+		imc_dbf.free_result(imc_db, m_res);
+		m_res = NULL;
+	}
+	if(room)
+		imc_release_room(room);
+	return er_ret;
+}
+
+int add_room_to_db(imc_room_p room) 
+{
+	db_key_t rkeys[3];
+	db_val_t rvalues[3];
+	
+	rkeys[0] = &imc_col_name;
+	rkeys[1] = &imc_col_domain;
+	rkeys[2] = &imc_col_flag;
+
+	rvalues[0].type = DB1_STR;
+	rvalues[0].nul = 0;
+	rvalues[0].val.str_val.s = room->name.s;
+	rvalues[0].val.str_val.len = room->name.len;
+	
+	rvalues[1].type = DB1_STR;
+	rvalues[1].nul = 0;
+	rvalues[1].val.str_val.s = room->domain.s;
+	rvalues[1].val.str_val.len = room->domain.len;
+
+	rvalues[2].type = DB1_INT;
+	rvalues[2].nul = 0;
+	rvalues[2].val.int_val = 0;	
+
+	if(imc_dbf.use_table(imc_db, &rooms_table)< 0)
+	{
+		LM_ERR("use_table failed on rooms_table\n");
+		return -1;
+	}
+
+	if(imc_dbf.insert(imc_db, rkeys, rvalues, 3)< 0)
+	{
+		LM_ERR("failed to insert room\n");
+		return -1;
+	}	
+
+	return 0;
+}
+
+int remove_room_from_db(imc_room_p room)
+{
+	db_key_t rkeys[2];
+	db_val_t rvalues[2];
+	db_key_t mkeys[1];
+	db_val_t mvalues[1];
+			
+	mkeys[0] = &imc_col_room;
+
+	mvalues[0].type = DB1_STR;
+	mvalues[0].nul = 0;
+	mvalues[0].val.str_val.s = room->uri.s;
+	mvalues[0].val.str_val.len = room->uri.len;
+
+	if(imc_dbf.use_table(imc_db, &members_table)< 0)
+	{
+		LM_ERR("use table failed\n ");
+		return -1;
+	}
+
+	if(imc_dbf.delete(imc_db, mkeys, 0 , mvalues, 1) < 0)
+	{
+		LM_ERR("failed to delete room member from db\n");
+		return -1;
+	}
+
+	rkeys[0] = &imc_col_name;
+	rkeys[1] = &imc_col_domain;
+
+	rvalues[0].type = DB1_STR;
+	rvalues[0].nul = 0;
+	rvalues[0].val.str_val.s = room->name.s;
+	rvalues[0].val.str_val.len = room->name.len;
+	
+	rvalues[1].type = DB1_STR;
+	rvalues[1].nul = 0;
+	rvalues[1].val.str_val.s = room->domain.s;
+	rvalues[1].val.str_val.len = room->domain.len;
+
+	if(imc_dbf.use_table(imc_db, &rooms_table)< 0)
+	{
+		LM_ERR("use_table failed on rooms_table\n");
+		return -1;
+	}
+
+	if(imc_dbf.delete(imc_db, rkeys, 0 , rvalues, 2) < 0)
+	{
+		LM_ERR("failed to delete room from db\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+int add_room_member_to_db(imc_member_p member, imc_room_p room, int flag) 
+{
+	db_key_t mkeys[4];
+	db_val_t mvalues[4];
+	
+	mkeys[0] = &imc_col_username;
+	mkeys[1] = &imc_col_domain;
+	mkeys[2] = &imc_col_room;
+	mkeys[3] = &imc_col_flag;
+
+	mvalues[0].type = DB1_STR;
+	mvalues[0].nul = 0;
+	mvalues[0].val.str_val.s = member->user.s;
+	mvalues[0].val.str_val.len = member->user.len;
+	
+	mvalues[1].type = DB1_STR;
+	mvalues[1].nul = 0;
+	mvalues[1].val.str_val.s = member->domain.s;
+	mvalues[1].val.str_val.len = member->domain.len;
+
+	mvalues[2].type = DB1_STR;
+	mvalues[2].nul = 0;
+	mvalues[2].val.str_val.s = room->uri.s;
+	mvalues[2].val.str_val.len = room->uri.len;
+
+	mvalues[3].type = DB1_INT;
+	mvalues[3].nul = 0;
+	mvalues[3].val.int_val = flag;		
+
+	if(imc_dbf.use_table(imc_db, &members_table)< 0)
+	{
+		LM_ERR("use_table failed on members_table\n");
+		return -1;
+	}
+
+	if(imc_dbf.insert(imc_db, mkeys, mvalues, 4)< 0)
+	{
+		LM_ERR("failed to insert member\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+int remove_room_member_from_db(imc_member_p member, imc_room_p room) {
+	db_key_t mkeys[3];
+	db_val_t mvalues[3];
+	
+	mkeys[0] = &imc_col_username;
+	mkeys[1] = &imc_col_domain;
+	mkeys[2] = &imc_col_room;
+
+	mvalues[0].type = DB1_STR;
+	mvalues[0].nul = 0;
+	mvalues[0].val.str_val.s = member->user.s;
+	mvalues[0].val.str_val.len = member->user.len;
+	
+	mvalues[1].type = DB1_STR;
+	mvalues[1].nul = 0;
+	mvalues[1].val.str_val.s = member->domain.s;
+	mvalues[1].val.str_val.len = member->domain.len;
+
+	mvalues[2].type = DB1_STR;
+	mvalues[2].nul = 0;
+	mvalues[2].val.str_val.s = room->uri.s;
+	mvalues[2].val.str_val.len = room->uri.len;
+
+	if(imc_dbf.use_table(imc_db, &members_table)< 0)
+	{
+		LM_ERR("use table failed\n ");
+		return -1;
+	}
+
+	if(imc_dbf.delete(imc_db, mkeys, 0 , mvalues, 3) < 0)
+	{
+		LM_ERR("failed to delete room member from db\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+int modify_room_member_in_db(imc_member_p member, imc_room_p room, int flag)
+{
+	db_key_t mkeys[3];
+	db_val_t mvalues[3];
+
+	db_key_t mukeys[1];
+	db_val_t muvalues[1];
+	
+	mkeys[0] = &imc_col_username;
+	mkeys[1] = &imc_col_domain;
+	mkeys[2] = &imc_col_room;	
+
+	mvalues[0].type = DB1_STR;
+	mvalues[0].nul = 0;
+	mvalues[0].val.str_val.s = member->user.s;
+	mvalues[0].val.str_val.len = member->user.len;
+	
+	mvalues[1].type = DB1_STR;
+	mvalues[1].nul = 0;
+	mvalues[1].val.str_val.s = member->domain.s;
+	mvalues[1].val.str_val.len = member->domain.len;
+
+	mvalues[2].type = DB1_STR;
+	mvalues[2].nul = 0;
+	mvalues[2].val.str_val.s = room->uri.s;
+	mvalues[2].val.str_val.len = room->uri.len;	
+
+	mukeys[0] = &imc_col_flag;
+	
+	muvalues[0].type = DB1_INT;
+	muvalues[0].nul = 0;
+	muvalues[0].val.int_val = flag;
+
+	if(imc_dbf.use_table(imc_db, &members_table)< 0)
+	{
+		LM_ERR("use_table failed on members_table\n");
+		return -1;
+	}
+
+	if(imc_dbf.update(imc_db, mkeys, 0, mvalues, mukeys, muvalues, 3, 1)< 0)
+	{
+		LM_ERR("failed to update member\n");
+		return -1;
+	}
+
+	return 0;
+}
+
 /**
  * add room
  */
@@ -344,7 +711,7 @@ imc_member_p imc_add_member(imc_room_p room, str* user, str* domain, int flags)
 	return imp;
 }
 
-imc_member_p imc_modify_member(imc_room_p room, str* user, str* domain, int flags) {
+int imc_modify_member(imc_room_p room, str* user, str* domain, int flags) {
 	imc_member_p imp = NULL;
 	unsigned int hashid;
 
@@ -352,7 +719,7 @@ imc_member_p imc_modify_member(imc_room_p room, str* user, str* domain, int flag
 			|| domain == NULL || domain->s==NULL || domain->len<=0)
 	{
 		LM_ERR("invalid parameters\n");
-		return NULL;
+		return -1;
 	}
 	
 	hashid = core_case_hash(user, domain, 0);
@@ -366,6 +733,8 @@ imc_member_p imc_modify_member(imc_room_p room, str* user, str* domain, int flag
 		{
 			LM_DBG("member found. modify flags\n");
 			imp->flags = flags;
+			imp->hashid = core_case_hash(&imp->user, &imp->domain, 0);			
+
 			return 0;
 		}
 		imp = imp->next;

+ 24 - 3
src/modules/imc/imc_mng.h

@@ -27,7 +27,7 @@
 #define _IMC_MNG_H_
 
 
-
+#include "../../lib/srdb1/db.h"
 #include "../../core/locking.h"
 #include "../../core/str.h"
 #include "../../core/parser/parse_from.h"
@@ -40,7 +40,21 @@
 
 #define IMC_MEMBER_OWNER_STR	"owner"
 #define IMC_MEMBER_ADMIN_STR	"admin"
-#define IMC_MEMBER_INVITED_STR	"member"
+#define IMC_MEMBER_STR			"member"
+
+extern db1_con_t *imc_db;
+extern db_func_t imc_dbf;
+
+extern int db_mode;
+
+extern str rooms_table;
+extern str members_table;
+
+extern str imc_col_username;
+extern str imc_col_domain;
+extern str imc_col_flag;
+extern str imc_col_room;
+extern str imc_col_name;
 
 typedef struct _imc_member
 {
@@ -84,8 +98,15 @@ typedef struct _imc_hentry
 	gen_lock_t lock;
 } imc_hentry_t, *imc_hentry_p;
 
+int load_rooms_from_db();
+int add_room_to_db(imc_room_p room);
+int remove_room_from_db(imc_room_p room);
+int add_room_member_to_db(imc_member_p member, imc_room_p room, int flag);
+int modify_room_member_in_db(imc_member_p member, imc_room_p room, int flag);
+int remove_room_member_from_db(imc_member_p member, imc_room_p room);
+
 imc_member_p imc_add_member(imc_room_p room, str* user, str* domain, int flags);
-imc_member_p imc_modify_member(imc_room_p room, str* user, str* domain, int flags);
+int imc_modify_member(imc_room_p room, str* user, str* domain, int flags);
 imc_member_p imc_get_member(imc_room_p room, str* user, str* domain);
 int imc_del_member(imc_room_p room, str* user, str* domain);