8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-23 06:03:02 +01:00

Slightly refine BeePlusTree accessor semantics

This commit is contained in:
skidder 2004-06-13 23:49:28 +00:00
parent 5803b123dc
commit 3ad92020ae
3 changed files with 189 additions and 42 deletions

View File

@ -32,7 +32,7 @@
* Contributor(s):
*
*
* $Id: class_test.cpp,v 1.16 2004-06-13 18:30:20 skidder Exp $
* $Id: class_test.cpp,v 1.17 2004-06-13 23:49:28 skidder Exp $
*
*/
@ -129,6 +129,67 @@ void testBePlusTree() {
printf(" DONE\n");
bool passed = true;
printf("Empty trees verifying fastRemove() result: ");
for (i = 0; i < v.getCount()-1; i++) {
if (!tree1.getLast())
passed = false;
tree1.current().count--;
if (!tree1.current().count)
if (tree1.fastRemove())
passed = false;
if (!tree2.getLast())
passed = false;
tree2.current().count--;
if (!tree2.current().count)
if (tree2.fastRemove())
passed = false;
}
if (!tree1.getLast())
passed = false;
tree1.current().count--;
if (tree1.current().count)
passed = false;
else
if (tree1.fastRemove())
passed = false;
if (!tree2.getLast())
passed = false;
tree2.current().count--;
if (tree2.current().count)
passed = false;
else
if (tree2.fastRemove())
passed = false;
printf(passed ? "PASSED\n" : "FAILED\n");
passed = true;
printf("Fill trees with data again: ");
cnt1 = 0; cnt2 = 0;
for (i = 0; i < v.getCount(); i++) {
if (tree1.locate(locEqual, v[i]))
tree1.current().count++;
else {
Test t;
t.value = v[i];
t.count = 1;
if (!tree1.add(t))
fb_assert(false);
cnt1++;
}
if (tree2.locate(locEqual, v[i]))
tree2.current().count++;
else {
Test t;
t.value = v[i];
t.count = 1;
if (!tree2.add(t))
fb_assert(false);
cnt2++;
}
}
printf(" DONE\n");
printf("Check that tree(2) contains test data: ");
for (i = 0; i < v.getCount(); i++) {
@ -171,13 +232,25 @@ void testBePlusTree() {
printf(passed ? "PASSED\n" : "FAILED\n");
printf("Remove half of data from the trees: ");
passed = true;
while (v.getCount() > TEST_ITEMS / 2) {
if (!tree1.locate(locEqual, v[v.getCount() - 1]))
fb_assert(false);
if (tree1.current().count > 1)
tree1.current().count--;
else {
tree1.fastRemove();
int nextValue = -1;
if (tree1.getNext()) {
nextValue = tree1.current().value;
tree1.getPrev();
}
if (tree1.fastRemove()) {
if (tree1.current().value != nextValue)
passed = false;
} else {
if (nextValue >= 0)
passed = false;
}
cnt1--;
}
if (!tree2.locate(locEqual, v[v.getCount() - 1]))
@ -185,13 +258,26 @@ void testBePlusTree() {
if (tree2.current().count > 1)
tree2.current().count--;
else {
tree2.fastRemove();
int nextValue = -1;
if (tree2.getNext()) {
nextValue = tree2.current().value;
tree2.getPrev();
}
if (tree2.fastRemove()) {
if (tree2.current().value != nextValue)
passed = false;
} else {
if (nextValue >= 0)
passed = false;
}
cnt2--;
}
v.shrink(v.getCount() - 1);
}
printf(" DONE\n");
printf(passed ? "PASSED\n" : "FAILED\n");
passed = true;
printf("Check that tree(2) contains test data: ");
for (i = 0; i < v.getCount(); i++) {
if(!tree1.locate(locEqual, v[i]))
@ -243,7 +329,18 @@ void testBePlusTree() {
if (tree1.current().count > 1)
tree1.current().count--;
else {
tree1.fastRemove();
int nextValue = -1;
if (tree1.getNext()) {
nextValue = tree1.current().value;
tree1.getPrev();
}
if (tree1.fastRemove()) {
if (tree1.current().value != nextValue)
passed = false;
} else {
if (nextValue >= 0)
passed = false;
}
cnt1--;
}
if (!tree2.locate(locEqual, v[i]))
@ -251,11 +348,23 @@ void testBePlusTree() {
if (tree2.current().count > 1)
tree2.current().count--;
else {
tree2.fastRemove();
int nextValue = -1;
if (tree2.getNext()) {
nextValue = tree2.current().value;
tree2.getPrev();
}
if (tree2.fastRemove()) {
if (tree2.current().value != nextValue)
passed = false;
} else {
if (nextValue >= 0)
passed = false;
}
cnt2--;
}
}
printf(" DONE\n");
printf(passed ? "PASSED\n" : "FAILED\n");
passed = true;
printf("Check that both trees do not contain anything: ");
if (tree1.getFirst())

View File

@ -2,12 +2,15 @@
# this should be compiled with optimization turned off and with NDEBUG undefined
ulimit -s unlimited
ulimit -c unlimited
g++ -ggdb -Wall -I../../include -DTESTING_ONLY -DDEBUG_GDS_ALLOC class_test.cpp alloc.cpp ../fb_exception.cpp 2> aa
#g++ -ggdb -Wall -I../../include -DTESTING_ONLY -DDEBUG_GDS_ALLOC class_test.cpp alloc.cpp ../fb_exception.cpp 2> aa
#./a.out
#export LD_LIBRARY_PATH=/usr/local/lib64
# Chose the best algorithm parameters for the target architecture
#g++ -O3 -DHAVE_STDLIB_H -DNDEBUG -DTESTING_ONLY \
#-I../../include class_perf.cpp alloc.cpp ../fb_exception.cpp 2> aa
#/usr/local/bin/
g++ -O3 -DHAVE_STDLIB_H -DNDEBUG -DTESTING_ONLY \
-I../../include class_perf.cpp alloc.cpp ../fb_exception.cpp 2> aa
#g++ -ggdb -I../../include class_perf.cpp alloc.cpp \
#../memory/memory_pool.cpp ../fb_exception.cpp ../memory/allocators.cpp 2> aa

View File

@ -32,7 +32,7 @@
* Contributor(s):
*
*
* $Id: tree.h,v 1.30 2004-06-13 03:09:14 brodsom Exp $
* $Id: tree.h,v 1.31 2004-06-13 23:49:28 skidder Exp $
*
*/
@ -149,8 +149,9 @@ public:
bool add(const Value& item);
/* Remove item as quickly as possible. Current position is undefined after this call */
void fastRemove() { defaultAccessor.fastRemove(); }
// Remove item. Current position moves to next item after this call.
// If next item doesn't exist method returns false
bool fastRemove() { return defaultAccessor.fastRemove(); }
bool locate(Key& key) { return defaultAccessor.locate(locEqual, key); }
@ -237,11 +238,12 @@ public:
public:
Accessor(BePlusTree* _tree) : tree(_tree), curr(NULL), curPos(0) {}
/* Remove item as quickly as possible. Current position is undefined after this call */
void fastRemove() {
// Remove item. Current position moves to next item after this call.
// If next item doesn't exist method returns false
bool fastRemove() {
if ( !tree->level ) {
curr->remove(curPos);
return;
return curPos < curr->getCount();
}
if ( curr->getCount() == 1 ) {
// Only one node left in the current page. We cannot remove it directly
@ -249,52 +251,66 @@ public:
fb_assert(curPos == 0);
ItemList *temp;
if ( (temp = curr->prev) && NEED_MERGE(temp->getCount(), LeafCount) ) {
temp = curr->next;
tree->_removePage(0, curr);
curr = temp;
return curr;
}
else
if ( (temp = curr->next) && NEED_MERGE(temp->getCount(), LeafCount) ) {
tree->_removePage(0, curr);
curr = temp;
return true;
}
else
if ( (temp = curr->prev) ) {
(*curr)[0] = (*temp)[temp->getCount() - 1];
temp->shrink(temp->getCount() - 1);
curr = curr->next;
return curr;
}
else
if ( (temp = curr->next) ) {
(*curr)[0] = (*temp)[0];
temp->remove(0);
return true;
}
else
{
// It means the tree is broken
fb_assert(false);
}
// It means the tree is broken
fb_assert(false);
return false;
}
else {
curr->remove(curPos);
ItemList *temp;
if ( (temp = curr->prev) && NEED_MERGE(temp->getCount() + curr->getCount(), LeafCount) ) {
// After join upper levels of the tree remain stable because join doesn't change
// key of the page. The same applies to lower case too.
temp->join(*curr);
tree->_removePage(0, curr);
}
else
curr->remove(curPos);
ItemList *temp;
if ( (temp = curr->prev) && NEED_MERGE(temp->getCount() + curr->getCount(), LeafCount) ) {
// After join upper levels of the tree remain stable because join doesn't change
// key of the page. The same applies to lower case too.
curPos += temp->getCount();
temp->join(*curr);
tree->_removePage(0, curr);
curr = temp;
// The code below will adjust current position if needed
} else {
if ( (temp = curr->next) && NEED_MERGE(temp->getCount() + curr->getCount(), LeafCount) ) {
curr->join(*temp);
tree->_removePage(0, temp);
return true;
}
}
if (curPos >= curr->getCount()) {
fb_assert(curPos == curr->getCount());
curPos = 0;
curr = curr->next;
return curr;
}
return true;
}
bool locate(Key& key) {
return locate(locEqual, key);
}
// Inlining is efficient here because LocType will be known in most cases
// and compiler will be able to eliminate most of code
// Position accessor on item having LocType relationship with given key
// If method returns false position of accessor is not defined.
bool locate(LocType lt, Key& key) {
// Inlining is efficient here because LocType will be known in most cases
// and compiler will be able to eliminate most of code
void *list = tree->root;
if (!list) return false; // Uninitalized tree
for (int lev = tree->level; lev; lev--) {
@ -334,6 +350,8 @@ public:
}
return false;
}
// If method returns false it means list is empty and
// position of accessor is not defined.
bool getFirst() {
void *items = tree->root;
if (!items) return false; // Uninitalized tree
@ -343,6 +361,8 @@ public:
curPos = 0;
return ((ItemList *)items)->getCount();
}
// If method returns false it means list is empty and
// position of accessor is not defined.
bool getLast() {
void *items = tree->root;
if (!items) return false; // Uninitalized tree
@ -352,20 +372,35 @@ public:
curPos = ((ItemList *)items)->getCount() - 1;
return curPos >= 0;
}
// Accessor position must be establised via successful call to getFirst(),
// getLast() or locate() before you can call this method
bool getNext() {
curPos++;
if (curPos >= curr->getCount()) {
curr = curr->next;
curPos = 0;
if (curr->next) {
curr = curr->next;
curPos = 0;
} else {
// If we reached end of the list just return false and do not invalidate position
curPos--;
return false;
}
}
return curr != 0;
return true;
}
// Accessor position must be establised via successful call to getFirst(),
// getLast() or locate() before you can call this method
bool getPrev() {
curPos--;
if (curPos < 0) {
curr = curr->prev;
if (!curr) return false;
curPos = curr->getCount()-1;
if (curr->prev) {
curr = curr->prev;
curPos = curr->getCount()-1;
} else {
// If we reached beginning of the list just return false and do not invalidate position
curPos = 0;
return false;
}
}
return true;
}