diff options
author | Michael Meeks <michael.meeks@suse.com> | 2012-09-19 15:48:21 +0100 |
---|---|---|
committer | Michael Meeks <michael.meeks@suse.com> | 2012-09-19 15:51:24 +0100 |
commit | e48e48910247335124f0726a7fcadb94556883b6 (patch) | |
tree | 86c2aa22352fda1c1068dac2a8c8319ff6d52f26 /sot | |
parent | fd2e3ff7b79d24a6b44b1e5b878b7b0ac4236b3e (diff) |
sot: substantially accelerate sorted cache write-out
Sort only the pages we want to write out, at the end, using a std::sort
instead of a hand-crafted linked-list mess maintained during use.
Cleanup StgPage as well, de-friend it from StgCache, clean member names.
Remove unused pCache member as well.
Change-Id: I0f53d1f85be373fce0d504b226d34ccaf575b2b3
Diffstat (limited to 'sot')
-rw-r--r-- | sot/source/sdstor/stgcache.cxx | 117 | ||||
-rw-r--r-- | sot/source/sdstor/stgcache.hxx | 48 | ||||
-rw-r--r-- | sot/source/sdstor/stgstrms.cxx | 6 |
3 files changed, 71 insertions, 100 deletions
diff --git a/sot/source/sdstor/stgcache.cxx b/sot/source/sdstor/stgcache.cxx index dd0b17f9bd32..ac628266d720 100644 --- a/sot/source/sdstor/stgcache.cxx +++ b/sot/source/sdstor/stgcache.cxx @@ -17,7 +17,6 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ - #include <string.h> #include <osl/endian.h> #include <tools/string.hxx> @@ -37,34 +36,40 @@ // a page buffer, even if a read fails. It is up to the caller to determine // the correctness of the I/O. -StgPage::StgPage( StgCache* p, short n ) +StgPage::StgPage( short nSize, sal_Int32 nPage ) + : mnPage( nPage ) + , mpData( new sal_uInt8[ nSize ] ) + , mnSize( nSize ) + , mbDirty( false ) { - OSL_ENSURE( n >= 512, "Unexpected page size is provided!" ); - pCache = p; - nData = n; - bDirty = sal_False; - nPage = 0; - pData = new sal_uInt8[ nData ]; - pNext2 = pLast2 = NULL; + OSL_ENSURE( mnSize >= 512, "Unexpected page size is provided!" ); + // We will write this data to a permanant file later + // best to clear if first. + memset( mpData, 0, mnSize ); } StgPage::~StgPage() { - delete [] pData; + delete [] mpData; } void StgPage::SetPage( short nOff, sal_Int32 nVal ) { - if( ( nOff < (short) ( nData / sizeof( sal_Int32 ) ) ) && nOff >= 0 ) + if( ( nOff < (short) ( mnSize / sizeof( sal_Int32 ) ) ) && nOff >= 0 ) { #ifdef OSL_BIGENDIAN - nVal = OSL_SWAPDWORD(nVal); + nVal = OSL_SWAPDWORD(nVal); #endif - ((sal_Int32*) pData )[ nOff ] = nVal; - bDirty = sal_True; + ((sal_Int32*) mpData )[ nOff ] = nVal; + mbDirty = true; } } +bool StgPage::IsPageGreater( const StgPage *pA, const StgPage *pB ) +{ + return pA->mnPage < pB->mnPage; +} + //////////////////////////////// class StgCache //////////////////////////// // The disk cache holds the cached sectors. The sector type differ according @@ -81,7 +86,6 @@ StgCache::StgCache() { nRef = 0; pStrm = NULL; - pElem1 = NULL; nPageSize = 512; nError = SVSTREAM_OK; bMyStream = sal_False; @@ -112,32 +116,10 @@ void StgCache::SetPhysPageSize( short n ) StgPage* StgCache::Create( sal_Int32 nPg ) { - StgPage* pElem = new StgPage( this, nPageSize ); - pElem->nPage = nPg; - // For data security, clear the buffer contents - memset( pElem->pData, 0, pElem->nData ); + StgPage* pElem = new StgPage( nPageSize, nPg ); - maLRUCache[pElem->nPage] = pElem; + maLRUCache[pElem->GetPage()] = pElem; - // insert to Sorted - if( !pElem1 ) - pElem1 = pElem->pNext2 = pElem->pLast2 = pElem; - else - { - StgPage* p = pElem1; - do - { - if( pElem->nPage < p->nPage ) - break; - p = p->pNext2; - } while( p != pElem1 ); - pElem->pNext2 = p; - pElem->pLast2 = p->pLast2; - pElem->pNext2->pLast2 = - pElem->pLast2->pNext2 = pElem; - if( p->nPage < pElem1->nPage ) - pElem1 = pElem; - } return pElem; } @@ -148,12 +130,7 @@ void StgCache::Erase( StgPage* pElem ) OSL_ENSURE( pElem, "The pointer should not be NULL!" ); if ( pElem ) { - maLRUCache.erase( pElem->nPage ); - // remove from Sorted - pElem->pNext2->pLast2 = pElem->pLast2; - pElem->pLast2->pNext2 = pElem->pNext2; - if( pElem1 == pElem ) - pElem1 = ( pElem->pNext2 == pElem ) ? NULL : pElem->pNext2; + maLRUCache.erase( pElem->GetPage() ); delete pElem; } } @@ -162,15 +139,6 @@ void StgCache::Erase( StgPage* pElem ) void StgCache::Clear() { - StgPage *pElem = pElem1; - if( pElem ) do - { - StgPage* pDelete = pElem; - pElem = pElem->pNext2; - delete pDelete; - } - while( pElem != pElem1 ); - pElem1 = NULL; maLRUCache.clear(); } @@ -197,7 +165,7 @@ StgPage* StgCache::Get( sal_Int32 nPage, sal_Bool bForce ) if( !p ) { p = Create( nPage ); - if( !Read( nPage, p->pData, 1 ) && bForce ) + if( !Read( nPage, p->GetData(), 1 ) && bForce ) { Erase( p ); p = NULL; @@ -222,32 +190,39 @@ StgPage* StgCache::Copy( sal_Int32 nNew, sal_Int32 nOld ) StgPage* q = Get( nOld, sal_True ); if( q ) { - OSL_ENSURE( p->nData == q->nData, "Unexpected page size!" ); - memcpy( p->pData, q->pData, p->nData ); + OSL_ENSURE( p->GetSize() == q->GetSize(), "Unexpected page size!" ); + memcpy( p->GetData(), q->GetData(), p->GetSize() ); } } - p->SetDirty(); + p->SetDirty( true ); return p; } -// Flush the cache whose owner is given. NULL flushes all. - +// Historically this wrote pages in a sorted, ascending order; +// continue that tradition. sal_Bool StgCache::Commit() { - StgPage* p = pElem1; - if( p ) do + std::vector< StgPage * > aToWrite; + for ( IndexToStgPage::iterator aIt = maLRUCache.begin(); + aIt != maLRUCache.end(); aIt++ ) { - if( p->bDirty ) - { - sal_Bool b = Write( p->nPage, p->pData, 1 ); - if( !b ) - return sal_False; - p->bDirty = sal_False; - } - p = p->pNext2; - } while( p != pElem1 ); + if ( aIt->second->IsDirty() ) + aToWrite.push_back( aIt->second ); + } + + std::sort( aToWrite.begin(), aToWrite.end(), StgPage::IsPageGreater ); + for (std::vector< StgPage * >::iterator aWr = aToWrite.begin(); + aWr != aToWrite.end(); aWr++) + { + StgPage *pPage = *aWr; + if ( !Write( pPage->GetPage(), pPage->GetData(), 1 ) ) + return sal_False; + pPage->SetDirty( false ); + } + pStrm->Flush(); SetError( pStrm->GetError() ); + return sal_True; } diff --git a/sot/source/sdstor/stgcache.hxx b/sot/source/sdstor/stgcache.hxx index dc1d88d2c240..d556c5997590 100644 --- a/sot/source/sdstor/stgcache.hxx +++ b/sot/source/sdstor/stgcache.hxx @@ -40,24 +40,20 @@ typedef boost::unordered_map > IndexToStgPage; class StgCache { - StgPage* pCur; // top of LRU list - StgPage* pElem1; // top of ordered list - sal_uLong nError; // error code - sal_Int32 nPages; // size of data area in pages - sal_uInt16 nRef; // reference count + sal_uLong nError; // error code + sal_Int32 nPages; // size of data area in pages + sal_uInt16 nRef; // reference count IndexToStgPage maLRUCache; // hash of index to cached pages short nPageSize; // page size of the file UCBStorageStream* pStorageStream; // holds reference to UCB storage stream void Erase( StgPage* ); // delete a cache element - void InsertToLRU( StgPage* ); // insert into LRU list - void InsertToOrdered( StgPage* ); // insert into ordered list - StgPage* Create( sal_Int32 ); // create a cached page + StgPage* Create( sal_Int32 ); // create a cached page protected: SvStream* pStrm; // physical stream - sal_Bool bMyStream; // sal_True: delete stream in dtor - sal_Bool bFile; // sal_True: file stream - sal_Int32 Page2Pos( sal_Int32 ); // page address --> file position + sal_Bool bMyStream; // sal_True: delete stream in dtor + sal_Bool bFile; // sal_True: file stream + sal_Int32 Page2Pos( sal_Int32 ); // page address --> file position public: StgCache(); ~StgCache(); @@ -89,27 +85,26 @@ public: }; class StgPage { - friend class StgCache; - StgCache* pCache; // the cache - StgPage *pNext2, *pLast2; // ordered chain - sal_Int32 nPage; // page # - sal_uInt8* pData; // nPageSize characters - short nData; // size of this page - sal_Bool bDirty; // dirty flag - StgPage( StgCache*, short ); - ~StgPage(); + const sal_Int32 mnPage; // page index + sal_uInt8* mpData; // nSize bytes + short mnSize; // size of this page + bool mbDirty; // dirty flag public: - void SetDirty() { bDirty = sal_True; } - sal_Int32 GetPage() { return nPage; } - void* GetData() { return pData; } - short GetSize() { return nData; } + StgPage( short nData, sal_Int32 nPage ); + ~StgPage(); + + sal_Int32 GetPage() { return mnPage; } + void* GetData() { return mpData; } + short GetSize() { return mnSize; } + bool IsDirty() { return mbDirty; } + void SetDirty( bool bDirty ) { mbDirty = bDirty; } // routines for accessing FAT pages // Assume that the data is a FAT page and get/put FAT data. sal_Int32 GetPage( short nOff ) { - if( ( nOff >= (short) ( nData / sizeof( sal_Int32 ) ) ) || nOff < 0 ) + if( ( nOff >= (short) ( mnSize / sizeof( sal_Int32 ) ) ) || nOff < 0 ) return -1; - sal_Int32 n = ((sal_Int32*) pData )[ nOff ]; + sal_Int32 n = ((sal_Int32*) mpData )[ nOff ]; #ifdef OSL_BIGENDIAN return OSL_SWAPDWORD(n); #else @@ -117,6 +112,7 @@ public: #endif } void SetPage( short, sal_Int32 ); // put an element + static bool IsPageGreater( const StgPage *pA, const StgPage *pB ); }; #endif diff --git a/sot/source/sdstor/stgstrms.cxx b/sot/source/sdstor/stgstrms.cxx index feb90c4ad2eb..af9aef1eae5c 100644 --- a/sot/source/sdstor/stgstrms.cxx +++ b/sot/source/sdstor/stgstrms.cxx @@ -869,7 +869,7 @@ void* StgDataStrm::GetPtr( sal_Int32 Pos, sal_Bool bForce, sal_Bool bDirty ) if (pPg && nOffset < pPg->GetSize()) { if( bDirty ) - pPg->SetDirty(); + pPg->SetDirty( true ); return ((sal_uInt8 *)pPg->GetData()) + nOffset; } } @@ -964,7 +964,7 @@ sal_Int32 StgDataStrm::Write( const void* pBuf, sal_Int32 n ) { // data is present, so use the cached data memcpy( pPg->GetData(), p, nBytes ); - pPg->SetDirty(); + pPg->SetDirty( true ); nRes = nBytes; } else @@ -978,7 +978,7 @@ sal_Int32 StgDataStrm::Write( const void* pBuf, sal_Int32 n ) if( !pPg ) break; memcpy( (sal_uInt8*)pPg->GetData() + nOffset, p, nBytes ); - pPg->SetDirty(); + pPg->SetDirty( true ); nRes = nBytes; } nDone += nRes; |