dict-commands.c revision e34d170f8f0e084bd94bfbc1a7085ece67e508df
8c294c1cd4d721818a59684cf7f2b36123f79163Stephen Gallagher/* Copyright (c) 2005-2012 Dovecot authors, see the included COPYING file */
8b1f525acd20f36c836e827de3c251088961c5d9Stephen Gallagher int (*func)(struct dict_connection *conn, const char *line);
8b1f525acd20f36c836e827de3c251088961c5d9Stephen Gallagherstatic int cmd_lookup(struct dict_connection *conn, const char *line)
df4cc3a83c5d6700b6a09ff96cb4a6b1949b1aa9Stephen Gallagher i_error("dict client: LOOKUP: Can't lookup while iterating");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ret = dict_lookup(conn->dict, pool_datastack_create(), line, &value);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher reply = t_strdup_printf("%c\n", ret == 0 ?
90fd1bbd6035cdab46faa3a695a2fb2be6508b17Sumit Bosestatic int cmd_iterate_flush(struct dict_connection *conn)
1d1a0a019d8d4d9ab0f51ada03604cd2cada287eSumit Bose while (dict_iterate(conn->iter_ctx, &key, &value)) {
f3c85d900c4663854cc7bbae7d9f77867ed1f69bSumit Bose str_printfa(str, "%c%s\t%s\n", DICT_PROTOCOL_REPLY_OK,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher o_stream_nsend(conn->output, str_data(str), str_len(str));
2a552e43581c74f51205c7141ec9f6e9542509f8Stephen Gallagher if (o_stream_get_buffer_used_size(conn->output) >
1a59af8245f183f22d87d067a90197d8e2ea958dJakub Hrozek /* continue later */
d921c1eba437662437847279f251a0a5d8f70127Maxim /* flushed everything, continue */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* finished iterating */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher o_stream_unset_flush_callback(conn->output);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher str_append_c(str, DICT_PROTOCOL_REPLY_FAIL);
5377441d7a846461c2d9a7a870cea711360a529aNikolai Kondrashov o_stream_nsend(conn->output, str_data(str), str_len(str));
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagherstatic int cmd_iterate(struct dict_connection *conn, const char *line)
e124844907ed6973915e4d56f5442ecd07535a12Jakub Hrozek const char *const *args;
5484044ea7bb632b915f706685fce509f6eacc48Jakub Hrozek unsigned int flags;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_error("dict client: ITERATE: Already iterating");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* <flags> <path> */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher conn->iter_ctx = dict_iterate_init_multiple(conn->dict, args+1, flags);
054b5d4bb98973698f74d66b14ccd14394b53f10Lukas Slebodnik o_stream_set_flush_callback(conn->output, cmd_iterate_flush, conn);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic struct dict_connection_transaction *
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherdict_connection_transaction_lookup(struct dict_connection *conn,
4f6931e854c698dcb1c09f99eb330ce2fb97e7c6Lukas Slebodnik unsigned int id)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct dict_connection_transaction *transaction;
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta array_foreach_modifiable(&conn->transactions, transaction) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherdict_connection_transaction_array_remove(struct dict_connection *conn,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct dict_connection_transaction *trans)
c737e1444fb186e349e59bfa9dac4995b720b4b1Jan Zeleny const struct dict_connection_transaction *transactions;
f1828234a850dd28465425248a83a993f262918fPavel Březina unsigned int i, count;
b69cb1787209e85cc246eb9a944242689bfe0c46Pavel Březina transactions = array_get(&conn->transactions, &count);
b69cb1787209e85cc246eb9a944242689bfe0c46Pavel Březina for (i = 0; i < count; i++) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic int cmd_begin(struct dict_connection *conn, const char *line)
1746e8b8399da2a7a8da4aace186f66055ccfec1Jakub Hrozek unsigned int id;
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina i_error("dict client: Invalid transaction ID %s", line);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (dict_connection_transaction_lookup(conn, id) != NULL) {
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholasta i_error("dict client: Transaction ID %u already exists", id);
19d3aba12c70528708be9440aca66038a291f29eYassir Elley trans = array_append_space(&conn->transactions);
f3a25949de81f80c136bb073e4a8f504b080c20cJakub Hrozek trans->ctx = dict_transaction_begin(conn->dict);
5484044ea7bb632b915f706685fce509f6eacc48Jakub Hrozekdict_connection_transaction_lookup_parse(struct dict_connection *conn,
3be9e26dcd169d44ae105f1b8a0674464c700b77Sumit Bose const char *line,
5484044ea7bb632b915f706685fce509f6eacc48Jakub Hrozek unsigned int id;
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose i_error("dict client: Invalid transaction ID %s", line);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher *trans_r = dict_connection_transaction_lookup(conn, id);
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce i_error("dict client: Transaction ID %u doesn't exist", id);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic int cmd_commit(struct dict_connection *conn, const char *line)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct dict_connection_transaction *trans;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_error("dict client: COMMIT: Can't commit while iterating");
a6098862048d4bb469130b9ff21be3020d6f2c54Sumit Bose if (dict_connection_transaction_lookup_parse(conn, line, &trans) < 0)
4bd20c075f0f187db0181dc53d00ab6cd47fdb4dJakub Hrozek o_stream_nsend_str(conn->output, t_strdup_printf("%c\n", chr));
4bd20c075f0f187db0181dc53d00ab6cd47fdb4dJakub Hrozek dict_connection_transaction_array_remove(conn, trans);
4bd20c075f0f187db0181dc53d00ab6cd47fdb4dJakub Hrozekstatic void cmd_commit_async_callback(int ret, void *context)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct dict_connection_transaction *trans = context;
90afedb00608547ae1f32aa7aafd552c4b306909Jakub Hrozek reply = t_strdup_printf("%c%c%u\n", DICT_PROTOCOL_REPLY_ASYNC_COMMIT,
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek o_stream_nsend_str(trans->conn->output, reply);
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek dict_connection_transaction_array_remove(trans->conn, trans);
a524965fbe0551f1b3a68f1e5c7a5689a652998fSumit Bosecmd_commit_async(struct dict_connection *conn, const char *line)
a5623363d6042290fe652a1ca5ce5a85a821236fPavel Březina i_error("dict client: COMMIT: Can't commit while iterating");
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina if (dict_connection_transaction_lookup_parse(conn, line, &trans) < 0)
ea422c7061072c125eb53b40d7f3ca444d886913Sumit Bose dict_transaction_commit_async(&trans->ctx, cmd_commit_async_callback,
6cb5bad3c8e2f35ca9dce1800a506d626f90c079Lukas Slebodnikstatic int cmd_rollback(struct dict_connection *conn, const char *line)
62370340092503baeaf6587d7ffe4fe25bd9582dPavel Reichl if (dict_connection_transaction_lookup_parse(conn, line, &trans) < 0)
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek dict_connection_transaction_array_remove(conn, trans);
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozekstatic int cmd_set(struct dict_connection *conn, const char *line)
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozek const char *const *args;
99f8be128274eba264ea1434a7eb2800bced5902Lukas Slebodnik /* <id> <key> <value> */
a2e417f38c57ed87c956ddcecf4dafca93842b65Lukas Slebodnik if (dict_connection_transaction_lookup_parse(conn, args[0], &trans) < 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic int cmd_unset(struct dict_connection *conn, const char *line)
fb3c5cdfcda069a5fbeb7b9d200c0881911364b8Jakub Hrozek const char *const *args;
9f521c61c17cecd9625ebc1b33c666fa3488622cJakub Hrozek /* <id> <key> */
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik i_error("dict client: UNSET: broken input");
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik if (dict_connection_transaction_lookup_parse(conn, args[0], &trans) < 0)
bf5a808fa92007c325c3996e79694badfab201d4Stephen Gallagherstatic int cmd_atomic_inc(struct dict_connection *conn, const char *line)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const char *const *args;
cbff3fcdce5b0377a62fbe74f32e476efbf7ca9cNikolai Kondrashov /* <id> <key> <diff> */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_error("dict client: ATOMIC_INC: broken input");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (dict_connection_transaction_lookup_parse(conn, args[0], &trans) < 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher { DICT_PROTOCOL_CMD_ITERATE, cmd_iterate },
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher { DICT_PROTOCOL_CMD_COMMIT_ASYNC, cmd_commit_async },
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher { DICT_PROTOCOL_CMD_ROLLBACK, cmd_rollback },
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose { DICT_PROTOCOL_CMD_ATOMIC_INC, cmd_atomic_inc },
90fd1bbd6035cdab46faa3a695a2fb2be6508b17Sumit Bosestatic struct dict_client_cmd *dict_command_find(char cmd)
90fd1bbd6035cdab46faa3a695a2fb2be6508b17Sumit Bose unsigned int i;
1d1a0a019d8d4d9ab0f51ada03604cd2cada287eSumit Boseint dict_command_input(struct dict_connection *conn, const char *line)
96453f402831275a39d5fb89c33c9776e148d03fStephen Gallagher i_error("dict client: Unknown command %c", *line);