Building my own database in c++

Table of Contents

Implementing a database page

1// ================================
2// File: include/db/page.h
3// Fixed-size page abstraction (disk + memory unit)
4// ================================
5#pragma once
6
7#include <array>
8#include "types.h"
9
10namespace db
11{
12
13    constexpr size_t PAGE_SIZE = 4096;
14    constexpr PageId INVALID_PAGE_ID = -1;
15
16    class Page
17    {
18    public:
19        Page();
20
21        PageId getId() const;
22
23        void setPageId(PageId id);
24
25        // Raw byte access for serializers / B-Tree nodes
26        uint8_t *data();
27        const uint8_t *data() const;
28
29        template <typename T>
30        T read(size_t offset) const
31        {
32            if (offset + sizeof(T) > PAGE_SIZE)
33            {
34                throw std::out_of_range("Reading past the DB page");
35            }
36            T val;
37            std::memcpy(&val, buffer_.data() + offset, sizeof(T));
38            return val;
39        }
40
41        template <typename T>
42        void write(size_t offset, const T &value)
43        {
44            if (offset + sizeof(T) > PAGE_SIZE)
45            {
46                throw std::out_of_range("Reading past the DB page");
47            }
48            std::memcpy(buffer_.data() + offset, &value, sizeof(T));
49            mark_dirty();
50        }
51
52        bool is_dirty() const;
53
54        void mark_dirty();
55
56        void clear_dirty();
57
58        // Used to track how many processes are pinning this page, so we do not evict from page table
59        int pin_count() const;
60
61        void pin();
62
63        void unpin();
64
65        void reset();
66
67    private:
68        PageId page_id_;
69        std::array<uint8_t, PAGE_SIZE> buffer_; // uint8_t is exactly one byte, unsigned, preferred over unsigned char
70        bool is_dirty_;
71        int pin_count_;
72    };
73
74} // namespace db
1#include "page.h"
2#include "types.h"
3
4using namespace db;
5
6Page::Page() : page_id_(INVALID_PAGE_ID), is_dirty_(false), pin_count_(0) {}
7
8PageId Page::getId() const
9{
10    return page_id_;
11}
12
13void Page::setPageId(PageId id)
14{
15    page_id_ = id;
16}
17
18uint8_t *Page::data()
19{
20    return buffer_.data();
21}
22
23const uint8_t *Page::data() const
24{
25    return buffer_.data();
26}
27
28bool Page::is_dirty() const
29{
30    return is_dirty_;
31}
32
33void Page::mark_dirty()
34{
35    is_dirty_ = true;
36}
37
38void Page::clear_dirty()
39{
40    is_dirty_ = false;
41}
42
43int Page::pin_count() const
44{
45    return pin_count_;
46}
47
48void Page::pin()
49{
50    pin_count_++;
51}
52
53void Page::unpin()
54{
55    if (pin_count_ > 0)
56        pin_count_--;
57}
58
59void Page::reset()
60{
61    page_id_ = -1; // reset to INVALID PAGE_ID
62    std::memset(buffer_.data(), 0, PAGE_SIZE);
63    is_dirty_ = false;
64    pin_count_ = 0;
65}