diff options
Diffstat (limited to 'store/source/stordata.cxx')
-rw-r--r-- | store/source/stordata.cxx | 1095 |
1 files changed, 1095 insertions, 0 deletions
diff --git a/store/source/stordata.cxx b/store/source/stordata.cxx new file mode 100644 index 000000000..7ce39a9c1 --- /dev/null +++ b/store/source/stordata.cxx @@ -0,0 +1,1095 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "stordata.hxx" + +#include <sal/types.h> +#include <sal/log.hxx> + +#include <store/types.h> +#include "storbase.hxx" +#include "storbios.hxx" + +using namespace store; + +/*======================================================================== + * + * OStoreDataPageObject implementation. + * + *======================================================================*/ +/* + * guard. + */ +storeError OStoreDataPageObject::guard (sal_uInt32 nAddr) +{ + return PageHolderObject< page >::guard (m_xPage, nAddr); +} + +/* + * verify. + */ +storeError OStoreDataPageObject::verify (sal_uInt32 nAddr) const +{ + return PageHolderObject< page >::verify (m_xPage, nAddr); +} + +/*======================================================================== + * + * OStoreIndirectionPageObject implementation. + * + *======================================================================*/ +/* + * store_truncate_Impl (single indirect page). + */ +static storeError store_truncate_Impl ( + sal_uInt32 nAddr, + sal_uInt16 nSingle, + OStorePageBIOS &rBIOS) +{ + if (nAddr != STORE_PAGE_NULL) + { + // Load single indirect page. + OStoreIndirectionPageObject aSingle; + storeError eErrCode = rBIOS.loadObjectAt (aSingle, nAddr); + if (eErrCode == store_E_None) + { + // Truncate to 'nSingle' direct pages. + eErrCode = aSingle.truncate (nSingle, rBIOS); + if (eErrCode != store_E_None) + return eErrCode; + } + else + { + if (eErrCode != store_E_InvalidChecksum) + return eErrCode; + } + + // Check for complete truncation. + if (nSingle == 0) + { + // Free single indirect page. + eErrCode = rBIOS.free (nAddr); + if (eErrCode != store_E_None) + return eErrCode; + } + } + return store_E_None; +} + +/* + * store_truncate_Impl (double indirect page). + */ +static storeError store_truncate_Impl ( + sal_uInt32 nAddr, + sal_uInt16 nDouble, + sal_uInt16 nSingle, + OStorePageBIOS &rBIOS) +{ + if (nAddr != STORE_PAGE_NULL) + { + // Load double indirect page. + OStoreIndirectionPageObject aDouble; + storeError eErrCode = rBIOS.loadObjectAt (aDouble, nAddr); + if (eErrCode == store_E_None) + { + // Truncate to 'nDouble', 'nSingle' pages. + eErrCode = aDouble.truncate (nDouble, nSingle, rBIOS); + if (eErrCode != store_E_None) + return eErrCode; + } + else + { + if (eErrCode != store_E_InvalidChecksum) + return eErrCode; + } + + // Check for complete truncation. + if ((nDouble + nSingle) == 0) + { + // Free double indirect page. + eErrCode = rBIOS.free (nAddr); + if (eErrCode != store_E_None) + return eErrCode; + } + } + return store_E_None; +} + +/* + * store_truncate_Impl (triple indirect page). + */ +static storeError store_truncate_Impl ( + sal_uInt32 nAddr, + sal_uInt16 nTriple, + sal_uInt16 nDouble, + sal_uInt16 nSingle, + OStorePageBIOS &rBIOS) +{ + if (nAddr != STORE_PAGE_NULL) + { + // Load triple indirect page. + OStoreIndirectionPageObject aTriple; + storeError eErrCode = rBIOS.loadObjectAt (aTriple, nAddr); + if (eErrCode != store_E_None) + return eErrCode; + + // Truncate to 'nTriple', 'nDouble', 'nSingle' pages. + eErrCode = aTriple.truncate (nTriple, nDouble, nSingle, rBIOS); + if (eErrCode != store_E_None) + return eErrCode; + + // Check for complete truncation. + if ((nTriple + nDouble + nSingle) == 0) + { + // Free triple indirect page. + eErrCode = rBIOS.free (nAddr); + if (eErrCode != store_E_None) + return eErrCode; + } + } + return store_E_None; +} + +/* + * loadOrCreate. + */ +storeError OStoreIndirectionPageObject::loadOrCreate ( + sal_uInt32 nAddr, + OStorePageBIOS & rBIOS) +{ + if (nAddr == STORE_PAGE_NULL) + { + storeError eErrCode = construct<page>(rBIOS.allocator()); + if (eErrCode != store_E_None) + return eErrCode; + + eErrCode = rBIOS.allocate (*this); + if (eErrCode != store_E_None) + return eErrCode; + + // Save location pending at caller. + return store_E_Pending; + } + return rBIOS.loadObjectAt (*this, nAddr); +} + +/* + * guard. + */ +storeError OStoreIndirectionPageObject::guard (sal_uInt32 nAddr) +{ + return PageHolderObject< page >::guard (m_xPage, nAddr); +} + +/* + * verify. + */ +storeError OStoreIndirectionPageObject::verify (sal_uInt32 nAddr) const +{ + return PageHolderObject< page >::verify (m_xPage, nAddr); +} + +/* + * read (single indirect). + */ +storeError OStoreIndirectionPageObject::read ( + sal_uInt16 nSingle, + OStoreDataPageObject &rData, + OStorePageBIOS &rBIOS) const +{ + PageHolderObject< page > xImpl (m_xPage); + page const & rPage = *xImpl; + + // Check arguments. + sal_uInt16 const nLimit = rPage.capacityCount(); + if (nSingle >= nLimit) + return store_E_InvalidAccess; + + // Obtain data page location. + sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nSingle]); + if (nAddr == STORE_PAGE_NULL) + return store_E_NotExists; + + // Load data page and leave. + return rBIOS.loadObjectAt (rData, nAddr); +} + +/* + * read (double indirect). + */ +storeError OStoreIndirectionPageObject::read ( + sal_uInt16 nDouble, + sal_uInt16 nSingle, + OStoreDataPageObject &rData, + OStorePageBIOS &rBIOS) const +{ + PageHolderObject< page > xImpl (m_xPage); + page const & rPage = *xImpl; + + // Check arguments. + sal_uInt16 const nLimit = rPage.capacityCount(); + if (!((nDouble < nLimit) && (nSingle < nLimit))) + return store_E_InvalidAccess; + + // Check single indirect page location. + sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nDouble]); + if (nAddr == STORE_PAGE_NULL) + return store_E_NotExists; + + // Load single indirect page. + OStoreIndirectionPageObject aSingle; + storeError eErrCode = rBIOS.loadObjectAt (aSingle, nAddr); + if (eErrCode != store_E_None) + return eErrCode; + + // Read single indirect and leave. + return aSingle.read (nSingle, rData, rBIOS); +} + +/* + * read (triple indirect). + */ +storeError OStoreIndirectionPageObject::read ( + sal_uInt16 nTriple, + sal_uInt16 nDouble, + sal_uInt16 nSingle, + OStoreDataPageObject &rData, + OStorePageBIOS &rBIOS) const +{ + PageHolderObject< page > xImpl (m_xPage); + page const & rPage = *xImpl; + + // Check arguments. + sal_uInt16 const nLimit = rPage.capacityCount(); + if (!((nTriple < nLimit) && (nDouble < nLimit) && (nSingle < nLimit))) + return store_E_InvalidAccess; + + // Check double indirect page location. + sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nTriple]); + if (nAddr == STORE_PAGE_NULL) + return store_E_NotExists; + + // Load double indirect page. + OStoreIndirectionPageObject aDouble; + storeError eErrCode = rBIOS.loadObjectAt (aDouble, nAddr); + if (eErrCode != store_E_None) + return eErrCode; + + // Read double indirect and leave. + return aDouble.read (nDouble, nSingle, rData, rBIOS); +} + +/* + * write (single indirect). + */ +storeError OStoreIndirectionPageObject::write ( + sal_uInt16 nSingle, + OStoreDataPageObject &rData, + OStorePageBIOS &rBIOS) +{ + PageHolderObject< page > xImpl (m_xPage); + page & rPage = *xImpl; + + // Check arguments. + sal_uInt16 const nLimit = rPage.capacityCount(); + if (nSingle >= nLimit) + return store_E_InvalidAccess; + + // Obtain data page location. + sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nSingle]); + if (nAddr == STORE_PAGE_NULL) + { + // Allocate data page. + storeError eErrCode = rBIOS.allocate (rData); + if (eErrCode != store_E_None) + return eErrCode; + + // Store data page location. + rPage.m_pData[nSingle] = store::htonl(rData.location()); + + // Save this page. + return rBIOS.saveObjectAt (*this, location()); + } + else + { + // Save data page. + return rBIOS.saveObjectAt (rData, nAddr); + } +} + +/* + * write (double indirect). + */ +storeError OStoreIndirectionPageObject::write ( + sal_uInt16 nDouble, + sal_uInt16 nSingle, + OStoreDataPageObject &rData, + OStorePageBIOS &rBIOS) +{ + PageHolderObject< page > xImpl (m_xPage); + page & rPage = *xImpl; + + // Check arguments. + sal_uInt16 const nLimit = rPage.capacityCount(); + if (!((nDouble < nLimit) && (nSingle < nLimit))) + return store_E_InvalidAccess; + + // Load or create single indirect page. + OStoreIndirectionPageObject aSingle; + storeError eErrCode = aSingle.loadOrCreate (store::ntohl(rPage.m_pData[nDouble]), rBIOS); + if (eErrCode != store_E_None) + { + if (eErrCode != store_E_Pending) + return eErrCode; + rPage.m_pData[nDouble] = store::htonl(aSingle.location()); + + eErrCode = rBIOS.saveObjectAt (*this, location()); + if (eErrCode != store_E_None) + return eErrCode; + } + + // Write single indirect and leave. + return aSingle.write (nSingle, rData, rBIOS); +} + +/* + * write (triple indirect). + */ +storeError OStoreIndirectionPageObject::write ( + sal_uInt16 nTriple, + sal_uInt16 nDouble, + sal_uInt16 nSingle, + OStoreDataPageObject &rData, + OStorePageBIOS &rBIOS) +{ + PageHolderObject< page > xImpl (m_xPage); + page & rPage = *xImpl; + + // Check arguments. + sal_uInt16 const nLimit = rPage.capacityCount(); + if (!((nTriple < nLimit) && (nDouble < nLimit) && (nSingle < nLimit))) + return store_E_InvalidAccess; + + // Load or create double indirect page. + OStoreIndirectionPageObject aDouble; + storeError eErrCode = aDouble.loadOrCreate (store::ntohl(rPage.m_pData[nTriple]), rBIOS); + if (eErrCode != store_E_None) + { + if (eErrCode != store_E_Pending) + return eErrCode; + rPage.m_pData[nTriple] = store::htonl(aDouble.location()); + + eErrCode = rBIOS.saveObjectAt (*this, location()); + if (eErrCode != store_E_None) + return eErrCode; + } + + // Write double indirect and leave. + return aDouble.write (nDouble, nSingle, rData, rBIOS); +} + +/* + * truncate (single indirect). + */ +storeError OStoreIndirectionPageObject::truncate ( + sal_uInt16 nSingle, + OStorePageBIOS & rBIOS) +{ + PageHolderObject< page > xImpl (m_xPage); + page & rPage = *xImpl; + + // Check arguments. + sal_uInt16 const nLimit = rPage.capacityCount(); + if (nSingle >= nLimit) + return store_E_InvalidAccess; + + // Truncate. + storeError eErrCode = store_E_None; + for (sal_uInt16 i = nLimit; i > nSingle; i--) + { + // Obtain data page location. + sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[i - 1]); + if (nAddr != STORE_PAGE_NULL) + { + // Free data page. + eErrCode = rBIOS.free (nAddr); + if (eErrCode != store_E_None) + return eErrCode; + + // Clear pointer to data page. + rPage.m_pData[i - 1] = STORE_PAGE_NULL; + touch(); + } + } + + // Check for modified page. + if (dirty()) + { + // Save this page. + eErrCode = rBIOS.saveObjectAt (*this, location()); + } + + // Done. + return eErrCode; +} + +/* + * truncate (double indirect). + */ +storeError OStoreIndirectionPageObject::truncate ( + sal_uInt16 nDouble, + sal_uInt16 nSingle, + OStorePageBIOS &rBIOS) +{ + PageHolderObject< page > xImpl (m_xPage); + page & rPage = *xImpl; + + // Check arguments. + sal_uInt16 const nLimit = rPage.capacityCount(); + if (!((nDouble < nLimit) && (nSingle < nLimit))) + return store_E_InvalidAccess; + + // Truncate. + storeError eErrCode = store_E_None; + for (sal_uInt16 i = nLimit; i > nDouble + 1; i--) + { + // Truncate single indirect page to zero direct pages. + eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[i - 1]), 0, rBIOS); + if (eErrCode != store_E_None) + return eErrCode; + + // Clear pointer to single indirect page. + rPage.m_pData[i - 1] = STORE_PAGE_NULL; + touch(); + } + + // Truncate last single indirect page to 'nSingle' direct pages. + eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[nDouble]), nSingle, rBIOS); + if (eErrCode != store_E_None) + return eErrCode; + + // Check for complete truncation. + if (nSingle == 0) + { + // Clear pointer to last single indirect page. + rPage.m_pData[nDouble] = STORE_PAGE_NULL; + touch(); + } + + // Check for modified page. + if (dirty()) + { + // Save this page. + eErrCode = rBIOS.saveObjectAt (*this, location()); + } + + // Done. + return eErrCode; +} + +/* + * truncate (triple indirect). + */ +storeError OStoreIndirectionPageObject::truncate ( + sal_uInt16 nTriple, + sal_uInt16 nDouble, + sal_uInt16 nSingle, + OStorePageBIOS &rBIOS) +{ + PageHolderObject< page > xImpl (m_xPage); + page & rPage = *xImpl; + + // Check arguments. + sal_uInt16 const nLimit = rPage.capacityCount(); + if (!((nTriple < nLimit) && (nDouble < nLimit) && (nSingle < nLimit))) + return store_E_InvalidAccess; + + // Truncate. + storeError eErrCode = store_E_None; + for (sal_uInt16 i = nLimit; i > nTriple + 1; i--) + { + // Truncate double indirect page to zero single indirect pages. + eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[i - 1]), 0, 0, rBIOS); + if (eErrCode != store_E_None) + return eErrCode; + + // Clear pointer to double indirect page. + rPage.m_pData[i - 1] = STORE_PAGE_NULL; + touch(); + } + + // Truncate last double indirect page to 'nDouble', 'nSingle' pages. + eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[nTriple]), nDouble, nSingle, rBIOS); + if (eErrCode != store_E_None) + return eErrCode; + + // Check for complete truncation. + if ((nDouble + nSingle) == 0) + { + // Clear pointer to last double indirect page. + rPage.m_pData[nTriple] = STORE_PAGE_NULL; + touch(); + } + + // Check for modified page. + if (dirty()) + { + // Save this page. + eErrCode = rBIOS.saveObjectAt (*this, location()); + } + + // Done. + return eErrCode; +} + +/*======================================================================== + * + * OStoreDirectoryPageObject implementation. + * + *======================================================================*/ +/* + * guard. + */ +storeError OStoreDirectoryPageObject::guard (sal_uInt32 nAddr) +{ + return PageHolderObject< page >::guard (m_xPage, nAddr); +} + +/* + * verify. + */ +storeError OStoreDirectoryPageObject::verify (sal_uInt32 nAddr) const +{ + return PageHolderObject< page >::verify (m_xPage, nAddr); + // OLD: m_rPage.verifyVersion (STORE_MAGIC_DIRECTORYPAGE); +} + +/* + * scope (external data page; private). + */ +OStoreDirectoryPageData::ChunkScope +OStoreDirectoryPageObject::scope ( + sal_uInt32 nPage, + page::DataBlock::LinkDescriptor &rDescr) const +{ + page const & rPage = PAGE(); + + sal_uInt32 index0, index1, index2, index3; + + // direct. + sal_uInt32 nCount = OStoreDirectoryDataBlock::directCount; + sal_uInt32 nLimit = nCount; + if (nPage < nLimit) + { + // Page to index reduction. + index0 = nPage; + + // Setup LinkDescriptor indices. + rDescr.m_nIndex0 = static_cast<sal_uInt16>(index0 & 0xffff); + + // Done. + return page::SCOPE_DIRECT; + } + nPage -= nLimit; + + // single indirect. + sal_uInt32 const nCapacity = indirect::capacityCount(rPage.m_aDescr); + nCount = OStoreDirectoryDataBlock::singleCount; + nLimit = nCount * nCapacity; + if (nPage < nLimit) + { + // Page to index reduction. + sal_uInt32 n = nPage; + + // Reduce to single indirect i(1), direct n = i(0). + index1 = n / nCapacity; + index0 = n % nCapacity; + + // Verify reduction. + n = index1 * nCapacity + index0; + if (n != nPage) + { + SAL_WARN("store", "wrong math on indirect indices"); + return page::SCOPE_UNKNOWN; + } + + // Setup LinkDescriptor indices. + rDescr.m_nIndex0 = static_cast<sal_uInt16>(index0 & 0xffff); + rDescr.m_nIndex1 = static_cast<sal_uInt16>(index1 & 0xffff); + + // Done. + return page::SCOPE_SINGLE; + } + nPage -= nLimit; + + // double indirect. + nCount = OStoreDirectoryDataBlock::doubleCount; + nLimit = nCount * nCapacity * nCapacity; + if (nPage < nLimit) + { + // Page to index reduction. + sal_uInt32 n = nPage; + + // Reduce to double indirect i(2), single indirect n = i(0). + index2 = n / (nCapacity * nCapacity); + n = n % (nCapacity * nCapacity); + + // Reduce to single indirect i(1), direct n = i(0). + index1 = n / nCapacity; + index0 = n % nCapacity; + + // Verify reduction. + n = index2 * nCapacity * nCapacity + + index1 * nCapacity + index0; + if (n != nPage) + { + SAL_WARN("store", "wrong math on double indirect indices"); + return page::SCOPE_UNKNOWN; + } + + // Setup LinkDescriptor indices. + rDescr.m_nIndex0 = static_cast<sal_uInt16>(index0 & 0xffff); + rDescr.m_nIndex1 = static_cast<sal_uInt16>(index1 & 0xffff); + rDescr.m_nIndex2 = static_cast<sal_uInt16>(index2 & 0xffff); + + // Done. + return page::SCOPE_DOUBLE; + } + nPage -= nLimit; + + // triple indirect. + nCount = OStoreDirectoryDataBlock::tripleCount; + nLimit = nCount * nCapacity * nCapacity * nCapacity; + if (nPage < nLimit) + { + // Page to index reduction. + sal_uInt32 n = nPage; + + // Reduce to triple indirect i(3), double indirect n. + index3 = n / (nCapacity * nCapacity * nCapacity); + n = n % (nCapacity * nCapacity * nCapacity); + + // Reduce to double indirect i(2), single indirect n. + index2 = n / (nCapacity * nCapacity); + n = n % (nCapacity * nCapacity); + + // Reduce to single indirect i(1), direct n = i(0). + index1 = n / nCapacity; + index0 = n % nCapacity; + + // Verify reduction. + n = index3 * nCapacity * nCapacity * nCapacity + + index2 * nCapacity * nCapacity + + index1 * nCapacity + index0; + if (n != nPage) + { + SAL_WARN("store", "wrong math on triple indirect indices"); + return page::SCOPE_UNKNOWN; + } + + // Setup LinkDescriptor indices. + rDescr.m_nIndex0 = static_cast<sal_uInt16>(index0 & 0xffff); + rDescr.m_nIndex1 = static_cast<sal_uInt16>(index1 & 0xffff); + rDescr.m_nIndex2 = static_cast<sal_uInt16>(index2 & 0xffff); + rDescr.m_nIndex3 = static_cast<sal_uInt16>(index3 & 0xffff); + + // Done. + return page::SCOPE_TRIPLE; + } + + // Unreachable (more than triple indirect). + return page::SCOPE_UNREACHABLE; +} + +/* + * read (external data page). + */ +storeError OStoreDirectoryPageObject::read ( + sal_uInt32 nPage, + OStoreDataPageObject &rData, + OStorePageBIOS &rBIOS) const +{ + // Determine scope and link indices. + page::DataBlock::LinkDescriptor aLink; + page::ChunkScope eScope = scope (nPage, aLink); + + storeError eErrCode = store_E_None; + if (eScope == page::SCOPE_DIRECT) + { + sal_uInt32 const nAddr = directLink (aLink.m_nIndex0); + if (nAddr == STORE_PAGE_NULL) + return store_E_NotExists; + + eErrCode = rBIOS.loadObjectAt (rData, nAddr); + } + else if (eScope == page::SCOPE_SINGLE) + { + sal_uInt32 const nAddr = singleLink (aLink.m_nIndex1); + if (nAddr == STORE_PAGE_NULL) + return store_E_NotExists; + + OStoreIndirectionPageObject aSingle; + eErrCode = rBIOS.loadObjectAt (aSingle, nAddr); + if (eErrCode != store_E_None) + return eErrCode; + + eErrCode = aSingle.read (aLink.m_nIndex0, rData, rBIOS); + } + else if (eScope == page::SCOPE_DOUBLE) + { + sal_uInt32 const nAddr = doubleLink (aLink.m_nIndex2); + if (nAddr == STORE_PAGE_NULL) + return store_E_NotExists; + + OStoreIndirectionPageObject aDouble; + eErrCode = rBIOS.loadObjectAt (aDouble, nAddr); + if (eErrCode != store_E_None) + return eErrCode; + + eErrCode = aDouble.read (aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS); + } + else if (eScope == page::SCOPE_TRIPLE) + { + sal_uInt32 const nAddr = tripleLink (aLink.m_nIndex3); + if (nAddr == STORE_PAGE_NULL) + return store_E_NotExists; + + OStoreIndirectionPageObject aTriple; + eErrCode = rBIOS.loadObjectAt (aTriple, nAddr); + if (eErrCode != store_E_None) + return eErrCode; + + eErrCode = aTriple.read (aLink.m_nIndex2, aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS); + } + else if (eScope == page::SCOPE_UNREACHABLE) + { + // Out of scope. + eErrCode = store_E_CantSeek; + } + else + { + // Unknown scope. + SAL_WARN("store", "OStoreDirectoryPageObject::get(): scope failed"); + eErrCode = store_E_Unknown; + } + + // Leave. + return eErrCode; +} + +/* + * write (external data page). + */ +storeError OStoreDirectoryPageObject::write ( + sal_uInt32 nPage, + OStoreDataPageObject &rData, + OStorePageBIOS &rBIOS) +{ + // Determine scope and link indices. + page::DataBlock::LinkDescriptor aLink; + page::ChunkScope eScope = scope (nPage, aLink); + + storeError eErrCode = store_E_None; + if (eScope == page::SCOPE_DIRECT) + { + sal_uInt32 const nAddr = directLink (aLink.m_nIndex0); + if (nAddr == STORE_PAGE_NULL) + { + // Allocate data page. + eErrCode = rBIOS.allocate (rData); + if (eErrCode != store_E_None) + return eErrCode; + + // Store data page location. + directLink (aLink.m_nIndex0, rData.location()); + } + else + { + // Save data page. + eErrCode = rBIOS.saveObjectAt (rData, nAddr); + } + } + else if (eScope == page::SCOPE_SINGLE) + { + OStoreIndirectionPageObject aSingle; + eErrCode = aSingle.loadOrCreate (singleLink (aLink.m_nIndex1), rBIOS); + if (eErrCode != store_E_None) + { + if (eErrCode != store_E_Pending) + return eErrCode; + singleLink (aLink.m_nIndex1, aSingle.location()); + } + + eErrCode = aSingle.write (aLink.m_nIndex0, rData, rBIOS); + } + else if (eScope == page::SCOPE_DOUBLE) + { + OStoreIndirectionPageObject aDouble; + eErrCode = aDouble.loadOrCreate (doubleLink (aLink.m_nIndex2), rBIOS); + if (eErrCode != store_E_None) + { + if (eErrCode != store_E_Pending) + return eErrCode; + doubleLink (aLink.m_nIndex2, aDouble.location()); + } + + eErrCode = aDouble.write (aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS); + } + else if (eScope == page::SCOPE_TRIPLE) + { + OStoreIndirectionPageObject aTriple; + eErrCode = aTriple.loadOrCreate (tripleLink (aLink.m_nIndex3), rBIOS); + if (eErrCode != store_E_None) + { + if (eErrCode != store_E_Pending) + return eErrCode; + tripleLink (aLink.m_nIndex3, aTriple.location()); + } + + eErrCode = aTriple.write (aLink.m_nIndex2, aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS); + } + else if (eScope == page::SCOPE_UNREACHABLE) + { + // Out of scope. + eErrCode = store_E_CantSeek; + } + else + { + // Unknown scope. + SAL_WARN("store", "OStoreDirectoryPageObject::put(): scope failed"); + eErrCode = store_E_Unknown; + } + + // Leave. + return eErrCode; +} + +/* + * truncate (external data page). + */ +storeError OStoreDirectoryPageObject::truncate ( + sal_uInt32 nPage, + OStorePageBIOS &rBIOS) +{ + // Determine scope and link indices. + page::DataBlock::LinkDescriptor aLink; + page::ChunkScope eScope = scope (nPage, aLink); + + storeError eErrCode = store_E_None; + if (eScope == page::SCOPE_DIRECT) + { + // Truncate all triple indirect pages. + eErrCode = truncate (page::SCOPE_TRIPLE, 0, rBIOS); + if (eErrCode != store_E_None) + return eErrCode; + + // Truncate all double indirect pages. + eErrCode = truncate (page::SCOPE_DOUBLE, 0, rBIOS); + if (eErrCode != store_E_None) + return eErrCode; + + // Truncate all single indirect pages. + eErrCode = truncate (page::SCOPE_SINGLE, 0, rBIOS); + if (eErrCode != store_E_None) + return eErrCode; + + // Truncate direct pages, including 'aLink.m_nIndex0'. + eErrCode = truncate (eScope, aLink.m_nIndex0, rBIOS); + } + else if (eScope == page::SCOPE_SINGLE) + { + // Truncate all triple indirect pages. + eErrCode = truncate (page::SCOPE_TRIPLE, 0, rBIOS); + if (eErrCode != store_E_None) + return eErrCode; + + // Truncate all double indirect pages. + eErrCode = truncate (page::SCOPE_DOUBLE, 0, rBIOS); + if (eErrCode != store_E_None) + return eErrCode; + + // Truncate single indirect pages, downto 'aLink.m_nIndex1'. + eErrCode = truncate (eScope, aLink.m_nIndex1 + 1, rBIOS); + if (eErrCode != store_E_None) + return eErrCode; + + // Truncate last single indirect page to ... pages. + eErrCode = store_truncate_Impl (singleLink (aLink.m_nIndex1), aLink.m_nIndex0, rBIOS); + if (eErrCode != store_E_None) + return eErrCode; + + // Check for complete truncation. + if (aLink.m_nIndex0 == 0) + { + // Clear pointer to last single indirect page. + singleLink (aLink.m_nIndex1, STORE_PAGE_NULL); + } + } + else if (eScope == page::SCOPE_DOUBLE) + { + // Truncate all triple indirect pages. + eErrCode = truncate (page::SCOPE_TRIPLE, 0, rBIOS); + if (eErrCode != store_E_None) + return eErrCode; + + // Truncate double indirect pages, downto 'aLink.m_nIndex2'. + eErrCode = truncate (eScope, aLink.m_nIndex2 + 1, rBIOS); + if (eErrCode != store_E_None) + return eErrCode; + + // Truncate last double indirect page to ... pages. + eErrCode = store_truncate_Impl ( + doubleLink (aLink.m_nIndex2), aLink.m_nIndex1, aLink.m_nIndex0, rBIOS); + if (eErrCode != store_E_None) + return eErrCode; + + // Check for complete truncation. + if ((aLink.m_nIndex1 + aLink.m_nIndex0) == 0) + { + // Clear pointer to last double indirect page. + doubleLink (aLink.m_nIndex2, STORE_PAGE_NULL); + } + } + else if (eScope == page::SCOPE_TRIPLE) + { + // Truncate triple indirect pages, downto 'aLink.m_nIndex3'. + eErrCode = truncate (eScope, aLink.m_nIndex3 + 1, rBIOS); + if (eErrCode != store_E_None) + return eErrCode; + + // Truncate last triple indirect page to ... pages. + eErrCode = store_truncate_Impl ( + tripleLink (aLink.m_nIndex3), aLink.m_nIndex2, aLink.m_nIndex1, aLink.m_nIndex0, rBIOS); + if (eErrCode != store_E_None) + return eErrCode; + + // Check for complete truncation. + if ((aLink.m_nIndex2 + aLink.m_nIndex1 + aLink.m_nIndex0) == 0) + { + // Clear pointer to last triple indirect page. + tripleLink (aLink.m_nIndex3, STORE_PAGE_NULL); + } + } + else if (eScope == page::SCOPE_UNREACHABLE) + { + // Out of scope. + eErrCode = store_E_CantSeek; + } + else + { + // Unknown scope. + SAL_WARN("store", "OStoreDirectoryPageObject::put(): scope failed"); + eErrCode = store_E_Unknown; + } + + // Leave. + return eErrCode; +} + +/* + * truncate (external data page scope; private). + */ +storeError OStoreDirectoryPageObject::truncate ( + page::ChunkScope eScope, + sal_uInt16 nRemain, + OStorePageBIOS &rBIOS) +{ + // Enter. + storeError eErrCode = store_E_None; + if (eScope == page::SCOPE_DIRECT) + { + // Truncate direct data pages. + for (sal_uInt16 i = OStoreDirectoryDataBlock::directCount; i > nRemain; i--) + { + // Obtain data page location. + sal_uInt32 nAddr = directLink (i - 1); + if (nAddr == STORE_PAGE_NULL) continue; + + // Free data page. + eErrCode = rBIOS.free (nAddr); + if (eErrCode != store_E_None) + break; + + // Clear pointer to data page. + directLink (i - 1, STORE_PAGE_NULL); + } + + // Done. + return eErrCode; + } + + if (eScope == page::SCOPE_SINGLE) + { + // Truncate single indirect pages. + for (sal_uInt16 i = OStoreDirectoryDataBlock::singleCount; i > nRemain; i--) + { + // Truncate single indirect page to zero data pages. + eErrCode = store_truncate_Impl (singleLink (i - 1), 0, rBIOS); + if (eErrCode != store_E_None) + break; + + // Clear pointer to single indirect page. + singleLink (i - 1, STORE_PAGE_NULL); + } + + // Done. + return eErrCode; + } + + if (eScope == page::SCOPE_DOUBLE) + { + // Truncate double indirect pages. + for (sal_uInt16 i = OStoreDirectoryDataBlock::doubleCount; i > nRemain; i--) + { + // Truncate double indirect page to zero single indirect pages. + eErrCode = store_truncate_Impl (doubleLink (i - 1), 0, 0, rBIOS); + if (eErrCode != store_E_None) + break; + + // Clear pointer to double indirect page. + doubleLink (i - 1, STORE_PAGE_NULL); + } + + // Done. + return eErrCode; + } + + if (eScope == page::SCOPE_TRIPLE) + { + // Truncate triple indirect pages. + for (sal_uInt16 i = OStoreDirectoryDataBlock::tripleCount; i > nRemain; i--) + { + // Truncate to zero double indirect pages. + eErrCode = store_truncate_Impl (tripleLink (i - 1), 0, 0, 0, rBIOS); + if (eErrCode != store_E_None) + break; + + // Clear pointer to triple indirect page. + tripleLink (i - 1, STORE_PAGE_NULL); + } + + // Done. + return eErrCode; + } + + // Invalid scope. + return store_E_InvalidAccess; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |