summaryrefslogtreecommitdiffstats
path: root/store/source/stordata.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'store/source/stordata.cxx')
-rw-r--r--store/source/stordata.cxx1095
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: */