[asterisk-commits] russell: branch russell/events r84324 - /team/russell/events/res/ais/lck.c
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Mon Oct 1 17:22:57 CDT 2007
Author: russell
Date: Mon Oct 1 17:22:56 2007
New Revision: 84324
URL: http://svn.digium.com/view/asterisk?view=rev&rev=84324
Log:
Add some more of the code for acquiring locks
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=84324&r1=84323&r2=84324
==============================================================================
--- team/russell/events/res/ais/lck.c (original)
+++ team/russell/events/res/ais/lck.c Mon Oct 1 17:22:56 2007
@@ -81,7 +81,8 @@
static struct ao2_container *lock_resources;
struct lock_resource {
- SaLckResourceHandleT *handle;
+ SaLckResourceHandleT handle;
+ SaLckLockIdT id;
SaNameT ais_name;
struct ast_str *name;
};
@@ -94,10 +95,22 @@
ast_free(lock->name);
}
+static inline struct lock_resource *lock_ref(struct lock_resource *lock)
+{
+ ao2_ref(lock, +1);
+ return lock;
+}
+
static inline struct lock_resource *lock_unref(struct lock_resource *lock)
{
ao2_ref(lock, -1);
return NULL;
+}
+
+static void lock_unref_cb(void *data)
+{
+ struct lock_resource *lock = data;
+ lock_unref(lock);
}
static struct lock_resource *find_lock(const char *name)
@@ -106,12 +119,15 @@
struct lock_resource *lock, tmp_lock = {
.name = lock_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)))
return lock;
+ /* Allocate and open the lock */
if (!(lock = ao2_alloc(sizeof(*lock), lock_destructor)))
return NULL;
@@ -122,9 +138,93 @@
if (!lock->name)
return lock_unref(lock);
- // XXX open the dlock
+ /* Map the name into the SaNameT for convenience */
+ ast_copy_string((char *) lock->ais_name.value, lock->name->str,
+ sizeof(lock->ais_name.value));
+ lock->ais_name.length = lock->name->used;
+
+ ais_res = saLckResourceOpen(lck_handle, &lock->ais_name,
+ SA_LCK_RESOURCE_CREATE, SA_TIME_ONE_SECOND * 3, &lock->handle);
+ if (ais_res != SA_AIS_OK) {
+ ast_log(LOG_ERROR, "Failed to open lock: %s\n", ais_err2str(ais_res));
+ return lock_unref(lock);
+ }
return lock;
+}
+
+const struct ast_datastore_info dlock_datastore_info = {
+ .type = "DLOCK",
+ .destroy = lock_unref_cb,
+};
+
+static void add_lock_to_chan(struct ast_channel *chan, struct lock_resource *lock,
+ enum lock_type lock_type, double timeout, char *buf, size_t len)
+{
+ struct ast_datastore *datastore;
+ SaAisErrorT ais_res;
+ SaLckLockModeT mode;
+ SaLckLockFlagsT flags;
+ SaLckLockStatusT status;
+
+ ast_channel_lock(chan);
+ datastore = ast_channel_datastore_find(chan, &dlock_datastore_info, lock->name->str);
+
+ if (datastore) {
+ ast_log(LOG_ERROR, "The DLOCk '%s' is already locked by channel '%s'\n",
+ lock->name->str, chan->name);
+ ast_channel_unlock(chan);
+ ast_copy_string(buf, "FAILURE", len);
+ return;
+ }
+ ast_channel_unlock(chan);
+
+ switch (lock_type) {
+ case TRY_RDLOCK:
+ flags = SA_LCK_LOCK_NO_QUEUE;
+ case RDLOCK:
+ mode = SA_LCK_PR_LOCK_MODE;
+ break;
+ case TRY_WRLOCK:
+ flags = SA_LCK_LOCK_NO_QUEUE;
+ case WRLOCK:
+ mode = SA_LCK_EX_LOCK_MODE;
+ }
+
+ /* Actually acquire the lock now */
+ ais_res = saLckResourceLock(lock->handle, &lock->id, mode, flags, 0,
+ (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));
+ return;
+ }
+
+ switch (status) {
+ case SA_LCK_LOCK_GRANTED:
+ ast_copy_string(buf, "SUCCESS", len);
+ break;
+ /*! XXX \todo Need to look at handling these other cases in a different way */
+ case SA_LCK_LOCK_DEADLOCK:
+ case SA_LCK_LOCK_NOT_QUEUED:
+ case SA_LCK_LOCK_ORPHANED:
+ case SA_LCK_LOCK_NO_MORE:
+ case SA_LCK_LOCK_DUPLICATE_EX:
+ ast_copy_string(buf, "FAILURE", len);
+ return;
+ }
+
+ if (!(datastore = ast_channel_datastore_alloc(&dlock_datastore_info,
+ lock->name->str))) {
+ ast_copy_string(buf, "FAILURE", len);
+ return;
+ }
+
+ datastore->data = lock_ref(lock);
+
+ ast_channel_lock(chan);
+ ast_channel_datastore_add(chan, datastore);
+ ast_channel_unlock(chan);
}
static int handle_lock(struct ast_channel *chan, enum lock_type lock_type,
@@ -136,7 +236,7 @@
);
int res = 0;
double timeout = 3;
- struct lock_resource *lock;
+ struct lock_resource *lock = NULL;
ast_autoservice_start(chan);
@@ -170,7 +270,9 @@
goto return_cleanup;
}
- // XXX
+ add_lock_to_chan(chan, lock, lock_type, timeout, buf, len);
+
+ lock = lock_unref(lock);
return_cleanup:
ast_autoservice_stop(chan);
More information about the asterisk-commits
mailing list