Rev 91: merged tridge's branch again in http://samba.org/~tridge/psomogyi/

psomogyi at gamax.hu psomogyi at gamax.hu
Sun Apr 29 14:28:54 GMT 2007


------------------------------------------------------------
revno: 91
revision-id: psomogyi at gamax.hu-20070429142835-4pd7m24sjko801ye
parent: psomogyi at gamax.hu-20070429142748-xzhvikj20c14dnaf
parent: tridge at samba.org-20070429141940-kxbij0fq3pj33qvn
committer: Peter Somogyi <psomogyi at gamax.hu>
branch nick: ctdb
timestamp: Sun 2007-04-29 16:28:35 +0200
message:
  merged tridge's branch again
modified:
  common/ctdb_call.c             ctdb_call.c-20061128065342-to93h6eejj5kon81-1
  common/ctdb_client.c           ctdb_client.c-20070411010216-3kd8v37k61steeya-1
  common/ctdb_control.c          ctdb_control.c-20070426122724-j6gkpiofhbwdin63-1
  common/ctdb_daemon.c           ctdb_daemon.c-20070409200331-3el1kqgdb9m4ib0g-1
  common/ctdb_io.c               ctdb_io.c-20070409200335-dzfc7f3rra5rcf60-1
  common/ctdb_util.c             ctdb_util.c-20061128065342-to93h6eejj5kon81-3
  direct/ctdbd.c                 ctdbd.c-20070411085044-dqmhr6mfeexnyt4m-1
  include/ctdb.h                 ctdb.h-20061117234101-o3qt14umlg9en8z0-11
  include/ctdb_private.h         ctdb_private.h-20061117234101-o3qt14umlg9en8z0-13
  tools/ctdb_control.c           ctdb_control.c-20070426122705-9ehj1l5lu2gn9kuj-1
    ------------------------------------------------------------
    revno: 44.1.177
    merged: tridge at samba.org-20070429141940-kxbij0fq3pj33qvn
    parent: tridge at samba.org-20070428171336-4yw1gh5qfslqan73
    committer: Andrew Tridgell <tridge at samba.org>
    branch nick: tridge
    timestamp: Sun 2007-04-29 16:19:40 +0200
    message:
      yay! finally fixed the bug that volker, ronnie and I have been chasing
      for 2 days.
      
      The main bug was in smbd, but there was a secondary (and more subtle)
      bug in ctdb that the bug in smbd exposed. When we get send a dmaster
      reply, we have to correctly update the dmaster in the recipient even
      if the original requst has timed out, otherwise ctdbd can get into a
      loop fighting over who will handle a key.
      
      This patch also cleans up the packet allocation, and makes ctdbd
      become a real daemon.
    ------------------------------------------------------------
    revno: 44.1.176
    merged: tridge at samba.org-20070428171336-4yw1gh5qfslqan73
    parent: tridge at samba.org-20070428165537-dq8tirclx8okd1ec
    committer: Andrew Tridgell <tridge at samba.org>
    branch nick: tridge
    timestamp: Sat 2007-04-28 19:13:36 +0200
    message:
      added reset status control
    ------------------------------------------------------------
    revno: 44.1.175
    merged: tridge at samba.org-20070428165537-dq8tirclx8okd1ec
    parent: tridge at samba.org-20070428161833-g1jbj1dibtxk28ih
    committer: Andrew Tridgell <tridge at samba.org>
    branch nick: tridge
    timestamp: Sat 2007-04-28 18:55:37 +0200
    message:
      removed unnecessary variable
=== modified file 'common/ctdb_call.c'
--- a/common/ctdb_call.c	2007-04-28 16:18:33 +0000
+++ b/common/ctdb_call.c	2007-04-29 14:19:40 +0000
@@ -211,15 +211,19 @@
 	tmp_ctx = talloc_new(ctdb);
 
 	/* send the CTDB_REPLY_DMASTER */
-	len = offsetof(struct ctdb_reply_dmaster, data) + data.dsize;
+	len = offsetof(struct ctdb_reply_dmaster, data) + key.dsize + data.dsize;
 	r = ctdb_transport_allocate(ctdb, tmp_ctx, CTDB_REPLY_DMASTER, len,
 				    struct ctdb_reply_dmaster);
 	CTDB_NO_MEMORY_FATAL(ctdb, r);
 
 	r->hdr.destnode  = new_dmaster;
 	r->hdr.reqid     = reqid;
+	r->rsn           = header->rsn;
+	r->keylen        = key.dsize;
 	r->datalen       = data.dsize;
-	memcpy(&r->data[0], data.dptr, data.dsize);
+	r->db_id         = ctdb_db->db_id;
+	memcpy(&r->data[0], key.dptr, key.dsize);
+	memcpy(&r->data[key.dsize], data.dptr, data.dsize);
 
 	ctdb_queue_packet(ctdb, &r->hdr);
 
@@ -256,6 +260,7 @@
 	r->hdr.destnode  = lmaster;
 	r->hdr.reqid     = c->hdr.reqid;
 	r->db_id         = c->db_id;
+	r->rsn           = header->rsn;
 	r->dmaster       = c->hdr.srcnode;
 	r->keylen        = key->dsize;
 	r->datalen       = data->dsize;
@@ -276,39 +281,43 @@
 
   must be called with the chainlock held. This function releases the chainlock
 */
-static void ctdb_become_dmaster(struct ctdb_context *ctdb, 
-				uint32_t reqid, TDB_DATA data)
+static void ctdb_become_dmaster(struct ctdb_db_context *ctdb_db, 
+				uint32_t reqid, TDB_DATA key, TDB_DATA data,
+				uint64_t rsn)
 {
 	struct ctdb_call_state *state;
-	struct ctdb_db_context *ctdb_db;
+	struct ctdb_context *ctdb = ctdb_db->ctdb;
+	struct ctdb_ltdb_header header;
+
+	DEBUG(2,("vnn %u dmaster response %08x\n", ctdb->vnn, ctdb_hash(&key)));
+
+	ZERO_STRUCT(header);
+	header.rsn = rsn;
+	header.dmaster = ctdb->vnn;
+
+	if (ctdb_ltdb_store(ctdb_db, key, &header, data) != 0) {
+		ctdb_fatal(ctdb, "ctdb_reply_dmaster store failed\n");
+		ctdb_ltdb_unlock(ctdb_db, key);
+		return;
+	}
 
 	state = ctdb_reqid_find(ctdb, reqid, struct ctdb_call_state);
 
 	if (state == NULL) {
+		DEBUG(0,("vnn %u Invalid reqid %u in ctdb_become_dmaster\n",
+			 ctdb->vnn, reqid));
+		ctdb_ltdb_unlock(ctdb_db, key);
 		return;
 	}
 
 	if (reqid != state->reqid) {
 		/* we found a record  but it was the wrong one */
-		DEBUG(0, ("Dropped orphaned dmaster reply with reqid:%d\n",reqid));
-		return;
-	}
-
-	ctdb_db = state->ctdb_db;
-
-	DEBUG(2,("vnn %u dmaster response %08x\n", 
-		 ctdb->vnn, ctdb_hash(&state->call.key)));
-
-	/* we're now the dmaster - update our local ltdb with new header
-	   and data */
-	state->header.dmaster = ctdb->vnn;
-
-	if (ctdb_ltdb_store(ctdb_db, state->call.key, &state->header, data) != 0) {
-		ctdb_fatal(ctdb, "ctdb_reply_dmaster store failed\n");
-		return;
-	}
-
-	ctdb_call_local(ctdb_db, &state->call, &state->header, &data, ctdb->vnn);
+		DEBUG(0, ("Dropped orphan in ctdb_become_dmaster with reqid:%d\n",reqid));
+		ctdb_ltdb_unlock(ctdb_db, key);
+		return;
+	}
+
+	ctdb_call_local(ctdb_db, &state->call, &header, &data, ctdb->vnn);
 
 	ctdb_ltdb_unlock(ctdb_db, state->call.key);
 
