[SCM] CTDB repository - branch master updated - ctdb-1.0.113-73-ga7a86da

Ronnie Sahlberg sahlberg at samba.org
Wed Feb 3 21:41:52 MST 2010


The branch, master has been updated
       via  a7a86dafa4d88a6bbc6a71b77ed79a178fd802a6 (commit)
       via  e3f198056230073135ea6354bbef30c5bb022f8f (commit)
       via  2d05a71349e9ade869b62cf261c2a9a21818a474 (commit)
      from  c3eec8f10764a647106087099eeb47b7196f7aac (commit)

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


- Log -----------------------------------------------------------------
commit a7a86dafa4d88a6bbc6a71b77ed79a178fd802a6
Author: Andrew Tridgell <tridge at samba.org>
Date:   Thu Feb 4 14:36:14 2010 +1100

    ctdb: when we fill the client packet queue we need to drop the client
    
    We can't just drop packets to the list, as those packets could be part
    of the core protocol the client is using. This happens (for example)
    when Samba is doing a traverse. If we drop a traverse packet then
    Samba hangs indefinately. We are better off dropping the ctdb socket
    to Samba.

commit e3f198056230073135ea6354bbef30c5bb022f8f
Author: Andrew Tridgell <tridge at samba.org>
Date:   Thu Feb 4 14:14:18 2010 +1100

    ctdb: move ctdb_io.c to use TLIST_*() macros
    
    This will make large packet queues much more efficient

commit 2d05a71349e9ade869b62cf261c2a9a21818a474
Author: Andrew Tridgell <tridge at samba.org>
Date:   Thu Feb 4 14:13:49 2010 +1100

    util: added TLIST_*() macros
    
    The TLIST_*() macros are like the DLIST_*() macros, but take both a
    head and tail pointer for the list. This means that adding an element
    to the end of the list is efficient (it doesn't need to walk the
    list).
    
    We should move all uses of the DLIST_*() macros which use
    DLIST_ADD_END() to use the TLIST_*() macros instead.

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

Summary of changes:
 common/ctdb_io.c     |   27 ++++++---------------------
 lib/util/dlinklist.h |   46 ++++++++++++++++++++++++++++++++++++++++++++++
 server/ctdb_daemon.c |   17 ++++++++++++-----
 3 files changed, 64 insertions(+), 26 deletions(-)


Changeset truncated at 500 lines:

diff --git a/common/ctdb_io.c b/common/ctdb_io.c
index 47681d2..3fa784d 100644
--- a/common/ctdb_io.c
+++ b/common/ctdb_io.c
@@ -45,13 +45,7 @@ struct ctdb_queue_pkt {
 struct ctdb_queue {
 	struct ctdb_context *ctdb;
 	struct ctdb_partial partial; /* partial input packet */
-	struct ctdb_queue_pkt *out_queue;
-	/* This field is used to track the last added item so we
-	   can append new items to the end cheaply.
-	   This relies of that items are always appended to the tail
-	   and that when reamoving items we only remove the head.
-	*/
-	struct ctdb_queue_pkt *out_queue_last_added;
+	struct ctdb_queue_pkt *out_queue, *out_queue_tail;
 	uint32_t out_queue_length;
 	struct fd_event *fde;
 	int fd;
@@ -200,7 +194,8 @@ static void queue_io_write(struct ctdb_queue *queue)
 		if (n == -1 && errno != EAGAIN && errno != EWOULDBLOCK) {
 			if (pkt->length != pkt->full_length) {
 				/* partial packet sent - we have to drop it */
-				DLIST_REMOVE(queue->out_queue, pkt);
+				TLIST_REMOVE(queue->out_queue, queue->out_queue_tail,
+					     pkt);
 				queue->out_queue_length--;
 				talloc_free(pkt);
 			}
@@ -219,7 +214,7 @@ static void queue_io_write(struct ctdb_queue *queue)
 			return;
 		}
 
-		DLIST_REMOVE(queue->out_queue, pkt);
+		TLIST_REMOVE(queue->out_queue, queue->out_queue_tail, pkt);
 		queue->out_queue_length--;
 		talloc_free(pkt);
 	}
@@ -300,18 +295,8 @@ int ctdb_queue_send(struct ctdb_queue *queue, uint8_t *data, uint32_t length)
 		EVENT_FD_WRITEABLE(queue->fde);
 	}
 
-	/* This relies on that when adding items to the queue, we always add
-	   them to the tail and that when removing items we only remove
-	   the head of queue item.
-	   The last_added item thus allows non n^2 behaviour when appending to
-	   very long queues.
-	*/
-	if (queue->out_queue == NULL) {
-		DLIST_ADD(queue->out_queue, pkt);
-	} else {
-		DLIST_ADD_END(queue->out_queue_last_added, pkt, struct ctdb_queue_pkt *);
-	}
-	queue->out_queue_last_added = pkt;
+	TLIST_ADD_END(queue->out_queue, queue->out_queue_tail, pkt);
+
 	queue->out_queue_length++;
 
 	if (queue->ctdb->tunable.verbose_memory_names != 0) {
diff --git a/lib/util/dlinklist.h b/lib/util/dlinklist.h
index f018d87..44747d6 100644
--- a/lib/util/dlinklist.h
+++ b/lib/util/dlinklist.h
@@ -110,4 +110,50 @@ do { \
 		} \
 } while (0)
 
+/*
+   The TLIST_*() macros are meant for when you have two list pointers,
+   one pointing at the head of the list and one pointing at the tail
+   of the list. This makes the common case of adding to the end of the
+   list and removing from the front of the list efficient
+
+   TLIST stands for "tailed list"
+
+   Note: When initialising the structure containing your lists, make
+   sure that you set both head and tail to NULL
+
+   Also, do not mix the TLIST_*() macros with the DLIST_* macros!
+*/
+
+/* TLIST_ADD_FRONT adds elements to the front of the list. */
+#define TLIST_ADD_FRONT(listhead, listtail, p) \
+do { \
+	DLIST_ADD(listhead, p); \
+	if (NULL == (listtail)) { \
+		(listtail) = (p); \
+	} \
+} while (0)
+
+/* TLIST_ADD_END adds elements to the end of the list. */
+#define TLIST_ADD_END(listhead, listtail, p) \
+do { \
+	if ((listtail) == NULL) { \
+		DLIST_ADD(listhead, p); \
+		(listtail) = (listhead); \
+	} else { \
+		(listtail)->next = (p); \
+		(p)->prev = (listtail); \
+		(p)->next = NULL; \
+		(listtail) = (p); \
+	} \
+} while (0)
+
+/* TLIST_REMOVE removes an element from the list */
+#define TLIST_REMOVE(listhead, listtail, p) \
+do { \
+	if ((p) == (listtail)) { \
+		(listtail) = (p)->prev; \
+	} \
+	DLIST_REMOVE(listhead, p); \
+} while (0)
+
 #endif /* _DLINKLIST_H */
diff --git a/server/ctdb_daemon.c b/server/ctdb_daemon.c
index 7fbbf3f..5903f69 100644
--- a/server/ctdb_daemon.c
+++ b/server/ctdb_daemon.c
@@ -100,8 +100,9 @@ static int daemon_queue_send(struct ctdb_client *client, struct ctdb_req_header
 	client->ctdb->statistics.client_packets_sent++;
 	if (hdr->operation == CTDB_REQ_MESSAGE) {
 		if (ctdb_queue_length(client->queue) > client->ctdb->tunable.max_queue_depth_drop_msg) {
-			DEBUG(DEBUG_ERR,("Drop CTDB_REQ_MESSAGE to client. Queue full.\n"));
-			return 0;
+			DEBUG(DEBUG_ERR,("CTDB_REQ_MESSAGE queue full - killing client connection.\n"));
+			talloc_free(client);
+			return -1;
 		}
 	}
 	return ctdb_queue_send(client->queue, (uint8_t *)hdr, hdr->length);
@@ -280,6 +281,10 @@ static void daemon_call_from_client_callback(struct ctdb_call_state *state)
 	memcpy(&r->data[0], dstate->call->reply_data.dptr, r->datalen);
 
 	res = daemon_queue_send(client, &r->hdr);
+	if (res == -1) {
+		/* client is dead - return immediately */
+		return;
+	}
 	if (res != 0) {
 		DEBUG(DEBUG_ERR, (__location__ " Failed to queue packet from daemon to client\n"));
 	}
@@ -890,6 +895,7 @@ static void daemon_control_callback(struct ctdb_context *ctdb,
 	struct ctdb_client *client = state->client;
 	struct ctdb_reply_control *r;
 	size_t len;
+	int ret;
 
 	/* construct a message to send to the client containing the data */
 	len = offsetof(struct ctdb_reply_control, data) + data.dsize;
@@ -910,9 +916,10 @@ static void daemon_control_callback(struct ctdb_context *ctdb,
 		memcpy(&r->data[r->datalen], errormsg, r->errorlen);
 	}
 
-	daemon_queue_send(client, &r->hdr);
-
-	talloc_free(state);
+	ret = daemon_queue_send(client, &r->hdr);
+	if (ret != -1) {
+		talloc_free(state);
+	}
 }
 
 /*


-- 
CTDB repository


More information about the samba-cvs mailing list