From cbedb240486a21c5d5676e7a7f4e2ba17a55dbab Mon Sep 17 00:00:00 2001 From: Vladimir Glazounov Date: Fri, 13 Mar 2009 15:52:34 +0000 Subject: CWS-TOOLING: integrate CWS mhu17 2009-01-23 14:08:09 +0100 mhu r266816 : CWS-TOOLING: rebase CWS mhu17 to trunk@266428 (milestone: DEV300:m39) 2009-01-16 17:49:37 +0100 mhu r266442 : #i98151# Migration to subversion. 2009-01-16 17:48:53 +0100 mhu r266441 : #i98151# Migration to subversion. 2009-01-16 17:47:56 +0100 mhu r266440 : #i98151# Migration to subversion. --- store/workben/t_page.cxx | 1574 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1574 insertions(+) create mode 100644 store/workben/t_page.cxx (limited to 'store/workben/t_page.cxx') diff --git a/store/workben/t_page.cxx b/store/workben/t_page.cxx new file mode 100644 index 000000000000..b488e1ac997b --- /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 > inline 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(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(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(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(lhs.m_cache, rhs.m_cache); + swap(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(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(lhs.m_refcount, rhs.m_refcount); + swap(lhs.m_pagedata, rhs.m_pagedata); + swap(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(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(p) ? static_cast(p) : 0; + } + + template< class U > + static U const * dynamic_page_cast (PageData const * p) + { + return isA(p) ? static_cast(p) : 0; + } + +public: + static PageHolderObject construct (rtl::Reference< PageData::Allocator > const & rxAllocator) + { + PageHolderObject tmp; + if (rxAllocator.is()) + { + PageHolder xPage (rxAllocator->construct(), rxAllocator); + store::swap(tmp.m_xPage, xPage); + } + return tmp; + } + + explicit PageHolderObject (PageHolder const & rxPage = PageHolder()) + : m_xPage (rxPage) + {} + + void swap (PageHolderObject & rhs) + { + store::swap(m_xPage, rhs.m_xPage); + } + + PageHolderObject (PageHolderObject const & rhs) + : m_xPage (rhs.m_xPage) + { + } + + PageHolderObject & operator= (PageHolderObject const & rhs) + { + PageHolderObject tmp (rhs); + this->swap(tmp); + return *this; + } + + T * operator->() + { + T * pImpl = dynamic_page_cast(m_xPage.get()); + OSL_PRECOND(pImpl != 0, "store::PageHolder::operator->(): Null pointer"); + return pImpl; + } + T const * operator->() const + { + T const * pImpl = dynamic_page_cast(m_xPage.get()); + OSL_PRECOND(pImpl != 0, "store::PageHolder::operator->(): Null pointer"); + return pImpl; + } + + T & operator*() + { + T * pImpl = dynamic_page_cast(m_xPage.get()); + OSL_PRECOND(pImpl != 0, "store::PageHolder::operator*(): Null pointer"); + return *pImpl; + } + T const & operator*() const + { + T const * pImpl = dynamic_page_cast(m_xPage.get()); + OSL_PRECOND(pImpl != 0, "store::PageHolder::operator*(): Null pointer"); + return *pImpl; + } + + static storeError guard (PageHolder & rxPage) + { + T * pImpl = dynamic_page_cast(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(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(pagedata); + return 0; +} + +template< class T > +T * dynamic_page_cast (PageData const * pagedata) +{ + if ((pagedata != 0) && (pagedata->type() == T::theTypeId)) + return static_cast(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::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::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(); + 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 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(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(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(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(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(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(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(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(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(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 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 xMapping; + result = xMapping.get().initialize (xFile.get()); + if (result == osl_File_E_None) + { + const sal_uInt32 nSize = sal::static_int_cast(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(&rData); + return 0; +} + +class InodePageObject : public PageObject +{ +public: + static InodePageObject createInstance (PageData & rData) + { + if (query(&rData, static_cast(0))) + return InodePageObjectV2 (static_cast(rData)); + else if (query(&rData, static_cast(0))) + return InodePageObjectV1 (static_cast(rData)); + } +}; + +#endif /* NYI */ + +/*======================================================================== + * + * main. + * + *======================================================================*/ + +#include + +#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(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 h1; + oslFileError result = h1.get().initialize (pFilename, FilePageAccess::MODE_TO_NATIVE(eAccessMode)); + if (result == osl_File_E_None) + { + ResourceHolder h2 (h1); + h1 = h2; + + if (eAccessMode == store_AccessReadOnly) + { + ResourceHolder m1; + result = m1.get().initialize (h1.get()); + + const sal_uInt32 nSize = sal::static_int_cast(m1.get().m_uSize); + (void) nSize; // UNUSED + + ResourceHolder m2 (m1); + m1 = m2; + + result = osl_File_E_None; + } + } + } + + return 0; +} -- cgit