@@ -381,7 +390,7 @@
 	/* check if the new dmaster is the lmaster, in which case we
 	   skip the dmaster reply */
 	if (c->dmaster == ctdb->vnn) {
-		ctdb_become_dmaster(ctdb, hdr->reqid, data);
+		ctdb_become_dmaster(ctdb_db, hdr->reqid, key, data, c->rsn);
 	} else {
 		ctdb_send_dmaster_reply(ctdb_db, &header, key, data, c->dmaster, hdr->reqid);
 		ctdb_ltdb_unlock(ctdb_db, key);
@@ -434,8 +443,8 @@
 	/* if we are not the dmaster, then send a redirect to the
 	   requesting node */
 	if (header.dmaster != ctdb->vnn) {
+		talloc_free(data.dptr);
 		ctdb_call_send_redirect(ctdb, call.key, c, &header);
-		talloc_free(data.dptr);
 		ctdb_ltdb_unlock(ctdb_db, call.key);
 		return;
 	}
@@ -465,7 +474,6 @@
 				    struct ctdb_reply_call);
 	CTDB_NO_MEMORY_FATAL(ctdb, r);
 	r->hdr.destnode  = hdr->srcnode;
-	r->hdr.srcnode   = hdr->destnode;
 	r->hdr.reqid     = hdr->reqid;
 	r->status        = call.status;
 	r->datalen       = call.reply_data.dsize;
@@ -498,7 +506,7 @@
 
 	if (hdr->reqid != state->reqid) {
 		/* we found a record  but it was the wrong one */
-		DEBUG(0, ("Dropped orphaned dmaster reply with reqid:%d\n",hdr->reqid));
+		DEBUG(0, ("Dropped orphaned call reply with reqid:%d\n",hdr->reqid));
 		return;
 	}
 
