mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 18:43:03 +01:00
Totally misc.
This commit is contained in:
parent
21a1eed8a1
commit
812058f940
@ -61,7 +61,8 @@ const int NODE_PAGE_SIZE = 3000;
|
|||||||
// should be more than enough. No checks are performed in code against overflow of this value
|
// should be more than enough. No checks are performed in code against overflow of this value
|
||||||
const int MAX_TREE_LEVEL = 30;
|
const int MAX_TREE_LEVEL = 30;
|
||||||
|
|
||||||
class MallocAllocator {
|
class MallocAllocator
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
void *allocate(size_t size) {
|
void *allocate(size_t size) {
|
||||||
return malloc(size);
|
return malloc(size);
|
||||||
@ -103,9 +104,10 @@ template <typename Value, typename Key = Value, typename Allocator = MallocAlloc
|
|||||||
typename Cmp = DefaultComparator<Key>,
|
typename Cmp = DefaultComparator<Key>,
|
||||||
int LeafCount = LEAF_PAGE_SIZE / sizeof(Value),
|
int LeafCount = LEAF_PAGE_SIZE / sizeof(Value),
|
||||||
int NodeCount = NODE_PAGE_SIZE / sizeof(void*)>
|
int NodeCount = NODE_PAGE_SIZE / sizeof(void*)>
|
||||||
class BePlusTree {
|
class BePlusTree
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
BePlusTree(Allocator *_pool)
|
explicit BePlusTree(Allocator *_pool)
|
||||||
: pool(_pool), level(0), root(NULL), defaultAccessor(this)
|
: pool(_pool), level(0), root(NULL), defaultAccessor(this)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
@ -119,13 +121,15 @@ public:
|
|||||||
append(from);
|
append(from);
|
||||||
}
|
}
|
||||||
|
|
||||||
BePlusTree& operator =(BePlusTree& from) {
|
BePlusTree& operator =(BePlusTree& from)
|
||||||
|
{
|
||||||
clear();
|
clear();
|
||||||
append(from);
|
append(from);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear() {
|
void clear()
|
||||||
|
{
|
||||||
defaultAccessor.curr = NULL;
|
defaultAccessor.curr = NULL;
|
||||||
|
|
||||||
// Do not deallocate root page if tree is shallow
|
// Do not deallocate root page if tree is shallow
|
||||||
@ -168,12 +172,14 @@ public:
|
|||||||
level = 0;
|
level = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
~BePlusTree() {
|
~BePlusTree()
|
||||||
|
{
|
||||||
clear();
|
clear();
|
||||||
pool->deallocate(root);
|
pool->deallocate(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isEmpty() const {
|
bool isEmpty() const
|
||||||
|
{
|
||||||
return
|
return
|
||||||
root == NULL ||
|
root == NULL ||
|
||||||
(level == 0 && ((ItemList*)root)->getCount() == 0);
|
(level == 0 && ((ItemList*)root)->getCount() == 0);
|
||||||
@ -209,7 +215,8 @@ public:
|
|||||||
Value& current() const { return defaultAccessor.current(); }
|
Value& current() const { return defaultAccessor.current(); }
|
||||||
|
|
||||||
// Returns true if this tree appears to contain more elements than the other
|
// Returns true if this tree appears to contain more elements than the other
|
||||||
bool seemsBiggerThan(const BePlusTree &other) const {
|
bool seemsBiggerThan(const BePlusTree &other) const
|
||||||
|
{
|
||||||
if (level != other.level)
|
if (level != other.level)
|
||||||
return level > other.level;
|
return level > other.level;
|
||||||
|
|
||||||
@ -225,11 +232,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Compute approximate number of leafs in the tree
|
// Compute approximate number of leafs in the tree
|
||||||
size_t approxCount() const {
|
size_t approxCount() const
|
||||||
|
{
|
||||||
if (!root)
|
if (!root)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (level == 0) return ((ItemList*)root)->getCount();
|
if (level == 0)
|
||||||
|
return ((ItemList*)root)->getCount();
|
||||||
|
|
||||||
// Tree is large. Roughtly estimate number of leaf nodes using number of
|
// Tree is large. Roughtly estimate number of leaf nodes using number of
|
||||||
// items in root list and depth of the tree. Theoretically possible fill
|
// items in root list and depth of the tree. Theoretically possible fill
|
||||||
@ -245,7 +254,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Compute approximate memory consumption for tree in bytes
|
// Compute approximate memory consumption for tree in bytes
|
||||||
size_t approxSize() const {
|
size_t approxSize() const
|
||||||
|
{
|
||||||
if (!root)
|
if (!root)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -263,7 +273,8 @@ public:
|
|||||||
return ((NodeList*)root)->getCount() * bytes_per_node;
|
return ((NodeList*)root)->getCount() * bytes_per_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
void append(BePlusTree& from) {
|
void append(BePlusTree& from)
|
||||||
|
{
|
||||||
// This is slow approach especially when used for assignment.
|
// This is slow approach especially when used for assignment.
|
||||||
// Optimize it when need arises.
|
// Optimize it when need arises.
|
||||||
Accessor accessor(&from);
|
Accessor accessor(&from);
|
||||||
@ -285,12 +296,15 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
class NodeList;
|
class NodeList;
|
||||||
|
|
||||||
class ItemList : public SortedVector<Value, LeafCount, Key, KeyOfValue, Cmp> {
|
class ItemList : public SortedVector<Value, LeafCount, Key, KeyOfValue, Cmp>
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
NodeList *parent;
|
NodeList *parent;
|
||||||
ItemList *next, *prev;
|
ItemList *next, *prev;
|
||||||
// Adds newly created item to doubly-linked list
|
// Adds newly created item to doubly-linked list
|
||||||
ItemList(ItemList *items) : parent(NULL) {
|
ItemList(ItemList *items)
|
||||||
|
: parent(NULL)
|
||||||
|
{
|
||||||
if ((next = items->next))
|
if ((next = items->next))
|
||||||
next->prev = this;
|
next->prev = this;
|
||||||
prev = items;
|
prev = items;
|
||||||
@ -306,10 +320,13 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
class NodeList : public SortedVector<void*, NodeCount, Key, NodeList, Cmp> {
|
class NodeList : public SortedVector<void*, NodeCount, Key, NodeList, Cmp>
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
// Adds newly created item to the doubly-linked list
|
// Adds newly created item to the doubly-linked list
|
||||||
NodeList(NodeList *items) : parent(NULL) {
|
NodeList(NodeList *items)
|
||||||
|
: parent(NULL)
|
||||||
|
{
|
||||||
if ((next = items->next))
|
if ((next = items->next))
|
||||||
next->prev = this;
|
next->prev = this;
|
||||||
prev = items;
|
prev = items;
|
||||||
@ -330,7 +347,8 @@ public:
|
|||||||
// add ItemList typedef for you compiler with whichever syntax it likes
|
// add ItemList typedef for you compiler with whichever syntax it likes
|
||||||
return KeyOfValue::generate(item, *((ItemList *)item)->begin());
|
return KeyOfValue::generate(item, *((ItemList *)item)->begin());
|
||||||
}
|
}
|
||||||
static void setNodeParentAndLevel(void *node, int level, NodeList *parent) {
|
static void setNodeParentAndLevel(void *node, int level, NodeList *parent)
|
||||||
|
{
|
||||||
if (level) {
|
if (level) {
|
||||||
((NodeList *)node)->parent = parent;
|
((NodeList *)node)->parent = parent;
|
||||||
((NodeList *)node)->level = level - 1;
|
((NodeList *)node)->level = level - 1;
|
||||||
@ -338,7 +356,8 @@ public:
|
|||||||
else
|
else
|
||||||
((ItemList *)node)->parent = parent;
|
((ItemList *)node)->parent = parent;
|
||||||
}
|
}
|
||||||
static void setNodeParent(void *node, int level, NodeList *parent) {
|
static void setNodeParent(void *node, int level, NodeList *parent)
|
||||||
|
{
|
||||||
if (level)
|
if (level)
|
||||||
((NodeList *)node)->parent = parent;
|
((NodeList *)node)->parent = parent;
|
||||||
else
|
else
|
||||||
@ -347,17 +366,20 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
class Accessor {
|
class Accessor
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
Accessor(BePlusTree* _tree) : curr(NULL), curPos(0), tree(_tree) {}
|
explicit Accessor(BePlusTree* _tree) : curr(NULL), curPos(0), tree(_tree) {}
|
||||||
|
|
||||||
bool add(const Value& item) {
|
bool add(const Value& item)
|
||||||
|
{
|
||||||
return tree->add(item, this);
|
return tree->add(item, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove item. Current position moves to next item after this call.
|
// Remove item. Current position moves to next item after this call.
|
||||||
// If next item doesn't exist method returns false
|
// If next item doesn't exist method returns false
|
||||||
bool fastRemove() {
|
bool fastRemove()
|
||||||
|
{
|
||||||
// invalidate current position of defaultAccessor
|
// invalidate current position of defaultAccessor
|
||||||
// if i'm not a defaultAccessor
|
// if i'm not a defaultAccessor
|
||||||
if (this != &tree->defaultAccessor)
|
if (this != &tree->defaultAccessor)
|
||||||
@ -425,17 +447,21 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool locate(const Key& key) {
|
bool locate(const Key& key)
|
||||||
|
{
|
||||||
return locate(locEqual, key);
|
return locate(locEqual, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Position accessor on item having LocType relationship with given key
|
// Position accessor on item having LocType relationship with given key
|
||||||
// If method returns false position of accessor is not defined.
|
// If method returns false position of accessor is not defined.
|
||||||
bool locate(LocType lt, const Key& key) {
|
bool locate(LocType lt, const Key& key)
|
||||||
|
{
|
||||||
// Inlining is efficient here because LocType will be known in most cases
|
// Inlining is efficient here because LocType will be known in most cases
|
||||||
// and compiler will be able to eliminate most of code
|
// and compiler will be able to eliminate most of code
|
||||||
void *list = tree->root;
|
void *list = tree->root;
|
||||||
if (!list) return false; // Uninitalized tree
|
if (!list)
|
||||||
|
return false; // Uninitalized tree
|
||||||
|
|
||||||
for (int lev = tree->level; lev; lev--) {
|
for (int lev = tree->level; lev; lev--) {
|
||||||
size_t pos;
|
size_t pos;
|
||||||
if (!((NodeList *)list)->find(key, pos))
|
if (!((NodeList *)list)->find(key, pos))
|
||||||
@ -483,10 +509,12 @@ public:
|
|||||||
}
|
}
|
||||||
// If method returns false it means list is empty and
|
// If method returns false it means list is empty and
|
||||||
// position of accessor is not defined.
|
// position of accessor is not defined.
|
||||||
bool getFirst() {
|
bool getFirst()
|
||||||
|
{
|
||||||
void *items = tree->root;
|
void *items = tree->root;
|
||||||
if (!items)
|
if (!items)
|
||||||
return false; // Uninitalized tree
|
return false; // Uninitalized tree
|
||||||
|
|
||||||
for (int i = tree->level; i > 0; i--)
|
for (int i = tree->level; i > 0; i--)
|
||||||
items = (*(NodeList *)items)[0];
|
items = (*(NodeList *)items)[0];
|
||||||
curr = (ItemList *)items;
|
curr = (ItemList *)items;
|
||||||
@ -495,10 +523,12 @@ public:
|
|||||||
}
|
}
|
||||||
// If method returns false it means list is empty and
|
// If method returns false it means list is empty and
|
||||||
// position of accessor is not defined.
|
// position of accessor is not defined.
|
||||||
bool getLast() {
|
bool getLast()
|
||||||
|
{
|
||||||
void *items = tree->root;
|
void *items = tree->root;
|
||||||
if (!items)
|
if (!items)
|
||||||
return false; // Uninitalized tree
|
return false; // Uninitalized tree
|
||||||
|
|
||||||
for (int i = tree->level; i > 0; i--)
|
for (int i = tree->level; i > 0; i--)
|
||||||
items = (*(NodeList *)items)[((NodeList *)items)->getCount() - 1];
|
items = (*(NodeList *)items)[((NodeList *)items)->getCount() - 1];
|
||||||
curr = (ItemList *)items;
|
curr = (ItemList *)items;
|
||||||
@ -510,7 +540,8 @@ public:
|
|||||||
}
|
}
|
||||||
// Accessor position must be establised via successful call to getFirst(),
|
// Accessor position must be establised via successful call to getFirst(),
|
||||||
// getLast() or locate() before you can call this method
|
// getLast() or locate() before you can call this method
|
||||||
bool getNext() {
|
bool getNext()
|
||||||
|
{
|
||||||
curPos++;
|
curPos++;
|
||||||
if (curPos >= curr->getCount()) {
|
if (curPos >= curr->getCount()) {
|
||||||
if (curr->next) {
|
if (curr->next) {
|
||||||
@ -527,7 +558,8 @@ public:
|
|||||||
}
|
}
|
||||||
// Accessor position must be establised via successful call to getFirst(),
|
// Accessor position must be establised via successful call to getFirst(),
|
||||||
// getLast() or locate() before you can call this method
|
// getLast() or locate() before you can call this method
|
||||||
bool getPrev() {
|
bool getPrev()
|
||||||
|
{
|
||||||
if (curPos == 0) {
|
if (curPos == 0) {
|
||||||
if (curr->prev) {
|
if (curr->prev) {
|
||||||
curr = curr->prev;
|
curr = curr->prev;
|
||||||
|
Loading…
Reference in New Issue
Block a user