diff --git a/src/tests/add-ons/kernel/file_systems/befs/btree/Inode.cpp b/src/tests/add-ons/kernel/file_systems/befs/btree/Inode.cpp deleted file mode 100644 index 2d38e76cee..0000000000 --- a/src/tests/add-ons/kernel/file_systems/befs/btree/Inode.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* Inode - emulation for the B+Tree torture test -** -** Initial version by Axel Dörfler, axeld@pinc-software.de -** This file may be used under the terms of the OpenBeOS License. -*/ - - -#include "Inode.h" -#include "Volume.h" -#include "Journal.h" - - -Inode::Inode(const char *name,int32 mode) - : - fMode(mode) -{ - fFile.SetTo(name,B_CREATE_FILE | B_READ_WRITE | B_ERASE_FILE); - fSize = 0; - fVolume = new Volume(&fFile); -} - - -Inode::~Inode() -{ - delete fVolume; -} - - -status_t -Inode::FindBlockRun(off_t pos, block_run &run, off_t &offset) -{ - // the whole file data is covered by this one block_run structure... - run.SetTo(0,0,1); - offset = 0; - return B_OK; -} - - -status_t -Inode::Append(Transaction *transaction, off_t bytes) -{ - return SetFileSize(transaction,Size() + bytes); -} - - -status_t -Inode::SetFileSize(Transaction *, off_t bytes) -{ - //printf("set size = %ld\n",bytes); - fSize = bytes; - return fFile.SetSize(bytes); -} - diff --git a/src/tests/add-ons/kernel/file_systems/befs/btree/Inode.h b/src/tests/add-ons/kernel/file_systems/befs/btree/Inode.h deleted file mode 100644 index cebfa194bd..0000000000 --- a/src/tests/add-ons/kernel/file_systems/befs/btree/Inode.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef INODE_H -#define INODE_H -/* Inode - emulation for the B+Tree torture test -** -** Initial version by Axel Dörfler, axeld@pinc-software.de -** This file may be used under the terms of the OpenBeOS License. -*/ - - -#include -#include - -#include "Lock.h" -#include "bfs.h" - - -class Volume; -class Transaction; - - -class Inode { - public: - Inode(const char *name,int32 mode = S_STR_INDEX | S_ALLOW_DUPS); - ~Inode(); - - ReadWriteLock &Lock() { return fLock; } - - status_t FindBlockRun(off_t pos,block_run &run,off_t &offset); - status_t Append(Transaction *,off_t bytes); - status_t SetFileSize(Transaction *,off_t bytes); - - Volume *GetVolume() const { return fVolume; } - off_t ID() const { return 0; } - int32 Mode() const { return fMode; } - char *Name() const { return "whatever"; } - block_run BlockRun() const { return block_run::Run(0,0,0); } - block_run Parent() const { return block_run::Run(0,0,0); } - off_t BlockNumber() const { return 0; } - bfs_inode *Node() { return (bfs_inode *)1; } - - off_t Size() const { return fSize; } - bool IsContainer() const { return true; } - bool IsDirectory() const { return true; } - - private: - Volume *fVolume; - BFile fFile; - off_t fSize; - ReadWriteLock fLock; - int32 fMode; -}; - -#endif /* INODE_H */ diff --git a/src/tests/add-ons/kernel/file_systems/befs/btree/Jamfile b/src/tests/add-ons/kernel/file_systems/befs/btree/Jamfile deleted file mode 100644 index 5681a9797b..0000000000 --- a/src/tests/add-ons/kernel/file_systems/befs/btree/Jamfile +++ /dev/null @@ -1,25 +0,0 @@ -SubDir OBOS_TOP src tests add-ons kernel file_systems befs btree ; - -SubDirHdrs $(OBOS_TOP) src add-ons kernel file_systems bfs ; - -rule FPreIncludes { return -include\ $(1:D=$(SUBDIR)) ; } - -{ - local defines = [ FDefines USER DEBUG ] ; # _NO_INLINE_ASM - local preIncludes = [ FPreIncludes Journal.h Inode.h ] ; - SubDirC++Flags $(defines) $(preIncludes) -fno-exceptions -fno-rtti ; #-fcheck-memory-usage -} - -SimpleTest btreeTest - : test.cpp - Volume.cpp - Inode.cpp - cache.cpp - BPlusTree.cpp - Utility.cpp - Debug.cpp - : be ; - -# Tell Jam where to find these sources -SEARCH on [ FGristFiles BPlusTree.cpp Utility.cpp Debug.cpp ] - = [ FDirName $(OBOS_TOP) src add-ons kernel file_systems bfs ] ; diff --git a/src/tests/add-ons/kernel/file_systems/befs/btree/Journal.h b/src/tests/add-ons/kernel/file_systems/befs/btree/Journal.h deleted file mode 100644 index db19c82ec1..0000000000 --- a/src/tests/add-ons/kernel/file_systems/befs/btree/Journal.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef JOURNAL_H -#define JOURNAL_H -/* Journal - emulation for the B+Tree torture test -** -** Initial version by Axel Dörfler, axeld@pinc-software.de -** This file may be used under the terms of the OpenBeOS License. -*/ - - -#include - -#include "Volume.h" -#include "Debug.h" -#include "cache.h" - - -class Transaction { - public: - Transaction(Volume *volume,off_t refBlock) - : - fVolume(volume) - { - } - - ~Transaction() - { - } - - status_t WriteBlocks(off_t blockNumber,const uint8 *buffer,size_t numBlocks = 1) - { - return cached_write(fVolume->Device(),blockNumber,buffer,numBlocks,fVolume->BlockSize()); - } - - void Done() - { - } - - protected: - Volume *fVolume; -}; - -#endif /* JOURNAL_H */ diff --git a/src/tests/add-ons/kernel/file_systems/befs/btree/Volume.cpp b/src/tests/add-ons/kernel/file_systems/befs/btree/Volume.cpp deleted file mode 100644 index 3529d7d119..0000000000 --- a/src/tests/add-ons/kernel/file_systems/befs/btree/Volume.cpp +++ /dev/null @@ -1,18 +0,0 @@ -/* Volume - emulation for the B+Tree torture test -** -** Initial version by Axel Dörfler, axeld@pinc-software.de -** This file may be used under the terms of the OpenBeOS License. -*/ - - -#include "Volume.h" - -#include - - -void -Volume::Panic() -{ - printf("PANIC!\n"); -} - diff --git a/src/tests/add-ons/kernel/file_systems/befs/btree/Volume.h b/src/tests/add-ons/kernel/file_systems/befs/btree/Volume.h deleted file mode 100644 index 74aa5f32e5..0000000000 --- a/src/tests/add-ons/kernel/file_systems/befs/btree/Volume.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef VOLUME_H -#define VOLUME_H -/* Volume - emulation for the B+Tree torture test -** -** Initial version by Axel Dörfler, axeld@pinc-software.de -** This file may be used under the terms of the OpenBeOS License. -*/ - - -#include - -#include "Lock.h" -#include "bfs.h" - - -class BFile; - - -class Volume { - public: - Volume(BFile *file) : fFile(file) {} - - BFile *Device() { return fFile; } - - int32 BlockSize() const { return 1024; } - off_t ToBlock(block_run run) const { return run.start; } - block_run ToBlockRun(off_t block) const { return block_run::Run(0,0,block); } - - static void Panic(); - - private: - BFile *fFile; -}; - - -#endif /* VOLUME_H */ diff --git a/src/tests/add-ons/kernel/file_systems/befs/btree/cache.cpp b/src/tests/add-ons/kernel/file_systems/befs/btree/cache.cpp deleted file mode 100644 index 2b9275188a..0000000000 --- a/src/tests/add-ons/kernel/file_systems/befs/btree/cache.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* cache - emulation for the B+Tree torture test -** -** Initial version by Axel Dörfler, axeld@pinc-software.de -** This file may be used under the terms of the OpenBeOS License. -*/ - - -#include "cache.h" - -#include -#include - -#include -#include - - -/* A note from the author: this cache implementation can only be used - * with the test program, it really suites no other needs. - * It's very simple and not that efficient, and simple holds the whole - * file in memory, all the time. - */ - - -BList gBlocks; - - -void -init_cache(BFile */*file*/,int32 /*blockSize*/) -{ -} - - -void -shutdown_cache(BFile *file,int32 blockSize) -{ - for (int32 i = 0;i < gBlocks.CountItems();i++) { - void *buffer = gBlocks.ItemAt(i); - if (buffer == NULL) { - printf("cache is corrupt!\n"); - exit(-1); - } - file->WriteAt(i * blockSize,buffer,blockSize); - free(buffer); - } -} - - -static status_t -readBlocks(BFile *file,uint32 num,uint32 size) -{ - for (int32 i = gBlocks.CountItems();i <= num;i++) { - void *buffer = malloc(size); - if (buffer == NULL) - return B_NO_MEMORY; - - gBlocks.AddItem(buffer); - if (file->ReadAt(i * size,buffer,size) < B_OK) - return B_IO_ERROR; - } - return B_OK; -} - - -int -cached_write(BFile *file, off_t num,const void *data,off_t numBlocks, int blockSize) -{ - //printf("cached_write(num = %Ld,data = %p,numBlocks = %Ld,blockSize = %ld)\n",num,data,numBlocks,blockSize); - if (file == NULL) - return B_BAD_VALUE; - - if (num >= gBlocks.CountItems()) - puts("Oh no!"); - - void *buffer = gBlocks.ItemAt(num); - if (buffer == NULL) - return B_BAD_VALUE; - - if (buffer != data && numBlocks == 1) - memcpy(buffer,data,blockSize); - - return B_OK; -} - - -void * -get_block(BFile *file, off_t num, int blockSize) -{ - //printf("get_block(num = %Ld,blockSize = %ld)\n",num,blockSize); - if (file == NULL) - return NULL; - - if (num >= gBlocks.CountItems()) - readBlocks(file,num,blockSize); - - return gBlocks.ItemAt(num); -} - - -int -release_block(BFile *file, off_t num) -{ - //printf("release_block(num = %Ld)\n",num); - return 0; -} - - diff --git a/src/tests/add-ons/kernel/file_systems/befs/btree/cache.h b/src/tests/add-ons/kernel/file_systems/befs/btree/cache.h deleted file mode 100644 index 0b260f792d..0000000000 --- a/src/tests/add-ons/kernel/file_systems/befs/btree/cache.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef CACHE_H -#define CACHE_H -/* cache - emulation for the B+Tree torture test -** -** Initial version by Axel Dörfler, axeld@pinc-software.de -** This file may be used under the terms of the OpenBeOS License. -*/ - - -#include - -class BFile; - - -extern void init_cache(BFile *file, int32 blockSize); -extern void shutdown_cache(BFile *file, int32 blockSize); - -extern int cached_write(BFile *file, off_t bnum, const void *data,off_t num_blocks, int bsize); -extern void *get_block(BFile *file, off_t bnum, int bsize); -extern int release_block(BFile *file, off_t bnum); - -#endif /* CACHE_H */ diff --git a/src/tests/add-ons/kernel/file_systems/befs/btree/cpp.h b/src/tests/add-ons/kernel/file_systems/befs/btree/cpp.h deleted file mode 100644 index 0b8faf6264..0000000000 --- a/src/tests/add-ons/kernel/file_systems/befs/btree/cpp.h +++ /dev/null @@ -1,5 +0,0 @@ -/* cpp - emulation for the B+Tree torture test -** -** Initial version by Axel Dörfler, axeld@pinc-software.de -** This file may be used under the terms of the OpenBeOS License. -*/ diff --git a/src/tests/add-ons/kernel/file_systems/befs/btree/test.cpp b/src/tests/add-ons/kernel/file_systems/befs/btree/test.cpp deleted file mode 100644 index e521ffbf2e..0000000000 --- a/src/tests/add-ons/kernel/file_systems/befs/btree/test.cpp +++ /dev/null @@ -1,759 +0,0 @@ -/* test - BFS B+Tree torture test -** -** Initial version by Axel Dörfler, axeld@pinc-software.de -** This file may be used under the terms of the OpenBeOS License. -*/ - - -#include "Volume.h" -#include "Inode.h" -#include "BPlusTree.h" - -#include - -#include -#include -#include -#include -#include - - -#define DEFAULT_ITERATIONS 10 -#define DEFAULT_NUM_KEYS 100 -#define DEFAULT_KEY_TYPE S_STR_INDEX - -#define MIN_STRING 3 -#define MAX_STRING 256 - -struct key { - void *data; - uint32 length; - int32 in; - int32 count; - off_t value; -}; - -key *gKeys; -int32 gNum = DEFAULT_NUM_KEYS; -int32 gType = DEFAULT_KEY_TYPE; -int32 gTreeCount = 0; -bool gVerbose, gExcessive; -int32 gIterations = DEFAULT_ITERATIONS; -int32 gHard = 1; -Volume *gVolume; -int32 gSeed = 42; - -// from cache.cpp (yes, we are that mean) -extern BList gBlocks; - - -// prototypes -void bailOut(); -void bailOutWithKey(void *key, uint16 length); -void dumpTree(); -void dumpKey(void *key, int32 length); -void dumpKeys(); - - -void -dumpTree() -{ - puts("\n*** Tree-Dump:\n"); - - bplustree_header *header = (bplustree_header *)gBlocks.ItemAt(0); - dump_bplustree_header(header); - - for (int32 i = 1;i < gBlocks.CountItems();i++) { - bplustree_node *node = (bplustree_node *)gBlocks.ItemAt(i); - printf("\n--- %s node at %ld --------------------------------------\n", - node->overflow_link == BPLUSTREE_NULL ? "leaf" : "index", - i * BPLUSTREE_NODE_SIZE); - dump_bplustree_node(node,header,gVolume); - } -} - - -void -bailOut() -{ - if (gVerbose) { - // dump the tree - dumpTree(); - } - - // in any case, write the tree back to disk - shutdown_cache(gVolume->Device(),gVolume->BlockSize()); - exit(-1); -} - - -void -bailOutWithKey(void *key,uint16 length) -{ - dumpKey(key,length); - putchar('\n'); - bailOut(); -} - - -void -dumpKey(void *key,int32 length) -{ - switch (gType) { - case S_STR_INDEX: - printf("\"%s\" (%ld bytes)",key,length); - break; - case S_INT_INDEX: - printf("%ld",*(int32 *)key); - break; - case S_UINT_INDEX: - printf("%lu",*(uint32 *)key); - break; - case S_LONG_LONG_INDEX: - printf("%Ld",*(int64 *)key); - break; - case S_ULONG_LONG_INDEX: - printf("%Lu",*(uint64 *)key); - break; - case S_FLOAT_INDEX: - printf("%g",*(float *)key); - break; - case S_DOUBLE_INDEX: - printf("%g",*(double *)key); - break; - } - if ((gType == S_INT_INDEX || gType == S_UINT_INDEX || gType == S_FLOAT_INDEX) - && length != 4) - printf(" (wrong length %ld)",length); - else if ((gType == S_LONG_LONG_INDEX || gType == S_ULONG_LONG_INDEX || gType == S_DOUBLE_INDEX) - && length != 8) - printf(" (wrong length %ld)",length); -} - - -void -dumpKeys() -{ - char *type; - switch (gType) { - case S_STR_INDEX: - type = "string"; - break; - case S_INT_INDEX: - type = "int32"; - break; - case S_UINT_INDEX: - type = "uint32"; - break; - case S_LONG_LONG_INDEX: - type = "int64"; - break; - case S_ULONG_LONG_INDEX: - type = "uint64"; - break; - case S_FLOAT_INDEX: - type = "float"; - break; - case S_DOUBLE_INDEX: - type = "double"; - break; - } - printf("Dumping %ld keys of type %s\n",gNum,type); - - for (int32 i = 0;i < gNum;i++) { - printf("% 8ld. (%3ld) key = ",i,gKeys[i].in); - dumpKey(gKeys[i].data,gKeys[i].length); - putchar('\n'); - } -} - - -// #pragma mark - -// -// Functions to generate the keys in every available type -// - - -void -generateName(int32 i,char *name,int32 *_length) -{ - // We're using the index position as a hint for the length - // of the string - this way, it's much less expansive to - // test for string uniqueness. - // We don't want to sort the strings to have more realistic - // access patterns to the tree (only true for the strings test). - int32 length = i % (MAX_STRING - MIN_STRING) + MIN_STRING; - for (int32 i = 0;i < length;i++) { - int32 c = int32(52.0 * rand() / RAND_MAX); - if (c >= 26) - name[i] = 'A' + c - 26; - else - name[i] = 'a' + c; - } - name[length] = 0; - *_length = length; -} - - -void -fillBuffer(void *buffer,int32 start) -{ - for (int32 i = 0;i < gNum;i++) { - switch (gType) { - case S_INT_INDEX: - { - int32 *array = (int32 *)buffer; - array[i] = start + i; - break; - } - case S_UINT_INDEX: - { - uint32 *array = (uint32 *)buffer; - array[i] = start + i; - break; - } - case S_LONG_LONG_INDEX: - { - int64 *array = (int64 *)buffer; - array[i] = start + i; - break; - } - case S_ULONG_LONG_INDEX: - { - uint64 *array = (uint64 *)buffer; - array[i] = start + i; - break; - } - case S_FLOAT_INDEX: - { - float *array = (float *)buffer; - array[i] = start + i * 1.0001; - break; - } - case S_DOUBLE_INDEX: - { - double *array = (double *)buffer; - array[i] = start + i * 1.0001; - break; - } - } - gKeys[i].value = i; - } -} - - -bool -findKey(void *key,int32 length,int32 maxIndex) -{ - for (int32 i = length;i < maxIndex;i += MAX_STRING - MIN_STRING) { - if (length == gKeys[i].length - && !memcpy(key,gKeys[i].data,length)) - return true; - } - return false; -} - - -status_t -createKeys() -{ - gKeys = (key *)malloc(gNum * sizeof(key)); - if (gKeys == NULL) - return B_NO_MEMORY; - - if (gType == S_STR_INDEX) { - for (int32 i = 0;i < gNum;i++) { - char name[B_FILE_NAME_LENGTH]; - int32 length,tries = 0; - bool last; - - // create unique keys! - do { - generateName(i,name,&length); - } while ((last = findKey(name,length,i)) && tries++ < 100); - - if (last) { - printf("Couldn't create unique key list!\n"); - dumpKeys(); - bailOut(); - } - - gKeys[i].data = malloc(length + 1); - memcpy(gKeys[i].data,name,length + 1); - gKeys[i].length = length; - gKeys[i].in = 0; - gKeys[i].count = 0; - gKeys[i].value = i; - } - } else { - int32 length; - int32 start = 0; - switch (gType) { - case S_FLOAT_INDEX: - case S_INT_INDEX: - start = -gNum / 2; - case S_UINT_INDEX: - length = 4; - break; - case S_DOUBLE_INDEX: - case S_LONG_LONG_INDEX: - start = -gNum / 2; - case S_ULONG_LONG_INDEX: - length = 8; - break; - default: - return B_BAD_VALUE; - } - uint8 *buffer = (uint8 *)malloc(length * gNum); - if (buffer == NULL) - return B_NO_MEMORY; - - for (int32 i = 0;i < gNum;i++) { - gKeys[i].data = (void *)(buffer + i * length); - gKeys[i].length = length; - gKeys[i].in = 0; - gKeys[i].count = 0; - } - fillBuffer(buffer,start); - } - return B_OK; -} - - -// #pragma mark - -// -// Tree validity checker -// - - -void -checkTreeContents(BPlusTree *tree) -{ - // reset counter - for (int32 i = 0;i < gNum;i++) - gKeys[i].count = 0; - - TreeIterator iterator(tree); - char key[B_FILE_NAME_LENGTH]; - uint16 length,duplicate; - off_t value; - status_t status; - while ((status = iterator.GetNextEntry(key,&length,B_FILE_NAME_LENGTH,&value,&duplicate)) == B_OK) { - if (value < 0 || value >= gNum) { - iterator.Dump(); - printf("\ninvalid value %Ld in tree: ",value); - bailOutWithKey(key,length); - } - if (gKeys[value].value != value) { - iterator.Dump(); - printf("\nkey pointing to the wrong value %Ld (should be %Ld)\n",value,gKeys[value].value); - bailOutWithKey(key,length); - } - if (length != gKeys[value].length - || memcmp(key,gKeys[value].data,length)) { - iterator.Dump(); - printf("\nkeys don't match (key index = %Ld, %ld times in tree, %ld. occassion):\n\tfound: ",value,gKeys[value].in,gKeys[value].count + 1); - dumpKey(key,length); - printf("\n\texpected: "); - dumpKey(gKeys[value].data,gKeys[value].length); - putchar('\n'); - bailOut(); - } - - gKeys[value].count++; - } - if (status != B_ENTRY_NOT_FOUND) { - printf("TreeIterator::GetNext() returned: %s\n",strerror(status)); - iterator.Dump(); - bailOut(); - } - - for (int32 i = 0;i < gNum;i++) { - if (gKeys[i].in != gKeys[i].count) { - printf("Key "); - dumpKey(gKeys[i].data,gKeys[i].length); - printf(" found only %ld from %ld\n",gKeys[i].count,gKeys[i].in); - } - } -} - - -void -checkTreeIntegrity(BPlusTree *tree) -{ - // simple test, just seeks down to every key - if it couldn't - // be found, something must be wrong - - TreeIterator iterator(tree); - for (int32 i = 0;i < gNum;i++) { - if (gKeys[i].in == 0) - continue; - - status_t status = iterator.Find((uint8 *)gKeys[i].data,gKeys[i].length); - if (status != B_OK) { - printf("TreeIterator::Find() returned: %s\n",strerror(status)); - bailOutWithKey(gKeys[i].data,gKeys[i].length); - } - } -} - - -void -checkTree(BPlusTree *tree) -{ - if (!gExcessive) - printf("* Check tree...\n"); - - checkTreeContents(tree); - checkTreeIntegrity(tree); -} - - -// #pragma mark - -// -// The tree "torture" functions -// - - -void -addAllKeys(Transaction *transaction, BPlusTree *tree) -{ - printf("*** Adding all keys to the tree...\n"); - for (int32 i = 0;i < gNum;i++) { - status_t status = tree->Insert(transaction,(uint8 *)gKeys[i].data,gKeys[i].length,gKeys[i].value); - if (status < B_OK) { - printf("BPlusTree::Insert() returned: %s\n",strerror(status)); - printf("key: "); - dumpKey(gKeys[i].data,gKeys[i].length); - putchar('\n'); - } - else { - gKeys[i].in++; - gTreeCount++; - } - } - checkTree(tree); -} - - -void -removeAllKeys(Transaction *transaction, BPlusTree *tree) -{ - printf("*** Removing all keys from the tree...\n"); - for (int32 i = 0;i < gNum;i++) { - while (gKeys[i].in > 0) { - status_t status = tree->Remove(transaction, (uint8 *)gKeys[i].data, - gKeys[i].length, gKeys[i].value); - if (status < B_OK) { - printf("BPlusTree::Remove() returned: %s\n", strerror(status)); - printf("key: "); - dumpKey(gKeys[i].data, gKeys[i].length); - putchar('\n'); - } - else { - gKeys[i].in--; - gTreeCount--; - } - } - } - checkTree(tree); - -} - - -void -duplicateTest(Transaction *transaction,BPlusTree *tree) -{ - int32 index = int32(1.0 * gNum * rand() / RAND_MAX); - if (index == gNum) - index = gNum - 1; - - printf("*** Duplicate test with key "); - dumpKey(gKeys[index].data,gKeys[index].length); - puts("..."); - - status_t status; - - int32 insertTotal = 0; - for (int32 i = 0;i < 8;i++) { - int32 insertCount = int32(1000.0 * rand() / RAND_MAX); - if (gVerbose) - printf("* insert %ld to %ld old entries...\n",insertCount,insertTotal + gKeys[index].in); - - for (int32 j = 0;j < insertCount;j++) { - status = tree->Insert(transaction,(uint8 *)gKeys[index].data,gKeys[index].length,insertTotal); - if (status < B_OK) { - printf("BPlusTree::Insert() returned: %s\n",strerror(status)); - bailOutWithKey(gKeys[index].data,gKeys[index].length); - } - insertTotal++; - gTreeCount++; - - if (gExcessive) - checkTree(tree); - } - - int32 count; - if (i < 7) { - count = int32(1000.0 * rand() / RAND_MAX); - if (count > insertTotal) - count = insertTotal; - } else - count = insertTotal; - - if (gVerbose) - printf("* remove %ld from %ld entries...\n",count,insertTotal + gKeys[index].in); - - for (int32 j = 0;j < count;j++) { - status_t status = tree->Remove(transaction,(uint8 *)gKeys[index].data,gKeys[index].length,insertTotal - 1); - if (status < B_OK) { - printf("BPlusTree::Remove() returned: %s\n",strerror(status)); - bailOutWithKey(gKeys[index].data,gKeys[index].length); - } - insertTotal--; - gTreeCount--; - - if (gExcessive) - checkTree(tree); - } - } - - if (!gExcessive) - checkTree(tree); -} - - -void -addRandomSet(Transaction *transaction,BPlusTree *tree,int32 num) -{ - printf("*** Add random set to tree (%ld to %ld old entries)...\n",num,gTreeCount); - - for (int32 i = 0;i < num;i++) { - int32 index = int32(1.0 * gNum * rand() / RAND_MAX); - if (index == gNum) - index = gNum - 1; - - if (gVerbose) - printf("adding key %ld (%ld times in the tree)\n",index,gKeys[index].in); - - status_t status = tree->Insert(transaction,(uint8 *)gKeys[index].data,gKeys[index].length,gKeys[index].value); - if (status < B_OK) { - printf("BPlusTree::Insert() returned: %s\n",strerror(status)); - bailOutWithKey(gKeys[index].data,gKeys[index].length); - } - gKeys[index].in++; - gTreeCount++; - - if (gExcessive) - checkTree(tree); - } - if (!gExcessive) - checkTree(tree); -} - - -void -removeRandomSet(Transaction *transaction,BPlusTree *tree,int32 num) -{ - printf("*** Remove random set from tree (%ld from %ld entries)...\n",num,gTreeCount); - - int32 tries = 500; - - for (int32 i = 0;i < num;i++) { - if (gTreeCount < 1) - break; - - int32 index = int32(1.0 * gNum * rand() / RAND_MAX); - if (index == gNum) - index = gNum - 1; - - if (gKeys[index].in == 0) { - i--; - if (tries-- < 0) - break; - continue; - } - - if (gVerbose) - printf("removing key %ld (%ld times in the tree)\n",index,gKeys[index].in); - - status_t status = tree->Remove(transaction,(uint8 *)gKeys[index].data,gKeys[index].length,gKeys[index].value); - if (status < B_OK) { - printf("BPlusTree::Remove() returned: %s\n",strerror(status)); - bailOutWithKey(gKeys[index].data,gKeys[index].length); - } - gKeys[index].in--; - gTreeCount--; - - if (gExcessive) - checkTree(tree); - } - if (!gExcessive) - checkTree(tree); -} - - -// #pragma mark - - - -void -usage(char *program) -{ - if (strrchr(program,'/')) - program = strrchr(program,'/') + 1; - fprintf(stderr,"usage: %s [-veh] [-t type] [-n keys] [-i iterations] [-h times] [-r seed]\n" - "BFS B+Tree torture test\n" - "\t-t\ttype is one of string, int32, uint32, int64, uint64, float,\n" - "\t\tor double; defaults to string.\n" - "\t-n\tkeys is the number of keys to be used,\n" - "\t\tminimum is 1, defaults to %ld.\n" - "\t-i\titerations is the number of the test cycles, defaults to %ld.\n" - "\t-r\tthe seed for the random function, defaults to %ld.\n" - "\t-h\tremoves the keys and start over again for x times.\n" - "\t-e\texcessive validity tests: tree contents will be tested after every operation\n" - "\t-v\tfor verbose output.\n", - program, DEFAULT_NUM_KEYS, DEFAULT_ITERATIONS, gSeed); - exit(0); -} - - -int -main(int argc,char **argv) -{ - char *program = argv[0]; - - while (*++argv) - { - char *arg = *argv; - if (*arg == '-') - { - if (arg[1] == '-') - usage(program); - - while (*++arg && isalpha(*arg)) - { - switch (*arg) - { - case 'v': - gVerbose = true; - break; - case 'e': - gExcessive = true; - break; - case 't': - if (*++argv == NULL) - usage(program); - - if (!strcmp(*argv,"string")) - gType = S_STR_INDEX; - else if (!strcmp(*argv,"int32") - || !strcmp(*argv,"int")) - gType = S_INT_INDEX; - else if (!strcmp(*argv,"uint32") - || !strcmp(*argv,"uint")) - gType = S_UINT_INDEX; - else if (!strcmp(*argv,"int64") - || !strcmp(*argv,"llong")) - gType = S_LONG_LONG_INDEX; - else if (!strcmp(*argv,"uint64") - || !strcmp(*argv,"ullong")) - gType = S_ULONG_LONG_INDEX; - else if (!strcmp(*argv,"float")) - gType = S_FLOAT_INDEX; - else if (!strcmp(*argv,"double")) - gType = S_DOUBLE_INDEX; - else - usage(program); - break; - case 'n': - if (*++argv == NULL || !isdigit(**argv)) - usage(program); - - gNum = atoi(*argv); - if (gNum < 1) - gNum = 1; - break; - case 'h': - if (*++argv == NULL || !isdigit(**argv)) - usage(program); - - gHard = atoi(*argv); - if (gHard < 1) - gHard = 1; - break; - case 'i': - if (*++argv == NULL || !isdigit(**argv)) - usage(program); - - gIterations = atoi(*argv); - if (gIterations < 1) - gIterations = 1; - break; - case 'r': - if (*++argv == NULL || !isdigit(**argv)) - usage(program); - - gSeed = atoi(*argv); - break; - } - } - } - else - break; - } - - // we do want to have reproducible random keys - if (gVerbose) - printf("Set seed to %ld\n",gSeed); - srand(gSeed); - - Inode inode("tree.data",gType | S_ALLOW_DUPS); - gVolume = inode.GetVolume(); - Transaction transaction(gVolume,0); - - init_cache(gVolume->Device(),gVolume->BlockSize()); - - // - // Create the tree, the keys, and add all keys to the tree initially - // - - BPlusTree tree(&transaction,&inode); - status_t status; - if ((status = tree.InitCheck()) < B_OK) { - fprintf(stderr,"creating tree failed: %s\n",strerror(status)); - bailOut(); - } - printf("*** Creating %ld keys...\n",gNum); - if ((status = createKeys()) < B_OK) { - fprintf(stderr,"creating keys failed: %s\n",strerror(status)); - bailOut(); - } - - if (gVerbose) - dumpKeys(); - - for (int32 j = 0; j < gHard; j++ ) { - addAllKeys(&transaction, &tree); - - // - // Run the tests (they will exit the app, if an error occurs) - // - - for (int32 i = 0;i < gIterations;i++) { - printf("---------- Test iteration %ld ---------------------------------\n",i+1); - - addRandomSet(&transaction,&tree,int32(1.0 * gNum * rand() / RAND_MAX)); - removeRandomSet(&transaction,&tree,int32(1.0 * gNum * rand() / RAND_MAX)); - duplicateTest(&transaction,&tree); - } - - removeAllKeys(&transaction, &tree); - } - - // of course, we would have to free all our memory in a real application here... - - // write the cache back to the tree - shutdown_cache(gVolume->Device(),gVolume->BlockSize()); - return 0; -} -