bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2015-2018 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"
e8434aad92ea6ff1c915b708294dbd0c7ff5908dMichael M Slusarz#include "net.h"
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen#include "write-full.h"
de5f478d9e7ae7b8e58082e0b30b6ce1f034236aTimo Sirainen#include "time-util.h"
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen#include "var-expand.h"
f7d018e7e0980044e3d537958126e44ef4c45056Timo Sirainen#include "settings-parser.h"
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen#include "sql-api-private.h"
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen#ifdef BUILD_CASSANDRA
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen#include <fcntl.h>
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
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen#define CASSANDRA_FALLBACK_WARN_INTERVAL_SECS 60
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen#define CASSANDRA_FALLBACK_FIRST_RETRY_MSECS 50
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen#define CASSANDRA_FALLBACK_MAX_RETRY_MSECS (1000*60)
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen
8952d797eca36f997ec36569e783871b597a9216Timo Sirainen#define CASS_QUERY_DEFAULT_WARN_TIMEOUT_MSECS (5*1000)
8952d797eca36f997ec36569e783871b597a9216Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainentypedef void driver_cassandra_callback_t(CassFuture *future, void *context);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainenenum cassandra_counter_type {
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen CASSANDRA_COUNTER_TYPE_QUERY_SENT,
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen CASSANDRA_COUNTER_TYPE_QUERY_RECV_OK,
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen CASSANDRA_COUNTER_TYPE_QUERY_RECV_ERR_NO_HOSTS,
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen CASSANDRA_COUNTER_TYPE_QUERY_RECV_ERR_QUEUE_FULL,
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen CASSANDRA_COUNTER_TYPE_QUERY_RECV_ERR_CLIENT_TIMEOUT,
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen CASSANDRA_COUNTER_TYPE_QUERY_RECV_ERR_SERVER_TIMEOUT,
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen CASSANDRA_COUNTER_TYPE_QUERY_RECV_ERR_SERVER_UNAVAILABLE,
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen CASSANDRA_COUNTER_TYPE_QUERY_RECV_ERR_OTHER,
01aca4a521410be85e1f39e37c662435d052f48aAki Tuomi CASSANDRA_COUNTER_TYPE_QUERY_SLOW,
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen CASSANDRA_COUNTER_COUNT
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen};
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainenstatic const char *counter_names[CASSANDRA_COUNTER_COUNT] = {
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen "sent",
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen "recv_ok",
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen "recv_err_no_hosts",
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen "recv_err_queue_full",
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen "recv_err_client_timeout",
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen "recv_err_server_timeout",
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen "recv_err_server_unavailable",
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen "recv_err_other",
01aca4a521410be85e1f39e37c662435d052f48aAki Tuomi "slow",
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen};
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainenenum cassandra_query_type {
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen CASSANDRA_QUERY_TYPE_READ,
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen CASSANDRA_QUERY_TYPE_READ_MORE,
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen CASSANDRA_QUERY_TYPE_WRITE,
8a6afcd8a6d9ed69626add85a7b75105ee3cb6a1Timo Sirainen CASSANDRA_QUERY_TYPE_DELETE,
8a6afcd8a6d9ed69626add85a7b75105ee3cb6a1Timo Sirainen
8a6afcd8a6d9ed69626add85a7b75105ee3cb6a1Timo Sirainen CASSANDRA_QUERY_TYPE_COUNT
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen};
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainenstatic const char *cassandra_query_type_names[CASSANDRA_QUERY_TYPE_COUNT] = {
8a6afcd8a6d9ed69626add85a7b75105ee3cb6a1Timo Sirainen "read", "read-more", "write", "delete"
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo 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
c72cfe4a2bda39fff3b8a8bd64b31a7cc14d7d11Timo Sirainen char *hosts, *keyspace, *user, *password;
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen CassConsistency read_consistency, write_consistency, delete_consistency;
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen CassConsistency read_fallback_consistency, write_fallback_consistency, delete_fallback_consistency;
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen CassLogLevel log_level;
14189e0d0af45ddcb888d026bd8d7e4609912ec5Timo Sirainen bool debug_queries;
e564ff0581fc44b78badf8da36e68f9f7a27807eTimo Sirainen bool latency_aware_routing;
f9eee365367f37b1692c07db6c23d30243844aaaTimo Sirainen unsigned int protocol_version;
f7d018e7e0980044e3d537958126e44ef4c45056Timo Sirainen unsigned int num_threads;
7cd055a212d44067e2d94452c05691d696c9f699Timo Sirainen unsigned int connect_timeout_msecs, request_timeout_msecs;
8952d797eca36f997ec36569e783871b597a9216Timo Sirainen unsigned int warn_timeout_msecs;
2599a77a28bde0653fa090802424469904d518eeTimo Sirainen unsigned int heartbeat_interval_secs, idle_timeout_secs;
07038d3a12a915e98f794566f56a0ed12e0653ebAki Tuomi unsigned int execution_retry_interval_msecs, execution_retry_times;
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen unsigned int page_size;
e8434aad92ea6ff1c915b708294dbd0c7ff5908dMichael M Slusarz in_port_t port;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen CassCluster *cluster;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen CassSession *session;
f0e416aa42058e7ccc0dc6deec0d4f4a19ee6ebeTimo Sirainen CassTimestampGen *timestamp_gen;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen int fd_pipe[2];
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct io *io_pipe;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen ARRAY(struct cassandra_sql_prepared_statement *) pending_prepares;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen ARRAY(struct cassandra_callback *) callbacks;
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen ARRAY(struct cassandra_result *) results;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen unsigned int callback_ids;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen char *metrics_path;
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen struct timeout *to_metrics;
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen uint64_t counters[CASSANDRA_COUNTER_COUNT];
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen
2a24f3565c61cb429d1e428601f153ce53b8bae3Timo Sirainen struct timeval primary_query_last_sent[CASSANDRA_QUERY_TYPE_COUNT];
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen time_t last_fallback_warning[CASSANDRA_QUERY_TYPE_COUNT];
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen unsigned int fallback_failures[CASSANDRA_QUERY_TYPE_COUNT];
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo 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;
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen CassConsistency consistency, fallback_consistency;
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen enum cassandra_query_type query_type;
caf029d36a826106e48b8682f15ea0fc01fdd8f4Timo Sirainen struct timeval page0_start_time, start_time, finish_time;
caf029d36a826106e48b8682f15ea0fc01fdd8f4Timo Sirainen unsigned int row_count, total_row_count, page_num;
18da63ba64987f2157cf8c490b4c4d1efba28733Timo Sirainen cass_int64_t timestamp;
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
b6c9cc2bf7517adcc0b9f98696c61bde321900f6Timo Sirainen bool is_prepared:1;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool query_sent:1;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool finished:1;
caf029d36a826106e48b8682f15ea0fc01fdd8f4Timo Sirainen bool paging_continues: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
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen struct cassandra_sql_statement *stmt;
92a7f5f9bf20c0bd1b1ac309d100f9c144e2b127Timo Sirainen char *query;
af619a25952f5ba550800daf69a119247b1fcda3Timo Sirainen cass_int64_t query_timestamp;
e22ec7998afd426c53c658483ce66b6e404e27c6Timo Sirainen char *error;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool begin_succeeded:1;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool begin_failed:1;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool failed:1;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen};
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainenstruct cassandra_sql_arg {
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen unsigned int column_idx;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen char *value_str;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen unsigned char *value_binary;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen size_t value_binary_size;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen int64_t value_int64;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen};
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainenstruct cassandra_sql_statement {
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen struct sql_statement stmt;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen struct cassandra_sql_prepared_statement *prep;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen CassStatement *cass_stmt;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen ARRAY(struct cassandra_sql_arg) pending_args;
125081bc1cac5f9fe006c36c88ca0535377c461cTimo Sirainen cass_int64_t timestamp;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen struct cassandra_result *result;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen};
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainenstruct cassandra_sql_prepared_statement {
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen struct sql_prepared_statement prep_stmt;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen char *query_template;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen /* NULL, until the prepare is asynchronously finished */
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen const CassPrepared *prepared;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen /* statements waiting for prepare to finish */
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen ARRAY(struct cassandra_sql_statement *) pending_statements;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen /* an error here will cause the prepare to be retried on the next
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen execution attempt. */
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen char *error;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen bool pending;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen};
709ee5a909d482f31611f9e6cc10d893a272e061Timo 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_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
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainenstatic void driver_cassandra_prepare_pending(struct cassandra_db *db);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainenstatic void
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainenprepare_finish_pending_statements(struct cassandra_sql_prepared_statement *prep_stmt);
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainenstatic void driver_cassandra_result_send_query(struct cassandra_result *result);
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{
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen struct cassandra_sql_prepared_statement *const *prep_stmtp;
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen struct cassandra_result *const *resultp;
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen
5f1d689131a75c39f064cbd4202373e7edf78f18Josef 'Jeff' Sipek 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
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen array_foreach(&db->pending_prepares, prep_stmtp) {
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen (*prep_stmtp)->pending = FALSE;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen (*prep_stmtp)->error = i_strdup(error);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen prepare_finish_pending_statements(*prep_stmtp);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen }
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen array_clear(&db->pending_prepares);
709ee5a909d482f31611f9e6cc10d893a272e061Timo 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
7c04ede0da5749691624a1fb962ac29cd0167050Timo Sirainen writing the callback id to the pipe. note that we must not use
7c04ede0da5749691624a1fb962ac29cd0167050Timo Sirainen almost any dovecot functions here because most of them are using
7c04ede0da5749691624a1fb962ac29cd0167050Timo Sirainen data-stack, which isn't thread-safe. especially don't use
7c04ede0da5749691624a1fb962ac29cd0167050Timo Sirainen i_error() here. */
7c04ede0da5749691624a1fb962ac29cd0167050Timo Sirainen if (write_full(cb->db->fd_pipe[1], &cb->id, sizeof(cb->id)) < 0) {
7c04ede0da5749691624a1fb962ac29cd0167050Timo Sirainen const char *str = t_strdup_printf(
7c04ede0da5749691624a1fb962ac29cd0167050Timo Sirainen "cassandra: write(pipe) failed: %s\n",
7c04ede0da5749691624a1fb962ac29cd0167050Timo Sirainen strerror(errno));
7c04ede0da5749691624a1fb962ac29cd0167050Timo Sirainen (void)write_full(STDERR_FILENO, str, strlen(str));
7c04ede0da5749691624a1fb962ac29cd0167050Timo Sirainen }
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 }
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen driver_cassandra_prepare_pending(db);
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{
f7d018e7e0980044e3d537958126e44ef4c45056Timo Sirainen const char *const *args, *key, *value, *error;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen string_t *hosts = t_str_new(64);
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen bool read_fallback_set = FALSE, write_fallback_set = FALSE, delete_fallback_set = FALSE;
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;
7cd055a212d44067e2d94452c05691d696c9f699Timo Sirainen db->connect_timeout_msecs = SQL_CONNECT_TIMEOUT_SECS*1000;
7cd055a212d44067e2d94452c05691d696c9f699Timo Sirainen db->request_timeout_msecs = SQL_QUERY_TIMEOUT_SECS*1000;
8952d797eca36f997ec36569e783871b597a9216Timo Sirainen db->warn_timeout_msecs = CASS_QUERY_DEFAULT_WARN_TIMEOUT_MSECS;
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);
e8434aad92ea6ff1c915b708294dbd0c7ff5908dMichael M Slusarz } else if (strcmp(key, "port") == 0) {
e8434aad92ea6ff1c915b708294dbd0c7ff5908dMichael M Slusarz if (net_str2port(value, &db->port) < 0)
e8434aad92ea6ff1c915b708294dbd0c7ff5908dMichael M Slusarz i_fatal("cassandra: Invalid port: %s", 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);
c72cfe4a2bda39fff3b8a8bd64b31a7cc14d7d11Timo Sirainen } else if (strcmp(key, "user") == 0) {
c72cfe4a2bda39fff3b8a8bd64b31a7cc14d7d11Timo Sirainen i_free(db->user);
c72cfe4a2bda39fff3b8a8bd64b31a7cc14d7d11Timo Sirainen db->user = i_strdup(value);
c72cfe4a2bda39fff3b8a8bd64b31a7cc14d7d11Timo Sirainen } else if (strcmp(key, "password") == 0) {
c72cfe4a2bda39fff3b8a8bd64b31a7cc14d7d11Timo Sirainen i_free(db->password);
c72cfe4a2bda39fff3b8a8bd64b31a7cc14d7d11Timo Sirainen db->password = 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);
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen } else if (strcmp(key, "read_fallback_consistency") == 0) {
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen if (consistency_parse(value, &db->read_fallback_consistency) < 0)
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen i_fatal("cassandra: Unknown read_fallback_consistency: %s", value);
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen read_fallback_set = TRUE;
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);
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen } else if (strcmp(key, "write_fallback_consistency") == 0) {
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen if (consistency_parse(value, &db->write_fallback_consistency) < 0)
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen i_fatal("cassandra: Unknown write_fallback_consistency: %s", value);
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen write_fallback_set = TRUE;
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);
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen } else if (strcmp(key, "delete_fallback_consistency") == 0) {
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen if (consistency_parse(value, &db->delete_fallback_consistency) < 0)
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen i_fatal("cassandra: Unknown delete_fallback_consistency: %s", value);
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen delete_fallback_set = TRUE;
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);
14189e0d0af45ddcb888d026bd8d7e4609912ec5Timo Sirainen } else if (strcmp(key, "debug_queries") == 0) {
14189e0d0af45ddcb888d026bd8d7e4609912ec5Timo Sirainen db->debug_queries = TRUE;
e564ff0581fc44b78badf8da36e68f9f7a27807eTimo Sirainen } else if (strcmp(key, "latency_aware_routing") == 0) {
e564ff0581fc44b78badf8da36e68f9f7a27807eTimo Sirainen db->latency_aware_routing = TRUE;
f9eee365367f37b1692c07db6c23d30243844aaaTimo Sirainen } else if (strcmp(key, "version") == 0) {
f9eee365367f37b1692c07db6c23d30243844aaaTimo Sirainen if (str_to_uint(value, &db->protocol_version) < 0)
f9eee365367f37b1692c07db6c23d30243844aaaTimo Sirainen i_fatal("cassandra: Invalid version: %s", value);
f7d018e7e0980044e3d537958126e44ef4c45056Timo Sirainen } else if (strcmp(key, "num_threads") == 0) {
f7d018e7e0980044e3d537958126e44ef4c45056Timo Sirainen if (str_to_uint(value, &db->num_threads) < 0)
f7d018e7e0980044e3d537958126e44ef4c45056Timo Sirainen i_fatal("cassandra: Invalid num_threads: %s", value);
2599a77a28bde0653fa090802424469904d518eeTimo Sirainen } else if (strcmp(key, "heartbeat_interval") == 0) {
2599a77a28bde0653fa090802424469904d518eeTimo Sirainen if (settings_get_time(value, &db->heartbeat_interval_secs, &error) < 0)
2599a77a28bde0653fa090802424469904d518eeTimo Sirainen i_fatal("cassandra: Invalid heartbeat_interval '%s': %s", value, error);
2599a77a28bde0653fa090802424469904d518eeTimo Sirainen } else if (strcmp(key, "idle_timeout") == 0) {
2599a77a28bde0653fa090802424469904d518eeTimo Sirainen if (settings_get_time(value, &db->idle_timeout_secs, &error) < 0)
2599a77a28bde0653fa090802424469904d518eeTimo Sirainen i_fatal("cassandra: Invalid idle_timeout '%s': %s", value, error);
f7d018e7e0980044e3d537958126e44ef4c45056Timo Sirainen } else if (strcmp(key, "connect_timeout") == 0) {
7cd055a212d44067e2d94452c05691d696c9f699Timo Sirainen if (settings_get_time_msecs(value, &db->connect_timeout_msecs, &error) < 0)
f7d018e7e0980044e3d537958126e44ef4c45056Timo Sirainen i_fatal("cassandra: Invalid connect_timeout '%s': %s", value, error);
f7d018e7e0980044e3d537958126e44ef4c45056Timo Sirainen } else if (strcmp(key, "request_timeout") == 0) {
7cd055a212d44067e2d94452c05691d696c9f699Timo Sirainen if (settings_get_time_msecs(value, &db->request_timeout_msecs, &error) < 0)
f7d018e7e0980044e3d537958126e44ef4c45056Timo Sirainen i_fatal("cassandra: Invalid request_timeout '%s': %s", value, error);
8952d797eca36f997ec36569e783871b597a9216Timo Sirainen } else if (strcmp(key, "warn_timeout") == 0) {
8952d797eca36f997ec36569e783871b597a9216Timo Sirainen if (settings_get_time_msecs(value, &db->warn_timeout_msecs, &error) < 0)
8952d797eca36f997ec36569e783871b597a9216Timo Sirainen i_fatal("cassandra: Invalid warn_timeout '%s': %s", value, error);
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen } else if (strcmp(key, "metrics") == 0) {
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen i_free(db->metrics_path);
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen db->metrics_path = i_strdup(value);
07038d3a12a915e98f794566f56a0ed12e0653ebAki Tuomi } else if (strcmp(key, "execution_retry_interval") == 0) {
07038d3a12a915e98f794566f56a0ed12e0653ebAki Tuomi if (settings_get_time_msecs(value, &db->execution_retry_interval_msecs, &error) < 0)
07038d3a12a915e98f794566f56a0ed12e0653ebAki Tuomi i_fatal("cassandra: Invalid execution_retry_interval '%s': %s", value, error);
07038d3a12a915e98f794566f56a0ed12e0653ebAki Tuomi#ifndef HAVE_CASSANDRA_SPECULATIVE_POLICY
07038d3a12a915e98f794566f56a0ed12e0653ebAki Tuomi i_fatal("cassandra: This cassandra version does not support execution_retry_interval");
07038d3a12a915e98f794566f56a0ed12e0653ebAki Tuomi#endif
07038d3a12a915e98f794566f56a0ed12e0653ebAki Tuomi } else if (strcmp(key, "execution_retry_times") == 0) {
07038d3a12a915e98f794566f56a0ed12e0653ebAki Tuomi if (str_to_uint(value, &db->execution_retry_times) < 0)
07038d3a12a915e98f794566f56a0ed12e0653ebAki Tuomi i_fatal("cassandra: Invalid execution_retry_times %s", value);
07038d3a12a915e98f794566f56a0ed12e0653ebAki Tuomi#ifndef HAVE_CASSANDRA_SPECULATIVE_POLICY
07038d3a12a915e98f794566f56a0ed12e0653ebAki Tuomi i_fatal("cassandra: This cassandra version does not support execution_retry_times");
07038d3a12a915e98f794566f56a0ed12e0653ebAki Tuomi#endif
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen } else if (strcmp(key, "page_size") == 0) {
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen if (str_to_uint(value, &db->page_size) < 0)
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen i_fatal("cassandra: Invalid page_size: %s", value);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen } else {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_fatal("cassandra: Unknown connect string: %s", key);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen if (!read_fallback_set)
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen db->read_fallback_consistency = db->read_consistency;
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen if (!write_fallback_set)
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen db->write_fallback_consistency = db->write_consistency;
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen if (!delete_fallback_set)
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen db->delete_fallback_consistency = db->delete_consistency;
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo 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
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainenstatic void
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainendriver_cassandra_get_metrics_json(struct cassandra_db *db, string_t *dest)
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen{
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen#define ADD_UINT64(_struct, _field) \
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen str_printfa(dest, "\""#_field"\": %llu,", (unsigned long long)metrics._struct._field);
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen#define ADD_DOUBLE(_struct, _field) \
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen str_printfa(dest, "\""#_field"\": %02lf,", metrics._struct._field);
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen CassMetrics metrics;
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen cass_session_get_metrics(db->session, &metrics);
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen str_append(dest, "{ \"requests\": {");
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen ADD_UINT64(requests, min);
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen ADD_UINT64(requests, max);
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen ADD_UINT64(requests, mean);
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen ADD_UINT64(requests, stddev);
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen ADD_UINT64(requests, median);
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen ADD_UINT64(requests, percentile_75th);
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen ADD_UINT64(requests, percentile_95th);
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen ADD_UINT64(requests, percentile_98th);
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen ADD_UINT64(requests, percentile_99th);
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen ADD_UINT64(requests, percentile_999th);
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen ADD_DOUBLE(requests, mean_rate);
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen ADD_DOUBLE(requests, one_minute_rate);
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen ADD_DOUBLE(requests, five_minute_rate);
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen ADD_DOUBLE(requests, fifteen_minute_rate);
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen str_truncate(dest, str_len(dest)-1);
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen str_append(dest, "}, \"stats\": {");
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen ADD_UINT64(stats, total_connections);
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen ADD_UINT64(stats, available_connections);
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen ADD_UINT64(stats, exceeded_pending_requests_water_mark);
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen ADD_UINT64(stats, exceeded_write_bytes_water_mark);
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen str_truncate(dest, str_len(dest)-1);
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen str_append(dest, "}, \"errors\": {");
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen ADD_UINT64(errors, connection_timeouts);
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen ADD_UINT64(errors, pending_request_timeouts);
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen ADD_UINT64(errors, request_timeouts);
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen str_truncate(dest, str_len(dest)-1);
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen str_append(dest, "}, \"queries\": {");
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen for (unsigned int i = 0; i < CASSANDRA_COUNTER_COUNT; i++) {
47a5a7e8296f3b8f2fac9a0659d4de3f2723ba4aMartti Rannanjärvi str_printfa(dest, "\"%s\": %"PRIu64",", counter_names[i],
47a5a7e8296f3b8f2fac9a0659d4de3f2723ba4aMartti Rannanjärvi db->counters[i]);
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen }
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen str_truncate(dest, str_len(dest)-1);
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen str_append(dest, "}}");
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen}
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainenstatic void driver_cassandra_metrics_write(struct cassandra_db *db)
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen{
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen struct var_expand_table tab[] = {
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen { '\0', NULL, NULL }
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen };
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen string_t *path = t_str_new(64);
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen string_t *data;
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen const char *error;
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen int fd;
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen if (var_expand(path, db->metrics_path, tab, &error) <= 0) {
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen i_error("cassandra: Failed to expand metrics_path=%s: %s",
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen db->metrics_path, error);
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen return;
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen }
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen fd = open(str_c(path), O_WRONLY | O_CREAT | O_TRUNC | O_NONBLOCK, 0600);
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen if (fd == -1) {
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen i_error("creat(%s) failed: %m", str_c(path));
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen return;
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen }
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen data = t_str_new(1024);
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen driver_cassandra_get_metrics_json(db, data);
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen if (write_full(fd, str_data(data), str_len(data)) < 0)
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen i_error("write(%s) failed: %m", str_c(path));
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen i_close_fd(&fd);
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen}
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo 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
4d8f538565145fd90eae48df5c4f2ed76e51ca78Timo Sirainen if (db->protocol_version > 0 && db->protocol_version < 4) {
4d8f538565145fd90eae48df5c4f2ed76e51ca78Timo Sirainen /* binding with column indexes requires v4 */
4d8f538565145fd90eae48df5c4f2ed76e51ca78Timo Sirainen db->api.v.prepared_statement_init = NULL;
4d8f538565145fd90eae48df5c4f2ed76e51ca78Timo Sirainen db->api.v.prepared_statement_deinit = NULL;
4d8f538565145fd90eae48df5c4f2ed76e51ca78Timo Sirainen db->api.v.statement_init_prepared = NULL;
4d8f538565145fd90eae48df5c4f2ed76e51ca78Timo Sirainen }
4d8f538565145fd90eae48df5c4f2ed76e51ca78Timo Sirainen
be59f9ae981dbe4bdd264053e9febd4ea5dad75bTimo Sirainen db->timestamp_gen = cass_timestamp_gen_monotonic_new();
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen db->cluster = cass_cluster_new();
f0e416aa42058e7ccc0dc6deec0d4f4a19ee6ebeTimo Sirainen cass_cluster_set_timestamp_gen(db->cluster, db->timestamp_gen);
7cd055a212d44067e2d94452c05691d696c9f699Timo Sirainen cass_cluster_set_connect_timeout(db->cluster, db->connect_timeout_msecs);
7cd055a212d44067e2d94452c05691d696c9f699Timo Sirainen cass_cluster_set_request_timeout(db->cluster, db->request_timeout_msecs);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen cass_cluster_set_contact_points(db->cluster, db->hosts);
c72cfe4a2bda39fff3b8a8bd64b31a7cc14d7d11Timo Sirainen if (db->user != NULL && db->password != NULL)
c72cfe4a2bda39fff3b8a8bd64b31a7cc14d7d11Timo Sirainen cass_cluster_set_credentials(db->cluster, db->user, db->password);
e8434aad92ea6ff1c915b708294dbd0c7ff5908dMichael M Slusarz if (db->port != 0)
e8434aad92ea6ff1c915b708294dbd0c7ff5908dMichael M Slusarz cass_cluster_set_port(db->cluster, db->port);
f9eee365367f37b1692c07db6c23d30243844aaaTimo Sirainen if (db->protocol_version != 0)
f9eee365367f37b1692c07db6c23d30243844aaaTimo Sirainen cass_cluster_set_protocol_version(db->cluster, db->protocol_version);
f7d018e7e0980044e3d537958126e44ef4c45056Timo Sirainen if (db->num_threads != 0)
f7d018e7e0980044e3d537958126e44ef4c45056Timo Sirainen cass_cluster_set_num_threads_io(db->cluster, db->num_threads);
e564ff0581fc44b78badf8da36e68f9f7a27807eTimo Sirainen if (db->latency_aware_routing)
00bcc83b18793b9ec5e5d264480a88bf78b10b33Timo Sirainen cass_cluster_set_latency_aware_routing(db->cluster, cass_true);
2599a77a28bde0653fa090802424469904d518eeTimo Sirainen if (db->heartbeat_interval_secs != 0)
2599a77a28bde0653fa090802424469904d518eeTimo Sirainen cass_cluster_set_connection_heartbeat_interval(db->cluster, db->heartbeat_interval_secs);
2599a77a28bde0653fa090802424469904d518eeTimo Sirainen if (db->idle_timeout_secs != 0)
2599a77a28bde0653fa090802424469904d518eeTimo Sirainen cass_cluster_set_connection_idle_timeout(db->cluster, db->idle_timeout_secs);
07038d3a12a915e98f794566f56a0ed12e0653ebAki Tuomi#ifdef HAVE_CASSANDRA_SPECULATIVE_POLICY
07038d3a12a915e98f794566f56a0ed12e0653ebAki Tuomi if (db->execution_retry_times > 0 && db->execution_retry_interval_msecs > 0)
07038d3a12a915e98f794566f56a0ed12e0653ebAki Tuomi cass_cluster_set_constant_speculative_execution_policy(db->cluster, db->execution_retry_interval_msecs, db->execution_retry_times);
07038d3a12a915e98f794566f56a0ed12e0653ebAki Tuomi#endif
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen db->session = cass_session_new();
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen if (db->metrics_path != NULL)
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen db->to_metrics = timeout_add(1000, driver_cassandra_metrics_write, db);
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen i_array_init(&db->results, 16);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_array_init(&db->callbacks, 16);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen i_array_init(&db->pending_prepares, 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);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen i_assert(array_count(&db->pending_prepares) == 0);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen array_free(&db->pending_prepares);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen cass_session_free(db->session);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen cass_cluster_free(db->cluster);
f0e416aa42058e7ccc0dc6deec0d4f4a19ee6ebeTimo Sirainen cass_timestamp_gen_free(db->timestamp_gen);
0d1b8b6bec79746c5d89d57dd8c1688946bd9237Josef 'Jeff' Sipek timeout_remove(&db->to_metrics);
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen i_free(db->metrics_path);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_free(db->hosts);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_free(db->error);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_free(db->keyspace);
c72cfe4a2bda39fff3b8a8bd64b31a7cc14d7d11Timo Sirainen i_free(db->user);
c72cfe4a2bda39fff3b8a8bd64b31a7cc14d7d11Timo Sirainen i_free(db->password);
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
a5f2707224b10f26e3d478a2b11e8d01f1b8f609Timo Sirainenstatic void driver_cassandra_log_result(struct cassandra_result *result,
caf029d36a826106e48b8682f15ea0fc01fdd8f4Timo Sirainen bool all_pages, long long reply_usecs)
a5f2707224b10f26e3d478a2b11e8d01f1b8f609Timo Sirainen{
a5f2707224b10f26e3d478a2b11e8d01f1b8f609Timo Sirainen struct cassandra_db *db = (struct cassandra_db *)result->api.db;
a5f2707224b10f26e3d478a2b11e8d01f1b8f609Timo Sirainen struct timeval now;
caf029d36a826106e48b8682f15ea0fc01fdd8f4Timo Sirainen unsigned int row_count;
a5f2707224b10f26e3d478a2b11e8d01f1b8f609Timo Sirainen
a5f2707224b10f26e3d478a2b11e8d01f1b8f609Timo Sirainen if (db->log_level < CASS_LOG_DEBUG && !db->debug_queries &&
a5f2707224b10f26e3d478a2b11e8d01f1b8f609Timo Sirainen reply_usecs/1000 < db->warn_timeout_msecs)
a5f2707224b10f26e3d478a2b11e8d01f1b8f609Timo Sirainen return;
a5f2707224b10f26e3d478a2b11e8d01f1b8f609Timo Sirainen
a5f2707224b10f26e3d478a2b11e8d01f1b8f609Timo Sirainen if (gettimeofday(&now, NULL) < 0)
a5f2707224b10f26e3d478a2b11e8d01f1b8f609Timo Sirainen i_fatal("gettimeofday() failed: %m");
caf029d36a826106e48b8682f15ea0fc01fdd8f4Timo Sirainen
caf029d36a826106e48b8682f15ea0fc01fdd8f4Timo Sirainen string_t *str = t_str_new(128);
b6c9cc2bf7517adcc0b9f98696c61bde321900f6Timo Sirainen str_printfa(str, "cassandra: Finished %squery '%s' (",
b6c9cc2bf7517adcc0b9f98696c61bde321900f6Timo Sirainen result->is_prepared ? "prepared " : "", result->query);
18da63ba64987f2157cf8c490b4c4d1efba28733Timo Sirainen if (result->timestamp != 0)
18da63ba64987f2157cf8c490b4c4d1efba28733Timo Sirainen str_printfa(str, "timestamp=%"PRId64", ", result->timestamp);
caf029d36a826106e48b8682f15ea0fc01fdd8f4Timo Sirainen if (all_pages) {
caf029d36a826106e48b8682f15ea0fc01fdd8f4Timo Sirainen str_printfa(str, "%u pages in total, ", result->page_num);
caf029d36a826106e48b8682f15ea0fc01fdd8f4Timo Sirainen row_count = result->total_row_count;
caf029d36a826106e48b8682f15ea0fc01fdd8f4Timo Sirainen } else {
caf029d36a826106e48b8682f15ea0fc01fdd8f4Timo Sirainen if (result->page_num > 0 || result->paging_continues)
caf029d36a826106e48b8682f15ea0fc01fdd8f4Timo Sirainen str_printfa(str, "page %u, ", result->page_num);
caf029d36a826106e48b8682f15ea0fc01fdd8f4Timo Sirainen row_count = result->row_count;
caf029d36a826106e48b8682f15ea0fc01fdd8f4Timo Sirainen }
caf029d36a826106e48b8682f15ea0fc01fdd8f4Timo Sirainen str_printfa(str, "%u rows, %lld+%lld us): %s", row_count, reply_usecs,
caf029d36a826106e48b8682f15ea0fc01fdd8f4Timo Sirainen timeval_diff_usecs(&now, &result->finish_time),
caf029d36a826106e48b8682f15ea0fc01fdd8f4Timo Sirainen result->error != NULL ? result->error : "success");
a5f2707224b10f26e3d478a2b11e8d01f1b8f609Timo Sirainen
a5f2707224b10f26e3d478a2b11e8d01f1b8f609Timo Sirainen if (reply_usecs/1000 >= db->warn_timeout_msecs) {
a5f2707224b10f26e3d478a2b11e8d01f1b8f609Timo Sirainen db->counters[CASSANDRA_COUNTER_TYPE_QUERY_SLOW]++;
caf029d36a826106e48b8682f15ea0fc01fdd8f4Timo Sirainen i_warning("%s", str_c(str));
a5f2707224b10f26e3d478a2b11e8d01f1b8f609Timo Sirainen } else {
caf029d36a826106e48b8682f15ea0fc01fdd8f4Timo Sirainen i_debug("%s", str_c(str));
a5f2707224b10f26e3d478a2b11e8d01f1b8f609Timo Sirainen }
a5f2707224b10f26e3d478a2b11e8d01f1b8f609Timo Sirainen}
a5f2707224b10f26e3d478a2b11e8d01f1b8f609Timo 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;
8952d797eca36f997ec36569e783871b597a9216Timo Sirainen long long reply_usecs;
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
8952d797eca36f997ec36569e783871b597a9216Timo Sirainen reply_usecs = timeval_diff_usecs(&result->finish_time, &result->start_time);
caf029d36a826106e48b8682f15ea0fc01fdd8f4Timo Sirainen driver_cassandra_log_result(result, FALSE, reply_usecs);
caf029d36a826106e48b8682f15ea0fc01fdd8f4Timo Sirainen
caf029d36a826106e48b8682f15ea0fc01fdd8f4Timo Sirainen if (result->page_num > 0 && !result->paging_continues) {
caf029d36a826106e48b8682f15ea0fc01fdd8f4Timo Sirainen /* Multi-page query finishes now. Log a debug/warning summary
caf029d36a826106e48b8682f15ea0fc01fdd8f4Timo Sirainen message about it separate from the per-page messages. */
caf029d36a826106e48b8682f15ea0fc01fdd8f4Timo Sirainen reply_usecs = timeval_diff_usecs(&result->finish_time,
caf029d36a826106e48b8682f15ea0fc01fdd8f4Timo Sirainen &result->page0_start_time);
caf029d36a826106e48b8682f15ea0fc01fdd8f4Timo Sirainen driver_cassandra_log_result(result, TRUE, reply_usecs);
caf029d36a826106e48b8682f15ea0fc01fdd8f4Timo 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);
c69a177207ed18d0f0210347430a60957136bd6cJosef 'Jeff' Sipek 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
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainenstatic void query_resend_with_fallback(struct cassandra_result *result)
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen{
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen struct cassandra_db *db = (struct cassandra_db *)result->api.db;
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen time_t last_warning =
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen ioloop_time - db->last_fallback_warning[result->query_type];
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen if (last_warning >= CASSANDRA_FALLBACK_WARN_INTERVAL_SECS) {
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen i_warning("%s - retrying future %s queries with consistency %s (instead of %s)",
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen result->error, cassandra_query_type_names[result->query_type],
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen cass_consistency_string(result->fallback_consistency),
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen cass_consistency_string(result->consistency));
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen db->last_fallback_warning[result->query_type] = ioloop_time;
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen }
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen i_free_and_null(result->error);
2a24f3565c61cb429d1e428601f153ce53b8bae3Timo Sirainen db->fallback_failures[result->query_type]++;
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen result->consistency = result->fallback_consistency;
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen driver_cassandra_result_send_query(result);
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen}
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainenstatic void counters_inc_error(struct cassandra_db *db, CassError error)
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen{
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen switch (error) {
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen case CASS_ERROR_LIB_NO_HOSTS_AVAILABLE:
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen db->counters[CASSANDRA_COUNTER_TYPE_QUERY_RECV_ERR_NO_HOSTS]++;
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen break;
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen case CASS_ERROR_LIB_REQUEST_QUEUE_FULL:
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen db->counters[CASSANDRA_COUNTER_TYPE_QUERY_RECV_ERR_QUEUE_FULL]++;
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen break;
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen case CASS_ERROR_LIB_REQUEST_TIMED_OUT:
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen db->counters[CASSANDRA_COUNTER_TYPE_QUERY_RECV_ERR_CLIENT_TIMEOUT]++;
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen break;
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen case CASS_ERROR_SERVER_WRITE_TIMEOUT:
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen db->counters[CASSANDRA_COUNTER_TYPE_QUERY_RECV_ERR_SERVER_TIMEOUT]++;
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen break;
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen case CASS_ERROR_SERVER_UNAVAILABLE:
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen db->counters[CASSANDRA_COUNTER_TYPE_QUERY_RECV_ERR_SERVER_UNAVAILABLE]++;
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen break;
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen default:
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen db->counters[CASSANDRA_COUNTER_TYPE_QUERY_RECV_ERR_OTHER]++;
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen break;
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen }
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen}
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic void query_callback(CassFuture *future, void *context)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct cassandra_result *result = context;
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen struct cassandra_db *db = (struct cassandra_db *)result->api.db;
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen CassError error = cass_future_error_code(future);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen if (error != CASS_OK) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen const char *errmsg;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen size_t errsize;
e401fa68eb1e7761ffd0b747919d44568555efeeTimo Sirainen int msecs;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen cass_future_error_message(future, &errmsg, &errsize);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_free(result->error);
e401fa68eb1e7761ffd0b747919d44568555efeeTimo Sirainen
e401fa68eb1e7761ffd0b747919d44568555efeeTimo Sirainen msecs = timeval_diff_msecs(&ioloop_timeval, &result->start_time);
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen counters_inc_error(db, error);
0098ac3b6dcd8ef6ac20f87a8285da201db75a01Timo Sirainen /* Timeouts bring uncertainty whether the query succeeded or
0098ac3b6dcd8ef6ac20f87a8285da201db75a01Timo Sirainen not. Also _SERVER_UNAVAILABLE could have actually written
0098ac3b6dcd8ef6ac20f87a8285da201db75a01Timo Sirainen enough copies of the data for the query to succeed. */
b8eb3211af2987d6e8f0d416156171fbd74f0737Timo Sirainen result->api.error_type = error == CASS_ERROR_SERVER_WRITE_TIMEOUT ||
0098ac3b6dcd8ef6ac20f87a8285da201db75a01Timo Sirainen error == CASS_ERROR_SERVER_UNAVAILABLE ||
b8eb3211af2987d6e8f0d416156171fbd74f0737Timo Sirainen error == CASS_ERROR_LIB_REQUEST_TIMED_OUT ?
5d9ecbcec051b570d29b8f433d6b26d8435236fdTimo Sirainen SQL_RESULT_ERROR_TYPE_WRITE_UNCERTAIN :
5d9ecbcec051b570d29b8f433d6b26d8435236fdTimo Sirainen SQL_RESULT_ERROR_TYPE_UNKNOWN;
caf029d36a826106e48b8682f15ea0fc01fdd8f4Timo Sirainen result->error = i_strdup_printf("Query '%s' failed: %.*s (in %u.%03u secs%s)",
caf029d36a826106e48b8682f15ea0fc01fdd8f4Timo Sirainen result->query, (int)errsize, errmsg, msecs/1000, msecs%1000,
caf029d36a826106e48b8682f15ea0fc01fdd8f4Timo Sirainen result->page_num == 0 ? "" : t_strdup_printf(", page %u", result->page_num));
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen
2522acb523343dd37bf788747d86d9470fc08025Timo Sirainen /* unavailable = cassandra server knows that there aren't
0098ac3b6dcd8ef6ac20f87a8285da201db75a01Timo Sirainen enough nodes available. "All hosts in current policy
0098ac3b6dcd8ef6ac20f87a8285da201db75a01Timo Sirainen attempted and were either unavailable or failed"
2522acb523343dd37bf788747d86d9470fc08025Timo Sirainen
b394d41ad4da0e2e7b8bfafccf3b4f3e9ac26ad1Timo Sirainen no hosts available = The client library couldn't connect to
b394d41ad4da0e2e7b8bfafccf3b4f3e9ac26ad1Timo Sirainen enough cassanra nodes. Error message is the same as for
b394d41ad4da0e2e7b8bfafccf3b4f3e9ac26ad1Timo Sirainen "unavailable".
b394d41ad4da0e2e7b8bfafccf3b4f3e9ac26ad1Timo Sirainen
2522acb523343dd37bf788747d86d9470fc08025Timo Sirainen write timeout = cassandra server couldn't reach all the
2522acb523343dd37bf788747d86d9470fc08025Timo Sirainen needed nodes. this may be because it hasn't yet detected
2522acb523343dd37bf788747d86d9470fc08025Timo Sirainen that the servers are down, or because the servers are just
2522acb523343dd37bf788747d86d9470fc08025Timo Sirainen too busy. we'll try the fallback consistency to avoid
2522acb523343dd37bf788747d86d9470fc08025Timo Sirainen unnecessary temporary errors. */
2522acb523343dd37bf788747d86d9470fc08025Timo Sirainen if ((error == CASS_ERROR_SERVER_UNAVAILABLE ||
b394d41ad4da0e2e7b8bfafccf3b4f3e9ac26ad1Timo Sirainen error == CASS_ERROR_LIB_NO_HOSTS_AVAILABLE ||
2522acb523343dd37bf788747d86d9470fc08025Timo Sirainen error == CASS_ERROR_SERVER_WRITE_TIMEOUT) &&
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen result->fallback_consistency != result->consistency) {
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen /* retry with fallback consistency */
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen query_resend_with_fallback(result);
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen return;
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen result_finish(result);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen db->counters[CASSANDRA_COUNTER_TYPE_QUERY_RECV_OK]++;
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen if (result->fallback_consistency != result->consistency) {
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen /* non-fallback query finished successfully. if there had been
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen any fallbacks, reset them. */
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen db->fallback_failures[result->query_type] = 0;
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen }
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo 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
a5f2707224b10f26e3d478a2b11e8d01f1b8f609Timo Sirainenstatic void driver_cassandra_init_statement(struct cassandra_result *result)
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen{
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen struct cassandra_db *db = (struct cassandra_db *)result->api.db;
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen cass_statement_set_consistency(result->statement, result->consistency);
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen
07038d3a12a915e98f794566f56a0ed12e0653ebAki Tuomi#ifdef HAVE_CASSANDRA_SPECULATIVE_POLICY
07038d3a12a915e98f794566f56a0ed12e0653ebAki Tuomi cass_statement_set_is_idempotent(result->statement, cass_true);
07038d3a12a915e98f794566f56a0ed12e0653ebAki Tuomi#endif
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen if (db->page_size > 0)
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen cass_statement_set_paging_size(result->statement, db->page_size);
a5f2707224b10f26e3d478a2b11e8d01f1b8f609Timo Sirainen}
a5f2707224b10f26e3d478a2b11e8d01f1b8f609Timo Sirainen
a5f2707224b10f26e3d478a2b11e8d01f1b8f609Timo Sirainenstatic void driver_cassandra_result_send_query(struct cassandra_result *result)
a5f2707224b10f26e3d478a2b11e8d01f1b8f609Timo Sirainen{
a5f2707224b10f26e3d478a2b11e8d01f1b8f609Timo Sirainen struct cassandra_db *db = (struct cassandra_db *)result->api.db;
a5f2707224b10f26e3d478a2b11e8d01f1b8f609Timo Sirainen CassFuture *future;
a5f2707224b10f26e3d478a2b11e8d01f1b8f609Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen i_assert(result->statement != NULL);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
a5f2707224b10f26e3d478a2b11e8d01f1b8f609Timo Sirainen db->counters[CASSANDRA_COUNTER_TYPE_QUERY_SENT]++;
214aff73cd9809446bef169b216d6eb5a81079d8Timo Sirainen if (result->query_type != CASSANDRA_QUERY_TYPE_READ_MORE)
214aff73cd9809446bef169b216d6eb5a81079d8Timo Sirainen driver_cassandra_init_statement(result);
a5f2707224b10f26e3d478a2b11e8d01f1b8f609Timo Sirainen
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen future = cass_session_execute(db->session, result->statement);
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen driver_cassandra_set_callback(future, db, query_callback, result);
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen}
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainenstatic bool
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainendriver_cassandra_want_fallback_query(struct cassandra_result *result)
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen{
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen struct cassandra_db *db = (struct cassandra_db *)result->api.db;
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen unsigned int failure_count = db->fallback_failures[result->query_type];
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen unsigned int i, msecs = CASSANDRA_FALLBACK_FIRST_RETRY_MSECS;
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen struct timeval tv;
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen if (failure_count == 0)
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen return FALSE;
2a24f3565c61cb429d1e428601f153ce53b8bae3Timo Sirainen /* double the retries every time. */
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen for (i = 1; i < failure_count; i++) {
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen msecs *= 2;
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen if (msecs >= CASSANDRA_FALLBACK_MAX_RETRY_MSECS) {
a8a5f2f8ccc134dcc7b61ea48664c3381db4a1aaTimo Sirainen msecs = CASSANDRA_FALLBACK_MAX_RETRY_MSECS;
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen break;
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen }
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen }
2a24f3565c61cb429d1e428601f153ce53b8bae3Timo Sirainen /* If last primary query sent timestamp + msecs is older than current
2a24f3565c61cb429d1e428601f153ce53b8bae3Timo Sirainen time, we need to retry the primary query. Note that this practically
2a24f3565c61cb429d1e428601f153ce53b8bae3Timo Sirainen prevents multiple primary queries from being attempted
2a24f3565c61cb429d1e428601f153ce53b8bae3Timo Sirainen simultaneously, because the caller updates primary_query_last_sent
2a24f3565c61cb429d1e428601f153ce53b8bae3Timo Sirainen immediately when returning.
2a24f3565c61cb429d1e428601f153ce53b8bae3Timo Sirainen
2a24f3565c61cb429d1e428601f153ce53b8bae3Timo Sirainen The only time when multiple primary queries can be running in
2a24f3565c61cb429d1e428601f153ce53b8bae3Timo Sirainen parallel is when the earlier query is being slow and hasn't finished
2a24f3565c61cb429d1e428601f153ce53b8bae3Timo Sirainen early enough. This could even be a wanted feature, since while the
2a24f3565c61cb429d1e428601f153ce53b8bae3Timo Sirainen first query might have to wait for a timeout, Cassandra could have
2a24f3565c61cb429d1e428601f153ce53b8bae3Timo Sirainen been fixed in the meantime and the second query finishes
2a24f3565c61cb429d1e428601f153ce53b8bae3Timo Sirainen successfully. */
2a24f3565c61cb429d1e428601f153ce53b8bae3Timo Sirainen tv = db->primary_query_last_sent[result->query_type];
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen timeval_add_msecs(&tv, msecs);
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen return timeval_cmp(&ioloop_timeval, &tv) < 0;
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen}
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo 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;
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
caf029d36a826106e48b8682f15ea0fc01fdd8f4Timo Sirainen if (result->page0_start_time.tv_sec == 0)
caf029d36a826106e48b8682f15ea0fc01fdd8f4Timo Sirainen result->page0_start_time = ioloop_timeval;
de5f478d9e7ae7b8e58082e0b30b6ce1f034236aTimo Sirainen result->start_time = ioloop_timeval;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen result->row_pool = pool_alloconly_create("cassandra result", 512);
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen switch (result->query_type) {
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen case CASSANDRA_QUERY_TYPE_READ:
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen result->consistency = db->read_consistency;
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen result->fallback_consistency = db->read_fallback_consistency;
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen break;
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen case CASSANDRA_QUERY_TYPE_READ_MORE:
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen /* consistency is already set and we don't want to fallback
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen at this point anymore. */
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen result->fallback_consistency = result->consistency;
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen break;
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen case CASSANDRA_QUERY_TYPE_WRITE:
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen result->consistency = db->write_consistency;
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen result->fallback_consistency = db->write_fallback_consistency;
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen break;
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen case CASSANDRA_QUERY_TYPE_DELETE:
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen result->consistency = db->delete_consistency;
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen result->fallback_consistency = db->delete_fallback_consistency;
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen break;
8a6afcd8a6d9ed69626add85a7b75105ee3cb6a1Timo Sirainen case CASSANDRA_QUERY_TYPE_COUNT:
8a6afcd8a6d9ed69626add85a7b75105ee3cb6a1Timo Sirainen i_unreached();
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen }
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen if (driver_cassandra_want_fallback_query(result))
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen result->consistency = result->fallback_consistency;
2a24f3565c61cb429d1e428601f153ce53b8bae3Timo Sirainen else
2a24f3565c61cb429d1e428601f153ce53b8bae3Timo Sirainen db->primary_query_last_sent[result->query_type] = ioloop_timeval;
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen driver_cassandra_result_send_query(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++) {
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen if (!results[i]->query_sent && results[i]->statement != NULL) {
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
a5f2707224b10f26e3d478a2b11e8d01f1b8f609Timo Sirainenstatic struct cassandra_result *
a5f2707224b10f26e3d478a2b11e8d01f1b8f609Timo Sirainendriver_cassandra_query_init(struct cassandra_db *db, const char *query,
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen enum cassandra_query_type query_type,
b6c9cc2bf7517adcc0b9f98696c61bde321900f6Timo Sirainen bool is_prepared,
ce74395e2a932342e04fb682395bcce111574969Timo Sirainen sql_query_callback_t *callback, void *context)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct cassandra_result *result;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen result = i_new(struct cassandra_result, 1);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen result->api = driver_cassandra_result;
a5f2707224b10f26e3d478a2b11e8d01f1b8f609Timo Sirainen result->api.db = &db->api;
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);
b6c9cc2bf7517adcc0b9f98696c61bde321900f6Timo Sirainen result->is_prepared = is_prepared;
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen array_append(&db->results, &result, 1);
a5f2707224b10f26e3d478a2b11e8d01f1b8f609Timo Sirainen return result;
a5f2707224b10f26e3d478a2b11e8d01f1b8f609Timo Sirainen}
a5f2707224b10f26e3d478a2b11e8d01f1b8f609Timo Sirainen
a5f2707224b10f26e3d478a2b11e8d01f1b8f609Timo Sirainenstatic void
a5f2707224b10f26e3d478a2b11e8d01f1b8f609Timo Sirainendriver_cassandra_query_full(struct sql_db *_db, const char *query,
a5f2707224b10f26e3d478a2b11e8d01f1b8f609Timo Sirainen enum cassandra_query_type query_type,
a5f2707224b10f26e3d478a2b11e8d01f1b8f609Timo Sirainen sql_query_callback_t *callback, void *context)
a5f2707224b10f26e3d478a2b11e8d01f1b8f609Timo Sirainen{
a5f2707224b10f26e3d478a2b11e8d01f1b8f609Timo Sirainen struct cassandra_db *db = (struct cassandra_db *)_db;
a5f2707224b10f26e3d478a2b11e8d01f1b8f609Timo Sirainen struct cassandra_result *result;
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen
b6c9cc2bf7517adcc0b9f98696c61bde321900f6Timo Sirainen result = driver_cassandra_query_init(db, query, query_type, FALSE,
a5f2707224b10f26e3d478a2b11e8d01f1b8f609Timo Sirainen callback, context);
a2c4998f6e1fe5ea9a2c9bafd678cd4b6b064a0bTimo Sirainen result->statement = cass_statement_new(query, 0);
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 *
8759c5d294e762fe9c5b7b19f3842b23aaaaf4ebTimo Sirainendriver_cassandra_sync_query(struct cassandra_db *db, const char *query,
8759c5d294e762fe9c5b7b19f3842b23aaaaf4ebTimo Sirainen enum cassandra_query_type query_type)
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
8759c5d294e762fe9c5b7b19f3842b23aaaaf4ebTimo Sirainen driver_cassandra_query_full(&db->api, query, query_type,
8759c5d294e762fe9c5b7b19f3842b23aaaaf4ebTimo Sirainen 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);
8759c5d294e762fe9c5b7b19f3842b23aaaaf4ebTimo Sirainen result = driver_cassandra_sync_query(db, query,
8759c5d294e762fe9c5b7b19f3842b23aaaaf4ebTimo Sirainen CASSANDRA_QUERY_TYPE_READ);
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;
b096ecf3188cdb9162460ed7ae885c03f3161462Timo Sirainen const char *type;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
23bdbb7b1831785c6ba6df190f6369da882d2b9dTimo Sirainen if (cass_value_is_null(value) != 0) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen *str_r = NULL;
0cb80fbd739a9a9b3618a5595b34458a0a994d9bTimo Sirainen *len_r = 0;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return 0;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b096ecf3188cdb9162460ed7ae885c03f3161462Timo Sirainen switch (cass_data_type_type(cass_value_data_type(value))) {
b096ecf3188cdb9162460ed7ae885c03f3161462Timo Sirainen case CASS_VALUE_TYPE_INT: {
b096ecf3188cdb9162460ed7ae885c03f3161462Timo Sirainen cass_int32_t num;
b096ecf3188cdb9162460ed7ae885c03f3161462Timo Sirainen
b096ecf3188cdb9162460ed7ae885c03f3161462Timo Sirainen rc = cass_value_get_int32(value, &num);
b096ecf3188cdb9162460ed7ae885c03f3161462Timo Sirainen if (rc == CASS_OK) {
b096ecf3188cdb9162460ed7ae885c03f3161462Timo Sirainen const char *str = t_strdup_printf("%d", num);
b096ecf3188cdb9162460ed7ae885c03f3161462Timo Sirainen output_size = strlen(str);
b096ecf3188cdb9162460ed7ae885c03f3161462Timo Sirainen output = (const void *)str;
b096ecf3188cdb9162460ed7ae885c03f3161462Timo Sirainen }
b096ecf3188cdb9162460ed7ae885c03f3161462Timo Sirainen type = "int32";
b096ecf3188cdb9162460ed7ae885c03f3161462Timo Sirainen break;
b096ecf3188cdb9162460ed7ae885c03f3161462Timo Sirainen }
344c4411571e25dcf2f974c07c116a6160c77338Timo Sirainen case CASS_VALUE_TYPE_TIMESTAMP:
769cbb608e9ed620063708aff49fc1b6e924394aTimo Sirainen case CASS_VALUE_TYPE_BIGINT: {
769cbb608e9ed620063708aff49fc1b6e924394aTimo Sirainen cass_int64_t num;
769cbb608e9ed620063708aff49fc1b6e924394aTimo Sirainen
769cbb608e9ed620063708aff49fc1b6e924394aTimo Sirainen rc = cass_value_get_int64(value, &num);
769cbb608e9ed620063708aff49fc1b6e924394aTimo Sirainen if (rc == CASS_OK) {
769cbb608e9ed620063708aff49fc1b6e924394aTimo Sirainen const char *str = t_strdup_printf("%lld", (long long)num);
769cbb608e9ed620063708aff49fc1b6e924394aTimo Sirainen output_size = strlen(str);
769cbb608e9ed620063708aff49fc1b6e924394aTimo Sirainen output = (const void *)str;
769cbb608e9ed620063708aff49fc1b6e924394aTimo Sirainen }
769cbb608e9ed620063708aff49fc1b6e924394aTimo Sirainen type = "int64";
769cbb608e9ed620063708aff49fc1b6e924394aTimo Sirainen break;
769cbb608e9ed620063708aff49fc1b6e924394aTimo Sirainen }
b096ecf3188cdb9162460ed7ae885c03f3161462Timo Sirainen default:
b096ecf3188cdb9162460ed7ae885c03f3161462Timo Sirainen rc = cass_value_get_bytes(value, &output, &output_size);
b096ecf3188cdb9162460ed7ae885c03f3161462Timo Sirainen type = "bytes";
b096ecf3188cdb9162460ed7ae885c03f3161462Timo Sirainen break;
b096ecf3188cdb9162460ed7ae885c03f3161462Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (rc != CASS_OK) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_free(result->error);
b096ecf3188cdb9162460ed7ae885c03f3161462Timo Sirainen result->error = i_strdup_printf("Couldn't get value as %s: %s",
b096ecf3188cdb9162460ed7ae885c03f3161462Timo Sirainen type, cass_error_desc(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
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainenstatic int driver_cassandra_result_next_page(struct cassandra_result *result)
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen{
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen struct cassandra_db *db = (struct cassandra_db *)result->api.db;
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen if (db->page_size == 0) {
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen /* no paging */
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen return 0;
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen }
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen if (cass_result_has_more_pages(result->result) == cass_false)
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen return 0;
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen /* callers that don't support sql_query_more() will still get a useful
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen error message. */
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen i_free(result->error);
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen result->error = i_strdup("Paged query has more results, but not supported by the caller");
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen return SQL_RESULT_NEXT_MORE;
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen}
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo 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
23bdbb7b1831785c6ba6df190f6369da882d2b9dTimo Sirainen if (cass_iterator_next(result->iterator) == 0)
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen return driver_cassandra_result_next_page(result);
37e8420b32a0fa3442c405616980e45beb494104Timo Sirainen result->row_count++;
caf029d36a826106e48b8682f15ea0fc01fdd8f4Timo Sirainen result->total_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
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainenstatic void
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainendriver_cassandra_result_more(struct sql_result **_result, bool async,
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen sql_query_callback_t *callback, void *context)
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen{
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen struct cassandra_db *db = (struct cassandra_db *)(*_result)->db;
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen struct cassandra_result *new_result;
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen struct cassandra_result *old_result =
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen (struct cassandra_result *)*_result;
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen /* Initialize the next page as a new sql_result */
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen new_result = driver_cassandra_query_init(db, old_result->query,
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen CASSANDRA_QUERY_TYPE_READ_MORE,
b6c9cc2bf7517adcc0b9f98696c61bde321900f6Timo Sirainen old_result->is_prepared,
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen callback, context);
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen /* Preserve the statement and update its paging state */
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen new_result->statement = old_result->statement;
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen old_result->statement = NULL;
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen cass_statement_set_paging_state(new_result->statement,
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen old_result->result);
caf029d36a826106e48b8682f15ea0fc01fdd8f4Timo Sirainen old_result->paging_continues = TRUE;
b07a3abc4cc692661f5afd2fb654acb687884613Timo Sirainen /* The caller did support paging. Clear out the "...not supported by
b07a3abc4cc692661f5afd2fb654acb687884613Timo Sirainen the caller" error text, so it won't be in the debug log output. */
b07a3abc4cc692661f5afd2fb654acb687884613Timo Sirainen i_free_and_null(old_result->error);
caf029d36a826106e48b8682f15ea0fc01fdd8f4Timo Sirainen
fa649b1fa91fa7aed260fe5d6da8d4d7b42ed3fbTimo Sirainen new_result->timestamp = old_result->timestamp;
214aff73cd9809446bef169b216d6eb5a81079d8Timo Sirainen new_result->consistency = old_result->consistency;
caf029d36a826106e48b8682f15ea0fc01fdd8f4Timo Sirainen new_result->page_num = old_result->page_num + 1;
caf029d36a826106e48b8682f15ea0fc01fdd8f4Timo Sirainen new_result->page0_start_time = old_result->page0_start_time;
caf029d36a826106e48b8682f15ea0fc01fdd8f4Timo Sirainen new_result->total_row_count = old_result->total_row_count;
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen sql_result_unref(*_result);
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen *_result = NULL;
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen if (async)
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen (void)driver_cassandra_send_query(new_result);
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen else {
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen i_assert(db->api.state == SQL_DB_STATE_IDLE);
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen driver_cassandra_sync_init(db);
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen (void)driver_cassandra_send_query(new_result);
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen if (new_result->result == NULL) {
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen db->io_pipe = io_loop_move_io(&db->io_pipe);
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen io_loop_run(db->ioloop);
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen }
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen driver_cassandra_sync_deinit(db);
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen callback(&new_result->api, context);
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen }
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen}
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo 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 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
92a7f5f9bf20c0bd1b1ac309d100f9c144e2b127Timo Sirainen i_free(ctx->query);
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;
bb2b3656ef7635acc374f7fc19b25aeeb454ae95Timo Sirainen struct sql_commit_result commit_result;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&commit_result);
bb2b3656ef7635acc374f7fc19b25aeeb454ae95Timo Sirainen if (sql_result_next_row(result) < 0) {
bb2b3656ef7635acc374f7fc19b25aeeb454ae95Timo Sirainen commit_result.error = sql_result_get_error(result);
bb2b3656ef7635acc374f7fc19b25aeeb454ae95Timo Sirainen commit_result.error_type = sql_result_get_error_type(result);
bb2b3656ef7635acc374f7fc19b25aeeb454ae95Timo Sirainen }
bb2b3656ef7635acc374f7fc19b25aeeb454ae95Timo Sirainen ctx->callback(&commit_result, 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;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen struct cassandra_db *db = (struct cassandra_db *)_ctx->db;
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen enum cassandra_query_type query_type;
bb2b3656ef7635acc374f7fc19b25aeeb454ae95Timo Sirainen struct sql_commit_result result;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&result);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen ctx->callback = callback;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen ctx->context = context;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen if (ctx->failed || (ctx->query == NULL && ctx->stmt == NULL)) {
bb2b3656ef7635acc374f7fc19b25aeeb454ae95Timo Sirainen if (ctx->failed)
bb2b3656ef7635acc374f7fc19b25aeeb454ae95Timo Sirainen result.error = ctx->error;
bb2b3656ef7635acc374f7fc19b25aeeb454ae95Timo Sirainen
bb2b3656ef7635acc374f7fc19b25aeeb454ae95Timo Sirainen callback(&result, context);
6b4b3e5fe8d9e84f4b1356ee898ca76996a11fe1Timo Sirainen driver_cassandra_transaction_unref(&ctx);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen return;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen }
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen /* just a single query, send it */
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen const char *query = ctx->query != NULL ?
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen ctx->query : sql_statement_get_query(&ctx->stmt->stmt);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen if (strncasecmp(query, "DELETE ", 7) == 0)
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen query_type = CASSANDRA_QUERY_TYPE_DELETE;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen else
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen query_type = CASSANDRA_QUERY_TYPE_WRITE;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen if (ctx->query != NULL) {
af619a25952f5ba550800daf69a119247b1fcda3Timo Sirainen struct cassandra_result *cass_result;
af619a25952f5ba550800daf69a119247b1fcda3Timo Sirainen
af619a25952f5ba550800daf69a119247b1fcda3Timo Sirainen cass_result = driver_cassandra_query_init(db, query, query_type,
af619a25952f5ba550800daf69a119247b1fcda3Timo Sirainen FALSE, transaction_commit_callback, ctx);
af619a25952f5ba550800daf69a119247b1fcda3Timo Sirainen cass_result->statement = cass_statement_new(query, 0);
af619a25952f5ba550800daf69a119247b1fcda3Timo Sirainen if (ctx->query_timestamp != 0) {
af619a25952f5ba550800daf69a119247b1fcda3Timo Sirainen cass_result->timestamp = ctx->query_timestamp;
af619a25952f5ba550800daf69a119247b1fcda3Timo Sirainen cass_statement_set_timestamp(cass_result->statement,
af619a25952f5ba550800daf69a119247b1fcda3Timo Sirainen ctx->query_timestamp);
af619a25952f5ba550800daf69a119247b1fcda3Timo Sirainen }
af619a25952f5ba550800daf69a119247b1fcda3Timo Sirainen (void)driver_cassandra_send_query(cass_result);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen } else {
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen ctx->stmt->result =
b6c9cc2bf7517adcc0b9f98696c61bde321900f6Timo Sirainen driver_cassandra_query_init(db, query, query_type, TRUE,
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen transaction_commit_callback, ctx);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen if (ctx->stmt->cass_stmt == NULL) {
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen /* wait for prepare to finish */
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen } else {
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen ctx->stmt->result->statement = ctx->stmt->cass_stmt;
fa649b1fa91fa7aed260fe5d6da8d4d7b42ed3fbTimo Sirainen ctx->stmt->result->timestamp = ctx->stmt->timestamp;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen (void)driver_cassandra_send_query(ctx->stmt->result);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen pool_unref(&ctx->stmt->stmt.pool);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
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;
8759c5d294e762fe9c5b7b19f3842b23aaaaf4ebTimo Sirainen struct cassandra_db *db = (struct cassandra_db *)_ctx->db;
b650f04c3b2e7dea2295bdbe3239eb82ec03ada0Timo Sirainen struct sql_result *result = NULL;
8759c5d294e762fe9c5b7b19f3842b23aaaaf4ebTimo Sirainen enum cassandra_query_type query_type;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
92a7f5f9bf20c0bd1b1ac309d100f9c144e2b127Timo Sirainen /* just a single query, send it */
92a7f5f9bf20c0bd1b1ac309d100f9c144e2b127Timo Sirainen if (strncasecmp(ctx->query, "DELETE ", 7) == 0)
92a7f5f9bf20c0bd1b1ac309d100f9c144e2b127Timo Sirainen query_type = CASSANDRA_QUERY_TYPE_DELETE;
92a7f5f9bf20c0bd1b1ac309d100f9c144e2b127Timo Sirainen else
92a7f5f9bf20c0bd1b1ac309d100f9c144e2b127Timo Sirainen query_type = CASSANDRA_QUERY_TYPE_WRITE;
92a7f5f9bf20c0bd1b1ac309d100f9c144e2b127Timo Sirainen driver_cassandra_sync_init(db);
92a7f5f9bf20c0bd1b1ac309d100f9c144e2b127Timo Sirainen result = driver_cassandra_sync_query(db, ctx->query, query_type);
92a7f5f9bf20c0bd1b1ac309d100f9c144e2b127Timo Sirainen driver_cassandra_sync_deinit(db);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
92a7f5f9bf20c0bd1b1ac309d100f9c144e2b127Timo Sirainen if (sql_result_next_row(result) < 0)
92a7f5f9bf20c0bd1b1ac309d100f9c144e2b127Timo Sirainen transaction_set_failed(ctx, sql_result_get_error(result));
92a7f5f9bf20c0bd1b1ac309d100f9c144e2b127Timo 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
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen if (ctx->stmt != NULL) {
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen /* nothing should be using this - don't bother implementing */
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen i_panic("cassandra: sql_transaction_commit_s() not supported for prepared statements");
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen }
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
92a7f5f9bf20c0bd1b1ac309d100f9c144e2b127Timo Sirainen if (ctx->query != NULL && !ctx->failed)
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
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen if (ctx->query != NULL || ctx->stmt != NULL) {
92a7f5f9bf20c0bd1b1ac309d100f9c144e2b127Timo Sirainen transaction_set_failed(ctx, "Multiple changes in transaction not supported");
92a7f5f9bf20c0bd1b1ac309d100f9c144e2b127Timo Sirainen return;
92a7f5f9bf20c0bd1b1ac309d100f9c144e2b127Timo Sirainen }
92a7f5f9bf20c0bd1b1ac309d100f9c144e2b127Timo Sirainen ctx->query = i_strdup(query);
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
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainenstatic CassError
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainendriver_cassandra_bind_int(struct cassandra_sql_statement *stmt,
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen unsigned int column_idx, int64_t value)
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen{
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen const CassDataType *data_type;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen CassValueType value_type;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
27688ec19adf1af07f9a996620caba05bb80acfbTimo Sirainen i_assert(stmt->prep != NULL);
27688ec19adf1af07f9a996620caba05bb80acfbTimo Sirainen
27688ec19adf1af07f9a996620caba05bb80acfbTimo Sirainen /* statements require exactly correct value type */
27688ec19adf1af07f9a996620caba05bb80acfbTimo Sirainen data_type = cass_prepared_parameter_data_type(stmt->prep->prepared, column_idx);
27688ec19adf1af07f9a996620caba05bb80acfbTimo Sirainen value_type = cass_data_type_type(data_type);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen switch (value_type) {
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen case CASS_VALUE_TYPE_INT:
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen if (value < -2147483648 || value > 2147483647)
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen return CASS_ERROR_LIB_INVALID_VALUE_TYPE;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen return cass_statement_bind_int32(stmt->cass_stmt, column_idx, value);
344c4411571e25dcf2f974c07c116a6160c77338Timo Sirainen case CASS_VALUE_TYPE_TIMESTAMP:
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen case CASS_VALUE_TYPE_BIGINT:
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen return cass_statement_bind_int64(stmt->cass_stmt, column_idx, value);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen case CASS_VALUE_TYPE_SMALL_INT:
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen if (value < -32768 || value > 32767)
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen return CASS_ERROR_LIB_INVALID_VALUE_TYPE;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen return cass_statement_bind_int16(stmt->cass_stmt, column_idx, value);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen case CASS_VALUE_TYPE_TINY_INT:
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen if (value < -128 || value > 127)
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen return CASS_ERROR_LIB_INVALID_VALUE_TYPE;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen return cass_statement_bind_int8(stmt->cass_stmt, column_idx, value);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen default:
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen return CASS_ERROR_LIB_INVALID_VALUE_TYPE;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen }
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen}
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainenstatic void prepare_finish_arg(struct cassandra_sql_statement *stmt,
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen const struct cassandra_sql_arg *arg)
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen{
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen CassError rc;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen if (arg->value_str != NULL) {
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen rc = cass_statement_bind_string(stmt->cass_stmt, arg->column_idx,
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen arg->value_str);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen } else if (arg->value_binary != NULL) {
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen rc = cass_statement_bind_bytes(stmt->cass_stmt, arg->column_idx,
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen arg->value_binary,
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen arg->value_binary_size);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen } else {
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen rc = driver_cassandra_bind_int(stmt, arg->column_idx,
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen arg->value_int64);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen }
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen if (rc != CASS_OK) {
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen i_error("cassandra: Statement '%s': Failed to bind column %u: %s",
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen stmt->stmt.query_template, arg->column_idx,
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen cass_error_desc(rc));
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen }
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen}
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainenstatic void prepare_finish_statement(struct cassandra_sql_statement *stmt)
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen{
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen const struct cassandra_sql_arg *arg;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen if (stmt->prep->prepared == NULL) {
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen i_assert(stmt->prep->error != NULL);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen if (stmt->result != NULL) {
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen stmt->result->error = i_strdup(stmt->prep->error);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen result_finish(stmt->result);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen }
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen return;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen }
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen stmt->cass_stmt = cass_prepared_bind(stmt->prep->prepared);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
125081bc1cac5f9fe006c36c88ca0535377c461cTimo Sirainen if (stmt->timestamp != 0)
125081bc1cac5f9fe006c36c88ca0535377c461cTimo Sirainen cass_statement_set_timestamp(stmt->cass_stmt, stmt->timestamp);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen if (array_is_created(&stmt->pending_args)) {
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen array_foreach(&stmt->pending_args, arg)
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen prepare_finish_arg(stmt, arg);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen }
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen if (stmt->result != NULL) {
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen stmt->result->statement = stmt->cass_stmt;
18da63ba64987f2157cf8c490b4c4d1efba28733Timo Sirainen stmt->result->timestamp = stmt->timestamp;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen (void)driver_cassandra_send_query(stmt->result);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen pool_unref(&stmt->stmt.pool);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen }
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen}
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainenstatic void
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainenprepare_finish_pending_statements(struct cassandra_sql_prepared_statement *prep_stmt)
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen{
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen struct cassandra_sql_statement *const *stmtp;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen array_foreach(&prep_stmt->pending_statements, stmtp)
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen prepare_finish_statement(*stmtp);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen array_clear(&prep_stmt->pending_statements);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen}
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainenstatic void prepare_callback(CassFuture *future, void *context)
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen{
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen struct cassandra_sql_prepared_statement *prep_stmt = context;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen CassError error = cass_future_error_code(future);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen if (error != CASS_OK) {
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen const char *errmsg;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen size_t errsize;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen cass_future_error_message(future, &errmsg, &errsize);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen i_free(prep_stmt->error);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen prep_stmt->error = i_strndup(errmsg, errsize);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen } else {
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen prep_stmt->prepared = cass_future_get_prepared(future);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen }
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen prepare_finish_pending_statements(prep_stmt);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen}
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainenstatic void prepare_start(struct cassandra_sql_prepared_statement *prep_stmt)
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen{
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen struct cassandra_db *db = (struct cassandra_db *)prep_stmt->prep_stmt.db;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen CassFuture *future;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen if (!SQL_DB_IS_READY(&db->api)) {
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen if (!prep_stmt->pending) {
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen prep_stmt->pending = TRUE;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen array_append(&db->pending_prepares, &prep_stmt, 1);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen if (sql_connect(&db->api) < 0)
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen i_unreached();
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen }
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen return;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen }
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen /* clear the current error in case we're retrying */
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen i_free_and_null(prep_stmt->error);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen future = cass_session_prepare(db->session, prep_stmt->query_template);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen driver_cassandra_set_callback(future, db, prepare_callback, prep_stmt);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen}
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainenstatic void driver_cassandra_prepare_pending(struct cassandra_db *db)
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen{
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen struct cassandra_sql_prepared_statement *const *prep_stmtp;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen i_assert(SQL_DB_IS_READY(&db->api));
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen array_foreach(&db->pending_prepares, prep_stmtp) {
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen (*prep_stmtp)->pending = FALSE;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen prepare_start(*prep_stmtp);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen }
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen array_clear(&db->pending_prepares);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen}
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainenstatic struct sql_prepared_statement *
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainendriver_cassandra_prepared_statement_init(struct sql_db *db,
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen const char *query_template)
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen{
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen struct cassandra_sql_prepared_statement *prep_stmt =
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen i_new(struct cassandra_sql_prepared_statement, 1);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen prep_stmt->prep_stmt.db = db;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen prep_stmt->query_template = i_strdup(query_template);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen i_array_init(&prep_stmt->pending_statements, 4);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen prepare_start(prep_stmt);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen return &prep_stmt->prep_stmt;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen}
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainenstatic void
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainendriver_cassandra_prepared_statement_deinit(struct sql_prepared_statement *_prep_stmt)
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen{
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen struct cassandra_sql_prepared_statement *prep_stmt =
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen (struct cassandra_sql_prepared_statement *)_prep_stmt;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen i_assert(array_count(&prep_stmt->pending_statements) == 0);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen if (prep_stmt->prepared != NULL)
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen cass_prepared_free(prep_stmt->prepared);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen array_free(&prep_stmt->pending_statements);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen i_free(prep_stmt->query_template);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen i_free(prep_stmt->error);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen i_free(prep_stmt);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen}
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainenstatic struct sql_statement *
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainendriver_cassandra_statement_init(struct sql_db *db ATTR_UNUSED,
27688ec19adf1af07f9a996620caba05bb80acfbTimo Sirainen const char *query_template ATTR_UNUSED)
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen{
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen pool_t pool = pool_alloconly_create("cassandra sql statement", 1024);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen struct cassandra_sql_statement *stmt =
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen p_new(pool, struct cassandra_sql_statement, 1);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen stmt->stmt.pool = pool;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen return &stmt->stmt;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen}
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainenstatic struct sql_statement *
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainendriver_cassandra_statement_init_prepared(struct sql_prepared_statement *_prep_stmt)
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen{
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen struct cassandra_sql_prepared_statement *prep_stmt =
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen (struct cassandra_sql_prepared_statement *)_prep_stmt;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen pool_t pool = pool_alloconly_create("cassandra prepared sql statement", 1024);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen struct cassandra_sql_statement *stmt =
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen p_new(pool, struct cassandra_sql_statement, 1);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen stmt->stmt.pool = pool;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen stmt->stmt.query_template =
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen p_strdup(stmt->stmt.pool, prep_stmt->query_template);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen stmt->prep = prep_stmt;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen if (prep_stmt->prepared != NULL) {
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen /* statement is already prepared. we can use it immediately. */
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen stmt->cass_stmt = cass_prepared_bind(prep_stmt->prepared);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen } else {
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen if (prep_stmt->error != NULL)
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen prepare_start(prep_stmt);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen /* need to wait until prepare is finished */
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen array_append(&prep_stmt->pending_statements, &stmt, 1);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen }
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen return &stmt->stmt;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen}
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainenstatic void
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainendriver_cassandra_statement_abort(struct sql_statement *_stmt)
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen{
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen struct cassandra_sql_statement *stmt =
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen (struct cassandra_sql_statement *)_stmt;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen if (stmt->cass_stmt != NULL)
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen cass_statement_free(stmt->cass_stmt);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen}
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainenstatic void
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainendriver_cassandra_statement_set_timestamp(struct sql_statement *_stmt,
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen const struct timespec *ts)
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen{
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen struct cassandra_sql_statement *stmt =
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen (struct cassandra_sql_statement *)_stmt;
186c97450c84494ba98e2905ca275f47ad334f4cTimo Sirainen cass_int64_t ts_usecs =
186c97450c84494ba98e2905ca275f47ad334f4cTimo Sirainen (cass_int64_t)ts->tv_sec * 1000000ULL +
186c97450c84494ba98e2905ca275f47ad334f4cTimo Sirainen ts->tv_nsec / 1000;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
18da63ba64987f2157cf8c490b4c4d1efba28733Timo Sirainen i_assert(stmt->result == NULL);
18da63ba64987f2157cf8c490b4c4d1efba28733Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen if (stmt->cass_stmt != NULL)
186c97450c84494ba98e2905ca275f47ad334f4cTimo Sirainen cass_statement_set_timestamp(stmt->cass_stmt, ts_usecs);
18da63ba64987f2157cf8c490b4c4d1efba28733Timo Sirainen stmt->timestamp = ts_usecs;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen}
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainenstatic struct cassandra_sql_arg *
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainendriver_cassandra_add_pending_arg(struct cassandra_sql_statement *stmt,
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen unsigned int column_idx)
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen{
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen struct cassandra_sql_arg *arg;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen if (!array_is_created(&stmt->pending_args))
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen p_array_init(&stmt->pending_args, stmt->stmt.pool, 8);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen arg = array_append_space(&stmt->pending_args);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen arg->column_idx = column_idx;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen return arg;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen}
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainenstatic void
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainendriver_cassandra_statement_bind_str(struct sql_statement *_stmt,
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen unsigned int column_idx,
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen const char *value)
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen{
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen struct cassandra_sql_statement *stmt =
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen (struct cassandra_sql_statement *)_stmt;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen if (stmt->cass_stmt != NULL)
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen cass_statement_bind_string(stmt->cass_stmt, column_idx, value);
27688ec19adf1af07f9a996620caba05bb80acfbTimo Sirainen else if (stmt->prep != NULL) {
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen struct cassandra_sql_arg *arg =
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen driver_cassandra_add_pending_arg(stmt, column_idx);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen arg->value_str = p_strdup(_stmt->pool, value);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen }
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen}
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainenstatic void
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainendriver_cassandra_statement_bind_binary(struct sql_statement *_stmt,
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen unsigned int column_idx,
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen const void *value, size_t value_size)
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen{
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen struct cassandra_sql_statement *stmt =
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen (struct cassandra_sql_statement *)_stmt;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen if (stmt->cass_stmt != NULL) {
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen cass_statement_bind_bytes(stmt->cass_stmt, column_idx,
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen value, value_size);
27688ec19adf1af07f9a996620caba05bb80acfbTimo Sirainen } else if (stmt->prep != NULL) {
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen struct cassandra_sql_arg *arg =
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen driver_cassandra_add_pending_arg(stmt, column_idx);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen arg->value_binary = p_memdup(_stmt->pool, value, value_size);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen arg->value_binary_size = value_size;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen }
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen}
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainenstatic void
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainendriver_cassandra_statement_bind_int64(struct sql_statement *_stmt,
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen unsigned int column_idx, int64_t value)
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen{
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen struct cassandra_sql_statement *stmt =
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen (struct cassandra_sql_statement *)_stmt;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen if (stmt->cass_stmt != NULL)
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen driver_cassandra_bind_int(stmt, column_idx, value);
27688ec19adf1af07f9a996620caba05bb80acfbTimo Sirainen else if (stmt->prep != NULL) {
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen struct cassandra_sql_arg *arg =
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen driver_cassandra_add_pending_arg(stmt, column_idx);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen arg->value_int64 = value;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen }
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen}
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainenstatic void
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainendriver_cassandra_statement_query(struct sql_statement *_stmt,
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen sql_query_callback_t *callback, void *context)
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen{
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen struct cassandra_sql_statement *stmt =
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen (struct cassandra_sql_statement *)_stmt;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen struct cassandra_db *db = (struct cassandra_db *)_stmt->db;
27688ec19adf1af07f9a996620caba05bb80acfbTimo Sirainen const char *query = sql_statement_get_query(_stmt);
b6c9cc2bf7517adcc0b9f98696c61bde321900f6Timo Sirainen bool is_prepared = stmt->cass_stmt != NULL || stmt->prep != NULL;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
27688ec19adf1af07f9a996620caba05bb80acfbTimo Sirainen stmt->result = driver_cassandra_query_init(db, query,
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen CASSANDRA_QUERY_TYPE_READ,
b6c9cc2bf7517adcc0b9f98696c61bde321900f6Timo Sirainen is_prepared,
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen callback, context);
27688ec19adf1af07f9a996620caba05bb80acfbTimo Sirainen if (stmt->cass_stmt != NULL) {
27688ec19adf1af07f9a996620caba05bb80acfbTimo Sirainen stmt->result->statement = stmt->cass_stmt;
fa649b1fa91fa7aed260fe5d6da8d4d7b42ed3fbTimo Sirainen stmt->result->timestamp = stmt->timestamp;
27688ec19adf1af07f9a996620caba05bb80acfbTimo Sirainen } else if (stmt->prep != NULL) {
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen /* wait for prepare to finish */
27688ec19adf1af07f9a996620caba05bb80acfbTimo Sirainen return;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen } else {
27688ec19adf1af07f9a996620caba05bb80acfbTimo Sirainen stmt->result->statement = cass_statement_new(query, 0);
18da63ba64987f2157cf8c490b4c4d1efba28733Timo Sirainen stmt->result->timestamp = stmt->timestamp;
125081bc1cac5f9fe006c36c88ca0535377c461cTimo Sirainen if (stmt->timestamp != 0) {
27688ec19adf1af07f9a996620caba05bb80acfbTimo Sirainen cass_statement_set_timestamp(stmt->result->statement,
125081bc1cac5f9fe006c36c88ca0535377c461cTimo Sirainen stmt->timestamp);
27688ec19adf1af07f9a996620caba05bb80acfbTimo Sirainen }
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen }
27688ec19adf1af07f9a996620caba05bb80acfbTimo Sirainen (void)driver_cassandra_send_query(stmt->result);
27688ec19adf1af07f9a996620caba05bb80acfbTimo Sirainen pool_unref(&_stmt->pool);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen}
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainenstatic struct sql_result *
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainendriver_cassandra_statement_query_s(struct sql_statement *_stmt ATTR_UNUSED)
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen{
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen i_panic("cassandra: sql_statement_query_s() not supported");
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen}
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainenstatic void
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainendriver_cassandra_update_stmt(struct sql_transaction_context *_ctx,
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen struct sql_statement *_stmt,
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen unsigned int *affected_rows)
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen{
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen struct cassandra_transaction_context *ctx =
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen (struct cassandra_transaction_context *)_ctx;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen struct cassandra_sql_statement *stmt =
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen (struct cassandra_sql_statement *)_stmt;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen i_assert(affected_rows == NULL);
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen if (ctx->query != NULL || ctx->stmt != NULL) {
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen transaction_set_failed(ctx, "Multiple changes in transaction not supported");
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen return;
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen }
27688ec19adf1af07f9a996620caba05bb80acfbTimo Sirainen if (stmt->prep != NULL)
27688ec19adf1af07f9a996620caba05bb80acfbTimo Sirainen ctx->stmt = stmt;
117ae14172071ab6334260dfd3cab3609234ef2aTimo Sirainen else {
27688ec19adf1af07f9a996620caba05bb80acfbTimo Sirainen ctx->query = i_strdup(sql_statement_get_query(_stmt));
af619a25952f5ba550800daf69a119247b1fcda3Timo Sirainen ctx->query_timestamp = stmt->timestamp;
117ae14172071ab6334260dfd3cab3609234ef2aTimo Sirainen pool_unref(&_stmt->pool);
117ae14172071ab6334260dfd3cab3609234ef2aTimo Sirainen }
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen}
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenconst struct sql_db driver_cassandra_db = {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen .name = "cassandra",
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen .flags = SQL_DB_FLAG_PREP_STATEMENTS,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen .v = {
ef597c4619eb021563f659b886c67762fce7a817Timo Sirainen .init = driver_cassandra_init_v,
ef597c4619eb021563f659b886c67762fce7a817Timo Sirainen .deinit = driver_cassandra_deinit_v,
ef597c4619eb021563f659b886c67762fce7a817Timo Sirainen .connect = driver_cassandra_connect,
ef597c4619eb021563f659b886c67762fce7a817Timo Sirainen .disconnect = driver_cassandra_disconnect,
ef597c4619eb021563f659b886c67762fce7a817Timo Sirainen .escape_string = driver_cassandra_escape_string,
ef597c4619eb021563f659b886c67762fce7a817Timo Sirainen .exec = driver_cassandra_exec,
ef597c4619eb021563f659b886c67762fce7a817Timo Sirainen .query = driver_cassandra_query,
ef597c4619eb021563f659b886c67762fce7a817Timo Sirainen .query_s = driver_cassandra_query_s,
ef597c4619eb021563f659b886c67762fce7a817Timo Sirainen
ef597c4619eb021563f659b886c67762fce7a817Timo Sirainen .transaction_begin = driver_cassandra_transaction_begin,
ef597c4619eb021563f659b886c67762fce7a817Timo Sirainen .transaction_commit = driver_cassandra_transaction_commit,
ef597c4619eb021563f659b886c67762fce7a817Timo Sirainen .transaction_commit_s = driver_cassandra_transaction_commit_s,
ef597c4619eb021563f659b886c67762fce7a817Timo Sirainen .transaction_rollback = driver_cassandra_transaction_rollback,
ef597c4619eb021563f659b886c67762fce7a817Timo Sirainen
ef597c4619eb021563f659b886c67762fce7a817Timo Sirainen .update = driver_cassandra_update,
ef597c4619eb021563f659b886c67762fce7a817Timo Sirainen
ef597c4619eb021563f659b886c67762fce7a817Timo Sirainen .escape_blob = driver_cassandra_escape_blob,
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen .prepared_statement_init = driver_cassandra_prepared_statement_init,
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen .prepared_statement_deinit = driver_cassandra_prepared_statement_deinit,
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen .statement_init = driver_cassandra_statement_init,
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen .statement_init_prepared = driver_cassandra_statement_init_prepared,
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen .statement_abort = driver_cassandra_statement_abort,
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen .statement_set_timestamp = driver_cassandra_statement_set_timestamp,
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen .statement_bind_str = driver_cassandra_statement_bind_str,
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen .statement_bind_binary = driver_cassandra_statement_bind_binary,
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen .statement_bind_int64 = driver_cassandra_statement_bind_int64,
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen .statement_query = driver_cassandra_statement_query,
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen .statement_query_s = driver_cassandra_statement_query_s,
709ee5a909d482f31611f9e6cc10d893a272e061Timo Sirainen .update_stmt = driver_cassandra_update_stmt,
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,
402f9bcf48cbccc17fdb5f3ea411a7967aed0fd0Timo Sirainen driver_cassandra_result_get_error,
dd3d20d9b5821077164183a260af9bde0db3ff3fTimo Sirainen driver_cassandra_result_more,
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