src/evpq.c
author Tero Marttila <terom@fixme.fi>
Sat, 11 Oct 2008 20:45:28 +0300
changeset 18 b12e78767248
parent 12 7f159ee3a3ff
child 21 e5da1d428e3e
permissions -rw-r--r--
url_test is starting to be properly functional
12
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     1
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     2
#include <event2/event.h>
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     3
#include <assert.h>
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     4
#include <stdlib.h>
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     5
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     6
#include "evpq.h"
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     7
#include "lib/error.h"
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     8
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     9
struct evpq_conn {
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    10
    struct event_base *ev_base;
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    11
    struct evpq_callback_info user_cb;
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    12
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    13
    PGconn *pg_conn;
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    14
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    15
    struct event *ev;
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    16
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    17
    enum evpq_state state;
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    18
};
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    19
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    20
/*
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    21
 * This evpq_conn has experienced a GENERAL FAILURE.
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    22
 */
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    23
static void _evpq_failure (struct evpq_conn *conn) {
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    24
    // update state
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    25
    conn->state = EVPQ_FAILURE;
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    26
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    27
    // notify
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    28
    conn->user_cb.fn_failure(conn, conn->user_cb.cb_arg);
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    29
}
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    30
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    31
/*
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    32
 * Initial connect was succesfull
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    33
 */
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    34
static void _evpq_connect_ok (struct evpq_conn *conn) {
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    35
    // update state
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    36
    conn->state = EVPQ_CONNECTED;
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    37
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    38
    // notify
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    39
    conn->user_cb.fn_connected(conn, conn->user_cb.cb_arg);
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    40
}
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    41
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    42
/*
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    43
 * Initial connect failed
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    44
 */
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    45
static void _evpq_connect_fail (struct evpq_conn *conn) {
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    46
    // just mark it as a generic failure
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    47
    _evpq_failure(conn);
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    48
}
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    49
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    50
/*
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    51
 * Receive a result and gives it to the user. If there was no more results, update state and tell the user.
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    52
 *
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    53
 * Returns zero if we got a result, 1 if there were/are no more results to handle.
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    54
 */
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    55
static int _evpq_query_result (struct evpq_conn *conn) {
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    56
    PGresult *result;
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    57
    
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    58
    // get the result
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    59
    if ((result = PQgetResult(conn->pg_conn)) == NULL) {
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    60
        // no more results, update state
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    61
        conn->state = EVPQ_CONNECTED;
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    62
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    63
        // tell the user the query is done
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    64
        conn->user_cb.fn_done(conn, conn->user_cb.cb_arg);
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    65
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    66
        // stop waiting for more results
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    67
        return 1;
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    68
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    69
    } else {
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    70
        // got a result, give it to the user
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    71
        conn->user_cb.fn_result(conn, result, conn->user_cb.cb_arg);
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    72
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    73
        // great
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    74
        return 0;
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    75
    }
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    76
}
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    77
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    78
/*
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    79
 * Schedule a new _evpq_event for this connection.
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    80
 */ 
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    81
static int _evpq_schedule (struct evpq_conn *conn, short what, void (*handler)(evutil_socket_t, short, void *)) {
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    82
    assert(conn->pg_conn != NULL);
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    83
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    84
    // ensure we have a valid socket, this should be the case after the PQstatus check...
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    85
    if (PQsocket(conn->pg_conn) < 0)
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    86
        FATAL("PQsocket gave invalid socket");
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    87
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    88
    // reschedule with a new event
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    89
    if (conn->ev) {
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    90
        event_assign(conn->ev, conn->ev_base, PQsocket(conn->pg_conn), what, handler, conn);
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    91
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    92
    } else {
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    93
        if ((conn->ev = event_new(conn->ev_base, PQsocket(conn->pg_conn), what, handler, conn)) == NULL)
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    94
            PERROR("event_new");
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    95
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    96
    }
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    97
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    98
    // add it
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    99
    // XXX: timeouts?
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   100
    if (event_add(conn->ev, NULL))
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   101
        PERROR("event_add");
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   102
    
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   103
    // success
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   104
    return 0;
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   105
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   106
error:
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   107
    return -1;
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   108
}
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   109
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   110
/*
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   111
 * Handle events on the PQ socket while connecting
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   112
 */
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   113
static void _evpq_connect_event (evutil_socket_t fd, short what, void *arg) {
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   114
    struct evpq_conn *conn = arg;
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   115
    PostgresPollingStatusType poll_status;
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   116
    
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   117
    // this is only for connect events
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   118
    assert(conn->state == EVPQ_CONNECT);
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   119
    
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   120
    // XXX: timeouts?
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   121
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   122
    // ask PQ what to do 
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   123
    switch ((poll_status = PQconnectPoll(conn->pg_conn))) {
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   124
        case PGRES_POLLING_READING:
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   125
            // poll for read
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   126
            what = EV_READ;
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   127
            
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   128
            // reschedule
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   129
            break;
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   130
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   131
        case PGRES_POLLING_WRITING:
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   132
            // poll for write
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   133
            what = EV_WRITE;
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   134
            
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   135
            // reschedule
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   136
            break;
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   137
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   138
        case PGRES_POLLING_OK:
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   139
            // connected
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   140
            _evpq_connect_ok(conn);
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   141
            
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   142
            // done
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   143
            return;
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   144
        
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   145
        case PGRES_POLLING_FAILED:
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   146
            // faaaaail!
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   147
            _evpq_connect_fail(conn);
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   148
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   149
            // done
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   150
            return;
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   151
        
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   152
        default:
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   153
            FATAL("PQconnectPoll gave a weird value: %d", poll_status);
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   154
    }
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   155
    
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   156
    // reschedule
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   157
    if (_evpq_schedule(conn, what, _evpq_connect_event))
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   158
        goto error;
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   159
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   160
    // done, wait for the next event
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   161
    return;
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   162
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   163
error:
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   164
    // XXX: reset?
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   165
    _evpq_failure(conn);
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   166
}
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   167
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   168
static void _evpq_query_event (evutil_socket_t fd, short what, void *arg) {
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   169
    struct evpq_conn *conn = arg;
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   170
    
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   171
    // this is only for query events
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   172
    assert(conn->state == EVPQ_QUERY);
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   173
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   174
    // XXX: PQflush, timeouts
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   175
    assert(what == EV_READ);
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   176
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   177
    // we're going to assume that all queries will *require* data for their results
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   178
    // this would break otherwise (PQconsumeInput might block?)
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   179
    assert(PQisBusy(conn->pg_conn) != 0);
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   180
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   181
    // handle input
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   182
    if (PQconsumeInput(conn->pg_conn) == 0)
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   183
        ERROR("PQconsumeInput: %s", PQerrorMessage(conn->pg_conn));
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   184
    
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   185
    // handle results
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   186
    while (PQisBusy(conn->pg_conn) == 0) {
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   187
        // handle the result
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   188
        if (_evpq_query_result(conn) == 1) {
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   189
            // no need to wait for anything anymore
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   190
            return;
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   191
        }
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   192
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   193
        // loop to handle the next result
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   194
    }
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   195
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   196
    // still need to wait for a result, so reschedule
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   197
    if (_evpq_schedule(conn, EV_READ, _evpq_query_event))
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   198
        goto error;
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   199
        
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   200
    // done, wait for the next event
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   201
    return;
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   202
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   203
error:
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   204
    // XXX: reset?
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   205
    _evpq_failure(conn);
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   206
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   207
}
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   208
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   209
struct evpq_conn *evpq_connect (struct event_base *ev_base, const char *conninfo, const struct evpq_callback_info cb_info) {
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   210
    struct evpq_conn *conn = NULL;
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   211
    
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   212
    // alloc our context
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   213
    if ((conn = calloc(1, sizeof(*conn))) == NULL)
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   214
        ERROR("calloc");
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   215
    
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   216
    // initial state
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   217
    conn->ev_base = ev_base;
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   218
    conn->user_cb = cb_info;
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   219
    conn->state = EVPQ_INIT;
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   220
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   221
    // create our PGconn
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   222
    if ((conn->pg_conn = PQconnectStart(conninfo)) == NULL)
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   223
        PERROR("PQconnectStart");
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   224
    
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   225
    // check for immediate failure
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   226
    if (PQstatus(conn->pg_conn) == CONNECTION_BAD)
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   227
        ERROR("PQstatus indicates CONNECTION_BAD after PQconnectStart");
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   228
    
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   229
    // assume PGRES_POLLING_WRITING
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   230
    if (_evpq_schedule(conn, EV_WRITE, _evpq_connect_event))
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   231
        goto error;
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   232
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   233
    // connecting
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   234
    conn->state = EVPQ_CONNECT;
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   235
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   236
    // success, wait for the connection to be established
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   237
    return conn;
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   238
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   239
error:
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   240
    if (conn) {
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   241
        if (conn->pg_conn)
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   242
            PQfinish(conn->pg_conn);
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   243
        
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   244
        free(conn);
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   245
    }
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   246
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   247
    return NULL;
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   248
}
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   249
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   250
int evpq_query (struct evpq_conn *conn, const char *command) {
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   251
    // check state
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   252
    if (conn->state != EVPQ_CONNECTED)
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   253
        ERROR("invalid evpq state: %d", conn->state);
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   254
    
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   255
    // do the query
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   256
    if (PQsendQuery(conn->pg_conn, command) == 0)
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   257
        ERROR("PQsendQuery: %s", PQerrorMessage(conn->pg_conn));
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   258
    
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   259
    // update state
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   260
    conn->state = EVPQ_QUERY;
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   261
    
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   262
    // XXX: PQflush
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   263
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   264
    // poll for read
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   265
    if (_evpq_schedule(conn, EV_READ, _evpq_query_event))
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   266
        goto error;
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   267
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   268
    // and then we wait
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   269
    return 0;
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   270
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   271
error:
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   272
    return -1;
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   273
}
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   274
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   275
const PGconn *evpq_pgconn (struct evpq_conn *conn) {
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   276
    return conn->pg_conn;
7f159ee3a3ff working basic evpq lib and test
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   277
}