[asterisk-commits] russell: branch russell/events r85401 - /team/russell/events/res/ais/lck.c

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu Oct 11 10:58:13 CDT 2007


Author: russell
Date: Thu Oct 11 10:58:12 2007
New Revision: 85401

URL: http://svn.digium.com/view/asterisk?view=rev&rev=85401
Log:
For multiple threads on the same node to use the same distributed lock, they
must each open their own handle to the lock.  So, change the container of
opened locks to be thread-local instead of global.

Modified:
    team/russell/events/res/ais/lck.c

Modified: team/russell/events/res/ais/lck.c
URL: http://svn.digium.com/view/asterisk/team/russell/events/res/ais/lck.c?view=diff&rev=85401&r1=85400&r2=85401
==============================================================================
--- team/russell/events/res/ais/lck.c (original)
+++ team/russell/events/res/ais/lck.c Thu Oct 11 10:58:12 2007
@@ -26,10 +26,6 @@
  *
  * This file contains the code specific to the use of the LCK 
  * (Distributed Locks) Service.
- *
- * XXX /todo Each thread that wants to use a distributed lock needs to get its
- * own handle by using the Open() API call.  A single lock handle from Open()
- * can not be shared between threads.
  */
 
 #include "asterisk.h"
@@ -82,21 +78,73 @@
 
 #define LOCK_BUCKETS 101
 
-static struct ao2_container *lock_resources;
+/*!
+ * Every thread that wants to use a distributed lock must open its own handle
+ * to the lock.  So, a thread-local container of opened locks is used to keep
+ * track of what locks have been opened.
+ *
+ * \todo It would be nice to be able to have a thread-local container, instead
+ * of using a thread-local wrapper like this.
+ */
+struct lock_resources {
+	struct ao2_container *locks;
+};
+
+static int lock_resources_init(void *);
+static void lock_resources_destroy(void *);
+
+AST_THREADSTORAGE_CUSTOM(locks_ts_key, 
+	lock_resources_init, lock_resources_destroy);
 
 struct lock_resource {
 	SaLckResourceHandleT handle;
 	SaLckLockIdT id;
 	SaNameT ais_name;
-	struct ast_str *name;
-};
+	const char *name;
+};
+
+static int lock_hash_cb(const void *obj, int flags)
+{
+	const struct lock_resource *lock = obj;
+
+	return ast_str_hash(lock->name);
+}
+
+static int lock_cmp_cb(void *obj, void *arg, int flags)
+{
+	struct lock_resource *lock1 = obj, *lock2 = arg;
+
+	return !strcasecmp(lock1->name, lock2->name) ? CMP_MATCH : 0;
+}
+
+static int lock_resources_init(void *data)
+{
+	struct lock_resources *lock_resources = data;
+
+	if (!(lock_resources->locks = ao2_container_alloc(LOCK_BUCKETS,
+			lock_hash_cb, lock_cmp_cb))) {
+		return -1;
+	}
+
+	return 0;
+
+}
+
+static void lock_resources_destroy(void *data)
+{
+	struct lock_resources *lock_resources = data;
+
+	ao2_ref(lock_resources->locks, -1);
+
+	ast_free(lock_resources);
+}
 
 static void lock_destructor(void *obj)
 {
 	struct lock_resource *lock = obj;
 
 	if (lock->name)
-		ast_free(lock->name);
+		ast_free((void *) lock->name);
 }
 
 static inline struct lock_resource *lock_ref(struct lock_resource *lock)
@@ -118,7 +166,7 @@
 
 	ais_res = saLckResourceUnlock(lock->id, SA_TIME_ONE_SECOND * 3);
 	if (ais_res != SA_AIS_OK) {
-		ast_log(LOG_ERROR, "Error unlocking '%s': %s\n", lock->name->str, 
+		ast_log(LOG_ERROR, "Error unlocking '%s': %s\n", lock->name, 
 			ais_err2str(ais_res));
 	}
 
@@ -127,33 +175,32 @@
 
 static struct lock_resource *find_lock(const char *name)
 {
-	struct ast_str *lock_name = ast_str_alloca(512);
 	struct lock_resource *lock, tmp_lock = {
-		.name = lock_name,
+		.name = name,
 	};
 	SaAisErrorT ais_res;
-
-	ast_str_set(&lock_name, 0, name);
-
-	/* Return the lock if it has already been opened on this node */
-	if ((lock = ao2_find(lock_resources, &tmp_lock, OBJ_POINTER)))
+	struct lock_resources *lock_resources;
+
+	if (!(lock_resources = ast_threadstorage_get(&locks_ts_key, 
+		sizeof(*lock_resources)))) {
+		return NULL;
+	}
+
+	/* Return the lock if it has already been opened by this thread */
+	if ((lock = ao2_find(lock_resources->locks, &tmp_lock, OBJ_POINTER)))
 		return lock;
 
 	/* Allocate and open the lock */
 	if (!(lock = ao2_alloc(sizeof(*lock), lock_destructor)))
 		return NULL;
 
-	if (!(lock->name = ast_str_create(16)))
+	if (!(lock->name = ast_strdup(name)))
 		return lock_unref(lock);
 
-	ast_str_set(&lock->name, 0, name);
-	if (!lock->name)
-		return lock_unref(lock);
-
 	/* Map the name into the SaNameT for convenience */
-	ast_copy_string((char *) lock->ais_name.value, lock->name->str,
+	ast_copy_string((char *) lock->ais_name.value, lock->name,
 		sizeof(lock->ais_name.value));
-	lock->ais_name.length = lock->name->used;
+	lock->ais_name.length = strlen(lock->name);
 
 	ais_res = saLckResourceOpen(lck_handle, &lock->ais_name,
 		SA_LCK_RESOURCE_CREATE, SA_TIME_ONE_SECOND * 3, &lock->handle);
@@ -180,11 +227,11 @@
 	SaLckLockStatusT status;
 
 	ast_channel_lock(chan);
-	datastore = ast_channel_datastore_find(chan, &dlock_datastore_info, lock->name->str);
+	datastore = ast_channel_datastore_find(chan, &dlock_datastore_info, lock->name);
 
 	if (datastore) {
 		ast_log(LOG_ERROR, "The DLOCk '%s' is already locked by channel '%s'\n",
-			lock->name->str, chan->name);
+			lock->name, chan->name);
 		ast_channel_unlock(chan);
 		ast_copy_string(buf, "FAILURE", len);
 		return;
@@ -215,7 +262,7 @@
 		(SaTimeT) timeout * SA_TIME_ONE_SECOND, &status);
 	if (ais_res != SA_AIS_OK) {
 		ast_log(LOG_ERROR, "Problem acquiring lock '%s': %s\n",
-			lock->name->str, ais_err2str(ais_res));
+			lock->name, ais_err2str(ais_res));
 		ast_copy_string(buf, (ais_res == SA_AIS_ERR_TIMEOUT) ? "TIMEOUT" : 
 			"FAILURE", len);
 		return;
@@ -238,7 +285,7 @@
 	}
 
 	if (!(datastore = ast_channel_datastore_alloc(&dlock_datastore_info, 
-		lock->name->str))) {
+		lock->name))) {
 		ast_copy_string(buf, "FAILURE", len);
 		return;
 	}
@@ -358,7 +405,7 @@
 	lock = datastore->data;
 	ais_res = saLckResourceUnlock(lock->id, SA_TIME_ONE_SECOND * 3);
 	if (ais_res != SA_AIS_OK) {
-		ast_log(LOG_ERROR, "Error unlocking '%s': %s\n", lock->name->str, 
+		ast_log(LOG_ERROR, "Error unlocking '%s': %s\n", lock->name, 
 			ais_err2str(ais_res));
 		res = -1;
 		ast_copy_string(buf, (ais_res == SA_AIS_ERR_TIMEOUT) ? "TIMEOUT" : 
@@ -460,33 +507,13 @@
 	.read = handle_unlock,
 };
 
-static int lock_hash_cb(const void *obj, int flags)
-{
-	const struct lock_resource *lock = obj;
-
-	return ast_str_hash(lock->name->str);
-}
-
-static int lock_cmp_cb(void *obj, void *arg, int flags)
-{
-	struct lock_resource *lock1 = obj, *lock2 = arg;
-
-	return !strcasecmp(lock1->name->str, lock2->name->str) ? CMP_MATCH : 0;
-}
-
 int ast_ais_lck_load_module(void)
 {
 	SaAisErrorT ais_res;
 	int res;
 
-	if (!(lock_resources = ao2_container_alloc(LOCK_BUCKETS, 
-		lock_hash_cb, lock_cmp_cb))) {
-		return -1;
-	}
-
 	ais_res = saLckInitialize(&lck_handle, &lck_callbacks, &ais_version);
 	if (ais_res != SA_AIS_OK) {
-		ao2_ref(lock_resources, -1);
 		ast_log(LOG_ERROR, "Could not initialize distributed locking service: %s\n",
 			ais_err2str(ais_res));
 		return -1;
@@ -519,7 +546,5 @@
 		res = -1;
 	}
 
-	ao2_ref(lock_resources, -1);
-
 	return res;
 }




More information about the asterisk-commits mailing list