/* -*- 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;
storeError OStoreDataPageObject::guard (sal_uInt32 nAddr)
{
return PageHolderObject< page >::guard (m_xPage, nAddr);
}
storeError OStoreDataPageObject::verify (sal_uInt32 nAddr) const
{
return PageHolderObject< page >::verify (m_xPage, nAddr);
}
/**
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;
}
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);
}
storeError OStoreIndirectionPageObject::guard (sal_uInt32 nAddr)
{
return PageHolderObject< page >::guard (m_xPage, nAddr);
}
storeError OStoreIndirectionPageObject::verify (sal_uInt32 nAddr) const
{
return PageHolderObject< page >::verify (m_xPage, nAddr);
}
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;
}
storeError OStoreDirectoryPageObject::guard (sal_uInt32 nAddr)
{
return PageHolderObject< page >::guard (m_xPage, nAddr);
}
storeError OStoreDirectoryPageObject::verify (sal_uInt32 nAddr) const
{
return PageHolderObject< page >::verify (m_xPage, nAddr);
}
OStoreDirectoryPageData::ChunkScope
OStoreDirectoryPageObject::scope (
sal_uInt32 nPage,
page::DataBlock::LinkDescriptor &rDescr) const
{
page const & rPage = PAGE();
sal_uInt32 index0, index1, index2;
// 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.
sal_uInt32 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;
}
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;
}
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;
}
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: */
↑ V1048 The 'nCount' variable was assigned the same value.