Example #1
0
static void
test_clear()
{
    genhash_t* h=get_test_hash();
    assert(genhash_size(h) == 26);
    genhash_clear(h);
    assert(genhash_size(h) == 0);
    genhash_free(h);
}
Example #2
0
static void
test_function_update()
{
    genhash_t* h=genhash_init(4, get_string_hash_ops());
    int type=0;

    assert_hash_val(NULL, h, "x");
    type=genhash_fun_update(h, "x", update_fun, free_str, NULL);
    assert(type == NEW);
    assert_hash_val("", h, "x");
    type=genhash_fun_update(h, "x", update_fun, free_str, NULL);
    assert(type == MODIFICATION);
    assert_hash_val("x", h, "x");
    type=genhash_fun_update(h, "x", update_fun, free_str, NULL);
    assert(type == MODIFICATION);
    assert_hash_val("xx", h, "x");

    assert(genhash_size(h) == 1);

    genhash_free(h);
}
Example #3
0
static void
test_multiple_keys()
{
    genhash_t* h=genhash_init(1, get_string_hash_ops());
    int deleted = 0, i = 0;

    /* Pollute the space to allow some hash collisions */
    for(i=0; i<16000; i++) {
        char key[8];
        snprintf(key, sizeof(key), "k%d", i);
        genhash_store(h, key, key);
        assert_hash_val(key, h, key);
    }

    assert_hash_val(NULL, h, "x");
    genhash_store(h, "x", "a");
    genhash_store(h, "x", "b");

    assert_hash_val("b", h, "x");
    deleted=genhash_delete(h, "x");
    assert(deleted == 1);
    assert_hash_val("a", h, "x");
    deleted=genhash_delete(h, "x");
    assert(deleted == 1);
    assert_hash_val(NULL, h, "x");
    deleted=genhash_delete(h, "x");
    assert(deleted == 0);

    genhash_store(h, "x", "a");
    genhash_store(h, "x", "b");
    genhash_store(h, "y", "yz");

    assert(genhash_size(h) == 16003);
    assert(genhash_size_for_key(h, "x") == 2);

    deleted=genhash_delete_all(h, "x");
    assert(deleted == 2);

    genhash_free(h);
}
Example #4
0
void mcache_set(mcache *m, void *it,
                uint64_t exptime,
                bool add_only,
                bool mod_exptime_if_exists) {
    assert(it);
    assert(m->funcs);
    assert(m->funcs->item_get_next(it) == NULL);
    assert(m->funcs->item_get_prev(it) == NULL);

    if (m == NULL) {
        return;
    }

    /* TODO: Our lock areas are possibly too wide. */

    if (m->lock) {
        cb_mutex_enter(m->lock);
    }

    if (m->map != NULL) {
        /* Evict some items if necessary. */
        int i;
        for (i = 0; m->lru_tail != NULL && i < 20; i++) {
            void *last_it;
            if ((uint32_t)genhash_size(m->map) < m->max) {
                break;
            }

            last_it = m->lru_tail;

            mcache_item_unlink(m, last_it);

            if (m->key_alloc) {
                int  len = m->funcs->item_key_len(last_it);
                char buf[KEY_MAX_LENGTH + 10];
                memcpy(buf, m->funcs->item_key(last_it), len);
                buf[len] = '\0';

                genhash_delete(m->map, buf);
            } else {
                genhash_delete(m->map, m->funcs->item_key(last_it));
            }

            m->tot_evictions++;
        }

        if ((uint32_t)genhash_size(m->map) < m->max) {
            char *key     = m->funcs->item_key(it);
            int   key_len = m->funcs->item_key_len(it);
            char *key_buf = NULL;

            if (m->key_alloc) {
                /* The ITEM_key is not NULL or space terminated, */
                /* and we need a copy, too, for hashtable ownership. */

                /* TODO: Move this outside the lock area? */

                key_buf = malloc(key_len + 1);
                if (key_buf != NULL) {
                    memcpy(key_buf, key, key_len);
                    key_buf[key_len] = '\0';
                    key = key_buf;
                } else {
                    key = NULL;
                }
            }

            if (key != NULL) {
                void *existing = add_only ? genhash_find(m->map, key) : NULL;
                if (existing != NULL) {
                    mcache_item_unlink(m, existing);
                    mcache_item_touch(m, existing);

                    if (mod_exptime_if_exists) {
                        m->funcs->item_set_exptime(existing, exptime);
                    }

                    m->tot_add_skips++;

                    if (settings.verbose > 1) {
                        moxi_log_write("mcache add-skip: %s\n", key);
                    }

                    if (key_buf != NULL) {
                        free(key_buf);
                    }
                } else {
                    m->funcs->item_set_exptime(it, exptime);
                    m->funcs->item_add_ref(it);

                    genhash_update(m->map, key, it);

                    m->tot_adds++;
                    m->tot_add_bytes += m->funcs->item_len(it);

                    if (settings.verbose > 1) {
                        moxi_log_write("mcache add: %s\n", key);
                    }
                }
            } else {
                m->tot_add_fails++;
            }
        } else {
            m->tot_add_fails++;
        }
    }

    if (m->lock) {
        cb_mutex_exit(m->lock);
    }
}