From 668737effd601778fba74edec14d22dd5b87457a Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Mon, 19 Apr 2010 15:16:53 +0000 Subject: CacheStoreMyriad is written, it's pretty much a copy of CacheStoreNids since Nids and Myriad pretty much share an API. However, there seems to be a bug in Myriad when a Myriad file is created and filled with data immediately, the header stream is mis-linking one of the blocks again. --- src/cachestoremyriad.cpp | 9 +++ src/cachestoremyriad.h | 156 +++++++++++++++++++++++++++++++++++++++++++++++ src/myriad.cpp | 69 +++++++++++++++------ src/myriad.h | 4 ++ src/tafcomment.cpp | 7 +++ src/tafcomment.h | 1 + src/tafgroup.cpp | 23 +++++++ src/tafgroup.h | 1 + src/tafproperty.cpp | 7 +++ src/tafproperty.h | 1 + 10 files changed, 258 insertions(+), 20 deletions(-) create mode 100644 src/cachestoremyriad.cpp create mode 100644 src/cachestoremyriad.h (limited to 'src') diff --git a/src/cachestoremyriad.cpp b/src/cachestoremyriad.cpp new file mode 100644 index 0000000..b08aea1 --- /dev/null +++ b/src/cachestoremyriad.cpp @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2007-2010 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. + */ + +#include "bu/cachestoremyriad.h" + diff --git a/src/cachestoremyriad.h b/src/cachestoremyriad.h new file mode 100644 index 0000000..a40ffb2 --- /dev/null +++ b/src/cachestoremyriad.h @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2007-2010 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_STORE_MYRIAD_H +#define BU_CACHE_STORE_MYRIAD_H + +#include "bu/fstring.h" +#include "bu/stream.h" +#include "bu/myriad.h" +#include "bu/cachestore.h" +#include "bu/myriadstream.h" + +#include "bu/archive.h" + +#include "bu/sio.h" + +namespace Bu +{ + template + keytype __cacheGetKey( const obtype *pObj ); + + template + obtype *__cacheStoreMyriadAlloc( const keytype &key ) + { + return new obtype(); + } + + template + void __cacheStoreMyriadStore( Bu::Stream &s, obtype &rObj, + const keytype & ) + { + Bu::Archive ar( s, Bu::Archive::save ); + ar << rObj; + } + + template + obtype *__cacheStoreMyriadLoad( Bu::Stream &s, const keytype &key ) + { + obtype *pObj = __cacheStoreMyriadAlloc( key ); + Bu::Archive ar( s, Bu::Archive::load ); + ar >> (*pObj); + return pObj; + } + + template + class CacheStoreMyriad : public CacheStore + { + public: + CacheStoreMyriad( Bu::Stream &sArch, + int iBlockSize=1024, int iPreAllocate=1 ) : + mStore( sArch ) + { + try + { + mStore.initialize(); + MyriadStream ns = mStore.openStream( 1 ); + Bu::Archive ar( ns, Bu::Archive::load ); + ar >> hId; + Bu::sio << hId << Bu::sio.nl; + } + catch( Bu::MyriadException &e ) + { + mStore.initialize( iBlockSize, iPreAllocate ); + int iStream = mStore.createStream(); + if( iStream != 1 ) + throw Bu::ExceptionBase("That's...horrible...id = %d.\n\n", iStream ); + MyriadStream ns = mStore.openStream( 1 ); + Bu::Archive ar( ns, Bu::Archive::save ); + ar << hId; + } + } + + virtual ~CacheStoreMyriad() + { + MyriadStream ns = mStore.openStream( 1 ); + Bu::Archive ar( ns, Bu::Archive::save ); + ar << hId; + } + + virtual obtype *load( const keytype &key ) + { + int iStream = hId.get( key ); + MyriadStream ns = mStore.openStream( iStream ); + obtype *pOb = __cacheStoreMyriadLoad( ns, key ); + return pOb; + } + + virtual void unload( obtype *pObj, const keytype &key ) + { + int iStream = hId.get( key ); + MyriadStream ns = mStore.openStream( iStream ); + __cacheStoreMyriadStore( ns, *pObj, key ); + delete pObj; + } + + virtual keytype create( obtype *pSrc ) + { + keytype key = __cacheGetKey( pSrc ); + int iStream = mStore.createStream(); + hId.insert( key, iStream ); + MyriadStream ns = mStore.openStream( iStream ); + __cacheStoreMyriadStore( ns, *pSrc, key ); + return key; + } + + virtual void sync() + { + MyriadStream ns = mStore.openStream( 1 ); + Bu::Archive ar( ns, Bu::Archive::save ); + ar << hId; + + mStore.sync(); + } + + virtual void sync( obtype *pSrc, const keytype &key ) + { + int iStream = hId.get( key ); + MyriadStream ns = mStore.openStream( iStream ); + __cacheStoreMyriadStore( ns, *pSrc, key ); + } + + virtual void destroy( obtype *pObj, const keytype &key ) + { + int iStream = hId.get( key ); + mStore.deleteStream( iStream ); + hId.erase( key ); + delete pObj; + } + + virtual bool has( const keytype &key ) + { + return hId.has( key ); + } + + virtual Bu::List getKeys() + { + return hId.getKeys(); + } + + virtual int getSize() + { + return hId.getSize(); + } + + private: + Myriad mStore; + typedef Bu::Hash StreamHash; + StreamHash hId; + }; +}; + +#endif diff --git a/src/myriad.cpp b/src/myriad.cpp index 58270c5..77b481d 100644 --- a/src/myriad.cpp +++ b/src/myriad.cpp @@ -34,7 +34,12 @@ Bu::Myriad::Myriad( Bu::Stream &sStore ) : Bu::Myriad::~Myriad() { - updateHeader(); + if( !hActiveBlocks.isEmpty() ) + { + sio << "Bu::Myriad::~Myriad(): Error: There are " + << hActiveBlocks.getSize() << " unsynced blocks!" << sio.nl; + } + sync(); for( StreamArray::iterator i = aStreams.begin(); i; i++ ) { @@ -46,7 +51,13 @@ void Bu::Myriad::sync() { updateHeader(); - // Later, also flush all caches. + for( BlockHash::iterator i = hActiveBlocks.begin(); i; i++ ) + { + if( (*i)->bChanged ) + { + syncBlock( *i ); + } + } } void Bu::Myriad::initialize() @@ -206,16 +217,19 @@ void Bu::Myriad::initialize( int iBlockSize, int iPreAllocate ) this->iBlocks = iPreAllocate; pStr->iSize = sStore.tell(); - sio << "Myriad: Actual end of header stream = " << pStr->iSize << sio.nl; +// sio << "Myriad: Actual end of header stream = " << pStr->iSize << sio.nl; pStr->iSize = iHeaderSize; for( int j = 0; j < iHeaderBlocks; j++ ) { pStr->aBlocks.append( j ); + bsBlockUsed.setBit( j ); } aStreams.append( pStr ); + sio << bsBlockUsed.toString() << sio.nl; + //hStreams.insert( 0, BlockArray( 0 ) ); } @@ -227,31 +241,36 @@ void Bu::Myriad::updateHeader() char cBuf; int iBuf; + for( StreamArray::iterator i = aStreams.begin(); i; i++ ) + { + sio << "Myriad: Stream " << Fmt(4) << (*i)->iId << ": " << (*i)->aBlocks << sio.nl; + } + // Compute the new size of the header. int iHeaderSize = 14 + 8*aStreams.getSize(); - sio << "Myriad: updateHeader: aStreams.getSize() = " << aStreams.getSize() - << sio.nl; +// sio << "Myriad: updateHeader: aStreams.getSize() = " << aStreams.getSize() +// << sio.nl; for( StreamArray::iterator i = aStreams.begin(); i; i++ ) { iHeaderSize += 4*(*i)->aBlocks.getSize(); - sio << "Myriad: updateHeader: (*i)->aBlocks.getSize() = " - << (*i)->aBlocks.getSize() << sio.nl; +// sio << "Myriad: updateHeader: (*i)->aBlocks.getSize() = " +// << (*i)->aBlocks.getSize() << sio.nl; } int iNewBlocks = blkDiv( iHeaderSize, iBlockSize ); while( iNewBlocks > aStreams[0]->aBlocks.getSize() ) { int iBlock = findEmptyBlock(); - sio << "Myriad: updateHeader: Appending block " << iBlock - << " to header." << sio.nl; +// sio << "Myriad: updateHeader: Appending block " << iBlock +// << " to header." << sio.nl; aStreams[0]->aBlocks.append( iBlock ); bsBlockUsed.setBit( iBlock ); iHeaderSize += 4; iNewBlocks = blkDiv( iHeaderSize, iBlockSize ); } aStreams[0]->iSize = iHeaderSize; - sio << "Myriad: updateHeader: iHeaderSize=" << iHeaderSize - << ", iNewBlocks=" << iNewBlocks << ", curBlocks=" - << aStreams[0]->aBlocks.getSize() << sio.nl; +// sio << "Myriad: updateHeader: iHeaderSize=" << iHeaderSize +// << ", iNewBlocks=" << iNewBlocks << ", curBlocks=" +// << aStreams[0]->aBlocks.getSize() << sio.nl; MyriadStream sHdr( *this, aStreams[0] ); sHdr.write( Myriad_MAGIC_CODE, 4 ); @@ -296,7 +315,7 @@ int Bu::Myriad::createStream( int iPreAllocate ) for( int j = 0; j < iPreAllocate; j++ ) { int iFreeBlock = findEmptyBlock(); - sio << "Myriad: Adding block " << iFreeBlock << sio.nl; +// sio << "Myriad: Adding block " << iFreeBlock << sio.nl; pStr->aBlocks.append( iFreeBlock ); bsBlockUsed.setBit( iFreeBlock ); } @@ -311,7 +330,7 @@ int Bu::Myriad::findEmptyBlock() if( bsBlockUsed.getBit( j ) == false ) return j; } - sio << "Myriad: findEmptyBlock(): No empty blocks, adding new one." << sio.nl; +// sio << "Myriad: findEmptyBlock(): No empty blocks, adding new one." << sio.nl; bsBlockUsed.setSize( bsBlockUsed.getSize()+1, false ); sStore.setPos( iBlockSize*iBlocks ); @@ -330,6 +349,7 @@ void Bu::Myriad::deleteStream( int /*iID*/ ) Bu::MyriadStream Bu::Myriad::openStream( int iId ) { + sio << "Myriad: Request to open stream: " << iId << sio.nl; return MyriadStream( *this, findStream( iId ) ); } @@ -361,8 +381,8 @@ Bu::Myriad::Stream *Bu::Myriad::findStream( int iId ) Bu::Myriad::Block *Bu::Myriad::getBlock( int iBlock ) { - sio << "Myriad: Reading block " << iBlock << ", bytes " - << iBlockSize*iBlock << "-" << iBlockSize*(iBlock+1) << sio.nl; +// sio << "Myriad: Reading block " << iBlock << ", bytes " +// << iBlockSize*iBlock << "-" << iBlockSize*(iBlock+1) << sio.nl; Block *pBlock = new Block; pBlock->pData = new char[iBlockSize]; sStore.setPos( iBlockSize * iBlock ); @@ -370,6 +390,8 @@ Bu::Myriad::Block *Bu::Myriad::getBlock( int iBlock ) pBlock->bChanged = false; pBlock->iBlockIndex = iBlock; + hActiveBlocks.insert( iBlock, pBlock ); + return pBlock; } @@ -377,14 +399,21 @@ void Bu::Myriad::releaseBlock( Bu::Myriad::Block *pBlock ) { if( pBlock == NULL ) return; - sio << "Myriad: Releasing block " << pBlock->iBlockIndex << sio.nl; +// sio << "Myriad: Releasing block " << pBlock->iBlockIndex << sio.nl; + syncBlock( pBlock ); + hActiveBlocks.erase( pBlock->iBlockIndex ); + delete[] pBlock->pData; + delete pBlock; +} + +void Bu::Myriad::syncBlock( Block *pBlock ) +{ if( pBlock->bChanged ) { - sio << "Myriad: - Block changed, writing back to stream." << sio.nl; +// sio << "Myriad: - Block changed, writing back to stream." << sio.nl; sStore.setPos( iBlockSize * pBlock->iBlockIndex ); sStore.write( pBlock->pData, iBlockSize ); + pBlock->bChanged = false; } - delete[] pBlock->pData; - delete pBlock; } diff --git a/src/myriad.h b/src/myriad.h index 0344057..8f626a4 100644 --- a/src/myriad.h +++ b/src/myriad.h @@ -12,6 +12,7 @@ #include "bu/bitstring.h" #include "bu/exceptionbase.h" #include "bu/array.h" +#include "bu/hash.h" namespace Bu { @@ -147,6 +148,7 @@ namespace Bu Block *getBlock( int iBlock ); void releaseBlock( Block *pBlock ); + void syncBlock( Block *pBlock ); private: Bu::Stream &sStore; @@ -155,6 +157,8 @@ namespace Bu int iUsed; Bu::BitString bsBlockUsed; StreamArray aStreams; + typedef Bu::Hash BlockHash; + BlockHash hActiveBlocks; }; }; diff --git a/src/tafcomment.cpp b/src/tafcomment.cpp index 4e0da9f..77b7ee4 100644 --- a/src/tafcomment.cpp +++ b/src/tafcomment.cpp @@ -7,6 +7,13 @@ #include "bu/tafcomment.h" +Bu::TafComment::TafComment( const Bu::TafComment &rSrc ) : + TafNode( typeComment ), + sText( rSrc.sText ), + bEOL( rSrc.bEOL ) +{ +} + Bu::TafComment::TafComment( const Bu::FString &sText, bool bEOL ) : TafNode( typeComment ), sText( sText ), diff --git a/src/tafcomment.h b/src/tafcomment.h index d1e200f..5b51f99 100644 --- a/src/tafcomment.h +++ b/src/tafcomment.h @@ -20,6 +20,7 @@ namespace Bu class TafComment : public TafNode { public: + TafComment( const Bu::TafComment &rSrc ); TafComment( const Bu::FString &sText, bool bEOL=false ); virtual ~TafComment(); diff --git a/src/tafgroup.cpp b/src/tafgroup.cpp index 7c1c818..c3f5b1e 100644 --- a/src/tafgroup.cpp +++ b/src/tafgroup.cpp @@ -9,6 +9,29 @@ #include "bu/tafproperty.h" #include "bu/tafcomment.h" +Bu::TafGroup::TafGroup( const TafGroup &rSrc ) : + TafNode( typeGroup ), + sName( rSrc.sName ) +{ + for( NodeList::const_iterator i = rSrc.lChildren.begin(); i; i++ ) + { + switch( (*i)->getType() ) + { + case typeGroup: + addChild( new TafGroup( *dynamic_cast(*i) ) ); + break; + + case typeProperty: + addChild( new TafProperty( *dynamic_cast(*i) ) ); + break; + + case typeComment: + addChild( new TafComment( *dynamic_cast(*i) ) ); + break; + } + } +} + Bu::TafGroup::TafGroup( const Bu::FString &sName ) : TafNode( typeGroup ), sName( sName ) diff --git a/src/tafgroup.h b/src/tafgroup.h index f76e5f9..ed70e8c 100644 --- a/src/tafgroup.h +++ b/src/tafgroup.h @@ -32,6 +32,7 @@ namespace Bu typedef Bu::Hash GroupHash; typedef Bu::List NodeList; + TafGroup( const TafGroup &rSrc ); TafGroup( const Bu::FString &sName ); virtual ~TafGroup(); diff --git a/src/tafproperty.cpp b/src/tafproperty.cpp index 4c7ab28..c847344 100644 --- a/src/tafproperty.cpp +++ b/src/tafproperty.cpp @@ -7,6 +7,13 @@ #include "bu/tafproperty.h" +Bu::TafProperty::TafProperty( const Bu::TafProperty &rSrc ) : + TafNode( typeProperty ), + sName( rSrc.sName ), + sValue( rSrc.sValue ) +{ +} + Bu::TafProperty::TafProperty( const Bu::FString &sName, const Bu::FString &sValue ) : TafNode( typeProperty ), sName( sName ), diff --git a/src/tafproperty.h b/src/tafproperty.h index 7dbeee2..62cc517 100644 --- a/src/tafproperty.h +++ b/src/tafproperty.h @@ -20,6 +20,7 @@ namespace Bu class TafProperty : public TafNode { public: + TafProperty( const Bu::TafProperty &rSrc ); TafProperty( const Bu::FString &sName, const Bu::FString &sValue ); virtual ~TafProperty(); -- cgit v1.2.3