aboutsummaryrefslogtreecommitdiff
path: root/src/experimental
diff options
context:
space:
mode:
authorMike Buland <eichlan@xagasoft.com>2013-03-17 23:45:21 +0000
committerMike Buland <eichlan@xagasoft.com>2013-03-17 23:45:21 +0000
commitfb5176bbd5355b02b7d0e65da3ef3f0105824cd0 (patch)
tree32a9d8114ce4852b901a35f6aec982e6071a3bac /src/experimental
parenta6d249cad214dc0baff0e80e56ffdec91d8a1cf0 (diff)
downloadlibbu++-fb5176bbd5355b02b7d0e65da3ef3f0105824cd0.tar.gz
libbu++-fb5176bbd5355b02b7d0e65da3ef3f0105824cd0.tar.bz2
libbu++-fb5176bbd5355b02b7d0e65da3ef3f0105824cd0.tar.xz
libbu++-fb5176bbd5355b02b7d0e65da3ef3f0105824cd0.zip
The new cache system has been broken out into it's individual headers, and is
now ready for actual use.
Diffstat (limited to 'src/experimental')
-rw-r--r--src/experimental/cache.cpp8
-rw-r--r--src/experimental/cache.h437
-rw-r--r--src/experimental/cachecalc.cpp8
-rw-r--r--src/experimental/cachecalc.h63
-rw-r--r--src/experimental/cachestore.cpp9
-rw-r--r--src/experimental/cachestore.h46
-rw-r--r--src/experimental/cachestorefiles.cpp9
-rw-r--r--src/experimental/cachestorefiles.h211
-rw-r--r--src/experimental/cachestoremyriad.cpp9
-rw-r--r--src/experimental/cachestoremyriad.h158
10 files changed, 0 insertions, 958 deletions
diff --git a/src/experimental/cache.cpp b/src/experimental/cache.cpp
deleted file mode 100644
index 840682a..0000000
--- a/src/experimental/cache.cpp
+++ /dev/null
@@ -1,8 +0,0 @@
1/*
2 * Copyright (C) 2007-2013 Xagasoft, All rights reserved.
3 *
4 * This file is part of the libbu++ library and is released under the
5 * terms of the license contained in the file LICENSE.
6 */
7
8#include "bu/cache.h"
diff --git a/src/experimental/cache.h b/src/experimental/cache.h
deleted file mode 100644
index b9d1b7a..0000000
--- a/src/experimental/cache.h
+++ /dev/null
@@ -1,437 +0,0 @@
1/*
2 * Copyright (C) 2007-2013 Xagasoft, All rights reserved.
3 *
4 * This file is part of the libbu++ library and is released under the
5 * terms of the license contained in the file LICENSE.
6 */
7
8#ifndef BU_CACHE_H
9#define BU_CACHE_H
10
11// #include "bu/cptr.h"
12#include "bu/hash.h"
13#include "bu/list.h"
14#include "bu/cachestore.h"
15#include "bu/cachecalc.h"
16
17#include "bu/trace.h"
18
19namespace Bu
20{
21// template<class keytype, class obtype>
22// keytype __cacheGetKey( obtype *&pObj );
23 template<class keytype, class obtype>
24 keytype __cacheGetKey( const obtype *pObj )
25 {
26 return pObj->getKey();
27 }
28
29 template<class keytype, class obtype>
30 class Cache
31 {
32 public:
33 /**
34 * Cache Pointer - Provides access to data that is held within the
35 * cache. This provides safe, refcounting access to data stored in
36 * the cache, with support for lazy loading.
37 */
38 class Ptr
39 {
40 friend class Bu::Cache<keytype, obtype>;
41 private:
42 Ptr( Cache<keytype, obtype> *pCache, obtype *pData,
43 const keytype &kId ) :
44 pCache( pCache ),
45 pData( pData ),
46 kId( kId )
47 {
48 if( pCache )
49 pCache->incRef( kId );
50 }
51
52 Ptr( Cache<keytype, obtype> *pCache, const keytype &kId ) :
53 pCache( pCache ),
54 pData( NULL ),
55 kId( kId )
56 {
57 }
58
59 public:
60 Ptr( const Ptr &rSrc ) :
61 pCache( rSrc.pCache ),
62 pData( rSrc.pData ),
63 kId( rSrc.kId )
64 {
65 if( pCache && pData )
66 pCache->incRef( kId );
67 }
68
69 Ptr() :
70 pCache( 0 ),
71 pData( 0 )
72 {
73 }
74
75 virtual ~Ptr()
76 {
77 if( pCache && pData )
78 pCache->decRef( kId );
79 }
80
81 obtype &operator*()
82 {
83 checkPtr();
84 return *pData;
85 }
86
87 const obtype &operator*() const
88 {
89 checkPtr();
90 return *pData;
91 }
92
93 obtype *operator->()
94 {
95 checkPtr();
96 return pData;
97 }
98
99 const obtype *operator->() const
100 {
101 checkPtr();
102 return pData;
103 }
104
105 bool isValid() const
106 {
107 return pCache != NULL;
108 }
109
110 bool isBound() const
111 {
112 return pData != NULL;
113 }
114
115 bool isSet() const
116 {
117 return pCache != NULL;
118 }
119
120 const keytype &getKey() const
121 {
122 return kId;
123 }
124
125 void unbind()
126 {
127 if( pCache && pData )
128 pCache->decRef( kId );
129 pData = NULL;
130 }
131
132 void clear()
133 {
134 unbind();
135 pCache = NULL;
136 }
137
138 void unset()
139 {
140 clear();
141 }
142
143 Ptr &operator=( const Ptr &rRhs )
144 {
145 if( pCache && pData )
146 pCache->decRef( kId );
147 pCache = rRhs.pCache;
148 pData = rRhs.pData;
149 kId = rRhs.kId;
150 if( pCache && pData )
151 pCache->incRef( kId );
152 return *this;
153 }
154
155 bool operator==( const Ptr &rRhs ) const
156 {
157 return pCache == rRhs.pCache && kId == rRhs.kId;
158 }
159
160 bool operator!=( const Ptr &rRhs ) const
161 {
162 return pCache != rRhs.pCache || kId != rRhs.kId;
163 }
164
165 private:
166 void checkPtr() const
167 {
168 if( pCache && !pData )
169 {
170 pData = pCache->getRaw( kId );
171 pCache->incRef( kId );
172 }
173 }
174
175 private:
176 Bu::Cache<keytype, obtype> *pCache;
177 mutable obtype *pData;
178 mutable keytype kId;
179 };
180
181 private:
182 typedef Bu::CacheStore<keytype, obtype> Store;
183 typedef Bu::List<Store *> StoreList;
184 typedef Bu::CacheCalc<keytype, obtype> Calc;
185
186 typedef struct CacheEntry
187 {
188 obtype *pData;
189 int iRefs;
190 time_t tLastSync;
191 } CacheEntry;
192
193 typedef Bu::Hash<keytype, CacheEntry> CidHash;
194
195 public:
196 typedef keytype Key;
197 Cache( Calc *pCalc, Store *pStore ) :
198 pCalc( pCalc ),
199 pStore( pStore )
200 {
201 TRACE();
202 pCalc->setCache( this );
203 }
204
205 virtual ~Cache()
206 {
207 TRACE();
208
209 // Better safe than sorry, better try a sync before anything
210 // else happens.
211 sync();
212
213 // Cycle through and unload all objects from the system.
214 for( typename CidHash::iterator i = hEnt.begin();
215 i != hEnt.end(); i++ )
216 {
217 if( i.getValue().iRefs > 0 )
218 {
219 // TODO: Throw an error in this case? iRefs != 0 for an
220 // object when the Cache is destroyed.
221 throw Bu::ExceptionBase("iRefs not zero.");
222 }
223 pStore->unload(
224 i.getValue().pData,
225 i.getKey()
226 );
227 }
228 delete pCalc;
229 delete pStore;
230 }
231
232 Ptr insert( obtype *pData )
233 {
234 TRACE( pData );
235 if( pStore->has( __cacheGetKey<keytype, obtype>( pData ) ) )
236 throw Bu::ExceptionBase("Key already exists in cache.");
237 CacheEntry e = {pData, 0, 0};
238 keytype k = pStore->create( pData );
239 hEnt.insert( k, e );
240
241 pCalc->onLoad( pData, k );
242
243 pStore->sync();
244
245 return Ptr( this, pData, k );
246 }
247
248 bool has( const keytype &cId )
249 {
250 return hEnt.has( cId ) || pStore->has( cId );
251 }
252
253 /**
254 * Retrieve an object from the cache and return a pointer to it.
255 * The object returned may be loaded from backend storage if needed,
256 * or the currently live object will be returned.
257 *@param cId The id of the object to load.
258 *@returns A pointer to the object.
259 */
260 Ptr get( const keytype &cId )
261 {
262 TRACE( cId );
263 try {
264 return Ptr( this, hEnt.get( cId ).pData, cId );
265 }
266 catch( Bu::HashException &e ) {
267 CacheEntry e = {pStore->load( cId ), 0, time( NULL )};
268 pCalc->onLoad( e.pData, cId );
269 hEnt.insert( cId, e );
270 return Ptr( this, e.pData, cId );
271 }
272 }
273
274 /**
275 * Retrieve a handle to an object without loading it now. This function
276 * will return a pointer that has not yet been "realized" but can be
277 * used normally. Upon initial use in any way the object will be
278 * loaded from the cache, either linking against the already loaded
279 * object or loading it fresh from the backend storage. The advantage
280 * of this is that you recieve a usable handle to the data, but it
281 * does not count as a reference yet, meaning that the data is loaded
282 * when you need it, not before.
283 */
284 Ptr getLazy( const keytype &cId )
285 {
286 TRACE( cId );
287 return Ptr( this, cId );
288 }
289
290 int getRefCount( const keytype &cId )
291 {
292 TRACE( cId );
293 return hEnt.get( cId ).iRefs;
294 }
295
296 void unload( const keytype &cId )
297 {
298 TRACE( cId );
299 try {
300 if( hEnt.get( cId ).iRefs > 0 )
301 {
302 printf("Shouldn't unload, references still exist!\n");
303 return;
304 }
305 }
306 catch( Bu::HashException &e ) {
307 // It's not here? Eh, return.
308 return;
309 }
310 obtype *pObj = hEnt.get( cId ).pData;
311 pCalc->onUnload( pObj, cId );
312 hEnt.erase( cId );
313
314 // The unload has to happen last just in case cId is a reference
315 // to data that is about to be deleted from memory by the unload.
316 pStore->unload( pObj, cId );
317 }
318
319 void erase( const keytype &cId )
320 {
321 TRACE( cId );
322 try {
323 if( hEnt.get( cId ).iRefs > 0 )
324 {
325 printf("Shouldn't erase, references still exist!\n");
326 return;
327 }
328
329 obtype *pObj = hEnt.get( cId ).pData;
330 pCalc->onDestroy( pObj, cId );
331 hEnt.erase( cId );
332
333 pStore->destroy( pObj, cId );
334 pStore->sync();
335 }
336 catch( Bu::HashException &e ) {
337 pCalc->onDestroy( cId );
338
339 if( hEnt.has( cId ) )
340 {
341 // The object was loaded by onDestroy
342 erase( cId );
343 }
344 else
345 {
346 pStore->destroy( cId );
347 pStore->sync();
348 }
349 }
350 }
351
352 typedef Bu::List<keytype> KeyList;
353 KeyList getKeys()
354 {
355 return pStore->getKeys();
356 }
357
358 KeyList getActiveKeys()
359 {
360 return hEnt.getKeys();
361 }
362
363 int getSize()
364 {
365 return pStore->getSize();
366 }
367
368 /**
369 * Make sure all currently loaded but not-in-use objects are synced to
370 * the store.
371 */
372 void sync()
373 {
374 TRACE();
375 int iSynced = 0;
376 for( typename CidHash::iterator i = hEnt.begin();
377 i != hEnt.end(); i++ )
378 {
379 if( i.getValue().iRefs == 0 )
380 {
381 if( pCalc->shouldSync(
382 i.getValue().pData,
383 i.getKey(),
384 i.getValue().tLastSync
385 ) )
386 {
387 pStore->sync(
388 i.getValue().pData,
389 i.getKey()
390 );
391 iSynced++;
392 i.getValue().tLastSync = time( NULL );
393 }
394 }
395 }
396 if( iSynced > 0 )
397 {
398 pStore->sync();
399 }
400 }
401
402 private:
403 void incRef( const keytype &cId )
404 {
405 TRACE( cId );
406 hEnt.get( cId ).iRefs++;
407 }
408
409 void decRef( const keytype &cId )
410 {
411 TRACE( cId );
412 CacheEntry &e = hEnt.get( cId );
413 e.iRefs--;
414 }
415
416 obtype *getRaw( const keytype &cId )
417 {
418 TRACE( cId );
419 try {
420 return hEnt.get( cId ).pData;
421 }
422 catch( Bu::HashException &e ) {
423 CacheEntry e = {pStore->load( cId ), 0, time( NULL )};
424 pCalc->onLoad( e.pData, cId );
425 hEnt.insert( cId, e );
426 return e.pData;
427 }
428 }
429
430 private:
431 CidHash hEnt;
432 Calc *pCalc;
433 Store *pStore;
434 };
435};
436
437#endif
diff --git a/src/experimental/cachecalc.cpp b/src/experimental/cachecalc.cpp
deleted file mode 100644
index 7e2940c..0000000
--- a/src/experimental/cachecalc.cpp
+++ /dev/null
@@ -1,8 +0,0 @@
1/*
2 * Copyright (C) 2007-2013 Xagasoft, All rights reserved.
3 *
4 * This file is part of the libbu++ library and is released under the
5 * terms of the license contained in the file LICENSE.
6 */
7
8#include "bu/cachecalc.h"
diff --git a/src/experimental/cachecalc.h b/src/experimental/cachecalc.h
deleted file mode 100644
index c6cf33a..0000000
--- a/src/experimental/cachecalc.h
+++ /dev/null
@@ -1,63 +0,0 @@
1/*
2 * Copyright (C) 2007-2013 Xagasoft, All rights reserved.
3 *
4 * This file is part of the libbu++ library and is released under the
5 * terms of the license contained in the file LICENSE.
6 */
7
8#ifndef BU_CACHE_CALC_H
9#define BU_CACHE_CALC_H
10
11#include "bu/trace.h"
12
13#include <time.h>
14
15namespace Bu
16{
17 template<class keytype, class obtype> class Cache;
18
19 template<class keytype, class obtype>
20 class CacheCalc
21 {
22 friend class Cache<keytype, obtype>;
23 private:
24 typedef Cache<keytype, obtype> MyCache;
25 public:
26 CacheCalc() :
27 pCache( (MyCache *)0 )
28 {
29 TRACE();
30 }
31
32 virtual ~CacheCalc()
33 {
34 TRACE();
35 }
36
37 virtual void onLoad( obtype *pSrc, const keytype &key )=0;
38 virtual void onUnload( obtype *pSrc, const keytype &key )=0;
39 virtual void onDestroy( obtype *pSrc, const keytype &key )=0;
40 virtual void onDestroy( const keytype &key )=0;
41 virtual bool shouldSync( obtype *pSrc, const keytype &key,
42 time_t tLastSync )=0;
43 virtual void onTick() { };
44
45 protected:
46 MyCache *getCache()
47 {
48 TRACE();
49 return pCache;
50 }
51
52 private:
53 void setCache( MyCache *pCache )
54 {
55 TRACE();
56 this->pCache = pCache;
57 }
58
59 MyCache *pCache;
60 };
61};
62
63#endif
diff --git a/src/experimental/cachestore.cpp b/src/experimental/cachestore.cpp
deleted file mode 100644
index 2082a50..0000000
--- a/src/experimental/cachestore.cpp
+++ /dev/null
@@ -1,9 +0,0 @@
1/*
2 * Copyright (C) 2007-2013 Xagasoft, All rights reserved.
3 *
4 * This file is part of the libbu++ library and is released under the
5 * terms of the license contained in the file LICENSE.
6 */
7
8#include "bu/cachestore.h"
9
diff --git a/src/experimental/cachestore.h b/src/experimental/cachestore.h
deleted file mode 100644
index 48a84ad..0000000
--- a/src/experimental/cachestore.h
+++ /dev/null
@@ -1,46 +0,0 @@
1/*
2 * Copyright (C) 2007-2013 Xagasoft, All rights reserved.
3 *
4 * This file is part of the libbu++ library and is released under the
5 * terms of the license contained in the file LICENSE.
6 */
7
8#ifndef BU_CACHE_STORE_H
9#define BU_CACHE_STORE_H
10
11#include "bu/list.h"
12
13namespace Bu
14{
15 /**
16 * Handles I/O for data in the cache. This also assigns ID's to the newly
17 * created objects that are requested through this system.
18 */
19 template<class keytype, class obtype>
20 class CacheStore
21 {
22 public:
23 CacheStore()
24 {
25 }
26
27 virtual ~CacheStore()
28 {
29 }
30
31 virtual obtype *load( const keytype &key )=0;
32 virtual void unload( obtype *pObj, const keytype &key )=0;
33 virtual keytype create( obtype *pSrc )=0;
34 virtual void sync()=0;
35 virtual void sync( obtype *pObj, const keytype &key )=0;
36 virtual void destroy( obtype *pObj, const keytype &key )=0;
37 virtual void destroy( const keytype &key )=0;
38 virtual bool has( const keytype &key )=0;
39 virtual Bu::List<keytype> getKeys() { return Bu::List<keytype>(); }
40 virtual int getSize() { return -1; }
41
42 private:
43 };
44};
45
46#endif
diff --git a/src/experimental/cachestorefiles.cpp b/src/experimental/cachestorefiles.cpp
deleted file mode 100644
index bf65660..0000000
--- a/src/experimental/cachestorefiles.cpp
+++ /dev/null
@@ -1,9 +0,0 @@
1/*
2 * Copyright (C) 2007-2013 Xagasoft, All rights reserved.
3 *
4 * This file is part of the libbu++ library and is released under the
5 * terms of the license contained in the file LICENSE.
6 */
7
8#include "bu/cachestorefiles.h"
9
diff --git a/src/experimental/cachestorefiles.h b/src/experimental/cachestorefiles.h
deleted file mode 100644
index 90b0a00..0000000
--- a/src/experimental/cachestorefiles.h
+++ /dev/null
@@ -1,211 +0,0 @@
1/*
2 * Copyright (C) 2007-2013 Xagasoft, All rights reserved.
3 *
4 * This file is part of the libbu++ library and is released under the
5 * terms of the license contained in the file LICENSE.
6 */
7
8#ifndef BU_CACHE_STORE_FILES_H
9#define BU_CACHE_STORE_FILES_H
10
11#include "bu/string.h"
12#include "bu/file.h"
13#include "bu/cachestore.h"
14#include "bu/archive.h"
15#include "bu/membuf.h"
16#include "bu/formatter.h"
17#include "bu/sio.h"
18
19#include <sys/types.h>
20#include <sys/stat.h>
21#include <dirent.h>
22#include <unistd.h>
23
24namespace Bu
25{
26 template<class keytype, class obtype>
27 keytype __cacheGetKey( const obtype *pObj );
28
29 template<class keytype, class obtype>
30 obtype *__cacheStoreFilesAlloc( const keytype &key )
31 {
32 return new obtype();
33 }
34
35 template<class keytype, class obtype>
36 void __cacheStoreFilesStore( Bu::Stream &s, obtype &rObj,
37 const keytype & )
38 {
39 Bu::Archive ar( s, Bu::Archive::save );
40 ar << rObj;
41 }
42
43 template<class keytype, class obtype>
44 obtype *__cacheStoreFilesLoad( Bu::Stream &s, const keytype &key )
45 {
46 obtype *pObj = __cacheStoreFilesAlloc<keytype, obtype>( key );
47 Bu::Archive ar( s, Bu::Archive::load );
48 ar >> (*pObj);
49 return pObj;
50 }
51
52 template<class keytype, class obtype>
53 class CacheStoreFiles : public CacheStore<keytype, obtype>
54 {
55 public:
56 CacheStoreFiles( const Bu::String &sPrefix ) :
57 sPrefix( sPrefix )
58 {
59 if( access( sPrefix.getStr(), W_OK|R_OK|X_OK ) )
60 {
61#ifdef WIN32
62 mkdir( sPrefix.getStr() );
63#else
64 mkdir( sPrefix.getStr(), 0755 );
65#endif
66 }
67 }
68
69 virtual ~CacheStoreFiles()
70 {
71 }
72
73 virtual obtype *load( const keytype &key )
74 {
75// try
76// {
77 Bu::MemBuf mb;
78 Bu::Formatter f( mb );
79 f << sPrefix << "/" << key;
80 Bu::File fIn( mb.getString(), Bu::File::Read );
81 obtype *pOb = __cacheStoreFilesLoad<keytype, obtype>( fIn, key );
82 return pOb;
83// }
84// catch( std::exception &e )
85// {
86// throw Bu::HashException( e.what() );
87// }
88 }
89
90 virtual void unload( obtype *pObj, const keytype & )
91 {
92 delete pObj;
93 }
94
95 virtual keytype create( obtype *pSrc )
96 {
97 keytype key = __cacheGetKey<keytype, obtype>( pSrc );
98 Bu::MemBuf mb;
99 Bu::Formatter f( mb );
100 f << sPrefix << "/" << key;
101
102 Bu::File fTouch( mb.getString(), Bu::File::WriteNew );
103
104 return key;
105 }
106
107 virtual void sync()
108 {
109 }
110
111 virtual void sync( obtype *pSrc, const keytype &key )
112 {
113 Bu::MemBuf mb;
114 Bu::Formatter f( mb );
115 f << sPrefix << "/" << key;
116
117 Bu::File fOut( mb.getString(), Bu::File::WriteNew );
118 __cacheStoreFilesStore<keytype, obtype>( fOut, *pSrc, key );
119 }
120
121 virtual void destroy( obtype *pObj, const keytype &key )
122 {
123 Bu::MemBuf mb;
124 Bu::Formatter f( mb );
125 f << sPrefix << "/" << key;
126
127 unlink( mb.getString().getStr() );
128 delete pObj;
129 }
130
131 virtual void destroy( const keytype &key )
132 {
133 Bu::MemBuf mb;
134 Bu::Formatter f( mb );
135 f << sPrefix << "/" << key;
136
137 unlink( mb.getString().getStr() );
138 }
139
140 virtual bool has( const keytype &key )
141 {
142 Bu::MemBuf mb;
143 Bu::Formatter f( mb );
144 f << sPrefix << "/";
145 Bu::String sBase = mb.getString();
146 f << key;
147
148 if( sBase == mb.getString() )
149 return false;
150
151 return access( mb.getString().getStr(), F_OK ) == 0;
152 }
153
154 virtual Bu::List<keytype> getKeys()
155 {
156 DIR *dir = opendir( sPrefix.getStr() );
157 struct dirent *de;
158 Bu::List<keytype> lKeys;
159
160 while( (de = readdir( dir ) ) )
161 {
162 if( de->d_type != DT_REG )
163 continue;
164
165 keytype tmp;
166 Bu::MemBuf mb( de->d_name );
167 Bu::Formatter f( mb );
168 try
169 {
170 Fmt fm;
171 fm.tokenize( false );
172 f << fm;
173 f >> tmp;
174 }
175 catch( Bu::ExceptionBase &e )
176 {
177 Bu::sio << "Parse error in dir-scan: " << e.what()
178 << Bu::sio.nl;
179 }
180 lKeys.append( tmp );
181 }
182 closedir( dir );
183
184 return lKeys;
185 }
186
187 virtual int getSize()
188 {
189 DIR *dir = opendir( sPrefix.getStr() );
190 struct dirent *de;
191 int iCount = 0;
192
193 while( (de = readdir( dir ) ) )
194 {
195 if( de->d_type != DT_REG )
196 continue;
197
198 iCount++;
199 }
200 closedir( dir );
201
202 return iCount;
203 }
204
205 private:
206 Bu::String sPrefix;
207 };
208
209};
210
211#endif
diff --git a/src/experimental/cachestoremyriad.cpp b/src/experimental/cachestoremyriad.cpp
deleted file mode 100644
index f6edc7a..0000000
--- a/src/experimental/cachestoremyriad.cpp
+++ /dev/null
@@ -1,9 +0,0 @@
1/*
2 * Copyright (C) 2007-2013 Xagasoft, All rights reserved.
3 *
4 * This file is part of the libbu++ library and is released under the
5 * terms of the license contained in the file LICENSE.
6 */
7
8#include "bu/cachestoremyriad.h"
9
diff --git a/src/experimental/cachestoremyriad.h b/src/experimental/cachestoremyriad.h
deleted file mode 100644
index 798d205..0000000
--- a/src/experimental/cachestoremyriad.h
+++ /dev/null
@@ -1,158 +0,0 @@
1/*
2 * Copyright (C) 2007-2013 Xagasoft, All rights reserved.
3 *
4 * This file is part of the libbu++ library and is released under the
5 * terms of the license contained in the file LICENSE.
6 */
7
8#ifndef BU_CACHE_STORE_MYRIAD_H
9#define BU_CACHE_STORE_MYRIAD_H
10
11#include "bu/string.h"
12#include "bu/stream.h"
13#include "bu/myriad.h"
14#include "bu/cachestore.h"
15#include "bu/myriadstream.h"
16
17#include "bu/archive.h"
18
19namespace Bu
20{
21 template<class keytype, class obtype>
22 keytype __cacheGetKey( const obtype *pObj );
23
24 template<class keytype, class obtype>
25 obtype *__cacheStoreMyriadAlloc( const keytype &key )
26 {
27 return new obtype();
28 }
29
30 template<class keytype, class obtype>
31 void __cacheStoreMyriadStore( Bu::Stream &s, obtype &rObj,
32 const keytype & )
33 {
34 Bu::Archive ar( s, Bu::Archive::save );
35 ar << rObj;
36 }
37
38 template<class keytype, class obtype>
39 obtype *__cacheStoreMyriadLoad( Bu::Stream &s, const keytype &key )
40 {
41 obtype *pObj = __cacheStoreMyriadAlloc<keytype, obtype>( key );
42 Bu::Archive ar( s, Bu::Archive::load );
43 ar >> (*pObj);
44 return pObj;
45 }
46
47 template<class keytype, class obtype>
48 class CacheStoreMyriad : public CacheStore<keytype, obtype>
49 {
50 public:
51 CacheStoreMyriad( Bu::Stream &sArch,
52 int iBlockSize=512, int iPreAllocate=8 ) :
53 mStore( sArch, iBlockSize, iPreAllocate )
54 {
55 try
56 {
57 MyriadStream ns = mStore.openStream( 1 );
58 Bu::Archive ar( ns, Bu::Archive::load );
59 ar >> hId;
60 }
61 catch( Bu::MyriadException &e )
62 {
63 int iStream = mStore.createStream();
64 if( iStream != 1 )
65 throw Bu::ExceptionBase("That's...horrible...id = %d.\n\n",
66 iStream );
67 MyriadStream ns = mStore.openStream( 1 );
68 Bu::Archive ar( ns, Bu::Archive::save );
69 ar << hId;
70 }
71 }
72
73 virtual ~CacheStoreMyriad()
74 {
75 MyriadStream ns = mStore.openStream( 1 );
76 Bu::Archive ar( ns, Bu::Archive::save );
77 ar << hId;
78 }
79
80 virtual obtype *load( const keytype &key )
81 {
82 int iStream = hId.get( key );
83 MyriadStream ns = mStore.openStream( iStream );
84 obtype *pOb = __cacheStoreMyriadLoad<keytype, obtype>( ns, key );
85 return pOb;
86 }
87
88 virtual void unload( obtype *pObj, const keytype & )
89 {
90 delete pObj;
91 }
92
93 virtual keytype create( obtype *pSrc )
94 {
95 keytype key = __cacheGetKey<keytype, obtype>( pSrc );
96 int iStream = mStore.createStream();
97 hId.insert( key, iStream );
98 MyriadStream ns = mStore.openStream( iStream );
99 __cacheStoreMyriadStore<keytype, obtype>( ns, *pSrc, key );
100 ns.setSize( ns.tell() );
101 return key;
102 }
103
104 virtual void sync()
105 {
106 MyriadStream ns = mStore.openStream( 1 );
107 Bu::Archive ar( ns, Bu::Archive::save );
108 ar << hId;
109 ns.setSize( ns.tell() );
110 mStore.sync();
111 }
112
113 virtual void sync( obtype *pSrc, const keytype &key )
114 {
115 int iStream = hId.get( key );
116 MyriadStream ns = mStore.openStream( iStream );
117 __cacheStoreMyriadStore<keytype, obtype>( ns, *pSrc, key );
118 ns.setSize( ns.tell() );
119 }
120
121 virtual void destroy( obtype *pObj, const keytype &key )
122 {
123 int iStream = hId.get( key );
124 mStore.deleteStream( iStream );
125 hId.erase( key );
126 delete pObj;
127 }
128
129 virtual void destroy( const keytype &key )
130 {
131 int iStream = hId.get( key );
132 mStore.deleteStream( iStream );
133 hId.erase( key );
134 }
135
136 virtual bool has( const keytype &key )
137 {
138 return hId.has( key );
139 }
140
141 virtual Bu::List<keytype> getKeys()
142 {
143 return hId.getKeys();
144 }
145
146 virtual int getSize()
147 {
148 return hId.getSize();
149 }
150
151 private:
152 Myriad mStore;
153 typedef Bu::Hash<keytype, long> StreamHash;
154 StreamHash hId;
155 };
156};
157
158#endif