Darwin  1.10(beta)
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
drwnPersistentStorageBuffer.h
1 /*****************************************************************************
2 ** DARWIN: A FRAMEWORK FOR MACHINE LEARNING RESEARCH AND DEVELOPMENT
3 ** Distributed under the terms of the BSD license (see the LICENSE file)
4 ** Copyright (c) 2007-2015, Stephen Gould
5 ** All rights reserved.
6 **
7 ******************************************************************************
8 ** FILENAME: drwnPersistentStorageBuffer.h
9 ** AUTHOR(S): Stephen Gould <stephen.gould@anu.edu.au>
10 **
11 *****************************************************************************/
12 
13 #pragma once
14 
15 #include <cstdlib>
16 #include <cassert>
17 #include <map>
18 #include <list>
19 #include <string>
20 
21 #include "drwnBase.h"
22 #include "drwnPersistentStorage.h"
23 
24 using namespace std;
25 
26 // drwnPersistentStorageBuffer -----------------------------------------------
37 
38 template <class T>
40  public:
41  static size_t MAX_MEMORY;
42  static size_t MAX_RECORDS;
43 
44  protected:
46  public:
47  string key;
49  bool dirty;
50 
51  public:
52  inline _drwnRecordEntry() : dirty(false) { /* do nothing */ }
53  inline _drwnRecordEntry(const string& k, drwnSmartPointer<T>& r) :
54  key(k), record(r), dirty(false) { /* do nothing */ }
55  inline ~_drwnRecordEntry() { /* do nothing */ }
56  };
57 
58  typedef list<_drwnRecordEntry> _drwnRecordList;
59  typedef map<string, typename _drwnRecordList::iterator> _drwnRecordRef;
60 
62  _drwnRecordRef _recref;
63  _drwnRecordList _records;
64  size_t _memoryUsed;
65 
66  public:
67  drwnPersistentStorageBuffer(const char *fileStem, bool bCompressed = false);
69 
71  size_t size() const { return _records.size(); }
73  size_t memory() const { return _memoryUsed; }
75  const drwnPersistentStorage& storage() const { return _storage; }
76 
78  drwnSmartPointer<T> read(const string& key);
79 
82  void write(const string& key, drwnSmartPointer<T>& p);
83 
85  void erase(const string& key);
86 
88  void flush();
89 
90 protected:
93  void enforceLimits();
94 };
95 
96 // drwnPersistentStorageBuffer Implementation --------------------------------
97 
98 template <class T>
100 
101 template <class T>
103 
104 template <class T>
105 drwnPersistentStorageBuffer<T>::drwnPersistentStorageBuffer(const char *fileStem, bool bCompressed) :
106  _storage(bCompressed), _memoryUsed(0)
107 {
108  _storage.open(fileStem);
109  DRWN_ASSERT(_storage.isOpen());
110 }
111 
112 template <class T>
114 {
115  flush(); // write pending records
116  _storage.close();
117 }
118 
119 template <class T>
121 {
122  typename _drwnRecordRef::iterator it = _recref.find(key);
123  if (it != _recref.end()) {
124  // move record to front of record list
125  _records.push_front(*it->second);
126  _records.erase(it->second);
127  it->second = _records.begin();
128  return it->second->record;
129  }
130 
131  // read record from storage and push to front of record list
132  drwnSmartPointer<T> p(new T());
133  _storage.read(key.c_str(), p);
134  _records.push_front(_drwnRecordEntry(key, p));
135  _recref.insert(make_pair(key, _records.begin()));
136  _memoryUsed += p->numBytesOnDisk();
137  enforceLimits();
138 
139  return p;
140 }
141 
142 template <class T>
144 {
145  // delete existing record with same key
146  typename _drwnRecordRef::iterator it = _recref.find(key);
147  if (it != _recref.end()) {
148  _memoryUsed -= it->second->record->numBytesOnDisk();
149  _records.erase(it->second);
150  _recref.erase(it);
151  }
152 
153  // add record to front of record list
154  _records.push_front(_drwnRecordEntry(key, p));
155  _records.front().dirty = true;
156  _recref.insert(make_pair(key, _records.begin()));
157 
158  _memoryUsed += p->numBytesOnDisk();
159  enforceLimits();
160 }
161 
162 template <class T>
164 {
165  typename _drwnRecordRef::iterator it = _recref.find(key);
166  if (it != _recref.end()) {
167  _memoryUsed -= it->second->record->numBytesOnDisk();
168  _records.erase(it->second);
169  _recref.erase(it);
170  }
171  _storage.erase(key.c_str());
172 }
173 
174 template <class T>
176 {
177  for (typename _drwnRecordList::const_iterator it = _records.begin(); it != _records.end(); it++) {
178  if (it->dirty) {
179  _storage.write(it->key.c_str(), it->record);
180  }
181  }
182 
183  _recref.clear();
184  _records.clear();
185  _memoryUsed = 0;
186 }
187 
188 template <class T>
190 {
191  while (!_records.empty()) {
192  if ((_records.size() <= MAX_RECORDS) && (_memoryUsed <= MAX_MEMORY)) break;
193 
194  const string key = _records.back().key;
195  DRWN_LOG_DEBUG("removing " << (_records.back().dirty ? "dirty" : "clean") <<
196  " record \"" << key << "\" from drwnPersistentStorageBuffer");
197  _memoryUsed -= _records.back().record->numBytesOnDisk();
198  if (_records.back().dirty) {
199  _storage.write(key.c_str(), _records.back().record);
200  }
201 
202  typename _drwnRecordRef::iterator it = _recref.find(key);
203  DRWN_ASSERT_MSG(it != _recref.end(), key);
204  _recref.erase(it);
205 
206  _records.pop_back();
207  }
208 }
void erase(const string &key)
erases a record from storage (and memory)
Definition: drwnPersistentStorageBuffer.h:163
Definition: drwnPersistentStorageBuffer.h:45
void enforceLimits()
checks memory and count limits, writes and frees pending records if exceeded
Definition: drwnPersistentStorageBuffer.h:189
size_t memory() const
returns memory used by in-memory records
Definition: drwnPersistentStorageBuffer.h:73
size_t _memoryUsed
current memory usage
Definition: drwnPersistentStorageBuffer.h:64
bool open(const char *indexFile, const char *dataFile)
open persistent storage index and data files
Definition: drwnPersistentStorage.cpp:70
_drwnRecordList _records
cached records (in most-recently-used order)
Definition: drwnPersistentStorageBuffer.h:63
size_t size() const
returns number of records in the buffer
Definition: drwnPersistentStorageBuffer.h:71
bool dirty
dirty flag (requires write-back)
Definition: drwnPersistentStorageBuffer.h:49
void write(const string &key, drwnSmartPointer< T > &p)
writes a record to storage (the write is delayed until the record is removed from memory or flush is ...
Definition: drwnPersistentStorageBuffer.h:143
_drwnRecordRef _recref
reference to records
Definition: drwnPersistentStorageBuffer.h:62
drwnPersistentStorage _storage
storage object
Definition: drwnPersistentStorageBuffer.h:61
drwnSmartPointer< T > read(const string &key)
returns a record from the in-memory buffer or disk storage
Definition: drwnPersistentStorageBuffer.h:120
static size_t MAX_RECORDS
maximum number of records stored
Definition: drwnPersistentStorageBuffer.h:42
Provides indexed storage for multiple records using two files (a binary data file and a text index fi...
Definition: drwnPersistentStorage.h:162
const drwnPersistentStorage & storage() const
returns a reference to the storage object
Definition: drwnPersistentStorageBuffer.h:75
bool isOpen() const
returns true if the persistent storage has been opened and not closed
Definition: drwnPersistentStorage.h:201
string key
the record's key
Definition: drwnPersistentStorageBuffer.h:47
drwnSmartPointer< T > record
the record's data
Definition: drwnPersistentStorageBuffer.h:48
Implements a shared pointer interface to avoid the need to deep copy constant (shared) objects...
Definition: drwnSmartPointer.h:64
Provides buffered storage (delayed write-back) of objects with a drwnPersistentRecord interface...
Definition: drwnPersistentStorageBuffer.h:39
static size_t MAX_MEMORY
maximum number of bytes stored
Definition: drwnPersistentStorageBuffer.h:41
void flush()
write all pending records to disk
Definition: drwnPersistentStorageBuffer.h:175