summaryrefslogtreecommitdiff
path: root/store
diff options
context:
space:
mode:
Diffstat (limited to 'store')
-rw-r--r--store/inc/makefile.mk51
-rw-r--r--store/inc/pch/precompiled_store.cxx32
-rw-r--r--store/inc/pch/precompiled_store.hxx35
-rw-r--r--store/inc/store/store.h414
-rw-r--r--store/inc/store/store.hxx390
-rw-r--r--store/inc/store/store.inl454
-rw-r--r--store/inc/store/types.h170
-rw-r--r--store/prj/build.lst5
-rw-r--r--store/prj/d.lst13
-rw-r--r--store/source/lockbyte.cxx989
-rw-r--r--store/source/lockbyte.hxx222
-rw-r--r--store/source/makefile.mk75
-rw-r--r--store/source/object.cxx115
-rw-r--r--store/source/object.hxx146
-rw-r--r--store/source/storbase.cxx205
-rw-r--r--store/source/storbase.hxx974
-rw-r--r--store/source/storbios.cxx1570
-rw-r--r--store/source/storbios.hxx302
-rw-r--r--store/source/storcach.cxx564
-rw-r--r--store/source/storcach.hxx115
-rw-r--r--store/source/stordata.cxx1207
-rw-r--r--store/source/stordata.hxx873
-rw-r--r--store/source/stordir.cxx249
-rw-r--r--store/source/stordir.hxx157
-rw-r--r--store/source/store.cxx768
-rw-r--r--store/source/storlckb.cxx454
-rw-r--r--store/source/storlckb.hxx174
-rw-r--r--store/source/storpage.cxx1066
-rw-r--r--store/source/storpage.hxx229
-rw-r--r--store/source/stortree.cxx688
-rw-r--r--store/source/stortree.hxx348
-rw-r--r--store/util/makefile.mk83
-rw-r--r--store/util/store.map31
-rw-r--r--store/util/store.xml7
-rw-r--r--store/version.mk44
-rw-r--r--store/workben/makefile.mk110
-rw-r--r--store/workben/t_base.cxx385
-rw-r--r--store/workben/t_file.cxx247
-rw-r--r--store/workben/t_leak.cxx19
-rw-r--r--store/workben/t_page.cxx1574
-rw-r--r--store/workben/t_store.cxx608
41 files changed, 16162 insertions, 0 deletions
diff --git a/store/inc/makefile.mk b/store/inc/makefile.mk
new file mode 100644
index 000000000000..7702b58970b8
--- /dev/null
+++ b/store/inc/makefile.mk
@@ -0,0 +1,51 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2008 by Sun Microsystems, Inc.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.3 $
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org 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 version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+PRJ=..
+
+PRJNAME=store
+TARGET=inc
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+
+# --- Files --------------------------------------------------------
+# --- Targets -------------------------------------------------------
+
+.INCLUDE : target.mk
+
+.IF "$(ENABLE_PCH)"!=""
+ALLTAR : \
+ $(SLO)$/precompiled.pch \
+ $(SLO)$/precompiled_ex.pch
+
+.ENDIF # "$(ENABLE_PCH)"!=""
+
diff --git a/store/inc/pch/precompiled_store.cxx b/store/inc/pch/precompiled_store.cxx
new file mode 100644
index 000000000000..4a539b879e27
--- /dev/null
+++ b/store/inc/pch/precompiled_store.cxx
@@ -0,0 +1,32 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: precompiled_store.cxx,v $
+ * $Revision: 1.3 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_store.hxx"
+
diff --git a/store/inc/pch/precompiled_store.hxx b/store/inc/pch/precompiled_store.hxx
new file mode 100644
index 000000000000..85b750d40589
--- /dev/null
+++ b/store/inc/pch/precompiled_store.hxx
@@ -0,0 +1,35 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: precompiled_store.hxx,v $
+ * $Revision: 1.3 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): Generated on 2006-09-01 17:50:03.342334
+
+#ifdef PRECOMPILED_HEADERS
+#endif
+
diff --git a/store/inc/store/store.h b/store/inc/store/store.h
new file mode 100644
index 000000000000..3a46f272daf4
--- /dev/null
+++ b/store/inc/store/store.h
@@ -0,0 +1,414 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: store.h,v $
+ * $Revision: 1.6 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _STORE_STORE_H_
+#define _STORE_STORE_H_ "$Revision: 1.6 $"
+
+#include <store/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Handle opaque type.
+ */
+typedef void* storeHandle;
+
+
+/** Acquire a Handle.
+ @param Handle [in] the Handle.
+ @return store_E_None upon success
+ */
+storeError SAL_CALL store_acquireHandle (
+ storeHandle Handle
+) SAL_THROW_EXTERN_C();
+
+
+/** Release a Handle.
+ @param Handle [in] the Handle.
+ @return store_E_None upon success,
+ store_E_InvalidHandle otherwise.
+ */
+storeError SAL_CALL store_releaseHandle (
+ storeHandle Handle
+) SAL_THROW_EXTERN_C();
+
+
+
+/** File Handle opaque type.
+ */
+typedef void* storeFileHandle;
+
+
+/** Open a temporary file in memory.
+ @param nPageSize [in] the creation page size,
+ integer multiple of minimum page size.
+ @param phFile [out] the File Handle.
+ @return store_E_None upon success
+ */
+storeError SAL_CALL store_createMemoryFile (
+ sal_uInt16 nPageSize,
+ storeFileHandle *phFile
+) SAL_THROW_EXTERN_C();
+
+
+/** Open a file.
+ @param pFilename [in] the filename as URL or system path.
+ @param eAccessMode [in] the access mode.
+ store_AccessCreate truncate existing and create,
+ store_AccessReadCreate create not existing,
+ store_AccessReadWrite write existing,
+ store_AccessReadOnly never modifies.
+ @param nPageSize [in] the creation page size,
+ integer multiple of minimum page size.
+ @param phFile [out] the File Handle.
+ @return store_E_None upon success
+ */
+storeError SAL_CALL store_openFile (
+ rtl_uString *pFilename,
+ storeAccessMode eAccessMode,
+ sal_uInt16 nPageSize,
+ storeFileHandle *phFile
+) SAL_THROW_EXTERN_C();
+
+
+/** Close a file.
+ @param hFile [in] the File Handle.
+ @return store_E_None upon success,
+ store_E_InvalidHandle otherwise.
+ */
+storeError SAL_CALL store_closeFile (
+ storeFileHandle hFile
+) SAL_THROW_EXTERN_C();
+
+
+/** Flush a file.
+ @param hFile [in] the File Handle.
+ @return store_E_None upon success
+ */
+storeError SAL_CALL store_flushFile (
+ storeFileHandle hFile
+) SAL_THROW_EXTERN_C();
+
+
+/** Get the number of referers to a file.
+ @param hFile [in] the File Handle.
+ @param pnRefCount [out] number of open directories and streams.
+ @return store_E_None upon success
+ */
+storeError SAL_CALL store_getFileRefererCount (
+ storeFileHandle hFile,
+ sal_uInt32 *pnRefCount
+) SAL_THROW_EXTERN_C();
+
+
+/** Get the size of a file.
+ @param hFile [in] the File Handle.
+ @param pnSize [out] the file size in bytes.
+ @return store_E_None upon success
+ */
+storeError SAL_CALL store_getFileSize (
+ storeFileHandle hFile,
+ sal_uInt32 *pnSize
+) SAL_THROW_EXTERN_C();
+
+
+/** Recover and Compact a file into another file.
+ @see store_openFile()
+
+ @param pSrcFilename [in] opened with store_AccessReadOnly.
+ @param pDstFilename [in] created with store_AccessCreate.
+ @return store_E_None upon success
+ */
+storeError SAL_CALL store_rebuildFile (
+ rtl_uString *pSrcFilename,
+ rtl_uString *pDstFilename
+) SAL_THROW_EXTERN_C();
+
+
+
+/** Directory Handle opaque type.
+ */
+typedef void* storeDirectoryHandle;
+
+
+/** Open a directory.
+ @see store_openFile()
+
+ @param hFile [in] the File Handle.
+ @param pPath [in] the directory path.
+ @param pName [in] the directory name.
+ @param eAccessMode [in] the access mode.
+ @param phDirectory [out] the Directory Handle.
+ @return store_E_None upon success
+ */
+storeError SAL_CALL store_openDirectory (
+ storeFileHandle hFile,
+ rtl_uString *pPath,
+ rtl_uString *pName,
+ storeAccessMode eAccessMode,
+ storeDirectoryHandle *phDirectory
+) SAL_THROW_EXTERN_C();
+
+
+/** Close a directory.
+ @param hDirectory [in] the Directory Handle.
+ @return store_E_None upon success,
+ store_E_InvalidHandle otherwise.
+ */
+storeError SAL_CALL store_closeDirectory (
+ storeDirectoryHandle hDirectory
+) SAL_THROW_EXTERN_C();
+
+
+/** Find first directory entry.
+ @param hDirectory [in] the Directory Handle.
+ @param pFindData [out] the Find Data structure.
+ @return store_E_None upon success,
+ store_E_NoMoreFile upon end of iteration.
+ */
+storeError SAL_CALL store_findFirst (
+ storeDirectoryHandle hDirectory,
+ storeFindData *pFindData
+) SAL_THROW_EXTERN_C();
+
+
+/** Find next directory entry.
+ @param hDirectory [in] the Directory Handle.
+ @param pFindData [out] the Find Data structure.
+ @return store_E_None upon success,
+ store_E_NoMoreFile upon end of iteration.
+ */
+storeError SAL_CALL store_findNext (
+ storeDirectoryHandle hDirectory,
+ storeFindData *pFindData
+) SAL_THROW_EXTERN_C();
+
+
+
+/** Stream Handle opaque type.
+ */
+typedef void* storeStreamHandle;
+
+
+/** Open a stream.
+ @see store_openFile()
+
+ @param hFile [in] the File Handle.
+ @param pPath [in] the stream path.
+ @param pName [in] the stream name.
+ @param eAccessMode [in] the access mode.
+ @param phStrm [out] the Stream Handle.
+ @return store_E_None upon success
+ */
+storeError SAL_CALL store_openStream (
+ storeFileHandle hFile,
+ rtl_uString *pPath,
+ rtl_uString *pName,
+ storeAccessMode eMode,
+ storeStreamHandle *phStrm
+) SAL_THROW_EXTERN_C();
+
+
+/** Close a stream.
+ @param hStrm [in] the Stream Handle.
+ @return store_E_None upon success,
+ store_E_InvalidHandle otherwise.
+ */
+storeError SAL_CALL store_closeStream (
+ storeStreamHandle hStrm
+) SAL_THROW_EXTERN_C();
+
+
+/** Read from a stream.
+ @param hStrm [in] the Stream Handle.
+ @param nOffset [in] the offset of the first byte to read.
+ @param pBuffer [out] the buffer.
+ @param nBytes [in] the number of bytes to read.
+ @param pnDone [out] the number of bytes actually read.
+ @return store_E_None upon success
+ */
+storeError SAL_CALL store_readStream (
+ storeStreamHandle hStrm,
+ sal_uInt32 nOffset,
+ void *pBuffer,
+ sal_uInt32 nBytes,
+ sal_uInt32 *pnDone
+) SAL_THROW_EXTERN_C();
+
+
+/** Write to a stream.
+ @param hStrm [in] the Stream Handle.
+ @param nOffset [in] the offset of the first byte to write.
+ @param pBuffer [in] the buffer.
+ @param nBytes [in] the number of bytes to write.
+ @param pnDone [out] the number of bytes actually written.
+ @return store_E_None upon success
+ */
+storeError SAL_CALL store_writeStream (
+ storeStreamHandle hStrm,
+ sal_uInt32 nOffset,
+ const void *pBuffer,
+ sal_uInt32 nBytes,
+ sal_uInt32 *pnDone
+) SAL_THROW_EXTERN_C();
+
+
+/** Flush a stream.
+ @param hStrm [in] the Stream Handle.
+ @return store_E_None upon success
+ */
+storeError SAL_CALL store_flushStream (
+ storeStreamHandle hStrm
+) SAL_THROW_EXTERN_C();
+
+
+/** Get the size of a stream.
+ @param hStrm [in] the Stream Handle.
+ @param pnSize [out] the stream size in bytes.
+ @return store_E_None upon success
+ */
+storeError SAL_CALL store_getStreamSize (
+ storeStreamHandle hStrm,
+ sal_uInt32 *pnSize
+) SAL_THROW_EXTERN_C();
+
+
+/** Set the size of a stream.
+ @param hStrm [in] the Stream Handle.
+ @param nSize [in] the new stream size in bytes.
+ @return store_E_None upon success
+ */
+storeError SAL_CALL store_setStreamSize (
+ storeStreamHandle hStrm,
+ sal_uInt32 nSize
+) SAL_THROW_EXTERN_C();
+
+
+
+/** Set attributes of a file entry.
+ @param hFile [in] the File Handle.
+ @param pPath [in] the entry path.
+ @param pName [in] the entry name.
+ @param nMask1 [in] the attributes to be cleared.
+ @param nMask2 [in] the attributes to be set.
+ @param pnAttrib [out] the resulting attributes, may be NULL.
+ @return store_E_None upon success
+ */
+storeError SAL_CALL store_attrib (
+ storeFileHandle hFile,
+ rtl_uString *pPath,
+ rtl_uString *pName,
+ sal_uInt32 nMask1,
+ sal_uInt32 nMask2,
+ sal_uInt32 *pnAttrib
+) SAL_THROW_EXTERN_C();
+
+
+/** Insert a file entry as 'hard link' to another file entry.
+ @precond Source must not exist, Destination must exist.
+ @postcond Source has attribute STORE_ATTRIB_ISLINK.
+ @see store_attrib()
+
+ @param hFile [in] the File Handle
+ @param pSrcPath [in] the Source path
+ @param pSrcName [in] the Source name
+ @param pDstPath [in] the Destination path
+ @param pDstName [in] the Destination name
+ @return store_E_None upon success
+ */
+storeError SAL_CALL store_link (
+ storeFileHandle hFile,
+ rtl_uString *pSrcPath, rtl_uString *pSrcName,
+ rtl_uString *pDstPath, rtl_uString *pDstName
+) SAL_THROW_EXTERN_C();
+
+
+/** Insert a file entry as 'symbolic link' to another file entry.
+ @precond Source must not exist
+ @postcond Source has attribute STORE_ATTRIB_ISLINK.
+ @see store_attrib()
+
+ @param hFile [in] the File Handle
+ @param pSrcPath [in] the Source path
+ @param pSrcName [in] the Source name
+ @param pDstPath [in] the Destination path
+ @param pDstName [in] the Destination name
+ @return store_E_None upon success
+ */
+storeError SAL_CALL store_symlink (
+ storeFileHandle hFile,
+ rtl_uString *pSrcPath, rtl_uString *pSrcName,
+ rtl_uString *pDstPath, rtl_uString *pDstName
+) SAL_THROW_EXTERN_C();
+
+
+/** Rename a file entry.
+ @param hFile [in] the File Handle
+ @param pSrcPath [in] the Source path
+ @param pSrcName [in] the Source name
+ @param pDstPath [in] the Destination path
+ @param pDstName [in] the Destination name
+ @return store_E_None upon success
+ */
+storeError SAL_CALL store_rename (
+ storeFileHandle hFile,
+ rtl_uString *pSrcPath, rtl_uString *pSrcName,
+ rtl_uString *pDstPath, rtl_uString *pDstName
+) SAL_THROW_EXTERN_C();
+
+
+/** Remove a file entry.
+ @param hFile [in] the File Handle
+ @param pPath [in] the entry path
+ @param pName [in] the entry name
+ @return store_E_None upon success
+ */
+storeError SAL_CALL store_remove (
+ storeFileHandle hFile,
+ rtl_uString *pPath,
+ rtl_uString *pName
+) SAL_THROW_EXTERN_C();
+
+/*========================================================================
+ *
+ * The End.
+ *
+ *======================================================================*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _STORE_STORE_H_ */
+
+
+
+
diff --git a/store/inc/store/store.hxx b/store/inc/store/store.hxx
new file mode 100644
index 000000000000..54f0d44024b8
--- /dev/null
+++ b/store/inc/store/store.hxx
@@ -0,0 +1,390 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: store.hxx,v $
+ * $Revision: 1.5 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _STORE_STORE_HXX_
+#define _STORE_STORE_HXX_ "$Revision: 1.5 $"
+
+#include <sal/types.h>
+#include <rtl/ustring.hxx>
+#include <store/store.h>
+
+namespace store
+{
+
+/*========================================================================
+ *
+ * OStoreStream interface.
+ *
+ *======================================================================*/
+class OStoreStream
+{
+public:
+ /** Construction.
+ */
+ inline OStoreStream (void) SAL_THROW(());
+
+ /** Destruction.
+ */
+ inline ~OStoreStream (void) SAL_THROW(());
+
+ /** Copy construction.
+ */
+ inline OStoreStream (
+ const OStoreStream& rOther) SAL_THROW(());
+
+ /** Assignment.
+ */
+ inline OStoreStream& operator= (
+ const OStoreStream& rOther) SAL_THROW(());
+
+
+ /** Construction from Stream Handle.
+ */
+ inline OStoreStream (storeStreamHandle Handle) SAL_THROW(());
+
+ /** Conversion into Stream Handle.
+ */
+ inline operator storeStreamHandle (void) const SAL_THROW(());
+
+ /** Check for a valid Stream Handle.
+ @return sal_True if valid, sal_False otherwise.
+ */
+ inline sal_Bool isValid (void) const SAL_THROW(());
+
+
+ /** Open the stream.
+ @see store_openStream()
+ */
+ inline storeError create (
+ storeFileHandle hFile,
+ const rtl::OUString &rPath,
+ const rtl::OUString &rName,
+ storeAccessMode eMode
+ ) SAL_THROW(());
+
+ /** Close the stream.
+ @see store_closeStream()
+ */
+ inline void close (void) SAL_THROW(());
+
+ /** Read from the stream.
+ @see store_readStream()
+ */
+ inline storeError readAt (
+ sal_uInt32 nOffset,
+ void *pBuffer,
+ sal_uInt32 nBytes,
+ sal_uInt32 &rnDone
+ ) SAL_THROW(());
+
+ /** Write to the stream.
+ @see store_writeStream()
+ */
+ inline storeError writeAt (
+ sal_uInt32 nOffset,
+ const void *pBuffer,
+ sal_uInt32 nBytes,
+ sal_uInt32 &rnDone
+ ) SAL_THROW(());
+
+ /** Flush the stream.
+ @see store_flushStream()
+ */
+ inline storeError flush (void) const SAL_THROW(());
+
+ /** Get the stream size.
+ @see store_getStreamSize()
+ */
+ inline storeError getSize (sal_uInt32 &rnSize) const SAL_THROW(());
+
+ /** Set the stream size.
+ @see store_setStreamSize()
+ */
+ inline storeError setSize (sal_uInt32 nSize) SAL_THROW(());
+
+private:
+ /** Representation.
+ */
+ storeStreamHandle m_hImpl;
+};
+
+/*========================================================================
+ *
+ * OStoreDirectory interface.
+ *
+ *======================================================================*/
+class OStoreDirectory
+{
+public:
+ /** Construction.
+ */
+ inline OStoreDirectory (void) SAL_THROW(());
+
+ /** Destruction.
+ */
+ inline ~OStoreDirectory (void) SAL_THROW(());
+
+ /** Copy construction.
+ */
+ inline OStoreDirectory (
+ const OStoreDirectory& rOther) SAL_THROW(());
+
+ /** Assignment.
+ */
+ inline OStoreDirectory& operator= (
+ const OStoreDirectory& rOther) SAL_THROW(());
+
+
+ /** Construction from Directory Handle.
+ */
+ inline OStoreDirectory (storeDirectoryHandle Handle) SAL_THROW(());
+
+ /** Conversion into Directory Handle.
+ */
+ inline operator storeDirectoryHandle (void) const SAL_THROW(());
+
+ /** Check for a valid Directory Handle.
+ @return sal_True if valid, sal_False otherwise.
+ */
+ inline sal_Bool isValid (void) const SAL_THROW(());
+
+
+ /** Open the directory.
+ @see store_openDirectory()
+ */
+ inline storeError create (
+ storeFileHandle hFile,
+ const rtl::OUString &rPath,
+ const rtl::OUString &rName,
+ storeAccessMode eMode
+ ) SAL_THROW(());
+
+ /** Close the directory.
+ @see store_closeDirectory()
+ */
+ inline void close (void) SAL_THROW(());
+
+
+ /** Directory iterator type.
+ @see first()
+ @see next()
+ */
+ typedef storeFindData iterator;
+
+ /** Find first directory entry.
+ @see store_findFirst()
+ */
+ inline storeError first (iterator& it) SAL_THROW(());
+
+ /** Find next directory entry.
+ @see store_findNext()
+ */
+ inline storeError next (iterator& it) SAL_THROW(());
+
+ /** Directory traversal helper.
+ @see travel()
+ */
+ class traveller
+ {
+ public:
+ /** Directory traversal callback.
+ @param it [in] current directory entry.
+ @return sal_True to continue iteration, sal_False to stop.
+ */
+ virtual sal_Bool visit (const iterator& it) = 0;
+ };
+
+ /** Directory traversal.
+ @see store_findFirst()
+ @see store_findNext()
+
+ @param rTraveller [in] the traversal callback.
+ @return store_E_NoMoreFiles upon end of iteration.
+ */
+ inline storeError travel (traveller& rTraveller) const;
+
+private:
+ /** Representation.
+ */
+ storeDirectoryHandle m_hImpl;
+};
+
+/*========================================================================
+ *
+ * OStoreFile interface.
+ *
+ *======================================================================*/
+class OStoreFile
+{
+public:
+ /** Construction.
+ */
+ inline OStoreFile (void) SAL_THROW(());
+
+ /** Destruction.
+ */
+ inline ~OStoreFile (void) SAL_THROW(());
+
+ /** Copy construction.
+ */
+ inline OStoreFile (const OStoreFile& rOther) SAL_THROW(());
+
+ /** Assignment.
+ */
+ inline OStoreFile& operator= (const OStoreFile& rOther) SAL_THROW(());
+
+
+ /** Construction from File Handle.
+ */
+ inline OStoreFile (storeFileHandle Handle) SAL_THROW(());
+
+ /** Conversion into File Handle.
+ */
+ inline operator storeFileHandle (void) const SAL_THROW(());
+
+ /** Check for a valid File Handle.
+ @return sal_True if valid, sal_False otherwise.
+ */
+ inline sal_Bool isValid (void) const SAL_THROW(());
+
+
+ /** Open the file.
+ @see store_openFile()
+ */
+ inline storeError create (
+ const rtl::OUString &rFilename,
+ storeAccessMode eAccessMode,
+ sal_uInt16 nPageSize = STORE_DEFAULT_PAGESIZE
+ ) SAL_THROW(());
+
+ /** Open the temporary file in memory.
+ @see store_createMemoryFile()
+ */
+ inline storeError createInMemory (
+ sal_uInt16 nPageSize = STORE_DEFAULT_PAGESIZE
+ ) SAL_THROW(());
+
+ /** Close the file.
+ @see store_closeFile()
+ */
+ inline void close (void) SAL_THROW(());
+
+ /** Flush the file.
+ @see store_flushFile()
+ */
+ inline storeError flush (void) const SAL_THROW(());
+
+ /** Get the number of referers to the file.
+ @see store_getFileRefererCount()
+ */
+ inline storeError getRefererCount (
+ sal_uInt32 &rnRefCount) const SAL_THROW(());
+
+ /** Get the file size.
+ @see store_getFileSize()
+ */
+ inline storeError getSize (
+ sal_uInt32 &rnSize) const SAL_THROW(());
+
+
+ /** Set attributes of a file entry.
+ @see store_attrib()
+ */
+ inline storeError attrib (
+ const rtl::OUString &rPath,
+ const rtl::OUString &rName,
+ sal_uInt32 nMask1,
+ sal_uInt32 nMask2,
+ sal_uInt32 &rnAttrib
+ ) SAL_THROW(());
+
+ /** Set attributes of a file entry.
+ @see store_attrib()
+ */
+ inline storeError attrib (
+ const rtl::OUString &rPath,
+ const rtl::OUString &rName,
+ sal_uInt32 nMask1,
+ sal_uInt32 nMask2
+ ) SAL_THROW(());
+
+ /** Insert a file entry as 'hard link' to another file entry.
+ @see store_link()
+ */
+ inline storeError link (
+ const rtl::OUString &rSrcPath, const rtl::OUString &rSrcName,
+ const rtl::OUString &rDstPath, const rtl::OUString &rDstName
+ ) SAL_THROW(());
+
+ /** Insert a file entry as 'symbolic link' to another file entry.
+ @see store_symlink()
+ */
+ inline storeError symlink (
+ const rtl::OUString &rSrcPath, const rtl::OUString &rSrcName,
+ const rtl::OUString &rDstPath, const rtl::OUString &rDstName
+ ) SAL_THROW(());
+
+ /** Rename a file entry.
+ @see store_rename()
+ */
+ inline storeError rename (
+ const rtl::OUString &rSrcPath, const rtl::OUString &rSrcName,
+ const rtl::OUString &rDstPath, const rtl::OUString &rDstName
+ ) SAL_THROW(());
+
+ /** Remove a file entry.
+ @see store_remove()
+ */
+ inline storeError remove (
+ const rtl::OUString &rPath,
+ const rtl::OUString &rName
+ ) SAL_THROW(());
+
+private:
+ /** Representation.
+ */
+ storeFileHandle m_hImpl;
+};
+
+/*========================================================================
+ *
+ * The End.
+ *
+ *======================================================================*/
+
+#include <store/store.inl>
+
+} // namespace store
+
+#endif /* !_STORE_STORE_HXX_ */
+
+
+
+
diff --git a/store/inc/store/store.inl b/store/inc/store/store.inl
new file mode 100644
index 000000000000..35aff6dde1e2
--- /dev/null
+++ b/store/inc/store/store.inl
@@ -0,0 +1,454 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: store.inl,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#define _STORE_STORE_INL_ "$Revision: 1.4 $"
+
+/*========================================================================
+ *
+ * OStoreStream implementation.
+ *
+ *======================================================================*/
+inline OStoreStream::OStoreStream (void) SAL_THROW(())
+ : m_hImpl (0)
+{
+}
+
+inline OStoreStream::~OStoreStream (void) SAL_THROW(())
+{
+ if (m_hImpl)
+ store_releaseHandle (m_hImpl);
+}
+
+inline OStoreStream::OStoreStream (
+ const OStoreStream& rOther) SAL_THROW(())
+ : m_hImpl (rOther.m_hImpl)
+{
+ if (m_hImpl)
+ store_acquireHandle (m_hImpl);
+}
+
+inline OStoreStream& OStoreStream::operator= (
+ const OStoreStream& rOther) SAL_THROW(())
+{
+ if (m_hImpl)
+ store_releaseHandle (m_hImpl);
+ m_hImpl = rOther.m_hImpl;
+ if (m_hImpl)
+ store_acquireHandle (m_hImpl);
+ return *this;
+}
+
+inline OStoreStream::OStoreStream (
+ storeStreamHandle Handle) SAL_THROW(())
+ : m_hImpl (Handle)
+{
+ if (m_hImpl)
+ store_acquireHandle (m_hImpl);
+}
+
+inline OStoreStream::operator storeStreamHandle (void) const SAL_THROW(())
+{
+ return m_hImpl;
+}
+
+inline sal_Bool OStoreStream::isValid (void) const SAL_THROW(())
+{
+ return (!!m_hImpl);
+}
+
+inline storeError OStoreStream::create (
+ storeFileHandle hFile,
+ const rtl::OUString &rPath,
+ const rtl::OUString &rName,
+ storeAccessMode eMode) SAL_THROW(())
+{
+ if (m_hImpl)
+ {
+ store_releaseHandle (m_hImpl);
+ m_hImpl = 0;
+ }
+ return store_openStream (
+ hFile, rPath.pData, rName.pData, eMode, &m_hImpl);
+}
+
+inline void OStoreStream::close (void) SAL_THROW(())
+{
+ if (m_hImpl)
+ {
+ store_closeStream (m_hImpl);
+ m_hImpl = 0;
+ }
+}
+
+inline storeError OStoreStream::readAt (
+ sal_uInt32 nOffset,
+ void *pBuffer,
+ sal_uInt32 nBytes,
+ sal_uInt32 &rnDone) SAL_THROW(())
+{
+ if (!m_hImpl)
+ return store_E_InvalidHandle;
+
+ return store_readStream (
+ m_hImpl, nOffset, pBuffer, nBytes, &rnDone);
+}
+
+inline storeError OStoreStream::writeAt (
+ sal_uInt32 nOffset,
+ const void *pBuffer,
+ sal_uInt32 nBytes,
+ sal_uInt32 &rnDone) SAL_THROW(())
+{
+ if (!m_hImpl)
+ return store_E_InvalidHandle;
+
+ return store_writeStream (
+ m_hImpl, nOffset, pBuffer, nBytes, &rnDone);
+}
+
+inline storeError OStoreStream::flush (void) const SAL_THROW(())
+{
+ if (!m_hImpl)
+ return store_E_InvalidHandle;
+
+ return store_flushStream (m_hImpl);
+}
+
+inline storeError OStoreStream::getSize (
+ sal_uInt32 &rnSize) const SAL_THROW(())
+{
+ if (!m_hImpl)
+ return store_E_InvalidHandle;
+
+ return store_getStreamSize (m_hImpl, &rnSize);
+}
+
+inline storeError OStoreStream::setSize (
+ sal_uInt32 nSize) SAL_THROW(())
+{
+ if (!m_hImpl)
+ return store_E_InvalidHandle;
+
+ return store_setStreamSize (m_hImpl, nSize);
+}
+
+/*========================================================================
+ *
+ * OStoreDirectory implementation.
+ *
+ *======================================================================*/
+inline OStoreDirectory::OStoreDirectory (void) SAL_THROW(())
+ : m_hImpl (0)
+{
+}
+
+inline OStoreDirectory::~OStoreDirectory (void) SAL_THROW(())
+{
+ if (m_hImpl)
+ store_releaseHandle (m_hImpl);
+}
+
+inline OStoreDirectory::OStoreDirectory (
+ const OStoreDirectory& rOther) SAL_THROW(())
+ : m_hImpl (rOther.m_hImpl)
+{
+ if (m_hImpl)
+ store_acquireHandle (m_hImpl);
+}
+
+inline OStoreDirectory& OStoreDirectory::operator= (
+ const OStoreDirectory& rOther) SAL_THROW(())
+{
+ if (m_hImpl)
+ store_releaseHandle (m_hImpl);
+ m_hImpl = rOther.m_hImpl;
+ if (m_hImpl)
+ store_acquireHandle (m_hImpl);
+ return *this;
+}
+
+inline OStoreDirectory::OStoreDirectory (
+ storeDirectoryHandle Handle) SAL_THROW(())
+ : m_hImpl (Handle)
+{
+ if (m_hImpl)
+ store_acquireHandle (m_hImpl);
+}
+
+inline OStoreDirectory::operator storeDirectoryHandle(void) const SAL_THROW(())
+{
+ return m_hImpl;
+}
+
+inline sal_Bool OStoreDirectory::isValid (void) const SAL_THROW(())
+{
+ return (!!m_hImpl);
+}
+
+inline storeError OStoreDirectory::create (
+ storeFileHandle hFile,
+ const rtl::OUString &rPath,
+ const rtl::OUString &rName,
+ storeAccessMode eMode) SAL_THROW(())
+{
+ if (m_hImpl)
+ {
+ store_releaseHandle (m_hImpl);
+ m_hImpl = 0;
+ }
+ return store_openDirectory (
+ hFile, rPath.pData, rName.pData, eMode, &m_hImpl);
+}
+
+inline void OStoreDirectory::close (void) SAL_THROW(())
+{
+ if (m_hImpl)
+ {
+ store_closeDirectory (m_hImpl);
+ m_hImpl = 0;
+ }
+}
+
+inline storeError OStoreDirectory::first (iterator& it) SAL_THROW(())
+{
+ if (!m_hImpl)
+ return store_E_InvalidHandle;
+
+ return store_findFirst (m_hImpl, &it);
+}
+
+inline storeError OStoreDirectory::next (iterator& it) SAL_THROW(())
+{
+ if (!m_hImpl)
+ return store_E_InvalidHandle;
+
+ return store_findNext (m_hImpl, &it);
+}
+
+inline storeError OStoreDirectory::travel (traveller& rTraveller) const
+{
+ storeError eErrCode = store_E_InvalidHandle;
+ if (m_hImpl)
+ {
+ iterator it;
+ eErrCode = store_findFirst (m_hImpl, &it);
+ while ((eErrCode == store_E_None) && rTraveller.visit(it))
+ eErrCode = store_findNext (m_hImpl, &it);
+ }
+ return eErrCode;
+}
+
+/*========================================================================
+ *
+ * OStoreFile implementation.
+ *
+ *======================================================================*/
+inline OStoreFile::OStoreFile (void) SAL_THROW(())
+ : m_hImpl (0)
+{
+}
+
+inline OStoreFile::~OStoreFile (void) SAL_THROW(())
+{
+ if (m_hImpl)
+ store_releaseHandle (m_hImpl);
+}
+
+inline OStoreFile::OStoreFile (
+ const OStoreFile& rOther) SAL_THROW(())
+ : m_hImpl (rOther.m_hImpl)
+{
+ if (m_hImpl)
+ store_acquireHandle (m_hImpl);
+}
+
+inline OStoreFile& OStoreFile::operator= (
+ const OStoreFile& rOther) SAL_THROW(())
+{
+ if (m_hImpl)
+ store_releaseHandle (m_hImpl);
+ m_hImpl = rOther.m_hImpl;
+ if (m_hImpl)
+ store_acquireHandle (m_hImpl);
+ return *this;
+}
+
+inline OStoreFile::OStoreFile (
+ storeFileHandle Handle) SAL_THROW(())
+ : m_hImpl (Handle)
+{
+ if (m_hImpl)
+ store_acquireHandle (m_hImpl);
+}
+
+inline OStoreFile::operator storeFileHandle (void) const SAL_THROW(())
+{
+ return m_hImpl;
+}
+
+inline sal_Bool OStoreFile::isValid (void) const SAL_THROW(())
+{
+ return (!!m_hImpl);
+}
+
+inline storeError OStoreFile::create (
+ const rtl::OUString &rFilename,
+ storeAccessMode eAccessMode,
+ sal_uInt16 nPageSize) SAL_THROW(())
+{
+ if (m_hImpl)
+ {
+ store_releaseHandle (m_hImpl);
+ m_hImpl = 0;
+ }
+ return store_openFile (rFilename.pData, eAccessMode, nPageSize, &m_hImpl);
+}
+
+inline storeError OStoreFile::createInMemory (
+ sal_uInt16 nPageSize) SAL_THROW(())
+{
+ if (m_hImpl)
+ {
+ store_releaseHandle (m_hImpl);
+ m_hImpl = 0;
+ }
+ return store_createMemoryFile (nPageSize, &m_hImpl);
+}
+
+inline void OStoreFile::close (void) SAL_THROW(())
+{
+ if (m_hImpl)
+ {
+ store_closeFile (m_hImpl);
+ m_hImpl = 0;
+ }
+}
+
+inline storeError OStoreFile::flush (void) const SAL_THROW(())
+{
+ if (!m_hImpl)
+ return store_E_InvalidHandle;
+
+ return store_flushFile (m_hImpl);
+}
+
+inline storeError OStoreFile::getRefererCount (
+ sal_uInt32 &rnRefCount) const SAL_THROW(())
+{
+ if (!m_hImpl)
+ return store_E_InvalidHandle;
+
+ return store_getFileRefererCount (m_hImpl, &rnRefCount);
+}
+
+inline storeError OStoreFile::getSize (
+ sal_uInt32 &rnSize) const SAL_THROW(())
+{
+ if (!m_hImpl)
+ return store_E_InvalidHandle;
+
+ return store_getFileSize (m_hImpl, &rnSize);
+}
+
+inline storeError OStoreFile::attrib (
+ const rtl::OUString &rPath,
+ const rtl::OUString &rName,
+ sal_uInt32 nMask1,
+ sal_uInt32 nMask2,
+ sal_uInt32 &rnAttrib) SAL_THROW(())
+{
+ if (!m_hImpl)
+ return store_E_InvalidHandle;
+
+ return store_attrib (
+ m_hImpl, rPath.pData, rName.pData, nMask1, nMask2, &rnAttrib);
+}
+
+inline storeError OStoreFile::attrib (
+ const rtl::OUString &rPath,
+ const rtl::OUString &rName,
+ sal_uInt32 nMask1,
+ sal_uInt32 nMask2) SAL_THROW(())
+{
+ if (!m_hImpl)
+ return store_E_InvalidHandle;
+
+ return store_attrib (
+ m_hImpl, rPath.pData, rName.pData, nMask1, nMask2, NULL);
+}
+
+inline storeError OStoreFile::link (
+ const rtl::OUString &rSrcPath, const rtl::OUString &rSrcName,
+ const rtl::OUString &rDstPath, const rtl::OUString &rDstName) SAL_THROW(())
+{
+ if (!m_hImpl)
+ return store_E_InvalidHandle;
+
+ return store_link (
+ m_hImpl,
+ rSrcPath.pData, rSrcName.pData,
+ rDstPath.pData, rDstName.pData);
+}
+
+inline storeError OStoreFile::symlink (
+ const rtl::OUString &rSrcPath, const rtl::OUString &rSrcName,
+ const rtl::OUString &rDstPath, const rtl::OUString &rDstName) SAL_THROW(())
+{
+ if (!m_hImpl)
+ return store_E_InvalidHandle;
+
+ return store_symlink (
+ m_hImpl,
+ rSrcPath.pData, rSrcName.pData,
+ rDstPath.pData, rDstName.pData);
+}
+
+inline storeError OStoreFile::rename (
+ const rtl::OUString &rSrcPath, const rtl::OUString &rSrcName,
+ const rtl::OUString &rDstPath, const rtl::OUString &rDstName) SAL_THROW(())
+{
+ if (!m_hImpl)
+ return store_E_InvalidHandle;
+
+ return store_rename (
+ m_hImpl,
+ rSrcPath.pData, rSrcName.pData,
+ rDstPath.pData, rDstName.pData);
+}
+
+inline storeError OStoreFile::remove (
+ const rtl::OUString &rPath, const rtl::OUString &rName) SAL_THROW(())
+{
+ if (!m_hImpl)
+ return store_E_InvalidHandle;
+
+ return store_remove (m_hImpl, rPath.pData, rName.pData);
+}
+
diff --git a/store/inc/store/types.h b/store/inc/store/types.h
new file mode 100644
index 000000000000..17551381aca5
--- /dev/null
+++ b/store/inc/store/types.h
@@ -0,0 +1,170 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: types.h,v $
+ * $Revision: 1.8 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _STORE_TYPES_H_
+#define _STORE_TYPES_H_ "$Revision: 1.8 $"
+
+#include <sal/types.h>
+#include <rtl/ustring.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** PageSize (recommended) default.
+ @see store_openFile()
+ */
+#define STORE_DEFAULT_PAGESIZE ((sal_uInt16)0x0400)
+
+
+/** PageSize (enforced) limits.
+ @see store_openFile()
+ */
+#define STORE_MINIMUM_PAGESIZE ((sal_uInt16)0x0200)
+#define STORE_MAXIMUM_PAGESIZE ((sal_uInt16)0x8000)
+
+
+/** NameSize (enforced) limit.
+ @see any param pName
+ @see store_E_NameTooLong
+ */
+#define STORE_MAXIMUM_NAMESIZE 256
+
+
+/** Attributes (predefined).
+ @see store_attrib()
+ */
+#define STORE_ATTRIB_ISLINK ((sal_uInt32)0x10000000)
+#define STORE_ATTRIB_ISDIR ((sal_uInt32)0x20000000)
+#define STORE_ATTRIB_ISFILE ((sal_uInt32)0x40000000)
+
+
+/** Access Mode enumeration.
+ @see store_openFile()
+ @see store_openDirectory()
+ @see store_openStream()
+ */
+enum __store_AccessMode
+{
+ store_AccessCreate,
+ store_AccessReadCreate,
+ store_AccessReadWrite,
+ store_AccessReadOnly,
+ store_Access_FORCE_EQUAL_SIZE = SAL_MAX_ENUM
+};
+
+/** Access Mode type.
+ */
+typedef enum __store_AccessMode storeAccessMode;
+
+
+/** Error Code enumeration.
+ */
+enum __store_Error
+{
+ store_E_None = 0,
+ store_E_AccessViolation,
+ store_E_LockingViolation,
+ store_E_CantSeek,
+ store_E_CantRead,
+ store_E_CantWrite,
+ store_E_InvalidAccess,
+ store_E_InvalidHandle,
+ store_E_InvalidParameter,
+ store_E_InvalidChecksum,
+ store_E_AlreadyExists,
+ store_E_NotExists,
+ store_E_NotDirectory,
+ store_E_NotFile,
+ store_E_NoMoreFiles,
+ store_E_NameTooLong,
+ store_E_OutOfMemory,
+ store_E_OutOfSpace,
+ store_E_Pending,
+ store_E_WrongFormat,
+ store_E_WrongVersion,
+ store_E_Unknown,
+ store_E_FORCE_EQUAL_SIZE = SAL_MAX_ENUM
+};
+
+/** Error Code type.
+ */
+typedef enum __store_Error storeError;
+
+
+/** Find Data structure.
+ @see store_findFirst()
+ @see store_findNext()
+ */
+struct __store_FindData
+{
+ /** Name.
+ @see m_nLength
+ */
+ sal_Unicode m_pszName[STORE_MAXIMUM_NAMESIZE];
+
+ /** Name Length.
+ @see m_pszName
+ */
+ sal_Int32 m_nLength;
+
+ /** Attributes.
+ @see store_attrib()
+ */
+ sal_uInt32 m_nAttrib;
+
+ /** Size.
+ @see store_getStreamSize()
+ @see store_setStreamSize()
+ */
+ sal_uInt32 m_nSize;
+
+ /** Reserved for internal use.
+ */
+ sal_uInt32 m_nReserved;
+};
+
+/** Find Data type.
+ */
+typedef struct __store_FindData storeFindData;
+
+
+/*========================================================================
+ *
+ * The End.
+ *
+ *======================================================================*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _STORE_TYPES_H_ */
+
diff --git a/store/prj/build.lst b/store/prj/build.lst
new file mode 100644
index 000000000000..938d95ebc029
--- /dev/null
+++ b/store/prj/build.lst
@@ -0,0 +1,5 @@
+s8 store : sal NULL
+s8 store usr1 - all s8_mkout NULL
+s8 store\inc nmake - all s8_inc NULL
+s8 store\source nmake - all s8_source s8_inc NULL
+s8 store\util nmake - all s8_util s8_source NULL
diff --git a/store/prj/d.lst b/store/prj/d.lst
new file mode 100644
index 000000000000..e39be093c53a
--- /dev/null
+++ b/store/prj/d.lst
@@ -0,0 +1,13 @@
+mkdir: %_DEST%\inc%_EXT%\store
+..\inc\store\*.h %_DEST%\inc%_EXT%\store\*.h
+..\inc\store\store.hxx %_DEST%\inc%_EXT%\store\store.hxx
+..\inc\store\store.inl %_DEST%\inc%_EXT%\store\store.inl
+..\util\store.xml %_DEST%\xml%_EXT%\store.xml
+
+..\%__SRC%\lib\istore.lib %_DEST%\lib%_EXT%\istore.lib
+..\%__SRC%\lib\libstore.*.* %_DEST%\lib%_EXT%\*
+..\%__SRC%\bin\sto*.dll %_DEST%\bin%_EXT%\sto*.dll
+
+
+
+linklib: libstore.*.*
diff --git a/store/source/lockbyte.cxx b/store/source/lockbyte.cxx
new file mode 100644
index 000000000000..a03628bfb740
--- /dev/null
+++ b/store/source/lockbyte.cxx
@@ -0,0 +1,989 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: lockbyte.cxx,v $
+ *
+ * $Revision: 1.1.2.4 $
+ *
+ * last change: $Author: mhu $ $Date: 2008/11/25 15:44:56 $
+ *
+ * The Contents of this file are made available subject to
+ * the terms of GNU Lesser General Public License Version 2.1.
+ *
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2005 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
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_store.hxx"
+
+#include "lockbyte.hxx"
+
+#include "sal/types.h"
+#include "osl/diagnose.h"
+#include "osl/file.h"
+#include "osl/process.h"
+#include "rtl/alloc.h"
+#include "rtl/ustring.hxx"
+
+#include "object.hxx"
+#include "storbase.hxx"
+
+#ifndef INCLUDED_STRING_H
+#include <string.h>
+#define INCLUDED_STRING_H
+#endif
+
+using namespace store;
+
+/*========================================================================
+ *
+ * ILockBytes (non-virtual interface) implementation.
+ *
+ *======================================================================*/
+
+storeError ILockBytes::initialize (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize)
+{
+ OSL_PRECOND((STORE_MINIMUM_PAGESIZE <= nPageSize) && (nPageSize <= STORE_MAXIMUM_PAGESIZE), "invalid PageSize");
+ return initialize_Impl (rxAllocator, nPageSize);
+}
+
+storeError ILockBytes::readPageAt (PageHolder & rPage, sal_uInt32 nOffset)
+{
+ OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::ILockBytes::readPageAt(): invalid Offset");
+ if (nOffset == STORE_PAGE_NULL)
+ return store_E_CantSeek;
+
+ return readPageAt_Impl (rPage, nOffset);
+}
+
+storeError ILockBytes::writePageAt (PageHolder const & rPage, sal_uInt32 nOffset)
+{
+ // [SECURITY:ValInput]
+ PageData const * pagedata = rPage.get();
+ OSL_PRECOND(!(pagedata == 0), "store::ILockBytes::writePageAt(): invalid Page");
+ if (pagedata == 0)
+ return store_E_InvalidParameter;
+
+ sal_uInt32 const offset = pagedata->location();
+ OSL_PRECOND(!(nOffset != offset), "store::ILockBytes::writePageAt(): inconsistent Offset");
+ if (nOffset != offset)
+ return store_E_InvalidParameter;
+
+ OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::ILockBytes::writePageAt(): invalid Offset");
+ if (nOffset == STORE_PAGE_NULL)
+ return store_E_CantSeek;
+
+ return writePageAt_Impl (rPage, nOffset);
+}
+
+storeError ILockBytes::readAt (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes)
+{
+ // [SECURITY:ValInput]
+ sal_uInt8 * dst_lo = static_cast<sal_uInt8*>(pBuffer);
+ if (!(dst_lo != 0))
+ return store_E_InvalidParameter;
+
+ sal_uInt8 * dst_hi = dst_lo + nBytes;
+ if (!(dst_lo < dst_hi))
+ return (dst_lo > dst_hi) ? store_E_InvalidParameter : store_E_None;
+
+ OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::ILockBytes::readAt(): invalid Offset");
+ if (nOffset == STORE_PAGE_NULL)
+ return store_E_CantSeek;
+
+ sal_uInt64 const src_size = nOffset + nBytes;
+ if (src_size > SAL_MAX_UINT32)
+ return store_E_CantSeek;
+
+ return readAt_Impl (nOffset, dst_lo, (dst_hi - dst_lo));
+}
+
+storeError ILockBytes::writeAt (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes)
+{
+ // [SECURITY:ValInput]
+ sal_uInt8 const * src_lo = static_cast<sal_uInt8 const*>(pBuffer);
+ if (!(src_lo != 0))
+ return store_E_InvalidParameter;
+
+ sal_uInt8 const * src_hi = src_lo + nBytes;
+ if (!(src_lo < src_hi))
+ return (src_lo > src_hi) ? store_E_InvalidParameter : store_E_None;
+
+ OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::ILockBytes::writeAt(): invalid Offset");
+ if (nOffset == STORE_PAGE_NULL)
+ return store_E_CantSeek;
+
+ sal_uInt64 const dst_size = nOffset + nBytes;
+ if (dst_size > SAL_MAX_UINT32)
+ return store_E_CantSeek;
+
+ return writeAt_Impl (nOffset, src_lo, (src_hi - src_lo));
+}
+
+storeError ILockBytes::getSize (sal_uInt32 & rnSize)
+{
+ rnSize = 0;
+ return getSize_Impl (rnSize);
+}
+
+storeError ILockBytes::setSize (sal_uInt32 nSize)
+{
+ return setSize_Impl (nSize);
+}
+
+storeError ILockBytes::flush()
+{
+ return flush_Impl();
+}
+
+storeError ILockBytes::lockRange (sal_uInt32 nOffset, sal_uInt32 nBytes)
+{
+ OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::ILockBytes::lockRange(): invalid Offset");
+ if (nOffset == STORE_PAGE_NULL)
+ return store_E_CantSeek;
+
+ sal_uInt64 size = nOffset + nBytes;
+ if (size > SAL_MAX_UINT32)
+ return store_E_CantSeek;
+
+#ifdef STORE_FEATURE_LOCKING
+ return lockRange_Impl (nOffset, nBytes);
+#else
+ return store_E_None; // E_Unsupported
+#endif /* STORE_FEATURE_LOCKING */
+}
+
+storeError ILockBytes::unlockRange (sal_uInt32 nOffset, sal_uInt32 nBytes)
+{
+ OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::ILockBytes::unlockRange(): invalid Offset");
+ if (nOffset == STORE_PAGE_NULL)
+ return store_E_CantSeek;
+
+ sal_uInt64 size = nOffset + nBytes;
+ if (size > SAL_MAX_UINT32)
+ return store_E_CantSeek;
+
+#ifdef STORE_FEATURE_LOCKING
+ return unlockRange_Impl (nOffset, nBytes);
+#else
+ return store_E_None; // E_Unsupported
+#endif /* STORE_FEATURE_LOCKING */
+}
+
+/*========================================================================
+ *
+ * FileLockBytes implementation.
+ *
+ *======================================================================*/
+namespace store
+{
+
+struct FileHandle
+{
+ oslFileHandle m_handle;
+
+ FileHandle() : m_handle(0) {}
+
+ bool operator != (FileHandle const & rhs)
+ {
+ return (m_handle != rhs.m_handle);
+ }
+
+ static storeError errorFromNative (oslFileError eErrno)
+ {
+ switch (eErrno)
+ {
+ case osl_File_E_None:
+ return store_E_None;
+
+ case osl_File_E_NOENT:
+ return store_E_NotExists;
+
+ case osl_File_E_ACCES:
+ case osl_File_E_PERM:
+ return store_E_AccessViolation;
+
+ case osl_File_E_AGAIN:
+ case osl_File_E_DEADLK:
+ return store_E_LockingViolation;
+
+ case osl_File_E_BADF:
+ return store_E_InvalidHandle;
+
+ case osl_File_E_INVAL:
+ return store_E_InvalidParameter;
+
+ case osl_File_E_NOMEM:
+ return store_E_OutOfMemory;
+
+ case osl_File_E_NOSPC:
+ return store_E_OutOfSpace;
+
+ case osl_File_E_OVERFLOW:
+ return store_E_CantSeek;
+
+ default:
+ return store_E_Unknown;
+ }
+ }
+
+ static sal_uInt32 modeToNative (storeAccessMode eAccessMode)
+ {
+ sal_uInt32 nFlags = 0;
+ switch (eAccessMode)
+ {
+ case store_AccessCreate:
+ case store_AccessReadCreate:
+ nFlags |= osl_File_OpenFlag_Create;
+ // fall through
+ case store_AccessReadWrite:
+ nFlags |= osl_File_OpenFlag_Write;
+ // fall through
+ case store_AccessReadOnly:
+ nFlags |= osl_File_OpenFlag_Read;
+ break;
+ default:
+ OSL_PRECOND(0, "store::FileHandle: unknown storeAccessMode");
+ }
+ return nFlags;
+ }
+
+ storeError initialize (rtl_uString * pFilename, storeAccessMode eAccessMode)
+ {
+ // Verify arguments.
+ sal_uInt32 nFlags = modeToNative (eAccessMode);
+ if (!pFilename || !nFlags)
+ return store_E_InvalidParameter;
+
+ // Convert into FileUrl.
+ rtl::OUString aFileUrl;
+ if (osl_getFileURLFromSystemPath (pFilename, &(aFileUrl.pData)) != osl_File_E_None)
+ {
+ // Not system path. Assume file url.
+ rtl_uString_assign (&(aFileUrl.pData), pFilename);
+ }
+ if (aFileUrl.compareToAscii("file://", 7) != 0)
+ {
+ // Not file url. Assume relative path.
+ rtl::OUString aCwdUrl;
+ (void) osl_getProcessWorkingDir (&(aCwdUrl.pData));
+
+ // Absolute file url.
+ (void) osl_getAbsoluteFileURL (aCwdUrl.pData, aFileUrl.pData, &(aFileUrl.pData));
+ }
+
+ // Acquire handle.
+ oslFileError result = osl_openFile (aFileUrl.pData, &m_handle, nFlags);
+ if (result == osl_File_E_EXIST)
+ {
+ // Already existing (O_CREAT | O_EXCL).
+ result = osl_openFile (aFileUrl.pData, &m_handle, osl_File_OpenFlag_Read | osl_File_OpenFlag_Write);
+ if ((result == osl_File_E_None) && (eAccessMode == store_AccessCreate))
+ {
+ // Truncate existing file.
+ result = osl_setFileSize (m_handle, 0);
+ }
+ }
+ if (result != osl_File_E_None)
+ return errorFromNative(result);
+ return store_E_None;
+ }
+
+ /** @see FileLockBytes destructor
+ */
+ static void closeFile (oslFileHandle hFile)
+ {
+ (void) osl_closeFile (hFile);
+ }
+
+ /** @see ResourceHolder<T>::destructor_type
+ */
+ struct CloseFile
+ {
+ void operator()(FileHandle & rFile) const
+ {
+ // Release handle.
+ closeFile (rFile.m_handle);
+ rFile.m_handle = 0;
+ }
+ };
+ typedef CloseFile destructor_type;
+};
+
+class FileLockBytes :
+ public store::OStoreObject,
+ public store::ILockBytes
+{
+ /** Representation.
+ */
+ oslFileHandle m_hFile;
+ sal_uInt32 m_nSize;
+ rtl::Reference< PageData::Allocator > m_xAllocator;
+
+ storeError initSize_Impl (sal_uInt32 & rnSize);
+
+ /** ILockBytes implementation.
+ */
+ virtual storeError initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize);
+
+ virtual storeError readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset);
+ virtual storeError writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset);
+
+ virtual storeError readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes);
+ virtual storeError writeAt_Impl (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes);
+
+ virtual storeError getSize_Impl (sal_uInt32 & rnSize);
+ virtual storeError setSize_Impl (sal_uInt32 nSize);
+
+ virtual storeError flush_Impl();
+
+ /** Not implemented.
+ */
+ FileLockBytes (FileLockBytes const &);
+ FileLockBytes & operator= (FileLockBytes const &);
+
+public:
+ /** Construction.
+ */
+ explicit FileLockBytes (FileHandle & rFile);
+
+ /** Delegate multiple inherited IReference.
+ */
+ virtual oslInterlockedCount SAL_CALL acquire();
+ virtual oslInterlockedCount SAL_CALL release();
+
+protected:
+ /** Destruction.
+ */
+ virtual ~FileLockBytes();
+};
+
+} // namespace store
+
+FileLockBytes::FileLockBytes (FileHandle & rFile)
+ : m_hFile (rFile.m_handle), m_nSize (SAL_MAX_UINT32), m_xAllocator()
+{
+}
+
+FileLockBytes::~FileLockBytes()
+{
+ FileHandle::closeFile (m_hFile);
+}
+
+oslInterlockedCount SAL_CALL FileLockBytes::acquire()
+{
+ return OStoreObject::acquire();
+}
+
+oslInterlockedCount SAL_CALL FileLockBytes::release()
+{
+ return OStoreObject::release();
+}
+
+storeError FileLockBytes::initSize_Impl (sal_uInt32 & rnSize)
+{
+ /* osl_getFileSize() uses slow 'fstat(h, &size)',
+ * instead of fast 'size = lseek(h, 0, SEEK_END)'.
+ * so, init size here, and track changes.
+ */
+ sal_uInt64 uSize = 0;
+ oslFileError result = osl_getFileSize (m_hFile, &uSize);
+ if (result != osl_File_E_None)
+ return FileHandle::errorFromNative(result);
+ if (uSize > SAL_MAX_UINT32)
+ return store_E_CantSeek;
+
+ rnSize = sal::static_int_cast<sal_uInt32>(uSize);
+ return store_E_None;
+}
+
+storeError FileLockBytes::initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize)
+{
+ storeError result = initSize_Impl (m_nSize);
+ if (result != store_E_None)
+ return (result);
+
+ result = PageData::Allocator::createInstance (rxAllocator, nPageSize);
+ if (result != store_E_None)
+ return (result);
+
+ // @see readPageAt_Impl().
+ m_xAllocator = rxAllocator;
+ return store_E_None;
+}
+
+storeError FileLockBytes::readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset)
+{
+ if (m_xAllocator.is())
+ {
+ PageHolder page (m_xAllocator->construct<PageData>(), m_xAllocator);
+ page.swap (rPage);
+ }
+
+ if (!m_xAllocator.is())
+ return store_E_InvalidAccess;
+ if (!rPage.get())
+ return store_E_OutOfMemory;
+
+ PageData * pagedata = rPage.get();
+ return readAt_Impl (nOffset, pagedata, pagedata->size());
+}
+
+storeError FileLockBytes::writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset)
+{
+ PageData const * pagedata = rPage.get();
+ OSL_PRECOND(pagedata != 0, "contract violation");
+ return writeAt_Impl (nOffset, pagedata, pagedata->size());
+}
+
+storeError FileLockBytes::readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes)
+{
+ sal_uInt64 nDone = 0;
+ oslFileError result = osl_readFileAt (m_hFile, nOffset, pBuffer, nBytes, &nDone);
+ if (result != osl_File_E_None)
+ return FileHandle::errorFromNative(result);
+ if (nDone != nBytes)
+ return (nDone != 0) ? store_E_CantRead : store_E_NotExists;
+ return store_E_None;
+}
+
+storeError FileLockBytes::writeAt_Impl (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes)
+{
+ sal_uInt64 nDone = 0;
+ oslFileError result = osl_writeFileAt (m_hFile, nOffset, pBuffer, nBytes, &nDone);
+ if (result != osl_File_E_None)
+ return FileHandle::errorFromNative(result);
+ if (nDone != nBytes)
+ return store_E_CantWrite;
+
+ sal_uInt64 const uSize = nOffset + nBytes;
+ OSL_PRECOND(uSize < SAL_MAX_UINT32, "store::ILockBytes::writeAt() contract violation");
+ if (uSize > m_nSize)
+ m_nSize = sal::static_int_cast<sal_uInt32>(uSize);
+ return store_E_None;
+}
+
+storeError FileLockBytes::getSize_Impl (sal_uInt32 & rnSize)
+{
+ rnSize = m_nSize;
+ return store_E_None;
+}
+
+storeError FileLockBytes::setSize_Impl (sal_uInt32 nSize)
+{
+ oslFileError result = osl_setFileSize (m_hFile, nSize);
+ if (result != osl_File_E_None)
+ return FileHandle::errorFromNative(result);
+
+ m_nSize = nSize;
+ return store_E_None;
+}
+
+storeError FileLockBytes::flush_Impl()
+{
+ oslFileError result = osl_syncFile (m_hFile);
+ if (result != osl_File_E_None)
+ return FileHandle::errorFromNative(result);
+ return store_E_None;
+}
+
+/*========================================================================
+ *
+ * MappedLockBytes implementation.
+ *
+ *======================================================================*/
+namespace store
+{
+
+struct FileMapping
+{
+ sal_uInt8 * m_pAddr;
+ sal_uInt32 m_nSize;
+
+ FileMapping() : m_pAddr(0), m_nSize(0) {}
+
+ bool operator != (FileMapping const & rhs) const
+ {
+ return ((m_pAddr != rhs.m_pAddr) || (m_nSize != rhs.m_nSize));
+ }
+
+ oslFileError initialize (oslFileHandle hFile)
+ {
+ // Determine mapping size.
+ sal_uInt64 uSize = 0;
+ oslFileError result = osl_getFileSize (hFile, &uSize);
+ if (result != osl_File_E_None)
+ return result;
+
+ // [SECURITY:IntOver]
+ if (uSize > SAL_MAX_UINT32)
+ return osl_File_E_OVERFLOW;
+ m_nSize = sal::static_int_cast<sal_uInt32>(uSize);
+
+ // Acquire mapping.
+ return osl_mapFile (hFile, reinterpret_cast<void**>(&m_pAddr), m_nSize, 0, osl_File_MapFlag_RandomAccess);
+ }
+
+ /** @see MappedLockBytes::destructor.
+ */
+ static void unmapFile (sal_uInt8 * pAddr, sal_uInt32 nSize)
+ {
+ (void) osl_unmapFile (pAddr, nSize);
+ }
+
+ /** @see ResourceHolder<T>::destructor_type
+ */
+ struct UnmapFile
+ {
+ void operator ()(FileMapping & rMapping) const
+ {
+ // Release mapping.
+ unmapFile (rMapping.m_pAddr, rMapping.m_nSize);
+ rMapping.m_pAddr = 0, rMapping.m_nSize = 0;
+ }
+ };
+ typedef UnmapFile destructor_type;
+};
+
+class MappedLockBytes :
+ public store::OStoreObject,
+ public store::PageData::Allocator,
+ public store::ILockBytes
+{
+ /** Representation.
+ */
+ sal_uInt8 * m_pData;
+ sal_uInt32 m_nSize;
+ sal_uInt16 m_nPageSize;
+
+ /** PageData::Allocator implementation.
+ */
+ virtual void allocate_Impl (void ** ppPage, sal_uInt16 * pnSize);
+ virtual void deallocate_Impl (void * pPage);
+
+ /** ILockBytes implementation.
+ */
+ virtual storeError initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize);
+
+ virtual storeError readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset);
+ virtual storeError writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset);
+
+ virtual storeError readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes);
+ virtual storeError writeAt_Impl (sal_uInt32 nOffset, const void * pBuffer, sal_uInt32 nBytes);
+
+ virtual storeError getSize_Impl (sal_uInt32 & rnSize);
+ virtual storeError setSize_Impl (sal_uInt32 nSize);
+
+ virtual storeError flush_Impl();
+
+ /** Not implemented.
+ */
+ MappedLockBytes (MappedLockBytes const &);
+ MappedLockBytes & operator= (MappedLockBytes const &);
+
+public:
+ /** Construction.
+ */
+ explicit MappedLockBytes (FileMapping & rMapping);
+
+ /** Delegate multiple inherited IReference.
+ */
+ virtual oslInterlockedCount SAL_CALL acquire();
+ virtual oslInterlockedCount SAL_CALL release();
+
+protected:
+ /* Destruction.
+ */
+ virtual ~MappedLockBytes();
+};
+
+} // namespace store
+
+MappedLockBytes::MappedLockBytes (FileMapping & rMapping)
+ : m_pData (rMapping.m_pAddr), m_nSize (rMapping.m_nSize), m_nPageSize(0)
+{
+}
+
+MappedLockBytes::~MappedLockBytes()
+{
+ FileMapping::unmapFile (m_pData, m_nSize);
+}
+
+oslInterlockedCount SAL_CALL MappedLockBytes::acquire()
+{
+ return OStoreObject::acquire();
+}
+
+oslInterlockedCount SAL_CALL MappedLockBytes::release()
+{
+ return OStoreObject::release();
+}
+
+void MappedLockBytes::allocate_Impl (void ** ppPage, sal_uInt16 * pnSize)
+{
+ OSL_PRECOND((ppPage != 0) && (pnSize != 0), "contract violation");
+ *ppPage = 0, *pnSize = m_nPageSize;
+}
+
+void MappedLockBytes::deallocate_Impl (void * pPage)
+{
+ OSL_PRECOND((m_pData <= pPage) && (pPage < m_pData + m_nSize), "contract violation");
+ (void)pPage; // UNUSED
+}
+
+storeError MappedLockBytes::initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize)
+{
+ rxAllocator = this;
+ m_nPageSize = nPageSize;
+ return store_E_None;
+}
+
+storeError MappedLockBytes::readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset)
+{
+ sal_uInt8 * src_lo = m_pData + nOffset;
+ if ((m_pData > src_lo) || (src_lo >= m_pData + m_nSize))
+ return store_E_NotExists;
+
+ sal_uInt8 * src_hi = src_lo + m_nPageSize;
+ if ((m_pData > src_hi) || (src_hi > m_pData + m_nSize))
+ return store_E_CantRead;
+
+ PageHolder page (reinterpret_cast< PageData* >(src_lo), static_cast< PageData::Allocator* >(this));
+ page.swap (rPage);
+
+ return store_E_None;
+}
+
+storeError MappedLockBytes::writePageAt_Impl (PageHolder const & /*rPage*/, sal_uInt32 /*nOffset*/)
+{
+ return store_E_AccessViolation;
+}
+
+storeError MappedLockBytes::readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes)
+{
+ sal_uInt8 const * src_lo = m_pData + nOffset;
+ if ((m_pData > src_lo) || (src_lo >= m_pData + m_nSize))
+ return store_E_NotExists;
+
+ sal_uInt8 const * src_hi = src_lo + nBytes;
+ if ((m_pData > src_hi) || (src_hi > m_pData + m_nSize))
+ return store_E_CantRead;
+
+ memcpy (pBuffer, src_lo, (src_hi - src_lo));
+ return store_E_None;
+}
+
+storeError MappedLockBytes::writeAt_Impl (sal_uInt32 /*nOffset*/, void const * /*pBuffer*/, sal_uInt32 /*nBytes*/)
+{
+ return store_E_AccessViolation;
+}
+
+storeError MappedLockBytes::getSize_Impl (sal_uInt32 & rnSize)
+{
+ rnSize = m_nSize;
+ return store_E_None;
+}
+
+storeError MappedLockBytes::setSize_Impl (sal_uInt32 /*nSize*/)
+{
+ return store_E_AccessViolation;
+}
+
+storeError MappedLockBytes::flush_Impl()
+{
+ return store_E_None;
+}
+
+/*========================================================================
+ *
+ * MemoryLockBytes implementation.
+ *
+ *======================================================================*/
+namespace store
+{
+
+class MemoryLockBytes :
+ public store::OStoreObject,
+ public store::ILockBytes
+{
+ /** Representation.
+ */
+ sal_uInt8 * m_pData;
+ sal_uInt32 m_nSize;
+ rtl::Reference< PageData::Allocator > m_xAllocator;
+
+ /** ILockBytes implementation.
+ */
+ virtual storeError initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize);
+
+ virtual storeError readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset);
+ virtual storeError writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset);
+
+ virtual storeError readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes);
+ virtual storeError writeAt_Impl (sal_uInt32 nOffset, const void * pBuffer, sal_uInt32 nBytes);
+
+ virtual storeError getSize_Impl (sal_uInt32 & rnSize);
+ virtual storeError setSize_Impl (sal_uInt32 nSize);
+
+ virtual storeError flush_Impl();
+
+ /** Not implemented.
+ */
+ MemoryLockBytes (MemoryLockBytes const &);
+ MemoryLockBytes& operator= (MemoryLockBytes const &);
+
+public:
+ /** Construction.
+ */
+ MemoryLockBytes();
+
+ /** Delegate multiple inherited IReference.
+ */
+ virtual oslInterlockedCount SAL_CALL acquire();
+ virtual oslInterlockedCount SAL_CALL release();
+
+protected:
+ /** Destruction.
+ */
+ virtual ~MemoryLockBytes();
+};
+
+} // namespace store
+
+MemoryLockBytes::MemoryLockBytes()
+ : m_pData (0), m_nSize (0), m_xAllocator()
+{}
+
+MemoryLockBytes::~MemoryLockBytes()
+{
+ rtl_freeMemory (m_pData);
+}
+
+oslInterlockedCount SAL_CALL MemoryLockBytes::acquire (void)
+{
+ return OStoreObject::acquire();
+}
+
+oslInterlockedCount SAL_CALL MemoryLockBytes::release (void)
+{
+ return OStoreObject::release();
+}
+
+storeError MemoryLockBytes::initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize)
+{
+ storeError result = PageData::Allocator::createInstance (rxAllocator, nPageSize);
+ if (result == store_E_None)
+ {
+ // @see readPageAt_Impl().
+ m_xAllocator = rxAllocator;
+ }
+ return result;
+}
+
+storeError MemoryLockBytes::readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset)
+{
+ if (m_xAllocator.is())
+ {
+ PageHolder page (m_xAllocator->construct<PageData>(), m_xAllocator);
+ page.swap (rPage);
+ }
+
+ if (!m_xAllocator.is())
+ return store_E_InvalidAccess;
+ if (!rPage.get())
+ return store_E_OutOfMemory;
+
+ PageData * pagedata = rPage.get();
+ return readAt_Impl (nOffset, pagedata, pagedata->size());
+}
+
+storeError MemoryLockBytes::writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset)
+{
+ PageData const * pagedata = rPage.get();
+ OSL_PRECOND(!(pagedata == 0), "contract violation");
+ return writeAt_Impl (nOffset, pagedata, pagedata->size());
+}
+
+storeError MemoryLockBytes::readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes)
+{
+ sal_uInt8 const * src_lo = m_pData + nOffset;
+ if ((m_pData > src_lo) || (src_lo >= m_pData + m_nSize))
+ return store_E_NotExists;
+
+ sal_uInt8 const * src_hi = src_lo + nBytes;
+ if ((m_pData > src_hi) || (src_hi > m_pData + m_nSize))
+ return store_E_CantRead;
+
+ memcpy (pBuffer, src_lo, (src_hi - src_lo));
+ return store_E_None;
+}
+
+storeError MemoryLockBytes::writeAt_Impl (sal_uInt32 nOffset, const void * pBuffer, sal_uInt32 nBytes)
+{
+ sal_uInt64 const dst_size = nOffset + nBytes;
+ OSL_PRECOND(dst_size < SAL_MAX_UINT32, "store::ILockBytes::writeAt() contract violation");
+ if (dst_size > m_nSize)
+ {
+ storeError eErrCode = setSize_Impl (sal::static_int_cast<sal_uInt32>(dst_size));
+ if (eErrCode != store_E_None)
+ return eErrCode;
+ }
+ OSL_POSTCOND(dst_size <= m_nSize, "store::MemoryLockBytes::setSize_Impl() contract violation");
+
+ sal_uInt8 * dst_lo = m_pData + nOffset;
+ if (dst_lo >= m_pData + m_nSize)
+ return store_E_CantSeek;
+
+ sal_uInt8 * dst_hi = dst_lo + nBytes;
+ if (dst_hi > m_pData + m_nSize)
+ return store_E_CantWrite;
+
+ memcpy (dst_lo, pBuffer, (dst_hi - dst_lo));
+ return store_E_None;
+}
+
+storeError MemoryLockBytes::getSize_Impl (sal_uInt32 & rnSize)
+{
+ rnSize = m_nSize;
+ return store_E_None;
+}
+
+storeError MemoryLockBytes::setSize_Impl (sal_uInt32 nSize)
+{
+ if (nSize != m_nSize)
+ {
+ sal_uInt8 * pData = reinterpret_cast<sal_uInt8*>(rtl_reallocateMemory (m_pData, nSize));
+ if (pData != 0)
+ {
+ if (nSize > m_nSize)
+ memset (pData + m_nSize, 0, sal::static_int_cast<size_t>(nSize - m_nSize));
+ }
+ else
+ {
+ if (nSize != 0)
+ return store_E_OutOfMemory;
+ }
+ m_pData = pData, m_nSize = nSize;
+ }
+ return store_E_None;
+}
+
+storeError MemoryLockBytes::flush_Impl()
+{
+ return store_E_None;
+}
+
+/*========================================================================
+ *
+ * ILockBytes factory implementations.
+ *
+ *======================================================================*/
+namespace store
+{
+
+template< class T > struct ResourceHolder
+{
+ typedef typename T::destructor_type destructor_type;
+
+ T m_value;
+
+ explicit ResourceHolder (T const & value = T()) : m_value (value) {}
+ ~ResourceHolder() { reset(); }
+
+ T & get() { return m_value; }
+ T const & get() const { return m_value; }
+
+ void set (T const & value) { m_value = value; }
+ void reset (T const & value = T())
+ {
+ T tmp (m_value);
+ if (tmp != value)
+ destructor_type()(tmp);
+ set (value);
+ }
+ T release()
+ {
+ T tmp (m_value);
+ set (T());
+ return tmp;
+ }
+
+ ResourceHolder (ResourceHolder & rhs)
+ {
+ set (rhs.release());
+ }
+ ResourceHolder & operator= (ResourceHolder & rhs)
+ {
+ reset (rhs.release());
+ return *this;
+ }
+};
+
+storeError
+FileLockBytes_createInstance (
+ rtl::Reference< ILockBytes > & rxLockBytes,
+ rtl_uString * pFilename,
+ storeAccessMode eAccessMode
+)
+{
+ // Acquire file handle.
+ ResourceHolder<FileHandle> xFile;
+ storeError result = xFile.get().initialize (pFilename, eAccessMode);
+ if (result != store_E_None)
+ return (result);
+
+ if (eAccessMode == store_AccessReadOnly)
+ {
+ ResourceHolder<FileMapping> xMapping;
+ if (xMapping.get().initialize (xFile.get().m_handle) == osl_File_E_None)
+ {
+ rxLockBytes = new MappedLockBytes (xMapping.get());
+ if (!rxLockBytes.is())
+ return store_E_OutOfMemory;
+ (void) xMapping.release();
+ }
+ }
+ if (!rxLockBytes.is())
+ {
+ rxLockBytes = new FileLockBytes (xFile.get());
+ if (!rxLockBytes.is())
+ return store_E_OutOfMemory;
+ (void) xFile.release();
+ }
+
+ return store_E_None;
+}
+
+storeError
+MemoryLockBytes_createInstance (
+ rtl::Reference< ILockBytes > & rxLockBytes
+)
+{
+ rxLockBytes = new MemoryLockBytes();
+ if (!rxLockBytes.is())
+ return store_E_OutOfMemory;
+
+ return store_E_None;
+}
+
+} // namespace store
diff --git a/store/source/lockbyte.hxx b/store/source/lockbyte.hxx
new file mode 100644
index 000000000000..20a8b0b77073
--- /dev/null
+++ b/store/source/lockbyte.hxx
@@ -0,0 +1,222 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: lockbyte.hxx,v $
+ *
+ * $Revision: 1.1.2.1 $
+ *
+ * last change: $Author: mhu $ $Date: 2008/09/18 16:10:50 $
+ *
+ * The Contents of this file are made available subject to
+ * the terms of GNU Lesser General Public License Version 2.1.
+ *
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2005 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
+ *
+ ************************************************************************/
+
+#ifndef _STORE_LOCKBYTE_HXX_
+#define _STORE_LOCKBYTE_HXX_ "$Revision: 1.1.2.1 $"
+
+#ifndef _SAL_TYPES_H_
+#include "sal/types.h"
+#endif
+
+#ifndef _RTL_REF_HXX_
+#include "rtl/ref.hxx"
+#endif
+#ifndef _RTL_USTRING_H_
+#include "rtl/ustring.h"
+#endif
+
+#ifndef _STORE_TYPES_H_
+#include "store/types.h"
+#endif
+#ifndef _STORE_STORBASE_HXX_
+#include "storbase.hxx"
+#endif
+
+namespace store
+{
+
+/*========================================================================
+ *
+ * ILockBytes interface.
+ *
+ *======================================================================*/
+class ILockBytes : public rtl::IReference
+{
+public:
+ /**
+ @param rxAllocator [out]
+ @param nPageSize [in]
+ */
+ storeError initialize (
+ rtl::Reference< PageData::Allocator > & rxAllocator,
+ sal_uInt16 nPageSize);
+
+ /**
+ @param rPage [out]
+ @param nOffset [in]
+ */
+ storeError readPageAt (
+ PageHolder & rPage,
+ sal_uInt32 nOffset);
+
+ /**
+ @param rPage [in]
+ @param nOffset [in]
+ */
+ storeError writePageAt (
+ PageHolder const & rPage,
+ sal_uInt32 nOffset);
+
+ /**
+ @param nOffset [in]
+ @param pBuffer [out]
+ @param nBytes [in]
+ @return store_E_None upon success
+ */
+ storeError readAt (
+ sal_uInt32 nOffset,
+ void *pBuffer,
+ sal_uInt32 nBytes);
+
+ /**
+ @param nOffset [in]
+ @param pBuffer [in]
+ @param nBytes [in]
+ @return store_E_None upon success
+ */
+ storeError writeAt (
+ sal_uInt32 nOffset,
+ const void *pBuffer,
+ sal_uInt32 nBytes);
+
+ /**
+ @param rnSize [out]
+ @return store_E_None upon success
+ */
+ storeError getSize (sal_uInt32 & rnSize);
+
+ /**
+ @param nSize [in]
+ @return store_E_None upon success
+ */
+ storeError setSize (sal_uInt32 nSize);
+
+ /**
+ @return store_E_None upon success
+ */
+ storeError flush();
+
+ /**
+ @param nOffset [in]
+ @param nBytes [in]
+ @return store_E_None upon success
+ store_E_LockingViolation
+ */
+ storeError lockRange (
+ sal_uInt32 nOffset,
+ sal_uInt32 nBytes);
+
+ /**
+ @param nOffset [in]
+ @param nBytes [in]
+ @return store_E_None upon success
+ store_E_LockingViolation
+ */
+ storeError unlockRange (
+ sal_uInt32 nOffset,
+ sal_uInt32 nBytes);
+
+private:
+ /** Implementation (abstract).
+ */
+ virtual storeError initialize_Impl (
+ rtl::Reference< PageData::Allocator > & rxAllocator,
+ sal_uInt16 nPageSize) = 0;
+
+ virtual storeError readPageAt_Impl (
+ PageHolder & rPage,
+ sal_uInt32 nOffset) = 0;
+
+ virtual storeError writePageAt_Impl (
+ PageHolder const & rPage,
+ sal_uInt32 nOffset) = 0;
+
+ virtual storeError readAt_Impl (
+ sal_uInt32 nOffset,
+ void *pBuffer,
+ sal_uInt32 nBytes) = 0;
+
+ virtual storeError writeAt_Impl (
+ sal_uInt32 nOffset,
+ const void *pBuffer,
+ sal_uInt32 nBytes) = 0;
+
+ virtual storeError getSize_Impl (
+ sal_uInt32 & rnSize) = 0;
+
+ virtual storeError setSize_Impl (
+ sal_uInt32 nSize) = 0;
+
+ virtual storeError flush_Impl() = 0;
+
+#ifdef STORE_FEATURE_LOCKING
+ virtual storeError lockRange_Impl (
+ sal_uInt32 nOffset,
+ sal_uInt32 nBytes) = 0;
+
+ virtual storeError unlockRange_Impl (
+ sal_uInt32 nOffset,
+ sal_uInt32 nBytes) = 0;
+#endif /* STORE_FEATURE_LOCKING */
+};
+
+/*========================================================================
+ *
+ * ILockBytes factories.
+ *
+ *======================================================================*/
+
+storeError
+FileLockBytes_createInstance (
+ rtl::Reference< store::ILockBytes > & rxLockBytes,
+ rtl_uString * pFilename,
+ storeAccessMode eAccessMode
+);
+
+storeError
+MemoryLockBytes_createInstance (
+ rtl::Reference< store::ILockBytes > & rxLockBytes
+);
+
+/*========================================================================
+ *
+ * The End.
+ *
+ *======================================================================*/
+
+} // namespace store
+
+#endif /* !_STORE_LOCKBYTE_HXX_ */
+
diff --git a/store/source/makefile.mk b/store/source/makefile.mk
new file mode 100644
index 000000000000..88b7b4af4c33
--- /dev/null
+++ b/store/source/makefile.mk
@@ -0,0 +1,75 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2008 by Sun Microsystems, Inc.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.5 $
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org 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 version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..
+
+PRJNAME=store
+TARGET=store
+
+# --- Settings ---
+
+.INCLUDE : settings.mk
+
+# --- Files ---
+
+SLOFILES= \
+ $(SLO)$/object.obj \
+ $(SLO)$/lockbyte.obj \
+ $(SLO)$/storbase.obj \
+ $(SLO)$/storbios.obj \
+ $(SLO)$/storcach.obj \
+ $(SLO)$/stordata.obj \
+ $(SLO)$/stordir.obj \
+ $(SLO)$/storlckb.obj \
+ $(SLO)$/stortree.obj \
+ $(SLO)$/storpage.obj \
+ $(SLO)$/store.obj
+
+.IF "$(debug)" != ""
+OBJFILES= \
+ $(OBJ)$/object.obj \
+ $(OBJ)$/lockbyte.obj \
+ $(OBJ)$/storbase.obj \
+ $(OBJ)$/storbios.obj \
+ $(OBJ)$/storcach.obj \
+ $(OBJ)$/stordata.obj \
+ $(OBJ)$/stordir.obj \
+ $(OBJ)$/storlckb.obj \
+ $(OBJ)$/stortree.obj \
+ $(OBJ)$/storpage.obj \
+ $(OBJ)$/store.obj
+
+.ENDIF # debug
+
+# --- Targets ---
+
+.INCLUDE : target.mk
+
diff --git a/store/source/object.cxx b/store/source/object.cxx
new file mode 100644
index 000000000000..38bea6a331f3
--- /dev/null
+++ b/store/source/object.cxx
@@ -0,0 +1,115 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: object.cxx,v $
+ * $Revision: 1.5 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_store.hxx"
+
+#include "object.hxx"
+
+#include "sal/types.h"
+#include "rtl/alloc.h"
+#include "rtl/ref.hxx"
+#include "osl/diagnose.h"
+#include "osl/interlck.h"
+
+namespace store
+{
+
+/*========================================================================
+ *
+ * OStoreObject implementation.
+ *
+ *======================================================================*/
+const sal_uInt32 OStoreObject::m_nTypeId = sal_uInt32(0x58190322);
+
+/*
+ * OStoreObject.
+ */
+OStoreObject::OStoreObject (void)
+ : m_nRefCount (0)
+{
+}
+
+/*
+ * ~OStoreObject.
+ */
+OStoreObject::~OStoreObject (void)
+{
+ OSL_ASSERT(m_nRefCount == 0);
+}
+
+/*
+ * operator new.
+ */
+void* OStoreObject::operator new (size_t n)
+{
+ return rtl_allocateMemory (n);
+}
+
+/*
+ * operator delete.
+ */
+void OStoreObject::operator delete (void *p, size_t)
+{
+ rtl_freeMemory (p);
+}
+
+/*
+ * isKindOf.
+ */
+sal_Bool SAL_CALL OStoreObject::isKindOf (sal_uInt32 nTypeId)
+{
+ return (nTypeId == m_nTypeId);
+}
+
+/*
+ * acquire.
+ */
+oslInterlockedCount SAL_CALL OStoreObject::acquire (void)
+{
+ oslInterlockedCount result = osl_incrementInterlockedCount (&m_nRefCount);
+ return (result);
+}
+
+/*
+ * release.
+ */
+oslInterlockedCount SAL_CALL OStoreObject::release (void)
+{
+ oslInterlockedCount result = osl_decrementInterlockedCount (&m_nRefCount);
+ if (result == 0)
+ {
+ // Last reference released.
+ delete this;
+ }
+ return (result);
+}
+
+} // namespace store
diff --git a/store/source/object.hxx b/store/source/object.hxx
new file mode 100644
index 000000000000..bc2a9bbcffe8
--- /dev/null
+++ b/store/source/object.hxx
@@ -0,0 +1,146 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: object.hxx,v $
+ *
+ * $Revision: 1.1.2.1 $
+ *
+ * last change: $Author: mhu $ $Date: 2008/09/18 16:10:51 $
+ *
+ * The Contents of this file are made available subject to
+ * the terms of GNU Lesser General Public License Version 2.1.
+ *
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2005 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
+ *
+ ************************************************************************/
+
+#ifndef _STORE_OBJECT_HXX_
+#define _STORE_OBJECT_HXX_ "$Revision: 1.1.2.1 $"
+
+#ifndef _SAL_TYPES_H_
+#include "sal/types.h"
+#endif
+
+#ifndef _RTL_REF_HXX_
+#include "rtl/ref.hxx"
+#endif
+
+#ifndef _OSL_INTERLCK_H_
+#include "osl/interlck.h"
+#endif
+
+namespace store
+{
+
+/*========================================================================
+ *
+ * IStoreHandle interface.
+ *
+ *======================================================================*/
+class IStoreHandle : public rtl::IReference
+{
+public:
+ /** Replaces dynamic_cast type checking.
+ */
+ virtual sal_Bool SAL_CALL isKindOf (sal_uInt32 nTypeId) = 0;
+};
+
+
+/** Template helper function as dynamic_cast replacement.
+ */
+template<class store_handle_type>
+store_handle_type * SAL_CALL query (
+ IStoreHandle * pHandle, store_handle_type *);
+
+/*========================================================================
+ *
+ * OStoreObject interface.
+ *
+ *======================================================================*/
+class OStoreObject : public store::IStoreHandle
+{
+ /** Template function specialization as dynamic_cast replacement.
+ */
+ friend OStoreObject*
+ SAL_CALL query<> (IStoreHandle *pHandle, OStoreObject*);
+
+public:
+ /** Construction.
+ */
+ OStoreObject (void);
+
+ /** Allocation.
+ */
+ static void* operator new (size_t n);
+ static void operator delete (void *p, size_t);
+
+ /** IStoreHandle.
+ */
+ virtual sal_Bool SAL_CALL isKindOf (sal_uInt32 nTypeId);
+
+ /** IReference.
+ */
+ virtual oslInterlockedCount SAL_CALL acquire (void);
+ virtual oslInterlockedCount SAL_CALL release (void);
+
+protected:
+ /** Destruction.
+ */
+ virtual ~OStoreObject (void);
+
+private:
+ /** The IStoreHandle TypeId.
+ */
+ static const sal_uInt32 m_nTypeId;
+
+ /** Representation.
+ */
+ oslInterlockedCount m_nRefCount;
+
+ /** Not implemented.
+ */
+ OStoreObject (const OStoreObject&);
+ OStoreObject& operator= (const OStoreObject&);
+};
+
+/** Template function specialization as dynamic_cast replacement.
+ */
+template<> inline OStoreObject*
+SAL_CALL query (IStoreHandle *pHandle, OStoreObject*)
+{
+ if (pHandle && pHandle->isKindOf (OStoreObject::m_nTypeId))
+ {
+ // Handle is kind of OStoreObject.
+ return static_cast<OStoreObject*>(pHandle);
+ }
+ return 0;
+}
+
+/*========================================================================
+ *
+ * The End.
+ *
+ *======================================================================*/
+
+} // namespace store
+
+#endif /* !_STORE_OBJECT_HXX_ */
diff --git a/store/source/storbase.cxx b/store/source/storbase.cxx
new file mode 100644
index 000000000000..747b70df393a
--- /dev/null
+++ b/store/source/storbase.cxx
@@ -0,0 +1,205 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: storbase.cxx,v $
+ *
+ * $Revision: 1.12.8.4 $
+ *
+ * last change: $Author: mhu $ $Date: 2008/10/31 18:28:18 $
+ *
+ * The Contents of this file are made available subject to
+ * the terms of GNU Lesser General Public License Version 2.1.
+ *
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2005 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
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_store.hxx"
+
+#include "storbase.hxx"
+
+#include "sal/types.h"
+#include "rtl/alloc.h"
+#include "rtl/ref.hxx"
+#include "osl/diagnose.h"
+
+#include "store/types.h"
+#include "object.hxx"
+
+#ifndef INCLUDED_STDIO_H
+#include <stdio.h>
+#define INCLUDED_STDIO_H
+#endif
+
+using namespace store;
+
+/*========================================================================
+ *
+ * SharedCount::Allocator.
+ *
+ *======================================================================*/
+SharedCount::Allocator &
+SharedCount::Allocator::get()
+{
+ static Allocator g_aSharedCountAllocator;
+ return g_aSharedCountAllocator;
+}
+
+SharedCount::Allocator::Allocator()
+{
+ m_cache = rtl_cache_create (
+ "store_shared_count_cache",
+ sizeof(long),
+ 0, // objalign
+ 0, // constructor
+ 0, // destructor
+ 0, // reclaim
+ 0, // userarg
+ 0, // default source
+ 0 // flags
+ );
+}
+
+SharedCount::Allocator::~Allocator()
+{
+ rtl_cache_destroy (m_cache), m_cache = 0;
+}
+
+/*========================================================================
+ *
+ * PageData::Allocator_Impl (default allocator).
+ *
+ *======================================================================*/
+namespace store
+{
+
+class PageData::Allocator_Impl :
+ public store::OStoreObject,
+ public store::PageData::Allocator
+{
+public:
+ /** Construction (two phase).
+ */
+ Allocator_Impl();
+
+ storeError initialize (sal_uInt16 nPageSize);
+
+ /** Delegate multiple inherited rtl::IReference.
+ */
+ virtual oslInterlockedCount SAL_CALL acquire()
+ {
+ return OStoreObject::acquire();
+ }
+ virtual oslInterlockedCount SAL_CALL release()
+ {
+ return OStoreObject::release();
+ }
+
+protected:
+ /** Destruction.
+ */
+ virtual ~Allocator_Impl();
+
+private:
+ /** Representation.
+ */
+ rtl_cache_type * m_page_cache;
+ sal_uInt16 m_page_size;
+
+ /** PageData::Allocator implementation.
+ */
+ virtual void allocate_Impl (void ** ppPage, sal_uInt16 * pnSize);
+ virtual void deallocate_Impl (void * pPage);
+
+ /** Not implemented.
+ */
+ Allocator_Impl (Allocator_Impl const &);
+ Allocator_Impl & operator= (Allocator_Impl const &);
+};
+
+} // namespace store
+
+PageData::Allocator_Impl::Allocator_Impl()
+ : m_page_cache(0), m_page_size(0)
+{}
+
+storeError
+PageData::Allocator_Impl::initialize (sal_uInt16 nPageSize)
+{
+ char name[RTL_CACHE_NAME_LENGTH + 1];
+ sal_Size size = sal::static_int_cast< sal_Size >(nPageSize);
+ (void) snprintf (name, sizeof(name), "store_page_alloc_%lu", size);
+
+ m_page_cache = rtl_cache_create (name, size, 0, 0, 0, 0, 0, 0, 0);
+ if (!m_page_cache)
+ return store_E_OutOfMemory;
+
+ m_page_size = nPageSize;
+ return store_E_None;
+}
+
+PageData::Allocator_Impl::~Allocator_Impl()
+{
+ rtl_cache_destroy(m_page_cache), m_page_cache = 0;
+}
+
+void PageData::Allocator_Impl::allocate_Impl (void ** ppPage, sal_uInt16 * pnSize)
+{
+ OSL_PRECOND((ppPage != 0) && (pnSize != 0), "contract violation");
+ *ppPage = rtl_cache_alloc(m_page_cache), *pnSize = m_page_size;
+}
+
+void PageData::Allocator_Impl::deallocate_Impl (void * pPage)
+{
+ OSL_PRECOND(pPage != 0, "contract violation");
+ rtl_cache_free(m_page_cache, pPage);
+}
+
+/*========================================================================
+ *
+ * PageData::Allocator factory.
+ *
+ *======================================================================*/
+
+storeError
+PageData::Allocator::createInstance (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize)
+{
+ rtl::Reference< PageData::Allocator_Impl > xAllocator (new PageData::Allocator_Impl());
+ if (!xAllocator.is())
+ return store_E_OutOfMemory;
+
+ rxAllocator = &*xAllocator;
+ return xAllocator->initialize (nPageSize);
+}
+
+/*========================================================================
+ *
+ * OStorePageObject.
+ *
+ *======================================================================*/
+/*
+ * ~OStorePageObject.
+ */
+OStorePageObject::~OStorePageObject (void)
+{
+}
diff --git a/store/source/storbase.hxx b/store/source/storbase.hxx
new file mode 100644
index 000000000000..04be2860f691
--- /dev/null
+++ b/store/source/storbase.hxx
@@ -0,0 +1,974 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: storbase.hxx,v $
+ * $Revision: 1.10 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _STORE_STORBASE_HXX_
+#define _STORE_STORBASE_HXX_ "$Revision: 1.10.8.4 $"
+
+#include "sal/types.h"
+
+#include "rtl/alloc.h"
+#include "rtl/crc.h"
+#include "rtl/ref.hxx"
+
+#include "osl/diagnose.h"
+#include "osl/endian.h"
+
+#include "store/types.h"
+
+#ifndef INCLUDED_STDDEF_H
+#include <stddef.h>
+#define INCLUDED_STDDEF_H
+#endif
+
+#ifndef INCLUDED_STRING_H
+#include <string.h>
+#define INCLUDED_STRING_H
+#endif
+
+/*========================================================================
+ *
+ * store common internals.
+ *
+ *======================================================================*/
+
+#ifndef STORE_IMPL_ISP2
+#define STORE_IMPL_ISP2(value) (((value) & ((value) - 1)) == 0)
+#endif
+
+#ifndef STORE_IMPL_CONCAT
+#define STORE_IMPL_CONCAT(x, y) STORE_IMPL_CONCAT2(x,y)
+#define STORE_IMPL_CONCAT2(x, y) x##y
+#endif
+
+#ifndef STORE_STATIC_ASSERT /* Compile time assertion */
+namespace store
+{
+ template< bool x > struct STATIC_ASSERTION_FAILURE;
+ template<> struct STATIC_ASSERTION_FAILURE< true > { enum { value = 1 }; };
+
+ template< int x > struct static_assert_test{};
+} // namespace store
+
+#define STORE_STATIC_ASSERT(pred) \
+typedef \
+store::static_assert_test< sizeof( store::STATIC_ASSERTION_FAILURE< (bool)(pred) > ) > \
+STORE_IMPL_CONCAT(static_assert_typedef_, __LINE__)
+
+#endif /* !STORE_STATIC_ASSERT */
+
+namespace store
+{
+
+#ifdef htons
+#undef htons
+#endif
+#ifdef ntohs
+#undef ntohs
+#endif
+
+#ifdef htonl
+#undef htonl
+#endif
+#ifdef ntohl
+#undef ntohl
+#endif
+
+#ifdef OSL_BIGENDIAN
+inline sal_uInt16 htons (sal_uInt16 h) { return OSL_SWAPWORD(h); }
+inline sal_uInt16 ntohs (sal_uInt16 n) { return OSL_SWAPWORD(n); }
+
+inline sal_uInt32 htonl (sal_uInt32 h) { return OSL_SWAPDWORD(h); }
+inline sal_uInt32 ntohl (sal_uInt32 n) { return OSL_SWAPDWORD(n); }
+#else
+inline sal_uInt16 htons (sal_uInt16 h) { return (h); }
+inline sal_uInt16 ntohs (sal_uInt16 n) { return (n); }
+
+inline sal_uInt32 htonl (sal_uInt32 h) { return (h); }
+inline sal_uInt32 ntohl (sal_uInt32 n) { return (n); }
+#endif /* OSL_BIGENDIAN */
+
+/** swap.
+ */
+template< typename T > void swap (T & lhs, T & rhs)
+{
+ T tmp = lhs; lhs = rhs; rhs = tmp;
+}
+
+/*========================================================================
+ *
+ * SharedCount.
+ *
+ *======================================================================*/
+class SharedCount
+{
+ long * m_pCount;
+
+ class Allocator
+ {
+ rtl_cache_type * m_cache;
+
+ public:
+ static Allocator & get();
+
+ long * alloc()
+ {
+ return static_cast<long*>(rtl_cache_alloc (m_cache));
+ }
+ void free (long * pCount)
+ {
+ rtl_cache_free (m_cache, pCount);
+ }
+
+ protected:
+ Allocator();
+ ~Allocator();
+ };
+
+public:
+ SharedCount()
+ : m_pCount(Allocator::get().alloc())
+ {
+ if (m_pCount != 0) (*m_pCount) = 1;
+ }
+
+ ~SharedCount()
+ {
+ if (m_pCount != 0)
+ {
+ long new_count = --(*m_pCount);
+ if (new_count == 0)
+ Allocator::get().free(m_pCount);
+ }
+ }
+
+ void swap (SharedCount & rhs) // nothrow
+ {
+ store::swap(m_pCount, rhs.m_pCount);
+ }
+
+ SharedCount (SharedCount const & rhs) // nothrow
+ : m_pCount (rhs.m_pCount)
+ {
+ if (m_pCount != 0) ++(*m_pCount);
+ }
+ SharedCount & operator= (SharedCount const & rhs) // nothrow
+ {
+ SharedCount tmp(rhs);
+ swap(tmp);
+ return *this;
+ }
+
+ bool operator== (long count) const
+ {
+ return (m_pCount != 0) ? *m_pCount == count : false;
+ }
+};
+
+/*========================================================================
+ *
+ * OStorePageGuard.
+ *
+ *======================================================================*/
+struct OStorePageGuard
+{
+ /** Representation.
+ */
+ sal_uInt32 m_nMagic;
+ sal_uInt32 m_nCRC32;
+
+ /** Construction.
+ */
+ explicit OStorePageGuard (sal_uInt32 nMagic = 0, sal_uInt32 nCRC32 = 0)
+ : m_nMagic (store::htonl(nMagic)),
+ m_nCRC32 (store::htonl(nCRC32))
+ {}
+
+ void swap (OStorePageGuard & rhs)
+ {
+ store::swap(m_nMagic, rhs.m_nMagic);
+ store::swap(m_nCRC32, rhs.m_nCRC32);
+ }
+
+ OStorePageGuard (OStorePageGuard const & rhs)
+ : m_nMagic (rhs.m_nMagic),
+ m_nCRC32 (rhs.m_nCRC32)
+ {}
+
+ OStorePageGuard& operator= (const OStorePageGuard& rhs)
+ {
+ m_nMagic = rhs.m_nMagic;
+ m_nCRC32 = rhs.m_nCRC32;
+ return *this;
+ }
+
+ /** Comparison.
+ */
+ bool operator== (const OStorePageGuard& rhs) const
+ {
+ return ((m_nMagic == rhs.m_nMagic) &&
+ (m_nCRC32 == rhs.m_nCRC32) );
+ }
+};
+
+/*========================================================================
+ *
+ * OStorePageDescriptor.
+ *
+ *======================================================================*/
+#define STORE_PAGE_NULL ((sal_uInt32)(~0))
+
+struct OStorePageDescriptor
+{
+ /** Representation.
+ */
+ sal_uInt32 m_nAddr;
+ sal_uInt16 m_nSize;
+ sal_uInt16 m_nUsed;
+
+ /** Construction.
+ */
+ explicit OStorePageDescriptor (
+ sal_uInt32 nAddr = STORE_PAGE_NULL,
+ sal_uInt16 nSize = 0,
+ sal_uInt16 nUsed = 0)
+ : m_nAddr (store::htonl(nAddr)),
+ m_nSize (store::htons(nSize)),
+ m_nUsed (store::htons(nUsed))
+ {}
+
+ void swap (OStorePageDescriptor & rhs)
+ {
+ store::swap(m_nAddr, rhs.m_nAddr);
+ store::swap(m_nSize, rhs.m_nSize);
+ store::swap(m_nUsed, rhs.m_nUsed);
+ }
+
+ OStorePageDescriptor (const OStorePageDescriptor & rhs)
+ : m_nAddr (rhs.m_nAddr),
+ m_nSize (rhs.m_nSize),
+ m_nUsed (rhs.m_nUsed)
+ {}
+
+ OStorePageDescriptor & operator= (const OStorePageDescriptor & rhs)
+ {
+ m_nAddr = rhs.m_nAddr;
+ m_nSize = rhs.m_nSize;
+ m_nUsed = rhs.m_nUsed;
+ return *this;
+ }
+
+ /** Comparison.
+ */
+ bool operator== (const OStorePageDescriptor & rhs) const
+ {
+ return ((m_nAddr == rhs.m_nAddr) &&
+ (m_nSize == rhs.m_nSize) );
+ }
+
+ bool operator<= (const OStorePageDescriptor & rhs) const
+ {
+ return ((m_nAddr == rhs.m_nAddr ) &&
+ (store::ntohs(m_nSize) <= store::ntohs(rhs.m_nSize)) );
+ }
+
+ bool operator< (const OStorePageDescriptor & rhs) const
+ {
+ if (m_nAddr == rhs.m_nAddr)
+ return (store::ntohs(m_nSize) < store::ntohs(rhs.m_nSize));
+ else
+ return (store::ntohl(m_nAddr) < store::ntohl(rhs.m_nAddr));
+ }
+};
+
+/*========================================================================
+ *
+ * OStorePageKey.
+ *
+ *======================================================================*/
+struct OStorePageKey
+{
+ /** Representation.
+ */
+ sal_uInt32 m_nLow;
+ sal_uInt32 m_nHigh;
+
+ /** Construction.
+ */
+ explicit OStorePageKey (sal_uInt32 nLow = 0, sal_uInt32 nHigh = 0)
+ : m_nLow (store::htonl(nLow)),
+ m_nHigh (store::htonl(nHigh))
+ {}
+
+ void swap (OStorePageKey & rhs)
+ {
+ store::swap(m_nLow, rhs.m_nLow);
+ store::swap(m_nHigh, rhs.m_nHigh);
+ }
+
+ OStorePageKey (const OStorePageKey & rhs)
+ : m_nLow (rhs.m_nLow), m_nHigh (rhs.m_nHigh)
+ {}
+
+ OStorePageKey & operator= (const OStorePageKey & rhs)
+ {
+ m_nLow = rhs.m_nLow;
+ m_nHigh = rhs.m_nHigh;
+ return *this;
+ }
+
+ /** Comparison.
+ */
+ bool operator== (const OStorePageKey & rhs) const
+ {
+ return ((m_nLow == rhs.m_nLow ) &&
+ (m_nHigh == rhs.m_nHigh) );
+ }
+
+ bool operator< (const OStorePageKey & rhs) const
+ {
+ if (m_nHigh == rhs.m_nHigh)
+ return (store::ntohl(m_nLow) < store::ntohl(rhs.m_nLow));
+ else
+ return (store::ntohl(m_nHigh) < store::ntohl(rhs.m_nHigh));
+ }
+};
+
+/*========================================================================
+ *
+ * OStorePageLink.
+ *
+ *======================================================================*/
+struct OStorePageLink
+{
+ /** Representation.
+ */
+ sal_uInt32 m_nAddr;
+
+ /** Construction.
+ */
+ explicit OStorePageLink (sal_uInt32 nAddr = STORE_PAGE_NULL)
+ : m_nAddr (store::htonl(nAddr))
+ {}
+
+ void swap (OStorePageLink & rhs)
+ {
+ store::swap(m_nAddr, rhs.m_nAddr);
+ }
+
+ OStorePageLink (const OStorePageLink & rhs)
+ : m_nAddr (rhs.m_nAddr)
+ {}
+
+ OStorePageLink & operator= (const OStorePageLink & rhs)
+ {
+ m_nAddr = rhs.m_nAddr;
+ return *this;
+ }
+
+ OStorePageLink & operator= (sal_uInt32 nAddr)
+ {
+ m_nAddr = store::htonl(nAddr);
+ return *this;
+ }
+
+ /** Comparison.
+ */
+ bool operator== (const OStorePageLink & rhs) const
+ {
+ return (m_nAddr == rhs.m_nAddr);
+ }
+
+ bool operator< (const OStorePageLink& rhs) const
+ {
+ return (store::ntohl(m_nAddr) < store::ntohl(rhs.m_nAddr));
+ }
+
+ /** Operation.
+ */
+ sal_uInt32 location() const
+ {
+ return store::ntohl(m_nAddr);
+ }
+
+ void link (OStorePageLink & rPred)
+ {
+ // @@@ swap (rPred); @@@
+ OStorePageLink tmp (rPred);
+ rPred = *this;
+ *this = tmp;
+ }
+
+ void unlink (OStorePageLink& rPred)
+ {
+ rPred = *this;
+ *this = OStorePageLink();
+ }
+};
+
+/*========================================================================
+ *
+ * PageData.
+ *
+ *======================================================================*/
+typedef struct PageData OStorePageData; // backward compat.
+struct PageData
+{
+ typedef OStorePageGuard G;
+ typedef OStorePageDescriptor D;
+ typedef OStorePageLink L;
+
+ /** Representation.
+ */
+ G m_aGuard;
+ D m_aDescr;
+ L m_aMarked;
+ L m_aUnused;
+
+ /** theSize.
+ */
+ static const size_t theSize = sizeof(G) + sizeof(D) + 2 * sizeof(L);
+ static const sal_uInt16 thePageSize = theSize;
+ STORE_STATIC_ASSERT(STORE_MINIMUM_PAGESIZE >= thePageSize);
+
+ /** location.
+ */
+ sal_uInt32 location() const
+ {
+ return store::ntohl(m_aDescr.m_nAddr);
+ }
+ void location (sal_uInt32 nAddr)
+ {
+ m_aDescr.m_nAddr = store::htonl(nAddr);
+ }
+
+ /** size.
+ */
+ sal_uInt16 size() const
+ {
+ return store::ntohs(m_aDescr.m_nSize);
+ }
+
+ /** type.
+ */
+ sal_uInt32 type() const
+ {
+ return store::ntohl(m_aGuard.m_nMagic);
+ }
+
+ /** Allocation.
+ */
+ class Allocator_Impl;
+ class Allocator : public rtl::IReference
+ {
+ public:
+ template< class T > T * construct()
+ {
+ void * page = 0; sal_uInt16 size = 0;
+ if (allocate (&page, &size))
+ {
+ return new(page) T(size);
+ }
+ return 0;
+ }
+
+ bool allocate (void ** ppPage, sal_uInt16 * pnSize)
+ {
+ allocate_Impl (ppPage, pnSize);
+ return ((*ppPage != 0) && (*pnSize != 0));
+ }
+
+ void deallocate (void * pPage)
+ {
+ if (pPage != 0)
+ deallocate_Impl (pPage);
+ }
+
+ static storeError createInstance (
+ rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize);
+
+ private:
+ /** Implementation (abstract).
+ */
+ virtual void allocate_Impl (void ** ppPage, sal_uInt16 * pnSize) = 0;
+ virtual void deallocate_Impl (void * pPage) = 0;
+ };
+
+ static void* operator new (size_t, void * p) { return p; }
+ static void operator delete (void * , void *) {}
+
+ /** Construction.
+ */
+ explicit PageData (sal_uInt16 nPageSize = thePageSize)
+ : m_aGuard(),
+ m_aDescr(STORE_PAGE_NULL, nPageSize, thePageSize),
+ m_aMarked(),
+ m_aUnused()
+ {}
+
+ void swap (PageData & rhs) // nothrow
+ {
+ m_aGuard.swap(rhs.m_aGuard);
+ m_aDescr.swap(rhs.m_aDescr);
+ m_aMarked.swap(rhs.m_aMarked);
+ m_aUnused.swap(rhs.m_aUnused);
+ }
+
+ PageData (PageData const & rhs) // nothrow
+ : m_aGuard (rhs.m_aGuard),
+ m_aDescr (rhs.m_aDescr),
+ m_aMarked(rhs.m_aMarked),
+ m_aUnused(rhs.m_aUnused)
+ {}
+
+ PageData & operator= (PageData const & rhs) // nothrow
+ {
+ PageData tmp (rhs);
+ swap (tmp);
+ return *this;
+ }
+
+ /** guard (external representation).
+ */
+ void guard()
+ {
+ sal_uInt32 nCRC32 = 0;
+ nCRC32 = rtl_crc32 (nCRC32, &m_aGuard.m_nMagic, sizeof(sal_uInt32));
+ nCRC32 = rtl_crc32 (nCRC32, &m_aDescr, theSize - sizeof(G));
+ m_aGuard.m_nCRC32 = store::htonl(nCRC32);
+ }
+ void guard (sal_uInt32 nAddr)
+ {
+ sal_uInt32 nCRC32 = 0;
+ nCRC32 = rtl_crc32 (nCRC32, &m_aGuard.m_nMagic, sizeof(sal_uInt32));
+ m_aDescr.m_nAddr = store::htonl(nAddr);
+ nCRC32 = rtl_crc32 (nCRC32, &m_aDescr, theSize - sizeof(G));
+ m_aGuard.m_nCRC32 = store::htonl(nCRC32);
+ }
+
+ /** verify (external representation).
+ */
+ storeError verify() const
+ {
+ sal_uInt32 nCRC32 = 0;
+ nCRC32 = rtl_crc32 (nCRC32, &m_aGuard.m_nMagic, sizeof(sal_uInt32));
+ nCRC32 = rtl_crc32 (nCRC32, &m_aDescr, theSize - sizeof(G));
+ if (m_aGuard.m_nCRC32 != store::htonl(nCRC32))
+ return store_E_InvalidChecksum;
+ else
+ return store_E_None;
+ }
+ storeError verify (sal_uInt32 nAddr) const
+ {
+ sal_uInt32 nCRC32 = 0;
+ nCRC32 = rtl_crc32 (nCRC32, &m_aGuard.m_nMagic, sizeof(sal_uInt32));
+ nCRC32 = rtl_crc32 (nCRC32, &m_aDescr, theSize - sizeof(G));
+ if (m_aGuard.m_nCRC32 != store::htonl(nCRC32))
+ return store_E_InvalidChecksum;
+ if (m_aDescr.m_nAddr != store::htonl(nAddr))
+ return store_E_InvalidAccess;
+ return store_E_None;
+ }
+
+ storeError verifyVersion (sal_uInt32 nMagic) const
+ {
+ if (m_aGuard.m_nMagic != store::htonl(nMagic))
+ return store_E_WrongVersion;
+ else
+ return store_E_None;
+ }
+};
+
+/*========================================================================
+ *
+ * PageHolder.
+ *
+ *======================================================================*/
+class PageHolder
+{
+ SharedCount m_refcount;
+ PageData * m_pagedata;
+
+ typedef rtl::Reference< PageData::Allocator > allocator_type;
+ allocator_type m_allocator;
+
+public:
+ explicit PageHolder (PageData * pagedata = 0, allocator_type const & allocator = allocator_type())
+ : m_refcount (),
+ m_pagedata (pagedata),
+ m_allocator(allocator)
+ {
+ OSL_ENSURE((m_pagedata == 0) || m_allocator.is(), "store::PageHolder::ctor(): pagedata w/o allocator.");
+ }
+
+ ~PageHolder()
+ {
+ if ((m_refcount == 1) && (m_pagedata != 0))
+ {
+ // free pagedata.
+ OSL_ENSURE(m_allocator.is(), "store::PageHolder::dtor(): pagedata w/o allocator.");
+ m_allocator->deallocate (m_pagedata);
+ }
+ }
+
+ void swap (PageHolder & rhs) // nothrow
+ {
+ m_refcount.swap(rhs.m_refcount);
+ store::swap(m_pagedata, rhs.m_pagedata);
+ store::swap(m_allocator, rhs.m_allocator);
+ }
+
+ PageHolder (PageHolder const & rhs) // nothrow
+ : m_refcount (rhs.m_refcount),
+ m_pagedata (rhs.m_pagedata),
+ m_allocator(rhs.m_allocator)
+ {}
+
+ PageHolder & operator= (PageHolder const & rhs) // nothrow
+ {
+ PageHolder tmp (rhs);
+ swap(tmp);
+ return *this;
+ }
+
+ PageData * get() { return m_pagedata; }
+ PageData const * get() const { return m_pagedata; }
+
+ PageData * operator->()
+ {
+ OSL_PRECOND(m_pagedata != 0, "store::PageHolder::operator->(): Null pointer");
+ return m_pagedata;
+ }
+ PageData const * operator->() const
+ {
+ OSL_PRECOND(m_pagedata != 0, "store::PageHolder::operator->(): Null pointer");
+ return m_pagedata;
+ }
+
+ PageData & operator*()
+ {
+ OSL_PRECOND(m_pagedata != 0, "store::PageHolder::operator*(): Null pointer");
+ return *m_pagedata;
+ }
+ PageData const & operator*() const
+ {
+ OSL_PRECOND(m_pagedata != 0, "store::PageHolder::operator*(): Null pointer");
+ return *m_pagedata;
+ }
+};
+
+/*========================================================================
+ *
+ * PageHolderObject.
+ *
+ *======================================================================*/
+template< class T >
+class PageHolderObject
+{
+ /** Representation.
+ */
+ PageHolder m_xPage;
+
+ /** Checked cast.
+ */
+ template< class U >
+ static bool isA (PageData const * p)
+ {
+ return ((p != 0) && (p->type() == U::theTypeId));
+ }
+
+ template< class U >
+ static U * dynamic_page_cast (PageData * p)
+ {
+ return isA<U>(p) ? static_cast<U*>(p) : 0;
+ }
+
+ template< class U >
+ static U const * dynamic_page_cast (PageData const * p)
+ {
+ return isA<U>(p) ? static_cast<U const *>(p) : 0;
+ }
+
+public:
+ bool construct (rtl::Reference< PageData::Allocator > const & rxAllocator)
+ {
+ if ((m_xPage.get() == 0) && rxAllocator.is())
+ {
+ PageHolder tmp (rxAllocator->construct<T>(), rxAllocator);
+ m_xPage.swap (tmp);
+ }
+ return (m_xPage.get() != 0);
+ }
+
+ static PageHolderObject<T> createInstance (rtl::Reference< PageData::Allocator > const & rxAllocator)
+ {
+ PageHolderObject<T> tmp;
+ (void) tmp.construct (rxAllocator);
+ return tmp;
+ }
+
+ explicit PageHolderObject (PageHolder const & rxPage = PageHolder())
+ : m_xPage (rxPage)
+ {}
+
+ void swap (PageHolderObject<T> & rhs)
+ {
+ m_xPage.swap (rhs.m_xPage);
+ }
+
+ PageHolderObject (PageHolderObject<T> const & rhs)
+ : m_xPage (rhs.m_xPage)
+ {}
+
+ PageHolderObject<T> & operator= (PageHolderObject<T> const & rhs)
+ {
+ PageHolderObject<T> tmp (rhs);
+ this->swap (tmp);
+ return *this;
+ }
+
+ bool is() const
+ {
+ return (m_xPage.get() != 0);
+ }
+
+#if 1 /* EXP */
+ PageHolder & get() { return m_xPage; }
+ PageHolder const & get() const { return m_xPage; }
+#endif /* EXP */
+
+ T * operator->()
+ {
+ T * pImpl = dynamic_page_cast<T>(m_xPage.get());
+ OSL_PRECOND(pImpl != 0, "store::PageHolder<T>::operator*(): Null pointer");
+ return pImpl;
+ }
+ T const * operator->() const
+ {
+ T const * pImpl = dynamic_page_cast<T>(m_xPage.get());
+ OSL_PRECOND(pImpl != 0, "store::PageHolder<T>::operator*(): Null pointer");
+ return pImpl;
+ }
+
+ T & operator*()
+ {
+ T * pImpl = dynamic_page_cast<T>(m_xPage.get());
+ OSL_PRECOND(pImpl != 0, "store::PageHolder<T>::operator*(): Null pointer");
+ return (*pImpl);
+ }
+ T const & operator*() const
+ {
+ T const * pImpl = dynamic_page_cast<T>(m_xPage.get());
+ OSL_PRECOND(pImpl != 0, "store::PageHolder<T>::operator*(): Null pointer");
+ return (*pImpl);
+ }
+
+ static storeError guard (PageHolder & rxPage, sal_uInt32 nAddr)
+ {
+ PageData * pHead = rxPage.get();
+ if (!pHead)
+ return store_E_InvalidAccess;
+ pHead->guard(nAddr);
+
+ T * pImpl = dynamic_page_cast<T>(pHead);
+ OSL_PRECOND(pImpl != 0, "store::PageHolder<T>::guard(): Null pointer");
+ pImpl->guard();
+
+ return store_E_None;
+ }
+ static storeError verify (PageHolder const & rxPage, sal_uInt32 nAddr)
+ {
+ PageData const * pHead = rxPage.get();
+ if (!pHead)
+ return store_E_InvalidAccess;
+
+ storeError eErrCode = pHead->verify(nAddr);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ T const * pImpl = dynamic_page_cast<T>(pHead);
+ if (!pImpl)
+ return store_E_WrongVersion;
+
+ return pImpl->verify();
+ }
+};
+
+/*========================================================================
+ *
+ * PageObject.
+ *
+ *======================================================================*/
+#if 1 /* EXP */
+class PageObject
+{
+public:
+ explicit PageObject (PageHolder const & rxPage = PageHolder())
+ : m_xPage (rxPage), m_bDirty (false)
+ {}
+
+ virtual ~PageObject()
+ {}
+
+ PageHolder & get() { return m_xPage; }
+ PageHolder const & get() const { return m_xPage; }
+
+ void clean() { m_bDirty = false; }
+ void touch() { m_bDirty = true; }
+
+ sal_uInt32 location() const
+ {
+ PageData const * pagedata = m_xPage.get();
+ return (pagedata != 0) ? pagedata->location() : STORE_PAGE_NULL;
+ }
+ void location (sal_uInt32 nAddr)
+ {
+ PageData * pagedata = m_xPage.get();
+ if (pagedata != 0)
+ pagedata->location (nAddr);
+ }
+
+protected:
+ PageHolder m_xPage;
+ bool m_bDirty;
+
+ virtual storeError guard (sal_uInt32 nAddr) = 0;
+ virtual storeError verify (sal_uInt32 nAddr) const = 0;
+};
+#endif /* EXP */
+
+class OStorePageBIOS;
+
+class OStorePageObject
+{
+ typedef OStorePageData page;
+
+public:
+ /** Allocation.
+ */
+ static void * operator new (size_t n) SAL_THROW(())
+ {
+ return rtl_allocateMemory (sal_uInt32(n));
+ }
+ static void operator delete (void * p, size_t) SAL_THROW(())
+ {
+ rtl_freeMemory (p);
+ }
+
+ /** State.
+ */
+ inline bool dirty (void) const;
+ inline void clean (void);
+ inline void touch (void);
+
+ /** Location.
+ */
+ inline sal_uInt32 location (void) const;
+ inline void location (sal_uInt32 nAddr);
+
+protected:
+ /** Representation.
+ */
+ PageHolder m_xPage;
+ bool m_bDirty;
+
+ /** Construction.
+ */
+ explicit OStorePageObject (PageHolder const & rxPage = PageHolder())
+ : m_xPage (rxPage), m_bDirty (false)
+ {}
+
+ /** Destruction.
+ */
+ virtual ~OStorePageObject (void);
+
+public:
+ template< class U >
+ PageHolderObject<U> makeHolder() const
+ {
+ return PageHolderObject<U>(m_xPage);
+ }
+
+ template< class U >
+ storeError construct (rtl::Reference< PageData::Allocator > const & rxAllocator)
+ {
+ if (!rxAllocator.is())
+ return store_E_InvalidAccess;
+
+ PageHolder tmp (rxAllocator->construct<U>(), rxAllocator);
+ if (!tmp.get())
+ return store_E_OutOfMemory;
+
+ m_xPage.swap (tmp);
+ return store_E_None;
+ }
+
+
+ PageHolder & get() { return m_xPage; }
+ PageHolder const & get() const { return m_xPage; }
+
+ virtual storeError guard (sal_uInt32 nAddr) = 0;
+ virtual storeError verify (sal_uInt32 nAddr) const = 0;
+};
+
+inline bool OStorePageObject::dirty (void) const
+{
+ return m_bDirty;
+}
+
+inline void OStorePageObject::clean (void)
+{
+ m_bDirty = false;
+}
+
+inline void OStorePageObject::touch (void)
+{
+ m_bDirty = true;
+}
+
+inline sal_uInt32 OStorePageObject::location (void) const
+{
+ return m_xPage->location();
+}
+
+inline void OStorePageObject::location (sal_uInt32 nAddr)
+{
+ m_xPage->location(nAddr);
+ touch();
+}
+
+/*========================================================================
+ *
+ * The End.
+ *
+ *======================================================================*/
+
+} // namespace store
+
+#endif /* !_STORE_STORBASE_HXX_ */
diff --git a/store/source/storbios.cxx b/store/source/storbios.cxx
new file mode 100644
index 000000000000..d1f15dcda247
--- /dev/null
+++ b/store/source/storbios.cxx
@@ -0,0 +1,1570 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: storbios.cxx,v $
+ *
+ * $Revision: 1.1.2.3 $
+ *
+ * last change: $Author: mhu $ $Date: 2008/10/31 18:28:18 $
+ *
+ * The Contents of this file are made available subject to
+ * the terms of GNU Lesser General Public License Version 2.1.
+ *
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2005 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
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_store.hxx"
+
+#include "storbios.hxx"
+
+#include "sal/types.h"
+#include "sal/macros.h"
+
+#include "rtl/alloc.h"
+#include "rtl/ref.hxx"
+
+#include "osl/diagnose.h"
+#include "osl/mutex.hxx"
+
+#include "store/types.h"
+#include "object.hxx"
+#include "lockbyte.hxx"
+#include "storcach.hxx"
+
+using namespace store;
+
+/*========================================================================
+ *
+ * OStoreSuperBlock.
+ *
+ *======================================================================*/
+#define STORE_MAGIC_SUPERBLOCK sal_uInt32(0x484D5343)
+
+struct OStoreSuperBlock
+{
+ typedef OStorePageGuard G;
+ typedef OStorePageDescriptor D;
+ typedef OStorePageLink L;
+
+ /** Representation.
+ */
+ G m_aGuard;
+ D m_aDescr;
+ sal_uInt32 m_nMarked;
+ L m_aMarked;
+ sal_uInt32 m_nUnused;
+ L m_aUnused;
+
+ /** theSize.
+ */
+ static const size_t theSize = sizeof(G) + sizeof(D) + 2 * (sizeof(L) + sizeof(sal_uInt32));
+
+ /** Construction.
+ */
+ 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)
+ {}
+
+ OStoreSuperBlock (const OStoreSuperBlock& rOther)
+ : m_aGuard (rOther.m_aGuard),
+ m_aDescr (rOther.m_aDescr),
+ m_nMarked (rOther.m_nMarked),
+ m_aMarked (rOther.m_aMarked),
+ m_nUnused (rOther.m_nUnused),
+ m_aUnused (rOther.m_aUnused)
+ {}
+
+ OStoreSuperBlock& operator= (const OStoreSuperBlock& rOther)
+ {
+ m_aGuard = rOther.m_aGuard;
+ m_aDescr = rOther.m_aDescr;
+ m_nMarked = rOther.m_nMarked;
+ m_aMarked = rOther.m_aMarked;
+ m_nUnused = rOther.m_nUnused;
+ m_aUnused = rOther.m_aUnused;
+ return *this;
+ }
+
+ /** Comparison.
+ */
+ sal_Bool operator== (const OStoreSuperBlock& rOther) const
+ {
+ return ((m_aGuard == rOther.m_aGuard ) &&
+ (m_aDescr == rOther.m_aDescr ) &&
+ (m_nMarked == rOther.m_nMarked) &&
+ (m_aMarked == rOther.m_aMarked) &&
+ (m_nUnused == rOther.m_nUnused) &&
+ (m_aUnused == rOther.m_aUnused) );
+ }
+
+ /** unused(Count|Head|Insert|Remove|Reset).
+ */
+ sal_uInt32 unusedCount (void) const
+ {
+ return store::ntohl(m_nUnused);
+ }
+ const L& unusedHead (void) 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 (void)
+ {
+ m_nUnused = store::htonl(0);
+ m_aUnused = L(0);
+ }
+
+ /** guard (external representation).
+ */
+ void guard()
+ {
+ sal_uInt32 nCRC32 = 0;
+ nCRC32 = rtl_crc32 (nCRC32, &m_aGuard.m_nMagic, sizeof(sal_uInt32));
+ nCRC32 = rtl_crc32 (nCRC32, &m_aDescr, theSize - sizeof(G));
+ m_aGuard.m_nCRC32 = store::htonl(nCRC32);
+ }
+
+ /** verify (external representation).
+ */
+ storeError verify() const
+ {
+ sal_uInt32 nMagic = store::ntohl(m_aGuard.m_nMagic);
+ if (nMagic != STORE_MAGIC_SUPERBLOCK)
+ return store_E_WrongFormat;
+
+ sal_uInt32 nCRC32 = 0;
+ nCRC32 = rtl_crc32 (nCRC32, &m_aGuard.m_nMagic, sizeof(sal_uInt32));
+ nCRC32 = rtl_crc32 (nCRC32, &m_aDescr, theSize - sizeof(G));
+ if (m_aGuard.m_nCRC32 != store::htonl(nCRC32))
+ return store_E_InvalidChecksum;
+ else
+ return store_E_None;
+ }
+};
+
+/*========================================================================
+ *
+ * OStoreStateBlock.
+ *
+ *======================================================================*/
+struct OStoreStateBlock
+{
+ enum StateBits
+ {
+ STATE_CLEAN = 0,
+ STATE_CLOSE_WAIT = 1,
+ STATE_FLUSH_WAIT = 2
+ };
+
+ /** Representation.
+ */
+ sal_uInt32 m_nState;
+
+ /** theSize.
+ */
+ static const size_t theSize = sizeof(sal_uInt32);
+
+ /** Construction.
+ */
+ OStoreStateBlock()
+ : m_nState (store::htonl(STATE_CLEAN))
+ {}
+
+ /** Operation.
+ */
+ bool closePending (void) const
+ {
+ sal_uInt32 nState = store::ntohl(m_nState);
+ return ((nState & STATE_CLOSE_WAIT) == STATE_CLOSE_WAIT);
+ }
+ void closed (void)
+ {
+ sal_uInt32 nState = store::ntohl(m_nState);
+ nState &= ~STATE_CLOSE_WAIT;
+ m_nState = store::htonl(nState);
+ }
+
+ bool flushPending (void) const
+ {
+ sal_uInt32 nState = store::ntohl(m_nState);
+ return ((nState & STATE_FLUSH_WAIT) == STATE_FLUSH_WAIT);
+ }
+ void flushed (void)
+ {
+ sal_uInt32 nState = store::ntohl(m_nState);
+ nState &= ~STATE_FLUSH_WAIT;
+ m_nState = store::htonl(nState);
+ }
+
+ void modified (void)
+ {
+ sal_uInt32 nState = store::ntohl(m_nState);
+ nState |= (STATE_CLOSE_WAIT | STATE_FLUSH_WAIT);
+ m_nState = store::htonl(nState);
+ }
+ void clean (void)
+ {
+ sal_uInt32 nState = store::ntohl(m_nState);
+ nState &= ~(STATE_CLOSE_WAIT | STATE_FLUSH_WAIT);
+ m_nState = store::htonl(nState);
+ }
+};
+
+/*========================================================================
+ *
+ * OStoreSuperBlockPage interface.
+ *
+ *======================================================================*/
+namespace store
+{
+
+struct OStoreSuperBlockPage
+{
+ typedef OStoreSuperBlock SuperBlock;
+ typedef OStoreStateBlock StateBlock;
+
+ /** Representation.
+ */
+ SuperBlock m_aSuperOne;
+ SuperBlock m_aSuperTwo;
+ StateBlock m_aState;
+
+ /** theSize.
+ */
+ static const size_t theSize = 2 * SuperBlock::theSize + StateBlock::theSize;
+ static const sal_uInt16 thePageSize = theSize;
+ STORE_STATIC_ASSERT(STORE_MINIMUM_PAGESIZE >= thePageSize);
+
+ /** Allocation.
+ */
+ static void * operator new (size_t n) SAL_THROW(())
+ {
+ return rtl_allocateMemory (sal::static_int_cast<sal_Size>(n));
+ }
+ static void operator delete (void * p, size_t) SAL_THROW(())
+ {
+ rtl_freeMemory (p);
+ }
+
+ static void * operator new (size_t, sal_uInt16 nPageSize) SAL_THROW(())
+ {
+ return rtl_allocateZeroMemory (sal::static_int_cast<sal_Size>(nPageSize));
+ }
+ static void operator delete (void * p, sal_uInt16) SAL_THROW(())
+ {
+ rtl_freeMemory (p);
+ }
+
+ /** Construction.
+ */
+ explicit OStoreSuperBlockPage (sal_uInt16 nPageSize = thePageSize)
+ : m_aSuperOne(nPageSize),
+ m_aSuperTwo(nPageSize),
+ m_aState()
+ {}
+
+ /** guard (external representation).
+ */
+ void guard()
+ {
+ m_aSuperOne.guard();
+ m_aSuperTwo.guard();
+ }
+
+ /** save.
+ */
+ storeError save (OStorePageBIOS &rBIOS)
+ {
+ // Guard.
+ guard();
+
+ // Write.
+ return rBIOS.write (0, this, theSize);
+ }
+
+ /** close.
+ */
+ storeError close (
+ OStorePageBIOS &rBIOS);
+
+ /** flush.
+ */
+ storeError flush (
+ OStorePageBIOS &rBIOS);
+
+ /** modified.
+ */
+ storeError modified (
+ OStorePageBIOS &rBIOS);
+
+ /** verify (with repair).
+ */
+ storeError verify (
+ OStorePageBIOS &rBIOS);
+};
+
+} // namespace store
+
+/*========================================================================
+ *
+ * OStoreSuperBlockPage implementation.
+ *
+ *======================================================================*/
+/*
+ * close.
+ */
+storeError OStoreSuperBlockPage::close (OStorePageBIOS &rBIOS)
+{
+ storeError eErrCode = store_E_None;
+ if (m_aState.closePending())
+ {
+ // Mark as modified.
+ m_aState.modified();
+
+ // Check access mode.
+ if (rBIOS.isWriteable())
+ {
+ // Save StateBlock.
+ StateBlock aState (m_aState);
+
+ // Mark as clean.
+ aState.clean();
+
+ // Write behind SuperBlock.
+ sal_uInt32 nAddr = 2 * SuperBlock::theSize;
+ eErrCode = rBIOS.write (nAddr, &aState, StateBlock::theSize);
+ }
+
+ // Mark as clean.
+ m_aState.clean();
+ }
+ return eErrCode;
+}
+
+/*
+ * flush.
+ */
+storeError OStoreSuperBlockPage::flush (OStorePageBIOS &rBIOS)
+{
+ storeError eErrCode = store_E_None;
+ if (m_aState.flushPending())
+ {
+ // Check access mode.
+ if (rBIOS.isWriteable())
+ {
+ // Save StateBlock.
+ StateBlock aState (m_aState);
+
+ // Mark as flushed.
+ aState.flushed();
+
+ // Write behind SuperBlock.
+ sal_uInt32 nAddr = 2 * SuperBlock::theSize;
+ eErrCode = rBIOS.write (nAddr, &aState, StateBlock::theSize);
+ }
+
+ // Mark as flushed.
+ m_aState.flushed();
+ }
+ return eErrCode;
+}
+
+/*
+ * modified.
+ */
+storeError OStoreSuperBlockPage::modified (OStorePageBIOS &rBIOS)
+{
+ storeError eErrCode = store_E_None;
+ if (!m_aState.flushPending())
+ {
+ // Mark as modified.
+ m_aState.modified();
+
+ // Check access mode.
+ if (rBIOS.isWriteable())
+ {
+ // Save StateBlock.
+ StateBlock aState (m_aState);
+
+ // Write behind SuperBlock.
+ sal_uInt32 nAddr = 2 * SuperBlock::theSize;
+ eErrCode = rBIOS.write (nAddr, &aState, StateBlock::theSize);
+ }
+ }
+ return eErrCode;
+}
+
+/*
+ * verify (with repair).
+ */
+storeError OStoreSuperBlockPage::verify (OStorePageBIOS &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.
+ OSL_TRACE("OStoreSuperBlockPage::verify(): double failure.\n");
+ }
+ }
+
+ // Done.
+ return eErrCode;
+}
+
+/*========================================================================
+ *
+ * OStorePageBIOS::Ace implementation.
+ *
+ *======================================================================*/
+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, void * /* arg */)
+{
+ 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;
+}
+
+/*========================================================================
+ *
+ * OStorePageBIOS::AceCache interface.
+ *
+ *======================================================================*/
+namespace store
+{
+
+class OStorePageBIOS::AceCache
+{
+ rtl_cache_type * m_ace_cache;
+
+public:
+ static AceCache & get();
+
+ OStorePageBIOS::Ace *
+ create (sal_uInt32 addr, sal_uInt32 used = 1);
+
+ void
+ destroy (OStorePageBIOS::Ace * ace);
+
+protected:
+ AceCache();
+ ~AceCache();
+};
+
+} // namespace store
+
+/*========================================================================
+ *
+ * OStorePageBIOS::AceCache implementation.
+ *
+ *======================================================================*/
+extern "C" typedef int (SAL_CALL * ace_constructor_type)(void*,void*);
+
+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
+ reinterpret_cast<ace_constructor_type>( OStorePageBIOS::Ace::constructor),
+ 0, // destructor,
+ 0, // reclaim,
+ 0, // userarg,
+ 0, // default source,
+ 0 // flags
+ );
+}
+
+OStorePageBIOS::AceCache::~AceCache()
+{
+ rtl_cache_destroy (m_ace_cache), m_ace_cache = 0;
+}
+
+OStorePageBIOS::Ace *
+OStorePageBIOS::AceCache::create (sal_uInt32 addr, sal_uInt32 used)
+{
+ Ace * ace = static_cast<Ace*>(rtl_cache_alloc (m_ace_cache));
+ if (ace != 0)
+ {
+ // verify invariant state.
+ OSL_ASSERT((ace->m_next == ace) && (ace->m_prev == ace));
+
+ // initialize.
+ ace->m_addr = addr;
+ ace->m_used = used;
+ }
+ return ace;
+}
+
+void
+OStorePageBIOS::AceCache::destroy (OStorePageBIOS::Ace * ace)
+{
+ if (ace != 0)
+ {
+ // 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 implementation.
+ *
+ *======================================================================*/
+/*
+ * OStorePageBIOS.
+ */
+OStorePageBIOS::OStorePageBIOS (void)
+ : m_xLockBytes (NULL),
+ m_pSuper (NULL),
+ m_bModified (sal_False),
+ m_bWriteable (sal_False)
+{
+}
+
+/*
+ * ~OStorePageBIOS.
+ */
+OStorePageBIOS::~OStorePageBIOS (void)
+{
+ OStorePageBIOS::close();
+}
+
+/*
+ * verify (SuperBlock with repair).
+ * Internal: Precond: initialized, exclusive access.
+ */
+storeError OStorePageBIOS::verify (SuperPage *&rpSuper)
+{
+ // Check SuperBlock page allocation.
+ if (rpSuper == 0)
+ {
+ // Allocate.
+ if ((rpSuper = new SuperPage()) == 0)
+ return store_E_OutOfMemory;
+
+ // Load (w/o verification).
+ storeError eErrCode = read (0, rpSuper, SuperPage::theSize);
+ if (eErrCode != store_E_None)
+ {
+ // Cleanup and fail.
+ delete rpSuper, rpSuper = 0;
+ return eErrCode;
+ }
+
+ // Check SuperBlock state.
+ if (rpSuper->m_aState.closePending())
+ OSL_TRACE("OStorePageBIOS::verify(): close pending.\n");
+
+ if (rpSuper->m_aState.flushPending())
+ OSL_TRACE("OStorePageBIOS::verify(): flush pending.\n");
+ }
+
+ // Verify SuperBlock page (with repair).
+ return rpSuper->verify (*this);
+}
+
+/*
+ * repair (SuperBlock).
+ * Internal: Precond: initialized, exclusive access.
+ */
+storeError OStorePageBIOS::repair (SuperPage *&rpSuper)
+{
+ // Acquire Lock.
+ storeError eErrCode = acquireLock (0, SuperPage::theSize);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ // Verify SuperBlock page (with repair).
+ eErrCode = verify (rpSuper);
+ if (eErrCode != store_E_None)
+ {
+ // Failure.
+ releaseLock (0, SuperPage::theSize);
+ return eErrCode;
+ }
+
+ // ReleaseLock.
+ return releaseLock (0, SuperPage::theSize);
+}
+
+/*
+ * create (SuperBlock).
+ * Internal: Precond: initialized, exclusive access.
+ */
+storeError OStorePageBIOS::create (sal_uInt16 nPageSize)
+{
+ // Check (internal) precond.
+ OSL_PRECOND(m_xLockBytes.is(), "store::PageBIOS::create(): contract violation");
+
+ // Check PageSize.
+ if ((STORE_MINIMUM_PAGESIZE > nPageSize) || (nPageSize > STORE_MAXIMUM_PAGESIZE))
+ return store_E_InvalidParameter;
+ nPageSize = ((nPageSize + STORE_MINIMUM_PAGESIZE - 1) & ~(STORE_MINIMUM_PAGESIZE - 1));
+
+ // Acquire Lock.
+ storeError eErrCode = acquireLock (0, nPageSize);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ // Allocate SuperBlock page.
+ delete m_pSuper, m_pSuper = 0;
+ if ((m_pSuper = new(nPageSize) SuperPage(nPageSize)) == 0)
+ {
+ // Cleanup and fail.
+ releaseLock (0, nPageSize);
+ return store_E_OutOfMemory;
+ }
+ m_pSuper->guard();
+
+ // Create initial page (w/ SuperBlock).
+ eErrCode = m_xLockBytes->writeAt (0, m_pSuper, nPageSize);
+ if (eErrCode != store_E_None)
+ {
+ // Cleanup and fail.
+ releaseLock (0, nPageSize);
+ return eErrCode;
+ }
+
+#ifdef STORE_FEATURE_COMMIT
+ // Commit.
+ eErrCode = m_xLockBytes->flush();
+ OSL_POSTCOND(
+ eErrCode == store_E_None,
+ "OStorePageBIOS::create(): flush failed");
+#endif /* STORE_FEATURE_COMMIT */
+
+ // Adjust modified state.
+ m_bModified = (eErrCode != store_E_None);
+
+ // Release Lock and finish.
+ return releaseLock (0, nPageSize);
+}
+
+/*
+ * initialize.
+ * Precond: none.
+ */
+storeError OStorePageBIOS::initialize (
+ ILockBytes * pLockBytes,
+ storeAccessMode eAccessMode,
+ sal_uInt16 & rnPageSize)
+{
+ // Acquire exclusive access.
+ osl::MutexGuard aGuard (m_aMutex);
+
+ // Check arguments.
+ storeError eErrCode = store_E_InvalidParameter;
+ if (!pLockBytes)
+ return eErrCode;
+
+ // Cleanup.
+#if 0 /* OLD */
+ __STORE_DELETEZ (m_pAcl); /* @@@ */
+#endif /* OLD */
+ delete m_pSuper, m_pSuper = 0;
+
+ // Initialize.
+ m_xLockBytes = pLockBytes;
+ m_bModified = sal_False;
+ m_bWriteable = (!(eAccessMode == store_AccessReadOnly));
+
+ // Check access mode.
+ if (eAccessMode == store_AccessReadOnly)
+ {
+ // Verify SuperBlock page.
+ eErrCode = verify (m_pSuper);
+ }
+ else if (eAccessMode != store_AccessCreate)
+ {
+ // Verify (w/ repair) SuperBlock page.
+ eErrCode = repair (m_pSuper);
+ }
+ else
+ {
+ // Truncate to zero length.
+ eErrCode = m_xLockBytes->setSize(0);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+#ifdef STORE_FEATURE_COMMIT
+ // Commit.
+ eErrCode = m_xLockBytes->flush();
+ if (eErrCode != store_E_None)
+ return eErrCode;
+#endif /* STORE_FEATURE_COMMIT */
+
+ // 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 == store_AccessReadOnly)
+ return store_E_NotExists;
+ if (eAccessMode == store_AccessReadWrite)
+ return store_E_NotExists;
+
+ // Create SuperBlock page.
+ eErrCode = create (rnPageSize);
+ }
+ if (eErrCode == store_E_None)
+ {
+ // Obtain modified state.
+ m_bModified = m_pSuper->m_aState.flushPending();
+
+ // 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;
+}
+
+/*
+ * acquireLock.
+ * Low Level: Precond: initialized, exclusive access.
+ */
+storeError OStorePageBIOS::acquireLock (
+ sal_uInt32 nAddr, sal_uInt32 nSize)
+{
+ // Check precond.
+ if (!m_xLockBytes.is())
+ return store_E_InvalidAccess;
+
+ // Acquire Lock.
+ return m_xLockBytes->lockRange (nAddr, nSize);
+}
+
+/*
+ * releaseLock.
+ * Low Level: Precond: initialized, exclusive access.
+ */
+storeError OStorePageBIOS::releaseLock (
+ sal_uInt32 nAddr, sal_uInt32 nSize)
+{
+ // Check precond.
+ if (!m_xLockBytes.is())
+ return store_E_InvalidAccess;
+
+ // Release Lock.
+ return m_xLockBytes->unlockRange (nAddr, nSize);
+}
+
+/*
+ * read.
+ * Low Level: Precond: initialized, exclusive access.
+ */
+storeError OStorePageBIOS::read (
+ sal_uInt32 nAddr, void *pData, sal_uInt32 nSize)
+{
+ // Check precond.
+ if (!m_xLockBytes.is())
+ return store_E_InvalidAccess;
+
+ // Read Page.
+ return m_xLockBytes->readAt (nAddr, pData, nSize);
+}
+
+/*
+ * write.
+ * Low Level: Precond: initialized, writeable, exclusive access.
+ */
+storeError OStorePageBIOS::write (
+ sal_uInt32 nAddr, const void *pData, sal_uInt32 nSize)
+{
+ // Check precond.
+ if (!m_xLockBytes.is())
+ return store_E_InvalidAccess;
+ if (!m_bWriteable)
+ return store_E_AccessViolation;
+
+ // Check modified state.
+ if (!m_bModified)
+ {
+ // Mark as modified.
+ m_bModified = sal_True;
+
+ // Mark SuperBlock modified.
+ storeError eErrCode = m_pSuper->modified (*this);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+ }
+
+ // Write Data.
+ return m_xLockBytes->writeAt (nAddr, pData, nSize);
+}
+
+/*
+ * acquirePage.
+ * Precond: 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 == store_AccessReadOnly)))
+ 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 == store_AccessReadOnly)
+ ace->m_used += 1;
+ else
+ return store_E_AccessViolation;
+ }
+ else
+ {
+ // Insert new entry.
+ Ace * entry = AceCache::get().create (rDescr.m_nAddr, 1);
+ 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;
+}
+
+/*
+ * releasePage.
+ * Precond: initialized.
+ */
+storeError OStorePageBIOS::releasePage (
+ const OStorePageDescriptor& rDescr, storeAccessMode /* eMode */)
+{
+ // 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;
+}
+
+/*
+ * getRefererCount.
+ * Precond: none.
+ */
+sal_uInt32 OStorePageBIOS::getRefererCount (void)
+{
+ // Acquire exclusive access.
+ osl::MutexGuard aGuard (m_aMutex);
+
+ // Obtain total referer count.
+ return m_ace_head.m_used;
+}
+
+/*
+ * allocate.
+ * Precond: initialized, writeable.
+ */
+storeError OStorePageBIOS::allocate (
+ OStorePageObject& rPage, Allocation eAlloc)
+{
+ // 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;
+
+ // Acquire SuperBlock Lock.
+ storeError eErrCode = acquireLock (0, SuperPage::theSize);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ // Load SuperBlock and require good health.
+ eErrCode = verify (m_pSuper);
+ if (eErrCode != store_E_None)
+ {
+ releaseLock (0, SuperPage::theSize);
+ return eErrCode;
+ }
+
+ // Check allocation.
+ if (eAlloc != ALLOCATE_EOF)
+ {
+ // Check FreeList.
+ OStorePageLink aListHead (m_pSuper->m_aSuperTwo.unusedHead());
+ if (aListHead.location())
+ {
+ // Allocate from FreeList.
+ OStorePageData aPageHead (OStorePageData::theSize);
+ aPageHead.location (aListHead.location());
+
+ // Load PageHead.
+ eErrCode = peek (aPageHead);
+ if (eErrCode != store_E_None)
+ {
+ releaseLock (0, SuperPage::theSize);
+ return eErrCode;
+ }
+
+ // Verify FreeList head.
+ OSL_PRECOND(
+ aPageHead.m_aUnused.m_nAddr != STORE_PAGE_NULL,
+ "OStorePageBIOS::allocate(): page not free");
+ if (aPageHead.m_aUnused.location() == STORE_PAGE_NULL)
+ {
+ // Recovery: Reset FreeList.
+ m_pSuper->m_aSuperTwo.unusedReset();
+ m_pSuper->m_aSuperOne = m_pSuper->m_aSuperTwo;
+
+ // Save SuperBlock page.
+ eErrCode = m_pSuper->save (*this);
+
+ // Release SuperBlock Lock.
+ releaseLock (0, SuperPage::theSize);
+
+ // Recovery: Allocate from EOF.
+ if (eErrCode == store_E_None)
+ return allocate (rPage, ALLOCATE_EOF);
+ else
+ return store_E_Unknown;
+ }
+
+ // Pop from FreeList.
+ aListHead = aPageHead.m_aUnused.location();
+ rPage.get()->m_aUnused = STORE_PAGE_NULL;
+
+ // Save page at PageHead location.
+ eErrCode = saveObjectAt_Impl (rPage, aPageHead.location());
+ if (eErrCode != store_E_None)
+ {
+ releaseLock (0, SuperPage::theSize);
+ return eErrCode;
+ }
+
+ // Save SuperBlock page.
+ m_pSuper->m_aSuperTwo.unusedRemove (aListHead);
+ m_pSuper->m_aSuperOne = m_pSuper->m_aSuperTwo;
+
+ eErrCode = m_pSuper->save (*this);
+ OSL_POSTCOND(
+ eErrCode == store_E_None,
+ "OStorePageBIOS::allocate(): SuperBlock save failed");
+
+ // Release SuperBlock Lock and finish.
+ return releaseLock (0, SuperPage::theSize);
+ }
+ }
+
+ // Allocate from logical EOF. Determine physical EOF.
+ sal_uInt32 nPhysLen = STORE_PAGE_NULL;
+ eErrCode = m_xLockBytes->getSize (nPhysLen);
+ if (eErrCode != store_E_None)
+ {
+ releaseLock (0, SuperPage::theSize);
+ return eErrCode;
+ }
+
+ // Obtain logical EOF.
+ OStorePageDescriptor aDescr (m_pSuper->m_aSuperTwo.m_aDescr);
+ sal_uInt32 nLogLen = store::ntohl(aDescr.m_nAddr);
+ if (nLogLen == 0)
+ nLogLen = nPhysLen; /* backward compatibility */
+
+ if (!(nLogLen < nPhysLen))
+ {
+ // Check modified state.
+ if (!m_bModified)
+ {
+ // Mark modified.
+ m_bModified = sal_True;
+
+ // Mark SuperBlock modified.
+ eErrCode = m_pSuper->modified (*this);
+ if (eErrCode != store_E_None)
+ {
+ releaseLock (0, SuperPage::theSize);
+ return eErrCode;
+ }
+ }
+
+ // Resize.
+ sal_uInt32 nAlign = SAL_MIN (nPhysLen, STORE_MAXIMUM_PAGESIZE);
+ nPhysLen = ((nPhysLen + nAlign) / nAlign) * nAlign;
+
+ eErrCode = m_xLockBytes->setSize (nPhysLen);
+ if (eErrCode != store_E_None)
+ {
+ releaseLock (0, SuperPage::theSize);
+ return eErrCode;
+ }
+ }
+
+ // Save page at logical EOF.
+ eErrCode = saveObjectAt_Impl (rPage, nLogLen);
+ if (eErrCode != store_E_None)
+ {
+ releaseLock (0, SuperPage::theSize);
+ return eErrCode;
+ }
+
+ // Save SuperBlock page.
+ nLogLen += store::ntohs(aDescr.m_nSize);
+ aDescr.m_nAddr = store::htonl(nLogLen);
+
+ m_pSuper->m_aSuperTwo.m_aDescr = aDescr;
+ m_pSuper->m_aSuperOne = m_pSuper->m_aSuperTwo;
+
+ eErrCode = m_pSuper->save (*this);
+ OSL_POSTCOND(
+ eErrCode == store_E_None,
+ "OStorePageBIOS::allocate(): SuperBlock save failed");
+
+ // Release SuperBlock Lock and finish.
+ return releaseLock (0, SuperPage::theSize);
+}
+
+/*
+ * free.
+ * Precond: initialized, writeable.
+ */
+storeError OStorePageBIOS::free (OStorePageData & /* rData */, 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;
+
+ // Acquire SuperBlock Lock.
+ storeError eErrCode = acquireLock (0, SuperPage::theSize);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ // Load SuperBlock and require good health.
+ eErrCode = verify (m_pSuper);
+ if (eErrCode != store_E_None)
+ {
+ releaseLock (0, SuperPage::theSize);
+ return eErrCode;
+ }
+
+ // Load PageHead.
+ OStorePageData aPageHead(OStorePageData::theSize);
+ aPageHead.location (nAddr);
+
+ eErrCode = peek (aPageHead);
+ if (eErrCode != store_E_None)
+ {
+ releaseLock (0, SuperPage::theSize);
+ return eErrCode;
+ }
+
+ // Invalidate cache.
+ (void) m_xCache->removePageAt (nAddr);
+
+ // Push onto FreeList.
+ OStorePageLink aListHead (m_pSuper->m_aSuperTwo.unusedHead());
+
+ aPageHead.m_aUnused.m_nAddr = aListHead.m_nAddr;
+ aListHead.m_nAddr = aPageHead.m_aDescr.m_nAddr;
+
+ // Save PageHead.
+ eErrCode = poke (aPageHead);
+ if (eErrCode != store_E_None)
+ {
+ releaseLock (0, SuperPage::theSize);
+ return eErrCode;
+ }
+
+ // Save SuperBlock page.
+ m_pSuper->m_aSuperTwo.unusedInsert (aListHead);
+ m_pSuper->m_aSuperOne = m_pSuper->m_aSuperTwo;
+
+ eErrCode = m_pSuper->save (*this);
+ OSL_POSTCOND(
+ eErrCode == store_E_None,
+ "OStorePageBIOS::free(): SuperBlock save failed");
+
+ // Release SuperBlock Lock and finish.
+ return releaseLock (0, SuperPage::theSize);
+}
+
+/*
+ * loadObjectAt.
+ * Precond: 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);
+}
+
+/*
+ * loadObjectAt_Impl.
+ * Internal: Precond: initialized, readable, exclusive access.
+ */
+storeError OStorePageBIOS::loadObjectAt_Impl (OStorePageObject & rPage, sal_uInt32 nAddr)
+{
+ 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);
+}
+
+/*
+ * saveObjectAt.
+ * Precond: 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);
+}
+
+/*
+ * saveObjectAt_Impl.
+ * Internal: Precond: initialized, writeable, exclusive access.
+ */
+storeError OStorePageBIOS::saveObjectAt_Impl (OStorePageObject & rPage, sal_uInt32 nAddr)
+{
+ // 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);
+}
+
+/*
+ * close.
+ * Precond: none.
+ */
+storeError OStorePageBIOS::close (void)
+{
+ // Acquire exclusive access.
+ osl::MutexGuard aGuard (m_aMutex);
+
+ // Check referer count.
+ if (m_ace_head.m_used > 0)
+ {
+ // Report remaining referer count.
+ OSL_TRACE("store::PageBIOS::close(): referer count: %d\n", m_ace_head.m_used);
+#if 1 /* NEW */
+ 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::close(): logic error");
+#endif /* NEW */
+ }
+
+ // Check SuperBlock page.
+ storeError eErrCode = store_E_None;
+ if (m_pSuper)
+ {
+ // Release SuperBlock page.
+ eErrCode = m_pSuper->close (*this);
+ delete m_pSuper, m_pSuper = 0;
+ }
+
+ // Release PageCache.
+ m_xCache.clear();
+
+ // Check LockBytes.
+ if (m_xLockBytes.is())
+ {
+#ifdef STORE_FEATURE_COMMIT
+ // Commit.
+ storeError result = m_xLockBytes->flush();
+ if (eErrCode == store_E_None)
+ {
+ // Previous result(s) okay. Propagate next result.
+ eErrCode = result;
+ }
+#endif /* STORE_FEATURE_COMMIT */
+
+ // Release LockBytes.
+ m_xLockBytes.clear();
+ }
+
+ // Done.
+ return eErrCode;
+}
+
+/*
+ * flush.
+ * Precond: initialized.
+ */
+storeError OStorePageBIOS::flush (void)
+{
+ // Acquire exclusive access.
+ osl::MutexGuard aGuard (m_aMutex);
+
+ // Check precond.
+ if (!m_xLockBytes.is())
+ return store_E_InvalidAccess;
+
+ // Check mode and state.
+ storeError eErrCode = store_E_None;
+ if (!(m_bWriteable && m_bModified))
+ return eErrCode;
+
+ // Flush SuperBlock page.
+ eErrCode = m_pSuper->flush (*this);
+
+ // Flush LockBytes.
+ storeError result = m_xLockBytes->flush();
+ if (eErrCode == store_E_None)
+ {
+ // Previous result(s) okay. Propagate next result.
+ eErrCode = result;
+ }
+
+ // Adjust modified state.
+ m_bModified = (eErrCode != store_E_None);
+
+ // Done.
+ return eErrCode;
+}
+
+/*
+ * size.
+ * Precond: initialized.
+ */
+storeError OStorePageBIOS::size (sal_uInt32 &rnSize)
+{
+ // Acquire exclusive access.
+ osl::MutexGuard aGuard (m_aMutex);
+
+ // Initialize [out] param.
+ rnSize = 0;
+
+ // Check precond.
+ if (!m_xLockBytes.is())
+ return store_E_InvalidAccess;
+
+ // Obtain LockBytes size.
+ return m_xLockBytes->getSize (rnSize);
+}
+
+/*
+ * scanBegin.
+ * Precond: initialized.
+ */
+storeError OStorePageBIOS::scanBegin (
+ ScanContext &rCtx, sal_uInt32 nMagic)
+{
+ // Acquire exclusive access.
+ osl::MutexGuard aGuard (m_aMutex);
+
+ // Initialize [out] param.
+ rCtx.m_aDescr = OStorePageDescriptor(0, 0, 0);
+ rCtx.m_nSize = 0;
+ rCtx.m_nMagic = nMagic;
+
+ // Check precond.
+ if (!m_xLockBytes.is())
+ return store_E_InvalidAccess;
+
+ // Check SuperBlock page.
+ storeError eErrCode = verify (m_pSuper);
+ if (eErrCode != store_E_None)
+ {
+ // Damaged. Determine page size (NYI).
+ OSL_TRACE ("OStorePageBIOS::scanBegin(): damaged.\n");
+ return eErrCode;
+ }
+
+ // Setup Context descriptor.
+ rCtx.m_aDescr = m_pSuper->m_aSuperOne.m_aDescr;
+ rCtx.m_aDescr.m_nAddr = rCtx.m_aDescr.m_nSize; // @@@ ntoh @@@
+
+ // Setup Context size.
+ eErrCode = size (rCtx.m_nSize);
+ if (eErrCode != store_E_None)
+ rCtx.m_nSize = ((sal_uInt32)(~0));
+
+ // Done.
+ return store_E_None;
+}
+
+/*
+ * scanNext.
+ * Precond: initialized.
+ */
+storeError OStorePageBIOS::scanNext (
+ ScanContext &rCtx, OStorePageObject &rPage)
+{
+ // Acquire exclusive access.
+ osl::MutexGuard aGuard (m_aMutex);
+
+ // Check precond.
+ if (!m_xLockBytes.is())
+ return store_E_InvalidAccess;
+
+ // Setup PageHead.
+ OStorePageData aPageHead (OStorePageData::theSize);
+
+ // Check context.
+ while (rCtx.isValid())
+ {
+ // Assign next location.
+ aPageHead.location (rCtx.m_aDescr.m_nAddr);
+ rCtx.m_aDescr.m_nAddr += rCtx.m_aDescr.m_nSize;
+
+ // Load PageHead.
+ storeError eErrCode = peek (aPageHead);
+ if (eErrCode != store_E_None)
+ continue;
+
+ // Check PageHead Magic number.
+ if (aPageHead.m_aGuard.m_nMagic != rCtx.m_nMagic)
+ continue;
+
+ // Check PageHead Unused link.
+ if (aPageHead.m_aUnused.m_nAddr != STORE_PAGE_NULL)
+ continue;
+
+ // Load page.
+ eErrCode = loadObjectAt_Impl (rPage, aPageHead.location());
+ if (eErrCode != store_E_None)
+ continue;
+
+ // Deliver page.
+ return store_E_None;
+ }
+
+ // Done.
+ return store_E_CantSeek;
+}
+
+/*
+ * peek (PageHead).
+ * Internal: Precond: initialized, readable, exclusive access.
+ */
+storeError OStorePageBIOS::peek (OStorePageData &rData)
+{
+ // Read PageHead.
+ storeError eErrCode = read (rData.location(), &rData, OStorePageData::theSize);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ // Verify PageHead.
+ return rData.verify();
+}
+
+/*
+ * poke (PageHead).
+ * Internal: Precond: initialized, writeable, exclusive access.
+ */
+storeError OStorePageBIOS::poke (OStorePageData &rData)
+{
+ // Guard PageHead.
+ rData.guard();
+
+ // Write PageHead.
+ return write (rData.location(), &rData, OStorePageData::theSize);
+}
diff --git a/store/source/storbios.hxx b/store/source/storbios.hxx
new file mode 100644
index 000000000000..d9a0f982bd3c
--- /dev/null
+++ b/store/source/storbios.hxx
@@ -0,0 +1,302 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: storbios.hxx,v $
+ *
+ * $Revision: 1.1.2.3 $
+ *
+ * last change: $Author: mhu $ $Date: 2008/10/31 18:28:18 $
+ *
+ * The Contents of this file are made available subject to
+ * the terms of GNU Lesser General Public License Version 2.1.
+ *
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2005 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
+ *
+ ************************************************************************/
+
+#ifndef _STORE_STORBIOS_HXX_
+#define _STORE_STORBIOS_HXX_ "$Revision: 1.1.2.3 $"
+
+#include "sal/types.h"
+#include "rtl/ref.hxx"
+#include "osl/mutex.hxx"
+
+#include "store/types.h"
+#include "object.hxx"
+#include "lockbyte.hxx"
+#include "storbase.hxx"
+#include "storcach.hxx"
+
+/*========================================================================
+ *
+ * OStorePageBIOS.
+ *
+ *======================================================================*/
+namespace store
+{
+
+struct OStoreSuperBlockPage;
+
+class OStorePageBIOS : public store::OStoreObject
+{
+public:
+ /** Construction.
+ */
+ OStorePageBIOS (void);
+
+ /** Conversion into Mutex&
+ */
+ inline operator osl::Mutex& (void) const;
+
+ /** Initialization.
+ * @param pLockBytes [in]
+ * @param eAccessMode [in]
+ * @param rnPageSize [inout]
+ * @return store_E_None upon success
+ */
+ virtual storeError initialize (
+ ILockBytes * pLockBytes,
+ storeAccessMode eAccessMode,
+ sal_uInt16 & rnPageSize);
+
+ rtl::Reference< PageData::Allocator > & allocator()
+ {
+ return m_xAllocator;
+ }
+
+ /** acquireLock.
+ */
+ storeError acquireLock (
+ sal_uInt32 nAddr, sal_uInt32 nSize);
+
+ /** releaseLock.
+ */
+ storeError releaseLock (
+ sal_uInt32 nAddr, sal_uInt32 nSize);
+
+ /** read.
+ */
+ storeError read (
+ sal_uInt32 nAddr, void *pData, sal_uInt32 nSize);
+
+ /** write.
+ */
+ storeError write (
+ sal_uInt32 nAddr, const void *pData, sal_uInt32 nSize);
+
+ /** isModified.
+ */
+ inline bool isModified (void) const;
+
+ /** isWriteable.
+ */
+ inline bool isWriteable (void) const;
+
+ /** isValid.
+ */
+ inline sal_Bool isValid (void) const;
+
+ /** Page Access.
+ */
+ storeError acquirePage (
+ const OStorePageDescriptor& rDescr, storeAccessMode eMode);
+
+ storeError releasePage (
+ const OStorePageDescriptor& rDescr, storeAccessMode eMode);
+
+ sal_uInt32 getRefererCount (void);
+
+ /** Page Allocation.
+ */
+ enum Allocation
+ {
+ ALLOCATE_FIRST = 0,
+ ALLOCATE_BEST = 1,
+ ALLOCATE_EOF = 2
+ };
+
+ storeError allocate (
+ OStorePageObject& rPage, Allocation eAllocation = ALLOCATE_FIRST);
+
+ storeError free (
+ OStorePageData & /* rData */, sal_uInt32 nAddr);
+
+ /** Page I/O.
+ */
+ storeError loadObjectAt (
+ OStorePageObject& rPage, sal_uInt32 nAddr);
+
+ storeError saveObjectAt (
+ OStorePageObject& rPage, sal_uInt32 nAddr);
+
+ /** close.
+ * @return store_E_None upon success.
+ */
+ storeError close (void);
+
+ /** flush.
+ * @return store_E_None upon success.
+ */
+ storeError flush (void);
+
+ /** size.
+ */
+ storeError size (sal_uInt32 &rnSize);
+
+ /** ScanContext.
+ */
+ struct ScanContext
+ {
+ /** Representation.
+ */
+ OStorePageDescriptor m_aDescr;
+ sal_uInt32 m_nSize;
+ sal_uInt32 m_nMagic;
+
+ /** Construction.
+ */
+ inline ScanContext (void);
+
+ /** isValid.
+ */
+ inline bool isValid (void) const;
+ };
+
+ /** scanBegin.
+ */
+ storeError scanBegin (
+ ScanContext &rCtx,
+ sal_uInt32 nMagic = 0);
+
+ /** scanNext.
+ */
+ storeError scanNext (
+ ScanContext &rCtx,
+ OStorePageObject &rPage);
+
+protected:
+ /** Destruction (OReference).
+ */
+ virtual ~OStorePageBIOS (void);
+
+private:
+ /** Representation.
+ */
+ rtl::Reference<ILockBytes> m_xLockBytes;
+ osl::Mutex m_aMutex;
+
+ typedef OStoreSuperBlockPage SuperPage;
+ SuperPage *m_pSuper;
+
+ bool m_bModified;
+ bool m_bWriteable;
+
+ rtl::Reference< PageData::Allocator > m_xAllocator;
+ rtl::Reference< PageCache > m_xCache;
+
+ /** Page Access (control).
+ */
+public:
+ struct Ace
+ {
+ Ace * m_next;
+ Ace * m_prev;
+
+ sal_uInt32 m_addr;
+ sal_uInt32 m_used;
+
+ Ace();
+ ~Ace();
+
+ static int SAL_CALL constructor (void * obj, void * arg);
+
+ static Ace * find (Ace * head, sal_uInt32 addr);
+ static void insert (Ace * head, Ace * entry);
+ };
+
+private:
+ Ace m_ace_head;
+
+ class AceCache;
+
+ /** create (SuperBlock).
+ */
+ storeError create (sal_uInt16 nPageSize);
+
+ /** SuperBlock verification and repair.
+ */
+ storeError verify (SuperPage *&rpSuper);
+ storeError repair (SuperPage *&rpSuper);
+
+ /** Page Maintenance.
+ */
+ storeError peek (
+ OStorePageData &rData);
+ storeError poke (
+ OStorePageData &rData);
+
+ storeError loadObjectAt_Impl (
+ OStorePageObject & rPage, sal_uInt32 nAddr);
+ storeError saveObjectAt_Impl (
+ OStorePageObject & rPage, sal_uInt32 nAddr);
+
+ /** Not implemented.
+ */
+ OStorePageBIOS (const OStorePageBIOS&);
+ OStorePageBIOS& operator= (const OStorePageBIOS&);
+};
+
+inline OStorePageBIOS::operator osl::Mutex& (void) const
+{
+ return (osl::Mutex&)m_aMutex;
+}
+inline bool OStorePageBIOS::isModified (void) const
+{
+ return m_bModified;
+}
+inline bool OStorePageBIOS::isWriteable (void) const
+{
+ return m_bWriteable;
+}
+inline sal_Bool OStorePageBIOS::isValid (void) const
+{
+ return m_xLockBytes.is();
+}
+
+inline OStorePageBIOS::ScanContext::ScanContext (void)
+ : m_aDescr (0, 0, 0), m_nSize (0), m_nMagic (0)
+{
+}
+inline bool OStorePageBIOS::ScanContext::isValid (void) const
+{
+ return (m_aDescr.m_nAddr < m_nSize);
+}
+
+/*========================================================================
+ *
+ * The End.
+ *
+ *======================================================================*/
+
+} // namespace store
+
+#endif /* !_STORE_STORBIOS_HXX_ */
diff --git a/store/source/storcach.cxx b/store/source/storcach.cxx
new file mode 100644
index 000000000000..6306784592e0
--- /dev/null
+++ b/store/source/storcach.cxx
@@ -0,0 +1,564 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: storcach.cxx,v $
+ * $Revision: 1.8 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_store.hxx"
+
+#include "storcach.hxx"
+
+#include "sal/types.h"
+#include "rtl/alloc.h"
+#include "osl/diagnose.h"
+
+#include "store/types.h"
+#include "object.hxx"
+#include "storbase.hxx"
+
+#ifndef INCLUDED_STDDEF_H
+#include <stddef.h>
+#define INCLUDED_STDDEF_H
+#endif
+
+using namespace store;
+
+/*========================================================================
+ *
+ * PageCache (non-virtual interface) implementation.
+ *
+ *======================================================================*/
+
+storeError PageCache::lookupPageAt (PageHolder & rxPage, sal_uInt32 nOffset)
+{
+ OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::PageCache::lookupPageAt(): invalid Offset");
+ if (nOffset == STORE_PAGE_NULL)
+ return store_E_CantSeek;
+
+ return lookupPageAt_Impl (rxPage, nOffset);
+}
+
+storeError PageCache::insertPageAt (PageHolder const & rxPage, sal_uInt32 nOffset)
+{
+ // [SECURITY:ValInput]
+ PageData const * pagedata = rxPage.get();
+ OSL_PRECOND(!(pagedata == 0), "store::PageCache::insertPageAt(): invalid Page");
+ if (pagedata == 0)
+ return store_E_InvalidParameter;
+
+ sal_uInt32 const offset = pagedata->location();
+ OSL_PRECOND(!(nOffset != offset), "store::PageCache::insertPageAt(): inconsistent Offset");
+ if (nOffset != offset)
+ return store_E_InvalidParameter;
+
+ OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::PageCache::insertPageAt(): invalid Offset");
+ if (nOffset == STORE_PAGE_NULL)
+ return store_E_CantSeek;
+
+ return insertPageAt_Impl (rxPage, nOffset);
+}
+
+storeError PageCache::updatePageAt (PageHolder const & rxPage, sal_uInt32 nOffset)
+{
+ // [SECURITY:ValInput]
+ PageData const * pagedata = rxPage.get();
+ OSL_PRECOND(!(pagedata == 0), "store::PageCache::updatePageAt(): invalid Page");
+ if (pagedata == 0)
+ return store_E_InvalidParameter;
+
+ sal_uInt32 const offset = pagedata->location();
+ OSL_PRECOND(!(nOffset != offset), "store::PageCache::updatePageAt(): inconsistent Offset");
+ if (nOffset != offset)
+ return store_E_InvalidParameter;
+
+ OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::PageCache::updatePageAt(): invalid Offset");
+ if (nOffset == STORE_PAGE_NULL)
+ return store_E_CantSeek;
+
+ return updatePageAt_Impl (rxPage, nOffset);
+}
+
+storeError PageCache::removePageAt (sal_uInt32 nOffset)
+{
+ OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::PageCache::removePageAt(): invalid Offset");
+ if (nOffset == STORE_PAGE_NULL)
+ return store_E_CantSeek;
+
+ return removePageAt_Impl (nOffset);
+}
+
+/*========================================================================
+ *
+ * Entry.
+ *
+ *======================================================================*/
+namespace
+{
+
+struct Entry
+{
+ /** Representation.
+ */
+ PageHolder m_xPage;
+ sal_uInt32 m_nOffset;
+ Entry * m_pNext;
+
+ /** Allocation.
+ */
+ static void * operator new (size_t, void * p) { return p; }
+ static void operator delete (void *, void *) {}
+
+ /** Construction.
+ */
+ explicit Entry (PageHolder const & rxPage = PageHolder(), sal_uInt32 nOffset = STORE_PAGE_NULL)
+ : m_xPage(rxPage), m_nOffset(nOffset), m_pNext(0)
+ {}
+
+ /** Destruction.
+ */
+ ~Entry() {}
+};
+
+} // namespace
+
+/*========================================================================
+ *
+ * EntryCache interface.
+ *
+ *======================================================================*/
+namespace
+{
+
+class EntryCache
+{
+ rtl_cache_type * m_entry_cache;
+
+public:
+ static EntryCache & get();
+
+ Entry * create (PageHolder const & rxPage, sal_uInt32 nOffset);
+
+ void destroy (Entry * entry);
+
+protected:
+ EntryCache();
+ ~EntryCache();
+};
+
+} // namespace
+
+/*========================================================================
+ *
+ * EntryCache implementation.
+ *
+ *======================================================================*/
+
+EntryCache & EntryCache::get()
+{
+ static EntryCache g_entry_cache;
+ return g_entry_cache;
+}
+
+EntryCache::EntryCache()
+{
+ m_entry_cache = rtl_cache_create (
+ "store_cache_entry_cache",
+ sizeof(Entry),
+ 0, // objalign
+ 0, // constructor
+ 0, // destructor
+ 0, // reclaim
+ 0, // userarg
+ 0, // default source
+ 0 // flags
+ );
+}
+
+EntryCache::~EntryCache()
+{
+ rtl_cache_destroy (m_entry_cache), m_entry_cache = 0;
+}
+
+Entry * EntryCache::create (PageHolder const & rxPage, sal_uInt32 nOffset)
+{
+ void * pAddr = rtl_cache_alloc (m_entry_cache);
+ if (pAddr != 0)
+ {
+ // construct.
+ return new(pAddr) Entry (rxPage, nOffset);
+ }
+ return 0;
+}
+
+void EntryCache::destroy (Entry * entry)
+{
+ if (entry != 0)
+ {
+ // destruct.
+ entry->~Entry();
+
+ // return to cache.
+ rtl_cache_free (m_entry_cache, entry);
+ }
+}
+
+/*========================================================================
+ *
+ * highbit():= log2() + 1 (complexity O(1))
+ *
+ *======================================================================*/
+static int highbit(sal_Size n)
+{
+ register int k = 1;
+
+ if (n == 0)
+ return (0);
+#if SAL_TYPES_SIZEOFLONG == 8
+ if (n & 0xffffffff00000000ul)
+ k |= 32, n >>= 32;
+#endif
+ if (n & 0xffff0000)
+ k |= 16, n >>= 16;
+ if (n & 0xff00)
+ k |= 8, n >>= 8;
+ if (n & 0xf0)
+ k |= 4, n >>= 4;
+ if (n & 0x0c)
+ k |= 2, n >>= 2;
+ if (n & 0x02)
+ k++;
+
+ return (k);
+}
+
+/*========================================================================
+ *
+ * PageCache_Impl implementation.
+ *
+ *======================================================================*/
+namespace store
+{
+
+class PageCache_Impl :
+ public store::OStoreObject,
+ public store::PageCache
+{
+ /** Representation.
+ */
+ static size_t const theTableSize = 32;
+ STORE_STATIC_ASSERT(STORE_IMPL_ISP2(theTableSize));
+
+ Entry ** m_hash_table;
+ Entry * m_hash_table_0[theTableSize];
+ size_t m_hash_size;
+ size_t m_hash_shift;
+ size_t const m_page_shift;
+
+ size_t m_hash_entries; // total number of entries in table.
+ size_t m_nHit;
+ size_t m_nMissed;
+
+ inline int hash_Impl(sal_uInt32 a, size_t s, size_t q, size_t m)
+ {
+ return ((((a) + ((a) >> (s)) + ((a) >> ((s) << 1))) >> (q)) & (m));
+ }
+ inline int hash_index_Impl (sal_uInt32 nOffset)
+ {
+ return hash_Impl(nOffset, m_hash_shift, m_page_shift, m_hash_size - 1);
+ }
+
+ Entry * lookup_Impl (Entry * entry, sal_uInt32 nOffset);
+ void rescale_Impl (sal_Size new_size);
+
+ /** PageCache Implementation.
+ */
+ virtual storeError lookupPageAt_Impl (
+ PageHolder & rxPage,
+ sal_uInt32 nOffset);
+
+ virtual storeError insertPageAt_Impl (
+ PageHolder const & rxPage,
+ sal_uInt32 nOffset);
+
+ virtual storeError updatePageAt_Impl (
+ PageHolder const & rxPage,
+ sal_uInt32 nOffset);
+
+ virtual storeError removePageAt_Impl (
+ sal_uInt32 nOffset);
+
+ /** Not implemented.
+ */
+ PageCache_Impl (PageCache_Impl const &);
+ PageCache_Impl & operator= (PageCache_Impl const &);
+
+public:
+ /** Construction.
+ */
+ explicit PageCache_Impl (sal_uInt16 nPageSize);
+
+ /** Delegate multiple inherited IReference.
+ */
+ virtual oslInterlockedCount SAL_CALL acquire();
+ virtual oslInterlockedCount SAL_CALL release();
+
+protected:
+ /** Destruction.
+ */
+ virtual ~PageCache_Impl (void);
+};
+
+} // namespace store
+
+PageCache_Impl::PageCache_Impl (sal_uInt16 nPageSize)
+ : m_hash_table (m_hash_table_0),
+ m_hash_size (theTableSize),
+ m_hash_shift (highbit(m_hash_size) - 1),
+ m_page_shift (highbit(nPageSize) - 1),
+ m_hash_entries (0),
+ m_nHit (0),
+ m_nMissed (0)
+{
+ static size_t const theSize = sizeof(m_hash_table_0) / sizeof(m_hash_table_0[0]);
+ STORE_STATIC_ASSERT(theSize == theTableSize);
+ memset(m_hash_table_0, 0, sizeof(m_hash_table_0));
+}
+
+PageCache_Impl::~PageCache_Impl()
+{
+ double s_x = 0.0, s_xx = 0.0;
+ sal_Size i, n = m_hash_size;
+ for (i = 0; i < n; i++)
+ {
+ int x = 0;
+ Entry * entry = m_hash_table[i];
+ while (entry != 0)
+ {
+ m_hash_table[i] = entry->m_pNext, entry->m_pNext = 0;
+ EntryCache::get().destroy (entry);
+ entry = m_hash_table[i];
+ x += 1;
+ }
+ s_x += double(x);
+ s_xx += double(x) * double(x);
+ }
+ double ave = s_x / double(n);
+ OSL_TRACE("ave hash chain length: %g", ave);
+ (void) ave;
+
+ if (m_hash_table != m_hash_table_0)
+ {
+ rtl_freeMemory (m_hash_table);
+ m_hash_table = m_hash_table_0;
+ m_hash_size = theTableSize;
+ m_hash_shift = highbit(m_hash_size) - 1;
+ }
+ OSL_TRACE("Hits: %u, Misses: %u", m_nHit, m_nMissed);
+}
+
+oslInterlockedCount PageCache_Impl::acquire()
+{
+ return OStoreObject::acquire();
+}
+
+oslInterlockedCount PageCache_Impl::release()
+{
+ return OStoreObject::release();
+}
+
+void PageCache_Impl::rescale_Impl (sal_Size new_size)
+{
+ sal_Size new_bytes = new_size * sizeof(Entry*);
+ Entry ** new_table = (Entry**)(rtl_allocateMemory(new_bytes));
+
+ if (new_table != 0)
+ {
+ Entry ** old_table = m_hash_table;
+ sal_Size old_size = m_hash_size;
+
+ OSL_TRACE("ave chain length: %u, total entries: %u [old_size: %u, new_size: %u]",
+ m_hash_entries >> m_hash_shift, m_hash_entries, old_size, new_size);
+
+ memset (new_table, 0, new_bytes);
+
+ m_hash_table = new_table;
+ m_hash_size = new_size;
+ m_hash_shift = highbit(m_hash_size) - 1;
+
+ sal_Size i;
+ for (i = 0; i < old_size; i++)
+ {
+ Entry * curr = old_table[i];
+ while (curr != 0)
+ {
+ Entry * next = curr->m_pNext;
+ int index = hash_index_Impl(curr->m_nOffset);
+ curr->m_pNext = m_hash_table[index], m_hash_table[index] = curr;
+ curr = next;
+ }
+ old_table[i] = 0;
+ }
+ if (old_table != m_hash_table_0)
+ {
+ //
+ rtl_freeMemory (old_table);
+ }
+ }
+}
+
+Entry * PageCache_Impl::lookup_Impl (Entry * entry, sal_uInt32 nOffset)
+{
+ register int lookups = 0;
+ while (entry != 0)
+ {
+ if (entry->m_nOffset == nOffset)
+ break;
+
+ lookups += 1;
+ entry = entry->m_pNext;
+ }
+ if (lookups > 2)
+ {
+ sal_Size new_size = m_hash_size, ave = m_hash_entries >> m_hash_shift;
+ for (; ave > 4; new_size *= 2, ave /= 2)
+ continue;
+ if (new_size != m_hash_size)
+ rescale_Impl (new_size);
+ }
+ return entry;
+}
+
+storeError PageCache_Impl::lookupPageAt_Impl (
+ PageHolder & rxPage,
+ sal_uInt32 nOffset)
+{
+ int index = hash_index_Impl(nOffset);
+ Entry const * entry = lookup_Impl (m_hash_table[index], nOffset);
+ if (entry != 0)
+ {
+ // Existing entry.
+ rxPage = entry->m_xPage;
+
+ // Update stats and leave.
+ m_nHit += 1;
+ return store_E_None;
+ }
+
+ // Cache miss. Update stats and leave.
+ m_nMissed += 1;
+ return store_E_NotExists;
+}
+
+storeError PageCache_Impl::insertPageAt_Impl (
+ PageHolder const & rxPage,
+ sal_uInt32 nOffset)
+{
+ Entry * entry = EntryCache::get().create (rxPage, nOffset);
+ if (entry != 0)
+ {
+ // Insert new entry.
+ int index = hash_index_Impl(nOffset);
+ entry->m_pNext = m_hash_table[index], m_hash_table[index] = entry;
+
+ // Update stats and leave.
+ m_hash_entries += 1;
+ return store_E_None;
+ }
+ return store_E_OutOfMemory;
+}
+
+storeError PageCache_Impl::updatePageAt_Impl (
+ PageHolder const & rxPage,
+ sal_uInt32 nOffset)
+{
+ int index = hash_index_Impl(nOffset);
+ Entry * entry = lookup_Impl (m_hash_table[index], nOffset);
+ if (entry != 0)
+ {
+ // Update existing entry.
+ entry->m_xPage = rxPage;
+
+ // Update stats and leave. // m_nUpdHit += 1;
+ return store_E_None;
+ }
+ return insertPageAt_Impl (rxPage, nOffset);
+}
+
+storeError PageCache_Impl::removePageAt_Impl (
+ sal_uInt32 nOffset)
+{
+ Entry ** ppEntry = &(m_hash_table[hash_index_Impl(nOffset)]);
+ while (*ppEntry != 0)
+ {
+ if ((*ppEntry)->m_nOffset == nOffset)
+ {
+ // Existing entry.
+ Entry * entry = (*ppEntry);
+
+ // Dequeue and destroy entry.
+ (*ppEntry) = entry->m_pNext, entry->m_pNext = 0;
+ EntryCache::get().destroy (entry);
+
+ // Update stats and leave.
+ m_hash_entries -= 1;
+ return store_E_None;
+ }
+ ppEntry = &((*ppEntry)->m_pNext);
+ }
+ return store_E_NotExists;
+}
+
+/*========================================================================
+ *
+ * Old OStorePageCache implementation.
+ *
+ * (two-way association (sorted address array, LRU chain)).
+ * (external OStorePageData representation).
+ *
+ *======================================================================*/
+
+/*========================================================================
+ *
+ * PageCache factory implementation.
+ *
+ *======================================================================*/
+namespace store {
+
+storeError
+PageCache_createInstance (
+ rtl::Reference< store::PageCache > & rxCache,
+ sal_uInt16 nPageSize)
+{
+ rxCache = new PageCache_Impl (nPageSize);
+ if (!rxCache.is())
+ return store_E_OutOfMemory;
+
+ return store_E_None;
+}
+
+} // namespace store
diff --git a/store/source/storcach.hxx b/store/source/storcach.hxx
new file mode 100644
index 000000000000..eb98bb786df5
--- /dev/null
+++ b/store/source/storcach.hxx
@@ -0,0 +1,115 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: storcach.hxx,v $
+ * $Revision: 1.6 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _STORE_STORCACH_HXX
+#define _STORE_STORCACH_HXX "$Revision: 1.6.8.2 $"
+
+#include "sal/types.h"
+#include "rtl/ref.hxx"
+
+#include "store/types.h"
+#include "storbase.hxx"
+
+namespace store
+{
+
+/*========================================================================
+ *
+ * PageCache interface.
+ *
+ *======================================================================*/
+
+class PageCache : public rtl::IReference
+{
+public:
+ /** load.
+ */
+ storeError lookupPageAt (
+ PageHolder & rxPage,
+ sal_uInt32 nOffset);
+
+ /** insert.
+ */
+ storeError insertPageAt (
+ PageHolder const & rxPage,
+ sal_uInt32 nOffset);
+
+ /** update, or insert.
+ */
+ storeError updatePageAt (
+ PageHolder const & rxPage,
+ sal_uInt32 nOffset);
+
+ /** remove (invalidate).
+ */
+ storeError removePageAt (
+ sal_uInt32 nOffset);
+
+private:
+ /** Implementation (abstract).
+ */
+ virtual storeError lookupPageAt_Impl (
+ PageHolder & rxPage,
+ sal_uInt32 nOffset) = 0;
+
+ virtual storeError insertPageAt_Impl (
+ PageHolder const & rxPage,
+ sal_uInt32 nOffset) = 0;
+
+ virtual storeError updatePageAt_Impl (
+ PageHolder const & rxPage,
+ sal_uInt32 nOffset) = 0;
+
+ virtual storeError removePageAt_Impl (
+ sal_uInt32 nOffset) = 0;
+};
+
+/*========================================================================
+ *
+ * PageCache factory.
+ *
+ *======================================================================*/
+
+storeError
+PageCache_createInstance (
+ rtl::Reference< store::PageCache > & rxCache,
+ sal_uInt16 nPageSize
+);
+
+/*========================================================================
+ *
+ * The End.
+ *
+ *======================================================================*/
+
+} // namespace store
+
+#endif /* !_STORE_STORCACH_HXX */
+
diff --git a/store/source/stordata.cxx b/store/source/stordata.cxx
new file mode 100644
index 000000000000..29350f8ebfdd
--- /dev/null
+++ b/store/source/stordata.cxx
@@ -0,0 +1,1207 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: stordata.cxx,v $
+ * $Revision: 1.6 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_store.hxx"
+
+#include "stordata.hxx"
+
+#include "sal/types.h"
+#include "osl/diagnose.h"
+
+#include "store/types.h"
+#include "storbase.hxx"
+#include "storbios.hxx"
+
+using namespace store;
+
+/*========================================================================
+ *
+ * OStoreDataPageObject implementation.
+ *
+ *======================================================================*/
+/*
+ * guard.
+ */
+storeError OStoreDataPageObject::guard (sal_uInt32 nAddr)
+{
+ return PageHolderObject< page >::guard (m_xPage, nAddr);
+}
+
+/*
+ * verify.
+ */
+storeError OStoreDataPageObject::verify (sal_uInt32 nAddr) const
+{
+ return PageHolderObject< page >::verify (m_xPage, nAddr);
+}
+
+/*========================================================================
+ *
+ * OStoreIndirectionPageObject implementation.
+ *
+ *======================================================================*/
+/*
+ * 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.
+ OStorePageData aPageHead;
+ eErrCode = rBIOS.free (aPageHead, 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.
+ OStorePageData aPageHead;
+ eErrCode = rBIOS.free (aPageHead, 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.
+ OStorePageData aPageHead;
+ eErrCode = rBIOS.free (aPageHead, nAddr);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+ }
+ }
+ return store_E_None;
+}
+
+/*
+ * loadOrCreate.
+ */
+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);
+}
+
+/*
+ * guard.
+ */
+storeError OStoreIndirectionPageObject::guard (sal_uInt32 nAddr)
+{
+ return PageHolderObject< page >::guard (m_xPage, nAddr);
+}
+
+/*
+ * verify.
+ */
+storeError OStoreIndirectionPageObject::verify (sal_uInt32 nAddr) const
+{
+ return PageHolderObject< page >::verify (m_xPage, nAddr);
+}
+
+/*
+ * read (single indirect).
+ */
+storeError OStoreIndirectionPageObject::read (
+ sal_uInt16 nSingle,
+ OStoreDataPageObject &rData,
+ OStorePageBIOS &rBIOS)
+{
+ 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)
+{
+ 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)
+{
+ 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;
+
+ // Save PageDescriptor.
+ OStorePageDescriptor aDescr (rPage.m_aDescr);
+ aDescr.m_nAddr = store::ntohl(aDescr.m_nAddr);
+ aDescr.m_nSize = store::ntohs(aDescr.m_nSize);
+
+ // Acquire Lock.
+ storeError eErrCode = rBIOS.acquireLock (aDescr.m_nAddr, aDescr.m_nSize);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ // Truncate.
+ 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.
+ OStorePageData aPageHead;
+ eErrCode = rBIOS.free (aPageHead, nAddr);
+ if (eErrCode != store_E_None)
+ {
+ rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize);
+ 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());
+ if (eErrCode != store_E_None)
+ {
+ // Must not happen.
+ OSL_TRACE("OStoreIndirectionPageObject::truncate(): save failed");
+
+ // Release Lock and Leave.
+ rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize);
+ return eErrCode;
+ }
+ }
+
+ // Release Lock and Leave.
+ return rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize);
+}
+
+/*
+ * 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;
+
+ // Save PageDescriptor.
+ OStorePageDescriptor aDescr (rPage.m_aDescr);
+ aDescr.m_nAddr = store::ntohl(aDescr.m_nAddr);
+ aDescr.m_nSize = store::ntohs(aDescr.m_nSize);
+
+ // Acquire Lock.
+ storeError eErrCode = rBIOS.acquireLock (aDescr.m_nAddr, aDescr.m_nSize);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ // Truncate.
+ 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)
+ {
+ rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize);
+ 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)
+ {
+ rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize);
+ 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());
+ if (eErrCode != store_E_None)
+ {
+ // Must not happen.
+ OSL_TRACE("OStoreIndirectionPageObject::truncate(): save failed");
+
+ // Release Lock and Leave.
+ rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize);
+ return eErrCode;
+ }
+ }
+
+ // Release Lock and Leave.
+ return rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize);
+}
+
+/*
+ * 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;
+
+ // Save PageDescriptor.
+ OStorePageDescriptor aDescr (rPage.m_aDescr);
+ aDescr.m_nAddr = store::ntohl(aDescr.m_nAddr);
+ aDescr.m_nSize = store::ntohs(aDescr.m_nSize);
+
+ // Acquire Lock.
+ storeError eErrCode = rBIOS.acquireLock (aDescr.m_nAddr, aDescr.m_nSize);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ // Truncate.
+ 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)
+ {
+ rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize);
+ 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)
+ {
+ rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize);
+ 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());
+ if (eErrCode != store_E_None)
+ {
+ // Must not happen.
+ OSL_TRACE("OStoreIndirectionPageObject::truncate(): save failed");
+
+ // Release Lock and Leave.
+ rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize);
+ return eErrCode;
+ }
+ }
+
+ // Release Lock and Leave.
+ return rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize);
+}
+
+/*========================================================================
+ *
+ * OStoreDirectoryPageObject implementation.
+ *
+ *======================================================================*/
+/*
+ * guard.
+ */
+storeError OStoreDirectoryPageObject::guard (sal_uInt32 nAddr)
+{
+ return PageHolderObject< page >::guard (m_xPage, nAddr);
+}
+
+/*
+ * verify.
+ */
+storeError OStoreDirectoryPageObject::verify (sal_uInt32 nAddr) const
+{
+ return PageHolderObject< page >::verify (m_xPage, nAddr);
+ // OLD: m_rPage.verifyVersion (STORE_MAGIC_DIRECTORYPAGE);
+}
+
+/*
+ * scope (external data page; private).
+ */
+OStoreDirectoryPageData::ChunkScope
+OStoreDirectoryPageObject::scope (
+ sal_uInt32 nPage,
+ page::DataBlock::LinkDescriptor &rDescr) const
+{
+ page const & rPage = PAGE();
+ OStoreDirectoryDataBlock const & rDataBlock = rPage.m_aDataBlock;
+
+ sal_uInt32 index0, index1, index2, index3;
+
+ // direct.
+ sal_uInt32 nCount = rDataBlock.directCount();
+ sal_uInt32 nLimit = nCount;
+ if (nPage < nLimit)
+ {
+ // Page to index reduction.
+ index0 = nPage;
+
+ // Setup LinkDescriptor indices.
+ rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff);
+
+ // Done.
+ return page::SCOPE_DIRECT;
+ }
+ nPage -= nLimit;
+
+ // single indirect.
+ sal_uInt32 const nCapacity = indirect::capacityCount(rPage.m_aDescr);
+ nCount = rDataBlock.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;
+ OSL_POSTCOND(n == nPage, "wrong math on indirect indices");
+ if (n != nPage)
+ return page::SCOPE_UNKNOWN;
+
+ // Setup LinkDescriptor indices.
+ rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff);
+ rDescr.m_nIndex1 = (sal_uInt16)(index1 & 0xffff);
+
+ // Done.
+ return page::SCOPE_SINGLE;
+ }
+ nPage -= nLimit;
+
+ // double indirect.
+ nCount = rDataBlock.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;
+ OSL_POSTCOND(n == nPage, "wrong math on double indirect indices");
+ if (n != nPage)
+ return page::SCOPE_UNKNOWN;
+
+ // Setup LinkDescriptor indices.
+ rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff);
+ rDescr.m_nIndex1 = (sal_uInt16)(index1 & 0xffff);
+ rDescr.m_nIndex2 = (sal_uInt16)(index2 & 0xffff);
+
+ // Done.
+ return page::SCOPE_DOUBLE;
+ }
+ nPage -= nLimit;
+
+ // triple indirect.
+ nCount = rDataBlock.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.
+ 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;
+ OSL_POSTCOND(n == nPage, "wrong math on triple indirect indices");
+ if (n != nPage)
+ return page::SCOPE_UNKNOWN;
+
+ // Setup LinkDescriptor indices.
+ rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff);
+ rDescr.m_nIndex1 = (sal_uInt16)(index1 & 0xffff);
+ rDescr.m_nIndex2 = (sal_uInt16)(index2 & 0xffff);
+ rDescr.m_nIndex3 = (sal_uInt16)(index3 & 0xffff);
+
+ // Done.
+ return page::SCOPE_TRIPLE;
+ }
+
+ // Unreachable (more than triple indirect).
+ return page::SCOPE_UNREACHABLE;
+}
+
+#if 0 /* NYI */
+/*
+ * chunk (external data page).
+ */
+inode::ChunkDescriptor OStoreDirectoryPageObject::chunk (sal_uInt32 nOffset)
+{
+ // @@@ INSUFFICIENT: NEED SCOPE AS WELL @@@
+ sal_uInt32 nCapacity = m_rPage.capacity();
+ if (nOffset < nCapacity)
+ // Internal scope (inode page).
+ return inode::ChunkDescriptor (nOffset, nCapacity);
+ else
+ // External scope (data page).
+ return inode::ChunkDescriptor (nOffset - nCapacity, data::capacity(m_rPage.m_aDescr));
+
+ inode::ChunkScope eScope = m_rPage.scope(nOffset);
+ if (eScope == inode::SCOPE_INTERNAL)
+ // Inode page (internal scope).
+ return inode::ChunkDescriptor (nOffset, m_rPage.capacity());
+ else
+ // Data page (external scope).
+ return inode::ChunkDescriptor (nOffset - m_rPage.capacity(), data::capacity(m_rPage.m_aDescr));
+}
+#endif /* NYI */
+
+/*
+ * read (external data page).
+ */
+storeError OStoreDirectoryPageObject::read (
+ 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)
+ 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.
+ OSL_TRACE("OStoreDirectoryPageObject::get(): scope failed");
+ eErrCode = store_E_Unknown;
+ }
+
+ // Leave.
+ return eErrCode;
+}
+
+/*
+ * write (external data page).
+ */
+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.
+ OSL_TRACE("OStoreDirectoryPageObject::put(): scope failed");
+ eErrCode = store_E_Unknown;
+ }
+
+ // Leave.
+ return eErrCode;
+}
+
+/*
+ * truncate (external data page).
+ */
+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.
+ OSL_TRACE("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)
+{
+ OStoreDirectoryDataBlock const & rDataBlock = PAGE().m_aDataBlock;
+
+ // Enter.
+ storeError eErrCode = store_E_None;
+ if (eScope == page::SCOPE_DIRECT)
+ {
+ // Truncate direct data pages.
+ sal_uInt16 i, n = rDataBlock.directCount();
+ for (i = n; i > nRemain; i--)
+ {
+ // Obtain data page location.
+ sal_uInt32 nAddr = directLink (i - 1);
+ if (nAddr == STORE_PAGE_NULL) continue;
+
+ // Free data page.
+ OStoreDataPageData aData;
+ eErrCode = rBIOS.free (aData, 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.
+ sal_uInt16 i, n = rDataBlock.singleCount();
+ for (i = n; 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.
+ sal_uInt16 i, n = rDataBlock.doubleCount();
+ for (i = n; 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.
+ sal_uInt16 i, n = rDataBlock.tripleCount();
+ for (i = n; 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;
+}
diff --git a/store/source/stordata.hxx b/store/source/stordata.hxx
new file mode 100644
index 000000000000..4610bac425fd
--- /dev/null
+++ b/store/source/stordata.hxx
@@ -0,0 +1,873 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: stordata.hxx,v $
+ * $Revision: 1.6 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _STORE_STORDATA_HXX_
+#define _STORE_STORDATA_HXX_ "$Revision: 1.6.8.2 $"
+
+#include "sal/types.h"
+#include "sal/macros.h"
+
+#include "store/types.h"
+#include "storbase.hxx"
+
+namespace store
+{
+
+/*========================================================================
+ *
+ * OStoreDataPageData.
+ *
+ *======================================================================*/
+#define STORE_MAGIC_DATAPAGE sal_uInt32(0x94190310)
+
+struct OStoreDataPageData : public store::OStorePageData
+{
+ typedef OStorePageData base;
+ typedef OStoreDataPageData self;
+
+ typedef OStorePageDescriptor D;
+
+ /** Representation.
+ */
+ sal_uInt8 m_pData[1];
+
+ /** type.
+ */
+ static const sal_uInt32 theTypeId = STORE_MAGIC_DATAPAGE;
+
+ /** size.
+ */
+ static const size_t theSize = 0;
+ static const sal_uInt16 thePageSize = base::theSize + self::theSize;
+ STORE_STATIC_ASSERT(STORE_MINIMUM_PAGESIZE >= self::thePageSize);
+
+ /** capacity.
+ */
+ static sal_uInt16 capacity (const D& rDescr) // @see inode::ChunkDescriptor
+ {
+ return (store::ntohs(rDescr.m_nSize) - self::thePageSize);
+ }
+ sal_uInt16 capacity() const
+ {
+ return self::capacity (base::m_aDescr);
+ }
+
+ /** usage.
+ */
+ sal_uInt16 usage() const
+ {
+ return (store::ntohs(base::m_aDescr.m_nUsed) - self::thePageSize);
+ }
+
+ /** Construction.
+ */
+ explicit OStoreDataPageData (sal_uInt16 nPageSize = self::thePageSize)
+ : base (nPageSize)
+ {
+ base::m_aGuard.m_nMagic = store::htonl(self::theTypeId);
+ base::m_aDescr.m_nUsed = store::htons(self::thePageSize);
+ if (capacity()) memset (m_pData, 0, capacity());
+ }
+
+ /** guard (external representation).
+ */
+ void guard() {}
+
+ /** verify (external representation).
+ */
+ storeError verify() const { return store_E_None; }
+};
+
+/*========================================================================
+ *
+ * OStoreDataPageObject.
+ *
+ *======================================================================*/
+class OStoreDataPageObject : public store::OStorePageObject
+{
+ typedef OStorePageObject base;
+ typedef OStoreDataPageData page;
+
+public:
+ /** Construction.
+ */
+ explicit OStoreDataPageObject (PageHolder const & rxPage = PageHolder())
+ : OStorePageObject (rxPage)
+ {}
+
+ /** External representation.
+ */
+ virtual storeError guard (sal_uInt32 nAddr);
+ virtual storeError verify (sal_uInt32 nAddr) const;
+};
+
+/*========================================================================
+ *
+ * OStoreIndirectionPageData.
+ *
+ *======================================================================*/
+#define STORE_MAGIC_INDIRECTPAGE sal_uInt32(0x89191107)
+
+struct OStoreIndirectionPageData : public store::OStorePageData
+{
+ typedef OStorePageData base;
+ typedef OStoreIndirectionPageData self;
+
+ typedef OStorePageGuard G;
+ typedef OStorePageDescriptor D;
+
+ /** Representation.
+ */
+ G m_aGuard;
+ sal_uInt32 m_pData[1];
+
+ /** type.
+ */
+ static const sal_uInt32 theTypeId = STORE_MAGIC_INDIRECTPAGE;
+
+ /** size.
+ */
+ static const size_t theSize = sizeof(G);
+ static const sal_uInt16 thePageSize = base::theSize + self::theSize;
+ STORE_STATIC_ASSERT(STORE_MINIMUM_PAGESIZE >= self::thePageSize);
+
+ /** capacity.
+ */
+ static sal_uInt16 capacity (const D& rDescr)
+ {
+ return (store::ntohs(rDescr.m_nSize) - self::thePageSize);
+ }
+ sal_uInt16 capacity() const
+ {
+ return self::capacity (base::m_aDescr);
+ }
+
+ /** capacityCount.
+ */
+ static sal_uInt16 capacityCount (const D& rDescr) // @see DirectoryPageObject::scope()
+ {
+ return sal_uInt16(capacity(rDescr) / sizeof(sal_uInt32));
+ }
+ sal_uInt16 capacityCount() const
+ {
+ return sal_uInt16(capacity() / sizeof(sal_uInt32));
+ }
+
+ /** Construction.
+ */
+ explicit OStoreIndirectionPageData (sal_uInt16 nPageSize)
+ : base (nPageSize)
+ {
+ base::m_aGuard.m_nMagic = store::htonl(self::theTypeId);
+ base::m_aDescr.m_nUsed = store::htons(self::thePageSize);
+ self::m_aGuard.m_nMagic = store::htonl(0);
+ memset (m_pData, STORE_PAGE_NULL, capacity());
+ }
+
+ /** guard (external representation).
+ */
+ void guard()
+ {
+ sal_uInt32 nCRC32 = 0;
+ nCRC32 = rtl_crc32 (nCRC32, &m_aGuard.m_nMagic, sizeof(sal_uInt32));
+ nCRC32 = rtl_crc32 (nCRC32, m_pData, capacity());
+ m_aGuard.m_nCRC32 = store::htonl(nCRC32);
+ }
+
+ /** verify (external representation).
+ */
+ storeError verify() const
+ {
+ sal_uInt32 nCRC32 = 0;
+ nCRC32 = rtl_crc32 (nCRC32, &m_aGuard.m_nMagic, sizeof(sal_uInt32));
+ nCRC32 = rtl_crc32 (nCRC32, m_pData, capacity());
+ if (m_aGuard.m_nCRC32 != store::htonl(nCRC32))
+ return store_E_InvalidChecksum;
+ else
+ return store_E_None;
+ }
+};
+
+/*========================================================================
+ *
+ * OStoreIndirectionPageObject.
+ *
+ *======================================================================*/
+class OStoreIndirectionPageObject : public store::OStorePageObject
+{
+ typedef OStorePageObject base;
+ typedef OStoreIndirectionPageData page;
+
+public:
+ /** Construction.
+ */
+ explicit OStoreIndirectionPageObject (PageHolder const & rxPage = PageHolder())
+ : OStorePageObject (rxPage)
+ {}
+
+ /** External representation.
+ */
+ storeError loadOrCreate (
+ sal_uInt32 nAddr,
+ OStorePageBIOS & rBIOS);
+
+ virtual storeError guard (sal_uInt32 nAddr);
+ virtual storeError verify (sal_uInt32 nAddr) const;
+
+ /** read (indirect data page).
+ */
+ storeError read (
+ sal_uInt16 nSingle,
+ OStoreDataPageObject &rData,
+ OStorePageBIOS &rBIOS);
+
+ storeError read (
+ sal_uInt16 nDouble,
+ sal_uInt16 nSingle,
+ OStoreDataPageObject &rData,
+ OStorePageBIOS &rBIOS);
+
+ storeError read (
+ sal_uInt16 nTriple,
+ sal_uInt16 nDouble,
+ sal_uInt16 nSingle,
+ OStoreDataPageObject &rData,
+ OStorePageBIOS &rBIOS);
+
+ /** write (indirect data page).
+ */
+ storeError write (
+ sal_uInt16 nSingle,
+ OStoreDataPageObject &rData,
+ OStorePageBIOS &rBIOS);
+
+ storeError write (
+ sal_uInt16 nDouble,
+ sal_uInt16 nSingle,
+ OStoreDataPageObject &rData,
+ OStorePageBIOS &rBIOS);
+
+ storeError write (
+ sal_uInt16 nTriple,
+ sal_uInt16 nDouble,
+ sal_uInt16 nSingle,
+ OStoreDataPageObject &rData,
+ OStorePageBIOS &rBIOS);
+
+ /** truncate (indirect data page).
+ */
+ storeError truncate (
+ sal_uInt16 nSingle,
+ OStorePageBIOS &rBIOS);
+
+ storeError truncate (
+ sal_uInt16 nDouble,
+ sal_uInt16 nSingle,
+ OStorePageBIOS &rBIOS);
+
+ storeError truncate (
+ sal_uInt16 nTriple,
+ sal_uInt16 nDouble,
+ sal_uInt16 nSingle,
+ OStorePageBIOS &rBIOS);
+};
+
+/*========================================================================
+ *
+ * OStorePageNameBlock.
+ *
+ *======================================================================*/
+struct OStorePageNameBlock
+{
+ typedef OStorePageGuard G;
+ typedef OStorePageKey K;
+
+ /** Representation.
+ */
+ G m_aGuard;
+ K m_aKey;
+ sal_uInt32 m_nAttrib;
+ sal_Char m_pData[STORE_MAXIMUM_NAMESIZE];
+
+ /** size.
+ */
+ static const size_t theSize = sizeof(G) + sizeof(K) + sizeof(sal_uInt32) + sizeof(sal_Char[STORE_MAXIMUM_NAMESIZE]);
+
+ /** initialize.
+ */
+ void initialize (void)
+ {
+ m_aGuard = G();
+ m_aKey = K();
+ m_nAttrib = 0;
+ memset (m_pData, 0, sizeof(m_pData));
+ }
+
+ /** Construction.
+ */
+ OStorePageNameBlock (void)
+ : m_aGuard(), m_aKey(), m_nAttrib (0)
+ {
+ memset (m_pData, 0, sizeof(m_pData));
+ }
+
+ /** guard (external representation).
+ */
+ void guard()
+ {
+ sal_uInt32 nCRC32 = 0;
+ nCRC32 = rtl_crc32 (nCRC32, &m_aGuard.m_nMagic, sizeof(sal_uInt32));
+ nCRC32 = rtl_crc32 (nCRC32, &m_aKey, theSize - sizeof(G));
+ m_aGuard.m_nCRC32 = store::htonl(nCRC32);
+ }
+
+ /** verify (external representation).
+ */
+ storeError verify() const
+ {
+ sal_uInt32 nCRC32 = 0;
+ nCRC32 = rtl_crc32 (nCRC32, &m_aGuard.m_nMagic, sizeof(sal_uInt32));
+ nCRC32 = rtl_crc32 (nCRC32, &m_aKey, theSize - sizeof(G));
+ if (m_aGuard.m_nCRC32 != store::htonl(nCRC32))
+ return store_E_InvalidChecksum;
+ else
+ return store_E_None;
+ }
+};
+
+/*========================================================================
+ *
+ * OStoreDirectoryDataBlock.
+ *
+ *======================================================================*/
+#define STORE_LIMIT_DATAPAGE_DIRECT 16
+#define STORE_LIMIT_DATAPAGE_SINGLE 8
+#define STORE_LIMIT_DATAPAGE_DOUBLE 1
+#define STORE_LIMIT_DATAPAGE_TRIPLE 1
+
+struct OStoreDirectoryDataBlock
+{
+ typedef OStorePageGuard G;
+
+ /** LinkDescriptor.
+ */
+ struct LinkDescriptor
+ {
+ /** Representation.
+ */
+ sal_uInt16 m_nIndex0;
+ sal_uInt16 m_nIndex1;
+ sal_uInt16 m_nIndex2;
+ sal_uInt16 m_nIndex3;
+
+ /** Construction.
+ */
+ LinkDescriptor (void)
+ : m_nIndex0 ((sal_uInt16)(~0)),
+ m_nIndex1 ((sal_uInt16)(~0)),
+ m_nIndex2 ((sal_uInt16)(~0)),
+ m_nIndex3 ((sal_uInt16)(~0))
+ {}
+ };
+
+ /** LinkTable.
+ */
+ struct LinkTable
+ {
+ /** Representation.
+ */
+ sal_uInt32 m_pDirect[STORE_LIMIT_DATAPAGE_DIRECT];
+ sal_uInt32 m_pSingle[STORE_LIMIT_DATAPAGE_SINGLE];
+ sal_uInt32 m_pDouble[STORE_LIMIT_DATAPAGE_DOUBLE];
+ sal_uInt32 m_pTriple[STORE_LIMIT_DATAPAGE_TRIPLE];
+
+ /** initialize.
+ */
+ void initialize (void)
+ {
+ memset(m_pDirect, STORE_PAGE_NULL, sizeof(m_pDirect));
+ memset(m_pSingle, STORE_PAGE_NULL, sizeof(m_pSingle));
+ memset(m_pDouble, STORE_PAGE_NULL, sizeof(m_pDouble));
+ memset(m_pTriple, STORE_PAGE_NULL, sizeof(m_pTriple));
+ }
+
+ /** Construction.
+ */
+ LinkTable (void)
+ {
+ initialize();
+ }
+ };
+
+ /** Representation.
+ */
+ G m_aGuard;
+ LinkTable m_aTable;
+ sal_uInt32 m_nDataLen;
+
+ /** size.
+ */
+ static const size_t theSize = sizeof(G) + sizeof(LinkTable) + sizeof(sal_uInt32);
+
+ /** initialize.
+ */
+ void initialize (void)
+ {
+ m_aGuard = G();
+ m_aTable.initialize();
+ m_nDataLen = 0;
+ }
+
+ /** Construction.
+ */
+ OStoreDirectoryDataBlock (void)
+ : m_aGuard(), m_aTable(), m_nDataLen (0)
+ {}
+
+ /** guard (external representation).
+ */
+ void guard()
+ {
+ sal_uInt32 nCRC32 = 0;
+ nCRC32 = rtl_crc32 (nCRC32, &m_aGuard.m_nMagic, sizeof(sal_uInt32));
+ nCRC32 = rtl_crc32 (nCRC32, &m_aTable, theSize - sizeof(G));
+ m_aGuard.m_nCRC32 = store::htonl(nCRC32);
+ }
+
+ /** verify (external representation).
+ */
+ storeError verify() const
+ {
+ sal_uInt32 nCRC32 = 0;
+ nCRC32 = rtl_crc32 (nCRC32, &m_aGuard.m_nMagic, sizeof(sal_uInt32));
+ nCRC32 = rtl_crc32 (nCRC32, &m_aTable, theSize - sizeof(G));
+ if (m_aGuard.m_nCRC32 != store::htonl(nCRC32))
+ return store_E_InvalidChecksum;
+ else
+ return store_E_None;
+ }
+
+ /** direct.
+ */
+ static sal_uInt16 directCount (void)
+ {
+ return ((sal_uInt16)(STORE_LIMIT_DATAPAGE_DIRECT));
+ }
+ sal_uInt32 directLink (sal_uInt16 nIndex) const
+ {
+ if (nIndex < directCount())
+ return store::ntohl(m_aTable.m_pDirect[nIndex]);
+ else
+ return STORE_PAGE_NULL;
+ }
+ void directLink (sal_uInt16 nIndex, sal_uInt32 nAddr)
+ {
+ if (nIndex < directCount())
+ m_aTable.m_pDirect[nIndex] = store::htonl(nAddr);
+ }
+
+ /** single.
+ */
+ static sal_uInt16 singleCount (void)
+ {
+ return ((sal_uInt16)(STORE_LIMIT_DATAPAGE_SINGLE));
+ }
+ sal_uInt32 singleLink (sal_uInt16 nIndex) const
+ {
+ if (nIndex < singleCount())
+ return store::ntohl(m_aTable.m_pSingle[nIndex]);
+ else
+ return STORE_PAGE_NULL;
+ }
+ void singleLink (sal_uInt16 nIndex, sal_uInt32 nAddr)
+ {
+ if (nIndex < singleCount())
+ m_aTable.m_pSingle[nIndex] = store::htonl(nAddr);
+ }
+
+ /** double.
+ */
+ static sal_uInt16 doubleCount (void)
+ {
+ return ((sal_uInt16)(STORE_LIMIT_DATAPAGE_DOUBLE));
+ }
+ sal_uInt32 doubleLink (sal_uInt16 nIndex) const
+ {
+ if (nIndex < doubleCount())
+ return store::ntohl(m_aTable.m_pDouble[nIndex]);
+ else
+ return STORE_PAGE_NULL;
+ }
+ void doubleLink (sal_uInt16 nIndex, sal_uInt32 nAddr)
+ {
+ if (nIndex < doubleCount())
+ m_aTable.m_pDouble[nIndex] = store::htonl(nAddr);
+ }
+
+ /** triple.
+ */
+ static sal_uInt16 tripleCount (void)
+ {
+ return ((sal_uInt16)(STORE_LIMIT_DATAPAGE_TRIPLE));
+ }
+ sal_uInt32 tripleLink (sal_uInt16 nIndex) const
+ {
+ if (nIndex < tripleCount())
+ return store::ntohl(m_aTable.m_pTriple[nIndex]);
+ else
+ return STORE_PAGE_NULL;
+ }
+ void tripleLink (sal_uInt16 nIndex, sal_uInt32 nAddr)
+ {
+ if (nIndex < tripleCount())
+ m_aTable.m_pTriple[nIndex] = store::htonl(nAddr);
+ }
+};
+
+/*========================================================================
+ *
+ * OStoreDirectoryPageData.
+ *
+ *======================================================================*/
+#define STORE_MAGIC_DIRECTORYPAGE sal_uInt32(0x62190120)
+
+struct OStoreDirectoryPageData : public store::OStorePageData
+{
+ typedef OStorePageData base;
+ typedef OStoreDirectoryPageData self;
+
+ typedef OStorePageDescriptor D;
+ typedef OStorePageNameBlock NameBlock;
+ typedef OStoreDirectoryDataBlock DataBlock;
+
+ /** Representation.
+ */
+ NameBlock m_aNameBlock;
+ DataBlock m_aDataBlock;
+ sal_uInt8 m_pData[1];
+
+ /** type.
+ */
+ static const sal_uInt32 theTypeId = STORE_MAGIC_DIRECTORYPAGE;
+
+ /** size.
+ */
+ static const size_t theSize = NameBlock::theSize + DataBlock::theSize;
+ static const sal_uInt16 thePageSize = base::theSize + self::theSize;
+ STORE_STATIC_ASSERT(STORE_MINIMUM_PAGESIZE >= self::thePageSize);
+
+ /** capacity.
+ */
+ sal_uInt16 capacity() const
+ {
+ return (store::ntohs(base::m_aDescr.m_nSize) - self::thePageSize);
+ }
+
+ /** usage.
+ */
+ sal_uInt16 usage() const
+ {
+ return (store::ntohs(base::m_aDescr.m_nUsed) - self::thePageSize);
+ }
+
+ /** initialize.
+ */
+ void initialize (void)
+ {
+ base::m_aGuard.m_nMagic = store::htonl(self::theTypeId);
+ base::m_aDescr.m_nUsed = store::htons(self::thePageSize);
+
+ m_aNameBlock.initialize();
+ m_aDataBlock.initialize();
+
+ memset (m_pData, 0, capacity());
+ }
+
+ /** Construction.
+ */
+ explicit OStoreDirectoryPageData (sal_uInt16 nPageSize)
+ : base (nPageSize), m_aNameBlock(), m_aDataBlock()
+ {
+ base::m_aGuard.m_nMagic = store::htonl(self::theTypeId);
+ base::m_aDescr.m_nUsed = store::htons(self::thePageSize);
+ memset (m_pData, 0, capacity());
+ }
+
+ /** guard (external representation).
+ */
+ void guard()
+ {
+ m_aNameBlock.guard();
+ m_aDataBlock.guard();
+ }
+
+ /** verify (external representation).
+ */
+ storeError verify() const
+ {
+ storeError eErrCode = m_aNameBlock.verify();
+ if (eErrCode == store_E_None)
+ eErrCode = m_aDataBlock.verify();
+ return eErrCode;
+ }
+
+ /** ChunkDescriptor.
+ */
+ struct ChunkDescriptor
+ {
+ /** Representation.
+ */
+ sal_uInt32 m_nPage;
+ sal_uInt16 m_nOffset;
+ sal_uInt16 m_nLength;
+
+ /** Construction.
+ */
+ ChunkDescriptor (sal_uInt32 nPosition, sal_uInt16 nCapacity)
+ {
+ m_nPage = nPosition / nCapacity;
+ m_nOffset = (sal_uInt16)((nPosition % nCapacity) & 0xffff);
+ m_nLength = nCapacity - m_nOffset;
+ }
+ };
+
+ /** ChunkScope.
+ */
+ enum ChunkScope
+ {
+ SCOPE_INTERNAL,
+ SCOPE_EXTERNAL,
+ SCOPE_DIRECT,
+ SCOPE_SINGLE,
+ SCOPE_DOUBLE,
+ SCOPE_TRIPLE,
+ SCOPE_UNREACHABLE,
+ SCOPE_UNKNOWN
+ };
+
+ /** scope (internal).
+ */
+ ChunkScope scope (sal_uInt32 nPosition) const
+ {
+ sal_uInt32 nCapacity = capacity();
+ if (nPosition < nCapacity)
+ return SCOPE_INTERNAL;
+ else
+ return SCOPE_EXTERNAL;
+ }
+};
+
+/*========================================================================
+ *
+ * OStoreDirectoryPageObject.
+ *
+ *======================================================================*/
+class OStoreDirectoryPageObject : public store::OStorePageObject
+{
+ typedef OStorePageObject base;
+ typedef OStoreDirectoryPageData page;
+ typedef OStoreIndirectionPageData indirect;
+
+ typedef OStorePageDescriptor D;
+
+public:
+ /** Construction.
+ */
+ explicit OStoreDirectoryPageObject (PageHolder const & rxPage = PageHolder())
+ : OStorePageObject (rxPage)
+ {}
+
+ /** External representation.
+ */
+ virtual storeError guard (sal_uInt32 nAddr);
+ virtual storeError verify (sal_uInt32 nAddr) const;
+
+ /** attrib.
+ */
+ sal_uInt32 attrib (void) const
+ {
+ return store::ntohl(PAGE().m_aNameBlock.m_nAttrib);
+ }
+ void attrib (sal_uInt32 nAttrib)
+ {
+ PAGE().m_aNameBlock.m_nAttrib = store::htonl(nAttrib);
+ touch();
+ }
+
+ /** key.
+ */
+ OStorePageKey key (void) const
+ {
+ return PAGE().m_aNameBlock.m_aKey;
+ }
+ void key (OStorePageKey const & rKey)
+ {
+ PAGE().m_aNameBlock.m_aKey = rKey;
+ touch();
+ }
+
+ /** path.
+ */
+ sal_uInt32 path (void) const
+ {
+ page const & rPage = PAGE();
+ const sal_Char * pszName = rPage.m_aNameBlock.m_pData;
+ sal_uInt32 nPath = store::ntohl(rPage.m_aNameBlock.m_aKey.m_nHigh);
+ return rtl_crc32 (nPath, pszName, rtl_str_getLength(pszName));
+ }
+
+ sal_Size getName (sal_Char * pBuffer, sal_Size nBufsiz) const
+ {
+ sal_Char const * pszName = PAGE().m_aNameBlock.m_pData;
+ sal_Size nLength = rtl_str_getLength(pszName);
+ memcpy (pBuffer, pszName, SAL_MIN(nLength, nBufsiz));
+ return nLength;
+ }
+
+ /** dataLength.
+ */
+ sal_uInt32 dataLength (void) const
+ {
+ return store::ntohl(PAGE().m_aDataBlock.m_nDataLen);
+ }
+ void dataLength (sal_uInt32 nLength)
+ {
+ PAGE().m_aDataBlock.m_nDataLen = store::htonl(nLength);
+ touch();
+ }
+
+ /** direct.
+ */
+ sal_uInt32 directLink (sal_uInt16 nIndex) const
+ {
+ return PAGE().m_aDataBlock.directLink (nIndex);
+ }
+ void directLink (sal_uInt16 nIndex, sal_uInt32 nAddr)
+ {
+ PAGE().m_aDataBlock.directLink (nIndex, nAddr);
+ touch();
+ }
+
+ /** single indirect.
+ */
+ sal_uInt32 singleLink (sal_uInt16 nIndex) const
+ {
+ return PAGE().m_aDataBlock.singleLink (nIndex);
+ }
+ void singleLink (sal_uInt16 nIndex, sal_uInt32 nAddr)
+ {
+ PAGE().m_aDataBlock.singleLink (nIndex, nAddr);
+ touch();
+ }
+
+ /** double indirect.
+ */
+ sal_uInt32 doubleLink (sal_uInt16 nIndex) const
+ {
+ return PAGE().m_aDataBlock.doubleLink (nIndex);
+ }
+ void doubleLink (sal_uInt16 nIndex, sal_uInt32 nAddr)
+ {
+ PAGE().m_aDataBlock.doubleLink (nIndex, nAddr);
+ touch();
+ }
+
+ /** triple indirect.
+ */
+ sal_uInt32 tripleLink (sal_uInt16 nIndex) const
+ {
+ return PAGE().m_aDataBlock.tripleLink (nIndex);
+ }
+ void tripleLink (sal_uInt16 nIndex, sal_uInt32 nAddr)
+ {
+ PAGE().m_aDataBlock.tripleLink (nIndex, nAddr);
+ touch();
+ }
+
+ /** read (external data page).
+ */
+ storeError read (
+ sal_uInt32 nPage,
+ OStoreDataPageObject &rData,
+ OStorePageBIOS &rBIOS);
+
+ /** write (external data page).
+ */
+ storeError write (
+ sal_uInt32 nPage,
+ OStoreDataPageObject &rData,
+ OStorePageBIOS &rBIOS);
+
+ /** truncate (external data page).
+ */
+ storeError truncate (
+ sal_uInt32 nPage,
+ OStorePageBIOS &rBIOS);
+
+private:
+ /** Representation.
+ */
+ page & PAGE()
+ {
+ page * pImpl = static_cast<page*>(m_xPage.get());
+ OSL_PRECOND(pImpl != 0, "OStoreDirectoryPageObject::PAGE(): Null pointer");
+ return (*pImpl);
+ }
+ page const & PAGE() const
+ {
+ page const * pImpl = static_cast<page const *>(m_xPage.get());
+ OSL_PRECOND(pImpl != 0, "OStoreDirectoryPageObject::PAGE(): Null pointer");
+ return (*pImpl);
+ }
+
+ /** scope (external data page; private).
+ */
+ page::ChunkScope scope (
+ sal_uInt32 nPage,
+ page::DataBlock::LinkDescriptor &rDescr) const;
+
+ /** truncate (external data page scope; private).
+ */
+ storeError truncate (
+ page::ChunkScope eScope,
+ sal_uInt16 nRemain,
+ OStorePageBIOS &rBIOS);
+};
+
+/*========================================================================
+ *
+ * The End.
+ *
+ *======================================================================*/
+
+} // namespace store
+
+#endif /* !_STORE_STORDATA_HXX_ */
+
diff --git a/store/source/stordir.cxx b/store/source/stordir.cxx
new file mode 100644
index 000000000000..0269e9cb51f1
--- /dev/null
+++ b/store/source/stordir.cxx
@@ -0,0 +1,249 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: stordir.cxx,v $
+ *
+ * $Revision: 1.1.2.2 $
+ *
+ * last change: $Author: mhu $ $Date: 2008/10/17 16:30:17 $
+ *
+ * The Contents of this file are made available subject to
+ * the terms of GNU Lesser General Public License Version 2.1.
+ *
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2005 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
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_store.hxx"
+
+#include "stordir.hxx"
+
+#ifndef _SAL_TYPES_H_
+#include <sal/types.h>
+#endif
+
+#ifndef _RTL_TEXTCVT_H_
+#include <rtl/textcvt.h>
+#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 "object.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
+
+using namespace store;
+
+/*========================================================================
+ *
+ * OStore... internals.
+ *
+ *======================================================================*/
+/*
+ * __store_convertTextToUnicode.
+ */
+inline sal_Size __store_convertTextToUnicode (
+ rtl_TextToUnicodeConverter hConverter,
+ const sal_Char *pSrcBuffer, sal_Size nSrcLength,
+ sal_Unicode *pDstBuffer, sal_Size nDstLength)
+{
+ sal_uInt32 nCvtInfo = 0;
+ sal_Size nCvtBytes = 0;
+ return rtl_convertTextToUnicode (
+ hConverter, 0,
+ pSrcBuffer, nSrcLength,
+ pDstBuffer, nDstLength,
+ OSTRING_TO_OUSTRING_CVTFLAGS,
+ &nCvtInfo, &nCvtBytes);
+}
+
+/*========================================================================
+ *
+ * OStoreDirectory_Impl implementation.
+ *
+ *======================================================================*/
+const sal_uInt32 OStoreDirectory_Impl::m_nTypeId = sal_uInt32(0x89191107);
+
+/*
+ * OStoreDirectory_Impl.
+ */
+OStoreDirectory_Impl::OStoreDirectory_Impl (void)
+ : m_xManager (),
+ m_aDescr (0, 0, 0),
+ m_nPath (0),
+ m_hTextCvt (NULL)
+{}
+
+/*
+ * ~OStoreDirectory_Impl.
+ */
+OStoreDirectory_Impl::~OStoreDirectory_Impl (void)
+{
+ if (m_xManager.is())
+ {
+ if (m_aDescr.m_nAddr != STORE_PAGE_NULL)
+ m_xManager->releasePage (m_aDescr, store_AccessReadOnly);
+ }
+ rtl_destroyTextToUnicodeConverter (m_hTextCvt);
+}
+
+/*
+ * isKindOf.
+ */
+sal_Bool SAL_CALL OStoreDirectory_Impl::isKindOf (sal_uInt32 nTypeId)
+{
+ return (nTypeId == m_nTypeId);
+}
+
+/*
+ * create.
+ */
+storeError OStoreDirectory_Impl::create (
+ OStorePageManager *pManager,
+ rtl_String *pPath,
+ rtl_String *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_ISDIR,
+ pPath, pName, eMode);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ if (!(aPage.attrib() & STORE_ATTRIB_ISDIR))
+ return store_E_NotDirectory;
+
+ inode_holder_type xNode (aPage.get());
+ eErrCode = xManager->acquirePage (xNode->m_aDescr, store_AccessReadOnly);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ // Evaluate iteration path.
+ m_nPath = aPage.path();
+ m_nPath = rtl_crc32 (m_nPath, "/", 1);
+
+ // Save page manager, and descriptor.
+ m_xManager = xManager;
+ m_aDescr = xNode->m_aDescr;
+
+ return store_E_None;
+}
+
+/*
+ * iterate.
+ */
+storeError OStoreDirectory_Impl::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.
+ OStorePageKey aKey (rFindData.m_nReserved, m_nPath);
+
+ // Iterate.
+ for (;;)
+ {
+ OStorePageLink aLink;
+ eErrCode = m_xManager->iterate (aKey, aLink, rFindData.m_nAttrib);
+ if (!((eErrCode == store_E_None) && (aKey.m_nHigh == store::htonl(m_nPath))))
+ break;
+
+ if (!(rFindData.m_nAttrib & STORE_ATTRIB_ISLINK))
+ {
+ // Load page.
+ OStoreDirectoryPageObject aPage;
+ eErrCode = m_xManager->loadObjectAt (aPage, aLink.location());
+ if (eErrCode == store_E_None)
+ {
+ inode_holder_type xNode (aPage.get());
+
+ // Setup FindData.
+ sal_Char *p = xNode->m_aNameBlock.m_pData;
+ sal_Size n = rtl_str_getLength (p);
+ sal_Size 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);
+ memset (&rFindData.m_pszName[n], 0, k);
+ }
+
+ rFindData.m_nLength = n;
+ rFindData.m_nAttrib |= aPage.attrib();
+ rFindData.m_nSize = aPage.dataLength();
+
+ // Leave.
+ rFindData.m_nReserved = store::ntohl(aKey.m_nLow);
+ return store_E_None;
+ }
+ }
+
+ if (aKey.m_nLow == 0)
+ break;
+ aKey.m_nLow = store::htonl(store::ntohl(aKey.m_nLow) - 1);
+ }
+
+ // Finished.
+ memset (&rFindData, 0, sizeof (storeFindData));
+ return store_E_NoMoreFiles;
+}
diff --git a/store/source/stordir.hxx b/store/source/stordir.hxx
new file mode 100644
index 000000000000..acfbf36af8d6
--- /dev/null
+++ b/store/source/stordir.hxx
@@ -0,0 +1,157 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: stordir.hxx,v $
+ *
+ * $Revision: 1.1.2.2 $
+ *
+ * last change: $Author: mhu $ $Date: 2008/10/17 16:30:17 $
+ *
+ * The Contents of this file are made available subject to
+ * the terms of GNU Lesser General Public License Version 2.1.
+ *
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2005 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
+ *
+ ************************************************************************/
+
+#ifndef _STORE_STORDIR_HXX_
+#define _STORE_STORDIR_HXX_ "$Revision: 1.1.2.2 $"
+
+#ifndef _SAL_TYPES_H_
+#include <sal/types.h>
+#endif
+
+#ifndef _RTL_TEXTCVT_H_
+#include <rtl/textcvt.h>
+#endif
+#ifndef _RTL_STRING_H_
+#include <rtl/string.h>
+#endif
+#ifndef _RTL_REF_HXX_
+#include <rtl/ref.hxx>
+#endif
+
+#ifndef _STORE_OBJECT_HXX_
+#include "object.hxx"
+#endif
+#ifndef _STORE_STORBASE_HXX_
+#include "storbase.hxx"
+#endif
+#ifndef _STORE_STORPAGE_HXX_
+#include "storpage.hxx"
+#endif
+
+namespace store
+{
+
+struct OStoreDirectoryPageData;
+
+/*========================================================================
+ *
+ * OStoreDirectory_Impl interface.
+ *
+ *======================================================================*/
+class OStoreDirectory_Impl : public store::OStoreObject
+{
+public:
+ /** Construction.
+ */
+ OStoreDirectory_Impl (void);
+
+ /** create (two-phase construction).
+ * @param pManager [in]
+ * @param pPath [in]
+ * @param pName [in]
+ * @param eAccessMode [in]
+ * @return store_E_None upon success.
+ */
+ storeError create (
+ OStorePageManager *pManager,
+ rtl_String *pPath,
+ rtl_String *pName,
+ storeAccessMode eAccessMode);
+
+ /** iterate.
+ * @param rFindData [out]
+ * @return store_E_None upon success,
+ * store_E_NoMoreFiles upon end of iteration.
+ */
+ storeError iterate (
+ storeFindData &rFindData);
+
+ /** IStoreHandle.
+ */
+ virtual sal_Bool SAL_CALL isKindOf (sal_uInt32 nTypeId);
+
+protected:
+ /** Destruction.
+ */
+ virtual ~OStoreDirectory_Impl (void);
+
+private:
+ /** IStoreHandle TypeId.
+ */
+ static const sal_uInt32 m_nTypeId;
+
+ /** IStoreHandle query() template function specialization.
+ */
+ friend OStoreDirectory_Impl*
+ SAL_CALL query<> (IStoreHandle *pHandle, OStoreDirectory_Impl*);
+
+ /** Representation.
+ */
+ typedef OStoreDirectoryPageData inode;
+ typedef PageHolderObject< inode > inode_holder_type;
+
+ rtl::Reference<OStorePageManager> m_xManager;
+
+ OStorePageDescriptor m_aDescr;
+ sal_uInt32 m_nPath;
+ rtl_TextToUnicodeConverter m_hTextCvt;
+
+ /** Not implemented.
+ */
+ OStoreDirectory_Impl (const OStoreDirectory_Impl&);
+ OStoreDirectory_Impl& operator= (const OStoreDirectory_Impl&);
+};
+
+template<> inline OStoreDirectory_Impl*
+SAL_CALL query (IStoreHandle *pHandle, OStoreDirectory_Impl*)
+{
+ if (pHandle && pHandle->isKindOf (OStoreDirectory_Impl::m_nTypeId))
+ {
+ // Handle is kind of OStoreDirectory_Impl.
+ return static_cast<OStoreDirectory_Impl*>(pHandle);
+ }
+ return 0;
+}
+
+/*========================================================================
+ *
+ * The End.
+ *
+ *======================================================================*/
+
+} // namespace store
+
+#endif /* !_STORE_STORDIR_HXX_ */
+
diff --git a/store/source/store.cxx b/store/source/store.cxx
new file mode 100644
index 000000000000..db27f7cbb05b
--- /dev/null
+++ b/store/source/store.cxx
@@ -0,0 +1,768 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: store.cxx,v $
+ * $Revision: 1.8 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_store.hxx"
+
+#include "store/store.h"
+
+#include <sal/types.h>
+#include <rtl/memory.h>
+#include <rtl/string.hxx>
+#include <rtl/ref.hxx>
+
+#include "object.hxx"
+#include "lockbyte.hxx"
+
+#include "storbase.hxx"
+#include "storpage.hxx"
+#include "stordir.hxx"
+#include "storlckb.hxx"
+
+using rtl::Reference;
+using rtl::OString;
+
+namespace store
+{
+/** Template helper class as type safe Reference to store_handle_type.
+ */
+template<class store_handle_type>
+class OStoreHandle : public rtl::Reference<store_handle_type>
+{
+public:
+ OStoreHandle (store_handle_type * pHandle)
+ : rtl::Reference<store_handle_type> (pHandle)
+ {}
+
+ static store_handle_type * SAL_CALL query (void * pHandle)
+ {
+ return store::query (
+ static_cast<IStoreHandle*>(pHandle),
+ static_cast<store_handle_type*>(0));
+ }
+};
+}
+
+
+using namespace store;
+
+/*========================================================================
+ *
+ * storeHandle implementation.
+ *
+ *======================================================================*/
+/*
+ * store_acquireHandle.
+ */
+storeError SAL_CALL store_acquireHandle (
+ storeHandle Handle
+) SAL_THROW_EXTERN_C()
+{
+ IStoreHandle *pHandle = static_cast<IStoreHandle*>(Handle);
+ if (!pHandle)
+ return store_E_InvalidHandle;
+
+ pHandle->acquire();
+ return store_E_None;
+}
+
+/*
+ * store_releaseHandle.
+ */
+storeError SAL_CALL store_releaseHandle (
+ storeHandle Handle
+) SAL_THROW_EXTERN_C()
+{
+ IStoreHandle *pHandle = static_cast<IStoreHandle*>(Handle);
+ if (!pHandle)
+ return store_E_InvalidHandle;
+
+ pHandle->release();
+ return store_E_None;
+}
+
+/*========================================================================
+ *
+ * storeFileHandle implementation.
+ *
+ *======================================================================*/
+/*
+ * store_createMemoryFile.
+ */
+storeError SAL_CALL store_createMemoryFile (
+ sal_uInt16 nPageSize,
+ storeFileHandle *phFile
+) SAL_THROW_EXTERN_C()
+{
+ if (!phFile)
+ return store_E_InvalidParameter;
+ *phFile = NULL;
+
+ Reference<ILockBytes> xLockBytes;
+
+ storeError eErrCode = MemoryLockBytes_createInstance(xLockBytes);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+ OSL_ASSERT(xLockBytes.is());
+
+ Reference<OStorePageManager> xManager (new OStorePageManager());
+ if (!xManager.is())
+ return store_E_OutOfMemory;
+
+ eErrCode = xManager->initialize (
+ &*xLockBytes, store_AccessCreate, nPageSize);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ xManager->acquire();
+
+ *phFile = (storeFileHandle)&(*xManager);
+ return store_E_None;
+}
+
+/*
+ * store_openFile.
+ */
+storeError SAL_CALL store_openFile (
+ rtl_uString *pFilename,
+ storeAccessMode eAccessMode,
+ sal_uInt16 nPageSize,
+ storeFileHandle *phFile
+) SAL_THROW_EXTERN_C()
+{
+ if (phFile)
+ *phFile = NULL;
+
+ if (!(pFilename && phFile))
+ return store_E_InvalidParameter;
+
+ Reference<ILockBytes> xLockBytes;
+
+ storeError eErrCode = FileLockBytes_createInstance (xLockBytes, pFilename, eAccessMode);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+ OSL_ASSERT(xLockBytes.is());
+
+ Reference<OStorePageManager> xManager (new OStorePageManager());
+ if (!xManager.is())
+ return store_E_OutOfMemory;
+
+ eErrCode = xManager->initialize (
+ &*xLockBytes, eAccessMode, nPageSize);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ xManager->acquire();
+
+ *phFile = (storeFileHandle)&(*xManager);
+ return store_E_None;
+}
+
+/*
+ * store_closeFile.
+ */
+storeError SAL_CALL store_closeFile (
+ storeFileHandle Handle
+) SAL_THROW_EXTERN_C()
+{
+ OStorePageManager *pManager =
+ OStoreHandle<OStorePageManager>::query (Handle);
+ if (!pManager)
+ return store_E_InvalidHandle;
+
+ storeError eErrCode = pManager->close();
+ pManager->release();
+ return eErrCode;
+}
+
+/*
+ * store_flushFile.
+ */
+storeError SAL_CALL store_flushFile (
+ storeFileHandle Handle
+) SAL_THROW_EXTERN_C()
+{
+ OStoreHandle<OStorePageManager> xManager (
+ OStoreHandle<OStorePageManager>::query (Handle));
+ if (!xManager.is())
+ return store_E_InvalidHandle;
+
+ return xManager->flush();
+}
+
+/*
+ * store_getFileRefererCount.
+ */
+storeError SAL_CALL store_getFileRefererCount (
+ storeFileHandle Handle,
+ sal_uInt32 *pnRefCount
+) SAL_THROW_EXTERN_C()
+{
+ OStoreHandle<OStorePageManager> xManager (
+ OStoreHandle<OStorePageManager>::query (Handle));
+ if (!xManager.is())
+ return store_E_InvalidHandle;
+
+ if (!pnRefCount)
+ return store_E_InvalidParameter;
+
+ *pnRefCount = xManager->getRefererCount();
+ return store_E_None;
+}
+
+/*
+ * store_getFileSize.
+ */
+storeError SAL_CALL store_getFileSize (
+ storeFileHandle Handle,
+ sal_uInt32 *pnSize
+) SAL_THROW_EXTERN_C()
+{
+ OStoreHandle<OStorePageManager> xManager (
+ OStoreHandle<OStorePageManager>::query (Handle));
+ if (!xManager.is())
+ return store_E_InvalidHandle;
+
+ if (!pnSize)
+ return store_E_InvalidParameter;
+
+ return xManager->size (*pnSize);
+}
+
+/*
+ * store_rebuildFile.
+ */
+storeError SAL_CALL store_rebuildFile (
+ rtl_uString *pSrcFilename,
+ rtl_uString *pDstFilename
+) SAL_THROW_EXTERN_C()
+{
+ storeError eErrCode = store_E_None;
+
+ if (!(pSrcFilename && pDstFilename))
+ return store_E_InvalidParameter;
+
+ Reference<OStorePageManager> xManager (new OStorePageManager());
+ if (!xManager.is())
+ return store_E_OutOfMemory;
+
+ Reference<ILockBytes> xSrcLB;
+ eErrCode = FileLockBytes_createInstance (xSrcLB, pSrcFilename, store_AccessReadOnly);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+ OSL_ASSERT(xSrcLB.is());
+
+ Reference<ILockBytes> xDstLB;
+ eErrCode = FileLockBytes_createInstance (xDstLB, pDstFilename, store_AccessCreate);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+ OSL_ASSERT(xDstLB.is());
+
+ return xManager->rebuild (&*xSrcLB, &*xDstLB);
+}
+
+/*========================================================================
+ *
+ * storeDirectoryHandle implementation.
+ *
+ *======================================================================*/
+/*
+ * store_openDirectory.
+ */
+storeError SAL_CALL store_openDirectory (
+ storeFileHandle hFile,
+ rtl_uString *pPath,
+ rtl_uString *pName,
+ storeAccessMode eAccessMode,
+ storeDirectoryHandle *phDirectory
+) SAL_THROW_EXTERN_C()
+{
+ storeError eErrCode = store_E_None;
+ if (phDirectory)
+ *phDirectory = NULL;
+
+ OStoreHandle<OStorePageManager> xManager (
+ OStoreHandle<OStorePageManager>::query (hFile));
+ if (!xManager.is())
+ return store_E_InvalidHandle;
+
+ if (!(pPath && pName && phDirectory))
+ return store_E_InvalidParameter;
+
+ Reference<OStoreDirectory_Impl> xDirectory (new OStoreDirectory_Impl());
+ if (!xDirectory.is())
+ return store_E_OutOfMemory;
+
+ OString aPath (pPath->buffer, pPath->length, RTL_TEXTENCODING_UTF8);
+ OString aName (pName->buffer, pName->length, RTL_TEXTENCODING_UTF8);
+
+ eErrCode = xDirectory->create (&*xManager, aPath.pData, aName.pData, eAccessMode);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ xDirectory->acquire();
+
+ *phDirectory = (storeDirectoryHandle)&(*xDirectory);
+ return store_E_None;
+}
+
+/*
+ * store_closeDirectory.
+ */
+storeError SAL_CALL store_closeDirectory (
+ storeDirectoryHandle Handle
+) SAL_THROW_EXTERN_C()
+{
+ OStoreDirectory_Impl *pDirectory =
+ OStoreHandle<OStoreDirectory_Impl>::query (Handle);
+ if (!pDirectory)
+ return store_E_InvalidHandle;
+
+ pDirectory->release();
+ return store_E_None;
+}
+
+/*
+ * store_findFirst.
+ */
+storeError SAL_CALL store_findFirst (
+ storeDirectoryHandle Handle,
+ storeFindData *pFindData
+) SAL_THROW_EXTERN_C()
+{
+ OStoreHandle<OStoreDirectory_Impl> xDirectory (
+ OStoreHandle<OStoreDirectory_Impl>::query (Handle));
+ if (!xDirectory.is())
+ return store_E_InvalidHandle;
+
+ if (!pFindData)
+ return store_E_InvalidParameter;
+
+ // Initialize FindData.
+ rtl_zeroMemory (pFindData, sizeof (storeFindData));
+
+ // Find first.
+ pFindData->m_nReserved = (sal_uInt32)(~0);
+ return xDirectory->iterate (*pFindData);
+}
+
+/*
+ * store_findNext.
+ */
+storeError SAL_CALL store_findNext (
+ storeDirectoryHandle Handle,
+ storeFindData *pFindData
+) SAL_THROW_EXTERN_C()
+{
+ OStoreHandle<OStoreDirectory_Impl> xDirectory (
+ OStoreHandle<OStoreDirectory_Impl>::query (Handle));
+ if (!xDirectory.is())
+ return store_E_InvalidHandle;
+
+ if (!pFindData)
+ return store_E_InvalidParameter;
+
+ // Check FindData.
+ if (!pFindData->m_nReserved)
+ return store_E_NoMoreFiles;
+
+ // Find next.
+ pFindData->m_nReserved -= 1;
+ return xDirectory->iterate (*pFindData);
+}
+
+/*========================================================================
+ *
+ * storeStreamHandle implementation.
+ *
+ *======================================================================*/
+/*
+ * store_openStream
+ */
+storeError SAL_CALL store_openStream (
+ storeFileHandle hFile,
+ rtl_uString *pPath,
+ rtl_uString *pName,
+ storeAccessMode eAccessMode,
+ storeStreamHandle *phStream
+) SAL_THROW_EXTERN_C()
+{
+ storeError eErrCode = store_E_None;
+ if (phStream)
+ *phStream = NULL;
+
+ OStoreHandle<OStorePageManager> xManager (
+ OStoreHandle<OStorePageManager>::query (hFile));
+ if (!xManager.is())
+ return store_E_InvalidHandle;
+
+ if (!(pPath && pName && phStream))
+ return store_E_InvalidParameter;
+
+ Reference<OStoreLockBytes> xLockBytes (new OStoreLockBytes());
+ if (!xLockBytes.is())
+ return store_E_OutOfMemory;
+
+ OString aPath (pPath->buffer, pPath->length, RTL_TEXTENCODING_UTF8);
+ OString aName (pName->buffer, pName->length, RTL_TEXTENCODING_UTF8);
+
+ eErrCode = xLockBytes->create (&*xManager, aPath.pData, aName.pData, eAccessMode);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ xLockBytes->acquire();
+
+ *phStream = (storeStreamHandle)&(*xLockBytes);
+ return store_E_None;
+}
+
+/*
+ * store_closeStream.
+ */
+storeError SAL_CALL store_closeStream (
+ storeStreamHandle Handle
+) SAL_THROW_EXTERN_C()
+{
+ OStoreLockBytes *pLockBytes =
+ OStoreHandle<OStoreLockBytes>::query (Handle);
+ if (!pLockBytes)
+ return store_E_InvalidHandle;
+
+ pLockBytes->release();
+ return store_E_None;
+}
+
+/*
+ * store_readStream.
+ */
+storeError SAL_CALL store_readStream (
+ storeStreamHandle Handle,
+ sal_uInt32 nOffset,
+ void *pBuffer,
+ sal_uInt32 nBytes,
+ sal_uInt32 *pnDone
+) SAL_THROW_EXTERN_C()
+{
+ OStoreHandle<OStoreLockBytes> xLockBytes (
+ OStoreHandle<OStoreLockBytes>::query (Handle));
+ if (!xLockBytes.is())
+ return store_E_InvalidHandle;
+
+ if (!(pBuffer && pnDone))
+ return store_E_InvalidParameter;
+
+ return xLockBytes->readAt (nOffset, pBuffer, nBytes, *pnDone);
+}
+
+/*
+ * store_writeStream.
+ */
+storeError SAL_CALL store_writeStream (
+ storeStreamHandle Handle,
+ sal_uInt32 nOffset,
+ const void *pBuffer,
+ sal_uInt32 nBytes,
+ sal_uInt32 *pnDone
+) SAL_THROW_EXTERN_C()
+{
+ OStoreHandle<OStoreLockBytes> xLockBytes (
+ OStoreHandle<OStoreLockBytes>::query (Handle));
+ if (!xLockBytes.is())
+ return store_E_InvalidHandle;
+
+ if (!(pBuffer && pnDone))
+ return store_E_InvalidParameter;
+
+ return xLockBytes->writeAt (nOffset, pBuffer, nBytes, *pnDone);
+}
+
+/*
+ * store_flushStream.
+ */
+storeError SAL_CALL store_flushStream (
+ storeStreamHandle Handle
+) SAL_THROW_EXTERN_C()
+{
+ OStoreHandle<OStoreLockBytes> xLockBytes (
+ OStoreHandle<OStoreLockBytes>::query (Handle));
+ if (!xLockBytes.is())
+ return store_E_InvalidHandle;
+
+ return xLockBytes->flush();
+}
+
+/*
+ * store_getStreamSize.
+ */
+storeError SAL_CALL store_getStreamSize (
+ storeStreamHandle Handle,
+ sal_uInt32 *pnSize
+) SAL_THROW_EXTERN_C()
+{
+ OStoreHandle<OStoreLockBytes> xLockBytes (
+ OStoreHandle<OStoreLockBytes>::query (Handle));
+ if (!xLockBytes.is())
+ return store_E_InvalidHandle;
+
+ if (!pnSize)
+ return store_E_InvalidParameter;
+
+ return xLockBytes->stat (*pnSize);
+}
+
+/*
+ * store_setStreamSize.
+ */
+storeError SAL_CALL store_setStreamSize (
+ storeStreamHandle Handle,
+ sal_uInt32 nSize
+) SAL_THROW_EXTERN_C()
+{
+ OStoreHandle<OStoreLockBytes> xLockBytes (
+ OStoreHandle<OStoreLockBytes>::query (Handle));
+ if (!xLockBytes.is())
+ return store_E_InvalidHandle;
+
+ return xLockBytes->setSize (nSize);
+}
+
+/*========================================================================
+ *
+ * Common storeDirectoryHandle and storeStreamHandle operations.
+ *
+ *======================================================================*/
+/*
+ * store_attrib.
+ */
+storeError SAL_CALL store_attrib (
+ storeFileHandle Handle,
+ rtl_uString *pPath,
+ rtl_uString *pName,
+ sal_uInt32 nMask1,
+ sal_uInt32 nMask2,
+ sal_uInt32 *pnAttrib
+) SAL_THROW_EXTERN_C()
+{
+ storeError eErrCode = store_E_None;
+ if (pnAttrib)
+ *pnAttrib = 0;
+
+ OStoreHandle<OStorePageManager> xManager (
+ OStoreHandle<OStorePageManager>::query (Handle));
+ if (!xManager.is())
+ return store_E_InvalidHandle;
+
+ if (!(pPath && pName))
+ return store_E_InvalidParameter;
+
+ // Setup page key.
+ OString aPath (pPath->buffer, pPath->length, RTL_TEXTENCODING_UTF8);
+ OString aName (pName->buffer, pName->length, RTL_TEXTENCODING_UTF8);
+ OStorePageKey aKey;
+
+ eErrCode = OStorePageManager::namei (aPath.pData, aName.pData, aKey);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ // Obtain or modify page attributes.
+ sal_uInt32 nAttrib = 0;
+ eErrCode = xManager->attrib (aKey, nMask1, nMask2, nAttrib);
+ if (pnAttrib)
+ *pnAttrib = nAttrib;
+ return eErrCode;
+}
+
+/*
+ * store_link.
+ */
+storeError SAL_CALL store_link (
+ storeFileHandle Handle,
+ rtl_uString *pSrcPath, rtl_uString *pSrcName,
+ rtl_uString *pDstPath, rtl_uString *pDstName
+) SAL_THROW_EXTERN_C()
+{
+ storeError eErrCode = store_E_None;
+
+ OStoreHandle<OStorePageManager> xManager (
+ OStoreHandle<OStorePageManager>::query (Handle));
+ if (!xManager.is())
+ return store_E_InvalidHandle;
+
+ if (!(pSrcPath && pSrcName))
+ return store_E_InvalidParameter;
+
+ if (!(pDstPath && pDstName))
+ return store_E_InvalidParameter;
+
+ // Setup 'Source' page key.
+ OString aSrcPath (
+ pSrcPath->buffer, pSrcPath->length, RTL_TEXTENCODING_UTF8);
+ OString aSrcName (
+ pSrcName->buffer, pSrcName->length, RTL_TEXTENCODING_UTF8);
+ OStorePageKey aSrcKey;
+
+ eErrCode = OStorePageManager::namei (
+ aSrcPath.pData, aSrcName.pData, aSrcKey);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ // Setup 'Destination' page key.
+ OString aDstPath (
+ pDstPath->buffer, pDstPath->length, RTL_TEXTENCODING_UTF8);
+ OString aDstName (
+ pDstName->buffer, pDstName->length, RTL_TEXTENCODING_UTF8);
+ OStorePageKey aDstKey;
+
+ eErrCode = OStorePageManager::namei (
+ aDstPath.pData, aDstName.pData, aDstKey);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ // Link 'Source' hard to 'Destination'.
+ return xManager->link (aSrcKey, aDstKey);
+}
+
+/*
+ * store_symlink.
+ */
+storeError SAL_CALL store_symlink (
+ storeFileHandle Handle,
+ rtl_uString *pSrcPath, rtl_uString *pSrcName,
+ rtl_uString *pDstPath, rtl_uString *pDstName
+) SAL_THROW_EXTERN_C()
+{
+ storeError eErrCode = store_E_None;
+
+ OStoreHandle<OStorePageManager> xManager (
+ OStoreHandle<OStorePageManager>::query (Handle));
+ if (!xManager.is())
+ return store_E_InvalidHandle;
+
+ if (!(pSrcPath && pSrcName))
+ return store_E_InvalidParameter;
+
+ if (!(pDstPath && pDstName))
+ return store_E_InvalidParameter;
+
+ // Setup 'Destination' page key.
+ OString aDstPath (
+ pDstPath->buffer, pDstPath->length, RTL_TEXTENCODING_UTF8);
+ OString aDstName (
+ pDstName->buffer, pDstName->length, RTL_TEXTENCODING_UTF8);
+ OStorePageKey aDstKey;
+
+ eErrCode = OStorePageManager::namei (
+ aDstPath.pData, aDstName.pData, aDstKey);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ // Insert 'Source' as symlink to 'Destination'.
+ OString aSrcPath (
+ pSrcPath->buffer, pSrcPath->length, RTL_TEXTENCODING_UTF8);
+ OString aSrcName (
+ pSrcName->buffer, pSrcName->length, RTL_TEXTENCODING_UTF8);
+
+ return xManager->symlink (aSrcPath.pData, aSrcName.pData, aDstKey);
+}
+
+/*
+ * store_rename.
+ */
+storeError SAL_CALL store_rename (
+ storeFileHandle Handle,
+ rtl_uString *pSrcPath, rtl_uString *pSrcName,
+ rtl_uString *pDstPath, rtl_uString *pDstName
+) SAL_THROW_EXTERN_C()
+{
+ storeError eErrCode = store_E_None;
+
+ OStoreHandle<OStorePageManager> xManager (
+ OStoreHandle<OStorePageManager>::query (Handle));
+ if (!xManager.is())
+ return store_E_InvalidHandle;
+
+ if (!(pSrcPath && pSrcName))
+ return store_E_InvalidParameter;
+
+ if (!(pDstPath && pDstName))
+ return store_E_InvalidParameter;
+
+ // Setup 'Source' page key.
+ OString aSrcPath (
+ pSrcPath->buffer, pSrcPath->length, RTL_TEXTENCODING_UTF8);
+ OString aSrcName (
+ pSrcName->buffer, pSrcName->length, RTL_TEXTENCODING_UTF8);
+ OStorePageKey aSrcKey;
+
+ eErrCode = OStorePageManager::namei (
+ aSrcPath.pData, aSrcName.pData, aSrcKey);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ // Rename 'Source' into 'Destination'.
+ OString aDstPath (
+ pDstPath->buffer, pDstPath->length, RTL_TEXTENCODING_UTF8);
+ OString aDstName (
+ pDstName->buffer, pDstName->length, RTL_TEXTENCODING_UTF8);
+
+ return xManager->rename (aSrcKey, aDstPath.pData, aDstName.pData);
+}
+
+/*
+ * store_remove.
+ */
+storeError SAL_CALL store_remove (
+ storeFileHandle Handle,
+ rtl_uString *pPath,
+ rtl_uString *pName
+) SAL_THROW_EXTERN_C()
+{
+ storeError eErrCode = store_E_None;
+
+ OStoreHandle<OStorePageManager> xManager (
+ OStoreHandle<OStorePageManager>::query (Handle));
+ if (!xManager.is())
+ return store_E_InvalidHandle;
+
+ if (!(pPath && pName))
+ return store_E_InvalidParameter;
+
+ // Setup page key.
+ OString aPath (pPath->buffer, pPath->length, RTL_TEXTENCODING_UTF8);
+ OString aName (pName->buffer, pName->length, RTL_TEXTENCODING_UTF8);
+ OStorePageKey aKey;
+
+ eErrCode = OStorePageManager::namei (aPath.pData, aName.pData, aKey);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ // Remove.
+ return xManager->remove (aKey);
+}
diff --git a/store/source/storlckb.cxx b/store/source/storlckb.cxx
new file mode 100644
index 000000000000..fc028f1da688
--- /dev/null
+++ b/store/source/storlckb.cxx
@@ -0,0 +1,454 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: storlckb.cxx,v $
+ * $Revision: 1.9 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_store.hxx"
+
+#include "storlckb.hxx"
+
+#include "sal/types.h"
+#include "sal/macros.h"
+#include "rtl/string.h"
+#include "rtl/ref.hxx"
+#include "osl/mutex.hxx"
+
+#include "store/types.h"
+#include "object.hxx"
+
+#include "storbase.hxx"
+#include "stordata.hxx"
+#include "storpage.hxx"
+
+using namespace store;
+
+/*========================================================================
+ *
+ * OStoreLockBytes implementation.
+ *
+ *======================================================================*/
+const sal_uInt32 OStoreLockBytes::m_nTypeId = sal_uInt32(0x94190310);
+
+/*
+ * OStoreLockBytes.
+ */
+OStoreLockBytes::OStoreLockBytes (void)
+ : m_xManager (),
+ m_xNode (),
+ m_bWriteable (false)
+{
+}
+
+/*
+ * ~OStoreLockBytes.
+ */
+OStoreLockBytes::~OStoreLockBytes (void)
+{
+ if (m_xManager.is())
+ {
+ if (m_xNode.is())
+ {
+ OStorePageDescriptor aDescr (m_xNode->m_aDescr);
+ if (m_bWriteable)
+ m_xManager->releasePage (aDescr, store_AccessReadWrite);
+ else
+ m_xManager->releasePage (aDescr, store_AccessReadOnly);
+ }
+ }
+}
+
+/*
+ * isKindOf.
+ */
+sal_Bool SAL_CALL OStoreLockBytes::isKindOf (sal_uInt32 nTypeId)
+{
+ return (nTypeId == m_nTypeId);
+}
+
+/*
+ * create.
+ */
+storeError OStoreLockBytes::create (
+ OStorePageManager *pManager,
+ rtl_String *pPath,
+ rtl_String *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 != store_AccessReadOnly)
+ eErrCode = xManager->acquirePage (xNode->m_aDescr, store_AccessReadWrite);
+ else
+ eErrCode = xManager->acquirePage (xNode->m_aDescr, store_AccessReadOnly);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ // ...
+ m_xManager = xManager;
+ m_xNode = xNode;
+ 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_xNode.get());
+
+ sal_uInt32 nDataLen = aPage.dataLength();
+ if ((nOffset + nBytes) > nDataLen)
+ nBytes = nDataLen - nOffset;
+
+ // Read data.
+ OStoreDataPageObject aData;
+ sal_uInt8 *pData = (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);
+ nLength = SAL_MIN(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);
+ nLength = SAL_MIN(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;
+}
+
+/*
+ * 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_xNode.get());
+ const sal_uInt8 *pData = (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);
+ nLength = SAL_MIN(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.
+// @@@ loadOrCreate()
+ 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.
+ nLength = SAL_MIN(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;
+}
+
+/*
+ * 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_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());
+}
+
+/*
+ * stat.
+ */
+storeError OStoreLockBytes::stat (sal_uInt32 &rnSize)
+{
+ rnSize = 0;
+
+ if (!m_xManager.is())
+ return store_E_InvalidAccess;
+
+ OStoreDirectoryPageObject aPage (m_xNode.get());
+ rnSize = aPage.dataLength();
+ return store_E_None;
+}
diff --git a/store/source/storlckb.hxx b/store/source/storlckb.hxx
new file mode 100644
index 000000000000..4a0dbfde873a
--- /dev/null
+++ b/store/source/storlckb.hxx
@@ -0,0 +1,174 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: storlckb.hxx,v $
+ * $Revision: 1.6 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _STORE_STORLCKB_HXX_
+#define _STORE_STORLCKB_HXX_ "$Revision: 1.6.8.1 $"
+
+#include "sal/types.h"
+
+#include "rtl/ustring.h"
+#include "rtl/ref.hxx"
+
+#include "object.hxx"
+#include "storbase.hxx"
+#include "storpage.hxx"
+
+namespace store
+{
+
+struct OStoreDataPageData;
+struct OStoreDirectoryPageData;
+
+/*========================================================================
+ *
+ * OStoreLockBytes interface.
+ *
+ *======================================================================*/
+class OStoreLockBytes : public store::OStoreObject
+{
+public:
+ /** Construction.
+ */
+ OStoreLockBytes (void);
+
+ /** create (two-phase construction).
+ * @param pManager [in]
+ * @param pPath [in]
+ * @param pName [in]
+ * @param eMode [in]
+ * @return store_E_None upon success
+ */
+ storeError create (
+ OStorePageManager *pManager,
+ rtl_String *pPath,
+ rtl_String *pName,
+ storeAccessMode eAccessMode);
+
+ /** Read at Offset into Buffer.
+ * @param nOffset [in]
+ * @param pBuffer [out]
+ * @param nBytes [in]
+ * @param rnDone [out]
+ * @return store_E_None upon success
+ */
+ storeError readAt (
+ sal_uInt32 nOffset,
+ void *pBuffer,
+ sal_uInt32 nBytes,
+ sal_uInt32 &rnDone);
+
+ /** Write at Offset from Buffer.
+ * @param nOffset [in]
+ * @param pBuffer [in]
+ * @param nBytes [in]
+ * @param rnDone [out]
+ * @return store_E_None upon success
+ */
+ storeError writeAt (
+ sal_uInt32 nOffset,
+ const void *pBuffer,
+ sal_uInt32 nBytes,
+ sal_uInt32 &rnDone);
+
+ /** flush.
+ * @return store_E_None upon success
+ */
+ storeError flush (void);
+
+ /** setSize.
+ * @param nSize [in]
+ * @return store_E_None upon success
+ */
+ storeError setSize (sal_uInt32 nSize);
+
+ /** stat.
+ * @paran rnSize [out]
+ * @return store_E_None upon success
+ */
+ storeError stat (sal_uInt32 &rnSize);
+
+ /** IStoreHandle.
+ */
+ virtual sal_Bool SAL_CALL isKindOf (sal_uInt32 nMagic);
+
+protected:
+ /** Destruction (OReference).
+ */
+ virtual ~OStoreLockBytes (void);
+
+private:
+ /** IStoreHandle TypeId.
+ */
+ static const sal_uInt32 m_nTypeId;
+
+ /** IStoreHandle query() template specialization.
+ */
+ friend OStoreLockBytes*
+ SAL_CALL query<> (IStoreHandle *pHandle, OStoreLockBytes*);
+
+ /** Representation.
+ */
+ rtl::Reference<OStorePageManager> m_xManager;
+
+ typedef OStoreDataPageData data;
+ typedef OStoreDirectoryPageData inode;
+
+ typedef PageHolderObject< inode > inode_holder_type;
+ inode_holder_type m_xNode;
+
+ bool m_bWriteable;
+
+ /** Not implemented.
+ */
+ OStoreLockBytes (const OStoreLockBytes&);
+ OStoreLockBytes& operator= (const OStoreLockBytes&);
+};
+
+template<> inline OStoreLockBytes*
+SAL_CALL query (IStoreHandle *pHandle, OStoreLockBytes*)
+{
+ if (pHandle && pHandle->isKindOf (OStoreLockBytes::m_nTypeId))
+ {
+ // Handle is kind of OStoreLockBytes.
+ return static_cast<OStoreLockBytes*>(pHandle);
+ }
+ return 0;
+}
+
+/*========================================================================
+ *
+ * The End.
+ *
+ *======================================================================*/
+
+} // namespace store
+
+#endif /* !_STORE_STORLCKB_HXX_ */
+
diff --git a/store/source/storpage.cxx b/store/source/storpage.cxx
new file mode 100644
index 000000000000..b112d5bb8fdd
--- /dev/null
+++ b/store/source/storpage.cxx
@@ -0,0 +1,1066 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: storpage.cxx,v $
+ * $Revision: 1.8 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_store.hxx"
+
+#include "storpage.hxx"
+
+#include "sal/types.h"
+#include "rtl/string.h"
+#include "rtl/ref.hxx"
+#include "osl/diagnose.h"
+#include "osl/mutex.hxx"
+
+#include "store/types.h"
+
+#include "object.hxx"
+#include "lockbyte.hxx"
+
+#include "storbase.hxx"
+#include "stordata.hxx"
+#include "stortree.hxx"
+
+using namespace store;
+
+/*========================================================================
+ *
+ * OStorePageManager implementation.
+ *
+ *======================================================================*/
+const sal_uInt32 OStorePageManager::m_nTypeId = sal_uInt32(0x62190120);
+
+/*
+ * OStorePageManager.
+ */
+OStorePageManager::OStorePageManager (void)
+{
+}
+
+/*
+ * ~OStorePageManager.
+ */
+OStorePageManager::~OStorePageManager (void)
+{
+}
+
+/*
+ * isKindOf.
+ */
+sal_Bool SAL_CALL OStorePageManager::isKindOf (sal_uInt32 nTypeId)
+{
+ return (nTypeId == m_nTypeId);
+}
+
+/*
+ * initialize (two-phase construction).
+ * Precond: none.
+ */
+storeError OStorePageManager::initialize (
+ ILockBytes * pLockBytes,
+ storeAccessMode eAccessMode,
+ sal_uInt16 & rnPageSize)
+{
+ // Acquire exclusive access.
+ osl::MutexGuard aGuard(*this);
+
+ // Check arguments.
+ if (!pLockBytes)
+ return store_E_InvalidParameter;
+
+ // Initialize base.
+ storeError eErrCode = base::initialize (pLockBytes, eAccessMode, rnPageSize);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ // Check for (not) writeable.
+ if (!base::isWriteable())
+ {
+ // Readonly. Load RootNode.
+ return base::loadObjectAt (m_aRoot, rnPageSize);
+ }
+
+ // Writeable. Load or Create RootNode.
+ eErrCode = m_aRoot.loadOrCreate (rnPageSize, *this);
+ if (eErrCode == store_E_Pending)
+ {
+ // Creation notification.
+ PageHolderObject< page > xRoot (m_aRoot.get());
+
+ // Pre-allocate left most entry (ugly, but we can't insert to left).
+ OStorePageKey aKey (rtl_crc32 (0, "/", 1), 0);
+ xRoot->insert (0, entry(aKey));
+
+ // Save RootNode.
+ eErrCode = base::saveObjectAt (m_aRoot, rnPageSize);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ // Flush for robustness.
+ (void) base::flush();
+ }
+
+ // Done.
+ return eErrCode;
+}
+
+/*
+ * find_lookup (w/o split()).
+ * Internal: Precond: initialized, readable, exclusive access.
+ */
+storeError OStorePageManager::find_lookup (
+ OStoreBTreeNodeObject & rNode,
+ sal_uInt16 & rIndex,
+ OStorePageKey const & rKey)
+{
+ // Find Node and Index.
+ storeError eErrCode = m_aRoot.find_lookup (rNode, rIndex, rKey, *this);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ // Greater or Equal.
+ PageHolderObject< page > xPage (rNode.get());
+ OSL_POSTCOND(rIndex < xPage->usageCount(), "store::PageManager::find_lookup(): logic error");
+ entry e (xPage->m_pData[rIndex]);
+
+ // Check for exact match.
+ if (e.compare(entry(rKey)) != entry::COMPARE_EQUAL)
+ {
+ // Page not present.
+ return store_E_NotExists;
+ }
+
+ // Check address.
+ if (e.m_aLink.location() == STORE_PAGE_NULL)
+ {
+ // Page not present.
+ return store_E_NotExists;
+ }
+
+ return store_E_None;
+}
+
+/*
+ * remove_Impl (possibly down from root).
+ * Internal: Precond: initialized, writeable, exclusive access.
+ */
+#if 0 /* EXP */
+storeError OStorePageManager::remove_Impl (entry & rEntry)
+{
+ // Find Node and Index.
+ OStoreBTreeNodeObject aNode;
+ sal_uInt16 nIndex = 0;
+ eErrCode = m_aRoot.find_lookup (aNode, nIndex, entry::CompareGreater(rEntry), *this);
+
+ // @@@
+
+ PageHolderObject< page > xPage (aNode.get());
+ page & rPage = (*xPage);
+
+ // Check current page index.
+ sal_uInt16 i = rPage.find (rEntry), n = rPage.usageCount();
+ if (!(i < n))
+ {
+ // Path to entry not exists (Must not happen(?)).
+ return store_E_NotExists;
+ }
+
+ // Compare entry.
+ entry::CompareResult result = rEntry.compare (rPage.m_pData[i]);
+
+ for (; result == entry::COMPARE_GREATER && xPage->depth() > 0; )
+ {
+ // Check next node address.
+ sal_uInt32 const nAddr = rPage.m_pData[i].m_aLink.location();
+ if (nAddr == STORE_PAGE_NULL)
+ {
+ // Path to entry not exists (Must not happen(?)).
+ return store_E_NotExists;
+ }
+
+ // Load next node page.
+ eErrCode = loadObjectAt (aNode, nAddr);
+
+ PageHolderObject< page > xNext (aNode.get());
+ xNext.swap (xPage);
+ }
+
+ aNode.remove (nIndex, rEntry, *this);
+
+
+ do
+ {
+ // Load next node page.
+ eErrCode = loadObjectAt (aNode, nAddr);
+
+ page const & rPage = (*xPage);
+
+ // Check current page index.
+ sal_uInt16 i = rPage.find (rEntry), n = rPage.usageCount();
+ if (!(i < n))
+ {
+ // Path to entry not exists (Must not happen(?)).
+ return store_E_NotExists;
+ }
+
+ // Compare entry.
+ result = rEntry.compare (rPage.m_pData[i]);
+
+ } while (result == entry::COMPATE_GREATER);
+}
+#endif /* EXP */
+
+storeError OStorePageManager::remove_Impl (entry & rEntry)
+{
+ OStoreBTreeNodeObject aNode (m_aRoot.get());
+
+ // Check current page index.
+ PageHolderObject< page > xPage (aNode.get());
+ sal_uInt16 i = xPage->find (rEntry), n = xPage->usageCount();
+ if (!(i < n))
+ {
+ // Path to entry not exists (Must not happen(?)).
+ return store_E_NotExists;
+ }
+
+ // Compare entry.
+ entry::CompareResult result = rEntry.compare (xPage->m_pData[i]);
+
+ // Iterate down until equal match.
+ while ((result == entry::COMPARE_GREATER) && (xPage->depth() > 0))
+ {
+ // Check link address.
+ sal_uInt32 const nAddr = xPage->m_pData[i].m_aLink.location();
+ if (nAddr == STORE_PAGE_NULL)
+ {
+ // Path to entry not exists (Must not happen(?)).
+ return store_E_NotExists;
+ }
+
+ // Load link page.
+ storeError eErrCode = loadObjectAt (aNode, nAddr);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ PageHolderObject< page > xNext (aNode.get());
+ xNext.swap (xPage);
+
+ // Check index.
+ i = xPage->find (rEntry), n = xPage->usageCount();
+ if (!(i < n))
+ {
+ // Path to entry not exists (Must not happen(?)).
+ return store_E_NotExists;
+ }
+
+ // Compare entry.
+ result = rEntry.compare (xPage->m_pData[i]);
+ }
+
+ OSL_POSTCOND(
+ result != entry::COMPARE_LESS,
+ "OStorePageManager::remove(): find failed");
+
+ // Check entry comparison.
+ if (result == entry::COMPARE_LESS)
+ {
+ // Must not happen.
+ return store_E_Unknown;
+ }
+
+ // Remove down from current page (recursive).
+ return aNode.remove (i, rEntry, *this);
+}
+
+/*
+ * namei.
+ * Precond: none (static).
+ */
+storeError OStorePageManager::namei (
+ const rtl_String *pPath, const rtl_String *pName, OStorePageKey &rKey)
+{
+ // Check parameter.
+ if (!(pPath && pName))
+ return store_E_InvalidParameter;
+
+ // Check name length.
+ if (!(pName->length < STORE_MAXIMUM_NAMESIZE))
+ return store_E_NameTooLong;
+
+ // Transform pathname into key.
+ rKey.m_nLow = store::htonl(rtl_crc32 (0, pName->buffer, pName->length));
+ rKey.m_nHigh = store::htonl(rtl_crc32 (0, pPath->buffer, pPath->length));
+
+ // Done.
+ return store_E_None;
+}
+
+/*
+ * iget.
+ * Precond: initialized.
+ */
+storeError OStorePageManager::iget (
+ OStoreDirectoryPageObject & rPage,
+ sal_uInt32 nAttrib,
+ const rtl_String * pPath,
+ const rtl_String * pName,
+ storeAccessMode eMode)
+{
+ // Acquire exclusive access.
+ osl::MutexGuard aGuard(*this);
+
+ // Check precond.
+ if (!self::isValid())
+ return store_E_InvalidAccess;
+
+ // Setup inode page key.
+ OStorePageKey aKey;
+ storeError eErrCode = 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 = store::htonl(rtl_crc32 (store::ntohl(aKey.m_nLow), "/", 1));
+ }
+
+ // Load inode page.
+ eErrCode = load_dirpage_Impl (aKey, rPage);
+ 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 (!base::isWriteable())
+ return store_E_AccessViolation;
+
+ // Create inode page.
+ eErrCode = rPage.construct< inode >(base::allocator());
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ // Setup inode nameblock.
+ PageHolderObject< inode > xPage (rPage.get());
+
+ rPage.key (aKey);
+ rPage.attrib (nAttrib);
+
+ memcpy (
+ &(xPage->m_aNameBlock.m_pData[0]),
+ pName->buffer, pName->length);
+
+ // Save inode page.
+ eErrCode = save_dirpage_Impl (aKey, rPage);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+ }
+
+ // Check for symbolic link.
+ if (rPage.attrib() & STORE_ATTRIB_ISLINK)
+ {
+ // Obtain 'Destination' page key.
+ PageHolderObject< inode > xPage (rPage.get());
+ OStorePageKey aDstKey;
+ memcpy (&aDstKey, &(xPage->m_pData[0]), sizeof(aDstKey));
+
+ // Load 'Destination' inode.
+ eErrCode = load_dirpage_Impl (aDstKey, rPage);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+ }
+
+ // Done.
+ return store_E_None;
+}
+
+/*
+ * iterate.
+ * Precond: initialized.
+ * ToDo: skip hardlink entries.
+ */
+storeError OStorePageManager::iterate (
+ OStorePageKey & rKey,
+ OStorePageLink & rLink,
+ sal_uInt32 & rAttrib)
+{
+ // Acquire exclusive access.
+ osl::MutexGuard aGuard(*this);
+
+ // Check precond.
+ if (!self::isValid())
+ return store_E_InvalidAccess;
+
+ // Find NodePage and Index.
+ OStoreBTreeNodeObject aNode;
+ sal_uInt16 i = 0;
+ storeError eErrCode = m_aRoot.find_lookup (aNode, i, rKey, *this);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ // GreaterEqual. Found next entry.
+ PageHolderObject< page > xNode (aNode.get());
+ entry e (xNode->m_pData[i]);
+
+ // Setup result.
+ rKey = e.m_aKey;
+ rLink = e.m_aLink;
+ rAttrib = store::ntohl(e.m_nAttrib);
+
+ // Done.
+ return store_E_None;
+}
+
+/*
+ * load => private: iget() @@@
+ * Internal: Precond: initialized, exclusive access.
+ */
+storeError OStorePageManager::load_dirpage_Impl (
+ const OStorePageKey &rKey,
+ OStoreDirectoryPageObject &rPage)
+{
+ // Find Node and Index.
+ OStoreBTreeNodeObject aNode;
+ sal_uInt16 i = 0;
+ storeError eErrCode = find_lookup (aNode, i, rKey);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ // Existing entry. Load page.
+ PageHolderObject< page > xNode (aNode.get());
+ entry e (xNode->m_pData[i]);
+ return loadObjectAt (rPage, e.m_aLink.location());
+}
+
+/*
+ * save => private: iget(), rebuild() @@@
+ * Internal: Precond: initialized, writeable, exclusive access.
+ */
+storeError OStorePageManager::save_dirpage_Impl (
+ const OStorePageKey &rKey,
+ OStoreDirectoryPageObject &rPage)
+{
+ // Find NodePage and Index.
+ node aNode;
+ sal_uInt16 i = 0;
+
+ storeError eErrCode = m_aRoot.find_insert (aNode, i, rKey, *this);
+ PageHolderObject< page > xNode (aNode.get());
+ if (eErrCode != store_E_None)
+ {
+ if (eErrCode != store_E_AlreadyExists)
+ return eErrCode;
+
+ // Existing entry.
+ entry e (xNode->m_pData[i]);
+ if (e.m_aLink.location() != STORE_PAGE_NULL)
+ {
+ // Save page to existing location.
+ return saveObjectAt (rPage, e.m_aLink.location());
+ }
+
+ // Allocate page.
+ eErrCode = base::allocate (rPage);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ // Update page location.
+ xNode->m_pData[i].m_aLink = rPage.location();
+
+ // Save modified NodePage.
+ return saveObjectAt (aNode, aNode.location());
+ }
+
+ // Allocate page.
+ eErrCode = base::allocate (rPage);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ // Insert.
+ OStorePageLink aLink (rPage.location());
+ xNode->insert (i + 1, entry (rKey, aLink));
+
+ // Save modified NodePage.
+ return saveObjectAt (aNode, aNode.location());
+}
+
+/*
+ * attrib [nAttrib = ((nAttrib & ~nMask1) | nMask2)].
+ * Precond: initialized.
+ */
+storeError OStorePageManager::attrib (
+ const OStorePageKey &rKey,
+ sal_uInt32 nMask1,
+ sal_uInt32 nMask2,
+ sal_uInt32 &rAttrib)
+{
+ // Acquire exclusive access.
+ osl::MutexGuard aGuard(*this);
+
+ // Check precond.
+ if (!self::isValid())
+ return store_E_InvalidAccess;
+
+ // Find NodePage and index.
+ OStoreBTreeNodeObject aNode;
+ sal_uInt16 i = 0;
+ storeError eErrCode = find_lookup (aNode, i, rKey);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ // Existing entry.
+ PageHolderObject< page > xNode (aNode.get());
+ entry e (xNode->m_pData[i]);
+ if (nMask1 != nMask2)
+ {
+ // Evaluate new attributes.
+ sal_uInt32 nAttrib = store::ntohl(e.m_nAttrib);
+
+ nAttrib &= ~nMask1;
+ nAttrib |= nMask2;
+
+ if (store::htonl(nAttrib) != e.m_nAttrib)
+ {
+ // Check access mode.
+ if (base::isWriteable())
+ {
+ // Set new attributes.
+ e.m_nAttrib = store::htonl(nAttrib);
+ xNode->m_pData[i] = e;
+
+ // Save modified NodePage.
+ eErrCode = saveObjectAt (aNode, aNode.location());
+ }
+ else
+ {
+ // Access denied.
+ eErrCode = store_E_AccessViolation;
+ }
+ }
+ }
+
+ // Obtain current attributes.
+ rAttrib = store::ntohl(e.m_nAttrib);
+ return eErrCode;
+}
+
+/*
+ * link (insert 'Source' as hardlink to 'Destination').
+ * Precond: initialized, writeable.
+ */
+storeError OStorePageManager::link (
+ const OStorePageKey &rSrcKey,
+ const OStorePageKey &rDstKey)
+{
+ // Acquire exclusive access.
+ osl::MutexGuard aGuard(*this);
+
+ // Check precond.
+ if (!self::isValid())
+ return store_E_InvalidAccess;
+
+ if (!base::isWriteable())
+ return store_E_AccessViolation;
+
+ // Find 'Destination' NodePage and Index.
+ OStoreBTreeNodeObject aDstNode;
+ sal_uInt16 i = 0;
+ storeError eErrCode = find_lookup (aDstNode, i, rDstKey);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ // Existing 'Destination' entry.
+ PageHolderObject< page > xDstNode (aDstNode.get());
+ entry e (xDstNode->m_pData[i]);
+ OStorePageLink aDstLink (e.m_aLink);
+
+ // Find 'Source' NodePage and Index.
+ OStoreBTreeNodeObject aSrcNode;
+ eErrCode = m_aRoot.find_insert (aSrcNode, i, rSrcKey, *this);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ // Insert 'Source' entry.
+ PageHolderObject< page > xSrcNode (aSrcNode.get());
+ xSrcNode->insert (i + 1, entry (rSrcKey, aDstLink, STORE_ATTRIB_ISLINK));
+ return saveObjectAt (aSrcNode, aSrcNode.location());
+}
+
+/*
+ * symlink (insert 'Source' DirectoryPage as symlink to 'Destination').
+ * Precond: initialized, writeable.
+ */
+storeError OStorePageManager::symlink (
+ const rtl_String *pSrcPath,
+ const rtl_String *pSrcName,
+ const OStorePageKey &rDstKey)
+{
+ // Acquire exclusive access.
+ osl::MutexGuard aGuard(*this);
+
+ // Check precond.
+ if (!self::isValid())
+ return store_E_InvalidAccess;
+
+ if (!base::isWriteable())
+ return store_E_AccessViolation;
+
+ // Check 'Source' parameter.
+ storeError eErrCode = store_E_InvalidParameter;
+ if (!(pSrcPath && pSrcName))
+ return eErrCode;
+
+ // Setup 'Source' page key.
+ OStorePageKey aSrcKey;
+ eErrCode = namei (pSrcPath, pSrcName, aSrcKey);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ // Find 'Source' NodePage and Index.
+ OStoreBTreeNodeObject aSrcNode;
+ sal_uInt16 i = 0;
+ eErrCode = m_aRoot.find_insert (aSrcNode, i, aSrcKey, *this);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ // Initialize directory page.
+ OStoreDirectoryPageObject aPage;
+ eErrCode = aPage.construct< inode >(base::allocator());
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ // Setup as 'Source' directory page.
+ inode_holder_type xNode (aPage.get());
+ aPage.key (aSrcKey);
+ memcpy (
+ &(xNode->m_aNameBlock.m_pData[0]),
+ pSrcName->buffer, pSrcName->length);
+
+ // Store 'Destination' page key.
+ OStorePageKey aDstKey (rDstKey);
+ memcpy (&(xNode->m_pData[0]), &aDstKey, sizeof(aDstKey));
+
+ // Mark 'Source' as symbolic link to 'Destination'.
+ aPage.attrib (STORE_ATTRIB_ISLINK);
+ aPage.dataLength (sal_uInt32(sizeof(aDstKey)));
+
+ // Allocate and save 'Source' directory page.
+ eErrCode = base::allocate (aPage);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ // Insert 'Source' entry.
+ PageHolderObject< page > xSrcNode (aSrcNode.get());
+ OStorePageLink aSrcLink (aPage.location());
+ xSrcNode->insert (i + 1, entry(aSrcKey, aSrcLink));
+
+ // Save modified NodePage.
+ return saveObjectAt (aSrcNode, aSrcNode.location());
+}
+
+/*
+ * rename.
+ * Precond: initialized, writeable.
+ */
+storeError OStorePageManager::rename (
+ const OStorePageKey &rSrcKey,
+ const rtl_String *pDstPath,
+ const rtl_String *pDstName)
+{
+ // Acquire exclusive access.
+ osl::MutexGuard aGuard(*this);
+
+ // Check precond.
+ if (!self::isValid())
+ return store_E_InvalidAccess;
+
+ if (!base::isWriteable())
+ return store_E_AccessViolation;
+
+ // Check 'Destination' parameter.
+ storeError eErrCode = store_E_InvalidParameter;
+ if (!(pDstPath && pDstName))
+ return eErrCode;
+
+ // Setup 'Destination' page key.
+ OStorePageKey aDstKey;
+ eErrCode = namei (pDstPath, pDstName, aDstKey);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ // Find 'Source' NodePage and Index.
+ OStoreBTreeNodeObject aSrcNode;
+ sal_uInt16 i = 0;
+ eErrCode = find_lookup (aSrcNode, i, rSrcKey);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ // Existing 'Source' entry.
+ PageHolderObject< page > xSrcNode (aSrcNode.get());
+ entry e (xSrcNode->m_pData[i]);
+
+ // Check for (not a) hardlink.
+ OStoreDirectoryPageObject aPage;
+ if (!(store::ntohl(e.m_nAttrib) & STORE_ATTRIB_ISLINK))
+ {
+ // Load directory page.
+ eErrCode = base::loadObjectAt (aPage, e.m_aLink.location());
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ // Check for directory.
+ if (aPage.attrib() & STORE_ATTRIB_ISDIR)
+ {
+ // Ugly, but necessary (backward compatibility).
+ aDstKey.m_nLow = store::htonl(rtl_crc32 (store::ntohl(aDstKey.m_nLow), "/", 1));
+ }
+ }
+
+ // Let 'Source' entry be 'Destination' entry.
+ e.m_aKey = aDstKey;
+
+ // Find 'Destination' NodePage and Index.
+ OStoreBTreeNodeObject aDstNode;
+ eErrCode = m_aRoot.find_insert (aDstNode, i, e.m_aKey, *this);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ // Insert 'Destination' entry.
+ PageHolderObject< page > xDstNode (aDstNode.get());
+ xDstNode->insert (i + 1, e);
+
+ eErrCode = saveObjectAt (aDstNode, aDstNode.location());
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ // Check for (not a) hardlink.
+ if (!(store::ntohl(e.m_nAttrib) & STORE_ATTRIB_ISLINK))
+ {
+ // Modify 'Source' directory page.
+ inode_holder_type xNode (aPage.get());
+
+ // Setup 'Destination' NameBlock.
+ sal_Int32 nDstLen = pDstName->length;
+ memcpy (
+ &(xNode->m_aNameBlock.m_pData[0]),
+ pDstName->buffer, pDstName->length);
+ memset (
+ &(xNode->m_aNameBlock.m_pData[nDstLen]),
+ 0, STORE_MAXIMUM_NAMESIZE - nDstLen);
+ aPage.key (e.m_aKey);
+
+ // Save directory page.
+ eErrCode = base::saveObjectAt (aPage, e.m_aLink.location());
+ if (eErrCode != store_E_None)
+ return eErrCode;
+ }
+
+ // Remove 'Source' entry.
+ e.m_aKey = rSrcKey;
+ return remove_Impl (e);
+}
+
+/*
+ * remove.
+ * Precond: initialized, writeable.
+ */
+storeError OStorePageManager::remove (const OStorePageKey &rKey)
+{
+ // Acquire exclusive access.
+ osl::MutexGuard aGuard(*this);
+
+ // Check precond.
+ if (!self::isValid())
+ return store_E_InvalidAccess;
+
+ if (!base::isWriteable())
+ return store_E_AccessViolation;
+
+ // Find NodePage and index.
+ OStoreBTreeNodeObject aNodePage;
+ sal_uInt16 i = 0;
+ storeError eErrCode = find_lookup (aNodePage, i, rKey);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ // Existing entry.
+ PageHolderObject< page > xNodePage (aNodePage.get());
+ entry e (xNodePage->m_pData[i]);
+
+ // Check for (not a) hardlink.
+ if (!(store::ntohl(e.m_nAttrib) & STORE_ATTRIB_ISLINK))
+ {
+ // Load directory page.
+ OStoreDirectoryPageObject aPage;
+ eErrCode = base::loadObjectAt (aPage, e.m_aLink.location());
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ inode_holder_type xNode (aPage.get());
+
+ // Acquire page write access.
+ OStorePageDescriptor aDescr (xNode->m_aDescr);
+ eErrCode = base::acquirePage (aDescr, store_AccessReadWrite);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ // Check for symbolic link.
+ if (!(aPage.attrib() & STORE_ATTRIB_ISLINK))
+ {
+ // Ordinary inode. Determine 'Data' scope.
+ inode::ChunkScope eScope = xNode->scope (aPage.dataLength());
+ if (eScope == inode::SCOPE_EXTERNAL)
+ {
+ // External 'Data' scope. Truncate all external data pages.
+ eErrCode = aPage.truncate (0, *this);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+ }
+
+ // Truncate internal data page.
+ memset (&(xNode->m_pData[0]), 0, xNode->capacity());
+ aPage.dataLength (0);
+ }
+
+ // Release page write access.
+ eErrCode = base::releasePage (aDescr, store_AccessReadWrite);
+
+ // Release and free directory page.
+ OStorePageData aPageHead;
+ eErrCode = base::free (aPageHead, aPage.location());
+ }
+
+ // Remove entry.
+ return remove_Impl (e);
+}
+
+/*
+ * RebuildContext.
+ */
+struct RebuildContext
+{
+ /** Representation.
+ */
+ rtl::Reference<OStorePageBIOS> m_xBIOS;
+ OStorePageBIOS::ScanContext m_aCtx;
+ sal_uInt16 m_nPageSize;
+
+ /** Construction.
+ */
+ RebuildContext (void)
+ : m_xBIOS (new OStorePageBIOS()),
+ m_nPageSize (0)
+ {}
+
+ /** initialize (PageBIOS and ScanContext).
+ */
+ storeError initialize (ILockBytes *pLockBytes, sal_uInt32 nMagic = 0)
+ {
+ storeError eErrCode = store_E_InvalidParameter;
+ if (pLockBytes)
+ {
+ m_xBIOS->initialize (pLockBytes, store_AccessReadOnly, m_nPageSize);
+ eErrCode = m_xBIOS->scanBegin (m_aCtx, nMagic);
+ }
+ return eErrCode;
+ }
+
+ /** initialize (ScanContext).
+ */
+ storeError initialize (sal_uInt32 nMagic = 0)
+ {
+ return m_xBIOS->scanBegin (m_aCtx, nMagic);
+ }
+
+ /** load (next ScanContext matching page).
+ */
+ storeError load (OStorePageObject &rPage)
+ {
+ if (m_aCtx.isValid())
+ return m_xBIOS->scanNext (m_aCtx, rPage);
+ else
+ return store_E_CantSeek;
+ }
+};
+
+/*
+ * rebuild.
+ * Precond: none.
+ */
+storeError OStorePageManager::rebuild (
+ ILockBytes *pSrcLB, ILockBytes *pDstLB)
+{
+ // Acquire exclusive access.
+ osl::MutexGuard aGuard(*this);
+
+ // Check arguments.
+ storeError eErrCode = store_E_InvalidParameter;
+ if (!(pSrcLB && pDstLB))
+ return eErrCode;
+
+ // Initialize 'Source' rebuild context.
+ RebuildContext aCtx;
+ eErrCode = aCtx.initialize (pSrcLB, STORE_MAGIC_DIRECTORYPAGE);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+ rtl::Reference<OStorePageBIOS> xSrcBIOS (aCtx.m_xBIOS);
+
+ // Initialize as 'Destination' with 'Source' page size.
+ eErrCode = self::initialize (pDstLB, store_AccessCreate, aCtx.m_nPageSize);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ // Pass One: Scan 'Source' directory pages.
+ {
+ // Scan 'Source' directory pages.
+ OStoreDirectoryPageObject aSrcPage;
+ while ((eErrCode = aCtx.load(aSrcPage)) == store_E_None)
+ {
+ OStoreDirectoryPageObject aDstPage;
+ eErrCode = aDstPage.construct< inode >(base::allocator());
+ if (eErrCode != store_E_None)
+ break;
+
+ inode_holder_type xSrcDir (aSrcPage.get());
+ inode_holder_type xDstDir (aDstPage.get());
+
+ // Copy NameBlock @@@ OLD @@@
+ memcpy (&(xDstDir->m_aNameBlock), &(xSrcDir->m_aNameBlock), sizeof(xSrcDir->m_aNameBlock));
+
+ // Obtain 'Source' data length.
+ sal_uInt32 nDataLen = aSrcPage.dataLength();
+ if (nDataLen > 0)
+ {
+ // Copy internal data area @@@ OLD @@@
+ memcpy (&(xDstDir->m_pData[0]), &(xSrcDir->m_pData[0]), xSrcDir->capacity());
+ }
+
+ // Insert 'Destination' directory page.
+ eErrCode = save_dirpage_Impl (aDstPage.key(), aDstPage);
+ if (eErrCode != store_E_None)
+ break;
+
+ // Check for external data page scope.
+ if (xSrcDir->scope(nDataLen) != inode::SCOPE_INTERNAL)
+ {
+ // Initialize 'Destination' data page.
+ typedef OStoreDataPageData data;
+ PageHolderObject< data > xData;
+ if (!xData.construct(base::allocator()))
+ return store_E_OutOfMemory;
+
+ // Determine data page count.
+ inode::ChunkDescriptor aDescr (
+ nDataLen - xDstDir->capacity(), xData->capacity());
+
+ sal_uInt32 i, n = aDescr.m_nPage;
+ if (aDescr.m_nOffset) n += 1;
+
+ // Copy data pages.
+ OStoreDataPageObject aData;
+ for (i = 0; i < n; i++)
+ {
+ // Read 'Source' data page.
+ osl::MutexGuard aSrcGuard (*xSrcBIOS);
+
+ eErrCode = aSrcPage.read (i, aData, *xSrcBIOS);
+ if (eErrCode != store_E_None)
+ continue;
+
+ // Write 'Destination' data page. @@@ READONLY @@@
+ eErrCode = aDstPage.write (i, aData, *this);
+ }
+ }
+
+ // Update 'Destination' directory page.
+ aDstPage.dataLength (nDataLen);
+ eErrCode = base::saveObjectAt (aDstPage, aDstPage.location());
+ }
+
+ // Save directory scan results.
+ flush();
+ }
+
+ // Pass Two: Scan 'Source' BTree nodes.
+ {
+ // Re-start 'Source' rebuild context.
+ aCtx.initialize (STORE_MAGIC_BTREENODE);
+
+ // Scan 'Source' BTree nodes.
+ OStoreBTreeNodeObject aNode;
+ while ((eErrCode = aCtx.load(aNode)) == store_E_None)
+ {
+ // Check for leaf node.
+ PageHolderObject< page > xNode (aNode.get());
+ if (xNode->depth() == 0)
+ {
+ sal_uInt16 i, n = xNode->usageCount();
+ for (i = 0; i < n; i++)
+ {
+ entry e (xNode->m_pData[i]);
+
+ // Check for Hard link.
+ if (e.m_nAttrib & STORE_ATTRIB_ISLINK)
+ {
+ // Load the hard link destination.
+ OStoreDirectoryPageObject aSrcPage;
+ eErrCode = xSrcBIOS->loadObjectAt (aSrcPage, e.m_aLink.location());
+ if (eErrCode == store_E_None)
+ {
+ OStorePageKey aDstKey (aSrcPage.key());
+ eErrCode = link (e.m_aKey, aDstKey);
+ }
+ e.m_nAttrib &= ~STORE_ATTRIB_ISLINK;
+ }
+
+ if (e.m_nAttrib)
+ {
+ // Ordinary attributes.
+ sal_uInt32 nAttrib = 0;
+ eErrCode = attrib (e.m_aKey, 0, e.m_nAttrib, nAttrib);
+ }
+ }
+ }
+ }
+
+ // Save BTree node scan results.
+ flush();
+ }
+
+ // Done.
+ return store_E_None;
+}
diff --git a/store/source/storpage.hxx b/store/source/storpage.hxx
new file mode 100644
index 000000000000..938e5dd63bc9
--- /dev/null
+++ b/store/source/storpage.hxx
@@ -0,0 +1,229 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: storpage.hxx,v $
+ * $Revision: 1.6 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _STORE_STORPAGE_HXX_
+#define _STORE_STORPAGE_HXX_ "$Revision: 1.6.8.2 $"
+
+#include "sal/types.h"
+
+#include "object.hxx"
+#include "lockbyte.hxx"
+
+#include "storbase.hxx"
+#include "storbios.hxx"
+#include "stortree.hxx"
+
+namespace store
+{
+
+struct OStoreDirectoryPageData;
+class OStoreDirectoryPageObject;
+
+/*========================================================================
+ *
+ * OStorePageManager interface.
+ *
+ *======================================================================*/
+class OStorePageManager : public store::OStorePageBIOS
+{
+public:
+ /** Construction.
+ */
+ OStorePageManager (void);
+
+ /** Initialization (two-phase construction).
+ */
+ virtual storeError initialize (
+ ILockBytes * pLockBytes,
+ storeAccessMode eAccessMode,
+ sal_uInt16 & rnPageSize);
+
+ /** isValid.
+ * @return sal_True upon successful initialization,
+ * sal_False otherwise.
+ */
+ inline sal_Bool isValid (void) const;
+
+ /** DirectoryPage I/O (managed).
+ */
+ static storeError namei (
+ const rtl_String *pPath,
+ const rtl_String *pName,
+ OStorePageKey &rKey);
+
+ storeError iget (
+ OStoreDirectoryPageObject & rPage, // [out]
+ sal_uInt32 nAttrib,
+ const rtl_String * pPath,
+ const rtl_String * pName,
+ storeAccessMode eMode);
+
+ storeError iterate (
+ OStorePageKey & rKey,
+ OStorePageLink & rLink,
+ sal_uInt32 & rAttrib);
+
+ /** attrib [nAttrib = ((nAttrib & ~nMask1) | nMask2)].
+ * @see store_attrib()
+ */
+ storeError attrib (
+ const OStorePageKey &rKey,
+ sal_uInt32 nMask1,
+ sal_uInt32 nMask2,
+ sal_uInt32 &rAttrib);
+
+ /** link (insert Source Key as hardlink to Destination).
+ * @see store_link()
+ */
+ storeError link (
+ const OStorePageKey &rSrcKey,
+ const OStorePageKey &rDstKey);
+
+ /** symlink (insert Source DirectoryPage as symlink to Destination).
+ * @see store_symlink()
+ */
+ storeError symlink (
+ const rtl_String *pSrcPath,
+ const rtl_String *pSrcName,
+ const OStorePageKey &rDstKey);
+
+ /** rename.
+ * @see store_rename()
+ */
+ storeError rename (
+ const OStorePageKey &rSrcKey,
+ const rtl_String *pDstPath,
+ const rtl_String *pDstName);
+
+ /** remove.
+ * @see store_remove()
+ */
+ storeError remove (
+ const OStorePageKey &rKey);
+
+ /** rebuild (combines recover and compact from 'Src' to 'Dst').
+ * @param pSrcLB [in] accessed readonly.
+ * @param pDstLB [in] truncated and accessed readwrite (as initialize()).
+ * @return store_E_None upon success.
+ *
+ * @see store_rebuildFile()
+ */
+ storeError rebuild (
+ ILockBytes *pSrcLB,
+ ILockBytes *pDstLB);
+
+ /** IStoreHandle.
+ */
+ virtual sal_Bool SAL_CALL isKindOf (sal_uInt32 nTypeId);
+
+protected:
+ /** Destruction.
+ */
+ virtual ~OStorePageManager (void);
+
+private:
+ /** Implementation.
+ */
+ typedef OStorePageBIOS base;
+ typedef OStorePageManager self;
+
+ typedef OStoreBTreeEntry entry;
+ typedef OStoreBTreeNodeData page;
+ typedef OStoreBTreeNodeObject node;
+
+ typedef OStoreDirectoryPageData inode;
+ typedef PageHolderObject< inode > inode_holder_type;
+
+ /** IStoreHandle TypeId.
+ */
+ static const sal_uInt32 m_nTypeId;
+
+ /** IStoreHandle query() template function specialization.
+ */
+ friend OStorePageManager*
+ SAL_CALL query<> (IStoreHandle *pHandle, OStorePageManager*);
+
+ /** Representation.
+ */
+ OStoreBTreeRootObject m_aRoot;
+
+ /** DirectoryPage I/O (managed).
+ */
+ storeError load_dirpage_Impl ( // @@@ => private: iget() @@@
+ const OStorePageKey &rKey,
+ OStoreDirectoryPageObject &rPage);
+
+ storeError save_dirpage_Impl ( // @@@ => private: iget(), rebuild() @@@
+ const OStorePageKey &rKey,
+ OStoreDirectoryPageObject &rPage);
+
+ /** find_lookup (node page and index, w/o split).
+ */
+ storeError find_lookup (
+ OStoreBTreeNodeObject & rNode,
+ sal_uInt16 & rIndex,
+ OStorePageKey const & rKey);
+
+ /** remove (possibly down from root).
+ */
+ storeError remove_Impl (entry & rEntry);
+
+ /** Not implemented.
+ */
+ OStorePageManager (const OStorePageManager&);
+ OStorePageManager& operator= (const OStorePageManager&);
+};
+
+inline sal_Bool OStorePageManager::isValid (void) const
+{
+ return (base::isValid() /* @@@ NYI && (m_aRoot.is()) */);
+}
+
+template<> inline OStorePageManager*
+SAL_CALL query (IStoreHandle *pHandle, OStorePageManager*)
+{
+ if (pHandle && pHandle->isKindOf (OStorePageManager::m_nTypeId))
+ {
+ // Handle is kind of OStorePageManager.
+ return static_cast<OStorePageManager*>(pHandle);
+ }
+ return 0;
+}
+
+/*========================================================================
+ *
+ * The End.
+ *
+ *======================================================================*/
+
+} // namespace store
+
+#endif /* !_STORE_STORPAGE_HXX_ */
+
diff --git a/store/source/stortree.cxx b/store/source/stortree.cxx
new file mode 100644
index 000000000000..614b995aba72
--- /dev/null
+++ b/store/source/stortree.cxx
@@ -0,0 +1,688 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: stortree.cxx,v $
+ * $Revision: 1.8 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_store.hxx"
+
+#include "stortree.hxx"
+
+#include "sal/types.h"
+#include "osl/diagnose.h"
+
+#include "store/types.h"
+
+#include "storbase.hxx"
+#include "storbios.hxx"
+
+using namespace store;
+
+/*========================================================================
+ *
+ * OStoreBTreeNodeData implementation.
+ *
+ *======================================================================*/
+/*
+ * OStoreBTreeNodeData.
+ */
+OStoreBTreeNodeData::OStoreBTreeNodeData (sal_uInt16 nPageSize)
+ : OStorePageData (nPageSize)
+{
+ base::m_aGuard.m_nMagic = store::htonl(self::theTypeId);
+ base::m_aDescr.m_nUsed = store::htons(self::thePageSize); // usageCount(0)
+ self::m_aGuard.m_nMagic = store::htonl(0); // depth(0)
+
+ sal_uInt16 const n = capacityCount();
+ T const t;
+
+ for (sal_uInt16 i = 1; i < n; i++)
+ m_pData[i] = t;
+}
+
+/*
+ * find.
+ */
+sal_uInt16 OStoreBTreeNodeData::find (const T& t) const
+{
+ register sal_Int32 l = 0;
+ register sal_Int32 r = usageCount() - 1;
+
+ while (l < r)
+ {
+ register sal_Int32 const m = ((l + r) >> 1);
+
+ if (t.m_aKey == m_pData[m].m_aKey)
+ return ((sal_uInt16)(m));
+ if (t.m_aKey < m_pData[m].m_aKey)
+ r = m - 1;
+ else
+ l = m + 1;
+ }
+
+ sal_uInt16 const k = ((sal_uInt16)(r));
+ if ((k < capacityCount()) && (t.m_aKey < m_pData[k].m_aKey))
+ return(k - 1);
+ else
+ return(k);
+}
+
+/*
+ * insert.
+ */
+void OStoreBTreeNodeData::insert (sal_uInt16 i, const T& t)
+{
+ sal_uInt16 const n = usageCount();
+ sal_uInt16 const m = capacityCount();
+ if ((n < m) && (i < m))
+ {
+ // shift right.
+ memmove (&(m_pData[i + 1]), &(m_pData[i]), (n - i) * sizeof(T));
+
+ // insert.
+ m_pData[i] = t;
+ usageCount (n + 1);
+ }
+}
+
+/*
+ * remove.
+ */
+void OStoreBTreeNodeData::remove (sal_uInt16 i)
+{
+ sal_uInt16 const n = usageCount();
+ if (i < n)
+ {
+ // shift left.
+ memmove (&(m_pData[i]), &(m_pData[i + 1]), (n - i - 1) * sizeof(T));
+
+ // truncate.
+ m_pData[n - 1] = T();
+ usageCount (n - 1);
+ }
+}
+
+#if 0 /* NYI */
+/*
+ * merge (with right page).
+ */
+void OStoreBTreeNodeData::merge (const self& rPageR)
+{
+ sal_uInt16 const n = usageCount();
+ sal_uInt16 const m = rPageR.usageCount();
+ if ((n + m) <= capacityCount())
+ {
+ memcpy (&(m_pData[n]), &(rPageR.m_pData[0]), m * sizeof(T));
+ usageCount (n + m);
+ }
+}
+#endif
+
+/*
+ * split (left half copied from right half of left page).
+ */
+void OStoreBTreeNodeData::split (const self& rPageL)
+{
+ sal_uInt16 const h = capacityCount() / 2;
+ memcpy (&(m_pData[0]), &(rPageL.m_pData[h]), h * sizeof(T));
+ truncate (h);
+}
+
+/*
+ * truncate.
+ */
+void OStoreBTreeNodeData::truncate (sal_uInt16 n)
+{
+ sal_uInt16 const m = capacityCount();
+ T const t;
+
+ for (sal_uInt16 i = n; i < m; i++)
+ m_pData[i] = t;
+ usageCount (n);
+}
+
+/*========================================================================
+ *
+ * OStoreBTreeNodeObject implementation.
+ *
+ *======================================================================*/
+/*
+ * guard.
+ */
+storeError OStoreBTreeNodeObject::guard (sal_uInt32 nAddr)
+{
+ return PageHolderObject< page >::guard (m_xPage, nAddr);
+}
+
+/*
+ * verify.
+ */
+storeError OStoreBTreeNodeObject::verify (sal_uInt32 nAddr) const
+{
+ return PageHolderObject< page >::verify (m_xPage, nAddr);
+}
+
+/*
+ * split.
+ */
+storeError OStoreBTreeNodeObject::split (
+ sal_uInt16 nIndexL,
+ PageHolderObject< page > & rxPageL,
+ OStorePageBIOS & rBIOS)
+{
+ PageHolderObject< page > xPage (m_xPage);
+ if (!xPage.is())
+ return store_E_InvalidAccess;
+
+ // Check left page usage.
+ if (!rxPageL.is())
+ return store_E_InvalidAccess;
+ if (!rxPageL->querySplit())
+ return store_E_None;
+
+ // Save PageDescriptor.
+ OStorePageDescriptor aDescr (xPage->m_aDescr);
+ aDescr.m_nAddr = store::ntohl(aDescr.m_nAddr);
+ aDescr.m_nSize = store::ntohs(aDescr.m_nSize);
+
+ // Acquire Lock.
+ storeError eErrCode = rBIOS.acquireLock (aDescr.m_nAddr, aDescr.m_nSize);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ // [Begin PageL Lock (NYI)]
+
+ // Construct right page.
+ PageHolderObject< page > xPageR;
+ if (!xPageR.construct (rBIOS.allocator()))
+ {
+ rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize);
+ return store_E_OutOfMemory;
+ }
+
+ // Split right page off left page.
+ xPageR->split (*rxPageL);
+ xPageR->depth (rxPageL->depth());
+
+ // Allocate right page.
+ self aNodeR (xPageR.get());
+ eErrCode = rBIOS.allocate (aNodeR);
+ if (eErrCode != store_E_None)
+ {
+ rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize);
+ return eErrCode;
+ }
+
+ // Truncate left page.
+ rxPageL->truncate (rxPageL->capacityCount() / 2);
+
+ // Save left page.
+ self aNodeL (rxPageL.get());
+ eErrCode = rBIOS.saveObjectAt (aNodeL, aNodeL.location());
+ if (eErrCode != store_E_None)
+ {
+ // Must not happen.
+ OSL_TRACE("OStoreBTreeNodeObject::split(): save() failed");
+
+ // Release Lock and Leave.
+ rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize);
+ return eErrCode;
+ }
+
+ // [End PageL Lock (NYI)]
+
+ // Insert right page.
+ OStorePageLink aLink (xPageR->location());
+ xPage->insert (nIndexL + 1, T(xPageR->m_pData[0].m_aKey, aLink));
+
+ // Save this page.
+ eErrCode = rBIOS.saveObjectAt (*this, location());
+ if (eErrCode != store_E_None)
+ {
+ // Must not happen.
+ OSL_TRACE("OStoreBTreeNodeObject::split(): save() failed");
+
+ // Release Lock and Leave.
+ rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize);
+ return eErrCode;
+ }
+
+ // Release Lock and Leave.
+ return rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize);
+}
+
+/*
+ * remove (down to leaf node, recursive).
+ */
+storeError OStoreBTreeNodeObject::remove (
+ sal_uInt16 nIndexL,
+ OStoreBTreeEntry & rEntryL,
+ OStorePageBIOS & rBIOS)
+{
+ PageHolderObject< page > xImpl (m_xPage);
+ page & rPage = (*xImpl);
+
+ // Save PageDescriptor.
+ OStorePageDescriptor aDescr (rPage.m_aDescr);
+ aDescr.m_nAddr = store::ntohl(aDescr.m_nAddr);
+ aDescr.m_nSize = store::ntohs(aDescr.m_nSize);
+
+ // Acquire Lock.
+ storeError eErrCode = rBIOS.acquireLock (aDescr.m_nAddr, aDescr.m_nSize);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ // Check depth.
+ if (rPage.depth())
+ {
+ // Check link entry.
+ T const aEntryL (rPage.m_pData[nIndexL]);
+ if (!(rEntryL.compare (aEntryL) == T::COMPARE_EQUAL))
+ {
+ rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize);
+ return store_E_InvalidAccess;
+ }
+
+ // Load link node.
+ self aNodeL;
+ eErrCode = rBIOS.loadObjectAt (aNodeL, aEntryL.m_aLink.location());
+ if (eErrCode != store_E_None)
+ {
+ rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize);
+ return eErrCode;
+ }
+
+ // Recurse: remove from link node.
+ eErrCode = aNodeL.remove (0, rEntryL, rBIOS);
+ if (eErrCode != store_E_None)
+ {
+ rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize);
+ return eErrCode;
+ }
+
+ // Check resulting link node usage.
+ PageHolderObject< page > xPageL (aNodeL.get());
+ if (xPageL->usageCount() == 0)
+ {
+ // Free empty link node.
+ OStorePageData aPageHead;
+ eErrCode = rBIOS.free (aPageHead, xPageL->location());
+ if (eErrCode != store_E_None)
+ {
+ rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize);
+ return eErrCode;
+ }
+
+ // Remove index.
+ rPage.remove (nIndexL);
+ touch();
+ }
+ else
+ {
+#if 0 /* NYI */
+ // Check for right sibling.
+ sal_uInt16 const nIndexR = nIndexL + 1;
+ if (nIndexR < rPage.usageCount())
+ {
+ // Load right link node.
+ self aNodeR;
+ eErrCode = rBIOS.loadObjectAt (aNodeR, rPage.m_pData[nIndexR].m_aLink.location());
+ if (eErrCode == store_E_None)
+ {
+ if (rPageL.queryMerge (rPageR))
+ {
+ rPageL.merge (rPageR);
+
+ eErrCode = rBIOS.free (aPageHead, rPageR.location());
+ }
+ }
+ }
+#endif /* NYI */
+
+ // Relink.
+ rPage.m_pData[nIndexL].m_aKey = xPageL->m_pData[0].m_aKey;
+ touch();
+ }
+ }
+ else
+ {
+ // Check leaf entry.
+ if (!(rEntryL.compare (rPage.m_pData[nIndexL]) == T::COMPARE_EQUAL))
+ {
+ rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize);
+ return store_E_NotExists;
+ }
+
+ // Save leaf entry.
+ rEntryL = rPage.m_pData[nIndexL];
+
+ // Remove leaf index.
+ rPage.remove (nIndexL);
+ touch();
+ }
+
+ // Check for modified node.
+ if (dirty())
+ {
+ // Save this page.
+ eErrCode = rBIOS.saveObjectAt (*this, location());
+ if (eErrCode != store_E_None)
+ {
+ // Must not happen.
+ OSL_TRACE("OStoreBTreeNodeObject::remove(): save() failed");
+
+ // Release Lock and Leave.
+ rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize);
+ return eErrCode;
+ }
+ }
+
+ // Release Lock and Leave.
+ return rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize);
+}
+
+/*========================================================================
+ *
+ * OStoreBTreeRootObject implementation.
+ *
+ *======================================================================*/
+/*
+ * testInvariant.
+ * Precond: root node page loaded.
+ */
+bool OStoreBTreeRootObject::testInvariant (char const * message)
+{
+ OSL_PRECOND(m_xPage.get() != 0, "OStoreBTreeRootObject::testInvariant(): Null pointer");
+ bool result = ((m_xPage->location() - m_xPage->size()) == 0);
+ OSL_POSTCOND(result, message); (void) message;
+ return result;
+}
+
+/*
+ * loadOrCreate.
+ */
+storeError OStoreBTreeRootObject::loadOrCreate (
+ sal_uInt32 nAddr,
+ OStorePageBIOS & rBIOS)
+{
+ storeError eErrCode = rBIOS.loadObjectAt (*this, nAddr);
+ if (eErrCode != store_E_NotExists)
+ return eErrCode;
+
+ eErrCode = construct<page>(rBIOS.allocator());
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ eErrCode = rBIOS.allocate (*this);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ // Notify caller of the creation.
+ (void) testInvariant("OStoreBTreeRootObject::loadOrCreate(): leave");
+ return store_E_Pending;
+}
+
+/*
+ * change.
+ */
+storeError OStoreBTreeRootObject::change (
+ PageHolderObject< page > & rxPageL,
+ OStorePageBIOS & rBIOS)
+{
+ PageHolderObject< page > xPage (m_xPage);
+ (void) testInvariant("OStoreBTreeRootObject::change(): enter");
+
+ // Save PageDescriptor.
+ OStorePageDescriptor aDescr (xPage->m_aDescr);
+ aDescr.m_nAddr = store::ntohl(aDescr.m_nAddr);
+ aDescr.m_nSize = store::ntohs(aDescr.m_nSize);
+
+ // Save root location.
+ sal_uInt32 const nRootAddr = xPage->location();
+
+ // Acquire Lock.
+ storeError eErrCode = rBIOS.acquireLock (aDescr.m_nAddr, aDescr.m_nSize);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ // Construct new root.
+ if (!rxPageL.construct (rBIOS.allocator()))
+ {
+ rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize);
+ return store_E_OutOfMemory;
+ }
+
+ // Save this as prev root.
+ eErrCode = rBIOS.allocate (*this);
+ if (eErrCode != store_E_None)
+ {
+ rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize);
+ return store_E_OutOfMemory;
+ }
+
+ // Setup new root.
+ rxPageL->depth (xPage->depth() + 1);
+ rxPageL->m_pData[0] = xPage->m_pData[0];
+ rxPageL->m_pData[0].m_aLink = xPage->location();
+ rxPageL->usageCount(1);
+
+ // Change root.
+ rxPageL.swap (xPage);
+ {
+ PageHolder tmp (xPage.get());
+ tmp.swap (m_xPage);
+ }
+
+ // Save this as new root.
+ eErrCode = rBIOS.saveObjectAt (*this, nRootAddr);
+ if (eErrCode != store_E_None)
+ {
+ // Must not happen.
+ OSL_TRACE("OStoreBTreeRootObject::change(): save() failed");
+
+ // Release Lock and Leave.
+ rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize);
+ return eErrCode;
+ }
+
+ // Flush for robustness.
+ (void) rBIOS.flush();
+
+ // Done. Release Lock and Leave.
+ (void) testInvariant("OStoreBTreeRootObject::change(): leave");
+ return rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize);
+}
+
+/*
+ * find_lookup (w/o split()).
+ * Precond: root node page loaded.
+ */
+storeError OStoreBTreeRootObject::find_lookup (
+ OStoreBTreeNodeObject & rNode, // [out]
+ sal_uInt16 & rIndex, // [out]
+ OStorePageKey const & rKey,
+ OStorePageBIOS & rBIOS)
+{
+ // Init node w/ root page.
+ (void) testInvariant("OStoreBTreeRootObject::find_lookup(): enter");
+ {
+ PageHolder tmp (m_xPage);
+ tmp.swap (rNode.get());
+ }
+
+ // Setup BTree entry.
+ T const entry (rKey);
+
+ // Check current page.
+ PageHolderObject< page > xPage (rNode.get());
+ for (; xPage->depth() > 0; xPage = rNode.makeHolder< page >())
+ {
+ // Find next page.
+ page const & rPage = (*xPage);
+ sal_uInt16 const i = rPage.find(entry);
+ sal_uInt16 const n = rPage.usageCount();
+ if (!(i < n))
+ {
+ // Path to entry not exists (Must not happen(?)).
+ return store_E_NotExists;
+ }
+
+ // Check address.
+ sal_uInt32 const nAddr = rPage.m_pData[i].m_aLink.location();
+ if (nAddr == STORE_PAGE_NULL)
+ {
+ // Path to entry not exists (Must not happen(?)).
+ return store_E_NotExists;
+ }
+
+ // Load next page.
+ storeError eErrCode = rBIOS.loadObjectAt (rNode, nAddr);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+ }
+
+ // Find index.
+ page const & rPage = (*xPage);
+ rIndex = rPage.find(entry);
+ if (!(rIndex < rPage.usageCount()))
+ return store_E_NotExists;
+
+ // Compare entry.
+ T::CompareResult eResult = entry.compare(rPage.m_pData[rIndex]);
+ OSL_POSTCOND(eResult != T::COMPARE_LESS, "store::BTreeRoot::find_lookup(): sort error");
+ if (eResult == T::COMPARE_LESS)
+ return store_E_Unknown;
+
+ // Greater or Equal.
+ (void) testInvariant("OStoreBTreeRootObject::find_lookup(): leave");
+ return store_E_None;
+}
+
+/*
+ * find_insert (possibly with split()).
+ * Precond: root node page loaded.
+ */
+storeError OStoreBTreeRootObject::find_insert (
+ OStoreBTreeNodeObject & rNode, // [out]
+ sal_uInt16 & rIndex, // [out]
+ OStorePageKey const & rKey,
+ OStorePageBIOS & rBIOS)
+{
+ (void) testInvariant("OStoreBTreeRootObject::find_insert(): enter");
+
+ // Check for RootNode split.
+ PageHolderObject< page > xRoot (m_xPage);
+ if (xRoot->querySplit())
+ {
+ PageHolderObject< page > xPageL;
+
+ // Change root.
+ storeError eErrCode = change (xPageL, rBIOS);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ // Split left page (prev root).
+ eErrCode = split (0, xPageL, rBIOS);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+ }
+
+ // Init node w/ root page.
+ {
+ PageHolder tmp (m_xPage);
+ tmp.swap (rNode.get());
+ }
+
+ // Setup BTree entry.
+ T const entry (rKey);
+
+ // Check current Page.
+ PageHolderObject< page > xPage (rNode.get());
+ for (; xPage->depth() > 0; xPage = rNode.makeHolder< page >())
+ {
+ // Find next page.
+ page const & rPage = (*xPage);
+ sal_uInt16 const i = rPage.find (entry);
+ sal_uInt16 const n = rPage.usageCount();
+ if (!(i < n))
+ {
+ // Path to entry not exists (Must not happen(?)).
+ return store_E_NotExists;
+ }
+
+ // Check address.
+ sal_uInt32 const nAddr = rPage.m_pData[i].m_aLink.location();
+ if (nAddr == STORE_PAGE_NULL)
+ {
+ // Path to entry not exists (Must not happen(?)).
+ return store_E_NotExists;
+ }
+
+ // Load next page.
+ OStoreBTreeNodeObject aNext;
+ storeError eErrCode = rBIOS.loadObjectAt (aNext, nAddr);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ // Check for next node split.
+ PageHolderObject< page > xNext (aNext.get());
+ if (xNext->querySplit())
+ {
+ // Split next node.
+ eErrCode = rNode.split (i, xNext, rBIOS);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ // Restart.
+ continue;
+ }
+
+ // Let next page be current.
+ PageHolder tmp (aNext.get());
+ tmp.swap (rNode.get());
+ }
+
+ // Find index.
+ page const & rPage = (*xPage);
+ rIndex = rPage.find(entry);
+ if (rIndex < rPage.usageCount())
+ {
+ // Compare entry.
+ T::CompareResult result = entry.compare (rPage.m_pData[rIndex]);
+ OSL_POSTCOND(result != T::COMPARE_LESS, "store::BTreeRoot::find_insert(): sort error");
+ if (result == T::COMPARE_LESS)
+ return store_E_Unknown;
+
+ if (result == T::COMPARE_EQUAL)
+ return store_E_AlreadyExists;
+ }
+
+ // Greater or not (yet) existing.
+ (void) testInvariant("OStoreBTreeRootObject::find_insert(): leave");
+ return store_E_None;
+}
diff --git a/store/source/stortree.hxx b/store/source/stortree.hxx
new file mode 100644
index 000000000000..9aa5da92cfda
--- /dev/null
+++ b/store/source/stortree.hxx
@@ -0,0 +1,348 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: stortree.hxx,v $
+ * $Revision: 1.6 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _STORE_STORTREE_HXX
+#define _STORE_STORTREE_HXX "$Revision: 1.6.8.2 $"
+
+#include "sal/types.h"
+
+#include "store/types.h"
+
+#include "storbase.hxx"
+
+namespace store
+{
+
+class OStorePageBIOS;
+
+/*========================================================================
+ *
+ * OStoreBTreeEntry.
+ *
+ *======================================================================*/
+struct OStoreBTreeEntry
+{
+ typedef OStorePageKey K;
+ typedef OStorePageLink L;
+
+ /** Representation.
+ */
+ K m_aKey;
+ L m_aLink;
+ sal_uInt32 m_nAttrib;
+
+ /** Construction.
+ */
+ explicit OStoreBTreeEntry (
+ K const & rKey = K(),
+ L const & rLink = L(),
+ sal_uInt32 nAttrib = 0)
+ : m_aKey (rKey),
+ m_aLink (rLink),
+ m_nAttrib (store::htonl(nAttrib))
+ {}
+
+ OStoreBTreeEntry (const OStoreBTreeEntry & rhs)
+ : m_aKey (rhs.m_aKey),
+ m_aLink (rhs.m_aLink),
+ m_nAttrib (rhs.m_nAttrib)
+ {}
+
+ OStoreBTreeEntry& operator= (const OStoreBTreeEntry & rhs)
+ {
+ m_aKey = rhs.m_aKey;
+ m_aLink = rhs.m_aLink;
+ m_nAttrib = rhs.m_nAttrib;
+ return *this;
+ }
+
+ /** Comparison.
+ */
+ enum CompareResult
+ {
+ COMPARE_LESS = -1,
+ COMPARE_EQUAL = 0,
+ COMPARE_GREATER = 1
+ };
+
+ CompareResult compare (const OStoreBTreeEntry& rOther) const
+ {
+ if (m_aKey < rOther.m_aKey)
+ return COMPARE_LESS;
+ else if (m_aKey == rOther.m_aKey)
+ return COMPARE_EQUAL;
+ else
+ return COMPARE_GREATER;
+ }
+};
+
+/*========================================================================
+ *
+ * OStoreBTreeNodeData.
+ *
+ *======================================================================*/
+#define STORE_MAGIC_BTREENODE sal_uInt32(0x58190322)
+
+struct OStoreBTreeNodeData : public store::OStorePageData
+{
+ typedef OStorePageData base;
+ typedef OStoreBTreeNodeData self;
+
+ typedef OStorePageGuard G;
+ typedef OStoreBTreeEntry T;
+
+ /** Representation.
+ */
+ G m_aGuard;
+ T m_pData[1];
+
+ /** type.
+ */
+ static const sal_uInt32 theTypeId = STORE_MAGIC_BTREENODE;
+
+ /** theSize.
+ */
+ static const size_t theSize = sizeof(G);
+ static const sal_uInt16 thePageSize = base::theSize + self::theSize;
+ STORE_STATIC_ASSERT(STORE_MINIMUM_PAGESIZE >= self::thePageSize);
+
+ /** capacity.
+ */
+ sal_uInt16 capacity (void) const
+ {
+ return (store::ntohs(base::m_aDescr.m_nSize) - self::thePageSize);
+ }
+
+ /** capacityCount (must be even).
+ */
+ sal_uInt16 capacityCount (void) const
+ {
+ return sal_uInt16(capacity() / sizeof(T));
+ }
+
+ /** usage.
+ */
+ sal_uInt16 usage (void) const
+ {
+ return (store::ntohs(base::m_aDescr.m_nUsed) - self::thePageSize);
+ }
+
+ /** usageCount.
+ */
+ sal_uInt16 usageCount (void) const
+ {
+ return sal_uInt16(usage() / sizeof(T));
+ }
+ void usageCount (sal_uInt16 nCount)
+ {
+ size_t const nBytes = self::thePageSize + nCount * sizeof(T);
+ base::m_aDescr.m_nUsed = store::htons(sal::static_int_cast< sal_uInt16 >(nBytes));
+ }
+
+ /** Construction.
+ */
+ explicit OStoreBTreeNodeData (sal_uInt16 nPageSize = self::thePageSize);
+
+ /** guard (external representation).
+ */
+ void guard()
+ {
+ sal_uInt32 nCRC32 = 0;
+ nCRC32 = rtl_crc32 (nCRC32, &m_aGuard.m_nMagic, sizeof(sal_uInt32));
+ nCRC32 = rtl_crc32 (nCRC32, m_pData, capacity());
+ m_aGuard.m_nCRC32 = store::htonl(nCRC32);
+ }
+
+ /** verify (external representation).
+ */
+ storeError verify() const
+ {
+ sal_uInt32 nCRC32 = 0;
+ nCRC32 = rtl_crc32 (nCRC32, &m_aGuard.m_nMagic, sizeof(sal_uInt32));
+ nCRC32 = rtl_crc32 (nCRC32, m_pData, capacity());
+ if (m_aGuard.m_nCRC32 != store::htonl(nCRC32))
+ return store_E_InvalidChecksum;
+ else
+ return store_E_None;
+ }
+
+ /** depth.
+ */
+ sal_uInt32 depth (void) const
+ {
+ return store::ntohl(self::m_aGuard.m_nMagic);
+ }
+ void depth (sal_uInt32 nDepth)
+ {
+ self::m_aGuard.m_nMagic = store::htonl(nDepth);
+ }
+
+ /** queryMerge.
+ */
+ sal_Bool queryMerge (const self &rPageR) const
+ {
+ return ((usageCount() + rPageR.usageCount()) <= capacityCount());
+ }
+
+ /** querySplit.
+ */
+ sal_Bool querySplit (void) const
+ {
+ return (!(usageCount() < capacityCount()));
+ }
+
+ /** Operation.
+ */
+ sal_uInt16 find (const T& t) const;
+ void insert (sal_uInt16 i, const T& t);
+ void remove (sal_uInt16 i);
+
+#if 0 /* NYI */
+ /** merge (with right page).
+ */
+ void merge (const self& rPageR);
+#endif
+
+ /** split (left half copied from right half of left page).
+ */
+ void split (const self& rPageL);
+
+ /** truncate (to n elements).
+ */
+ void truncate (sal_uInt16 n);
+};
+
+/*========================================================================
+ *
+ * OStoreBTreeNodeObject.
+ *
+ *======================================================================*/
+class OStoreBTreeNodeObject : public store::OStorePageObject
+{
+ typedef OStorePageObject base;
+ typedef OStoreBTreeNodeObject self;
+ typedef OStoreBTreeNodeData page;
+
+ typedef OStoreBTreeEntry T;
+
+public:
+ /** Construction.
+ */
+ explicit OStoreBTreeNodeObject (PageHolder const & rxPage = PageHolder())
+ : OStorePageObject (rxPage)
+ {}
+
+ /** External representation.
+ */
+ virtual storeError guard (sal_uInt32 nAddr);
+ virtual storeError verify (sal_uInt32 nAddr) const;
+
+ /** split.
+ *
+ * @param rxPageL [inout] left child to be split
+ */
+ storeError split (
+ sal_uInt16 nIndexL,
+ PageHolderObject< page > & rxPageL,
+ OStorePageBIOS & rBIOS);
+
+ /** remove (down to leaf node, recursive).
+ */
+ storeError remove (
+ sal_uInt16 nIndexL,
+ OStoreBTreeEntry & rEntryL,
+ OStorePageBIOS & rBIOS);
+};
+
+/*========================================================================
+ *
+ * OStoreBTreeRootObject.
+ *
+ *======================================================================*/
+class OStoreBTreeRootObject : public store::OStoreBTreeNodeObject
+{
+ typedef OStoreBTreeNodeObject base;
+ typedef OStoreBTreeNodeData page;
+
+ typedef OStoreBTreeEntry T;
+
+public:
+ /** Construction.
+ */
+ explicit OStoreBTreeRootObject (PageHolder const & rxPage = PageHolder())
+ : OStoreBTreeNodeObject (rxPage)
+ {}
+
+ storeError loadOrCreate (
+ sal_uInt32 nAddr,
+ OStorePageBIOS & rBIOS);
+
+ /** find_lookup (w/o split()).
+ * Precond: root node page loaded.
+ */
+ storeError find_lookup (
+ OStoreBTreeNodeObject & rNode, // [out]
+ sal_uInt16 & rIndex, // [out]
+ OStorePageKey const & rKey,
+ OStorePageBIOS & rBIOS);
+
+ /** find_insert (possibly with split()).
+ * Precond: root node page loaded.
+ */
+ storeError find_insert (
+ OStoreBTreeNodeObject & rNode,
+ sal_uInt16 & rIndex,
+ OStorePageKey const & rKey,
+ OStorePageBIOS & rBIOS);
+
+private:
+ /** testInvariant.
+ * Precond: root node page loaded.
+ */
+ bool testInvariant (char const * message);
+
+ /** change (Root).
+ *
+ * @param rxPageL [out] prev. root (needs split)
+ */
+ storeError change (
+ PageHolderObject< page > & rxPageL,
+ OStorePageBIOS & rBIOS);
+};
+
+/*========================================================================
+ *
+ * The End.
+ *
+ *======================================================================*/
+
+} // namespace store
+
+#endif /* !_STORE_STORTREE_HXX */
diff --git a/store/util/makefile.mk b/store/util/makefile.mk
new file mode 100644
index 000000000000..57733e5ca2a9
--- /dev/null
+++ b/store/util/makefile.mk
@@ -0,0 +1,83 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2008 by Sun Microsystems, Inc.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.24 $
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org 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 version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..
+
+PRJNAME=store
+TARGET=store
+TARGETTYPE=CUI
+
+USE_LDUMP2=TRUE
+USE_DEFFILE=TRUE
+
+NO_BSYMBOLIC=TRUE
+NO_DEFAULT_STL=TRUE
+
+UNIXVERSIONNAMES=UDK
+
+# --- Settings ---
+
+.INCLUDE : settings.mk
+
+# --- Debug-Library ---
+
+.IF "$(debug)" != ""
+
+LIB1TARGET= $(LB)$/$(TARGET)dbg.lib
+LIB1ARCHIV= $(LB)$/lib$(TARGET)dbg.a
+LIB1FILES= $(LB)$/store.lib
+
+.ENDIF # debug
+
+# --- Shared-Library ---
+
+SHL1TARGET= $(TARGET)
+SHL1IMPLIB= istore
+
+SHL1VERSIONMAP= $(TARGET).map
+
+SHL1STDLIBS= $(SALLIB)
+
+SHL1DEF= $(MISC)$/$(SHL1TARGET).def
+SHL1LIBS= $(SLB)$/store.lib
+SHL1RPATH= URELIB
+
+# --- Def-File ---
+
+DEF1NAME= $(SHL1TARGET)
+DEF1DES=Store
+
+# --- Targets ---
+
+.INCLUDE : target.mk
+
+
+
diff --git a/store/util/store.map b/store/util/store.map
new file mode 100644
index 000000000000..51fc36048b96
--- /dev/null
+++ b/store/util/store.map
@@ -0,0 +1,31 @@
+UDK_3_0_0 {
+ global:
+ store_acquireHandle;
+ store_attrib;
+ store_closeDirectory;
+ store_closeFile;
+ store_closeStream;
+ store_createMemoryFile;
+ store_findFirst;
+ store_findNext;
+ store_flushFile;
+ store_flushStream;
+ store_getFileRefererCount;
+ store_getFileSize;
+ store_getStreamSize;
+ store_link;
+ store_openDirectory;
+ store_openFile;
+ store_openStream;
+ store_readStream;
+ store_rebuildFile;
+ store_releaseHandle;
+ store_remove;
+ store_rename;
+ store_setStreamSize;
+ store_symlink;
+ store_writeStream;
+ local:
+ *;
+};
+
diff --git a/store/util/store.xml b/store/util/store.xml
new file mode 100644
index 000000000000..0cd8cbef9d2c
--- /dev/null
+++ b/store/util/store.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE module-description PUBLIC "-//StarOffice//DTD ComponentDescription 1.0//EN" "module-description.dtd">
+<module-description xmlns:xlink="http://www.w3.org/1999/xlink">
+ <module-name> store </module-name>
+ <project-build-dependency> sal </project-build-dependency>
+ <runtime-module-dependency> sal </runtime-module-dependency>
+</module-description>
diff --git a/store/version.mk b/store/version.mk
new file mode 100644
index 000000000000..e9171328da44
--- /dev/null
+++ b/store/version.mk
@@ -0,0 +1,44 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2008 by Sun Microsystems, Inc.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# $RCSfile: version.mk,v $
+#
+# $Revision: 1.3 $
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org 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 version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+# target
+STORE_TARGET=store
+
+# the major
+STORE_MAJOR=2
+# the minor
+STORE_MINOR=0
+# the micro
+STORE_MICRO=0
+
+# this is a c++ compatible library
+STORE_CPP=0
+
diff --git a/store/workben/makefile.mk b/store/workben/makefile.mk
new file mode 100644
index 000000000000..4b58d26409a0
--- /dev/null
+++ b/store/workben/makefile.mk
@@ -0,0 +1,110 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2008 by Sun Microsystems, Inc.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.6 $
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org 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 version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..
+
+PRJNAME=store
+TARGET=workben
+
+LIBTARGET=NO
+TARGETTYPE=CUI
+NO_DEFAULT_STL=TRUE
+
+# --- Settings ---
+
+.INCLUDE : settings.mk
+
+.IF "$(STORELIB)" == ""
+.IF "$(GUI)" == "UNX"
+STORELIB= -lstore
+.ELSE # unx
+.IF "$(GUI)$(COM)"=="WNTGCC"
+STORELIB= -lstore$(UDK_MAJOR)
+.ELSE
+STORELIB= $(LB)$/istore.lib
+.ENDIF
+.ENDIF # unx
+.ENDIF # storelib
+
+.IF "$(GUI)" == "UNX"
+STOREDBGLIB= $(LB)$/libstoredbg.a
+.ELSE # unx
+.IF "$(GUI)$(COM)"=="WNTGCC"
+STOREDBGLIB= $(LB)$/libstoredbg.a
+.ELSE
+STOREDBGLIB= $(LB)$/storedbg.lib
+.ENDIF
+.ENDIF # unx
+
+CFLAGS+= -I..$/source
+
+# --- Files ---
+
+OBJFILES= \
+ $(OBJ)$/t_leak.obj \
+ $(OBJ)$/t_file.obj \
+ $(OBJ)$/t_page.obj \
+ $(OBJ)$/t_base.obj \
+ $(OBJ)$/t_store.obj
+
+APP1TARGET= t_file
+APP1OBJS= $(OBJ)$/t_file.obj
+APP1STDLIBS= $(STOREDBGLIB)
+APP1STDLIBS+= $(SALLIB)
+APP1DEPN= $(STOREDBGLIB)
+
+APP2TARGET= t_page
+APP2OBJS= $(OBJ)$/t_page.obj
+APP2STDLIBS= $(STOREDBGLIB)
+APP2STDLIBS+= $(SALLIB)
+APP2DEPN= $(STOREDBGLIB)
+
+APP3TARGET= t_base
+APP3OBJS= $(OBJ)$/t_base.obj
+APP3STDLIBS= $(STOREDBGLIB)
+APP3STDLIBS+= $(SALLIB)
+APP3DEPN= $(STOREDBGLIB)
+
+APP4TARGET= t_store
+APP4OBJS= $(OBJ)$/t_store.obj
+APP4STDLIBS= $(STORELIB)
+APP4STDLIBS+= $(SALLIB)
+APP4DEPN= $(SLB)$/store.lib
+APP4RPATH= UREBIN
+
+ APP5TARGET= t_leak
+ APP5OBJS= $(OBJ)$/t_leak.obj
+ APP5STDLIBS+= $(SALLIB)
+
+# --- Targets ---
+
+.INCLUDE : target.mk
+
diff --git a/store/workben/t_base.cxx b/store/workben/t_base.cxx
new file mode 100644
index 000000000000..593736e4d57b
--- /dev/null
+++ b/store/workben/t_base.cxx
@@ -0,0 +1,385 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: t_base.cxx,v $
+ * $Revision: 1.8 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_store.hxx"
+
+#include "sal/types.h"
+#include "osl/diagnose.h"
+#include "osl/thread.h"
+#include "rtl/memory.h"
+#include "rtl/ustring.hxx"
+
+#include "object.hxx"
+#include "storbase.hxx"
+#include "storbios.hxx"
+#include "lockbyte.hxx"
+
+using namespace store;
+
+#define TEST_PAGESIZE 1024
+
+/*========================================================================
+ *
+ * OTestObject.
+ *
+ *======================================================================*/
+class OTestObject : public store::OStoreObject
+{
+public:
+ OTestObject (void);
+
+ virtual sal_Bool SAL_CALL isKindOf (sal_uInt32 nTypeId);
+
+protected:
+ virtual ~OTestObject (void);
+};
+
+OTestObject::OTestObject (void)
+{
+}
+
+OTestObject::~OTestObject (void)
+{
+}
+
+sal_Bool SAL_CALL OTestObject::isKindOf (sal_uInt32 nTypeId)
+{
+ return (nTypeId == 42);
+}
+
+namespace store
+{
+static OTestObject* SAL_CALL query (IStoreHandle *pHandle, OTestObject*)
+{
+ if (pHandle && pHandle->isKindOf (42))
+ return static_cast<OTestObject*>(pHandle);
+ else
+ return 0;
+}
+}
+
+/*========================================================================
+ *
+ * OTestBIOS.
+ *
+ *======================================================================*/
+namespace store
+{
+
+class OTestBIOS : public store::OStorePageBIOS
+{
+ typedef store::OStorePageBIOS base;
+
+ friend OTestBIOS* SAL_CALL query<> (IStoreHandle * pHandle, OTestBIOS *);
+
+public:
+ OTestBIOS (void);
+
+ virtual storeError initialize (
+ ILockBytes * pLockBytes,
+ storeAccessMode eAccessMode,
+ sal_uInt16 & rnPageSize);
+
+ virtual sal_Bool SAL_CALL isKindOf (sal_uInt32 nTypeId);
+
+protected:
+ virtual ~OTestBIOS (void);
+};
+
+} // namespace store
+
+OTestBIOS::OTestBIOS (void)
+{
+}
+
+OTestBIOS::~OTestBIOS (void)
+{
+}
+
+sal_Bool SAL_CALL OTestBIOS::isKindOf (sal_uInt32 nTypeId)
+{
+ return (nTypeId == 4242);
+}
+
+storeError OTestBIOS::initialize (
+ ILockBytes *pLockBytes, storeAccessMode eAccessMode, sal_uInt16 & rnPageSize)
+{
+ return base::initialize (pLockBytes, eAccessMode, rnPageSize);
+}
+
+namespace store
+{
+template<> OTestBIOS* SAL_CALL query (IStoreHandle *pHandle, OTestBIOS*)
+{
+ if (pHandle && pHandle->isKindOf (4242))
+ return static_cast<OTestBIOS*>(pHandle);
+ else
+ return 0;
+}
+}
+
+/*========================================================================
+ *
+ * __store_test_handle.
+ *
+ *======================================================================*/
+static void __store_test_handle (void* Handle)
+{
+ IStoreHandle *pHandle = static_cast<IStoreHandle*>(Handle);
+ if (pHandle)
+ {
+ pHandle->acquire();
+ pHandle->isKindOf (42);
+ pHandle->release();
+ }
+
+ OTestObject *pObj = query (pHandle, static_cast<OTestObject*>(0));
+ if (pObj)
+ {
+ pObj->acquire();
+ pObj->isKindOf (42);
+ pObj->release();
+ }
+}
+
+/*========================================================================
+ *
+ * unicode.
+ *
+ *======================================================================*/
+static void __store_string_newFromUnicode_WithLength (
+ rtl_String **newString, const sal_Unicode *value, sal_Int32 length)
+{
+ rtl_uString2String (
+ newString,
+ value, length,
+ RTL_TEXTENCODING_UTF8,
+ OUSTRING_TO_OSTRING_CVTFLAGS);
+}
+
+#if 0 /* UNSUSED */
+static void __store_string_newFromUnicode (
+ rtl_String **newString, const rtl_uString *value)
+{
+ __store_string_newFromUnicode_WithLength (
+ newString, value->buffer, value->length);
+}
+#endif /* UNUSED */
+
+static void __store_string_newFromUnicode (
+ rtl_String **newString, const sal_Unicode *value)
+{
+ __store_string_newFromUnicode_WithLength (
+ newString, value, rtl_ustr_getLength (value));
+}
+
+static storeError __store_namei (
+ const sal_Unicode *pszPath,
+ const sal_Unicode *pszName,
+ OStorePageKey &rKey)
+{
+ rtl::OString aName (
+ pszName, rtl_ustr_getLength (pszName), RTL_TEXTENCODING_UTF8);
+
+ rtl_String *pszNameA = 0;
+ __store_string_newFromUnicode (&pszNameA, pszName);
+
+ storeError eErrCode = store_E_NameTooLong;
+ if (pszNameA->length < sal_Int32(sizeof(sal_Char[STORE_MAXIMUM_NAMESIZE])))
+ {
+ rtl_String *pszPathA = 0;
+ __store_string_newFromUnicode (&pszPathA, pszPath);
+
+ rKey.m_nLow = rtl_crc32 (0, pszNameA->buffer, pszNameA->length);
+ rKey.m_nHigh = rtl_crc32 (0, pszPathA->buffer, pszPathA->length);
+
+ rtl_string_release (pszPathA);
+ eErrCode = store_E_None;
+ }
+
+ rtl_string_release (pszNameA);
+ return eErrCode;
+}
+
+static sal_Size __store_convertTextToUnicode (
+ rtl_TextToUnicodeConverter hConvert,
+ const sal_Char *pszText, sal_Size nTextLen,
+ sal_Unicode *pBuffer, sal_Size nBuffer)
+{
+ sal_uInt32 nInfo = 0;
+ sal_Size nSrcLen = 0;
+
+ sal_Int32 nDstLen = rtl_convertTextToUnicode (
+ hConvert, 0,
+ pszText, nTextLen,
+ pBuffer, nBuffer,
+ OSTRING_TO_OUSTRING_CVTFLAGS,
+ &nInfo, &nSrcLen);
+
+ pBuffer[nDstLen] = 0;
+ return nDstLen;
+}
+
+struct MyFindData
+{
+ sal_Unicode m_pszName[STORE_MAXIMUM_NAMESIZE];
+ sal_Int32 m_nLength;
+ sal_uInt32 m_nAttrib;
+ sal_uInt32 m_nSize;
+ sal_uInt32 m_nReserved;
+};
+
+static void __store_testUnicode (const sal_Char *pszFilename)
+{
+ // ...
+ rtl_TextToUnicodeConverter hConvert;
+ hConvert = rtl_createTextToUnicodeConverter (RTL_TEXTENCODING_UTF8);
+
+ MyFindData it;
+ rtl_zeroMemory (&it, sizeof(it));
+
+ sal_Int32 n = rtl_str_getLength (pszFilename);
+ n = __store_convertTextToUnicode (
+ hConvert, pszFilename, n,
+ it.m_pszName, STORE_MAXIMUM_NAMESIZE - 1);
+ if (it.m_nLength > n)
+ rtl_zeroMemory (
+ &it.m_pszName[n], ((it.m_nLength - n) * sizeof(sal_Unicode)));
+ it.m_nLength = n;
+
+ rtl_destroyTextToUnicodeConverter (hConvert);
+
+ // ...
+ rtl_String *pszFileA = NULL;
+ rtl_uString *pszFileW = NULL;
+
+ // rtl_uString_newFromAscii (&pszFileW, pszFilename);
+
+ // ...
+ rtl_string_newFromStr (&pszFileA, pszFilename);
+
+ rtl_string2UString (
+ &pszFileW,
+ pszFileA->buffer, pszFileA->length,
+ RTL_TEXTENCODING_MS_1252,
+ OSTRING_TO_OUSTRING_CVTFLAGS);
+
+ rtl_string_release (pszFileA);
+
+ // ...
+ OStorePageKey aKey;
+ __store_namei (pszFileW->buffer, pszFileW->buffer, aKey);
+
+ // ...
+ rtl_uString2String (
+ &pszFileA,
+ pszFileW->buffer, pszFileW->length,
+ RTL_TEXTENCODING_UTF8,
+ OUSTRING_TO_OSTRING_CVTFLAGS);
+
+ rtl_uString_release (pszFileW);
+
+ // ...
+ rtl_string_release (pszFileA);
+}
+
+/*========================================================================
+ *
+ * main.
+ *
+ *======================================================================*/
+int SAL_CALL main (int argc, char **argv)
+{
+ OSL_PRECOND(argc > 1, "t_base: error: insufficient number of arguments.");
+ if (argc < 2)
+ return 0;
+
+ __store_testUnicode (argv[1]);
+
+ rtl::Reference<ILockBytes> xLockBytes;
+
+ rtl::OUString aFilename (
+ argv[1], rtl_str_getLength(argv[1]),
+ osl_getThreadTextEncoding());
+
+ storeError eErrCode = FileLockBytes_createInstance (
+ xLockBytes, aFilename.pData, store_AccessReadCreate);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+
+ rtl::Reference<OTestObject> xObject (new OTestObject());
+ __store_test_handle (&*xObject);
+
+ rtl::Reference<OTestBIOS> xBIOS (new OTestBIOS());
+ __store_test_handle (&*xBIOS);
+
+
+ if (!xBIOS.is())
+ return 0;
+
+ sal_uInt16 nPageSize = TEST_PAGESIZE;
+ eErrCode = xBIOS->initialize (&*xLockBytes, store_AccessReadWrite, nPageSize);
+ if (eErrCode != store_E_None)
+ {
+ // Check reason.
+ if (eErrCode != store_E_NotExists)
+ return eErrCode;
+
+ // Create.
+ eErrCode = xBIOS->initialize (&*xLockBytes, store_AccessReadCreate, nPageSize);
+ if (eErrCode != store_E_None)
+ return eErrCode;
+ }
+ xLockBytes.clear();
+
+ sal_Char pBuffer[TEST_PAGESIZE];
+ rtl_zeroMemory (pBuffer, sizeof (pBuffer));
+ rtl_copyMemory (pBuffer, argv[0], rtl_str_getLength(argv[0]) + 1);
+
+ eErrCode = xBIOS->acquireLock (TEST_PAGESIZE, sizeof(pBuffer));
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ eErrCode = xBIOS->write (TEST_PAGESIZE, pBuffer, sizeof (pBuffer));
+ if (eErrCode != store_E_None)
+ {
+ xBIOS->releaseLock (TEST_PAGESIZE, sizeof(pBuffer));
+ return eErrCode;
+ }
+
+ eErrCode = xBIOS->releaseLock (TEST_PAGESIZE, sizeof(pBuffer));
+ if (eErrCode != store_E_None)
+ return eErrCode;
+
+ xBIOS.clear();
+ return 0;
+}
diff --git a/store/workben/t_file.cxx b/store/workben/t_file.cxx
new file mode 100644
index 000000000000..d4feb25651eb
--- /dev/null
+++ b/store/workben/t_file.cxx
@@ -0,0 +1,247 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: t_file.cxx,v $
+ * $Revision: 1.8 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_store.hxx"
+
+#include "sal/types.h"
+#include "osl/thread.h"
+#include "rtl/ustring.hxx"
+
+#include "lockbyte.hxx"
+
+#ifndef INCLUDED_STDIO_H
+#include <stdio.h>
+#define INCLUDED_STDIO_H
+#endif
+
+#include "osl/file.h"
+#include "osl/process.h"
+
+using namespace store;
+
+#define TEST_PAGESIZE 16384
+
+/*========================================================================
+ *
+ * main.
+ *
+ *======================================================================*/
+int SAL_CALL main (int argc, char **argv)
+{
+ storeError eErrCode = store_E_None;
+ rtl::Reference<ILockBytes> xLockBytes;
+
+ if (argc > 1)
+ {
+ rtl::OUString aFilename (
+ argv[1], rtl_str_getLength(argv[1]),
+ osl_getThreadTextEncoding());
+
+#if 0 /* EXP */
+ oslFileError result;
+ rtl::OUString aPath;
+
+ result = osl_getFileURLFromSystemPath(aFilename.pData, &(aPath.pData));
+ if (result != osl_File_E_None)
+ {
+ // not SystemPath, assume FileUrl.
+ aPath = aFilename;
+ }
+ if (rtl_ustr_ascii_shortenedCompare_WithLength(aPath.pData->buffer, aPath.pData->length, "file://", 7) != 0)
+ {
+ // not FileUrl, assume relative path.
+ rtl::OUString aBase;
+ (void) osl_getProcessWorkingDir (&(aBase.pData));
+
+ // absolute FileUrl.
+ (void) osl_getAbsoluteFileURL(aBase.pData, aPath.pData, &(aPath.pData));
+ }
+ aFilename = aPath;
+#endif /* EXP */
+
+ eErrCode = FileLockBytes_createInstance (
+ xLockBytes, aFilename.pData, store_AccessReadWrite);
+ if (eErrCode != store_E_None)
+ {
+ // Check reason.
+ if (eErrCode != store_E_NotExists)
+ {
+ fprintf (stderr, "t_file: create() error: %d\n", eErrCode);
+ return eErrCode;
+ }
+
+ // Create.
+ eErrCode = FileLockBytes_createInstance (
+ xLockBytes, aFilename.pData, store_AccessReadCreate);
+ if (eErrCode != store_E_None)
+ {
+ fprintf (stderr, "t_file: create() error: %d\n", eErrCode);
+ return eErrCode;
+ }
+ }
+ fprintf (stdout, "t_file: using FileLockBytes(\"%s\") implementation.\n", argv[1]);
+ }
+ else
+ {
+ eErrCode = MemoryLockBytes_createInstance (xLockBytes);
+ if (eErrCode != store_E_None)
+ {
+ fprintf (stderr, "t_file: create() error: %d\n", eErrCode);
+ return eErrCode;
+ }
+ fprintf (stdout, "t_file: using MemoryLockBytes implementation.\n");
+ }
+
+ rtl::Reference< PageData::Allocator > xAllocator;
+ eErrCode = xLockBytes->initialize (xAllocator, TEST_PAGESIZE);
+ if (eErrCode != store_E_None)
+ {
+ fprintf (stderr, "t_file: initialize() error: %d\n", eErrCode);
+ return eErrCode;
+ }
+
+ sal_Char buffer[TEST_PAGESIZE];
+ rtl_fillMemory (buffer, sizeof(buffer), sal_uInt8('B'));
+
+ sal_uInt32 i, k;
+ for (k = 0; k < 4; k++)
+ {
+ sal_uInt32 index = k * TEST_PAGESIZE / 4;
+ buffer[index] = 'A';
+ }
+
+ for (i = 0; i < 256; i++)
+ {
+ sal_uInt32 offset = i * TEST_PAGESIZE;
+ eErrCode = xLockBytes->setSize (offset + TEST_PAGESIZE);
+ if (eErrCode != store_E_None)
+ {
+ fprintf (stderr, "t_file: setSize() error: %d\n", eErrCode);
+ return eErrCode;
+ }
+
+ for (k = 0; k < 4; k++)
+ {
+ sal_uInt32 magic = i * 4 + k;
+ if (magic)
+ {
+ sal_uInt32 verify = 0;
+ eErrCode = xLockBytes->readAt (
+ 0, &verify, sizeof(verify));
+ if (eErrCode != store_E_None)
+ {
+ fprintf (stderr, "t_file: readAt() error: %d\n", eErrCode);
+ return eErrCode;
+ }
+ if (verify != magic)
+ {
+ // Failure.
+ fprintf (stderr, "Expected %ld read %ld\n", (unsigned long)(magic), (unsigned long)(verify));
+ }
+ }
+
+ sal_uInt32 index = k * TEST_PAGESIZE / 4;
+ eErrCode = xLockBytes->writeAt (
+ offset + index, &(buffer[index]), TEST_PAGESIZE / 4);
+ if (eErrCode != store_E_None)
+ {
+ fprintf (stderr, "t_file: writeAt() error: %d\n", eErrCode);
+ return eErrCode;
+ }
+
+ magic += 1;
+ eErrCode = xLockBytes->writeAt (
+ 0, &magic, sizeof(magic));
+ if (eErrCode != store_E_None)
+ {
+ fprintf (stderr, "t_file: writeAt() error: %d\n", eErrCode);
+ return eErrCode;
+ }
+ }
+ }
+
+ eErrCode = xLockBytes->flush();
+ if (eErrCode != store_E_None)
+ {
+ fprintf (stderr, "t_file: flush() error: %d\n", eErrCode);
+ return eErrCode;
+ }
+
+ sal_Char verify[TEST_PAGESIZE];
+ for (i = 0; i < 256; i++)
+ {
+ sal_uInt32 offset = i * TEST_PAGESIZE;
+
+ eErrCode = xLockBytes->readAt (offset, verify, TEST_PAGESIZE);
+ if (eErrCode != store_E_None)
+ {
+ fprintf (stderr, "t_file: readAt() error: %d\n", eErrCode);
+ return eErrCode;
+ }
+
+ sal_uInt32 index = 0;
+ if (offset == 0)
+ {
+ sal_uInt32 magic = 256 * 4;
+ if (rtl_compareMemory (&verify[index], &magic, sizeof(magic)))
+ {
+ // Failure.
+ fprintf (stderr, "t_file: Unexpected value at 0x00000000\n");
+ }
+ index += 4;
+ }
+ if (rtl_compareMemory (
+ &verify[index], &buffer[index], TEST_PAGESIZE - index))
+ {
+ // Failure.
+ fprintf (stderr, "t_file: Unexpected block at 0x%08x\n", (unsigned)(offset));
+ }
+ }
+
+ for (i = 0; i < 256; i++)
+ {
+ PageHolder xPage;
+ sal_uInt32 offset = i * TEST_PAGESIZE;
+
+ eErrCode = xLockBytes->readPageAt (xPage, offset);
+ if (eErrCode != store_E_None)
+ {
+ fprintf (stderr, "t_file: readPageAt() error: %d\n", eErrCode);
+ return eErrCode;
+ }
+
+ PageData * page = xPage.get();
+ (void)page; // UNUSED
+ }
+
+ xLockBytes.clear();
+ return 0;
+}
diff --git a/store/workben/t_leak.cxx b/store/workben/t_leak.cxx
new file mode 100644
index 000000000000..d4d7b8a840e1
--- /dev/null
+++ b/store/workben/t_leak.cxx
@@ -0,0 +1,19 @@
+/*
+ * t_leak.cxx
+ */
+
+#include "sal/main.h"
+#include "osl/process.h"
+#include "osl/thread.h"
+
+ int main (int /*argc*/, char ** /*argv*/)
+//SAL_IMPLEMENT_MAIN()
+{
+ rtl_Locale * pLocale = 0;
+ osl_getProcessLocale (&pLocale);
+#if 0
+ rtl_TextEncoding te = osl_getThreadTextEncoding();
+ (void) te;
+#endif
+ return 0;
+}
diff --git a/store/workben/t_page.cxx b/store/workben/t_page.cxx
new file mode 100644
index 000000000000..a0645f00bc58
--- /dev/null
+++ b/store/workben/t_page.cxx
@@ -0,0 +1,1574 @@
+/*
+ * t_page.cxx
+ */
+
+#include "osl/diagnose.h"
+#include "rtl/alloc.h"
+#include "rtl/ref.hxx"
+
+#include "storbase.hxx"
+
+#include "osl/file.h"
+#include "rtl/ustring.hxx"
+
+/*========================================================================
+ *
+ * OTest...
+ *
+ *======================================================================*/
+
+template< class T > void swap (T & lhs, T & rhs)
+{
+ T tmp = rhs; rhs = lhs; lhs = tmp;
+}
+
+/*======================================================================*/
+
+class SharedCount
+{
+ long * m_pCount;
+
+ class Allocator
+ {
+ rtl_cache_type * m_cache;
+
+ public:
+ static Allocator & get();
+
+ long * alloc()
+ {
+ return static_cast<long*>(rtl_cache_alloc (m_cache));
+ }
+ void free (long * pCount)
+ {
+ rtl_cache_free (m_cache, pCount);
+ }
+
+ protected:
+ Allocator();
+ ~Allocator();
+ };
+
+public:
+ SharedCount()
+ : m_pCount(Allocator::get().alloc())
+ {
+ if (m_pCount != 0) (*m_pCount) = 1;
+ }
+
+ ~SharedCount()
+ {
+ if (m_pCount != 0)
+ {
+ long new_count = --(*m_pCount);
+ if (new_count == 0)
+ Allocator::get().free(m_pCount);
+ }
+ }
+
+ bool operator== (long count) const
+ {
+ return (m_pCount != 0) ? *m_pCount == count : false;
+ }
+
+ friend void swap<> (SharedCount & lhs, SharedCount & rhs); // nothrow
+
+ SharedCount (SharedCount const & rhs); // nothrow
+ SharedCount & operator= (SharedCount const & rhs); // nothrow
+};
+
+template<>
+inline void swap (SharedCount & lhs, SharedCount & rhs) // nothrow
+{
+ swap<long*>(lhs.m_pCount, rhs.m_pCount);
+}
+
+SharedCount::SharedCount (SharedCount const & rhs) // nothrow
+ : m_pCount (rhs.m_pCount)
+{
+ if (m_pCount != 0) ++(*m_pCount);
+}
+
+SharedCount &
+SharedCount::operator= (SharedCount const & rhs) // nothrow
+{
+ SharedCount tmp(rhs);
+ swap<SharedCount>(tmp, *this);
+ return *this;
+}
+
+SharedCount::Allocator &
+SharedCount::Allocator::get()
+{
+ static Allocator g_aSharedCountAllocator;
+ return g_aSharedCountAllocator;
+}
+
+SharedCount::Allocator::Allocator()
+{
+ m_cache = rtl_cache_create (
+ "store_shared_count_cache",
+ sizeof(long),
+ 0, // objalign
+ 0, // constructor
+ 0, // destructor
+ 0, // reclaim
+ 0, // userarg
+ 0, // default source
+ 0 // flags
+ );
+}
+
+SharedCount::Allocator::~Allocator()
+{
+ rtl_cache_destroy (m_cache), m_cache = 0;
+}
+
+/*======================================================================*/
+
+#if 0 /* OLD */
+
+typedef store::OStorePageData PageData;
+
+#else /* NEW */
+
+#if defined(OSL_BIGENDIAN)
+#define STORE_DWORD(dword) OSL_SWAPDWORD((dword))
+#else
+#define STORE_DWORD(dword) (dword)
+#endif
+
+struct PageData
+{
+ typedef store::OStorePageGuard G;
+ typedef store::OStorePageDescriptor D;
+ typedef store::OStorePageLink L;
+
+ /** Representation.
+ */
+ G m_aGuard;
+ D m_aDescr;
+ L m_aMarked;
+ L m_aUnused;
+
+ /** theSize.
+ */
+ static const size_t theSize = sizeof(G) + sizeof(D) + 2 * sizeof(L);
+ static const sal_uInt16 thePageSize = theSize;
+ STORE_STATIC_ASSERT(STORE_MINIMUM_PAGESIZE >= thePageSize);
+
+ /** type.
+ */
+ sal_uInt32 type() const { return m_aGuard.m_nMagic; /* @@@ */ }
+
+ /** offset.
+ */
+ sal_uInt32 offset() const { return m_aDescr.m_nAddr; /* @@@ */ }
+ void offset (sal_uInt32 nOffset) { m_aDescr.m_nAddr = nOffset; }
+
+ /** size.
+ */
+ sal_uInt16 size() const { return m_aDescr.m_nSize; /* @@@ */ }
+
+ /** Allocation.
+ */
+ class Allocator : public rtl::IReference
+ {
+ public:
+ template< class T > T * construct()
+ {
+ void * page = 0; sal_uInt16 size = 0;
+ if (allocate (&page, &size))
+ {
+ return new(page) T(size);
+ }
+ return 0;
+ }
+
+ virtual bool allocate (void ** ppPage, sal_uInt16 * pnSize) = 0;
+ virtual void deallocate (void * pPage) = 0;
+ };
+
+ static void * operator new (size_t, void * p) { return p; }
+ static void operator delete (void *, void *) {}
+
+ /** Construction.
+ */
+ explicit PageData (sal_uInt16 nPageSize = thePageSize)
+ : m_aDescr (STORE_PAGE_NULL, nPageSize, thePageSize)
+ {}
+
+ /** ...
+ */
+ void guard()
+ {}
+
+ storeError verify() const
+ {
+ return store_E_None;
+ }
+};
+
+#endif /* NEW */
+
+class IPageAllocator
+{
+public:
+ virtual void deallocate (void * p) = 0;
+};
+
+class PageAllocator
+{
+ rtl_cache_type * m_cache;
+ SharedCount m_refcount;
+
+public:
+ PageAllocator()
+ : m_cache(0), m_refcount()
+ {}
+
+ ~PageAllocator()
+ {
+ // NYI
+ if (m_refcount == 1)
+ {
+ }
+ }
+
+ friend void swap<>(PageAllocator & lhs, PageAllocator & rhs);
+
+ PageAllocator (PageAllocator const & rhs);
+ PageAllocator & operator= (PageAllocator const & rhs);
+};
+
+template<>
+inline void swap (PageAllocator & lhs, PageAllocator & rhs)
+{
+ swap<rtl_cache_type*>(lhs.m_cache, rhs.m_cache);
+ swap<SharedCount>(lhs.m_refcount, rhs.m_refcount);
+}
+
+PageAllocator::PageAllocator (PageAllocator const & rhs)
+ : m_cache (rhs.m_cache),
+ m_refcount (rhs.m_refcount)
+{
+}
+
+PageAllocator &
+PageAllocator::operator= (PageAllocator const & rhs)
+{
+ PageAllocator tmp (rhs);
+ swap<PageAllocator>(tmp, *this);
+ return *this;
+}
+
+/*======================================================================*/
+
+class PageHolder
+{
+ SharedCount m_refcount;
+ PageData * m_pagedata;
+
+ typedef rtl::Reference< PageData::Allocator > allocator_type;
+ allocator_type m_allocator;
+
+public:
+ explicit PageHolder (PageData * pagedata = 0, allocator_type const & allocator = allocator_type())
+ : m_refcount (),
+ m_pagedata (pagedata),
+ m_allocator(allocator)
+ {}
+
+ ~PageHolder()
+ {
+ if ((m_refcount == 1) && (m_pagedata != 0) && m_allocator.is())
+ {
+ // free pagedata.
+ m_allocator->deallocate (m_pagedata);
+ }
+ }
+
+ PageData * get() { return m_pagedata; }
+ PageData const * get() const { return m_pagedata; }
+
+ PageData * operator->() { return m_pagedata; }
+ PageData const * operator->() const { return m_pagedata; }
+
+ friend void swap<> (PageHolder & lhs, PageHolder & rhs); // nothrow
+
+ PageHolder (PageHolder const & rhs); // nothrow
+ PageHolder & operator= (PageHolder const & rhs); // nothrow
+};
+
+template<>
+inline void swap (PageHolder & lhs, PageHolder & rhs) // nothrow
+{
+ swap<SharedCount>(lhs.m_refcount, rhs.m_refcount);
+ swap<PageData*>(lhs.m_pagedata, rhs.m_pagedata);
+ swap<PageHolder::allocator_type>(lhs.m_allocator, rhs.m_allocator);
+}
+
+PageHolder::PageHolder (PageHolder const & rhs) // nothrow
+ : m_refcount (rhs.m_refcount),
+ m_pagedata (rhs.m_pagedata),
+ m_allocator(rhs.m_allocator)
+{}
+
+PageHolder &
+PageHolder::operator= (PageHolder const & rhs) // nothrow
+{
+ PageHolder tmp (rhs);
+ swap<PageHolder>(tmp, *this);
+ return *this;
+}
+
+/*======================================================================*/
+
+template< class T >
+class PageHolderObject
+{
+protected:
+ /** Representation.
+ */
+ PageHolder m_xPage;
+
+ /** Checked cast.
+ */
+ template< class U >
+ static bool isA (PageData const * p)
+ {
+ return ((p != 0) && (p->type() == U::theTypeId));
+ }
+
+ template< class U >
+ static U * dynamic_page_cast (PageData * p)
+ {
+ return isA<U>(p) ? static_cast<U*>(p) : 0;
+ }
+
+ template< class U >
+ static U const * dynamic_page_cast (PageData const * p)
+ {
+ return isA<U>(p) ? static_cast<U const *>(p) : 0;
+ }
+
+public:
+ static PageHolderObject<T> construct (rtl::Reference< PageData::Allocator > const & rxAllocator)
+ {
+ PageHolderObject<T> tmp;
+ if (rxAllocator.is())
+ {
+ PageHolder xPage (rxAllocator->construct<T>(), rxAllocator);
+ store::swap<PageHolder>(tmp.m_xPage, xPage);
+ }
+ return tmp;
+ }
+
+ explicit PageHolderObject (PageHolder const & rxPage = PageHolder())
+ : m_xPage (rxPage)
+ {}
+
+ void swap (PageHolderObject<T> & rhs)
+ {
+ store::swap<PageHolder>(m_xPage, rhs.m_xPage);
+ }
+
+ PageHolderObject (PageHolderObject<T> const & rhs)
+ : m_xPage (rhs.m_xPage)
+ {
+ }
+
+ PageHolderObject<T> & operator= (PageHolderObject<T> const & rhs)
+ {
+ PageHolderObject<T> tmp (rhs);
+ this->swap(tmp);
+ return *this;
+ }
+
+ T * operator->()
+ {
+ T * pImpl = dynamic_page_cast<T>(m_xPage.get());
+ OSL_PRECOND(pImpl != 0, "store::PageHolder<T>::operator->(): Null pointer");
+ return pImpl;
+ }
+ T const * operator->() const
+ {
+ T const * pImpl = dynamic_page_cast<T>(m_xPage.get());
+ OSL_PRECOND(pImpl != 0, "store::PageHolder<T>::operator->(): Null pointer");
+ return pImpl;
+ }
+
+ T & operator*()
+ {
+ T * pImpl = dynamic_page_cast<T>(m_xPage.get());
+ OSL_PRECOND(pImpl != 0, "store::PageHolder<T>::operator*(): Null pointer");
+ return *pImpl;
+ }
+ T const & operator*() const
+ {
+ T const * pImpl = dynamic_page_cast<T>(m_xPage.get());
+ OSL_PRECOND(pImpl != 0, "store::PageHolder<T>::operator*(): Null pointer");
+ return *pImpl;
+ }
+
+ static storeError guard (PageHolder & rxPage)
+ {
+ T * pImpl = dynamic_page_cast<T>(rxPage.get());
+ if (pImpl != 0)
+ { pImpl->guard(); return store_E_None; }
+ else if (rxPage.get() != 0)
+ return store_E_WrongVersion;
+ else
+ return store_E_InvalidAccess;
+ }
+ static storeError verify (PageHolder const & rxPage)
+ {
+ T const * pImpl = dynamic_page_cast<T>(rxPage.get());
+ if (pImpl != 0)
+ return pImpl->verify();
+ else if (rxPage.get() != 0)
+ return store_E_WrongVersion;
+ else
+ return store_E_InvalidAccess;
+ }
+};
+
+/*======================================================================*/
+
+class PageObject
+{
+public:
+ explicit PageObject (PageHolder const & rxPage = PageHolder())
+ : m_xPage (rxPage)
+ {}
+
+ virtual ~PageObject();
+
+ PageHolder & get() { return m_xPage; }
+ PageHolder const & get() const { return m_xPage; }
+
+ PageData * operator->()
+ {
+ PageData * pImpl = m_xPage.get();
+ OSL_PRECOND(pImpl != 0, "store::PageObject::operator->(): Null pointer");
+ return pImpl;
+ }
+ PageData & operator*()
+ {
+ PageData * pImpl = m_xPage.get();
+ OSL_PRECOND(pImpl != 0, "store::PageObject::operator*(): Null pointer");
+ return *pImpl;
+ }
+
+ virtual void guard();
+ virtual storeError verify() const;
+
+protected:
+ PageHolder m_xPage;
+};
+
+PageObject::~PageObject()
+{}
+void PageObject::guard()
+{
+ PageData * p = m_xPage.get();
+ p->guard();
+}
+storeError PageObject::verify() const
+{
+ PageData const * p = m_xPage.get();
+ return p->verify();
+}
+
+/*======================================================================*/
+
+template< class T >
+T * dynamic_page_cast (PageData * pagedata)
+{
+ if ((pagedata != 0) && (pagedata->type() == T::theTypeId))
+ return static_cast<T*>(pagedata);
+ return 0;
+}
+
+template< class T >
+T * dynamic_page_cast (PageData const * pagedata)
+{
+ if ((pagedata != 0) && (pagedata->type() == T::theTypeId))
+ return static_cast<T*>(pagedata);
+ return 0;
+}
+
+/*======================================================================*/
+
+class TestBIOS
+{
+public:
+ storeError loadPageAt (PageHolder & rPage, storeError (*pfnVerify)(PageHolder const &))
+ {
+ return (pfnVerify)(rPage);
+ }
+
+ storeError allocate (PageHolder & rxPage, ...)
+ {
+ // NYI: PageObject.save(nAddr, *this);
+ (void)rxPage; // NYI
+ return store_E_Unknown; // NYI
+ }
+
+ storeError loadAt (PageHolder & rPage, sal_uInt32 nOffset)
+ {
+ (void)rPage; // NYI
+ (void)nOffset; // NYI
+ return store_E_Unknown; // NYI
+ }
+ storeError saveAt (PageHolder const & rPage, sal_uInt32 nOffset)
+ {
+ (void)rPage; // NYI
+ (void)nOffset; // NYI
+ return store_E_Unknown; // NYI
+ }
+
+ template< class T >
+ storeError save (PageHolder & rxPage, sal_uInt32 nOffset)
+ {
+ storeError result = PageHolderObject<T>::guard (rxPage);
+ if (result != store_E_None)
+ return result;
+ return saveAt (rxPage, nOffset);
+ }
+
+ storeError lookupAt (PageHolder & rPage, sal_uInt32 nOffset)
+ {
+ (void)rPage; // NYI
+ (void)nOffset; // NYI
+ return store_E_NotExists;
+ }
+ storeError replaceAt (PageHolder const & rPage, sal_uInt32 nOffset)
+ {
+ (void)rPage; // NYI
+ (void)nOffset; // NYI
+ return store_E_None;
+ }
+};
+
+struct TestDataV1 : public PageData
+{
+ static const sal_uInt32 theTypeId = 6 * 9;
+};
+struct TestData : public PageData
+{
+ typedef PageData base;
+ typedef TestData self;
+
+ static const sal_uInt32 theTypeId = 42;
+
+ void guard()
+ {
+ base::guard();
+ // self::m_aGuard = ...;
+ }
+ storeError verify() const
+ {
+ storeError result = base::verify();
+ if (result != store_E_None)
+ return result;
+ if (!(base::type() == self::theTypeId))
+ return store_E_WrongVersion;
+ return store_E_None;
+ }
+
+ storeError dwim() const
+ {
+ return store_E_None;
+ }
+};
+class TestObject : public PageObject
+{
+ typedef PageObject base;
+
+public:
+
+ void dwim()
+ {
+ PageHolderObject< TestData > xPage (m_xPage);
+ xPage->guard();
+ }
+
+ virtual void guard()
+ {
+ TestData * pagedata = dynamic_page_cast< TestData >(m_xPage.get());
+ if (pagedata != 0)
+ {}
+ }
+ virtual storeError verify() const
+ {
+ storeError result = base::verify();
+ if (result != store_E_None)
+ return result;
+
+ TestData const * pagedata = dynamic_page_cast< TestData const >(m_xPage.get());
+ if (!pagedata)
+ return store_E_WrongVersion;
+
+ return pagedata->verify();
+ }
+
+ static storeError verify (PageHolder const & rPage)
+ {
+ return PageHolderObject< TestData >::verify (rPage);
+ }
+
+ storeError loadAt (sal_uInt32 nOffset, TestBIOS & rBIOS)
+ {
+ storeError result = rBIOS.lookupAt (m_xPage, nOffset); // cache lookup
+ if (result == store_E_NotExists)
+ {
+ result = rBIOS.loadAt (m_xPage, nOffset);
+ if (result != store_E_None)
+ return result;
+
+ result = PageHolderObject< TestData >::verify (m_xPage);
+ if (result != store_E_None)
+ return result;
+
+ result = rBIOS.replaceAt (m_xPage, nOffset); // cache insert
+ }
+ return result;
+ }
+ storeError saveAt (sal_uInt32 nOffset, TestBIOS & rBIOS)
+ {
+ if (!m_xPage.get())
+ return store_E_InvalidAccess;
+ m_xPage->m_aDescr.m_nAddr = store::htonl(nOffset); // m_xPage->location (nOffset);
+
+ storeError result = PageHolderObject< TestData >::guard (m_xPage);
+ if (result != store_E_None)
+ return result;
+
+ result = rBIOS.saveAt (m_xPage, nOffset);
+ if (result != store_E_None)
+ return result;
+
+ return rBIOS.replaceAt (m_xPage, nOffset); // cache update
+ }
+};
+
+class TestObjectV2 : public PageHolderObject< TestData >
+{
+ typedef PageHolderObject< TestData > base;
+
+public:
+ storeError saveAt (sal_uInt32 nOffset, TestBIOS & rBIOS)
+ {
+ m_xPage->offset(nOffset);
+
+ storeError result = PageHolderObject< TestData >::guard (m_xPage);
+ if (result != store_E_None)
+ return result;
+
+ result = rBIOS.saveAt (m_xPage, nOffset);
+ if (result != store_E_None)
+ return result;
+
+ return rBIOS.replaceAt (m_xPage, nOffset);
+ }
+#if 1
+ storeError dwim() const
+ {
+ TestData const * pImpl1 = operator->();
+
+ PageHolderObject< TestData > xImpl (m_xPage);
+
+ TestData const * pImpl2 = &*xImpl;
+ OSL_ASSERT(pImpl1 == pImpl2);
+
+ return xImpl->dwim();
+ }
+#endif
+};
+
+class TestClient
+{
+public:
+ void dwim(TestBIOS & rBIOS)
+ {
+ TestObject aObj;
+
+ rBIOS.loadPageAt(aObj.get(), aObj.verify);
+ rBIOS.loadPageAt(aObj.get(), TestObject::verify);
+ rBIOS.loadPageAt(aObj.get(), PageHolderObject<TestData>::verify);
+
+ aObj.loadAt (1024, rBIOS);
+
+ TestObjectV2 aObj2;
+ aObj2.dwim();
+ aObj2->dwim();
+ }
+};
+
+/*======================================================================*/
+#if 0 /* NYI */
+BIOS::load (PageObject & rPage, sal_uInt32 nOffset)
+{
+ result = m_xCache->readPageAt (rPage.get(), nOffset);
+ if (result == NotExists)
+ {
+ result = m_xLockBytes->readPageAt (rPage.get(), nOffset);
+ if (result != None)
+ return result;
+
+ result = rPage.verify();
+ if (result != None)
+ return result;
+
+ result = m_xCache->writePageAt (rPage.get(), nOffset);
+ }
+ return result;
+}
+BIOS::save (PageObject & rPage, sal_uInt32 nOffset)
+{
+ rPage.guard();
+ result = m_xLockBytes->writePageAt (rPage.get(), nOffset);
+ if (result != None)
+ return result;
+
+ return m_xCache->writePageAt (rPage.get(), nOffset);
+}
+BIOS::init (rxLockBytes, eAccessMode, nPageSize)
+{
+ SuperPage super;
+ if (eAccessMode == store_AccessCreate)
+ {
+ sal_uInt16 pagesize = nPageSize;
+ if ((STORE_MINIMUM_PAGESIZE > pagesize) || (pagesize > STORE_MAXIMUM_PAGESIZE))
+ return store_E_InvalidParameter;
+
+ pagesize = ((pagesize + STORE_MINIMUM_PAGESIZE - 1) & ~(STORE_MINIMUM_PAGESIZE - 1));
+ rxLockBytes->init (pagesize);
+
+ super = allocator->construct<SuperPage>();
+ super->guard();
+
+ rxLockBytes->writeAt (0, super, super->size());
+
+ }
+ if (eAccessMode != store_AccessCreate)
+ {
+ rxLockBytes->readAt (0, &super, super::theSize);
+
+ super.verify();
+ }
+ if (eErrCode != store_E_NotExists)
+
+
+}
+#endif /* NYI */
+/*======================================================================*/
+
+#if 0 /* NYI */
+class PageCache
+{
+ std::set<const sal_uInt32, PageObject> m_pages;
+public:
+ storeError readPageAt (PageObject & rPage, sal_uInt32 nOffset);
+ storeError writePageAt (PageObject const & rPage, sal_uInt32 nOffset);
+};
+#endif /* NYI */
+
+/*======================================================================*/
+
+class IPageAllocator;
+class IPageAccess
+{
+public:
+ virtual storeError initialize (storeAccessMode eAccessMode, sal_uInt16 nPageSize) = 0;
+ virtual IPageAllocator & getAllocator () = 0;
+
+public:
+ storeError readPageAt (PageHolder & rPage, sal_uInt32 nOffset)
+ {
+ return readPageAt_Impl (rPage, nOffset);
+ }
+ storeError writePageAt (PageHolder const & rPage, sal_uInt32 nOffset)
+ {
+ // [SECURITY:ValInput]
+ PageData const * pagedata = rPage.get();
+ OSL_PRECOND(!(pagedata == 0), "invalid Page");
+ if (pagedata == 0)
+ return store_E_InvalidParameter;
+
+ sal_uInt32 const offset = pagedata->offset();
+ OSL_PRECOND(!(nOffset != offset), "inconsistent Offset");
+ if (nOffset != offset)
+ return store_E_InvalidParameter;
+
+ OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::IPageAccess::writePageAt(): invalid Offset");
+ if (nOffset == STORE_PAGE_NULL)
+ return store_E_CantSeek;
+
+ return writePageAt_Impl (rPage, nOffset);
+ }
+
+ storeError peekAt (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes)
+ {
+ // [SECURITY:ValInput]
+ sal_uInt8 * dst_lo = static_cast<sal_uInt8*>(pBuffer);
+ if (!(dst_lo != 0))
+ return store_E_InvalidParameter;
+
+ sal_uInt8 * dst_hi = dst_lo + nBytes;
+ if (!(dst_lo < dst_hi))
+ return (dst_lo > dst_hi) ? store_E_InvalidParameter : store_E_None;
+
+ sal_uInt64 const dst_size = nOffset + nBytes;
+ if (dst_size > SAL_MAX_UINT32)
+ return store_E_CantSeek;
+
+ return peekAt_Impl (nOffset, dst_lo, (dst_hi - dst_lo));
+ }
+
+ storeError pokeAt (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes)
+ {
+ // [SECURITY:ValInput]
+ sal_uInt8 const * src_lo = static_cast<sal_uInt8 const*>(pBuffer);
+ if (!(src_lo != 0))
+ return store_E_InvalidParameter;
+
+ sal_uInt8 const * src_hi = src_lo + nBytes;
+ if (!(src_lo < src_hi))
+ return (src_lo > src_hi) ? store_E_InvalidParameter : store_E_None;
+
+ sal_uInt64 const dst_size = nOffset + nBytes;
+ if (dst_size > SAL_MAX_UINT32)
+ return store_E_CantSeek;
+
+ return pokeAt_Impl (nOffset, src_lo, (src_hi - src_lo));
+ }
+
+ storeError getSize (sal_uInt32 & rnSize)
+ {
+ rnSize = 0;
+ return getSize_Impl (rnSize);
+ }
+
+ storeError setSize (sal_uInt32 nSize)
+ {
+ return setSize_Impl (nSize);
+ }
+
+private:
+ virtual storeError readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset) = 0;
+ virtual storeError writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset) = 0;
+
+ virtual storeError peekAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes) = 0;
+ virtual storeError pokeAt_Impl (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes) = 0;
+
+ virtual storeError getSize_Impl (sal_uInt32 & rnSize) = 0;
+ virtual storeError setSize_Impl (sal_uInt32 nSize) = 0;
+};
+
+/*======================================================================*/
+
+template< class T > struct ResourceHolder
+{
+ typedef typename T::destructor_type destructor_type;
+
+ T m_value;
+
+ explicit ResourceHolder (T const & value = T()) : m_value (value) {}
+ ~ResourceHolder() { reset(); }
+
+ T & get() { return m_value; }
+ T const & get() const { return m_value; }
+
+ void set (T const & value) { m_value = value; }
+ void reset (T const & value = T())
+ {
+ T tmp (m_value);
+ if (tmp != value)
+ destructor_type()(tmp);
+ set (value);
+ }
+ T release()
+ {
+ T tmp (m_value);
+ set (T());
+ return tmp;
+ }
+
+ ResourceHolder (ResourceHolder & rhs)
+ {
+ set (rhs.release());
+ }
+ ResourceHolder & operator= (ResourceHolder & rhs)
+ {
+ reset (rhs.release());
+ return *this;
+ }
+};
+
+struct FileHandle
+{
+ oslFileHandle m_handle;
+
+ FileHandle() : m_handle(0) {}
+
+ operator oslFileHandle() { return m_handle; }
+
+ bool operator != (FileHandle const & rhs)
+ {
+ return (m_handle != rhs.m_handle);
+ }
+
+ oslFileError initialize (rtl_uString * pFilename, sal_uInt32 nFlags)
+ {
+ // Verify arguments.
+ if (!pFilename || !nFlags)
+ return osl_File_E_INVAL;
+
+ // Convert into FileUrl.
+ rtl::OUString aFileUrl;
+ if (osl_getFileURLFromSystemPath (pFilename, &(aFileUrl.pData)) != osl_File_E_None)
+ {
+ // Not system path. Maybe a file url, already.
+ rtl_uString_assign (&(aFileUrl.pData), pFilename);
+ }
+
+ // Acquire handle.
+ return osl_openFile (aFileUrl.pData, &m_handle, nFlags);
+ }
+
+ struct CloseFile
+ {
+ void operator()(FileHandle & rFile) const
+ {
+ if (rFile.m_handle != 0)
+ {
+ // Release handle.
+ (void) osl_closeFile (rFile.m_handle);
+ rFile.m_handle = 0;
+ }
+ }
+ };
+ typedef CloseFile destructor_type;
+};
+
+struct FileMapping
+{
+ void * m_pAddr;
+ sal_uInt64 m_uSize;
+
+ FileMapping() : m_pAddr(0), m_uSize(0) {}
+
+ bool operator != (FileMapping const & rhs) const
+ {
+ return ((m_pAddr != rhs.m_pAddr) || (m_uSize != rhs.m_uSize));
+ }
+
+ oslFileError initialize (oslFileHandle hFile)
+ {
+ // Determine mapping size.
+ oslFileError result = osl_getFileSize (hFile, &m_uSize);
+ if (result != osl_File_E_None)
+ return result;
+ if (m_uSize > SAL_MAX_UINT32)
+ return osl_File_E_OVERFLOW;
+
+ // Acquire mapping.
+ return osl_mapFile (hFile, &m_pAddr, m_uSize, 0, 0);
+ }
+
+ struct UnmapFile
+ {
+ void operator ()(FileMapping & rMapping) const
+ {
+ if ((rMapping.m_pAddr != 0) && (rMapping.m_uSize != 0))
+ {
+ // Release mapping.
+ (void) osl_unmapFile (rMapping.m_pAddr, rMapping.m_uSize);
+ rMapping.m_pAddr = 0, rMapping.m_uSize = 0;
+ }
+ }
+ };
+ typedef UnmapFile destructor_type;
+};
+
+/*======================================================================*/
+
+class FilePageAccess : public IPageAccess
+{
+ oslFileHandle m_hFile;
+
+public:
+ static storeError ERROR_FROM_NATIVE (oslFileError eErrno);
+ static sal_uInt32 MODE_TO_NATIVE (storeAccessMode eMode);
+
+public:
+ explicit FilePageAccess (oslFileHandle hFile = 0) : m_hFile (hFile) {}
+ virtual storeError initialize (storeAccessMode eAccessMode, sal_uInt16 nPageSize);
+
+private:
+ virtual storeError readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset);
+ virtual storeError writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset);
+
+ /* see @ OFileLockBytes */
+ virtual storeError peekAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes);
+ virtual storeError pokeAt_Impl (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes);
+
+ virtual storeError getSize_Impl (sal_uInt32 & rnSize);
+ virtual storeError setSize_Impl (sal_uInt32 nSize);
+
+protected:
+ virtual ~FilePageAccess();
+
+private:
+ /** Not implemented.
+ */
+ FilePageAccess (FilePageAccess const &);
+ FilePageAccess & operator= (FilePageAccess const &);
+};
+
+storeError FilePageAccess::initialize (storeAccessMode eAccessMode, sal_uInt16 nPageSize)
+{
+ (void) eAccessMode; // UNUSED
+ (void) nPageSize; // UNUSED
+ return store_E_Unknown; // NYI
+}
+FilePageAccess::~FilePageAccess()
+{
+ if (m_hFile != 0)
+ (void) osl_closeFile (m_hFile);
+}
+storeError FilePageAccess::readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset)
+{
+ PageHolder page (0/*allocate()*/); /* @@@ construct w/ deallocator argument @@@ */
+ if (!page.get())
+ return store_E_OutOfMemory;
+
+ swap<PageHolder>(page, rPage);
+ return peekAt (nOffset, rPage.get(), 0/*size*/);
+}
+storeError FilePageAccess::writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset)
+{
+ return pokeAt (nOffset, rPage.get(), 0/*size*/);
+}
+storeError FilePageAccess::peekAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes)
+{
+ sal_uInt64 nDone = 0;
+ oslFileError result = osl_readFileAt (m_hFile, nOffset, pBuffer, nBytes, &nDone);
+ if (result != osl_File_E_None)
+ return ERROR_FROM_NATIVE(result);
+ if (nDone != nBytes)
+ return (nDone != 0) ? store_E_CantRead : store_E_NotExists;
+ return store_E_None;
+}
+storeError FilePageAccess::pokeAt_Impl (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes)
+{
+ sal_uInt64 nDone = 0;
+ oslFileError result = osl_writeFileAt (m_hFile, nOffset, pBuffer, nBytes, &nDone);
+ if (result != osl_File_E_None)
+ return ERROR_FROM_NATIVE(result);
+ if (nDone != nBytes)
+ return store_E_CantWrite;
+ return store_E_None;
+}
+storeError FilePageAccess::getSize_Impl (sal_uInt32 & rnSize)
+{
+ sal_uInt64 uSize = 0;
+ oslFileError result = osl_getFileSize (m_hFile, &uSize);
+ if (result != osl_File_E_None)
+ return ERROR_FROM_NATIVE(result);
+ if (uSize > SAL_MAX_UINT32)
+ return store_E_CantSeek;
+
+ rnSize = sal::static_int_cast<sal_uInt32>(uSize);
+ return store_E_None;
+}
+storeError FilePageAccess::setSize_Impl (sal_uInt32 nSize)
+{
+ oslFileError result = osl_setFileSize (m_hFile, nSize);
+ if (result != osl_File_E_None)
+ return ERROR_FROM_NATIVE(result);
+ return store_E_None;
+}
+storeError FilePageAccess::ERROR_FROM_NATIVE (oslFileError eErrno)
+{
+ switch (eErrno)
+ {
+ case osl_File_E_None:
+ return store_E_None;
+
+ case osl_File_E_NOENT:
+ return store_E_NotExists;
+
+ case osl_File_E_ACCES:
+ case osl_File_E_PERM:
+ return store_E_AccessViolation;
+
+ case osl_File_E_AGAIN:
+ case osl_File_E_DEADLK:
+ return store_E_LockingViolation;
+
+ case osl_File_E_BADF:
+ return store_E_InvalidHandle;
+
+ case osl_File_E_INVAL:
+ return store_E_InvalidParameter;
+
+ case osl_File_E_NOSPC:
+ return store_E_OutOfSpace;
+
+ case osl_File_E_OVERFLOW:
+ return store_E_CantSeek;
+
+ default:
+ return store_E_Unknown;
+ }
+}
+sal_uInt32 FilePageAccess::MODE_TO_NATIVE(storeAccessMode eAccessMode)
+{
+ sal_uInt32 nMode = 0;
+ switch (eAccessMode)
+ {
+ case store_AccessCreate:
+ case store_AccessReadCreate:
+ nMode |= osl_File_OpenFlag_Create;
+ // fall through
+ case store_AccessReadWrite:
+ nMode |= osl_File_OpenFlag_Write;
+ // fall through
+ case store_AccessReadOnly:
+ nMode |= osl_File_OpenFlag_Read;
+ break;
+ default:
+ OSL_PRECOND(0, "store::FilePageAccess: unknown storeAccessMode");
+ }
+ return nMode;
+}
+
+/*===*/
+
+class MemoryPageAccess : public IPageAccess
+{
+ /** Representation.
+ */
+ sal_uInt8 * m_pData;
+ sal_uInt32 m_nSize;
+
+ /** Callback function to release Representation.
+ */
+ typedef void (*destructor_type)(sal_uInt8 * pData, sal_uInt32 nSize);
+ destructor_type m_destructor;
+
+ /** Default destructor callback.
+ */
+ static void freeMemory (sal_uInt8 * pData, sal_uInt32 nSize);
+
+public:
+ MemoryPageAccess()
+ : m_pData (0), m_nSize (0), m_destructor (MemoryPageAccess::freeMemory)
+ {}
+ MemoryPageAccess (sal_uInt8 * pData, sal_uInt32 nSize, destructor_type destructor = MemoryPageAccess::freeMemory)
+ : m_pData (pData), m_nSize (nSize), m_destructor (destructor)
+ {}
+
+ virtual storeError initialize (storeAccessMode eAccessMode, sal_uInt16 nPageSize);
+
+private:
+ /** Page (size aligned) access.
+ */
+ virtual storeError readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset);
+ virtual storeError writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset);
+
+ /** Low level access.
+ */
+ virtual storeError peekAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes);
+ virtual storeError pokeAt_Impl (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes);
+
+ virtual storeError getSize_Impl (sal_uInt32 & rnSize);
+ virtual storeError setSize_Impl (sal_uInt32 nSize);
+
+protected:
+ virtual ~MemoryPageAccess();
+
+private:
+ /** Not implemented.
+ */
+ MemoryPageAccess (MemoryPageAccess const &);
+ MemoryPageAccess & operator= (MemoryPageAccess const &);
+};
+
+storeError MemoryPageAccess::initialize (storeAccessMode eAccessMode, sal_uInt16 nPageSize)
+{
+ (void) eAccessMode; // UNUSED
+ (void) nPageSize; // UNUSED
+ return store_E_Unknown; // NYI
+}
+MemoryPageAccess::~MemoryPageAccess()
+{
+ if (m_destructor != 0)
+ {
+ // release resource.
+ (*m_destructor)(m_pData, m_nSize);
+ }
+}
+storeError MemoryPageAccess::readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset)
+{
+ /* OSL_PRECOND(nOffset % size == 0, "Unaligned page read."); */
+ PageHolder page (reinterpret_cast< PageData* >(m_pData + nOffset));
+ swap<PageHolder>(page, rPage);
+ return store_E_None;
+}
+storeError MemoryPageAccess::writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset)
+{
+ PageData const * pagedata = rPage.get();
+ if (!(pagedata != 0))
+ return store_E_InvalidParameter;
+
+#if 0 /* NYI */
+ sal_uInt16 const bytes = pagedata->size(); // Descr.m_nSize;
+ OSL_ASSERT(bytes >= PageData::thePageSize);
+
+ offset = rPage.location(); // Descr.m_nAddr;
+ OSL_ASSERT(nOffset == offset);
+
+ OSL_PRECOND(offset % bytes == 0, "Unaligned page write.");
+#endif /* NYI */
+ return pokeAt (nOffset, pagedata, pagedata->size());
+}
+storeError MemoryPageAccess::peekAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes)
+{
+ // [SECURITY:ValInput]
+ sal_uInt8 * dst_lo = static_cast<sal_uInt8*>(pBuffer);
+ if (!(dst_lo != 0))
+ return store_E_InvalidParameter;
+
+ sal_uInt8 * dst_hi = dst_lo + nBytes;
+ if (!(dst_lo <= dst_hi))
+ return store_E_InvalidParameter;
+
+ // ...
+ sal_uInt8 const * src_lo = m_pData + nOffset;
+ if (!(src_lo <= m_pData + m_nSize))
+ return store_E_CantSeek;
+
+ sal_uInt8 const * src_hi = src_lo + nBytes;
+ if (!(src_hi <= m_pData + m_nSize))
+ return store_E_CantRead;
+
+ // copy.
+ memcpy (pBuffer, src_lo, (src_hi - src_lo));
+ return store_E_None;
+}
+storeError MemoryPageAccess::pokeAt_Impl (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes)
+{
+ // [SECURITY:ValInput]
+ sal_uInt8 const * src_lo = static_cast<sal_uInt8 const*>(pBuffer);
+ if (!(src_lo != 0))
+ return store_E_InvalidParameter;
+
+ sal_uInt8 const * src_hi = src_lo + nBytes;
+ if (!(src_lo <= src_hi))
+ return store_E_InvalidParameter;
+
+ sal_uInt64 const uSize = nOffset + nBytes;
+ if (uSize > SAL_MAX_UINT32)
+ return store_E_CantSeek;
+
+ // ...
+ if (uSize > m_nSize)
+ {
+ // increase size.
+ storeError eErrCode = setSize (sal::static_int_cast<sal_uInt32>(uSize));
+ if (eErrCode != store_E_None)
+ return eErrCode;
+ }
+
+ sal_uInt8 * dst_lo = m_pData + nOffset;
+ if (!(dst_lo <= m_pData + m_nSize))
+ return store_E_CantSeek;
+
+ sal_uInt8 * dst_hi = dst_lo + nBytes;
+ if (!(dst_hi <= m_pData + m_nSize))
+ return store_E_CantWrite;
+
+ // copy.
+ memcpy (dst_lo, src_lo, (src_hi - src_lo));
+ return store_E_None;
+}
+storeError MemoryPageAccess::getSize_Impl (sal_uInt32 & rnSize)
+{
+ rnSize = m_nSize;
+ return store_E_None;
+}
+storeError MemoryPageAccess::setSize_Impl (sal_uInt32 nSize)
+{
+ if (nSize != m_nSize)
+ {
+ sal_uInt8 * pData = static_cast<sal_uInt8*>(rtl_reallocateMemory (m_pData, nSize));
+ if (pData != 0)
+ {
+ if (nSize > m_nSize)
+ memset (pData + m_nSize, 0, sal::static_int_cast< size_t >(nSize - m_nSize));
+ }
+ else
+ {
+ if (nSize != 0)
+ return store_E_OutOfMemory;
+ }
+ m_pData = pData, m_nSize = nSize;
+ }
+ return store_E_None;
+}
+void MemoryPageAccess::freeMemory (sal_uInt8 * pData, sal_uInt32 /*nSize*/)
+{
+ rtl_freeMemory (pData);
+}
+
+/*===*/
+
+class MappedPageAccess : public MemoryPageAccess
+{
+ /** @see MemoryPageAccess::destructor_type callback function.
+ */
+ static void unmapFile (sal_uInt8 * pData, sal_uInt32 nSize);
+
+public:
+ MappedPageAccess (sal_uInt8 * pData, sal_uInt32 nSize);
+
+ virtual storeError initialize (storeAccessMode eAccessMode, sal_uInt16 nPageSize);
+
+ virtual storeError writePageAt (PageHolder const & rPage, sal_uInt32 nOffset);
+
+private:
+ virtual storeError pokeAt_Impl (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes);
+ virtual storeError setSize_Impl (sal_uInt32 nSize);
+
+protected:
+ virtual ~MappedPageAccess() {}
+};
+
+MappedPageAccess::MappedPageAccess (sal_uInt8 * pData, sal_uInt32 nSize)
+ : MemoryPageAccess (pData, nSize, MappedPageAccess::unmapFile)
+{
+}
+storeError MappedPageAccess::initialize (storeAccessMode eAccessMode, sal_uInt16 nPageSize)
+{
+ OSL_PRECOND(eAccessMode == store_AccessReadOnly, "store::MappedPageAccess: invalid AccessMode");
+ return MemoryPageAccess::initialize (eAccessMode, nPageSize);
+}
+storeError MappedPageAccess::writePageAt (PageHolder const & /*rPage*/, sal_uInt32 /*nOffset*/)
+{
+ return store_E_AccessViolation;
+}
+storeError MappedPageAccess::pokeAt_Impl (sal_uInt32 /*nOffset*/, void const * /*pBuffer*/, sal_uInt32 /*nBytes*/)
+{
+ return store_E_AccessViolation;
+}
+storeError MappedPageAccess::setSize_Impl (sal_uInt32 /*nSize*/)
+{
+ return store_E_AccessViolation;
+}
+void MappedPageAccess::unmapFile (sal_uInt8 * pData, sal_uInt32 nSize)
+{
+ (void) osl_unmapFile (pData, nSize);
+}
+
+#if 0 /* NYI */
+storeError MemoryPageAccess_createInstance (
+ rtl::Reference< IPageAccess > & rxPageAccess,
+ storeAccessMode eAccessMode,
+ sal_uInt16 nPageSize
+)
+{
+ rxPageAccess = new MemoryPageAccess();
+ if (!rxPageAccess.is())
+ return store_E_OutOfMemory;
+
+ return rxPageAccess->initialize (eAccessMode, nPageSize);
+}
+
+storeError FilePageAccess_createInstance (
+ rtl::Reference< IPageAccess > & rxPageAccess,
+ rtl_uString * pFilename,
+ storeAccessMode eAccessMode,
+ sal_uInt16 nPageSize
+)
+{
+ // Acquire file handle.
+ ResourceHolder<FileHandle> xFile;
+ result = xFile.get().initialize (pFilename, MODE_TO_NATIVE(eAccessMode));
+ if (result != osl_File_E_None)
+ return ERROR_FROM_NATIVE(result);
+
+ if (eAccessMode == store_AccessReadOnly)
+ {
+ ResourceHolder<FileMapping> xMapping;
+ result = xMapping.get().initialize (xFile.get());
+ if (result == osl_File_E_None)
+ {
+ const sal_uInt32 nSize = sal::static_int_cast<sal_uInt32>(xMapping.get().m_uSize);
+ rxPageAccess = new MappedPageAccess (xMapping.get().m_pAddr, nSize);
+ if (!rxPageAccess.is())
+ return store_E_OutOfMemory;
+ (void) xMapping.release();
+ }
+ }
+ if (!rxPageAccess.is())
+ {
+ rxPageAccess = new FilePageAccess (xFile.get());
+ if (!rxPageAccess.is())
+ return store_E_OutOfMemory;
+ (void) xFile.release();
+ }
+ return rxPageAccess->initialize (eAccessMode, nPageSize);
+}
+#endif /* NYI */
+
+/*========================================================================
+ *
+ * test...
+ *
+ *======================================================================*/
+#if 0 /* NYI */
+
+struct IDataBlock
+{
+ virtual sal_uInt16 singleCount() const = 0;
+ virtual sal_uInt32 singleLink (sal_uInt16 nIndex) const = 0;
+ virtual void singleLink (sal_uInt16 nIndex, sal_uInt32 nAddr) = 0;
+
+ virtual storeError get() = 0;
+ virtual storeError put() = 0;
+ virtual storeError truncate() = 0;
+};
+
+struct InodePageData : public PageData
+{
+ virtual INameBlock & getNameBlock() = 0;
+ virtual IDataBlock & getDataBlock() = 0;
+};
+
+template< class page_data_type >
+page_data_type * query (PageData *, page_data_type *);
+
+template<> InodePageDataV2*
+query (PageData & rData, InodePageDataV2 *)
+{
+ if (rData.isKindOf(InodePageDataV2::m_nTypeId))
+ return static_cast<InodePageDataV2*>(&rData);
+ return 0;
+}
+
+class InodePageObject : public PageObject
+{
+public:
+ static InodePageObject createInstance (PageData & rData)
+ {
+ if (query(&rData, static_cast<InodePageDataV2*>(0)))
+ return InodePageObjectV2 (static_cast<InodePageDataV2&>(rData));
+ else if (query(&rData, static_cast<InodePageDataV1*>(0)))
+ return InodePageObjectV1 (static_cast<InodePageDataV1&>(rData));
+ }
+};
+
+#endif /* NYI */
+
+/*========================================================================
+ *
+ * main.
+ *
+ *======================================================================*/
+
+#include <stdio.h>
+
+#if 0 /* EXP */
+class Interface
+{
+public:
+ virtual void deallocate(void *) /* = 0 */;
+};
+
+class Implementation : public Interface
+{
+ SharedCount m_count;
+
+public:
+ Implementation() : Interface() { printf("Ctor(%p)\n", this); }
+ ~Implementation() { printf("Dtor(%p)\n", this); }
+
+ Implementation (Implementation const & rhs) : Interface(), m_count (rhs.m_count) { printf("CopyCtor(%p)\n", this); }
+
+ virtual void deallocate(void *) {}
+};
+
+Interface Interface_createInstance()
+{
+ Implementation aInst;
+ return aInst;
+}
+#endif /* EXP */
+
+int SAL_CALL main (int argc, char ** argv)
+{
+ OSL_PRECOND(argc >= 1, "t_page: error: insufficient number of arguments.");
+ if (argc < 1)
+ return 0;
+
+ {
+ void *a = (void*)1, *b = (void*)2;
+ swap<void*>(a, b);
+ }
+ {
+ PageObject a;
+ PageObject b (a);
+ PageObject c;
+
+ c = b;
+ a = a;
+
+ }
+ {
+ TestBIOS aBIOS;
+ TestClient aClient;
+ aClient.dwim (aBIOS);
+ }
+#if 0 /* EXP */
+ {
+ Interface aIfc1 (Interface_createInstance());
+ Interface aIfc2 (aIfc1);
+ }
+#endif /* EXP */
+
+ if (argc > 1)
+ {
+ rtl_uString * pFilename = 0;
+ rtl_uString_newFromAscii (&pFilename, argv[1]);
+ storeAccessMode eAccessMode = store_AccessReadOnly;
+
+ // Acquire file handle.
+ ResourceHolder<FileHandle> h1;
+ oslFileError result = h1.get().initialize (pFilename, FilePageAccess::MODE_TO_NATIVE(eAccessMode));
+ if (result == osl_File_E_None)
+ {
+ ResourceHolder<FileHandle> h2 (h1);
+ h1 = h2;
+
+ if (eAccessMode == store_AccessReadOnly)
+ {
+ ResourceHolder<FileMapping> m1;
+ result = m1.get().initialize (h1.get());
+
+ const sal_uInt32 nSize = sal::static_int_cast<sal_uInt32>(m1.get().m_uSize);
+ (void) nSize; // UNUSED
+
+ ResourceHolder<FileMapping> m2 (m1);
+ m1 = m2;
+
+ result = osl_File_E_None;
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/store/workben/t_store.cxx b/store/workben/t_store.cxx
new file mode 100644
index 000000000000..cabd301cd5d2
--- /dev/null
+++ b/store/workben/t_store.cxx
@@ -0,0 +1,608 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: t_store.cxx,v $
+ * $Revision: 1.7 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_store.hxx"
+
+#define _T_STORE_CXX "$Revision: 1.7.8.2 $"
+#include <sal/types.h>
+#include <osl/diagnose.h>
+#include <osl/thread.h>
+#include <osl/time.h>
+#include <rtl/ustring.hxx>
+#include <store/store.hxx>
+
+#include <stdio.h>
+
+#if (defined(WNT) && defined(PROFILE))
+extern "C"
+{
+ void StartCAP (void);
+ void StopCAP (void);
+ void DumpCAP (void);
+}
+#endif /* PROFILE */
+
+using rtl::OUString;
+
+/*========================================================================
+ *
+ * Internals.
+ *
+ *======================================================================*/
+#define _DEMOSTOR_BUFSIZ 512 /* 4096, 1024, 512 */
+#define _DEMOSTOR_LOOPS 1000 /* 1000, 2000 */
+
+#define _DEMOSTOR_REMOVE 0
+#define _DEMOSTOR_REBUILD 0
+
+enum Options
+{
+ OPTION_HELP = 0x0001,
+ OPTION_FILE = 0x0002,
+ OPTION_PAUSE = 0x0004,
+ OPTION_REBUILD = 0x0008,
+
+ OPTION_DUMP = 0x0010,
+ OPTION_ITER = 0x0020,
+ OPTION_LINK = 0x0040,
+
+ OPTION_READ = 0x0100,
+ OPTION_WRITE = 0x0200,
+ OPTION_CREAT = 0x0400,
+ OPTION_TRUNC = 0x0800
+};
+
+inline sal_Char ascii_toLowerCase (sal_Char ch)
+{
+ if ((ch >= 0x41) && (ch <= 0x5A))
+ return (ch + 0x20);
+ else
+ return (ch);
+}
+
+/*========================================================================
+ *
+ * Timing.
+ *
+ *======================================================================*/
+struct OTime : public TimeValue
+{
+ OTime (void)
+ {
+ Seconds = 0;
+ Nanosec = 0;
+ }
+
+ static OTime getSystemTime (void)
+ {
+ OTime tv;
+ osl_getSystemTime (&tv);
+ return tv;
+ }
+
+ OTime& operator-= (const OTime& rPast)
+ {
+ Seconds -= rPast.Seconds;
+ if (Nanosec < rPast.Nanosec)
+ {
+ Seconds -= 1;
+ Nanosec += 1000000000;
+ }
+ Nanosec -= rPast.Nanosec;
+ return *this;
+ }
+
+ friend OTime operator- (const OTime& rTimeA, const OTime& rTimeB)
+ {
+ OTime aTimeC (rTimeA);
+ aTimeC -= rTimeB;
+ return aTimeC;
+ }
+};
+
+/*========================================================================
+ *
+ * DirectoryTraveller.
+ *
+ *======================================================================*/
+typedef store::OStoreDirectory Directory;
+
+class DirectoryTraveller : public Directory::traveller
+{
+ typedef store::OStoreFile file;
+ typedef Directory::iterator iter;
+
+ store::OStoreFile m_aFile;
+ OUString m_aPath;
+
+ sal_uInt32 m_nOptions;
+ unsigned int m_nLevel;
+ unsigned int m_nCount;
+
+public:
+ DirectoryTraveller (
+ const file& rFile,
+ const OUString &rPath,
+ const OUString &rName,
+ sal_uInt32 nOptions,
+ unsigned int nLevel = 0);
+
+ virtual ~DirectoryTraveller (void);
+
+ virtual sal_Bool visit (const iter& it);
+};
+
+/*
+ * DirectoryTraveller.
+ */
+DirectoryTraveller::DirectoryTraveller (
+ const file& rFile,
+ const OUString &rPath,
+ const OUString &rName,
+ sal_uInt32 nOptions,
+ unsigned int nLevel)
+ : m_aFile (rFile),
+ m_aPath (rPath),
+ m_nOptions (nOptions),
+ m_nLevel (nLevel),
+ m_nCount (0)
+{
+ m_aPath += rName;
+ m_aPath += OUString::createFromAscii("/");
+}
+
+/*
+ * ~DirectoryTraveller.
+ */
+DirectoryTraveller::~DirectoryTraveller (void)
+{
+}
+
+/*
+ * visit.
+ */
+sal_Bool DirectoryTraveller::visit (const iter& it)
+{
+ m_nCount++;
+ if (m_nOptions & OPTION_DUMP)
+ {
+ rtl::OString aName (it.m_pszName, it.m_nLength, RTL_TEXTENCODING_UTF8);
+ printf ("Visit(%d,%d): %s [0x%08x] %d [Bytes]\n",
+ m_nLevel, m_nCount,
+ aName.pData->buffer, (unsigned int)(it.m_nAttrib), (unsigned int)(it.m_nSize));
+ }
+ if (it.m_nAttrib & STORE_ATTRIB_ISDIR)
+ {
+ OUString aName (it.m_pszName, it.m_nLength);
+ if (aName.compareToAscii ("XTextViewCursorSupplier") == 0)
+ {
+ m_nCount += 1 - 1;
+ }
+ Directory aSubDir;
+
+ storeError eErrCode = aSubDir.create (
+ m_aFile, m_aPath, aName, store_AccessReadOnly);
+ if (eErrCode == store_E_None)
+ {
+ sal_uInt32 nRefCount = 0;
+ m_aFile.getRefererCount (nRefCount);
+
+ DirectoryTraveller aSubTraveller (
+ m_aFile, m_aPath, aName, m_nOptions, m_nLevel + 1);
+ aSubDir.travel (aSubTraveller);
+ }
+ }
+ return sal_True;
+}
+
+/*========================================================================
+ *
+ * main.
+ *
+ *======================================================================*/
+int SAL_CALL main (int argc, char **argv)
+{
+#if (defined(WNT) && defined(PROFILE))
+ StartCAP();
+#else
+ OTime aMainStartTime (OTime::getSystemTime());
+#endif /* PROFILE */
+
+ store::OStoreFile aFile;
+ storeError eErrCode = store_E_None;
+
+ sal_uInt32 nOptions = 0;
+ for (int i = 1; i < argc; i++)
+ {
+ const char *opt = argv[i];
+ if (opt[0] == '-')
+ {
+ switch (ascii_toLowerCase(sal_Char(opt[1])))
+ {
+ case 'f':
+ nOptions |= OPTION_FILE;
+ break;
+
+ case 'd':
+ nOptions |= OPTION_DUMP;
+ break;
+ case 'i':
+ nOptions |= OPTION_ITER;
+ break;
+ case 'l':
+ nOptions |= OPTION_LINK;
+ break;
+
+ case 'r':
+ nOptions |= OPTION_READ;
+ break;
+ case 'w':
+ nOptions |= OPTION_WRITE;
+ break;
+ case 'c':
+ nOptions |= OPTION_CREAT;
+ break;
+ case 't':
+ nOptions |= OPTION_TRUNC;
+ break;
+
+ case 'p':
+ nOptions |= OPTION_PAUSE;
+ break;
+
+ case 'h':
+ default:
+ nOptions |= OPTION_HELP;
+ break;
+ }
+ }
+ else
+ {
+ if (nOptions & OPTION_FILE)
+ {
+ OUString aName (
+ argv[i], rtl_str_getLength(argv[i]),
+ osl_getThreadTextEncoding());
+ if ((nOptions & OPTION_CREAT) && (nOptions & OPTION_TRUNC))
+ eErrCode = aFile.create (aName, store_AccessCreate);
+ else if (nOptions & OPTION_CREAT)
+ eErrCode = aFile.create (aName, store_AccessReadCreate);
+ else if (nOptions & OPTION_WRITE)
+ eErrCode = aFile.create (aName, store_AccessReadWrite);
+ else
+ eErrCode = aFile.create (aName, store_AccessReadOnly);
+ if (eErrCode != store_E_None)
+ {
+ printf ("Error: can't open file: %s\n", argv[i]);
+ exit (0);
+ }
+ }
+ }
+ }
+
+ if ((nOptions == 0) || (nOptions & OPTION_HELP))
+ {
+ printf ("Usage:\tt_store "
+ "[[-c] [-t] [-r] [-w]] [[-i] [-d] [-h]] "
+ "[-f filename]\n");
+
+ printf ("\nOptions:\n");
+ printf ("-c\tcreate\n");
+ printf ("-t\ttruncate\n");
+ printf ("-r\tread\n");
+ printf ("-w\twrite\n");
+ printf ("-i\titerate\n");
+ printf ("-d\tdump\n");
+ printf ("-h\thelp\n");
+ printf ("-f\tfilename\n");
+
+ printf ("\nExamples:");
+ printf ("\nt_store -c -w -f t_store.rdb\n");
+ printf ("\tCreate file 't_store.rdb',\n"
+ "\twrite fixed number (1000) of streams.\n");
+ printf ("\nt_store -c -i -d -f t_store.rdb\n");
+ printf ("\tOpen file 't_store.rdb', "
+ "create '/' directory,\n"
+ "\titerate directory tree, "
+ "dump directory info.\n");
+
+ exit (0);
+ }
+
+ if (!aFile.isValid())
+ {
+ eErrCode = aFile.createInMemory();
+ if (eErrCode != store_E_None)
+ {
+ printf ("Error: can't create memory file\n");
+ exit (0);
+ }
+ }
+
+ // Stream Read/Write.
+ OUString aPath (RTL_CONSTASCII_USTRINGPARAM("/"));
+ if ((nOptions & OPTION_READ) || (nOptions & OPTION_WRITE))
+ {
+ // Mode.
+ storeAccessMode eMode = store_AccessReadOnly;
+ if (nOptions & OPTION_WRITE)
+ eMode = store_AccessReadWrite;
+ if (nOptions & OPTION_CREAT)
+ eMode = store_AccessCreate;
+
+ // Buffer.
+ char pBuffer[_DEMOSTOR_BUFSIZ] = "Hello World";
+ pBuffer[_DEMOSTOR_BUFSIZ - 2] = 'B';
+ pBuffer[_DEMOSTOR_BUFSIZ - 1] = '\0';
+
+ // Load/Save.
+#ifndef PROFILE
+ OTime aStartTime (OTime::getSystemTime());
+#endif /* PROFILE */
+
+ for (int i = 0; i < _DEMOSTOR_LOOPS; i++)
+ {
+ OUString aName (RTL_CONSTASCII_USTRINGPARAM("demostor-"));
+ aName += OUString::valueOf ((sal_Int32)(i + 1), 10);
+ aName += OUString::createFromAscii (".dat");
+
+#if (_DEMOSTOR_REMOVE == 1)
+ eErrCode = aFile.remove (aPath, aName);
+ if ((eErrCode != store_E_None ) &&
+ (eErrCode != store_E_NotExists) )
+ break;
+#endif /* _REMOVE */
+
+ store::OStoreStream aStream;
+ eErrCode = aStream.create (aFile, aPath, aName, eMode);
+ if (eErrCode != store_E_None)
+ {
+ OSL_TRACE("OStoreStream(%d)::create(): error: %d", i, eErrCode);
+ break;
+ }
+
+ if (nOptions & OPTION_TRUNC)
+ {
+ eErrCode = aStream.setSize(0);
+ if (eErrCode != store_E_None)
+ {
+ OSL_TRACE("OStoreStream(%d)::setSize(0): error: %d", i, eErrCode);
+ break;
+ }
+ }
+
+ sal_uInt32 nDone = 0;
+ if (nOptions & OPTION_WRITE)
+ {
+ eErrCode = aStream.writeAt (
+ 0, pBuffer, sizeof(pBuffer), nDone);
+ if (eErrCode != store_E_None)
+ {
+ OSL_TRACE("OStoreStream(%d)::writeAt(): error: %d", i, eErrCode);
+ break;
+ }
+ }
+
+ if (nOptions & OPTION_READ)
+ {
+ sal_uInt32 nOffset = 0;
+ for (;;)
+ {
+ eErrCode = aStream.readAt (
+ nOffset, pBuffer, sizeof(pBuffer), nDone);
+ if (eErrCode != store_E_None)
+ {
+ OSL_TRACE("OStoreStream(%d)::readAt(): error: %d", i, eErrCode);
+ break;
+ }
+ if (nDone == 0)
+ break;
+ nOffset += nDone;
+ }
+ }
+
+ aStream.close();
+
+#ifndef PROFILE
+ if (((i + 1) % (_DEMOSTOR_LOOPS/10)) == 0)
+ {
+ OTime aDelta (OTime::getSystemTime() - aStartTime);
+
+ sal_uInt32 nDelta = aDelta.Seconds * 1000000;
+ nDelta += (aDelta.Nanosec / 1000);
+
+ printf ("%d: %12.4g[usec]\n", (i+1),
+ (double)(nDelta)/(double)(i+1));
+ }
+#endif /* PROFILE */
+ }
+
+#ifndef PROFILE
+ OTime aDelta (OTime::getSystemTime() - aStartTime);
+
+ sal_uInt32 nDelta = aDelta.Seconds * 1000000;
+ nDelta += (aDelta.Nanosec / 1000);
+
+ printf ("Total(rd,wr): %d[usec]\n", (unsigned int)(nDelta));
+#endif /* PROFILE */
+ }
+
+ // Link/Rename.
+ if (nOptions & OPTION_LINK)
+ {
+ // Create symlink to (root) directory.
+ eErrCode = aFile.symlink (
+ aPath, OUString::createFromAscii("000000/"),
+ OUString(), aPath);
+ OSL_POSTCOND(
+ ((eErrCode == store_E_None ) ||
+ (eErrCode == store_E_AlreadyExists) ),
+ "t_store::main(): store_symlink() failed");
+
+ // Create symlink to file.
+ OUString aLinkName (RTL_CONSTASCII_USTRINGPARAM("demostor-1.lnk"));
+
+ eErrCode = aFile.symlink (
+ aPath, aLinkName,
+ aPath, OUString::createFromAscii("demostor-1.dat"));
+ OSL_POSTCOND(
+ ((eErrCode == store_E_None ) ||
+ (eErrCode == store_E_AlreadyExists) ),
+ "t_store::main(): store_symlink() failed");
+ if ((eErrCode == store_E_None ) ||
+ (eErrCode == store_E_AlreadyExists) )
+ {
+ OUString aShortcut (
+ RTL_CONSTASCII_USTRINGPARAM("Shortcut to demostor-1.dat"));
+ eErrCode = aFile.rename (
+ aPath, aLinkName,
+ aPath, aShortcut);
+ OSL_POSTCOND(
+ ((eErrCode == store_E_None ) ||
+ (eErrCode == store_E_AlreadyExists) ),
+ "t_store::main(): store_rename() failed");
+ }
+
+ // Create directory.
+ OUString aDirName (RTL_CONSTASCII_USTRINGPARAM("demostor-1.dir"));
+ store::OStoreDirectory aDir;
+
+ eErrCode = aDir.create (
+ aFile, aPath, aDirName, store_AccessReadCreate);
+ OSL_POSTCOND(
+ (eErrCode == store_E_None),
+ "t_store::main(): store_createDirectory() failed");
+ if (eErrCode == store_E_None)
+ {
+#if 0 /* NYI */
+ // Rename directory.
+ eErrCode = aFile.rename (
+ aPath, "demostor-1.dir/",
+ aPath, "Renamed demostor-1.dir");
+ OSL_POSTCOND(
+ ((eErrCode == store_E_None ) ||
+ (eErrCode == store_E_AlreadyExists) ),
+ "t_store::main(): store_rename() failed");
+
+ eErrCode = aFile.rename (
+ aPath, "Renamed demostor-1.dir/",
+ aPath, "demostor-1.dir");
+ OSL_POSTCOND(
+ (eErrCode == store_E_None),
+ "t_store::main(): store_rename() failed");
+#endif /* NYI */
+ }
+ }
+
+ // Directory iteration.
+ if (nOptions & OPTION_ITER)
+ {
+#ifndef PROFILE
+ OTime aStartTime (OTime::getSystemTime());
+#endif /* PROFILE */
+ OUString aEmpty;
+
+ // Root directory.
+ store::OStoreDirectory aRootDir;
+ if (nOptions & OPTION_LINK)
+ {
+ // Open symlink entry.
+ eErrCode = aRootDir.create (
+ aFile, aPath, OUString::createFromAscii("000000"),
+ store_AccessReadOnly);
+ }
+ else
+ {
+ // Open direct entry.
+ if (nOptions & OPTION_CREAT)
+ eErrCode = aRootDir.create (
+ aFile, aEmpty, aEmpty, store_AccessReadCreate);
+ else if (nOptions & OPTION_WRITE)
+ eErrCode = aRootDir.create (
+ aFile, aEmpty, aEmpty, store_AccessReadWrite);
+ else
+ eErrCode = aRootDir.create (
+ aFile, aEmpty, aEmpty, store_AccessReadOnly);
+ }
+
+ if (eErrCode == store_E_None)
+ {
+ // Traverse directory tree.
+ DirectoryTraveller aTraveller (
+ aFile, aEmpty, aEmpty, nOptions, 0);
+ aRootDir.travel (aTraveller);
+ }
+ else
+ {
+ // Failure.
+ printf ("Error: can't open directory: \"/\"\n");
+ }
+
+#ifndef PROFILE
+ OTime aDelta (OTime::getSystemTime() - aStartTime);
+
+ sal_uInt32 nDelta = aDelta.Seconds * 1000000;
+ nDelta += (aDelta.Nanosec / 1000);
+
+ printf ("Total(iter): %d[usec]\n", (unsigned int)(nDelta));
+#endif /* PROFILE */
+ }
+
+ if (nOptions & OPTION_PAUSE)
+ {
+ TimeValue tv;
+ tv.Seconds = 300;
+ tv.Nanosec = 0;
+ osl_waitThread (&tv);
+ }
+
+ // Size.
+ sal_uInt32 nSize = 0;
+ aFile.getSize (nSize);
+
+ // Done.
+ aFile.close();
+
+#if (defined(WNT) && defined(PROFILE))
+ StopCAP();
+ DumpCAP();
+#endif /* PROFILE */
+#ifndef PROFILE
+ OTime aDelta (OTime::getSystemTime() - aMainStartTime);
+
+ sal_uInt32 nDelta = aDelta.Seconds * 1000000;
+ nDelta += (aDelta.Nanosec / 1000);
+
+ printf ("Total: %d[usec]\n", (unsigned int)(nDelta));
+#endif /* PROFILE */
+
+ return 0;
+}