Forráskód Böngészése

Extra_attrs lock handling improvement

- new avp_db parameter (auto_unlock_extra_attrs)
  0 (default) : report sript writer's BUG when any lock remains locked
  1 : unlock all locks in postscript callback

- use hash (table_name) + hash(id) for locking instead of the same lock for the whole group
Michal Matyska 17 éve
szülő
commit
0d533bdd58

+ 2 - 0
modules_s/avp_db/avp_db.c

@@ -62,6 +62,7 @@ static char* type_column      = "type";
 static char* val_column       = "value";
 static char* val_column       = "value";
 static char* flags_column     = "flags";
 static char* flags_column     = "flags";
 static char* scheme_column    = "scheme";
 static char* scheme_column    = "scheme";
+int   auto_unlock      = 0;
 
 
 db_ctx_t* ctx = 0;
 db_ctx_t* ctx = 0;
 db_cmd_t *load_user_attrs_cmd = NULL;
 db_cmd_t *load_user_attrs_cmd = NULL;
@@ -111,6 +112,7 @@ static param_export_t params[] = {
     {"scheme_column",    PARAM_STRING, &scheme_column   },
     {"scheme_column",    PARAM_STRING, &scheme_column   },
 
 
 	{"attr_group", PARAM_STR | PARAM_USE_FUNC, (void*)declare_attr_group },
 	{"attr_group", PARAM_STR | PARAM_USE_FUNC, (void*)declare_attr_group },
+	{"auto_unlock_extra_attrs", PARAM_INT, &auto_unlock },
     {0, 0, 0}
     {0, 0, 0}
 };
 };
 
 

+ 1 - 0
modules_s/avp_db/avp_db.h

@@ -28,3 +28,4 @@
 #include "../../db/db.h"
 #include "../../db/db.h"
 
 
 extern db_ctx_t* ctx;
 extern db_ctx_t* ctx;
+extern int auto_unlock;

+ 15 - 0
modules_s/avp_db/doc/params.xml

@@ -214,4 +214,19 @@ route {
 	</para>
 	</para>
     </section>
     </section>
 
 
+    <section id="auto_unlock_extra_attrs">
+	<title><varname>auto_unlock_extra_attrs</varname> (string)</title>
+	<para>
+		Determines the action when any of the 'extra attributes' lock is detected when
+		routing script execution was finished.
+
+		When the value of this parameter is zero (default) BUG level message is logged, 
+		but the lock is kept, so another process trying to obtain the lock might get stuck.
+
+		If the value is nonzero, DEBUG level message is sent to the log and all the locks are released.
+	</para>
+	<para>
+		Default value is 0.
+	</para>
+    </section>
 </section>
 </section>

+ 30 - 10
modules_s/avp_db/extra_attrs.c

@@ -6,6 +6,8 @@
 #include "../../mem/mem.h"
 #include "../../mem/mem.h"
 #include "../../mem/shm_mem.h"
 #include "../../mem/shm_mem.h"
 #include "../../lock_ops.h"
 #include "../../lock_ops.h"
+#include "../../script_cb.h"
+#include "../../hashes.h"
 
 
 #define set_str_val(f,s)	(f).v.lstr=(s); \
 #define set_str_val(f,s)	(f).v.lstr=(s); \
 	(f).flags = 0;
 	(f).flags = 0;
@@ -424,6 +426,24 @@ int extra_attrs_fixup(void** param, int param_no)
 gen_lock_t *locks = NULL; /* set of mutexes allocated in shared memory */
 gen_lock_t *locks = NULL; /* set of mutexes allocated in shared memory */
 int lock_counters[LOCK_CNT]; /* set of counters (each proces has its own counters) */
 int lock_counters[LOCK_CNT]; /* set of counters (each proces has its own counters) */
 
 
+static int avpdb_post_script_cb(struct sip_msg *msg, void *param) {
+	int i;
+
+	for (i=0; i<LOCK_CNT; i++) {
+		if (lock_counters[i] > 0) {
+			if (auto_unlock) {
+				DEBUG("post script auto unlock extra attrs <%d>\n", i);
+				lock_release(&locks[i]);
+				lock_counters[i]=0;
+			} else {
+				BUG("script writer didn't unlock extra attrs !!!\n");
+				return 1;
+			}
+		}
+	}
+	return 1;
+}
+
 int init_extra_avp_locks()
 int init_extra_avp_locks()
 {
 {
 	int i;
 	int i;
@@ -444,22 +464,19 @@ int init_extra_avp_locks()
 	registered_table_t *t = tables;
 	registered_table_t *t = tables;
 	i = 0;
 	i = 0;
 	while (t) {
 	while (t) {
-		t->group_mutex_idx = (i++) % LOCK_CNT;
-		/* TODO: add mutex idx as a hash from table name 
-		 * (more groups can access the same table) */
+		t->group_mutex_idx = get_hash1_raw(t->table_name, strlen(t->table_name)) % LOCK_CNT;
 		t = t->next;
 		t = t->next;
 	}
 	}
+
+	register_script_cb(avpdb_post_script_cb, REQ_TYPE_CB | RPL_TYPE_CB| POST_SCRIPT_CB, 0);
+
 	return 0;
 	return 0;
 }
 }
 
 
 static inline int find_mutex(registered_table_t *t, str *id)
 static inline int find_mutex(registered_table_t *t, str *id)
 {
 {
-	/* TODO: add locking according table
-	 * TODO: add locking according table+id/id
-	 * the second one will probably avoid many colisions on mutex */
-
-	/* 'group id' locking */
-	return t->group_mutex_idx;
+	/* hash(table_name) + hash(id) */
+	return ((t->group_mutex_idx + get_hash1_raw(id->s, id->len)) % LOCK_CNT);
 }
 }
 
 
 int lock_extra_attrs(struct sip_msg* msg, char *_table, char* _id)
 int lock_extra_attrs(struct sip_msg* msg, char *_table, char* _id)
@@ -509,11 +526,14 @@ int unlock_extra_attrs(struct sip_msg* msg, char *_table, char* _id)
 		/* mutex is locked more times by this process */
 		/* mutex is locked more times by this process */
 		lock_counters[mutex_idx]--;
 		lock_counters[mutex_idx]--;
 	}
 	}
-	else {
+	else if (lock_counters[mutex_idx] == 1) {
 		/* the mutex is locked once => unlock it and reset counter */
 		/* the mutex is locked once => unlock it and reset counter */
 		lock_release(&locks[mutex_idx]);
 		lock_release(&locks[mutex_idx]);
 		lock_counters[mutex_idx] = 0;
 		lock_counters[mutex_idx] = 0;
 	}
 	}
+	else {
+		BUG("trying to unlock without lock group=\"%s\" id=\"%.*s\"\n", t->id, id.len, id.s);
+	}
 
 
 	return 1;
 	return 1;
 }
 }