Add rolling statistics that are collected across 10 second intervals.
[metze/ctdb/wip.git] / libctdb / sync.c
index b4c7b06246576cbebc9c2bdce4d1eb67e8b98c36..a1be3be9fadf6a50309eae7ddcde2bac7ff49dcc 100644 (file)
@@ -23,6 +23,9 @@
 #include <stdlib.h>
 #include "libctdb_private.h"
 
+/* Remove type-safety macros. */
+#undef ctdb_set_message_handler
+
 /* On failure, frees req and returns NULL. */
 static struct ctdb_request *synchronous(struct ctdb_connection *ctdb,
                                        struct ctdb_request *req,
@@ -41,12 +44,16 @@ static struct ctdb_request *synchronous(struct ctdb_connection *ctdb,
                        /* Signalled is OK, other error is bad. */
                        if (errno == EINTR)
                                continue;
-                       ctdb_request_free(ctdb, req);
+                       ctdb_cancel(ctdb, req);
                        DEBUG(ctdb, LOG_ERR, "ctdb_synchronous: poll failed");
                        return NULL;
                }
-               if (ctdb_service(ctdb, fds.revents) < 0) {
-                       ctdb_request_free(ctdb, req);
+               if (!ctdb_service(ctdb, fds.revents)) {
+                       /* It can have failed after it completed request. */
+                       if (!*done)
+                               ctdb_cancel(ctdb, req);
+                       else
+                               ctdb_request_free(ctdb, req);
                        return NULL;
                }
        }
@@ -59,12 +66,12 @@ static void set(struct ctdb_connection *ctdb,
        *done = true;
 }
 
-int ctdb_getrecmaster(struct ctdb_connection *ctdb,
-                     uint32_t destnode, uint32_t *recmaster)
+bool ctdb_getrecmaster(struct ctdb_connection *ctdb,
+                      uint32_t destnode, uint32_t *recmaster)
 {
        struct ctdb_request *req;
        bool done = false;
-       int ret = -1;
+       bool ret = false;
 
        req = synchronous(ctdb,
                          ctdb_getrecmaster_send(ctdb, destnode, set, &done),
@@ -77,7 +84,7 @@ int ctdb_getrecmaster(struct ctdb_connection *ctdb,
 }
 
 struct ctdb_db *ctdb_attachdb(struct ctdb_connection *ctdb,
-                             const char *name, int persistent,
+                             const char *name, bool persistent,
                              uint32_t tdb_flags)
 {
        struct ctdb_request *req;
@@ -95,12 +102,12 @@ struct ctdb_db *ctdb_attachdb(struct ctdb_connection *ctdb,
        return ret;
 }
 
-int ctdb_getpnn(struct ctdb_connection *ctdb,
-               uint32_t destnode, uint32_t *pnn)
+bool ctdb_getpnn(struct ctdb_connection *ctdb,
+                uint32_t destnode, uint32_t *pnn)
 {
        struct ctdb_request *req;
        bool done = false;
-       int ret = -1;
+       bool ret = false;
 
        req = synchronous(ctdb,
                          ctdb_getpnn_send(ctdb, destnode, set, &done),
@@ -111,3 +118,112 @@ int ctdb_getpnn(struct ctdb_connection *ctdb,
        }
        return ret;
 }
+
+bool ctdb_getnodemap(struct ctdb_connection *ctdb,
+                uint32_t destnode, struct ctdb_node_map **nodemap)
+{
+       struct ctdb_request *req;
+       bool done = false;
+       bool ret = false;
+
+       *nodemap = NULL;
+
+       req = synchronous(ctdb,
+                         ctdb_getnodemap_send(ctdb, destnode, set, &done),
+                         &done);
+       if (req != NULL) {
+               ret = ctdb_getnodemap_recv(ctdb, req, nodemap);
+               ctdb_request_free(ctdb, req);
+       }
+       return ret;
+}
+
+bool ctdb_getpublicips(struct ctdb_connection *ctdb,
+                      uint32_t destnode, struct ctdb_all_public_ips **ips)
+{
+       struct ctdb_request *req;
+       bool done = false;
+       bool ret = false;
+
+       *ips = NULL;
+
+       req = synchronous(ctdb,
+                         ctdb_getpublicips_send(ctdb, destnode, set, &done),
+                         &done);
+       if (req != NULL) {
+               ret = ctdb_getpublicips_recv(ctdb, req, ips);
+               ctdb_request_free(ctdb, req);
+       }
+       return ret;
+}
+
+bool ctdb_set_message_handler(struct ctdb_connection *ctdb, uint64_t srvid,
+                             ctdb_message_fn_t handler, void *cbdata)
+{
+       struct ctdb_request *req;
+       bool done = false;
+       bool ret = false;
+
+       req = synchronous(ctdb,
+                         ctdb_set_message_handler_send(ctdb, srvid, handler,
+                                                       cbdata, set, &done),
+                         &done);
+       if (req != NULL) {
+               ret = ctdb_set_message_handler_recv(ctdb, req);
+               ctdb_request_free(ctdb, req);
+       }
+       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;
+}