5 #include "osl/diagnose.h"
9 #include "storbase.hxx"
12 #include "rtl/ustring.hxx"
14 /*========================================================================
18 *======================================================================*/
20 template< class T
> void swap (T
& lhs
, T
& rhs
)
22 T tmp
= rhs
; rhs
= lhs
; lhs
= tmp
;
25 /*======================================================================*/
33 rtl_cache_type
* m_cache
;
36 static Allocator
& get();
40 return static_cast<long*>(rtl_cache_alloc (m_cache
));
42 void free (long * pCount
)
44 rtl_cache_free (m_cache
, pCount
);
54 : m_pCount(Allocator::get().alloc())
56 if (m_pCount
!= 0) (*m_pCount
) = 1;
63 long new_count
= --(*m_pCount
);
65 Allocator::get().free(m_pCount
);
69 bool operator== (long count
) const
71 return (m_pCount
!= 0) ? *m_pCount
== count
: false;
74 friend void swap
<> (SharedCount
& lhs
, SharedCount
& rhs
); // nothrow
76 SharedCount (SharedCount
const & rhs
); // nothrow
77 SharedCount
& operator= (SharedCount
const & rhs
); // nothrow
81 inline void swap (SharedCount
& lhs
, SharedCount
& rhs
) // nothrow
83 swap
<long*>(lhs
.m_pCount
, rhs
.m_pCount
);
86 SharedCount::SharedCount (SharedCount
const & rhs
) // nothrow
87 : m_pCount (rhs
.m_pCount
)
89 if (m_pCount
!= 0) ++(*m_pCount
);
93 SharedCount::operator= (SharedCount
const & rhs
) // nothrow
96 swap
<SharedCount
>(tmp
, *this);
100 SharedCount::Allocator
&
101 SharedCount::Allocator::get()
103 static Allocator g_aSharedCountAllocator
;
104 return g_aSharedCountAllocator
;
107 SharedCount::Allocator::Allocator()
109 m_cache
= rtl_cache_create (
110 "store_shared_count_cache",
122 SharedCount::Allocator::~Allocator()
124 rtl_cache_destroy (m_cache
), m_cache
= 0;
127 /*======================================================================*/
131 typedef store::OStorePageData PageData
;
135 #if defined(OSL_BIGENDIAN)
136 #define STORE_DWORD(dword) OSL_SWAPDWORD((dword))
138 #define STORE_DWORD(dword) (dword)
143 typedef store::OStorePageGuard G
;
144 typedef store::OStorePageDescriptor D
;
145 typedef store::OStorePageLink L
;
156 static const size_t theSize
= sizeof(G
) + sizeof(D
) + 2 * sizeof(L
);
157 static const sal_uInt16 thePageSize
= theSize
;
158 STORE_STATIC_ASSERT(STORE_MINIMUM_PAGESIZE
>= thePageSize
);
162 sal_uInt32
type() const { return m_aGuard
.m_nMagic
; /* @@@ */ }
166 sal_uInt32
offset() const { return m_aDescr
.m_nAddr
; /* @@@ */ }
167 void offset (sal_uInt32 nOffset
) { m_aDescr
.m_nAddr
= nOffset
; }
171 sal_uInt16
size() const { return m_aDescr
.m_nSize
; /* @@@ */ }
175 class Allocator
: public rtl::IReference
178 template< class T
> T
* construct()
180 void * page
= 0; sal_uInt16 size
= 0;
181 if (allocate (&page
, &size
))
183 return new(page
) T(size
);
188 virtual bool allocate (void ** ppPage
, sal_uInt16
* pnSize
) = 0;
189 virtual void deallocate (void * pPage
) = 0;
192 static void * operator new (size_t, void * p
) { return p
; }
193 static void operator delete (void *, void *) {}
197 explicit PageData (sal_uInt16 nPageSize
= thePageSize
)
198 : m_aDescr (STORE_PAGE_NULL
, nPageSize
, thePageSize
)
206 storeError
verify() const
217 virtual void deallocate (void * p
) = 0;
222 rtl_cache_type
* m_cache
;
223 SharedCount m_refcount
;
227 : m_cache(0), m_refcount()
238 friend void swap
<>(PageAllocator
& lhs
, PageAllocator
& rhs
);
240 PageAllocator (PageAllocator
const & rhs
);
241 PageAllocator
& operator= (PageAllocator
const & rhs
);
245 inline void swap (PageAllocator
& lhs
, PageAllocator
& rhs
)
247 swap
<rtl_cache_type
*>(lhs
.m_cache
, rhs
.m_cache
);
248 swap
<SharedCount
>(lhs
.m_refcount
, rhs
.m_refcount
);
251 PageAllocator::PageAllocator (PageAllocator
const & rhs
)
252 : m_cache (rhs
.m_cache
),
253 m_refcount (rhs
.m_refcount
)
258 PageAllocator::operator= (PageAllocator
const & rhs
)
260 PageAllocator
tmp (rhs
);
261 swap
<PageAllocator
>(tmp
, *this);
265 /*======================================================================*/
269 SharedCount m_refcount
;
270 PageData
* m_pagedata
;
272 typedef rtl::Reference
< PageData::Allocator
> allocator_type
;
273 allocator_type m_allocator
;
276 explicit PageHolder (PageData
* pagedata
= 0, allocator_type
const & allocator
= allocator_type())
278 m_pagedata (pagedata
),
279 m_allocator(allocator
)
284 if ((m_refcount
== 1) && (m_pagedata
!= 0) && m_allocator
.is())
287 m_allocator
->deallocate (m_pagedata
);
291 PageData
* get() { return m_pagedata
; }
292 PageData
const * get() const { return m_pagedata
; }
294 PageData
* operator->() { return m_pagedata
; }
295 PageData
const * operator->() const { return m_pagedata
; }
297 friend void swap
<> (PageHolder
& lhs
, PageHolder
& rhs
); // nothrow
299 PageHolder (PageHolder
const & rhs
); // nothrow
300 PageHolder
& operator= (PageHolder
const & rhs
); // nothrow
304 inline void swap (PageHolder
& lhs
, PageHolder
& rhs
) // nothrow
306 swap
<SharedCount
>(lhs
.m_refcount
, rhs
.m_refcount
);
307 swap
<PageData
*>(lhs
.m_pagedata
, rhs
.m_pagedata
);
308 swap
<PageHolder::allocator_type
>(lhs
.m_allocator
, rhs
.m_allocator
);
311 PageHolder::PageHolder (PageHolder
const & rhs
) // nothrow
312 : m_refcount (rhs
.m_refcount
),
313 m_pagedata (rhs
.m_pagedata
),
314 m_allocator(rhs
.m_allocator
)
318 PageHolder::operator= (PageHolder
const & rhs
) // nothrow
320 PageHolder
tmp (rhs
);
321 swap
<PageHolder
>(tmp
, *this);
325 /*======================================================================*/
328 class PageHolderObject
338 static bool isA (PageData
const * p
)
340 return ((p
!= 0) && (p
->type() == U::theTypeId
));
344 static U
* dynamic_page_cast (PageData
* p
)
346 return isA
<U
>(p
) ? static_cast<U
*>(p
) : 0;
350 static U
const * dynamic_page_cast (PageData
const * p
)
352 return isA
<U
>(p
) ? static_cast<U
const *>(p
) : 0;
356 static PageHolderObject
<T
> construct (rtl::Reference
< PageData::Allocator
> const & rxAllocator
)
358 PageHolderObject
<T
> tmp
;
359 if (rxAllocator
.is())
361 PageHolder
xPage (rxAllocator
->construct
<T
>(), rxAllocator
);
362 store::swap
<PageHolder
>(tmp
.m_xPage
, xPage
);
367 explicit PageHolderObject (PageHolder
const & rxPage
= PageHolder())
371 void swap (PageHolderObject
<T
> & rhs
)
373 store::swap
<PageHolder
>(m_xPage
, rhs
.m_xPage
);
376 PageHolderObject (PageHolderObject
<T
> const & rhs
)
377 : m_xPage (rhs
.m_xPage
)
381 PageHolderObject
<T
> & operator= (PageHolderObject
<T
> const & rhs
)
383 PageHolderObject
<T
> tmp (rhs
);
390 T
* pImpl
= dynamic_page_cast
<T
>(m_xPage
.get());
391 OSL_PRECOND(pImpl
!= 0, "store::PageHolder<T>::operator->(): Null pointer");
394 T
const * operator->() const
396 T
const * pImpl
= dynamic_page_cast
<T
>(m_xPage
.get());
397 OSL_PRECOND(pImpl
!= 0, "store::PageHolder<T>::operator->(): Null pointer");
403 T
* pImpl
= dynamic_page_cast
<T
>(m_xPage
.get());
404 OSL_PRECOND(pImpl
!= 0, "store::PageHolder<T>::operator*(): Null pointer");
407 T
const & operator*() const
409 T
const * pImpl
= dynamic_page_cast
<T
>(m_xPage
.get());
410 OSL_PRECOND(pImpl
!= 0, "store::PageHolder<T>::operator*(): Null pointer");
414 static storeError
guard (PageHolder
& rxPage
)
416 T
* pImpl
= dynamic_page_cast
<T
>(rxPage
.get());
418 { pImpl
->guard(); return store_E_None
; }
419 else if (rxPage
.get() != 0)
420 return store_E_WrongVersion
;
422 return store_E_InvalidAccess
;
424 static storeError
verify (PageHolder
const & rxPage
)
426 T
const * pImpl
= dynamic_page_cast
<T
>(rxPage
.get());
428 return pImpl
->verify();
429 else if (rxPage
.get() != 0)
430 return store_E_WrongVersion
;
432 return store_E_InvalidAccess
;
436 /*======================================================================*/
441 explicit PageObject (PageHolder
const & rxPage
= PageHolder())
445 virtual ~PageObject();
447 PageHolder
& get() { return m_xPage
; }
448 PageHolder
const & get() const { return m_xPage
; }
450 PageData
* operator->()
452 PageData
* pImpl
= m_xPage
.get();
453 OSL_PRECOND(pImpl
!= 0, "store::PageObject::operator->(): Null pointer");
456 PageData
& operator*()
458 PageData
* pImpl
= m_xPage
.get();
459 OSL_PRECOND(pImpl
!= 0, "store::PageObject::operator*(): Null pointer");
463 virtual void guard();
464 virtual storeError
verify() const;
470 PageObject::~PageObject()
472 void PageObject::guard()
474 PageData
* p
= m_xPage
.get();
477 storeError
PageObject::verify() const
479 PageData
const * p
= m_xPage
.get();
483 /*======================================================================*/
486 T
* dynamic_page_cast (PageData
* pagedata
)
488 if ((pagedata
!= 0) && (pagedata
->type() == T::theTypeId
))
489 return static_cast<T
*>(pagedata
);
494 T
* dynamic_page_cast (PageData
const * pagedata
)
496 if ((pagedata
!= 0) && (pagedata
->type() == T::theTypeId
))
497 return static_cast<T
*>(pagedata
);
501 /*======================================================================*/
506 storeError
loadPageAt (PageHolder
& rPage
, storeError (*pfnVerify
)(PageHolder
const &))
508 return (pfnVerify
)(rPage
);
511 storeError
allocate (PageHolder
& rxPage
, ...)
513 // NYI: PageObject.save(nAddr, *this);
515 return store_E_Unknown
; // NYI
518 storeError
loadAt (PageHolder
& rPage
, sal_uInt32 nOffset
)
521 (void)nOffset
; // NYI
522 return store_E_Unknown
; // NYI
524 storeError
saveAt (PageHolder
const & rPage
, sal_uInt32 nOffset
)
527 (void)nOffset
; // NYI
528 return store_E_Unknown
; // NYI
532 storeError
save (PageHolder
& rxPage
, sal_uInt32 nOffset
)
534 storeError result
= PageHolderObject
<T
>::guard (rxPage
);
535 if (result
!= store_E_None
)
537 return saveAt (rxPage
, nOffset
);
540 storeError
lookupAt (PageHolder
& rPage
, sal_uInt32 nOffset
)
543 (void)nOffset
; // NYI
544 return store_E_NotExists
;
546 storeError
replaceAt (PageHolder
const & rPage
, sal_uInt32 nOffset
)
549 (void)nOffset
; // NYI
554 struct TestDataV1
: public PageData
556 static const sal_uInt32 theTypeId
= 6 * 9;
558 struct TestData
: public PageData
560 typedef PageData base
;
561 typedef TestData self
;
563 static const sal_uInt32 theTypeId
= 42;
568 // self::m_aGuard = ...;
570 storeError
verify() const
572 storeError result
= base::verify();
573 if (result
!= store_E_None
)
575 if (!(base::type() == self::theTypeId
))
576 return store_E_WrongVersion
;
580 storeError
dwim() const
585 class TestObject
: public PageObject
587 typedef PageObject base
;
593 PageHolderObject
< TestData
> xPage (m_xPage
);
599 TestData
* pagedata
= dynamic_page_cast
< TestData
>(m_xPage
.get());
603 virtual storeError
verify() const
605 storeError result
= base::verify();
606 if (result
!= store_E_None
)
609 TestData
const * pagedata
= dynamic_page_cast
< TestData
const >(m_xPage
.get());
611 return store_E_WrongVersion
;
613 return pagedata
->verify();
616 static storeError
verify (PageHolder
const & rPage
)
618 return PageHolderObject
< TestData
>::verify (rPage
);
621 storeError
loadAt (sal_uInt32 nOffset
, TestBIOS
& rBIOS
)
623 storeError result
= rBIOS
.lookupAt (m_xPage
, nOffset
); // cache lookup
624 if (result
== store_E_NotExists
)
626 result
= rBIOS
.loadAt (m_xPage
, nOffset
);
627 if (result
!= store_E_None
)
630 result
= PageHolderObject
< TestData
>::verify (m_xPage
);
631 if (result
!= store_E_None
)
634 result
= rBIOS
.replaceAt (m_xPage
, nOffset
); // cache insert
638 storeError
saveAt (sal_uInt32 nOffset
, TestBIOS
& rBIOS
)
641 return store_E_InvalidAccess
;
642 m_xPage
->m_aDescr
.m_nAddr
= store::htonl(nOffset
); // m_xPage->location (nOffset);
644 storeError result
= PageHolderObject
< TestData
>::guard (m_xPage
);
645 if (result
!= store_E_None
)
648 result
= rBIOS
.saveAt (m_xPage
, nOffset
);
649 if (result
!= store_E_None
)
652 return rBIOS
.replaceAt (m_xPage
, nOffset
); // cache update
656 class TestObjectV2
: public PageHolderObject
< TestData
>
658 typedef PageHolderObject
< TestData
> base
;
661 storeError
saveAt (sal_uInt32 nOffset
, TestBIOS
& rBIOS
)
663 m_xPage
->offset(nOffset
);
665 storeError result
= PageHolderObject
< TestData
>::guard (m_xPage
);
666 if (result
!= store_E_None
)
669 result
= rBIOS
.saveAt (m_xPage
, nOffset
);
670 if (result
!= store_E_None
)
673 return rBIOS
.replaceAt (m_xPage
, nOffset
);
676 storeError
dwim() const
678 TestData
const * pImpl1
= operator->();
680 PageHolderObject
< TestData
> xImpl (m_xPage
);
682 TestData
const * pImpl2
= &*xImpl
;
683 OSL_ASSERT(pImpl1
== pImpl2
);
685 return xImpl
->dwim();
693 void dwim(TestBIOS
& rBIOS
)
697 rBIOS
.loadPageAt(aObj
.get(), aObj
.verify
);
698 rBIOS
.loadPageAt(aObj
.get(), TestObject::verify
);
699 rBIOS
.loadPageAt(aObj
.get(), PageHolderObject
<TestData
>::verify
);
701 aObj
.loadAt (1024, rBIOS
);
709 /*======================================================================*/
711 BIOS::load (PageObject
& rPage
, sal_uInt32 nOffset
)
713 result
= m_xCache
->readPageAt (rPage
.get(), nOffset
);
714 if (result
== NotExists
)
716 result
= m_xLockBytes
->readPageAt (rPage
.get(), nOffset
);
720 result
= rPage
.verify();
724 result
= m_xCache
->writePageAt (rPage
.get(), nOffset
);
728 BIOS::save (PageObject
& rPage
, sal_uInt32 nOffset
)
731 result
= m_xLockBytes
->writePageAt (rPage
.get(), nOffset
);
735 return m_xCache
->writePageAt (rPage
.get(), nOffset
);
737 BIOS::init (rxLockBytes
, eAccessMode
, nPageSize
)
740 if (eAccessMode
== store_AccessCreate
)
742 sal_uInt16 pagesize
= nPageSize
;
743 if ((STORE_MINIMUM_PAGESIZE
> pagesize
) || (pagesize
> STORE_MAXIMUM_PAGESIZE
))
744 return store_E_InvalidParameter
;
746 pagesize
= ((pagesize
+ STORE_MINIMUM_PAGESIZE
- 1) & ~(STORE_MINIMUM_PAGESIZE
- 1));
747 rxLockBytes
->init (pagesize
);
749 super
= allocator
->construct
<SuperPage
>();
752 rxLockBytes
->writeAt (0, super
, super
->size());
755 if (eAccessMode
!= store_AccessCreate
)
757 rxLockBytes
->readAt (0, &super
, super::theSize
);
761 if (eErrCode
!= store_E_NotExists
)
766 /*======================================================================*/
771 std::set
<const sal_uInt32
, PageObject
> m_pages
;
773 storeError
readPageAt (PageObject
& rPage
, sal_uInt32 nOffset
);
774 storeError
writePageAt (PageObject
const & rPage
, sal_uInt32 nOffset
);
778 /*======================================================================*/
780 class IPageAllocator
;
784 virtual storeError
initialize (storeAccessMode eAccessMode
, sal_uInt16 nPageSize
) = 0;
785 virtual IPageAllocator
& getAllocator () = 0;
788 storeError
readPageAt (PageHolder
& rPage
, sal_uInt32 nOffset
)
790 return readPageAt_Impl (rPage
, nOffset
);
792 storeError
writePageAt (PageHolder
const & rPage
, sal_uInt32 nOffset
)
794 // [SECURITY:ValInput]
795 PageData
const * pagedata
= rPage
.get();
796 OSL_PRECOND(!(pagedata
== 0), "invalid Page");
798 return store_E_InvalidParameter
;
800 sal_uInt32
const offset
= pagedata
->offset();
801 OSL_PRECOND(!(nOffset
!= offset
), "inconsistent Offset");
802 if (nOffset
!= offset
)
803 return store_E_InvalidParameter
;
805 OSL_PRECOND(!(nOffset
== STORE_PAGE_NULL
), "store::IPageAccess::writePageAt(): invalid Offset");
806 if (nOffset
== STORE_PAGE_NULL
)
807 return store_E_CantSeek
;
809 return writePageAt_Impl (rPage
, nOffset
);
812 storeError
peekAt (sal_uInt32 nOffset
, void * pBuffer
, sal_uInt32 nBytes
)
814 // [SECURITY:ValInput]
815 sal_uInt8
* dst_lo
= static_cast<sal_uInt8
*>(pBuffer
);
817 return store_E_InvalidParameter
;
819 sal_uInt8
* dst_hi
= dst_lo
+ nBytes
;
820 if (!(dst_lo
< dst_hi
))
821 return (dst_lo
> dst_hi
) ? store_E_InvalidParameter
: store_E_None
;
823 sal_uInt64
const dst_size
= nOffset
+ nBytes
;
824 if (dst_size
> SAL_MAX_UINT32
)
825 return store_E_CantSeek
;
827 return peekAt_Impl (nOffset
, dst_lo
, (dst_hi
- dst_lo
));
830 storeError
pokeAt (sal_uInt32 nOffset
, void const * pBuffer
, sal_uInt32 nBytes
)
832 // [SECURITY:ValInput]
833 sal_uInt8
const * src_lo
= static_cast<sal_uInt8
const*>(pBuffer
);
835 return store_E_InvalidParameter
;
837 sal_uInt8
const * src_hi
= src_lo
+ nBytes
;
838 if (!(src_lo
< src_hi
))
839 return (src_lo
> src_hi
) ? store_E_InvalidParameter
: store_E_None
;
841 sal_uInt64
const dst_size
= nOffset
+ nBytes
;
842 if (dst_size
> SAL_MAX_UINT32
)
843 return store_E_CantSeek
;
845 return pokeAt_Impl (nOffset
, src_lo
, (src_hi
- src_lo
));
848 storeError
getSize (sal_uInt32
& rnSize
)
851 return getSize_Impl (rnSize
);
854 storeError
setSize (sal_uInt32 nSize
)
856 return setSize_Impl (nSize
);
860 virtual storeError
readPageAt_Impl (PageHolder
& rPage
, sal_uInt32 nOffset
) = 0;
861 virtual storeError
writePageAt_Impl (PageHolder
const & rPage
, sal_uInt32 nOffset
) = 0;
863 virtual storeError
peekAt_Impl (sal_uInt32 nOffset
, void * pBuffer
, sal_uInt32 nBytes
) = 0;
864 virtual storeError
pokeAt_Impl (sal_uInt32 nOffset
, void const * pBuffer
, sal_uInt32 nBytes
) = 0;
866 virtual storeError
getSize_Impl (sal_uInt32
& rnSize
) = 0;
867 virtual storeError
setSize_Impl (sal_uInt32 nSize
) = 0;
870 /*======================================================================*/
872 template< class T
> struct ResourceHolder
874 typedef typename
T::destructor_type destructor_type
;
878 explicit ResourceHolder (T
const & value
= T()) : m_value (value
) {}
879 ~ResourceHolder() { reset(); }
881 T
& get() { return m_value
; }
882 T
const & get() const { return m_value
; }
884 void set (T
const & value
) { m_value
= value
; }
885 void reset (T
const & value
= T())
889 destructor_type()(tmp
);
899 ResourceHolder (ResourceHolder
& rhs
)
903 ResourceHolder
& operator= (ResourceHolder
& rhs
)
905 reset (rhs
.release());
912 oslFileHandle m_handle
;
914 FileHandle() : m_handle(0) {}
916 operator oslFileHandle() { return m_handle
; }
918 bool operator != (FileHandle
const & rhs
)
920 return (m_handle
!= rhs
.m_handle
);
923 oslFileError
initialize (rtl_uString
* pFilename
, sal_uInt32 nFlags
)
926 if (!pFilename
|| !nFlags
)
927 return osl_File_E_INVAL
;
929 // Convert into FileUrl.
930 rtl::OUString aFileUrl
;
931 if (osl_getFileURLFromSystemPath (pFilename
, &(aFileUrl
.pData
)) != osl_File_E_None
)
933 // Not system path. Maybe a file url, already.
934 rtl_uString_assign (&(aFileUrl
.pData
), pFilename
);
938 return osl_openFile (aFileUrl
.pData
, &m_handle
, nFlags
);
943 void operator()(FileHandle
& rFile
) const
945 if (rFile
.m_handle
!= 0)
948 (void) osl_closeFile (rFile
.m_handle
);
953 typedef CloseFile destructor_type
;
961 FileMapping() : m_pAddr(0), m_uSize(0) {}
963 bool operator != (FileMapping
const & rhs
) const
965 return ((m_pAddr
!= rhs
.m_pAddr
) || (m_uSize
!= rhs
.m_uSize
));
968 oslFileError
initialize (oslFileHandle hFile
)
970 // Determine mapping size.
971 oslFileError result
= osl_getFileSize (hFile
, &m_uSize
);
972 if (result
!= osl_File_E_None
)
974 if (m_uSize
> SAL_MAX_UINT32
)
975 return osl_File_E_OVERFLOW
;
978 return osl_mapFile (hFile
, &m_pAddr
, m_uSize
, 0, 0);
983 void operator ()(FileMapping
& rMapping
) const
985 if ((rMapping
.m_pAddr
!= 0) && (rMapping
.m_uSize
!= 0))
988 (void) osl_unmapFile (rMapping
.m_pAddr
, rMapping
.m_uSize
);
989 rMapping
.m_pAddr
= 0, rMapping
.m_uSize
= 0;
993 typedef UnmapFile destructor_type
;
996 /*======================================================================*/
998 class FilePageAccess
: public IPageAccess
1000 oslFileHandle m_hFile
;
1003 static storeError
ERROR_FROM_NATIVE (oslFileError eErrno
);
1004 static sal_uInt32
MODE_TO_NATIVE (storeAccessMode eMode
);
1007 explicit FilePageAccess (oslFileHandle hFile
= 0) : m_hFile (hFile
) {}
1008 virtual storeError
initialize (storeAccessMode eAccessMode
, sal_uInt16 nPageSize
);
1011 virtual storeError
readPageAt_Impl (PageHolder
& rPage
, sal_uInt32 nOffset
);
1012 virtual storeError
writePageAt_Impl (PageHolder
const & rPage
, sal_uInt32 nOffset
);
1014 /* see @ OFileLockBytes */
1015 virtual storeError
peekAt_Impl (sal_uInt32 nOffset
, void * pBuffer
, sal_uInt32 nBytes
);
1016 virtual storeError
pokeAt_Impl (sal_uInt32 nOffset
, void const * pBuffer
, sal_uInt32 nBytes
);
1018 virtual storeError
getSize_Impl (sal_uInt32
& rnSize
);
1019 virtual storeError
setSize_Impl (sal_uInt32 nSize
);
1022 virtual ~FilePageAccess();
1025 /** Not implemented.
1027 FilePageAccess (FilePageAccess
const &);
1028 FilePageAccess
& operator= (FilePageAccess
const &);
1031 storeError
FilePageAccess::initialize (storeAccessMode eAccessMode
, sal_uInt16 nPageSize
)
1033 (void) eAccessMode
; // UNUSED
1034 (void) nPageSize
; // UNUSED
1035 return store_E_Unknown
; // NYI
1037 FilePageAccess::~FilePageAccess()
1040 (void) osl_closeFile (m_hFile
);
1042 storeError
FilePageAccess::readPageAt_Impl (PageHolder
& rPage
, sal_uInt32 nOffset
)
1044 PageHolder
page (0/*allocate()*/); /* @@@ construct w/ deallocator argument @@@ */
1046 return store_E_OutOfMemory
;
1048 swap
<PageHolder
>(page
, rPage
);
1049 return peekAt (nOffset
, rPage
.get(), 0/*size*/);
1051 storeError
FilePageAccess::writePageAt_Impl (PageHolder
const & rPage
, sal_uInt32 nOffset
)
1053 return pokeAt (nOffset
, rPage
.get(), 0/*size*/);
1055 storeError
FilePageAccess::peekAt_Impl (sal_uInt32 nOffset
, void * pBuffer
, sal_uInt32 nBytes
)
1057 sal_uInt64 nDone
= 0;
1058 oslFileError result
= osl_readFileAt (m_hFile
, nOffset
, pBuffer
, nBytes
, &nDone
);
1059 if (result
!= osl_File_E_None
)
1060 return ERROR_FROM_NATIVE(result
);
1061 if (nDone
!= nBytes
)
1062 return (nDone
!= 0) ? store_E_CantRead
: store_E_NotExists
;
1063 return store_E_None
;
1065 storeError
FilePageAccess::pokeAt_Impl (sal_uInt32 nOffset
, void const * pBuffer
, sal_uInt32 nBytes
)
1067 sal_uInt64 nDone
= 0;
1068 oslFileError result
= osl_writeFileAt (m_hFile
, nOffset
, pBuffer
, nBytes
, &nDone
);
1069 if (result
!= osl_File_E_None
)
1070 return ERROR_FROM_NATIVE(result
);
1071 if (nDone
!= nBytes
)
1072 return store_E_CantWrite
;
1073 return store_E_None
;
1075 storeError
FilePageAccess::getSize_Impl (sal_uInt32
& rnSize
)
1077 sal_uInt64 uSize
= 0;
1078 oslFileError result
= osl_getFileSize (m_hFile
, &uSize
);
1079 if (result
!= osl_File_E_None
)
1080 return ERROR_FROM_NATIVE(result
);
1081 if (uSize
> SAL_MAX_UINT32
)
1082 return store_E_CantSeek
;
1084 rnSize
= sal::static_int_cast
<sal_uInt32
>(uSize
);
1085 return store_E_None
;
1087 storeError
FilePageAccess::setSize_Impl (sal_uInt32 nSize
)
1089 oslFileError result
= osl_setFileSize (m_hFile
, nSize
);
1090 if (result
!= osl_File_E_None
)
1091 return ERROR_FROM_NATIVE(result
);
1092 return store_E_None
;
1094 storeError
FilePageAccess::ERROR_FROM_NATIVE (oslFileError eErrno
)
1098 case osl_File_E_None
:
1099 return store_E_None
;
1101 case osl_File_E_NOENT
:
1102 return store_E_NotExists
;
1104 case osl_File_E_ACCES
:
1105 case osl_File_E_PERM
:
1106 return store_E_AccessViolation
;
1108 case osl_File_E_AGAIN
:
1109 case osl_File_E_DEADLK
:
1110 return store_E_LockingViolation
;
1112 case osl_File_E_BADF
:
1113 return store_E_InvalidHandle
;
1115 case osl_File_E_INVAL
:
1116 return store_E_InvalidParameter
;
1118 case osl_File_E_NOSPC
:
1119 return store_E_OutOfSpace
;
1121 case osl_File_E_OVERFLOW
:
1122 return store_E_CantSeek
;
1125 return store_E_Unknown
;
1128 sal_uInt32
FilePageAccess::MODE_TO_NATIVE(storeAccessMode eAccessMode
)
1130 sal_uInt32 nMode
= 0;
1131 switch (eAccessMode
)
1133 case store_AccessCreate
:
1134 case store_AccessReadCreate
:
1135 nMode
|= osl_File_OpenFlag_Create
;
1137 case store_AccessReadWrite
:
1138 nMode
|= osl_File_OpenFlag_Write
;
1140 case store_AccessReadOnly
:
1141 nMode
|= osl_File_OpenFlag_Read
;
1144 OSL_PRECOND(0, "store::FilePageAccess: unknown storeAccessMode");
1151 class MemoryPageAccess
: public IPageAccess
1155 sal_uInt8
* m_pData
;
1158 /** Callback function to release Representation.
1160 typedef void (*destructor_type
)(sal_uInt8
* pData
, sal_uInt32 nSize
);
1161 destructor_type m_destructor
;
1163 /** Default destructor callback.
1165 static void freeMemory (sal_uInt8
* pData
, sal_uInt32 nSize
);
1169 : m_pData (0), m_nSize (0), m_destructor (MemoryPageAccess::freeMemory
)
1171 MemoryPageAccess (sal_uInt8
* pData
, sal_uInt32 nSize
, destructor_type destructor
= MemoryPageAccess::freeMemory
)
1172 : m_pData (pData
), m_nSize (nSize
), m_destructor (destructor
)
1175 virtual storeError
initialize (storeAccessMode eAccessMode
, sal_uInt16 nPageSize
);
1178 /** Page (size aligned) access.
1180 virtual storeError
readPageAt_Impl (PageHolder
& rPage
, sal_uInt32 nOffset
);
1181 virtual storeError
writePageAt_Impl (PageHolder
const & rPage
, sal_uInt32 nOffset
);
1183 /** Low level access.
1185 virtual storeError
peekAt_Impl (sal_uInt32 nOffset
, void * pBuffer
, sal_uInt32 nBytes
);
1186 virtual storeError
pokeAt_Impl (sal_uInt32 nOffset
, void const * pBuffer
, sal_uInt32 nBytes
);
1188 virtual storeError
getSize_Impl (sal_uInt32
& rnSize
);
1189 virtual storeError
setSize_Impl (sal_uInt32 nSize
);
1192 virtual ~MemoryPageAccess();
1195 /** Not implemented.
1197 MemoryPageAccess (MemoryPageAccess
const &);
1198 MemoryPageAccess
& operator= (MemoryPageAccess
const &);
1201 storeError
MemoryPageAccess::initialize (storeAccessMode eAccessMode
, sal_uInt16 nPageSize
)
1203 (void) eAccessMode
; // UNUSED
1204 (void) nPageSize
; // UNUSED
1205 return store_E_Unknown
; // NYI
1207 MemoryPageAccess::~MemoryPageAccess()
1209 if (m_destructor
!= 0)
1211 // release resource.
1212 (*m_destructor
)(m_pData
, m_nSize
);
1215 storeError
MemoryPageAccess::readPageAt_Impl (PageHolder
& rPage
, sal_uInt32 nOffset
)
1217 /* OSL_PRECOND(nOffset % size == 0, "Unaligned page read."); */
1218 PageHolder
page (reinterpret_cast< PageData
* >(m_pData
+ nOffset
));
1219 swap
<PageHolder
>(page
, rPage
);
1220 return store_E_None
;
1222 storeError
MemoryPageAccess::writePageAt_Impl (PageHolder
const & rPage
, sal_uInt32 nOffset
)
1224 PageData
const * pagedata
= rPage
.get();
1225 if (!(pagedata
!= 0))
1226 return store_E_InvalidParameter
;
1229 sal_uInt16
const bytes
= pagedata
->size(); // Descr.m_nSize;
1230 OSL_ASSERT(bytes
>= PageData::thePageSize
);
1232 offset
= rPage
.location(); // Descr.m_nAddr;
1233 OSL_ASSERT(nOffset
== offset
);
1235 OSL_PRECOND(offset
% bytes
== 0, "Unaligned page write.");
1237 return pokeAt (nOffset
, pagedata
, pagedata
->size());
1239 storeError
MemoryPageAccess::peekAt_Impl (sal_uInt32 nOffset
, void * pBuffer
, sal_uInt32 nBytes
)
1241 // [SECURITY:ValInput]
1242 sal_uInt8
* dst_lo
= static_cast<sal_uInt8
*>(pBuffer
);
1244 return store_E_InvalidParameter
;
1246 sal_uInt8
* dst_hi
= dst_lo
+ nBytes
;
1247 if (!(dst_lo
<= dst_hi
))
1248 return store_E_InvalidParameter
;
1251 sal_uInt8
const * src_lo
= m_pData
+ nOffset
;
1252 if (!(src_lo
<= m_pData
+ m_nSize
))
1253 return store_E_CantSeek
;
1255 sal_uInt8
const * src_hi
= src_lo
+ nBytes
;
1256 if (!(src_hi
<= m_pData
+ m_nSize
))
1257 return store_E_CantRead
;
1260 memcpy (pBuffer
, src_lo
, (src_hi
- src_lo
));
1261 return store_E_None
;
1263 storeError
MemoryPageAccess::pokeAt_Impl (sal_uInt32 nOffset
, void const * pBuffer
, sal_uInt32 nBytes
)
1265 // [SECURITY:ValInput]
1266 sal_uInt8
const * src_lo
= static_cast<sal_uInt8
const*>(pBuffer
);
1268 return store_E_InvalidParameter
;
1270 sal_uInt8
const * src_hi
= src_lo
+ nBytes
;
1271 if (!(src_lo
<= src_hi
))
1272 return store_E_InvalidParameter
;
1274 sal_uInt64
const uSize
= nOffset
+ nBytes
;
1275 if (uSize
> SAL_MAX_UINT32
)
1276 return store_E_CantSeek
;
1279 if (uSize
> m_nSize
)
1282 storeError eErrCode
= setSize (sal::static_int_cast
<sal_uInt32
>(uSize
));
1283 if (eErrCode
!= store_E_None
)
1287 sal_uInt8
* dst_lo
= m_pData
+ nOffset
;
1288 if (!(dst_lo
<= m_pData
+ m_nSize
))
1289 return store_E_CantSeek
;
1291 sal_uInt8
* dst_hi
= dst_lo
+ nBytes
;
1292 if (!(dst_hi
<= m_pData
+ m_nSize
))
1293 return store_E_CantWrite
;
1296 memcpy (dst_lo
, src_lo
, (src_hi
- src_lo
));
1297 return store_E_None
;
1299 storeError
MemoryPageAccess::getSize_Impl (sal_uInt32
& rnSize
)
1302 return store_E_None
;
1304 storeError
MemoryPageAccess::setSize_Impl (sal_uInt32 nSize
)
1306 if (nSize
!= m_nSize
)
1308 sal_uInt8
* pData
= static_cast<sal_uInt8
*>(rtl_reallocateMemory (m_pData
, nSize
));
1311 if (nSize
> m_nSize
)
1312 memset (pData
+ m_nSize
, 0, sal::static_int_cast
< size_t >(nSize
- m_nSize
));
1317 return store_E_OutOfMemory
;
1319 m_pData
= pData
, m_nSize
= nSize
;
1321 return store_E_None
;
1323 void MemoryPageAccess::freeMemory (sal_uInt8
* pData
, sal_uInt32
/*nSize*/)
1325 rtl_freeMemory (pData
);
1330 class MappedPageAccess
: public MemoryPageAccess
1332 /** @see MemoryPageAccess::destructor_type callback function.
1334 static void unmapFile (sal_uInt8
* pData
, sal_uInt32 nSize
);
1337 MappedPageAccess (sal_uInt8
* pData
, sal_uInt32 nSize
);
1339 virtual storeError
initialize (storeAccessMode eAccessMode
, sal_uInt16 nPageSize
);
1341 virtual storeError
writePageAt (PageHolder
const & rPage
, sal_uInt32 nOffset
);
1344 virtual storeError
pokeAt_Impl (sal_uInt32 nOffset
, void const * pBuffer
, sal_uInt32 nBytes
);
1345 virtual storeError
setSize_Impl (sal_uInt32 nSize
);
1348 virtual ~MappedPageAccess() {}
1351 MappedPageAccess::MappedPageAccess (sal_uInt8
* pData
, sal_uInt32 nSize
)
1352 : MemoryPageAccess (pData
, nSize
, MappedPageAccess::unmapFile
)
1355 storeError
MappedPageAccess::initialize (storeAccessMode eAccessMode
, sal_uInt16 nPageSize
)
1357 OSL_PRECOND(eAccessMode
== store_AccessReadOnly
, "store::MappedPageAccess: invalid AccessMode");
1358 return MemoryPageAccess::initialize (eAccessMode
, nPageSize
);
1360 storeError
MappedPageAccess::writePageAt (PageHolder
const & /*rPage*/, sal_uInt32
/*nOffset*/)
1362 return store_E_AccessViolation
;
1364 storeError
MappedPageAccess::pokeAt_Impl (sal_uInt32
/*nOffset*/, void const * /*pBuffer*/, sal_uInt32
/*nBytes*/)
1366 return store_E_AccessViolation
;
1368 storeError
MappedPageAccess::setSize_Impl (sal_uInt32
/*nSize*/)
1370 return store_E_AccessViolation
;
1372 void MappedPageAccess::unmapFile (sal_uInt8
* pData
, sal_uInt32 nSize
)
1374 (void) osl_unmapFile (pData
, nSize
);
1378 storeError
MemoryPageAccess_createInstance (
1379 rtl::Reference
< IPageAccess
> & rxPageAccess
,
1380 storeAccessMode eAccessMode
,
1381 sal_uInt16 nPageSize
1384 rxPageAccess
= new MemoryPageAccess();
1385 if (!rxPageAccess
.is())
1386 return store_E_OutOfMemory
;
1388 return rxPageAccess
->initialize (eAccessMode
, nPageSize
);
1391 storeError
FilePageAccess_createInstance (
1392 rtl::Reference
< IPageAccess
> & rxPageAccess
,
1393 rtl_uString
* pFilename
,
1394 storeAccessMode eAccessMode
,
1395 sal_uInt16 nPageSize
1398 // Acquire file handle.
1399 ResourceHolder
<FileHandle
> xFile
;
1400 result
= xFile
.get().initialize (pFilename
, MODE_TO_NATIVE(eAccessMode
));
1401 if (result
!= osl_File_E_None
)
1402 return ERROR_FROM_NATIVE(result
);
1404 if (eAccessMode
== store_AccessReadOnly
)
1406 ResourceHolder
<FileMapping
> xMapping
;
1407 result
= xMapping
.get().initialize (xFile
.get());
1408 if (result
== osl_File_E_None
)
1410 const sal_uInt32 nSize
= sal::static_int_cast
<sal_uInt32
>(xMapping
.get().m_uSize
);
1411 rxPageAccess
= new MappedPageAccess (xMapping
.get().m_pAddr
, nSize
);
1412 if (!rxPageAccess
.is())
1413 return store_E_OutOfMemory
;
1414 (void) xMapping
.release();
1417 if (!rxPageAccess
.is())
1419 rxPageAccess
= new FilePageAccess (xFile
.get());
1420 if (!rxPageAccess
.is())
1421 return store_E_OutOfMemory
;
1422 (void) xFile
.release();
1424 return rxPageAccess
->initialize (eAccessMode
, nPageSize
);
1428 /*========================================================================
1432 *======================================================================*/
1437 virtual sal_uInt16
singleCount() const = 0;
1438 virtual sal_uInt32
singleLink (sal_uInt16 nIndex
) const = 0;
1439 virtual void singleLink (sal_uInt16 nIndex
, sal_uInt32 nAddr
) = 0;
1441 virtual storeError
get() = 0;
1442 virtual storeError
put() = 0;
1443 virtual storeError
truncate() = 0;
1446 struct InodePageData
: public PageData
1448 virtual INameBlock
& getNameBlock() = 0;
1449 virtual IDataBlock
& getDataBlock() = 0;
1452 template< class page_data_type
>
1453 page_data_type
* query (PageData
*, page_data_type
*);
1455 template<> InodePageDataV2
*
1456 query (PageData
& rData
, InodePageDataV2
*)
1458 if (rData
.isKindOf(InodePageDataV2::m_nTypeId
))
1459 return static_cast<InodePageDataV2
*>(&rData
);
1463 class InodePageObject
: public PageObject
1466 static InodePageObject
createInstance (PageData
& rData
)
1468 if (query(&rData
, static_cast<InodePageDataV2
*>(0)))
1469 return InodePageObjectV2 (static_cast<InodePageDataV2
&>(rData
));
1470 else if (query(&rData
, static_cast<InodePageDataV1
*>(0)))
1471 return InodePageObjectV1 (static_cast<InodePageDataV1
&>(rData
));
1477 /*========================================================================
1481 *======================================================================*/
1489 virtual void deallocate(void *) /* = 0 */;
1492 class Implementation
: public Interface
1494 SharedCount m_count
;
1497 Implementation() : Interface() { printf("Ctor(%p)\n", this); }
1498 ~Implementation() { printf("Dtor(%p)\n", this); }
1500 Implementation (Implementation
const & rhs
) : Interface(), m_count (rhs
.m_count
) { printf("CopyCtor(%p)\n", this); }
1502 virtual void deallocate(void *) {}
1505 Interface
Interface_createInstance()
1507 Implementation aInst
;
1512 int SAL_CALL
main (int argc
, char ** argv
)
1514 OSL_PRECOND(argc
>= 1, "t_page: error: insufficient number of arguments.");
1519 void *a
= (void*)1, *b
= (void*)2;
1534 aClient
.dwim (aBIOS
);
1538 Interface
aIfc1 (Interface_createInstance());
1539 Interface
aIfc2 (aIfc1
);
1545 rtl_uString
* pFilename
= 0;
1546 rtl_uString_newFromAscii (&pFilename
, argv
[1]);
1547 storeAccessMode eAccessMode
= store_AccessReadOnly
;
1549 // Acquire file handle.
1550 ResourceHolder
<FileHandle
> h1
;
1551 oslFileError result
= h1
.get().initialize (pFilename
, FilePageAccess::MODE_TO_NATIVE(eAccessMode
));
1552 if (result
== osl_File_E_None
)
1554 ResourceHolder
<FileHandle
> h2 (h1
);
1557 if (eAccessMode
== store_AccessReadOnly
)
1559 ResourceHolder
<FileMapping
> m1
;
1560 result
= m1
.get().initialize (h1
.get());
1562 const sal_uInt32 nSize
= sal::static_int_cast
<sal_uInt32
>(m1
.get().m_uSize
);
1563 (void) nSize
; // UNUSED
1565 ResourceHolder
<FileMapping
> m2 (m1
);
1568 result
= osl_File_E_None
;