Untitled
unknown
plain_text
a year ago
5.6 kB
3
Indexable
#include "fixed.h" #include <cassert> #include <cmath> #include <cstdint> #include <cstring> #include <vector> #include "marshal.h" #include "page.h" #include "row.h" #include "table.h" namespace shdb { class FlexiblePage : public IPage { public: FlexiblePage(std::shared_ptr<Frame> frame, std::shared_ptr<Marshal> marshal) : frame(std::move(frame)), marshal(std::move(marshal)) { header.free_start = 0; header.free_end = page_size - 1; header.free_space = header.free_end - header.free_start; } RowIndex getRowCount() override { return header.free_space / sizeof(Node); } // free_space - > Node|Node|Node Row getRow(RowIndex index) override { uint8_t* cur_node_add = getCurNodeAddress(index); // current size is size of node * cur index Node node; mempcpy(&node, cur_node_add, sizeof(Node)); uint8_t* row_start = frame->getData() + node.offset; return marshal->deserializeRow(row_start); } void deleteRow(RowIndex index) override { uint8_t* cur_node_add = getCurNodeAddress(index); Node del_node; mempcpy(&del_node, cur_node_add, sizeof(Node)); RowIndex node_index = index; RowIndex nodes_counter = getRowCount(); std::vector<Node> nodes; for (RowIndex i = index; i < nodes_counter; ++i) { moveToFirstNodeAndFillDataForMovingRows(i, i + 1, nodes, del_node.length); // + offset for all rows } //after move to start need to decline node from header.start_free header.free_start -= sizeof(Node); header.free_end += del_node.length; header.free_space = header.free_start - header.free_end; //need to move all rows to the end and change their offsets uint8_t* row_del_start = frame->getData() + del_node.offset; uint8_t* another_row_start = nullptr; for (const Node& node : nodes) { another_row_start = frame->getData() + node.offset; if (node.length == del_node.length) { mempcpy(row_del_start, another_row_start, del_node.length); } else if (node.length > del_node.length) { uint8_t* first_part = another_row_start + node.length - del_node.length; // copy part of del_node mempcpy(row_del_start, first_part, del_node.length); uint8_t* second_part = another_row_start + del_node.length; // copy the tail of another row mempcpy(second_part, another_row_start, node.length - del_node.length); } else { uint8_t* first_part = row_del_start + del_node.length - node.length; //copy to the end mempcpy(first_part, another_row_start, node.length); } row_del_start = another_row_start; } // uint8_t* row_start = frame->getData() + node.offset; // uint8_t* end_row = frame->getData() + node.offset + node.length; } std::pair<bool, RowIndex> insertRow(const Row & row) override { size_t needed_space = marshal->getRowSpace(row); if (header.free_space < needed_space + sizeof(Node)) { return {false, 0}; } // we can insert only if it Node node; node.offset = header.free_end - needed_space; node.length = needed_space; uint8_t* place_for_insert = frame->getData() + node.offset; uint8_t* place_for_add_node = frame->getData() + header.free_start; marshal->serializeRow(place_for_insert, row); mempcpy(place_for_add_node, &node, sizeof(Node)); header.free_end -= needed_space; header.free_start += sizeof(Node); header.free_space = header.free_end - header.free_start; std::cerr << header.free_start / sizeof(Node) << std::endl; return {true, header.free_start / sizeof(Node)}; } private: struct Header { uint16_t free_start; // offset to start free space uint16_t free_end; // offset to end free space uint16_t free_space; // free place }; struct Node { uint16_t offset; // offset for finding row uint16_t length; // length of row }; uint8_t* getCurNodeAddress(RowIndex index) { return frame->getData() + index * sizeof(Node); // current size is size of node * cur index } void moveToFirstNodeAndFillDataForMovingRows(int ind1, int ind2, std::vector<Node>& nodes, uint16_t offset_change) { uint8_t* first_node_ptr = getCurNodeAddress(ind1); uint8_t* second_node_ptr = getCurNodeAddress(ind2); Node second_node; mempcpy(&second_node, second_node_ptr, sizeof(Node)); nodes.emplace_back(second_node); second_node.offset += offset_change; mempcpy(first_node_ptr, &second_node, sizeof(Node)); } Header header; std::shared_ptr<Frame> frame; std::shared_ptr<Marshal> marshal; size_t row_counter = 0; }; class FlexiblePageProvider : public IPageProvider { public: explicit FlexiblePageProvider(std::shared_ptr<Marshal> marshal) : marshal(marshal) { } std::shared_ptr<IPage> getPage(std::shared_ptr<Frame> frame) override { return std::make_shared<FlexiblePage>(std::move(frame), marshal); } std::shared_ptr<Marshal> marshal; }; std::shared_ptr<IPageProvider> createFlexiblePageProvider(std::shared_ptr<Schema> schema) { auto marshal = std::make_shared<Marshal>(std::move(schema)); return std::make_shared<FlexiblePageProvider>(std::move(marshal)); } }
Editor is loading...