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:
parent
5803b123dc
commit
3ad92020ae
@ -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())
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user