Mercurial > dovecot > core-2.2
view src/doveadm/dsync/dsync-brain.c @ 14629:c93ca5e46a8a
Marked functions parameters that are allowed to be NULL. Some APIs were also changed.
The non-obvious APIs where NULL parameter was changed to "" are
master_service_init() and auth_master_user_list_init().
These checks can currently be enabled only on a patched clang:
http://llvm.org/bugs/show_bug.cgi?id=6786
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sun, 24 Jun 2012 00:52:57 +0300 |
parents | b2076acc3715 |
children | 1ce71b5bc94a |
line wrap: on
line source
/* Copyright (c) 2012 Dovecot authors, see the included COPYING file */ #include "lib.h" #include "array.h" #include "hash.h" #include "mail-namespace.h" #include "dsync-mailbox-tree.h" #include "dsync-slave.h" #include "dsync-brain-private.h" static void dsync_brain_run_io(void *context) { struct dsync_brain *brain = context; bool changed, try_pending; if (dsync_slave_has_failed(brain->slave)) { io_loop_stop(current_ioloop); brain->failed = TRUE; return; } try_pending = TRUE; do { if (!dsync_brain_run(brain, &changed)) { io_loop_stop(current_ioloop); break; } if (changed) try_pending = TRUE; else if (try_pending) { if (dsync_slave_has_pending_data(brain->slave)) changed = TRUE; try_pending = FALSE; } } while (changed); } static struct dsync_brain * dsync_brain_common_init(struct mail_user *user, struct dsync_slave *slave) { struct dsync_brain *brain; pool_t pool; pool = pool_alloconly_create("dsync brain", 10240); brain = p_new(pool, struct dsync_brain, 1); brain->pool = pool; brain->user = user; brain->slave = slave; brain->sync_type = DSYNC_BRAIN_SYNC_TYPE_UNKNOWN; brain->remote_mailbox_states = hash_table_create(default_pool, brain->pool, 0, guid_128_hash, guid_128_cmp); p_array_init(&brain->mailbox_states, pool, 64); return brain; } struct dsync_brain * dsync_brain_master_init(struct mail_user *user, struct dsync_slave *slave, struct mail_namespace *sync_ns, enum dsync_brain_sync_type sync_type, enum dsync_brain_flags flags, const char *state) { struct dsync_slave_settings slave_set; struct dsync_brain *brain; const char *error; i_assert(sync_type != DSYNC_BRAIN_SYNC_TYPE_UNKNOWN); i_assert(sync_type != DSYNC_BRAIN_SYNC_TYPE_STATE || *state != '\0'); brain = dsync_brain_common_init(user, slave); brain->sync_type = sync_type; if (sync_ns != NULL) brain->sync_ns = sync_ns; brain->master_brain = TRUE; brain->mails_have_guids = (flags & DSYNC_BRAIN_FLAG_MAILS_HAVE_GUIDS) != 0; brain->guid_requests = (flags & DSYNC_BRAIN_FLAG_SEND_REQUESTS) != 0; brain->state = DSYNC_STATE_SEND_MAILBOX_TREE; if (sync_type == DSYNC_BRAIN_SYNC_TYPE_STATE) { if (dsync_mailbox_states_import(&brain->mailbox_states, state, &error) < 0) { array_clear(&brain->mailbox_states); i_error("Saved sync state is invalid, " "falling back to full sync: %s", error); brain->sync_type = DSYNC_BRAIN_SYNC_TYPE_FULL; } else { brain->state = DSYNC_STATE_MASTER_SEND_LAST_COMMON; } } dsync_brain_mailbox_trees_init(brain); memset(&slave_set, 0, sizeof(slave_set)); slave_set.sync_ns_prefix = sync_ns == NULL ? NULL : sync_ns->prefix; slave_set.sync_type = sync_type; slave_set.guid_requests = brain->guid_requests; slave_set.mails_have_guids = brain->mails_have_guids; dsync_slave_send_handshake(slave, &slave_set); dsync_slave_set_io_callback(slave, dsync_brain_run_io, brain); return brain; } struct dsync_brain * dsync_brain_slave_init(struct mail_user *user, struct dsync_slave *slave) { struct dsync_brain *brain; brain = dsync_brain_common_init(user, slave); brain->state = DSYNC_STATE_SLAVE_RECV_HANDSHAKE; dsync_slave_set_io_callback(slave, dsync_brain_run_io, brain); return brain; } int dsync_brain_deinit(struct dsync_brain **_brain) { struct dsync_brain *brain = *_brain; int ret; *_brain = NULL; if (dsync_slave_has_failed(brain->slave) || brain->state != DSYNC_STATE_DONE) brain->failed = TRUE; if (brain->box != NULL) dsync_brain_sync_mailbox_deinit(brain); if (brain->local_tree_iter != NULL) dsync_mailbox_tree_iter_deinit(&brain->local_tree_iter); hash_table_destroy(&brain->remote_mailbox_states); ret = brain->failed ? -1 : 0; pool_unref(&brain->pool); return ret; } static bool dsync_brain_slave_recv_handshake(struct dsync_brain *brain) { const struct dsync_slave_settings *slave_set; i_assert(!brain->master_brain); if (dsync_slave_recv_handshake(brain->slave, &slave_set) == 0) return FALSE; if (slave_set->sync_ns_prefix != NULL) { brain->sync_ns = mail_namespace_find(brain->user->namespaces, slave_set->sync_ns_prefix); if (brain->sync_ns == NULL) { i_error("Requested sync namespace prefix=%s doesn't exist", slave_set->sync_ns_prefix); brain->failed = TRUE; return TRUE; } } i_assert(brain->sync_type == DSYNC_BRAIN_SYNC_TYPE_UNKNOWN); brain->sync_type = slave_set->sync_type; brain->guid_requests = slave_set->guid_requests; brain->mails_have_guids = slave_set->mails_have_guids; dsync_brain_mailbox_trees_init(brain); if (brain->sync_type == DSYNC_BRAIN_SYNC_TYPE_STATE) brain->state = DSYNC_STATE_SLAVE_RECV_LAST_COMMON; else brain->state = DSYNC_STATE_SEND_MAILBOX_TREE; return TRUE; } static void dsync_brain_master_send_last_common(struct dsync_brain *brain) { const struct dsync_mailbox_state *states; unsigned int count; enum dsync_slave_send_ret ret = DSYNC_SLAVE_SEND_RET_OK; i_assert(brain->master_brain); states = array_get(&brain->mailbox_states, &count); while (brain->mailbox_state_idx < count) { if (ret == DSYNC_SLAVE_SEND_RET_FULL) return; ret = dsync_slave_send_mailbox_state(brain->slave, &states[brain->mailbox_state_idx++]); } dsync_slave_send_end_of_list(brain->slave); brain->state = DSYNC_STATE_SEND_MAILBOX_TREE; brain->mailbox_state_idx = 0; } static bool dsync_brain_slave_recv_last_common(struct dsync_brain *brain) { struct dsync_mailbox_state state; enum dsync_slave_recv_ret ret; bool changed = FALSE; i_assert(!brain->master_brain); while ((ret = dsync_slave_recv_mailbox_state(brain->slave, &state)) > 0) { array_append(&brain->mailbox_states, &state, 1); changed = TRUE; } if (ret == DSYNC_SLAVE_RECV_RET_FINISHED) { brain->state = DSYNC_STATE_SEND_MAILBOX_TREE; changed = TRUE; } return changed; } static bool dsync_brain_run_real(struct dsync_brain *brain, bool *changed_r) { bool changed = FALSE, ret = TRUE; if (brain->failed) return FALSE; switch (brain->state) { case DSYNC_STATE_SLAVE_RECV_HANDSHAKE: changed = dsync_brain_slave_recv_handshake(brain); break; case DSYNC_STATE_MASTER_SEND_LAST_COMMON: dsync_brain_master_send_last_common(brain); changed = TRUE; break; case DSYNC_STATE_SLAVE_RECV_LAST_COMMON: changed = dsync_brain_slave_recv_last_common(brain); break; case DSYNC_STATE_SEND_MAILBOX_TREE: dsync_brain_send_mailbox_tree(brain); changed = TRUE; break; case DSYNC_STATE_RECV_MAILBOX_TREE: changed = dsync_brain_recv_mailbox_tree(brain); break; case DSYNC_STATE_SEND_MAILBOX_TREE_DELETES: dsync_brain_send_mailbox_tree_deletes(brain); changed = TRUE; break; case DSYNC_STATE_RECV_MAILBOX_TREE_DELETES: changed = dsync_brain_recv_mailbox_tree_deletes(brain); break; case DSYNC_STATE_MASTER_SEND_MAILBOX: dsync_brain_master_send_mailbox(brain); changed = TRUE; break; case DSYNC_STATE_SLAVE_RECV_MAILBOX: changed = dsync_brain_slave_recv_mailbox(brain); break; case DSYNC_STATE_SYNC_MAILS: changed = dsync_brain_sync_mails(brain); break; case DSYNC_STATE_DONE: changed = TRUE; ret = FALSE; break; } *changed_r = changed; return brain->failed ? FALSE : ret; } bool dsync_brain_run(struct dsync_brain *brain, bool *changed_r) { bool ret; *changed_r = FALSE; if (dsync_slave_has_failed(brain->slave)) { brain->failed = TRUE; return FALSE; } T_BEGIN { ret = dsync_brain_run_real(brain, changed_r); } T_END; if (!brain->failed) dsync_slave_flush(brain->slave); return ret; } bool dsync_brain_has_failed(struct dsync_brain *brain) { return brain->failed; }