diff options
Diffstat (limited to 'store/source/stordata.cxx')
-rw-r--r-- | store/source/stordata.cxx | 1130 |
1 files changed, 1130 insertions, 0 deletions
diff --git a/store/source/stordata.cxx b/store/source/stordata.cxx new file mode 100644 index 000000000000..901da15c8040 --- /dev/null +++ b/store/source/stordata.cxx @@ -0,0 +1,1130 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_store.hxx" + +#include "stordata.hxx" + +#include "sal/types.h" +#include "osl/diagnose.h" + +#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) +{ + 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) +{ + 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) +{ + 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(); + OStoreDirectoryDataBlock const & rDataBlock = rPage.m_aDataBlock; + + sal_uInt32 index0, index1, index2, index3; + + // direct. + sal_uInt32 nCount = rDataBlock.directCount(); + sal_uInt32 nLimit = nCount; + if (nPage < nLimit) + { + // Page to index reduction. + index0 = nPage; + + // Setup LinkDescriptor indices. + rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff); + + // Done. + return page::SCOPE_DIRECT; + } + nPage -= nLimit; + + // single indirect. + sal_uInt32 const nCapacity = indirect::capacityCount(rPage.m_aDescr); + nCount = rDataBlock.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; + OSL_POSTCOND(n == nPage, "wrong math on indirect indices"); + if (n != nPage) + return page::SCOPE_UNKNOWN; + + // Setup LinkDescriptor indices. + rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff); + rDescr.m_nIndex1 = (sal_uInt16)(index1 & 0xffff); + + // Done. + return page::SCOPE_SINGLE; + } + nPage -= nLimit; + + // double indirect. + nCount = rDataBlock.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; + OSL_POSTCOND(n == nPage, "wrong math on double indirect indices"); + if (n != nPage) + return page::SCOPE_UNKNOWN; + + // Setup LinkDescriptor indices. + rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff); + rDescr.m_nIndex1 = (sal_uInt16)(index1 & 0xffff); + rDescr.m_nIndex2 = (sal_uInt16)(index2 & 0xffff); + + // Done. + return page::SCOPE_DOUBLE; + } + nPage -= nLimit; + + // triple indirect. + nCount = rDataBlock.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; + OSL_POSTCOND(n == nPage, "wrong math on triple indirect indices"); + if (n != nPage) + return page::SCOPE_UNKNOWN; + + // Setup LinkDescriptor indices. + rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff); + rDescr.m_nIndex1 = (sal_uInt16)(index1 & 0xffff); + rDescr.m_nIndex2 = (sal_uInt16)(index2 & 0xffff); + rDescr.m_nIndex3 = (sal_uInt16)(index3 & 0xffff); + + // Done. + return page::SCOPE_TRIPLE; + } + + // Unreachable (more than triple indirect). + return page::SCOPE_UNREACHABLE; +} + +#if 0 /* NYI */ +/* + * chunk (external data page). + */ +inode::ChunkDescriptor OStoreDirectoryPageObject::chunk (sal_uInt32 nOffset) +{ + // @@@ INSUFFICIENT: NEED SCOPE AS WELL @@@ + sal_uInt32 nCapacity = m_rPage.capacity(); + if (nOffset < nCapacity) + // Internal scope (inode page). + return inode::ChunkDescriptor (nOffset, nCapacity); + else + // External scope (data page). + return inode::ChunkDescriptor (nOffset - nCapacity, data::capacity(m_rPage.m_aDescr)); + + inode::ChunkScope eScope = m_rPage.scope(nOffset); + if (eScope == inode::SCOPE_INTERNAL) + // Inode page (internal scope). + return inode::ChunkDescriptor (nOffset, m_rPage.capacity()); + else + // Data page (external scope). + return inode::ChunkDescriptor (nOffset - m_rPage.capacity(), data::capacity(m_rPage.m_aDescr)); +} +#endif /* NYI */ + +/* + * read (external data page). + */ +storeError OStoreDirectoryPageObject::read ( + 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) + 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. + OSL_TRACE("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. + OSL_TRACE("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. + OSL_TRACE("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) +{ + OStoreDirectoryDataBlock const & rDataBlock = PAGE().m_aDataBlock; + + // Enter. + storeError eErrCode = store_E_None; + if (eScope == page::SCOPE_DIRECT) + { + // Truncate direct data pages. + sal_uInt16 i, n = rDataBlock.directCount(); + for (i = n; 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. + sal_uInt16 i, n = rDataBlock.singleCount(); + for (i = n; 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. + sal_uInt16 i, n = rDataBlock.doubleCount(); + for (i = n; 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. + sal_uInt16 i, n = rDataBlock.tripleCount(); + for (i = n; 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; +} |