summaryrefslogtreecommitdiff
path: root/sot
diff options
context:
space:
mode:
authorMichael Meeks <michael.meeks@suse.com>2012-09-19 15:48:21 +0100
committerMichael Meeks <michael.meeks@suse.com>2012-09-19 15:51:24 +0100
commite48e48910247335124f0726a7fcadb94556883b6 (patch)
tree86c2aa22352fda1c1068dac2a8c8319ff6d52f26 /sot
parentfd2e3ff7b79d24a6b44b1e5b878b7b0ac4236b3e (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.cxx117
-rw-r--r--sot/source/sdstor/stgcache.hxx48
-rw-r--r--sot/source/sdstor/stgstrms.cxx6
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;