update dev300-m58
[ooovba.git] / store / workben / t_page.cxx
bloba0645f00bc58170cb4db4e1d7c2706ed31961e7e
1 /*
2 * t_page.cxx
3 */
5 #include "osl/diagnose.h"
6 #include "rtl/alloc.h"
7 #include "rtl/ref.hxx"
9 #include "storbase.hxx"
11 #include "osl/file.h"
12 #include "rtl/ustring.hxx"
14 /*========================================================================
16 * OTest...
18 *======================================================================*/
20 template< class T > void swap (T & lhs, T & rhs)
22 T tmp = rhs; rhs = lhs; lhs = tmp;
25 /*======================================================================*/
27 class SharedCount
29 long * m_pCount;
31 class Allocator
33 rtl_cache_type * m_cache;
35 public:
36 static Allocator & get();
38 long * alloc()
40 return static_cast<long*>(rtl_cache_alloc (m_cache));
42 void free (long * pCount)
44 rtl_cache_free (m_cache, pCount);
47 protected:
48 Allocator();
49 ~Allocator();
52 public:
53 SharedCount()
54 : m_pCount(Allocator::get().alloc())
56 if (m_pCount != 0) (*m_pCount) = 1;
59 ~SharedCount()
61 if (m_pCount != 0)
63 long new_count = --(*m_pCount);
64 if (new_count == 0)
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
80 template<>
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);
92 SharedCount &
93 SharedCount::operator= (SharedCount const & rhs) // nothrow
95 SharedCount tmp(rhs);
96 swap<SharedCount>(tmp, *this);
97 return *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",
111 sizeof(long),
112 0, // objalign
113 0, // constructor
114 0, // destructor
115 0, // reclaim
116 0, // userarg
117 0, // default source
118 0 // flags
122 SharedCount::Allocator::~Allocator()
124 rtl_cache_destroy (m_cache), m_cache = 0;
127 /*======================================================================*/
129 #if 0 /* OLD */
131 typedef store::OStorePageData PageData;
133 #else /* NEW */
135 #if defined(OSL_BIGENDIAN)
136 #define STORE_DWORD(dword) OSL_SWAPDWORD((dword))
137 #else
138 #define STORE_DWORD(dword) (dword)
139 #endif
141 struct PageData
143 typedef store::OStorePageGuard G;
144 typedef store::OStorePageDescriptor D;
145 typedef store::OStorePageLink L;
147 /** Representation.
149 G m_aGuard;
150 D m_aDescr;
151 L m_aMarked;
152 L m_aUnused;
154 /** theSize.
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);
160 /** type.
162 sal_uInt32 type() const { return m_aGuard.m_nMagic; /* @@@ */ }
164 /** offset.
166 sal_uInt32 offset() const { return m_aDescr.m_nAddr; /* @@@ */ }
167 void offset (sal_uInt32 nOffset) { m_aDescr.m_nAddr = nOffset; }
169 /** size.
171 sal_uInt16 size() const { return m_aDescr.m_nSize; /* @@@ */ }
173 /** Allocation.
175 class Allocator : public rtl::IReference
177 public:
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);
185 return 0;
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 *) {}
195 /** Construction.
197 explicit PageData (sal_uInt16 nPageSize = thePageSize)
198 : m_aDescr (STORE_PAGE_NULL, nPageSize, thePageSize)
201 /** ...
203 void guard()
206 storeError verify() const
208 return store_E_None;
212 #endif /* NEW */
214 class IPageAllocator
216 public:
217 virtual void deallocate (void * p) = 0;
220 class PageAllocator
222 rtl_cache_type * m_cache;
223 SharedCount m_refcount;
225 public:
226 PageAllocator()
227 : m_cache(0), m_refcount()
230 ~PageAllocator()
232 // NYI
233 if (m_refcount == 1)
238 friend void swap<>(PageAllocator & lhs, PageAllocator & rhs);
240 PageAllocator (PageAllocator const & rhs);
241 PageAllocator & operator= (PageAllocator const & rhs);
244 template<>
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)
257 PageAllocator &
258 PageAllocator::operator= (PageAllocator const & rhs)
260 PageAllocator tmp (rhs);
261 swap<PageAllocator>(tmp, *this);
262 return *this;
265 /*======================================================================*/
267 class PageHolder
269 SharedCount m_refcount;
270 PageData * m_pagedata;
272 typedef rtl::Reference< PageData::Allocator > allocator_type;
273 allocator_type m_allocator;
275 public:
276 explicit PageHolder (PageData * pagedata = 0, allocator_type const & allocator = allocator_type())
277 : m_refcount (),
278 m_pagedata (pagedata),
279 m_allocator(allocator)
282 ~PageHolder()
284 if ((m_refcount == 1) && (m_pagedata != 0) && m_allocator.is())
286 // free pagedata.
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
303 template<>
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)
317 PageHolder &
318 PageHolder::operator= (PageHolder const & rhs) // nothrow
320 PageHolder tmp (rhs);
321 swap<PageHolder>(tmp, *this);
322 return *this;
325 /*======================================================================*/
327 template< class T >
328 class PageHolderObject
330 protected:
331 /** Representation.
333 PageHolder m_xPage;
335 /** Checked cast.
337 template< class U >
338 static bool isA (PageData const * p)
340 return ((p != 0) && (p->type() == U::theTypeId));
343 template< class U >
344 static U * dynamic_page_cast (PageData * p)
346 return isA<U>(p) ? static_cast<U*>(p) : 0;
349 template< class U >
350 static U const * dynamic_page_cast (PageData const * p)
352 return isA<U>(p) ? static_cast<U const *>(p) : 0;
355 public:
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);
364 return tmp;
367 explicit PageHolderObject (PageHolder const & rxPage = PageHolder())
368 : m_xPage (rxPage)
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);
384 this->swap(tmp);
385 return *this;
388 T * operator->()
390 T * pImpl = dynamic_page_cast<T>(m_xPage.get());
391 OSL_PRECOND(pImpl != 0, "store::PageHolder<T>::operator->(): Null pointer");
392 return pImpl;
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");
398 return pImpl;
401 T & operator*()
403 T * pImpl = dynamic_page_cast<T>(m_xPage.get());
404 OSL_PRECOND(pImpl != 0, "store::PageHolder<T>::operator*(): Null pointer");
405 return *pImpl;
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");
411 return *pImpl;
414 static storeError guard (PageHolder & rxPage)
416 T * pImpl = dynamic_page_cast<T>(rxPage.get());
417 if (pImpl != 0)
418 { pImpl->guard(); return store_E_None; }
419 else if (rxPage.get() != 0)
420 return store_E_WrongVersion;
421 else
422 return store_E_InvalidAccess;
424 static storeError verify (PageHolder const & rxPage)
426 T const * pImpl = dynamic_page_cast<T>(rxPage.get());
427 if (pImpl != 0)
428 return pImpl->verify();
429 else if (rxPage.get() != 0)
430 return store_E_WrongVersion;
431 else
432 return store_E_InvalidAccess;
436 /*======================================================================*/
438 class PageObject
440 public:
441 explicit PageObject (PageHolder const & rxPage = PageHolder())
442 : m_xPage (rxPage)
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");
454 return pImpl;
456 PageData & operator*()
458 PageData * pImpl = m_xPage.get();
459 OSL_PRECOND(pImpl != 0, "store::PageObject::operator*(): Null pointer");
460 return *pImpl;
463 virtual void guard();
464 virtual storeError verify() const;
466 protected:
467 PageHolder m_xPage;
470 PageObject::~PageObject()
472 void PageObject::guard()
474 PageData * p = m_xPage.get();
475 p->guard();
477 storeError PageObject::verify() const
479 PageData const * p = m_xPage.get();
480 return p->verify();
483 /*======================================================================*/
485 template< class T >
486 T * dynamic_page_cast (PageData * pagedata)
488 if ((pagedata != 0) && (pagedata->type() == T::theTypeId))
489 return static_cast<T*>(pagedata);
490 return 0;
493 template< class T >
494 T * dynamic_page_cast (PageData const * pagedata)
496 if ((pagedata != 0) && (pagedata->type() == T::theTypeId))
497 return static_cast<T*>(pagedata);
498 return 0;
501 /*======================================================================*/
503 class TestBIOS
505 public:
506 storeError loadPageAt (PageHolder & rPage, storeError (*pfnVerify)(PageHolder const &))
508 return (pfnVerify)(rPage);
511 storeError allocate (PageHolder & rxPage, ...)
513 // NYI: PageObject.save(nAddr, *this);
514 (void)rxPage; // NYI
515 return store_E_Unknown; // NYI
518 storeError loadAt (PageHolder & rPage, sal_uInt32 nOffset)
520 (void)rPage; // NYI
521 (void)nOffset; // NYI
522 return store_E_Unknown; // NYI
524 storeError saveAt (PageHolder const & rPage, sal_uInt32 nOffset)
526 (void)rPage; // NYI
527 (void)nOffset; // NYI
528 return store_E_Unknown; // NYI
531 template< class T >
532 storeError save (PageHolder & rxPage, sal_uInt32 nOffset)
534 storeError result = PageHolderObject<T>::guard (rxPage);
535 if (result != store_E_None)
536 return result;
537 return saveAt (rxPage, nOffset);
540 storeError lookupAt (PageHolder & rPage, sal_uInt32 nOffset)
542 (void)rPage; // NYI
543 (void)nOffset; // NYI
544 return store_E_NotExists;
546 storeError replaceAt (PageHolder const & rPage, sal_uInt32 nOffset)
548 (void)rPage; // NYI
549 (void)nOffset; // NYI
550 return store_E_None;
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;
565 void guard()
567 base::guard();
568 // self::m_aGuard = ...;
570 storeError verify() const
572 storeError result = base::verify();
573 if (result != store_E_None)
574 return result;
575 if (!(base::type() == self::theTypeId))
576 return store_E_WrongVersion;
577 return store_E_None;
580 storeError dwim() const
582 return store_E_None;
585 class TestObject : public PageObject
587 typedef PageObject base;
589 public:
591 void dwim()
593 PageHolderObject< TestData > xPage (m_xPage);
594 xPage->guard();
597 virtual void guard()
599 TestData * pagedata = dynamic_page_cast< TestData >(m_xPage.get());
600 if (pagedata != 0)
603 virtual storeError verify() const
605 storeError result = base::verify();
606 if (result != store_E_None)
607 return result;
609 TestData const * pagedata = dynamic_page_cast< TestData const >(m_xPage.get());
610 if (!pagedata)
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)
628 return result;
630 result = PageHolderObject< TestData >::verify (m_xPage);
631 if (result != store_E_None)
632 return result;
634 result = rBIOS.replaceAt (m_xPage, nOffset); // cache insert
636 return result;
638 storeError saveAt (sal_uInt32 nOffset, TestBIOS & rBIOS)
640 if (!m_xPage.get())
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)
646 return result;
648 result = rBIOS.saveAt (m_xPage, nOffset);
649 if (result != store_E_None)
650 return result;
652 return rBIOS.replaceAt (m_xPage, nOffset); // cache update
656 class TestObjectV2 : public PageHolderObject< TestData >
658 typedef PageHolderObject< TestData > base;
660 public:
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)
667 return result;
669 result = rBIOS.saveAt (m_xPage, nOffset);
670 if (result != store_E_None)
671 return result;
673 return rBIOS.replaceAt (m_xPage, nOffset);
675 #if 1
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();
687 #endif
690 class TestClient
692 public:
693 void dwim(TestBIOS & rBIOS)
695 TestObject aObj;
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);
703 TestObjectV2 aObj2;
704 aObj2.dwim();
705 aObj2->dwim();
709 /*======================================================================*/
710 #if 0 /* NYI */
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);
717 if (result != None)
718 return result;
720 result = rPage.verify();
721 if (result != None)
722 return result;
724 result = m_xCache->writePageAt (rPage.get(), nOffset);
726 return result;
728 BIOS::save (PageObject & rPage, sal_uInt32 nOffset)
730 rPage.guard();
731 result = m_xLockBytes->writePageAt (rPage.get(), nOffset);
732 if (result != None)
733 return result;
735 return m_xCache->writePageAt (rPage.get(), nOffset);
737 BIOS::init (rxLockBytes, eAccessMode, nPageSize)
739 SuperPage super;
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>();
750 super->guard();
752 rxLockBytes->writeAt (0, super, super->size());
755 if (eAccessMode != store_AccessCreate)
757 rxLockBytes->readAt (0, &super, super::theSize);
759 super.verify();
761 if (eErrCode != store_E_NotExists)
765 #endif /* NYI */
766 /*======================================================================*/
768 #if 0 /* NYI */
769 class PageCache
771 std::set<const sal_uInt32, PageObject> m_pages;
772 public:
773 storeError readPageAt (PageObject & rPage, sal_uInt32 nOffset);
774 storeError writePageAt (PageObject const & rPage, sal_uInt32 nOffset);
776 #endif /* NYI */
778 /*======================================================================*/
780 class IPageAllocator;
781 class IPageAccess
783 public:
784 virtual storeError initialize (storeAccessMode eAccessMode, sal_uInt16 nPageSize) = 0;
785 virtual IPageAllocator & getAllocator () = 0;
787 public:
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");
797 if (pagedata == 0)
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);
816 if (!(dst_lo != 0))
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);
834 if (!(src_lo != 0))
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)
850 rnSize = 0;
851 return getSize_Impl (rnSize);
854 storeError setSize (sal_uInt32 nSize)
856 return setSize_Impl (nSize);
859 private:
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;
876 T m_value;
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())
887 T tmp (m_value);
888 if (tmp != value)
889 destructor_type()(tmp);
890 set (value);
892 T release()
894 T tmp (m_value);
895 set (T());
896 return tmp;
899 ResourceHolder (ResourceHolder & rhs)
901 set (rhs.release());
903 ResourceHolder & operator= (ResourceHolder & rhs)
905 reset (rhs.release());
906 return *this;
910 struct FileHandle
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)
925 // Verify arguments.
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);
937 // Acquire handle.
938 return osl_openFile (aFileUrl.pData, &m_handle, nFlags);
941 struct CloseFile
943 void operator()(FileHandle & rFile) const
945 if (rFile.m_handle != 0)
947 // Release handle.
948 (void) osl_closeFile (rFile.m_handle);
949 rFile.m_handle = 0;
953 typedef CloseFile destructor_type;
956 struct FileMapping
958 void * m_pAddr;
959 sal_uInt64 m_uSize;
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)
973 return result;
974 if (m_uSize > SAL_MAX_UINT32)
975 return osl_File_E_OVERFLOW;
977 // Acquire mapping.
978 return osl_mapFile (hFile, &m_pAddr, m_uSize, 0, 0);
981 struct UnmapFile
983 void operator ()(FileMapping & rMapping) const
985 if ((rMapping.m_pAddr != 0) && (rMapping.m_uSize != 0))
987 // Release mapping.
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;
1002 public:
1003 static storeError ERROR_FROM_NATIVE (oslFileError eErrno);
1004 static sal_uInt32 MODE_TO_NATIVE (storeAccessMode eMode);
1006 public:
1007 explicit FilePageAccess (oslFileHandle hFile = 0) : m_hFile (hFile) {}
1008 virtual storeError initialize (storeAccessMode eAccessMode, sal_uInt16 nPageSize);
1010 private:
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);
1021 protected:
1022 virtual ~FilePageAccess();
1024 private:
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()
1039 if (m_hFile != 0)
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 @@@ */
1045 if (!page.get())
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)
1096 switch (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;
1124 default:
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;
1136 // fall through
1137 case store_AccessReadWrite:
1138 nMode |= osl_File_OpenFlag_Write;
1139 // fall through
1140 case store_AccessReadOnly:
1141 nMode |= osl_File_OpenFlag_Read;
1142 break;
1143 default:
1144 OSL_PRECOND(0, "store::FilePageAccess: unknown storeAccessMode");
1146 return nMode;
1149 /*===*/
1151 class MemoryPageAccess : public IPageAccess
1153 /** Representation.
1155 sal_uInt8 * m_pData;
1156 sal_uInt32 m_nSize;
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);
1167 public:
1168 MemoryPageAccess()
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);
1177 private:
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);
1191 protected:
1192 virtual ~MemoryPageAccess();
1194 private:
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;
1228 #if 0 /* NYI */
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.");
1236 #endif /* NYI */
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);
1243 if (!(dst_lo != 0))
1244 return store_E_InvalidParameter;
1246 sal_uInt8 * dst_hi = dst_lo + nBytes;
1247 if (!(dst_lo <= dst_hi))
1248 return store_E_InvalidParameter;
1250 // ...
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;
1259 // copy.
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);
1267 if (!(src_lo != 0))
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;
1278 // ...
1279 if (uSize > m_nSize)
1281 // increase size.
1282 storeError eErrCode = setSize (sal::static_int_cast<sal_uInt32>(uSize));
1283 if (eErrCode != store_E_None)
1284 return eErrCode;
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;
1295 // copy.
1296 memcpy (dst_lo, src_lo, (src_hi - src_lo));
1297 return store_E_None;
1299 storeError MemoryPageAccess::getSize_Impl (sal_uInt32 & rnSize)
1301 rnSize = m_nSize;
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));
1309 if (pData != 0)
1311 if (nSize > m_nSize)
1312 memset (pData + m_nSize, 0, sal::static_int_cast< size_t >(nSize - m_nSize));
1314 else
1316 if (nSize != 0)
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);
1328 /*===*/
1330 class MappedPageAccess : public MemoryPageAccess
1332 /** @see MemoryPageAccess::destructor_type callback function.
1334 static void unmapFile (sal_uInt8 * pData, sal_uInt32 nSize);
1336 public:
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);
1343 private:
1344 virtual storeError pokeAt_Impl (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes);
1345 virtual storeError setSize_Impl (sal_uInt32 nSize);
1347 protected:
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);
1377 #if 0 /* NYI */
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);
1426 #endif /* NYI */
1428 /*========================================================================
1430 * test...
1432 *======================================================================*/
1433 #if 0 /* NYI */
1435 struct IDataBlock
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);
1460 return 0;
1463 class InodePageObject : public PageObject
1465 public:
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));
1475 #endif /* NYI */
1477 /*========================================================================
1479 * main.
1481 *======================================================================*/
1483 #include <stdio.h>
1485 #if 0 /* EXP */
1486 class Interface
1488 public:
1489 virtual void deallocate(void *) /* = 0 */;
1492 class Implementation : public Interface
1494 SharedCount m_count;
1496 public:
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;
1508 return aInst;
1510 #endif /* EXP */
1512 int SAL_CALL main (int argc, char ** argv)
1514 OSL_PRECOND(argc >= 1, "t_page: error: insufficient number of arguments.");
1515 if (argc < 1)
1516 return 0;
1519 void *a = (void*)1, *b = (void*)2;
1520 swap<void*>(a, b);
1523 PageObject a;
1524 PageObject b (a);
1525 PageObject c;
1527 c = b;
1528 a = a;
1532 TestBIOS aBIOS;
1533 TestClient aClient;
1534 aClient.dwim (aBIOS);
1536 #if 0 /* EXP */
1538 Interface aIfc1 (Interface_createInstance());
1539 Interface aIfc2 (aIfc1);
1541 #endif /* EXP */
1543 if (argc > 1)
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);
1555 h1 = h2;
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);
1566 m1 = m2;
1568 result = osl_File_E_None;
1573 return 0;