1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: storbase.hxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 #ifndef _STORE_STORBASE_HXX_
32 #define _STORE_STORBASE_HXX_ "$Revision: 1.10.8.4 $"
34 #include "sal/types.h"
36 #include "rtl/alloc.h"
38 #include "rtl/ref.hxx"
40 #include "osl/diagnose.h"
41 #include "osl/endian.h"
43 #include "store/types.h"
45 #ifndef INCLUDED_STDDEF_H
47 #define INCLUDED_STDDEF_H
50 #ifndef INCLUDED_STRING_H
52 #define INCLUDED_STRING_H
55 /*========================================================================
57 * store common internals.
59 *======================================================================*/
61 #ifndef STORE_IMPL_ISP2
62 #define STORE_IMPL_ISP2(value) (((value) & ((value) - 1)) == 0)
65 #ifndef STORE_IMPL_CONCAT
66 #define STORE_IMPL_CONCAT(x, y) STORE_IMPL_CONCAT2(x,y)
67 #define STORE_IMPL_CONCAT2(x, y) x##y
70 #ifndef STORE_STATIC_ASSERT /* Compile time assertion */
73 template< bool x
> struct STATIC_ASSERTION_FAILURE
;
74 template<> struct STATIC_ASSERTION_FAILURE
< true > { enum { value
= 1 }; };
76 template< int x
> struct static_assert_test
{};
79 #define STORE_STATIC_ASSERT(pred) \
81 store::static_assert_test< sizeof( store::STATIC_ASSERTION_FAILURE< (bool)(pred) > ) > \
82 STORE_IMPL_CONCAT(static_assert_typedef_, __LINE__)
84 #endif /* !STORE_STATIC_ASSERT */
104 inline sal_uInt16
htons (sal_uInt16 h
) { return OSL_SWAPWORD(h
); }
105 inline sal_uInt16
ntohs (sal_uInt16 n
) { return OSL_SWAPWORD(n
); }
107 inline sal_uInt32
htonl (sal_uInt32 h
) { return OSL_SWAPDWORD(h
); }
108 inline sal_uInt32
ntohl (sal_uInt32 n
) { return OSL_SWAPDWORD(n
); }
110 inline sal_uInt16
htons (sal_uInt16 h
) { return (h
); }
111 inline sal_uInt16
ntohs (sal_uInt16 n
) { return (n
); }
113 inline sal_uInt32
htonl (sal_uInt32 h
) { return (h
); }
114 inline sal_uInt32
ntohl (sal_uInt32 n
) { return (n
); }
115 #endif /* OSL_BIGENDIAN */
119 template< typename T
> void swap (T
& lhs
, T
& rhs
)
121 T tmp
= lhs
; lhs
= rhs
; rhs
= tmp
;
124 /*========================================================================
128 *======================================================================*/
135 rtl_cache_type
* m_cache
;
138 static Allocator
& get();
142 return static_cast<long*>(rtl_cache_alloc (m_cache
));
144 void free (long * pCount
)
146 rtl_cache_free (m_cache
, pCount
);
156 : m_pCount(Allocator::get().alloc())
158 if (m_pCount
!= 0) (*m_pCount
) = 1;
165 long new_count
= --(*m_pCount
);
167 Allocator::get().free(m_pCount
);
171 void swap (SharedCount
& rhs
) // nothrow
173 store::swap(m_pCount
, rhs
.m_pCount
);
176 SharedCount (SharedCount
const & rhs
) // nothrow
177 : m_pCount (rhs
.m_pCount
)
179 if (m_pCount
!= 0) ++(*m_pCount
);
181 SharedCount
& operator= (SharedCount
const & rhs
) // nothrow
183 SharedCount
tmp(rhs
);
188 bool operator== (long count
) const
190 return (m_pCount
!= 0) ? *m_pCount
== count
: false;
194 /*========================================================================
198 *======================================================================*/
199 struct OStorePageGuard
208 explicit OStorePageGuard (sal_uInt32 nMagic
= 0, sal_uInt32 nCRC32
= 0)
209 : m_nMagic (store::htonl(nMagic
)),
210 m_nCRC32 (store::htonl(nCRC32
))
213 void swap (OStorePageGuard
& rhs
)
215 store::swap(m_nMagic
, rhs
.m_nMagic
);
216 store::swap(m_nCRC32
, rhs
.m_nCRC32
);
219 OStorePageGuard (OStorePageGuard
const & rhs
)
220 : m_nMagic (rhs
.m_nMagic
),
221 m_nCRC32 (rhs
.m_nCRC32
)
224 OStorePageGuard
& operator= (const OStorePageGuard
& rhs
)
226 m_nMagic
= rhs
.m_nMagic
;
227 m_nCRC32
= rhs
.m_nCRC32
;
233 bool operator== (const OStorePageGuard
& rhs
) const
235 return ((m_nMagic
== rhs
.m_nMagic
) &&
236 (m_nCRC32
== rhs
.m_nCRC32
) );
240 /*========================================================================
242 * OStorePageDescriptor.
244 *======================================================================*/
245 #define STORE_PAGE_NULL ((sal_uInt32)(~0))
247 struct OStorePageDescriptor
257 explicit OStorePageDescriptor (
258 sal_uInt32 nAddr
= STORE_PAGE_NULL
,
259 sal_uInt16 nSize
= 0,
260 sal_uInt16 nUsed
= 0)
261 : m_nAddr (store::htonl(nAddr
)),
262 m_nSize (store::htons(nSize
)),
263 m_nUsed (store::htons(nUsed
))
266 void swap (OStorePageDescriptor
& rhs
)
268 store::swap(m_nAddr
, rhs
.m_nAddr
);
269 store::swap(m_nSize
, rhs
.m_nSize
);
270 store::swap(m_nUsed
, rhs
.m_nUsed
);
273 OStorePageDescriptor (const OStorePageDescriptor
& rhs
)
274 : m_nAddr (rhs
.m_nAddr
),
275 m_nSize (rhs
.m_nSize
),
276 m_nUsed (rhs
.m_nUsed
)
279 OStorePageDescriptor
& operator= (const OStorePageDescriptor
& rhs
)
281 m_nAddr
= rhs
.m_nAddr
;
282 m_nSize
= rhs
.m_nSize
;
283 m_nUsed
= rhs
.m_nUsed
;
289 bool operator== (const OStorePageDescriptor
& rhs
) const
291 return ((m_nAddr
== rhs
.m_nAddr
) &&
292 (m_nSize
== rhs
.m_nSize
) );
295 bool operator<= (const OStorePageDescriptor
& rhs
) const
297 return ((m_nAddr
== rhs
.m_nAddr
) &&
298 (store::ntohs(m_nSize
) <= store::ntohs(rhs
.m_nSize
)) );
301 bool operator< (const OStorePageDescriptor
& rhs
) const
303 if (m_nAddr
== rhs
.m_nAddr
)
304 return (store::ntohs(m_nSize
) < store::ntohs(rhs
.m_nSize
));
306 return (store::ntohl(m_nAddr
) < store::ntohl(rhs
.m_nAddr
));
310 /*========================================================================
314 *======================================================================*/
324 explicit OStorePageKey (sal_uInt32 nLow
= 0, sal_uInt32 nHigh
= 0)
325 : m_nLow (store::htonl(nLow
)),
326 m_nHigh (store::htonl(nHigh
))
329 void swap (OStorePageKey
& rhs
)
331 store::swap(m_nLow
, rhs
.m_nLow
);
332 store::swap(m_nHigh
, rhs
.m_nHigh
);
335 OStorePageKey (const OStorePageKey
& rhs
)
336 : m_nLow (rhs
.m_nLow
), m_nHigh (rhs
.m_nHigh
)
339 OStorePageKey
& operator= (const OStorePageKey
& rhs
)
342 m_nHigh
= rhs
.m_nHigh
;
348 bool operator== (const OStorePageKey
& rhs
) const
350 return ((m_nLow
== rhs
.m_nLow
) &&
351 (m_nHigh
== rhs
.m_nHigh
) );
354 bool operator< (const OStorePageKey
& rhs
) const
356 if (m_nHigh
== rhs
.m_nHigh
)
357 return (store::ntohl(m_nLow
) < store::ntohl(rhs
.m_nLow
));
359 return (store::ntohl(m_nHigh
) < store::ntohl(rhs
.m_nHigh
));
363 /*========================================================================
367 *======================================================================*/
368 struct OStorePageLink
376 explicit OStorePageLink (sal_uInt32 nAddr
= STORE_PAGE_NULL
)
377 : m_nAddr (store::htonl(nAddr
))
380 void swap (OStorePageLink
& rhs
)
382 store::swap(m_nAddr
, rhs
.m_nAddr
);
385 OStorePageLink (const OStorePageLink
& rhs
)
386 : m_nAddr (rhs
.m_nAddr
)
389 OStorePageLink
& operator= (const OStorePageLink
& rhs
)
391 m_nAddr
= rhs
.m_nAddr
;
395 OStorePageLink
& operator= (sal_uInt32 nAddr
)
397 m_nAddr
= store::htonl(nAddr
);
403 bool operator== (const OStorePageLink
& rhs
) const
405 return (m_nAddr
== rhs
.m_nAddr
);
408 bool operator< (const OStorePageLink
& rhs
) const
410 return (store::ntohl(m_nAddr
) < store::ntohl(rhs
.m_nAddr
));
415 sal_uInt32
location() const
417 return store::ntohl(m_nAddr
);
420 void link (OStorePageLink
& rPred
)
422 // @@@ swap (rPred); @@@
423 OStorePageLink
tmp (rPred
);
428 void unlink (OStorePageLink
& rPred
)
431 *this = OStorePageLink();
435 /*========================================================================
439 *======================================================================*/
440 typedef struct PageData OStorePageData
; // backward compat.
443 typedef OStorePageGuard G
;
444 typedef OStorePageDescriptor D
;
445 typedef OStorePageLink L
;
456 static const size_t theSize
= sizeof(G
) + sizeof(D
) + 2 * sizeof(L
);
457 static const sal_uInt16 thePageSize
= theSize
;
458 STORE_STATIC_ASSERT(STORE_MINIMUM_PAGESIZE
>= thePageSize
);
462 sal_uInt32
location() const
464 return store::ntohl(m_aDescr
.m_nAddr
);
466 void location (sal_uInt32 nAddr
)
468 m_aDescr
.m_nAddr
= store::htonl(nAddr
);
473 sal_uInt16
size() const
475 return store::ntohs(m_aDescr
.m_nSize
);
480 sal_uInt32
type() const
482 return store::ntohl(m_aGuard
.m_nMagic
);
487 class Allocator_Impl
;
488 class Allocator
: public rtl::IReference
491 template< class T
> T
* construct()
493 void * page
= 0; sal_uInt16 size
= 0;
494 if (allocate (&page
, &size
))
496 return new(page
) T(size
);
501 bool allocate (void ** ppPage
, sal_uInt16
* pnSize
)
503 allocate_Impl (ppPage
, pnSize
);
504 return ((*ppPage
!= 0) && (*pnSize
!= 0));
507 void deallocate (void * pPage
)
510 deallocate_Impl (pPage
);
513 static storeError
createInstance (
514 rtl::Reference
< PageData::Allocator
> & rxAllocator
, sal_uInt16 nPageSize
);
517 /** Implementation (abstract).
519 virtual void allocate_Impl (void ** ppPage
, sal_uInt16
* pnSize
) = 0;
520 virtual void deallocate_Impl (void * pPage
) = 0;
523 static void* operator new (size_t, void * p
) { return p
; }
524 static void operator delete (void * , void *) {}
528 explicit PageData (sal_uInt16 nPageSize
= thePageSize
)
530 m_aDescr(STORE_PAGE_NULL
, nPageSize
, thePageSize
),
535 void swap (PageData
& rhs
) // nothrow
537 m_aGuard
.swap(rhs
.m_aGuard
);
538 m_aDescr
.swap(rhs
.m_aDescr
);
539 m_aMarked
.swap(rhs
.m_aMarked
);
540 m_aUnused
.swap(rhs
.m_aUnused
);
543 PageData (PageData
const & rhs
) // nothrow
544 : m_aGuard (rhs
.m_aGuard
),
545 m_aDescr (rhs
.m_aDescr
),
546 m_aMarked(rhs
.m_aMarked
),
547 m_aUnused(rhs
.m_aUnused
)
550 PageData
& operator= (PageData
const & rhs
) // nothrow
557 /** guard (external representation).
561 sal_uInt32 nCRC32
= 0;
562 nCRC32
= rtl_crc32 (nCRC32
, &m_aGuard
.m_nMagic
, sizeof(sal_uInt32
));
563 nCRC32
= rtl_crc32 (nCRC32
, &m_aDescr
, theSize
- sizeof(G
));
564 m_aGuard
.m_nCRC32
= store::htonl(nCRC32
);
566 void guard (sal_uInt32 nAddr
)
568 sal_uInt32 nCRC32
= 0;
569 nCRC32
= rtl_crc32 (nCRC32
, &m_aGuard
.m_nMagic
, sizeof(sal_uInt32
));
570 m_aDescr
.m_nAddr
= store::htonl(nAddr
);
571 nCRC32
= rtl_crc32 (nCRC32
, &m_aDescr
, theSize
- sizeof(G
));
572 m_aGuard
.m_nCRC32
= store::htonl(nCRC32
);
575 /** verify (external representation).
577 storeError
verify() const
579 sal_uInt32 nCRC32
= 0;
580 nCRC32
= rtl_crc32 (nCRC32
, &m_aGuard
.m_nMagic
, sizeof(sal_uInt32
));
581 nCRC32
= rtl_crc32 (nCRC32
, &m_aDescr
, theSize
- sizeof(G
));
582 if (m_aGuard
.m_nCRC32
!= store::htonl(nCRC32
))
583 return store_E_InvalidChecksum
;
587 storeError
verify (sal_uInt32 nAddr
) const
590 sal_uInt32 nCRC32
= 0;
591 nCRC32
= rtl_crc32 (nCRC32
, &m_aGuard
.m_nMagic
, sizeof(sal_uInt32
));
592 nCRC32
= rtl_crc32 (nCRC32
, &m_aDescr
, theSize
- sizeof(G
));
593 if (m_aGuard
.m_nCRC32
!= store::htonl(nCRC32
))
594 return store_E_InvalidChecksum
;
595 if (m_aDescr
.m_nAddr
!= store::htonl(nAddr
))
596 return store_E_InvalidAccess
;
600 storeError
verifyVersion (sal_uInt32 nMagic
) const
602 if (m_aGuard
.m_nMagic
!= store::htonl(nMagic
))
603 return store_E_WrongVersion
;
609 /*========================================================================
613 *======================================================================*/
616 SharedCount m_refcount
;
617 PageData
* m_pagedata
;
619 typedef rtl::Reference
< PageData::Allocator
> allocator_type
;
620 allocator_type m_allocator
;
623 explicit PageHolder (PageData
* pagedata
= 0, allocator_type
const & allocator
= allocator_type())
625 m_pagedata (pagedata
),
626 m_allocator(allocator
)
628 OSL_ENSURE((m_pagedata
== 0) || m_allocator
.is(), "store::PageHolder::ctor(): pagedata w/o allocator.");
633 if ((m_refcount
== 1) && (m_pagedata
!= 0))
636 OSL_ENSURE(m_allocator
.is(), "store::PageHolder::dtor(): pagedata w/o allocator.");
637 m_allocator
->deallocate (m_pagedata
);
641 void swap (PageHolder
& rhs
) // nothrow
643 m_refcount
.swap(rhs
.m_refcount
);
644 store::swap(m_pagedata
, rhs
.m_pagedata
);
645 store::swap(m_allocator
, rhs
.m_allocator
);
648 PageHolder (PageHolder
const & rhs
) // nothrow
649 : m_refcount (rhs
.m_refcount
),
650 m_pagedata (rhs
.m_pagedata
),
651 m_allocator(rhs
.m_allocator
)
654 PageHolder
& operator= (PageHolder
const & rhs
) // nothrow
656 PageHolder
tmp (rhs
);
661 PageData
* get() { return m_pagedata
; }
662 PageData
const * get() const { return m_pagedata
; }
664 PageData
* operator->()
666 OSL_PRECOND(m_pagedata
!= 0, "store::PageHolder::operator->(): Null pointer");
669 PageData
const * operator->() const
671 OSL_PRECOND(m_pagedata
!= 0, "store::PageHolder::operator->(): Null pointer");
675 PageData
& operator*()
677 OSL_PRECOND(m_pagedata
!= 0, "store::PageHolder::operator*(): Null pointer");
680 PageData
const & operator*() const
682 OSL_PRECOND(m_pagedata
!= 0, "store::PageHolder::operator*(): Null pointer");
687 /*========================================================================
691 *======================================================================*/
693 class PageHolderObject
702 static bool isA (PageData
const * p
)
704 return ((p
!= 0) && (p
->type() == U::theTypeId
));
708 static U
* dynamic_page_cast (PageData
* p
)
710 return isA
<U
>(p
) ? static_cast<U
*>(p
) : 0;
714 static U
const * dynamic_page_cast (PageData
const * p
)
716 return isA
<U
>(p
) ? static_cast<U
const *>(p
) : 0;
720 bool construct (rtl::Reference
< PageData::Allocator
> const & rxAllocator
)
722 if ((m_xPage
.get() == 0) && rxAllocator
.is())
724 PageHolder
tmp (rxAllocator
->construct
<T
>(), rxAllocator
);
727 return (m_xPage
.get() != 0);
730 static PageHolderObject
<T
> createInstance (rtl::Reference
< PageData::Allocator
> const & rxAllocator
)
732 PageHolderObject
<T
> tmp
;
733 (void) tmp
.construct (rxAllocator
);
737 explicit PageHolderObject (PageHolder
const & rxPage
= PageHolder())
741 void swap (PageHolderObject
<T
> & rhs
)
743 m_xPage
.swap (rhs
.m_xPage
);
746 PageHolderObject (PageHolderObject
<T
> const & rhs
)
747 : m_xPage (rhs
.m_xPage
)
750 PageHolderObject
<T
> & operator= (PageHolderObject
<T
> const & rhs
)
752 PageHolderObject
<T
> tmp (rhs
);
759 return (m_xPage
.get() != 0);
763 PageHolder
& get() { return m_xPage
; }
764 PageHolder
const & get() const { return m_xPage
; }
769 T
* pImpl
= dynamic_page_cast
<T
>(m_xPage
.get());
770 OSL_PRECOND(pImpl
!= 0, "store::PageHolder<T>::operator*(): Null pointer");
773 T
const * operator->() const
775 T
const * pImpl
= dynamic_page_cast
<T
>(m_xPage
.get());
776 OSL_PRECOND(pImpl
!= 0, "store::PageHolder<T>::operator*(): Null pointer");
782 T
* pImpl
= dynamic_page_cast
<T
>(m_xPage
.get());
783 OSL_PRECOND(pImpl
!= 0, "store::PageHolder<T>::operator*(): Null pointer");
786 T
const & operator*() const
788 T
const * pImpl
= dynamic_page_cast
<T
>(m_xPage
.get());
789 OSL_PRECOND(pImpl
!= 0, "store::PageHolder<T>::operator*(): Null pointer");
793 static storeError
guard (PageHolder
& rxPage
, sal_uInt32 nAddr
)
795 PageData
* pHead
= rxPage
.get();
797 return store_E_InvalidAccess
;
800 T
* pImpl
= dynamic_page_cast
<T
>(pHead
);
801 OSL_PRECOND(pImpl
!= 0, "store::PageHolder<T>::guard(): Null pointer");
806 static storeError
verify (PageHolder
const & rxPage
, sal_uInt32 nAddr
)
808 PageData
const * pHead
= rxPage
.get();
810 return store_E_InvalidAccess
;
812 storeError eErrCode
= pHead
->verify(nAddr
);
813 if (eErrCode
!= store_E_None
)
816 T
const * pImpl
= dynamic_page_cast
<T
>(pHead
);
818 return store_E_WrongVersion
;
820 return pImpl
->verify();
824 /*========================================================================
828 *======================================================================*/
833 explicit PageObject (PageHolder
const & rxPage
= PageHolder())
834 : m_xPage (rxPage
), m_bDirty (false)
837 virtual ~PageObject()
840 PageHolder
& get() { return m_xPage
; }
841 PageHolder
const & get() const { return m_xPage
; }
843 void clean() { m_bDirty
= false; }
844 void touch() { m_bDirty
= true; }
846 sal_uInt32
location() const
848 PageData
const * pagedata
= m_xPage
.get();
849 return (pagedata
!= 0) ? pagedata
->location() : STORE_PAGE_NULL
;
851 void location (sal_uInt32 nAddr
)
853 PageData
* pagedata
= m_xPage
.get();
855 pagedata
->location (nAddr
);
862 virtual storeError
guard (sal_uInt32 nAddr
) = 0;
863 virtual storeError
verify (sal_uInt32 nAddr
) const = 0;
867 class OStorePageBIOS
;
869 class OStorePageObject
871 typedef OStorePageData page
;
876 static void * operator new (size_t n
) SAL_THROW(())
878 return rtl_allocateMemory (sal_uInt32(n
));
880 static void operator delete (void * p
, size_t) SAL_THROW(())
887 inline bool dirty (void) const;
888 inline void clean (void);
889 inline void touch (void);
893 inline sal_uInt32
location (void) const;
894 inline void location (sal_uInt32 nAddr
);
904 explicit OStorePageObject (PageHolder
const & rxPage
= PageHolder())
905 : m_xPage (rxPage
), m_bDirty (false)
910 virtual ~OStorePageObject (void);
914 PageHolderObject
<U
> makeHolder() const
916 return PageHolderObject
<U
>(m_xPage
);
920 storeError
construct (rtl::Reference
< PageData::Allocator
> const & rxAllocator
)
922 if (!rxAllocator
.is())
923 return store_E_InvalidAccess
;
925 PageHolder
tmp (rxAllocator
->construct
<U
>(), rxAllocator
);
927 return store_E_OutOfMemory
;
934 PageHolder
& get() { return m_xPage
; }
935 PageHolder
const & get() const { return m_xPage
; }
937 virtual storeError
guard (sal_uInt32 nAddr
) = 0;
938 virtual storeError
verify (sal_uInt32 nAddr
) const = 0;
941 inline bool OStorePageObject::dirty (void) const
946 inline void OStorePageObject::clean (void)
951 inline void OStorePageObject::touch (void)
956 inline sal_uInt32
OStorePageObject::location (void) const
958 return m_xPage
->location();
961 inline void OStorePageObject::location (sal_uInt32 nAddr
)
963 m_xPage
->location(nAddr
);
967 /*========================================================================
971 *======================================================================*/
975 #endif /* !_STORE_STORBASE_HXX_ */