[Libreoffice-commits] .: sot/source

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Wed Sep 19 07:51:34 PDT 2012


 sot/source/sdstor/stgcache.cxx |  117 ++++++++++++++++-------------------------
 sot/source/sdstor/stgcache.hxx |   48 +++++++---------
 sot/source/sdstor/stgstrms.cxx |    6 +-
 3 files changed, 71 insertions(+), 100 deletions(-)

New commits:
commit e48e48910247335124f0726a7fcadb94556883b6
Author: Michael Meeks <michael.meeks at suse.com>
Date:   Wed Sep 19 15:48:21 2012 +0100

    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

diff --git a/sot/source/sdstor/stgcache.cxx b/sot/source/sdstor/stgcache.cxx
index dd0b17f..ac62826 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 dc1d88d..d556c59 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 feb90c4..af9aef1 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;


More information about the Libreoffice-commits mailing list