merged tridge's branch
[samba.git] / ctdb / common / ctdb_daemon.c
index ff3431a392db60073d5048d0f96e529c14454b1f..0ec201d29fb9bf848e22d22146f71b62b069e7f0 100644 (file)
@@ -44,6 +44,11 @@ static void daemon_incoming_packet(void *, uint8_t *, uint32_t );
 
 static void ctdb_main_loop(struct ctdb_context *ctdb)
 {
+       /* we are the dispatcher process now, so start the protocol going */
+       if (ctdb_init_transport(ctdb)) {
+               exit(1);
+       }
+
        ctdb->methods->start(ctdb);
 
        /* go into a wait loop to allow other nodes to complete */
@@ -223,31 +228,50 @@ static void daemon_request_connect_wait(struct ctdb_client *client,
 
 
 /*
-  called when the daemon gets a status request from a client
+  called when the daemon gets a getdbpath request from a client
  */
-static void daemon_request_status(struct ctdb_client *client, 
-                                 struct ctdb_req_status *c)
+static void daemon_request_getdbpath(struct ctdb_client *client, 
+                                 struct ctdb_req_getdbpath *c)
 {
-       struct ctdb_reply_status r;
-       int res;
+       struct ctdb_reply_getdbpath *r;
+       struct ctdb_db_context *ctdb_db;
+       char *path;
+       int res, len;
+
+       ctdb_db = find_ctdb_db(client->ctdb, c->db_id);
+       if (!ctdb_db) {
+               DEBUG(0, (__location__ " Unknown database in request. db_id==0x%08x",
+                         c->db_id));
+               ctdb_db->ctdb->status.pending_calls--;
+               return;
+       }
+
+       path = talloc_asprintf(c, "%s/%s", ctdb_db->ctdb->db_directory, ctdb_db->db_name);
 
        /* now send the reply */
-       ZERO_STRUCT(r);
+       len = offsetof(struct ctdb_reply_getdbpath, data) + strlen(path);
+       r = ctdbd_allocate_pkt(ctdb_db->ctdb, len);
 
-       r.hdr.length     = sizeof(r);
-       r.hdr.ctdb_magic = CTDB_MAGIC;
-       r.hdr.ctdb_version = CTDB_VERSION;
-       r.hdr.operation = CTDB_REPLY_STATUS;
-       r.hdr.reqid = c->hdr.reqid;
-       r.status = client->ctdb->status;
-       
-       res = daemon_queue_send(client, &r.hdr);
+       talloc_set_name_const(r, "reply_getdbpath packet");
+
+       memset(r, 0, offsetof(struct ctdb_reply_getdbpath, data));
+
+       r->hdr.length       = len;
+       r->hdr.ctdb_magic   = CTDB_MAGIC;
+       r->hdr.ctdb_version = CTDB_VERSION;
+       r->hdr.operation    = CTDB_REPLY_GETDBPATH;
+       r->hdr.reqid        = c->hdr.reqid;
+       r->datalen          = strlen(path);
+       memcpy(&r->data[0], path, r->datalen);
+
+       res = daemon_queue_send(client, &(r->hdr));
        if (res != 0) {
-               DEBUG(0,(__location__ " Failed to queue a connect wait response\n"));
+               DEBUG(0,(__location__ " Failed to queue a getdbpath response\n"));
                return;
        }
 }
 
+
 /*
   destroy a ctdb_client
 */
@@ -437,6 +461,10 @@ static void daemon_request_call_from_client(struct ctdb_client *client,
        state->async.private_data = dstate;
 }
 
+
+static void daemon_request_control_from_client(struct ctdb_client *client, 
+                                              struct ctdb_req_control *c);
+
 /* data contains a packet from the client */
 static void daemon_incoming_packet(void *p, uint8_t *data, uint32_t nread)
 {
@@ -473,6 +501,7 @@ static void daemon_incoming_packet(void *p, uint8_t *data, uint32_t nread)
                daemon_request_register_message_handler(client, 
                                                        (struct ctdb_req_register *)hdr);
                break;
+
        case CTDB_REQ_MESSAGE:
                ctdb->status.client.req_message++;
                daemon_request_message_from_client(client, (struct ctdb_req_message *)hdr);
@@ -488,9 +517,13 @@ static void daemon_incoming_packet(void *p, uint8_t *data, uint32_t nread)
                daemon_request_shutdown(client, (struct ctdb_req_shutdown *)hdr);
                break;
 
-       case CTDB_REQ_STATUS:
-               ctdb->status.client.req_status++;
-               daemon_request_status(client, (struct ctdb_req_status *)hdr);
+       case CTDB_REQ_GETDBPATH:
+               daemon_request_getdbpath(client, (struct ctdb_req_getdbpath *)hdr);
+               break;
+
+       case CTDB_REQ_CONTROL:
+               ctdb->status.client.req_control++;
+               daemon_request_control_from_client(client, (struct ctdb_req_control *)hdr);
                break;
 
        default:
@@ -645,8 +678,6 @@ int ctdb_start(struct ctdb_context *ctdb)
        struct fd_event *fde;
        const char *domain_socket_name;
 
-       /* generate a name to use for our local socket */
-       ctdb->daemon.name = talloc_asprintf(ctdb, "%s.%s", CTDB_PATH, ctdb->address.address);
        /* get rid of any old sockets */
        unlink(ctdb->daemon.name);
 
@@ -672,6 +703,12 @@ int ctdb_start(struct ctdb_context *ctdb)
                close(fd[0]);
                close(ctdb->daemon.sd);
                ctdb->daemon.sd = -1;
+
+               /* Added because of ctdb->methods->allocate_pkt calls */
+               /* TODO: clean */
+               int ctdb_tcp_init(struct ctdb_context *ctdb);
+               ctdb_tcp_init(ctdb);
+
                return 0;
        }
 
@@ -709,3 +746,77 @@ void ctdb_request_finished(struct ctdb_context *ctdb, struct ctdb_req_header *hd
 {
        ctdb->num_finished++;
 }
+
+
+struct daemon_control_state {
+       struct ctdb_client *client;
+       struct ctdb_req_control *c;
+};
+
+/*
+  callback when a control reply comes in
+ */
+static void daemon_control_callback(struct ctdb_context *ctdb,
+                                   uint32_t status, TDB_DATA data, 
+                                   void *private_data)
+{
+       struct daemon_control_state *state = talloc_get_type(private_data, 
+                                                            struct daemon_control_state);
+       struct ctdb_client *client = state->client;
+       struct ctdb_reply_control *r;
+       size_t len;
+
+       DEBUG(0,("callback: size=%u\n", data.dsize));
+       DEBUG(0,("callback: size=%u\n", data.dsize));
+       DEBUG(0,("callback: size=%u\n", data.dsize));
+       DEBUG(0,("callback: size=%u\n", data.dsize));
+       DEBUG(0,("callback: size=%u\n", data.dsize));
+       DEBUG(0,("callback: size=%u\n", data.dsize));
+
+       /* construct a message to send to the client containing the data */
+       len = offsetof(struct ctdb_req_control, data) + data.dsize;
+       r = ctdbd_allocate_pkt(client, len);
+       talloc_set_name_const(r, "reply_control packet");
+
+       memset(r, 0, offsetof(struct ctdb_req_message, data));
+
+       r->hdr.length    = len;
+       r->hdr.ctdb_magic = CTDB_MAGIC;
+       r->hdr.ctdb_version = CTDB_VERSION;
+       r->hdr.operation = CTDB_REPLY_CONTROL;
+       r->status        = status;
+       r->datalen       = data.dsize;
+       memcpy(&r->data[0], data.dptr, data.dsize);
+
+       daemon_queue_send(client, &r->hdr);
+
+       talloc_free(state);
+}
+
+/*
+  this is called when the ctdb daemon received a ctdb request control
+  from a local client over the unix domain socket
+ */
+static void daemon_request_control_from_client(struct ctdb_client *client, 
+                                              struct ctdb_req_control *c)
+{
+       TDB_DATA data;
+       int res;
+       struct daemon_control_state *state;
+
+       state = talloc(client, struct daemon_control_state);
+       CTDB_NO_MEMORY_VOID(client->ctdb, state);
+
+       state->client = client;
+       state->c = talloc_steal(state, c);
+       
+       data.dptr = &c->data[0];
+       data.dsize = c->datalen;
+       res = ctdb_daemon_send_control(client->ctdb, c->hdr.destnode,
+                                      c->srvid, c->opcode, data, daemon_control_callback,
+                                      state);
+       if (res != 0) {
+               DEBUG(0,(__location__ " Failed to send control to remote node %u\n",
+                        c->hdr.destnode));
+       }
+}