Untitled
unknown
plain_text
2 years ago
5.6 kB
13
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...