Commit 58515a50 authored by Yoni Fogel's avatar Yoni Fogel

Closes 551

'Lock tree manager' object created to hold data shared by all lock trees
i.e. Current number of locks (per env) and max locks (per env)
Uses functions to change max_locks.
Added tests for lock tree manager.


git-svn-id: file:///svn/tokudb@2948 c7de825b-a66e-492c-adef-691d508d4ae1
parent 8a520dd0
......@@ -122,33 +122,111 @@ int toku__lt_point_cmp(const toku_point* x, const toku_point* y) {
toku__recreate_DBT(&point_2, y->data_payload, y->data_len));
}
static inline BOOL toku__lt_percent_ranges_free(toku_lock_tree* tree,
u_int32_t percent) {
assert(tree && tree->max_ranges && tree->num_ranges && (percent <= 100));
u_int64_t max_ranges64 = *tree->max_ranges;
return *tree->num_ranges <= max_ranges64 * (100 - percent) / 100;
/* Lock tree manager functions begin here */
int toku_ltm_create(toku_ltm** pmgr,
u_int32_t max_locks,
void* (*user_malloc) (size_t),
void (*user_free) (void*),
void* (*user_realloc)(void*, size_t)) {
int r = ENOSYS;
toku_ltm* tmp_mgr = NULL;
if (!pmgr || !max_locks || !user_malloc || !user_free || !user_realloc) {
r = EINVAL; goto cleanup;
}
tmp_mgr = (toku_ltm*)user_malloc(sizeof(*tmp_mgr));
if (!tmp_mgr) { r = ENOMEM; goto cleanup; }
memset(tmp_mgr, 0, sizeof(toku_ltm));
r = toku_ltm_set_max_locks(tmp_mgr, max_locks);
if (r!=0) { goto cleanup; }
tmp_mgr->malloc = user_malloc;
tmp_mgr->free = user_free;
tmp_mgr->realloc = user_realloc;
r = toku_lth_create(&tmp_mgr->lth, user_malloc, user_free, user_realloc);
if (r!=0) { goto cleanup; }
if (!tmp_mgr->lth) { r = ENOMEM; goto cleanup; }
r = 0;
*pmgr = tmp_mgr;
cleanup:
if (r!=0) {
if (tmp_mgr) {
if (tmp_mgr->lth) {
toku_lth_close(tmp_mgr->lth);
}
user_free(tmp_mgr);
}
}
return r;
}
int toku_ltm_close(toku_ltm* mgr) {
int r = ENOSYS;
int first_error = 0;
if (!mgr) { r = EINVAL; goto cleanup; }
toku_lth_start_scan(mgr->lth);
toku_lock_tree* lt;
while ((lt = toku_lth_next(mgr->lth)) != NULL) {
r = toku_lt_close(lt);
if (r!=0 && first_error==0) { first_error = r; }
}
toku_lth_close(mgr->lth);
mgr->free(mgr);
r = first_error;
cleanup:
return r;
}
int toku_ltm_get_max_locks(toku_ltm* mgr, u_int32_t* max_locks) {
int r = ENOSYS;
if (!mgr || !max_locks) { r = EINVAL; goto cleanup; }
*max_locks = mgr->max_locks;
r = 0;
cleanup:
return r;
}
int toku_ltm_set_max_locks(toku_ltm* mgr, u_int32_t max_locks) {
int r = ENOSYS;
if (!mgr || !max_locks) {
r = EINVAL; goto cleanup;
}
if (max_locks < mgr->curr_locks) {
r = EDOM; goto cleanup;
}
mgr->max_locks = max_locks;
r = 0;
cleanup:
return r;
}
/* Functions to update the range count and compare it with the
maximum number of ranges */
static inline BOOL toku__lt_range_test_incr(toku_lock_tree* tree, u_int32_t replace) {
assert(tree);
assert(tree->num_ranges);
assert(replace <= *tree->num_ranges);
return *tree->num_ranges - replace < *tree->max_ranges;
static inline BOOL toku__mgr_lock_test_incr(toku_ltm* tree_mgr,
u_int32_t replace_locks) {
assert(tree_mgr);
assert(replace_locks <= tree_mgr->curr_locks);
return tree_mgr->curr_locks - replace_locks < tree_mgr->max_locks;
}
static inline void toku__lt_range_incr(toku_lock_tree* tree, u_int32_t replace) {
assert(toku__lt_range_test_incr(tree, replace));
*tree->num_ranges -= replace;
*tree->num_ranges += 1;
static inline void toku__mgr_lock_incr(toku_ltm* tree_mgr, u_int32_t replace_locks) {
assert(toku__mgr_lock_test_incr(tree_mgr, replace_locks));
tree_mgr->curr_locks -= replace_locks;
tree_mgr->curr_locks += 1;
}
static inline void toku__lt_range_decr(toku_lock_tree* tree, u_int32_t ranges) {
assert(tree);
assert(tree->num_ranges);
assert(*tree->num_ranges >= ranges);
*tree->num_ranges -= ranges;
static inline void toku__mgr_lock_decr(toku_ltm* tree_mgr, u_int32_t locks) {
assert(tree_mgr);
assert(tree_mgr->curr_locks >= locks);
tree_mgr->curr_locks -= locks;
}
static inline void toku__p_free(toku_lock_tree* tree, toku_point* point) {
......@@ -656,7 +734,7 @@ static inline int toku__consolidate(toku_lock_tree* tree,
r = toku__lt_extend_extreme(tree, to_insert, &alloc_left, &alloc_right,
numfound);
if (r!=0) return r;
if (!toku__lt_range_test_incr(tree, numfound)) {
if (!toku__mgr_lock_test_incr(tree->mgr, numfound)) {
*out_of_locks = TRUE;
return 0;
}
......@@ -702,7 +780,7 @@ static inline int toku__consolidate(toku_lock_tree* tree,
if (numfound) return toku__lt_panic(tree, TOKU_LT_INCONSISTENT);
goto died2; }
#endif
toku__lt_range_incr(tree, numfound);
toku__mgr_lock_incr(tree->mgr, numfound);
return 0;
}
......@@ -924,16 +1002,15 @@ static inline int toku__lt_borderwrite_insert(toku_lock_tree* tree,
}
int toku_lt_create(toku_lock_tree** ptree, DB* db, BOOL duplicates,
int (*panic)(DB*, int), u_int32_t* max_ranges,
u_int32_t* num_ranges,
int (*panic)(DB*, int),
toku_ltm* mgr,
int (*compare_fun)(DB*,const DBT*,const DBT*),
int (*dup_compare)(DB*,const DBT*,const DBT*),
void* (*user_malloc) (size_t),
void (*user_free) (void*),
void* (*user_realloc)(void*, size_t)) {
if (!ptree || !db || !compare_fun || !dup_compare || !panic ||
!max_ranges || !num_ranges || !user_malloc || !user_free ||
!user_realloc || !*max_ranges) { return EINVAL; }
if (!ptree || !db || !mgr || !compare_fun || !dup_compare || !panic ||
!user_malloc || !user_free || !user_realloc) { return EINVAL; }
int r;
toku_lock_tree* tmp_tree = (toku_lock_tree*)user_malloc(sizeof(*tmp_tree));
......@@ -943,8 +1020,7 @@ int toku_lt_create(toku_lock_tree** ptree, DB* db, BOOL duplicates,
tmp_tree->db = db;
tmp_tree->duplicates = duplicates;
tmp_tree->panic = panic;
tmp_tree->max_ranges = max_ranges;
tmp_tree->num_ranges = num_ranges;
tmp_tree->mgr = mgr;
tmp_tree->compare_fun = compare_fun;
tmp_tree->dup_compare = dup_compare;
tmp_tree->malloc = user_malloc;
......@@ -1152,7 +1228,7 @@ static inline int toku__escalate_writes_from_border_range(toku_lock_tree* tree,
r = toku_rt_insert(self_write, border_range);
if (r != 0) { r = toku__lt_panic(tree, r); goto cleanup; }
toku__lt_range_incr(tree, numfound);
toku__mgr_lock_incr(tree->mgr, numfound);
r = 0;
cleanup:
return r;
......@@ -1198,7 +1274,7 @@ static inline int toku__escalate_reads_from_border_range(toku_lock_tree* tree,
}
}
toku__lt_range_decr(tree, removed);
toku__mgr_lock_decr(tree->mgr, removed);
r = 0;
cleanup:
return r;
......@@ -1236,7 +1312,7 @@ static int toku__do_escalation(toku_lock_tree* tree, BOOL* locks_available) {
if (r!=0) { r = toku__lt_panic(tree, r); goto cleanup; }
}
r = 0;
*locks_available = toku__lt_range_test_incr(tree, 0);
*locks_available = toku__mgr_lock_test_incr(tree->mgr, 0);
/* Escalation is allowed if 1/10th of the locks (or more) are free. */
cleanup:
if (r!=0) {
......@@ -1343,7 +1419,7 @@ static int toku__lt_try_acquire_write_lock(toku_lock_tree* tree, DB_TXN* txn,
*/
toku_range to_insert;
toku__init_insert(&to_insert, &endpoint, &endpoint, txn);
if (!toku__lt_range_test_incr(tree, 0)) {
if (!toku__mgr_lock_test_incr(tree->mgr, 0)) {
*out_of_locks = TRUE; return 0;
}
......@@ -1360,7 +1436,7 @@ static int toku__lt_try_acquire_write_lock(toku_lock_tree* tree, DB_TXN* txn,
/* Need to update borderwrite. */
r = toku__lt_borderwrite_insert(tree, &query, &to_insert);
if (r!=0) return toku__lt_panic(tree, r);
toku__lt_range_incr(tree, 0);
toku__mgr_lock_incr(tree->mgr, 0);
return 0;
}
......@@ -1589,7 +1665,7 @@ int toku_lt_unlock(toku_lock_tree* tree, DB_TXN* txn) {
if (selfread || selfwrite) toku_rth_delete(tree->rth, txn);
toku__lt_range_decr(tree, ranges);
toku__mgr_lock_decr(tree->mgr, ranges);
return 0;
......
......@@ -22,6 +22,7 @@
#include <db.h>
#include <brttypes.h>
#include <rangetree.h>
#include <lth.h>
#include <rth.h>
/** Errors returned by lock trees */
......@@ -34,7 +35,19 @@ typedef enum {
char* toku_lt_strerror(TOKU_LT_ERROR r /**< Error code */)
__attribute__((const,pure));
#if !defined(TOKU_LOCKTREE_DEFINE)
#define TOKU_LOCKTREE_DEFINE
typedef struct __toku_lock_tree toku_lock_tree;
#endif
#if !defined(TOKU_LTH_DEFINE)
#define TOKU_LTH_DEFINE
typedef struct __toku_lth toku_lth;
#endif
typedef struct __toku_ltm toku_ltm;
/** \brief The lock tree structure */
struct __toku_lock_tree {
/** The database for which this locktree will be handling locks */
......@@ -64,12 +77,10 @@ struct __toku_lock_tree {
*/
toku_range* buf;
u_int32_t buflen; /**< The length of buf */
/** The maximum number of ranges allowed. */
u_int32_t* max_ranges;
/** The current number of ranges. */
u_int32_t* num_ranges;
/** Whether lock escalation is allowed. */
BOOL lock_escalation_allowed;
/** Lock tree manager */
toku_ltm* mgr;
/** The lock callback function. */
int (*lock_callback)(DB_TXN*, toku_lock_tree*);
/** The key compare function */
......@@ -86,6 +97,20 @@ struct __toku_lock_tree {
void* (*realloc)(void*, size_t);
};
struct __toku_ltm {
/** The maximum number of locks allowed for the environment. */
u_int32_t max_locks;
/** The current number of locks for the environment. */
u_int32_t curr_locks;
/** The list of lock trees it manages. */
toku_lth* lth;
/** The user malloc function */
void* (*malloc) (size_t);
/** The user free function */
void (*free) (void*);
/** The user realloc function */
void* (*realloc)(void*, size_t);
};
extern const DBT* const toku_lt_infinity; /**< Special value denoting
+infty */
......@@ -146,8 +171,8 @@ typedef struct __toku_point toku_point;
instead.
*/
int toku_lt_create(toku_lock_tree** ptree, DB* db, BOOL duplicates,
int (*panic)(DB*, int), u_int32_t* max_locks,
u_int32_t* num_locks,
int (*panic)(DB*, int),
toku_ltm* mgr,
int (*compare_fun)(DB*,const DBT*,const DBT*),
int (*dup_compare)(DB*,const DBT*,const DBT*),
void* (*user_malloc) (size_t),
......@@ -385,4 +410,66 @@ int toku_lt_unlock(toku_lock_tree* tree, DB_TXN* txn);
int toku_lt_set_txn_add_lt_callback(toku_lock_tree* tree,
int (*callback)(DB_TXN*, toku_lock_tree*));
/* Lock tree manager functions begin here */
/**
Creates a lock tree manager..
\param pmgr A buffer for the new lock tree manager.
\param max_locks The maximum number of locks.
\param user_malloc A user provided malloc(3) function.
\param user_free A user provided free(3) function.
\param user_realloc A user provided realloc(3) function.
\return
- 0 on success.
- EINVAL if any pointer parameter is NULL.
- May return other errors due to system calls.
*/
int toku_ltm_create(toku_ltm** pmgr,
u_int32_t max_locks,
void* (*user_malloc) (size_t),
void (*user_free) (void*),
void* (*user_realloc)(void*, size_t));
/**
Closes and frees a lock tree manager..
\param mgr The lock tree manager.
\return
- 0 on success.
- EINVAL if any pointer parameter is NULL.
- May return other errors due to system calls.
*/
int toku_ltm_close(toku_ltm* mgr);
/**
Sets the maximum number of locks on the lock tree manager.
\param mgr The lock tree manager to which to set max_locks.
\param max_locks The new maximum number of locks.
\return
- 0 on success.
- EINVAL if tree is NULL or max_locks is 0
- EDOM if max_locks is less than the number of locks held by any lock tree
held by the manager
*/
int toku_ltm_set_max_locks(toku_ltm* mgr, u_int32_t max_locks);
/**
Sets the maximum number of locks on the lock tree manager.
\param mgr The lock tree manager to which to set max_locks.
\param max_locks A buffer to return the number of max locks.
\return
- 0 on success.
- EINVAL if any parameter is NULL.
*/
int toku_ltm_get_max_locks(toku_ltm* mgr, u_int32_t* max_locks);
#endif
......@@ -17,6 +17,13 @@
#include <brttypes.h>
#include <locktree.h>
#if !defined(TOKU_LOCKTREE_DEFINE)
#define TOKU_LOCKTREE_DEFINE
typedef struct __toku_lock_tree toku_lock_tree;
#endif
typedef struct __toku_lth_value toku_lth_value;
struct __toku_lth_value {
toku_lock_tree* hash_key;
......@@ -30,11 +37,15 @@ struct __toku_lth_elt {
toku_lth_elt* prev_in_iteration;
};
#if !defined(TOKU_LTH_DEFINE)
#define TOKU_LTH_DEFINE
typedef struct __toku_lth toku_lth;
#endif
struct __toku_lth {
toku_lth_elt* buckets;
uint32 num_buckets;
uint32 num_keys;
u_int32_t num_buckets;
u_int32_t num_keys;
toku_lth_elt iter_head;
toku_lth_elt* iter_curr;
BOOL iter_is_valid;
......@@ -46,6 +57,7 @@ struct __toku_lth {
void* (*realloc)(void*, size_t);
};
int toku_lth_create(toku_lth** ptable,
void* (*user_malloc) (size_t),
void (*user_free) (void*),
......
......@@ -3,13 +3,16 @@
int main() {
int r;
toku_lock_tree* lt = NULL;
toku_ltm* mgr = NULL;
DB* db = (DB*)1;
u_int32_t max_locks = 1000;
u_int32_t memcnt = 0;
BOOL duplicates;
r = toku_ltm_create(&mgr, max_locks, toku_malloc, toku_free, toku_realloc);
CKERR(r);
for (duplicates = 0; duplicates < 2; duplicates++) {
r = toku_lt_create(&lt, db, duplicates, dbpanic, &max_locks, &memcnt,
r = toku_lt_create(&lt, db, duplicates, dbpanic, mgr,
dbcmp, dbcmp, toku_malloc, toku_free, toku_realloc);
CKERR(r);
assert(lt);
......
......@@ -6,8 +6,8 @@ static DBT _key;
static DBT _data;
DBT* key;
DBT* data;
u_int32_t mem = 1000;
u_int32_t memcnt = 0;
u_int32_t max_locks = 1000;
toku_ltm* ltm = NULL;
static void do_range_test(int (*acquire)(toku_lock_tree*, DB_TXN*,
const DBT*, const DBT*,
......@@ -40,8 +40,7 @@ static void do_range_test(int (*acquire)(toku_lock_tree*, DB_TXN*,
reverse_data_l = &_data_l;
reverse_data_r = &_data_r;
}
memcnt = 0;
r = toku_lt_create(&lt, db, duplicates, dbpanic, &mem, &memcnt,
r = toku_lt_create(&lt, db, duplicates, dbpanic, ltm,
dbcmp, dbcmp, toku_malloc, toku_free, toku_realloc);
CKERR(r);
assert(lt);
......@@ -123,6 +122,7 @@ static void do_range_test(int (*acquire)(toku_lock_tree*, DB_TXN*,
lt = NULL;
}
}
static void do_point_test(int (*acquire)(toku_lock_tree*, DB_TXN*,
const DBT*, const DBT*)) {
int r;
......@@ -145,8 +145,7 @@ static void do_point_test(int (*acquire)(toku_lock_tree*, DB_TXN*,
reverse_data = &_data;
data = NULL;
}
memcnt = 0;
r = toku_lt_create(&lt, db, duplicates, dbpanic, &mem, &memcnt,
r = toku_lt_create(&lt, db, duplicates, dbpanic, ltm,
dbcmp, dbcmp, toku_malloc, toku_free, toku_realloc);
CKERR(r);
assert(lt);
......@@ -199,55 +198,77 @@ int main(int argc, const char *argv[]) {
DB* db = (DB*)1;
BOOL duplicates = FALSE;
r = toku_ltm_create(NULL, max_locks, toku_malloc, toku_free, toku_realloc);
CKERR2(r, EINVAL);
assert(ltm == NULL);
r = toku_ltm_create(&ltm, 0, toku_malloc, toku_free, toku_realloc);
CKERR2(r, EINVAL);
assert(ltm == NULL);
r = toku_ltm_create(&ltm, max_locks, NULL, toku_free, toku_realloc);
CKERR2(r, EINVAL);
assert(ltm == NULL);
r = toku_ltm_create(&ltm, max_locks, toku_malloc, NULL, toku_realloc);
CKERR2(r, EINVAL);
assert(ltm == NULL);
r = toku_ltm_create(&ltm, max_locks, toku_malloc, toku_free, NULL);
CKERR2(r, EINVAL);
assert(ltm == NULL);
/* Actually create it. */
r = toku_ltm_create(&ltm, max_locks, toku_malloc, toku_free, toku_realloc);
CKERR(r);
assert(ltm);
r = toku_ltm_set_max_locks(NULL, max_locks);
CKERR2(r, EINVAL);
r = toku_ltm_set_max_locks(ltm, 0);
CKERR2(r, EINVAL);
r = toku_ltm_set_max_locks(ltm, max_locks);
CKERR(r);
u_int32_t get_max = 73; //Some random number that isn't 0.
r = toku_ltm_get_max_locks(NULL, &get_max);
CKERR2(r, EINVAL);
assert(get_max == 73);
r = toku_ltm_get_max_locks(ltm, NULL);
CKERR2(r, EINVAL);
assert(get_max == 73);
r = toku_ltm_get_max_locks(ltm, &get_max);
CKERR(r);
assert(get_max == max_locks);
/* create tests. */
for (duplicates = 0; duplicates < 2; duplicates++) {
memcnt = 0;
r = toku_lt_create(NULL, db, duplicates, dbpanic, &mem, &memcnt,
r = toku_lt_create(NULL, db, duplicates, dbpanic, ltm,
dbcmp, dbcmp, toku_malloc, toku_free, toku_realloc);
CKERR2(r, EINVAL);
memcnt = 0;
r = toku_lt_create(&lt, NULL, duplicates, dbpanic, &mem, &memcnt,
dbcmp, dbcmp, toku_malloc, toku_free, toku_realloc);
CKERR2(r, EINVAL);
memcnt = 0;
r = toku_lt_create(&lt, db, duplicates, NULL, &mem, &memcnt,
r = toku_lt_create(&lt, NULL, duplicates, dbpanic, ltm,
dbcmp, dbcmp, toku_malloc, toku_free, toku_realloc);
CKERR2(r, EINVAL);
u_int32_t old_mem = mem;
mem = 0;
memcnt = 0;
r = toku_lt_create(&lt, db, duplicates, dbpanic, &mem, &memcnt,
r = toku_lt_create(&lt, db, duplicates, NULL, ltm,
dbcmp, dbcmp, toku_malloc, toku_free, toku_realloc);
CKERR2(r, EINVAL);
mem = old_mem;
memcnt = 0;
r = toku_lt_create(&lt, db, duplicates, dbpanic, &mem, NULL,
NULL, dbcmp, toku_malloc, toku_free, toku_realloc);
r = toku_lt_create(&lt, db, duplicates, dbpanic, NULL,
dbcmp, dbcmp, toku_malloc, toku_free, toku_realloc);
CKERR2(r, EINVAL);
memcnt = 0;
r = toku_lt_create(&lt, db, duplicates, dbpanic, &mem, &memcnt,
r = toku_lt_create(&lt, db, duplicates, dbpanic, ltm,
NULL, dbcmp, toku_malloc, toku_free, toku_realloc);
CKERR2(r, EINVAL);
memcnt = 0;
r = toku_lt_create(&lt, db, duplicates, dbpanic, &mem, &memcnt,
dbcmp, NULL,
toku_malloc, toku_free, toku_realloc);
r = toku_lt_create(&lt, db, duplicates, dbpanic, ltm,
dbcmp, NULL, toku_malloc, toku_free, toku_realloc);
CKERR2(r, EINVAL);
memcnt = 0;
r = toku_lt_create(&lt, db, duplicates, dbpanic, &mem, &memcnt,
dbcmp, dbcmp,
NULL, toku_free, toku_realloc);
r = toku_lt_create(&lt, db, duplicates, dbpanic, ltm,
dbcmp, dbcmp, NULL, toku_free, toku_realloc);
CKERR2(r, EINVAL);
memcnt = 0;
r = toku_lt_create(&lt, db, duplicates, dbpanic, &mem, &memcnt,
r = toku_lt_create(&lt, db, duplicates, dbpanic, ltm,
dbcmp, dbcmp, toku_malloc, NULL, toku_realloc);
CKERR2(r, EINVAL);
memcnt = 0;
r = toku_lt_create(&lt, db, duplicates, dbpanic, &mem, &memcnt,
r = toku_lt_create(&lt, db, duplicates, dbpanic, ltm,
dbcmp, dbcmp, toku_malloc, toku_free, NULL);
CKERR2(r, EINVAL);
}
......
......@@ -7,10 +7,10 @@ toku_range_tree* toku__lt_ifexist_selfread(toku_lock_tree* tree, DB_TXN* txn);
int r;
toku_lock_tree* lt = NULL;
toku_ltm* ltm = NULL;
DB* db = (DB*)1;
DB_TXN* txn = (DB_TXN*)1;
u_int32_t mem = 4096 * 1000;
u_int32_t memcnt = 0;
u_int32_t max_locks = 1000;
BOOL duplicates = FALSE;
int nums[100];
......@@ -47,8 +47,11 @@ void init_query(BOOL dups) {
}
void setup_tree(BOOL dups) {
memcnt = 0;
r = toku_lt_create(&lt, db, dups, dbpanic, &mem, &memcnt, dbcmp, dbcmp,
assert(!lt && !ltm);
r = toku_ltm_create(&ltm, max_locks, toku_malloc, toku_free, toku_realloc);
CKERR(r);
assert(ltm);
r = toku_lt_create(&lt, db, dups, dbpanic, ltm, dbcmp, dbcmp,
toku_malloc, toku_free, toku_realloc);
CKERR(r);
assert(lt);
......@@ -56,10 +59,13 @@ void setup_tree(BOOL dups) {
}
void close_tree(void) {
assert(lt);
assert(lt && ltm);
r = toku_lt_close(lt);
CKERR(r);
r = toku_ltm_close(ltm);
CKERR(r);
lt = NULL;
ltm = NULL;
}
typedef enum { null = -1, infinite = -2, neg_infinite = -3 } lt_infty;
......
......@@ -7,9 +7,9 @@ toku_range_tree* toku__lt_ifexist_selfread(toku_lock_tree* tree, DB_TXN* txn);
int r;
toku_lock_tree* lt = NULL;
toku_ltm* ltm = NULL;
DB* db = (DB*)1;
u_int32_t mem = 1000;
u_int32_t memcnt = 0;
u_int32_t max_locks = 1000;
BOOL duplicates = FALSE;
int nums[100];
......@@ -46,8 +46,11 @@ void init_query(BOOL dups) {
}
void setup_tree(BOOL dups) {
memcnt = 0;
r = toku_lt_create(&lt, db, dups, dbpanic, &mem, &memcnt, dbcmp, dbcmp,
assert(!lt && !ltm);
r = toku_ltm_create(&ltm, max_locks, toku_malloc, toku_free, toku_realloc);
CKERR(r);
assert(ltm);
r = toku_lt_create(&lt, db, dups, dbpanic, ltm, dbcmp, dbcmp,
toku_malloc, toku_free, toku_realloc);
CKERR(r);
assert(lt);
......@@ -55,10 +58,13 @@ void setup_tree(BOOL dups) {
}
void close_tree(void) {
assert(lt);
assert(lt && ltm);
r = toku_lt_close(lt);
CKERR(r);
r = toku_ltm_close(ltm);
CKERR(r);
lt = NULL;
ltm = NULL;
}
typedef enum { null = -1, infinite = -2, neg_infinite = -3 } lt_infty;
......
......@@ -7,9 +7,9 @@ toku_range_tree* toku__lt_ifexist_selfread(toku_lock_tree* tree, DB_TXN* txn);
int r;
toku_lock_tree* lt = NULL;
toku_ltm* ltm = NULL;
DB* db = (DB*)1;
u_int32_t max_locks = 10;
u_int32_t num_locks = 0;
BOOL duplicates = FALSE;
int nums[10000];
......@@ -46,9 +46,11 @@ void init_query(BOOL dups) {
}
void setup_tree(BOOL dups) {
num_locks = 0;
assert(lt == NULL);
r = toku_lt_create(&lt, db, dups, dbpanic, &max_locks, &num_locks, intcmp, intcmp,
assert(!lt && !ltm);
r = toku_ltm_create(&ltm, max_locks, toku_malloc, toku_free, toku_realloc);
CKERR(r);
assert(ltm);
r = toku_lt_create(&lt, db, dups, dbpanic, ltm, intcmp, intcmp,
toku_malloc, toku_free, toku_realloc);
CKERR(r);
assert(lt);
......@@ -56,10 +58,13 @@ void setup_tree(BOOL dups) {
}
void close_tree(void) {
assert(lt);
assert(lt && ltm);
r = toku_lt_close(lt);
CKERR(r);
r = toku_ltm_close(ltm);
CKERR(r);
lt = NULL;
ltm = NULL;
}
typedef enum { null = -1, infinite = -2, neg_infinite = -3 } lt_infty;
......@@ -344,9 +349,9 @@ void run_escalation_test(BOOL dups) {
lt_insert_write(dups, 0, 'a', i, i);
lt_insert_write(dups, 0, 'b', i+1, i+1);
}
lt_insert_write(dups, ENOMEM, 'a', 100, 100);
lt_insert_write(dups, ENOMEM, 'b', 100, 100);
lt_insert_write(dups, ENOMEM, 'c', 100, 100);
lt_insert_write(dups, TOKUDB_OUT_OF_LOCKS, 'a', 100, 100);
lt_insert_write(dups, TOKUDB_OUT_OF_LOCKS, 'b', 100, 100);
lt_insert_write(dups, TOKUDB_OUT_OF_LOCKS, 'c', 100, 100);
close_tree();
/* ******************** */
/*
......@@ -367,12 +372,12 @@ void run_escalation_test(BOOL dups) {
lt_insert_write(dups, 0, 'b', i+1, i+1);
}
assert(lt->lock_escalation_allowed);
lt_insert_write(dups, ENOMEM, 'a', 100, 100);
lt_insert_write(dups, ENOMEM, 'b', 100, 100);
lt_insert_write(dups, ENOMEM, 'c', 100, 100);
lt_insert_read(dups, ENOMEM, 'a', 100, 100, 100, 100);
lt_insert_read(dups, ENOMEM, 'b', 100, 100, 100, 100);
lt_insert_read(dups, ENOMEM, 'c', 100, 100, 100, 100);
lt_insert_write(dups, TOKUDB_OUT_OF_LOCKS, 'a', 100, 100);
lt_insert_write(dups, TOKUDB_OUT_OF_LOCKS, 'b', 100, 100);
lt_insert_write(dups, TOKUDB_OUT_OF_LOCKS, 'c', 100, 100);
lt_insert_read(dups, TOKUDB_OUT_OF_LOCKS, 'a', 100, 100, 100, 100);
lt_insert_read(dups, TOKUDB_OUT_OF_LOCKS, 'b', 100, 100, 100, 100);
lt_insert_read(dups, TOKUDB_OUT_OF_LOCKS, 'c', 100, 100, 100, 100);
lt_unlock('b');
assert(lt->lock_escalation_allowed);
for (i = 50; i < 1000; i++) {
......@@ -396,12 +401,12 @@ void run_escalation_test(BOOL dups) {
}
lt_insert_read (dups, 0, 'b', 5, 5, 5, 5);
lt_insert_read (dups, 0, 'b', 2, 2, 2, 2);
lt_insert_write(dups, ENOMEM, 'a', 100, 100);
lt_insert_write(dups, ENOMEM, 'b', 100, 100);
lt_insert_write(dups, ENOMEM, 'c', 100, 100);
lt_insert_read(dups, ENOMEM, 'a', 100, 100, 100, 100);
lt_insert_read(dups, ENOMEM, 'b', 100, 100, 100, 100);
lt_insert_read(dups, ENOMEM, 'c', 100, 100, 100, 100);
lt_insert_write(dups, TOKUDB_OUT_OF_LOCKS, 'a', 100, 100);
lt_insert_write(dups, TOKUDB_OUT_OF_LOCKS, 'b', 100, 100);
lt_insert_write(dups, TOKUDB_OUT_OF_LOCKS, 'c', 100, 100);
lt_insert_read(dups, TOKUDB_OUT_OF_LOCKS, 'a', 100, 100, 100, 100);
lt_insert_read(dups, TOKUDB_OUT_OF_LOCKS, 'b', 100, 100, 100, 100);
lt_insert_read(dups, TOKUDB_OUT_OF_LOCKS, 'c', 100, 100, 100, 100);
lt_unlock('b');
assert(lt->lock_escalation_allowed);
for (i = 50; i < 1000; i++) {
......@@ -425,12 +430,12 @@ void run_escalation_test(BOOL dups) {
}
lt_insert_read (dups, 0, 'b', 5, 5, 6, 6);
lt_insert_read (dups, 0, 'b', 2, 2, 3, 3);
lt_insert_write(dups, ENOMEM, 'a', 100, 100);
lt_insert_write(dups, ENOMEM, 'b', 100, 100);
lt_insert_write(dups, ENOMEM, 'c', 100, 100);
lt_insert_read(dups, ENOMEM, 'a', 100, 100, 100, 100);
lt_insert_read(dups, ENOMEM, 'b', 100, 100, 100, 100);
lt_insert_read(dups, ENOMEM, 'c', 100, 100, 100, 100);
lt_insert_write(dups, TOKUDB_OUT_OF_LOCKS, 'a', 100, 100);
lt_insert_write(dups, TOKUDB_OUT_OF_LOCKS, 'b', 100, 100);
lt_insert_write(dups, TOKUDB_OUT_OF_LOCKS, 'c', 100, 100);
lt_insert_read(dups, TOKUDB_OUT_OF_LOCKS, 'a', 100, 100, 100, 100);
lt_insert_read(dups, TOKUDB_OUT_OF_LOCKS, 'b', 100, 100, 100, 100);
lt_insert_read(dups, TOKUDB_OUT_OF_LOCKS, 'c', 100, 100, 100, 100);
lt_unlock('b');
assert(lt->lock_escalation_allowed);
for (i = 50; i < 1000; i++) {
......
......@@ -7,7 +7,7 @@
#include "../newbrt/brttypes.h"
#include "../newbrt/brt.h"
#include "../newbrt/list.h"
#include "./lock_tree/lth.h"
#include "./lock_tree/locktree.h"
struct db_header {
int n_databases; // Or there can be >=1 named databases. This is the count.
......@@ -61,8 +61,7 @@ struct __toku_db_env_internal {
unsigned long cachetable_size;
CACHETABLE cachetable;
TOKULOGGER logger;
u_int32_t max_locks;
u_int32_t num_locks;
toku_ltm* ltm;
};
struct __toku_db_txn_internal {
......
......@@ -382,6 +382,7 @@ static int toku_env_close(DB_ENV * env, u_int32_t flags) {
if (env->i->tmp_dir)
toku_free(env->i->tmp_dir);
toku_free(env->i->dir);
toku_ltm_close(env->i->ltm);
toku_free(env->i);
toku_free(env);
ydb_unref();
......@@ -539,12 +540,11 @@ static int toku_env_set_lk_detect(DB_ENV * env, u_int32_t detect) {
}
static int toku_env_set_lk_max_locks(DB_ENV *dbenv, u_int32_t max) {
int r = ENOSYS;
HANDLE_PANICKED_ENV(dbenv);
if (env_opened(dbenv)) { return EINVAL; }
if (!max) { return EINVAL; }
if (max < dbenv->i->num_locks) { return EDOM; }
dbenv->i->max_locks = max;
return 0;
r = toku_ltm_set_max_locks(dbenv->i->ltm, max);
return r;
}
#if DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR <= 4
......@@ -559,9 +559,7 @@ static int locked_env_set_lk_max(DB_ENV * env, u_int32_t lk_max) {
static int toku_env_get_lk_max_locks(DB_ENV *dbenv, u_int32_t *lk_maxp) {
HANDLE_PANICKED_ENV(dbenv);
if (!lk_maxp) return EINVAL;
*lk_maxp = dbenv->i->max_locks;
return 0;
return toku_ltm_get_max_locks(dbenv->i->ltm, lk_maxp);
}
static int locked_env_set_lk_max_locks(DB_ENV *dbenv, u_int32_t max) {
......@@ -685,10 +683,12 @@ static int locked_env_txn_stat(DB_ENV * env, DB_TXN_STAT ** statp, u_int32_t fla
static int locked_txn_begin(DB_ENV * env, DB_TXN * stxn, DB_TXN ** txn, u_int32_t flags);
static int toku_env_create(DB_ENV ** envp, u_int32_t flags) {
if (flags!=0) return EINVAL;
DB_ENV *MALLOC(result);
if (result == 0)
return ENOMEM;
int r = ENOSYS;
DB_ENV* result = NULL;
if (flags!=0) { r = EINVAL; goto cleanup; }
MALLOC(result);
if (result == 0) { r = ENOMEM; goto cleanup; }
memset(result, 0, sizeof *result);
result->err = toku_locked_env_err;
result->open = locked_env_open;
......@@ -722,31 +722,40 @@ static int toku_env_create(DB_ENV ** envp, u_int32_t flags) {
result->txn_begin = locked_txn_begin;
MALLOC(result->i);
if (result->i == 0) {
toku_free(result);
return ENOMEM;
}
if (result->i == 0) { r = ENOMEM; goto cleanup; }
memset(result->i, 0, sizeof *result->i);
result->i->is_panicked=0;
result->i->ref_count = 1;
result->i->errcall = 0;
result->i->errpfx = 0;
result->i->errfile = 0;
result->i->max_locks = __toku_env_default_max_locks;
r = toku_ltm_create(&result->i->ltm, __toku_env_default_max_locks,
toku_malloc, toku_free, toku_realloc);
if (r!=0) { goto cleanup; }
{
int r = toku_logger_create(&result->i->logger);
if (r!=0) {
toku_free(result->i);
toku_free(result);
return r;
}
r = toku_logger_create(&result->i->logger);
if (r!=0) { goto cleanup; }
assert(result->i->logger);
}
ydb_add_ref();
*envp = result;
return 0;
r = 0;
cleanup:
if (r!=0) {
if (result) {
if (result->i) {
if (result->i->ltm) {
toku_ltm_close(result->i->ltm);
}
toku_free(result->i);
}
toku_free(result);
}
}
return r;
}
int db_env_create(DB_ENV ** envp, u_int32_t flags) {
......@@ -2030,8 +2039,7 @@ static int toku_db_open(DB * db, DB_TXN * txn, const char *fname, const char *db
if (need_locktree) {
r = toku_lt_create(&db->i->lt, db, FALSE,
toku_db_lt_panic, &db->dbenv->i->max_locks,
&db->dbenv->i->num_locks,
toku_db_lt_panic, db->dbenv->i->ltm,
db->i->brt->compare_fun, db->i->brt->dup_compare,
toku_malloc, toku_free, toku_realloc);
if (r!=0) goto error_cleanup;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment