diff options
Diffstat (limited to 'store/workben')
-rw-r--r-- | store/workben/makefile.mk | 108 | ||||
-rw-r--r-- | store/workben/t_base.cxx | 365 | ||||
-rw-r--r-- | store/workben/t_file.cxx | 225 | ||||
-rw-r--r-- | store/workben/t_leak.cxx | 18 | ||||
-rw-r--r-- | store/workben/t_page.cxx | 1358 | ||||
-rw-r--r-- | store/workben/t_store.cxx | 591 |
6 files changed, 2665 insertions, 0 deletions
diff --git a/store/workben/makefile.mk b/store/workben/makefile.mk new file mode 100644 index 000000000000..8893f4c7d646 --- /dev/null +++ b/store/workben/makefile.mk @@ -0,0 +1,108 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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) +APP1RPATH= UREBIN + +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) +APP3RPATH= UREBIN + +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..6a96b7c15bb1 --- /dev/null +++ b/store/workben/t_base.cxx @@ -0,0 +1,365 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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); +} + +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->write (TEST_PAGESIZE, pBuffer, sizeof (pBuffer)); + if (eErrCode != store_E_None) + return eErrCode; + + xBIOS.clear(); + return 0; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/store/workben/t_file.cxx b/store/workben/t_file.cxx new file mode 100644 index 000000000000..6357e7b8a5a6 --- /dev/null +++ b/store/workben/t_file.cxx @@ -0,0 +1,225 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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()); + + 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; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/store/workben/t_leak.cxx b/store/workben/t_leak.cxx new file mode 100644 index 000000000000..32033268d618 --- /dev/null +++ b/store/workben/t_leak.cxx @@ -0,0 +1,18 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * 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); + return 0; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/store/workben/t_page.cxx b/store/workben/t_page.cxx new file mode 100644 index 000000000000..33ca80ea81a9 --- /dev/null +++ b/store/workben/t_page.cxx @@ -0,0 +1,1358 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * 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 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; + } +}; + +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(); + } +}; + +/*======================================================================*/ + +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; + + 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); +} + +/*======================================================================== + * + * main. + * + *======================================================================*/ + +#include <stdio.h> + +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 (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; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/store/workben/t_store.cxx b/store/workben/t_store.cxx new file mode 100644 index 000000000000..19678b2ab86e --- /dev/null +++ b/store/workben/t_store.cxx @@ -0,0 +1,591 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 +#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(RTL_CONSTASCII_USTRINGPARAM("/")); +} + +/* + * ~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(RTL_CONSTASCII_USTRINGPARAM (".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(RTL_CONSTASCII_USTRINGPARAM("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(RTL_CONSTASCII_USTRINGPARAM("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) + { + } + } + + // 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(RTL_CONSTASCII_USTRINGPARAM("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; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |