1
0
mirror of https://github.com/MariaDB/server.git synced 2025-12-01 17:39:21 +03:00
Files
mariadb/src/lock_tree/lth.c
Rich Prohaska 4f46b25a02 rename to toku_portability.h addresses #1269
git-svn-id: file:///svn/toku/tokudb.1032b@7952 c7de825b-a66e-492c-adef-691d508d4ae1
2013-04-16 23:57:29 -04:00

171 lines
5.2 KiB
C

/* -*- mode: C; c-basic-offset: 4 -*- */
#ident "Copyright (c) 2007-8 Tokutek Inc. All rights reserved."
#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
/**
\file hash_lth.h
\brief Hash lth
*/
#include "toku_portability.h"
#include "lth.h"
#include <assert.h>
#include <errno.h>
#include <string.h>
/* TODO: reallocate the hash lth if it grows too big. Perhaps, use toku_get_prime in newbrt/primes.c */
const u_int32_t __toku_lth_init_size = 521;
static inline u_int32_t toku__lth_hash(toku_lth* lth, toku_lock_tree* key) {
size_t tmp = (size_t)key;
return tmp % lth->num_buckets;
}
static inline void toku__invalidate_scan(toku_lth* lth) {
lth->iter_is_valid = FALSE;
}
int toku_lth_create(toku_lth** plth,
void* (*user_malloc) (size_t),
void (*user_free) (void*),
void* (*user_realloc)(void*, size_t)) {
int r = ENOSYS;
assert(plth && user_malloc && user_free && user_realloc);
toku_lth* tmp = NULL;
tmp = (toku_lth*)user_malloc(sizeof(*tmp));
if (!tmp) { r = ENOMEM; goto cleanup; }
memset(tmp, 0, sizeof(*tmp));
tmp->malloc = user_malloc;
tmp->free = user_free;
tmp->realloc = user_realloc;
tmp->num_buckets = __toku_lth_init_size;
tmp->buckets = (toku_lth_elt*)
tmp->malloc(tmp->num_buckets * sizeof(*tmp->buckets));
if (!tmp->buckets) { r = ENOMEM; goto cleanup; }
memset(tmp->buckets, 0, tmp->num_buckets * sizeof(*tmp->buckets));
toku__invalidate_scan(tmp);
tmp->iter_head.next_in_iteration = &tmp->iter_head;
tmp->iter_head.prev_in_iteration = &tmp->iter_head;
*plth = tmp;
r = 0;
cleanup:
if (r != 0) {
if (tmp) {
if (tmp->buckets) { user_free(tmp->buckets); }
user_free(tmp);
}
}
return r;
}
toku_lock_tree* toku_lth_find(toku_lth* lth, toku_lock_tree* key) {
assert(lth && key);
u_int32_t index = toku__lth_hash(lth, key);
toku_lth_elt* head = &lth->buckets[index];
toku_lth_elt* current = head->next_in_bucket;
while (current) {
if (current->value.hash_key == key) break;
current = current->next_in_bucket;
}
return current ? current->value.hash_key : NULL;
}
void toku_lth_start_scan(toku_lth* lth) {
assert(lth);
lth->iter_curr = &lth->iter_head;
lth->iter_is_valid = TRUE;
}
static inline toku_lth_elt* toku__lth_next(toku_lth* lth) {
assert(lth);
assert(lth->iter_is_valid);
lth->iter_curr = lth->iter_curr->next_in_iteration;
lth->iter_is_valid = (BOOL)(lth->iter_curr != &lth->iter_head);
return lth->iter_curr;
}
toku_lock_tree* toku_lth_next(toku_lth* lth) {
assert(lth);
toku_lth_elt* next = toku__lth_next(lth);
return lth->iter_curr != &lth->iter_head ? next->value.hash_key : NULL;
}
/* Element MUST exist. */
void toku_lth_delete(toku_lth* lth, toku_lock_tree* key) {
assert(lth && key);
toku__invalidate_scan(lth);
/* Must have elements. */
assert(lth->num_keys);
u_int32_t index = toku__lth_hash(lth, key);
toku_lth_elt* head = &lth->buckets[index];
toku_lth_elt* prev = head;
toku_lth_elt* current = prev->next_in_bucket;
while (current != NULL) {
if (current->value.hash_key == key) break;
prev = current;
current = current->next_in_bucket;
}
/* Must be found. */
assert(current);
current->prev_in_iteration->next_in_iteration = current->next_in_iteration;
current->next_in_iteration->prev_in_iteration = current->prev_in_iteration;
prev->next_in_bucket = current->next_in_bucket;
lth->free(current);
lth->num_keys--;
return;
}
/* Will allow you to insert it over and over. You need to keep track. */
int toku_lth_insert(toku_lth* lth, toku_lock_tree* key) {
int r = ENOSYS;
assert(lth && key);
toku__invalidate_scan(lth);
u_int32_t index = toku__lth_hash(lth, key);
/* Allocate a new one. */
toku_lth_elt* element = (toku_lth_elt*)lth->malloc(sizeof(*element));
if (!element) { r = ENOMEM; goto cleanup; }
memset(element, 0, sizeof(*element));
element->value.hash_key = key;
element->next_in_iteration = lth->iter_head.next_in_iteration;
element->prev_in_iteration = &lth->iter_head;
element->next_in_iteration->prev_in_iteration = element;
element->prev_in_iteration->next_in_iteration = element;
element->next_in_bucket = lth->buckets[index].next_in_bucket;
lth->buckets[index].next_in_bucket = element;
lth->num_keys++;
r = 0;
cleanup:
return r;
}
void toku_lth_close(toku_lth* lth) {
assert(lth);
toku_lth_elt* element;
toku_lth_elt* head = &lth->iter_head;
toku_lth_elt* next = NULL;
toku_lth_start_scan(lth);
next = toku__lth_next(lth);
while (next != head) {
element = next;
next = toku__lth_next(lth);
lth->free(element);
}
lth->free(lth->buckets);
lth->free(lth);
}