driver-cassandra.c revision 37e8420b32a0fa3442c405616980e45beb494104
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen/* Copyright (c) 2015 Dovecot authors, see the included COPYING file */
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen#include "lib.h"
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen#include "array.h"
b87761f9bbef949f31dae297e619ac3f5e9c2b2eTimo Sirainen#include "hex-binary.h"
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen#include "str.h"
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen#include "ioloop.h"
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen#include "write-full.h"
de5f478d9e7ae7b8e58082e0b30b6ce1f034236aTimo Sirainen#include "time-util.h"
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen#include "sql-api-private.h"
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen#ifdef BUILD_CASSANDRA
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen#include <unistd.h>
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen#include <cassandra.h>
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen#define IS_CONNECTED(db) \
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen ((db)->api.state != SQL_DB_STATE_DISCONNECTED && \
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen (db)->api.state != SQL_DB_STATE_CONNECTING)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainentypedef void driver_cassandra_callback_t(CassFuture *future, void *context);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainenenum cassandra_query_type {
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen CASSANDRA_QUERY_TYPE_READ,
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen CASSANDRA_QUERY_TYPE_WRITE,
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen CASSANDRA_QUERY_TYPE_DELETE
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen};
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstruct cassandra_callback {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen unsigned int id;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen CassFuture *future;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct cassandra_db *db;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen driver_cassandra_callback_t *callback;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen void *context;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen};
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstruct cassandra_db {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct sql_db api;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen char *hosts, *keyspace;
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen CassConsistency read_consistency, write_consistency, delete_consistency;
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen CassLogLevel log_level;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen CassCluster *cluster;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen CassSession *session;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen int fd_pipe[2];
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct io *io_pipe;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen ARRAY(struct cassandra_callback *) callbacks;
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen ARRAY(struct cassandra_result *) results;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen unsigned int callback_ids;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen /* for synchronous queries: */
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct ioloop *ioloop, *orig_ioloop;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct sql_result *sync_result;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen char *error;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen};
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstruct cassandra_result {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct sql_result api;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen CassStatement *statement;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen const CassResult *result;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen CassIterator *iterator;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen char *query;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen char *error;
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen enum cassandra_query_type query_type;
2ccb478c35972517721ce415d81fcbd11a73fad3Timo Sirainen struct timeval start_time, finish_time;
37e8420b32a0fa3442c405616980e45beb494104Timo Sirainen unsigned int row_count;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen pool_t row_pool;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen ARRAY_TYPE(const_string) fields;
61f39b0358a72ebc693d84ba5bac74489ee7df41Timo Sirainen ARRAY(size_t) field_sizes;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen sql_query_callback_t *callback;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen void *context;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen unsigned int query_sent:1;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen unsigned int finished:1;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen};
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstruct cassandra_transaction_context {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct sql_transaction_context ctx;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen int refcount;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen sql_commit_callback_t *callback;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen void *context;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen pool_t query_pool;
e22ec7998afd426c53c658483ce66b6e404e27c6Timo Sirainen char *error;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen unsigned int begin_succeeded:1;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen unsigned int begin_failed:1;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen unsigned int failed:1;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen};
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenextern const struct sql_db driver_cassandra_db;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenextern const struct sql_result driver_cassandra_result;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic struct {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen CassConsistency consistency;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen const char *name;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen} cass_consistency_names[] = {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen { CASS_CONSISTENCY_ANY, "any" },
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen { CASS_CONSISTENCY_ONE, "one" },
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen { CASS_CONSISTENCY_TWO, "two" },
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen { CASS_CONSISTENCY_THREE, "three" },
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen { CASS_CONSISTENCY_QUORUM, "" },
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen { CASS_CONSISTENCY_ALL, "all" },
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen { CASS_CONSISTENCY_QUORUM, "" },
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen { CASS_CONSISTENCY_ALL, "all" },
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen { CASS_CONSISTENCY_LOCAL_QUORUM, "local-quorum" },
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen { CASS_CONSISTENCY_EACH_QUORUM, "each-quorum" },
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen { CASS_CONSISTENCY_SERIAL, "serial" },
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen { CASS_CONSISTENCY_LOCAL_SERIAL, "local-serial" },
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen { CASS_CONSISTENCY_LOCAL_ONE, "local-one" }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen};
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainenstatic struct {
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen CassLogLevel log_level;
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen const char *name;
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen} cass_log_level_names[] = {
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen { CASS_LOG_CRITICAL, "critical" },
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen { CASS_LOG_ERROR, "error" },
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen { CASS_LOG_WARN, "warn" },
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen { CASS_LOG_INFO, "info" },
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen { CASS_LOG_DEBUG, "debug" },
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen { CASS_LOG_TRACE, "trace" }
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen};
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainenstatic void driver_cassandra_send_queries(struct cassandra_db *db);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic void result_finish(struct cassandra_result *result);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic int consistency_parse(const char *str, CassConsistency *consistency_r)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen unsigned int i;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen for (i = 0; i < N_ELEMENTS(cass_consistency_names); i++) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (strcmp(cass_consistency_names[i].name, str) == 0) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen *consistency_r = cass_consistency_names[i].consistency;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return 0;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return -1;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainenstatic int log_level_parse(const char *str, CassLogLevel *log_level_r)
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen{
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen unsigned int i;
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen for (i = 0; i < N_ELEMENTS(cass_log_level_names); i++) {
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen if (strcmp(cass_log_level_names[i].name, str) == 0) {
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen *log_level_r = cass_log_level_names[i].log_level;
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen return 0;
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen }
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen }
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen return -1;
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen}
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic void driver_cassandra_set_state(struct cassandra_db *db, enum sql_db_state state)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen /* switch back to original ioloop in case the caller wants to
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen add/remove timeouts */
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (db->ioloop != NULL)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen io_loop_set_current(db->orig_ioloop);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen sql_db_set_state(&db->api, state);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (db->ioloop != NULL)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen io_loop_set_current(db->ioloop);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainenstatic void driver_cassandra_close(struct cassandra_db *db, const char *error)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen struct cassandra_result *const *resultp;
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (db->io_pipe != NULL)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen io_remove(&db->io_pipe);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (db->fd_pipe[0] != -1) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_close_fd(&db->fd_pipe[0]);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_close_fd(&db->fd_pipe[1]);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen driver_cassandra_set_state(db, SQL_DB_STATE_DISCONNECTED);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen while (array_count(&db->results) > 0) {
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen resultp = array_idx(&db->results, 0);
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen if ((*resultp)->error == NULL)
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen (*resultp)->error = i_strdup(error);
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen result_finish(*resultp);
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen }
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (db->ioloop != NULL) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen /* running a sync query, stop it */
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen io_loop_stop(db->ioloop);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic void driver_cassandra_log_error(CassFuture *future, const char *str)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen const char *message;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen size_t size;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen cass_future_error_message(future, &message, &size);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_error("cassandra: %s: %.*s", str, (int)size, message);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic void driver_cassandra_future_callback(CassFuture *future ATTR_UNUSED,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen void *context)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct cassandra_callback *cb = context;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen /* this isn't the main thread - communicate with main thread by
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen writing the callback id to the pipe */
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (write_full(cb->db->fd_pipe[1], &cb->id, sizeof(cb->id)) < 0)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_error("cassandra: write(pipe) failed: %m");
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic void cassandra_callback_run(struct cassandra_callback *cb)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen cb->callback(cb->future, cb->context);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen cass_future_free(cb->future);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_free(cb);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic void driver_cassandra_input_id(struct cassandra_db *db, unsigned int id)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct cassandra_callback *cb, *const *cbp;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen /* usually there are only a few callbacks, so don't bother with using
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen a hash table */
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen array_foreach(&db->callbacks, cbp) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen cb = *cbp;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (cb->id == id) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen array_delete(&db->callbacks,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen array_foreach_idx(&db->callbacks, cbp), 1);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen cassandra_callback_run(cb);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_panic("cassandra: Received unknown ID %u", id);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic void driver_cassandra_input(struct cassandra_db *db)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen unsigned int ids[1024];
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen ssize_t ret;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen ret = read(db->fd_pipe[0], ids, sizeof(ids));
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (ret < 0)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_error("cassandra: read(pipe) failed: %m");
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen else if (ret == 0)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_error("cassandra: read(pipe) failed: EOF");
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen else if (ret % sizeof(ids[0]) != 0)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_error("cassandra: read(pipe) returned wrong amount of data");
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen else {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen /* success */
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen unsigned int i, count = ret / sizeof(ids[0]);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen for (i = 0; i < count && db->api.state != SQL_DB_STATE_DISCONNECTED; i++)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen driver_cassandra_input_id(db, ids[i]);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen driver_cassandra_close(db, "IPC pipe closed");
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic void
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainendriver_cassandra_set_callback(CassFuture *future, struct cassandra_db *db,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen driver_cassandra_callback_t *callback,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen void *context)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct cassandra_callback *cb;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen cb = i_new(struct cassandra_callback, 1);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen cb->id = ++db->callback_ids;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen cb->future = future;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen cb->callback = callback;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen cb->context = context;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen cb->db = db;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen array_append(&db->callbacks, &cb, 1);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen cass_future_set_callback(future, driver_cassandra_future_callback, cb);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic void connect_callback(CassFuture *future, void *context)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct cassandra_db *db = context;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen CassError rc;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if ((rc = cass_future_error_code(future)) != CASS_OK) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen driver_cassandra_log_error(future,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen "Couldn't connect to Cassandra");
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen driver_cassandra_close(db, "Couldn't connect to Cassandra");
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen driver_cassandra_set_state(db, SQL_DB_STATE_IDLE);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (db->ioloop != NULL) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen /* driver_cassandra_sync_init() waiting for connection to
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen finish */
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen io_loop_stop(db->ioloop);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen driver_cassandra_send_queries(db);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic int driver_cassandra_connect(struct sql_db *_db)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct cassandra_db *db = (struct cassandra_db *)_db;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen CassFuture *future;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_assert(db->api.state == SQL_DB_STATE_DISCONNECTED);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (pipe(db->fd_pipe) < 0) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_error("pipe() failed: %m");
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return -1;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen db->io_pipe = io_add(db->fd_pipe[0], IO_READ,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen driver_cassandra_input, db);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen driver_cassandra_set_state(db, SQL_DB_STATE_CONNECTING);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen future = cass_session_connect_keyspace(db->session, db->cluster, db->keyspace);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen driver_cassandra_set_callback(future, db, connect_callback, db);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return 0;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic void driver_cassandra_disconnect(struct sql_db *_db)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct cassandra_db *db = (struct cassandra_db *)_db;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen driver_cassandra_close(db, "Disconnected");
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic const char *
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainendriver_cassandra_escape_string(struct sql_db *db ATTR_UNUSED,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen const char *string)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen string_t *escaped;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen unsigned int i;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (strchr(string, '\'') == NULL)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return string;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen escaped = t_str_new(strlen(string)+10);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen for (i = 0; string[i] != '\0'; i++) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (string[i] == '\'')
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen str_append_c(escaped, '\'');
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen str_append_c(escaped, string[i]);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return str_c(escaped);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic void driver_cassandra_parse_connect_string(struct cassandra_db *db,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen const char *connect_string)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen const char *const *args, *key, *value;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen string_t *hosts = t_str_new(64);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen db->log_level = CASS_LOG_WARN;
6ea145a99eeee923602f04d3c9183bbdba6cd190Timo Sirainen db->read_consistency = CASS_CONSISTENCY_LOCAL_QUORUM;
6ea145a99eeee923602f04d3c9183bbdba6cd190Timo Sirainen db->write_consistency = CASS_CONSISTENCY_LOCAL_QUORUM;
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen db->delete_consistency = CASS_CONSISTENCY_LOCAL_QUORUM;
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen args = t_strsplit_spaces(connect_string, " ");
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen for (; *args != NULL; args++) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen value = strchr(*args, '=');
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (value == NULL) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_fatal("cassandra: Missing value in connect string: %s",
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen *args);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen key = t_strdup_until(*args, value++);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (strcmp(key, "host") == 0) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (str_len(hosts) > 0)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen str_append_c(hosts, ',');
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen str_append(hosts, value);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen } else if (strcmp(key, "dbname") == 0 ||
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen strcmp(key, "keyspace") == 0) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_free(db->keyspace);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen db->keyspace = i_strdup(value);
ce74395e2a932342e04fb682395bcce111574969Timo Sirainen } else if (strcmp(key, "read_consistency") == 0) {
ce74395e2a932342e04fb682395bcce111574969Timo Sirainen if (consistency_parse(value, &db->read_consistency) < 0)
ce74395e2a932342e04fb682395bcce111574969Timo Sirainen i_fatal("cassandra: Unknown read_consistency: %s", value);
ce74395e2a932342e04fb682395bcce111574969Timo Sirainen } else if (strcmp(key, "write_consistency") == 0) {
ce74395e2a932342e04fb682395bcce111574969Timo Sirainen if (consistency_parse(value, &db->write_consistency) < 0)
ce74395e2a932342e04fb682395bcce111574969Timo Sirainen i_fatal("cassandra: Unknown write_consistency: %s", value);
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen } else if (strcmp(key, "delete_consistency") == 0) {
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen if (consistency_parse(value, &db->delete_consistency) < 0)
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen i_fatal("cassandra: Unknown delete_consistency: %s", value);
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen } else if (strcmp(key, "log_level") == 0) {
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen if (log_level_parse(value, &db->log_level) < 0)
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen i_fatal("cassandra: Unknown log_level: %s", value);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen } else {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_fatal("cassandra: Unknown connect string: %s", key);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (str_len(hosts) == 0)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_fatal("cassandra: No hosts given in connect string");
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (db->keyspace == NULL)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_fatal("cassandra: No dbname given in connect string");
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen db->hosts = i_strdup(str_c(hosts));
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic struct sql_db *driver_cassandra_init_v(const char *connect_string)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct cassandra_db *db;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen db = i_new(struct cassandra_db, 1);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen db->api = driver_cassandra_db;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen db->fd_pipe[0] = db->fd_pipe[1] = -1;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen T_BEGIN {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen driver_cassandra_parse_connect_string(db, connect_string);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen } T_END;
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen cass_log_set_level(db->log_level);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen db->cluster = cass_cluster_new();
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen cass_cluster_set_connect_timeout(db->cluster, SQL_CONNECT_TIMEOUT_SECS * 1000);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen cass_cluster_set_request_timeout(db->cluster, SQL_QUERY_TIMEOUT_SECS * 1000);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen cass_cluster_set_contact_points(db->cluster, db->hosts);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen db->session = cass_session_new();
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen i_array_init(&db->results, 16);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_array_init(&db->callbacks, 16);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return &db->api;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic void driver_cassandra_deinit_v(struct sql_db *_db)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct cassandra_db *db = (struct cassandra_db *)_db;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen driver_cassandra_close(db, "Deinitialized");
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_assert(array_count(&db->callbacks) == 0);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen array_free(&db->callbacks);
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen i_assert(array_count(&db->results) == 0);
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen array_free(&db->results);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen cass_session_free(db->session);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen cass_cluster_free(db->cluster);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_free(db->hosts);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_free(db->error);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_free(db->keyspace);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen array_free(&_db->module_contexts);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_free(db);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainenstatic void driver_cassandra_result_unlink(struct cassandra_db *db,
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen struct cassandra_result *result)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen struct cassandra_result *const *results;
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen unsigned int i, count;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen results = array_get(&db->results, &count);
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen for (i = 0; i < count; i++) {
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen if (results[i] == result) {
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen array_delete(&db->results, i, 1);
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen return;
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen }
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen }
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen i_unreached();
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic void driver_cassandra_result_free(struct sql_result *_result)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct cassandra_db *db = (struct cassandra_db *)_result->db;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct cassandra_result *result = (struct cassandra_result *)_result;
2ccb478c35972517721ce415d81fcbd11a73fad3Timo Sirainen struct timeval now;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b457d2ecf97fb52064f9dd563fd4e8065af39dfbTimo Sirainen i_assert(!result->api.callback);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_assert(result->callback == NULL);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (_result == db->sync_result)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen db->sync_result = NULL;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
2ccb478c35972517721ce415d81fcbd11a73fad3Timo Sirainen if (db->log_level >= CASS_LOG_DEBUG) {
2ccb478c35972517721ce415d81fcbd11a73fad3Timo Sirainen if (gettimeofday(&now, NULL) < 0)
2ccb478c35972517721ce415d81fcbd11a73fad3Timo Sirainen i_fatal("gettimeofday() failed: %m");
37e8420b32a0fa3442c405616980e45beb494104Timo Sirainen i_debug("cassandra: Finished query '%s' (%u rows, %lld+%lld us): %s", result->query,
37e8420b32a0fa3442c405616980e45beb494104Timo Sirainen result->row_count,
2ccb478c35972517721ce415d81fcbd11a73fad3Timo Sirainen timeval_diff_usecs(&result->finish_time, &result->start_time),
2ccb478c35972517721ce415d81fcbd11a73fad3Timo Sirainen timeval_diff_usecs(&now, &result->finish_time),
2ccb478c35972517721ce415d81fcbd11a73fad3Timo Sirainen result->error != NULL ? result->error : "success");
2ccb478c35972517721ce415d81fcbd11a73fad3Timo Sirainen }
2ccb478c35972517721ce415d81fcbd11a73fad3Timo Sirainen
f0e811f0e306bb20d3da9c26353bdd5669132f29Timo Sirainen if (result->result != NULL)
f0e811f0e306bb20d3da9c26353bdd5669132f29Timo Sirainen cass_result_free(result->result);
f0e811f0e306bb20d3da9c26353bdd5669132f29Timo Sirainen if (result->iterator != NULL)
f0e811f0e306bb20d3da9c26353bdd5669132f29Timo Sirainen cass_iterator_free(result->iterator);
3e8842470a4a17017529d43b39c40a7549c2ecf2Timo Sirainen if (result->statement != NULL)
3e8842470a4a17017529d43b39c40a7549c2ecf2Timo Sirainen cass_statement_free(result->statement);
3e8842470a4a17017529d43b39c40a7549c2ecf2Timo Sirainen if (result->row_pool != NULL)
3e8842470a4a17017529d43b39c40a7549c2ecf2Timo Sirainen pool_unref(&result->row_pool);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_free(result->query);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_free(result->error);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_free(result);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic void result_finish(struct cassandra_result *result)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct cassandra_db *db = (struct cassandra_db *)result->api.db;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen bool free_result = TRUE;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen result->finished = TRUE;
2ccb478c35972517721ce415d81fcbd11a73fad3Timo Sirainen result->finish_time = ioloop_timeval;
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen driver_cassandra_result_unlink(db, result);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b650f04c3b2e7dea2295bdbe3239eb82ec03ada0Timo Sirainen i_assert((result->error != NULL) == (result->iterator == NULL));
b650f04c3b2e7dea2295bdbe3239eb82ec03ada0Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen result->api.callback = TRUE;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen T_BEGIN {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen result->callback(&result->api, result->context);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen } T_END;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen result->api.callback = FALSE;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen free_result = db->sync_result != &result->api;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (db->ioloop != NULL)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen io_loop_stop(db->ioloop);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
1856c361aad526948d56d8aafd576bca94516b92Timo Sirainen i_assert(!free_result || result->api.refcount > 0);
1856c361aad526948d56d8aafd576bca94516b92Timo Sirainen result->callback = NULL;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (free_result)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen sql_result_unref(&result->api);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic void query_callback(CassFuture *future, void *context)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct cassandra_result *result = context;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (cass_future_error_code(future) != CASS_OK) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen const char *errmsg;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen size_t errsize;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen cass_future_error_message(future, &errmsg, &errsize);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_free(result->error);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen result->error = i_strdup_printf("Query '%s' failed: %.*s",
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen result->query,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen (int)errsize, errmsg);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen result_finish(result);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen result->result = cass_future_get_result(future);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen result->iterator = cass_iterator_from_result(result->result);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen result_finish(result);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainenstatic int driver_cassandra_send_query(struct cassandra_result *result)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct cassandra_db *db = (struct cassandra_db *)result->api.db;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen CassFuture *future;
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen int ret;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen if (!SQL_DB_IS_READY(&db->api)) {
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen if ((ret = sql_connect(&db->api)) <= 0) {
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen if (ret < 0)
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen driver_cassandra_close(db, "Couldn't connect to Cassandra");
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen return ret;
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen }
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
de5f478d9e7ae7b8e58082e0b30b6ce1f034236aTimo Sirainen result->start_time = ioloop_timeval;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen result->row_pool = pool_alloconly_create("cassandra result", 512);
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen result->statement = cass_statement_new(result->query, 0);
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen switch (result->query_type) {
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen case CASSANDRA_QUERY_TYPE_READ:
6ea145a99eeee923602f04d3c9183bbdba6cd190Timo Sirainen cass_statement_set_consistency(result->statement, db->read_consistency);
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen break;
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen case CASSANDRA_QUERY_TYPE_WRITE:
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen cass_statement_set_consistency(result->statement, db->write_consistency);
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen break;
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen case CASSANDRA_QUERY_TYPE_DELETE:
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen cass_statement_set_consistency(result->statement, db->delete_consistency);
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen break;
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen future = cass_session_execute(db->session, result->statement);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen driver_cassandra_set_callback(future, db, query_callback, result);
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen result->query_sent = TRUE;
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen return 1;
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen}
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainenstatic void driver_cassandra_send_queries(struct cassandra_db *db)
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen{
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen struct cassandra_result *const *results;
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen unsigned int i, count;
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen results = array_get(&db->results, &count);
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen for (i = 0; i < count; i++) {
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen if (!results[i]->query_sent) {
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen if (driver_cassandra_send_query(results[i]) <= 0)
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen break;
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen }
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic void exec_callback(struct sql_result *_result ATTR_UNUSED,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen void *context ATTR_UNUSED)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
ce74395e2a932342e04fb682395bcce111574969Timo Sirainenstatic void
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainendriver_cassandra_query_full(struct sql_db *_db, const char *query,
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen enum cassandra_query_type query_type,
ce74395e2a932342e04fb682395bcce111574969Timo Sirainen sql_query_callback_t *callback, void *context)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen struct cassandra_db *db = (struct cassandra_db *)_db;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct cassandra_result *result;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen result = i_new(struct cassandra_result, 1);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen result->api = driver_cassandra_result;
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen result->api.db = _db;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen result->api.refcount = 1;
ce74395e2a932342e04fb682395bcce111574969Timo Sirainen result->callback = callback;
ce74395e2a932342e04fb682395bcce111574969Timo Sirainen result->context = context;
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen result->query_type = query_type;
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen result->query = i_strdup(query);
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen array_append(&db->results, &result, 1);
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen (void)driver_cassandra_send_query(result);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
ce74395e2a932342e04fb682395bcce111574969Timo Sirainenstatic void driver_cassandra_exec(struct sql_db *db, const char *query)
ce74395e2a932342e04fb682395bcce111574969Timo Sirainen{
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen driver_cassandra_query_full(db, query, CASSANDRA_QUERY_TYPE_WRITE, exec_callback, NULL);
ce74395e2a932342e04fb682395bcce111574969Timo Sirainen}
ce74395e2a932342e04fb682395bcce111574969Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic void driver_cassandra_query(struct sql_db *db, const char *query,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen sql_query_callback_t *callback, void *context)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen driver_cassandra_query_full(db, query, CASSANDRA_QUERY_TYPE_READ, callback, context);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic void cassandra_query_s_callback(struct sql_result *result, void *context)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct cassandra_db *db = context;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen db->sync_result = result;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic void driver_cassandra_sync_init(struct cassandra_db *db)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (sql_connect(&db->api) < 0)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen db->orig_ioloop = current_ioloop;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen db->ioloop = io_loop_create();
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (IS_CONNECTED(db))
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_assert(db->api.state == SQL_DB_STATE_CONNECTING);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen db->io_pipe = io_loop_move_io(&db->io_pipe);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen /* wait for connecting to finish */
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen io_loop_run(db->ioloop);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic void driver_cassandra_sync_deinit(struct cassandra_db *db)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (db->orig_ioloop == NULL)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return;
e07677bb15404a3c18ad205efae86d6db31c3150Timo Sirainen if (db->io_pipe != NULL) {
e07677bb15404a3c18ad205efae86d6db31c3150Timo Sirainen io_loop_set_current(db->orig_ioloop);
e07677bb15404a3c18ad205efae86d6db31c3150Timo Sirainen db->io_pipe = io_loop_move_io(&db->io_pipe);
e07677bb15404a3c18ad205efae86d6db31c3150Timo Sirainen io_loop_set_current(db->ioloop);
e07677bb15404a3c18ad205efae86d6db31c3150Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen io_loop_destroy(&db->ioloop);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic struct sql_result *
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainendriver_cassandra_sync_query(struct cassandra_db *db, const char *query)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct sql_result *result;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_assert(db->sync_result == NULL);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen switch (db->api.state) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen case SQL_DB_STATE_CONNECTING:
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen case SQL_DB_STATE_BUSY:
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_unreached();
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen case SQL_DB_STATE_DISCONNECTED:
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen sql_not_connected_result.refcount++;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return &sql_not_connected_result;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen case SQL_DB_STATE_IDLE:
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen break;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen driver_cassandra_query(&db->api, query, cassandra_query_s_callback, db);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (db->sync_result == NULL) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen db->io_pipe = io_loop_move_io(&db->io_pipe);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen io_loop_run(db->ioloop);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen result = db->sync_result;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (result == &sql_not_connected_result) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen /* we don't end up in cassandra's free function, so sync_result
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen won't be set to NULL if we don't do it here. */
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen db->sync_result = NULL;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen } else if (result == NULL) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen result = &sql_not_connected_result;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen result->refcount++;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return result;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic struct sql_result *
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainendriver_cassandra_query_s(struct sql_db *_db, const char *query)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct cassandra_db *db = (struct cassandra_db *)_db;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct sql_result *result;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen driver_cassandra_sync_init(db);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen result = driver_cassandra_sync_query(db, query);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen driver_cassandra_sync_deinit(db);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return result;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic int
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainendriver_cassandra_get_value(struct cassandra_result *result,
61f39b0358a72ebc693d84ba5bac74489ee7df41Timo Sirainen const CassValue *value, const char **str_r,
61f39b0358a72ebc693d84ba5bac74489ee7df41Timo Sirainen size_t *len_r)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
61f39b0358a72ebc693d84ba5bac74489ee7df41Timo Sirainen const unsigned char *output;
61f39b0358a72ebc693d84ba5bac74489ee7df41Timo Sirainen void *output_dup;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen size_t output_size;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen CassError rc;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (cass_value_is_null(value)) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen *str_r = NULL;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return 0;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
61f39b0358a72ebc693d84ba5bac74489ee7df41Timo Sirainen rc = cass_value_get_bytes(value, &output, &output_size);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (rc != CASS_OK) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_free(result->error);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen result->error = i_strdup_printf("Couldn't get value as string (code=%d)", rc);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return -1;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
61f39b0358a72ebc693d84ba5bac74489ee7df41Timo Sirainen output_dup = p_malloc(result->row_pool, output_size + 1);
61f39b0358a72ebc693d84ba5bac74489ee7df41Timo Sirainen memcpy(output_dup, output, output_size);
61f39b0358a72ebc693d84ba5bac74489ee7df41Timo Sirainen *str_r = output_dup;
61f39b0358a72ebc693d84ba5bac74489ee7df41Timo Sirainen *len_r = output_size;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return 0;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic int driver_cassandra_result_next_row(struct sql_result *_result)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct cassandra_result *result = (struct cassandra_result *)_result;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen const CassRow *row;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen const CassValue *value;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen const char *str;
61f39b0358a72ebc693d84ba5bac74489ee7df41Timo Sirainen size_t size;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen unsigned int i;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen int ret = 1;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (result->iterator == NULL)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return -1;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (!cass_iterator_next(result->iterator))
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return 0;
37e8420b32a0fa3442c405616980e45beb494104Timo Sirainen result->row_count++;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen p_clear(result->row_pool);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen p_array_init(&result->fields, result->row_pool, 8);
61f39b0358a72ebc693d84ba5bac74489ee7df41Timo Sirainen p_array_init(&result->field_sizes, result->row_pool, 8);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen row = cass_iterator_get_row(result->iterator);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen for (i = 0; (value = cass_row_get_column(row, i)) != NULL; i++) {
61f39b0358a72ebc693d84ba5bac74489ee7df41Timo Sirainen if (driver_cassandra_get_value(result, value, &str, &size) < 0) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen ret = -1;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen break;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen array_append(&result->fields, &str, 1);
61f39b0358a72ebc693d84ba5bac74489ee7df41Timo Sirainen array_append(&result->field_sizes, &size, 1);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return ret;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic unsigned int
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainendriver_cassandra_result_get_fields_count(struct sql_result *_result)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct cassandra_result *result = (struct cassandra_result *)_result;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return array_count(&result->fields);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic const char *
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainendriver_cassandra_result_get_field_name(struct sql_result *_result ATTR_UNUSED,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen unsigned int idx ATTR_UNUSED)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_unreached();
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic int
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainendriver_cassandra_result_find_field(struct sql_result *_result ATTR_UNUSED,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen const char *field_name ATTR_UNUSED)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_unreached();
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic const char *
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainendriver_cassandra_result_get_field_value(struct sql_result *_result,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen unsigned int idx)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct cassandra_result *result = (struct cassandra_result *)_result;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen const char *const *strp;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen strp = array_idx(&result->fields, idx);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return *strp;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic const unsigned char *
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainendriver_cassandra_result_get_field_value_binary(struct sql_result *_result ATTR_UNUSED,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen unsigned int idx ATTR_UNUSED,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen size_t *size_r ATTR_UNUSED)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
61f39b0358a72ebc693d84ba5bac74489ee7df41Timo Sirainen struct cassandra_result *result = (struct cassandra_result *)_result;
61f39b0358a72ebc693d84ba5bac74489ee7df41Timo Sirainen const char *const *strp;
61f39b0358a72ebc693d84ba5bac74489ee7df41Timo Sirainen const size_t *sizep;
61f39b0358a72ebc693d84ba5bac74489ee7df41Timo Sirainen
61f39b0358a72ebc693d84ba5bac74489ee7df41Timo Sirainen strp = array_idx(&result->fields, idx);
61f39b0358a72ebc693d84ba5bac74489ee7df41Timo Sirainen sizep = array_idx(&result->field_sizes, idx);
61f39b0358a72ebc693d84ba5bac74489ee7df41Timo Sirainen *size_r = *sizep;
61f39b0358a72ebc693d84ba5bac74489ee7df41Timo Sirainen return (const void *)*strp;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic const char *
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainendriver_cassandra_result_find_field_value(struct sql_result *result ATTR_UNUSED,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen const char *field_name ATTR_UNUSED)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_unreached();
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic const char *const *
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainendriver_cassandra_result_get_values(struct sql_result *_result)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct cassandra_result *result = (struct cassandra_result *)_result;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return array_idx(&result->fields, 0);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic const char *driver_cassandra_result_get_error(struct sql_result *_result)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct cassandra_result *result = (struct cassandra_result *)_result;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (result->error != NULL)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return result->error;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return "FIXME";
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic struct sql_transaction_context *
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainendriver_cassandra_transaction_begin(struct sql_db *db)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct cassandra_transaction_context *ctx;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen ctx = i_new(struct cassandra_transaction_context, 1);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen ctx->ctx.db = db;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen ctx->refcount = 1;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen /* we need to be able to handle multiple open transactions, so at least
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen for now just keep them in memory until commit time. */
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen ctx->query_pool = pool_alloconly_create("cassandra transaction", 1024);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return &ctx->ctx;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic void
6b4b3e5fe8d9e84f4b1356ee898ca76996a11fe1Timo Sirainendriver_cassandra_transaction_unref(struct cassandra_transaction_context **_ctx)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
6b4b3e5fe8d9e84f4b1356ee898ca76996a11fe1Timo Sirainen struct cassandra_transaction_context *ctx = *_ctx;
6b4b3e5fe8d9e84f4b1356ee898ca76996a11fe1Timo Sirainen
6b4b3e5fe8d9e84f4b1356ee898ca76996a11fe1Timo Sirainen *_ctx = NULL;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_assert(ctx->refcount > 0);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (--ctx->refcount > 0)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen pool_unref(&ctx->query_pool);
e22ec7998afd426c53c658483ce66b6e404e27c6Timo Sirainen i_free(ctx->error);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_free(ctx);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
e22ec7998afd426c53c658483ce66b6e404e27c6Timo Sirainenstatic void
e22ec7998afd426c53c658483ce66b6e404e27c6Timo Sirainentransaction_set_failed(struct cassandra_transaction_context *ctx,
e22ec7998afd426c53c658483ce66b6e404e27c6Timo Sirainen const char *error)
e22ec7998afd426c53c658483ce66b6e404e27c6Timo Sirainen{
e22ec7998afd426c53c658483ce66b6e404e27c6Timo Sirainen if (ctx->failed) {
e22ec7998afd426c53c658483ce66b6e404e27c6Timo Sirainen i_assert(ctx->error != NULL);
e22ec7998afd426c53c658483ce66b6e404e27c6Timo Sirainen } else {
e22ec7998afd426c53c658483ce66b6e404e27c6Timo Sirainen i_assert(ctx->error == NULL);
e22ec7998afd426c53c658483ce66b6e404e27c6Timo Sirainen ctx->failed = TRUE;
e22ec7998afd426c53c658483ce66b6e404e27c6Timo Sirainen ctx->error = i_strdup(error);
e22ec7998afd426c53c658483ce66b6e404e27c6Timo Sirainen }
e22ec7998afd426c53c658483ce66b6e404e27c6Timo Sirainen}
e22ec7998afd426c53c658483ce66b6e404e27c6Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic void
ce74395e2a932342e04fb682395bcce111574969Timo Sirainentransaction_commit_callback(struct sql_result *result, void *context)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
ce74395e2a932342e04fb682395bcce111574969Timo Sirainen struct cassandra_transaction_context *ctx = context;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (sql_result_next_row(result) < 0)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen ctx->callback(sql_result_get_error(result), ctx->context);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen else
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen ctx->callback(NULL, ctx->context);
6b4b3e5fe8d9e84f4b1356ee898ca76996a11fe1Timo Sirainen driver_cassandra_transaction_unref(&ctx);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic void
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainendriver_cassandra_transaction_commit(struct sql_transaction_context *_ctx,
ce74395e2a932342e04fb682395bcce111574969Timo Sirainen sql_commit_callback_t *callback, void *context)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct cassandra_transaction_context *ctx =
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen (struct cassandra_transaction_context *)_ctx;
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen enum cassandra_query_type query_type;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen ctx->callback = callback;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen ctx->context = context;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (ctx->failed || _ctx->head == NULL) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen callback(ctx->failed ? ctx->error : NULL, context);
6b4b3e5fe8d9e84f4b1356ee898ca76996a11fe1Timo Sirainen driver_cassandra_transaction_unref(&ctx);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen } else if (_ctx->head->next == NULL) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen /* just a single query, send it */
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen if (strncasecmp(_ctx->head->query, "DELETE ", 7) == 0)
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen query_type = CASSANDRA_QUERY_TYPE_DELETE;
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen else
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen query_type = CASSANDRA_QUERY_TYPE_WRITE;
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen driver_cassandra_query_full(_ctx->db, _ctx->head->query, query_type,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen transaction_commit_callback, ctx);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen } else {
ce74395e2a932342e04fb682395bcce111574969Timo Sirainen /* multiple queries - we don't actually have a transaction though */
ce74395e2a932342e04fb682395bcce111574969Timo Sirainen callback("Multiple changes in transaction not supported", context);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic void
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainencommit_multi_fail(struct cassandra_transaction_context *ctx,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct sql_result *result, const char *query)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
e22ec7998afd426c53c658483ce66b6e404e27c6Timo Sirainen transaction_set_failed(ctx, t_strdup_printf(
e22ec7998afd426c53c658483ce66b6e404e27c6Timo Sirainen "%s (query: %s)", sql_result_get_error(result), query));
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen sql_result_unref(result);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b650f04c3b2e7dea2295bdbe3239eb82ec03ada0Timo Sirainenstatic int
b650f04c3b2e7dea2295bdbe3239eb82ec03ada0Timo Sirainendriver_cassandra_transaction_commit_multi(struct cassandra_transaction_context *ctx,
b650f04c3b2e7dea2295bdbe3239eb82ec03ada0Timo Sirainen struct sql_result **result_r)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct cassandra_db *db = (struct cassandra_db *)ctx->ctx.db;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct sql_result *result;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct sql_transaction_query *query;
b650f04c3b2e7dea2295bdbe3239eb82ec03ada0Timo Sirainen int ret = 0;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen result = driver_cassandra_sync_query(db, "BEGIN");
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (sql_result_next_row(result) < 0) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen commit_multi_fail(ctx, result, "BEGIN");
b650f04c3b2e7dea2295bdbe3239eb82ec03ada0Timo Sirainen return -1;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen sql_result_unref(result);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen /* send queries */
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen for (query = ctx->ctx.head; query != NULL; query = query->next) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen result = driver_cassandra_sync_query(db, query->query);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (sql_result_next_row(result) < 0) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen commit_multi_fail(ctx, result, query->query);
b650f04c3b2e7dea2295bdbe3239eb82ec03ada0Timo Sirainen ret = -1;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen break;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen sql_result_unref(result);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b650f04c3b2e7dea2295bdbe3239eb82ec03ada0Timo Sirainen *result_r = driver_cassandra_sync_query(db, ctx->failed ?
b650f04c3b2e7dea2295bdbe3239eb82ec03ada0Timo Sirainen "ROLLBACK" : "COMMIT");
b650f04c3b2e7dea2295bdbe3239eb82ec03ada0Timo Sirainen return ret;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic void
e22ec7998afd426c53c658483ce66b6e404e27c6Timo Sirainendriver_cassandra_try_commit_s(struct cassandra_transaction_context *ctx)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct sql_transaction_context *_ctx = &ctx->ctx;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct cassandra_db *db = (struct cassandra_db *)_ctx->db;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct sql_transaction_query *single_query = NULL;
b650f04c3b2e7dea2295bdbe3239eb82ec03ada0Timo Sirainen struct sql_result *result = NULL;
b650f04c3b2e7dea2295bdbe3239eb82ec03ada0Timo Sirainen int ret = 0;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (_ctx->head->next == NULL) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen /* just a single query, send it */
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen single_query = _ctx->head;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen result = sql_query_s(_ctx->db, single_query->query);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen } else {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen /* multiple queries, use a transaction */
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen driver_cassandra_sync_init(db);
b650f04c3b2e7dea2295bdbe3239eb82ec03ada0Timo Sirainen ret = driver_cassandra_transaction_commit_multi(ctx, &result);
b650f04c3b2e7dea2295bdbe3239eb82ec03ada0Timo Sirainen i_assert(ret == 0 || ctx->failed);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen driver_cassandra_sync_deinit(db);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
e22ec7998afd426c53c658483ce66b6e404e27c6Timo Sirainen if (!ctx->failed) {
e22ec7998afd426c53c658483ce66b6e404e27c6Timo Sirainen if (sql_result_next_row(result) < 0)
e22ec7998afd426c53c658483ce66b6e404e27c6Timo Sirainen transaction_set_failed(ctx, sql_result_get_error(result));
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (result != NULL)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen sql_result_unref(result);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic int
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainendriver_cassandra_transaction_commit_s(struct sql_transaction_context *_ctx,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen const char **error_r)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct cassandra_transaction_context *ctx =
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen (struct cassandra_transaction_context *)_ctx;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (_ctx->head != NULL)
e22ec7998afd426c53c658483ce66b6e404e27c6Timo Sirainen driver_cassandra_try_commit_s(ctx);
b50234708ad651e98a4198e1b910106b279aae32Timo Sirainen *error_r = t_strdup(ctx->error);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_assert(ctx->refcount == 1);
b650f04c3b2e7dea2295bdbe3239eb82ec03ada0Timo Sirainen i_assert((*error_r != NULL) == ctx->failed);
6b4b3e5fe8d9e84f4b1356ee898ca76996a11fe1Timo Sirainen driver_cassandra_transaction_unref(&ctx);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return *error_r == NULL ? 0 : -1;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic void
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainendriver_cassandra_transaction_rollback(struct sql_transaction_context *_ctx)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct cassandra_transaction_context *ctx =
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen (struct cassandra_transaction_context *)_ctx;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_assert(ctx->refcount == 1);
6b4b3e5fe8d9e84f4b1356ee898ca76996a11fe1Timo Sirainen driver_cassandra_transaction_unref(&ctx);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic void
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainendriver_cassandra_update(struct sql_transaction_context *_ctx, const char *query,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen unsigned int *affected_rows)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct cassandra_transaction_context *ctx =
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen (struct cassandra_transaction_context *)_ctx;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_assert(affected_rows == NULL);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen sql_transaction_add_query(_ctx, ctx->query_pool, query, affected_rows);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b87761f9bbef949f31dae297e619ac3f5e9c2b2eTimo Sirainenstatic const char *
b87761f9bbef949f31dae297e619ac3f5e9c2b2eTimo Sirainendriver_cassandra_escape_blob(struct sql_db *_db ATTR_UNUSED,
b87761f9bbef949f31dae297e619ac3f5e9c2b2eTimo Sirainen const unsigned char *data, size_t size)
b87761f9bbef949f31dae297e619ac3f5e9c2b2eTimo Sirainen{
b87761f9bbef949f31dae297e619ac3f5e9c2b2eTimo Sirainen string_t *str = t_str_new(128);
b87761f9bbef949f31dae297e619ac3f5e9c2b2eTimo Sirainen
b87761f9bbef949f31dae297e619ac3f5e9c2b2eTimo Sirainen str_append(str, "0x");
b87761f9bbef949f31dae297e619ac3f5e9c2b2eTimo Sirainen binary_to_hex_append(str, data, size);
b87761f9bbef949f31dae297e619ac3f5e9c2b2eTimo Sirainen return str_c(str);
b87761f9bbef949f31dae297e619ac3f5e9c2b2eTimo Sirainen}
b87761f9bbef949f31dae297e619ac3f5e9c2b2eTimo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenconst struct sql_db driver_cassandra_db = {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen .name = "cassandra",
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen .flags = 0,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen .v = {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen driver_cassandra_init_v,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen driver_cassandra_deinit_v,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen driver_cassandra_connect,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen driver_cassandra_disconnect,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen driver_cassandra_escape_string,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen driver_cassandra_exec,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen driver_cassandra_query,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen driver_cassandra_query_s,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen driver_cassandra_transaction_begin,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen driver_cassandra_transaction_commit,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen driver_cassandra_transaction_commit_s,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen driver_cassandra_transaction_rollback,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b87761f9bbef949f31dae297e619ac3f5e9c2b2eTimo Sirainen driver_cassandra_update,
b87761f9bbef949f31dae297e619ac3f5e9c2b2eTimo Sirainen
b87761f9bbef949f31dae297e619ac3f5e9c2b2eTimo Sirainen driver_cassandra_escape_blob
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen};
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenconst struct sql_result driver_cassandra_result = {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen .v = {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen driver_cassandra_result_free,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen driver_cassandra_result_next_row,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen driver_cassandra_result_get_fields_count,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen driver_cassandra_result_get_field_name,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen driver_cassandra_result_find_field,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen driver_cassandra_result_get_field_value,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen driver_cassandra_result_get_field_value_binary,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen driver_cassandra_result_find_field_value,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen driver_cassandra_result_get_values,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen driver_cassandra_result_get_error
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen};
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenconst char *driver_cassandra_version = DOVECOT_ABI_VERSION;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenvoid driver_cassandra_init(void);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenvoid driver_cassandra_deinit(void);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenvoid driver_cassandra_init(void)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen sql_driver_register(&driver_cassandra_db);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenvoid driver_cassandra_deinit(void)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen sql_driver_unregister(&driver_cassandra_db);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen#endif