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:
Yoni Fogel 2008-06-02 21:28:03 +00:00
parent 6f7da78963
commit 2ef26e0057
6 changed files with 3354 additions and 3354 deletions

View file

@ -1,87 +1,87 @@
/* -*- mode: C; c-basic-offset: 4 -*- */ /* -*- mode: C; c-basic-offset: 4 -*- */
#ident "Copyright (c) 2007-8 Tokutek Inc. All rights reserved." #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." #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 <errno.h>
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
#include <limits.h> #include <limits.h>
#include <memory.h> #include <memory.h>
#include <hashfun.h> #include <hashfun.h>
#include "db_id.h" #include "db_id.h"
BOOL toku_db_id_equals(const toku_db_id* a, const toku_db_id* b) { BOOL toku_db_id_equals(const toku_db_id* a, const toku_db_id* b) {
assert(a && b); assert(a && b);
return a == b || return a == b ||
(a->saved_hash == b->saved_hash && (a->saved_hash == b->saved_hash &&
!strcmp(a->absolute_path, b->absolute_path) && !strcmp(a->absolute_path, b->absolute_path) &&
!strcmp(a->sub_database_name, b->sub_database_name)); !strcmp(a->sub_database_name, b->sub_database_name));
} }
void toku_db_id_add_ref(toku_db_id* db_id) { void toku_db_id_add_ref(toku_db_id* db_id) {
assert(db_id); assert(db_id);
assert(db_id->ref_count > 0); assert(db_id->ref_count > 0);
db_id->ref_count++; db_id->ref_count++;
} }
static void toku_db_id_close(toku_db_id* db_id) { static void toku_db_id_close(toku_db_id* db_id) {
toku_free(db_id->absolute_path); toku_free(db_id->absolute_path);
toku_free(db_id->sub_database_name); toku_free(db_id->sub_database_name);
toku_free(db_id); toku_free(db_id);
} }
void toku_db_id_remove_ref(toku_db_id* db_id) { void toku_db_id_remove_ref(toku_db_id* db_id) {
assert(db_id); assert(db_id);
assert(db_id->ref_count > 0); assert(db_id->ref_count > 0);
db_id->ref_count--; db_id->ref_count--;
if (db_id->ref_count > 0) { return; } if (db_id->ref_count > 0) { return; }
toku_db_id_close(db_id); toku_db_id_close(db_id);
} }
int toku_db_id_create(toku_db_id** pdbid, const char* path, int toku_db_id_create(toku_db_id** pdbid, const char* path,
const char* sub_database_name) { const char* sub_database_name) {
int r = ENOSYS; int r = ENOSYS;
assert(sub_database_name); assert(sub_database_name);
toku_db_id* db_id = NULL; toku_db_id* db_id = NULL;
db_id = (toku_db_id *)toku_malloc(sizeof(*db_id)); db_id = (toku_db_id *)toku_malloc(sizeof(*db_id));
if (!db_id) { r = ENOMEM; goto cleanup; } if (!db_id) { r = ENOMEM; goto cleanup; }
memset(db_id, 0, sizeof(*db_id)); memset(db_id, 0, sizeof(*db_id));
db_id->absolute_path = (char *)toku_malloc((PATH_MAX + 1) * sizeof(char)); db_id->absolute_path = (char *)toku_malloc((PATH_MAX + 1) * sizeof(char));
if (!db_id->absolute_path) { r = ENOMEM; goto cleanup; } if (!db_id->absolute_path) { r = ENOMEM; goto cleanup; }
/* TODO: BUG! Buffer overflow if the path > PATH_MAX. */ /* TODO: BUG! Buffer overflow if the path > PATH_MAX. */
if (realpath(path, db_id->absolute_path) == NULL) { if (realpath(path, db_id->absolute_path) == NULL) {
r = errno; r = errno;
goto cleanup; goto cleanup;
} }
char* tmp = (char*)toku_realloc(db_id->absolute_path, char* tmp = (char*)toku_realloc(db_id->absolute_path,
(strlen(db_id->absolute_path) + 1) * sizeof(char)); (strlen(db_id->absolute_path) + 1) * sizeof(char));
if (!tmp) { r = ENOMEM; goto cleanup; } if (!tmp) { r = ENOMEM; goto cleanup; }
db_id->absolute_path = tmp; db_id->absolute_path = tmp;
db_id->sub_database_name = toku_strdup(sub_database_name); db_id->sub_database_name = toku_strdup(sub_database_name);
if (!db_id->sub_database_name) { r = ENOMEM; goto cleanup; } if (!db_id->sub_database_name) { r = ENOMEM; goto cleanup; }
db_id->saved_hash = hash_key((unsigned char*)db_id->absolute_path, db_id->saved_hash = hash_key((unsigned char*)db_id->absolute_path,
strlen(db_id->absolute_path)); strlen(db_id->absolute_path));
db_id->saved_hash = hash_key_extend(db_id->saved_hash, db_id->saved_hash = hash_key_extend(db_id->saved_hash,
(unsigned char*)db_id->sub_database_name, (unsigned char*)db_id->sub_database_name,
strlen(db_id->sub_database_name)); strlen(db_id->sub_database_name));
db_id->ref_count = 1; db_id->ref_count = 1;
*pdbid = db_id; *pdbid = db_id;
r = 0; r = 0;
cleanup: cleanup:
if (r != 0) { if (r != 0) {
if (db_id != NULL) { if (db_id != NULL) {
if (db_id->absolute_path) { toku_free(db_id->absolute_path); } if (db_id->absolute_path) { toku_free(db_id->absolute_path); }
if (db_id->sub_database_name) { toku_free(db_id->sub_database_name); } if (db_id->sub_database_name) { toku_free(db_id->sub_database_name); }
toku_free(db_id); toku_free(db_id);
} }
} }
return r; return r;
} }

