Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  stordata.cxx   Sprache: C

 
/* -*- 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: */

Messung V0.5
C=88 H=96 G=91

¤ Dauer der Verarbeitung: 0.3 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge