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 11 kB image not shown  

Quelle  storlckb.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 "storlckb.hxx"

#include <sal/types.h>
#include <rtl/string.h>
#include <rtl/ref.hxx>
#include <osl/mutex.hxx>

#include <store/types.h>

#include "storbase.hxx"
#include "stordata.hxx"
#include "storpage.hxx"

using namespace store;

const sal_uInt32 OStoreLockBytes::m_nTypeId(0x94190310);

OStoreLockBytes::OStoreLockBytes()
    : m_bWriteable (false)
{
}

OStoreLockBytes::~OStoreLockBytes()
{
    if (m_xManager.is() && m_xNode.is())
    {
        m_xManager->releasePage(m_xNode->m_aDescr);
    }
}

bool OStoreLockBytes::isKindOf (sal_uInt32 nTypeId)
{
    return (nTypeId == m_nTypeId);
}

storeError OStoreLockBytes::create (
    OStorePageManager *pManager,
    rtl_String const  *pPath,
    rtl_String const  *pName,
    storeAccessMode    eMode)
{
    rtl::Reference<OStorePageManager> xManager (pManager);
    if (!xManager.is())
        return store_E_InvalidAccess;

    if (!(pPath && pName))
        return store_E_InvalidParameter;

    OStoreDirectoryPageObject aPage;
    storeError eErrCode = xManager->iget (
        aPage, STORE_ATTRIB_ISFILE,
        pPath, pName, eMode);
    if (eErrCode != store_E_None)
        return eErrCode;

    if (!(aPage.attrib() & STORE_ATTRIB_ISFILE))
    {
        // No ISFILE in older versions (backward compatibility).
        if (aPage.attrib() & STORE_ATTRIB_ISLINK)
            return store_E_NotFile;
    }

    inode_holder_type xNode (aPage.get());
    if (eMode != storeAccessMode::ReadOnly)
        eErrCode = xManager->acquirePage (xNode->m_aDescr, storeAccessMode::ReadWrite);
    else
        eErrCode = xManager->acquirePage (xNode->m_aDescr, storeAccessMode::ReadOnly);
    if (eErrCode != store_E_None)
        return eErrCode;

    m_xManager   = std::move(xManager);
    m_xNode      = xNode;
    m_bWriteable = (eMode != storeAccessMode::ReadOnly);

    // Check for truncation.
    if (eMode == storeAccessMode::Create)
    {
        // Truncate to zero length.
        eErrCode = setSize(0);
    }
    return eErrCode;
}

storeError OStoreLockBytes::readAt (
    sal_uInt32  nOffset,
    void       *pBuffer,
    sal_uInt32  nBytes,
    sal_uInt32 &rnDone)
{
    rnDone = 0;

    if (!m_xManager.is())
        return store_E_InvalidAccess;

    if (!pBuffer)
        return store_E_InvalidParameter;
    if (!nBytes)
        return store_E_None;

    // Acquire exclusive access.
    osl::MutexGuard aGuard (*m_xManager);

    // Determine data length.
    OStoreDirectoryPageObject aPage (m_xNode.get());

    sal_uInt32 nDataLen = aPage.dataLength();
    if ((nOffset + nBytes) > nDataLen)
        nBytes = nDataLen - nOffset;

    // Read data.
    OStoreDataPageObject aData;
    sal_uInt8 *pData = static_cast<sal_uInt8*>(pBuffer);
    while ((0 < nBytes) && (nOffset < nDataLen))
    {
        // Determine 'Offset' scope.
        inode::ChunkScope eScope = m_xNode->scope (nOffset);
        if (eScope == inode::SCOPE_INTERNAL)
        {
            // Read from inode page (internal scope).
            inode::ChunkDescriptor aDescr (
                nOffset, m_xNode->capacity());

            sal_uInt32 nLength = sal_uInt32(aDescr.m_nLength);
            if(nLength > nBytes)
            {
                nLength = nBytes;
            }
            memcpy (
                &pData[rnDone],
                &m_xNode->m_pData[aDescr.m_nOffset],
                nLength);

            // Adjust counters.
            rnDone  += nLength;
            nOffset += nLength;
            nBytes  -= nLength;
        }
        else
        {
            // Read from data page (external scope).
            inode::ChunkDescriptor aDescr (
                nOffset - m_xNode->capacity(), OStoreDataPageData::capacity(m_xNode->m_aDescr)); // @@@

            sal_uInt32 nLength = sal_uInt32(aDescr.m_nLength);
            if(nLength > nBytes)
            {
                nLength = nBytes;
            }

            storeError eErrCode = aPage.read (aDescr.m_nPage, aData, *m_xManager);
            if (eErrCode != store_E_None)
            {
                if (eErrCode != store_E_NotExists)
                    return eErrCode;

                memset (
                    &pData[rnDone],
                    0,
                    nLength);
            }
            else
            {
                PageHolderObject< data > xData (aData.makeHolder<data>());
                memcpy (
                    &pData[rnDone],
                    &xData->m_pData[aDescr.m_nOffset],
                    nLength);
            }

            // Adjust counters.
            rnDone  += nLength;
            nOffset += nLength;
            nBytes  -= nLength;
        }
    }

    // Done.
    return store_E_None;
}

storeError OStoreLockBytes::writeAt (
    sal_uInt32  nOffset,
    const void *pBuffer,
    sal_uInt32  nBytes,
    sal_uInt32 &rnDone)
{
    rnDone = 0;

    if (!m_xManager.is())
        return store_E_InvalidAccess;
    if (!m_bWriteable)
        return store_E_AccessViolation;

    if (!pBuffer)
        return store_E_InvalidParameter;
    if (!nBytes)
        return store_E_None;

    // Acquire exclusive access.
    osl::MutexGuard aGuard (*m_xManager);

    // Write data.
    OStoreDirectoryPageObject aPage (m_xNode.get());
    const sal_uInt8 *pData = static_cast<const sal_uInt8*>(pBuffer);

    storeError eErrCode = store_E_None;
    while (nBytes > 0)
    {
        // Determine 'Offset' scope.
        inode::ChunkScope eScope = m_xNode->scope (nOffset);
        if (eScope == inode::SCOPE_INTERNAL)
        {
            // Write to inode page (internal scope).
            inode::ChunkDescriptor aDescr (
                nOffset, m_xNode->capacity());

            sal_uInt32 nLength = sal_uInt32(aDescr.m_nLength);
            if(nLength > nBytes)
            {
                nLength = nBytes;
            }

            memcpy (
                &m_xNode->m_pData[aDescr.m_nOffset],
                &pData[rnDone], nLength);

            // Mark inode dirty.
            aPage.touch();

            // Adjust counters.
            rnDone  += nLength;
            nOffset += nLength;
            nBytes  -= nLength;

            // Adjust data length.
            if (aPage.dataLength() < nOffset)
                aPage.dataLength (nOffset);
        }
        else
        {
            // Write to data page (external scope).
            OStoreDataPageObject aData;

            inode::ChunkDescriptor aDescr (
                nOffset - m_xNode->capacity(), OStoreDataPageData::capacity(m_xNode->m_aDescr)); // @@@

            sal_uInt32 nLength = sal_uInt32(aDescr.m_nLength);
            if ((aDescr.m_nOffset > 0) || (nBytes < nLength))
            {
                // Unaligned. Need to load/create data page.
                eErrCode = aPage.read (aDescr.m_nPage, aData, *m_xManager);
                if (eErrCode != store_E_None)
                {
                    if (eErrCode != store_E_NotExists)
                        return eErrCode;

                    eErrCode = aData.construct<data>(m_xManager->allocator());
                    if (eErrCode != store_E_None)
                        return eErrCode;
                }
            }

            PageHolderObject< data > xData (aData.makeHolder<data>());
            if (!xData.is())
            {
                eErrCode = aData.construct<data>(m_xManager->allocator());
                if (eErrCode != store_E_None)
                    return eErrCode;
                xData = aData.makeHolder<data>();
            }

            // Modify data page.
            if(nLength > nBytes)
            {
                nLength = nBytes;
            }
            memcpy (
                &xData->m_pData[aDescr.m_nOffset],
                &pData[rnDone], nLength);

            // Save data page.
            eErrCode = aPage.write (aDescr.m_nPage, aData, *m_xManager);
            if (eErrCode != store_E_None)
                return eErrCode;

            // Adjust counters.
            rnDone  += nLength;
            nOffset += nLength;
            nBytes  -= nLength;

            // Adjust data length.
            if (aPage.dataLength() < nOffset)
                aPage.dataLength (nOffset);
        }
    }

    // Check for modified inode.
    if (aPage.dirty())
        return m_xManager->saveObjectAt (aPage, aPage.location());
    else
        return store_E_None;
}

storeError OStoreLockBytes::setSize (sal_uInt32 nSize)
{
    if (!m_xManager.is())
        return store_E_InvalidAccess;
    if (!m_bWriteable)
        return store_E_AccessViolation;

    // Acquire exclusive access.
    osl::MutexGuard aGuard (*m_xManager);

    // Determine current length.
    OStoreDirectoryPageObject aPage (m_xNode.get());
    sal_uInt32 nDataLen = aPage.dataLength();

    if (nSize == nDataLen)
        return store_E_None;

    if (nSize < nDataLen)
    {
        // Truncate.
        storeError eErrCode = store_E_None;

        // Determine 'Size' scope.
        inode::ChunkScope eSizeScope = m_xNode->scope (nSize);
        if (eSizeScope == inode::SCOPE_INTERNAL)
        {
            // Internal 'Size' scope. Determine 'Data' scope.
            inode::ChunkScope eDataScope = m_xNode->scope (nDataLen);
            if (eDataScope == inode::SCOPE_EXTERNAL)
            {
                // External 'Data' scope. Truncate all external data pages.
                eErrCode = aPage.truncate (0, *m_xManager);
                if (eErrCode != store_E_None)
                    return eErrCode;
            }

            // Truncate internal data page.
            inode::ChunkDescriptor aDescr (nSize, m_xNode->capacity());
            memset (
                &(m_xNode->m_pData[aDescr.m_nOffset]),
                0, aDescr.m_nLength);
        }
        else
        {
            // External 'Size' scope. Truncate external data pages.
            inode::ChunkDescriptor aDescr (
                nSize - m_xNode->capacity(), OStoreDataPageData::capacity(m_xNode->m_aDescr)); // @@@

            sal_uInt32 nPage = aDescr.m_nPage;
            if (aDescr.m_nOffset) nPage += 1;

            eErrCode = aPage.truncate (nPage, *m_xManager);
            if (eErrCode != store_E_None)
                return eErrCode;
        }
    }

    // Set (extended or truncated) size.
    aPage.dataLength (nSize);

    // Save modified inode.
    return m_xManager->saveObjectAt (aPage, aPage.location());
}

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

Messung V0.5
C=95 H=96 G=95

¤ Dauer der Verarbeitung: 0.12 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.