View file

@ -1,28 +1,28 @@
/* -*- mode: C; c-basic-offset: 4 -*- */ /* -*- mode: C; c-basic-offset: 4 -*- */
#ident "Copyright (c) 2007-8 Tokutek Inc. All rights reserved." #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." #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> #include <brttypes.h>
#if !defined(TOKU_DB_ID_H) #if !defined(TOKU_DB_ID_H)
#define TOKU_DB_ID_H #define TOKU_DB_ID_H
typedef struct __toku_db_id { typedef struct __toku_db_id {
char* absolute_path; char* absolute_path;
char* sub_database_name; char* sub_database_name;
u_int32_t saved_hash; u_int32_t saved_hash;
u_int32_t ref_count; u_int32_t ref_count;
} toku_db_id; } toku_db_id;
/* db_id methods */ /* db_id methods */
int toku_db_id_create(toku_db_id** pdbid, const char* path, int toku_db_id_create(toku_db_id** pdbid, const char* path,
const char* sub_database_name); const char* sub_database_name);
BOOL toku_db_id_equals(const toku_db_id* a, const toku_db_id* b); 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_add_ref(toku_db_id* db_id);
void toku_db_id_remove_ref(toku_db_id* db_id); void toku_db_id_remove_ref(toku_db_id* db_id);
#endif /* #if !defined(TOKU_DB_ID_H) */ #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

View file

