Dynalib Utils
DynaCacheImpl.h
Go to the documentation of this file.
1 //
2 // Created by Ken Kopelson on 6/03/18.
3 //
4 
5 #ifndef DYNACACHEIMPL_H
6 #define DYNACACHEIMPL_H
7 
8 #include "DynaCache.h"
9 #include "ICachePage.h"
10 #include "ICacheFile.h"
11 
12 #define MAKE_CACHETYPE_INSTANCE(C, T) \
13  template class DynaCache<C>; \
14  typedef DynaCache<C> T##Cache
15 
16 template<class T>
18  _pageList = new DynaLinkedList<T>();
19  _pageList->setOwnsMembers(true);
20  _pageMap = new DynaHashMap<Index, LinkedEntry<T>>();
21  _pageMap->setOwnsMembers(false); // Map holds references only
22 }
23 
24 template<class T>
26  // TODO: trying flush here instead of "clear"
27  // clear();
28  flush();
29  delete _pageMap;
30  _pageMap = nullptr;
31  delete _pageList;
32  _pageList = nullptr;
33  delete _listener;
34  _listener = nullptr;
35 }
36 
37 template<class T>
39  _autoTouch = other._autoTouch;
40  _maxPages = other._maxPages;
41  _pageList = other._pageList->copy();
42  _pageMap = other._pageMap->copy();
43  _listener = other._listener;
44 }
45 
46 template<class T>
48  return new DynaCache<T>(*this);
49 }
50 
51 template<class T>
52 void DynaCache<T>::setAutoTouch(bool autoTouch) {
53  _autoTouch = autoTouch;
54 }
55 
56 template<class T>
58  return _autoTouch;
59 }
60 
61 template<class T>
63  _pageFlushes = 0L;
64  _pageReplacements = 0L;
65  _pageAccesses = 0L;
66 }
67 
68 template<class T>
70  flush();
71  _pageMap->clear();
72  _pageList->clear();
73 }
74 
75 template<class T>
77  return _pageList == nullptr || _pageList->size() == 0;
78 }
79 
80 template<class T>
82  return _pageList != nullptr && _pageList->size() >= _maxPages;
83 }
84 
85 template<class T>
87  if (_pageList != nullptr) {
88  for (T* page : *_pageList) {
89  if (page->isDirty())
90  return true;
91  }
92  }
93  return false;
94 }
95 
96 template<class T>
98  int count = 0;
99  if (_pageList != nullptr) {
100  for (T* page : *_pageList) {
101  if (page->isDirty())
102  ++count;
103  }
104  }
105  return count;
106 }
107 
108 template<class T>
110  return _maxPages;
111 }
112 
113 template<class T>
115  return _pageList->size();
116 }
117 
118 template<class T>
120  return _pageList;
121 }
122 
123 template<class T>
124 void DynaCache<T>::setMaxPages(int maxPages) {
125  if (maxPages < _maxPages) {
126  for (int i = maxPages; i < _maxPages; ++i)
127  removeLastPage();
128  }
129  _maxPages = maxPages;
130 }
131 
132 template<class T>
134  _listener = listener;
135 }
136 
137 template<class T>
139  if (_pageList != nullptr && !_pageList->isEmpty()) {
140  for (T* page : *_pageList) {
141  flushPage(page);
142  }
143  }
144 }
145 
146 template<class T>
147 void DynaCache<T>::flushPage(T* page) {
148  if (_listener != nullptr)
149  _listener->onFlush((ICachePage<T>*)page);
150 }
151 
152 template<class T>
154  if (_pageList != nullptr) {
155  _pageList->moveToFirst(entry);
156  ++_pageAccesses;
157  }
158 }
159 
160 template<class T>
162  try {
163  return new T();
164  }
165  catch (Exception& e) {
166  }
167  return nullptr;
168 }
169 
170 template<class T>
172  auto* entry = _pageList->pushEntry(page);
173  ++_pageAccesses;
174  _pageMap->put(page->getKeyValue(), entry);
175  if (_listener != nullptr)
176  _listener->onAddNew((ICachePage<T>*)page);
177  return entry;
178 }
179 
180 template<class T>
182  T* page = entry->getObject();
183  flushPage(page);
184  return page;
185 }
186 
187 template<class T>
189  auto* entry = _pageList->getLast();
190  if (entry != nullptr) {
191  T* page = getPageForRemoval(entry);
192  _pageMap->remove(page->getKeyValue()); // Use 'remove' because the map doesn't own the entry
193  page->clear();
194  page->setKeyValue(keyValue);
195  _pageMap->put(keyValue, entry);
199  touchEntry(entry);
200  ++_pageReplacements;
201  }
202  return entry;
203 }
204 
205 template<class T>
207  auto* entry = _pageList->getLast();
208  if (entry != nullptr) {
209  T* page = getPageForRemoval(entry);
210  _pageMap->remove(page->getKeyValue());
211  entry->setObject(newPage);
212  _pageMap->put(newPage->getKeyValue(), entry);
213  if (_pageList->isOwnsMembers()) {
214  delete page; // The old page is no longer needed and must be deleted
215  }
216  touchEntry(entry);
217  ++_pageReplacements;
218  }
219  return entry;
220 }
221 
222 template<class T>
224  auto* entry = findPageEntry(keyValue);
225  if (entry != nullptr) {
226  T* page = getPageForRemoval(entry);
227  _pageMap->remove(page->getKeyValue());
228  _pageList->deleteEntry(entry);
229  }
230 }
231 
232 template<class T>
234  auto* entry = _pageList->getLast();
235  if (entry != nullptr) {
236  T* page = getPageForRemoval(entry);
237  _pageMap->remove(page->getKeyValue());
238  _pageList->deleteEntry(entry); // Will delete the page since the list owns it
239  }
240 }
241 
242 template<class T>
243 void DynaCache<T>::purgePages(double removePercent) {
244  int pagesToRemove = (int)(((double)_pageList->count()) * removePercent);
245  for (int i = 0; i < pagesToRemove; ++i) {
246  removeLastPage();
247  }
248 }
249 
250 
251 template<class T>
253  auto* entry = _pageMap->get(keyValue);
254  return entry;
255 }
256 
257 template<class T>
259  auto* entry = findPageEntry(keyValue);
260  if (entry != nullptr && _autoTouch)
261  touchEntry(entry);
262  return entry;
263 }
264 
265 template<class T>
267  auto* entry = findPageEntry(keyValue);
268  if (entry == nullptr) {
269  if (_pageList->size() >= _maxPages)
270  entry = useLastPage(keyValue);
271  if (entry == nullptr) {
272  T* page = getNewPage();
273  page->setKeyValue(keyValue);
274  entry = addNewPage(page);
275  }
276  }
277  else
278  touchEntry(entry);
279  return entry;
280 }
281 
282 template<class T>
284  auto* entry = findPageEntry(page->getKeyValue());
285  if (entry == nullptr) {
286  if (_pageList->size() >= _maxPages)
287  entry = useLastPage(page);
288  if (entry == nullptr)
289  entry = addNewPage(page);
290  }
291  else
292  touchEntry(entry);
293  return entry;
294 }
295 
296 template<class T>
298  auto* entry = findPageEntry(keyValue);
299  return entry != nullptr ? entry->getObject() : nullptr;
300 }
301 
302 template<class T>
304  auto* entry = getPageEntry(keyValue);
305  return entry != nullptr ? entry->getObject() : nullptr;
306 }
307 
308 template<class T>
310  auto* entry = putPageEntry(keyValue);
311  return entry != nullptr ? entry->getObject() : nullptr;
312 }
313 
314 template<class T>
316  auto* entry = putPageEntry(page);
317  return entry != nullptr ? entry->getObject() : nullptr;
318 }
319 
320 template<class T>
322  try {
323  cout << "\n---------------------- Cache Status -------------------------" << endl;
324  if (name != "") {
325  cout << "File Name : " << name << endl;
326  }
327  cout << "Configured Max. Pages : " << getMaxPages() << endl;
328  cout << "Total Pages Loaded : " << _pageList->size() << endl;
329  cout << "Total Dirty Pages : " << getDirtyPageCount() << endl;
330  cout << "\n----------------------- Statistics --------------------------" << endl;
331  cout << "Page Flushes : " << _pageFlushes << endl;
332  cout << "Page Accesses : " << _pageAccesses << endl;
333  cout << "Page Replacements : " << _pageReplacements << endl;
334  cout << endl;
335  }
336  catch (Exception& e) {
337  }
338 }
339 
340 #endif
T * getObject() const
Definition: DynaLinkedListImpl.h:58
void resetStats()
Definition: DynaCacheImpl.h:62
virtual void flushPage(T *page)
Definition: DynaCacheImpl.h:147
virtual T * getPageForRemoval(LinkedEntry< T > *entry)
Definition: DynaCacheImpl.h:181
void setOwnsMembers(bool ownsMembers)
Definition: DynaLinkedListImpl.h:149
Definition: IDynaCacheListener.h:11
bool isEmpty()
Definition: DynaCacheImpl.h:76
void touchEntry(LinkedEntry< T > *entry)
Definition: DynaCacheImpl.h:153
DynaLinkedList< T > * getPageList()
Definition: DynaCacheImpl.h:119
bool isFull()
Definition: DynaCacheImpl.h:81
Definition: DynaLinkedList.h:32
T * putPage(Index keyValue)
Definition: DynaCacheImpl.h:309
Definition: DynaCache.h:16
void setAutoTouch(bool autoTouch)
Definition: DynaCacheImpl.h:52
virtual void setListener(IDynaCacheListener< T > *listener)
Definition: DynaCacheImpl.h:133
virtual ~DynaCache()
Definition: DynaCacheImpl.h:25
Definition: String.h:60
LinkedEntry< T > * useLastPage(Index keyValue)
Definition: DynaCacheImpl.h:188
int getPageCount()
Definition: DynaCacheImpl.h:114
Definition: DynaHashMap.h:73
Definition: ICachePage.h:18
DynaLinkedList< T > * _pageList
Definition: DynaCache.h:20
LinkedEntry< T > * findPageEntry(Index keyValue)
Definition: DynaCacheImpl.h:252
DynaCache()
Definition: DynaCacheImpl.h:17
std::ostream & cout()
T * findPage(Index keyValue)
Definition: DynaCacheImpl.h:297
Definition: IntWrapper.h:13
Definition: DynaLinkedList.h:28
DynaCache< T > * copy() override
Definition: DynaCacheImpl.h:47
int getDirtyPageCount()
Definition: DynaCacheImpl.h:97
T * getPage(Index keyValue)
Definition: DynaCacheImpl.h:303
void removeLastPage()
Definition: DynaCacheImpl.h:233
DynaHashMap< Index, LinkedEntry< T > > * _pageMap
Definition: DynaCache.h:21
void removePage(Index keyValue)
Definition: DynaCacheImpl.h:223
void clear()
Definition: DynaCacheImpl.h:69
int _maxPages
Definition: DynaCache.h:19
bool isAutoTouch()
Definition: DynaCacheImpl.h:57
LinkedEntry< T > * addNewPage(T *page)
Definition: DynaCacheImpl.h:171
bool isDirty()
Definition: DynaCacheImpl.h:86
Definition: Exception.h:13
T * getNewPage()
Definition: DynaCacheImpl.h:161
void printStatReport(String &name)
Definition: DynaCacheImpl.h:321
LinkedEntry< T > * putPageEntry(Index keyValue)
Definition: DynaCacheImpl.h:266
void setMaxPages(int maxPages)
Definition: DynaCacheImpl.h:124
void setOwnsMembers(bool ownsMembers)
Definition: DynaHashMap.h:121
IDynaCacheListener< T > * _listener
Definition: DynaCache.h:22
int getMaxPages()
Definition: DynaCacheImpl.h:109
LinkedEntry< T > * getPageEntry(Index keyValue)
Definition: DynaCacheImpl.h:258
virtual void purgePages(double removePercent=0.80)
Definition: DynaCacheImpl.h:243
void flush()
Definition: DynaCacheImpl.h:138