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}