diff --git a/lladd.pws b/lladd.pws index 8877904..87e27a4 100644 --- a/lladd.pws +++ b/lladd.pws @@ -11,15 +11,15 @@ filter.file.ignore.hidden=0 filter.dir.ignore.hidden=0 [filenumbers] -0=71 -1=97 -2=126 -3=155 -4=351 -5=67 -6=56 -7=1 -8=63 +0=135 +1=1 +2=1 +3=113 +4=51 +5=439 +6=545 +7=122 +8=30 9=1 10=67 11=1 @@ -51,13 +51,15 @@ filter.dir.ignore.hidden=0 17= [filelist] -0=/home/sears/lladd/lladd/logger/logger2.h -1=/home/sears/lladd/src/lladd/transactional2.c -2=/home/sears/lladd/src/lladd/operations.c -3=/home/sears/lladd/lladd/operations.h -4=/home/sears/lladd/test/lladd/check_operations.c -5=/home/sears/lladd/lladd/operations/nestedTopActions.h -6=/home/sears/lladd/src/lladd/operations/nestedTopActions.c +0=/home/sears/lladd/lladd/constants.h +1=/home/sears/lladd/lladd/operations.h +2=/home/sears/lladd/src/lladd/page.c +3=/home/sears/lladd/src/lladd/operations/set.c +4=/home/sears/lladd/src/lladd/operations/arrayList.c +5=/home/sears/lladd/test/lladd/check_page.c +6=/home/sears/lladd/test/lladd/check_operations.c +7=/home/sears/lladd/src/lladd/operations/alloc.c +8=/home/sears/lladd/lladd/operations/alloc.h [Project Tree] 0=0 @@ -73,11 +75,11 @@ filter.dir.ignore.hidden=0 [File Tree] 0=0 1=0:6 -2=0:6:1 -3=0:6:2 -4=0:9 -5=0:9:4 -6=0:9:4:3 +2=0:6:2 +3=0:9 +4=0:9:4 +5=0:9:4:3 +6=0:9:4:4 7=0:10 8=0:10:5 diff --git a/lladd/constants.h b/lladd/constants.h index c9b9fe4..4b1469c 100644 --- a/lladd/constants.h +++ b/lladd/constants.h @@ -118,6 +118,8 @@ terms specified in this license. #define OPERATION_UNDO_LINEAR_INSERT 24 #define OPERATION_LINEAR_DELETE 25 #define OPERATION_UNDO_LINEAR_DELETE 26 +#define OPERATION_SET_RANGE 27 +#define OPERATION_SET_RANGE_INVERSE 28 /* number above should be less than number below */ #define MAX_OPERATIONS 40 diff --git a/lladd/operations/set.h b/lladd/operations/set.h index e3bc33c..5599f36 100644 --- a/lladd/operations/set.h +++ b/lladd/operations/set.h @@ -59,4 +59,13 @@ terms specified in this license. Operation getSet(); +Operation getSetRangeInverse(); +Operation getSetRange(); +/** + @todo TsetRange is slow as implemented; although it is efficient with log + space, it performs a number of extra memcpy() calls over the entire record. +*/ +void TsetRange(int xid, recordid rid, int offset, int length, const void * dat); + + #endif diff --git a/src/lladd/operations/linearHash.c b/src/lladd/operations/linearHash.c index 9b14ec2..1fbf4a2 100644 --- a/src/lladd/operations/linearHash.c +++ b/src/lladd/operations/linearHash.c @@ -205,7 +205,7 @@ if(mycount <= 0 && !(mycount * -1) % FF_AM) { */ // int j; TarrayListInstantExtend(xid, hash, 1 /*AMORTIZE*/); - pthread_mutex_lock(&linearHashMutex); + // pthread_mutex_lock(&linearHashMutex); //Already hold this! recordid * headerRidB = pblHtLookup(openHashes, &(hash.page), sizeof(int)); diff --git a/src/lladd/operations/set.c b/src/lladd/operations/set.c index e8a79b3..08e9505 100644 --- a/src/lladd/operations/set.c +++ b/src/lladd/operations/set.c @@ -48,11 +48,83 @@ terms specified in this license. #include /*#include */ #include "../page.h" - +#include +#include static int operate(int xid, Page *p, lsn_t lsn, recordid rid, const void *dat) { writeRecord(xid, p, lsn, rid, dat); return 0; } +typedef struct { + int offset; + int realRecordLength; +} set_range_t; + +static int operateRange(int xid, Page * p, lsn_t lsn, recordid rid, const void * dat) { + int diffLength = rid.size - sizeof(set_range_t); + assert(! (diffLength % 2)); + diffLength /= 2; + const set_range_t * range = dat; + rid.size = range->realRecordLength; + + byte * data = (byte*)(range + 1); + byte * tmp = malloc(rid.size); + + readRecord(xid, p, rid, tmp); + memcpy(tmp+range->offset, data, diffLength); + writeRecord(xid, p, lsn, rid, tmp); + + free(tmp); + return 0; +} + +static int deOperateRange(int xid, Page * p, lsn_t lsn, recordid rid, const void * dat) { + int diffLength = rid.size - sizeof(set_range_t); + assert(! (diffLength % 2)); + diffLength /= 2; + + const set_range_t * range = dat; + rid.size = range->realRecordLength; + + byte * data = (byte*)(range + 1); + data += diffLength; + byte * tmp = malloc(rid.size); + + readRecord(xid, p, rid, tmp); + memcpy(tmp+range->offset, data, diffLength); + writeRecord(xid, p, lsn, rid, tmp); + + free(tmp); + return 0; +} +void TsetRange(int xid, recordid rid, int offset, int length, const void * dat) { + + set_range_t * range = malloc(sizeof(set_range_t) + 2 * length); + byte * record = malloc(rid.size); + + range->offset = offset; + range->realRecordLength = rid.size; + + // Copy new value into log structure + memcpy(range + 1, dat, length); + + Page * p = loadPage(rid.page); + // No further locking is necessary here; readRecord protects the + // page layout, but attempts at concurrent modification have undefined + // results. (See page.c) + readRecord(xid, p, rid, record); + + // Copy old value into log structure + memcpy((byte*)(range + 1) + length, record+offset, length); + + // Pass size of range into Tupdate via the recordid. + rid.size = sizeof(set_range_t) + 2 * length; + Tupdate(xid, rid, range, OPERATION_SET_RANGE); + + releasePage(p); + free(record); + free(range); + +} Operation getSet() { Operation o = { @@ -63,3 +135,23 @@ Operation getSet() { }; return o; } + +Operation getSetRange() { + Operation o = { + OPERATION_SET_RANGE, + SIZEOF_RECORD, + OPERATION_SET_RANGE_INVERSE, + &operateRange + }; + return o; +} + +Operation getSetRangeInverse() { + Operation o = { + OPERATION_SET_RANGE_INVERSE, + SIZEOF_RECORD, + OPERATION_SET_RANGE, + &deOperateRange + }; + return o; +} diff --git a/src/lladd/transactional2.c b/src/lladd/transactional2.c index 767d3f2..510f230 100644 --- a/src/lladd/transactional2.c +++ b/src/lladd/transactional2.c @@ -64,6 +64,9 @@ void setupOperationsTable() { operationsTable[OPERATION_UNDO_LINEAR_INSERT] = getUndoLinearInsert(); operationsTable[OPERATION_LINEAR_DELETE] = getLinearDelete(); operationsTable[OPERATION_UNDO_LINEAR_DELETE] = getUndoLinearDelete(); + + operationsTable[OPERATION_SET_RANGE] = getSetRange(); + operationsTable[OPERATION_SET_RANGE_INVERSE] = getSetRangeInverse(); } diff --git a/test/lladd/check_operations.c b/test/lladd/check_operations.c index 7a53e3c..e45f393 100644 --- a/test/lladd/check_operations.c +++ b/test/lladd/check_operations.c @@ -448,6 +448,64 @@ START_TEST(operation_instant_set) { } END_TEST +START_TEST(operation_set_range) { + printf("Set Range"); + Tinit(); + + int xid = Tbegin(); + + int buf1[20]; + int buf2[20]; + + int range[20]; + + recordid rid = Talloc(xid, sizeof(int) * 20); + + for(int i = 0; i < 20; i++) { + buf1[i] = i; + } + + Tset(xid, rid, buf1); + + Tcommit(xid); + + xid = Tbegin(); + + Tread(xid, rid, buf2); + for(int i = 0; i < 20; i++) { + assert(buf2[i] == i); + } + + for(int i = 0; i < 5; i++) { + range[i] = 100 + i; + } + + TsetRange(xid, rid, sizeof(int) * 10, sizeof(int) * 5, range); + // Check forward action + Tread(xid, rid, buf2); + + for(int i = 0; i < 20; i++) { + if(i < 10 || i >= 15) { + assert(buf2[i] == i); + } else { + assert(buf2[i] == 100 + i - 10); + } + } + + Tabort(xid); + + xid = Tbegin(); + + Tread(xid, rid, buf2); + //Check undo. + for(int i = 0; i < 20; i++) { + assert(buf2[i] == i); + } + + Tcommit(xid); + +} END_TEST +#define ARRAY_LIST_CHECK_ITER 10000 START_TEST(operation_array_list) { Tinit(); @@ -456,7 +514,7 @@ START_TEST(operation_array_list) { recordid rid = TarrayListAlloc(xid, 4, 2, sizeof(int)); - TarrayListExtend(xid, rid, 100000); + TarrayListExtend(xid, rid, ARRAY_LIST_CHECK_ITER); printf("commit"); fflush(stdout); @@ -471,12 +529,12 @@ START_TEST(operation_array_list) { rid2.slot = 0; rid2.size = sizeof(int); - for(int i = 0; i < 100000; i++) { + for(int i = 0; i < ARRAY_LIST_CHECK_ITER; i++) { rid2.slot = i; Tset(xid, rid2, &i); } - for(int i = 0; i < 100000; i++) { + for(int i = 0; i < ARRAY_LIST_CHECK_ITER; i++) { rid2.slot = i; int j; Tread(xid, rid2, &j); @@ -491,13 +549,13 @@ START_TEST(operation_array_list) { xid = Tbegin(); - for(int i = 0; i < 100000; i++) { + for(int i = 0; i < ARRAY_LIST_CHECK_ITER; i++) { int j = 0-i; rid2.slot = i; Tset(xid, rid2, &j); } - for(int i = 0; i < 100000; i++) { + for(int i = 0; i < ARRAY_LIST_CHECK_ITER; i++) { rid2.slot = i; int j = 0-i; int k; @@ -512,7 +570,7 @@ START_TEST(operation_array_list) { fflush(stdout); xid = Tbegin(); - for(int i = 0; i < 100000; i++) { + for(int i = 0; i < ARRAY_LIST_CHECK_ITER; i++) { rid2.slot = i; int j; Tread(xid, rid2, &j); @@ -542,6 +600,7 @@ Suite * check_suite(void) { tcase_add_test(tc, operation_physical_do_undo); tcase_add_test(tc, operation_nestedTopAction); tcase_add_test(tc, operation_instant_set); + tcase_add_test(tc, operation_set_range); tcase_add_test(tc, operation_prepare); tcase_add_test(tc, operation_array_list); /* --------------------------------------------- */