]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
replicator: Add refcounting to user
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Mon, 27 Nov 2017 15:42:06 +0000 (17:42 +0200)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Mon, 27 Nov 2017 16:46:43 +0000 (18:46 +0200)
src/replication/replicator/replicator-queue.c
src/replication/replicator/replicator-queue.h

index b7d1ec7adcfaf08e251d87be04a2b2545741b639..9609df68f4cd83117ae00abc11cb7b2d98670254 100644 (file)
@@ -125,6 +125,27 @@ void replicator_queue_set_change_callback(struct replicator_queue *queue,
        queue->change_context = context;
 }
 
+void replicator_user_ref(struct replicator_user *user)
+{
+       i_assert(user->refcount > 0);
+       user->refcount++;
+}
+
+bool replicator_user_unref(struct replicator_user **_user)
+{
+       struct replicator_user *user = *_user;
+
+       i_assert(user->refcount > 0);
+       *_user = NULL;
+       if (--user->refcount > 0)
+               return TRUE;
+
+       i_free(user->state);
+       i_free(user->username);
+       i_free(user);
+       return FALSE;
+}
+
 struct replicator_user *
 replicator_queue_lookup(struct replicator_queue *queue, const char *username)
 {
@@ -140,6 +161,7 @@ replicator_queue_add_int(struct replicator_queue *queue, const char *username,
        user = replicator_queue_lookup(queue, username);
        if (user == NULL) {
                user = i_new(struct replicator_user, 1);
+               user->refcount = 1;
                user->username = i_strdup(username);
                hash_table_insert(queue->user_hash, user->username, user);
        } else {
@@ -200,10 +222,7 @@ void replicator_queue_remove(struct replicator_queue *queue,
        if (!user->popped)
                priorityq_remove(queue->user_queue, &user->item);
        hash_table_remove(queue->user_hash, user->username);
-
-       i_free(user->state);
-       i_free(user->username);
-       i_free(user);
+       replicator_user_unref(&user);
 
        if (queue->change_callback != NULL)
                queue->change_callback(queue->change_context);
index a9b3b36752dc95169efafab60fe8ba785b929203..a298a5d9ed8009e31350eeb6d42180997af6f266 100644 (file)
@@ -15,6 +15,7 @@ struct replicator_user {
        /* last_fast_sync is always >= last_full_sync. */
        time_t last_fast_sync, last_full_sync, last_successful_sync;
 
+       int refcount;
        enum replication_priority priority;
        /* User isn't currently in replication queue */
        bool popped:1;
@@ -37,6 +38,11 @@ void replicator_queue_set_change_callback(struct replicator_queue *queue,
                                          void (*callback)(void *context),
                                          void *context);
 
+/* Reference the user */
+void replicator_user_ref(struct replicator_user *user);
+/* Unreference the user. Returns TRUE if refcount is still >0. */
+bool replicator_user_unref(struct replicator_user **user);
+
 /* Lookup an existing user */
 struct replicator_user *
 replicator_queue_lookup(struct replicator_queue *queue, const char *username);