blob: a2f7fd0f0964b4b0a0ac69bd44be6e53426bcc31 [file] [log] [blame]
/**************************************************************
*
* 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
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the 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;
}