Fix bug in LinearHashNTA: inserting over an old key, then aborting set deleted the old key instead of restoring it to its original value
This commit is contained in:
parent
3b8679d09b
commit
00e474e3fe
2 changed files with 53 additions and 3 deletions
|
@ -185,6 +185,8 @@ stasis_operation_impl stasis_op_impl_linear_hash_remove() {
|
|||
}
|
||||
|
||||
compensated_function int ThashInsert(int xid, recordid hashHeader, const byte* key, int keySize, const byte* value, int valueSize) {
|
||||
/* XXX slow, but doesn't generate any log entries unless the key exists */
|
||||
int ret = ThashRemove(xid, hashHeader, key, keySize);
|
||||
hashHeader.size = sizeof(lladd_hash_header);
|
||||
pthread_mutex_lock(&linear_hash_mutex);
|
||||
int argSize = sizeof(linearHash_insert_arg)+keySize;
|
||||
|
@ -193,14 +195,12 @@ compensated_function int ThashInsert(int xid, recordid hashHeader, const byte* k
|
|||
arg->keySize = keySize;
|
||||
memcpy(arg+1, key, keySize);
|
||||
|
||||
int ret;
|
||||
|
||||
/** @todo MEMORY LEAK arg, handle on pthread_cancel.. */
|
||||
void * handle;
|
||||
begin_action_ret(pthread_mutex_unlock, &linear_hash_mutex, compensation_error()) {
|
||||
handle = TbeginNestedTopAction(xid, OPERATION_LINEAR_HASH_INSERT, (byte*)arg, argSize);
|
||||
free(arg);
|
||||
ret = __ThashInsert(xid, hashHeader, key, keySize, value, valueSize);
|
||||
__ThashInsert(xid, hashHeader, key, keySize, value, valueSize);
|
||||
} end_action_ret(compensation_error());
|
||||
|
||||
TendNestedTopAction(xid, handle);
|
||||
|
|
|
@ -67,6 +67,55 @@ static int arryCmp(int * a, int * b, int len) {
|
|||
return memcmp(a,b,len);
|
||||
}
|
||||
|
||||
START_TEST(linearHashNTAabortTest) {
|
||||
Tinit();
|
||||
|
||||
int xid = Tbegin();
|
||||
recordid rid = ThashCreate(xid, -1, -1);
|
||||
assert(0 == ThashInsert(xid, rid, "foo", 4, "bar", 4));
|
||||
char * ret;
|
||||
int len = ThashLookup(xid, rid, "foo", 4, &ret);
|
||||
assert(len == 4);
|
||||
assert(!strcmp("bar", ret));
|
||||
free(ret);
|
||||
Tcommit(xid);
|
||||
|
||||
xid = Tbegin();
|
||||
|
||||
assert(1 == ThashInsert(xid, rid, "foo", 4, "baz", 4));
|
||||
assert(0 == ThashInsert(xid, rid, "bar", 4, "bat", 4));
|
||||
|
||||
len = ThashLookup(xid, rid, "foo", 4, &ret);
|
||||
assert(len == 4);
|
||||
assert(!strcmp("baz", ret));
|
||||
free(ret);
|
||||
|
||||
len = ThashLookup(xid, rid, "bar", 4, &ret);
|
||||
assert(len == 4);
|
||||
assert(!strcmp("bat", ret));
|
||||
free(ret);
|
||||
|
||||
Tabort(xid);
|
||||
|
||||
len = ThashLookup(xid, rid, "foo", 4, &ret);
|
||||
assert(len == 4);
|
||||
assert(!strcmp("bar", ret));
|
||||
free(ret);
|
||||
|
||||
/*
|
||||
assert_equal(nil, Hash.lookup( -1, rid, "bar"))
|
||||
assert_equal(0, Tdeinit)
|
||||
assert_equal(0, Tinit)
|
||||
assert_equal("bar", Hash.lookup( -1, rid, "foo"))
|
||||
assert_equal(nil, Hash.lookup( -1, rid, "bar"))
|
||||
assert_equal(0, Hash.insert(xid, rid, "bar", "bat"))
|
||||
assert_equal("bat", Hash.lookup(xid,rid,"bar"))
|
||||
assert_equal(0, Raw.Tdeinit)
|
||||
*/
|
||||
|
||||
Tdeinit();
|
||||
} END_TEST
|
||||
|
||||
/**
|
||||
@test
|
||||
*/
|
||||
|
@ -621,6 +670,7 @@ Suite * check_suite(void) {
|
|||
|
||||
tcase_set_timeout(tc, 1200); // 20 minute timeout
|
||||
/* Sub tests are added, one per line, here */
|
||||
tcase_add_test(tc, linearHashNTAabortTest);
|
||||
tcase_add_test(tc, lookupPrefix);
|
||||
tcase_add_test(tc, emptyHashIterator);
|
||||
tcase_add_test(tc, emptyHashIterator2);
|
||||
|
|
Loading…
Reference in a new issue