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:
Sears Russell 2010-09-01 04:01:20 +00:00
parent 3b8679d09b
commit 00e474e3fe
2 changed files with 53 additions and 3 deletions

View file

@ -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);

View file

@ -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);