[SCM] CTDB repository - branch 1.2.40 updated - ctdb-1.2.57-7-g4455822

Amitay Isaacs amitay at samba.org
Tue Feb 19 00:09:33 MST 2013


The branch, 1.2.40 has been updated
       via  44558223c2f83cafbe4ee63b4ce3d508dc7f0a02 (commit)
       via  9d8338fc14cfa5f4d8236eccb90ffdd4cdc11343 (commit)
       via  c6e1b84595039edb5c49a5851b440710dc0e2ac1 (commit)
       via  aae948c3c2ce1d2678ce57b4219674bafda5008e (commit)
       via  4697a83866a04357d386473a50685f677a730daf (commit)
       via  1cbdb44d604461509676b903a9e9515e7cab2598 (commit)
       via  537bed11c339a10faf45a6ede778f7c8e26e4f91 (commit)
      from  584e8c25971219614f3f2bfd5be233b04de7e0af (commit)

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


- Log -----------------------------------------------------------------
commit 44558223c2f83cafbe4ee63b4ce3d508dc7f0a02
Author: Amitay Isaacs <amitay at gmail.com>
Date:   Tue Feb 19 18:09:05 2013 +1100

    New Version 1.2.58
    
    Signed-off-by: Amitay Isaacs <amitay at gmail.com>

commit 9d8338fc14cfa5f4d8236eccb90ffdd4cdc11343
Author: Ronnie Sahlberg <ronniesahlberg at gmail.com>
Date:   Fri May 25 12:27:59 2012 +1000

    RECOVER: When we pull databases during recovery, we used to reallocate the databuffer for each entry added. This would normally not be an issue, but for cases where memory is fragmented, this could start to cost significant cpu if we need to reallocate and move to a different region.
    
    Change this to instead preallocate , by default, 10MByte chunks to the data buffer.
    This significantly reduces the number of potential reallocate and move  operations that may be required.
    
    Create a tunable to override/change how much preallocation should be used.
    
    Conflicts:
    	include/ctdb_private.h
    	server/ctdb_tunables.c
    
    Cherry-pick-from: 1f262deaad0818f159f9c68330f7fec121679023
    
    Also, make sure the preallocation size is 10MB and not 100MB.
    
    Signed-off-by: Amitay Isaacs <amitay at gmail.com>

commit c6e1b84595039edb5c49a5851b440710dc0e2ac1
Author: Martin Schwenke <martin at meltin.net>
Date:   Tue Feb 5 12:09:36 2013 +1100

    Logging: Free the ringbuffer in child processes created with ctdb_fork()
    
    At the moment the log ringbuffer is duplicated in every child process.
    Althought it is copy-on-write we want to see if it is contributing to
    out-of-memory situations when there are a lot of children.
    
    The ringbuffer isn't accessible from any of the children anyway...
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    
    Conflicts:
    	common/ctdb_fork.c
    
    Cherry-pick-from: a82d3ec12f0fda16d6bfa8442a07595de897c10e

commit aae948c3c2ce1d2678ce57b4219674bafda5008e
Author: Martin Schwenke <martin at meltin.net>
Date:   Tue Feb 5 12:08:11 2013 +1100

    Logging: New function ctdb_log_ringbuffer_free()
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    
    Cherry-pick-from: a4f622e85168f59417c11705f1734e0352e1d44a

commit 4697a83866a04357d386473a50685f677a730daf
Author: Amitay Isaacs <amitay at gmail.com>
Date:   Mon Feb 11 11:25:49 2013 +1100

    eventscripts: Remove calls to "smbstatus -np" for samba cleanup
    
    This is an artifact from older versions of Samba. In the newer versions of
    Samba, "smbstatus -np" command does not do anything useful, but causes a
    traverse in CTDB which is expensive and causes CPU utilization to shoot up.
    
    Signed-off-by: Amitay Isaacs <amitay at gmail.com>
    
    Conflicts:
    	config/events.d/50.samba
    
    Cherry-pick-from: 053b89c6dbce47001505524606889334559d2ec4

commit 1cbdb44d604461509676b903a9e9515e7cab2598
Author: Amitay Isaacs <amitay at gmail.com>
Date:   Fri Jan 18 10:42:14 2013 +1100

    common/io: Rewrite socket handling code to read all available data
    
    This improves the processing of packets considerably.  It has been
    observed that there can be as many as 10 packets in the socket buffer and
    the current code of reading a single packet from a socket at a time is
    not very optimal.  This change reads all the bytes from socket buffer and
    then parses to extract multiple packets.  If there are multiple packets,
    set up a timed event to process next packet.
    
    Signed-off-by: Amitay Isaacs <amitay at gmail.com>
    
    Cherry-pick-from: d788bc8f7212b7dc1587ae592242dc8c876f4053
    
    Conflicts:
    	common/ctdb_io.c

commit 537bed11c339a10faf45a6ede778f7c8e26e4f91
Author: Amitay Isaacs <amitay at gmail.com>
Date:   Tue Jan 22 13:27:20 2013 +1100

    daemon: Make sure all the traverse children are terminated if traverse times out
    
    When traverse times out, callback function is called with key and data set to
    tdb_null.  This is also the way to signal end of traverse.  So if the traverse
    times out, callback function treats it as traverse ended and frees state without
    calling the destructor.
    
    Keep track if the traverse timed out, so callback function can take appropriate
    action for traverse timeout and traverse end.
    
    Signed-off-by: Amitay Isaacs <amitay at gmail.com>
    
    Cherry-pick-from: 35da9a7c2a0f5e54e61588c3c3455f06ebc66822

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

Summary of changes:
 common/ctdb_io.c           |  160 +++++++++++++++++++++++++-------------------
 common/ctdb_logging.c      |    9 ++-
 common/ctdb_util.c         |    2 +
 config/events.d/50.samba   |   31 +--------
 include/ctdb_private.h     |    3 +-
 packaging/RPM/ctdb.spec.in |    8 ++-
 server/ctdb_recover.c      |    7 ++-
 server/ctdb_recoverd.c     |    7 ++-
 server/ctdb_traverse.c     |   14 +++-
 server/ctdb_tunables.c     |    1 +
 10 files changed, 138 insertions(+), 104 deletions(-)


Changeset truncated at 500 lines:

diff --git a/common/ctdb_io.c b/common/ctdb_io.c
index 0f44b87..2a12a18 100644
--- a/common/ctdb_io.c
+++ b/common/ctdb_io.c
@@ -31,9 +31,10 @@
 #include <stdarg.h>
 
 /* structures for packet queueing - see common/ctdb_io.c */
-struct ctdb_partial {
+struct ctdb_buffer {
 	uint8_t *data;
 	uint32_t length;
+	uint32_t size;
 };
 
 struct ctdb_queue_pkt {
@@ -45,7 +46,7 @@ struct ctdb_queue_pkt {
 
 struct ctdb_queue {
 	struct ctdb_context *ctdb;
-	struct ctdb_partial partial; /* partial input packet */
+	struct ctdb_buffer buffer; /* input buffer */
 	struct ctdb_queue_pkt *out_queue, *out_queue_tail;
 	uint32_t out_queue_length;
 	struct fd_event *fde;
@@ -79,6 +80,75 @@ static void dump_packet(unsigned char *data, size_t len)
 	talloc_free(p);
 }
 
+static void queue_process(struct ctdb_queue *queue);
+
+static void queue_process_event(struct event_context *ev, struct timed_event *te,
+				struct timeval t, void *private_data)
+{
+	struct ctdb_queue *queue = talloc_get_type(private_data, struct ctdb_queue);
+
+	queue_process(queue);
+}
+
+/*
+ * This function is used to process data in queue buffer.
+ *
+ * Queue callback function can end up freeing the queue, there should not be a
+ * loop processing packets from queue buffer.  Instead set up a timed event for
+ * immediate run to process remaining packets from buffer.
+ */
+static void queue_process(struct ctdb_queue *queue)
+{
+	uint32_t pkt_size;
+	uint8_t *data;
+
+	if (queue->buffer.length < sizeof(pkt_size)) {
+		return;
+	}
+
+	pkt_size = *(uint32_t *)queue->buffer.data;
+	if (pkt_size == 0) {
+		DEBUG(DEBUG_CRIT, ("Invalid packet of length 0\n"));
+		goto failed;
+	}
+
+	if (queue->buffer.length < pkt_size) {
+		DEBUG(DEBUG_DEBUG, ("Partial packet data read\n"));
+		return;
+	}
+
+	/* Extract complete packet */
+	data = talloc_size(queue, pkt_size);
+	if (data == NULL) {
+		DEBUG(DEBUG_ERR, ("read error alloc failed for %u\n", pkt_size));
+		return;
+	}
+	memcpy(data, queue->buffer.data, pkt_size);
+
+	/* Shift packet out from buffer */
+	if (queue->buffer.length > pkt_size) {
+		memmove(queue->buffer.data,
+			queue->buffer.data + pkt_size,
+			queue->buffer.length - pkt_size);
+	}
+	queue->buffer.length -= pkt_size;
+
+	if (queue->buffer.length > 0) {
+		/* There is more data to be processed, setup timed event */
+		event_add_timed(queue->ctdb->ev, queue, timeval_zero(),
+				queue_process_event, queue);
+	}
+
+	/* It is the responsibility of the callback to free 'data' */
+	queue->callback(data, pkt_size, queue->private_data);
+	return;
+
+failed:
+	queue->callback(NULL, 0, queue->private_data);
+
+}
+
+
 /*
   called when an incoming connection is readable
   This function MUST be safe for reentry via the queue callback!
@@ -86,10 +156,6 @@ static void dump_packet(unsigned char *data, size_t len)
 static void queue_io_read(struct ctdb_queue *queue)
 {
 	int num_ready = 0;
-	uint32_t sz_bytes_req;
-	uint32_t pkt_size;
-	uint32_t pkt_bytes_remaining;
-	uint32_t to_read;
 	ssize_t nread;
 	uint8_t *data;
 
@@ -101,77 +167,33 @@ static void queue_io_read(struct ctdb_queue *queue)
 		goto failed;
 	}
 
-	if (queue->partial.data == NULL) {
-		/* starting fresh, allocate buf for size bytes */
-		sz_bytes_req = sizeof(pkt_size);
-		queue->partial.data = talloc_size(queue, sz_bytes_req);
-		if (queue->partial.data == NULL) {
-			DEBUG(DEBUG_ERR,("read error alloc failed for %u\n",
-					 sz_bytes_req));
+	if (queue->buffer.data == NULL) {
+		/* starting fresh, allocate buf to read data */
+		queue->buffer.data = talloc_size(queue, num_ready);
+		if (queue->buffer.data == NULL) {
+			DEBUG(DEBUG_ERR, ("read error alloc failed for %u\n", num_ready));
 			goto failed;
 		}
-	} else if (queue->partial.length < sizeof(pkt_size)) {
-		/* yet to find out the packet length */
-		sz_bytes_req = sizeof(pkt_size) - queue->partial.length;
-	} else {
-		/* partial packet, length known, full buf allocated */
-		sz_bytes_req = 0;
-	}
-	data = queue->partial.data;
-
-	if (sz_bytes_req > 0) {
-		to_read = MIN(sz_bytes_req, num_ready);
-		nread = read(queue->fd, data + queue->partial.length,
-			     to_read);
-		if (nread <= 0) {
-			DEBUG(DEBUG_ERR,("read error nread=%d\n", (int)nread));
+		queue->buffer.size = num_ready;
+	} else if (queue->buffer.length + num_ready > queue->buffer.size) {
+		/* extending buffer */
+		data = talloc_realloc_size(queue, queue->buffer.data, queue->buffer.length + num_ready);
+		if (data == NULL) {
+			DEBUG(DEBUG_ERR, ("read error realloc failed for %u\n", queue->buffer.length + num_ready));
 			goto failed;
 		}
-		queue->partial.length += nread;
-
-		if (nread < sz_bytes_req) {
-			/* not enough to know the length */
-			DEBUG(DEBUG_DEBUG,("Partial packet length read\n"));
-			return;
-		}
-		/* size now known, allocate buffer for the full packet */
-		queue->partial.data = talloc_realloc_size(queue, data,
-							  *(uint32_t *)data);
-		if (queue->partial.data == NULL) {
-			DEBUG(DEBUG_ERR,("read error alloc failed for %u\n",
-					 *(uint32_t *)data));
-			goto failed;
-		}
-		data = queue->partial.data;
-		num_ready -= nread;
+		queue->buffer.data = data;
+		queue->buffer.size = queue->buffer.length + num_ready;
 	}
 
-	pkt_size = *(uint32_t *)data;
-	if (pkt_size == 0) {
-		DEBUG(DEBUG_CRIT,("Invalid packet of length 0\n"));
-		goto failed;
-	}
-
-	pkt_bytes_remaining = pkt_size - queue->partial.length;
-	to_read = MIN(pkt_bytes_remaining, num_ready);
-	nread = read(queue->fd, data + queue->partial.length,
-		     to_read);
+	nread = read(queue->fd, queue->buffer.data + queue->buffer.length, num_ready);
 	if (nread <= 0) {
-		DEBUG(DEBUG_ERR,("read error nread=%d\n",
-				 (int)nread));
+		DEBUG(DEBUG_ERR, ("read error nread=%d\n", (int)nread));
 		goto failed;
 	}
-	queue->partial.length += nread;
-
-	if (queue->partial.length < pkt_size) {
-		DEBUG(DEBUG_DEBUG,("Partial packet data read\n"));
-		return;
-	}
+	queue->buffer.length += nread;
 
-	queue->partial.data = NULL;
-	queue->partial.length = 0;
-	/* it is the responsibility of the callback to free 'data' */
-	queue->callback(data, pkt_size, queue->private_data);
+	queue_process(queue);
 	return;
 
 failed:
@@ -364,6 +386,9 @@ int ctdb_queue_set_fd(struct ctdb_queue *queue, int fd)
 /* If someone sets up this pointer, they want to know if the queue is freed */
 static int queue_destructor(struct ctdb_queue *queue)
 {
+	TALLOC_FREE(queue->buffer.data);
+	queue->buffer.length = 0;
+	queue->buffer.size = 0;
 	if (queue->destroyed != NULL)
 		*queue->destroyed = true;
 	return 0;
@@ -374,7 +399,6 @@ static int queue_destructor(struct ctdb_queue *queue)
  */
 struct ctdb_queue *ctdb_queue_setup(struct ctdb_context *ctdb,
 				    TALLOC_CTX *mem_ctx, int fd, int alignment,
-				    
 				    ctdb_queue_cb_fn_t callback,
 				    void *private_data, const char *fmt, ...)
 {
diff --git a/common/ctdb_logging.c b/common/ctdb_logging.c
index dee4dfd..bcc954a 100644
--- a/common/ctdb_logging.c
+++ b/common/ctdb_logging.c
@@ -86,7 +86,14 @@ void log_ringbuffer(const char *format, ...)
 	va_end(ap);
 }
 
-
+void ctdb_log_ringbuffer_free(void)
+{
+	if (log_entries != NULL) {
+		free(log_entries);
+		log_entries = NULL;
+	}
+	log_ringbuf_size = 0;
+}
 
 static void ctdb_collect_log(struct ctdb_context *ctdb, struct ctdb_get_log_addr *log_addr)
 {
diff --git a/common/ctdb_util.c b/common/ctdb_util.c
index dfd0b9f..d8d5ed7 100644
--- a/common/ctdb_util.c
+++ b/common/ctdb_util.c
@@ -388,6 +388,8 @@ pid_t ctdb_fork(struct ctdb_context *ctdb)
 			ctdb_restore_scheduler(ctdb);
 		}
 		ctdb->can_send_controls = false;
+
+		ctdb_log_ringbuffer_free();
 	}
 	return pid;
 }
diff --git a/config/events.d/50.samba b/config/events.d/50.samba
index 55ddf32..0a7d5b8 100755
--- a/config/events.d/50.samba
+++ b/config/events.d/50.samba
@@ -107,11 +107,6 @@ stop_samba() {
 	return 0
 }
 
-# set default samba cleanup period - in minutes
-[ -z "$SAMBA_CLEANUP_PERIOD" ] && {
-    SAMBA_CLEANUP_PERIOD=10
-}
-
 # we keep a cached copy of smb.conf here
 smbconf_cache="$CTDB_VARDIR/state/samba/smb.conf.cache"
 
@@ -207,15 +202,6 @@ list_samba_shares ()
 
 
 ###########################
-# periodic cleanup function
-periodic_cleanup() {
-    # running smbstatus scrubs any dead entries from the connections
-    # and sessionid database
-    # echo "Running periodic cleanup of samba databases"
-    smbstatus -np > /dev/null 2>&1 &
-}
-
-###########################
 
 [ "$1" = "monitor" ] && {
 ctdb_start_stop_service
@@ -226,11 +212,11 @@ is_ctdb_managed_service || is_ctdb_managed_service "winbind" || exit 0
 
 ###########################
 
-case "$1" in 
+case "$1" in
      startup)
 	ctdb_service_start
 	;;
-	
+
      shutdown)
 	ctdb_service_stop
 	;;
@@ -239,17 +225,6 @@ case "$1" in
 	# create the state directory for samba
 	/bin/mkdir -p $CTDB_VARDIR/state/samba
 
-	# Create a dummy file to track when we need to do periodic cleanup
-	# of samba databases
-	[ -f $CTDB_VARDIR/state/samba/periodic_cleanup ] || {
-		touch $CTDB_VARDIR/state/samba/periodic_cleanup
-	}
-	[ `/usr/bin/find $CTDB_VARDIR/state/samba/periodic_cleanup -mmin +$SAMBA_CLEANUP_PERIOD | wc -l` -eq 1 ] && {
-		# Cleanup the databases
-	    	periodic_cleanup
-		touch $CTDB_VARDIR/state/samba/periodic_cleanup
-	}
-
 	[ "$CTDB_MANAGES_SAMBA" = "yes" ] && {
 		[ "$CTDB_SAMBA_SKIP_SHARE_CHECK" = "yes" ] || {
 			testparm_background_update
@@ -261,7 +236,7 @@ case "$1" in
 				exit 1
 			    }
 			}
-			
+
 			list_samba_shares |
 			ctdb_check_directories_probe || {
 			    testparm_foreground_update
diff --git a/include/ctdb_private.h b/include/ctdb_private.h
index dffe87c..6f97702 100644
--- a/include/ctdb_private.h
+++ b/include/ctdb_private.h
@@ -125,6 +125,7 @@ struct ctdb_tunable {
 	uint32_t deferred_rebalance_on_node_add;
 	uint32_t recover_pdb_by_seqnum;
 	uint32_t fetch_collapse;
+	uint32_t pulldb_preallocation_size;
 };
 
 /*
@@ -1372,7 +1373,7 @@ extern int log_ringbuf_size;
 
 int32_t ctdb_control_get_log(struct ctdb_context *ctdb, TDB_DATA addr);
 int32_t ctdb_control_clear_log(struct ctdb_context *ctdb);
-
+void ctdb_log_ringbuffer_free(void);
 
 struct ctdb_log_state *ctdb_fork_with_logging(TALLOC_CTX *mem_ctx,
 					      struct ctdb_context *ctdb,
diff --git a/packaging/RPM/ctdb.spec.in b/packaging/RPM/ctdb.spec.in
index 9337095..3ad5dcc 100644
--- a/packaging/RPM/ctdb.spec.in
+++ b/packaging/RPM/ctdb.spec.in
@@ -3,7 +3,7 @@ Name: ctdb
 Summary: Clustered TDB
 Vendor: Samba Team
 Packager: Samba Team <samba at samba.org>
-Version: 1.2.57
+Version: 1.2.58
 Release: 1GITHASH
 Epoch: 0
 License: GNU GPL version 3
@@ -148,6 +148,12 @@ development libraries for ctdb
 
 %changelog
 
+* Tue Feb 19 2013 : Version 1.2.58
+  - Terminate traverse children when traverse operation times out
+  - Rewrite socket handling code to read all available data
+  - Remove call to "smbstatus -np" as part of periodic cleanup
+  - Free log ringbuffer in ctdb_fork() for child processes
+  - Use preallocation for pulldb buffer during recovery, instead of growing it
 * Thu Feb 07 2013 : Version 1.2.57
   - Backport fetch lock collapse patches
   - Backport debugging of hung eventscripts via external script
diff --git a/server/ctdb_recover.c b/server/ctdb_recover.c
index 06b5ed1..df0dc66 100644
--- a/server/ctdb_recover.c
+++ b/server/ctdb_recover.c
@@ -338,6 +338,7 @@ struct pulldb_data {
 	struct ctdb_context *ctdb;
 	struct ctdb_marshall_buffer *pulldata;
 	uint32_t len;
+	uint32_t allocated_len;
 	bool failed;
 };
 
@@ -352,7 +353,10 @@ static int traverse_pulldb(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data,
 		params->failed = true;
 		return -1;
 	}
-	params->pulldata = talloc_realloc_size(NULL, params->pulldata, rec->length + params->len);
+	if (params->len + rec->length >= params->allocated_len) {
+		params->allocated_len = rec->length + params->len + params->ctdb->tunable.pulldb_preallocation_size;
+		params->pulldata = talloc_realloc_size(NULL, params->pulldata, params->allocated_len);
+	}
 	if (params->pulldata == NULL) {
 		DEBUG(DEBUG_CRIT,(__location__ " Failed to expand pulldb_data to %u\n", rec->length + params->len));
 		ctdb_fatal(params->ctdb, "failed to allocate memory for recovery. shutting down\n");
@@ -396,6 +400,7 @@ int32_t ctdb_control_pull_db(struct ctdb_context *ctdb, TDB_DATA indata, TDB_DAT
 	params.ctdb = ctdb;
 	params.pulldata = reply;
 	params.len = offsetof(struct ctdb_marshall_buffer, data);
+	params.allocated_len = params.len;
 	params.failed = false;
 
 	if (ctdb_db->unhealthy_reason) {
diff --git a/server/ctdb_recoverd.c b/server/ctdb_recoverd.c
index d111555..7b6534e 100644
--- a/server/ctdb_recoverd.c
+++ b/server/ctdb_recoverd.c
@@ -1170,6 +1170,7 @@ struct recdb_data {
 	struct ctdb_context *ctdb;
 	struct ctdb_marshall_buffer *recdata;
 	uint32_t len;
+	uint32_t allocated_len;
 	bool failed;
 	bool persistent;
 };
@@ -1198,7 +1199,10 @@ static int traverse_recdb(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data,
 		params->failed = true;
 		return -1;
 	}
-	params->recdata = talloc_realloc_size(NULL, params->recdata, rec->length + params->len);
+	if (params->len + rec->length >= params->allocated_len) {
+		params->allocated_len = rec->length + params->len + params->ctdb->tunable.pulldb_preallocation_size;
+		params->recdata = talloc_realloc_size(NULL, params->recdata, params->allocated_len);
+	}
 	if (params->recdata == NULL) {
 		DEBUG(DEBUG_CRIT,(__location__ " Failed to expand recdata to %u (%u records)\n", 
 			 rec->length + params->len, params->recdata->count));
@@ -1237,6 +1241,7 @@ static int push_recdb_database(struct ctdb_context *ctdb, uint32_t dbid,
 	params.ctdb = ctdb;
 	params.recdata = recdata;
 	params.len = offsetof(struct ctdb_marshall_buffer, data);
+	params.allocated_len = params.len;
 	params.failed = false;
 	params.persistent = persistent;
 
diff --git a/server/ctdb_traverse.c b/server/ctdb_traverse.c
index 5ad374f..8eac15a 100644
--- a/server/ctdb_traverse.c
+++ b/server/ctdb_traverse.c
@@ -210,6 +210,7 @@ struct ctdb_traverse_all_handle {
 	ctdb_traverse_fn_t callback;
 	void *private_data;
 	uint32_t null_count;
+	bool timedout;
 };
 
 /*
@@ -238,6 +239,7 @@ static void ctdb_traverse_all_timeout(struct event_context *ev, struct timed_eve
 	DEBUG(DEBUG_ERR,(__location__ " Traverse all timeout on database:%s\n", state->ctdb_db->db_name));
 	CTDB_INCREMENT_STAT(state->ctdb, timeouts.traverse);
 
+	state->timedout = true;
 	state->callback(state->private_data, tdb_null, tdb_null);
 }
 
@@ -282,6 +284,7 @@ static struct ctdb_traverse_all_handle *ctdb_daemon_traverse_all(struct ctdb_db_
 	state->callback     = callback;
 	state->private_data = start_state;
 	state->null_count   = 0;
+	state->timedout     = false;
 	
 	talloc_set_destructor(state, ctdb_traverse_all_destructor);
 
@@ -541,9 +544,14 @@ static void traverse_start_callback(void *p, TDB_DATA key, TDB_DATA data)
 
 	ctdb_dispatch_message(state->ctdb, state->srvid, cdata);
 	if (key.dsize == 0 && data.dsize == 0) {
-		/* end of traverse */
-		talloc_set_destructor(state, NULL);
-		talloc_free(state);
+	    	if (state->h->timedout) {
+		    	/* timed out, send TRAVERSE_KILL control */
+			talloc_free(state);
+		} else {
+			/* end of traverse */
+			talloc_set_destructor(state, NULL);
+			talloc_free(state);
+		}
 	}
 }
 
diff --git a/server/ctdb_tunables.c b/server/ctdb_tunables.c
index 26c45ab..4c7146e 100644
--- a/server/ctdb_tunables.c
+++ b/server/ctdb_tunables.c
@@ -73,6 +73,7 @@ static const struct {
 	{ "DeferredRebalanceOnNodeAdd", 300, offsetof(struct ctdb_tunable, deferred_rebalance_on_node_add) },
 	{ "RecoverPDBBySeqNum",  1, offsetof(struct ctdb_tunable, recover_pdb_by_seqnum) },
 	{ "FetchCollapse",       1, offsetof(struct ctdb_tunable, fetch_collapse) },
+	{ "PullDBPreallocation", 10*1024*1024,  offsetof(struct ctdb_tunable, pulldb_preallocation_size), false },
 };
 
 /*


-- 
CTDB repository


More information about the samba-cvs mailing list