872 lines
23 KiB
C++
872 lines
23 KiB
C++
/*************************************************************************
|
|
*
|
|
* $RCSfile: storlckb.cxx,v $
|
|
*
|
|
* $Revision: 1.2 $
|
|
*
|
|
* last change: $Author: mhu $ $Date: 2001-03-13 21:03:26 $
|
|
*
|
|
* The Contents of this file are made available subject to the terms of
|
|
* either of the following licenses
|
|
*
|
|
* - GNU Lesser General Public License Version 2.1
|
|
* - Sun Industry Standards Source License Version 1.1
|
|
*
|
|
* Sun Microsystems Inc., October, 2000
|
|
*
|
|
* GNU Lesser General Public License Version 2.1
|
|
* =============================================
|
|
* Copyright 2000 by Sun Microsystems, Inc.
|
|
* 901 San Antonio Road, Palo Alto, CA 94303, USA
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License version 2.1, as published by the Free Software Foundation.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
|
* MA 02111-1307 USA
|
|
*
|
|
*
|
|
* Sun Industry Standards Source License Version 1.1
|
|
* =================================================
|
|
* The contents of this file are subject to the Sun Industry Standards
|
|
* Source License Version 1.1 (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.openoffice.org/license.html.
|
|
*
|
|
* Software provided under this License is provided on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
|
|
* WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
|
|
* MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
|
|
* See the License for the specific provisions governing your rights and
|
|
* obligations concerning the Software.
|
|
*
|
|
* The Initial Developer of the Original Code is: Sun Microsystems, Inc.
|
|
*
|
|
* Copyright: 2000 by Sun Microsystems, Inc.
|
|
*
|
|
* All Rights Reserved.
|
|
*
|
|
* Contributor(s): Matthias Huetsch <matthias.huetsch@sun.com>
|
|
*
|
|
*
|
|
************************************************************************/
|
|
|
|
#define _STORE_STORLCKB_CXX_ "$Revision: 1.2 $"
|
|
|
|
#ifndef _SAL_TYPES_H_
|
|
#include <sal/types.h>
|
|
#endif
|
|
#ifndef _SAL_MACROS_H_
|
|
#include <sal/macros.h>
|
|
#endif
|
|
|
|
#ifndef _RTL_MEMORY_H_
|
|
#include <rtl/memory.h>
|
|
#endif
|
|
#ifndef _RTL_TEXTCVT_H_
|
|
#include <rtl/textcvt.h>
|
|
#endif
|
|
#ifndef _RTL_STRING_HXX_
|
|
#include <rtl/string.hxx>
|
|
#endif
|
|
#ifndef _RTL_REF_HXX_
|
|
#include <rtl/ref.hxx>
|
|
#endif
|
|
|
|
#ifndef _OSL_MUTEX_HXX_
|
|
#include <osl/mutex.hxx>
|
|
#endif
|
|
|
|
#ifndef _STORE_TYPES_H_
|
|
#include <store/types.h>
|
|
#endif
|
|
#ifndef _STORE_OBJECT_HXX_
|
|
#include <store/object.hxx>
|
|
#endif
|
|
#ifndef _STORE_LOCKBYTE_HXX_
|
|
#include <store/lockbyte.hxx>
|
|
#endif
|
|
|
|
#ifndef _STORE_STORBASE_HXX_
|
|
#include <storbase.hxx>
|
|
#endif
|
|
#ifndef _STORE_STORDATA_HXX_
|
|
#include <stordata.hxx>
|
|
#endif
|
|
#ifndef _STORE_STORPAGE_HXX_
|
|
#include <storpage.hxx>
|
|
#endif
|
|
|
|
#ifndef _STORE_STORLCKB_HXX_
|
|
#include <storlckb.hxx>
|
|
#endif
|
|
|
|
using namespace store;
|
|
|
|
/*========================================================================
|
|
*
|
|
* OStore... internals.
|
|
*
|
|
*======================================================================*/
|
|
/*
|
|
* __store_convertTextToUnicode.
|
|
*/
|
|
inline sal_Int32 __store_convertTextToUnicode (
|
|
rtl_TextToUnicodeConverter hConverter,
|
|
const sal_Char *pSrcBuffer, sal_Int32 nSrcLength,
|
|
sal_Unicode *pDstBuffer, sal_Int32 nDstLength)
|
|
{
|
|
sal_uInt32 nCvtInfo, nCvtBytes = 0;
|
|
return rtl_convertTextToUnicode (
|
|
hConverter, 0,
|
|
pSrcBuffer, nSrcLength,
|
|
pDstBuffer, nDstLength,
|
|
OSTRING_TO_OUSTRING_CVTFLAGS,
|
|
&nCvtInfo, &nCvtBytes);
|
|
}
|
|
|
|
/*
|
|
* __store_iget.
|
|
* Precond: exclusive access.
|
|
*/
|
|
static storeError __store_iget (
|
|
OStorePageManager &rManager,
|
|
OStoreDirectoryPageData &rNode,
|
|
sal_uInt32 nAttrib,
|
|
const rtl_String *pPath,
|
|
const rtl_String *pName,
|
|
storeAccessMode eMode)
|
|
{
|
|
// Setup inode page key.
|
|
OStorePageKey aKey;
|
|
storeError eErrCode = OStorePageNameBlock::namei (pPath, pName, aKey);
|
|
if (eErrCode != store_E_None)
|
|
return eErrCode;
|
|
|
|
// Check for directory.
|
|
if (nAttrib & STORE_ATTRIB_ISDIR)
|
|
{
|
|
// Ugly, but necessary (backward compatibility).
|
|
aKey.m_nLow = OStorePageGuard::crc32 (aKey.m_nLow, "/", 1);
|
|
}
|
|
|
|
// Load inode page.
|
|
OStoreDirectoryPageObject aPage (rNode);
|
|
eErrCode = rManager.load (aKey, aPage);
|
|
if (eErrCode != store_E_None)
|
|
{
|
|
// Check mode and reason.
|
|
if (eErrCode != store_E_NotExists)
|
|
return eErrCode;
|
|
|
|
if (eMode == store_AccessReadWrite)
|
|
return store_E_NotExists;
|
|
if (eMode == store_AccessReadOnly)
|
|
return store_E_NotExists;
|
|
|
|
if (!rManager.isWriteable())
|
|
return store_E_AccessViolation;
|
|
|
|
// Setup inode nameblock.
|
|
rNode.m_aNameBlock.m_aKey = aKey;
|
|
rNode.m_aNameBlock.m_nAttrib = nAttrib;
|
|
|
|
rtl_copyMemory (
|
|
&rNode.m_aNameBlock.m_pData[0],
|
|
pName->buffer, pName->length);
|
|
|
|
// Save inode page.
|
|
eErrCode = rManager.save (aKey, aPage);
|
|
if (eErrCode != store_E_None)
|
|
return eErrCode;
|
|
}
|
|
|
|
// Check for symbolic link.
|
|
if (aPage.attrib() & STORE_ATTRIB_ISLINK)
|
|
{
|
|
// Obtain 'Destination' page key.
|
|
OStorePageKey aDstKey;
|
|
rtl_copyMemory (&aDstKey, &rNode.m_pData[0], sizeof(aDstKey));
|
|
|
|
#ifdef OSL_BIGENDIAN
|
|
// Swap to internal representation.
|
|
aDstKey.swap();
|
|
#endif /* OSL_BIGENDIAN */
|
|
|
|
// Load 'Destination' inode.
|
|
eErrCode = rManager.load (aDstKey, aPage);
|
|
if (eErrCode != store_E_None)
|
|
return eErrCode;
|
|
}
|
|
|
|
// Done.
|
|
return store_E_None;
|
|
}
|
|
|
|
/*========================================================================
|
|
*
|
|
* OStoreDirectory implementation.
|
|
*
|
|
*======================================================================*/
|
|
const sal_uInt32 OStoreDirectory::m_nTypeId = sal_uInt32(0x89191107);
|
|
|
|
/*
|
|
* OStoreDirectory.
|
|
*/
|
|
OStoreDirectory::OStoreDirectory (void)
|
|
: m_xManager (NULL),
|
|
m_pNode (NULL),
|
|
m_aDescr (0, 0, 0),
|
|
m_nPath (0),
|
|
m_hTextCvt (NULL)
|
|
{
|
|
}
|
|
|
|
/*
|
|
* ~OStoreDirectory.
|
|
*/
|
|
OStoreDirectory::~OStoreDirectory (void)
|
|
{
|
|
if (m_xManager.is())
|
|
{
|
|
osl::MutexGuard aGuard (*m_xManager);
|
|
if (m_pNode)
|
|
{
|
|
m_xManager->releasePage (m_aDescr, store_AccessReadOnly);
|
|
}
|
|
}
|
|
delete m_pNode;
|
|
rtl_destroyTextToUnicodeConverter (m_hTextCvt);
|
|
}
|
|
|
|
/*
|
|
* isKindOf.
|
|
*/
|
|
sal_Bool SAL_CALL OStoreDirectory::isKindOf (sal_uInt32 nTypeId)
|
|
{
|
|
return (nTypeId == m_nTypeId);
|
|
}
|
|
|
|
/*
|
|
* create.
|
|
*/
|
|
storeError OStoreDirectory::create (
|
|
OStorePageManager *pManager,
|
|
rtl_uString *pPath,
|
|
rtl_uString *pName,
|
|
storeAccessMode eMode)
|
|
{
|
|
rtl::Reference<OStorePageManager> xManager (pManager);
|
|
if (!xManager.is())
|
|
return store_E_InvalidAccess;
|
|
|
|
if (!(pPath && pName))
|
|
return store_E_InvalidParameter;
|
|
|
|
osl::MutexGuard aGuard (*xManager);
|
|
storeError eErrCode = xManager->getPageSize (m_aDescr.m_nSize);
|
|
if (eErrCode != store_E_None)
|
|
return eErrCode;
|
|
|
|
delete m_pNode;
|
|
m_pNode = new(m_aDescr.m_nSize) inode(m_aDescr.m_nSize);
|
|
if (!m_pNode)
|
|
return store_E_OutOfMemory;
|
|
|
|
rtl::OString aPath (pPath->buffer, pPath->length, RTL_TEXTENCODING_UTF8);
|
|
rtl::OString aName (pName->buffer, pName->length, RTL_TEXTENCODING_UTF8);
|
|
|
|
eErrCode = __store_iget (
|
|
*xManager, *m_pNode, STORE_ATTRIB_ISDIR,
|
|
aPath.pData, aName.pData, eMode);
|
|
if (eErrCode != store_E_None)
|
|
return eErrCode;
|
|
|
|
sal_uInt32 nAttrib = m_pNode->m_aNameBlock.m_nAttrib;
|
|
if (!(nAttrib & STORE_ATTRIB_ISDIR))
|
|
return store_E_NotDirectory;
|
|
|
|
m_aDescr = m_pNode->m_aDescr;
|
|
eErrCode = xManager->acquirePage (m_aDescr, store_AccessReadOnly);
|
|
if (eErrCode == store_E_None)
|
|
{
|
|
// Evaluate iteration path from NameBlock.
|
|
typedef OStorePageGuard G;
|
|
sal_Char *pszName = m_pNode->m_aNameBlock.m_pData;
|
|
|
|
m_nPath = m_pNode->m_aNameBlock.m_aKey.m_nHigh;
|
|
m_nPath = G::crc32 (m_nPath, pszName, rtl_str_getLength(pszName));
|
|
m_nPath = G::crc32 (m_nPath, "/", 1);
|
|
|
|
// Accept page manager.
|
|
m_xManager = xManager;
|
|
}
|
|
return eErrCode;
|
|
}
|
|
|
|
/*
|
|
* iterate.
|
|
*/
|
|
storeError OStoreDirectory::iterate (storeFindData &rFindData)
|
|
{
|
|
if (!m_xManager.is())
|
|
return store_E_InvalidAccess;
|
|
|
|
storeError eErrCode = store_E_NoMoreFiles;
|
|
if (!rFindData.m_nReserved)
|
|
return eErrCode;
|
|
|
|
// Acquire exclusive access.
|
|
osl::MutexGuard aGuard (*m_xManager);
|
|
|
|
// Check TextConverter.
|
|
if (m_hTextCvt == NULL)
|
|
m_hTextCvt = rtl_createTextToUnicodeConverter(RTL_TEXTENCODING_UTF8);
|
|
|
|
// Setup iteration key and page buffer.
|
|
OStorePageKey aKey (rFindData.m_nReserved, m_nPath);
|
|
OStoreDirectoryPageObject aPage (*m_pNode);
|
|
|
|
// Iterate.
|
|
for (;;)
|
|
{
|
|
eErrCode = m_xManager->iterate (aKey, aPage, rFindData.m_nAttrib);
|
|
if (!((eErrCode == store_E_None) && (aKey.m_nHigh == m_nPath)))
|
|
break;
|
|
|
|
if (!(rFindData.m_nAttrib & STORE_ATTRIB_ISLINK))
|
|
{
|
|
// Load page.
|
|
eErrCode = m_xManager->load (aPage);
|
|
if (eErrCode == store_E_None)
|
|
{
|
|
// Setup FindData.
|
|
sal_Char *p = m_pNode->m_aNameBlock.m_pData;
|
|
sal_Int32 n = rtl_str_getLength (p);
|
|
sal_Int32 k = rFindData.m_nLength;
|
|
|
|
n = __store_convertTextToUnicode (
|
|
m_hTextCvt, p, n,
|
|
rFindData.m_pszName, STORE_MAXIMUM_NAMESIZE - 1);
|
|
if (k > n)
|
|
{
|
|
k = (k - n) * sizeof(sal_Unicode);
|
|
rtl_zeroMemory (&rFindData.m_pszName[n], k);
|
|
}
|
|
|
|
rFindData.m_nLength = n;
|
|
rFindData.m_nAttrib |= aPage.attrib();
|
|
rFindData.m_nSize = aPage.dataLength();
|
|
|
|
// Leave.
|
|
rFindData.m_nReserved = aKey.m_nLow;
|
|
return store_E_None;
|
|
}
|
|
}
|
|
|
|
if (aKey.m_nLow > 0)
|
|
aKey.m_nLow -= 1;
|
|
else
|
|
break;
|
|
}
|
|
|
|
// Finished.
|
|
rtl_zeroMemory (&rFindData, sizeof (storeFindData));
|
|
return store_E_NoMoreFiles;
|
|
}
|
|
|
|
/*========================================================================
|
|
*
|
|
* OStoreLockBytes implementation.
|
|
*
|
|
*======================================================================*/
|
|
const sal_uInt32 OStoreLockBytes::m_nTypeId = sal_uInt32(0x94190310);
|
|
|
|
/*
|
|
* OStoreLockBytes.
|
|
*/
|
|
OStoreLockBytes::OStoreLockBytes (void)
|
|
: m_xManager (NULL),
|
|
m_nPageSize (0),
|
|
m_pNode (NULL),
|
|
m_pData (NULL),
|
|
m_pSingle (NULL),
|
|
m_pDouble (NULL),
|
|
m_pTriple (NULL),
|
|
m_bWriteable (sal_False)
|
|
{
|
|
}
|
|
|
|
/*
|
|
* ~OStoreLockBytes.
|
|
*/
|
|
OStoreLockBytes::~OStoreLockBytes (void)
|
|
{
|
|
if (m_xManager.is())
|
|
{
|
|
osl::MutexGuard aGuard (*m_xManager);
|
|
if (m_pNode)
|
|
{
|
|
OStorePageDescriptor aDescr (m_pNode->m_aDescr);
|
|
if (m_bWriteable)
|
|
m_xManager->releasePage (aDescr, store_AccessReadWrite);
|
|
else
|
|
m_xManager->releasePage (aDescr, store_AccessReadOnly);
|
|
}
|
|
}
|
|
|
|
delete m_pNode;
|
|
delete m_pData;
|
|
|
|
delete m_pSingle;
|
|
delete m_pDouble;
|
|
delete m_pTriple;
|
|
}
|
|
|
|
/*
|
|
* isKindOf.
|
|
*/
|
|
sal_Bool SAL_CALL OStoreLockBytes::isKindOf (sal_uInt32 nTypeId)
|
|
{
|
|
return (nTypeId == m_nTypeId);
|
|
}
|
|
|
|
/*
|
|
* acquire.
|
|
*/
|
|
oslInterlockedCount SAL_CALL OStoreLockBytes::acquire (void)
|
|
{
|
|
return OStoreObject::acquire();
|
|
}
|
|
|
|
/*
|
|
* release.
|
|
*/
|
|
oslInterlockedCount SAL_CALL OStoreLockBytes::release (void)
|
|
{
|
|
return OStoreObject::release();
|
|
}
|
|
|
|
/*
|
|
* create.
|
|
*/
|
|
storeError OStoreLockBytes::create (
|
|
OStorePageManager *pManager,
|
|
rtl_uString *pPath,
|
|
rtl_uString *pName,
|
|
storeAccessMode eMode)
|
|
{
|
|
rtl::Reference<OStorePageManager> xManager (pManager);
|
|
if (!xManager.is())
|
|
return store_E_InvalidAccess;
|
|
|
|
if (!(pPath && pName))
|
|
return store_E_InvalidParameter;
|
|
|
|
osl::MutexGuard aGuard (*xManager);
|
|
storeError eErrCode = xManager->getPageSize (m_nPageSize);
|
|
if (eErrCode != store_E_None)
|
|
return eErrCode;
|
|
|
|
delete m_pNode;
|
|
m_pNode = new(m_nPageSize) inode(m_nPageSize);
|
|
if (!m_pNode)
|
|
return store_E_OutOfMemory;
|
|
|
|
rtl::OString aPath (pPath->buffer, pPath->length, RTL_TEXTENCODING_UTF8);
|
|
rtl::OString aName (pName->buffer, pName->length, RTL_TEXTENCODING_UTF8);
|
|
|
|
eErrCode = __store_iget (
|
|
*xManager, *m_pNode, STORE_ATTRIB_ISFILE,
|
|
aPath.pData, aName.pData, eMode);
|
|
if (eErrCode != store_E_None)
|
|
return eErrCode;
|
|
|
|
sal_uInt32 nAttrib = m_pNode->m_aNameBlock.m_nAttrib;
|
|
if (!(nAttrib & STORE_ATTRIB_ISFILE))
|
|
{
|
|
// No ISFILE in older versions (backward compatibility).
|
|
if (nAttrib & STORE_ATTRIB_ISLINK)
|
|
return store_E_NotFile;
|
|
}
|
|
|
|
// ...
|
|
OStorePageDescriptor aDescr (m_pNode->m_aDescr);
|
|
if (eMode != store_AccessReadOnly)
|
|
eErrCode = xManager->acquirePage (aDescr, store_AccessReadWrite);
|
|
else
|
|
eErrCode = xManager->acquirePage (aDescr, store_AccessReadOnly);
|
|
if (eErrCode != store_E_None)
|
|
return eErrCode;
|
|
|
|
// ...
|
|
m_xManager = xManager;
|
|
m_bWriteable = (eMode != store_AccessReadOnly);
|
|
|
|
// Check for truncation.
|
|
if (eMode == store_AccessCreate)
|
|
{
|
|
// Truncate to zero length.
|
|
eErrCode = setSize(0);
|
|
}
|
|
return eErrCode;
|
|
}
|
|
|
|
/*
|
|
* readAt.
|
|
*/
|
|
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_pNode);
|
|
|
|
sal_uInt32 nDataLen = aPage.dataLength();
|
|
if ((nOffset + nBytes) > nDataLen)
|
|
nBytes = nDataLen - nOffset;
|
|
|
|
// Read data.
|
|
sal_uInt8 *pData = (sal_uInt8*)pBuffer;
|
|
while ((0 < nBytes) && (nOffset < nDataLen))
|
|
{
|
|
// Determine 'Offset' scope.
|
|
inode::ChunkScope eScope = m_pNode->scope (nOffset);
|
|
if (eScope == inode::SCOPE_INTERNAL)
|
|
{
|
|
// Read from inode page (internal scope).
|
|
inode::ChunkDescriptor aDescr (
|
|
nOffset, m_pNode->capacity());
|
|
|
|
sal_uInt32 nLength = sal_uInt32(aDescr.m_nLength);
|
|
nLength = SAL_MIN(nLength, nBytes);
|
|
|
|
rtl_copyMemory (
|
|
&pData[rnDone],
|
|
&m_pNode->m_pData[aDescr.m_nOffset],
|
|
nLength);
|
|
|
|
// Adjust counters.
|
|
rnDone += nLength;
|
|
nOffset += nLength;
|
|
nBytes -= nLength;
|
|
}
|
|
else
|
|
{
|
|
// Read from data page (external scope).
|
|
if (!m_pData)
|
|
m_pData = new(m_nPageSize) data(m_nPageSize);
|
|
if (!m_pData)
|
|
return store_E_OutOfMemory;
|
|
OStoreDataPageObject aData (*m_pData);
|
|
|
|
inode::ChunkDescriptor aDescr (
|
|
nOffset - m_pNode->capacity(), m_pData->capacity());
|
|
|
|
sal_uInt32 nLength = sal_uInt32(aDescr.m_nLength);
|
|
nLength = SAL_MIN(nLength, nBytes);
|
|
|
|
storeError eErrCode = aPage.get (
|
|
aDescr.m_nPage, m_pSingle, m_pDouble, m_pTriple,
|
|
aData, *m_xManager, NULL);
|
|
if (eErrCode != store_E_None)
|
|
{
|
|
if (eErrCode != store_E_NotExists)
|
|
return eErrCode;
|
|
|
|
rtl_zeroMemory (
|
|
&pData[rnDone],
|
|
nLength);
|
|
}
|
|
else
|
|
{
|
|
rtl_copyMemory (
|
|
&pData[rnDone],
|
|
&m_pData->m_pData[aDescr.m_nOffset],
|
|
nLength);
|
|
}
|
|
|
|
// Adjust counters.
|
|
rnDone += nLength;
|
|
nOffset += nLength;
|
|
nBytes -= nLength;
|
|
}
|
|
}
|
|
|
|
// Done.
|
|
return store_E_None;
|
|
}
|
|
|
|
/*
|
|
* writeAt.
|
|
*/
|
|
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_pNode);
|
|
const sal_uInt8 *pData = (const sal_uInt8*)pBuffer;
|
|
|
|
storeError eErrCode = store_E_None;
|
|
while (nBytes > 0)
|
|
{
|
|
// Determine 'Offset' scope.
|
|
inode::ChunkScope eScope = m_pNode->scope (nOffset);
|
|
if (eScope == inode::SCOPE_INTERNAL)
|
|
{
|
|
// Write to inode page (internal scope).
|
|
inode::ChunkDescriptor aDescr (
|
|
nOffset, m_pNode->capacity());
|
|
|
|
sal_uInt32 nLength = sal_uInt32(aDescr.m_nLength);
|
|
nLength = SAL_MIN(nLength, nBytes);
|
|
|
|
rtl_copyMemory (
|
|
&m_pNode->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).
|
|
if (!m_pData)
|
|
m_pData = new(m_nPageSize) data(m_nPageSize);
|
|
if (!m_pData)
|
|
return store_E_OutOfMemory;
|
|
OStoreDataPageObject aData (*m_pData);
|
|
|
|
inode::ChunkDescriptor aDescr (
|
|
nOffset - m_pNode->capacity(), m_pData->capacity());
|
|
|
|
sal_uInt32 nLength = sal_uInt32(aDescr.m_nLength);
|
|
if ((aDescr.m_nOffset > 0) || (nBytes < nLength))
|
|
{
|
|
// Unaligned. Need to load/create data page.
|
|
eErrCode = aPage.get (
|
|
aDescr.m_nPage, m_pSingle, m_pDouble, m_pTriple,
|
|
aData, *m_xManager, NULL);
|
|
if (eErrCode != store_E_None)
|
|
{
|
|
if (eErrCode != store_E_NotExists)
|
|
return eErrCode;
|
|
|
|
rtl_zeroMemory (
|
|
&m_pData->m_pData[0],
|
|
m_pData->capacity());
|
|
}
|
|
}
|
|
|
|
// Modify data page.
|
|
nLength = SAL_MIN(nLength, nBytes);
|
|
|
|
rtl_copyMemory (
|
|
&m_pData->m_pData[aDescr.m_nOffset],
|
|
&pData[rnDone], nLength);
|
|
|
|
// Save data page.
|
|
eErrCode = aPage.put (
|
|
aDescr.m_nPage, m_pSingle, m_pDouble, m_pTriple,
|
|
aData, *m_xManager, NULL);
|
|
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->save (aPage);
|
|
else
|
|
return store_E_None;
|
|
}
|
|
|
|
/*
|
|
* flush.
|
|
*/
|
|
storeError OStoreLockBytes::flush (void)
|
|
{
|
|
if (!m_xManager.is())
|
|
return store_E_InvalidAccess;
|
|
|
|
return m_xManager->flush();
|
|
}
|
|
|
|
/*
|
|
* setSize.
|
|
*/
|
|
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_pNode);
|
|
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_pNode->scope (nSize);
|
|
if (eSizeScope == inode::SCOPE_INTERNAL)
|
|
{
|
|
// Internal 'Size' scope. Determine 'Data' scope.
|
|
inode::ChunkScope eDataScope = m_pNode->scope (nDataLen);
|
|
if (eDataScope == inode::SCOPE_EXTERNAL)
|
|
{
|
|
// External 'Data' scope.
|
|
if (!m_pData)
|
|
m_pData = new(m_nPageSize) data(m_nPageSize);
|
|
if (!m_pData)
|
|
return store_E_OutOfMemory;
|
|
OStoreDataPageObject aData (*m_pData);
|
|
|
|
// Truncate all external data pages.
|
|
eErrCode = aPage.truncate (
|
|
0, m_pSingle, m_pDouble, m_pTriple,
|
|
aData, *m_xManager, NULL);
|
|
if (eErrCode != store_E_None)
|
|
return eErrCode;
|
|
}
|
|
|
|
// Truncate internal data page.
|
|
inode::ChunkDescriptor aDescr (nSize, m_pNode->capacity());
|
|
rtl_zeroMemory (
|
|
&m_pNode->m_pData[aDescr.m_nOffset],
|
|
aDescr.m_nLength);
|
|
}
|
|
else
|
|
{
|
|
// External 'Size' scope.
|
|
if (!m_pData)
|
|
m_pData = new(m_nPageSize) data(m_nPageSize);
|
|
if (!m_pData)
|
|
return store_E_OutOfMemory;
|
|
OStoreDataPageObject aData (*m_pData);
|
|
|
|
// Truncate external data pages.
|
|
inode::ChunkDescriptor aDescr (
|
|
nSize - m_pNode->capacity(), m_pData->capacity());
|
|
|
|
sal_uInt32 nPage = aDescr.m_nPage;
|
|
if (aDescr.m_nOffset) nPage += 1;
|
|
|
|
eErrCode = aPage.truncate (
|
|
nPage, m_pSingle, m_pDouble, m_pTriple,
|
|
aData, *m_xManager, NULL);
|
|
if (eErrCode != store_E_None)
|
|
return eErrCode;
|
|
}
|
|
}
|
|
|
|
// Set (extended or truncated) size.
|
|
aPage.dataLength (nSize);
|
|
|
|
// Save modified inode.
|
|
return m_xManager->save (aPage);
|
|
}
|
|
|
|
/*
|
|
* stat.
|
|
*/
|
|
storeError OStoreLockBytes::stat (sal_uInt32 &rnSize)
|
|
{
|
|
rnSize = 0;
|
|
|
|
if (!m_xManager.is())
|
|
return store_E_InvalidAccess;
|
|
|
|
rnSize = m_pNode->m_aDataBlock.m_nDataLen;
|
|
return store_E_None;
|
|
}
|
|
|
|
/*
|
|
* lockRange.
|
|
*/
|
|
storeError OStoreLockBytes::lockRange (
|
|
sal_uInt32 nOffset, sal_uInt32 nBytes)
|
|
{
|
|
// (NYI).
|
|
return store_E_None;
|
|
}
|
|
|
|
/*
|
|
* unlockRange.
|
|
*/
|
|
storeError OStoreLockBytes::unlockRange (
|
|
sal_uInt32 nOffset, sal_uInt32 nBytes)
|
|
{
|
|
// (NYI).
|
|
return store_E_None;
|
|
}
|
|
|