Implemented a linear hash from scratch. Concurrency hasn't been done, but it's probably correct in the single thread case.

This commit is contained in:
Sears Russell 2004-10-12 02:44:47 +00:00
parent 5064e3fac2
commit a078f25475
14 changed files with 674 additions and 10 deletions

View file

@ -77,8 +77,8 @@ terms specified in this license.
/* #define MAX_BUFFER_SIZE 100003 */
/*#define MAX_BUFFER_SIZE 10007*/
/*#define MAX_BUFFER_SIZE 5003*/
#define MAX_BUFFER_SIZE 2003
#define MAX_BUFFER_SIZE 5003
/*#define MAX_BUFFER_SIZE 2003 */
/* #define MAX_BUFFER_SIZE 71 */
/*#define MAX_BUFFER_SIZE 7 */
/*#define BUFFER_ASOOCIATIVE 2 */

17
lladd/crc32.h Normal file
View file

@ -0,0 +1,17 @@
/* This CRC code was taken from: http://www.axlradius.com/freestuff/crc2.c
(It is presumably in the public domain. Other files under /freestuff/ are...)
( Added a #include for this .h file. Otherwise, crc32 is a verbatim copy of the file from the internet.)
*/
/**
Usage:
unsigned long crc = -1L
crc = crc32(buffer, length, crc)
*/
unsigned long crc32(void *buffer, unsigned int count, unsigned long crc);

4
lladd/hash.h Normal file
View file

@ -0,0 +1,4 @@
#include <lladd/crc32.h>
/** @todo replace() powl in hash with something more efficient, if hash() becomes a bottleneck. */
unsigned int hash(void * val, long val_length, unsigned char tableBits, unsigned long nextExtension);

View file

