BFS B+tree test: style cleanup.

This commit is contained in:
Axel Dörfler
2015-01-15 20:30:45 +01:00
parent f982c9ed88
commit 758cfd808a
@@ -1,21 +1,23 @@
/* test - BFS B+Tree torture test /*
** * Copyright 2001-2015, Axel Dörfler, [email protected].
** Initial version by Axel Dörfler, [email protected] * This file may be used under the terms of the MIT License.
** This file may be used under the terms of the OpenBeOS License. */
*/
#include "Volume.h" //! BFS B+Tree torture test
#include "Inode.h"
#include "BPlusTree.h"
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <List.h> #include <List.h>
#include <sys/stat.h> #include "BPlusTree.h"
#include <string.h> #include "Inode.h"
#include <stdlib.h> #include "Volume.h"
#include <stdio.h>
#include <ctype.h>
#define DEFAULT_ITERATIONS 10 #define DEFAULT_ITERATIONS 10
@@ -26,21 +28,21 @@
#define MAX_STRING 256 #define MAX_STRING 256
struct key { struct key {
void *data; void* data;
uint32 length; uint32 length;
int32 in; int32 in;
int32 count; int32 count;
off_t value; off_t value;
}; };
key *gKeys; key* gKeys;
int32 gNum = DEFAULT_NUM_KEYS; int32 gNum = DEFAULT_NUM_KEYS;
int32 gType = DEFAULT_KEY_TYPE; int32 gType = DEFAULT_KEY_TYPE;
int32 gTreeCount = 0; int32 gTreeCount = 0;
bool gVerbose, gExcessive; bool gVerbose, gExcessive;
int32 gIterations = DEFAULT_ITERATIONS; int32 gIterations = DEFAULT_ITERATIONS;
int32 gHard = 1; int32 gHard = 1;
Volume *gVolume; Volume* gVolume;
int32 gSeed = 42; int32 gSeed = 42;
// from cache.cpp (yes, we are that mean) // from cache.cpp (yes, we are that mean)
@@ -49,9 +51,9 @@ extern BList gBlocks;
// prototypes // prototypes
void bailOut(); void bailOut();
void bailOutWithKey(void *key, uint16 length); void bailOutWithKey(void* key, uint16 length);
void dumpTree(); void dumpTree();
void dumpKey(void *key, int32 length); void dumpKey(void* key, int32 length);
void dumpKeys(); void dumpKeys();
@@ -60,15 +62,15 @@ dumpTree()
{ {
puts("\n*** Tree-Dump:\n"); puts("\n*** Tree-Dump:\n");
bplustree_header *header = (bplustree_header *)gBlocks.ItemAt(0); bplustree_header* header = (bplustree_header*)gBlocks.ItemAt(0);
dump_bplustree_header(header); dump_bplustree_header(header);
for (int32 i = 1;i < gBlocks.CountItems();i++) { for (int32 i = 1; i < gBlocks.CountItems(); i++) {
bplustree_node *node = (bplustree_node *)gBlocks.ItemAt(i); bplustree_node* node = (bplustree_node*)gBlocks.ItemAt(i);
printf("\n--- %s node at %ld --------------------------------------\n", printf("\n--- %s node at %ld --------------------------------------\n",
node->overflow_link == BPLUSTREE_NULL ? "leaf" : "index", node->overflow_link == BPLUSTREE_NULL ? "leaf" : "index",
i * BPLUSTREE_NODE_SIZE); i * BPLUSTREE_NODE_SIZE);
dump_bplustree_node(node,header,gVolume); dump_bplustree_node(node, header, gVolume);
} }
} }
@@ -82,13 +84,13 @@ bailOut()
} }
// in any case, write the tree back to disk // in any case, write the tree back to disk
shutdown_cache(gVolume->Device(),gVolume->BlockSize()); shutdown_cache(gVolume->Device(), gVolume->BlockSize());
exit(-1); exit(-1);
} }
void void
bailOutWithKey(void *key, uint16 length) bailOutWithKey(void* key, uint16 length)
{ {
dumpKey(key, length); dumpKey(key, length);
putchar('\n'); putchar('\n');
@@ -97,44 +99,44 @@ bailOutWithKey(void *key, uint16 length)
void void
dumpKey(void *key, int32 length) dumpKey(void* key, int32 length)
{ {
switch (gType) { switch (gType) {
case S_STR_INDEX: case S_STR_INDEX:
printf("\"%s\" (%ld bytes)", (char *)key, length); printf("\"%s\" (%ld bytes)", (char*)key, length);
break; break;
case S_INT_INDEX: case S_INT_INDEX:
printf("%ld", *(int32 *)key); printf("%ld", *(int32*)key);
break; break;
case S_UINT_INDEX: case S_UINT_INDEX:
printf("%lu", *(uint32 *)key); printf("%lu", *(uint32*)key);
break; break;
case S_LONG_LONG_INDEX: case S_LONG_LONG_INDEX:
printf("%Ld", *(int64 *)key); printf("%Ld", *(int64*)key);
break; break;
case S_ULONG_LONG_INDEX: case S_ULONG_LONG_INDEX:
printf("%Lu", *(uint64 *)key); printf("%Lu", *(uint64*)key);
break; break;
case S_FLOAT_INDEX: case S_FLOAT_INDEX:
printf("%g", *(float *)key); printf("%g", *(float*)key);
break; break;
case S_DOUBLE_INDEX: case S_DOUBLE_INDEX:
printf("%g", *(double *)key); printf("%g", *(double*)key);
break; break;
} }
if ((gType == S_INT_INDEX || gType == S_UINT_INDEX || gType == S_FLOAT_INDEX) if ((gType == S_INT_INDEX || gType == S_UINT_INDEX
&& length != 4) || gType == S_FLOAT_INDEX) && length != 4)
printf(" (wrong length %ld)",length); printf(" (wrong length %ld)", length);
else if ((gType == S_LONG_LONG_INDEX || gType == S_ULONG_LONG_INDEX || gType == S_DOUBLE_INDEX) else if ((gType == S_LONG_LONG_INDEX || gType == S_ULONG_LONG_INDEX
&& length != 8) || gType == S_DOUBLE_INDEX) && length != 8)
printf(" (wrong length %ld)",length); printf(" (wrong length %ld)", length);
} }
void void
dumpKeys() dumpKeys()
{ {
const char *type; const char* type;
switch (gType) { switch (gType) {
case S_STR_INDEX: case S_STR_INDEX:
type = "string"; type = "string";
@@ -161,24 +163,21 @@ dumpKeys()
debugger("unknown type in gType"); debugger("unknown type in gType");
return; return;
} }
printf("Dumping %ld keys of type %s\n",gNum,type); printf("Dumping %ld keys of type %s\n", gNum, type);
for (int32 i = 0;i < gNum;i++) { for (int32 i = 0; i < gNum; i++) {
printf("% 8ld. (%3ld) key = ",i,gKeys[i].in); printf("% 8ld. (%3ld) key = ", i, gKeys[i].in);
dumpKey(gKeys[i].data,gKeys[i].length); dumpKey(gKeys[i].data, gKeys[i].length);
putchar('\n'); putchar('\n');
} }
} }
// #pragma mark - // #pragma mark - Key generation
//
// Functions to generate the keys in every available type
//
void void
generateName(int32 i,char *name,int32 *_length) generateName(int32 i, char* name, int32* _length)
{ {
// We're using the index position as a hint for the length // We're using the index position as a hint for the length
// of the string - this way, it's much less expansive to // of the string - this way, it's much less expansive to
@@ -186,7 +185,7 @@ generateName(int32 i,char *name,int32 *_length)
// We don't want to sort the strings to have more realistic // We don't want to sort the strings to have more realistic
// access patterns to the tree (only true for the strings test). // access patterns to the tree (only true for the strings test).
int32 length = i % (MAX_STRING - MIN_STRING) + MIN_STRING; int32 length = i % (MAX_STRING - MIN_STRING) + MIN_STRING;
for (int32 i = 0;i < length;i++) { for (int32 i = 0; i < length; i++) {
int32 c = int32(52.0 * rand() / RAND_MAX); int32 c = int32(52.0 * rand() / RAND_MAX);
if (c >= 26) if (c >= 26)
name[i] = 'A' + c - 26; name[i] = 'A' + c - 26;
@@ -199,43 +198,43 @@ generateName(int32 i,char *name,int32 *_length)
void void
fillBuffer(void *buffer,int32 start) fillBuffer(void* buffer, int32 start)
{ {
for (int32 i = 0;i < gNum;i++) { for (int32 i = 0; i < gNum; i++) {
switch (gType) { switch (gType) {
case S_INT_INDEX: case S_INT_INDEX:
{ {
int32 *array = (int32 *)buffer; int32* array = (int32*)buffer;
array[i] = start + i; array[i] = start + i;
break; break;
} }
case S_UINT_INDEX: case S_UINT_INDEX:
{ {
uint32 *array = (uint32 *)buffer; uint32* array = (uint32*)buffer;
array[i] = start + i; array[i] = start + i;
break; break;
} }
case S_LONG_LONG_INDEX: case S_LONG_LONG_INDEX:
{ {
int64 *array = (int64 *)buffer; int64* array = (int64*)buffer;
array[i] = start + i; array[i] = start + i;
break; break;
} }
case S_ULONG_LONG_INDEX: case S_ULONG_LONG_INDEX:
{ {
uint64 *array = (uint64 *)buffer; uint64* array = (uint64*)buffer;
array[i] = start + i; array[i] = start + i;
break; break;
} }
case S_FLOAT_INDEX: case S_FLOAT_INDEX:
{ {
float *array = (float *)buffer; float* array = (float*)buffer;
array[i] = start + i * 1.0001; array[i] = start + i * 1.0001;
break; break;
} }
case S_DOUBLE_INDEX: case S_DOUBLE_INDEX:
{ {
double *array = (double *)buffer; double* array = (double*)buffer;
array[i] = start + i * 1.0001; array[i] = start + i * 1.0001;
break; break;
} }
@@ -246,9 +245,9 @@ fillBuffer(void *buffer,int32 start)
bool bool
findKey(void *key, int32 length, int32 maxIndex) findKey(void* key, int32 length, int32 maxIndex)
{ {
for (int32 i = length;i < maxIndex;i += MAX_STRING - MIN_STRING) { for (int32 i = length; i < maxIndex; i += MAX_STRING - MIN_STRING) {
if (length == (int32)gKeys[i].length if (length == (int32)gKeys[i].length
&& !memcpy(key, gKeys[i].data, length)) && !memcpy(key, gKeys[i].data, length))
return true; return true;
@@ -260,20 +259,21 @@ findKey(void *key, int32 length, int32 maxIndex)
status_t status_t
createKeys() createKeys()
{ {
gKeys = (key *)malloc(gNum * sizeof(key)); gKeys = (key*)malloc(gNum * sizeof(key));
if (gKeys == NULL) if (gKeys == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
if (gType == S_STR_INDEX) { if (gType == S_STR_INDEX) {
for (int32 i = 0;i < gNum;i++) { for (int32 i = 0; i < gNum; i++) {
char name[B_FILE_NAME_LENGTH]; char name[B_FILE_NAME_LENGTH];
int32 length,tries = 0; int32 length;
int32 tries = 0;
bool last; bool last;
// create unique keys! // create unique keys!
do { do {
generateName(i,name,&length); generateName(i, name, &length);
} while ((last = findKey(name,length,i)) && tries++ < 100); } while ((last = findKey(name, length, i)) && tries++ < 100);
if (last) { if (last) {
printf("Couldn't create unique key list!\n"); printf("Couldn't create unique key list!\n");
@@ -282,7 +282,7 @@ createKeys()
} }
gKeys[i].data = malloc(length + 1); gKeys[i].data = malloc(length + 1);
memcpy(gKeys[i].data,name,length + 1); memcpy(gKeys[i].data, name, length + 1);
gKeys[i].length = length; gKeys[i].length = length;
gKeys[i].in = 0; gKeys[i].in = 0;
gKeys[i].count = 0; gKeys[i].count = 0;
@@ -307,58 +307,60 @@ createKeys()
default: default:
return B_BAD_VALUE; return B_BAD_VALUE;
} }
uint8 *buffer = (uint8 *)malloc(length * gNum); uint8* buffer = (uint8*)malloc(length * gNum);
if (buffer == NULL) if (buffer == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
for (int32 i = 0;i < gNum;i++) { for (int32 i = 0; i < gNum; i++) {
gKeys[i].data = (void *)(buffer + i * length); gKeys[i].data = (void*)(buffer + i * length);
gKeys[i].length = length; gKeys[i].length = length;
gKeys[i].in = 0; gKeys[i].in = 0;
gKeys[i].count = 0; gKeys[i].count = 0;
} }
fillBuffer(buffer,start); fillBuffer(buffer, start);
} }
return B_OK; return B_OK;
} }
// #pragma mark - // #pragma mark - Validity checker
//
// Tree validity checker
//
void void
checkTreeContents(BPlusTree *tree) checkTreeContents(BPlusTree* tree)
{ {
// reset counter // reset counter
for (int32 i = 0;i < gNum;i++) for (int32 i = 0; i < gNum; i++)
gKeys[i].count = 0; gKeys[i].count = 0;
TreeIterator iterator(tree); TreeIterator iterator(tree);
char key[B_FILE_NAME_LENGTH]; char key[B_FILE_NAME_LENGTH];
uint16 length,duplicate; uint16 length;
uint16 duplicate;
off_t value; off_t value;
status_t status; status_t status;
while ((status = iterator.GetNextEntry(key,&length,B_FILE_NAME_LENGTH,&value,&duplicate)) == B_OK) { while ((status = iterator.GetNextEntry(key, &length, B_FILE_NAME_LENGTH,
&value, &duplicate)) == B_OK) {
if (value < 0 || value >= gNum) { if (value < 0 || value >= gNum) {
iterator.Dump(); iterator.Dump();
printf("\ninvalid value %Ld in tree: ",value); printf("\ninvalid value %Ld in tree: ", value);
bailOutWithKey(key,length); bailOutWithKey(key, length);
} }
if (gKeys[value].value != value) { if (gKeys[value].value != value) {
iterator.Dump(); iterator.Dump();
printf("\nkey pointing to the wrong value %Ld (should be %Ld)\n",value,gKeys[value].value); printf("\nkey pointing to the wrong value %Ld (should be %Ld)\n",
bailOutWithKey(key,length); value, gKeys[value].value);
bailOutWithKey(key, length);
} }
if (length != gKeys[value].length if (length != gKeys[value].length
|| memcmp(key,gKeys[value].data,length)) { || memcmp(key, gKeys[value].data, length)) {
iterator.Dump(); 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); printf("\nkeys don't match (key index = %Ld, %ld times in tree, "
dumpKey(key,length); "%ld. occassion):\n\tfound: ", value, gKeys[value].in,
gKeys[value].count + 1);
dumpKey(key, length);
printf("\n\texpected: "); printf("\n\texpected: ");
dumpKey(gKeys[value].data,gKeys[value].length); dumpKey(gKeys[value].data, gKeys[value].length);
putchar('\n'); putchar('\n');
bailOut(); bailOut();
} }
@@ -366,46 +368,46 @@ checkTreeContents(BPlusTree *tree)
gKeys[value].count++; gKeys[value].count++;
} }
if (status != B_ENTRY_NOT_FOUND) { if (status != B_ENTRY_NOT_FOUND) {
printf("TreeIterator::GetNext() returned: %s\n",strerror(status)); printf("TreeIterator::GetNext() returned: %s\n", strerror(status));
iterator.Dump(); iterator.Dump();
bailOut(); bailOut();
} }
for (int32 i = 0;i < gNum;i++) { for (int32 i = 0; i < gNum; i++) {
if (gKeys[i].in != gKeys[i].count) { if (gKeys[i].in != gKeys[i].count) {
printf("Key "); printf("Key ");
dumpKey(gKeys[i].data,gKeys[i].length); dumpKey(gKeys[i].data, gKeys[i].length);
printf(" found only %ld from %ld\n",gKeys[i].count,gKeys[i].in); printf(" found only %ld from %ld\n", gKeys[i].count, gKeys[i].in);
bailOut(); bailOut();
} }
} }
} }
/*! Simple test, just seeks down to every key - if it's in and couldn't
be found or it's not in and can be found, something must be wrong
*/
void void
checkTreeIntegrity(BPlusTree *tree) checkTreeIntegrity(BPlusTree* tree)
{ {
// simple test, just seeks down to every key - if it's in and couldn't
// be found or it's not in and can be found, something must be wrong
TreeIterator iterator(tree); TreeIterator iterator(tree);
for (int32 i = 0;i < gNum;i++) { for (int32 i = 0; i < gNum; i++) {
status_t status = iterator.Find((uint8 *)gKeys[i].data,gKeys[i].length); status_t status = iterator.Find((uint8*)gKeys[i].data, gKeys[i].length);
if (gKeys[i].in == 0) { if (gKeys[i].in == 0) {
if (status == B_OK) { if (status == B_OK) {
printf("found key %" B_PRId32 " even though it's not in!\n", i); printf("found key %" B_PRId32 " even though it's not in!\n", i);
bailOutWithKey(gKeys[i].data, gKeys[i].length); bailOutWithKey(gKeys[i].data, gKeys[i].length);
} }
} else if (status != B_OK) { } else if (status != B_OK) {
printf("TreeIterator::Find() returned: %s\n",strerror(status)); printf("TreeIterator::Find() returned: %s\n", strerror(status));
bailOutWithKey(gKeys[i].data,gKeys[i].length); bailOutWithKey(gKeys[i].data, gKeys[i].length);
} }
} }
} }
void void
checkTree(BPlusTree *tree) checkTree(BPlusTree* tree)
{ {
if (!gExcessive) if (!gExcessive)
printf("* Check tree...\n"); printf("* Check tree...\n");
@@ -422,25 +424,22 @@ checkTree(BPlusTree *tree)
} }
// #pragma mark - // #pragma mark - "Torture" functions
//
// The tree "torture" functions
//
void void
addAllKeys(Transaction &transaction, BPlusTree *tree) addAllKeys(Transaction& transaction, BPlusTree* tree)
{ {
printf("*** Adding all keys to the tree...\n"); printf("*** Adding all keys to the tree...\n");
for (int32 i = 0;i < gNum;i++) { for (int32 i = 0; i < gNum; i++) {
status_t status = tree->Insert(transaction,(uint8 *)gKeys[i].data,gKeys[i].length,gKeys[i].value); status_t status = tree->Insert(transaction, (uint8*)gKeys[i].data,
if (status < B_OK) { gKeys[i].length, gKeys[i].value);
printf("BPlusTree::Insert() returned: %s\n",strerror(status)); if (status != B_OK) {
printf("BPlusTree::Insert() returned: %s\n", strerror(status));
printf("key: "); printf("key: ");
dumpKey(gKeys[i].data,gKeys[i].length); dumpKey(gKeys[i].data, gKeys[i].length);
putchar('\n'); putchar('\n');
} } else {
else {
gKeys[i].in++; gKeys[i].in++;
gTreeCount++; gTreeCount++;
} }
@@ -450,20 +449,19 @@ addAllKeys(Transaction &transaction, BPlusTree *tree)
void void
removeAllKeys(Transaction &transaction, BPlusTree *tree) removeAllKeys(Transaction& transaction, BPlusTree* tree)
{ {
printf("*** Removing all keys from the tree...\n"); printf("*** Removing all keys from the tree...\n");
for (int32 i = 0;i < gNum;i++) { for (int32 i = 0; i < gNum; i++) {
while (gKeys[i].in > 0) { while (gKeys[i].in > 0) {
status_t status = tree->Remove(transaction, (uint8 *)gKeys[i].data, status_t status = tree->Remove(transaction, (uint8*)gKeys[i].data,
gKeys[i].length, gKeys[i].value); gKeys[i].length, gKeys[i].value);
if (status < B_OK) { if (status != B_OK) {
printf("BPlusTree::Remove() returned: %s\n", strerror(status)); printf("BPlusTree::Remove() returned: %s\n", strerror(status));
printf("key: "); printf("key: ");
dumpKey(gKeys[i].data, gKeys[i].length); dumpKey(gKeys[i].data, gKeys[i].length);
putchar('\n'); putchar('\n');
} } else {
else {
gKeys[i].in--; gKeys[i].in--;
gTreeCount--; gTreeCount--;
} }
@@ -475,29 +473,32 @@ removeAllKeys(Transaction &transaction, BPlusTree *tree)
void void
duplicateTest(Transaction &transaction,BPlusTree *tree) duplicateTest(Transaction& transaction, BPlusTree* tree)
{ {
int32 index = int32(1.0 * gNum * rand() / RAND_MAX); int32 index = int32(1.0 * gNum * rand() / RAND_MAX);
if (index == gNum) if (index == gNum)
index = gNum - 1; index = gNum - 1;
printf("*** Duplicate test with key "); printf("*** Duplicate test with key ");
dumpKey(gKeys[index].data,gKeys[index].length); dumpKey(gKeys[index].data, gKeys[index].length);
puts("..."); puts("...");
status_t status; status_t status;
int32 insertTotal = 0; int32 insertTotal = 0;
for (int32 i = 0;i < 8;i++) { for (int32 i = 0; i < 8; i++) {
int32 insertCount = int32(1000.0 * rand() / RAND_MAX); int32 insertCount = int32(1000.0 * rand() / RAND_MAX);
if (gVerbose) if (gVerbose) {
printf("* insert %ld to %ld old entries...\n",insertCount,insertTotal + gKeys[index].in); printf("* insert %ld to %ld old entries...\n", insertCount,
insertTotal + gKeys[index].in);
}
for (int32 j = 0;j < insertCount;j++) { for (int32 j = 0; j < insertCount; j++) {
status = tree->Insert(transaction,(uint8 *)gKeys[index].data,gKeys[index].length,gKeys[index].value); status = tree->Insert(transaction, (uint8*)gKeys[index].data,
if (status < B_OK) { gKeys[index].length, gKeys[index].value);
printf("BPlusTree::Insert() returned: %s\n",strerror(status)); if (status != B_OK) {
bailOutWithKey(gKeys[index].data,gKeys[index].length); printf("BPlusTree::Insert() returned: %s\n", strerror(status));
bailOutWithKey(gKeys[index].data, gKeys[index].length);
} }
insertTotal++; insertTotal++;
gTreeCount++; gTreeCount++;
@@ -515,14 +516,18 @@ duplicateTest(Transaction &transaction,BPlusTree *tree)
} else } else
count = insertTotal; count = insertTotal;
if (gVerbose) if (gVerbose) {
printf("* remove %ld from %ld entries...\n",count,insertTotal + gKeys[index].in); printf("* remove %ld from %ld entries...\n", count,
insertTotal + gKeys[index].in);
}
for (int32 j = 0;j < count;j++) { for (int32 j = 0; j < count; j++) {
status_t status = tree->Remove(transaction,(uint8 *)gKeys[index].data,gKeys[index].length,gKeys[index].value); status_t status = tree->Remove(transaction,
if (status < B_OK) { (uint8*)gKeys[index].data, gKeys[index].length,
printf("BPlusTree::Remove() returned: %s\n",strerror(status)); gKeys[index].value);
bailOutWithKey(gKeys[index].data,gKeys[index].length); if (status != B_OK) {
printf("BPlusTree::Remove() returned: %s\n", strerror(status));
bailOutWithKey(gKeys[index].data, gKeys[index].length);
} }
insertTotal--; insertTotal--;
gTreeCount--; gTreeCount--;
@@ -539,22 +544,26 @@ duplicateTest(Transaction &transaction,BPlusTree *tree)
void void
addRandomSet(Transaction &transaction,BPlusTree *tree,int32 num) addRandomSet(Transaction& transaction, BPlusTree* tree, int32 num)
{ {
printf("*** Add random set to tree (%ld to %ld old entries)...\n",num,gTreeCount); printf("*** Add random set to tree (%ld to %ld old entries)...\n",
num, gTreeCount);
for (int32 i = 0;i < num;i++) { for (int32 i = 0; i < num; i++) {
int32 index = int32(1.0 * gNum * rand() / RAND_MAX); int32 index = int32(1.0 * gNum * rand() / RAND_MAX);
if (index == gNum) if (index == gNum)
index = gNum - 1; index = gNum - 1;
if (gVerbose) if (gVerbose) {
printf("adding key %ld (%ld times in the tree)\n",index,gKeys[index].in); 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); status_t status = tree->Insert(transaction, (uint8*)gKeys[index].data,
if (status < B_OK) { gKeys[index].length, gKeys[index].value);
printf("BPlusTree::Insert() returned: %s\n",strerror(status)); if (status != B_OK) {
bailOutWithKey(gKeys[index].data,gKeys[index].length); printf("BPlusTree::Insert() returned: %s\n", strerror(status));
bailOutWithKey(gKeys[index].data, gKeys[index].length);
} }
gKeys[index].in++; gKeys[index].in++;
gTreeCount++; gTreeCount++;
@@ -568,13 +577,14 @@ addRandomSet(Transaction &transaction,BPlusTree *tree,int32 num)
void void
removeRandomSet(Transaction &transaction,BPlusTree *tree,int32 num) removeRandomSet(Transaction& transaction, BPlusTree* tree, int32 num)
{ {
printf("*** Remove random set from tree (%ld from %ld entries)...\n",num,gTreeCount); printf("*** Remove random set from tree (%ld from %ld entries)...\n",
num, gTreeCount);
int32 tries = 500; int32 tries = 500;
for (int32 i = 0;i < num;i++) { for (int32 i = 0; i < num; i++) {
if (gTreeCount < 1) if (gTreeCount < 1)
break; break;
@@ -589,13 +599,16 @@ removeRandomSet(Transaction &transaction,BPlusTree *tree,int32 num)
continue; continue;
} }
if (gVerbose) if (gVerbose) {
printf("removing key %ld (%ld times in the tree)\n",index,gKeys[index].in); 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); status_t status = tree->Remove(transaction, (uint8*)gKeys[index].data,
if (status < B_OK) { gKeys[index].length, gKeys[index].value);
printf("BPlusTree::Remove() returned: %s\n",strerror(status)); if (status != B_OK) {
bailOutWithKey(gKeys[index].data,gKeys[index].length); printf("BPlusTree::Remove() returned: %s\n", strerror(status));
bailOutWithKey(gKeys[index].data, gKeys[index].length);
} }
gKeys[index].in--; gKeys[index].in--;
gTreeCount--; gTreeCount--;
@@ -612,11 +625,12 @@ removeRandomSet(Transaction &transaction,BPlusTree *tree,int32 num)
void void
usage(char *program) usage(char* program)
{ {
if (strrchr(program,'/')) if (strrchr(program, '/'))
program = strrchr(program,'/') + 1; program = strrchr(program, '/') + 1;
fprintf(stderr,"usage: %s [-veh] [-t type] [-n keys] [-i iterations] [-h times] [-r seed]\n" fprintf(stderr, "usage: %s [-veh] [-t type] [-n keys] [-i iterations] "
"[-h times] [-r seed]\n"
"BFS B+Tree torture test\n" "BFS B+Tree torture test\n"
"\t-t\ttype is one of string, int32, uint32, int64, uint64, float,\n" "\t-t\ttype is one of string, int32, uint32, int64, uint64, float,\n"
"\t\tor double; defaults to string.\n" "\t\tor double; defaults to string.\n"
@@ -625,7 +639,8 @@ usage(char *program)
"\t-i\titerations is the number of the test cycles, defaults to %d.\n" "\t-i\titerations is the number of the test cycles, defaults to %d.\n"
"\t-r\tthe seed for the random function, 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-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-e\texcessive validity tests: tree contents will be tested after "
"every operation\n"
"\t-v\tfor verbose output.\n", "\t-v\tfor verbose output.\n",
program, DEFAULT_NUM_KEYS, DEFAULT_ITERATIONS, gSeed); program, DEFAULT_NUM_KEYS, DEFAULT_ITERATIONS, gSeed);
exit(0); exit(0);
@@ -633,22 +648,18 @@ usage(char *program)
int int
main(int argc,char **argv) main(int argc, char** argv)
{ {
char *program = argv[0]; char* program = argv[0];
while (*++argv) while (*++argv) {
{ char* arg = *argv;
char *arg = *argv; if (*arg == '-') {
if (*arg == '-')
{
if (arg[1] == '-') if (arg[1] == '-')
usage(program); usage(program);
while (*++arg && isalpha(*arg)) while (*++arg && isalpha(*arg)) {
{ switch (*arg) {
switch (*arg)
{
case 'v': case 'v':
gVerbose = true; gVerbose = true;
break; break;
@@ -659,23 +670,23 @@ main(int argc,char **argv)
if (*++argv == NULL) if (*++argv == NULL)
usage(program); usage(program);
if (!strcmp(*argv,"string")) if (!strcmp(*argv, "string"))
gType = S_STR_INDEX; gType = S_STR_INDEX;
else if (!strcmp(*argv,"int32") else if (!strcmp(*argv, "int32")
|| !strcmp(*argv,"int")) || !strcmp(*argv, "int"))
gType = S_INT_INDEX; gType = S_INT_INDEX;
else if (!strcmp(*argv,"uint32") else if (!strcmp(*argv, "uint32")
|| !strcmp(*argv,"uint")) || !strcmp(*argv, "uint"))
gType = S_UINT_INDEX; gType = S_UINT_INDEX;
else if (!strcmp(*argv,"int64") else if (!strcmp(*argv, "int64")
|| !strcmp(*argv,"llong")) || !strcmp(*argv, "llong"))
gType = S_LONG_LONG_INDEX; gType = S_LONG_LONG_INDEX;
else if (!strcmp(*argv,"uint64") else if (!strcmp(*argv, "uint64")
|| !strcmp(*argv,"ullong")) || !strcmp(*argv, "ullong"))
gType = S_ULONG_LONG_INDEX; gType = S_ULONG_LONG_INDEX;
else if (!strcmp(*argv,"float")) else if (!strcmp(*argv, "float"))
gType = S_FLOAT_INDEX; gType = S_FLOAT_INDEX;
else if (!strcmp(*argv,"double")) else if (!strcmp(*argv, "double"))
gType = S_DOUBLE_INDEX; gType = S_DOUBLE_INDEX;
else else
usage(program); usage(program);
@@ -712,55 +723,55 @@ main(int argc,char **argv)
break; break;
} }
} }
} } else
else
break; break;
} }
// we do want to have reproducible random keys // we do want to have reproducible random keys
if (gVerbose) if (gVerbose)
printf("Set seed to %ld\n",gSeed); printf("Set seed to %ld\n", gSeed);
srand(gSeed); srand(gSeed);
Inode inode("tree.data",gType | S_ALLOW_DUPS); Inode inode("tree.data", gType | S_ALLOW_DUPS);
rw_lock_write_lock(&inode.Lock()); rw_lock_write_lock(&inode.Lock());
gVolume = inode.GetVolume(); gVolume = inode.GetVolume();
Transaction transaction(gVolume,0); Transaction transaction(gVolume, 0);
init_cache(gVolume->Device(),gVolume->BlockSize()); init_cache(gVolume->Device(), gVolume->BlockSize());
//
// Create the tree, the keys, and add all keys to the tree initially // Create the tree, the keys, and add all keys to the tree initially
//
BPlusTree tree(transaction,&inode); BPlusTree tree(transaction, &inode);
status_t status; status_t status = tree.InitCheck();
if ((status = tree.InitCheck()) < B_OK) { if (status != B_OK) {
fprintf(stderr,"creating tree failed: %s\n",strerror(status)); fprintf(stderr, "creating tree failed: %s\n", strerror(status));
bailOut(); bailOut();
} }
printf("*** Creating %ld keys...\n",gNum);
if ((status = createKeys()) < B_OK) { printf("*** Creating %ld keys...\n", gNum);
fprintf(stderr,"creating keys failed: %s\n",strerror(status)); status = createKeys();
if (status != B_OK) {
fprintf(stderr, "creating keys failed: %s\n", strerror(status));
bailOut(); bailOut();
} }
if (gVerbose) if (gVerbose)
dumpKeys(); dumpKeys();
for (int32 j = 0; j < gHard; j++ ) { for (int32 j = 0; j < gHard; j++) {
addAllKeys(transaction, &tree); addAllKeys(transaction, &tree);
//
// Run the tests (they will exit the app, if an error occurs) // Run the tests (they will exit the app, if an error occurs)
//
for (int32 i = 0;i < gIterations;i++) { for (int32 i = 0; i < gIterations; i++) {
printf("---------- Test iteration %ld ---------------------------------\n",i+1); printf("---------- Test iteration %ld --------------------------\n",
i + 1);
addRandomSet(transaction,&tree,int32(1.0 * gNum * rand() / RAND_MAX)); addRandomSet(transaction, &tree,
removeRandomSet(transaction,&tree,int32(1.0 * gNum * rand() / RAND_MAX)); int32(1.0 * gNum * rand() / RAND_MAX));
duplicateTest(transaction,&tree); removeRandomSet(transaction, &tree,
int32(1.0 * gNum * rand() / RAND_MAX));
duplicateTest(transaction, &tree);
} }
removeAllKeys(transaction, &tree); removeAllKeys(transaction, &tree);
@@ -771,7 +782,7 @@ main(int argc,char **argv)
// of course, we would have to free all our memory in a real application here... // of course, we would have to free all our memory in a real application here...
// write the cache back to the tree // write the cache back to the tree
shutdown_cache(gVolume->Device(),gVolume->BlockSize()); shutdown_cache(gVolume->Device(), gVolume->BlockSize());
return 0; return 0;
} }