pool_t pool;
char *connect_string;
+ char *host;
PGconn *pg;
struct io *io;
enum io_condition io_dir;
struct pgsql_result *cur_result;
- struct ioloop *ioloop;
+ struct ioloop *ioloop, *orig_ioloop;
struct sql_result *sync_result;
char *error;
static void result_finish(struct pgsql_result *result);
+static void driver_pgsql_set_state(struct pgsql_db *db, enum sql_db_state state)
+{
+ /* switch back to original ioloop in case the caller wants to
+ add/remove timeouts */
+ if (db->ioloop != NULL)
+ current_ioloop = db->orig_ioloop;
+ sql_db_set_state(&db->api, state);
+ if (db->ioloop != NULL)
+ current_ioloop = db->ioloop;
+}
+
static void driver_pgsql_close(struct pgsql_db *db)
{
db->io_dir = 0;
if (db->to_connect != NULL)
timeout_remove(&db->to_connect);
- sql_db_set_state(&db->api, SQL_DB_STATE_DISCONNECTED);
+ driver_pgsql_set_state(db, SQL_DB_STATE_DISCONNECTED);
if (db->ioloop != NULL) {
/* running a sync query, stop it */
i_info("pgsql: Connected to %s", PQdb(db->pg));
if (db->to_connect != NULL)
timeout_remove(&db->to_connect);
- sql_db_set_state(&db->api, SQL_DB_STATE_IDLE);
+ driver_pgsql_set_state(db, SQL_DB_STATE_IDLE);
if (db->ioloop != NULL) {
/* driver_pgsql_sync_init() waiting for connection to
finish */
static void driver_pgsql_connect_timeout(struct pgsql_db *db)
{
+ const char *dbname = PQdb(db->pg);
unsigned int secs = ioloop_time - db->api.last_connect_try;
i_error("pgsql: Connect failed to %s: Timeout after %u seconds",
- PQdb(db->pg), secs);
+ dbname != NULL ? dbname : db->host, secs);
driver_pgsql_close(db);
}
/* nonblocking connecting begins. */
if (PQsetnonblocking(db->pg, 1) < 0)
i_error("pgsql: PQsetnonblocking() failed");
+ i_assert(db->to_connect == NULL);
db->to_connect = timeout_add(SQL_CONNECT_TIMEOUT_SECS * 1000,
driver_pgsql_connect_timeout, db);
db->io = io_add(PQsocket(db->pg), IO_WRITE, connect_callback, db);
db->io_dir = IO_WRITE;
- sql_db_set_state(&db->api, SQL_DB_STATE_CONNECTING);
+ driver_pgsql_set_state(db, SQL_DB_STATE_CONNECTING);
return 0;
}
db = i_new(struct pgsql_db, 1);
db->connect_string = i_strdup(connect_string);
db->api = driver_pgsql_db;
+
+ T_BEGIN {
+ const char *const *arg = t_strsplit(connect_string, " ");
+
+ for (; *arg != NULL; arg++) {
+ if (strncmp(*arg, "host=", 5) == 0)
+ db->host = i_strdup(*arg + 5);
+ }
+ } T_END;
return &db->api;
}
_db->no_reconnect = TRUE;
driver_pgsql_close(db);
+ i_free(db->host);
i_free(db->error);
i_free(db->connect_string);
array_free(&_db->module_contexts);
if (db->fatal_error)
driver_pgsql_close(db);
else
- sql_db_set_state(&db->api, SQL_DB_STATE_IDLE);
+ driver_pgsql_set_state(db, SQL_DB_STATE_IDLE);
}
static void consume_results(struct pgsql_db *db)
return;
}
- sql_db_set_state(&db->api, SQL_DB_STATE_BUSY);
+ driver_pgsql_set_state(db, SQL_DB_STATE_BUSY);
if (ret > 0) {
/* write blocks */
db->io = io_add(PQsocket(db->pg), IO_WRITE,
static void driver_pgsql_sync_init(struct pgsql_db *db)
{
+ db->orig_ioloop = current_ioloop;
if (db->io == NULL) {
db->ioloop = io_loop_create();
return;
i_assert(db->api.state == SQL_DB_STATE_CONNECTING);
- /* have to move our existing I/O handler to new I/O loop */
+ /* have to move our existing I/O and timeout handlers to new I/O loop */
io_remove(&db->io);
+ if (db->to_connect != NULL)
+ timeout_remove(&db->to_connect);
db->ioloop = io_loop_create();
+ db->to_connect = timeout_add(SQL_CONNECT_TIMEOUT_SECS * 1000,
+ driver_pgsql_connect_timeout, db);
db->io = io_add(PQsocket(db->pg), db->io_dir, connect_callback, db);
/* wait for connecting to finish */
io_loop_run(db->ioloop);