lib: Add lib/util/server_id.h
[kai/samba-autobuild/.git] / source3 / lib / messages_ctdbd.c
index 0ce4da7649abc39f1610f86df9c16edd01996cfc..a32a80d224035c3b2ab1a01718b983e8da3a7c61 100644 (file)
 */
 
 #include "includes.h"
+#include "lib/util/server_id.h"
 #include "messages.h"
 #include "util_tdb.h"
 #include "lib/util/iov_buf.h"
 #include "lib/messages_util.h"
-
-#include "ctdb.h"
-#include "ctdb_private.h"
 #include "ctdbd_conn.h"
+#include "lib/cluster_support.h"
 
 
 struct messaging_ctdbd_context {
        struct ctdbd_connection *conn;
+       struct tevent_fd *fde;
 };
 
 /*
@@ -53,6 +53,7 @@ struct ctdbd_connection *messaging_ctdbd_connection(void)
                ev = samba_tevent_context_init(NULL);
                if (!ev) {
                        DEBUG(0,("samba_tevent_context_init failed\n"));
+                       return NULL;
                }
 
                msg = messaging_init(NULL, ev);
@@ -83,7 +84,6 @@ static int messaging_ctdb_send(struct server_id src,
                backend->private_data, struct messaging_ctdbd_context);
        uint8_t hdr[MESSAGE_HDR_LENGTH];
        struct iovec iov2[iovlen+1];
-       NTSTATUS status;
 
        if (num_fds > 0) {
                return ENOSYS;
@@ -93,12 +93,8 @@ static int messaging_ctdb_send(struct server_id src,
        iov2[0] = (struct iovec){ .iov_base = hdr, .iov_len = sizeof(hdr) };
        memcpy(&iov2[1], iov, iovlen * sizeof(*iov));
 
-       status = ctdbd_messaging_send_iov(ctx->conn, pid.vnn, pid.pid,
-                                         iov2, iovlen+1);
-       if (NT_STATUS_IS_OK(status)) {
-               return 0;
-       }
-       return map_errno_from_nt_status(status);
+       return ctdbd_messaging_send_iov(ctx->conn, pid.vnn, pid.pid,
+                                       iov2, iovlen+1);
 }
 
 static int messaging_ctdbd_destructor(struct messaging_ctdbd_context *ctx)
@@ -111,44 +107,31 @@ static int messaging_ctdbd_destructor(struct messaging_ctdbd_context *ctx)
        return 0;
 }
 
-static void messaging_ctdb_recv(struct ctdb_req_message *msg,
-                               void *private_data)
+static int messaging_ctdb_recv(
+       uint32_t src_vnn, uint32_t dst_vnn, uint64_t dst_srvid,
+       const uint8_t *msg, size_t msg_len, void *private_data)
 {
        struct messaging_context *msg_ctx = talloc_get_type_abort(
                private_data, struct messaging_context);
        struct server_id me = messaging_server_id(msg_ctx);
-       NTSTATUS status;
+       int ret;
        struct iovec iov;
-       size_t msg_len;
-       uint8_t *msg_buf;
        struct server_id src, dst;
        enum messaging_type msg_type;
        struct server_id_buf idbuf;
 
-       msg_len = msg->hdr.length;
-       if (msg_len < offsetof(struct ctdb_req_message, data)) {
-               DEBUG(10, ("%s: len %u too small\n", __func__,
-                          (unsigned)msg_len));
-               return;
-       }
-       msg_len -= offsetof(struct ctdb_req_message, data);
-
-       if (msg_len < msg->datalen) {
-               DEBUG(10, ("%s: msg_len=%u < msg->datalen=%u\n", __func__,
-                          (unsigned)msg_len, (unsigned)msg->datalen));
-               return;
-       }
-
        if (msg_len < MESSAGE_HDR_LENGTH) {
                DEBUG(1, ("%s: message too short: %u\n", __func__,
                          (unsigned)msg_len));
-               return;
+               return 0;
        }
 
-       message_hdr_get(&msg_type, &src, &dst, msg->data);
+       message_hdr_get(&msg_type, &src, &dst, msg);
 
-       msg_len -= MESSAGE_HDR_LENGTH;
-       msg_buf = msg->data + MESSAGE_HDR_LENGTH;
+       iov = (struct iovec) {
+               .iov_base = discard_const_p(uint8_t, msg) + MESSAGE_HDR_LENGTH,
+               .iov_len = msg_len - MESSAGE_HDR_LENGTH
+       };
 
        DEBUG(10, ("%s: Received message 0x%x len %u from %s\n",
                   __func__, (unsigned)msg_type, (unsigned)msg_len,
@@ -160,73 +143,147 @@ static void messaging_ctdb_recv(struct ctdb_req_message *msg,
                DEBUG(10, ("%s: I'm %s, ignoring msg to %s\n", __func__,
                           server_id_str_buf(me, &id1),
                           server_id_str_buf(dst, &id2)));
-               return;
+               return 0;
        }
 
-       iov = (struct iovec) { .iov_base = msg_buf, .iov_len = msg_len };
-
        /*
         * Go through the event loop
         */
 
-       status = messaging_send_iov_from(msg_ctx, src, dst, msg_type,
-                                        &iov, 1, NULL, 0);
+       ret = messaging_send_iov_from(msg_ctx, src, dst, msg_type,
+                                     &iov, 1, NULL, 0);
 
-       if (!NT_STATUS_IS_OK(status)) {
+       if (ret != 0) {
                DEBUG(10, ("%s: messaging_send_iov_from failed: %s\n",
-                          __func__, nt_errstr(status)));
+                          __func__, strerror(ret)));
        }
+
+       return 0;
 }
 
