LCOV - code coverage report
Current view: top level - store/source - storbios.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 390 0.0 %
Date: 2014-04-14 Functions: 0 51 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10