Mercurial > dovecot > core-2.2
view src/indexer/indexer-queue.c @ 17130:add8c00fb3cc
Updated copyright notices to include year 2014.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Tue, 04 Feb 2014 16:23:22 -0500 |
parents | 36ef72481934 |
children | 4f90011e9823 |
line wrap: on
line source
/* Copyright (c) 2011-2014 Dovecot authors, see the included COPYING file */ #include "lib.h" #include "llist.h" #include "hash.h" #include "indexer-queue.h" struct indexer_queue { indexer_status_callback_t *callback; void (*listen_callback)(struct indexer_queue *); /* username+mailbox -> indexer_request */ HASH_TABLE(struct indexer_request *, struct indexer_request *) requests; struct indexer_request *head, *tail; }; static unsigned int indexer_request_hash(const struct indexer_request *request) { return str_hash(request->username) ^ str_hash(request->mailbox); } static int indexer_request_cmp(const struct indexer_request *r1, const struct indexer_request *r2) { return strcmp(r1->username, r2->username) == 0 && strcmp(r1->mailbox, r2->mailbox) == 0 ? 0 : 1; } struct indexer_queue * indexer_queue_init(indexer_status_callback_t *callback) { struct indexer_queue *queue; queue = i_new(struct indexer_queue, 1); queue->callback = callback; hash_table_create(&queue->requests, default_pool, 0, indexer_request_hash, indexer_request_cmp); return queue; } void indexer_queue_deinit(struct indexer_queue **_queue) { struct indexer_queue *queue = *_queue; *_queue = NULL; i_assert(indexer_queue_is_empty(queue)); hash_table_destroy(&queue->requests); i_free(queue); } void indexer_queue_set_listen_callback(struct indexer_queue *queue, void (*callback)(struct indexer_queue *)) { queue->listen_callback = callback; } static struct indexer_request * indexer_queue_lookup(struct indexer_queue *queue, const char *username, const char *mailbox) { struct indexer_request lookup_request; lookup_request.username = (void *)username; lookup_request.mailbox = (void *)mailbox; return hash_table_lookup(queue->requests, &lookup_request); } static void request_add_context(struct indexer_request *request, void *context) { unsigned int count = 0; if (context == NULL) return; if (request->contexts == NULL) { request->contexts = i_new(void *, 2); } else { for (; request->contexts[count] != NULL; count++) ; request->contexts = i_realloc(request->contexts, sizeof(*request->contexts) * (count + 1), sizeof(*request->contexts) * (count + 2)); } request->contexts[count] = context; } static struct indexer_request * indexer_queue_append_request(struct indexer_queue *queue, bool append, const char *username, const char *mailbox, unsigned int max_recent_msgs, void *context) { struct indexer_request *request; request = indexer_queue_lookup(queue, username, mailbox); if (request == NULL) { request = i_new(struct indexer_request, 1); request->username = i_strdup(username); request->mailbox = i_strdup(mailbox); request->max_recent_msgs = max_recent_msgs; request_add_context(request, context); hash_table_insert(queue->requests, request, request); } else { if (request->max_recent_msgs > max_recent_msgs) request->max_recent_msgs = max_recent_msgs; request_add_context(request, context); if (append) { /* keep the request in its old position */ return request; } /* move request to beginning of the queue */ DLLIST2_REMOVE(&queue->head, &queue->tail, request); } if (append) DLLIST2_APPEND(&queue->head, &queue->tail, request); else DLLIST2_PREPEND(&queue->head, &queue->tail, request); return request; } static void indexer_queue_append_finish(struct indexer_queue *queue) { if (queue->listen_callback != NULL) queue->listen_callback(queue); indexer_refresh_proctitle(); } void indexer_queue_append(struct indexer_queue *queue, bool append, const char *username, const char *mailbox, unsigned int max_recent_msgs, void *context) { struct indexer_request *request; request = indexer_queue_append_request(queue, append, username, mailbox, max_recent_msgs, context); request->index = TRUE; indexer_queue_append_finish(queue); } void indexer_queue_append_optimize(struct indexer_queue *queue, const char *username, const char *mailbox, void *context) { struct indexer_request *request; request = indexer_queue_append_request(queue, TRUE, username, mailbox, 0, context); request->optimize = TRUE; indexer_queue_append_finish(queue); } struct indexer_request *indexer_queue_request_peek(struct indexer_queue *queue) { return queue->head; } void indexer_queue_request_remove(struct indexer_queue *queue) { struct indexer_request *request = queue->head; 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, struct indexer_request *request, int percentage) { unsigned int i; if (request->contexts != NULL) { for (i = 0; request->contexts[i] != NULL; i++) queue->callback(percentage, request->contexts[i]); } } void indexer_queue_request_status(struct indexer_queue *queue, struct indexer_request *request, int percentage) { i_assert(percentage >= 0 && percentage < 100); indexer_queue_request_status_int(queue, request, percentage); } void indexer_queue_request_finish(struct indexer_queue *queue, struct indexer_request **_request, bool success) { struct indexer_request *request = *_request; *_request = NULL; indexer_queue_request_status_int(queue, request, success ? 100 : -1); i_free(request->contexts); i_free(request->username); i_free(request->mailbox); i_free(request); } void indexer_queue_cancel_all(struct indexer_queue *queue) { struct indexer_request *request; while ((request = indexer_queue_request_peek(queue)) != NULL) { indexer_queue_request_remove(queue); indexer_queue_request_finish(queue, &request, -1); } } bool indexer_queue_is_empty(struct indexer_queue *queue) { return queue->head == NULL; } unsigned int indexer_queue_count(struct indexer_queue *queue) { return hash_table_count(queue->requests); }