@@ -525,26 +533,22 @@
 void ctdb_reply_dmaster(struct ctdb_context *ctdb, struct ctdb_req_header *hdr)
 {
 	struct ctdb_reply_dmaster *c = (struct ctdb_reply_dmaster *)hdr;
-	struct ctdb_call_state *state;
 	struct ctdb_db_context *ctdb_db;
-	TDB_DATA data;
+	TDB_DATA key, data;
 	int ret;
 
-	state = ctdb_reqid_find(ctdb, hdr->reqid, struct ctdb_call_state);
-
-	if (state == NULL) {
-		return;
-	}
-
-	if (hdr->reqid != state->reqid) {
-		/* we found a record  but it was the wrong one */
-		DEBUG(0, ("Dropped orphaned dmaster reply with reqid:%d\n",hdr->reqid));
-		return;
-	}
-
-	ctdb_db = state->ctdb_db;
-
-	ret = ctdb_ltdb_lock_requeue(ctdb_db, state->call.key, hdr,
+	ctdb_db = find_ctdb_db(ctdb, c->db_id);
+	if (ctdb_db == NULL) {
+		DEBUG(0,("Unknown db_id 0x%x in ctdb_reply_dmaster\n", c->db_id));
+		return;
+	}
+	
+	key.dptr = c->data;
+	key.dsize = c->keylen;
+	data.dptr = &c->data[key.dsize];
+	data.dsize = c->datalen;
+
+	ret = ctdb_ltdb_lock_requeue(ctdb_db, key, hdr,
 				     ctdb_recv_raw_pkt, ctdb);
 	if (ret == -2) {
 		return;
@@ -554,10 +558,7 @@
 		return;
 	}
 
-	data.dptr = c->data;
-	data.dsize = c->datalen;
-
-	ctdb_become_dmaster(ctdb, hdr->reqid, data);
+	ctdb_become_dmaster(ctdb_db, hdr->reqid, key, data, c->rsn);
 }
 
 
@@ -571,12 +572,14 @@
 
 	state = ctdb_reqid_find(ctdb, hdr->reqid, struct ctdb_call_state);
 	if (state == NULL) {
+		DEBUG(0,("vnn %u Invalid reqid %u in ctdb_reply_error\n",
+			 ctdb->vnn, hdr->reqid));
 		return;
 	}
 
 	if (hdr->reqid != state->reqid) {
 		/* we found a record  but it was the wrong one */
-		DEBUG(0, ("Dropped orphaned dmaster reply with reqid:%d\n",hdr->reqid));
+		DEBUG(0, ("Dropped orphaned error reply with reqid:%d\n",hdr->reqid));
 		return;
 	}
 
@@ -595,7 +598,7 @@
 */
 static int ctdb_call_destructor(struct ctdb_call_state *state)
 {
-	ctdb_reqid_remove(state->node->ctdb, state->reqid);
+	ctdb_reqid_remove(state->ctdb_db->ctdb, state->reqid);
 	return 0;
 }
 
@@ -609,7 +612,7 @@
 	struct ctdb_call_state *state = talloc_get_type(private_data, struct ctdb_call_state);
 	DEBUG(0,(__location__ " call timeout for reqid %d\n", state->c->hdr.reqid));
 	state->state = CTDB_CALL_ERROR;
-	ctdb_set_error(state->node->ctdb, "ctdb_call %u timed out",
+	ctdb_set_error(state->ctdb_db->ctdb, "ctdb_call %u timed out",
 		       state->c->hdr.reqid);
 	if (state->async.fn) {
 		state->async.fn(state);
@@ -650,7 +653,6 @@
 	talloc_steal(state, data->dptr);
 
 	state->state = CTDB_CALL_DONE;
-	state->node = ctdb->nodes[ctdb->vnn];
 	state->call = *call;
 	state->ctdb_db = ctdb_db;
 
@@ -711,9 +713,7 @@
 	state->call.call_data.dptr = &state->c->data[call->key.dsize];
 	state->call.key.dptr       = &state->c->data[0];
 
-	state->node   = ctdb->nodes[header->dmaster];
 	state->state  = CTDB_CALL_WAIT;
-	state->header = *header;
 	state->ctdb_db = ctdb_db;
 
 	ctdb_queue_packet(ctdb, &state->c->hdr);
@@ -734,16 +734,16 @@
 int ctdb_daemon_call_recv(struct ctdb_call_state *state, struct ctdb_call *call)
 {
 	while (state->state < CTDB_CALL_DONE) {
-		event_loop_once(state->node->ctdb->ev);
+		event_loop_once(state->ctdb_db->ctdb->ev);
 	}
 	if (state->state != CTDB_CALL_DONE) {
-		ctdb_set_error(state->node->ctdb, "%s", state->errmsg);
+		ctdb_set_error(state->ctdb_db->ctdb, "%s", state->errmsg);
 		talloc_free(state);
 		return -1;
 	}
 
 	if (state->call.reply_data.dsize) {
-		call->reply_data.dptr = talloc_memdup(state->node->ctdb,
+		call->reply_data.dptr = talloc_memdup(state->ctdb_db->ctdb,
 						      state->call.reply_data.dptr,
 						      state->call.reply_data.dsize);
 		call->reply_data.dsize = state->call.reply_data.dsize;

=== modified file 'common/ctdb_client.c'
--- a/common/ctdb_client.c	2007-04-28 15:42:40 +0000
+++ b/common/ctdb_client.c	2007-04-29 14:19:40 +0000
@@ -78,7 +78,7 @@
 
 	if (hdr->reqid != state->reqid) {
 		/* we found a record  but it was the wrong one */
-		DEBUG(0, ("Dropped orphaned reply with reqid:%d\n",hdr->reqid));
+		DEBUG(0, ("Dropped client call reply with reqid:%d\n",hdr->reqid));
 		return;
 	}
 
@@ -414,7 +414,6 @@
 	CTDB_NO_MEMORY(ctdb, r);
 
 	r->hdr.destnode  = vnn;
-	r->hdr.srcnode   = ctdb->vnn;
 	r->srvid         = srvid;
 	r->datalen       = data.dsize;
 	memcpy(&r->data[0], data.dptr, data.dsize);
@@ -674,7 +673,6 @@
 	
 	c->hdr.reqid        = state->reqid;
 	c->hdr.destnode     = destnode;
-	c->hdr.srcnode      = ctdb->vnn;
 	c->hdr.reqid        = state->reqid;
 	c->opcode           = opcode;
 	c->srvid            = srvid;
@@ -1054,3 +1052,24 @@
 	talloc_free(map);
 	return nodes;
 }
+
+
+/*
+  reset remote status
+ */
+int ctdb_status_reset(struct ctdb_context *ctdb, uint32_t destnode)
+{
+	int ret;
+	TDB_DATA data;
+	int32_t res;
+
+	ZERO_STRUCT(data);
+	ret = ctdb_control(ctdb, destnode, 0, 
+			   CTDB_CONTROL_STATUS_RESET, data, 
+			   NULL, NULL, &res);
+	if (ret != 0 || res != 0) {
+		DEBUG(0,(__location__ " ctdb_control for reset status failed\n"));
+		return -1;
+	}
+	return 0;
+}

=== modified file 'common/ctdb_control.c'
--- a/common/ctdb_control.c	2007-04-28 13:15:21 +0000
+++ b/common/ctdb_control.c	2007-04-29 14:19:40 +0000
@@ -80,6 +80,12 @@
 		return 0;
 	}
 
+	case CTDB_CONTROL_STATUS_RESET: {
+		CHECK_CONTROL_DATA_SIZE(0);
+		ZERO_STRUCT(ctdb->status);
+		return 0;
+	}
+
 	case CTDB_CONTROL_GETVNNMAP: {
 		uint32_t i, len;
 		CHECK_CONTROL_DATA_SIZE(0);
@@ -242,6 +248,8 @@
 
 	state = ctdb_reqid_find(ctdb, hdr->reqid, struct ctdb_control_state);
 	if (state == NULL) {
+		DEBUG(0,("vnn %u Invalid reqid %u in ctdb_reply_control\n",
+			 ctdb->vnn, hdr->reqid));
 		return;
 	}
 

=== modified file 'common/ctdb_daemon.c'
--- a/common/ctdb_daemon.c	2007-04-28 13:15:21 +0000
+++ b/common/ctdb_daemon.c	2007-04-29 14:19:40 +0000
@@ -673,6 +673,48 @@
 	return 0;
 }
 
+
+/*
+  start the protocol going as a daemon
+*/
+int ctdb_start_daemon(struct ctdb_context *ctdb)
+{
+	int res;
+	struct fd_event *fde;
+	const char *domain_socket_name;
+
+	/* get rid of any old sockets */
+	unlink(ctdb->daemon.name);
+
+	/* create a unix domain stream socket to listen to */
+	res = ux_socket_bind(ctdb);
+	if (res!=0) {
+		DEBUG(0,(__location__ " Failed to open CTDB unix domain socket\n"));
+		exit(10);
+	}
+
+	if (fork()) {
+		return 0;
+	}
+
+	tdb_reopen_all(False);
+
+	setsid();
+	block_signal(SIGPIPE);
+	block_signal(SIGCHLD);
+
+	/* ensure the socket is deleted on exit of the daemon */
+	domain_socket_name = talloc_strdup(talloc_autofree_context(), ctdb->daemon.name);
+	talloc_set_destructor(domain_socket_name, unlink_destructor);	
+
+	ctdb->ev = event_context_init(NULL);
+	fde = event_add_fd(ctdb->ev, ctdb, ctdb->daemon.sd, EVENT_FD_READ, 
+			   ctdb_accept_client, ctdb);
+	ctdb_main_loop(ctdb);
+
+	return 0;
+}
+
 /*
   allocate a packet for use in client<->daemon communication
  */
@@ -685,6 +727,7 @@
 	int size;
 	struct ctdb_req_header *hdr;
 	size = ((length+1)+(CTDB_DS_ALIGNMENT-1)) & ~(CTDB_DS_ALIGNMENT-1);
+
 	hdr = (struct ctdb_req_header *)talloc_size(mem_ctx, size);
 	if (hdr == NULL) {
 		DEBUG(0,("Unable to allocate packet for operation %u of length %u\n",
@@ -692,11 +735,12 @@
 		return NULL;
 	}
 	talloc_set_name_const(hdr, type);
-	memset(hdr, 0, slength);
+	memset(hdr, 0, size);
 	hdr->operation    = operation;
-	hdr->length       = length;
+	hdr->length       = size;
 	hdr->ctdb_magic   = CTDB_MAGIC;
 	hdr->ctdb_version = CTDB_VERSION;
+	hdr->srcnode      = ctdb->vnn;
 	if (ctdb->vnn_map) {
 		hdr->generation = ctdb->vnn_map->generation;
 	}
@@ -724,9 +768,9 @@
 		return NULL;
 	}
 	talloc_set_name_const(hdr, type);
-	memset(hdr, 0, slength);
+	memset(hdr, 0, size);
 	hdr->operation    = operation;
-	hdr->length       = length;
+	hdr->length       = size;
 	hdr->ctdb_magic   = CTDB_MAGIC;
 	hdr->ctdb_version = CTDB_VERSION;
 	hdr->generation   = ctdb->vnn_map->generation;

=== modified file 'common/ctdb_io.c'
--- a/common/ctdb_io.c	2007-04-16 00:21:44 +0000
+++ b/common/ctdb_io.c	2007-04-29 14:19:40 +0000
@@ -64,8 +64,10 @@
 	ssize_t nread;
 	uint8_t *data, *data_base;
 
-	if (ioctl(queue->fd, FIONREAD, &num_ready) != 0 ||
-	    num_ready == 0) {
+	if (ioctl(queue->fd, FIONREAD, &num_ready) != 0) {
+		return;
+	}
+	if (num_ready == 0) {
 		/* the descriptor has been closed */
 		goto failed;
 	}
@@ -75,11 +77,14 @@
 						  num_ready + queue->partial.length);
 
 	if (queue->partial.data == NULL) {
+		DEBUG(0,("read error alloc failed for %u\n", 
+			 num_ready + queue->partial.length));
 		goto failed;
 	}
 
 	nread = read(queue->fd, queue->partial.data + queue->partial.length, num_ready);
 	if (nread <= 0) {
+		DEBUG(0,("read error nread=%d\n", nread));
 		goto failed;
 	}
 
@@ -106,6 +111,7 @@
 		len = *(uint32_t *)data;
 		d2 = talloc_memdup(queue, data, len);
 		if (d2 == NULL) {
+			DEBUG(0,("read error memdup failed for %u\n", len));
 			/* sigh */
 			goto failed;
 		}
@@ -122,6 +128,8 @@
 		} else {
 			queue->partial.data = talloc_memdup(queue, data, nread);
 			if (queue->partial.data == NULL) {
+				DEBUG(0,("read error memdup partial failed for %u\n", 
+					 nread));
 				goto failed;
 			}
 			queue->partial.length = nread;
@@ -155,8 +163,11 @@
 	while (queue->out_queue) {
 		struct ctdb_queue_pkt *pkt = queue->out_queue;
 		ssize_t n;
-
-		n = write(queue->fd, pkt->data, pkt->length);
+		if (queue->ctdb->flags & CTDB_FLAG_TORTURE) {
+			n = write(queue->fd, pkt->data, 1);
+		} else {
+			n = write(queue->fd, pkt->data, pkt->length);
+		}
 
 		if (n == -1 && errno != EAGAIN && errno != EWOULDBLOCK) {
 			event_add_timed(queue->ctdb->ev, queue, timeval_zero(), 
@@ -213,7 +224,8 @@
 	
 	/* if the queue is empty then try an immediate write, avoiding
 	   queue overhead. This relies on non-blocking sockets */
-	if (queue->out_queue == NULL && queue->fd != -1) {
+	if (queue->out_queue == NULL && queue->fd != -1 &&
+	    !(queue->ctdb->flags & CTDB_FLAG_TORTURE)) {
 		ssize_t n = write(queue->fd, data, length2);
 		if (n == -1 && errno != EAGAIN && errno != EWOULDBLOCK) {
 			event_add_timed(queue->ctdb->ev, queue, timeval_zero(), 

=== modified file 'common/ctdb_util.c'
--- a/common/ctdb_util.c	2007-04-28 08:50:32 +0000
+++ b/common/ctdb_util.c	2007-04-29 14:19:40 +0000
@@ -129,6 +129,51 @@
 	}
 }
 
+#if 0
+struct idr_fake {
+	uint32_t size;
+	void **ptrs;
+};
+
+static void idr_fake_init(struct ctdb_context *ctdb)
+{
+	if (ctdb->fidr) return;
+	ctdb->fidr = talloc(ctdb, struct idr_fake);
+	ctdb->fidr->size = 0x10000;
+	ctdb->fidr->ptrs = talloc_zero_array(ctdb->fidr, void *, 
+						 ctdb->fidr->size);
+}
+
+uint32_t ctdb_reqid_new(struct ctdb_context *ctdb, void *state)
+{
+	uint32_t i;
+	idr_fake_init(ctdb);
+	for (i=0;i<ctdb->fidr->size;i++) {
+		if (ctdb->fidr->ptrs[i] == NULL) {
+			ctdb->fidr->ptrs[i] = state;
+			return i;
+		}
+	}
+	return (uint32_t)-1;
+}
+
+void *_ctdb_reqid_find(struct ctdb_context *ctdb, uint32_t reqid, const char *type, const char *location)
+{
+	idr_fake_init(ctdb);
+	if (ctdb->fidr->ptrs[reqid] == NULL) {
+		DEBUG(0,("bad fidr id %u\n", reqid));
+	}
+	return ctdb->fidr->ptrs[reqid];
+}
+
+
+void ctdb_reqid_remove(struct ctdb_context *ctdb, uint32_t reqid)
+{
+	idr_fake_init(ctdb);
+	ctdb->fidr->ptrs[reqid] = NULL;
+}
+
+#else
 uint32_t ctdb_reqid_new(struct ctdb_context *ctdb, void *state)
 {
 	uint32_t id;
@@ -161,3 +206,4 @@
 	}
 }
 
+#endif

=== modified file 'direct/ctdbd.c'
--- a/direct/ctdbd.c	2007-04-18 23:14:25 +0000
+++ b/direct/ctdbd.c	2007-04-29 14:19:40 +0000
@@ -56,7 +56,6 @@
 	int opt;
 	const char **extra_argv;
 	int extra_argc = 0;
-	int ret;
 	poptContext pc;
 	struct event_context *ev;
 
@@ -91,22 +90,13 @@
 		ctdb_db = ctdb_attach(ctdb, tok, TDB_DEFAULT, 
 				      O_RDWR|O_CREAT|O_TRUNC, 0666);
 		if (!ctdb_db) {
-			printf("ctdb_attach to '%s'failed - %s\n", tok, 
-			       ctdb_errstr(ctdb));
+			DEBUG(0,("ctdb_attach to '%s'failed - %s\n", tok, 
+				 ctdb_errstr(ctdb)));
 			exit(1);
 		}
-		printf("Attached to database '%s'\n", tok);
-	}
-
-	/* start the protocol running */
-	ret = ctdb_start(ctdb);
-
-/*	event_loop_wait(ev);*/
-	while (1) {
-		event_loop_once(ev);
-	}
-
-	/* shut it down */
-	talloc_free(ev);
-	return 0;
+		DEBUG(1, ("Attached to database '%s'\n", tok));
+	}
+
+	/* start the protocol running (as a child) */
+	return ctdb_start_daemon(ctdb);
 }

=== modified file 'include/ctdb.h'
--- a/include/ctdb.h	2007-04-28 15:42:40 +0000
+++ b/include/ctdb.h	2007-04-29 14:19:40 +0000
@@ -107,6 +107,7 @@
   start the ctdb protocol
 */
 int ctdb_start(struct ctdb_context *ctdb);
+int ctdb_start_daemon(struct ctdb_context *ctdb);
 
 /*
   attach to a ctdb database
@@ -256,4 +257,6 @@
 uint32_t *ctdb_get_connected_nodes(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx,
 				   uint32_t *num_nodes);
 
+int ctdb_status_reset(struct ctdb_context *ctdb, uint32_t destnode);
+
 #endif

=== modified file 'include/ctdb_private.h'
--- a/include/ctdb_private.h	2007-04-28 16:18:33 +0000
+++ b/include/ctdb_private.h	2007-04-29 14:19:40 +0000
@@ -195,6 +195,7 @@
 	struct ctdb_status status;
 	struct ctdb_vnn_map *vnn_map;
 	uint32_t num_clients;
+	struct idr_fake *fidr;
 };
 
 struct ctdb_db_context {
@@ -251,7 +252,8 @@
 		    CTDB_CONTROL_GET_DEBUG,
 		    CTDB_CONTROL_SET_DEBUG,
 		    CTDB_CONTROL_GET_DBMAP,
-		    CTDB_CONTROL_GET_NODEMAP};
+		    CTDB_CONTROL_GET_NODEMAP,
+		    CTDB_CONTROL_STATUS_RESET};
 
 enum call_state {CTDB_CALL_WAIT, CTDB_CALL_DONE, CTDB_CALL_ERROR};
 
@@ -263,10 +265,8 @@
 	uint32_t reqid;
 	struct ctdb_req_call *c;
 	struct ctdb_db_context *ctdb_db;
-	struct ctdb_node *node;
 	const char *errmsg;
 	struct ctdb_call call;
-	struct ctdb_ltdb_header header;
 	struct {
 		void (*fn)(struct ctdb_call_state *);
 		void *private_data;
@@ -347,6 +347,7 @@
 struct ctdb_req_dmaster {
 	struct ctdb_req_header hdr;
 	uint32_t db_id;
+	uint64_t rsn;
 	uint32_t dmaster;
 	uint32_t keylen;
 	uint32_t datalen;
@@ -355,6 +356,9 @@
 
 struct ctdb_reply_dmaster {
 	struct ctdb_req_header hdr;
+	uint32_t db_id;
+	uint64_t rsn;
+	uint32_t keylen;
 	uint32_t datalen;
 	uint8_t  data[1];
 };

=== modified file 'tools/ctdb_control.c'
--- a/tools/ctdb_control.c	2007-04-28 16:18:33 +0000
+++ b/tools/ctdb_control.c	2007-04-28 17:13:36 +0000
@@ -36,6 +36,7 @@
 	printf("  ping\n");
 	printf("  process-exists <vnn:pid>           see if a process exists\n");
 	printf("  status <vnn|all>                   show ctdb status on a node\n");
+	printf("  statusreset <vnn|all>              reset status on a node\n");
 	printf("  debug <vnn|all> <level>            set ctdb debug level on a node\n");
 	printf("  debuglevel                         display ctdb debug levels\n");
 	printf("  getvnnmap <vnn>                    display ctdb vnnmap\n");
@@ -170,6 +171,56 @@
 	return 0;
 }
 
+
+/*
+  reset status on all nodes
+ */
+static int control_status_reset_all(struct ctdb_context *ctdb)
+{
+	int ret, i;
+	uint32_t *nodes;
+	uint32_t num_nodes;
+
+	nodes = ctdb_get_connected_nodes(ctdb, ctdb, &num_nodes);
+	CTDB_NO_MEMORY(ctdb, nodes);
+	
+	for (i=0;i<num_nodes;i++) {
+		ret = ctdb_status_reset(ctdb, nodes[i]);
+		if (ret != 0) {
+			printf("Unable to reset status on node %u\n", nodes[i]);
+			return ret;
+		}
+	}
+	talloc_free(nodes);
+	return 0;
+}
+
+
+/*
+  reset remote ctdb status
+ */
+static int control_status_reset(struct ctdb_context *ctdb, int argc, const char **argv)
+{
+	uint32_t vnn;
+	int ret;
+	if (argc < 1) {
+		usage();
+	}
+
+	if (strcmp(argv[0], "all") == 0) {
+		return control_status_reset_all(ctdb);
+	}
+
+	vnn = strtoul(argv[0], NULL, 0);
+
+	ret = ctdb_status_reset(ctdb, vnn);
+	if (ret != 0) {
+		printf("Unable to reset status on node %u\n", vnn);
+		return ret;
+	}
+	return 0;
+}
+
 /*
   display remote ctdb vnn map
  */
@@ -441,6 +492,8 @@
 		ret = control_process_exists(ctdb, extra_argc-1, extra_argv+1);
 	} else if (strcmp(control, "status") == 0) {
 		ret = control_status(ctdb, extra_argc-1, extra_argv+1);
+	} else if (strcmp(control, "statusreset") == 0) {
+		ret = control_status_reset(ctdb, extra_argc-1, extra_argv+1);
 	} else if (strcmp(control, "getvnnmap") == 0) {
 		ret = control_getvnnmap(ctdb, extra_argc-1, extra_argv+1);
 	} else if (strcmp(control, "getdbmap") == 0) {



More information about the samba-cvs mailing list