Exemplo n.º 1
0
ol_bucket *ol_get_bucket(const ol_database *db, const char *key, const size_t klen, char (*_key)[KEY_SIZE], size_t *_klen) {
    if (db == NULL)
        return NULL;

    uint32_t hash;
    _ol_trunc(key, klen, *_key);
    *_klen = strnlen(*_key, KEY_SIZE);

    if (*_klen == 0)
        return NULL;

    MurmurHash3_x86_32(*_key, *_klen, DEVILS_SEED, &hash);

    unsigned int index = _ol_calc_idx(db->cur_ht_size, hash);
    if (db->hashes[index] != NULL) {
        size_t larger_key = 0;
        ol_bucket *tmp_bucket;
        tmp_bucket = db->hashes[index];
        larger_key = tmp_bucket->klen > klen ? tmp_bucket->klen : klen;
        if (strncmp(tmp_bucket->key, key, larger_key) == 0) {
            return tmp_bucket;
        } else if (tmp_bucket->next != NULL) {
            /* Keys were not the same, traverse the linked list to see if it's
             * farther down. */
            do {
                tmp_bucket = tmp_bucket->next;
                larger_key = tmp_bucket->klen > klen ? tmp_bucket->klen : klen;
                if (strncmp(tmp_bucket->key, key, larger_key) == 0)
                    return tmp_bucket;
            } while (tmp_bucket->next != NULL);
        }
    }
    return NULL;
}
Exemplo 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;
}