libctdb: implement synchronous readrecordlock interface.
[metze/ctdb/wip.git] / libctdb / sync.c
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;
+}