Ejemplo n.º 1
0
static inline int _ol_close_common(ol_database *db) {
    debug("Closing \"%s\" database.", db->name);

    /* TODO: Commit/abort transactions here. */
    /*
    if (!new_db->is_enabled(OL_F_DISABLE_TX, &new_db->feature_set)) {
    }
    */

    unsigned int iterations = ol_ht_bucket_max(db->cur_ht_size);
    int rcrd_cnt = db->rcrd_cnt;
    int freed = 0;
    debug("Freeing %d records.", rcrd_cnt);
    debug("Hash table iterations: %d.", iterations);

    int i = 0;
    for (; i < iterations; i++) { /* 8=======D */
        if (db->hashes[i] != NULL) {
            ol_bucket *ptr, *next;
            for (ptr = db->hashes[i]; NULL != ptr; ptr = next) {
                next = ptr->next;
                _ol_free_bucket(&ptr);
                freed++;
            }
        }
    }

    if (!db->is_enabled(OL_F_DISABLE_TX, &db->feature_set)) {
        ols_close(db->cur_transactions);
        free(db->cur_transactions);
        check(freed >= rcrd_cnt, "Error: Couldn't free all records.\nRecords freed: %d", freed);
    }

    if (db->tree != NULL) {
        debug("Destroying tree.");
        ols_close(db->tree);
        free(db->tree);
        db->tree = NULL;
    }

    return OL_SUCCESS;

error:
    return OL_FAILURE;
}
Ejemplo n.º 2
0
int olt_scoop(ol_transaction *tx, const char *key, size_t klen) {
    /* you know... like scoop some data from the jar and eat it? All gone. */
    uint32_t hash;
    char _key[KEY_SIZE] = {'\0'};
    _ol_trunc(key, klen, _key);
    size_t _klen = strnlen(_key, KEY_SIZE);
    check(_klen > 0, "Key length cannot be zero.");

    MurmurHash3_x86_32(_key, _klen, DEVILS_SEED, &hash);
    ol_database *operating_db = tx->transaction_db;
    /* First attempt to calculate the index in the transaction_db */
    unsigned int index = _ol_calc_idx(tx->transaction_db->cur_ht_size, hash);
    /* If we couldn't find it in the transaction_db, look for the value in the
     * parent_db (the one we forked from) */
    if (tx->transaction_db->hashes[index] == NULL &&
            tx->parent_db != NULL) {
        index = _ol_calc_idx(tx->parent_db->cur_ht_size, hash);
        operating_db = tx->parent_db;
    }

    if (operating_db->hashes[index] == NULL)
        return OL_FAILURE;

    /* Now that we know what database we're operating on, continue
     * as usual. */
    ol_bucket *to_free = NULL;
    int return_level = OL_FAILURE;

    size_t larger_key = 0;
    ol_bucket *bucket = operating_db->hashes[index];
    larger_key = bucket->klen > _klen ? bucket->klen : _klen;
    if (strncmp(bucket->key, _key, larger_key) == 0) {
        /* We only ACTUALLY want to delete something if we're operating on the transaction_db */
        if (operating_db == tx->transaction_db)
            operating_db->hashes[index] = bucket->next;

        to_free = bucket;
        return_level = OL_SUCCESS;
    } else { /* Keys weren't the same, traverse the bucket LL */
        while (bucket->next != NULL) {
            ol_bucket *last = bucket;
            bucket = bucket->next;
            larger_key = bucket->klen > klen ? bucket->klen : klen;
            if (strncmp(bucket->key, _key, larger_key) == 0) {
                if (operating_db == tx->transaction_db) {
                    if (bucket->next != NULL)
                        last->next = bucket->next;
                    else
                        last->next = NULL;
                }

                to_free = bucket;
                return_level = OL_SUCCESS;
                break;
            }
        }
    }

    if (to_free != NULL) {
        /* Only delete the node from the transaction_db. */
        if (operating_db == tx->transaction_db &&
            tx->transaction_db->is_enabled(OL_F_SPLAYTREE, &tx->transaction_db->feature_set)) {
            ols_delete(tx->transaction_db->tree, to_free->node);
            to_free->node = NULL;
        }

        /* Write the SCOOP command to the log, so we can replay it later. */
        if (tx->transaction_db->state != OL_S_STARTUP) {
            ol_aol_write_cmd(tx->transaction_db, "SCOOP", bucket);
        }

        /* Again, only delete the key from the transaction_db, not the parent. */
        if (operating_db == tx->transaction_db) {
            unsigned char *data_ptr = tx->transaction_db->values + to_free->data_offset;
            const size_t data_size = to_free->data_size;
            if (data_size != 0)
                memset(data_ptr, '\0', data_size);
            _ol_free_bucket(&to_free);
            tx->transaction_db->rcrd_cnt -= 1;
        }
    }

    /* Flag the transaction as dirty. */
    tx->dirty = 1;

    return return_level;
error:
    return OL_FAILURE;
}