dict-commands.c revision 79fff61b8fa0ec3c892e22cf792109dc1b398a30
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2005-2016 Dovecot authors, see the included COPYING file */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch int (*func)(struct dict_connection_cmd *cmd, const char *line);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void dict_connection_cmd_output_more(struct dict_connection_cmd *cmd);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void dict_connection_cmd_free(struct dict_connection_cmd *cmd)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (dict_iterate_deinit(&cmd->iter, &error) < 0)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void dict_connection_cmd_remove(struct dict_connection_cmd *cmd)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch unsigned int i, count;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch for (i = 0; i < count; i++) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void dict_connection_cmds_flush(struct dict_connection *conn)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct dict_connection_cmd *cmd, *const *first_cmdp;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* command not finished yet */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschcmd_lookup_callback(const struct dict_lookup_result *result, void *context)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch DICT_PROTOCOL_REPLY_OK, str_tabescape(result->value));
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch cmd->reply = i_strdup_printf("%c\n", DICT_PROTOCOL_REPLY_NOTFOUND);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch cmd->reply = i_strdup_printf("%c%s\n", DICT_PROTOCOL_REPLY_FAIL,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic int cmd_lookup(struct dict_connection_cmd *cmd, const char *line)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch dict_lookup_async(cmd->conn->dict, line, cmd_lookup_callback, cmd);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic int cmd_iterate_flush(struct dict_connection_cmd *cmd)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch while (dict_iterate(cmd->iter, &key, &value)) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if ((cmd->iter_flags & DICT_ITERATE_FLAG_NO_VALUE) == 0)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch o_stream_nsend(cmd->conn->output, str_data(str), str_len(str));
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (o_stream_get_buffer_used_size(cmd->conn->output) >
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* continue later when there's more space
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch in output buffer */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch o_stream_set_flush_pending(cmd->conn->output, TRUE);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* flushed everything, continue */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* wait for the next iteration callback */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (dict_iterate_deinit(&cmd->iter, &error) < 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch str_printfa(str, "%c%s", DICT_PROTOCOL_REPLY_FAIL, error);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void cmd_iterate_callback(void *context)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic int cmd_iterate(struct dict_connection_cmd *cmd, const char *line)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const char *const *args;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch unsigned int flags;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("dict client: ITERATE: broken input");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* <flags> <path> */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch cmd->iter = dict_iterate_init_multiple(cmd->conn->dict, args+1, flags);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch dict_iterate_set_async_callback(cmd->iter, cmd_iterate_callback, cmd);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschdict_connection_transaction_lookup(struct dict_connection *conn,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch unsigned int id)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct dict_connection_transaction *transaction;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch array_foreach_modifiable(&conn->transactions, transaction) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschdict_connection_transaction_array_remove(struct dict_connection *conn,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch unsigned int id)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const struct dict_connection_transaction *transactions;
ca4526e3b5fbf5ea3dd477a2098522a44c9ac52cTimo Sirainen unsigned int i, count;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch transactions = array_get(&conn->transactions, &count);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch for (i = 0; i < count; i++) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic int cmd_begin(struct dict_connection_cmd *cmd, const char *line)
ca4526e3b5fbf5ea3dd477a2098522a44c9ac52cTimo Sirainen unsigned int id;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("dict client: Invalid transaction ID %s", line);
4fa772eefd5a22a597601488be44997e788cb60dStephan Bosch if (dict_connection_transaction_lookup(cmd->conn, id) != NULL) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("dict client: Transaction ID %u already exists", id);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (!array_is_created(&cmd->conn->transactions))
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch trans = array_append_space(&cmd->conn->transactions);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch trans->ctx = dict_transaction_begin(cmd->conn->dict);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschdict_connection_transaction_lookup_parse(struct dict_connection *conn,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch unsigned int id;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("dict client: Invalid transaction ID %s", line);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch *trans_r = dict_connection_transaction_lookup(conn, id);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("dict client: Transaction ID %u doesn't exist", id);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschcmd_commit_finish(struct dict_connection_cmd *cmd,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const struct dict_commit_result *result, bool async)
3858a7a5da361c35f1e6e50c8e3214dc0cf379d6Phil Carmody str_append_c(str, DICT_PROTOCOL_REPLY_ASYNC_COMMIT);
4fa772eefd5a22a597601488be44997e788cb60dStephan Bosch dict_connection_transaction_array_remove(cmd->conn, cmd->trans_id);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void cmd_commit_callback(const struct dict_commit_result *result,
4fa772eefd5a22a597601488be44997e788cb60dStephan Boschstatic void cmd_commit_callback_async(const struct dict_commit_result *result,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschcmd_commit(struct dict_connection_cmd *cmd, const char *line)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (dict_connection_transaction_lookup_parse(cmd->conn, line, &trans) < 0)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch dict_transaction_commit_async(&trans->ctx, cmd_commit_callback, cmd);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschcmd_commit_async(struct dict_connection_cmd *cmd, const char *line)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (dict_connection_transaction_lookup_parse(cmd->conn, line, &trans) < 0)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch dict_transaction_commit_async(&trans->ctx, cmd_commit_callback_async, cmd);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic int cmd_rollback(struct dict_connection_cmd *cmd, const char *line)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (dict_connection_transaction_lookup_parse(cmd->conn, line, &trans) < 0)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch dict_connection_transaction_array_remove(cmd->conn, trans->id);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic int cmd_set(struct dict_connection_cmd *cmd, const char *line)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const char *const *args;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* <id> <key> <value> */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (dict_connection_transaction_lookup_parse(cmd->conn, args[0], &trans) < 0)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic int cmd_unset(struct dict_connection_cmd *cmd, const char *line)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const char *const *args;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* <id> <key> */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (dict_connection_transaction_lookup_parse(cmd->conn, args[0], &trans) < 0)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic int cmd_atomic_inc(struct dict_connection_cmd *cmd, const char *line)
2d72e8492960794037a1ca90df34f7ab2a170a81Timo Sirainen const char *const *args;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* <id> <key> <diff> */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("dict client: ATOMIC_INC: broken input");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (dict_connection_transaction_lookup_parse(cmd->conn, args[0], &trans) < 0)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch { DICT_PROTOCOL_CMD_COMMIT_ASYNC, cmd_commit_async },
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch { DICT_PROTOCOL_CMD_ATOMIC_INC, cmd_atomic_inc },
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic const struct dict_cmd_func *dict_command_find(enum dict_protocol_cmd cmd)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch unsigned int i;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschint dict_command_input(struct dict_connection *conn, const char *line)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch cmd_func = dict_command_find((enum dict_protocol_cmd)*line);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("dict client: Unknown command %c", *line);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if ((ret = cmd_func->func(cmd, line + 1)) <= 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void dict_connection_cmd_output_more(struct dict_connection_cmd *cmd)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct dict_connection_cmd *const *first_cmdp;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschvoid dict_connection_cmds_output_more(struct dict_connection *conn)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct dict_connection_cmd *cmd, *const *first_cmdp;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* only iterators may be returning a lot of data */
4fa772eefd5a22a597601488be44997e788cb60dStephan Bosch /* unfinished */
4fa772eefd5a22a597601488be44997e788cb60dStephan Bosch /* cmd should be freed now */