@ -1,280 +1,280 @@
/* -*- mode: C; c-basic-offset: 4 -*- */ /* -*- mode: C; c-basic-offset: 4 -*- */
#ident "Copyright (c) 2007-8 Tokutek Inc. All rights reserved." #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." #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 \file linear.c
\brief Range tree implementation \brief Range tree implementation
See rangetree.h for documentation on the following. */ See rangetree.h for documentation on the following. */
//Currently this is a stub implementation just so we can write and compile tests //Currently this is a stub implementation just so we can write and compile tests
//before actually implementing the range tree. //before actually implementing the range tree.
#include <rangetree.h> #include <rangetree.h>
#include <errno.h> #include <errno.h>
#include <assert.h> #include <assert.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
struct __toku_range_tree_local { struct __toku_range_tree_local {
//Linear version only fields: //Linear version only fields:
toku_range* ranges; toku_range* ranges;
u_int32_t ranges_len; u_int32_t ranges_len;
}; };
#include <rangetree-internal.h> #include <rangetree-internal.h>
static const u_int32_t minlen = 64; static const u_int32_t minlen = 64;
static inline int toku__rt_decrease_capacity(toku_range_tree* tree, static inline int toku__rt_decrease_capacity(toku_range_tree* tree,
u_int32_t _num) { u_int32_t _num) {
//TODO: SOME ATTRIBUTE TO REMOVE NEVER EXECUTABLE ERROR: assert(tree); //TODO: SOME ATTRIBUTE TO REMOVE NEVER EXECUTABLE ERROR: assert(tree);
u_int32_t num = _num < minlen ? minlen : _num; u_int32_t num = _num < minlen ? minlen : _num;
if (tree->i.ranges_len >= num * 2) { if (tree->i.ranges_len >= num * 2) {
u_int32_t temp_len = tree->i.ranges_len; u_int32_t temp_len = tree->i.ranges_len;
while (temp_len >= num * 2) temp_len /= 2; while (temp_len >= num * 2) temp_len /= 2;
assert(temp_len >= _num); //Sanity check. assert(temp_len >= _num); //Sanity check.
toku_range* temp_ranges = toku_range* temp_ranges =
tree->realloc(tree->i.ranges, temp_len * sizeof(toku_range)); tree->realloc(tree->i.ranges, temp_len * sizeof(toku_range));
if (!temp_ranges) return errno; if (!temp_ranges) return errno;
tree->i.ranges = temp_ranges; tree->i.ranges = temp_ranges;
tree->i.ranges_len = temp_len; tree->i.ranges_len = temp_len;
} }
return 0; return 0;
} }
static inline int toku__rt_increase_capacity(toku_range_tree* tree, static inline int toku__rt_increase_capacity(toku_range_tree* tree,
u_int32_t num) { u_int32_t num) {
//TODO: SOME ATTRIBUTE TO REMOVE NEVER EXECUTABLE ERROR: assert(tree); //TODO: SOME ATTRIBUTE TO REMOVE NEVER EXECUTABLE ERROR: assert(tree);
if (tree->i.ranges_len < num) { if (tree->i.ranges_len < num) {
u_int32_t temp_len = tree->i.ranges_len; u_int32_t temp_len = tree->i.ranges_len;
while (temp_len < num) temp_len *= 2; while (temp_len < num) temp_len *= 2;
toku_range* temp_ranges = toku_range* temp_ranges =
tree->realloc(tree->i.ranges, temp_len * sizeof(toku_range)); tree->realloc(tree->i.ranges, temp_len * sizeof(toku_range));
if (!temp_ranges) return errno; if (!temp_ranges) return errno;
tree->i.ranges = temp_ranges; tree->i.ranges = temp_ranges;
tree->i.ranges_len = temp_len; tree->i.ranges_len = temp_len;
} }
return 0; return 0;
} }
static inline BOOL toku__rt_overlap(toku_range_tree* tree, static inline BOOL toku__rt_overlap(toku_range_tree* tree,
toku_interval* a, toku_interval* b) { toku_interval* a, toku_interval* b) {
assert(tree); assert(tree);
assert(a); assert(a);
assert(b); assert(b);
//a->left <= b->right && b->left <= a->right //a->left <= b->right && b->left <= a->right
return (tree->end_cmp(a->left, b->right) <= 0 && return (tree->end_cmp(a->left, b->right) <= 0 &&
tree->end_cmp(b->left, a->right) <= 0); tree->end_cmp(b->left, a->right) <= 0);
} }
static inline BOOL toku__rt_exact(toku_range_tree* tree, static inline BOOL toku__rt_exact(toku_range_tree* tree,
toku_range* a, toku_range* b) { toku_range* a, toku_range* b) {
assert(tree); assert(tree);
assert(a); assert(a);
assert(b); assert(b);
return (tree->end_cmp (a->ends.left, b->ends.left) == 0 && return (tree->end_cmp (a->ends.left, b->ends.left) == 0 &&
tree->end_cmp (a->ends.right, b->ends.right) == 0 && tree->end_cmp (a->ends.right, b->ends.right) == 0 &&
tree->data_cmp(a->data, b->data) == 0); tree->data_cmp(a->data, b->data) == 0);
} }
static inline int toku__rt_cmp(toku_range_tree* tree, static inline int toku__rt_cmp(toku_range_tree* tree,
toku_range* a, toku_range* b) { toku_range* a, toku_range* b) {
int cmp = 0; int cmp = 0;
assert(tree); assert(tree);
assert(a); assert(a);
assert(b); assert(b);
cmp = tree->end_cmp(a->ends.left, b->ends.left); cmp = tree->end_cmp(a->ends.left, b->ends.left);
if (cmp!=0) { goto cleanup; } if (cmp!=0) { goto cleanup; }
cmp = tree->end_cmp(a->ends.right, b->ends.right); cmp = tree->end_cmp(a->ends.right, b->ends.right);
if (cmp!=0) { goto cleanup; } if (cmp!=0) { goto cleanup; }
cmp = tree->data_cmp(a->data, b->data); cmp = tree->data_cmp(a->data, b->data);
if (cmp!=0) { goto cleanup; } if (cmp!=0) { goto cleanup; }
cmp = 0; cmp = 0;
cleanup: cleanup:
return cmp; return cmp;
} }
int toku_rt_create(toku_range_tree** ptree, int toku_rt_create(toku_range_tree** ptree,
int (*end_cmp)(const toku_point*,const toku_point*), int (*end_cmp)(const toku_point*,const toku_point*),
int (*data_cmp)(const TXNID,const TXNID), int (*data_cmp)(const TXNID,const TXNID),
BOOL allow_overlaps, BOOL allow_overlaps,
void* (*user_malloc) (size_t), void* (*user_malloc) (size_t),
void (*user_free) (void*), void (*user_free) (void*),
void* (*user_realloc)(void*, size_t)) { void* (*user_realloc)(void*, size_t)) {
int r; int r;
toku_range_tree* tmptree; toku_range_tree* tmptree;
if (!ptree) return EINVAL; if (!ptree) return EINVAL;
r = toku_rt_super_create(ptree, &tmptree, end_cmp, data_cmp, allow_overlaps, r = toku_rt_super_create(ptree, &tmptree, end_cmp, data_cmp, allow_overlaps,
user_malloc, user_free, user_realloc); user_malloc, user_free, user_realloc);
if (0) { if (0) {
died1: died1:
user_free(tmptree); user_free(tmptree);
return r; return r;
} }
if (r!=0) return r; if (r!=0) return r;
//Any local initializers go here. //Any local initializers go here.
tmptree->i.ranges_len = minlen; tmptree->i.ranges_len = minlen;
tmptree->i.ranges = (toku_range*) tmptree->i.ranges = (toku_range*)
user_malloc(tmptree->i.ranges_len * sizeof(toku_range)); user_malloc(tmptree->i.ranges_len * sizeof(toku_range));
if (!tmptree->i.ranges) { r = errno; goto died1; } if (!tmptree->i.ranges) { r = errno; goto died1; }
*ptree = tmptree; *ptree = tmptree;
return 0; return 0;
} }
void toku_rt_clear(toku_range_tree* tree) { void toku_rt_clear(toku_range_tree* tree) {
assert(tree); assert(tree);
toku__rt_decrease_capacity(tree, 0); toku__rt_decrease_capacity(tree, 0);
tree->numelements = 0; tree->numelements = 0;
} }
int toku_rt_close(toku_range_tree* tree) { int toku_rt_close(toku_range_tree* tree) {
if (!tree) return EINVAL; if (!tree) return EINVAL;
tree->free(tree->i.ranges); tree->free(tree->i.ranges);
tree->free(tree); tree->free(tree);
return 0; return 0;
} }
int toku_rt_find(toku_range_tree* tree, toku_interval* query, u_int32_t k, 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) { toku_range** buf, u_int32_t* buflen, u_int32_t* numfound) {
if (!tree || !query || !buf || !buflen || !numfound) return EINVAL; if (!tree || !query || !buf || !buflen || !numfound) return EINVAL;
if (*buflen == 0) return EINVAL; if (*buflen == 0) return EINVAL;
u_int32_t temp_numfound = 0; u_int32_t temp_numfound = 0;
int r; int r;
u_int32_t i; u_int32_t i;
for (i = 0; i < tree->numelements; i++) { for (i = 0; i < tree->numelements; i++) {
if (toku__rt_overlap(tree, query, &tree->i.ranges[i].ends)) { if (toku__rt_overlap(tree, query, &tree->i.ranges[i].ends)) {
r = toku__rt_increase_buffer(tree, buf, buflen, temp_numfound + 1); r = toku__rt_increase_buffer(tree, buf, buflen, temp_numfound + 1);
if (r != 0) return r; if (r != 0) return r;
(*buf)[temp_numfound++] = tree->i.ranges[i]; (*buf)[temp_numfound++] = tree->i.ranges[i];
//k == 0 means limit of infinity, this is not a bug. //k == 0 means limit of infinity, this is not a bug.
if (temp_numfound == k) break; if (temp_numfound == k) break;
} }
} }
*numfound = temp_numfound; *numfound = temp_numfound;
return 0; return 0;
} }
int toku_rt_insert(toku_range_tree* tree, toku_range* range) { int toku_rt_insert(toku_range_tree* tree, toku_range* range) {
if (!tree || !range) return EINVAL; if (!tree || !range) return EINVAL;
u_int32_t i; u_int32_t i;
u_int32_t move; u_int32_t move;
int r; int r;
//EDOM cases //EDOM cases
if (tree->allow_overlaps) { if (tree->allow_overlaps) {
for (i = 0; i < tree->numelements; i++) { for (i = 0; i < tree->numelements; i++) {
if (toku__rt_exact (tree, range, &tree->i.ranges[i])) return EDOM; if (toku__rt_exact (tree, range, &tree->i.ranges[i])) return EDOM;
} }
} }
else { else {
for (i = 0; i < tree->numelements; i++) { for (i = 0; i < tree->numelements; i++) {
if (toku__rt_overlap(tree, &range->ends, &tree->i.ranges[i].ends)) return EDOM; if (toku__rt_overlap(tree, &range->ends, &tree->i.ranges[i].ends)) return EDOM;
} }
} }
for (i = 0; i < tree->numelements; i++) { for (i = 0; i < tree->numelements; i++) {
if (toku__rt_cmp(tree, range, &tree->i.ranges[i]) > 0) { break; } if (toku__rt_cmp(tree, range, &tree->i.ranges[i]) > 0) { break; }
} }
/* Goes in slot 'i' */ /* Goes in slot 'i' */
r = toku__rt_increase_capacity(tree, tree->numelements + 1); r = toku__rt_increase_capacity(tree, tree->numelements + 1);
if (r != 0) return r; if (r != 0) return r;
tree->numelements++; tree->numelements++;
/* Shift to make room. */ /* Shift to make room. */
for (move = tree->numelements - 1; move > i; move--) { for (move = tree->numelements - 1; move > i; move--) {
tree->i.ranges[move] = tree->i.ranges[move - 1]; tree->i.ranges[move] = tree->i.ranges[move - 1];
} }
tree->i.ranges[i] = *range; tree->i.ranges[i] = *range;
return 0; return 0;
} }
int toku_rt_delete(toku_range_tree* tree, toku_range* range) { int toku_rt_delete(toku_range_tree* tree, toku_range* range) {
if (!tree || !range) return EINVAL; if (!tree || !range) return EINVAL;
u_int32_t i; u_int32_t i;
u_int32_t move; u_int32_t move;
for (i = 0; for (i = 0;
i < tree->numelements && i < tree->numelements &&
!toku__rt_exact(tree, range, &(tree->i.ranges[i])); !toku__rt_exact(tree, range, &(tree->i.ranges[i]));
i++) {} i++) {}
//EDOM case: Not Found //EDOM case: Not Found
if (i == tree->numelements) return EDOM; if (i == tree->numelements) return EDOM;
/* Shift left. */ /* Shift left. */
for (move = i; move < tree->numelements - 1; move++) { for (move = i; move < tree->numelements - 1; move++) {
tree->i.ranges[move] = tree->i.ranges[move + 1]; tree->i.ranges[move] = tree->i.ranges[move + 1];
} }
toku__rt_decrease_capacity(tree, --tree->numelements); toku__rt_decrease_capacity(tree, --tree->numelements);
return 0; return 0;
} }
int toku_rt_predecessor (toku_range_tree* tree, toku_point* point, int toku_rt_predecessor (toku_range_tree* tree, toku_point* point,
toku_range* pred, BOOL* wasfound) { toku_range* pred, BOOL* wasfound) {
if (!tree || !point || !pred || !wasfound) return EINVAL; if (!tree || !point || !pred || !wasfound) return EINVAL;
if (tree->allow_overlaps) return EINVAL; if (tree->allow_overlaps) return EINVAL;
toku_range* best = NULL; toku_range* best = NULL;
u_int32_t i; u_int32_t i;
for (i = 0; i < tree->numelements; i++) { for (i = 0; i < tree->numelements; i++) {
if (toku__rt_p_cmp(tree, point, &tree->i.ranges[i].ends) > 0 && 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->end_cmp(best->ends.left, tree->i.ranges[i].ends.left) < 0)) {
best = &tree->i.ranges[i]; best = &tree->i.ranges[i];
} }
} }
*wasfound = best != NULL; *wasfound = best != NULL;
if (best) *pred = *best; if (best) *pred = *best;
return 0; return 0;
} }
int toku_rt_successor (toku_range_tree* tree, toku_point* point, int toku_rt_successor (toku_range_tree* tree, toku_point* point,
toku_range* succ, BOOL* wasfound) { toku_range* succ, BOOL* wasfound) {
if (!tree || !point || !succ || !wasfound) return EINVAL; if (!tree || !point || !succ || !wasfound) return EINVAL;
if (tree->allow_overlaps) return EINVAL; if (tree->allow_overlaps) return EINVAL;
toku_range* best = NULL; toku_range* best = NULL;
u_int32_t i; u_int32_t i;
for (i = 0; i < tree->numelements; i++) { for (i = 0; i < tree->numelements; i++) {
if (toku__rt_p_cmp(tree, point, &tree->i.ranges[i].ends) < 0 && 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->end_cmp(best->ends.left, tree->i.ranges[i].ends.left) > 0)) {
best = &tree->i.ranges[i]; best = &tree->i.ranges[i];
} }
} }
*wasfound = best != NULL; *wasfound = best != NULL;
if (best) *succ = *best; if (best) *succ = *best;
return 0; return 0;
} }
int toku_rt_get_allow_overlaps(toku_range_tree* tree, BOOL* allowed) { int toku_rt_get_allow_overlaps(toku_range_tree* tree, BOOL* allowed) {
if (!tree || !allowed) return EINVAL; if (!tree || !allowed) return EINVAL;
*allowed = tree->allow_overlaps; *allowed = tree->allow_overlaps;
return 0; return 0;
} }
int toku_rt_get_size(toku_range_tree* tree, u_int32_t* size) { int toku_rt_get_size(toku_range_tree* tree, u_int32_t* size) {
if (!tree || !size) return EINVAL; if (!tree || !size) return EINVAL;
*size = tree->numelements; *size = tree->numelements;
return 0; return 0;
} }
int toku_rt_iterate(toku_range_tree* tree, int (*f)(toku_range*,void*), void* extra) { int toku_rt_iterate(toku_range_tree* tree, int (*f)(toku_range*,void*), void* extra) {
u_int32_t index; u_int32_t index;
int r = ENOSYS; int r = ENOSYS;
for (index = 0; index < tree->numelements; index++) { for (index = 0; index < tree->numelements; index++) {
if ((r = f(&tree->i.ranges[index], extra))) goto cleanup; if ((r = f(&tree->i.ranges[index], extra))) goto cleanup;
} }
r = 0; r = 0;
cleanup: cleanup:
return r; return r;
} }

View file

@ -1,298 +1,298 @@
/* -*- mode: C; c-basic-offset: 4 -*- */ /* -*- mode: C; c-basic-offset: 4 -*- */
#ident "Copyright (c) 2007-8 Tokutek Inc. All rights reserved." #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." #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 \file linear.c
\brief Range tree implementation \brief Range tree implementation
See rangetree.h for documentation on the following. */ See rangetree.h for documentation on the following. */
//Currently this is a stub implementation just so we can write and compile tests //Currently this is a stub implementation just so we can write and compile tests
//before actually implementing the range tree. //before actually implementing the range tree.
#include <rangetree.h> #include <rangetree.h>
#include <errno.h> #include <errno.h>
#include <assert.h> #include <assert.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
typedef toku_range *OMTVALUE; typedef toku_range *OMTVALUE;
#include "../../newbrt/omt.h" #include "../../newbrt/omt.h"
struct __toku_range_tree_local { struct __toku_range_tree_local {
//Logarithmic non-overlapping version only fields: //Logarithmic non-overlapping version only fields:
OMT omt; OMT omt;
}; };
#include <rangetree-internal.h> #include <rangetree-internal.h>
int toku_rt_create(toku_range_tree** ptree, int toku_rt_create(toku_range_tree** ptree,
int (*end_cmp)(const toku_point*,const toku_point*), int (*end_cmp)(const toku_point*,const toku_point*),
int (*data_cmp)(const TXNID,const TXNID), int (*data_cmp)(const TXNID,const TXNID),
BOOL allow_overlaps, BOOL allow_overlaps,
void* (*user_malloc) (size_t), void* (*user_malloc) (size_t),
void (*user_free) (void*), void (*user_free) (void*),
void* (*user_realloc)(void*, size_t)) { void* (*user_realloc)(void*, size_t)) {
int r = ENOSYS; int r = ENOSYS;
toku_range_tree* temptree = NULL; toku_range_tree* temptree = NULL;
if (allow_overlaps) return EINVAL; if (allow_overlaps) return EINVAL;
r = toku_rt_super_create(ptree, &temptree, end_cmp, data_cmp, allow_overlaps, r = toku_rt_super_create(ptree, &temptree, end_cmp, data_cmp, allow_overlaps,
user_malloc, user_free, user_realloc); user_malloc, user_free, user_realloc);
if (r!=0) { goto cleanup; } if (r!=0) { goto cleanup; }
//Any local initializers go here. //Any local initializers go here.
r = toku_omt_create(&temptree->i.omt); r = toku_omt_create(&temptree->i.omt);
if (r!=0) { goto cleanup; } if (r!=0) { goto cleanup; }
*ptree = temptree; *ptree = temptree;
r = 0; r = 0;
cleanup: cleanup:
if (r!=0) { if (r!=0) {
if (temptree) user_free(temptree); if (temptree) user_free(temptree);
} }
return r; return r;
} }
static int rt_clear_helper(OMTVALUE value, u_int32_t UU(index), void* extra) { static int rt_clear_helper(OMTVALUE value, u_int32_t UU(index), void* extra) {
void (*user_free)(void*) = extra; void (*user_free)(void*) = extra;
user_free(value); user_free(value);
return 0; return 0;
} }
int toku_rt_close(toku_range_tree* tree) { int toku_rt_close(toku_range_tree* tree) {
if (!tree) { return EINVAL; } if (!tree) { return EINVAL; }
int r = toku_omt_iterate(tree->i.omt, rt_clear_helper, tree->free); int r = toku_omt_iterate(tree->i.omt, rt_clear_helper, tree->free);
assert(r==0); assert(r==0);
toku_omt_destroy(&tree->i.omt); toku_omt_destroy(&tree->i.omt);
tree->free(tree); tree->free(tree);
return 0; return 0;
} }
void toku_rt_clear(toku_range_tree* tree) { void toku_rt_clear(toku_range_tree* tree) {
assert(tree); assert(tree);
int r = toku_omt_iterate(tree->i.omt, rt_clear_helper, tree->free); int r = toku_omt_iterate(tree->i.omt, rt_clear_helper, tree->free);
assert(r==0); assert(r==0);
toku_omt_clear(tree->i.omt); toku_omt_clear(tree->i.omt);
tree->numelements = 0; tree->numelements = 0;
} }
typedef struct { typedef struct {
int (*end_cmp)(const toku_point*,const toku_point*); int (*end_cmp)(const toku_point*,const toku_point*);
toku_interval query; toku_interval query;
} rt_heavi_extra; } rt_heavi_extra;
static int rt_heaviside(OMTVALUE candidate, void* extra) { static int rt_heaviside(OMTVALUE candidate, void* extra) {
toku_range* range_candidate = candidate; toku_range* range_candidate = candidate;
rt_heavi_extra* info = extra; 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.right, info->query.left) < 0) return -1;
if (info->end_cmp(range_candidate->ends.left, info->query.right) > 0) return 1; if (info->end_cmp(range_candidate->ends.left, info->query.right) > 0) return 1;
return 0; return 0;
} }
typedef struct { typedef struct {
int (*end_cmp)(const toku_point*,const toku_point*); int (*end_cmp)(const toku_point*,const toku_point*);
toku_interval query; toku_interval query;
u_int32_t k; u_int32_t k;
u_int32_t numfound; u_int32_t numfound;
toku_range_tree* rt; toku_range_tree* rt;
toku_range** buf; toku_range** buf;
u_int32_t* buflen; u_int32_t* buflen;
} rt_find_info; } rt_find_info;
static int rt_find_helper(OMTVALUE value, u_int32_t UU(index), void* extra) { static int rt_find_helper(OMTVALUE value, u_int32_t UU(index), void* extra) {
rt_find_info* info = extra; rt_find_info* info = extra;
toku_range* range = value; toku_range* range = value;
int r = ENOSYS; int r = ENOSYS;
if (info->end_cmp(range->ends.left, info->query.right) > 0) { if (info->end_cmp(range->ends.left, info->query.right) > 0) {
r = TOKUDB_SUCCEEDED_EARLY; r = TOKUDB_SUCCEEDED_EARLY;
goto cleanup; goto cleanup;
} }
r = toku__rt_increase_buffer(info->rt, info->buf, info->buflen, info->numfound + 1); r = toku__rt_increase_buffer(info->rt, info->buf, info->buflen, info->numfound + 1);
if (r!=0) goto cleanup; if (r!=0) goto cleanup;
(*info->buf)[info->numfound++] = *range; (*info->buf)[info->numfound++] = *range;
if (info->numfound>=info->k) { if (info->numfound>=info->k) {
r = TOKUDB_SUCCEEDED_EARLY; r = TOKUDB_SUCCEEDED_EARLY;
goto cleanup; goto cleanup;
} }
r = 0; r = 0;
cleanup: cleanup:
return r; return r;
} }
int toku_rt_find(toku_range_tree* tree, toku_interval* query, u_int32_t k, 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) { toku_range** buf, u_int32_t* buflen, u_int32_t* numfound) {
int r = ENOSYS; int r = ENOSYS;
if (!tree || !query || !buf || !buflen || !numfound || *buflen == 0) { if (!tree || !query || !buf || !buflen || !numfound || *buflen == 0) {
r = EINVAL; goto cleanup; r = EINVAL; goto cleanup;
} }
assert(!tree->allow_overlaps); assert(!tree->allow_overlaps);
/* k = 0 means return ALL. (infinity) */ /* k = 0 means return ALL. (infinity) */
if (k == 0) { k = UINT32_MAX; } if (k == 0) { k = UINT32_MAX; }
u_int32_t leftmost; u_int32_t leftmost;
u_int32_t rightmost = toku_omt_size(tree->i.omt); u_int32_t rightmost = toku_omt_size(tree->i.omt);
rt_heavi_extra extra; rt_heavi_extra extra;
extra.end_cmp = tree->end_cmp; extra.end_cmp = tree->end_cmp;
extra.query = *query; extra.query = *query;
r = toku_omt_find_zero(tree->i.omt, rt_heaviside, &extra, NULL, &leftmost, NULL); r = toku_omt_find_zero(tree->i.omt, rt_heaviside, &extra, NULL, &leftmost, NULL);
if (r==DB_NOTFOUND) { if (r==DB_NOTFOUND) {
/* Nothing overlaps. */ /* Nothing overlaps. */
*numfound = 0; *numfound = 0;
r = 0; r = 0;
goto cleanup; goto cleanup;
} }
if (r!=0) goto cleanup; if (r!=0) goto cleanup;
rt_find_info info; rt_find_info info;
info.end_cmp = tree->end_cmp; info.end_cmp = tree->end_cmp;
info.query = *query; info.query = *query;
info.k = k; info.k = k;
info.numfound = 0; info.numfound = 0;
info.rt = tree; info.rt = tree;
info.buf = buf; info.buf = buf;
info.buflen = buflen; info.buflen = buflen;
r = toku_omt_iterate_on_range(tree->i.omt, leftmost, rightmost, rt_find_helper, &info); r = toku_omt_iterate_on_range(tree->i.omt, leftmost, rightmost, rt_find_helper, &info);
if (r==TOKUDB_SUCCEEDED_EARLY) r=0; if (r==TOKUDB_SUCCEEDED_EARLY) r=0;
if (r!=0) goto cleanup; if (r!=0) goto cleanup;
*numfound = info.numfound; *numfound = info.numfound;
r = 0; r = 0;
cleanup: cleanup:
return r; return r;
} }
int toku_rt_insert(toku_range_tree* tree, toku_range* range) { int toku_rt_insert(toku_range_tree* tree, toku_range* range) {
int r = ENOSYS; int r = ENOSYS;
toku_range* insert_range = NULL; toku_range* insert_range = NULL;
if (!tree || !range) { r = EINVAL; goto cleanup; } if (!tree || !range) { r = EINVAL; goto cleanup; }
assert(!tree->allow_overlaps); assert(!tree->allow_overlaps);
u_int32_t index; u_int32_t index;
rt_heavi_extra extra; rt_heavi_extra extra;
extra.end_cmp = tree->end_cmp; extra.end_cmp = tree->end_cmp;
extra.query = range->ends; extra.query = range->ends;
r = toku_omt_find_zero(tree->i.omt, rt_heaviside, &extra, NULL, &index, NULL); r = toku_omt_find_zero(tree->i.omt, rt_heaviside, &extra, NULL, &index, NULL);
if (r==0) { r = EDOM; goto cleanup; } if (r==0) { r = EDOM; goto cleanup; }
if (r!=DB_NOTFOUND) goto cleanup; if (r!=DB_NOTFOUND) goto cleanup;
insert_range = tree->malloc(sizeof(*insert_range)); insert_range = tree->malloc(sizeof(*insert_range));
*insert_range = *range; *insert_range = *range;
if ((r = toku_omt_insert_at(tree->i.omt, insert_range, index))) goto cleanup; if ((r = toku_omt_insert_at(tree->i.omt, insert_range, index))) goto cleanup;
tree->numelements++; tree->numelements++;
r = 0; r = 0;
cleanup: cleanup:
if (r!=0) { if (r!=0) {
if (insert_range) tree->free(insert_range); if (insert_range) tree->free(insert_range);
} }
return r; return r;
} }
int toku_rt_delete(toku_range_tree* tree, toku_range* range) { int toku_rt_delete(toku_range_tree* tree, toku_range* range) {
int r = ENOSYS; int r = ENOSYS;
if (!tree || !range) { r = EINVAL; goto cleanup; } if (!tree || !range) { r = EINVAL; goto cleanup; }
assert(!tree->allow_overlaps); assert(!tree->allow_overlaps);
OMTVALUE value = NULL; OMTVALUE value = NULL;
u_int32_t index; u_int32_t index;
rt_heavi_extra extra; rt_heavi_extra extra;
extra.end_cmp = tree->end_cmp; extra.end_cmp = tree->end_cmp;
extra.query = range->ends; extra.query = range->ends;
r = toku_omt_find_zero(tree->i.omt, rt_heaviside, &extra, &value, &index, NULL); r = toku_omt_find_zero(tree->i.omt, rt_heaviside, &extra, &value, &index, NULL);
if (r!=0) { r = EDOM; goto cleanup; } if (r!=0) { r = EDOM; goto cleanup; }
assert(value); assert(value);
toku_range* data = value; toku_range* data = value;
if (tree->end_cmp(data->ends.left, range->ends.left) || if (tree->end_cmp(data->ends.left, range->ends.left) ||
tree->end_cmp(data->ends.right, range->ends.right) || tree->end_cmp(data->ends.right, range->ends.right) ||
tree->data_cmp(data->data, range->data)) { tree->data_cmp(data->data, range->data)) {
r = EDOM; r = EDOM;
goto cleanup; goto cleanup;
} }
if ((r = toku_omt_delete_at(tree->i.omt, index))) goto cleanup; if ((r = toku_omt_delete_at(tree->i.omt, index))) goto cleanup;
tree->free(data); tree->free(data);
tree->numelements--; tree->numelements--;
r = 0; r = 0;
cleanup: cleanup:
return r; return r;
} }
static inline int rt_neightbor(toku_range_tree* tree, toku_point* point, static inline int rt_neightbor(toku_range_tree* tree, toku_point* point,
toku_range* neighbor, BOOL* wasfound, int direction) { toku_range* neighbor, BOOL* wasfound, int direction) {
int r = ENOSYS; int r = ENOSYS;
if (!tree || !point || !neighbor || !wasfound || tree->allow_overlaps) { if (!tree || !point || !neighbor || !wasfound || tree->allow_overlaps) {
r = EINVAL; goto cleanup; r = EINVAL; goto cleanup;
} }
u_int32_t index; u_int32_t index;
OMTVALUE value = NULL; OMTVALUE value = NULL;
rt_heavi_extra extra; rt_heavi_extra extra;
extra.end_cmp = tree->end_cmp; extra.end_cmp = tree->end_cmp;
extra.query.left = point; extra.query.left = point;
extra.query.right = point; extra.query.right = point;
assert(direction==1 || direction==-1); assert(direction==1 || direction==-1);
r = toku_omt_find(tree->i.omt, rt_heaviside, &extra, direction, &value, &index, NULL); r = toku_omt_find(tree->i.omt, rt_heaviside, &extra, direction, &value, &index, NULL);
if (r==DB_NOTFOUND) { if (r==DB_NOTFOUND) {
*wasfound = FALSE; *wasfound = FALSE;
r = 0; r = 0;
goto cleanup; goto cleanup;
} }
if (r!=0) goto cleanup; if (r!=0) goto cleanup;
assert(value); assert(value);
toku_range* data = value; toku_range* data = value;
*wasfound = TRUE; *wasfound = TRUE;
*neighbor = *data; *neighbor = *data;
r = 0; r = 0;
cleanup: cleanup:
return r; return r;
} }
int toku_rt_predecessor (toku_range_tree* tree, toku_point* point, int toku_rt_predecessor (toku_range_tree* tree, toku_point* point,
toku_range* pred, BOOL* wasfound) { toku_range* pred, BOOL* wasfound) {
return rt_neightbor(tree, point, pred, wasfound, -1); return rt_neightbor(tree, point, pred, wasfound, -1);
} }
int toku_rt_successor (toku_range_tree* tree, toku_point* point, int toku_rt_successor (toku_range_tree* tree, toku_point* point,
toku_range* succ, BOOL* wasfound) { toku_range* succ, BOOL* wasfound) {
return rt_neightbor(tree, point, succ, wasfound, 1); return rt_neightbor(tree, point, succ, wasfound, 1);
} }
int toku_rt_get_allow_overlaps(toku_range_tree* tree, BOOL* allowed) { int toku_rt_get_allow_overlaps(toku_range_tree* tree, BOOL* allowed) {
if (!tree || !allowed) return EINVAL; if (!tree || !allowed) return EINVAL;
assert(!tree->allow_overlaps); assert(!tree->allow_overlaps);
*allowed = tree->allow_overlaps; *allowed = tree->allow_overlaps;
return 0; return 0;
} }
int toku_rt_get_size(toku_range_tree* tree, u_int32_t* size) { int toku_rt_get_size(toku_range_tree* tree, u_int32_t* size) {
if (!tree || !size) return EINVAL; if (!tree || !size) return EINVAL;
*size = tree->numelements; *size = tree->numelements;
return 0; return 0;
} }
typedef struct { typedef struct {
int (*f)(toku_range*,void*); int (*f)(toku_range*,void*);
void* extra; void* extra;
} rt_iter_info; } rt_iter_info;
static int rt_iterate_helper(OMTVALUE value, u_int32_t UU(index), void* extra) { static int rt_iterate_helper(OMTVALUE value, u_int32_t UU(index), void* extra) {
rt_iter_info* info = extra; rt_iter_info* info = extra;
return info->f(value, info->extra); return info->f(value, info->extra);
} }
int toku_rt_iterate(toku_range_tree* tree, int (*f)(toku_range*,void*), void* extra) { int toku_rt_iterate(toku_range_tree* tree, int (*f)(toku_range*,void*), void* extra) {
rt_iter_info info; rt_iter_info info;
info.f = f; info.f = f;
info.extra = extra; info.extra = extra;
return toku_omt_iterate(tree->i.omt, rt_iterate_helper, &info); return toku_omt_iterate(tree->i.omt, rt_iterate_helper, &info);
} }