libctdb: implement synchronous readrecordlock interface.
authorRusty Russell <rusty@rustcorp.com.au>
Mon, 21 Jun 2010 05:17:34 +0000 (14:47 +0930)
committerRusty Russell <rusty@rustcorp.com.au>
Mon, 21 Jun 2010 05:17:34 +0000 (14:47 +0930)
Because this doesn't use a generic callback, it's not quite as trivial
as the other sync wrappers.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
include/ctdb.h
libctdb/ctdb.c
libctdb/sync.c

index a9ee63ff25a6489532600d21542cb81071ff21da..c5e6f935e42d50c24da0e951983ce52bd79f94eb 100644 (file)
@@ -475,6 +475,7 @@ void ctdb_detachdb(struct ctdb_connection *ctdb, struct ctdb_db *db);
 
 /**
  * ctdb_readrecordlock - read and lock a record (synchronous)
+ * @ctdb: the ctdb_connection from ctdb_connect.
  * @ctdb_db: the database handle from ctdb_attachdb/ctdb_attachdb_recv.
  * @key: the key of the record to lock.
  * @req: a pointer to the request, if one is needed.
@@ -482,7 +483,8 @@ void ctdb_detachdb(struct ctdb_connection *ctdb, struct ctdb_db *db);
  * Do a ctdb_readrecordlock_send and wait for it to complete.
  * Returns NULL on failure.
  */
-struct ctdb_lock *ctdb_readrecordlock(struct ctdb_db *ctdb_db, TDB_DATA key,
+struct ctdb_lock *ctdb_readrecordlock(struct ctdb_connection *ctdb,
+                                     struct ctdb_db *ctdb_db, TDB_DATA key,
                                      TDB_DATA *data);
 
 
index 096a9264f0a4e012bf46e53853732281dbe1b027..23acef4ada9ae6b26c0668b5da8471df7d3afc03 100644 (file)
@@ -794,6 +794,7 @@ static void readrecordlock_retry(struct ctdb_connection *ctdb,
                /* Now it's their responsibility to free lock & request! */
                req->extra_destructor = NULL;
                lock->callback(lock->ctdb_db, lock, data, private);
+               ctdb_request_free(ctdb, req);
                return;
        }
 
index 43db2cf6b5a05ffaa7d43274ec4caab5d8401778..2e6ba9926fe5dae1b804a1e7c49a113082a7c483 100644 (file)
@@ -115,3 +115,56 @@ bool ctdb_getpnn(struct ctdb_connection *ctdb,
        }
        return ret;
 }
+
+struct rrl_info {
+       bool done;
+       struct ctdb_lock *lock;
+       TDB_DATA *data;
+};
+
+static void rrl_callback(struct ctdb_db *ctdb_db,
+                        struct ctdb_lock *lock,
+                        TDB_DATA data,
+                        struct rrl_info *rrl)
+{
+       rrl->done = true;
+       rrl->lock = lock;
+       *rrl->data = data;
+}
+
+struct ctdb_lock *ctdb_readrecordlock(struct ctdb_connection *ctdb,
+                                     struct ctdb_db *ctdb_db, TDB_DATA key,
+                                     TDB_DATA *data)
+{
+       struct pollfd fds;
+       struct rrl_info rrl;
+
+       rrl.done = false;
+       rrl.lock = NULL;
+       rrl.data = data;
+
+       /* Immediate failure is easy. */
+       if (!ctdb_readrecordlock_async(ctdb_db, key, rrl_callback, &rrl))
+               return NULL;
+
+       /* Immediate success is easy. */
+       if (!rrl.done) {
+               /* Otherwise wait until callback called. */
+               fds.fd = ctdb_get_fd(ctdb);
+               while (!rrl.done) {
+                       fds.events = ctdb_which_events(ctdb);
+                       if (poll(&fds, 1, -1) < 0) {
+                               /* Signalled is OK, other error is bad. */
+                               if (errno == EINTR)
+                                       continue;
+                               DEBUG(ctdb, LOG_ERR,
+                                     "ctdb_readrecordlock: poll failed");
+                               return NULL;
+                       }
+                       if (!ctdb_service(ctdb, fds.revents)) {
+                               break;
+                       }
+               }
+       }
+       return rrl.lock;
+}