smbd/winbindd: Do an early check if ctdbd is functional
[mat/samba.git] / source3 / lib / ctdbd_conn.c
index e1ca3ce4e9d4478860e971437f62c2717374f72d..6ab4bbe70466e5e875fa18d8f27698fe51ec59a6 100644 (file)
@@ -128,7 +128,8 @@ static NTSTATUS get_cluster_vnn(struct ctdbd_connection *conn, uint32_t *vnn)
                               CTDB_CURRENT_NODE, CTDB_CONTROL_GET_PNN, 0, 0,
                               tdb_null, NULL, NULL, &cstatus);
        if (!NT_STATUS_IS_OK(status)) {
-               cluster_fatal("ctdbd_control failed\n");
+               DEBUG(1, ("ctdbd_control failed: %s\n", nt_errstr(status)));
+               return status;
        }
        *vnn = (uint32_t)cstatus;
        return status;
@@ -151,7 +152,8 @@ static bool ctdbd_working(struct ctdbd_connection *conn, uint32_t vnn)
                               CTDB_CONTROL_GET_NODEMAP, 0, 0,
                               tdb_null, talloc_tos(), &outdata, &cstatus);
        if (!NT_STATUS_IS_OK(status)) {
-               cluster_fatal("ctdbd_control failed\n");
+               DEBUG(1, ("ctdbd_control failed: %s\n", nt_errstr(status)));
+               return false;
        }
        if ((cstatus != 0) || (outdata.dptr == NULL)) {
                DEBUG(2, ("Received invalid ctdb data\n"));
@@ -201,7 +203,7 @@ static NTSTATUS ctdbd_connect(TALLOC_CTX *mem_ctx,
 {
        struct ctdb_packet_context *result;
        const char *sockname = lp_ctdbd_socket();
-       struct sockaddr_un addr;
+       struct sockaddr_un addr = { 0, };
        int fd;
        socklen_t salen;
 
@@ -211,7 +213,6 @@ static NTSTATUS ctdbd_connect(TALLOC_CTX *mem_ctx,
                return map_nt_error_from_unix(errno);
        }
 
-       ZERO_STRUCT(addr);
        addr.sun_family = AF_UNIX;
        snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", sockname);
 
@@ -476,7 +477,7 @@ static NTSTATUS ctdb_read_req(struct ctdbd_connection *conn, uint32_t reqid,
                 * We're waiting for a call reply, but an async message has
                 * crossed. Defer dispatching to the toplevel event loop.
                 */
-               evt = event_add_timed(conn->msg_ctx->event_ctx,
+               evt = tevent_add_timer(conn->msg_ctx->event_ctx,
                                      conn->msg_ctx->event_ctx,
                                      timeval_zero(),
                                      deferred_message_dispatch,
@@ -721,9 +722,9 @@ NTSTATUS ctdbd_register_msg_ctx(struct ctdbd_connection *conn,
        SMB_ASSERT(conn->msg_ctx == NULL);
        SMB_ASSERT(conn->fde == NULL);
 
-       if (!(conn->fde = event_add_fd(msg_ctx->event_ctx, conn,
+       if (!(conn->fde = tevent_add_fd(msg_ctx->event_ctx, conn,
                                       ctdb_packet_get_fd(conn->pkt),
-                                      EVENT_FD_READ,
+                                      TEVENT_FD_READ,
                                       ctdbd_socket_handler,
                                       conn))) {
                DEBUG(0, ("event_add_fd failed\n"));
@@ -1414,11 +1415,13 @@ NTSTATUS ctdbd_migrate(struct ctdbd_connection *conn, uint32_t db_id,
 }
 
 /*
- * remotely fetch a record (read-only)
+ * Fetch a record and parse it
  */
-NTSTATUS ctdbd_fetch(struct ctdbd_connection *conn, uint32_t db_id,
-                    TDB_DATA key, TALLOC_CTX *mem_ctx, TDB_DATA *data,
-                    bool local_copy)
+NTSTATUS ctdbd_parse(struct ctdbd_connection *conn, uint32_t db_id,
+                    TDB_DATA key, bool local_copy,
+                    void (*parser)(TDB_DATA key, TDB_DATA data,
+                                   void *private_data),
+                    void *private_data)
 {
        struct ctdb_req_call req;
        struct ctdb_reply_call *reply;
@@ -1473,21 +1476,17 @@ NTSTATUS ctdbd_fetch(struct ctdbd_connection *conn, uint32_t db_id,
                goto fail;
        }
 
-       data->dsize = reply->datalen;
-       if (data->dsize == 0) {
-               data->dptr = NULL;
-               goto done;
-       }
-
-       data->dptr = (uint8 *)talloc_memdup(mem_ctx, &reply->data[0],
-                                           reply->datalen);
-       if (data->dptr == NULL) {
-               DEBUG(0, ("talloc failed\n"));
-               status = NT_STATUS_NO_MEMORY;
+       if (reply->datalen == 0) {
+               /*
+                * Treat an empty record as non-existing
+                */
+               status = NT_STATUS_NOT_FOUND;
                goto fail;
        }
 
- done:
+       parser(key, make_tdb_data(&reply->data[0], reply->datalen),
+              private_data);
+
        status = NT_STATUS_OK;
  fail:
        TALLOC_FREE(reply);
@@ -1823,8 +1822,32 @@ NTSTATUS ctdb_unwatch(struct ctdbd_connection *conn)
        return status;
 }
 
+NTSTATUS ctdbd_probe(void)
+{
+       /*
+        * Do a very early check if ctdbd is around to avoid an abort and core
+        * later
+        */
+       struct ctdbd_connection *conn = NULL;
+       NTSTATUS status;
+
+       status = ctdbd_messaging_connection(talloc_tos(), &conn);
+
+       /*
+        * We only care if we can connect.
+        */
+       TALLOC_FREE(conn);
+
+       return status;
+}
+
 #else
 
+NTSTATUS ctdbd_probe(void)
+{
+       return NT_STATUS_OK;
+}
+
 NTSTATUS ctdbd_messaging_send_blob(struct ctdbd_connection *conn,
                                   uint32_t dst_vnn, uint64_t dst_srvid,
                                   const uint8_t *buf, size_t buflen)