LCOV - code coverage report
Current view: top level - sot/source/sdstor - stgcache.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 191 238 80.3 %
Date: 2012-08-25 Functions: 23 25 92.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 87 150 58.0 %

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*
       3                 :            :  * This file is part of the LibreOffice project.
       4                 :            :  *
       5                 :            :  * This Source Code Form is subject to the terms of the Mozilla Public
       6                 :            :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7                 :            :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8                 :            :  *
       9                 :            :  * This file incorporates work covered by the following license notice:
      10                 :            :  *
      11                 :            :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12                 :            :  *   contributor license agreements. See the NOTICE file distributed
      13                 :            :  *   with this work for additional information regarding copyright
      14                 :            :  *   ownership. The ASF licenses this file to you under the Apache
      15                 :            :  *   License, Version 2.0 (the "License"); you may not use this file
      16                 :            :  *   except in compliance with the License. You may obtain a copy of
      17                 :            :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18                 :            :  */
      19                 :            : 
      20                 :            : 
      21                 :            : #if defined(_MSC_VER) && (_MSC_VER<1200)
      22                 :            : #include <tools/presys.h>
      23                 :            : #endif
      24                 :            : #include <boost/unordered_map.hpp>
      25                 :            : #if defined(_MSC_VER) && (_MSC_VER<1200)
      26                 :            : #include <tools/postsys.h>
      27                 :            : #endif
      28                 :            : 
      29                 :            : #include <string.h>
      30                 :            : #include <osl/endian.h>
      31                 :            : #include <tools/string.hxx>
      32                 :            : 
      33                 :            : #include "sot/stg.hxx"
      34                 :            : #include "stgelem.hxx"
      35                 :            : #include "stgcache.hxx"
      36                 :            : #include "stgstrms.hxx"
      37                 :            : #include "stgdir.hxx"
      38                 :            : #include "stgio.hxx"
      39                 :            : 
      40                 :            : /*************************************************************************/
      41                 :            : //-----------------------------------------------------------------------------
      42                 :            : typedef boost::unordered_map
      43                 :            : <
      44                 :            :     sal_Int32,
      45                 :            :     StgPage *,
      46                 :            :     boost::hash< sal_Int32 >,
      47                 :            :     std::equal_to< sal_Int32 >
      48                 :            : > UsrStgPagePtr_Impl;
      49                 :            : #ifdef _MSC_VER
      50                 :            : #pragma warning( disable: 4786 )
      51                 :            : #endif
      52                 :            : 
      53                 :            : //#define   CHECK_DIRTY 1
      54                 :            : //#define   READ_AFTER_WRITE 1
      55                 :            : 
      56                 :            : ////////////////////////////// class StgPage /////////////////////////////
      57                 :            : // This class implements buffer functionality. The cache will always return
      58                 :            : // a page buffer, even if a read fails. It is up to the caller to determine
      59                 :            : // the correctness of the I/O.
      60                 :            : 
      61                 :      10567 : StgPage::StgPage( StgCache* p, short n )
      62                 :            : {
      63                 :            :     OSL_ENSURE( n >= 512, "Unexpected page size is provided!" );
      64                 :      10567 :     pCache = p;
      65                 :      10567 :     nData  = n;
      66                 :      10567 :     bDirty = sal_False;
      67                 :      10567 :     nPage  = 0;
      68                 :      10567 :     pData  = new sal_uInt8[ nData ];
      69                 :            :     pNext1 =
      70                 :            :     pNext2 =
      71                 :            :     pLast1 =
      72                 :      10567 :     pLast2 = NULL;
      73                 :      10567 :     pOwner = NULL;
      74                 :      10567 : }
      75                 :            : 
      76                 :      10483 : StgPage::~StgPage()
      77                 :            : {
      78         [ +  - ]:      10483 :     delete [] pData;
      79                 :      10483 : }
      80                 :            : 
      81                 :      48331 : void StgPage::SetPage( short nOff, sal_Int32 nVal )
      82                 :            : {
      83 [ +  - ][ +  - ]:      48331 :     if( ( nOff < (short) ( nData / sizeof( sal_Int32 ) ) ) && nOff >= 0 )
      84                 :            :     {
      85                 :            : #ifdef OSL_BIGENDIAN
      86                 :            :       nVal = OSL_SWAPDWORD(nVal);
      87                 :            : #endif
      88                 :      48331 :         ((sal_Int32*) pData )[ nOff ] = nVal;
      89                 :      48331 :         bDirty = sal_True;
      90                 :            :     }
      91                 :      48331 : }
      92                 :            : 
      93                 :            : //////////////////////////////// class StgCache ////////////////////////////
      94                 :            : 
      95                 :            : // The disk cache holds the cached sectors. The sector type differ according
      96                 :            : // to their purpose.
      97                 :            : 
      98                 :        376 : sal_Int32 lcl_GetPageCount( sal_uLong nFileSize, short nPageSize )
      99                 :            : {
     100                 :            : //    return (nFileSize >= 512) ? (nFileSize - 512) / nPageSize : 0;
     101                 :            :     // #i61980# reallife: last page may be incomplete, return number of *started* pages
     102         [ +  + ]:        376 :     return (nFileSize >= 512) ? (nFileSize - 512 + nPageSize - 1) / nPageSize : 0;
     103                 :            : }
     104                 :            : 
     105                 :        375 : StgCache::StgCache()
     106                 :            : {
     107                 :        375 :     nRef = 0;
     108                 :        375 :     pStrm = NULL;
     109                 :        375 :     pCur = pElem1 = NULL;
     110                 :        375 :     nPageSize = 512;
     111                 :        375 :     nError = SVSTREAM_OK;
     112                 :        375 :     bMyStream = sal_False;
     113                 :        375 :     bFile = sal_False;
     114                 :        375 :     pLRUCache = NULL;
     115                 :        375 :     pStorageStream = NULL;
     116                 :        375 : }
     117                 :            : 
     118                 :        369 : StgCache::~StgCache()
     119                 :            : {
     120                 :        369 :     Clear();
     121                 :        369 :     SetStrm( NULL, sal_False );
     122         [ -  + ]:        369 :     delete (UsrStgPagePtr_Impl*)pLRUCache;
     123                 :        369 : }
     124                 :            : 
     125                 :        367 : void StgCache::SetPhysPageSize( short n )
     126                 :            : {
     127                 :            :     OSL_ENSURE( n >= 512, "Unexpecte page size is provided!" );
     128         [ +  - ]:        367 :     if ( n >= 512 )
     129                 :            :     {
     130                 :        367 :         nPageSize = n;
     131                 :        367 :         sal_uLong nPos = pStrm->Tell();
     132                 :        367 :         sal_uLong nFileSize = pStrm->Seek( STREAM_SEEK_TO_END );
     133                 :        367 :         nPages = lcl_GetPageCount( nFileSize, nPageSize );
     134                 :        367 :         pStrm->Seek( nPos );
     135                 :            :     }
     136                 :        367 : }
     137                 :            : 
     138                 :            : // Create a new cache element
     139                 :            : // pCur points to this element
     140                 :            : 
     141                 :      10567 : StgPage* StgCache::Create( sal_Int32 nPg )
     142                 :            : {
     143         [ +  - ]:      10567 :     StgPage* pElem = new StgPage( this, nPageSize );
     144                 :      10567 :     pElem->nPage = nPg;
     145                 :            :     // For data security, clear the buffer contents
     146                 :      10567 :     memset( pElem->pData, 0, pElem->nData );
     147                 :            : 
     148                 :            :     // insert to LRU
     149         [ +  + ]:      10567 :     if( pCur )
     150                 :            :     {
     151                 :      10200 :         pElem->pNext1 = pCur;
     152                 :      10200 :         pElem->pLast1 = pCur->pLast1;
     153                 :            :         pElem->pNext1->pLast1 =
     154                 :      10200 :         pElem->pLast1->pNext1 = pElem;
     155                 :            :     }
     156                 :            :     else
     157                 :        367 :         pElem->pNext1 = pElem->pLast1 = pElem;
     158         [ +  + ]:      10567 :     if( !pLRUCache )
     159 [ +  - ][ +  - ]:        367 :         pLRUCache = new UsrStgPagePtr_Impl();
     160                 :      10567 :     (*(UsrStgPagePtr_Impl*)pLRUCache)[pElem->nPage] = pElem;
     161                 :      10567 :     pCur = pElem;
     162                 :            : 
     163                 :            :     // insert to Sorted
     164         [ +  + ]:      10567 :     if( !pElem1 )
     165                 :        367 :         pElem1 = pElem->pNext2 = pElem->pLast2 = pElem;
     166                 :            :     else
     167                 :            :     {
     168                 :      10200 :         StgPage* p = pElem1;
     169         [ +  + ]:     114158 :         do
     170                 :            :         {
     171         [ +  + ]:     121394 :             if( pElem->nPage < p->nPage )
     172                 :       7236 :                 break;
     173                 :     114158 :             p = p->pNext2;
     174                 :            :         } while( p != pElem1 );
     175                 :      10200 :         pElem->pNext2 = p;
     176                 :      10200 :         pElem->pLast2 = p->pLast2;
     177                 :            :         pElem->pNext2->pLast2 =
     178                 :      10200 :         pElem->pLast2->pNext2 = pElem;
     179         [ -  + ]:      10200 :         if( p->nPage < pElem1->nPage )
     180                 :          0 :             pElem1 = pElem;
     181                 :            :     }
     182                 :      10567 :     return pElem;
     183                 :            : }
     184                 :            : 
     185                 :            : // Delete the given element
     186                 :            : 
     187                 :          0 : void StgCache::Erase( StgPage* pElem )
     188                 :            : {
     189                 :            :     OSL_ENSURE( pElem, "The pointer should not be NULL!" );
     190         [ #  # ]:          0 :     if ( pElem )
     191                 :            :     {
     192                 :            :         OSL_ENSURE( pElem->pNext1 && pElem->pLast1, "The pointers may not be NULL!" );
     193                 :            :         //remove from LRU
     194                 :          0 :         pElem->pNext1->pLast1 = pElem->pLast1;
     195                 :          0 :         pElem->pLast1->pNext1 = pElem->pNext1;
     196         [ #  # ]:          0 :         if( pCur == pElem )
     197         [ #  # ]:          0 :             pCur = ( pElem->pNext1 == pElem ) ? NULL : pElem->pNext1;
     198         [ #  # ]:          0 :         if( pLRUCache )
     199                 :          0 :             ((UsrStgPagePtr_Impl*)pLRUCache)->erase( pElem->nPage );
     200                 :            :         // remove from Sorted
     201                 :          0 :         pElem->pNext2->pLast2 = pElem->pLast2;
     202                 :          0 :         pElem->pLast2->pNext2 = pElem->pNext2;
     203         [ #  # ]:          0 :         if( pElem1 == pElem )
     204         [ #  # ]:          0 :             pElem1 = ( pElem->pNext2 == pElem ) ? NULL : pElem->pNext2;
     205         [ #  # ]:          0 :         delete pElem;
     206                 :            :     }
     207                 :          0 : }
     208                 :            : 
     209                 :            : // remove all cache elements without flushing them
     210                 :            : 
     211                 :        369 : void StgCache::Clear()
     212                 :            : {
     213                 :        369 :     StgPage* pElem = pCur;
     214 [ +  + ][ +  + ]:      10852 :     if( pCur ) do
     215                 :            :     {
     216                 :      10483 :         StgPage* pDelete = pElem;
     217                 :      10483 :         pElem = pElem->pNext1;
     218         [ +  - ]:      10483 :         delete pDelete;
     219                 :            :     }
     220                 :            :     while( pCur != pElem );
     221                 :        369 :     pCur = NULL;
     222                 :        369 :     pElem1 = NULL;
     223         [ +  + ]:        369 :     delete (UsrStgPagePtr_Impl*)pLRUCache;
     224                 :        369 :     pLRUCache = NULL;
     225                 :        369 : }
     226                 :            : 
     227                 :            : // Look for a cached page
     228                 :            : 
     229                 :    2346983 : StgPage* StgCache::Find( sal_Int32 nPage )
     230                 :            : {
     231         [ +  + ]:    2346983 :     if( !pLRUCache )
     232                 :        367 :         return NULL;
     233         [ +  - ]:    2346616 :     UsrStgPagePtr_Impl::iterator aIt = ((UsrStgPagePtr_Impl*)pLRUCache)->find( nPage );
     234 [ +  - ][ +  + ]:    2346616 :     if( aIt != ((UsrStgPagePtr_Impl*)pLRUCache)->end() )
     235                 :            :     {
     236                 :            :         // page found
     237         [ +  - ]:    2320237 :         StgPage* pFound = (*aIt).second;
     238                 :            :         OSL_ENSURE( pFound, "The pointer may not be NULL!" );
     239                 :            : 
     240         [ +  + ]:    2320237 :         if( pFound != pCur )
     241                 :            :         {
     242                 :            :             OSL_ENSURE( pFound->pNext1 && pFound->pLast1, "The pointers may not be NULL!" );
     243                 :            :             // remove from LRU
     244                 :     581074 :             pFound->pNext1->pLast1 = pFound->pLast1;
     245                 :     581074 :             pFound->pLast1->pNext1 = pFound->pNext1;
     246                 :            :             // insert to LRU
     247                 :     581074 :             pFound->pNext1 = pCur;
     248                 :     581074 :             pFound->pLast1 = pCur->pLast1;
     249                 :            :             pFound->pNext1->pLast1 =
     250                 :     581074 :             pFound->pLast1->pNext1 = pFound;
     251                 :            :         }
     252                 :    2320237 :         return pFound;
     253                 :            :     }
     254                 :    2346983 :     return NULL;
     255                 :            : }
     256                 :            : 
     257                 :            : // Load a page into the cache
     258                 :            : 
     259                 :    2328342 : StgPage* StgCache::Get( sal_Int32 nPage, sal_Bool bForce )
     260                 :            : {
     261                 :    2328342 :     StgPage* p = Find( nPage );
     262         [ +  + ]:    2328342 :     if( !p )
     263                 :            :     {
     264                 :       8388 :         p = Create( nPage );
     265 [ -  + ][ -  + ]:       8388 :         if( !Read( nPage, p->pData, 1 ) && bForce )
                 [ +  + ]
     266                 :            :         {
     267                 :          0 :             Erase( p );
     268                 :          0 :             p = NULL;
     269                 :          0 :             SetError( SVSTREAM_READ_ERROR );
     270                 :            :         }
     271                 :            :     }
     272                 :    2328342 :     return p;
     273                 :            : }
     274                 :            : 
     275                 :            : // Copy an existing page into a new page. Use this routine
     276                 :            : // to duplicate an existing stream or to create new entries.
     277                 :            : // The new page is initially marked dirty. No owner is copied.
     278                 :            : 
     279                 :       2245 : StgPage* StgCache::Copy( sal_Int32 nNew, sal_Int32 nOld )
     280                 :            : {
     281                 :       2245 :     StgPage* p = Find( nNew );
     282         [ +  + ]:       2245 :     if( !p )
     283                 :       2179 :         p = Create( nNew );
     284         [ -  + ]:       2245 :     if( nOld >= 0 )
     285                 :            :     {
     286                 :            :         // old page: we must have this data!
     287                 :          0 :         StgPage* q = Get( nOld, sal_True );
     288         [ #  # ]:          0 :         if( q )
     289                 :            :         {
     290                 :            :             OSL_ENSURE( p->nData == q->nData, "Unexpected page size!" );
     291                 :          0 :             memcpy( p->pData, q->pData, p->nData );
     292                 :            :         }
     293                 :            :     }
     294                 :       2245 :     p->SetDirty();
     295                 :       2245 :     return p;
     296                 :            : }
     297                 :            : 
     298                 :            : // Flush the cache whose owner is given. NULL flushes all.
     299                 :            : 
     300                 :        159 : sal_Bool StgCache::Commit()
     301                 :            : {
     302                 :        159 :     StgPage* p = pElem1;
     303 [ +  - ][ +  + ]:       2738 :     if( p ) do
     304                 :            :     {
     305         [ +  + ]:       2588 :         if( p->bDirty )
     306                 :            :         {
     307                 :       2423 :             sal_Bool b = Write( p->nPage, p->pData, 1 );
     308         [ +  + ]:       2423 :             if( !b )
     309                 :          9 :                 return sal_False;
     310                 :       2414 :             p->bDirty = sal_False;
     311                 :            :         }
     312                 :       2579 :         p = p->pNext2;
     313                 :            :     } while( p != pElem1 );
     314                 :        150 :     pStrm->Flush();
     315                 :        150 :     SetError( pStrm->GetError() );
     316                 :            : #ifdef CHECK_DIRTY
     317                 :            :     p = pElem1;
     318                 :            :     if( p ) do
     319                 :            :     {
     320                 :            :         if( p->bDirty )
     321                 :            :         {
     322                 :            :             ErrorBox( NULL, WB_OK, String("SO2: Dirty Block in Ordered List") ).Execute();
     323                 :            :             sal_Bool b = Write( p->nPage, p->pData, 1 );
     324                 :            :             if( !b )
     325                 :            :                 return sal_False;
     326                 :            :             p->bDirty = sal_False;
     327                 :            :         }
     328                 :            :         p = p->pNext2;
     329                 :            :     } while( p != pElem1 );
     330                 :            :     p = pElem1;
     331                 :            :     if( p ) do
     332                 :            :     {
     333                 :            :         if( p->bDirty )
     334                 :            :         {
     335                 :            :             ErrorBox( NULL, WB_OK, String("SO2: Dirty Block in LRU List") ).Execute();
     336                 :            :             sal_Bool b = Write( p->nPage, p->pData, 1 );
     337                 :            :             if( !b )
     338                 :            :                 return sal_False;
     339                 :            :             p->bDirty = sal_False;
     340                 :            :         }
     341                 :            :         p = p->pNext1;
     342                 :            :     } while( p != pElem1 );
     343                 :            : #endif
     344                 :        159 :     return sal_True;
     345                 :            : }
     346                 :            : 
     347                 :            : // Set a stream
     348                 :            : 
     349                 :        744 : void StgCache::SetStrm( SvStream* p, sal_Bool bMy )
     350                 :            : {
     351         [ -  + ]:        744 :     if( pStorageStream )
     352                 :            :     {
     353                 :          0 :         pStorageStream->ReleaseRef();
     354                 :          0 :         pStorageStream = NULL;
     355                 :            :     }
     356                 :            : 
     357         [ +  + ]:        744 :     if( bMyStream )
     358         [ +  - ]:          9 :         delete pStrm;
     359                 :        744 :     pStrm = p;
     360                 :        744 :     bMyStream = bMy;
     361                 :        744 : }
     362                 :            : 
     363                 :          0 : void StgCache::SetStrm( UCBStorageStream* pStgStream )
     364                 :            : {
     365         [ #  # ]:          0 :     if( pStorageStream )
     366                 :          0 :         pStorageStream->ReleaseRef();
     367                 :          0 :     pStorageStream = pStgStream;
     368                 :            : 
     369         [ #  # ]:          0 :     if( bMyStream )
     370         [ #  # ]:          0 :         delete pStrm;
     371                 :            : 
     372                 :          0 :     pStrm = NULL;
     373                 :            : 
     374         [ #  # ]:          0 :     if ( pStorageStream )
     375                 :            :     {
     376                 :          0 :         pStorageStream->AddRef();
     377                 :          0 :         pStrm = pStorageStream->GetModifySvStream();
     378                 :            :     }
     379                 :            : 
     380                 :          0 :     bMyStream = sal_False;
     381                 :          0 : }
     382                 :            : 
     383                 :            : // Open/close the disk file
     384                 :            : 
     385                 :          9 : sal_Bool StgCache::Open( const String& rName, StreamMode nMode )
     386                 :            : {
     387                 :            :     // do not open in exclusive mode!
     388         [ -  + ]:          9 :     if( nMode & STREAM_SHARE_DENYALL )
     389                 :          0 :         nMode = ( ( nMode & ~STREAM_SHARE_DENYALL ) | STREAM_SHARE_DENYWRITE );
     390         [ +  - ]:          9 :     SvFileStream* pFileStrm = new SvFileStream( rName, nMode );
     391                 :            :     // SvStream "Feature" Write Open auch erfolgreich, wenns nicht klappt
     392                 :          9 :     sal_Bool bAccessDenied = sal_False;
     393 [ -  + ][ #  # ]:          9 :     if( ( nMode & STREAM_WRITE ) && !pFileStrm->IsWritable() )
                 [ -  + ]
     394                 :            :     {
     395                 :          0 :         pFileStrm->Close();
     396                 :          0 :         bAccessDenied = sal_True;
     397                 :            :     }
     398                 :          9 :     SetStrm( pFileStrm, sal_True );
     399         [ +  - ]:          9 :     if( pFileStrm->IsOpen() )
     400                 :            :     {
     401                 :          9 :         sal_uLong nFileSize = pStrm->Seek( STREAM_SEEK_TO_END );
     402                 :          9 :         nPages = lcl_GetPageCount( nFileSize, nPageSize );
     403                 :          9 :         pStrm->Seek( 0L );
     404                 :            :     }
     405                 :            :     else
     406                 :          0 :         nPages = 0;
     407                 :          9 :     bFile = sal_True;
     408         [ +  - ]:          9 :     SetError( bAccessDenied ? ERRCODE_IO_ACCESSDENIED : pStrm->GetError() );
     409                 :          9 :     return Good();
     410                 :            : }
     411                 :            : 
     412                 :        366 : void StgCache::Close()
     413                 :            : {
     414         [ -  + ]:        366 :     if( bFile )
     415                 :            :     {
     416                 :          0 :         ((SvFileStream*) pStrm)->Close();
     417                 :          0 :         SetError( pStrm->GetError() );
     418                 :            :     }
     419                 :        366 : }
     420                 :            : 
     421                 :            : // low level I/O
     422                 :            : 
     423                 :      22491 : sal_Bool StgCache::Read( sal_Int32 nPage, void* pBuf, sal_Int32 nPg )
     424                 :            : {
     425         [ +  + ]:      22491 :     if( Good() )
     426                 :            :     {
     427                 :            :         /*  #i73846# real life: a storage may refer to a page one-behind the
     428                 :            :             last valid page (see document attached to the issue). In that case
     429                 :            :             (if nPage==nPages), just do nothing here and let the caller work on
     430                 :            :             the empty zero-filled buffer. */
     431         [ -  + ]:      22473 :         if ( nPage > nPages )
     432                 :          0 :             SetError( SVSTREAM_READ_ERROR );
     433         [ +  - ]:      22473 :         else if ( nPage < nPages )
     434                 :            :         {
     435                 :      22473 :             sal_uLong nPos = Page2Pos( nPage );
     436         [ -  + ]:      22473 :             sal_Int32 nPg2 = ( ( nPage + nPg ) > nPages ) ? nPages - nPage : nPg;
     437                 :      22473 :             sal_uLong nBytes = nPg2 * nPageSize;
     438                 :            :             // fixed address and size for the header
     439         [ -  + ]:      22473 :             if( nPage == -1 )
     440                 :            :             {
     441                 :          0 :                 nPos = 0L, nBytes = 512;
     442                 :          0 :                 nPg2 = nPg;
     443                 :            :             }
     444         [ +  + ]:      22473 :             if( pStrm->Tell() != nPos )
     445                 :            :             {
     446                 :       5895 :                 if( pStrm->Seek( nPos ) != nPos ) {
     447                 :            :     #ifdef CHECK_DIRTY
     448                 :            :                     ErrorBox( NULL, WB_OK, String("SO2: Seek failed") ).Execute();
     449                 :            :     #endif
     450                 :            :                 }
     451                 :            :             }
     452                 :      22473 :             pStrm->Read( pBuf, nBytes );
     453         [ -  + ]:      22473 :             if ( nPg != nPg2 )
     454                 :          0 :                 SetError( SVSTREAM_READ_ERROR );
     455                 :            :             else
     456                 :      22473 :                 SetError( pStrm->GetError() );
     457                 :            :         }
     458                 :            :     }
     459                 :      22491 :     return Good();
     460                 :            : }
     461                 :            : 
     462                 :       4499 : sal_Bool StgCache::Write( sal_Int32 nPage, void* pBuf, sal_Int32 nPg )
     463                 :            : {
     464         [ +  - ]:       4499 :     if( Good() )
     465                 :            :     {
     466                 :       4499 :         sal_uLong nPos = Page2Pos( nPage );
     467                 :       4499 :         sal_uLong nBytes = 0;
     468         [ +  - ]:       4499 :         if ( SAL_MAX_INT32 / nPg > nPageSize )
     469                 :       4499 :             nBytes = nPg * nPageSize;
     470                 :            : 
     471                 :            :         // fixed address and size for the header
     472                 :            :         // nPageSize must be >= 512, otherwise the header can not be written here, we check it on import
     473         [ -  + ]:       4499 :         if( nPage == -1 )
     474                 :          0 :             nPos = 0L, nBytes = 512;
     475         [ +  + ]:       4499 :         if( pStrm->Tell() != nPos )
     476                 :            :         {
     477                 :        398 :             if( pStrm->Seek( nPos ) != nPos ) {
     478                 :            : #ifdef CHECK_DIRTY
     479                 :            :                 ErrorBox( NULL, WB_OK, String("SO2: Seek failed") ).Execute();
     480                 :            : #endif
     481                 :            :             }
     482                 :            :         }
     483                 :       4499 :         sal_uLong nRes = pStrm->Write( pBuf, nBytes );
     484         [ -  + ]:       4499 :         if( nRes != nBytes )
     485                 :          0 :             SetError( SVSTREAM_WRITE_ERROR );
     486                 :            :         else
     487                 :       4499 :             SetError( pStrm->GetError() );
     488                 :            : #ifdef READ_AFTER_WRITE
     489                 :            :         sal_uInt8 cBuf[ 512 ];
     490                 :            :         pStrm->Flush();
     491                 :            :         pStrm->Seek( nPos );
     492                 :            :         sal_Bool bRes = ( pStrm->Read( cBuf, 512 ) == 512 );
     493                 :            :         if( bRes )
     494                 :            :             bRes = !memcmp( cBuf, pBuf, 512 );
     495                 :            :         if( !bRes )
     496                 :            :         {
     497                 :            :             ErrorBox( NULL, WB_OK, String("SO2: Read after Write failed") ).Execute();
     498                 :            :             pStrm->SetError( SVSTREAM_WRITE_ERROR );
     499                 :            :         }
     500                 :            : #endif
     501                 :            :     }
     502                 :       4499 :     return Good();
     503                 :            : }
     504                 :            : 
     505                 :            : // set the file size in pages
     506                 :            : 
     507                 :       1966 : sal_Bool StgCache::SetSize( sal_Int32 n )
     508                 :            : {
     509                 :            :     // Add the file header
     510                 :       1966 :     sal_Int32 nSize = n * nPageSize + 512;
     511                 :       1966 :     pStrm->SetStreamSize( nSize );
     512                 :       1966 :     SetError( pStrm->GetError() );
     513         [ +  - ]:       1966 :     if( !nError )
     514                 :       1966 :         nPages = n;
     515                 :       1966 :     return Good();
     516                 :            : }
     517                 :            : 
     518                 :      31905 : void StgCache::SetError( sal_uLong n )
     519                 :            : {
     520 [ +  + ][ +  + ]:      31905 :     if( n && !nError )
     521                 :        145 :         nError = n;
     522                 :      31905 : }
     523                 :            : 
     524                 :        861 : void StgCache::ResetError()
     525                 :            : {
     526                 :        861 :     nError = SVSTREAM_OK;
     527                 :        861 :     pStrm->ResetError();
     528                 :        861 : }
     529                 :            : 
     530                 :    2253765 : void StgCache::MoveError( StorageBase& r )
     531                 :            : {
     532         [ +  + ]:    2253765 :     if( nError != SVSTREAM_OK )
     533                 :            :     {
     534                 :        145 :         r.SetError( nError );
     535                 :        145 :         ResetError();
     536                 :            :     }
     537                 :    2253765 : }
     538                 :            : 
     539                 :            : // Utility functions
     540                 :            : 
     541                 :      26972 : sal_Int32 StgCache::Page2Pos( sal_Int32 nPage )
     542                 :            : {
     543         [ -  + ]:      26972 :     if( nPage < 0 ) nPage = 0;
     544                 :      26972 :     return( nPage * nPageSize ) + nPageSize;
     545                 :            : }
     546                 :            : 
     547                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10