LCOV - code coverage report
Current view: top level - libreoffice/store/source - storpage.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 103 398 25.9 %
Date: 2012-12-27 Functions: 11 23 47.8 %
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             : 
      21             : #include "storpage.hxx"
      22             : 
      23             : #include "sal/types.h"
      24             : #include "rtl/string.h"
      25             : #include "rtl/ref.hxx"
      26             : #include "osl/diagnose.h"
      27             : #include "osl/mutex.hxx"
      28             : 
      29             : #include "store/types.h"
      30             : 
      31             : #include "object.hxx"
      32             : #include "lockbyte.hxx"
      33             : 
      34             : #include "storbase.hxx"
      35             : #include "stordata.hxx"
      36             : #include "stortree.hxx"
      37             : 
      38             : using namespace store;
      39             : 
      40             : /*========================================================================
      41             :  *
      42             :  * OStorePageManager implementation.
      43             :  *
      44             :  *======================================================================*/
      45             : const sal_uInt32 OStorePageManager::m_nTypeId = sal_uInt32(0x62190120);
      46             : 
      47             : /*
      48             :  * OStorePageManager.
      49             :  */
      50       10724 : OStorePageManager::OStorePageManager (void)
      51             : {
      52       10724 : }
      53             : 
      54             : /*
      55             :  * ~OStorePageManager.
      56             :  */
      57       20922 : OStorePageManager::~OStorePageManager (void)
      58             : {
      59       20922 : }
      60             : 
      61             : /*
      62             :  * isKindOf.
      63             :  */
      64      924061 : sal_Bool SAL_CALL OStorePageManager::isKindOf (sal_uInt32 nTypeId)
      65             : {
      66      924061 :     return (nTypeId == m_nTypeId);
      67             : }
      68             : 
      69             : /*
      70             :  * initialize (two-phase construction).
      71             :  * Precond: none.
      72             :  */
      73       10724 : storeError OStorePageManager::initialize (
      74             :     ILockBytes *    pLockBytes,
      75             :     storeAccessMode eAccessMode,
      76             :     sal_uInt16 &    rnPageSize)
      77             : {
      78             :     // Acquire exclusive access.
      79       10724 :     osl::MutexGuard aGuard(*this);
      80             : 
      81             :     // Check arguments.
      82       10724 :     if (!pLockBytes)
      83           0 :         return store_E_InvalidParameter;
      84             : 
      85             :     // Initialize base.
      86       10724 :     storeError eErrCode = base::initialize (pLockBytes, eAccessMode, rnPageSize);
      87       10724 :     if (eErrCode != store_E_None)
      88           0 :         return eErrCode;
      89             : 
      90             :     // Check for (not) writeable.
      91       10724 :     if (!base::isWriteable())
      92             :     {
      93             :         // Readonly. Load RootNode.
      94        5526 :         return base::loadObjectAt (m_aRoot, rnPageSize);
      95             :     }
      96             : 
      97             :     // Writeable. Load or Create RootNode.
      98        5198 :     eErrCode = m_aRoot.loadOrCreate (rnPageSize, *this);
      99        5198 :     if (eErrCode == store_E_Pending)
     100             :     {
     101             :         // Creation notification.
     102        5198 :         PageHolderObject< page > xRoot (m_aRoot.get());
     103             : 
     104             :         // Pre-allocate left most entry (ugly, but we can't insert to left).
     105        5198 :         OStorePageKey aKey (rtl_crc32 (0, "/", 1), 0);
     106        5198 :         xRoot->insert (0, entry(aKey));
     107             : 
     108             :         // Save RootNode.
     109        5198 :         eErrCode = base::saveObjectAt (m_aRoot, rnPageSize);
     110             :     }
     111             : 
     112             :     // Done.
     113        5198 :     return eErrCode;
     114             : }
     115             : 
     116             : /*
     117             :  * find_lookup (w/o split()).
     118             :  * Internal: Precond: initialized, readable, exclusive access.
     119             :  */
     120      913600 : storeError OStorePageManager::find_lookup (
     121             :     OStoreBTreeNodeObject & rNode,
     122             :     sal_uInt16 &            rIndex,
     123             :     OStorePageKey const &   rKey)
     124             : {
     125             :     // Find Node and Index.
     126      913600 :     storeError eErrCode = m_aRoot.find_lookup (rNode, rIndex, rKey, *this);
     127      913600 :     if (eErrCode != store_E_None)
     128           0 :         return eErrCode;
     129             : 
     130             :     // Greater or Equal.
     131      913600 :     PageHolderObject< page > xPage (rNode.get());
     132             :     OSL_POSTCOND(rIndex < xPage->usageCount(), "store::PageManager::find_lookup(): logic error");
     133      913600 :     entry e (xPage->m_pData[rIndex]);
     134             : 
     135             :     // Check for exact match.
     136      913600 :     if (e.compare(entry(rKey)) != entry::COMPARE_EQUAL)
     137             :     {
     138             :         // Page not present.
     139      468272 :         return store_E_NotExists;
     140             :     }
     141             : 
     142             :     // Check address.
     143      445328 :     if (e.m_aLink.location() == STORE_PAGE_NULL)
     144             :     {
     145             :         // Page not present.
     146        5198 :         return store_E_NotExists;
     147             :     }
     148             : 
     149      440130 :     return store_E_None;
     150             : }
     151             : 
     152             : /*
     153             :  * remove_Impl (possibly down from root).
     154             :  * Internal: Precond: initialized, writeable, exclusive access.
     155             :  */
     156             : 
     157           0 : storeError OStorePageManager::remove_Impl (entry & rEntry)
     158             : {
     159           0 :     OStoreBTreeNodeObject aNode (m_aRoot.get());
     160             : 
     161             :     // Check current page index.
     162           0 :     PageHolderObject< page > xPage (aNode.get());
     163           0 :     sal_uInt16 i = xPage->find (rEntry), n = xPage->usageCount();
     164           0 :     if (!(i < n))
     165             :     {
     166             :         // Path to entry not exists (Must not happen(?)).
     167           0 :         return store_E_NotExists;
     168             :     }
     169             : 
     170             :     // Compare entry.
     171           0 :     entry::CompareResult result = rEntry.compare (xPage->m_pData[i]);
     172             : 
     173             :     // Iterate down until equal match.
     174           0 :     while ((result == entry::COMPARE_GREATER) && (xPage->depth() > 0))
     175             :     {
     176             :         // Check link address.
     177           0 :         sal_uInt32 const nAddr = xPage->m_pData[i].m_aLink.location();
     178           0 :         if (nAddr == STORE_PAGE_NULL)
     179             :         {
     180             :             // Path to entry not exists (Must not happen(?)).
     181           0 :             return store_E_NotExists;
     182             :         }
     183             : 
     184             :         // Load link page.
     185           0 :         storeError eErrCode = loadObjectAt (aNode, nAddr);
     186           0 :         if (eErrCode != store_E_None)
     187           0 :             return eErrCode;
     188             : 
     189           0 :         PageHolderObject< page > xNext (aNode.get());
     190           0 :         xNext.swap (xPage);
     191             : 
     192             :         // Check index.
     193           0 :         i = xPage->find (rEntry), n = xPage->usageCount();
     194           0 :         if (!(i < n))
     195             :         {
     196             :             // Path to entry not exists (Must not happen(?)).
     197           0 :             return store_E_NotExists;
     198             :         }
     199             : 
     200             :         // Compare entry.
     201           0 :         result = rEntry.compare (xPage->m_pData[i]);
     202           0 :     }
     203             : 
     204             :     OSL_POSTCOND(
     205             :         result != entry::COMPARE_LESS,
     206             :         "OStorePageManager::remove(): find failed");
     207             : 
     208             :     // Check entry comparison.
     209           0 :     if (result == entry::COMPARE_LESS)
     210             :     {
     211             :         // Must not happen.
     212           0 :         return store_E_Unknown;
     213             :     }
     214             : 
     215             :     // Remove down from current page (recursive).
     216           0 :     return aNode.remove (i, rEntry, *this);
     217             : }
     218             : 
     219             : /*
     220             :  * namei.
     221             :  * Precond: none (static).
     222             :  */
     223      913600 : storeError OStorePageManager::namei (
     224             :     const rtl_String *pPath, const rtl_String *pName, OStorePageKey &rKey)
     225             : {
     226             :     // Check parameter.
     227      913600 :     if (!(pPath && pName))
     228           0 :         return store_E_InvalidParameter;
     229             : 
     230             :     // Check name length.
     231      913600 :     if (!(pName->length < STORE_MAXIMUM_NAMESIZE))
     232           0 :         return store_E_NameTooLong;
     233             : 
     234             :     // Transform pathname into key.
     235      913600 :     rKey.m_nLow  = store::htonl(rtl_crc32 (0, pName->buffer, pName->length));
     236      913600 :     rKey.m_nHigh = store::htonl(rtl_crc32 (0, pPath->buffer, pPath->length));
     237             : 
     238             :     // Done.
     239      913600 :     return store_E_None;
     240             : }
     241             : 
     242             : /*
     243             :  * iget.
     244             :  * Precond: initialized.
     245             :  */
     246      913600 : storeError OStorePageManager::iget (
     247             :     OStoreDirectoryPageObject & rPage,
     248             :     sal_uInt32                  nAttrib,
     249             :     const rtl_String          * pPath,
     250             :     const rtl_String          * pName,
     251             :     storeAccessMode             eMode)
     252             : {
     253             :     // Acquire exclusive access.
     254      913600 :     osl::MutexGuard aGuard(*this);
     255             : 
     256             :     // Check precond.
     257      913600 :     if (!self::isValid())
     258           0 :         return store_E_InvalidAccess;
     259             : 
     260             :     // Setup inode page key.
     261      913600 :     OStorePageKey aKey;
     262      913600 :     storeError eErrCode = namei (pPath, pName, aKey);
     263      913600 :     if (eErrCode != store_E_None)
     264           0 :         return eErrCode;
     265             : 
     266             :     // Check for directory.
     267      913600 :     if (nAttrib & STORE_ATTRIB_ISDIR)
     268             :     {
     269             :         // Ugly, but necessary (backward compatibility).
     270      666113 :         aKey.m_nLow = store::htonl(rtl_crc32 (store::ntohl(aKey.m_nLow), "/", 1));
     271             :     }
     272             : 
     273             :     // Load inode page.
     274      913600 :     eErrCode = load_dirpage_Impl (aKey, rPage);
     275      913600 :     if (eErrCode != store_E_None)
     276             :     {
     277             :         // Check mode and reason.
     278      473470 :         if (eErrCode != store_E_NotExists)
     279           0 :             return eErrCode;
     280             : 
     281      473470 :         if (eMode == store_AccessReadWrite)
     282       10858 :             return store_E_NotExists;
     283      462612 :         if (eMode == store_AccessReadOnly)
     284      383445 :             return store_E_NotExists;
     285             : 
     286       79167 :         if (!base::isWriteable())
     287           0 :             return store_E_AccessViolation;
     288             : 
     289             :         // Create inode page.
     290       79167 :         eErrCode = rPage.construct< inode >(base::allocator());
     291       79167 :         if (eErrCode != store_E_None)
     292           0 :             return eErrCode;
     293             : 
     294             :         // Setup inode nameblock.
     295       79167 :         PageHolderObject< inode > xPage (rPage.get());
     296             : 
     297       79167 :         rPage.key (aKey);
     298       79167 :         rPage.attrib (nAttrib);
     299             : 
     300             :         memcpy (
     301       79167 :             &(xPage->m_aNameBlock.m_pData[0]),
     302      158334 :             pName->buffer, pName->length);
     303             : 
     304             :         // Save inode page.
     305       79167 :         eErrCode = save_dirpage_Impl (aKey, rPage);
     306       79167 :         if (eErrCode != store_E_None)
     307           0 :             return eErrCode;
     308             :     }
     309             : 
     310             :     // Check for symbolic link.
     311      519297 :     if (rPage.attrib() & STORE_ATTRIB_ISLINK)
     312             :     {
     313             :         // Obtain 'Destination' page key.
     314           0 :         PageHolderObject< inode > xPage (rPage.get());
     315           0 :         OStorePageKey aDstKey;
     316           0 :         memcpy (&aDstKey, &(xPage->m_pData[0]), sizeof(aDstKey));
     317             : 
     318             :         // Load 'Destination' inode.
     319           0 :         eErrCode = load_dirpage_Impl (aDstKey, rPage);
     320           0 :         if (eErrCode != store_E_None)
     321           0 :             return eErrCode;
     322             :     }
     323             : 
     324             :     // Done.
     325      519297 :     return store_E_None;
     326             : }
     327             : 
     328             : /*
     329             :  * iterate.
     330             :  * Precond: initialized.
     331             :  * ToDo: skip hardlink entries.
     332             :  */
     333      238646 : storeError OStorePageManager::iterate (
     334             :     OStorePageKey &  rKey,
     335             :     OStorePageLink & rLink,
     336             :     sal_uInt32 &     rAttrib)
     337             : {
     338             :     // Acquire exclusive access.
     339      238646 :     osl::MutexGuard aGuard(*this);
     340             : 
     341             :     // Check precond.
     342      238646 :     if (!self::isValid())
     343           0 :         return store_E_InvalidAccess;
     344             : 
     345             :     // Find NodePage and Index.
     346      238646 :     OStoreBTreeNodeObject aNode;
     347      238646 :     sal_uInt16 i = 0;
     348      238646 :     storeError eErrCode = m_aRoot.find_lookup (aNode, i, rKey, *this);
     349      238646 :     if (eErrCode != store_E_None)
     350           0 :         return eErrCode;
     351             : 
     352             :     // GreaterEqual. Found next entry.
     353      238646 :     PageHolderObject< page > xNode (aNode.get());
     354      238646 :     entry e (xNode->m_pData[i]);
     355             : 
     356             :     // Setup result.
     357      238646 :     rKey    = e.m_aKey;
     358      238646 :     rLink   = e.m_aLink;
     359      238646 :     rAttrib = store::ntohl(e.m_nAttrib);
     360             : 
     361             :     // Done.
     362      238646 :     return store_E_None;
     363             : }
     364             : 
     365             : /*
     366             :  * load => private: iget() @@@
     367             :  * Internal: Precond: initialized, exclusive access.
     368             :  */
     369      913600 : storeError OStorePageManager::load_dirpage_Impl (
     370             :     const OStorePageKey       &rKey,
     371             :     OStoreDirectoryPageObject &rPage)
     372             : {
     373             :     // Find Node and Index.
     374      913600 :     OStoreBTreeNodeObject aNode;
     375      913600 :     sal_uInt16 i = 0;
     376      913600 :     storeError eErrCode = find_lookup (aNode, i, rKey);
     377      913600 :     if (eErrCode != store_E_None)
     378      473470 :         return eErrCode;
     379             : 
     380             :     // Existing entry. Load page.
     381      440130 :     PageHolderObject< page > xNode (aNode.get());
     382      440130 :     entry e (xNode->m_pData[i]);
     383      440130 :     return loadObjectAt (rPage, e.m_aLink.location());
     384             : }
     385             : 
     386             : /*
     387             :  * save => private: iget(), rebuild() @@@
     388             :  * Internal: Precond: initialized, writeable, exclusive access.
     389             :  */
     390       79167 : storeError OStorePageManager::save_dirpage_Impl (
     391             :     const OStorePageKey       &rKey,
     392             :     OStoreDirectoryPageObject &rPage)
     393             : {
     394             :     // Find NodePage and Index.
     395       79167 :     node aNode;
     396       79167 :     sal_uInt16 i = 0;
     397             : 
     398       79167 :     storeError eErrCode = m_aRoot.find_insert (aNode, i, rKey, *this);
     399       79167 :     PageHolderObject< page > xNode (aNode.get());
     400       79167 :     if (eErrCode != store_E_None)
     401             :     {
     402        5198 :         if (eErrCode != store_E_AlreadyExists)
     403           0 :             return eErrCode;
     404             : 
     405             :         // Existing entry.
     406        5198 :         entry e (xNode->m_pData[i]);
     407        5198 :         if (e.m_aLink.location() != STORE_PAGE_NULL)
     408             :         {
     409             :             // Save page to existing location.
     410           0 :             return saveObjectAt (rPage, e.m_aLink.location());
     411             :         }
     412             : 
     413             :         // Allocate page.
     414        5198 :         eErrCode = base::allocate (rPage);
     415        5198 :         if (eErrCode != store_E_None)
     416           0 :             return eErrCode;
     417             : 
     418             :         // Update page location.
     419        5198 :         xNode->m_pData[i].m_aLink = rPage.location();
     420             : 
     421             :         // Save modified NodePage.
     422        5198 :         return saveObjectAt (aNode, aNode.location());
     423             :     }
     424             : 
     425             :     // Allocate page.
     426       73969 :     eErrCode = base::allocate (rPage);
     427       73969 :     if (eErrCode != store_E_None)
     428           0 :         return eErrCode;
     429             : 
     430             :     // Insert.
     431       73969 :     OStorePageLink aLink (rPage.location());
     432       73969 :     xNode->insert (i + 1, entry (rKey, aLink));
     433             : 
     434             :     // Save modified NodePage.
     435       73969 :     return saveObjectAt (aNode, aNode.location());
     436             : }
     437             : 
     438             : /*
     439             :  * attrib [nAttrib = ((nAttrib & ~nMask1) | nMask2)].
     440             :  * Precond: initialized.
     441             :  */
     442           0 : storeError OStorePageManager::attrib (
     443             :     const OStorePageKey &rKey,
     444             :     sal_uInt32           nMask1,
     445             :     sal_uInt32           nMask2,
     446             :     sal_uInt32          &rAttrib)
     447             : {
     448             :     // Acquire exclusive access.
     449           0 :     osl::MutexGuard aGuard(*this);
     450             : 
     451             :     // Check precond.
     452           0 :     if (!self::isValid())
     453           0 :         return store_E_InvalidAccess;
     454             : 
     455             :     // Find NodePage and index.
     456           0 :     OStoreBTreeNodeObject aNode;
     457           0 :     sal_uInt16 i = 0;
     458           0 :     storeError eErrCode = find_lookup (aNode, i, rKey);
     459           0 :     if (eErrCode != store_E_None)
     460           0 :         return eErrCode;
     461             : 
     462             :     // Existing entry.
     463           0 :     PageHolderObject< page > xNode (aNode.get());
     464           0 :     entry e (xNode->m_pData[i]);
     465           0 :     if (nMask1 != nMask2)
     466             :     {
     467             :         // Evaluate new attributes.
     468           0 :         sal_uInt32 nAttrib = store::ntohl(e.m_nAttrib);
     469             : 
     470           0 :         nAttrib &= ~nMask1;
     471           0 :         nAttrib |=  nMask2;
     472             : 
     473           0 :         if (store::htonl(nAttrib) != e.m_nAttrib)
     474             :         {
     475             :             // Check access mode.
     476           0 :             if (base::isWriteable())
     477             :             {
     478             :                 // Set new attributes.
     479           0 :                 e.m_nAttrib = store::htonl(nAttrib);
     480           0 :                 xNode->m_pData[i] = e;
     481             : 
     482             :                 // Save modified NodePage.
     483           0 :                 eErrCode = saveObjectAt (aNode, aNode.location());
     484             :             }
     485             :             else
     486             :             {
     487             :                 // Access denied.
     488           0 :                 eErrCode = store_E_AccessViolation;
     489             :             }
     490             :         }
     491             :     }
     492             : 
     493             :     // Obtain current attributes.
     494           0 :     rAttrib = store::ntohl(e.m_nAttrib);
     495           0 :     return eErrCode;
     496             : }
     497             : 
     498             : /*
     499             :  * link (insert 'Source' as hardlink to 'Destination').
     500             :  * Precond: initialized, writeable.
     501             :  */
     502           0 : storeError OStorePageManager::link (
     503             :     const OStorePageKey &rSrcKey,
     504             :     const OStorePageKey &rDstKey)
     505             : {
     506             :     // Acquire exclusive access.
     507           0 :     osl::MutexGuard aGuard(*this);
     508             : 
     509             :     // Check precond.
     510           0 :     if (!self::isValid())
     511           0 :         return store_E_InvalidAccess;
     512             : 
     513           0 :     if (!base::isWriteable())
     514           0 :         return store_E_AccessViolation;
     515             : 
     516             :     // Find 'Destination' NodePage and Index.
     517           0 :     OStoreBTreeNodeObject aDstNode;
     518           0 :     sal_uInt16 i = 0;
     519           0 :     storeError eErrCode = find_lookup (aDstNode, i, rDstKey);
     520           0 :     if (eErrCode != store_E_None)
     521           0 :         return eErrCode;
     522             : 
     523             :     // Existing 'Destination' entry.
     524           0 :     PageHolderObject< page > xDstNode (aDstNode.get());
     525           0 :     entry e (xDstNode->m_pData[i]);
     526           0 :     OStorePageLink aDstLink (e.m_aLink);
     527             : 
     528             :     // Find 'Source' NodePage and Index.
     529           0 :     OStoreBTreeNodeObject aSrcNode;
     530           0 :     eErrCode = m_aRoot.find_insert (aSrcNode, i, rSrcKey, *this);
     531           0 :     if (eErrCode != store_E_None)
     532           0 :         return eErrCode;
     533             : 
     534             :     // Insert 'Source' entry.
     535           0 :     PageHolderObject< page > xSrcNode (aSrcNode.get());
     536           0 :     xSrcNode->insert (i + 1, entry (rSrcKey, aDstLink, STORE_ATTRIB_ISLINK));
     537           0 :     return saveObjectAt (aSrcNode, aSrcNode.location());
     538             : }
     539             : 
     540             : /*
     541             :  * symlink (insert 'Source' DirectoryPage as symlink to 'Destination').
     542             :  * Precond: initialized, writeable.
     543             :  */
     544           0 : storeError OStorePageManager::symlink (
     545             :     const rtl_String    *pSrcPath,
     546             :     const rtl_String    *pSrcName,
     547             :     const OStorePageKey &rDstKey)
     548             : {
     549             :     // Acquire exclusive access.
     550           0 :     osl::MutexGuard aGuard(*this);
     551             : 
     552             :     // Check precond.
     553           0 :     if (!self::isValid())
     554           0 :         return store_E_InvalidAccess;
     555             : 
     556           0 :     if (!base::isWriteable())
     557           0 :         return store_E_AccessViolation;
     558             : 
     559             :     // Check 'Source' parameter.
     560           0 :     storeError eErrCode = store_E_InvalidParameter;
     561           0 :     if (!(pSrcPath && pSrcName))
     562           0 :         return eErrCode;
     563             : 
     564             :     // Setup 'Source' page key.
     565           0 :     OStorePageKey aSrcKey;
     566           0 :     eErrCode = namei (pSrcPath, pSrcName, aSrcKey);
     567           0 :     if (eErrCode != store_E_None)
     568           0 :         return eErrCode;
     569             : 
     570             :     // Find 'Source' NodePage and Index.
     571           0 :     OStoreBTreeNodeObject aSrcNode;
     572           0 :     sal_uInt16 i = 0;
     573           0 :     eErrCode = m_aRoot.find_insert (aSrcNode, i, aSrcKey, *this);
     574           0 :     if (eErrCode != store_E_None)
     575           0 :         return eErrCode;
     576             : 
     577             :     // Initialize directory page.
     578           0 :     OStoreDirectoryPageObject aPage;
     579           0 :     eErrCode = aPage.construct< inode >(base::allocator());
     580           0 :     if (eErrCode != store_E_None)
     581           0 :         return eErrCode;
     582             : 
     583             :     // Setup as 'Source' directory page.
     584           0 :     inode_holder_type xNode (aPage.get());
     585           0 :     aPage.key (aSrcKey);
     586             :     memcpy (
     587           0 :         &(xNode->m_aNameBlock.m_pData[0]),
     588           0 :         pSrcName->buffer, pSrcName->length);
     589             : 
     590             :     // Store 'Destination' page key.
     591           0 :     OStorePageKey aDstKey (rDstKey);
     592           0 :     memcpy (&(xNode->m_pData[0]), &aDstKey, sizeof(aDstKey));
     593             : 
     594             :     // Mark 'Source' as symbolic link to 'Destination'.
     595           0 :     aPage.attrib (STORE_ATTRIB_ISLINK);
     596           0 :     aPage.dataLength (sal_uInt32(sizeof(aDstKey)));
     597             : 
     598             :     // Allocate and save 'Source' directory page.
     599           0 :     eErrCode = base::allocate (aPage);
     600           0 :     if (eErrCode != store_E_None)
     601           0 :         return eErrCode;
     602             : 
     603             :     // Insert 'Source' entry.
     604           0 :     PageHolderObject< page > xSrcNode (aSrcNode.get());
     605           0 :     OStorePageLink aSrcLink (aPage.location());
     606           0 :     xSrcNode->insert (i + 1, entry(aSrcKey, aSrcLink));
     607             : 
     608             :     // Save modified NodePage.
     609           0 :     return saveObjectAt (aSrcNode, aSrcNode.location());
     610             : }
     611             : 
     612             : /*
     613             :  * rename.
     614             :  * Precond: initialized, writeable.
     615             :  */
     616           0 : storeError OStorePageManager::rename (
     617             :     const OStorePageKey &rSrcKey,
     618             :     const rtl_String    *pDstPath,
     619             :     const rtl_String    *pDstName)
     620             : {
     621             :     // Acquire exclusive access.
     622           0 :     osl::MutexGuard aGuard(*this);
     623             : 
     624             :     // Check precond.
     625           0 :     if (!self::isValid())
     626           0 :         return store_E_InvalidAccess;
     627             : 
     628           0 :     if (!base::isWriteable())
     629           0 :         return store_E_AccessViolation;
     630             : 
     631             :     // Check 'Destination' parameter.
     632           0 :     storeError eErrCode = store_E_InvalidParameter;
     633           0 :     if (!(pDstPath && pDstName))
     634           0 :         return eErrCode;
     635             : 
     636             :     // Setup 'Destination' page key.
     637           0 :     OStorePageKey aDstKey;
     638           0 :     eErrCode = namei (pDstPath, pDstName, aDstKey);
     639           0 :     if (eErrCode != store_E_None)
     640           0 :         return eErrCode;
     641             : 
     642             :     // Find 'Source' NodePage and Index.
     643           0 :     OStoreBTreeNodeObject aSrcNode;
     644           0 :     sal_uInt16 i = 0;
     645           0 :     eErrCode = find_lookup (aSrcNode, i, rSrcKey);
     646           0 :     if (eErrCode != store_E_None)
     647           0 :         return eErrCode;
     648             : 
     649             :     // Existing 'Source' entry.
     650           0 :     PageHolderObject< page > xSrcNode (aSrcNode.get());
     651           0 :     entry e (xSrcNode->m_pData[i]);
     652             : 
     653             :     // Check for (not a) hardlink.
     654           0 :     OStoreDirectoryPageObject aPage;
     655           0 :     if (!(store::ntohl(e.m_nAttrib) & STORE_ATTRIB_ISLINK))
     656             :     {
     657             :         // Load directory page.
     658           0 :         eErrCode = base::loadObjectAt (aPage, e.m_aLink.location());
     659           0 :         if (eErrCode != store_E_None)
     660           0 :             return eErrCode;
     661             : 
     662             :         // Check for directory.
     663           0 :         if (aPage.attrib() & STORE_ATTRIB_ISDIR)
     664             :         {
     665             :             // Ugly, but necessary (backward compatibility).
     666           0 :             aDstKey.m_nLow = store::htonl(rtl_crc32 (store::ntohl(aDstKey.m_nLow), "/", 1));
     667             :         }
     668             :     }
     669             : 
     670             :     // Let 'Source' entry be 'Destination' entry.
     671           0 :     e.m_aKey = aDstKey;
     672             : 
     673             :     // Find 'Destination' NodePage and Index.
     674           0 :     OStoreBTreeNodeObject aDstNode;
     675           0 :     eErrCode = m_aRoot.find_insert (aDstNode, i, e.m_aKey, *this);
     676           0 :     if (eErrCode != store_E_None)
     677           0 :         return eErrCode;
     678             : 
     679             :     // Insert 'Destination' entry.
     680           0 :     PageHolderObject< page > xDstNode (aDstNode.get());
     681           0 :     xDstNode->insert (i + 1, e);
     682             : 
     683           0 :     eErrCode = saveObjectAt (aDstNode, aDstNode.location());
     684           0 :     if (eErrCode != store_E_None)
     685           0 :         return eErrCode;
     686             : 
     687             :     // Check for (not a) hardlink.
     688           0 :     if (!(store::ntohl(e.m_nAttrib) & STORE_ATTRIB_ISLINK))
     689             :     {
     690             :         // Modify 'Source' directory page.
     691           0 :         inode_holder_type xNode (aPage.get());
     692             : 
     693             :         // Setup 'Destination' NameBlock.
     694           0 :         sal_Int32 nDstLen = pDstName->length;
     695             :         memcpy (
     696           0 :             &(xNode->m_aNameBlock.m_pData[0]),
     697           0 :             pDstName->buffer, pDstName->length);
     698             :         memset (
     699           0 :             &(xNode->m_aNameBlock.m_pData[nDstLen]),
     700           0 :             0, STORE_MAXIMUM_NAMESIZE - nDstLen);
     701           0 :         aPage.key (e.m_aKey);
     702             : 
     703             :         // Save directory page.
     704           0 :         eErrCode = base::saveObjectAt (aPage, e.m_aLink.location());
     705           0 :         if (eErrCode != store_E_None)
     706           0 :             return eErrCode;
     707             :     }
     708             : 
     709             :     // Remove 'Source' entry.
     710           0 :     e.m_aKey = rSrcKey;
     711           0 :     return remove_Impl (e);
     712             : }
     713             : 
     714             : /*
     715             :  * remove.
     716             :  * Precond: initialized, writeable.
     717             :  */
     718           0 : storeError OStorePageManager::remove (const OStorePageKey &rKey)
     719             : {
     720             :     // Acquire exclusive access.
     721           0 :     osl::MutexGuard aGuard(*this);
     722             : 
     723             :     // Check precond.
     724           0 :     if (!self::isValid())
     725           0 :         return store_E_InvalidAccess;
     726             : 
     727           0 :     if (!base::isWriteable())
     728           0 :         return store_E_AccessViolation;
     729             : 
     730             :     // Find NodePage and index.
     731           0 :     OStoreBTreeNodeObject aNodePage;
     732           0 :     sal_uInt16 i = 0;
     733           0 :     storeError eErrCode = find_lookup (aNodePage, i, rKey);
     734           0 :     if (eErrCode != store_E_None)
     735           0 :         return eErrCode;
     736             : 
     737             :     // Existing entry.
     738           0 :     PageHolderObject< page > xNodePage (aNodePage.get());
     739           0 :     entry e (xNodePage->m_pData[i]);
     740             : 
     741             :     // Check for (not a) hardlink.
     742           0 :     if (!(store::ntohl(e.m_nAttrib) & STORE_ATTRIB_ISLINK))
     743             :     {
     744             :         // Load directory page.
     745           0 :         OStoreDirectoryPageObject aPage;
     746           0 :         eErrCode = base::loadObjectAt (aPage, e.m_aLink.location());
     747           0 :         if (eErrCode != store_E_None)
     748           0 :             return eErrCode;
     749             : 
     750           0 :         inode_holder_type xNode (aPage.get());
     751             : 
     752             :         // Acquire page write access.
     753           0 :         OStorePageDescriptor aDescr (xNode->m_aDescr);
     754           0 :         eErrCode = base::acquirePage (aDescr, store_AccessReadWrite);
     755           0 :         if (eErrCode != store_E_None)
     756           0 :             return eErrCode;
     757             : 
     758             :         // Check for symbolic link.
     759           0 :         if (!(aPage.attrib() & STORE_ATTRIB_ISLINK))
     760             :         {
     761             :             // Ordinary inode. Determine 'Data' scope.
     762           0 :             inode::ChunkScope eScope = xNode->scope (aPage.dataLength());
     763           0 :             if (eScope == inode::SCOPE_EXTERNAL)
     764             :             {
     765             :                 // External 'Data' scope. Truncate all external data pages.
     766           0 :                 eErrCode = aPage.truncate (0, *this);
     767           0 :                 if (eErrCode != store_E_None)
     768           0 :                     return eErrCode;
     769             :             }
     770             : 
     771             :             // Truncate internal data page.
     772           0 :             memset (&(xNode->m_pData[0]), 0, xNode->capacity());
     773           0 :             aPage.dataLength (0);
     774             :         }
     775             : 
     776             :         // Release page write access.
     777           0 :         eErrCode = base::releasePage (aDescr);
     778             : 
     779             :         // Release and free directory page.
     780           0 :         eErrCode = base::free (aPage.location());
     781             :     }
     782             : 
     783             :     // Remove entry.
     784           0 :     return remove_Impl (e);
     785             : }
     786             : 
     787             : /*
     788             :  * RebuildContext.
     789             :  */
     790           0 : struct RebuildContext
     791             : {
     792             :     /** Representation.
     793             :     */
     794             :     rtl::Reference<OStorePageBIOS> m_xBIOS;
     795             :     OStorePageBIOS::ScanContext    m_aCtx;
     796             :     sal_uInt16                     m_nPageSize;
     797             : 
     798             :     /** Construction.
     799             :      */
     800           0 :     RebuildContext (void)
     801           0 :         : m_xBIOS     (new OStorePageBIOS()),
     802           0 :           m_nPageSize (0)
     803           0 :     {}
     804             : 
     805             :     /** initialize (PageBIOS and ScanContext).
     806             :     */
     807           0 :     storeError initialize (ILockBytes *pLockBytes, sal_uInt32 nMagic = 0)
     808             :     {
     809           0 :         storeError eErrCode = store_E_InvalidParameter;
     810           0 :         if (pLockBytes)
     811             :         {
     812           0 :             m_xBIOS->initialize (pLockBytes, store_AccessReadOnly, m_nPageSize);
     813           0 :             eErrCode = m_xBIOS->scanBegin (m_aCtx, nMagic);
     814             :         }
     815           0 :         return eErrCode;
     816             :     }
     817             : 
     818             :     /** initialize (ScanContext).
     819             :     */
     820           0 :     storeError initialize (sal_uInt32 nMagic = 0)
     821             :     {
     822           0 :         return m_xBIOS->scanBegin (m_aCtx, nMagic);
     823             :     }
     824             : 
     825             :     /** load (next ScanContext matching page).
     826             :     */
     827           0 :     storeError load (OStorePageObject &rPage)
     828             :     {
     829           0 :         if (m_aCtx.isValid())
     830           0 :             return m_xBIOS->scanNext (m_aCtx, rPage);
     831             :         else
     832           0 :             return store_E_CantSeek;
     833             :     }
     834             : };
     835             : 
     836             : /*
     837             :  * rebuild.
     838             :  * Precond: none.
     839             :  */
     840           0 : storeError OStorePageManager::rebuild (
     841             :     ILockBytes *pSrcLB, ILockBytes *pDstLB)
     842             : {
     843             :     // Acquire exclusive access.
     844           0 :     osl::MutexGuard aGuard(*this);
     845             : 
     846             :     // Check arguments.
     847           0 :     storeError eErrCode = store_E_InvalidParameter;
     848           0 :     if (!(pSrcLB && pDstLB))
     849           0 :         return eErrCode;
     850             : 
     851             :     // Initialize 'Source' rebuild context.
     852           0 :     RebuildContext aCtx;
     853           0 :     eErrCode = aCtx.initialize (pSrcLB, STORE_MAGIC_DIRECTORYPAGE);
     854           0 :     if (eErrCode != store_E_None)
     855           0 :         return eErrCode;
     856           0 :     rtl::Reference<OStorePageBIOS> xSrcBIOS (aCtx.m_xBIOS);
     857             : 
     858             :     // Initialize as 'Destination' with 'Source' page size.
     859           0 :     eErrCode = self::initialize (pDstLB, store_AccessCreate, aCtx.m_nPageSize);
     860           0 :     if (eErrCode != store_E_None)
     861           0 :         return eErrCode;
     862             : 
     863             :     // Pass One: Scan 'Source' directory pages.
     864             :     {
     865             :         // Scan 'Source' directory pages.
     866           0 :         OStoreDirectoryPageObject aSrcPage;
     867           0 :         while ((eErrCode = aCtx.load(aSrcPage)) == store_E_None)
     868             :         {
     869           0 :             OStoreDirectoryPageObject aDstPage;
     870           0 :             eErrCode = aDstPage.construct< inode >(base::allocator());
     871           0 :             if (eErrCode != store_E_None)
     872             :                 break;
     873             : 
     874           0 :             inode_holder_type xSrcDir (aSrcPage.get());
     875           0 :             inode_holder_type xDstDir (aDstPage.get());
     876             : 
     877             :             // Copy NameBlock @@@ OLD @@@
     878           0 :             memcpy (&(xDstDir->m_aNameBlock), &(xSrcDir->m_aNameBlock), sizeof(xSrcDir->m_aNameBlock));
     879             : 
     880             :             // Obtain 'Source' data length.
     881           0 :             sal_uInt32 nDataLen = aSrcPage.dataLength();
     882           0 :             if (nDataLen > 0)
     883             :             {
     884             :                 // Copy internal data area @@@ OLD @@@
     885           0 :                 memcpy (&(xDstDir->m_pData[0]), &(xSrcDir->m_pData[0]), xSrcDir->capacity());
     886             :             }
     887             : 
     888             :             // Insert 'Destination' directory page.
     889           0 :             eErrCode = save_dirpage_Impl (aDstPage.key(), aDstPage);
     890           0 :             if (eErrCode != store_E_None)
     891             :                 break;
     892             : 
     893             :             // Check for external data page scope.
     894           0 :             if (xSrcDir->scope(nDataLen) != inode::SCOPE_INTERNAL)
     895             :             {
     896             :                 // Initialize 'Destination' data page.
     897             :                 typedef OStoreDataPageData data;
     898           0 :                 PageHolderObject< data > xData;
     899           0 :                 if (!xData.construct(base::allocator()))
     900           0 :                     return store_E_OutOfMemory;
     901             : 
     902             :                 // Determine data page count.
     903             :                 inode::ChunkDescriptor aDescr (
     904           0 :                     nDataLen - xDstDir->capacity(), xData->capacity());
     905             : 
     906           0 :                 sal_uInt32 i, n = aDescr.m_nPage;
     907           0 :                 if (aDescr.m_nOffset) n += 1;
     908             : 
     909             :                 // Copy data pages.
     910           0 :                 OStoreDataPageObject aData;
     911           0 :                 for (i = 0; i < n; i++)
     912             :                 {
     913             :                     // Read 'Source' data page.
     914           0 :                     osl::MutexGuard aSrcGuard (*xSrcBIOS);
     915             : 
     916           0 :                     eErrCode = aSrcPage.read (i, aData, *xSrcBIOS);
     917           0 :                     if (eErrCode != store_E_None)
     918           0 :                         continue;
     919             : 
     920             :                     // Write 'Destination' data page. @@@ READONLY @@@
     921           0 :                     eErrCode = aDstPage.write (i, aData, *this);
     922           0 :                 }
     923             :             }
     924             : 
     925             :             // Update 'Destination' directory page.
     926           0 :             aDstPage.dataLength (nDataLen);
     927           0 :             eErrCode = base::saveObjectAt (aDstPage, aDstPage.location());
     928           0 :         }
     929             : 
     930             :         // Save directory scan results.
     931           0 :         flush();
     932             :     }
     933             : 
     934             :     // Pass Two: Scan 'Source' BTree nodes.
     935             :     {
     936             :         // Re-start 'Source' rebuild context.
     937           0 :         aCtx.initialize (STORE_MAGIC_BTREENODE);
     938             : 
     939             :         // Scan 'Source' BTree nodes.
     940           0 :         OStoreBTreeNodeObject aNode;
     941           0 :         while ((eErrCode = aCtx.load(aNode)) == store_E_None)
     942             :         {
     943             :             // Check for leaf node.
     944           0 :             PageHolderObject< page > xNode (aNode.get());
     945           0 :             if (xNode->depth() == 0)
     946             :             {
     947           0 :                 sal_uInt16 i, n = xNode->usageCount();
     948           0 :                 for (i = 0; i < n; i++)
     949             :                 {
     950           0 :                     entry e (xNode->m_pData[i]);
     951             : 
     952             :                     // Check for Hard link.
     953           0 :                     if (e.m_nAttrib & STORE_ATTRIB_ISLINK)
     954             :                     {
     955             :                         // Load the hard link destination.
     956           0 :                         OStoreDirectoryPageObject aSrcPage;
     957           0 :                         eErrCode = xSrcBIOS->loadObjectAt (aSrcPage, e.m_aLink.location());
     958           0 :                         if (eErrCode == store_E_None)
     959             :                         {
     960           0 :                             OStorePageKey aDstKey (aSrcPage.key());
     961           0 :                             eErrCode = link (e.m_aKey, aDstKey);
     962             :                         }
     963           0 :                         e.m_nAttrib &= ~STORE_ATTRIB_ISLINK;
     964             :                     }
     965             : 
     966           0 :                     if (e.m_nAttrib)
     967             :                     {
     968             :                         // Ordinary attributes.
     969           0 :                         sal_uInt32 nAttrib = 0;
     970           0 :                         eErrCode = attrib (e.m_aKey, 0, e.m_nAttrib, nAttrib);
     971             :                     }
     972             :                 }
     973             :             }
     974           0 :         }
     975             : 
     976             :         // Save BTree node scan results.
     977           0 :         flush();
     978             :     }
     979             : 
     980             :     // Done.
     981           0 :     return store_E_None;
     982             : }
     983             : 
     984             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10