2015-04-15 19:05:58 +02:00
# include "CachedBlock.h"
2015-04-18 14:47:12 +02:00
# include "NewBlock.h"
2015-04-16 14:10:44 +02:00
# include "CachingBlockStore.h"
2015-04-15 15:46:35 +02:00
# include "../../interface/Block.h"
2015-04-15 19:05:58 +02:00
# include <algorithm>
2015-06-21 17:43:31 +02:00
# include <messmer/cpp-utils/pointer/cast.h>
2015-04-15 19:05:58 +02:00
2015-04-15 15:46:35 +02:00
using std : : unique_ptr ;
2015-04-15 19:05:58 +02:00
using std : : make_unique ;
2015-04-15 20:39:58 +02:00
using cpputils : : dynamic_pointer_move ;
2015-04-25 02:48:41 +02:00
using cpputils : : Data ;
2015-04-15 15:46:35 +02:00
namespace blockstore {
2015-04-16 14:10:44 +02:00
namespace caching {
2015-04-15 15:46:35 +02:00
2015-04-16 14:10:44 +02:00
CachingBlockStore : : CachingBlockStore ( std : : unique_ptr < BlockStore > baseBlockStore )
2015-04-18 14:47:12 +02:00
: _baseBlockStore ( std : : move ( baseBlockStore ) ) , _cache ( ) , _numNewBlocks ( 0 ) {
2015-04-15 15:46:35 +02:00
}
2015-04-18 14:47:12 +02:00
Key CachingBlockStore : : createKey ( ) {
return _baseBlockStore - > createKey ( ) ;
}
unique_ptr < Block > CachingBlockStore : : tryCreate ( const Key & key , Data data ) {
+ + _numNewBlocks ;
return make_unique < CachedBlock > ( make_unique < NewBlock > ( key , std : : move ( data ) , this ) , this ) ;
2015-04-15 15:46:35 +02:00
}
2015-04-16 14:10:44 +02:00
unique_ptr < Block > CachingBlockStore : : load ( const Key & key ) {
2015-04-27 22:46:57 +02:00
boost : : optional < unique_ptr < Block > > optBlock = _cache . pop ( key ) ;
unique_ptr < Block > block ;
//TODO an optional<> class with .getOrElse() would make this code simpler. boost::optional<>::value_or_eval didn't seem to work with unique_ptr members.
if ( optBlock ) {
block = std : : move ( * optBlock ) ;
} else {
block = _baseBlockStore - > load ( key ) ;
if ( block . get ( ) = = nullptr ) {
return nullptr ;
}
2015-04-15 20:39:58 +02:00
}
return make_unique < CachedBlock > ( std : : move ( block ) , this ) ;
2015-04-15 15:46:35 +02:00
}
2015-04-16 14:10:44 +02:00
void CachingBlockStore : : remove ( std : : unique_ptr < Block > block ) {
2015-04-18 14:47:12 +02:00
auto baseBlock = dynamic_pointer_move < CachedBlock > ( block ) - > releaseBlock ( ) ;
auto baseNewBlock = dynamic_pointer_move < NewBlock > ( baseBlock ) ;
if ( baseNewBlock . get ( ) ! = nullptr ) {
if ( ! baseNewBlock - > alreadyExistsInBaseStore ( ) ) {
- - _numNewBlocks ;
}
baseNewBlock - > remove ( ) ;
} else {
_baseBlockStore - > remove ( std : : move ( baseBlock ) ) ;
}
2015-04-15 15:46:35 +02:00
}
2015-04-16 14:10:44 +02:00
uint64_t CachingBlockStore : : numBlocks ( ) const {
2015-04-18 14:47:12 +02:00
return _baseBlockStore - > numBlocks ( ) + _numNewBlocks ;
2015-04-15 15:46:35 +02:00
}
2015-04-16 14:10:44 +02:00
void CachingBlockStore : : release ( unique_ptr < Block > block ) {
2015-04-27 22:46:57 +02:00
Key key = block - > key ( ) ;
_cache . push ( key , std : : move ( block ) ) ;
2015-04-15 19:05:58 +02:00
}
2015-04-18 14:47:12 +02:00
std : : unique_ptr < Block > CachingBlockStore : : tryCreateInBaseStore ( const Key & key , Data data ) {
auto block = _baseBlockStore - > tryCreate ( key , std : : move ( data ) ) ;
if ( block . get ( ) ! = nullptr ) {
- - _numNewBlocks ;
}
return block ;
}
void CachingBlockStore : : removeFromBaseStore ( std : : unique_ptr < Block > block ) {
_baseBlockStore - > remove ( std : : move ( block ) ) ;
}
2015-04-15 15:46:35 +02:00
}
}