ipc-group.c revision 4ee00532a265bdfb38539d811fcd12d51210ac35
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher/* Copyright (c) 2011-2012 Dovecot authors, see the included COPYING file */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#include "lib.h"
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#include "array.h"
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#include "ipc-connection.h"
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek#include "ipc-group.h"
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek
06c1952db1ab5598e3d68132f9c846bc59c94ef7Jakub Hrozekstruct ipc_group_cmd {
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek ipc_cmd_callback_t *callback;
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek void *context;
2cb6f28b3a12bb714bf14494d31eb6b6fff64b8bJakub Hrozek
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher int refcount;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher char *first_error;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher};
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
fbeb1aba9e11e7aab8adac943276ca040f0c5311Jakub Hrozekstatic ARRAY(struct ipc_group *) ipc_groups;
fbeb1aba9e11e7aab8adac943276ca040f0c5311Jakub Hrozek
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozekstruct ipc_group *ipc_group_alloc(int listen_fd)
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek{
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek struct ipc_group *group;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_assert(ipc_group_lookup_listen_fd(listen_fd) == NULL);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher group = i_new(struct ipc_group, 1);
7a14e8f66c0e932fe2954d792614a3b61d444bd1Jakub Hrozek group->listen_fd = listen_fd;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher array_append(&ipc_groups, &group, 1);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return group;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozekvoid ipc_group_free(struct ipc_group **_group)
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozek{
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozek struct ipc_group *const *groups, *group = *_group;
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozek unsigned int i, count;
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek i_assert(group->connections == NULL);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek *_group = NULL;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher groups = array_get(&ipc_groups, &count);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher for (i = 0; i < count; i++) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (groups[i] == group) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher array_delete(&ipc_groups, i, 1);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher break;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_free(group->name);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_free(group);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozekstruct ipc_group *ipc_group_lookup_listen_fd(int listen_fd)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct ipc_group *const *groupp;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher array_foreach(&ipc_groups, groupp) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if ((*groupp)->listen_fd == listen_fd)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return *groupp;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return NULL;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstruct ipc_group *ipc_group_lookup_name(const char *name)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct ipc_group *const *groupp;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher array_foreach(&ipc_groups, groupp) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if ((*groupp)->name != NULL &&
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher strcmp((*groupp)->name, name) == 0)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return *groupp;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return NULL;
fbeb1aba9e11e7aab8adac943276ca040f0c5311Jakub Hrozek}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozekint ipc_group_update_name(struct ipc_group *group, const char *name)
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozek{
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozek if (group->name == NULL)
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozek group->name = i_strdup(name);
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek else if (strcmp(group->name, name) != 0)
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher return -1;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return 0;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void ipc_group_cmd_callback(enum ipc_cmd_status status,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const char *line, void *context)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct ipc_group_cmd *group_cmd = context;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_assert(group_cmd->refcount > 0);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek switch (status) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher case IPC_CMD_STATUS_REPLY:
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher group_cmd->callback(IPC_CMD_STATUS_REPLY, line,
fbeb1aba9e11e7aab8adac943276ca040f0c5311Jakub Hrozek group_cmd->context);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher break;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher case IPC_CMD_STATUS_ERROR:
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozek if (group_cmd->first_error == NULL)
ea929f1b022fc2cb77dec89b0e12accef983ec85Jakub Hrozek group_cmd->first_error = i_strdup(line);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* fall through */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher case IPC_CMD_STATUS_OK:
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (--group_cmd->refcount > 0)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher break;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (group_cmd->first_error == NULL) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher group_cmd->callback(IPC_CMD_STATUS_OK, line,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher group_cmd->context);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher } else {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher group_cmd->callback(IPC_CMD_STATUS_ERROR,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher group_cmd->first_error,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher group_cmd->context);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_free(group_cmd->first_error);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_free(group_cmd);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher break;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherbool ipc_group_cmd(struct ipc_group *group, const char *cmd,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ipc_cmd_callback_t *callback, void *context)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct ipc_connection *conn, *next;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct ipc_group_cmd *group_cmd;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (group->connections == NULL) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher callback(IPC_CMD_STATUS_OK, NULL, context);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return FALSE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher group_cmd = i_new(struct ipc_group_cmd, 1);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher group_cmd->callback = callback;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher group_cmd->context = context;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher for (conn = group->connections; conn != NULL; conn = next) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher next = conn->next;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek group_cmd->refcount++;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ipc_connection_cmd(conn, cmd,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ipc_group_cmd_callback, group_cmd);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return TRUE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallaghervoid ipc_groups_init(void)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_array_init(&ipc_groups, 16);
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozek}
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallaghervoid ipc_groups_deinit(void)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct ipc_group *const *groupp, *group;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher while (array_count(&ipc_groups) > 0) {
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozek groupp = array_idx(&ipc_groups, 0);
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek group = *groupp;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher while ((*groupp)->connections != NULL) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct ipc_connection *conn = (*groupp)->connections;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ipc_connection_destroy(&conn);
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ipc_group_free(&group);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher array_free(&ipc_groups);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher