LCOV - code coverage report
Current view: top level - store/source - storbios.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 282 395 71.4 %
Date: 2012-08-25 Functions: 45 51 88.2 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 137 302 45.4 %

           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                 :            : #include "storbios.hxx"
      22                 :            : 
      23                 :            : #include "sal/types.h"
      24                 :            : #include "sal/macros.h"
      25                 :            : 
      26                 :            : #include "rtl/alloc.h"
      27                 :            : #include "rtl/ref.hxx"
      28                 :            : 
      29                 :            : #include "osl/diagnose.h"
      30                 :            : #include "osl/mutex.hxx"
      31                 :            : 
      32                 :            : #include "store/types.h"
      33                 :            : #include "object.hxx"
      34                 :            : #include "lockbyte.hxx"
      35                 :            : #include "storcach.hxx"
      36                 :            : 
      37                 :            : using namespace store;
      38                 :            : 
      39                 :            : /*========================================================================
      40                 :            :  *
      41                 :            :  * OStoreSuperBlock.
      42                 :            :  *
      43                 :            :  *======================================================================*/
      44                 :            : #define STORE_MAGIC_SUPERBLOCK sal_uInt32(0x484D5343)
      45                 :            : 
      46                 :            : struct OStoreSuperBlock
      47                 :            : {
      48                 :            :     typedef OStorePageGuard      G;
      49                 :            :     typedef OStorePageDescriptor D;
      50                 :            :     typedef OStorePageLink       L;
      51                 :            : 
      52                 :            :     /** Representation.
      53                 :            :      */
      54                 :            :     G          m_aGuard;
      55                 :            :     D          m_aDescr;
      56                 :            :     sal_uInt32 m_nMarked;
      57                 :            :     L          m_aMarked;
      58                 :            :     sal_uInt32 m_nUnused;
      59                 :            :     L          m_aUnused;
      60                 :            : 
      61                 :            :     /** theSize.
      62                 :            :      */
      63                 :            :     static const size_t theSize = sizeof(G) + sizeof(D) + 2 * (sizeof(L) + sizeof(sal_uInt32));
      64                 :            : 
      65                 :            :     /** Construction.
      66                 :            :      */
      67                 :      35588 :     explicit OStoreSuperBlock (sal_uInt16 nPageSize)
      68                 :            :         : m_aGuard  (STORE_MAGIC_SUPERBLOCK),
      69                 :            :           m_aDescr  (nPageSize, nPageSize, STORE_MINIMUM_PAGESIZE),
      70                 :      35588 :           m_nMarked (store::htonl(0)),
      71                 :            :           m_aMarked (0),
      72                 :      35588 :           m_nUnused (store::htonl(0)),
      73                 :     106764 :           m_aUnused (0)
      74                 :      35588 :     {}
      75                 :            : 
      76                 :            :     OStoreSuperBlock (const OStoreSuperBlock & rhs)
      77                 :            :         : m_aGuard  (rhs.m_aGuard),
      78                 :            :           m_aDescr  (rhs.m_aDescr),
      79                 :            :           m_nMarked (rhs.m_nMarked),
      80                 :            :           m_aMarked (rhs.m_aMarked),
      81                 :            :           m_nUnused (rhs.m_nUnused),
      82                 :            :           m_aUnused (rhs.m_aUnused)
      83                 :            :     {}
      84                 :            : 
      85                 :      30403 :     OStoreSuperBlock& operator= (const OStoreSuperBlock & rhs)
      86                 :            :     {
      87                 :      30403 :         m_aGuard  = rhs.m_aGuard;
      88                 :      30403 :         m_aDescr  = rhs.m_aDescr;
      89                 :      30403 :         m_nMarked = rhs.m_nMarked;
      90                 :      30403 :         m_aMarked = rhs.m_aMarked;
      91                 :      30403 :         m_nUnused = rhs.m_nUnused;
      92                 :      30403 :         m_aUnused = rhs.m_aUnused;
      93                 :      30403 :         return *this;
      94                 :            :     }
      95                 :            : 
      96                 :            :     /** Comparison.
      97                 :            :      */
      98                 :     159662 :     sal_Bool operator== (const OStoreSuperBlock & rhs) const
      99                 :            :     {
     100                 :     159662 :         return ((m_aGuard  == rhs.m_aGuard ) &&
     101                 :     159662 :                 (m_aDescr  == rhs.m_aDescr ) &&
     102                 :            :                 (m_nMarked == rhs.m_nMarked) &&
     103                 :     159662 :                 (m_aMarked == rhs.m_aMarked) &&
     104                 :            :                 (m_nUnused == rhs.m_nUnused) &&
     105   [ +  -  +  - ]:     478986 :                 (m_aUnused == rhs.m_aUnused)    );
         [ +  - ][ +  - ]
           [ +  -  +  - ]
     106                 :            :     }
     107                 :            : 
     108                 :            :     /** unused(Count|Head|Insert|Remove|Reset).
     109                 :            :      */
     110                 :      24152 :     sal_uInt32 unusedCount (void) const
     111                 :            :     {
     112                 :      24152 :         return store::ntohl(m_nUnused);
     113                 :            :     }
     114                 :     148522 :     const L& unusedHead (void) const
     115                 :            :     {
     116                 :     148522 :         return m_aUnused;
     117                 :            :     }
     118                 :      12087 :     void unusedInsert (const L& rLink)
     119                 :            :     {
     120                 :      12087 :         sal_uInt32 nUnused = unusedCount();
     121                 :      12087 :         m_nUnused = store::htonl(nUnused + 1);
     122                 :      12087 :         m_aUnused = rLink;
     123                 :      12087 :     }
     124                 :      12065 :     void unusedRemove (const L& rLink)
     125                 :            :     {
     126                 :      12065 :         sal_uInt32 nUnused = unusedCount();
     127                 :      12065 :         m_nUnused = store::htonl(nUnused - 1);
     128                 :      12065 :         m_aUnused = rLink;
     129                 :      12065 :     }
     130                 :          0 :     void unusedReset (void)
     131                 :            :     {
     132                 :          0 :         m_nUnused = store::htonl(0);
     133                 :          0 :         m_aUnused = L(0);
     134                 :          0 :     }
     135                 :            : 
     136                 :            :     /** guard (external representation).
     137                 :            :      */
     138                 :      30403 :     void guard()
     139                 :            :     {
     140                 :      30403 :         sal_uInt32 nCRC32 = 0;
     141                 :      30403 :         nCRC32 = rtl_crc32 (nCRC32, &m_aGuard.m_nMagic, sizeof(sal_uInt32));
     142                 :      30403 :         nCRC32 = rtl_crc32 (nCRC32, &m_aDescr, theSize - sizeof(G));
     143                 :      30403 :         m_aGuard.m_nCRC32 = store::htonl(nCRC32);
     144                 :      30403 :     }
     145                 :            : 
     146                 :            :     /** verify (external representation).
     147                 :            :      */
     148                 :     320122 :     storeError verify() const
     149                 :            :     {
     150                 :     320122 :         sal_uInt32 nMagic = store::ntohl(m_aGuard.m_nMagic);
     151         [ +  + ]:     320122 :         if (nMagic != STORE_MAGIC_SUPERBLOCK)
     152                 :        798 :             return store_E_WrongFormat;
     153                 :            : 
     154                 :     319324 :         sal_uInt32 nCRC32 = 0;
     155                 :     319324 :         nCRC32 = rtl_crc32 (nCRC32, &m_aGuard.m_nMagic, sizeof(sal_uInt32));
     156                 :     319324 :         nCRC32 = rtl_crc32 (nCRC32, &m_aDescr, theSize - sizeof(G));
     157         [ -  + ]:     319324 :         if (m_aGuard.m_nCRC32 != store::htonl(nCRC32))
     158                 :          0 :             return store_E_InvalidChecksum;
     159                 :            :         else
     160                 :     320122 :             return store_E_None;
     161                 :            :     }
     162                 :            : };
     163                 :            : 
     164                 :            : /*========================================================================
     165                 :            :  *
     166                 :            :  * SuperBlockPage interface.
     167                 :            :  *
     168                 :            :  *======================================================================*/
     169                 :            : namespace store
     170                 :            : {
     171                 :            : 
     172                 :            : struct SuperBlockPage
     173                 :            : {
     174                 :            :     typedef OStoreSuperBlock SuperBlock;
     175                 :            : 
     176                 :            :     /** Representation.
     177                 :            :      */
     178                 :            :     SuperBlock m_aSuperOne;
     179                 :            :     SuperBlock m_aSuperTwo;
     180                 :            : 
     181                 :            :     /** theSize.
     182                 :            :      */
     183                 :            :     static const size_t     theSize     = 2 * SuperBlock::theSize;
     184                 :            :     static const sal_uInt16 thePageSize = theSize;
     185                 :            :     STORE_STATIC_ASSERT(STORE_MINIMUM_PAGESIZE >= thePageSize);
     186                 :            : 
     187                 :            :     /** Allocation.
     188                 :            :      */
     189                 :      11543 :     static void * operator new (size_t n) SAL_THROW(())
     190                 :            :     {
     191                 :      11543 :         return rtl_allocateMemory (sal::static_int_cast<sal_Size>(n));
     192                 :            :     }
     193                 :      51880 :     static void operator delete (void * p) SAL_THROW(())
     194                 :            :     {
     195                 :      51880 :         rtl_freeMemory (p);
     196                 :      51880 :     }
     197                 :            : 
     198                 :       6251 :     static void * operator new (SAL_UNUSED_PARAMETER size_t, sal_uInt16 nPageSize) SAL_THROW(())
     199                 :            :     {
     200                 :       6251 :         return rtl_allocateZeroMemory (sal::static_int_cast<sal_Size>(nPageSize));
     201                 :            :     }
     202                 :            :     static void operator delete (void * p, SAL_UNUSED_PARAMETER sal_uInt16) SAL_THROW(())
     203                 :            :     {
     204                 :            :         rtl_freeMemory (p);
     205                 :            :     }
     206                 :            : 
     207                 :            :     /** Construction.
     208                 :            :      */
     209                 :      17794 :     explicit SuperBlockPage (sal_uInt16 nPageSize = thePageSize)
     210                 :            :         : m_aSuperOne(nPageSize),
     211                 :      17794 :           m_aSuperTwo(nPageSize)
     212                 :      17794 :     {}
     213                 :            : 
     214                 :            :     /** save.
     215                 :            :      */
     216                 :      30403 :     storeError save (OStorePageBIOS & rBIOS, sal_uInt32 nSize = theSize)
     217                 :            :     {
     218                 :      30403 :         m_aSuperOne.guard();
     219                 :      30403 :         m_aSuperTwo = m_aSuperOne;
     220                 :      30403 :         return rBIOS.write (0, this, nSize);
     221                 :            :     }
     222                 :            : 
     223                 :            :     /** Page allocation.
     224                 :            :      */
     225                 :            :     storeError unusedHead (
     226                 :            :         OStorePageBIOS & rBIOS,
     227                 :            :         PageData &       rPageHead);
     228                 :            : 
     229                 :            :     storeError unusedPop (
     230                 :            :         OStorePageBIOS & rBIOS,
     231                 :            :         PageData const & rPageHead);
     232                 :            : 
     233                 :            :     storeError unusedPush (
     234                 :            :         OStorePageBIOS & rBIOS,
     235                 :            :         sal_uInt32       nAddr);
     236                 :            : 
     237                 :            :     /** verify (with repair).
     238                 :            :      */
     239                 :            :     storeError verify (OStorePageBIOS & rBIOS);
     240                 :            : };
     241                 :            : 
     242                 :            : } // namespace store
     243                 :            : 
     244                 :            : /*========================================================================
     245                 :            :  *
     246                 :            :  * SuperBlockPage implementation.
     247                 :            :  *
     248                 :            :  *======================================================================*/
     249                 :            : /*
     250                 :            :  * unusedHead(): get freelist head (alloc page, step 1).
     251                 :            :  */
     252                 :     136435 : storeError SuperBlockPage::unusedHead (OStorePageBIOS & rBIOS, PageData & rPageHead)
     253                 :            : {
     254         [ +  - ]:     136435 :     storeError eErrCode = verify (rBIOS);
     255         [ -  + ]:     136435 :     if (eErrCode != store_E_None)
     256                 :          0 :         return eErrCode;
     257                 :            : 
     258                 :            :     // Check freelist head.
     259                 :     136435 :     OStorePageLink const aListHead (m_aSuperOne.unusedHead());
     260         [ +  + ]:     136435 :     if (aListHead.location() == 0)
     261                 :            :     {
     262                 :            :         // Freelist empty, see SuperBlock::ctor().
     263                 :     124370 :         rPageHead.location (STORE_PAGE_NULL);
     264                 :     124370 :         return store_E_None;
     265                 :            :     }
     266                 :            : 
     267                 :            :     // Load PageHead.
     268         [ +  - ]:      12065 :     eErrCode = rBIOS.read (aListHead.location(), &rPageHead, PageData::theSize);
     269         [ -  + ]:      12065 :     if (eErrCode != store_E_None)
     270                 :          0 :         return eErrCode;
     271                 :            : 
     272                 :      12065 :     eErrCode = rPageHead.verify (aListHead.location());
     273         [ -  + ]:      12065 :     if (eErrCode != store_E_None)
     274                 :          0 :         return eErrCode;
     275                 :            : 
     276                 :            :     // Verify page is unused.
     277                 :      12065 :     sal_uInt32 const nAddr = rPageHead.m_aUnused.location();
     278                 :            :     OSL_POSTCOND(nAddr != STORE_PAGE_NULL, "store::SuperBlock::unusedHead(): page not free");
     279         [ -  + ]:      12065 :     if (nAddr == STORE_PAGE_NULL)
     280                 :            :     {
     281                 :            :         // Page in use.
     282                 :          0 :         rPageHead.location (STORE_PAGE_NULL);
     283                 :            : 
     284                 :            :         // Recovery: Reset freelist to empty.
     285                 :          0 :         m_aSuperOne.unusedReset();
     286         [ #  # ]:          0 :         eErrCode = save (rBIOS);
     287                 :            :     }
     288                 :     136435 :     return eErrCode;
     289                 :            : }
     290                 :            : 
     291                 :            : /*
     292                 :            :  * unusedPop(): pop freelist head (alloc page, step 2).
     293                 :            :  */
     294                 :      12065 : storeError SuperBlockPage::unusedPop (OStorePageBIOS & rBIOS, PageData const & rPageHead)
     295                 :            : {
     296                 :      12065 :     sal_uInt32 const nAddr = rPageHead.m_aUnused.location();
     297                 :            :     OSL_PRECOND(nAddr != STORE_PAGE_NULL, "store::SuperBlock::unusedPop(): page not free");
     298         [ -  + ]:      12065 :     if (nAddr == STORE_PAGE_NULL)
     299                 :          0 :         return store_E_CantSeek;
     300                 :            : 
     301                 :            :     // Pop from FreeList.
     302                 :      12065 :     OStorePageLink const aListHead (nAddr);
     303                 :      12065 :     m_aSuperOne.unusedRemove (aListHead);
     304         [ +  - ]:      12065 :     return save (rBIOS);
     305                 :            : }
     306                 :            : 
     307                 :            : /*
     308                 :            :  * unusedPush(): push new freelist head.
     309                 :            :  */
     310                 :      12087 : storeError SuperBlockPage::unusedPush (OStorePageBIOS & rBIOS, sal_uInt32 nAddr)
     311                 :            : {
     312         [ +  - ]:      12087 :     storeError eErrCode = verify (rBIOS);
     313         [ -  + ]:      12087 :     if (eErrCode != store_E_None)
     314                 :          0 :         return eErrCode;
     315                 :            : 
     316                 :      12087 :     PageData aPageHead;
     317         [ +  - ]:      12087 :     eErrCode = rBIOS.read (nAddr, &aPageHead, PageData::theSize);
     318         [ -  + ]:      12087 :     if (eErrCode != store_E_None)
     319                 :          0 :         return eErrCode;
     320                 :            : 
     321                 :      12087 :     eErrCode = aPageHead.verify (nAddr);
     322         [ -  + ]:      12087 :     if (eErrCode != store_E_None)
     323                 :          0 :         return eErrCode;
     324                 :            : 
     325                 :      12087 :     aPageHead.m_aUnused = m_aSuperOne.unusedHead();
     326                 :      12087 :     aPageHead.guard (nAddr);
     327                 :            : 
     328         [ +  - ]:      12087 :     eErrCode = rBIOS.write (nAddr, &aPageHead, PageData::theSize);
     329         [ -  + ]:      12087 :     if (eErrCode != store_E_None)
     330                 :          0 :         return eErrCode;
     331                 :            : 
     332                 :      12087 :     OStorePageLink const aListHead (nAddr);
     333                 :      12087 :     m_aSuperOne.unusedInsert(aListHead);
     334         [ +  - ]:      12087 :     return save (rBIOS);
     335                 :            : }
     336                 :            : 
     337                 :            : /*
     338                 :            :  * verify (with repair).
     339                 :            :  */
     340                 :     160061 : storeError SuperBlockPage::verify (OStorePageBIOS & rBIOS)
     341                 :            : {
     342                 :            :     // Verify 1st copy.
     343                 :     160061 :     storeError eErrCode = m_aSuperOne.verify();
     344         [ +  + ]:     160061 :     if (eErrCode == store_E_None)
     345                 :            :     {
     346                 :            :         // Ok. Verify 2nd copy.
     347                 :     159662 :         eErrCode = m_aSuperTwo.verify();
     348         [ +  - ]:     159662 :         if (eErrCode == store_E_None)
     349                 :            :         {
     350                 :            :             // Ok. Ensure identical copies (1st copy wins).
     351         [ -  + ]:     159662 :             if (!(m_aSuperOne == m_aSuperTwo))
     352                 :            :             {
     353                 :            :                 // Different. Replace 2nd copy with 1st copy.
     354                 :          0 :                 m_aSuperTwo = m_aSuperOne;
     355                 :            : 
     356                 :            :                 // Write back.
     357         [ #  # ]:          0 :                 if (rBIOS.isWriteable())
     358                 :          0 :                     eErrCode = rBIOS.write (0, this, theSize);
     359                 :            :                 else
     360                 :          0 :                     eErrCode = store_E_None;
     361                 :            :             }
     362                 :            :         }
     363                 :            :         else
     364                 :            :         {
     365                 :            :             // Failure. Replace 2nd copy with 1st copy.
     366                 :          0 :             m_aSuperTwo = m_aSuperOne;
     367                 :            : 
     368                 :            :             // Write back.
     369         [ #  # ]:          0 :             if (rBIOS.isWriteable())
     370                 :          0 :                 eErrCode = rBIOS.write (0, this, theSize);
     371                 :            :             else
     372                 :          0 :                 eErrCode = store_E_None;
     373                 :            :         }
     374                 :            :     }
     375                 :            :     else
     376                 :            :     {
     377                 :            :         // Failure. Verify 2nd copy.
     378                 :        399 :         eErrCode = m_aSuperTwo.verify();
     379         [ -  + ]:        399 :         if (eErrCode == store_E_None)
     380                 :            :         {
     381                 :            :             // Ok. Replace 1st copy with 2nd copy.
     382                 :          0 :             m_aSuperOne = m_aSuperTwo;
     383                 :            : 
     384                 :            :             // Write back.
     385         [ #  # ]:          0 :             if (rBIOS.isWriteable())
     386                 :          0 :                 eErrCode = rBIOS.write (0, this, theSize);
     387                 :            :             else
     388                 :          0 :                 eErrCode = store_E_None;
     389                 :            :         }
     390                 :            :         else
     391                 :            :         {
     392                 :            :             // Double Failure.
     393                 :            :             OSL_TRACE("OStoreSuperBlockPage::verify(): double failure.");
     394                 :            :         }
     395                 :            :     }
     396                 :            : 
     397                 :            :     // Done.
     398                 :     160061 :     return eErrCode;
     399                 :            : }
     400                 :            : 
     401                 :            : /*========================================================================
     402                 :            :  *
     403                 :            :  * OStorePageBIOS::Ace implementation.
     404                 :            :  *
     405                 :            :  *======================================================================*/
     406                 :      17794 : OStorePageBIOS::Ace::Ace()
     407                 :      17794 :   : m_next (this), m_prev (this), m_addr (STORE_PAGE_NULL), m_used (0)
     408                 :      17794 : {}
     409                 :            : 
     410                 :      17043 : OStorePageBIOS::Ace::~Ace()
     411                 :            : {
     412                 :      17043 :   m_next->m_prev = m_prev, m_prev->m_next = m_next;
     413                 :      17043 : }
     414                 :            : 
     415                 :            : int
     416                 :     169554 : SAL_CALL OStorePageBIOS::Ace::constructor (
     417                 :            :     void * obj, SAL_UNUSED_PARAMETER void * /* arg */)
     418                 :            : {
     419                 :     169554 :   Ace * ace = static_cast<Ace*>(obj);
     420                 :     169554 :   ace->m_next = ace->m_prev = ace;
     421                 :     169554 :   return 1;
     422                 :            : }
     423                 :            : 
     424                 :            : OStorePageBIOS::Ace *
     425                 :    2397970 : OStorePageBIOS::Ace::find (OStorePageBIOS::Ace * head, sal_uInt32 addr)
     426                 :            : {
     427                 :            :   OStorePageBIOS::Ace * entry;
     428         [ +  + ]:    4885638 :   for (entry = head->m_next; entry != head; entry = entry->m_next)
     429                 :            :   {
     430         [ +  + ]:    3686653 :     if (entry->m_addr >= addr)
     431                 :    1198985 :       return entry;
     432                 :            :   }
     433                 :    2397970 :   return head;
     434                 :            : }
     435                 :            : 
     436                 :            : void
     437                 :    1198985 : OStorePageBIOS::Ace::insert (OStorePageBIOS::Ace * head, OStorePageBIOS::Ace * entry)
     438                 :            : {
     439                 :            :   // insert entry at queue tail (before head).
     440                 :    1198985 :   entry->m_next = head;
     441                 :    1198985 :   entry->m_prev = head->m_prev;
     442                 :    1198985 :   head->m_prev = entry;
     443                 :    1198985 :   entry->m_prev->m_next = entry;
     444                 :    1198985 : }
     445                 :            : 
     446                 :            : /*========================================================================
     447                 :            :  *
     448                 :            :  * OStorePageBIOS::AceCache interface.
     449                 :            :  *
     450                 :            :  *======================================================================*/
     451                 :            : namespace store
     452                 :            : {
     453                 :            : 
     454                 :            : class OStorePageBIOS::AceCache
     455                 :            : {
     456                 :            :   rtl_cache_type * m_ace_cache;
     457                 :            : 
     458                 :            : public:
     459                 :            :   static AceCache & get();
     460                 :            : 
     461                 :            :   OStorePageBIOS::Ace *
     462                 :            :   create (sal_uInt32 addr, sal_uInt32 used = 1);
     463                 :            : 
     464                 :            :   void
     465                 :            :   destroy (OStorePageBIOS::Ace * ace);
     466                 :            : 
     467                 :            : protected:
     468                 :            :   AceCache();
     469                 :            :   ~AceCache();
     470                 :            : };
     471                 :            : 
     472                 :            : } // namespace store
     473                 :            : 
     474                 :            : /*========================================================================
     475                 :            :  *
     476                 :            :  * OStorePageBIOS::AceCache implementation.
     477                 :            :  *
     478                 :            :  *======================================================================*/
     479                 :            : extern "C"  typedef  int (SAL_CALL * ace_constructor_type)(void*,void*);
     480                 :            : 
     481                 :            : OStorePageBIOS::AceCache &
     482                 :    2397970 : OStorePageBIOS::AceCache::get()
     483                 :            : {
     484 [ +  + ][ +  - ]:    2397970 :   static AceCache g_ace_cache;
     485                 :    2397970 :   return g_ace_cache;
     486                 :            : }
     487                 :            : 
     488                 :        960 : OStorePageBIOS::AceCache::AceCache()
     489                 :            : {
     490                 :            :   m_ace_cache = rtl_cache_create (
     491                 :            :     "store_ace_cache",
     492                 :            :     sizeof (OStorePageBIOS::Ace),
     493                 :            :     0, // objalign
     494                 :            :    reinterpret_cast<ace_constructor_type>( OStorePageBIOS::Ace::constructor),
     495                 :            :     0, // destructor,
     496                 :            :     0, // reclaim,
     497                 :            :     0, // userarg,
     498                 :            :     0, // default source,
     499                 :            :     0  // flags
     500                 :        960 :     );
     501                 :        960 : }
     502                 :            : 
     503                 :        960 : OStorePageBIOS::AceCache::~AceCache()
     504                 :            : {
     505                 :        960 :   rtl_cache_destroy (m_ace_cache), m_ace_cache = 0;
     506                 :        960 : }
     507                 :            : 
     508                 :            : OStorePageBIOS::Ace *
     509                 :    1198985 : OStorePageBIOS::AceCache::create (sal_uInt32 addr, sal_uInt32 used)
     510                 :            : {
     511                 :    1198985 :   Ace * ace = static_cast<Ace*>(rtl_cache_alloc (m_ace_cache));
     512         [ +  - ]:    1198985 :   if (ace != 0)
     513                 :            :   {
     514                 :            :     // verify invariant state.
     515                 :            :     OSL_ASSERT((ace->m_next == ace) && (ace->m_prev == ace));
     516                 :            : 
     517                 :            :     // initialize.
     518                 :    1198985 :     ace->m_addr = addr;
     519                 :    1198985 :     ace->m_used = used;
     520                 :            :   }
     521                 :    1198985 :   return ace;
     522                 :            : }
     523                 :            : 
     524                 :            : void
     525                 :    1198985 : OStorePageBIOS::AceCache::destroy (OStorePageBIOS::Ace * ace)
     526                 :            : {
     527         [ +  - ]:    1198985 :   if (ace != 0)
     528                 :            :   {
     529                 :            :     // remove from queue (if any).
     530                 :    1198985 :     ace->m_next->m_prev = ace->m_prev, ace->m_prev->m_next = ace->m_next;
     531                 :            : 
     532                 :            :     // restore invariant state.
     533                 :    1198985 :     ace->m_next = ace->m_prev = ace;
     534                 :            : 
     535                 :            :     // return to cache.
     536                 :    1198985 :     rtl_cache_free (m_ace_cache, ace);
     537                 :            :   }
     538                 :    1198985 : }
     539                 :            : 
     540                 :            : /*========================================================================
     541                 :            :  *
     542                 :            :  * OStorePageBIOS implementation.
     543                 :            :  *
     544                 :            :  *======================================================================*/
     545                 :            : /*
     546                 :            :  * OStorePageBIOS.
     547                 :            :  */
     548                 :      17794 : OStorePageBIOS::OStorePageBIOS (void)
     549                 :            :     : m_xLockBytes (NULL),
     550                 :            :       m_pSuper     (NULL),
     551 [ +  - ][ +  - ]:      17794 :       m_bWriteable (false)
     552                 :            : {
     553                 :      17794 : }
     554                 :            : 
     555                 :            : /*
     556                 :            :  * ~OStorePageBIOS.
     557                 :            :  */
     558 [ +  - ][ +  - ]:      17043 : OStorePageBIOS::~OStorePageBIOS (void)
         [ +  - ][ +  - ]
     559                 :            : {
     560         [ +  - ]:      17043 :     cleanup_Impl();
     561         [ -  + ]:      17043 : }
     562                 :            : 
     563                 :            : /*
     564                 :            :  * initialize.
     565                 :            :  * Precond: none.
     566                 :            :  */
     567                 :      17794 : storeError OStorePageBIOS::initialize (
     568                 :            :     ILockBytes *    pLockBytes,
     569                 :            :     storeAccessMode eAccessMode,
     570                 :            :     sal_uInt16 &    rnPageSize)
     571                 :            : {
     572                 :            :     // Acquire exclusive access.
     573         [ +  - ]:      17794 :     osl::MutexGuard aGuard (m_aMutex);
     574                 :            : 
     575                 :            :     // Initialize.
     576         [ +  - ]:      17794 :     storeError eErrCode = initialize_Impl (pLockBytes, eAccessMode, rnPageSize);
     577         [ +  + ]:      17794 :     if (eErrCode != store_E_None)
     578                 :            :     {
     579                 :            :         // Cleanup.
     580         [ +  - ]:        403 :         cleanup_Impl();
     581                 :            :     }
     582         [ +  - ]:      17794 :     return eErrCode;
     583                 :            : }
     584                 :            : 
     585                 :            : /*
     586                 :            :  * initialize_Impl.
     587                 :            :  * Internal: Precond: exclusive access.
     588                 :            :  */
     589                 :      17794 : storeError OStorePageBIOS::initialize_Impl (
     590                 :            :     ILockBytes *    pLockBytes,
     591                 :            :     storeAccessMode eAccessMode,
     592                 :            :     sal_uInt16 &    rnPageSize)
     593                 :            : {
     594                 :            :     // Cleanup.
     595                 :      17794 :     cleanup_Impl();
     596                 :            : 
     597                 :            :     // Initialize.
     598                 :      17794 :     m_xLockBytes = pLockBytes;
     599         [ -  + ]:      17794 :     if (!m_xLockBytes.is())
     600                 :          0 :         return store_E_InvalidParameter;
     601                 :      17794 :     m_bWriteable = (eAccessMode != store_AccessReadOnly);
     602                 :            : 
     603                 :            :     // Check access mode.
     604                 :      17794 :     storeError eErrCode = store_E_None;
     605         [ +  + ]:      17794 :     if (eAccessMode != store_AccessCreate)
     606                 :            :     {
     607                 :            :         // Load SuperBlock page.
     608         [ -  + ]:      11543 :         if ((m_pSuper = new SuperBlockPage()) == 0)
     609                 :          0 :             return store_E_OutOfMemory;
     610                 :            : 
     611                 :      11543 :         eErrCode = read (0, m_pSuper, SuperBlockPage::theSize);
     612         [ +  + ]:      11543 :         if (eErrCode == store_E_None)
     613                 :            :         {
     614                 :            :             // Verify SuperBlock page (with repair).
     615                 :      11539 :             eErrCode = m_pSuper->verify (*this);
     616                 :            :         }
     617                 :            :     }
     618                 :            :     else
     619                 :            :     {
     620                 :            :         // Truncate to zero length.
     621                 :       6251 :         eErrCode = m_xLockBytes->setSize(0);
     622         [ -  + ]:       6251 :         if (eErrCode != store_E_None)
     623                 :          0 :             return eErrCode;
     624                 :            : 
     625                 :            :         // Mark as not existing.
     626                 :       6251 :         eErrCode = store_E_NotExists;
     627                 :            :     }
     628                 :            : 
     629         [ +  + ]:      17794 :     if (eErrCode != store_E_None)
     630                 :            :     {
     631                 :            :         // Check reason.
     632         [ +  + ]:       6654 :         if (eErrCode != store_E_NotExists)
     633                 :        399 :             return eErrCode;
     634                 :            : 
     635                 :            :         // Check mode.
     636         [ +  + ]:       6255 :         if (eAccessMode == store_AccessReadOnly)
     637                 :          4 :             return store_E_NotExists;
     638         [ -  + ]:       6251 :         if (eAccessMode == store_AccessReadWrite)
     639                 :          0 :             return store_E_NotExists;
     640                 :            : 
     641                 :            :         // Check PageSize.
     642 [ +  - ][ -  + ]:       6251 :         if ((STORE_MINIMUM_PAGESIZE > rnPageSize) || (rnPageSize > STORE_MAXIMUM_PAGESIZE))
     643                 :          0 :             return store_E_InvalidParameter;
     644                 :       6251 :         rnPageSize = ((rnPageSize + STORE_MINIMUM_PAGESIZE - 1) & ~(STORE_MINIMUM_PAGESIZE - 1));
     645                 :            : 
     646                 :            :         // Create initial page (w/ SuperBlock).
     647         [ -  + ]:       6251 :         if ((m_pSuper = new(rnPageSize) SuperBlockPage(rnPageSize)) == 0)
     648                 :          0 :             return store_E_OutOfMemory;
     649                 :       6251 :         eErrCode = m_pSuper->save (*this, rnPageSize);
     650                 :            :     }
     651         [ +  - ]:      17391 :     if (eErrCode == store_E_None)
     652                 :            :     {
     653                 :            :         // Obtain page size.
     654                 :      17391 :         rnPageSize = store::ntohs(m_pSuper->m_aSuperOne.m_aDescr.m_nSize);
     655                 :            : 
     656                 :            :         // Create page allocator.
     657                 :      17391 :         eErrCode = m_xLockBytes->initialize (m_xAllocator, rnPageSize);
     658         [ -  + ]:      17391 :         if (eErrCode != store_E_None)
     659                 :          0 :             return eErrCode;
     660                 :            : 
     661                 :            :         // Create page cache.
     662                 :      17391 :         eErrCode = PageCache_createInstance (m_xCache, rnPageSize);
     663                 :            :     }
     664                 :      17794 :     return eErrCode;
     665                 :            : }
     666                 :            : 
     667                 :            : /*
     668                 :            :  * cleanup_Impl.
     669                 :            :  * Internal: Precond: exclusive access.
     670                 :            :  */
     671                 :      51880 : void OStorePageBIOS::cleanup_Impl()
     672                 :            : {
     673                 :            :     // Check referer count.
     674         [ -  + ]:      51880 :     if (m_ace_head.m_used > 0)
     675                 :            :     {
     676                 :            :         // Report remaining referer count.
     677                 :            :         OSL_TRACE("store::PageBIOS::cleanup_Impl(): referer count: %d", m_ace_head.m_used);
     678         [ #  # ]:          0 :         for (Ace * ace = m_ace_head.m_next; ace != &m_ace_head; ace = m_ace_head.m_next)
     679                 :            :         {
     680                 :          0 :             m_ace_head.m_used -= ace->m_used;
     681                 :          0 :             AceCache::get().destroy (ace);
     682                 :            :         }
     683                 :            :         OSL_ENSURE(m_ace_head.m_used == 0, "store::PageBIOS::cleanup_Impl(): logic error");
     684                 :            :     }
     685                 :            : 
     686                 :            :     // Release SuperBlock page.
     687                 :      51880 :     delete m_pSuper, m_pSuper = 0;
     688                 :            : 
     689                 :            :     // Release PageCache.
     690                 :      51880 :     m_xCache.clear();
     691                 :            : 
     692                 :            :     // Release PageAllocator.
     693                 :      51880 :     m_xAllocator.clear();
     694                 :            : 
     695                 :            :     // Release LockBytes.
     696                 :      51880 :     m_xLockBytes.clear();
     697                 :      51880 : }
     698                 :            : 
     699                 :            : /*
     700                 :            :  * read.
     701                 :            :  * Low Level: Precond: initialized, exclusive access.
     702                 :            :  */
     703                 :      35695 : storeError OStorePageBIOS::read (
     704                 :            :     sal_uInt32 nAddr, void *pData, sal_uInt32 nSize)
     705                 :            : {
     706                 :            :     // Check precond.
     707         [ -  + ]:      35695 :     if (!m_xLockBytes.is())
     708                 :          0 :         return store_E_InvalidAccess;
     709                 :            : 
     710                 :            :     // Read Data.
     711                 :      35695 :     return m_xLockBytes->readAt (nAddr, pData, nSize);
     712                 :            : }
     713                 :            : 
     714                 :            : /*
     715                 :            :  * write.
     716                 :            :  * Low Level: Precond: initialized, writeable, exclusive access.
     717                 :            :  */
     718                 :      42490 : storeError OStorePageBIOS::write (
     719                 :            :     sal_uInt32 nAddr, const void *pData, sal_uInt32 nSize)
     720                 :            : {
     721                 :            :     // Check precond.
     722         [ -  + ]:      42490 :     if (!m_xLockBytes.is())
     723                 :          0 :         return store_E_InvalidAccess;
     724         [ -  + ]:      42490 :     if (!m_bWriteable)
     725                 :          0 :         return store_E_AccessViolation;
     726                 :            : 
     727                 :            :     // Write Data.
     728                 :      42490 :     return m_xLockBytes->writeAt (nAddr, pData, nSize);
     729                 :            : }
     730                 :            : 
     731                 :            : /*
     732                 :            :  * acquirePage.
     733                 :            :  * Precond: initialized.
     734                 :            :  */
     735                 :    1198985 : storeError OStorePageBIOS::acquirePage (
     736                 :            :     const OStorePageDescriptor& rDescr, storeAccessMode eMode)
     737                 :            : {
     738                 :            :     // Acquire exclusive access.
     739         [ +  - ]:    1198985 :     osl::MutexGuard aGuard (m_aMutex);
     740                 :            : 
     741                 :            :     // Check precond.
     742         [ -  + ]:    1198985 :     if (!m_xLockBytes.is())
     743                 :          0 :         return store_E_InvalidAccess;
     744                 :            : 
     745                 :            :     // Check access mode.
     746 [ +  + ][ -  + ]:    1198985 :     if (!(m_bWriteable || (eMode == store_AccessReadOnly)))
     747                 :          0 :         return store_E_AccessViolation;
     748                 :            : 
     749                 :            :     // Find access control list entry.
     750                 :    1198985 :     Ace * ace = Ace::find (&m_ace_head, rDescr.m_nAddr);
     751         [ -  + ]:    1198985 :     if (ace->m_addr == rDescr.m_nAddr)
     752                 :            :     {
     753                 :            :       // Acquire existing entry (with ShareDenyWrite).
     754         [ #  # ]:          0 :       if (eMode == store_AccessReadOnly)
     755                 :          0 :         ace->m_used += 1;
     756                 :            :       else
     757                 :          0 :         return store_E_AccessViolation;
     758                 :            :     }
     759                 :            :     else
     760                 :            :     {
     761                 :            :       // Insert new entry.
     762         [ +  - ]:    1198985 :       Ace * entry = AceCache::get().create (rDescr.m_nAddr, 1);
     763         [ -  + ]:    1198985 :       if (!entry)
     764                 :          0 :         return store_E_OutOfMemory;
     765                 :    1198985 :       Ace::insert (ace, entry);
     766                 :            :     }
     767                 :            : 
     768                 :            :     // Increment total referer count and finish.
     769                 :    1198985 :     m_ace_head.m_used += 1;
     770         [ +  - ]:    1198985 :     return store_E_None;
     771                 :            : }
     772                 :            : 
     773                 :            : /*
     774                 :            :  * releasePage.
     775                 :            :  * Precond: initialized.
     776                 :            :  */
     777                 :    1198985 : storeError OStorePageBIOS::releasePage (const OStorePageDescriptor& rDescr)
     778                 :            : {
     779                 :            :     // Acquire exclusive access.
     780         [ +  - ]:    1198985 :     osl::MutexGuard aGuard (m_aMutex);
     781                 :            : 
     782                 :            :     // Check precond.
     783         [ -  + ]:    1198985 :     if (!m_xLockBytes.is())
     784                 :          0 :         return store_E_InvalidAccess;
     785                 :            : 
     786                 :            :     // Find access control list entry.
     787                 :    1198985 :     Ace * ace = Ace::find (&m_ace_head, rDescr.m_nAddr);
     788         [ -  + ]:    1198985 :     if (ace->m_addr != rDescr.m_nAddr)
     789                 :          0 :       return store_E_NotExists;
     790                 :            : 
     791                 :            :     // Release existing entry.
     792         [ -  + ]:    1198985 :     if (ace->m_used > 1)
     793                 :          0 :       ace->m_used -= 1;
     794                 :            :     else
     795         [ +  - ]:    1198985 :       AceCache::get().destroy (ace);
     796                 :            : 
     797                 :            :     // Decrement total referer count and finish.
     798                 :    1198985 :     m_ace_head.m_used -= 1;
     799         [ +  - ]:    1198985 :     return store_E_None;
     800                 :            : }
     801                 :            : 
     802                 :            : /*
     803                 :            :  * getRefererCount.
     804                 :            :  * Precond: none.
     805                 :            :  */
     806                 :          0 : sal_uInt32 OStorePageBIOS::getRefererCount (void)
     807                 :            : {
     808                 :            :     // Acquire exclusive access.
     809         [ #  # ]:          0 :     osl::MutexGuard aGuard (m_aMutex);
     810                 :            : 
     811                 :            :     // Obtain total referer count.
     812         [ #  # ]:          0 :     return m_ace_head.m_used;
     813                 :            : }
     814                 :            : 
     815                 :            : /*
     816                 :            :  * allocate.
     817                 :            :  * Precond: initialized, writeable.
     818                 :            :  */
     819                 :     136435 : storeError OStorePageBIOS::allocate (
     820                 :            :     OStorePageObject& rPage, Allocation eAlloc)
     821                 :            : {
     822                 :            :     // Acquire exclusive access.
     823         [ +  - ]:     136435 :     osl::MutexGuard aGuard (m_aMutex);
     824                 :            : 
     825                 :            :     // Check precond.
     826         [ -  + ]:     136435 :     if (!m_xLockBytes.is())
     827                 :          0 :         return store_E_InvalidAccess;
     828         [ -  + ]:     136435 :     if (!m_bWriteable)
     829                 :          0 :         return store_E_AccessViolation;
     830                 :            : 
     831                 :            :     // Check allocation type.
     832                 :     136435 :     storeError eErrCode = store_E_None;
     833         [ +  - ]:     136435 :     if (eAlloc != ALLOCATE_EOF)
     834                 :            :     {
     835                 :            :         // Try freelist head.
     836                 :     136435 :         PageData aPageHead;
     837         [ +  - ]:     136435 :         eErrCode = m_pSuper->unusedHead (*this, aPageHead);
     838         [ -  + ]:     136435 :         if (eErrCode != store_E_None)
     839                 :          0 :             return eErrCode;
     840                 :            : 
     841                 :     136435 :         sal_uInt32 const nAddr = aPageHead.location();
     842         [ +  + ]:     136435 :         if (nAddr != STORE_PAGE_NULL)
     843                 :            :         {
     844                 :            :             // Save page.
     845         [ +  - ]:      12065 :             eErrCode = saveObjectAt_Impl (rPage, nAddr);
     846         [ -  + ]:      12065 :             if (eErrCode != store_E_None)
     847                 :          0 :                 return eErrCode;
     848                 :            : 
     849                 :            :             // Pop freelist head and finish.
     850         [ +  - ]:     136435 :             return m_pSuper->unusedPop (*this, aPageHead);
     851                 :            :         }
     852                 :            :     }
     853                 :            : 
     854                 :            :     // Allocate from EOF. Determine current size.
     855                 :     124370 :     sal_uInt32 nSize = STORE_PAGE_NULL;
     856         [ +  - ]:     124370 :     eErrCode = m_xLockBytes->getSize (nSize);
     857         [ -  + ]:     124370 :     if (eErrCode != store_E_None)
     858                 :          0 :         return eErrCode;
     859                 :            : 
     860                 :            :     // Save page at current EOF.
     861 [ +  - ][ +  - ]:     136435 :     return saveObjectAt_Impl (rPage, nSize);
     862                 :            : }
     863                 :            : 
     864                 :            : /*
     865                 :            :  * free.
     866                 :            :  * Precond: initialized, writeable.
     867                 :            :  */
     868                 :      12087 : storeError OStorePageBIOS::free (sal_uInt32 nAddr)
     869                 :            : {
     870                 :            :     // Acquire exclusive access.
     871         [ +  - ]:      12087 :     osl::MutexGuard aGuard (m_aMutex);
     872                 :            : 
     873                 :            :     // Check precond.
     874         [ -  + ]:      12087 :     if (!m_xLockBytes.is())
     875                 :          0 :         return store_E_InvalidAccess;
     876         [ -  + ]:      12087 :     if (!m_bWriteable)
     877                 :          0 :         return store_E_AccessViolation;
     878                 :            : 
     879                 :            :     // Invalidate cache.
     880         [ +  - ]:      12087 :     (void) m_xCache->removePageAt (nAddr);
     881                 :            : 
     882                 :            :     // Push onto freelist.
     883 [ +  - ][ +  - ]:      12087 :     return m_pSuper->unusedPush (*this, nAddr);
     884                 :            : }
     885                 :            : 
     886                 :            : /*
     887                 :            :  * loadObjectAt.
     888                 :            :  * Precond: initialized, readable.
     889                 :            :  */
     890                 :    5563111 : storeError OStorePageBIOS::loadObjectAt (OStorePageObject & rPage, sal_uInt32 nAddr)
     891                 :            : {
     892                 :            :     // Acquire exclusive access.
     893         [ +  - ]:    5563111 :     osl::MutexGuard aGuard (m_aMutex);
     894                 :            : 
     895                 :            :     // Check precond.
     896         [ -  + ]:    5563111 :     if (!m_xLockBytes.is())
     897                 :          0 :         return store_E_InvalidAccess;
     898                 :            : 
     899 [ +  - ][ +  - ]:    5563111 :     return loadObjectAt_Impl (rPage, nAddr);
     900                 :            : }
     901                 :            : 
     902                 :            : /*
     903                 :            :  * loadObjectAt_Impl.
     904                 :            :  * Internal: Precond: initialized, readable, exclusive access.
     905                 :            :  */
     906                 :    5563111 : storeError OStorePageBIOS::loadObjectAt_Impl (OStorePageObject & rPage, sal_uInt32 nAddr)
     907                 :            : {
     908                 :    5563111 :     storeError eErrCode = m_xCache->lookupPageAt (rPage.get(), nAddr);
     909         [ +  + ]:    5563111 :     if (eErrCode != store_E_NotExists)
     910                 :    4899045 :         return eErrCode;
     911                 :            : 
     912                 :            :     // Read page.
     913                 :     664066 :     eErrCode = m_xLockBytes->readPageAt (rPage.get(), nAddr);
     914         [ +  + ]:     664066 :     if (eErrCode != store_E_None)
     915                 :       6251 :         return eErrCode;
     916                 :            : 
     917                 :            :     // Verify page.
     918                 :     657815 :     eErrCode = rPage.verify (nAddr);
     919         [ -  + ]:     657815 :     if (eErrCode != store_E_None)
     920                 :          0 :         return eErrCode;
     921                 :            : 
     922                 :            :     // Mark page as clean.
     923                 :     657815 :     rPage.clean();
     924                 :            : 
     925                 :            :     // Cache page.
     926                 :    5563111 :     return m_xCache->insertPageAt (rPage.get(), nAddr);
     927                 :            : }
     928                 :            : 
     929                 :            : /*
     930                 :            :  * saveObjectAt.
     931                 :            :  * Precond: initialized, writeable.
     932                 :            :  */
     933                 :     240114 : storeError OStorePageBIOS::saveObjectAt (OStorePageObject & rPage, sal_uInt32 nAddr)
     934                 :            : {
     935                 :            :     // Acquire exclusive access.
     936         [ +  - ]:     240114 :     osl::MutexGuard aGuard (m_aMutex);
     937                 :            : 
     938                 :            :     // Check precond.
     939         [ -  + ]:     240114 :     if (!m_xLockBytes.is())
     940                 :          0 :         return store_E_InvalidAccess;
     941         [ -  + ]:     240114 :     if (!m_bWriteable)
     942                 :          0 :         return store_E_AccessViolation;
     943                 :            : 
     944                 :            :     // Save Page.
     945 [ +  - ][ +  - ]:     240114 :     return saveObjectAt_Impl (rPage, nAddr);
     946                 :            : }
     947                 :            : 
     948                 :            : /*
     949                 :            :  * saveObjectAt_Impl.
     950                 :            :  * Internal: Precond: initialized, writeable, exclusive access.
     951                 :            :  */
     952                 :     376549 : storeError OStorePageBIOS::saveObjectAt_Impl (OStorePageObject & rPage, sal_uInt32 nAddr)
     953                 :            : {
     954                 :            :     // Guard page (incl. set location).
     955                 :     376549 :     storeError eErrCode = rPage.guard (nAddr);
     956         [ -  + ]:     376549 :     if (eErrCode != store_E_None)
     957                 :          0 :         return eErrCode;
     958                 :            : 
     959                 :            :     // Write page.
     960                 :     376549 :     eErrCode = m_xLockBytes->writePageAt(rPage.get(), nAddr);
     961         [ -  + ]:     376549 :     if (eErrCode != store_E_None)
     962                 :          0 :         return eErrCode;
     963                 :            : 
     964                 :            :     // Mark page as clean.
     965                 :     376549 :     rPage.clean();
     966                 :            : 
     967                 :            :     // Cache page.
     968                 :     376549 :     return m_xCache->updatePageAt (rPage.get(), nAddr);
     969                 :            : }
     970                 :            : 
     971                 :            : /*
     972                 :            :  * close.
     973                 :            :  * Precond: none.
     974                 :            :  */
     975                 :      16640 : storeError OStorePageBIOS::close()
     976                 :            : {
     977                 :            :     // Acquire exclusive access.
     978         [ +  - ]:      16640 :     osl::MutexGuard aGuard (m_aMutex);
     979                 :            : 
     980                 :            :     // Cleanup.
     981         [ +  - ]:      16640 :     cleanup_Impl();
     982                 :            : 
     983                 :            :     // Done.
     984         [ +  - ]:      16640 :     return store_E_None;
     985                 :            : }
     986                 :            : 
     987                 :            : /*
     988                 :            :  * flush.
     989                 :            :  * Precond: initialized.
     990                 :            :  */
     991                 :         66 : storeError OStorePageBIOS::flush (void)
     992                 :            : {
     993                 :            :     // Acquire exclusive access.
     994         [ +  - ]:         66 :     osl::MutexGuard aGuard (m_aMutex);
     995                 :            : 
     996                 :            :     // Check precond.
     997         [ -  + ]:         66 :     if (!m_xLockBytes.is())
     998                 :          0 :         return store_E_InvalidAccess;
     999                 :            : 
    1000                 :            :     // Flush LockBytes and finish.
    1001 [ +  - ][ +  - ]:         66 :     return m_xLockBytes->flush();
    1002                 :            : }
    1003                 :            : 
    1004                 :            : /*
    1005                 :            :  * size.
    1006                 :            :  * Precond: initialized.
    1007                 :            :  */
    1008                 :          0 : storeError OStorePageBIOS::size (sal_uInt32 &rnSize)
    1009                 :            : {
    1010                 :            :     // Acquire exclusive access.
    1011         [ #  # ]:          0 :     osl::MutexGuard aGuard (m_aMutex);
    1012                 :            : 
    1013                 :            :     // Initialize [out] param.
    1014                 :          0 :     rnSize = 0;
    1015                 :            : 
    1016                 :            :     // Check precond.
    1017         [ #  # ]:          0 :     if (!m_xLockBytes.is())
    1018                 :          0 :         return store_E_InvalidAccess;
    1019                 :            : 
    1020                 :            :     // Obtain LockBytes size.
    1021 [ #  # ][ #  # ]:          0 :     return m_xLockBytes->getSize (rnSize);
    1022                 :            : }
    1023                 :            : 
    1024                 :            : /*
    1025                 :            :  * scanBegin.
    1026                 :            :  * Precond: initialized.
    1027                 :            :  */
    1028                 :          0 : storeError OStorePageBIOS::scanBegin (
    1029                 :            :     ScanContext &rCtx, sal_uInt32 nMagic)
    1030                 :            : {
    1031                 :            :     // Acquire exclusive access.
    1032         [ #  # ]:          0 :     osl::MutexGuard aGuard (m_aMutex);
    1033                 :            : 
    1034                 :            :     // Initialize [out] param.
    1035                 :          0 :     rCtx.m_aDescr = OStorePageDescriptor(0, 0, 0);
    1036                 :          0 :     rCtx.m_nSize  = 0;
    1037                 :          0 :     rCtx.m_nMagic = nMagic;
    1038                 :            : 
    1039                 :            :     // Check precond.
    1040         [ #  # ]:          0 :     if (!m_xLockBytes.is())
    1041                 :          0 :         return store_E_InvalidAccess;
    1042                 :            : 
    1043                 :            :     // Check SuperBlock page.
    1044         [ #  # ]:          0 :     storeError eErrCode = m_pSuper->verify (*this);
    1045         [ #  # ]:          0 :     if (eErrCode != store_E_None)
    1046                 :            :     {
    1047                 :            :         // Damaged. Determine page size (NYI).
    1048                 :            :         OSL_TRACE ("OStorePageBIOS::scanBegin(): damaged.\n");
    1049                 :          0 :         return eErrCode;
    1050                 :            :     }
    1051                 :            : 
    1052                 :            :     // Setup Context descriptor.
    1053                 :          0 :     rCtx.m_aDescr = m_pSuper->m_aSuperOne.m_aDescr;
    1054                 :          0 :     rCtx.m_aDescr.m_nSize = store::ntohs(rCtx.m_aDescr.m_nSize);
    1055                 :          0 :     rCtx.m_aDescr.m_nAddr = rCtx.m_aDescr.m_nSize;
    1056                 :            : 
    1057                 :            :     // Setup Context size.
    1058         [ #  # ]:          0 :     eErrCode = size (rCtx.m_nSize);
    1059         [ #  # ]:          0 :     if (eErrCode != store_E_None)
    1060                 :          0 :         rCtx.m_nSize = ((sal_uInt32)(~0));
    1061                 :            : 
    1062                 :            :     // Done.
    1063         [ #  # ]:          0 :     return store_E_None;
    1064                 :            : }
    1065                 :            : 
    1066                 :            : /*
    1067                 :            :  * scanNext.
    1068                 :            :  * Precond: initialized.
    1069                 :            :  */
    1070                 :          0 : storeError OStorePageBIOS::scanNext (
    1071                 :            :     ScanContext &rCtx, OStorePageObject &rPage)
    1072                 :            : {
    1073                 :            :     // Acquire exclusive access.
    1074         [ #  # ]:          0 :     osl::MutexGuard aGuard (m_aMutex);
    1075                 :            : 
    1076                 :            :     // Check precond.
    1077         [ #  # ]:          0 :     if (!m_xLockBytes.is())
    1078                 :          0 :         return store_E_InvalidAccess;
    1079                 :            : 
    1080                 :            :     // Setup PageHead.
    1081                 :          0 :     PageData aPageHead;
    1082                 :            : 
    1083                 :            :     // Check context.
    1084         [ #  # ]:          0 :     while (rCtx.isValid())
    1085                 :            :     {
    1086                 :            :         // Assign next location.
    1087                 :          0 :         sal_uInt32 nAddr = rCtx.m_aDescr.m_nAddr;
    1088                 :          0 :         rCtx.m_aDescr.m_nAddr += rCtx.m_aDescr.m_nSize;
    1089                 :            : 
    1090                 :            :         // Read PageHead.
    1091         [ #  # ]:          0 :         storeError eErrCode = read (nAddr, &aPageHead, PageData::theSize);
    1092         [ #  # ]:          0 :         if (eErrCode != store_E_None)
    1093                 :          0 :             continue;
    1094                 :            : 
    1095                 :            :         // Verify PageHead.
    1096                 :          0 :         eErrCode = aPageHead.verify (nAddr);
    1097         [ #  # ]:          0 :         if (eErrCode != store_E_None)
    1098                 :          0 :             continue;
    1099                 :            : 
    1100                 :            :         // Check PageHead Magic number.
    1101         [ #  # ]:          0 :         if (aPageHead.m_aGuard.m_nMagic != rCtx.m_nMagic)
    1102                 :          0 :             continue;
    1103                 :            : 
    1104                 :            :         // Check PageHead Unused link.
    1105         [ #  # ]:          0 :         if (aPageHead.m_aUnused.m_nAddr != STORE_PAGE_NULL)
    1106                 :          0 :             continue;
    1107                 :            : 
    1108                 :            :         // Load page.
    1109         [ #  # ]:          0 :         eErrCode = loadObjectAt_Impl (rPage, nAddr);
    1110         [ #  # ]:          0 :         if (eErrCode != store_E_None)
    1111                 :          0 :             continue;
    1112                 :            : 
    1113                 :            :         // Deliver page.
    1114                 :          0 :         return store_E_None;
    1115                 :            :     }
    1116                 :            : 
    1117                 :            :     // Done.
    1118         [ #  # ]:          0 :     return store_E_CantSeek;
    1119                 :            : }
    1120                 :            : 
    1121                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10