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

Generated by: LCOV version 1.11