lib: Add lib/util/server_id.h
[kai/samba-autobuild/.git] / source3 / lib / messages_ctdbd.c
index 949fb272805e599340940123fbe0120a9dd81820..a32a80d224035c3b2ab1a01718b983e8da3a7c61 100644 (file)
 */
 
 #include "includes.h"
+#include "lib/util/server_id.h"
 #include "messages.h"
 #include "util_tdb.h"
-
-#ifdef CLUSTER_SUPPORT
-
-/*
- * It is not possible to include ctdb.h and tdb_compat.h (included via
- * some other include above) without warnings. This fixes those
- * warnings.
- */
-
-#ifdef typesafe_cb
-#undef typesafe_cb
-#endif
-
-#ifdef typesafe_cb_preargs
-#undef typesafe_cb_preargs
-#endif
-
-#ifdef typesafe_cb_postargs
-#undef typesafe_cb_postargs
-#endif
-
-#include "ctdb.h"
-#include "ctdb_private.h"
+#include "lib/util/iov_buf.h"
+#include "lib/messages_util.h"
 #include "ctdbd_conn.h"
+#include "lib/cluster_support.h"
 
 
 struct messaging_ctdbd_context {
        struct ctdbd_connection *conn;
+       struct tevent_fd *fde;
 };
 
 /*
@@ -65,12 +47,13 @@ struct ctdbd_connection *messaging_ctdbd_connection(void)
 
        if (global_ctdb_connection_pid == 0 &&
            global_ctdbd_connection == NULL) {
-               struct event_context *ev;
+               struct tevent_context *ev;
                struct messaging_context *msg;
 
                ev = samba_tevent_context_init(NULL);
                if (!ev) {
                        DEBUG(0,("samba_tevent_context_init failed\n"));
+                       return NULL;
                }
 
                msg = messaging_init(NULL, ev);
@@ -82,31 +65,36 @@ struct ctdbd_connection *messaging_ctdbd_connection(void)
 
        if (global_ctdb_connection_pid != getpid()) {
                DEBUG(0,("messaging_ctdbd_connection():"
-                        "valid for pid[%d] but it's [%d]\n",
-                        global_ctdb_connection_pid, getpid()));
+                        "valid for pid[%jd] but it's [%jd]\n",
+                        (intmax_t)global_ctdb_connection_pid,
+                        (intmax_t)getpid()));
                smb_panic("messaging_ctdbd_connection() invalid process\n");
        }
 
        return global_ctdbd_connection;
 }
 
-static NTSTATUS messaging_ctdb_send(struct messaging_context *msg_ctx,
-                                   struct server_id pid, int msg_type,
-                                   const DATA_BLOB *data,
-                                   struct messaging_backend *backend)
+static int messaging_ctdb_send(struct server_id src,
+                              struct server_id pid, int msg_type,
+                              const struct iovec *iov, int iovlen,
+                              const int *fds, size_t num_fds,
+                              struct messaging_backend *backend)
 {
        struct messaging_ctdbd_context *ctx = talloc_get_type_abort(
                backend->private_data, struct messaging_ctdbd_context);
+       uint8_t hdr[MESSAGE_HDR_LENGTH];
+       struct iovec iov2[iovlen+1];
 
-       struct messaging_rec msg;
+       if (num_fds > 0) {
+               return ENOSYS;
+       }
 
-       msg.msg_version = MESSAGE_VERSION;
-       msg.msg_type    = msg_type;
-       msg.dest        = pid;
-       msg.src         = msg_ctx->id;
-       msg.buf         = *data;
+       message_hdr_put(hdr, msg_type, src, pid);
+       iov2[0] = (struct iovec){ .iov_base = hdr, .iov_len = sizeof(hdr) };
+       memcpy(&iov2[1], iov, iovlen * sizeof(*iov));
 
-       return ctdbd_messaging_send(ctx->conn, pid.vnn, pid.pid, &msg);
+       return ctdbd_messaging_send_iov(ctx->conn, pid.vnn, pid.pid,
+                                       iov2, iovlen+1);
 }
 
 static int messaging_ctdbd_destructor(struct messaging_ctdbd_context *ctx)
@@ -119,41 +107,128 @@ static int messaging_ctdbd_destructor(struct messaging_ctdbd_context *ctx)
        return 0;
 }
 
-NTSTATUS messaging_ctdbd_init(struct messaging_context *msg_ctx,
-                             TALLOC_CTX *mem_ctx,
-                             struct messaging_backend **presult)
+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_backend *result;
-       struct messaging_ctdbd_context *ctx;
-       NTSTATUS status;
+       struct messaging_context *msg_ctx = talloc_get_type_abort(
+               private_data, struct messaging_context);
+       struct server_id me = messaging_server_id(msg_ctx);
+       int ret;
+       struct iovec iov;
+       struct server_id src, dst;
+       enum messaging_type msg_type;
+       struct server_id_buf idbuf;
+
+       if (msg_len < MESSAGE_HDR_LENGTH) {
+               DEBUG(1, ("%s: message too short: %u\n", __func__,
+                         (unsigned)msg_len));
+               return 0;
+       }
 
-       if (!(result = talloc(mem_ctx, struct messaging_backend))) {
-               DEBUG(0, ("talloc failed\n"));
-               return NT_STATUS_NO_MEMORY;
+       message_hdr_get(&msg_type, &src, &dst, msg);
+
+       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,
+                  server_id_str_buf(src, &idbuf)));
+
+       if (!server_id_same_process(&me, &dst)) {
+               struct server_id_buf id1, id2;
+
+               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 0;
        }
 
-       if (!(ctx = talloc(result, struct messaging_ctdbd_context))) {
-               DEBUG(0, ("talloc failed\n"));
-               TALLOC_FREE(result);
-               return NT_STATUS_NO_MEMORY;
+       /*
+        * Go through the event loop
+        */
+
+       ret = messaging_send_iov_from(msg_ctx, src, dst, msg_type,
+                                     &iov, 1, NULL, 0);
+
+       if (ret != 0) {
+               DEBUG(10, ("%s: messaging_send_iov_from failed: %s\n",
+                          __func__, strerror(ret)));
        }
 
