[SCM] CTDB repository - branch master updated - e24152fbd06ba4c2b6cfd473751c7f00a676b9ae

Andrew Tridgell tridge at samba.org
Fri Jul 18 03:46:49 GMT 2008


The branch, master has been updated
       via  e24152fbd06ba4c2b6cfd473751c7f00a676b9ae (commit)
       via  af38c8d4cc03e1b5a314ea2338346c5f8c80aa95 (commit)
       via  ccf9334bd20b1398623dd649987aa15119dac14e (commit)
       via  1ffccb3e0b3b5bd376c5302304029af393709518 (commit)
       via  8140825e1d06053a900fd0adf0a150622c0fc146 (commit)
       via  05918bcb58acd2add7e13c028de09641a7519cd1 (commit)
       via  d7e9c0010a40f9335d28cf108e8f5cf411970a03 (commit)
       via  9478852f2b4f530994b2211fff45413d1da82dd9 (commit)
       via  2b0bd6c302545f2533a7a67dfc6bb5f9f60799f7 (commit)
      from  9043913a54fe707083697f0587c6ffde86ca5a69 (commit)

http://gitweb.samba.org/?p=tridge/ctdb.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit e24152fbd06ba4c2b6cfd473751c7f00a676b9ae
Author: Andrew Tridgell <tridge at samba.org>
Date:   Fri Jul 18 13:46:01 2008 +1000

    fixed a bug where we would look for a signal past the end of the
    signal arrays
    
    This could cause the events code to get into a loop chewing CPU

commit af38c8d4cc03e1b5a314ea2338346c5f8c80aa95
Merge: 05918bcb58acd2add7e13c028de09641a7519cd1 ccf9334bd20b1398623dd649987aa15119dac14e
Author: Andrew Tridgell <tridge at samba.org>
Date:   Thu Jul 17 18:45:15 2008 +1000

    Merge commit 'ronnie/master'

commit ccf9334bd20b1398623dd649987aa15119dac14e
Author: Ronnie Sahlberg <ronniesahlberg at gmail.com>
Date:   Thu Jul 17 13:56:17 2008 +1000

    new version 1.0.48

commit 1ffccb3e0b3b5bd376c5302304029af393709518
Author: Ronnie Sahlberg <ronniesahlberg at gmail.com>
Date:   Thu Jul 17 13:50:55 2008 +1000

    Add two new controls  to start and cancel a persistent update.
    This allows ctdb to automatically start a new full blown recovery
    if a client has started updating the local tdb for a persistent database
    but is kill -9ed before it has ensured the update is distributed clusterwide.

commit 8140825e1d06053a900fd0adf0a150622c0fc146
Author: Ronnie Sahlberg <ronniesahlberg at gmail.com>
Date:   Thu Jul 17 09:04:15 2008 +1000

    Do not allow "ctdb eventscript" to start new eventscripts while we are in recovery mode

commit 05918bcb58acd2add7e13c028de09641a7519cd1
Merge: 9478852f2b4f530994b2211fff45413d1da82dd9 d7e9c0010a40f9335d28cf108e8f5cf411970a03
Author: Andrew Tridgell <tridge at samba.org>
Date:   Wed Jul 16 16:58:16 2008 +1000

    Merge commit 'ronnie/master'

commit d7e9c0010a40f9335d28cf108e8f5cf411970a03
Merge: 2b0bd6c302545f2533a7a67dfc6bb5f9f60799f7 9043913a54fe707083697f0587c6ffde86ca5a69
Author: Ronnie Sahlberg <ronniesahlberg at gmail.com>
Date:   Wed Jul 16 16:51:37 2008 +1000

    Merge git://git.samba.org/tridge/ctdb

commit 9478852f2b4f530994b2211fff45413d1da82dd9
Merge: 9043913a54fe707083697f0587c6ffde86ca5a69 2b0bd6c302545f2533a7a67dfc6bb5f9f60799f7
Author: Andrew Tridgell <tridge at samba.org>
Date:   Wed Jul 16 12:46:43 2008 +1000

    Merge commit 'ronnie/master'

commit 2b0bd6c302545f2533a7a67dfc6bb5f9f60799f7
Author: Ronnie Sahlberg <ronniesahlberg at gmail.com>
Date:   Wed Jul 16 12:23:18 2008 +1000

    change how we filter out "empty" records in the traversecode
    so that we output the same list of keys in "catdb" as "tdbdump".
    
    when traversing a persistent database, as an optimization, only
    traverse on the local node (and thus skip checking if we are
    dmaster or not). If the local node is not part of the vnnmap and thus
    would not be guaranteed to have an uptodate persistent database
    we instead traverse it on one of the other nodes that are in the vnnmap.

-----------------------------------------------------------------------

Summary of changes:
 client/ctdb_client.c       |    5 ++-
 include/ctdb_private.h     |    9 +++++
 lib/events/events_signal.c |   10 +++---
 packaging/RPM/ctdb.spec    |   13 +++++++-
 server/ctdb_control.c      |    6 ++++
 server/ctdb_daemon.c       |    6 ++++
 server/ctdb_persistent.c   |   48 +++++++++++++++++++++++++++++
 server/ctdb_traverse.c     |   71 +++++++++++++++++++++++++++++++++++--------
 server/eventscript.c       |    5 +++
 9 files changed, 150 insertions(+), 23 deletions(-)


Changeset truncated at 500 lines:

diff --git a/client/ctdb_client.c b/client/ctdb_client.c
index ed999f2..544f5d1 100644
--- a/client/ctdb_client.c
+++ b/client/ctdb_client.c
@@ -1847,6 +1847,7 @@ int ctdb_traverse(struct ctdb_db_context *ctdb_db, ctdb_traverse_func fn, void *
 	return state.count;
 }
 
+#define ISASCII(x) ((x>31)&&(x<128))
 /*
   called on each key during a catdb
  */
@@ -1861,7 +1862,7 @@ static int dumpdb_fn(struct ctdb_context *ctdb, TDB_DATA key, TDB_DATA data, voi
 
 	fprintf(f, "key(%u) = \"", (unsigned)key.dsize);
 	for (i=0;i<key.dsize;i++) {
-		if (isascii(key.dptr[i])) {
+		if (ISASCII(key.dptr[i])) {
 			fprintf(f, "%c", key.dptr[i]);
 		} else {
 			fprintf(f, "\\%02X", key.dptr[i]);
@@ -1871,7 +1872,7 @@ static int dumpdb_fn(struct ctdb_context *ctdb, TDB_DATA key, TDB_DATA data, voi
 
 	fprintf(f, "data(%u) = \"", (unsigned)data.dsize);
 	for (i=sizeof(*h);i<data.dsize;i++) {
-		if (isascii(data.dptr[i])) {
+		if (ISASCII(data.dptr[i])) {
 			fprintf(f, "%c", data.dptr[i]);
 		} else {
 			fprintf(f, "\\%02X", data.dptr[i]);
diff --git a/include/ctdb_private.h b/include/ctdb_private.h
index 4124f64..66e7709 100644
--- a/include/ctdb_private.h
+++ b/include/ctdb_private.h
@@ -161,6 +161,7 @@ struct ctdb_client {
 	uint32_t client_id;
 	pid_t pid;
 	struct ctdb_tcp_list *tcp_list;
+	uint32_t num_persistent_updates;
 };
 
 
@@ -544,6 +545,8 @@ enum ctdb_controls {CTDB_CONTROL_PROCESS_EXISTS          = 0,
 		    CTDB_CONTROL_DEL_PUBLIC_IP           = 78,
 		    CTDB_CONTROL_RUN_EVENTSCRIPTS        = 79,
 		    CTDB_CONTROL_GET_CAPABILITIES	 = 80,
+		    CTDB_CONTROL_START_PERSISTENT_UPDATE = 81,
+		    CTDB_CONTROL_CANCEL_PERSISTENT_UPDATE= 82,
 };	
 
 /*
@@ -812,6 +815,12 @@ int ctdb_ltdb_store(struct ctdb_db_context *ctdb_db, TDB_DATA key,
 		    struct ctdb_ltdb_header *header, TDB_DATA data);
 int ctdb_ltdb_persistent_store(struct ctdb_db_context *ctdb_db, TDB_DATA key, 
 		    struct ctdb_ltdb_header *header, TDB_DATA data);
+int32_t ctdb_control_start_persistent_update(struct ctdb_context *ctdb, 
+			struct ctdb_req_control *c,
+			TDB_DATA recdata);
+int32_t ctdb_control_cancel_persistent_update(struct ctdb_context *ctdb, 
+			struct ctdb_req_control *c,
+			TDB_DATA recdata);
 void ctdb_queue_packet(struct ctdb_context *ctdb, struct ctdb_req_header *hdr);
 void ctdb_queue_packet_opcode(struct ctdb_context *ctdb, struct ctdb_req_header *hdr, unsigned opcode);
 int ctdb_ltdb_lock_requeue(struct ctdb_db_context *ctdb_db, 
diff --git a/lib/events/events_signal.c b/lib/events/events_signal.c
index 2f6d499..128a9bc 100644
--- a/lib/events/events_signal.c
+++ b/lib/events/events_signal.c
@@ -46,15 +46,15 @@ struct sigcounter {
   the poor design of signals means that this table must be static global
 */
 static struct sig_state {
-	struct signal_event *sig_handlers[NUM_SIGNALS];
-	struct sigaction *oldact[NUM_SIGNALS];
-	struct sigcounter signal_count[NUM_SIGNALS];
+	struct signal_event *sig_handlers[NUM_SIGNALS+1];
+	struct sigaction *oldact[NUM_SIGNALS+1];
+	struct sigcounter signal_count[NUM_SIGNALS+1];
 	struct sigcounter got_signal;
 	int pipe_hack[2];
 #ifdef SA_SIGINFO
 	/* with SA_SIGINFO we get quite a lot of info per signal */
-	siginfo_t *sig_info[NUM_SIGNALS];
-	struct sigcounter sig_blocked[NUM_SIGNALS];
+	siginfo_t *sig_info[NUM_SIGNALS+1];
+	struct sigcounter sig_blocked[NUM_SIGNALS+1];
 #endif
 } *sig_state;
 
diff --git a/packaging/RPM/ctdb.spec b/packaging/RPM/ctdb.spec
index 07ae721..84f9cf6 100644
--- a/packaging/RPM/ctdb.spec
+++ b/packaging/RPM/ctdb.spec
@@ -5,7 +5,7 @@ Vendor: Samba Team
 Packager: Samba Team <samba at samba.org>
 Name: ctdb
 Version: 1.0
-Release: 47
+Release: 48
 Epoch: 0
 License: GNU GPL version 3
 Group: System Environment/Daemons
@@ -118,7 +118,16 @@ fi
 %{_includedir}/ctdb_private.h
 
 %changelog
-* Fri Jul 11 2008 : Version 1.0.48-pre
+* Thu Jul 17 2008 : Version 1.0.48
+ - Update the spec file.
+ - Do not start new user-triggered eventscripts if we are already
+   inside recovery mode.
+ - Add two new controls to start/cancel a persistent update.
+   A client such as samba can use these to tell ctdbd that it will soon
+   be writing directly to the persistent database tdb file. So if
+   samba is -9ed before it has eitehr done the persistent_store or
+   canceled the operation, ctdb knows that the persistent databases
+   'may' be out of sync and therefore a full blown recovery is called for.
  - Add two new options :
    CTDB_SAMBA_SKIP_CONF_CHECK and CTDB_SAMBA_CHECK_PORTS that can be used
    to override what checks to do when monitoring samba health.
diff --git a/server/ctdb_control.c b/server/ctdb_control.c
index aaadbae..1ae8e85 100644
--- a/server/ctdb_control.c
+++ b/server/ctdb_control.c
@@ -394,6 +394,12 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb,
 	case CTDB_CONTROL_GET_CAPABILITIES:
 		return ctdb_control_get_capabilities(ctdb, outdata);
 
+	case CTDB_CONTROL_START_PERSISTENT_UPDATE:
+		return ctdb_control_start_persistent_update(ctdb, c, indata);
+
+	case CTDB_CONTROL_CANCEL_PERSISTENT_UPDATE:
+		return ctdb_control_cancel_persistent_update(ctdb, c, indata);
+
 	default:
 		DEBUG(DEBUG_CRIT,(__location__ " Unknown CTDB control opcode %u\n", opcode));
 		return -1;
diff --git a/server/ctdb_daemon.c b/server/ctdb_daemon.c
index c153a97..aeb0cbd 100644
--- a/server/ctdb_daemon.c
+++ b/server/ctdb_daemon.c
@@ -210,6 +210,12 @@ static int ctdb_client_destructor(struct ctdb_client *client)
 	ctdb_takeover_client_destructor_hook(client);
 	ctdb_reqid_remove(client->ctdb, client->client_id);
 	client->ctdb->statistics.num_clients--;
+
+	if (client->num_persistent_updates != 0) {
+		DEBUG(DEBUG_ERR,(__location__ " Client disconnecting with %u persistent updates in flight. Starting recovery\n", client->num_persistent_updates));
+		client->ctdb->recovery_mode = CTDB_RECOVERY_ACTIVE;
+	}
+
 	return 0;
 }
 
diff --git a/server/ctdb_persistent.c b/server/ctdb_persistent.c
index 713950a..66311a9 100644
--- a/server/ctdb_persistent.c
+++ b/server/ctdb_persistent.c
@@ -81,9 +81,16 @@ int32_t ctdb_control_persistent_store(struct ctdb_context *ctdb,
 				      struct ctdb_req_control *c, 
 				      TDB_DATA recdata, bool *async_reply)
 {
+	struct ctdb_client *client = ctdb_reqid_find(ctdb, c->client_id, struct ctdb_client);
 	struct ctdb_persistent_state *state;
 	int i;
 
+	if (client == NULL) {
+		DEBUG(DEBUG_ERR,(__location__ " can not match persistent_store to a client. Returning error\n"));
+		return -1;
+	}
+	client->num_persistent_updates--;
+
 	state = talloc_zero(ctdb, struct ctdb_persistent_state);
 	CTDB_NO_MEMORY(ctdb, state);
 
@@ -410,3 +417,44 @@ int32_t ctdb_control_update_record(struct ctdb_context *ctdb,
 
 	return 0;
 }
+
+
+
+/*
+  start a persistent store operation. passing both the key, header and
+  data to the daemon. If the client disconnects before it has issued
+  a persistent_update call to the daemon we trigger a full recovery
+  to ensure the databases are brought back in sync.
+  for now we ignore the recdata that the client has passed to us.
+ */
+int32_t ctdb_control_start_persistent_update(struct ctdb_context *ctdb, 
+				      struct ctdb_req_control *c,
+				      TDB_DATA recdata)
+{
+	struct ctdb_client *client = ctdb_reqid_find(ctdb, c->client_id, struct ctdb_client);
+
+	if (client == NULL) {
+		DEBUG(DEBUG_ERR,(__location__ " can not match start_persistent_update to a client. Returning error\n"));
+		return -1;
+	}
+
+	client->num_persistent_updates++;
+
+	return 0;
+}
+
+int32_t ctdb_control_cancel_persistent_update(struct ctdb_context *ctdb, 
+				      struct ctdb_req_control *c,
+				      TDB_DATA recdata)
+{
+	struct ctdb_client *client = ctdb_reqid_find(ctdb, c->client_id, struct ctdb_client);
+
+	if (client == NULL) {
+		DEBUG(DEBUG_ERR,(__location__ " can not match cancel_persistent_update to a client. Returning error\n"));
+		return -1;
+	}
+
+	client->num_persistent_updates--;
+
+	return 0;
+}
diff --git a/server/ctdb_traverse.c b/server/ctdb_traverse.c
index 10895ed..35ae318 100644
--- a/server/ctdb_traverse.c
+++ b/server/ctdb_traverse.c
@@ -87,11 +87,19 @@ static int ctdb_traverse_local_fn(struct tdb_context *tdb, TDB_DATA key, TDB_DAT
 	struct ctdb_rec_data *d;
 	struct ctdb_ltdb_header *hdr;
 
-	/* filter out non-authoritative and zero-length records */
+	
 	hdr = (struct ctdb_ltdb_header *)data.dptr;
-	if (data.dsize <= sizeof(struct ctdb_ltdb_header) ||
-	    hdr->dmaster != h->ctdb_db->ctdb->pnn) {
-		return 0;
+
+	if (h->ctdb_db->persistent == 0) {
+		/* filter out zero-length records */
+		if (data.dsize <= sizeof(struct ctdb_ltdb_header)) {
+			return 0;
+		}
+
+		/* filter out non-authoritative records */
+		if (hdr->dmaster != h->ctdb_db->ctdb->pnn) {
+			return 0;
+		}
 	}
 
 	d = ctdb_marshall_record(h, 0, key, NULL, data);
@@ -174,6 +182,7 @@ static struct ctdb_traverse_local_handle *ctdb_traverse_local(struct ctdb_db_con
 
 struct ctdb_traverse_all_handle {
 	struct ctdb_context *ctdb;
+	struct ctdb_db_context *ctdb_db;
 	uint32_t reqid;
 	ctdb_traverse_fn_t callback;
 	void *private_data;
@@ -224,17 +233,19 @@ static struct ctdb_traverse_all_handle *ctdb_daemon_traverse_all(struct ctdb_db_
 	int ret;
 	TDB_DATA data;
 	struct ctdb_traverse_all r;
+	uint32_t destination;
 
 	state = talloc(ctdb_db, struct ctdb_traverse_all_handle);
 	if (state == NULL) {
 		return NULL;
 	}
 
-	state->ctdb = ctdb;
-	state->reqid = ctdb_reqid_new(ctdb_db->ctdb, state);
-	state->callback = callback;
+	state->ctdb         = ctdb;
+	state->ctdb_db      = ctdb_db;
+	state->reqid        = ctdb_reqid_new(ctdb_db->ctdb, state);
+	state->callback     = callback;
 	state->private_data = private_data;
-	state->null_count = 0;
+	state->null_count   = 0;
 	
 	talloc_set_destructor(state, ctdb_traverse_all_destructor);
 
@@ -245,10 +256,37 @@ static struct ctdb_traverse_all_handle *ctdb_daemon_traverse_all(struct ctdb_db_
 	data.dptr = (uint8_t *)&r;
 	data.dsize = sizeof(r);
 
-	/* tell all the nodes in the cluster to start sending records to this node */
-	ret = ctdb_daemon_send_control(ctdb, CTDB_BROADCAST_VNNMAP, 0, 
-				       CTDB_CONTROL_TRAVERSE_ALL,
-				       0, CTDB_CTRL_FLAG_NOREPLY, data, NULL, NULL);
+	if (ctdb_db->persistent == 0) {
+		/* normal database, traverse all nodes */	  
+		destination = CTDB_BROADCAST_VNNMAP;
+	} else {
+		int i;
+		/* persistent database, traverse one node, preferably
+		 * the local one
+		 */
+		destination = ctdb->pnn;
+		/* check we are in the vnnmap */
+		for (i=0; i < ctdb->vnn_map->size; i++) {
+			if (ctdb->vnn_map->map[i] == ctdb->pnn) {
+				break;
+			}
+		}
+		/* if we are not in the vnn map we just pick the first
+		 * node instead
+		 */
+		if (i == ctdb->vnn_map->size) {
+			destination = ctdb->vnn_map->map[0];
+		}
+	}
+
+	/* tell all the nodes in the cluster to start sending records to this
+	 * node, or if it is a persistent database, just tell the local
+	 * node
+	 */
+	ret = ctdb_daemon_send_control(ctdb, destination, 0, 
+			       CTDB_CONTROL_TRAVERSE_ALL,
+			       0, CTDB_CTRL_FLAG_NOREPLY, data, NULL, NULL);
+
 	if (ret != 0) {
 		talloc_free(state);
 		return NULL;
@@ -371,8 +409,13 @@ int32_t ctdb_control_traverse_data(struct ctdb_context *ctdb, TDB_DATA data, TDB
 
 	if (key.dsize == 0 && data.dsize == 0) {
 		state->null_count++;
-		if (state->null_count != ctdb_get_num_active_nodes(ctdb)) {
-			return 0;
+		/* Persistent databases are only scanned on one node (the local
+		 * node)
+		 */
+		if (state->ctdb_db->persistent == 0) {
+			if (state->null_count != ctdb_get_num_active_nodes(ctdb)) {
+				return 0;
+			}
 		}
 	}
 
diff --git a/server/eventscript.c b/server/eventscript.c
index 3168122..057bc80 100644
--- a/server/eventscript.c
+++ b/server/eventscript.c
@@ -489,6 +489,11 @@ int32_t ctdb_run_eventscripts(struct ctdb_context *ctdb,
 
 	DEBUG(DEBUG_NOTICE,("Forced running of eventscripts with arguments %s\n", indata.dptr));
 
+	if (ctdb->recovery_mode != CTDB_RECOVERY_NORMAL) {
+		DEBUG(DEBUG_ERR, (__location__ " Aborted running eventscript \"%s\" while in RECOVERY mode\n", indata.dptr));
+		return -1;
+	}
+
 	ctdb_disable_monitoring(ctdb);
 
 	ret = ctdb_event_script_callback(ctdb, 


-- 
CTDB repository


More information about the samba-cvs mailing list