/b_tree/Node.cpp
C++ | 464 lines | 282 code | 47 blank | 135 comment | 40 complexity | 617f1831b465e2c295e59890d59bea5d MD5 | raw file
Possible License(s): BSD-3-Clause
- #ifndef DBS_NODE_CPP
- #define DBS_NODE_CPP
- #include "TreeStructs.h"
- #include "../util/tid.h"
- #include "../buffer/BufferFrame.h"
- #include "../buffer/BufferManager.h"
- #include <iostream>
- #include <sstream>
- #include <stdexcept>
- #include <cstring>
- //TODO - replace this const
- #define DEBUGSIZE 85
- using namespace std;
- template <class K>
- class Node {
- private:
- NodeData* data;
- K* keyOffset;
- void* valueOffset;
- bool dirty = false;
- BufferFrame& bufferFrame;
- unsigned int totalSpace;
-
- /**
- * Binary search within the node
- */
- K* binaryLookup(K* from, K* to, K key) {
- //TODO - compare
- return lower_bound(from, to, key);
- }
-
- /**
- * Returns the position where to insert the new key
- */
- unsigned int insertionOffset(K key) {
- K* keyPos = binaryLookup(keyOffset, keyOffset + data->entryCount - 1, key);
- return keyPos - keyOffset;
- }
-
- /**
- * Removes the given key and handles the memory
- */
- void removeKey(K key) {
- //Delete the key
- K* to = binaryLookup(keyOffset, keyOffset + data->entryCount - 1, key);
- //TODO - compare
- if (*to != key) {
- cout << "Could not remove key: " << key << " there is no such key" << endl;
- return;
- }
- K* from = to + 1;
- unsigned moveAmount = (keyOffset + data->entryCount - (to + 1)) * sizeof(K);
- //Move the memory and overwrite the old key
- memmove(to, from, moveAmount);
- }
- /**
- * toString method for booleans
- */
- string printBool(bool val) {
- if (val) {
- return "true";
- } else {
- return "false";
- }
- }
- /**
- * Calculate the value and key offset
- */
- void refreshValueOffset() {
- //The total amount of tuples is the size minus the header minus the first value
- //divided by the size of the key,value pairs
- if (data->isLeaf) {
- totalSpace = (PAGESIZE - sizeof(NodeData)) / (sizeof(K) + sizeof(TID));
- } else {
- totalSpace = (PAGESIZE - sizeof(NodeData)) / (sizeof(K) + sizeof(unsigned int));
- }
- valueOffset = keyOffset + totalSpace;
- }
- public:
- /**
- * Housing for this node is a given BufferFrame
- */
- Node(BufferFrame& bf) : bufferFrame(bf) {
- data = static_cast<NodeData *>(bf.getData());
- keyOffset = reinterpret_cast<K *>(static_cast<NodeData *>(data) + 1);
- refreshValueOffset();
- }
- ~Node() {
- cout << "Node destructor called" << endl;
- //TODO clean up
- }
- /**
- * Returns the offset for a given key
- */
- K* getKeyOffsetForKey(K key) {
- cout << "Looking for TID of key:" << key << endl;
- K* it = binaryLookup(keyOffset, keyOffset + data->entryCount - 1, key);
- //TODO - compare
- if (*it != key) {
- return NULL;
- } else {
- return it;
- }
- }
- /**
- * Sets the leaf property of this node to val
- */
- void setLeaf(bool val) {
- dirty = true;
- data->isLeaf = val;
- refreshValueOffset();
- }
- /**
- * Returns the next sibling and throws an exception if the node is no leaf
- */
- unsigned int getNextSibling() {
- if (isLeaf()) {
- return data->rightMostEntry;
- } else {
- throw new runtime_error("Get next sibling is called on an inner node");
- }
- }
- /**
- * Sets the next sibling and throws an exception if the node is no leaf
- */
- void setNextSibling(unsigned int val) {
- if (isLeaf()) {
- data->rightMostEntry = val;
- } else {
- throw new runtime_error("Set next sibling is called on an inner node");
- }
- }
- /**
- * Returns the keyOffset
- */
- K* getKeyOffset() {
- return keyOffset;
- }
-
- /**
- * Returns the valueOffset
- */
- void* getValueOffset() {
- return valueOffset;
- }
-
- /**
- * retuns the dirty property
- */
- bool isDirty() {
- return dirty;
- }
-
- /**
- * Returns the amount of free space in this node
- */
- unsigned int getFreeSpace() {
- return (totalSpace - data->entryCount);
- }
-
- /**
- * Returns whether there is space for more key, value pairs or not
- */
- bool isSpaceFree() {
- return ((totalSpace - data->entryCount) > 0);
- }
-
- /**
- * Returns the capacity of the node
- */
- unsigned int getCapacity() {
- return totalSpace;
- }
- /**
- * Returns the amount of entries in the node
- */
- unsigned int getEntryCount() {
- return data->entryCount;
- }
- /**
- * Returns the value at a hgiven index and throws an exception if the node is no leaf
- */
- unsigned int getValueAt(unsigned int index) {
- if (isLeaf()) {
- throw runtime_error("GetValueAt is called for a leaf node");
- }
- return *(static_cast<unsigned int*>(valueOffset) + index);
- }
- /**
- * Checks whether this node is a leaf or not
- */
- bool isLeaf() {
- return data->isLeaf;
- }
-
- /**
- * Splits the node by moving key value pairs to the given newNode
- */
- Node<K>* splitNode(Node<K>* newNode) {
- unsigned int mid = data->entryCount / 2;
- K* keyMiddle = keyOffset + mid;
- unsigned int newNodeCount = data->entryCount - mid;
- unsigned int oldNodeCount = mid;
-
- //Set the counts for old and new node
- newNode->setEntryCount(newNodeCount);
- setEntryCount(oldNodeCount);
- //Set the leaf property depending on the split node
- newNode->setLeaf(isLeaf());
- //Rearange the next pointer
- if (isLeaf()) {
- newNode->setNextSibling(getNextSibling());
- setNextSibling(newNode->getBufferFrame().getPageNo());
- } else {
- newNode->setUpper(getUpper());
- setUpper(0);
- }
- //Copy the keys to the new node
- memcpy(newNode->getKeyOffset(), keyMiddle, newNodeCount * sizeof(K));
- if (isLeaf()) {
- memcpy(newNode->getValueOffset(), static_cast<TID*>(valueOffset) + oldNodeCount, newNodeCount * sizeof(TID));
- //Clear old values
- memset(static_cast<TID*>(valueOffset) + oldNodeCount, 0, newNodeCount * sizeof(TID));
- } else {
- memcpy(newNode->getValueOffset(), static_cast<unsigned int*>(valueOffset) + oldNodeCount, newNodeCount * sizeof(unsigned int));
- //Clear old values
- memset(static_cast<unsigned int*>(valueOffset) + oldNodeCount, 0, newNodeCount * sizeof(unsigned int));
- }
- //Clear the old key data
- memset(keyMiddle, 0, newNodeCount * sizeof(K));
- return newNode;
- }
-
- /**
- * Removes a key, value pair specified by the Key key
- */
- void remove(K key) {
- K* to = binaryLookup(keyOffset, keyOffset + data->entryCount - 1, key);
- //TODO - compare
- if (*to != key) {
- cout << "Could not remove key " << key << " cause there is none" << endl;
- return;
- }
- //Delete the value
- if (isLeaf()) {
- TID* to = findTidValue(key);
- TID* from = to + 1;
- unsigned int moveAmount = ((static_cast<TID*>(valueOffset) + data->entryCount) - (to + 1)) * sizeof(TID);
- //Move the memory and overwrite the old value
- memmove(to, from, moveAmount);
- } else {
- unsigned int* to = findPageIdValuePtr(key);
- unsigned int* from = to + 1;
- unsigned int moveAmount = ((static_cast<unsigned int*>(valueOffset) + data->entryCount) - (to + 1)) * sizeof(unsigned int);
- //Move the memory and overwrite the old value
- memmove(to, from, moveAmount);
- }
- removeKey(key);
- --data->entryCount;
- dirty = true;
- }
- /**
- * Inserts a given key, value pair into the node and ensures the order within the node
- */
- void insert(K key, void* val) {
- //Get the offset of the next smaller key in this node
- unsigned int offset = insertionOffset(key);
- //Declare variables for insertionpoints
- K* insertKey = keyOffset + offset;
- cout << "Offset is: " << offset << endl;
- //Calculate how many bytes we have to move
- unsigned int moveAmount = (data->entryCount - offset) * sizeof(K);
- //Move the key by one slot
- K * from = insertKey;
- K * to = from + 1;
- memmove(to, from, moveAmount);
-
- if (isLeaf()) {
- //Calculate the position where we have to insert the TID
- TID * insertTID = reinterpret_cast<TID *>(valueOffset) + offset;
- //Calculate how many bytes we have to move
- moveAmount = (data->entryCount - offset) * sizeof(TID);
- TID * to = insertTID + 1;
- //Move the values by one slot
- memmove(to, insertTID, moveAmount);
- //Insert the value for the TID
- *insertTID = *static_cast<TID *>(val);
- } else {
- //Calculate the position where we have to insert the pageNo
- unsigned int * insertPageNo = reinterpret_cast<unsigned int *>(valueOffset) + offset;
- //Calculate how many bytes we have to move
- moveAmount = (data->entryCount - offset) * sizeof(unsigned int);
- unsigned int * to = insertPageNo + 1;
- //Move the values by one slot
- memmove(to, from, moveAmount);
- //Insert the value for the pageNo
- *insertPageNo = *static_cast<unsigned int*>(val);
- }
- *insertKey = key;
- ++data->entryCount;
- dirty = true;
- }
- /**
- * Prints the content of the node
- */
- string print() {
- ostringstream oss;
- oss << "node" << getBufferFrame().getPageNo() << "[shape=record, label=\"";
- oss << "<pageId> " << bufferFrame.getPageNo() << " | <isLeaf> " << printBool(isLeaf()) << " | ";
- for(unsigned int i = 1; i <= data->entryCount; i++) {
- oss << "<key" << i << "> " << *(keyOffset + (i-1)) << " | ";
- }
- for(unsigned int i = 1; i <= data->entryCount; i++) {
- oss << "<val" << i << "> ";
- if (isLeaf()) {
- TID* tid = (static_cast<TID *>(valueOffset) + (i-1));
- oss << tid->pageId << "/" << tid->slotId << " | ";
- } else {
- oss << "* | ";
- }
- }
-
- oss << "<next> *\"];";
- return oss.str();
- }
-
- /**
- * Retrieves the TID for the given key
- */
- TID* findTidValue(K key) {
- cout << "Looking for TID of key:" << key << endl;
- K* it = binaryLookup(keyOffset, keyOffset + data->entryCount - 1, key);
- //TODO - compare
- if (*it != key) {
- return NULL;
- } else {
- int pos = it - keyOffset;
- return static_cast<TID *>(valueOffset) + pos;
- }
- }
-
- /**
- * Retrieves the pageId for the given key
- */
- unsigned int findPageIdValue(K key) {
- cout << "Looking for pageId of key:" << key << endl;
- K* it = binaryLookup(keyOffset, keyOffset + data->entryCount - 1, key);
- //TODO - compare
- if (*it < key) {
- return data->rightMostEntry;
- }
- int pos = it - keyOffset;
- unsigned int pageId = *(static_cast<unsigned int *>(valueOffset) + pos);
- return pageId;
- }
-
- /**
- * Returns a pointer to the value of a given key
- */
- unsigned int* findPageIdValuePtr(K key) {
- cout << "Looking for pageId of key:" << key << endl;
- K* it = binaryLookup(keyOffset, keyOffset + data->entryCount - 1, key);
- //TODO - compare
- if (*it < key) {
- return &data->rightMostEntry;
- }
- int pos = it - keyOffset;
- unsigned int* pageId = static_cast<unsigned int *>(valueOffset) + pos;
- return pageId;
- }
- /**
- * Updates the pageId(value) for a given key and throws an exception if the node is a leaf
- */
- void updatePageIdForInsertKey(K key, unsigned int newVal) {
- if (isLeaf()) {
- throw runtime_error("Calling updatePageIdForInsertKey on a leaf");
- }
- cout << "Updating pageId for key:" << key << endl;
- K* it = binaryLookup(keyOffset, keyOffset + data->entryCount - 1, key);
- //TODO - compare
- if (*it < key) {
- data->rightMostEntry = newVal;
- } else {
- int pos = it - keyOffset;
- *(static_cast<unsigned int *>(valueOffset) + pos) = newVal;
- }
- }
- /**
- * Returns the maximum key of this node
- */
- K getMaxKey() {
- return *(keyOffset + data->entryCount - 1);
- }
-
- /**
- * Returns the minimum key of this node
- */
- K getMinKey() {
- return *keyOffset;
- }
- /**
- * Returns the bufferframe of this node
- */
- BufferFrame& getBufferFrame() {
- return bufferFrame;
- }
-
- /**
- * Sets the entry count for this node
- */
- void setEntryCount(unsigned int cnt) {
- data->entryCount = cnt;
- }
- /**
- * Sets the upper value of the node and throws an exception if the node is a leaf
- */
- void setUpper(unsigned int val) {
- if (!isLeaf()) {
- data->rightMostEntry = val;
- } else {
- throw runtime_error("Set upper is called on an inner node");
- }
- }
- /**
- * Returns the upper value of the node and throws an exception if the node is a leaf
- */
- unsigned int getUpper() {
- if (!isLeaf()) {
- return data->rightMostEntry;
- } else {
- throw runtime_error("Get upper is called on an inner node");
- }
- }
- };
- #endif