-       status = ctdbd_messaging_connection(ctx, &ctx->conn);
+       return 0;
+}
+
+static void messaging_ctdbd_readable(struct tevent_context *ev,
+                                    struct tevent_fd *fde,
+                                    uint16_t flags,
+                                    void *private_data)
+{
+       struct ctdbd_connection *conn = talloc_get_type_abort(
+               private_data, struct ctdbd_connection);
 
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(10, ("ctdbd_messaging_connection failed: %s\n",
-                          nt_errstr(status)));
-               TALLOC_FREE(result);
-               return status;
+       if ((flags & TEVENT_FD_READ) == 0) {
+               return;
+       }
+       ctdbd_socket_readable(conn);
+}
+
+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_register_msg_ctx(ctx->conn, msg_ctx);
+       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_register_msg_ctx 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;
+       }
+
+       ctdb_fd = ctdbd_conn_get_fd(ctx->conn);
+       ev = messaging_tevent_context(msg_ctx);
+
+       ctx->fde = tevent_add_fd(ev, ctx, ctdb_fd, TEVENT_FD_READ,
+                                messaging_ctdbd_readable, ctx->conn);
+       if (ctx->fde == NULL) {
+               return ENOMEM;
        }
 
        global_ctdb_connection_pid = getpid();
@@ -162,25 +237,53 @@ NTSTATUS messaging_ctdbd_init(struct messaging_context *msg_ctx,
 
        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;
 }
 
-#else
-
-NTSTATUS messaging_ctdbd_init(struct messaging_context *msg_ctx,
-                             TALLOC_CTX *mem_ctx,
-                             struct messaging_backend **presult)
+int messaging_ctdbd_reinit(struct messaging_context *msg_ctx,
+                          TALLOC_CTX *mem_ctx,
+                          struct messaging_backend *backend)
 {
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
+       struct messaging_ctdbd_context *ctx = talloc_get_type_abort(
+               backend->private_data, struct messaging_ctdbd_context);
+       int ret;
 
-struct ctdbd_connection *messaging_ctdbd_connection(void)
-{
-       return NULL;
-}
+       ret = messaging_ctdbd_init_internal(msg_ctx, mem_ctx, ctx, true);
+       if (ret != 0) {
+               return ret;
+       }
 
-#endif
+       return 0;
+}