Untitled

mail@pastecode.io avatar
unknown
plain_text
7 months ago
5.6 kB
1
Indexable
Never
#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));
}

}