Exemple #1
0
/** Check if the ticket has already been issued
 * @return 0 if not unique; otherwise 1 */
static int __check_if_ticket_exists(const unsigned int ticket)
{
    MDB_txn *txn;

    int e = mdb_txn_begin(sv->db_env, NULL, MDB_RDONLY, &txn);
    if (0 != e)
        mdb_fatal(e);

    MDB_val k = { .mv_size = sizeof(ticket), .mv_data = (void*)&ticket };
    MDB_val v;

    e = mdb_get(txn, sv->tickets, &k, &v);
    switch (e)
    {
    case 0:
        break;
    case MDB_NOTFOUND:
        e = mdb_txn_commit(txn);
        if (0 != e)
            mdb_fatal(e);
        return 0;
    default:
        mdb_fatal(e);
    }

    e = mdb_txn_commit(txn);
    if (0 != e)
        mdb_fatal(e);

    return 1;
}

static unsigned int __generate_ticket()
{
    unsigned int ticket;

    do
    {
        // TODO need better random number generator
        ticket = rand();
    }
    while (__check_if_ticket_exists(ticket));
    return ticket;
}
Exemple #2
0
static int __batcher_commit(batch_monitor_t* m, batch_queue_t* bq)
{
    if (0 == heap_count(bq->queue))
        return 0;

    MDB_txn *txn;

    int e = mdb_txn_begin(sv->db_env, NULL, 0, &txn);
    if (0 != e)
        mdb_fatal(e);

    while (0 < heap_count(bq->queue))
    {
        batch_item_t* item = heap_poll(bq->queue);
        e = mdb_put(txn, sv->docs, &item->key, &item->val, item->flags);
        switch (e)
        {
        case 0:
            break;
        case MDB_MAP_FULL:
        {
            mdb_txn_abort(txn);
            while ((item = heap_poll(bq->queue)))
                ;
            snprintf(batcher_error, BATCHER_ERROR_LEN, "NOT ENOUGH SPACE");
            return -1;
        }
        case MDB_KEYEXIST:
            item->flags = WOULD_OVERWRITE;
            break;
        default:
            mdb_fatal(e);
        }
    }

    e = mdb_txn_commit(txn);
    if (0 != e)
        mdb_fatal(e);

    return 0;
}
Exemple #3
0
/** Get a list of document keys where the key prefix matches the provided key */
static int __get_keys(h2o_req_t *req, kstr_t* key)
{
    get_keys_generator_t *gen = h2o_mem_alloc_pool(&req->pool, sizeof(*gen));
    gen->super.proceed = __get_keys_proceed;
    gen->super.stop = __get_keys_close;
    gen->req = req;
    gen->key = key;

    req->res.status = 200;
    req->res.reason = "OK";
    h2o_start_response(req, &gen->super);

    int e;

    e = mdb_txn_begin(sv->db_env, NULL, MDB_RDONLY, &gen->txn);
    if (0 != e)
        mdb_fatal(e);

    e = mdb_cursor_open(gen->txn, sv->docs, &gen->curs);
    if (0 != e)
        mdb_fatal(e);

    MDB_val k = { .mv_size = key->len, .mv_data = key->s }, v;
Exemple #4
0
/** Put a document into the database at this key
 * If the "Prefers: ETag" header is set, we perform a CAS operation */
static int __put(h2o_req_t *req, kstr_t* key)
{
    char* sv_etag = __remove_stored_etag(key);
    h2o_iovec_t cli_etag = __get_if_match_header_value(req, key);
    if (0 < cli_etag.len &&
        !__should_etag_conditional_put_succeed(req, key, sv_etag, &cli_etag))
    {
        if (sv_etag)
            free(sv_etag);
        return h2oh_respond_with_error(req, 412, "BAD ETAG");
    }

    if (sv_etag)
        free(sv_etag);

    batch_item_t item = {
        .flags       = 0,
        .key.mv_data = key->s,
        .key.mv_size = key->len,
        .val.mv_data = req->entity.base,
        .val.mv_size = req->entity.len,
    };

    int e = bmon_offer(&sv->batch, &item);
    if (0 != e)
        return h2oh_respond_with_error(req, 400, batcher_error);
    return h2oh_respond_with_success(req, 200);
}

typedef struct
{
    h2o_generator_t super;
    h2o_req_t *req;
    MDB_txn *txn;
    MDB_cursor* curs;
    kstr_t* key;
} get_keys_generator_t;

static void __get_keys_close(h2o_generator_t *_self, h2o_req_t *req)
{
    get_keys_generator_t *gen = (void*)_self;

    mdb_cursor_close(gen->curs);

    int e = mdb_txn_commit(gen->txn);
    if (0 != e)
        mdb_fatal(e);
}