@ -148,7 +148,7 @@ typedef struct {
#include "operations/noop.h"
#include "operations/instantSet.h"
#include "operations/arrayList.h"
#include "operations/linearHash.h"
extern Operation operationsTable[]; /* [MAX_OPERATIONS]; memset somewhere */
/** Performs an operation during normal execution.

View file

@ -0,0 +1,26 @@
#include <lladd/operations.h>
#ifndef __LINEAR_HASH_H
#define __LINEAR_HASH_H
/**
@file
@ingroup OPERATIONS
$Id$
*/
recordid ThashAlloc(int xid, int keySize, int valSize) ;
void ThashInsert(int xid, recordid hashRid,
void * key, int keySize,
void * val, int valSize);
void ThashDelete(int xid, recordid hashRid,
void * key, int keySize);
void ThashUpdate(int xid, recordid hashRid, void * key, int keySize, void * val, int valSize);
int ThashLookup(int xid, recordid hashRid, void * key, int keySize, void * buf, int valSize);
#endif

View file

@ -3,13 +3,13 @@
lib_LIBRARIES=liblladd.a
#liblladd_a_LIBADD=logger/liblogger.a operations/liboperations.a
# removed: recovery.c transactional.c logger.c logger/logparser.c logger/logstreamer.c
liblladd_a_SOURCES=common.c stats.c io.c bufferManager.c linkedlist.c operations.c \
liblladd_a_SOURCES=crc32.c common.c stats.c io.c bufferManager.c linkedlist.c operations.c \
pageFile.c pageCache.c page.c blobManager.c recovery2.c transactional2.c \
logger/logEntry.c logger/logWriter.c logger/logHandle.c logger/logger2.c \
operations/pageOperations.c page/indirect.c operations/decrement.c \
operations/increment.c operations/prepare.c operations/set.c \
operations/alloc.c operations/noop.c operations/instantSet.c \
page/slotted.c operations/lladdhash.c page/header.c page/fixed.c \
operations/arrayList.c
operations/arrayList.c hash.c operations/linearHash.c
AM_CFLAGS= -g -Wall -pedantic -std=gnu99

66
src/lladd/crc32.c Normal file
View file

@ -0,0 +1,66 @@
// Calculate a CRC 32 checksum.
#include <lladd/crc32.h> /*Added 10-6-04 */
#include <malloc.h>
#include <stdio.h>
// LAST MODIFIED:[7-28-93]
// Usage:
// unsigned long crc = -1L
// crc = crc32(buffer, length, crc)
unsigned long crc32(void *buffer, unsigned int count, unsigned long crc);
static int BuildCRCTable(void);
static unsigned long *CRCTable; // Table constructed for fast lookup.
#define CRC32_POLYNOMIAL 0xEDB88320L
// Initialize the CRC calculation table
//
static int BuildCRCTable(void)
{
int i, j;
unsigned long crc;
CRCTable = malloc(256 * sizeof(unsigned long));
if (CRCTable == NULL)
{
fprintf(stderr, "Can't malloc space for CRC table in file %s\n", __FILE__);
return -1L;
}
for (i = 0; i <= 255; i++)
{
crc = i;
for (j = 8; j > 0; j--)
if (crc & 1)
crc = (crc >> 1) ^ CRC32_POLYNOMIAL;
else
crc >>= 1;
CRCTable[i] = crc;
}
return 0;
}
unsigned long crc32(void *buffer, unsigned int count, unsigned long crc)
{
unsigned long temp1, temp2;
static int firsttime = 1;
unsigned char *p = (unsigned char *)buffer;
if (firsttime)
{
if (BuildCRCTable())
return -1;
firsttime = 0;
}
while (count-- != 0)
{
temp1 = (crc >> 8) & 0x00FFFFFFL;
temp2 = CRCTable[((int)crc ^ *p++) & 0xFF];
crc = temp1 ^ temp2;
}
return crc;
}

53
src/lladd/hash.c Normal file
View file

@ -0,0 +1,53 @@
#include <lladd/hash.h>
#include <math.h>
/*static int thomasWangs32BitMixFunction(int key);
static unsigned long thomasWangs64BitMixFunction(unsigned long key);*/
/** @todo replace powl in hash with something more efficient, if hash() becomes a bottleneck. */
unsigned int hash(void * val, long val_length, unsigned char tableBits, unsigned long nextExtension) {
unsigned long tableLength = powl(2, tableBits);
unsigned long oldTableLength = powl(2, tableBits - 1);
unsigned long unmixed = crc32(val, val_length, (unsigned long)-1L);
unsigned long ret = unmixed & (oldTableLength - 1);
if(*(int*)val == 4090) {
printf("here too!");
}
/* What would the low hash value be? */
/* printf("hash(%d, bits=%d, ext=%ld) first: %ld ", *(int*)val, tableBits, nextExtension, ret); */
if(ret < nextExtension) { /* Might be too low. */
ret = unmixed & (tableLength - 1);
/* printf("second: %ld", ret); */
}
/* printf("\n"); */
return (int) ret;
}
/*static unsigned long thomasWangs64BitMixFunction(unsigned long key)
{
key += ~(key << 32L);
key ^= (key >> 22L);
key += ~(key << 13L);
key ^= (key >> 8L);
key += (key << 3L);
key ^= (key >> 15L);
key += ~(key << 27L);
key ^= (key >> 31L);
return key;
}
static int thomasWangs32BitMixFunction(int key)
{
key += ~(key << 15);
key ^= (key >> 10);
key += (key << 3);
key ^= (key >> 6);
key += ~(key << 11);
key ^= (key >> 16);
return key;
}
*/

View file

@ -50,7 +50,7 @@ recordid TarrayListAlloc(int xid, int count, int multiplier, int size) {
recordid rid;
rid.page = firstPage;
rid.size = 0;
rid.size = size;
rid.slot = 0;
Tupdate(xid, rid, &tlp, OPERATION_ARRAY_LIST_ALLOC);

View file

@ -0,0 +1,281 @@
#include <lladd/operations/linearHash.h>
#include <lladd/hash.h>
#include <limits.h>
#include <assert.h>
/**
A from-scratch implementation of linear hashing. Uses the
arrayList operations to implement its hashbuckets.
*/
#define BUCKETS_OFFSET (2)
#define headerKeySize (headerRidA.page)
#define headerValSize (headerRidA.slot)
#define headerHashBits (headerRidB.page)
#define headerNextSplit (headerRidB.slot)
#include <math.h>
#include <malloc.h>
#include <string.h>
#include <lladd/operations/linearHash.h>
typedef struct {
recordid next;
} hashEntry;
void rehash(int xid, recordid hash, int next_split, int i);
void update_hash_header(int xid, recordid hash, int i, int next_split);
int deleteFromBucket(int xid, recordid hash, int bucket_number, void * key, int keySize, recordid * deletedEntry);
void insertIntoBucket(int xid, recordid hashRid, int bucket_number, hashEntry * e, int keySize, int valSize, recordid deletedEntry);
int findInBucket(int xid, recordid hashRid, int bucket_number, const void * key, int keySize, void * val, int valSize);
int findInBucket(int xid, recordid hashRid, int bucket_number, const void * key, int keySize, void * val, int valSize) {
hashEntry * e = malloc(sizeof(hashEntry) + keySize + valSize);
recordid bucket = hashRid;
bucket.slot = bucket_number;
recordid nextEntry;
Tread(xid, bucket, &nextEntry);
if(nextEntry.size) {
e = malloc(nextEntry.size);
} else {
e = malloc(1);
}
int found = 0;
while(nextEntry.size > 0) {
Tread(xid, nextEntry, e);
if(!memcmp(key, e+1, keySize)) {
memcpy(val, ((byte*)(e+1))+keySize, valSize);
found = 1;
break;
}
nextEntry = e->next;
}
return found;
}
void expand (int xid, recordid hash, int next_split, int i) {
TarrayListExtend(xid, hash, 1);
if(next_split >= powl(2,i-1)+2) {
/* printf("\n\n%d %d (i++)\n\n", next_split, i); */
i++;
next_split = 2;
}
/* printf("-%d-", next_split); */
/* printf("rehash(%d, %d + 2)\n", i, next_split - 2); */
rehash(xid, hash, next_split, i);
next_split++;
update_hash_header(xid, hash, i, next_split);
}
void update_hash_header(int xid, recordid hash, int i, int next_split) {
recordid headerRidB;
hash.slot = 1;
Tread(xid, hash, &headerRidB);
/* headerHashBits and headerHashSplit are #defined to refer to headerRidB. */
headerHashBits = i;
headerNextSplit = next_split;
Tset(xid, hash, &headerRidB);
}
void rehash(int xid, recordid hashRid, int next_split, int i) {
recordid bucket = hashRid;
bucket.slot = next_split;
recordid headerRidA;
Tread(xid, hashRid, &headerRidA);
/* recordid oldRid;
oldRid.page = 0;
oldRid.slot = 0;
oldRid.size = 0; */
hashEntry * e = calloc(1,sizeof(hashEntry) + headerValSize + headerKeySize);
assert(bucket.size < 1000);
if(bucket.size) {
Tread(xid, bucket, &bucket);
}
while(bucket.size > 0) {
Tread(xid, bucket, e);
/* printf("#%d", *(int*)(e+1)); */
int old_hash = hash(e+1, headerKeySize, i-1, ULONG_MAX) + 2;
assert(next_split == old_hash);
int new_hash = hash(e+1, headerKeySize, i, ULONG_MAX) + 2;
bucket = e->next;
/* oldRid = bucket; */
assert((!bucket.size )|| bucket.size == sizeof(hashEntry) + headerValSize + headerKeySize);
if(new_hash != next_split) {
assert(new_hash == next_split + powl(2, i-1));
/* recordid newRid = hashRid;
newRid.slot = new_hash;
recordid ptr;
Tread(xid, newRid, &ptr); */
/* printf("Moving from %d to %d.\n", next_split, new_hash);
fflush(NULL); */
recordid oldEntry;
/* printf("!"); */
assert(deleteFromBucket(xid, hashRid, next_split, e+1, headerKeySize, &oldEntry));
insertIntoBucket(xid, hashRid, new_hash, e, headerKeySize, headerValSize, oldEntry);
} else {
/* printf("-"); */
/* printf("Not moving %d.\n", next_split);
fflush(NULL); */
}
}
free(e);
}
void insertIntoBucket(int xid, recordid hashRid, int bucket_number, hashEntry * e, int keySize, int valSize, recordid newEntry) {
recordid deleteMe;
if(deleteFromBucket(xid, hashRid, bucket_number, e+1, keySize, &deleteMe)) {
Tdealloc(xid, deleteMe);
}
/*@todo consider recovery for insertIntoBucket. */
/* recordid newEntry = Talloc(xid, sizeof(hashEntry) + keySize + valSize); */
recordid bucket = hashRid;
bucket.slot = bucket_number;
Tread(xid, bucket, &(e->next));
Tset(xid, newEntry, e);
Tset(xid, bucket, &newEntry);
}
int deleteFromBucket(int xid, recordid hash, int bucket_number, void * key, int keySize, recordid * deletedEntry) {
hashEntry * e;
recordid bucket = hash;
bucket.slot = bucket_number;
recordid nextEntry;
Tread(xid, bucket, &nextEntry);
if(nextEntry.size) {
e = calloc(1,nextEntry.size);
} else {
e = calloc(1,1);
}
int first = 1;
int found = 0;
recordid lastEntry;
while(nextEntry.size > 0) {
Tread(xid, nextEntry, e);
if(!memcmp(key, e+1, keySize)) {
if(first) {
assert(e->next.size < 1000);
Tset(xid, bucket, &(e->next));
} else {
recordid next = e->next;
Tread(xid, lastEntry, e);
assert(next.size < 1000);
e->next = next;
Tset(xid, lastEntry, e);
}
*deletedEntry = nextEntry;
/* Tdealloc(xid, nextEntry); */
found = 1;
break;
}
lastEntry = nextEntry;
first = 0;
nextEntry = e->next;
}
return found;
}
recordid ThashAlloc(int xid, int keySize, int valSize) {
/* Want 16 buckets + 2 header rids, doubling on overflow. */
recordid rid = TarrayListAlloc(xid, 16 + 2, 2, sizeof(recordid));
TarrayListExtend(xid, rid, 32+2);
recordid headerRidA, headerRidB;
headerKeySize = keySize;
headerValSize = valSize;
headerNextSplit = INT_MAX;
headerHashBits = 4;
rid.slot =0;
Tset(xid, rid, &headerRidA);
rid.slot =1;
Tset(xid, rid, &headerRidB);
rid.slot =0;
return rid;
}
void ThashInsert(int xid, recordid hashRid,
void * key, int keySize,
void * val, int valSize) {
recordid headerRidA, headerRidB;
recordid tmp = hashRid;
tmp.slot = 0;
Tread(xid, tmp, &headerRidA);
assert(headerKeySize == keySize);
tmp.slot = 1;
Tread(xid, tmp, &headerRidB);
assert(headerValSize == valSize);
int bucket = hash(key, keySize, headerHashBits, headerNextSplit - 2) + 2;
hashEntry * e = calloc(1,sizeof(hashEntry) + keySize + valSize);
memcpy(e+1, key, keySize);
memcpy(((byte*)(e+1)) + keySize, val, valSize);
recordid newEntry = Talloc(xid, sizeof(hashEntry) + keySize + valSize);
/* printf("%d -> %d\n", *(int*)(e+1), bucket); */
insertIntoBucket(xid, hashRid, bucket, e, keySize, valSize, newEntry);
expand(xid, hashRid, headerNextSplit, headerHashBits);
free(e);
}
/** @todo hash hable probably should track the number of items in it,
so that expand can be selectively called. */
void ThashDelete(int xid, recordid hashRid,
void * key, int keySize) {
recordid headerRidB;
recordid tmp = hashRid;
tmp.slot = 1;
Tread(xid, tmp, &headerRidB);
int bucket_number = hash(key, keySize, headerHashBits, headerNextSplit - 2) + 2;
recordid deleteMe;
if(deleteFromBucket(xid, hashRid, bucket_number, key, keySize, &deleteMe)) {
Tdealloc(xid, deleteMe);
}
}
void ThashUpdate(int xid, recordid hashRid, void * key, int keySize, void * val, int valSize) {
ThashDelete(xid, hashRid, key, keySize);
ThashInsert(xid, hashRid, key, keySize, val, valSize);
}
int ThashLookup(int xid, recordid hashRid, void * key, int keySize, void * buf, int valSize) {
recordid headerRidB;
recordid tmp = hashRid;
tmp.slot = 1;
Tread(xid, tmp, &headerRidB);
int bucket_number = hash(key, keySize, headerHashBits, headerNextSplit - 2) + 2;
/* printf("look in %d\n", bucket_number); */
int ret = findInBucket(xid, hashRid, bucket_number, key, keySize, buf, valSize);
return ret;
}

View file

@ -148,7 +148,7 @@ void pageOperationsInit() {
assert(freepage);
free(p.memAddr);
/* free(p.memAddr); */
deletelock(p.loadlatch);
deletelock(p.rwlatch);

View file

@ -1,12 +1,12 @@
INCLUDES = @CHECK_CFLAGS@
if HAVE_CHECK
## Had to disable check_lht because lht needs to be rewritten.
TESTS = check_logEntry check_logWriter check_page check_operations check_transactional2 check_recovery check_blobRecovery check_bufferManager check_indirect check_lladdhash check_pageOperations
TESTS = check_logEntry check_logWriter check_page check_operations check_transactional2 check_recovery check_blobRecovery check_bufferManager check_indirect check_lladdhash check_pageOperations check_linearHash
else
TESTS =
endif
noinst_PROGRAMS = $(TESTS)
LDADD = @CHECK_LIBS@ $(top_builddir)/src/lladd/liblladd.a $(top_builddir)/src/pbl/libpbl.a $(top_builddir)/src/libdfa/librw.a #-lefence
CLEANFILES = check_lht.log check_logEntry.log storefile.txt logfile.txt blob0_file.txt blob1_file.txt check_blobRecovery.log check_logWriter.log check_operations.log check_recovery.log check_transactional2.log check_page.log check_bufferManager.log check_indirect.log check_bufferMananger.log check_lladdhash.log check_pageOperations.log
CLEANFILES = check_lht.log check_logEntry.log storefile.txt logfile.txt blob0_file.txt blob1_file.txt check_blobRecovery.log check_logWriter.log check_operations.log check_recovery.log check_transactional2.log check_page.log check_bufferManager.log check_indirect.log check_bufferMananger.log check_lladdhash.log check_pageOperations.log check_linearhash.log
AM_CFLAGS= -g -Wall -pedantic -std=gnu99

View file

@ -0,0 +1,217 @@
/*---
This software is copyrighted by the Regents of the University of
California, and other parties. The following terms apply to all files
associated with the software unless explicitly disclaimed in
individual files.
The authors hereby grant permission to use, copy, modify, distribute,
and license this software and its documentation for any purpose,
provided that existing copyright notices are retained in all copies
and that this notice is included verbatim in any distributions. No
written agreement, license, or royalty fee is required for any of the
authorized uses. Modifications to this software may be copyrighted by
their authors and need not follow the licensing terms described here,
provided that the new terms are clearly indicated on the first page of
each file where they apply.
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
GOVERNMENT USE: If you are acquiring this software on behalf of the
U.S. government, the Government shall have only "Restricted Rights" in
the software and related documentation as defined in the Federal
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
acquiring the software on behalf of the Department of Defense, the
software shall be classified as "Commercial Computer Software" and the
Government shall have only "Restricted Rights" as defined in Clause
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
authors grant the U.S. Government and others acting in its behalf
permission to use and distribute the software in accordance with the
terms specified in this license.
---*/
#include <config.h>
#include <check.h>
#include "../check_includes.h"
#include <lladd/transactional.h>
#include <assert.h>
#include <lladd/hash.h>
#include <limits.h>
#include <math.h>
#define LOG_NAME "check_linearHash.log"
/** @test
executes each of the insert / remove / lookup operations a few times.
*/
#define NUM_ENTRIES 100000
/* #define NUM_ENTRIES 2000*/
/* #define NUM_ENTRIES 1000 */
/*#define NUM_ENTRIES 100 */
START_TEST(checkHashFcn) {
int i;
srandom(12312313);
for(i = 0; i < 100000;i++) {
int j = (int) (100000.0*random()/(RAND_MAX+1.0)); /* int for CRC. */
int k = (int) 2+(30.0*random()/(RAND_MAX+1.0)); /* number of bits in result. */
unsigned long first = hash(&j, sizeof(int), k, ULONG_MAX);
int boundary = first + 10;
unsigned long second = hash(&j, sizeof(int), k, boundary);
assert(first == second);
unsigned long third = hash(&j, sizeof(int), k+1, ULONG_MAX);
assert((first == third) || (powl(2,k)+ first == third));
}
} END_TEST
START_TEST(simpleLinearHashTest)
{
Tinit();
int xid = Tbegin();
recordid hashRoot = ThashAlloc(xid, sizeof(int), sizeof(recordid));
for(int i = 0; i < NUM_ENTRIES; i++) {
recordid rid;
rid.page=i+1;
rid.slot=i+2;
rid.size=i+3;
/* assert(isNullRecord(lHtInsert(xid, hash, &i, sizeof(int), rid)));
assert(!isNullRecord(lHtInsert(xid, hash, &i, sizeof(int), rid))); */
if(i == 4090) {
printf("here");
}
ThashInsert(xid, hashRoot, &i, sizeof(int), &rid, sizeof(recordid));
/* printf("%d\n", i); */
assert(ThashLookup(xid, hashRoot, &i, sizeof(int), &rid, sizeof(recordid)));
assert(rid.page == i+1);
assert(rid.slot == i+2);
assert(rid.size == i+3);
if(! (i % 1000)) {
printf("%d\n", i);
fflush(NULL);
}
}
printf("Done inserting.\n");
fflush(NULL);
for(int i = 0; i < NUM_ENTRIES; i+=10) {
/*recordid rid = lHtRemove(xid, hash, &i, sizeof(int)); */
recordid rid;
assert(ThashLookup(xid, hashRoot, &i, sizeof(int), &rid, sizeof(recordid)));
assert(rid.page == (i+1));
assert(rid.slot == (i+2));
assert(rid.size == (i+3));
ThashDelete(xid, hashRoot, &i, sizeof(int));
}
printf("Done deleting mod 10.\n");
fflush(NULL);
for(int i = 0; i < NUM_ENTRIES; i++) {
recordid rid;
if(i % 10) {
assert(ThashLookup(xid, hashRoot, &i, sizeof(int), &rid, sizeof(recordid)));
assert(rid.page == (i+1));
assert(rid.slot == (i+2));
assert(rid.size == (i+3));
} else {
assert(!ThashLookup(xid, hashRoot, &i, sizeof(int), &rid, sizeof(recordid)));
}
}
printf("Done checking mod 10.\n");
Tcommit(xid);
xid = Tbegin();
recordid rid;
for(int i = 0; i < NUM_ENTRIES; i++) {
if(i % 10) {
assert(ThashLookup(xid, hashRoot, &i, sizeof(int), &rid, sizeof(recordid)));
ThashDelete(xid, hashRoot, &i, sizeof(int));
assert(rid.page == (i+1));
assert(rid.slot == (i+2));
assert(rid.size == (i+3));
} else {
assert(!ThashLookup(xid, hashRoot, &i, sizeof(int), &rid, sizeof(recordid)));
ThashDelete(xid, hashRoot, &i, sizeof(int));
}
}
printf("Done deleting rest.\n");
fflush(NULL);
for(int i = 0; i < NUM_ENTRIES; i++) {
assert(!ThashLookup(xid, hashRoot, &i, sizeof(int), &rid, sizeof(recordid)));
}
printf("Aborting..\n");
fflush(NULL);
Tabort(xid);
printf("done aborting..\n");
fflush(NULL);
xid = Tbegin();
for(int i = 0; i < NUM_ENTRIES; i++) {
if(i % 10) {
assert( ThashLookup(xid, hashRoot, &i, sizeof(int), &rid, sizeof(recordid)));
assert(rid.page == (i+1));
assert(rid.slot == (i+2));
assert(rid.size == (i+3));
} else {
assert(!ThashLookup(xid, hashRoot, &i, sizeof(int), &rid, sizeof(recordid)));
}
}
printf("done checking..\n");
fflush(NULL);
Tcommit(xid);
Tdeinit();
}
END_TEST
Suite * check_suite(void) {
Suite *s = suite_create("linearHash");
/* Begin a new test */
TCase *tc = tcase_create("simple");
/* Sub tests are added, one per line, here */
/* tcase_add_test(tc, checkHashFcn); */
tcase_add_test(tc, simpleLinearHashTest);
/* --------------------------------------------- */
tcase_add_checked_fixture(tc, setup, teardown);
suite_add_tcase(s, tc);
return s;
}
#include "../check_setup.h"

View file

@ -63,7 +63,7 @@ int main() {
printf("Couldn't open log.\n");
}
lh = getLSNHandle(44);
lh = getLogHandle(); /*LSNHandle(0); */
while((le = nextInLog(&lh))) {