-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpage_cache.hpp
More file actions
180 lines (149 loc) · 5.95 KB
/
page_cache.hpp
File metadata and controls
180 lines (149 loc) · 5.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
#ifndef PAGE_CACHE_HPP
#define PAGE_CACHE_HPP
#include "dependencies/sqlite/sqlite3.h"
class Page : sqlite3_pcache_page {
public:
/**
* Construct a Page.
* @param pageSize Size in bytes of the page.
* @param extraSize Size in bytes of the buffer to store extra information.
*/
Page(int pageSize, int extraSize);
Page(const Page &) = delete;
Page &operator=(const Page &) = delete;
~Page();
private:
void *pBufInner_;
};
class PageCache {
public:
/**
* Construct a PageCache.
* @param pageSize Page size in bytes. Assumed to be a power of two.
* @param extraSize Extra space in bytes. Assumed to be less than 250.
*/
PageCache(int pageSize, int extraSize);
/**
* Destroy the PageCache.
*/
virtual ~PageCache() = default;
/**
* Set the maximum number of pages in the cache. Discard unpinned pages until
* either the number of pages in the cache is less than or equal to
* `maxNumPages` or all the pages in the cache are pinned. If there are still
* too many pages after discarding all unpinned pages, pages will continue to
* be discarded after being unpinned in the `unpinPage` function.
* @param maxNumPages Maximum number of pages in the cache.
*/
virtual void setMaxNumPages(int maxNumPages) = 0;
/**
* Get the number of pages in the cache, both pinned and unpinned.
* @return Number of pages in the cache.
*/
[[nodiscard]] virtual int getNumPages() const = 0;
/**
* Fetch and pin a page. If the page is already in the cache, return a
* pointer to the page. If the page is not already in the cache, use the
* `allocate` parameter to determine how to proceed. If `allocate` is false,
* return a null pointer. If `allocate` is true, examine the number of pages
* in the cache. If the number of pages in the cache is less than the maximum,
* allocate and return a pointer to a new page. If the number of pages in the
* cache is greater than or equal to the maximum, return a pointer to an
* existing unpinned page. If all pages are pinned, return a null pointer.
* @param pageId Page ID.
* @param allocate Allocate new page on miss.
* @param hit True if the request was a hit and false otherwise.
* @return Pointer to a page. May be null.
*/
virtual Page *fetchPage(unsigned pageId, bool allocate) = 0;
/**
* Unpin a page. The page is unpinned regardless of the number of prior
* fetches, meaning it can be safely discarded. If `discard` is true, discard
* the page. If `discard` is false, examine the number of pages in the cache.
* If the number of pages in the cache is greater than the maximum, discard
* the page.
* @param page Pointer to a page.
* @param discard Discard the page.
*/
virtual void unpinPage(Page *page, bool discard) = 0;
/**
* Change the page ID associated with a page. If a page with page ID
* `newPageId` is already in the cache, it is assumed that the page is
* unpinned, and the page is discarded.
* @param page Pointer to a page.
* @param newPageId New page ID.
*/
virtual void changePageId(Page *page, unsigned newPageId) = 0;
/**
* Discard all pages with page IDs greater than or equal to `pageIdLimit`. If
* any of these pages are pinned, then they are implicitly unpinned, meaning
* they can be safely discarded.
* @param pageIdLimit Page ID limit.
*/
virtual void discardPages(unsigned pageIdLimit) = 0;
/**
* Get the number of fetches since creation.
* @return Number of fetches since creation.
*/
[[nodiscard]] unsigned long long getNumFetches() const;
/**
* Get the number of hits since creation.
* @return Number of hits since creation.
*/
[[nodiscard]] unsigned long long getNumHits() const;
protected:
/** Maximum number of pages in the cache. */
int maxNumPages_;
/** Size in bytes of a page. */
int pageSize_;
/** Size in bytes of the buffer to store extra information. */
int extraSize_;
/** Number of fetches since creation. */
unsigned long long numFetches_;
/** Number of hits since creation. */
unsigned long long numHits_;
};
template <typename PageCacheImplementation>
struct PageCacheMethods : sqlite3_pcache_methods2 {
explicit PageCacheMethods() : sqlite3_pcache_methods2() {
xInit = [](void *) { return SQLITE_OK; };
xShutdown = nullptr;
xCreate = [](int pageSize, int extraSize, int) {
return (sqlite3_pcache *)new PageCacheImplementation(pageSize, extraSize);
};
xCachesize = [](sqlite3_pcache *pageCacheBase, int maxNumPages) {
auto pageCache = (PageCache *)pageCacheBase;
pageCache->setMaxNumPages(maxNumPages);
};
xPagecount = [](sqlite3_pcache *pageCacheBase) {
auto pageCache = (PageCache *)pageCacheBase;
return pageCache->getNumPages();
};
xFetch = [](sqlite3_pcache *pageCacheBase, unsigned pageId,
int createFlag) {
auto pageCache = (PageCache *)pageCacheBase;
return (sqlite3_pcache_page *)pageCache->fetchPage(pageId, createFlag);
};
xUnpin = [](sqlite3_pcache *pageCacheBase, sqlite3_pcache_page *pageBase,
int discard) {
auto pageCache = (PageCache *)pageCacheBase;
auto page = (Page *)pageBase;
pageCache->unpinPage(page, discard);
};
xRekey = [](sqlite3_pcache *pageCacheBase, sqlite3_pcache_page *pageBase,
unsigned, unsigned newPageId) {
auto pageCache = (PageCache *)pageCacheBase;
auto page = (Page *)pageBase;
pageCache->changePageId(page, newPageId);
};
xTruncate = [](sqlite3_pcache *pageCacheBase, unsigned pageIdLimit) {
auto pageCache = (PageCache *)pageCacheBase;
pageCache->discardPages(pageIdLimit);
};
xDestroy = [](sqlite3_pcache *pageCacheBase) {
auto pageCache = (PageCache *)pageCacheBase;
delete pageCache;
};
}
};
#endif