-NTSTATUS messaging_ctdbd_init(struct messaging_context *msg_ctx,
-                             TALLOC_CTX *mem_ctx,
-                             struct messaging_backend **presult)
+static void messaging_ctdbd_readable(struct tevent_context *ev,
+                                    struct tevent_fd *fde,
+                                    uint16_t flags,
+                                    void *private_data)
 {
-       struct messaging_backend *result;
-       struct messaging_ctdbd_context *ctx;
-       NTSTATUS status;
+       struct ctdbd_connection *conn = talloc_get_type_abort(
+               private_data, struct ctdbd_connection);
 
-       if (!(result = talloc(mem_ctx, struct messaging_backend))) {
-               DEBUG(0, ("talloc failed\n"));
-               return NT_STATUS_NO_MEMORY;
+       if ((flags & TEVENT_FD_READ) == 0) {
+               return;
        }
+       ctdbd_socket_readable(conn);
+}
 
-       if (!(ctx = talloc(result, struct messaging_ctdbd_context))) {
-               DEBUG(0, ("talloc failed\n"));
-               TALLOC_FREE(result);
-               return NT_STATUS_NO_MEMORY;
+static int messaging_ctdbd_init_internal(struct messaging_context *msg_ctx,
+                                        TALLOC_CTX *mem_ctx,
+                                        struct messaging_ctdbd_context *ctx,
+                                        bool reinit)
+{
+       struct tevent_context *ev;
+       int ret, ctdb_fd;
+
+       if (reinit) {
+               TALLOC_FREE(ctx->fde);
+
+               ret = ctdbd_reinit_connection(ctx,
+                                             lp_ctdbd_socket(),
+                                             lp_ctdb_timeout(),
+                                             ctx->conn);
+               if (ret != 0) {
+                       DBG_ERR("ctdbd_reinit_connection failed: %s\n",
+                               strerror(ret));
+                       return ret;
+               }
+       } else {
+               ret = ctdbd_init_connection(ctx,
+                                           lp_ctdbd_socket(),
+                                           lp_ctdb_timeout(),
+                                           &ctx->conn);
+               if (ret != 0) {
+                       DBG_ERR("ctdbd_init_connection failed: %s\n",
+                               strerror(ret));
+                       return ret;
+               }
        }
 
-       status = ctdbd_messaging_connection(ctx, &ctx->conn);
+       ret = register_with_ctdbd(ctx->conn, MSG_SRVID_SAMBA, NULL, NULL);
+       if (ret != 0) {
+               DBG_DEBUG("Could not register MSG_SRVID_SAMBA: %s\n",
+                         strerror(ret));
+               return ret;
+       }
 
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(10, ("ctdbd_messaging_connection failed: %s\n",
-                          nt_errstr(status)));
-               TALLOC_FREE(result);
-               return status;
+       ret = register_with_ctdbd(ctx->conn, getpid(),
+                                 messaging_ctdb_recv, msg_ctx);
+       if (ret != 0) {
+               DEBUG(10, ("register_with_ctdbd failed: %s\n",
+                          strerror(ret)));
+               return ret;
        }
 
-       status = ctdbd_register_msg_ctx(ctx->conn, msg_ctx);
+       ctdb_fd = ctdbd_conn_get_fd(ctx->conn);
+       ev = messaging_tevent_context(msg_ctx);
 
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(10, ("ctdbd_register_msg_ctx failed: %s\n",
-                          nt_errstr(status)));
-               TALLOC_FREE(result);
-               return status;
+       ctx->fde = tevent_add_fd(ev, ctx, ctdb_fd, TEVENT_FD_READ,
+                                messaging_ctdbd_readable, ctx->conn);
+       if (ctx->fde == NULL) {
+               return ENOMEM;
        }
 
-       status = register_with_ctdbd(ctx->conn, getpid(),
-                                    messaging_ctdb_recv, msg_ctx);
-
        global_ctdb_connection_pid = getpid();
        global_ctdbd_connection = ctx->conn;
        talloc_set_destructor(ctx, messaging_ctdbd_destructor);
 
        set_my_vnn(ctdbd_vnn(ctx->conn));
 
+       return 0;
+}
+
+int messaging_ctdbd_init(struct messaging_context *msg_ctx,
+                        TALLOC_CTX *mem_ctx,
+                        struct messaging_backend **presult)
+{
+       struct messaging_backend *result;
+       struct messaging_ctdbd_context *ctx;
+       int ret;
+
+       if (!(result = talloc(mem_ctx, struct messaging_backend))) {
+               DEBUG(0, ("talloc failed\n"));
+               return ENOMEM;
+       }
+
+       if (!(ctx = talloc(result, struct messaging_ctdbd_context))) {
+               DEBUG(0, ("talloc failed\n"));
+               TALLOC_FREE(result);
+               return ENOMEM;
+       }
+
+       ret = messaging_ctdbd_init_internal(msg_ctx, mem_ctx, ctx, false);
+       if (ret != 0) {
+               TALLOC_FREE(result);
+               return ret;
+       }
+
        result->send_fn = messaging_ctdb_send;
        result->private_data = (void *)ctx;
 
        *presult = result;
-       return NT_STATUS_OK;
+       return 0;
+}
+
+int messaging_ctdbd_reinit(struct messaging_context *msg_ctx,
+                          TALLOC_CTX *mem_ctx,
+                          struct messaging_backend *backend)
+{
+       struct messaging_ctdbd_context *ctx = talloc_get_type_abort(
+               backend->private_data, struct messaging_ctdbd_context);
+       int ret;
+
+       ret = messaging_ctdbd_init_internal(msg_ctx, mem_ctx, ctx, true);
+       if (ret != 0) {
+               return ret;
+       }
+
+       return 0;
 }