From fb5176bbd5355b02b7d0e65da3ef3f0105824cd0 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Sun, 17 Mar 2013 23:45:21 +0000 Subject: The new cache system has been broken out into it's individual headers, and is now ready for actual use. --- src/experimental/cache.h | 437 ----------------------------------------------- 1 file changed, 437 deletions(-) delete mode 100644 src/experimental/cache.h (limited to 'src/experimental/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 @@ -/* - * Copyright (C) 2007-2013 Xagasoft, All rights reserved. - * - * This file is part of the libbu++ library and is released under the - * terms of the license contained in the file LICENSE. - */ - -#ifndef BU_CACHE_H -#define BU_CACHE_H - -// #include "bu/cptr.h" -#include "bu/hash.h" -#include "bu/list.h" -#include "bu/cachestore.h" -#include "bu/cachecalc.h" - -#include "bu/trace.h" - -namespace Bu -{ -// template -// keytype __cacheGetKey( obtype *&pObj ); - template - keytype __cacheGetKey( const obtype *pObj ) - { - return pObj->getKey(); - } - - template - class Cache - { - public: - /** - * Cache Pointer - Provides access to data that is held within the - * cache. This provides safe, refcounting access to data stored in - * the cache, with support for lazy loading. - */ - class Ptr - { - friend class Bu::Cache; - private: - Ptr( Cache *pCache, obtype *pData, - const keytype &kId ) : - pCache( pCache ), - pData( pData ), - kId( kId ) - { - if( pCache ) - pCache->incRef( kId ); - } - - Ptr( Cache *pCache, const keytype &kId ) : - pCache( pCache ), - pData( NULL ), - kId( kId ) - { - } - - public: - Ptr( const Ptr &rSrc ) : - pCache( rSrc.pCache ), - pData( rSrc.pData ), - kId( rSrc.kId ) - { - if( pCache && pData ) - pCache->incRef( kId ); - } - - Ptr() : - pCache( 0 ), - pData( 0 ) - { - } - - virtual ~Ptr() - { - if( pCache && pData ) - pCache->decRef( kId ); - } - - obtype &operator*() - { - checkPtr(); - return *pData; - } - - const obtype &operator*() const - { - checkPtr(); - return *pData; - } - - obtype *operator->() - { - checkPtr(); - return pData; - } - - const obtype *operator->() const - { - checkPtr(); - return pData; - } - - bool isValid() const - { - return pCache != NULL; - } - - bool isBound() const - { - return pData != NULL; - } - - bool isSet() const - { - return pCache != NULL; - } - - const keytype &getKey() const - { - return kId; - } - - void unbind() - { - if( pCache && pData ) - pCache->decRef( kId ); - pData = NULL; - } - - void clear() - { - unbind(); - pCache = NULL; - } - - void unset() - { - clear(); - } - - Ptr &operator=( const Ptr &rRhs ) - { - if( pCache && pData ) - pCache->decRef( kId ); - pCache = rRhs.pCache; - pData = rRhs.pData; - kId = rRhs.kId; - if( pCache && pData ) - pCache->incRef( kId ); - return *this; - } - - bool operator==( const Ptr &rRhs ) const - { - return pCache == rRhs.pCache && kId == rRhs.kId; - } - - bool operator!=( const Ptr &rRhs ) const - { - return pCache != rRhs.pCache || kId != rRhs.kId; - } - - private: - void checkPtr() const - { - if( pCache && !pData ) - { - pData = pCache->getRaw( kId ); - pCache->incRef( kId ); - } - } - - private: - Bu::Cache *pCache; - mutable obtype *pData; - mutable keytype kId; - }; - - private: - typedef Bu::CacheStore Store; - typedef Bu::List StoreList; - typedef Bu::CacheCalc Calc; - - typedef struct CacheEntry - { - obtype *pData; - int iRefs; - time_t tLastSync; - } CacheEntry; - - typedef Bu::Hash CidHash; - - public: - typedef keytype Key; - Cache( Calc *pCalc, Store *pStore ) : - pCalc( pCalc ), - pStore( pStore ) - { - TRACE(); - pCalc->setCache( this ); - } - - virtual ~Cache() - { - TRACE(); - - // Better safe than sorry, better try a sync before anything - // else happens. - sync(); - - // Cycle through and unload all objects from the system. - for( typename CidHash::iterator i = hEnt.begin(); - i != hEnt.end(); i++ ) - { - if( i.getValue().iRefs > 0 ) - { - // TODO: Throw an error in this case? iRefs != 0 for an - // object when the Cache is destroyed. - throw Bu::ExceptionBase("iRefs not zero."); - } - pStore->unload( - i.getValue().pData, - i.getKey() - ); - } - delete pCalc; - delete pStore; - } - - Ptr insert( obtype *pData ) - { - TRACE( pData ); - if( pStore->has( __cacheGetKey( pData ) ) ) - throw Bu::ExceptionBase("Key already exists in cache."); - CacheEntry e = {pData, 0, 0}; - keytype k = pStore->create( pData ); - hEnt.insert( k, e ); - - pCalc->onLoad( pData, k ); - - pStore->sync(); - - return Ptr( this, pData, k ); - } - - bool has( const keytype &cId ) - { - return hEnt.has( cId ) || pStore->has( cId ); - } - - /** - * Retrieve an object from the cache and return a pointer to it. - * The object returned may be loaded from backend storage if needed, - * or the currently live object will be returned. - *@param cId The id of the object to load. - *@returns A pointer to the object. - */ - Ptr get( const keytype &cId ) - { - TRACE( cId ); - try { - return Ptr( this, hEnt.get( cId ).pData, cId ); - } - catch( Bu::HashException &e ) { - CacheEntry e = {pStore->load( cId ), 0, time( NULL )}; - pCalc->onLoad( e.pData, cId ); - hEnt.insert( cId, e ); - return Ptr( this, e.pData, cId ); - } - } - - /** - * Retrieve a handle to an object without loading it now. This function - * will return a pointer that has not yet been "realized" but can be - * used normally. Upon initial use in any way the object will be - * loaded from the cache, either linking against the already loaded - * object or loading it fresh from the backend storage. The advantage - * of this is that you recieve a usable handle to the data, but it - * does not count as a reference yet, meaning that the data is loaded - * when you need it, not before. - */ - Ptr getLazy( const keytype &cId ) - { - TRACE( cId ); - return Ptr( this, cId ); - } - - int getRefCount( const keytype &cId ) - { - TRACE( cId ); - return hEnt.get( cId ).iRefs; - } - - void unload( const keytype &cId ) - { - TRACE( cId ); - try { - if( hEnt.get( cId ).iRefs > 0 ) - { - printf("Shouldn't unload, references still exist!\n"); - return; - } - } - catch( Bu::HashException &e ) { - // It's not here? Eh, return. - return; - } - obtype *pObj = hEnt.get( cId ).pData; - pCalc->onUnload( pObj, cId ); - hEnt.erase( cId ); - - // The unload has to happen last just in case cId is a reference - // to data that is about to be deleted from memory by the unload. - pStore->unload( pObj, cId ); - } - - void erase( const keytype &cId ) - { - TRACE( cId ); - try { - if( hEnt.get( cId ).iRefs > 0 ) - { - printf("Shouldn't erase, references still exist!\n"); - return; - } - - obtype *pObj = hEnt.get( cId ).pData; - pCalc->onDestroy( pObj, cId ); - hEnt.erase( cId ); - - pStore->destroy( pObj, cId ); - pStore->sync(); - } - catch( Bu::HashException &e ) { - pCalc->onDestroy( cId ); - - if( hEnt.has( cId ) ) - { - // The object was loaded by onDestroy - erase( cId ); - } - else - { - pStore->destroy( cId ); - pStore->sync(); - } - } - } - - typedef Bu::List KeyList; - KeyList getKeys() - { - return pStore->getKeys(); - } - - KeyList getActiveKeys() - { - return hEnt.getKeys(); - } - - int getSize() - { - return pStore->getSize(); - } - - /** - * Make sure all currently loaded but not-in-use objects are synced to - * the store. - */ - void sync() - { - TRACE(); - int iSynced = 0; - for( typename CidHash::iterator i = hEnt.begin(); - i != hEnt.end(); i++ ) - { - if( i.getValue().iRefs == 0 ) - { - if( pCalc->shouldSync( - i.getValue().pData, - i.getKey(), - i.getValue().tLastSync - ) ) - { - pStore->sync( - i.getValue().pData, - i.getKey() - ); - iSynced++; - i.getValue().tLastSync = time( NULL ); - } - } - } - if( iSynced > 0 ) - { - pStore->sync(); - } - } - - private: - void incRef( const keytype &cId ) - { - TRACE( cId ); - hEnt.get( cId ).iRefs++; - } - - void decRef( const keytype &cId ) - { - TRACE( cId ); - CacheEntry &e = hEnt.get( cId ); - e.iRefs--; - } - - obtype *getRaw( const keytype &cId ) - { - TRACE( cId ); - try { - return hEnt.get( cId ).pData; - } - catch( Bu::HashException &e ) { - CacheEntry e = {pStore->load( cId ), 0, time( NULL )}; - pCalc->onLoad( e.pData, cId ); - hEnt.insert( cId, e ); - return e.pData; - } - } - - private: - CidHash hEnt; - Calc *pCalc; - Store *pStore; - }; -}; - -#endif -- cgit v1.2.3