Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/store/source/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 21 kB image not shown  

Quelle  storbios.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 <sal/config.h>

#include "storbios.hxx"

#include <sal/types.h>
#include <sal/log.hxx>

#include <rtl/alloc.h>
#include <rtl/ref.hxx>

#include <osl/diagnose.h>
#include <osl/mutex.hxx>

#include <store/types.h>
#include "lockbyte.hxx"
#include "storcach.hxx"

using namespace store;

constexpr sal_uInt32 STORE_MAGIC_SUPERBLOCK = 0x484D5343;

namespace {

struct OStoreSuperBlock
{
    typedef OStorePageGuard      G;
    typedef OStorePageDescriptor D;
    typedef OStorePageLink       L;

    G          m_aGuard;
    D          m_aDescr;
    sal_uInt32 m_nMarked;
    L          m_aMarked;
    sal_uInt32 m_nUnused;
    L          m_aUnused;

    static const size_t theSize = sizeof(G) + sizeof(D) + 2 * (sizeof(L) + sizeof(sal_uInt32));

    explicit OStoreSuperBlock (sal_uInt16 nPageSize)
        : m_aGuard  (STORE_MAGIC_SUPERBLOCK),
          m_aDescr  (nPageSize, nPageSize, STORE_MINIMUM_PAGESIZE),
          m_nMarked (store::htonl(0)),
          m_aMarked (0),
          m_nUnused (store::htonl(0)),
          m_aUnused (0)
    {}

    bool operator== (const OStoreSuperBlock & rhs) const
    {
        return ((m_aGuard  == rhs.m_aGuard ) &&
                (m_aDescr  == rhs.m_aDescr ) &&
                (m_nMarked == rhs.m_nMarked) &&
                (m_aMarked == rhs.m_aMarked) &&
                (m_nUnused == rhs.m_nUnused) &&
                (m_aUnused == rhs.m_aUnused)    );
    }

    sal_uInt32 unusedCount() const
    {
        return store::ntohl(m_nUnused);
    }

    const L& unusedHead() const
    {
        return m_aUnused;
    }

    void unusedInsert (const L& rLink)
    {
        sal_uInt32 nUnused = unusedCount();
        m_nUnused = store::htonl(nUnused + 1);
        m_aUnused = rLink;
    }

    void unusedRemove (const L& rLink)
    {
        sal_uInt32 nUnused = unusedCount();
        m_nUnused = store::htonl(nUnused - 1);
        m_aUnused = rLink;
    }

    void unusedReset()
    {
        m_nUnused = store::htonl(0);
        m_aUnused = L(0);
    }

    void guard()
    {
        sal_uInt32 nCRC32 = rtl_crc32 (0, &m_aGuard.m_nMagic, sizeof(sal_uInt32));
        nCRC32 = rtl_crc32 (nCRC32, &m_aDescr, static_cast<sal_uInt32>(theSize - sizeof(G)));
        m_aGuard.m_nCRC32 = store::htonl(nCRC32);
    }

    storeError verify() const
    {
        sal_uInt32 nMagic = store::ntohl(m_aGuard.m_nMagic);
        if (nMagic != STORE_MAGIC_SUPERBLOCK)
            return store_E_WrongFormat;

        sal_uInt32 nCRC32 = rtl_crc32 (0, &m_aGuard.m_nMagic, sizeof(sal_uInt32));
        nCRC32 = rtl_crc32 (nCRC32, &m_aDescr, static_cast<sal_uInt32>(theSize - sizeof(G)));
        if (m_aGuard.m_nCRC32 != store::htonl(nCRC32))
            return store_E_InvalidChecksum;
        else
            return store_E_None;
    }
};

}

namespace store
{

struct SuperBlockPage
{
    typedef OStoreSuperBlock SuperBlock;

    SuperBlock m_aSuperOne;
    SuperBlock m_aSuperTwo;

    static const size_t     theSize     = 2 * SuperBlock::theSize;
    static const sal_uInt16 thePageSize = theSize;
    static_assert(STORE_MINIMUM_PAGESIZE >= thePageSize, "must be at least thePageSize");

    static void * operator new (size_t n)
    {
        return std::malloc(sal::static_int_cast<sal_Size>(n));
    }

    static void operator delete (void * p)
    {
        std::free (p);
    }

    static void * operator new (SAL_UNUSED_PARAMETER size_t, sal_uInt16 nPageSize)
    {
        return rtl_allocateZeroMemory (sal::static_int_cast<sal_Size>(nPageSize));
    }

    static void operator delete (void * p, SAL_UNUSED_PARAMETER sal_uInt16)
    {
        std::free (p);
    }

    explicit SuperBlockPage (sal_uInt16 nPageSize = thePageSize)
        : m_aSuperOne(nPageSize),
          m_aSuperTwo(nPageSize)
    {}

    storeError save (OStorePageBIOS const & rBIOS, sal_uInt32 nSize = theSize)
    {
        m_aSuperOne.guard();
        m_aSuperTwo = m_aSuperOne;
        return rBIOS.write (0, this, nSize);
    }

    /** Page allocation.
     */

    storeError unusedHead (
        OStorePageBIOS const & rBIOS,
        PageData &       rPageHead);

    storeError unusedPop (
        OStorePageBIOS const & rBIOS,
        PageData const & rPageHead);

    storeError unusedPush (
        OStorePageBIOS const & rBIOS,
        sal_uInt32       nAddr);

    storeError verify (OStorePageBIOS const & rBIOS);
};

// namespace store

/**
   Get freelist head (alloc page, step 1).
 */

storeError SuperBlockPage::unusedHead (OStorePageBIOS const & rBIOS, PageData & rPageHead)
{
    storeError eErrCode = verify (rBIOS);
    if (eErrCode != store_E_None)
        return eErrCode;

    // Check freelist head.
    OStorePageLink const aListHead (m_aSuperOne.unusedHead());
    if (aListHead.location() == 0)
    {
        // Freelist empty, see SuperBlock::ctor().
        rPageHead.location (STORE_PAGE_NULL);
        return store_E_None;
    }

    // Load PageHead.
    eErrCode = rBIOS.read (aListHead.location(), &rPageHead, PageData::theSize);
    if (eErrCode != store_E_None)
        return eErrCode;

    eErrCode = rPageHead.verify (aListHead.location());
    if (eErrCode != store_E_None)
        return eErrCode;

    // Verify page is unused.
    sal_uInt32 const nAddr = rPageHead.m_aUnused.location();
    if (nAddr == STORE_PAGE_NULL)
    {
        SAL_WARN("store""store::SuperBlock::unusedHead(): page not free");

        // Page in use.
        rPageHead.location (STORE_PAGE_NULL);

        // Recovery: Reset freelist to empty.
        m_aSuperOne.unusedReset();
        eErrCode = save (rBIOS);
    }
    return eErrCode;
}

/**
   Pop freelist head (alloc page, step 2).
 */

storeError SuperBlockPage::unusedPop (OStorePageBIOS const & rBIOS, PageData const &&nbsp;rPageHead)
{
    sal_uInt32 const nAddr = rPageHead.m_aUnused.location();
    OSL_PRECOND(nAddr != STORE_PAGE_NULL, "store::SuperBlock::unusedPop(): page not free");
    if (nAddr == STORE_PAGE_NULL)
        return store_E_CantSeek;

    // Pop from FreeList.
    OStorePageLink const aListHead (nAddr);
    m_aSuperOne.unusedRemove (aListHead);
    return save (rBIOS);
}

/**
   Push new freelist head.
 */

storeError SuperBlockPage::unusedPush (OStorePageBIOS const & rBIOS, sal_uInt32 nAddr)
{
    storeError eErrCode = verify (rBIOS);
    if (eErrCode != store_E_None)
        return eErrCode;

    PageData aPageHead;
    eErrCode = rBIOS.read (nAddr, &aPageHead, PageData::theSize);
    if (eErrCode != store_E_None)
        return eErrCode;

    eErrCode = aPageHead.verify (nAddr);
    if (eErrCode != store_E_None)
        return eErrCode;

    aPageHead.m_aUnused = m_aSuperOne.unusedHead();
    aPageHead.guard (nAddr);

    eErrCode = rBIOS.write (nAddr, &aPageHead, PageData::theSize);
    if (eErrCode != store_E_None)
        return eErrCode;

    OStorePageLink const aListHead (nAddr);
    m_aSuperOne.unusedInsert(aListHead);
    return save (rBIOS);
}

/**
   Verify (with repair).
 */

storeError SuperBlockPage::verify (OStorePageBIOS const & rBIOS)
{
    // Verify 1st copy.
    storeError eErrCode = m_aSuperOne.verify();
    if (eErrCode == store_E_None)
    {
        // Ok. Verify 2nd copy.
        eErrCode = m_aSuperTwo.verify();
        if (eErrCode == store_E_None)
        {
            // Ok. Ensure identical copies (1st copy wins).
            if (!(m_aSuperOne == m_aSuperTwo))
            {
                // Different. Replace 2nd copy with 1st copy.
                m_aSuperTwo = m_aSuperOne;

                // Write back.
                if (rBIOS.isWriteable())
                    eErrCode = rBIOS.write (0, this, theSize);
                else
                    eErrCode = store_E_None;
            }
        }
        else
        {
            // Failure. Replace 2nd copy with 1st copy.
            m_aSuperTwo = m_aSuperOne;

            // Write back.
            if (rBIOS.isWriteable())
                eErrCode = rBIOS.write (0, this, theSize);
            else
                eErrCode = store_E_None;
        }
    }
    else
    {
        // Failure. Verify 2nd copy.
        eErrCode = m_aSuperTwo.verify();
        if (eErrCode == store_E_None)
        {
            // Ok. Replace 1st copy with 2nd copy.
            m_aSuperOne = m_aSuperTwo;

            // Write back.
            if (rBIOS.isWriteable())
                eErrCode = rBIOS.write (0, this, theSize);
            else
                eErrCode = store_E_None;
        }
        else
        {
            // Double Failure.
            SAL_WARN("store""OStoreSuperBlockPage::verify(): double failure.");
        }
    }

    // Done.
    return eErrCode;
}

OStorePageBIOS::Ace::Ace()
  : m_next (this), m_prev (this), m_addr (STORE_PAGE_NULL), m_used (0)
{}

OStorePageBIOS::Ace::~Ace()
{
  m_next->m_prev = m_prev;
  m_prev->m_next = m_next;
}

int
SAL_CALL OStorePageBIOS::Ace::constructor (
    void * obj, SAL_UNUSED_PARAMETER void*)
{
  Ace * ace = static_cast<Ace*>(obj);
  ace->m_next = ace->m_prev = ace;
  return 1;
}

OStorePageBIOS::Ace *
OStorePageBIOS::Ace::find (OStorePageBIOS::Ace * head, sal_uInt32 addr)
{
  OStorePageBIOS::Ace * entry;
  for (entry = head->m_next; entry != head; entry = entry->m_next)
  {
    if (entry->m_addr >= addr)
      return entry;
  }
  return head;
}

void
OStorePageBIOS::Ace::insert (OStorePageBIOS::Ace * head, OStorePageBIOS::Ace * entry)
{
  // insert entry at queue tail (before head).
  entry->m_next = head;
  entry->m_prev = head->m_prev;
  head->m_prev = entry;
  entry->m_prev->m_next = entry;
}

namespace store
{

class OStorePageBIOS::AceCache
{
  rtl_cache_type * m_ace_cache;

public:
  static AceCache & get();

  OStorePageBIOS::Ace *
  create (sal_uInt32 addr);

  void
  destroy (OStorePageBIOS::Ace * ace);

protected:
  AceCache();
  ~AceCache();
};

// namespace store

OStorePageBIOS::AceCache &
OStorePageBIOS::AceCache::get()
{
  static AceCache g_ace_cache;
  return g_ace_cache;
}

OStorePageBIOS::AceCache::AceCache()
{
  m_ace_cache = rtl_cache_create (
    "store_ace_cache",
    sizeof (OStorePageBIOS::Ace),
    0, // objalign
    OStorePageBIOS::Ace::constructor,
    nullptr, // destructor,
    nullptr, // reclaim,
    nullptr, // userarg,
    nullptr, // default source,
    0  // flags
    );
}

OStorePageBIOS::AceCache::~AceCache()
{
  rtl_cache_destroy (m_ace_cache);
  m_ace_cache = nullptr;
}

OStorePageBIOS::Ace *
OStorePageBIOS::AceCache::create (sal_uInt32 addr)
{
  Ace * ace = static_cast<Ace*>(rtl_cache_alloc (m_ace_cache));
  if (ace != nullptr)
  {
    // verify invariant state.
    OSL_ASSERT((ace->m_next == ace) && (ace->m_prev == ace));

    // initialize.
    ace->m_addr = addr;
    ace->m_used = 1;
  }
  return ace;
}

void
OStorePageBIOS::AceCache::destroy (OStorePageBIOS::Ace * ace)
{
  if (ace != nullptr)
  {
    // remove from queue (if any).
    ace->m_next->m_prev = ace->m_prev;
    ace->m_prev->m_next = ace->m_next;

    // restore invariant state.
    ace->m_next = ace->m_prev = ace;

    // return to cache.
    rtl_cache_free (m_ace_cache, ace);
  }
}

OStorePageBIOS::OStorePageBIOS()
    : m_bWriteable (false)
{
}

OStorePageBIOS::~OStorePageBIOS()
{
    cleanup_Impl();
}

storeError OStorePageBIOS::initialize (
    ILockBytes *    pLockBytes,
    storeAccessMode eAccessMode,
    sal_uInt16 &    rnPageSize)
{
    // Acquire exclusive access.
    osl::MutexGuard aGuard (m_aMutex);

    // Initialize.
    storeError eErrCode = initialize_Impl (pLockBytes, eAccessMode, rnPageSize);
    if (eErrCode != store_E_None)
    {
        // Cleanup.
        cleanup_Impl();
    }
    return eErrCode;
}

/**
   initialize_Impl.
   @pre exclusive access
 */

storeError OStorePageBIOS::initialize_Impl (
    ILockBytes *    pLockBytes,
    storeAccessMode eAccessMode,
    sal_uInt16 &    rnPageSize)
{
    // Cleanup.
    cleanup_Impl();

    // Initialize.
    m_xLockBytes = pLockBytes;
    if (!m_xLockBytes.is())
        return store_E_InvalidParameter;
    m_bWriteable = (eAccessMode != storeAccessMode::ReadOnly);

    // Check access mode.
    storeError eErrCode = store_E_None;
    if (eAccessMode != storeAccessMode::Create)
    {
        // Load SuperBlock page.
        m_pSuper.reset(new SuperBlockPage());

        eErrCode = read (0, m_pSuper.get(), SuperBlockPage::theSize);
        if (eErrCode == store_E_None)
        {
            // Verify SuperBlock page (with repair).
            eErrCode = m_pSuper->verify (*this);
        }
    }
    else
    {
        // Truncate to zero length.
        eErrCode = m_xLockBytes->setSize(0);
        if (eErrCode != store_E_None)
            return eErrCode;

        // Mark as not existing.
        eErrCode = store_E_NotExists;
    }

    if (eErrCode != store_E_None)
    {
        // Check reason.
        if (eErrCode != store_E_NotExists)
            return eErrCode;

        // Check mode.
        if (eAccessMode == storeAccessMode::ReadOnly)
            return store_E_NotExists;
        if (eAccessMode == storeAccessMode::ReadWrite)
            return store_E_NotExists;

        // Check PageSize.
        if ((STORE_MINIMUM_PAGESIZE > rnPageSize) || (rnPageSize > STORE_MAXIMUM_PAGESIZE))
            return store_E_InvalidParameter;
        rnPageSize = ((rnPageSize + STORE_MINIMUM_PAGESIZE - 1) & ~(STORE_MINIMUM_PAGESIZE - 1));

        // Create initial page (w/ SuperBlock).
        m_pSuper.reset(new(rnPageSize) SuperBlockPage(rnPageSize));
        eErrCode = m_pSuper->save (*this, rnPageSize);
    }
    if (eErrCode == store_E_None)
    {
        // Obtain page size.
        rnPageSize = store::ntohs(m_pSuper->m_aSuperOne.m_aDescr.m_nSize);

        // Create page allocator.
        eErrCode = m_xLockBytes->initialize (m_xAllocator, rnPageSize);
        if (eErrCode != store_E_None)
            return eErrCode;

        // Create page cache.
        eErrCode = PageCache_createInstance (m_xCache, rnPageSize);
    }
    return eErrCode;
}

/*
  @pre exclusive access.
 */

void OStorePageBIOS::cleanup_Impl()
{
    // Check referer count.
    if (m_ace_head.m_used > 0)
    {
        // Report remaining referer count.
        SAL_INFO("store""referer count: " << m_ace_head.m_used);
        for (Ace * ace = m_ace_head.m_next; ace != &m_ace_head; ace = m_ace_head.m_next)
        {
            m_ace_head.m_used -= ace->m_used;
            AceCache::get().destroy (ace);
        }
        OSL_ENSURE(m_ace_head.m_used == 0, "store::PageBIOS::cleanup_Impl(): logic error");
    }

    // Release SuperBlock page.
    m_pSuper.reset();

    // Release PageCache.
    m_xCache.clear();

    // Release PageAllocator.
    m_xAllocator.clear();

    // Release LockBytes.
    m_xLockBytes.clear();
}

/**
    @pre initialized, exclusive access.
 */

storeError OStorePageBIOS::read (
    sal_uInt32 nAddr, void *pData, sal_uInt32 nSize) const
{
    // Check precond.
    if (!m_xLockBytes.is())
        return store_E_InvalidAccess;

    // Read Data.
    return m_xLockBytes->readAt (nAddr, pData, nSize);
}

/**
   @pre initialized, writeable, exclusive access.
 */

storeError OStorePageBIOS::write (
    sal_uInt32 nAddr, const void *pData, sal_uInt32 nSize) const
{
    // Check precond.
    if (!m_xLockBytes.is())
        return store_E_InvalidAccess;
    if (!m_bWriteable)
        return store_E_AccessViolation;

    // Write Data.
    return m_xLockBytes->writeAt (nAddr, pData, nSize);
}

/**
   @pre initialized.
 */

storeError OStorePageBIOS::acquirePage (
    const OStorePageDescriptor& rDescr, storeAccessMode eMode)
{
    // Acquire exclusive access.
    osl::MutexGuard aGuard (m_aMutex);

    // Check precond.
    if (!m_xLockBytes.is())
        return store_E_InvalidAccess;

    // Check access mode.
    if (!(m_bWriteable || (eMode == storeAccessMode::ReadOnly)))
        return store_E_AccessViolation;

    // Find access control list entry.
    Ace * ace = Ace::find (&m_ace_head, rDescr.m_nAddr);
    if (ace->m_addr == rDescr.m_nAddr)
    {
      // Acquire existing entry (with ShareDenyWrite).
      if (eMode == storeAccessMode::ReadOnly)
        ace->m_used += 1;
      else
        return store_E_AccessViolation;
    }
    else
    {
      // Insert new entry.
      Ace * entry = AceCache::get().create (rDescr.m_nAddr);
      if (!entry)
        return store_E_OutOfMemory;
      Ace::insert (ace, entry);
    }

    // Increment total referer count and finish.
    m_ace_head.m_used += 1;
    return store_E_None;
}

/**
   @pre initialized.
 */

storeError OStorePageBIOS::releasePage (const OStorePageDescriptor& rDescr)
{
    // Acquire exclusive access.
    osl::MutexGuard aGuard (m_aMutex);

    // Check precond.
    if (!m_xLockBytes.is())
        return store_E_InvalidAccess;

    // Find access control list entry.
    Ace * ace = Ace::find (&m_ace_head, rDescr.m_nAddr);
    if (ace->m_addr != rDescr.m_nAddr)
      return store_E_NotExists;

    // Release existing entry.
    if (ace->m_used > 1)
      ace->m_used -= 1;
    else
      AceCache::get().destroy (ace);

    // Decrement total referer count and finish.
    m_ace_head.m_used -= 1;
    return store_E_None;
}

/**
   @pre initialized, writeable.
 */

storeError OStorePageBIOS::allocate (
    OStorePageObject& rPage)
{
    // Acquire exclusive access.
    osl::MutexGuard aGuard (m_aMutex);

    // Check precond.
    if (!m_xLockBytes.is())
        return store_E_InvalidAccess;
    if (!m_bWriteable)
        return store_E_AccessViolation;

    // Check allocation type.
    storeError eErrCode = store_E_None;
    // Try freelist head.
    PageData aPageHead;
    eErrCode = m_pSuper->unusedHead (*this, aPageHead);
    if (eErrCode != store_E_None)
        return eErrCode;

    sal_uInt32 const nAddr = aPageHead.location();
    if (nAddr != STORE_PAGE_NULL)
    {
        // Save page.
        eErrCode = saveObjectAt_Impl (rPage, nAddr);
        if (eErrCode != store_E_None)
            return eErrCode;

        // Pop freelist head and finish.
        return m_pSuper->unusedPop (*this, aPageHead);
    }

    // Allocate from EOF. Determine current size.
    sal_uInt32 nSize = STORE_PAGE_NULL;
    eErrCode = m_xLockBytes->getSize (nSize);
    if (eErrCode != store_E_None)
        return eErrCode;

    // Save page at current EOF.
    return saveObjectAt_Impl (rPage, nSize);
}

/**
   @pre initialized, writeable.
 */

storeError OStorePageBIOS::free (sal_uInt32 nAddr)
{
    // Acquire exclusive access.
    osl::MutexGuard aGuard (m_aMutex);

    // Check precond.
    if (!m_xLockBytes.is())
        return store_E_InvalidAccess;
    if (!m_bWriteable)
        return store_E_AccessViolation;

    // Invalidate cache.
    (void) m_xCache->removePageAt (nAddr);

    // Push onto freelist.
    return m_pSuper->unusedPush (*this, nAddr);
}

/**
   @pre initialized, readable.
 */

storeError OStorePageBIOS::loadObjectAt (OStorePageObject & rPage, sal_uInt32 nAddr)
{
    // Acquire exclusive access.
    osl::MutexGuard aGuard (m_aMutex);

    // Check precond.
    if (!m_xLockBytes.is())
        return store_E_InvalidAccess;

    return loadObjectAt_Impl (rPage, nAddr);
}

/**
   @pre initialized, readable, exclusive access.
 */

storeError OStorePageBIOS::loadObjectAt_Impl (OStorePageObject & rPage, sal_uInt32 nAddr) const
{
    storeError eErrCode = m_xCache->lookupPageAt (rPage.get(), nAddr);
    if (eErrCode != store_E_NotExists)
        return eErrCode;

    // Read page.
    eErrCode = m_xLockBytes->readPageAt (rPage.get(), nAddr);
    if (eErrCode != store_E_None)
        return eErrCode;

    // Verify page.
    eErrCode = rPage.verify (nAddr);
    if (eErrCode != store_E_None)
        return eErrCode;

    // Mark page as clean.
    rPage.clean();

    // Cache page.
    return m_xCache->insertPageAt (rPage.get(), nAddr);
}

/**
   @pre initialized, writeable.
 */

storeError OStorePageBIOS::saveObjectAt (OStorePageObject & rPage, sal_uInt32 nAddr)
{
    // Acquire exclusive access.
    osl::MutexGuard aGuard (m_aMutex);

    // Check precond.
    if (!m_xLockBytes.is())
        return store_E_InvalidAccess;
    if (!m_bWriteable)
        return store_E_AccessViolation;

    // Save Page.
    return saveObjectAt_Impl (rPage, nAddr);
}

/**
   @pre initialized, writeable, exclusive access.
 */

storeError OStorePageBIOS::saveObjectAt_Impl (OStorePageObject & rPage, sal_uInt32 nAddr) const
{
    // Guard page (incl. set location).
    storeError eErrCode = rPage.guard (nAddr);
    if (eErrCode != store_E_None)
        return eErrCode;

    // Write page.
    eErrCode = m_xLockBytes->writePageAt(rPage.get(), nAddr);
    if (eErrCode != store_E_None)
        return eErrCode;

    // Mark page as clean.
    rPage.clean();

    // Cache page.
    return m_xCache->updatePageAt (rPage.get(), nAddr);
}

/**
   @pre none.
 */

storeError OStorePageBIOS::close()
{
    // Acquire exclusive access.
    osl::MutexGuard aGuard (m_aMutex);

    // Cleanup.
    cleanup_Impl();

    // Done.
    return store_E_None;
}

/**
   @pre initialized.
 */

storeError OStorePageBIOS::flush()
{
    // Acquire exclusive access.
    osl::MutexGuard aGuard (m_aMutex);

    // Check precond.
    if (!m_xLockBytes.is())
        return store_E_InvalidAccess;

    // Flush LockBytes and finish.
    return m_xLockBytes->flush();
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=89 H=100 G=94

¤ Dauer der Verarbeitung: 0.6 Sekunden  ¤

*© 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.