1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #ifndef _STORE_STORBASE_HXX_
21 #define _STORE_STORBASE_HXX_
23 #include "sal/config.h"
25 #include "boost/static_assert.hpp"
26 #include "sal/types.h"
28 #include "rtl/alloc.h"
30 #include "rtl/ref.hxx"
32 #include "osl/diagnose.h"
33 #include "osl/endian.h"
35 #include "store/types.h"
40 /*========================================================================
42 * store common internals.
44 *======================================================================*/
46 #ifndef STORE_IMPL_ISP2
47 #define STORE_IMPL_ISP2(value) (((value) & ((value) - 1)) == 0)
50 #ifndef STORE_IMPL_CONCAT
51 #define STORE_IMPL_CONCAT(x, y) STORE_IMPL_CONCAT2(x,y)
52 #define STORE_IMPL_CONCAT2(x, y) x##y
73 inline sal_uInt16
htons (sal_uInt16 h
) { return OSL_SWAPWORD(h
); }
74 inline sal_uInt16
ntohs (sal_uInt16 n
) { return OSL_SWAPWORD(n
); }
76 inline sal_uInt32
htonl (sal_uInt32 h
) { return OSL_SWAPDWORD(h
); }
77 inline sal_uInt32
ntohl (sal_uInt32 n
) { return OSL_SWAPDWORD(n
); }
79 inline sal_uInt16
htons (sal_uInt16 h
) { return (h
); }
80 inline sal_uInt16
ntohs (sal_uInt16 n
) { return (n
); }
82 inline sal_uInt32
htonl (sal_uInt32 h
) { return (h
); }
83 inline sal_uInt32
ntohl (sal_uInt32 n
) { return (n
); }
84 #endif /* OSL_BIGENDIAN */
88 template< typename T
> void swap (T
& lhs
, T
& rhs
)
90 T tmp
= lhs
; lhs
= rhs
; rhs
= tmp
;
93 /*========================================================================
97 *======================================================================*/
104 rtl_cache_type
* m_cache
;
107 static Allocator
& get();
111 return static_cast<long*>(rtl_cache_alloc (m_cache
));
113 void free (long * pCount
)
115 rtl_cache_free (m_cache
, pCount
);
125 : m_pCount(Allocator::get().alloc())
127 if (m_pCount
!= 0) (*m_pCount
) = 1;
134 long new_count
= --(*m_pCount
);
136 Allocator::get().free(m_pCount
);
140 void swap (SharedCount
& rhs
) // nothrow
142 store::swap(m_pCount
, rhs
.m_pCount
);
145 SharedCount (SharedCount
const & rhs
) // nothrow
146 : m_pCount (rhs
.m_pCount
)
148 if (m_pCount
!= 0) ++(*m_pCount
);
150 SharedCount
& operator= (SharedCount
const & rhs
) // nothrow
152 SharedCount
tmp(rhs
);
157 bool operator== (long count
) const
159 return (m_pCount
!= 0) ? *m_pCount
== count
: false;
163 /*========================================================================
167 *======================================================================*/
168 struct OStorePageGuard
177 explicit OStorePageGuard (sal_uInt32 nMagic
= 0, sal_uInt32 nCRC32
= 0)
178 : m_nMagic (store::htonl(nMagic
)),
179 m_nCRC32 (store::htonl(nCRC32
))
182 void swap (OStorePageGuard
& rhs
)
184 store::swap(m_nMagic
, rhs
.m_nMagic
);
185 store::swap(m_nCRC32
, rhs
.m_nCRC32
);
188 OStorePageGuard (OStorePageGuard
const & rhs
)
189 : m_nMagic (rhs
.m_nMagic
),
190 m_nCRC32 (rhs
.m_nCRC32
)
193 OStorePageGuard
& operator= (const OStorePageGuard
& rhs
)
195 m_nMagic
= rhs
.m_nMagic
;
196 m_nCRC32
= rhs
.m_nCRC32
;
202 bool operator== (const OStorePageGuard
& rhs
) const
204 return ((m_nMagic
== rhs
.m_nMagic
) &&
205 (m_nCRC32
== rhs
.m_nCRC32
) );
209 /*========================================================================
211 * OStorePageDescriptor.
213 *======================================================================*/
214 #define STORE_PAGE_NULL ((sal_uInt32)(~0))
216 struct OStorePageDescriptor
226 explicit OStorePageDescriptor (
227 sal_uInt32 nAddr
= STORE_PAGE_NULL
,
228 sal_uInt16 nSize
= 0,
229 sal_uInt16 nUsed
= 0)
230 : m_nAddr (store::htonl(nAddr
)),
231 m_nSize (store::htons(nSize
)),
232 m_nUsed (store::htons(nUsed
))
235 void swap (OStorePageDescriptor
& rhs
)
237 store::swap(m_nAddr
, rhs
.m_nAddr
);
238 store::swap(m_nSize
, rhs
.m_nSize
);
239 store::swap(m_nUsed
, rhs
.m_nUsed
);
242 OStorePageDescriptor (const OStorePageDescriptor
& rhs
)
243 : m_nAddr (rhs
.m_nAddr
),
244 m_nSize (rhs
.m_nSize
),
245 m_nUsed (rhs
.m_nUsed
)
248 OStorePageDescriptor
& operator= (const OStorePageDescriptor
& rhs
)
250 m_nAddr
= rhs
.m_nAddr
;
251 m_nSize
= rhs
.m_nSize
;
252 m_nUsed
= rhs
.m_nUsed
;
258 bool operator== (const OStorePageDescriptor
& rhs
) const
260 return ((m_nAddr
== rhs
.m_nAddr
) &&
261 (m_nSize
== rhs
.m_nSize
) );
264 bool operator<= (const OStorePageDescriptor
& rhs
) const
266 return ((m_nAddr
== rhs
.m_nAddr
) &&
267 (store::ntohs(m_nSize
) <= store::ntohs(rhs
.m_nSize
)) );
270 bool operator< (const OStorePageDescriptor
& rhs
) const
272 if (m_nAddr
== rhs
.m_nAddr
)
273 return (store::ntohs(m_nSize
) < store::ntohs(rhs
.m_nSize
));
275 return (store::ntohl(m_nAddr
) < store::ntohl(rhs
.m_nAddr
));
279 /*========================================================================
283 *======================================================================*/
293 explicit OStorePageKey (sal_uInt32 nLow
= 0, sal_uInt32 nHigh
= 0)
294 : m_nLow (store::htonl(nLow
)),
295 m_nHigh (store::htonl(nHigh
))
298 void swap (OStorePageKey
& rhs
)
300 store::swap(m_nLow
, rhs
.m_nLow
);
301 store::swap(m_nHigh
, rhs
.m_nHigh
);
304 OStorePageKey (const OStorePageKey
& rhs
)
305 : m_nLow (rhs
.m_nLow
), m_nHigh (rhs
.m_nHigh
)
308 OStorePageKey
& operator= (const OStorePageKey
& rhs
)
311 m_nHigh
= rhs
.m_nHigh
;
317 bool operator== (const OStorePageKey
& rhs
) const
319 return ((m_nLow
== rhs
.m_nLow
) &&
320 (m_nHigh
== rhs
.m_nHigh
) );
323 bool operator< (const OStorePageKey
& rhs
) const
325 if (m_nHigh
== rhs
.m_nHigh
)
326 return (store::ntohl(m_nLow
) < store::ntohl(rhs
.m_nLow
));
328 return (store::ntohl(m_nHigh
) < store::ntohl(rhs
.m_nHigh
));
332 /*========================================================================
336 *======================================================================*/
337 struct OStorePageLink
345 explicit OStorePageLink (sal_uInt32 nAddr
= STORE_PAGE_NULL
)
346 : m_nAddr (store::htonl(nAddr
))
349 void swap (OStorePageLink
& rhs
)
351 store::swap(m_nAddr
, rhs
.m_nAddr
);
354 OStorePageLink (const OStorePageLink
& rhs
)
355 : m_nAddr (rhs
.m_nAddr
)
358 OStorePageLink
& operator= (const OStorePageLink
& rhs
)
360 m_nAddr
= rhs
.m_nAddr
;
364 OStorePageLink
& operator= (sal_uInt32 nAddr
)
366 m_nAddr
= store::htonl(nAddr
);
372 bool operator== (const OStorePageLink
& rhs
) const
374 return (m_nAddr
== rhs
.m_nAddr
);
377 bool operator< (const OStorePageLink
& rhs
) const
379 return (store::ntohl(m_nAddr
) < store::ntohl(rhs
.m_nAddr
));
384 sal_uInt32
location() const
386 return store::ntohl(m_nAddr
);
389 void link (OStorePageLink
& rPred
)
391 // @@@ swap (rPred); @@@
392 OStorePageLink
tmp (rPred
);
397 void unlink (OStorePageLink
& rPred
)
400 *this = OStorePageLink();
404 /*========================================================================
408 *======================================================================*/
409 typedef struct PageData OStorePageData
; // backward compat.
412 typedef OStorePageGuard G
;
413 typedef OStorePageDescriptor D
;
414 typedef OStorePageLink L
;
425 static const size_t theSize
= sizeof(G
) + sizeof(D
) + 2 * sizeof(L
);
426 static const sal_uInt16 thePageSize
= theSize
;
427 BOOST_STATIC_ASSERT(STORE_MINIMUM_PAGESIZE
>= thePageSize
);
431 sal_uInt32
location() const
433 return store::ntohl(m_aDescr
.m_nAddr
);
435 void location (sal_uInt32 nAddr
)
437 m_aDescr
.m_nAddr
= store::htonl(nAddr
);
442 sal_uInt16
size() const
444 return store::ntohs(m_aDescr
.m_nSize
);
449 sal_uInt32
type() const
451 return store::ntohl(m_aGuard
.m_nMagic
);
456 class Allocator_Impl
;
457 class Allocator
: public rtl::IReference
460 template< class T
> T
* construct()
462 void * page
= 0; sal_uInt16 size
= 0;
463 if (allocate (&page
, &size
))
465 return new(page
) T(size
);
470 bool allocate (void ** ppPage
, sal_uInt16
* pnSize
)
472 allocate_Impl (ppPage
, pnSize
);
473 return ((*ppPage
!= 0) && (*pnSize
!= 0));
476 void deallocate (void * pPage
)
479 deallocate_Impl (pPage
);
482 static storeError
createInstance (
483 rtl::Reference
< PageData::Allocator
> & rxAllocator
, sal_uInt16 nPageSize
);
489 /** Implementation (abstract).
491 virtual void allocate_Impl (void ** ppPage
, sal_uInt16
* pnSize
) = 0;
492 virtual void deallocate_Impl (void * pPage
) = 0;
495 static void* operator new (size_t, void * p
) { return p
; }
496 static void operator delete (void * , void *) {}
500 explicit PageData (sal_uInt16 nPageSize
= thePageSize
)
502 m_aDescr(STORE_PAGE_NULL
, nPageSize
, thePageSize
),
507 void swap (PageData
& rhs
) // nothrow
509 m_aGuard
.swap(rhs
.m_aGuard
);
510 m_aDescr
.swap(rhs
.m_aDescr
);
511 m_aMarked
.swap(rhs
.m_aMarked
);
512 m_aUnused
.swap(rhs
.m_aUnused
);
515 PageData (PageData
const & rhs
) // nothrow
516 : m_aGuard (rhs
.m_aGuard
),
517 m_aDescr (rhs
.m_aDescr
),
518 m_aMarked(rhs
.m_aMarked
),
519 m_aUnused(rhs
.m_aUnused
)
522 PageData
& operator= (PageData
const & rhs
) // nothrow
529 /** guard (external representation).
531 void guard (sal_uInt32 nAddr
)
533 sal_uInt32 nCRC32
= 0;
534 nCRC32
= rtl_crc32 (nCRC32
, &m_aGuard
.m_nMagic
, sizeof(sal_uInt32
));
535 m_aDescr
.m_nAddr
= store::htonl(nAddr
);
536 nCRC32
= rtl_crc32 (nCRC32
, &m_aDescr
, theSize
- sizeof(G
));
537 m_aGuard
.m_nCRC32
= store::htonl(nCRC32
);
540 /** verify (external representation).
542 storeError
verify (sal_uInt32 nAddr
) const
544 sal_uInt32 nCRC32
= 0;
545 nCRC32
= rtl_crc32 (nCRC32
, &m_aGuard
.m_nMagic
, sizeof(sal_uInt32
));
546 nCRC32
= rtl_crc32 (nCRC32
, &m_aDescr
, theSize
- sizeof(G
));
547 if (m_aGuard
.m_nCRC32
!= store::htonl(nCRC32
))
548 return store_E_InvalidChecksum
;
549 if (m_aDescr
.m_nAddr
!= store::htonl(nAddr
))
550 return store_E_InvalidAccess
;
554 storeError
verifyVersion (sal_uInt32 nMagic
) const
556 if (m_aGuard
.m_nMagic
!= store::htonl(nMagic
))
557 return store_E_WrongVersion
;
563 /*========================================================================
567 *======================================================================*/
570 SharedCount m_refcount
;
571 PageData
* m_pagedata
;
573 typedef rtl::Reference
< PageData::Allocator
> allocator_type
;
574 allocator_type m_allocator
;
577 explicit PageHolder (PageData
* pagedata
= 0, allocator_type
const & allocator
= allocator_type())
579 m_pagedata (pagedata
),
580 m_allocator(allocator
)
582 OSL_ENSURE((m_pagedata
== 0) || m_allocator
.is(), "store::PageHolder::ctor(): pagedata w/o allocator.");
587 if ((m_refcount
== 1) && (m_pagedata
!= 0))
590 OSL_ENSURE(m_allocator
.is(), "store::PageHolder::dtor(): pagedata w/o allocator.");
591 m_allocator
->deallocate (m_pagedata
);
595 void swap (PageHolder
& rhs
) // nothrow
597 m_refcount
.swap(rhs
.m_refcount
);
598 store::swap(m_pagedata
, rhs
.m_pagedata
);
599 store::swap(m_allocator
, rhs
.m_allocator
);
602 PageHolder (PageHolder
const & rhs
) // nothrow
603 : m_refcount (rhs
.m_refcount
),
604 m_pagedata (rhs
.m_pagedata
),
605 m_allocator(rhs
.m_allocator
)
608 PageHolder
& operator= (PageHolder
const & rhs
) // nothrow
610 PageHolder
tmp (rhs
);
615 PageData
* get() { return m_pagedata
; }
616 PageData
const * get() const { return m_pagedata
; }
618 PageData
* operator->()
620 OSL_PRECOND(m_pagedata
!= 0, "store::PageHolder::operator->(): Null pointer");
623 PageData
const * operator->() const
625 OSL_PRECOND(m_pagedata
!= 0, "store::PageHolder::operator->(): Null pointer");
629 PageData
& operator*()
631 OSL_PRECOND(m_pagedata
!= 0, "store::PageHolder::operator*(): Null pointer");
634 PageData
const & operator*() const
636 OSL_PRECOND(m_pagedata
!= 0, "store::PageHolder::operator*(): Null pointer");
641 /*========================================================================
645 *======================================================================*/
647 class PageHolderObject
656 static bool isA (PageData
const * p
)
658 return ((p
!= 0) && (p
->type() == U::theTypeId
));
662 static U
* dynamic_page_cast (PageData
* p
)
664 return isA
<U
>(p
) ? static_cast<U
*>(p
) : 0;
668 static U
const * dynamic_page_cast (PageData
const * p
)
670 return isA
<U
>(p
) ? static_cast<U
const *>(p
) : 0;
674 bool construct (rtl::Reference
< PageData::Allocator
> const & rxAllocator
)
676 if ((m_xPage
.get() == 0) && rxAllocator
.is())
678 PageHolder
tmp (rxAllocator
->construct
<T
>(), rxAllocator
);
681 return (m_xPage
.get() != 0);
684 static PageHolderObject
<T
> createInstance (rtl::Reference
< PageData::Allocator
> const & rxAllocator
)
686 PageHolderObject
<T
> tmp
;
687 (void) tmp
.construct (rxAllocator
);
691 explicit PageHolderObject (PageHolder
const & rxPage
= PageHolder())
695 void swap (PageHolderObject
<T
> & rhs
)
697 m_xPage
.swap (rhs
.m_xPage
);
700 PageHolderObject (PageHolderObject
<T
> const & rhs
)
701 : m_xPage (rhs
.m_xPage
)
704 PageHolderObject
<T
> & operator= (PageHolderObject
<T
> const & rhs
)
706 PageHolderObject
<T
> tmp (rhs
);
713 return (m_xPage
.get() != 0);
717 PageHolder
& get() { return m_xPage
; }
718 PageHolder
const & get() const { return m_xPage
; }
723 T
* pImpl
= dynamic_page_cast
<T
>(m_xPage
.get());
724 OSL_PRECOND(pImpl
!= 0, "store::PageHolder<T>::operator*(): Null pointer");
727 T
const * operator->() const
729 T
const * pImpl
= dynamic_page_cast
<T
>(m_xPage
.get());
730 OSL_PRECOND(pImpl
!= 0, "store::PageHolder<T>::operator*(): Null pointer");
736 T
* pImpl
= dynamic_page_cast
<T
>(m_xPage
.get());
737 OSL_PRECOND(pImpl
!= 0, "store::PageHolder<T>::operator*(): Null pointer");
740 T
const & operator*() const
742 T
const * pImpl
= dynamic_page_cast
<T
>(m_xPage
.get());
743 OSL_PRECOND(pImpl
!= 0, "store::PageHolder<T>::operator*(): Null pointer");
747 static storeError
guard (PageHolder
& rxPage
, sal_uInt32 nAddr
)
749 PageData
* pHead
= rxPage
.get();
751 return store_E_InvalidAccess
;
754 T
* pImpl
= dynamic_page_cast
<T
>(pHead
);
755 OSL_PRECOND(pImpl
!= 0, "store::PageHolder<T>::guard(): Null pointer");
760 static storeError
verify (PageHolder
const & rxPage
, sal_uInt32 nAddr
)
762 PageData
const * pHead
= rxPage
.get();
764 return store_E_InvalidAccess
;
766 storeError eErrCode
= pHead
->verify(nAddr
);
767 if (eErrCode
!= store_E_None
)
770 T
const * pImpl
= dynamic_page_cast
<T
>(pHead
);
772 return store_E_WrongVersion
;
774 return pImpl
->verify();
778 /*========================================================================
782 *======================================================================*/
787 explicit PageObject (PageHolder
const & rxPage
= PageHolder())
788 : m_xPage (rxPage
), m_bDirty (false)
791 virtual ~PageObject()
794 PageHolder
& get() { return m_xPage
; }
795 PageHolder
const & get() const { return m_xPage
; }
797 void clean() { m_bDirty
= false; }
798 void touch() { m_bDirty
= true; }
800 sal_uInt32
location() const
802 PageData
const * pagedata
= m_xPage
.get();
803 return (pagedata
!= 0) ? pagedata
->location() : STORE_PAGE_NULL
;
805 void location (sal_uInt32 nAddr
)
807 PageData
* pagedata
= m_xPage
.get();
809 pagedata
->location (nAddr
);
816 virtual storeError
guard (sal_uInt32 nAddr
) = 0;
817 virtual storeError
verify (sal_uInt32 nAddr
) const = 0;
821 class OStorePageBIOS
;
823 class OStorePageObject
825 typedef OStorePageData page
;
830 static void * operator new (size_t n
) SAL_THROW(())
832 return rtl_allocateMemory (sal_uInt32(n
));
834 static void operator delete (void * p
) SAL_THROW(())
841 inline bool dirty (void) const;
842 inline void clean (void);
843 inline void touch (void);
847 inline sal_uInt32
location (void) const;
848 inline void location (sal_uInt32 nAddr
);
858 explicit OStorePageObject (PageHolder
const & rxPage
= PageHolder())
859 : m_xPage (rxPage
), m_bDirty (false)
864 virtual ~OStorePageObject (void);
868 PageHolderObject
<U
> makeHolder() const
870 return PageHolderObject
<U
>(m_xPage
);
874 storeError
construct (rtl::Reference
< PageData::Allocator
> const & rxAllocator
)
876 if (!rxAllocator
.is())
877 return store_E_InvalidAccess
;
879 PageHolder
tmp (rxAllocator
->construct
<U
>(), rxAllocator
);
881 return store_E_OutOfMemory
;
888 PageHolder
& get() { return m_xPage
; }
889 PageHolder
const & get() const { return m_xPage
; }
891 virtual storeError
guard (sal_uInt32 nAddr
) = 0;
892 virtual storeError
verify (sal_uInt32 nAddr
) const = 0;
895 inline bool OStorePageObject::dirty (void) const
900 inline void OStorePageObject::clean (void)
905 inline void OStorePageObject::touch (void)
910 inline sal_uInt32
OStorePageObject::location (void) const
912 return m_xPage
->location();
915 inline void OStorePageObject::location (sal_uInt32 nAddr
)
917 m_xPage
->location(nAddr
);
921 /*========================================================================
925 *======================================================================*/
929 #endif /* !_STORE_STORBASE_HXX_ */
931 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */