changeset 18824:2f5799572a2f

indexer: Improved handling multiple indexing requests to the same mailbox. If a request arrives for a mailbox that we were already indexes, the previous code simply sent the indexing request to the existing worker process. This could have caused a lot of requests to be buffered to the same mailbox if the indexing took a long time, which could have taken a while to process even though they weren't really doing anything indexing work. The new code instead just keeps track in memory that when the earlier indexing is finished, it's done again once to finish any pending changes.
author Timo Sirainen <tss@iki.fi>
date Wed, 03 Jun 2015 22:30:05 +0300
parents a5d5d2dd6aea
children 576267a41570
files src/indexer/indexer-queue.c src/indexer/indexer-queue.h src/indexer/indexer.c
diffstat 3 files changed, 51 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/src/indexer/indexer-queue.c	Wed Jun 03 22:26:05 2015 +0300
+++ b/src/indexer/indexer-queue.c	Wed Jun 03 22:30:05 2015 +0300
@@ -98,6 +98,14 @@
 		if (request->max_recent_msgs > max_recent_msgs)
 			request->max_recent_msgs = max_recent_msgs;
 		request_add_context(request, context);
+		if (request->working) {
+			/* we're already indexing this mailbox. */
+			if (append)
+				request->reindex_tail = TRUE;
+			else
+				request->reindex_head = TRUE;
+			return request;
+		}
 		if (append) {
 			/* keep the request in its old position */
 			return request;
@@ -156,8 +164,6 @@
 	i_assert(request != NULL);
 
 	DLLIST2_REMOVE(&queue->head, &queue->tail, request);
-	hash_table_remove(queue->requests, request);
-	indexer_refresh_proctitle();
 }
 
 static void indexer_queue_request_status_int(struct indexer_queue *queue,
@@ -167,7 +173,7 @@
 	void *const *contextp;
 	unsigned int i;
 
-	for (i = 0; i < array_count(&request->contexts); i++) {
+	for (i = 0; i < request->working_context_idx; i++) {
 		contextp = array_idx(&request->contexts, i);
 		queue->callback(percentage, *contextp);
 	}
@@ -182,6 +188,14 @@
 	indexer_queue_request_status_int(queue, request, percentage);
 }
 
+void indexer_queue_request_work(struct indexer_request *request)
+{
+	request->working = TRUE;
+	request->working_context_idx =
+		!array_is_created(&request->contexts) ? 0 :
+		array_count(&request->contexts);
+}
+
 void indexer_queue_request_finish(struct indexer_queue *queue,
 				  struct indexer_request **_request,
 				  bool success)
@@ -191,11 +205,31 @@
 	*_request = NULL;
 
 	indexer_queue_request_status_int(queue, request, success ? 100 : -1);
+
+	if (request->reindex_head || request->reindex_tail) {
+		i_assert(request->working);
+		request->working = FALSE;
+		request->reindex_head = FALSE;
+		request->reindex_tail = FALSE;
+		if (request->working_context_idx > 0) {
+			array_delete(&request->contexts, 0,
+				     request->working_context_idx);
+		}
+		if (request->reindex_head)
+			DLLIST2_PREPEND(&queue->head, &queue->tail, request);
+		else
+			DLLIST2_APPEND(&queue->head, &queue->tail, request);
+		return;
+	}
+
+	hash_table_remove(queue->requests, request);
 	if (array_is_created(&request->contexts))
 		array_free(&request->contexts);
 	i_free(request->username);
 	i_free(request->mailbox);
 	i_free(request);
+
+	indexer_refresh_proctitle();
 }
 
 void indexer_queue_cancel_all(struct indexer_queue *queue)
--- a/src/indexer/indexer-queue.h	Wed Jun 03 22:26:05 2015 +0300
+++ b/src/indexer/indexer-queue.h	Wed Jun 03 22:30:05 2015 +0300
@@ -14,6 +14,17 @@
 	unsigned int index:1;
 	/* optimize this mailbox */
 	unsigned int optimize:1;
+	/* currently indexing this mailbox */
+	unsigned int working:1;
+	/* after indexing is finished, add this request back to the queue and
+	   reindex it (i.e. a new indexing request came while we were
+	   working.) */
+	unsigned int reindex_head:1;
+	unsigned int reindex_tail:1;
+
+	/* when working finished, call this number of contexts and leave the
+	   rest to the reindexing. */
+	unsigned int working_context_idx;
 
 	ARRAY(void *) contexts;
 };
@@ -45,6 +56,8 @@
 void indexer_queue_request_status(struct indexer_queue *queue,
 				  struct indexer_request *request,
 				  int percentage);
+/* Start working on a request */
+void indexer_queue_request_work(struct indexer_request *request);
 /* Finish the request and free its memory. */
 void indexer_queue_request_finish(struct indexer_queue *queue,
 				  struct indexer_request **request,
--- a/src/indexer/indexer.c	Wed Jun 03 22:26:05 2015 +0300
+++ b/src/indexer/indexer.c	Wed Jun 03 22:30:05 2015 +0300
@@ -50,6 +50,7 @@
 	wrequest->conn = conn;
 	wrequest->request = request;
 
+	indexer_queue_request_work(request);
 	worker_connection_request(conn, request, wrequest);
 }