LCOV - code coverage report
Current view: top level - store/source - stordata.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 89 451 19.7 %
Date: 2014-04-11 Functions: 10 24 41.7 %
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 "stordata.hxx"
      21             : 
      22             : #include "sal/types.h"
      23             : #include "osl/diagnose.h"
      24             : 
      25             : #include "store/types.h"
      26             : #include "storbase.hxx"
      27             : #include "storbios.hxx"
      28             : 
      29             : using namespace store;
      30             : 
      31             : /*========================================================================
      32             :  *
      33             :  * OStoreDataPageObject implementation.
      34             :  *
      35             :  *======================================================================*/
      36             : /*
      37             :  * guard.
      38             :  */
      39         119 : storeError OStoreDataPageObject::guard (sal_uInt32 nAddr)
      40             : {
      41         119 :     return PageHolderObject< page >::guard (m_xPage, nAddr);
      42             : }
      43             : 
      44             : /*
      45             :  * verify.
      46             :  */
      47           0 : storeError OStoreDataPageObject::verify (sal_uInt32 nAddr) const
      48             : {
      49           0 :     return PageHolderObject< page >::verify (m_xPage, nAddr);
      50             : }
      51             : 
      52             : /*========================================================================
      53             :  *
      54             :  * OStoreIndirectionPageObject implementation.
      55             :  *
      56             :  *======================================================================*/
      57             : /*
      58             :   * store_truncate_Impl (single indirect page).
      59             :   */
      60           8 : static storeError store_truncate_Impl (
      61             :     sal_uInt32      nAddr,
      62             :     sal_uInt16      nSingle,
      63             :     OStorePageBIOS &rBIOS)
      64             : {
      65           8 :     if (nAddr != STORE_PAGE_NULL)
      66             :     {
      67             :         // Load single indirect page.
      68           0 :         OStoreIndirectionPageObject aSingle;
      69           0 :         storeError eErrCode = rBIOS.loadObjectAt (aSingle, nAddr);
      70           0 :         if (eErrCode == store_E_None)
      71             :         {
      72             :             // Truncate to 'nSingle' direct pages.
      73           0 :             eErrCode = aSingle.truncate (nSingle, rBIOS);
      74           0 :             if (eErrCode != store_E_None)
      75           0 :                 return eErrCode;
      76             :         }
      77             :         else
      78             :         {
      79           0 :             if (eErrCode != store_E_InvalidChecksum)
      80           0 :                 return eErrCode;
      81             :         }
      82             : 
      83             :         // Check for complete truncation.
      84           0 :         if (nSingle == 0)
      85             :         {
      86             :             // Free single indirect page.
      87           0 :             eErrCode = rBIOS.free (nAddr);
      88           0 :             if (eErrCode != store_E_None)
      89           0 :                 return eErrCode;
      90           0 :         }
      91             :     }
      92           8 :     return store_E_None;
      93             : }
      94             : 
      95             : /*
      96             :  * store_truncate_Impl (double indirect page).
      97             :  */
      98           1 : static storeError store_truncate_Impl (
      99             :     sal_uInt32       nAddr,
     100             :     sal_uInt16       nDouble,
     101             :     sal_uInt16       nSingle,
     102             :     OStorePageBIOS  &rBIOS)
     103             : {
     104           1 :     if (nAddr != STORE_PAGE_NULL)
     105             :     {
     106             :         // Load double indirect page.
     107           0 :         OStoreIndirectionPageObject aDouble;
     108           0 :         storeError eErrCode = rBIOS.loadObjectAt (aDouble, nAddr);
     109           0 :         if (eErrCode == store_E_None)
     110             :         {
     111             :             // Truncate to 'nDouble', 'nSingle' pages.
     112           0 :             eErrCode = aDouble.truncate (nDouble, nSingle, rBIOS);
     113           0 :             if (eErrCode != store_E_None)
     114           0 :                 return eErrCode;
     115             :         }
     116             :         else
     117             :         {
     118           0 :             if (eErrCode != store_E_InvalidChecksum)
     119           0 :                 return eErrCode;
     120             :         }
     121             : 
     122             :         // Check for complete truncation.
     123           0 :         if ((nDouble + nSingle) == 0)
     124             :         {
     125             :             // Free double indirect page.
     126           0 :             eErrCode = rBIOS.free (nAddr);
     127           0 :             if (eErrCode != store_E_None)
     128           0 :                 return eErrCode;
     129           0 :         }
     130             :     }
     131           1 :     return store_E_None;
     132             : }
     133             : 
     134             : /*
     135             :  * store_truncate_Impl (triple indirect page).
     136             :  */
     137           1 : static storeError store_truncate_Impl (
     138             :     sal_uInt32       nAddr,
     139             :     sal_uInt16       nTriple,
     140             :     sal_uInt16       nDouble,
     141             :     sal_uInt16       nSingle,
     142             :     OStorePageBIOS  &rBIOS)
     143             : {
     144           1 :     if (nAddr != STORE_PAGE_NULL)
     145             :     {
     146             :         // Load triple indirect page.
     147           0 :         OStoreIndirectionPageObject aTriple;
     148           0 :         storeError eErrCode = rBIOS.loadObjectAt (aTriple, nAddr);
     149           0 :         if (eErrCode != store_E_None)
     150           0 :             return eErrCode;
     151             : 
     152             :         // Truncate to 'nTriple', 'nDouble', 'nSingle' pages.
     153           0 :         eErrCode = aTriple.truncate (nTriple, nDouble, nSingle, rBIOS);
     154           0 :         if (eErrCode != store_E_None)
     155           0 :             return eErrCode;
     156             : 
     157             :         // Check for complete truncation.
     158           0 :         if ((nTriple + nDouble + nSingle) == 0)
     159             :         {
     160             :             // Free triple indirect page.
     161           0 :             eErrCode = rBIOS.free (nAddr);
     162           0 :             if (eErrCode != store_E_None)
     163           0 :                 return eErrCode;
     164           0 :         }
     165             :     }
     166           1 :     return store_E_None;
     167             : }
     168             : 
     169             : /*
     170             :  * loadOrCreate.
     171             :  */
     172           0 : storeError OStoreIndirectionPageObject::loadOrCreate (
     173             :     sal_uInt32       nAddr,
     174             :     OStorePageBIOS & rBIOS)
     175             : {
     176           0 :     if (nAddr == STORE_PAGE_NULL)
     177             :     {
     178           0 :         storeError eErrCode = construct<page>(rBIOS.allocator());
     179           0 :         if (eErrCode != store_E_None)
     180           0 :             return eErrCode;
     181             : 
     182           0 :         eErrCode = rBIOS.allocate (*this);
     183           0 :         if (eErrCode != store_E_None)
     184           0 :             return eErrCode;
     185             : 
     186             :         // Save location pending at caller.
     187           0 :         return store_E_Pending;
     188             :     }
     189           0 :     return rBIOS.loadObjectAt (*this, nAddr);
     190             : }
     191             : 
     192             : /*
     193             :  * guard.
     194             :  */
     195           0 : storeError OStoreIndirectionPageObject::guard (sal_uInt32 nAddr)
     196             : {
     197           0 :     return PageHolderObject< page >::guard (m_xPage, nAddr);
     198             : }
     199             : 
     200             : /*
     201             :  * verify.
     202             :  */
     203           0 : storeError OStoreIndirectionPageObject::verify (sal_uInt32 nAddr) const
     204             : {
     205           0 :     return PageHolderObject< page >::verify (m_xPage, nAddr);
     206             : }
     207             : 
     208             : /*
     209             :  * read (single indirect).
     210             :  */
     211           0 : storeError OStoreIndirectionPageObject::read (
     212             :     sal_uInt16             nSingle,
     213             :     OStoreDataPageObject  &rData,
     214             :     OStorePageBIOS        &rBIOS)
     215             : {
     216           0 :     PageHolderObject< page > xImpl (m_xPage);
     217           0 :     page const & rPage = (*xImpl);
     218             : 
     219             :     // Check arguments.
     220           0 :     sal_uInt16 const nLimit = rPage.capacityCount();
     221           0 :     if (!(nSingle < nLimit))
     222           0 :         return store_E_InvalidAccess;
     223             : 
     224             :     // Obtain data page location.
     225           0 :     sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nSingle]);
     226           0 :     if (nAddr == STORE_PAGE_NULL)
     227           0 :         return store_E_NotExists;
     228             : 
     229             :     // Load data page and leave.
     230           0 :     return rBIOS.loadObjectAt (rData, nAddr);
     231             : }
     232             : 
     233             : /*
     234             :  * read (double indirect).
     235             :  */
     236           0 : storeError OStoreIndirectionPageObject::read (
     237             :     sal_uInt16             nDouble,
     238             :     sal_uInt16             nSingle,
     239             :     OStoreDataPageObject  &rData,
     240             :     OStorePageBIOS        &rBIOS)
     241             : {
     242           0 :     PageHolderObject< page > xImpl (m_xPage);
     243           0 :     page const & rPage = (*xImpl);
     244             : 
     245             :     // Check arguments.
     246           0 :     sal_uInt16 const nLimit = rPage.capacityCount();
     247           0 :     if (!((nDouble < nLimit) && (nSingle < nLimit)))
     248           0 :         return store_E_InvalidAccess;
     249             : 
     250             :     // Check single indirect page location.
     251           0 :     sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nDouble]);
     252           0 :     if (nAddr == STORE_PAGE_NULL)
     253           0 :         return store_E_NotExists;
     254             : 
     255             :     // Load single indirect page.
     256           0 :     OStoreIndirectionPageObject aSingle;
     257           0 :     storeError eErrCode = rBIOS.loadObjectAt (aSingle, nAddr);
     258           0 :     if (eErrCode != store_E_None)
     259           0 :         return eErrCode;
     260             : 
     261             :     // Read single indirect and leave.
     262           0 :     return aSingle.read (nSingle, rData, rBIOS);
     263             : }
     264             : 
     265             : /*
     266             :  * read (triple indirect).
     267             :  */
     268           0 : storeError OStoreIndirectionPageObject::read (
     269             :     sal_uInt16             nTriple,
     270             :     sal_uInt16             nDouble,
     271             :     sal_uInt16             nSingle,
     272             :     OStoreDataPageObject  &rData,
     273             :     OStorePageBIOS        &rBIOS)
     274             : {
     275           0 :     PageHolderObject< page > xImpl (m_xPage);
     276           0 :     page const & rPage = (*xImpl);
     277             : 
     278             :     // Check arguments.
     279           0 :     sal_uInt16 const nLimit = rPage.capacityCount();
     280           0 :     if (!((nTriple < nLimit) && (nDouble < nLimit) && (nSingle < nLimit)))
     281           0 :         return store_E_InvalidAccess;
     282             : 
     283             :     // Check double indirect page location.
     284           0 :     sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nTriple]);
     285           0 :     if (nAddr == STORE_PAGE_NULL)
     286           0 :         return store_E_NotExists;
     287             : 
     288             :     // Load double indirect page.
     289           0 :     OStoreIndirectionPageObject aDouble;
     290           0 :     storeError eErrCode = rBIOS.loadObjectAt (aDouble, nAddr);
     291           0 :     if (eErrCode != store_E_None)
     292           0 :         return eErrCode;
     293             : 
     294             :     // Read double indirect and leave.
     295           0 :     return aDouble.read (nDouble, nSingle, rData, rBIOS);
     296             : }
     297             : 
     298             : /*
     299             :  * write (single indirect).
     300             :  */
     301           0 : storeError OStoreIndirectionPageObject::write (
     302             :     sal_uInt16             nSingle,
     303             :     OStoreDataPageObject  &rData,
     304             :     OStorePageBIOS        &rBIOS)
     305             : {
     306           0 :     PageHolderObject< page > xImpl (m_xPage);
     307           0 :     page & rPage = (*xImpl);
     308             : 
     309             :     // Check arguments.
     310           0 :     sal_uInt16 const nLimit = rPage.capacityCount();
     311           0 :     if (!(nSingle < nLimit))
     312           0 :         return store_E_InvalidAccess;
     313             : 
     314             :     // Obtain data page location.
     315           0 :     sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nSingle]);
     316           0 :     if (nAddr == STORE_PAGE_NULL)
     317             :     {
     318             :         // Allocate data page.
     319           0 :         storeError eErrCode = rBIOS.allocate (rData);
     320           0 :         if (eErrCode != store_E_None)
     321           0 :             return eErrCode;
     322             : 
     323             :         // Store data page location.
     324           0 :         rPage.m_pData[nSingle] = store::htonl(rData.location());
     325             : 
     326             :         // Save this page.
     327           0 :         return rBIOS.saveObjectAt (*this, location());
     328             :     }
     329             :     else
     330             :     {
     331             :         // Save data page.
     332           0 :         return rBIOS.saveObjectAt (rData, nAddr);
     333           0 :     }
     334             : }
     335             : 
     336             : /*
     337             :  * write (double indirect).
     338             :  */
     339           0 : storeError OStoreIndirectionPageObject::write (
     340             :     sal_uInt16             nDouble,
     341             :     sal_uInt16             nSingle,
     342             :     OStoreDataPageObject  &rData,
     343             :     OStorePageBIOS        &rBIOS)
     344             : {
     345           0 :     PageHolderObject< page > xImpl (m_xPage);
     346           0 :     page & rPage = (*xImpl);
     347             : 
     348             :     // Check arguments.
     349           0 :     sal_uInt16 const nLimit = rPage.capacityCount();
     350           0 :     if (!((nDouble < nLimit) && (nSingle < nLimit)))
     351           0 :         return store_E_InvalidAccess;
     352             : 
     353             :     // Load or create single indirect page.
     354           0 :     OStoreIndirectionPageObject aSingle;
     355           0 :     storeError eErrCode = aSingle.loadOrCreate (store::ntohl(rPage.m_pData[nDouble]), rBIOS);
     356           0 :     if (eErrCode != store_E_None)
     357             :     {
     358           0 :         if (eErrCode != store_E_Pending)
     359           0 :             return eErrCode;
     360           0 :         rPage.m_pData[nDouble] = store::htonl(aSingle.location());
     361             : 
     362           0 :         eErrCode = rBIOS.saveObjectAt (*this, location());
     363           0 :         if (eErrCode != store_E_None)
     364           0 :             return eErrCode;
     365             :     }
     366             : 
     367             :     // Write single indirect and leave.
     368           0 :     return aSingle.write (nSingle, rData, rBIOS);
     369             : }
     370             : 
     371             : /*
     372             :  * write (triple indirect).
     373             :  */
     374           0 : storeError OStoreIndirectionPageObject::write (
     375             :     sal_uInt16             nTriple,
     376             :     sal_uInt16             nDouble,
     377             :     sal_uInt16             nSingle,
     378             :     OStoreDataPageObject  &rData,
     379             :     OStorePageBIOS        &rBIOS)
     380             : {
     381           0 :     PageHolderObject< page > xImpl (m_xPage);
     382           0 :     page & rPage = (*xImpl);
     383             : 
     384             :     // Check arguments.
     385           0 :     sal_uInt16 const nLimit = rPage.capacityCount();
     386           0 :     if (!((nTriple < nLimit) && (nDouble < nLimit) && (nSingle < nLimit)))
     387           0 :         return store_E_InvalidAccess;
     388             : 
     389             :     // Load or create double indirect page.
     390           0 :     OStoreIndirectionPageObject aDouble;
     391           0 :     storeError eErrCode = aDouble.loadOrCreate (store::ntohl(rPage.m_pData[nTriple]), rBIOS);
     392           0 :     if (eErrCode != store_E_None)
     393             :     {
     394           0 :         if (eErrCode != store_E_Pending)
     395           0 :             return eErrCode;
     396           0 :         rPage.m_pData[nTriple] = store::htonl(aDouble.location());
     397             : 
     398           0 :         eErrCode = rBIOS.saveObjectAt (*this, location());
     399           0 :         if (eErrCode != store_E_None)
     400           0 :             return eErrCode;
     401             :     }
     402             : 
     403             :     // Write double indirect and leave.
     404           0 :     return aDouble.write (nDouble, nSingle, rData, rBIOS);
     405             : }
     406             : 
     407             : /*
     408             :  * truncate (single indirect).
     409             :  */
     410           0 : storeError OStoreIndirectionPageObject::truncate (
     411             :     sal_uInt16       nSingle,
     412             :     OStorePageBIOS & rBIOS)
     413             : {
     414           0 :     PageHolderObject< page > xImpl (m_xPage);
     415           0 :     page & rPage = (*xImpl);
     416             : 
     417             :     // Check arguments.
     418           0 :     sal_uInt16 const nLimit = rPage.capacityCount();
     419           0 :     if (!(nSingle < nLimit))
     420           0 :         return store_E_InvalidAccess;
     421             : 
     422             :     // Truncate.
     423           0 :     storeError eErrCode = store_E_None;
     424           0 :     for (sal_uInt16 i = nLimit; i > nSingle; i--)
     425             :     {
     426             :         // Obtain data page location.
     427           0 :         sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[i - 1]);
     428           0 :         if (nAddr != STORE_PAGE_NULL)
     429             :         {
     430             :             // Free data page.
     431           0 :             eErrCode = rBIOS.free (nAddr);
     432           0 :             if (eErrCode != store_E_None)
     433           0 :                 return eErrCode;
     434             : 
     435             :             // Clear pointer to data page.
     436           0 :             rPage.m_pData[i - 1] = STORE_PAGE_NULL;
     437           0 :             touch();
     438             :         }
     439             :     }
     440             : 
     441             :     // Check for modified page.
     442           0 :     if (dirty())
     443             :     {
     444             :         // Save this page.
     445           0 :         eErrCode = rBIOS.saveObjectAt (*this, location());
     446             :     }
     447             : 
     448             :     // Done.
     449           0 :     return eErrCode;
     450             : }
     451             : 
     452             : /*
     453             :  * truncate (double indirect).
     454             :  */
     455           0 : storeError OStoreIndirectionPageObject::truncate (
     456             :     sal_uInt16             nDouble,
     457             :     sal_uInt16             nSingle,
     458             :     OStorePageBIOS        &rBIOS)
     459             : {
     460           0 :     PageHolderObject< page > xImpl (m_xPage);
     461           0 :     page & rPage = (*xImpl);
     462             : 
     463             :     // Check arguments.
     464           0 :     sal_uInt16 const nLimit = rPage.capacityCount();
     465           0 :     if (!((nDouble < nLimit) && (nSingle < nLimit)))
     466           0 :         return store_E_InvalidAccess;
     467             : 
     468             :     // Truncate.
     469           0 :     storeError eErrCode = store_E_None;
     470           0 :     for (sal_uInt16 i = nLimit; i > nDouble + 1; i--)
     471             :     {
     472             :         // Truncate single indirect page to zero direct pages.
     473           0 :         eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[i - 1]), 0, rBIOS);
     474           0 :         if (eErrCode != store_E_None)
     475           0 :             return eErrCode;
     476             : 
     477             :         // Clear pointer to single indirect page.
     478           0 :         rPage.m_pData[i - 1] = STORE_PAGE_NULL;
     479           0 :         touch();
     480             :     }
     481             : 
     482             :     // Truncate last single indirect page to 'nSingle' direct pages.
     483           0 :     eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[nDouble]), nSingle, rBIOS);
     484           0 :     if (eErrCode != store_E_None)
     485           0 :         return eErrCode;
     486             : 
     487             :     // Check for complete truncation.
     488           0 :     if (nSingle == 0)
     489             :     {
     490             :         // Clear pointer to last single indirect page.
     491           0 :         rPage.m_pData[nDouble] = STORE_PAGE_NULL;
     492           0 :         touch();
     493             :     }
     494             : 
     495             :     // Check for modified page.
     496           0 :     if (dirty())
     497             :     {
     498             :         // Save this page.
     499           0 :         eErrCode = rBIOS.saveObjectAt (*this, location());
     500             :     }
     501             : 
     502             :     // Done.
     503           0 :     return eErrCode;
     504             : }
     505             : 
     506             : /*
     507             :  * truncate (triple indirect).
     508             :  */
     509           0 : storeError OStoreIndirectionPageObject::truncate (
     510             :     sal_uInt16             nTriple,
     511             :     sal_uInt16             nDouble,
     512             :     sal_uInt16             nSingle,
     513             :     OStorePageBIOS        &rBIOS)
     514             : {
     515           0 :     PageHolderObject< page > xImpl (m_xPage);
     516           0 :     page & rPage = (*xImpl);
     517             : 
     518             :     // Check arguments.
     519           0 :     sal_uInt16 const nLimit = rPage.capacityCount();
     520           0 :     if (!((nTriple < nLimit) && (nDouble < nLimit) && (nSingle < nLimit)))
     521           0 :         return store_E_InvalidAccess;
     522             : 
     523             :     // Truncate.
     524           0 :     storeError eErrCode = store_E_None;
     525           0 :     for (sal_uInt16 i = nLimit; i > nTriple + 1; i--)
     526             :     {
     527             :         // Truncate double indirect page to zero single indirect pages.
     528           0 :         eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[i - 1]), 0, 0, rBIOS);
     529           0 :         if (eErrCode != store_E_None)
     530           0 :             return eErrCode;
     531             : 
     532             :         // Clear pointer to double indirect page.
     533           0 :         rPage.m_pData[i - 1] = STORE_PAGE_NULL;
     534           0 :         touch();
     535             :     }
     536             : 
     537             :     // Truncate last double indirect page to 'nDouble', 'nSingle' pages.
     538           0 :     eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[nTriple]), nDouble, nSingle, rBIOS);
     539           0 :     if (eErrCode != store_E_None)
     540           0 :         return eErrCode;
     541             : 
     542             :     // Check for complete truncation.
     543           0 :     if ((nDouble + nSingle) == 0)
     544             :     {
     545             :         // Clear pointer to last double indirect page.
     546           0 :         rPage.m_pData[nTriple] = STORE_PAGE_NULL;
     547           0 :         touch();
     548             :     }
     549             : 
     550             :     // Check for modified page.
     551           0 :     if (dirty())
     552             :     {
     553             :         // Save this page.
     554           0 :         eErrCode = rBIOS.saveObjectAt (*this, location());
     555             :     }
     556             : 
     557             :     // Done.
     558           0 :     return eErrCode;
     559             : }
     560             : 
     561             : /*========================================================================
     562             :  *
     563             :  * OStoreDirectoryPageObject implementation.
     564             :  *
     565             :  *======================================================================*/
     566             : /*
     567             :  * guard.
     568             :  */
     569        1357 : storeError OStoreDirectoryPageObject::guard (sal_uInt32 nAddr)
     570             : {
     571        1357 :     return PageHolderObject< page >::guard (m_xPage, nAddr);
     572             : }
     573             : 
     574             : /*
     575             :  * verify.
     576             :  */
     577           0 : storeError OStoreDirectoryPageObject::verify (sal_uInt32 nAddr) const
     578             : {
     579           0 :     return PageHolderObject< page >::verify (m_xPage, nAddr);
     580             :     // OLD: m_rPage.verifyVersion (STORE_MAGIC_DIRECTORYPAGE);
     581             : }
     582             : 
     583             : /*
     584             :  * scope (external data page; private).
     585             :  */
     586             : OStoreDirectoryPageData::ChunkScope
     587         237 : OStoreDirectoryPageObject::scope (
     588             :     sal_uInt32                       nPage,
     589             :     page::DataBlock::LinkDescriptor &rDescr) const
     590             : {
     591         237 :     page const & rPage = PAGE();
     592         237 :     OStoreDirectoryDataBlock const & rDataBlock = rPage.m_aDataBlock;
     593             : 
     594             :     sal_uInt32 index0, index1, index2, index3;
     595             : 
     596             :     // direct.
     597         237 :     sal_uInt32 nCount = rDataBlock.directCount();
     598         237 :     sal_uInt32 nLimit = nCount;
     599         237 :     if (nPage < nLimit)
     600             :     {
     601             :         // Page to index reduction.
     602         237 :         index0 = nPage;
     603             : 
     604             :         // Setup LinkDescriptor indices.
     605         237 :         rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff);
     606             : 
     607             :         // Done.
     608         237 :         return page::SCOPE_DIRECT;
     609             :     }
     610           0 :     nPage -= nLimit;
     611             : 
     612             :     // single indirect.
     613           0 :     sal_uInt32 const nCapacity = indirect::capacityCount(rPage.m_aDescr);
     614           0 :     nCount = rDataBlock.singleCount();
     615           0 :     nLimit = nCount * nCapacity;
     616           0 :     if (nPage < nLimit)
     617             :     {
     618             :         // Page to index reduction.
     619           0 :         sal_uInt32 n = nPage;
     620             : 
     621             :         // Reduce to single indirect i(1), direct n = i(0).
     622           0 :         index1 = n / nCapacity;
     623           0 :         index0 = n % nCapacity;
     624             : 
     625             :         // Verify reduction.
     626           0 :         n = index1 * nCapacity + index0;
     627             :         OSL_POSTCOND(n == nPage, "wrong math on indirect indices");
     628           0 :         if (n != nPage)
     629           0 :             return page::SCOPE_UNKNOWN;
     630             : 
     631             :         // Setup LinkDescriptor indices.
     632           0 :         rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff);
     633           0 :         rDescr.m_nIndex1 = (sal_uInt16)(index1 & 0xffff);
     634             : 
     635             :         // Done.
     636           0 :         return page::SCOPE_SINGLE;
     637             :     }
     638           0 :     nPage -= nLimit;
     639             : 
     640             :     // double indirect.
     641           0 :     nCount = rDataBlock.doubleCount();
     642           0 :     nLimit = nCount * nCapacity * nCapacity;
     643           0 :     if (nPage < nLimit)
     644             :     {
     645             :         // Page to index reduction.
     646           0 :         sal_uInt32 n = nPage;
     647             : 
     648             :         // Reduce to double indirect i(2), single indirect n = i(0).
     649           0 :         index2 = n / (nCapacity * nCapacity);
     650           0 :         n      = n % (nCapacity * nCapacity);
     651             : 
     652             :         // Reduce to single indirect i(1), direct n = i(0).
     653           0 :         index1 = n / nCapacity;
     654           0 :         index0 = n % nCapacity;
     655             : 
     656             :         // Verify reduction.
     657           0 :         n = index2 * nCapacity * nCapacity +
     658           0 :             index1 * nCapacity + index0;
     659             :         OSL_POSTCOND(n == nPage, "wrong math on double indirect indices");
     660           0 :         if (n != nPage)
     661           0 :             return page::SCOPE_UNKNOWN;
     662             : 
     663             :         // Setup LinkDescriptor indices.
     664           0 :         rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff);
     665           0 :         rDescr.m_nIndex1 = (sal_uInt16)(index1 & 0xffff);
     666           0 :         rDescr.m_nIndex2 = (sal_uInt16)(index2 & 0xffff);
     667             : 
     668             :         // Done.
     669           0 :         return page::SCOPE_DOUBLE;
     670             :     }
     671           0 :     nPage -= nLimit;
     672             : 
     673             :     // triple indirect.
     674           0 :     nCount = rDataBlock.tripleCount();
     675           0 :     nLimit = nCount * nCapacity * nCapacity * nCapacity;
     676           0 :     if (nPage < nLimit)
     677             :     {
     678             :         // Page to index reduction.
     679           0 :         sal_uInt32 n = nPage;
     680             : 
     681             :         // Reduce to triple indirect i(3), double indirect n.
     682           0 :         index3 = n / (nCapacity * nCapacity * nCapacity);
     683           0 :         n      = n % (nCapacity * nCapacity * nCapacity);
     684             : 
     685             :         // Reduce to double indirect i(2), single indirect n.
     686           0 :         index2 = n / (nCapacity * nCapacity);
     687           0 :         n      = n % (nCapacity * nCapacity);
     688             : 
     689             :         // Reduce to single indirect i(1), direct n = i(0).
     690           0 :         index1 = n / nCapacity;
     691           0 :         index0 = n % nCapacity;
     692             : 
     693             :         // Verify reduction.
     694           0 :         n = index3 * nCapacity * nCapacity * nCapacity +
     695           0 :             index2 * nCapacity * nCapacity +
     696           0 :             index1 * nCapacity + index0;
     697             :         OSL_POSTCOND(n == nPage, "wrong math on triple indirect indices");
     698           0 :         if (n != nPage)
     699           0 :             return page::SCOPE_UNKNOWN;
     700             : 
     701             :         // Setup LinkDescriptor indices.
     702           0 :         rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff);
     703           0 :         rDescr.m_nIndex1 = (sal_uInt16)(index1 & 0xffff);
     704           0 :         rDescr.m_nIndex2 = (sal_uInt16)(index2 & 0xffff);
     705           0 :         rDescr.m_nIndex3 = (sal_uInt16)(index3 & 0xffff);
     706             : 
     707             :         // Done.
     708           0 :         return page::SCOPE_TRIPLE;
     709             :     }
     710             : 
     711             :     // Unreachable (more than triple indirect).
     712           0 :     return page::SCOPE_UNREACHABLE;
     713             : }
     714             : 
     715             : /*
     716             :  * read (external data page).
     717             :  */
     718         117 : storeError OStoreDirectoryPageObject::read (
     719             :     sal_uInt32             nPage,
     720             :     OStoreDataPageObject  &rData,
     721             :     OStorePageBIOS        &rBIOS)
     722             : {
     723             :     // Determine scope and link indices.
     724         117 :     page::DataBlock::LinkDescriptor aLink;
     725         117 :     page::ChunkScope eScope = scope (nPage, aLink);
     726             : 
     727         117 :     storeError eErrCode = store_E_None;
     728         117 :     if (eScope == page::SCOPE_DIRECT)
     729             :     {
     730         117 :         sal_uInt32 const nAddr = directLink (aLink.m_nIndex0);
     731         117 :         if (nAddr == STORE_PAGE_NULL)
     732         116 :             return store_E_NotExists;
     733             : 
     734           1 :         eErrCode = rBIOS.loadObjectAt (rData, nAddr);
     735             :     }
     736           0 :     else if (eScope == page::SCOPE_SINGLE)
     737             :     {
     738           0 :         sal_uInt32 const nAddr = singleLink (aLink.m_nIndex1);
     739           0 :         if (nAddr == STORE_PAGE_NULL)
     740           0 :             return store_E_NotExists;
     741             : 
     742           0 :         OStoreIndirectionPageObject aSingle;
     743           0 :         eErrCode = rBIOS.loadObjectAt (aSingle, nAddr);
     744           0 :         if (eErrCode != store_E_None)
     745           0 :             return eErrCode;
     746             : 
     747           0 :         eErrCode = aSingle.read (aLink.m_nIndex0, rData, rBIOS);
     748             :     }
     749           0 :     else if (eScope == page::SCOPE_DOUBLE)
     750             :     {
     751           0 :         sal_uInt32 const nAddr = doubleLink (aLink.m_nIndex2);
     752           0 :         if (nAddr == STORE_PAGE_NULL)
     753           0 :             return store_E_NotExists;
     754             : 
     755           0 :         OStoreIndirectionPageObject aDouble;
     756           0 :         eErrCode = rBIOS.loadObjectAt (aDouble, nAddr);
     757           0 :         if (eErrCode != store_E_None)
     758           0 :             return eErrCode;
     759             : 
     760           0 :         eErrCode = aDouble.read (aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS);
     761             :     }
     762           0 :     else if (eScope == page::SCOPE_TRIPLE)
     763             :     {
     764           0 :         sal_uInt32 const nAddr = tripleLink (aLink.m_nIndex3);
     765           0 :         if (nAddr == STORE_PAGE_NULL)
     766           0 :             return store_E_NotExists;
     767             : 
     768           0 :         OStoreIndirectionPageObject aTriple;
     769           0 :         eErrCode = rBIOS.loadObjectAt (aTriple, nAddr);
     770           0 :         if (eErrCode != store_E_None)
     771           0 :             return eErrCode;
     772             : 
     773           0 :         eErrCode = aTriple.read (aLink.m_nIndex2, aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS);
     774             :     }
     775           0 :     else if (eScope == page::SCOPE_UNREACHABLE)
     776             :     {
     777             :         // Out of scope.
     778           0 :         eErrCode = store_E_CantSeek;
     779             :     }
     780             :     else
     781             :     {
     782             :         // Unknown scope.
     783             :         OSL_TRACE("OStoreDirectoryPageObject::get(): scope failed");
     784           0 :         eErrCode = store_E_Unknown;
     785             :     }
     786             : 
     787             :     // Leave.
     788           1 :     return eErrCode;
     789             : }
     790             : 
     791             : /*
     792             :  * write (external data page).
     793             :  */
     794         119 : storeError OStoreDirectoryPageObject::write (
     795             :     sal_uInt32             nPage,
     796             :     OStoreDataPageObject  &rData,
     797             :     OStorePageBIOS        &rBIOS)
     798             : {
     799             :     // Determine scope and link indices.
     800         119 :     page::DataBlock::LinkDescriptor aLink;
     801         119 :     page::ChunkScope eScope = scope (nPage, aLink);
     802             : 
     803         119 :     storeError eErrCode = store_E_None;
     804         119 :     if (eScope == page::SCOPE_DIRECT)
     805             :     {
     806         119 :         sal_uInt32 const nAddr = directLink (aLink.m_nIndex0);
     807         119 :         if (nAddr == STORE_PAGE_NULL)
     808             :         {
     809             :             // Allocate data page.
     810         119 :             eErrCode = rBIOS.allocate (rData);
     811         119 :             if (eErrCode != store_E_None)
     812           0 :                 return eErrCode;
     813             : 
     814             :             // Store data page location.
     815         119 :             directLink (aLink.m_nIndex0, rData.location());
     816             :         }
     817             :         else
     818             :         {
     819             :             // Save data page.
     820           0 :             eErrCode = rBIOS.saveObjectAt (rData, nAddr);
     821             :         }
     822             :     }
     823           0 :     else if (eScope == page::SCOPE_SINGLE)
     824             :     {
     825           0 :         OStoreIndirectionPageObject aSingle;
     826           0 :         eErrCode = aSingle.loadOrCreate (singleLink (aLink.m_nIndex1), rBIOS);
     827           0 :         if (eErrCode != store_E_None)
     828             :         {
     829           0 :             if (eErrCode != store_E_Pending)
     830           0 :                 return eErrCode;
     831           0 :             singleLink (aLink.m_nIndex1, aSingle.location());
     832             :         }
     833             : 
     834           0 :         eErrCode = aSingle.write (aLink.m_nIndex0, rData, rBIOS);
     835             :     }
     836           0 :     else if (eScope == page::SCOPE_DOUBLE)
     837             :     {
     838           0 :         OStoreIndirectionPageObject aDouble;
     839           0 :         eErrCode = aDouble.loadOrCreate (doubleLink (aLink.m_nIndex2), rBIOS);
     840           0 :         if (eErrCode != store_E_None)
     841             :         {
     842           0 :             if (eErrCode != store_E_Pending)
     843           0 :                 return eErrCode;
     844           0 :             doubleLink (aLink.m_nIndex2, aDouble.location());
     845             :         }
     846             : 
     847           0 :         eErrCode = aDouble.write (aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS);
     848             :     }
     849           0 :     else if (eScope == page::SCOPE_TRIPLE)
     850             :     {
     851           0 :         OStoreIndirectionPageObject aTriple;
     852           0 :         eErrCode = aTriple.loadOrCreate (tripleLink (aLink.m_nIndex3), rBIOS);
     853           0 :         if (eErrCode != store_E_None)
     854             :         {
     855           0 :             if (eErrCode != store_E_Pending)
     856           0 :                 return eErrCode;
     857           0 :             tripleLink (aLink.m_nIndex3, aTriple.location());
     858             :         }
     859             : 
     860           0 :         eErrCode = aTriple.write (aLink.m_nIndex2, aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS);
     861             :     }
     862           0 :     else if (eScope == page::SCOPE_UNREACHABLE)
     863             :     {
     864             :         // Out of scope.
     865           0 :         eErrCode = store_E_CantSeek;
     866             :     }
     867             :     else
     868             :     {
     869             :         // Unknown scope.
     870             :         OSL_TRACE("OStoreDirectoryPageObject::put(): scope failed");
     871           0 :         eErrCode = store_E_Unknown;
     872             :     }
     873             : 
     874             :     // Leave.
     875         119 :     return eErrCode;
     876             : }
     877             : 
     878             : /*
     879             :  * truncate (external data page).
     880             :  */
     881           1 : storeError OStoreDirectoryPageObject::truncate (
     882             :     sal_uInt32             nPage,
     883             :     OStorePageBIOS        &rBIOS)
     884             : {
     885             :     // Determine scope and link indices.
     886           1 :     page::DataBlock::LinkDescriptor aLink;
     887           1 :     page::ChunkScope eScope = scope (nPage, aLink);
     888             : 
     889           1 :     storeError eErrCode = store_E_None;
     890           1 :     if (eScope == page::SCOPE_DIRECT)
     891             :     {
     892             :         // Truncate all triple indirect pages.
     893           1 :         eErrCode = truncate (page::SCOPE_TRIPLE, 0, rBIOS);
     894           1 :         if (eErrCode != store_E_None)
     895           0 :             return eErrCode;
     896             : 
     897             :         // Truncate all double indirect pages.
     898           1 :         eErrCode = truncate (page::SCOPE_DOUBLE, 0, rBIOS);
     899           1 :         if (eErrCode != store_E_None)
     900           0 :             return eErrCode;
     901             : 
     902             :         // Truncate all single indirect pages.
     903           1 :         eErrCode = truncate (page::SCOPE_SINGLE, 0, rBIOS);
     904           1 :         if (eErrCode != store_E_None)
     905           0 :             return eErrCode;
     906             : 
     907             :         // Truncate direct pages, including 'aLink.m_nIndex0'.
     908           1 :         eErrCode = truncate (eScope, aLink.m_nIndex0, rBIOS);
     909             :     }
     910           0 :     else if (eScope == page::SCOPE_SINGLE)
     911             :     {
     912             :         // Truncate all triple indirect pages.
     913           0 :         eErrCode = truncate (page::SCOPE_TRIPLE, 0, rBIOS);
     914           0 :         if (eErrCode != store_E_None)
     915           0 :             return eErrCode;
     916             : 
     917             :         // Truncate all double indirect pages.
     918           0 :         eErrCode = truncate (page::SCOPE_DOUBLE, 0, rBIOS);
     919           0 :         if (eErrCode != store_E_None)
     920           0 :             return eErrCode;
     921             : 
     922             :         // Truncate single indirect pages, downto 'aLink.m_nIndex1'.
     923           0 :         eErrCode = truncate (eScope, aLink.m_nIndex1 + 1, rBIOS);
     924           0 :         if (eErrCode != store_E_None)
     925           0 :             return eErrCode;
     926             : 
     927             :         // Truncate last single indirect page to ... pages.
     928           0 :         eErrCode = store_truncate_Impl (singleLink (aLink.m_nIndex1), aLink.m_nIndex0, rBIOS);
     929           0 :         if (eErrCode != store_E_None)
     930           0 :             return eErrCode;
     931             : 
     932             :         // Check for complete truncation.
     933           0 :         if (aLink.m_nIndex0 == 0)
     934             :         {
     935             :             // Clear pointer to last single indirect page.
     936           0 :             singleLink (aLink.m_nIndex1, STORE_PAGE_NULL);
     937             :         }
     938             :     }
     939           0 :     else if (eScope == page::SCOPE_DOUBLE)
     940             :     {
     941             :         // Truncate all triple indirect pages.
     942           0 :         eErrCode = truncate (page::SCOPE_TRIPLE, 0, rBIOS);
     943           0 :         if (eErrCode != store_E_None)
     944           0 :             return eErrCode;
     945             : 
     946             :         // Truncate double indirect pages, downto 'aLink.m_nIndex2'.
     947           0 :         eErrCode = truncate (eScope, aLink.m_nIndex2 + 1, rBIOS);
     948           0 :         if (eErrCode != store_E_None)
     949           0 :             return eErrCode;
     950             : 
     951             :         // Truncate last double indirect page to ... pages.
     952             :         eErrCode = store_truncate_Impl (
     953           0 :             doubleLink (aLink.m_nIndex2), aLink.m_nIndex1, aLink.m_nIndex0, rBIOS);
     954           0 :         if (eErrCode != store_E_None)
     955           0 :             return eErrCode;
     956             : 
     957             :         // Check for complete truncation.
     958           0 :         if ((aLink.m_nIndex1 + aLink.m_nIndex0) == 0)
     959             :         {
     960             :             // Clear pointer to last double indirect page.
     961           0 :             doubleLink (aLink.m_nIndex2, STORE_PAGE_NULL);
     962             :         }
     963             :     }
     964           0 :     else if (eScope == page::SCOPE_TRIPLE)
     965             :     {
     966             :         // Truncate triple indirect pages, downto 'aLink.m_nIndex3'.
     967           0 :         eErrCode = truncate (eScope, aLink.m_nIndex3 + 1, rBIOS);
     968           0 :         if (eErrCode != store_E_None)
     969           0 :             return eErrCode;
     970             : 
     971             :         // Truncate last triple indirect page to ... pages.
     972             :         eErrCode = store_truncate_Impl (
     973           0 :             tripleLink (aLink.m_nIndex3), aLink.m_nIndex2, aLink.m_nIndex1, aLink.m_nIndex0, rBIOS);
     974           0 :         if (eErrCode != store_E_None)
     975           0 :             return eErrCode;
     976             : 
     977             :         // Check for complete truncation.
     978           0 :         if ((aLink.m_nIndex2 + aLink.m_nIndex1 + aLink.m_nIndex0) == 0)
     979             :         {
     980             :             // Clear pointer to last triple indirect page.
     981           0 :             tripleLink (aLink.m_nIndex3, STORE_PAGE_NULL);
     982             :         }
     983             :     }
     984           0 :     else if (eScope == page::SCOPE_UNREACHABLE)
     985             :     {
     986             :         // Out of scope.
     987           0 :         eErrCode = store_E_CantSeek;
     988             :     }
     989             :     else
     990             :     {
     991             :         // Unknown scope.
     992             :         OSL_TRACE("OStoreDirectoryPageObject::put(): scope failed");
     993           0 :         eErrCode = store_E_Unknown;
     994             :     }
     995             : 
     996             :     // Leave.
     997           1 :     return eErrCode;
     998             : }
     999             : 
    1000             : /*
    1001             :  * truncate (external data page scope; private).
    1002             :  */
    1003           4 : storeError OStoreDirectoryPageObject::truncate (
    1004             :     page::ChunkScope       eScope,
    1005             :     sal_uInt16             nRemain,
    1006             :     OStorePageBIOS        &rBIOS)
    1007             : {
    1008           4 :     OStoreDirectoryDataBlock const & rDataBlock = PAGE().m_aDataBlock;
    1009             : 
    1010             :     // Enter.
    1011           4 :     storeError eErrCode = store_E_None;
    1012           4 :     if (eScope == page::SCOPE_DIRECT)
    1013             :     {
    1014             :         // Truncate direct data pages.
    1015           1 :         sal_uInt16 i, n = rDataBlock.directCount();
    1016          17 :         for (i = n; i > nRemain; i--)
    1017             :         {
    1018             :             // Obtain data page location.
    1019          16 :             sal_uInt32 nAddr = directLink (i - 1);
    1020          16 :             if (nAddr == STORE_PAGE_NULL) continue;
    1021             : 
    1022             :             // Free data page.
    1023           1 :             eErrCode = rBIOS.free (nAddr);
    1024           1 :             if (eErrCode != store_E_None)
    1025           0 :                 break;
    1026             : 
    1027             :             // Clear pointer to data page.
    1028           1 :             directLink (i - 1, STORE_PAGE_NULL);
    1029             :         }
    1030             : 
    1031             :         // Done.
    1032           1 :         return eErrCode;
    1033             :     }
    1034             : 
    1035           3 :     if (eScope == page::SCOPE_SINGLE)
    1036             :     {
    1037             :         // Truncate single indirect pages.
    1038           1 :         sal_uInt16 i, n = rDataBlock.singleCount();
    1039           9 :         for (i = n; i > nRemain; i--)
    1040             :         {
    1041             :             // Truncate single indirect page to zero data pages.
    1042           8 :             eErrCode = store_truncate_Impl (singleLink (i - 1), 0, rBIOS);
    1043           8 :             if (eErrCode != store_E_None)
    1044           0 :                 break;
    1045             : 
    1046             :             // Clear pointer to single indirect page.
    1047           8 :             singleLink (i - 1, STORE_PAGE_NULL);
    1048             :         }
    1049             : 
    1050             :         // Done.
    1051           1 :         return eErrCode;
    1052             :     }
    1053             : 
    1054           2 :     if (eScope == page::SCOPE_DOUBLE)
    1055             :     {
    1056             :         // Truncate double indirect pages.
    1057           1 :         sal_uInt16 i, n = rDataBlock.doubleCount();
    1058           2 :         for (i = n; i > nRemain; i--)
    1059             :         {
    1060             :             // Truncate double indirect page to zero single indirect pages.
    1061           1 :             eErrCode = store_truncate_Impl (doubleLink (i - 1), 0, 0, rBIOS);
    1062           1 :             if (eErrCode != store_E_None)
    1063           0 :                 break;
    1064             : 
    1065             :             // Clear pointer to double indirect page.
    1066           1 :             doubleLink (i - 1, STORE_PAGE_NULL);
    1067             :         }
    1068             : 
    1069             :         // Done.
    1070           1 :         return eErrCode;
    1071             :     }
    1072             : 
    1073           1 :     if (eScope == page::SCOPE_TRIPLE)
    1074             :     {
    1075             :         // Truncate triple indirect pages.
    1076           1 :         sal_uInt16 i, n = rDataBlock.tripleCount();
    1077           2 :         for (i = n; i > nRemain; i--)
    1078             :         {
    1079             :             // Truncate to zero double indirect pages.
    1080           1 :             eErrCode = store_truncate_Impl (tripleLink (i - 1), 0, 0, 0, rBIOS);
    1081           1 :             if (eErrCode != store_E_None)
    1082           0 :                 break;
    1083             : 
    1084             :             // Clear pointer to triple indirect page.
    1085           1 :             tripleLink (i - 1, STORE_PAGE_NULL);
    1086             :         }
    1087             : 
    1088             :         // Done.
    1089           1 :         return eErrCode;
    1090             :     }
    1091             : 
    1092             :     // Invalid scope.
    1093           0 :     return store_E_InvalidAccess;
    1094             : }
    1095             : 
    1096             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10