mirror of
https://github.com/MariaDB/server.git
synced 2025-01-22 23:04:20 +01:00
Converted all dos files to unix format (endlines only changed)
git-svn-id: file:///svn/tokudb@4327 c7de825b-a66e-492c-adef-691d508d4ae1
This commit is contained in:
parent
6f7da78963
commit
2ef26e0057
6 changed files with 3354 additions and 3354 deletions
|
@ -1,87 +1,87 @@
|
|||
/* -*- 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."
|
||||
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <memory.h>
|
||||
#include <hashfun.h>
|
||||
#include "db_id.h"
|
||||
|
||||
|
||||
BOOL toku_db_id_equals(const toku_db_id* a, const toku_db_id* b) {
|
||||
assert(a && b);
|
||||
return a == b ||
|
||||
(a->saved_hash == b->saved_hash &&
|
||||
!strcmp(a->absolute_path, b->absolute_path) &&
|
||||
!strcmp(a->sub_database_name, b->sub_database_name));
|
||||
}
|
||||
|
||||
void toku_db_id_add_ref(toku_db_id* db_id) {
|
||||
assert(db_id);
|
||||
assert(db_id->ref_count > 0);
|
||||
db_id->ref_count++;
|
||||
}
|
||||
|
||||
static void toku_db_id_close(toku_db_id* db_id) {
|
||||
toku_free(db_id->absolute_path);
|
||||
toku_free(db_id->sub_database_name);
|
||||
toku_free(db_id);
|
||||
}
|
||||
|
||||
void toku_db_id_remove_ref(toku_db_id* db_id) {
|
||||
assert(db_id);
|
||||
assert(db_id->ref_count > 0);
|
||||
db_id->ref_count--;
|
||||
if (db_id->ref_count > 0) { return; }
|
||||
toku_db_id_close(db_id);
|
||||
}
|
||||
|
||||
int toku_db_id_create(toku_db_id** pdbid, const char* path,
|
||||
const char* sub_database_name) {
|
||||
int r = ENOSYS;
|
||||
assert(sub_database_name);
|
||||
toku_db_id* db_id = NULL;
|
||||
|
||||
db_id = (toku_db_id *)toku_malloc(sizeof(*db_id));
|
||||
if (!db_id) { r = ENOMEM; goto cleanup; }
|
||||
memset(db_id, 0, sizeof(*db_id));
|
||||
|
||||
db_id->absolute_path = (char *)toku_malloc((PATH_MAX + 1) * sizeof(char));
|
||||
if (!db_id->absolute_path) { r = ENOMEM; goto cleanup; }
|
||||
|
||||
/* TODO: BUG! Buffer overflow if the path > PATH_MAX. */
|
||||
if (realpath(path, db_id->absolute_path) == NULL) {
|
||||
r = errno;
|
||||
goto cleanup;
|
||||
}
|
||||
char* tmp = (char*)toku_realloc(db_id->absolute_path,
|
||||
(strlen(db_id->absolute_path) + 1) * sizeof(char));
|
||||
if (!tmp) { r = ENOMEM; goto cleanup; }
|
||||
db_id->absolute_path = tmp;
|
||||
|
||||
db_id->sub_database_name = toku_strdup(sub_database_name);
|
||||
if (!db_id->sub_database_name) { r = ENOMEM; goto cleanup; }
|
||||
|
||||
db_id->saved_hash = hash_key((unsigned char*)db_id->absolute_path,
|
||||
strlen(db_id->absolute_path));
|
||||
db_id->saved_hash = hash_key_extend(db_id->saved_hash,
|
||||
(unsigned char*)db_id->sub_database_name,
|
||||
strlen(db_id->sub_database_name));
|
||||
|
||||
db_id->ref_count = 1;
|
||||
*pdbid = db_id;
|
||||
r = 0;
|
||||
cleanup:
|
||||
if (r != 0) {
|
||||
if (db_id != NULL) {
|
||||
if (db_id->absolute_path) { toku_free(db_id->absolute_path); }
|
||||
if (db_id->sub_database_name) { toku_free(db_id->sub_database_name); }
|
||||
toku_free(db_id);
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
/* -*- 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."
|
||||
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <memory.h>
|
||||
#include <hashfun.h>
|
||||
#include "db_id.h"
|
||||
|
||||
|
||||
BOOL toku_db_id_equals(const toku_db_id* a, const toku_db_id* b) {
|
||||
assert(a && b);
|
||||
return a == b ||
|
||||
(a->saved_hash == b->saved_hash &&
|
||||
!strcmp(a->absolute_path, b->absolute_path) &&
|
||||
!strcmp(a->sub_database_name, b->sub_database_name));
|
||||
}
|
||||
|
||||
void toku_db_id_add_ref(toku_db_id* db_id) {
|
||||
assert(db_id);
|
||||
assert(db_id->ref_count > 0);
|
||||
db_id->ref_count++;
|
||||
}
|
||||
|
||||
static void toku_db_id_close(toku_db_id* db_id) {
|
||||
toku_free(db_id->absolute_path);
|
||||
toku_free(db_id->sub_database_name);
|
||||
toku_free(db_id);
|
||||
}
|
||||
|
||||
void toku_db_id_remove_ref(toku_db_id* db_id) {
|
||||
assert(db_id);
|
||||
assert(db_id->ref_count > 0);
|
||||
db_id->ref_count--;
|
||||
if (db_id->ref_count > 0) { return; }
|
||||
toku_db_id_close(db_id);
|
||||
}
|
||||
|
||||
int toku_db_id_create(toku_db_id** pdbid, const char* path,
|
||||
const char* sub_database_name) {
|
||||
int r = ENOSYS;
|
||||
assert(sub_database_name);
|
||||
toku_db_id* db_id = NULL;
|
||||
|
||||
db_id = (toku_db_id *)toku_malloc(sizeof(*db_id));
|
||||
if (!db_id) { r = ENOMEM; goto cleanup; }
|
||||
memset(db_id, 0, sizeof(*db_id));
|
||||
|
||||
db_id->absolute_path = (char *)toku_malloc((PATH_MAX + 1) * sizeof(char));
|
||||
if (!db_id->absolute_path) { r = ENOMEM; goto cleanup; }
|
||||
|
||||
/* TODO: BUG! Buffer overflow if the path > PATH_MAX. */
|
||||
if (realpath(path, db_id->absolute_path) == NULL) {
|
||||
r = errno;
|
||||
goto cleanup;
|
||||
}
|
||||
char* tmp = (char*)toku_realloc(db_id->absolute_path,
|
||||
(strlen(db_id->absolute_path) + 1) * sizeof(char));
|
||||
if (!tmp) { r = ENOMEM; goto cleanup; }
|
||||
db_id->absolute_path = tmp;
|
||||
|
||||
db_id->sub_database_name = toku_strdup(sub_database_name);
|
||||
if (!db_id->sub_database_name) { r = ENOMEM; goto cleanup; }
|
||||
|
||||
db_id->saved_hash = hash_key((unsigned char*)db_id->absolute_path,
|
||||
strlen(db_id->absolute_path));
|
||||
db_id->saved_hash = hash_key_extend(db_id->saved_hash,
|
||||
(unsigned char*)db_id->sub_database_name,
|
||||
strlen(db_id->sub_database_name));
|
||||
|
||||
db_id->ref_count = 1;
|
||||
*pdbid = db_id;
|
||||
r = 0;
|
||||
cleanup:
|
||||
if (r != 0) {
|
||||
if (db_id != NULL) {
|
||||
if (db_id->absolute_path) { toku_free(db_id->absolute_path); }
|
||||
if (db_id->sub_database_name) { toku_free(db_id->sub_database_name); }
|
||||
toku_free(db_id);
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
|
|
@ -1,28 +1,28 @@
|
|||
/* -*- 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."
|
||||
|
||||
#include <brttypes.h>
|
||||
|
||||
#if !defined(TOKU_DB_ID_H)
|
||||
#define TOKU_DB_ID_H
|
||||
|
||||
typedef struct __toku_db_id {
|
||||
char* absolute_path;
|
||||
char* sub_database_name;
|
||||
u_int32_t saved_hash;
|
||||
u_int32_t ref_count;
|
||||
} toku_db_id;
|
||||
|
||||
/* db_id methods */
|
||||
int toku_db_id_create(toku_db_id** pdbid, const char* path,
|
||||
const char* sub_database_name);
|
||||
|
||||
BOOL toku_db_id_equals(const toku_db_id* a, const toku_db_id* b);
|
||||
|
||||
void toku_db_id_add_ref(toku_db_id* db_id);
|
||||
|
||||
void toku_db_id_remove_ref(toku_db_id* db_id);
|
||||
|
||||
#endif /* #if !defined(TOKU_DB_ID_H) */
|
||||
/* -*- 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."
|
||||
|
||||
#include <brttypes.h>
|
||||
|
||||
#if !defined(TOKU_DB_ID_H)
|
||||
#define TOKU_DB_ID_H
|
||||
|
||||
typedef struct __toku_db_id {
|
||||
char* absolute_path;
|
||||
char* sub_database_name;
|
||||
u_int32_t saved_hash;
|
||||
u_int32_t ref_count;
|
||||
} toku_db_id;
|
||||
|
||||
/* db_id methods */
|
||||
int toku_db_id_create(toku_db_id** pdbid, const char* path,
|
||||
const char* sub_database_name);
|
||||
|
||||
BOOL toku_db_id_equals(const toku_db_id* a, const toku_db_id* b);
|
||||
|
||||
void toku_db_id_add_ref(toku_db_id* db_id);
|
||||
|
||||
void toku_db_id_remove_ref(toku_db_id* db_id);
|
||||
|
||||
#endif /* #if !defined(TOKU_DB_ID_H) */
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,280 +1,280 @@
|
|||
/* -*- 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 linear.c
|
||||
\brief Range tree implementation
|
||||
|
||||
See rangetree.h for documentation on the following. */
|
||||
|
||||
//Currently this is a stub implementation just so we can write and compile tests
|
||||
//before actually implementing the range tree.
|
||||
|
||||
#include <rangetree.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
struct __toku_range_tree_local {
|
||||
//Linear version only fields:
|
||||
toku_range* ranges;
|
||||
u_int32_t ranges_len;
|
||||
};
|
||||
#include <rangetree-internal.h>
|
||||
|
||||
|
||||
static const u_int32_t minlen = 64;
|
||||
|
||||
static inline int toku__rt_decrease_capacity(toku_range_tree* tree,
|
||||
u_int32_t _num) {
|
||||
//TODO: SOME ATTRIBUTE TO REMOVE NEVER EXECUTABLE ERROR: assert(tree);
|
||||
u_int32_t num = _num < minlen ? minlen : _num;
|
||||
|
||||
if (tree->i.ranges_len >= num * 2) {
|
||||
u_int32_t temp_len = tree->i.ranges_len;
|
||||
while (temp_len >= num * 2) temp_len /= 2;
|
||||
assert(temp_len >= _num); //Sanity check.
|
||||
toku_range* temp_ranges =
|
||||
tree->realloc(tree->i.ranges, temp_len * sizeof(toku_range));
|
||||
if (!temp_ranges) return errno;
|
||||
tree->i.ranges = temp_ranges;
|
||||
tree->i.ranges_len = temp_len;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int toku__rt_increase_capacity(toku_range_tree* tree,
|
||||
u_int32_t num) {
|
||||
//TODO: SOME ATTRIBUTE TO REMOVE NEVER EXECUTABLE ERROR: assert(tree);
|
||||
if (tree->i.ranges_len < num) {
|
||||
u_int32_t temp_len = tree->i.ranges_len;
|
||||
while (temp_len < num) temp_len *= 2;
|
||||
toku_range* temp_ranges =
|
||||
tree->realloc(tree->i.ranges, temp_len * sizeof(toku_range));
|
||||
if (!temp_ranges) return errno;
|
||||
tree->i.ranges = temp_ranges;
|
||||
tree->i.ranges_len = temp_len;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline BOOL toku__rt_overlap(toku_range_tree* tree,
|
||||
toku_interval* a, toku_interval* b) {
|
||||
assert(tree);
|
||||
assert(a);
|
||||
assert(b);
|
||||
//a->left <= b->right && b->left <= a->right
|
||||
return (tree->end_cmp(a->left, b->right) <= 0 &&
|
||||
tree->end_cmp(b->left, a->right) <= 0);
|
||||
}
|
||||
|
||||
static inline BOOL toku__rt_exact(toku_range_tree* tree,
|
||||
toku_range* a, toku_range* b) {
|
||||
assert(tree);
|
||||
assert(a);
|
||||
assert(b);
|
||||
|
||||
return (tree->end_cmp (a->ends.left, b->ends.left) == 0 &&
|
||||
tree->end_cmp (a->ends.right, b->ends.right) == 0 &&
|
||||
tree->data_cmp(a->data, b->data) == 0);
|
||||
}
|
||||
|
||||
static inline int toku__rt_cmp(toku_range_tree* tree,
|
||||
toku_range* a, toku_range* b) {
|
||||
int cmp = 0;
|
||||
assert(tree);
|
||||
assert(a);
|
||||
assert(b);
|
||||
|
||||
cmp = tree->end_cmp(a->ends.left, b->ends.left);
|
||||
if (cmp!=0) { goto cleanup; }
|
||||
cmp = tree->end_cmp(a->ends.right, b->ends.right);
|
||||
if (cmp!=0) { goto cleanup; }
|
||||
cmp = tree->data_cmp(a->data, b->data);
|
||||
if (cmp!=0) { goto cleanup; }
|
||||
|
||||
cmp = 0;
|
||||
cleanup:
|
||||
return cmp;
|
||||
}
|
||||
|
||||
int toku_rt_create(toku_range_tree** ptree,
|
||||
int (*end_cmp)(const toku_point*,const toku_point*),
|
||||
int (*data_cmp)(const TXNID,const TXNID),
|
||||
BOOL allow_overlaps,
|
||||
void* (*user_malloc) (size_t),
|
||||
void (*user_free) (void*),
|
||||
void* (*user_realloc)(void*, size_t)) {
|
||||
int r;
|
||||
toku_range_tree* tmptree;
|
||||
|
||||
if (!ptree) return EINVAL;
|
||||
r = toku_rt_super_create(ptree, &tmptree, end_cmp, data_cmp, allow_overlaps,
|
||||
user_malloc, user_free, user_realloc);
|
||||
if (0) {
|
||||
died1:
|
||||
user_free(tmptree);
|
||||
return r;
|
||||
}
|
||||
if (r!=0) return r;
|
||||
|
||||
//Any local initializers go here.
|
||||
tmptree->i.ranges_len = minlen;
|
||||
tmptree->i.ranges = (toku_range*)
|
||||
user_malloc(tmptree->i.ranges_len * sizeof(toku_range));
|
||||
if (!tmptree->i.ranges) { r = errno; goto died1; }
|
||||
|
||||
*ptree = tmptree;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void toku_rt_clear(toku_range_tree* tree) {
|
||||
assert(tree);
|
||||
toku__rt_decrease_capacity(tree, 0);
|
||||
tree->numelements = 0;
|
||||
}
|
||||
|
||||
int toku_rt_close(toku_range_tree* tree) {
|
||||
if (!tree) return EINVAL;
|
||||
tree->free(tree->i.ranges);
|
||||
tree->free(tree);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int toku_rt_find(toku_range_tree* tree, toku_interval* query, u_int32_t k,
|
||||
toku_range** buf, u_int32_t* buflen, u_int32_t* numfound) {
|
||||
if (!tree || !query || !buf || !buflen || !numfound) return EINVAL;
|
||||
if (*buflen == 0) return EINVAL;
|
||||
|
||||
u_int32_t temp_numfound = 0;
|
||||
int r;
|
||||
u_int32_t i;
|
||||
|
||||
for (i = 0; i < tree->numelements; i++) {
|
||||
if (toku__rt_overlap(tree, query, &tree->i.ranges[i].ends)) {
|
||||
r = toku__rt_increase_buffer(tree, buf, buflen, temp_numfound + 1);
|
||||
if (r != 0) return r;
|
||||
(*buf)[temp_numfound++] = tree->i.ranges[i];
|
||||
//k == 0 means limit of infinity, this is not a bug.
|
||||
if (temp_numfound == k) break;
|
||||
}
|
||||
}
|
||||
*numfound = temp_numfound;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int toku_rt_insert(toku_range_tree* tree, toku_range* range) {
|
||||
if (!tree || !range) return EINVAL;
|
||||
|
||||
u_int32_t i;
|
||||
u_int32_t move;
|
||||
int r;
|
||||
|
||||
//EDOM cases
|
||||
if (tree->allow_overlaps) {
|
||||
for (i = 0; i < tree->numelements; i++) {
|
||||
if (toku__rt_exact (tree, range, &tree->i.ranges[i])) return EDOM;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (i = 0; i < tree->numelements; i++) {
|
||||
if (toku__rt_overlap(tree, &range->ends, &tree->i.ranges[i].ends)) return EDOM;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < tree->numelements; i++) {
|
||||
if (toku__rt_cmp(tree, range, &tree->i.ranges[i]) > 0) { break; }
|
||||
}
|
||||
/* Goes in slot 'i' */
|
||||
r = toku__rt_increase_capacity(tree, tree->numelements + 1);
|
||||
if (r != 0) return r;
|
||||
tree->numelements++;
|
||||
/* Shift to make room. */
|
||||
for (move = tree->numelements - 1; move > i; move--) {
|
||||
tree->i.ranges[move] = tree->i.ranges[move - 1];
|
||||
}
|
||||
tree->i.ranges[i] = *range;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int toku_rt_delete(toku_range_tree* tree, toku_range* range) {
|
||||
if (!tree || !range) return EINVAL;
|
||||
u_int32_t i;
|
||||
u_int32_t move;
|
||||
|
||||
for (i = 0;
|
||||
i < tree->numelements &&
|
||||
!toku__rt_exact(tree, range, &(tree->i.ranges[i]));
|
||||
i++) {}
|
||||
//EDOM case: Not Found
|
||||
if (i == tree->numelements) return EDOM;
|
||||
/* Shift left. */
|
||||
for (move = i; move < tree->numelements - 1; move++) {
|
||||
tree->i.ranges[move] = tree->i.ranges[move + 1];
|
||||
}
|
||||
toku__rt_decrease_capacity(tree, --tree->numelements);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int toku_rt_predecessor (toku_range_tree* tree, toku_point* point,
|
||||
toku_range* pred, BOOL* wasfound) {
|
||||
if (!tree || !point || !pred || !wasfound) return EINVAL;
|
||||
if (tree->allow_overlaps) return EINVAL;
|
||||
toku_range* best = NULL;
|
||||
u_int32_t i;
|
||||
|
||||
for (i = 0; i < tree->numelements; i++) {
|
||||
if (toku__rt_p_cmp(tree, point, &tree->i.ranges[i].ends) > 0 &&
|
||||
(!best || tree->end_cmp(best->ends.left, tree->i.ranges[i].ends.left) < 0)) {
|
||||
best = &tree->i.ranges[i];
|
||||
}
|
||||
}
|
||||
*wasfound = best != NULL;
|
||||
if (best) *pred = *best;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int toku_rt_successor (toku_range_tree* tree, toku_point* point,
|
||||
toku_range* succ, BOOL* wasfound) {
|
||||
if (!tree || !point || !succ || !wasfound) return EINVAL;
|
||||
if (tree->allow_overlaps) return EINVAL;
|
||||
toku_range* best = NULL;
|
||||
u_int32_t i;
|
||||
|
||||
for (i = 0; i < tree->numelements; i++) {
|
||||
if (toku__rt_p_cmp(tree, point, &tree->i.ranges[i].ends) < 0 &&
|
||||
(!best || tree->end_cmp(best->ends.left, tree->i.ranges[i].ends.left) > 0)) {
|
||||
best = &tree->i.ranges[i];
|
||||
}
|
||||
}
|
||||
*wasfound = best != NULL;
|
||||
if (best) *succ = *best;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int toku_rt_get_allow_overlaps(toku_range_tree* tree, BOOL* allowed) {
|
||||
if (!tree || !allowed) return EINVAL;
|
||||
*allowed = tree->allow_overlaps;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int toku_rt_get_size(toku_range_tree* tree, u_int32_t* size) {
|
||||
if (!tree || !size) return EINVAL;
|
||||
*size = tree->numelements;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int toku_rt_iterate(toku_range_tree* tree, int (*f)(toku_range*,void*), void* extra) {
|
||||
u_int32_t index;
|
||||
|
||||
int r = ENOSYS;
|
||||
for (index = 0; index < tree->numelements; index++) {
|
||||
if ((r = f(&tree->i.ranges[index], extra))) goto cleanup;
|
||||
}
|
||||
r = 0;
|
||||
cleanup:
|
||||
return r;
|
||||
}
|
||||
|
||||
/* -*- 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 linear.c
|
||||
\brief Range tree implementation
|
||||
|
||||
See rangetree.h for documentation on the following. */
|
||||
|
||||
//Currently this is a stub implementation just so we can write and compile tests
|
||||
//before actually implementing the range tree.
|
||||
|
||||
#include <rangetree.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
struct __toku_range_tree_local {
|
||||
//Linear version only fields:
|
||||
toku_range* ranges;
|
||||
u_int32_t ranges_len;
|
||||
};
|
||||
#include <rangetree-internal.h>
|
||||
|
||||
|
||||
static const u_int32_t minlen = 64;
|
||||
|
||||
static inline int toku__rt_decrease_capacity(toku_range_tree* tree,
|
||||
u_int32_t _num) {
|
||||
//TODO: SOME ATTRIBUTE TO REMOVE NEVER EXECUTABLE ERROR: assert(tree);
|
||||
u_int32_t num = _num < minlen ? minlen : _num;
|
||||
|
||||
if (tree->i.ranges_len >= num * 2) {
|
||||
u_int32_t temp_len = tree->i.ranges_len;
|
||||
while (temp_len >= num * 2) temp_len /= 2;
|
||||
assert(temp_len >= _num); //Sanity check.
|
||||
toku_range* temp_ranges =
|
||||
tree->realloc(tree->i.ranges, temp_len * sizeof(toku_range));
|
||||
if (!temp_ranges) return errno;
|
||||
tree->i.ranges = temp_ranges;
|
||||
tree->i.ranges_len = temp_len;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int toku__rt_increase_capacity(toku_range_tree* tree,
|
||||
u_int32_t num) {
|
||||
//TODO: SOME ATTRIBUTE TO REMOVE NEVER EXECUTABLE ERROR: assert(tree);
|
||||
if (tree->i.ranges_len < num) {
|
||||
u_int32_t temp_len = tree->i.ranges_len;
|
||||
while (temp_len < num) temp_len *= 2;
|
||||
toku_range* temp_ranges =
|
||||
tree->realloc(tree->i.ranges, temp_len * sizeof(toku_range));
|
||||
if (!temp_ranges) return errno;
|
||||
tree->i.ranges = temp_ranges;
|
||||
tree->i.ranges_len = temp_len;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline BOOL toku__rt_overlap(toku_range_tree* tree,
|
||||
toku_interval* a, toku_interval* b) {
|
||||
assert(tree);
|
||||
assert(a);
|
||||
assert(b);
|
||||
//a->left <= b->right && b->left <= a->right
|
||||
return (tree->end_cmp(a->left, b->right) <= 0 &&
|
||||
tree->end_cmp(b->left, a->right) <= 0);
|
||||
}
|
||||
|
||||
static inline BOOL toku__rt_exact(toku_range_tree* tree,
|
||||
toku_range* a, toku_range* b) {
|
||||
assert(tree);
|
||||
assert(a);
|
||||
assert(b);
|
||||
|
||||
return (tree->end_cmp (a->ends.left, b->ends.left) == 0 &&
|
||||
tree->end_cmp (a->ends.right, b->ends.right) == 0 &&
|
||||
tree->data_cmp(a->data, b->data) == 0);
|
||||
}
|
||||
|
||||
static inline int toku__rt_cmp(toku_range_tree* tree,
|
||||
toku_range* a, toku_range* b) {
|
||||
int cmp = 0;
|
||||
assert(tree);
|
||||
assert(a);
|
||||
assert(b);
|
||||
|
||||
cmp = tree->end_cmp(a->ends.left, b->ends.left);
|
||||
if (cmp!=0) { goto cleanup; }
|
||||
cmp = tree->end_cmp(a->ends.right, b->ends.right);
|
||||
if (cmp!=0) { goto cleanup; }
|
||||
cmp = tree->data_cmp(a->data, b->data);
|
||||
if (cmp!=0) { goto cleanup; }
|
||||
|
||||
cmp = 0;
|
||||
cleanup:
|
||||
return cmp;
|
||||
}
|
||||
|
||||
int toku_rt_create(toku_range_tree** ptree,
|
||||
int (*end_cmp)(const toku_point*,const toku_point*),
|
||||
int (*data_cmp)(const TXNID,const TXNID),
|
||||
BOOL allow_overlaps,
|
||||
void* (*user_malloc) (size_t),
|
||||
void (*user_free) (void*),
|
||||
void* (*user_realloc)(void*, size_t)) {
|
||||
int r;
|
||||
toku_range_tree* tmptree;
|
||||
|
||||
if (!ptree) return EINVAL;
|
||||
r = toku_rt_super_create(ptree, &tmptree, end_cmp, data_cmp, allow_overlaps,
|
||||
user_malloc, user_free, user_realloc);
|
||||
if (0) {
|
||||
died1:
|
||||
user_free(tmptree);
|
||||
return r;
|
||||
}
|
||||
if (r!=0) return r;
|
||||
|
||||
//Any local initializers go here.
|
||||
tmptree->i.ranges_len = minlen;
|
||||
tmptree->i.ranges = (toku_range*)
|
||||
user_malloc(tmptree->i.ranges_len * sizeof(toku_range));
|
||||
if (!tmptree->i.ranges) { r = errno; goto died1; }
|
||||
|
||||
*ptree = tmptree;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void toku_rt_clear(toku_range_tree* tree) {
|
||||
assert(tree);
|
||||
toku__rt_decrease_capacity(tree, 0);
|
||||
tree->numelements = 0;
|
||||
}
|
||||
|
||||
int toku_rt_close(toku_range_tree* tree) {
|
||||
if (!tree) return EINVAL;
|
||||
tree->free(tree->i.ranges);
|
||||
tree->free(tree);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int toku_rt_find(toku_range_tree* tree, toku_interval* query, u_int32_t k,
|
||||
toku_range** buf, u_int32_t* buflen, u_int32_t* numfound) {
|
||||
if (!tree || !query || !buf || !buflen || !numfound) return EINVAL;
|
||||
if (*buflen == 0) return EINVAL;
|
||||
|
||||
u_int32_t temp_numfound = 0;
|
||||
int r;
|
||||
u_int32_t i;
|
||||
|
||||
for (i = 0; i < tree->numelements; i++) {
|
||||
if (toku__rt_overlap(tree, query, &tree->i.ranges[i].ends)) {
|
||||
r = toku__rt_increase_buffer(tree, buf, buflen, temp_numfound + 1);
|
||||
if (r != 0) return r;
|
||||
(*buf)[temp_numfound++] = tree->i.ranges[i];
|
||||
//k == 0 means limit of infinity, this is not a bug.
|
||||
if (temp_numfound == k) break;
|
||||
}
|
||||
}
|
||||
*numfound = temp_numfound;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int toku_rt_insert(toku_range_tree* tree, toku_range* range) {
|
||||
if (!tree || !range) return EINVAL;
|
||||
|
||||
u_int32_t i;
|
||||
u_int32_t move;
|
||||
int r;
|
||||
|
||||
//EDOM cases
|
||||
if (tree->allow_overlaps) {
|
||||
for (i = 0; i < tree->numelements; i++) {
|
||||
if (toku__rt_exact (tree, range, &tree->i.ranges[i])) return EDOM;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (i = 0; i < tree->numelements; i++) {
|
||||
if (toku__rt_overlap(tree, &range->ends, &tree->i.ranges[i].ends)) return EDOM;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < tree->numelements; i++) {
|
||||
if (toku__rt_cmp(tree, range, &tree->i.ranges[i]) > 0) { break; }
|
||||
}
|
||||
/* Goes in slot 'i' */
|
||||
r = toku__rt_increase_capacity(tree, tree->numelements + 1);
|
||||
if (r != 0) return r;
|
||||
tree->numelements++;
|
||||
/* Shift to make room. */
|
||||
for (move = tree->numelements - 1; move > i; move--) {
|
||||
tree->i.ranges[move] = tree->i.ranges[move - 1];
|
||||
}
|
||||
tree->i.ranges[i] = *range;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int toku_rt_delete(toku_range_tree* tree, toku_range* range) {
|
||||
if (!tree || !range) return EINVAL;
|
||||
u_int32_t i;
|
||||
u_int32_t move;
|
||||
|
||||
for (i = 0;
|
||||
i < tree->numelements &&
|
||||
!toku__rt_exact(tree, range, &(tree->i.ranges[i]));
|
||||
i++) {}
|
||||
//EDOM case: Not Found
|
||||
if (i == tree->numelements) return EDOM;
|
||||
/* Shift left. */
|
||||
for (move = i; move < tree->numelements - 1; move++) {
|
||||
tree->i.ranges[move] = tree->i.ranges[move + 1];
|
||||
}
|
||||
toku__rt_decrease_capacity(tree, --tree->numelements);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int toku_rt_predecessor (toku_range_tree* tree, toku_point* point,
|
||||
toku_range* pred, BOOL* wasfound) {
|
||||
if (!tree || !point || !pred || !wasfound) return EINVAL;
|
||||
if (tree->allow_overlaps) return EINVAL;
|
||||
toku_range* best = NULL;
|
||||
u_int32_t i;
|
||||
|
||||
for (i = 0; i < tree->numelements; i++) {
|
||||
if (toku__rt_p_cmp(tree, point, &tree->i.ranges[i].ends) > 0 &&
|
||||
(!best || tree->end_cmp(best->ends.left, tree->i.ranges[i].ends.left) < 0)) {
|
||||
best = &tree->i.ranges[i];
|
||||
}
|
||||
}
|
||||
*wasfound = best != NULL;
|
||||
if (best) *pred = *best;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int toku_rt_successor (toku_range_tree* tree, toku_point* point,
|
||||
toku_range* succ, BOOL* wasfound) {
|
||||
if (!tree || !point || !succ || !wasfound) return EINVAL;
|
||||
if (tree->allow_overlaps) return EINVAL;
|
||||
toku_range* best = NULL;
|
||||
u_int32_t i;
|
||||
|
||||
for (i = 0; i < tree->numelements; i++) {
|
||||
if (toku__rt_p_cmp(tree, point, &tree->i.ranges[i].ends) < 0 &&
|
||||
(!best || tree->end_cmp(best->ends.left, tree->i.ranges[i].ends.left) > 0)) {
|
||||
best = &tree->i.ranges[i];
|
||||
}
|
||||
}
|
||||
*wasfound = best != NULL;
|
||||
if (best) *succ = *best;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int toku_rt_get_allow_overlaps(toku_range_tree* tree, BOOL* allowed) {
|
||||
if (!tree || !allowed) return EINVAL;
|
||||
*allowed = tree->allow_overlaps;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int toku_rt_get_size(toku_range_tree* tree, u_int32_t* size) {
|
||||
if (!tree || !size) return EINVAL;
|
||||
*size = tree->numelements;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int toku_rt_iterate(toku_range_tree* tree, int (*f)(toku_range*,void*), void* extra) {
|
||||
u_int32_t index;
|
||||
|
||||
int r = ENOSYS;
|
||||
for (index = 0; index < tree->numelements; index++) {
|
||||
if ((r = f(&tree->i.ranges[index], extra))) goto cleanup;
|
||||
}
|
||||
r = 0;
|
||||
cleanup:
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,298 +1,298 @@
|
|||
/* -*- 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 linear.c
|
||||
\brief Range tree implementation
|
||||
|
||||
See rangetree.h for documentation on the following. */
|
||||
|
||||
//Currently this is a stub implementation just so we can write and compile tests
|
||||
//before actually implementing the range tree.
|
||||
|
||||
#include <rangetree.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
typedef toku_range *OMTVALUE;
|
||||
#include "../../newbrt/omt.h"
|
||||
|
||||
struct __toku_range_tree_local {
|
||||
//Logarithmic non-overlapping version only fields:
|
||||
OMT omt;
|
||||
};
|
||||
#include <rangetree-internal.h>
|
||||
|
||||
|
||||
int toku_rt_create(toku_range_tree** ptree,
|
||||
int (*end_cmp)(const toku_point*,const toku_point*),
|
||||
int (*data_cmp)(const TXNID,const TXNID),
|
||||
BOOL allow_overlaps,
|
||||
void* (*user_malloc) (size_t),
|
||||
void (*user_free) (void*),
|
||||
void* (*user_realloc)(void*, size_t)) {
|
||||
int r = ENOSYS;
|
||||
toku_range_tree* temptree = NULL;
|
||||
|
||||
if (allow_overlaps) return EINVAL;
|
||||
r = toku_rt_super_create(ptree, &temptree, end_cmp, data_cmp, allow_overlaps,
|
||||
user_malloc, user_free, user_realloc);
|
||||
if (r!=0) { goto cleanup; }
|
||||
|
||||
//Any local initializers go here.
|
||||
r = toku_omt_create(&temptree->i.omt);
|
||||
if (r!=0) { goto cleanup; }
|
||||
|
||||
*ptree = temptree;
|
||||
r = 0;
|
||||
cleanup:
|
||||
if (r!=0) {
|
||||
if (temptree) user_free(temptree);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
static int rt_clear_helper(OMTVALUE value, u_int32_t UU(index), void* extra) {
|
||||
void (*user_free)(void*) = extra;
|
||||
user_free(value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int toku_rt_close(toku_range_tree* tree) {
|
||||
if (!tree) { return EINVAL; }
|
||||
int r = toku_omt_iterate(tree->i.omt, rt_clear_helper, tree->free);
|
||||
assert(r==0);
|
||||
toku_omt_destroy(&tree->i.omt);
|
||||
tree->free(tree);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void toku_rt_clear(toku_range_tree* tree) {
|
||||
assert(tree);
|
||||
int r = toku_omt_iterate(tree->i.omt, rt_clear_helper, tree->free);
|
||||
assert(r==0);
|
||||
toku_omt_clear(tree->i.omt);
|
||||
tree->numelements = 0;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
int (*end_cmp)(const toku_point*,const toku_point*);
|
||||
toku_interval query;
|
||||
} rt_heavi_extra;
|
||||
|
||||
static int rt_heaviside(OMTVALUE candidate, void* extra) {
|
||||
toku_range* range_candidate = candidate;
|
||||
rt_heavi_extra* info = extra;
|
||||
|
||||
if (info->end_cmp(range_candidate->ends.right, info->query.left) < 0) return -1;
|
||||
if (info->end_cmp(range_candidate->ends.left, info->query.right) > 0) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
int (*end_cmp)(const toku_point*,const toku_point*);
|
||||
toku_interval query;
|
||||
u_int32_t k;
|
||||
u_int32_t numfound;
|
||||
toku_range_tree* rt;
|
||||
toku_range** buf;
|
||||
u_int32_t* buflen;
|
||||
} rt_find_info;
|
||||
|
||||
static int rt_find_helper(OMTVALUE value, u_int32_t UU(index), void* extra) {
|
||||
rt_find_info* info = extra;
|
||||
toku_range* range = value;
|
||||
int r = ENOSYS;
|
||||
|
||||
if (info->end_cmp(range->ends.left, info->query.right) > 0) {
|
||||
r = TOKUDB_SUCCEEDED_EARLY;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
r = toku__rt_increase_buffer(info->rt, info->buf, info->buflen, info->numfound + 1);
|
||||
if (r!=0) goto cleanup;
|
||||
(*info->buf)[info->numfound++] = *range;
|
||||
if (info->numfound>=info->k) {
|
||||
r = TOKUDB_SUCCEEDED_EARLY;
|
||||
goto cleanup;
|
||||
}
|
||||
r = 0;
|
||||
cleanup:
|
||||
return r;
|
||||
}
|
||||
|
||||
int toku_rt_find(toku_range_tree* tree, toku_interval* query, u_int32_t k,
|
||||
toku_range** buf, u_int32_t* buflen, u_int32_t* numfound) {
|
||||
int r = ENOSYS;
|
||||
|
||||
if (!tree || !query || !buf || !buflen || !numfound || *buflen == 0) {
|
||||
r = EINVAL; goto cleanup;
|
||||
}
|
||||
assert(!tree->allow_overlaps);
|
||||
|
||||
/* k = 0 means return ALL. (infinity) */
|
||||
if (k == 0) { k = UINT32_MAX; }
|
||||
|
||||
u_int32_t leftmost;
|
||||
u_int32_t rightmost = toku_omt_size(tree->i.omt);
|
||||
rt_heavi_extra extra;
|
||||
extra.end_cmp = tree->end_cmp;
|
||||
extra.query = *query;
|
||||
|
||||
r = toku_omt_find_zero(tree->i.omt, rt_heaviside, &extra, NULL, &leftmost, NULL);
|
||||
if (r==DB_NOTFOUND) {
|
||||
/* Nothing overlaps. */
|
||||
*numfound = 0;
|
||||
r = 0;
|
||||
goto cleanup;
|
||||
}
|
||||
if (r!=0) goto cleanup;
|
||||
rt_find_info info;
|
||||
info.end_cmp = tree->end_cmp;
|
||||
info.query = *query;
|
||||
info.k = k;
|
||||
info.numfound = 0;
|
||||
info.rt = tree;
|
||||
info.buf = buf;
|
||||
info.buflen = buflen;
|
||||
|
||||
r = toku_omt_iterate_on_range(tree->i.omt, leftmost, rightmost, rt_find_helper, &info);
|
||||
if (r==TOKUDB_SUCCEEDED_EARLY) r=0;
|
||||
if (r!=0) goto cleanup;
|
||||
*numfound = info.numfound;
|
||||
r = 0;
|
||||
cleanup:
|
||||
return r;
|
||||
}
|
||||
|
||||
int toku_rt_insert(toku_range_tree* tree, toku_range* range) {
|
||||
int r = ENOSYS;
|
||||
toku_range* insert_range = NULL;
|
||||
if (!tree || !range) { r = EINVAL; goto cleanup; }
|
||||
assert(!tree->allow_overlaps);
|
||||
|
||||
u_int32_t index;
|
||||
rt_heavi_extra extra;
|
||||
extra.end_cmp = tree->end_cmp;
|
||||
extra.query = range->ends;
|
||||
|
||||
r = toku_omt_find_zero(tree->i.omt, rt_heaviside, &extra, NULL, &index, NULL);
|
||||
if (r==0) { r = EDOM; goto cleanup; }
|
||||
if (r!=DB_NOTFOUND) goto cleanup;
|
||||
insert_range = tree->malloc(sizeof(*insert_range));
|
||||
*insert_range = *range;
|
||||
if ((r = toku_omt_insert_at(tree->i.omt, insert_range, index))) goto cleanup;
|
||||
|
||||
tree->numelements++;
|
||||
r = 0;
|
||||
cleanup:
|
||||
if (r!=0) {
|
||||
if (insert_range) tree->free(insert_range);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
int toku_rt_delete(toku_range_tree* tree, toku_range* range) {
|
||||
int r = ENOSYS;
|
||||
if (!tree || !range) { r = EINVAL; goto cleanup; }
|
||||
assert(!tree->allow_overlaps);
|
||||
|
||||
OMTVALUE value = NULL;
|
||||
u_int32_t index;
|
||||
rt_heavi_extra extra;
|
||||
extra.end_cmp = tree->end_cmp;
|
||||
extra.query = range->ends;
|
||||
|
||||
r = toku_omt_find_zero(tree->i.omt, rt_heaviside, &extra, &value, &index, NULL);
|
||||
if (r!=0) { r = EDOM; goto cleanup; }
|
||||
assert(value);
|
||||
toku_range* data = value;
|
||||
if (tree->end_cmp(data->ends.left, range->ends.left) ||
|
||||
tree->end_cmp(data->ends.right, range->ends.right) ||
|
||||
tree->data_cmp(data->data, range->data)) {
|
||||
r = EDOM;
|
||||
goto cleanup;
|
||||
}
|
||||
if ((r = toku_omt_delete_at(tree->i.omt, index))) goto cleanup;
|
||||
tree->free(data);
|
||||
|
||||
tree->numelements--;
|
||||
r = 0;
|
||||
cleanup:
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline int rt_neightbor(toku_range_tree* tree, toku_point* point,
|
||||
toku_range* neighbor, BOOL* wasfound, int direction) {
|
||||
int r = ENOSYS;
|
||||
if (!tree || !point || !neighbor || !wasfound || tree->allow_overlaps) {
|
||||
r = EINVAL; goto cleanup;
|
||||
}
|
||||
u_int32_t index;
|
||||
OMTVALUE value = NULL;
|
||||
rt_heavi_extra extra;
|
||||
extra.end_cmp = tree->end_cmp;
|
||||
extra.query.left = point;
|
||||
extra.query.right = point;
|
||||
|
||||
assert(direction==1 || direction==-1);
|
||||
r = toku_omt_find(tree->i.omt, rt_heaviside, &extra, direction, &value, &index, NULL);
|
||||
if (r==DB_NOTFOUND) {
|
||||
*wasfound = FALSE;
|
||||
r = 0;
|
||||
goto cleanup;
|
||||
}
|
||||
if (r!=0) goto cleanup;
|
||||
assert(value);
|
||||
toku_range* data = value;
|
||||
*wasfound = TRUE;
|
||||
*neighbor = *data;
|
||||
r = 0;
|
||||
cleanup:
|
||||
return r;
|
||||
}
|
||||
|
||||
int toku_rt_predecessor (toku_range_tree* tree, toku_point* point,
|
||||
toku_range* pred, BOOL* wasfound) {
|
||||
return rt_neightbor(tree, point, pred, wasfound, -1);
|
||||
}
|
||||
|
||||
int toku_rt_successor (toku_range_tree* tree, toku_point* point,
|
||||
toku_range* succ, BOOL* wasfound) {
|
||||
return rt_neightbor(tree, point, succ, wasfound, 1);
|
||||
}
|
||||
|
||||
int toku_rt_get_allow_overlaps(toku_range_tree* tree, BOOL* allowed) {
|
||||
if (!tree || !allowed) return EINVAL;
|
||||
assert(!tree->allow_overlaps);
|
||||
*allowed = tree->allow_overlaps;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int toku_rt_get_size(toku_range_tree* tree, u_int32_t* size) {
|
||||
if (!tree || !size) return EINVAL;
|
||||
*size = tree->numelements;
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
int (*f)(toku_range*,void*);
|
||||
void* extra;
|
||||
} rt_iter_info;
|
||||
|
||||
static int rt_iterate_helper(OMTVALUE value, u_int32_t UU(index), void* extra) {
|
||||
rt_iter_info* info = extra;
|
||||
return info->f(value, info->extra);
|
||||
}
|
||||
|
||||
int toku_rt_iterate(toku_range_tree* tree, int (*f)(toku_range*,void*), void* extra) {
|
||||
rt_iter_info info;
|
||||
info.f = f;
|
||||
info.extra = extra;
|
||||
return toku_omt_iterate(tree->i.omt, rt_iterate_helper, &info);
|
||||
}
|
||||
|
||||
/* -*- 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 linear.c
|
||||
\brief Range tree implementation
|
||||
|
||||
See rangetree.h for documentation on the following. */
|
||||
|
||||
//Currently this is a stub implementation just so we can write and compile tests
|
||||
//before actually implementing the range tree.
|
||||
|
||||
#include <rangetree.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
typedef toku_range *OMTVALUE;
|
||||
#include "../../newbrt/omt.h"
|
||||
|
||||
struct __toku_range_tree_local {
|
||||
//Logarithmic non-overlapping version only fields:
|
||||
OMT omt;
|
||||
};
|
||||
#include <rangetree-internal.h>
|
||||
|
||||
|
||||
int toku_rt_create(toku_range_tree** ptree,
|
||||
int (*end_cmp)(const toku_point*,const toku_point*),
|
||||
int (*data_cmp)(const TXNID,const TXNID),
|
||||
BOOL allow_overlaps,
|
||||
void* (*user_malloc) (size_t),
|
||||
void (*user_free) (void*),
|
||||
void* (*user_realloc)(void*, size_t)) {
|
||||
int r = ENOSYS;
|
||||
toku_range_tree* temptree = NULL;
|
||||
|
||||
if (allow_overlaps) return EINVAL;
|
||||
r = toku_rt_super_create(ptree, &temptree, end_cmp, data_cmp, allow_overlaps,
|
||||
user_malloc, user_free, user_realloc);
|
||||
if (r!=0) { goto cleanup; }
|
||||
|
||||
//Any local initializers go here.
|
||||
r = toku_omt_create(&temptree->i.omt);
|
||||
if (r!=0) { goto cleanup; }
|
||||
|
||||
*ptree = temptree;
|
||||
r = 0;
|
||||
cleanup:
|
||||
if (r!=0) {
|
||||
if (temptree) user_free(temptree);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
static int rt_clear_helper(OMTVALUE value, u_int32_t UU(index), void* extra) {
|
||||
void (*user_free)(void*) = extra;
|
||||
user_free(value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int toku_rt_close(toku_range_tree* tree) {
|
||||
if (!tree) { return EINVAL; }
|
||||
int r = toku_omt_iterate(tree->i.omt, rt_clear_helper, tree->free);
|
||||
assert(r==0);
|
||||
toku_omt_destroy(&tree->i.omt);
|
||||
tree->free(tree);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void toku_rt_clear(toku_range_tree* tree) {
|
||||
assert(tree);
|
||||
int r = toku_omt_iterate(tree->i.omt, rt_clear_helper, tree->free);
|
||||
assert(r==0);
|
||||
toku_omt_clear(tree->i.omt);
|
||||
tree->numelements = 0;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
int (*end_cmp)(const toku_point*,const toku_point*);
|
||||
toku_interval query;
|
||||
} rt_heavi_extra;
|
||||
|
||||
static int rt_heaviside(OMTVALUE candidate, void* extra) {
|
||||
toku_range* range_candidate = candidate;
|
||||
rt_heavi_extra* info = extra;
|
||||
|
||||
if (info->end_cmp(range_candidate->ends.right, info->query.left) < 0) return -1;
|
||||
if (info->end_cmp(range_candidate->ends.left, info->query.right) > 0) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
int (*end_cmp)(const toku_point*,const toku_point*);
|
||||
toku_interval query;
|
||||
u_int32_t k;
|
||||
u_int32_t numfound;
|
||||
toku_range_tree* rt;
|
||||
toku_range** buf;
|
||||
u_int32_t* buflen;
|
||||
} rt_find_info;
|
||||
|
||||
static int rt_find_helper(OMTVALUE value, u_int32_t UU(index), void* extra) {
|
||||
rt_find_info* info = extra;
|
||||
toku_range* range = value;
|
||||
int r = ENOSYS;
|
||||
|
||||
if (info->end_cmp(range->ends.left, info->query.right) > 0) {
|
||||
r = TOKUDB_SUCCEEDED_EARLY;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
r = toku__rt_increase_buffer(info->rt, info->buf, info->buflen, info->numfound + 1);
|
||||
if (r!=0) goto cleanup;
|
||||
(*info->buf)[info->numfound++] = *range;
|
||||
if (info->numfound>=info->k) {
|
||||
r = TOKUDB_SUCCEEDED_EARLY;
|
||||
goto cleanup;
|
||||
}
|
||||
r = 0;
|
||||
cleanup:
|
||||
return r;
|
||||
}
|
||||
|
||||
int toku_rt_find(toku_range_tree* tree, toku_interval* query, u_int32_t k,
|
||||
toku_range** buf, u_int32_t* buflen, u_int32_t* numfound) {
|
||||
int r = ENOSYS;
|
||||
|
||||
if (!tree || !query || !buf || !buflen || !numfound || *buflen == 0) {
|
||||
r = EINVAL; goto cleanup;
|
||||
}
|
||||
assert(!tree->allow_overlaps);
|
||||
|
||||
/* k = 0 means return ALL. (infinity) */
|
||||
if (k == 0) { k = UINT32_MAX; }
|
||||
|
||||
u_int32_t leftmost;
|
||||
u_int32_t rightmost = toku_omt_size(tree->i.omt);
|
||||
rt_heavi_extra extra;
|
||||
extra.end_cmp = tree->end_cmp;
|
||||
extra.query = *query;
|
||||
|
||||
r = toku_omt_find_zero(tree->i.omt, rt_heaviside, &extra, NULL, &leftmost, NULL);
|
||||
if (r==DB_NOTFOUND) {
|
||||
/* Nothing overlaps. */
|
||||
*numfound = 0;
|
||||
r = 0;
|
||||
goto cleanup;
|
||||
}
|
||||
if (r!=0) goto cleanup;
|
||||
rt_find_info info;
|
||||
info.end_cmp = tree->end_cmp;
|
||||
info.query = *query;
|
||||
info.k = k;
|
||||
info.numfound = 0;
|
||||
info.rt = tree;
|
||||
info.buf = buf;
|
||||
info.buflen = buflen;
|
||||
|
||||
r = toku_omt_iterate_on_range(tree->i.omt, leftmost, rightmost, rt_find_helper, &info);
|
||||
if (r==TOKUDB_SUCCEEDED_EARLY) r=0;
|
||||
if (r!=0) goto cleanup;
|
||||
*numfound = info.numfound;
|
||||
r = 0;
|
||||
cleanup:
|
||||
return r;
|
||||
}
|
||||
|
||||
int toku_rt_insert(toku_range_tree* tree, toku_range* range) {
|
||||
int r = ENOSYS;
|
||||
toku_range* insert_range = NULL;
|
||||
if (!tree || !range) { r = EINVAL; goto cleanup; }
|
||||
assert(!tree->allow_overlaps);
|
||||
|
||||
u_int32_t index;
|
||||
rt_heavi_extra extra;
|
||||
extra.end_cmp = tree->end_cmp;
|
||||
extra.query = range->ends;
|
||||
|
||||
r = toku_omt_find_zero(tree->i.omt, rt_heaviside, &extra, NULL, &index, NULL);
|
||||
if (r==0) { r = EDOM; goto cleanup; }
|
||||
if (r!=DB_NOTFOUND) goto cleanup;
|
||||
insert_range = tree->malloc(sizeof(*insert_range));
|
||||
*insert_range = *range;
|
||||
if ((r = toku_omt_insert_at(tree->i.omt, insert_range, index))) goto cleanup;
|
||||
|
||||
tree->numelements++;
|
||||
r = 0;
|
||||
cleanup:
|
||||
if (r!=0) {
|
||||
if (insert_range) tree->free(insert_range);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
int toku_rt_delete(toku_range_tree* tree, toku_range* range) {
|
||||
int r = ENOSYS;
|
||||
if (!tree || !range) { r = EINVAL; goto cleanup; }
|
||||
assert(!tree->allow_overlaps);
|
||||
|
||||
OMTVALUE value = NULL;
|
||||
u_int32_t index;
|
||||
rt_heavi_extra extra;
|
||||
extra.end_cmp = tree->end_cmp;
|
||||
extra.query = range->ends;
|
||||
|
||||
r = toku_omt_find_zero(tree->i.omt, rt_heaviside, &extra, &value, &index, NULL);
|
||||
if (r!=0) { r = EDOM; goto cleanup; }
|
||||
assert(value);
|
||||
toku_range* data = value;
|
||||
if (tree->end_cmp(data->ends.left, range->ends.left) ||
|
||||
tree->end_cmp(data->ends.right, range->ends.right) ||
|
||||
tree->data_cmp(data->data, range->data)) {
|
||||
r = EDOM;
|
||||
goto cleanup;
|
||||
}
|
||||
if ((r = toku_omt_delete_at(tree->i.omt, index))) goto cleanup;
|
||||
tree->free(data);
|
||||
|
||||
tree->numelements--;
|
||||
r = 0;
|
||||
cleanup:
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline int rt_neightbor(toku_range_tree* tree, toku_point* point,
|
||||
toku_range* neighbor, BOOL* wasfound, int direction) {
|
||||
int r = ENOSYS;
|
||||
if (!tree || !point || !neighbor || !wasfound || tree->allow_overlaps) {
|
||||
r = EINVAL; goto cleanup;
|
||||
}
|
||||
u_int32_t index;
|
||||
OMTVALUE value = NULL;
|
||||
rt_heavi_extra extra;
|
||||
extra.end_cmp = tree->end_cmp;
|
||||
extra.query.left = point;
|
||||
extra.query.right = point;
|
||||
|
||||
assert(direction==1 || direction==-1);
|
||||
r = toku_omt_find(tree->i.omt, rt_heaviside, &extra, direction, &value, &index, NULL);
|
||||
if (r==DB_NOTFOUND) {
|
||||
*wasfound = FALSE;
|
||||
r = 0;
|
||||
goto cleanup;
|
||||
}
|
||||
if (r!=0) goto cleanup;
|
||||
assert(value);
|
||||
toku_range* data = value;
|
||||
*wasfound = TRUE;
|
||||
*neighbor = *data;
|
||||
r = 0;
|
||||
cleanup:
|
||||
return r;
|
||||
}
|
||||
|
||||
int toku_rt_predecessor (toku_range_tree* tree, toku_point* point,
|
||||
toku_range* pred, BOOL* wasfound) {
|
||||
return rt_neightbor(tree, point, pred, wasfound, -1);
|
||||
}
|
||||
|
||||
int toku_rt_successor (toku_range_tree* tree, toku_point* point,
|
||||
toku_range* succ, BOOL* wasfound) {
|
||||
return rt_neightbor(tree, point, succ, wasfound, 1);
|
||||
}
|
||||
|
||||
int toku_rt_get_allow_overlaps(toku_range_tree* tree, BOOL* allowed) {
|
||||
if (!tree || !allowed) return EINVAL;
|
||||
assert(!tree->allow_overlaps);
|
||||
*allowed = tree->allow_overlaps;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int toku_rt_get_size(toku_range_tree* tree, u_int32_t* size) {
|
||||
if (!tree || !size) return EINVAL;
|
||||
*size = tree->numelements;
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
int (*f)(toku_range*,void*);
|
||||
void* extra;
|
||||
} rt_iter_info;
|
||||
|
||||
static int rt_iterate_helper(OMTVALUE value, u_int32_t UU(index), void* extra) {
|
||||
rt_iter_info* info = extra;
|
||||
return info->f(value, info->extra);
|
||||
}
|
||||
|
||||
int toku_rt_iterate(toku_range_tree* tree, int (*f)(toku_range*,void*), void* extra) {
|
||||
rt_iter_info info;
|
||||
info.f = f;
|
||||
info.extra = extra;
|
||||
return toku_omt_iterate(tree->i.omt, rt_iterate_helper, &info);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue