Zero  0.1.0
page_evictioner_other.hpp
Go to the documentation of this file.
1 #ifndef __ZERO_PAGE_EVICTIONER_OTHER_HPP
2 #define __ZERO_PAGE_EVICTIONER_OTHER_HPP
3 
4 #include "page_evictioner.hpp"
5 #include "buffer_pool.hpp"
6 #include "multi_clock.hpp"
7 #include "hashtable_deque.hpp"
8 #include <mutex>
9 #include <cmath>
10 
11 namespace zero::buffer_pool {
12 
23  template<bool on_page_unfix/* = false*/>
25  public:
33  PageEvictionerCAR(const BufferPool* bufferPool) :
34  PageEvictioner(bufferPool),
35  _clocks(bufferPool->getBlockCount()),
36  _b1(bufferPool->getBlockCount() - 1),
37  _b2(bufferPool->getBlockCount() - 1),
38  _p(0),
39  _c(bufferPool->getBlockCount() - 1),
40  _handMovement(0) {};
41 
45  ~PageEvictionerCAR() final {};
46 
57  bf_idx pickVictim() noexcept final {
58  bool evictedPage = false;
59  bf_idx blockedT1 = 0;
60  bf_idx blockedT2 = 0;
61 
62  while (!evictedPage) {
63  if (should_exit()) {
64  return 0;
65  } // the buffer index 0 has the semantics of null
66 
67  if (_handMovement >= _c) {
68  smlevel_0::bf->getPageCleaner()->wakeup(false);
69  DBG3(<< "Run Page_Cleaner ...");
70  _handMovement = 0;
71  }
72  uint32_t iterations = (blockedT1 + blockedT2) / _c;
73  if ((blockedT1 + blockedT2) % _c == 0 && (blockedT1 + blockedT2) > 0) {
74  DBG1(<< "Iterated " << iterations << "-times in CAR's pick_victim().");
75  }
76  w_assert1(iterations < 3);
77  DBG3(<< "p = " << _p);
78  std::lock_guard<std::mutex> guard(_latch);
79  if ((_clocks.sizeOf<T_1>() >= std::max<uint32_t>(uint32_t(1), _p) || blockedT2 >= _clocks.sizeOf<T_2>())
80  && blockedT1 < _clocks.sizeOf<T_1>()) {
81  bool t1Head;
82  _clocks.getHead<T_1>(t1Head);
83  bf_idx t1HeadIndex;
84  _clocks.getHeadIndex<T_1>(t1HeadIndex);
85  w_assert1(t1HeadIndex != 0);
86 
87  if (!t1Head) {
88  evictedPage = evictOne(t1HeadIndex);
89  PageID evictedPID = smlevel_0::bf->getControlBlock(t1HeadIndex)._pid;
90 
91  if (evictedPage) {
92  _clocks.removeHead<T_1>(t1HeadIndex);
93  _b1.pushToBack(evictedPID);
94  DBG5(<< "Removed from T_1: " << t1HeadIndex << "; New size: " << _clocks.sizeOf<T_1>() << "; Free frames: " << smlevel_0::bf->getFreeList()->getCount());
95  return t1HeadIndex;
96  } else {
97  _clocks.moveHead<T_1>();
98  blockedT1++;
99  _handMovement++;
100  continue;
101  }
102  } else {
103  _clocks.setHead<T_1>(false);
104 
105  _clocks.switchHeadToTail<T_1, T_2>(t1HeadIndex);
106  DBG5(<< "Removed from T_1: " << t1HeadIndex << "; New size: " << _clocks.sizeOf<T_1>() << "; Free frames: " << smlevel_0::bf->getFreeList()->getCount());
107  DBG5(<< "Added to T_2: " << t1HeadIndex << "; New size: " << _clocks.sizeOf<T_2>() << "; Free frames: " << smlevel_0::bf->getFreeList()->getCount());
108  continue;
109  }
110  } else if (blockedT2 < _clocks.sizeOf<T_2>()) {
111  bool t2Head;
112  _clocks.getHead<T_2>(t2Head);
113  bf_idx t2HeadIndex;
114  _clocks.getHeadIndex<T_2>(t2HeadIndex);
115  w_assert1(t2HeadIndex != 0);
116 
117  if (!t2Head) {
118  evictedPage = evictOne(t2HeadIndex);
119  PageID evictedPID = smlevel_0::bf->getControlBlock(t2HeadIndex)._pid;
120 
121  if (evictedPage) {
122  _clocks.removeHead<T_2>(t2HeadIndex);
123  _b2.pushToBack(evictedPID);
124  DBG5(<< "Removed from T_2: " << t2HeadIndex << "; New size: " << _clocks.sizeOf<T_2>() << "; Free frames: " << smlevel_0::bf->getFreeList()->getCount());
125 
126  return t2HeadIndex;
127  } else {
128  _clocks.moveHead<T_2>();
129  blockedT2++;
130  _handMovement++;
131  continue;
132  }
133  } else {
134  _clocks.setHead<T_2>(false);
135 
136  _clocks.moveHead<T_2>();
137  _handMovement++;
138  continue;
139  }
140  } else {
141  return 0;
142  }
143  }
144  return 0; // Suppress compiler warning about missing return statement!
145  };
146 
154  void updateOnPageHit(bf_idx idx) noexcept final {
155  if constexpr (!on_page_unfix) {
156  _clocks.set(idx, true);
157  }
158  };
159 
167  void updateOnPageUnfix(bf_idx idx) noexcept final {
168  if constexpr (on_page_unfix) {
169  _clocks.set(idx, true);
170  }
171  };
172 
183  void updateOnPageMiss(bf_idx idx, PageID pid) noexcept final {
184  std::lock_guard<std::mutex> guard(_latch);
185  if (!_b1.contains(pid) && !_b2.contains(pid)) {
186  if (_clocks.sizeOf<T_1>() + _b1.length() >= _c) {
187  _b1.popFromFront();
188  } else if (_clocks.sizeOf<T_1>() + _clocks.sizeOf<T_2>() + _b1.length() + _b2.length() >= 2 * (_c)) {
189  _b2.popFromFront();
190  }
191  _clocks.addTail<T_1>(idx);
192  DBG5(<< "Added to T_1: " << idx << "; New size: " << _clocks.sizeOf<T_1>() << "; Free frames: " << smlevel_0::bf->getFreeList()->getCount());
193  _clocks.set(idx, false);
194  } else if (_b1.contains(pid)) {
195  _p = std::min(_p + std::max<uint32_t>(uint32_t(1), (_b2.length() / _b1.length())), _c);
196  _b1.remove(pid);
197  _clocks.addTail<T_2>(idx);
198  DBG5(<< "Added to T_2: " << idx << "; New size: " << _clocks.sizeOf<T_2>() << "; Free frames: " << smlevel_0::bf->getFreeList()->getCount());
199  _clocks.set(idx, false);
200  } else {
201  _p = std::max<int32_t>(int32_t(_p) - std::max<int32_t>(1, (_b1.length() / _b2.length())), 0);
202  _b2.remove(pid);
203  _clocks.addTail<T_2>(idx);
204  DBG5(<< "Added to T_2: " << idx << "; New size: " << _clocks.sizeOf<T_2>() << "; Free frames: " << smlevel_0::bf->getFreeList()->getCount());
205  _clocks.set(idx, false);
206  }
208  && _clocks.sizeOf<T_1>() + _clocks.sizeOf<T_2>() <= _c);
209  w_assert1(0 <= _clocks.sizeOf<T_1>() + _b1.length() && _clocks.sizeOf<T_1>() + _b1.length() <= _c);
210  w_assert1(0 <= _clocks.sizeOf<T_2>() + _b2.length() && _clocks.sizeOf<T_2>() + _b2.length() <= 2 * (_c));
212  && _clocks.sizeOf<T_1>() + _clocks.sizeOf<T_2>() + _b1.length() + _b2.length() <= 2 * (_c));
213  };
214 
223  void updateOnPageFixed(bf_idx idx) noexcept final {};
224 
232  void updateOnPageDirty(bf_idx idx) noexcept final {};
233 
241  void updateOnPageBlocked(bf_idx idx) noexcept final {};
242 
252  void updateOnPageSwizzled(bf_idx idx) noexcept final {};
253 
261  void updateOnPageExplicitlyUnbuffered(bf_idx idx) noexcept final {
262  try {
263  _clocks.remove(idx);
265  };
266 
275  void updateOnPointerSwizzling(bf_idx idx) noexcept final {};
276 
288  virtual void releaseInternalLatches() noexcept final {
289  _latch.unlock();
290  };
291 
292  protected:
304 
311 
318 
323  u_int32_t _p;
324 
329  u_int32_t _c;
330 
337 
347  std::mutex _latch;
348 
354  enum clock_index {
355  T_1 = 0,
356  T_2 = 1
357  };
358  };
359 } // zero::buffer_pool
360 #endif // __ZERO_PAGE_EVICTIONER_OTHER_HPP
clock_index
Clock names.
Definition: page_evictioner_other.hpp:354
PageEvictionerCAR(const BufferPool *bufferPool)
Constructor for a CAR page evictioner.
Definition: page_evictioner_other.hpp:33
void moveHead()
Move the clock hand forward.
Definition: multi_clock.hpp:156
#define w_assert1(x)
Level 1 should not add significant extra time.
Definition: w_base.h:198
hashtable_deque::HashtableDeque< PageID, 1|0x80000000 > _b1
LRU-list .
Definition: page_evictioner_other.hpp:310
Definition: buffer_pool.hpp:34
hashtable_deque::HashtableDeque< PageID, 1|0x80000000 > _b2
LRU-list .
Definition: page_evictioner_other.hpp:317
#define DBG3(a)
Definition: w_debug.h:253
void updateOnPageExplicitlyUnbuffered(bf_idx idx) noexcept final
Updates the eviction statistics on explicit eviction.
Definition: page_evictioner_other.hpp:261
~PageEvictionerCAR() final
Destructor for a CAR page evictioner.
Definition: page_evictioner_other.hpp:45
void updateOnPageUnfix(bf_idx idx) noexcept final
Updates the eviction statistics on page unfix.
Definition: page_evictioner_other.hpp:167
void updateOnPointerSwizzling(bf_idx idx) noexcept final
Updates the eviction statistics of pages when its pointer got swizzled in its parent page...
Definition: page_evictioner_other.hpp:275
void updateOnPageMiss(bf_idx idx, PageID pid) noexcept final
Updates the eviction statistics on page miss.
Definition: page_evictioner_other.hpp:183
uint32_t bf_idx
Definition: basics.h:56
bool evictOne(bf_idx &victim)
Evicts a page from the buffer pool.
Definition: page_evictioner.cpp:24
Page evictioner for the buffer pool.
Definition: page_evictioner.hpp:24
u_int32_t _p
Parameter .
Definition: page_evictioner_other.hpp:323
multi_clock::MultiHandedClock< bf_idx, bool, 2, 0 > _clocks
Clocks and .
Definition: page_evictioner_other.hpp:303
bool contains(const key_type &k) const noexcept
Entry with given key contained.
Definition: hashtable_deque.hpp:69
virtual void releaseInternalLatches() noexcept final
Releases the internal latches of this page evictioner.
Definition: page_evictioner_other.hpp:288
std::mutex _latch
Latch of _clocks, _b1 and _b2.
Definition: page_evictioner_other.hpp:347
void remove(const key_type &index)
Remove the specified entry from any clock.
Definition: multi_clock.hpp:437
uint32_t PageID
Definition: basics.h:45
void switchHeadToTail(key_type &movedIndex)
Moves an entry from the head of one clock to the tail of another one.
Definition: multi_clock.hpp:484
void popFromFront()
Removes the next key from this deque.
Definition: hashtable_deque.hpp:143
#define DBG1(a)
Definition: w_debug.h:251
void updateOnPageFixed(bf_idx idx) noexcept final
Updates the eviction statistics of used pages during eviction.
Definition: page_evictioner_other.hpp:223
void getHeadIndex(key_type &headIndex) const
Get the index of the entry where the clock hand of the specified clock points to. ...
Definition: multi_clock.hpp:133
uint64_t length() const noexcept
Number of entries in this deque.
Definition: hashtable_deque.hpp:805
Definition: page_evictioner_other.hpp:355
void getHead(value_type &head) const
Get the value of the entry where the clock hand of the specified clock points to. ...
Definition: multi_clock.hpp:91
Definition: page_evictioner_other.hpp:356
bf_idx pickVictim() noexcept final
Selects a page to be evicted from the buffer pool.
Definition: page_evictioner_other.hpp:57
void remove(const key_type &k)
Removes a specific key from this deque.
Definition: hashtable_deque.hpp:343
void updateOnPageSwizzled(bf_idx idx) noexcept final
Updates the eviction statistics of pages containing swizzled pointers during eviction.
Definition: page_evictioner_other.hpp:252
A buffer manager that exploits the tree structure of indexes.
Definition: buffer_pool.hpp:40
void updateOnPageHit(bf_idx idx) noexcept final
Updates the eviction statistics on page hit.
Definition: page_evictioner_other.hpp:154
void updateOnPageBlocked(bf_idx idx) noexcept final
Updates the eviction statistics of pages that cannot be evicted at all.
Definition: page_evictioner_other.hpp:241
void updateOnPageDirty(bf_idx idx) noexcept final
Updates the eviction statistics of dirty pages during eviction.
Definition: page_evictioner_other.hpp:232
void addTail(const key_type &index)
Make the specified index the__ZERO_MULTICLOCK_HPP tail of the specified clock.
Definition: multi_clock.hpp:182
Page Eviction Algorithm CAR.
Definition: page_evictioner_other.hpp:24
void pushToBack(const key_type &k)
Add the key to the back of this deque.
Definition: hashtable_deque.hpp:80
void set(const key_type &index, const value_type &newValue) noexcept
Sets the value that corresponds to the specified index.
Definition: multi_clock.hpp:580
void setHead(const value_type newValue)
Set the value of the entry where the clock hand of the specified clock points to. ...
Definition: multi_clock.hpp:113
const T min(const T x, const T y)
Definition: w_minmax.h:52
#define DBG5(a)
Definition: w_debug.h:254
key_type sizeOf() const noexcept
Returns the number of entries in the specified clock.
Definition: multi_clock.hpp:503
A generic RAII guard class.
Definition: guard.h:94
Exception thrown when a key is not already contained in a MultiHandedClock.
Definition: multi_clock_exceptions.hpp:246
void removeHead(key_type &removedIndex)
Remove the head entry from the specified clock.
Definition: multi_clock.hpp:412
bf_idx _handMovement
Clock hand movements in current circulation.
Definition: page_evictioner_other.hpp:336
u_int32_t _c
Parameter .
Definition: page_evictioner_other.hpp:329
bool should_exit() const
Definition: worker_thread.h:63