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 INCLUDED_STORE_SOURCE_STORBASE_HXX
21 #define INCLUDED_STORE_SOURCE_STORBASE_HXX
23 #include <sal/config.h>
24 #include <salhelper/simplereferenceobject.hxx>
26 #include <sal/types.h>
29 #include <rtl/ref.hxx>
31 #include <osl/diagnose.h>
32 #include <osl/endian.h>
34 #include <store/types.h>
39 /** @file store common internals.
60 inline sal_uInt16
htons (sal_uInt16 h
) { return OSL_SWAPWORD(h
); }
61 inline sal_uInt16
ntohs (sal_uInt16 n
) { return OSL_SWAPWORD(n
); }
63 inline sal_uInt32
htonl (sal_uInt32 h
) { return OSL_SWAPDWORD(h
); }
64 inline sal_uInt32
ntohl (sal_uInt32 n
) { return OSL_SWAPDWORD(n
); }
66 inline sal_uInt16
htons (sal_uInt16 h
) { return h
; }
67 inline sal_uInt16
ntohs (sal_uInt16 n
) { return n
; }
69 inline sal_uInt32
htonl (sal_uInt32 h
) { return h
; }
70 inline sal_uInt32
ntohl (sal_uInt32 n
) { return n
; }
71 #endif /* OSL_BIGENDIAN */
73 struct OStorePageGuard
82 explicit OStorePageGuard (sal_uInt32 nMagic
= 0)
83 : m_nMagic (store::htonl(nMagic
)),
84 m_nCRC32 (store::htonl(0))
87 void swap (OStorePageGuard
& rhs
)
89 std::swap(m_nMagic
, rhs
.m_nMagic
);
90 std::swap(m_nCRC32
, rhs
.m_nCRC32
);
93 OStorePageGuard (OStorePageGuard
const & rhs
)
94 : m_nMagic (rhs
.m_nMagic
),
95 m_nCRC32 (rhs
.m_nCRC32
)
98 OStorePageGuard
& operator= (const OStorePageGuard
& rhs
)
100 m_nMagic
= rhs
.m_nMagic
;
101 m_nCRC32
= rhs
.m_nCRC32
;
107 bool operator== (const OStorePageGuard
& rhs
) const
109 return ((m_nMagic
== rhs
.m_nMagic
) &&
110 (m_nCRC32
== rhs
.m_nCRC32
) );
114 #define STORE_PAGE_NULL (sal_uInt32(~0))
116 struct OStorePageDescriptor
126 explicit OStorePageDescriptor (
130 : m_nAddr (store::htonl(nAddr
)),
131 m_nSize (store::htons(nSize
)),
132 m_nUsed (store::htons(nUsed
))
135 void swap (OStorePageDescriptor
& rhs
)
137 std::swap(m_nAddr
, rhs
.m_nAddr
);
138 std::swap(m_nSize
, rhs
.m_nSize
);
139 std::swap(m_nUsed
, rhs
.m_nUsed
);
142 OStorePageDescriptor (const OStorePageDescriptor
& rhs
)
143 : m_nAddr (rhs
.m_nAddr
),
144 m_nSize (rhs
.m_nSize
),
145 m_nUsed (rhs
.m_nUsed
)
148 OStorePageDescriptor
& operator= (const OStorePageDescriptor
& rhs
)
150 m_nAddr
= rhs
.m_nAddr
;
151 m_nSize
= rhs
.m_nSize
;
152 m_nUsed
= rhs
.m_nUsed
;
158 bool operator== (const OStorePageDescriptor
& rhs
) const
160 return ((m_nAddr
== rhs
.m_nAddr
) &&
161 (m_nSize
== rhs
.m_nSize
) );
174 explicit OStorePageKey (sal_uInt32 nLow
= 0, sal_uInt32 nHigh
= 0)
175 : m_nLow (store::htonl(nLow
)),
176 m_nHigh (store::htonl(nHigh
))
181 bool operator== (const OStorePageKey
& rhs
) const
183 return ((m_nLow
== rhs
.m_nLow
) &&
184 (m_nHigh
== rhs
.m_nHigh
) );
187 bool operator< (const OStorePageKey
& rhs
) const
189 if (m_nHigh
== rhs
.m_nHigh
)
190 return (store::ntohl(m_nLow
) < store::ntohl(rhs
.m_nLow
));
192 return (store::ntohl(m_nHigh
) < store::ntohl(rhs
.m_nHigh
));
196 struct OStorePageLink
204 explicit OStorePageLink (sal_uInt32 nAddr
= STORE_PAGE_NULL
)
205 : m_nAddr (store::htonl(nAddr
))
208 void swap (OStorePageLink
& rhs
)
210 std::swap(m_nAddr
, rhs
.m_nAddr
);
213 OStorePageLink
& operator= (sal_uInt32 nAddr
)
215 m_nAddr
= store::htonl(nAddr
);
221 bool operator== (const OStorePageLink
& rhs
) const
223 return (m_nAddr
== rhs
.m_nAddr
);
228 sal_uInt32
location() const
230 return store::ntohl(m_nAddr
);
237 typedef OStorePageGuard G
;
238 typedef OStorePageDescriptor D
;
239 typedef OStorePageLink L
;
250 static const size_t theSize
= sizeof(G
) + sizeof(D
) + 2 * sizeof(L
);
251 static const sal_uInt16 thePageSize
= theSize
;
252 static_assert(STORE_MINIMUM_PAGESIZE
>= thePageSize
, "must be at least thePageSize");
256 sal_uInt32
location() const
258 return store::ntohl(m_aDescr
.m_nAddr
);
260 void location (sal_uInt32 nAddr
)
262 m_aDescr
.m_nAddr
= store::htonl(nAddr
);
267 sal_uInt16
size() const
269 return store::ntohs(m_aDescr
.m_nSize
);
274 sal_uInt32
type() const
276 return store::ntohl(m_aGuard
.m_nMagic
);
281 class Allocator_Impl
;
282 class Allocator
: public virtual salhelper::SimpleReferenceObject
285 template< class T
> T
* construct()
287 void * page
= nullptr; sal_uInt16 size
= 0;
288 if (allocate (&page
, &size
))
290 return new(page
) T(size
);
295 bool allocate (void ** ppPage
, sal_uInt16
* pnSize
)
297 allocate_Impl (ppPage
, pnSize
);
298 return ((*ppPage
!= nullptr) && (*pnSize
!= 0));
301 void deallocate (void * pPage
)
303 if (pPage
!= nullptr)
304 deallocate_Impl (pPage
);
307 static storeError
createInstance (
308 rtl::Reference
< PageData::Allocator
> & rxAllocator
, sal_uInt16 nPageSize
);
311 virtual ~Allocator() override
{}
314 /** Implementation (abstract).
316 virtual void allocate_Impl (void ** ppPage
, sal_uInt16
* pnSize
) = 0;
317 virtual void deallocate_Impl (void * pPage
) = 0;
322 explicit Deallocate(rtl::Reference
<Allocator
> const & allocator
):
323 allocator_(allocator
) {};
325 void operator ()(void * page
) const { allocator_
->deallocate(page
); }
328 rtl::Reference
<Allocator
> allocator_
;
331 static void* operator new (size_t, void * p
) { return p
; }
332 static void operator delete (void * , void *) {}
336 explicit PageData (sal_uInt16 nPageSize
= thePageSize
)
338 m_aDescr(STORE_PAGE_NULL
, nPageSize
, thePageSize
),
343 void swap (PageData
& rhs
) // nothrow
345 m_aGuard
.swap(rhs
.m_aGuard
);
346 m_aDescr
.swap(rhs
.m_aDescr
);
347 m_aMarked
.swap(rhs
.m_aMarked
);
348 m_aUnused
.swap(rhs
.m_aUnused
);
351 PageData (PageData
const & rhs
) // nothrow
352 : m_aGuard (rhs
.m_aGuard
),
353 m_aDescr (rhs
.m_aDescr
),
354 m_aMarked(rhs
.m_aMarked
),
355 m_aUnused(rhs
.m_aUnused
)
358 PageData
& operator= (PageData
const & rhs
) // nothrow
365 /** guard (external representation).
367 void guard (sal_uInt32 nAddr
)
369 sal_uInt32 nCRC32
= rtl_crc32 (0, &m_aGuard
.m_nMagic
, sizeof(sal_uInt32
));
370 m_aDescr
.m_nAddr
= store::htonl(nAddr
);
371 nCRC32
= rtl_crc32 (nCRC32
, &m_aDescr
, static_cast<sal_uInt32
>(theSize
- sizeof(G
)));
372 m_aGuard
.m_nCRC32
= store::htonl(nCRC32
);
375 /** verify (external representation).
377 storeError
verify (sal_uInt32 nAddr
) const
379 sal_uInt32 nCRC32
= rtl_crc32 (0, &m_aGuard
.m_nMagic
, sizeof(sal_uInt32
));
380 nCRC32
= rtl_crc32 (nCRC32
, &m_aDescr
, static_cast<sal_uInt32
>(theSize
- sizeof(G
)));
381 if (m_aGuard
.m_nCRC32
!= store::htonl(nCRC32
))
382 return store_E_InvalidChecksum
;
383 if (m_aDescr
.m_nAddr
!= store::htonl(nAddr
))
384 return store_E_InvalidAccess
;
391 class PageHolderObject
395 std::shared_ptr
<PageData
> m_xPage
;
400 static bool isA (PageData
const * p
)
402 return ((p
!= nullptr) && (p
->type() == U::theTypeId
));
406 static U
* dynamic_page_cast (PageData
* p
)
408 return isA
<U
>(p
) ? static_cast<U
*>(p
) : 0;
412 static U
const * dynamic_page_cast (PageData
const * p
)
414 return isA
<U
>(p
) ? static_cast<U
const *>(p
) : 0;
418 bool construct (rtl::Reference
< PageData::Allocator
> const & rxAllocator
)
420 if ((m_xPage
.get() == nullptr) && rxAllocator
.is())
422 std::shared_ptr
<PageData
> tmp (rxAllocator
->construct
<T
>(), PageData::Deallocate(rxAllocator
));
425 return (m_xPage
.get() != nullptr);
428 explicit PageHolderObject (std::shared_ptr
<PageData
> const & rxPage
= std::shared_ptr
<PageData
>())
432 void swap (PageHolderObject
<T
> & rhs
)
434 m_xPage
.swap (rhs
.m_xPage
);
437 PageHolderObject (PageHolderObject
<T
> const & rhs
)
438 : m_xPage (rhs
.m_xPage
)
441 PageHolderObject
<T
> & operator= (PageHolderObject
<T
> const & rhs
)
443 PageHolderObject
<T
> tmp (rhs
);
450 return (m_xPage
.get() != nullptr);
453 std::shared_ptr
<PageData
> & get() { return m_xPage
; }
454 std::shared_ptr
<PageData
> const & get() const { return m_xPage
; }
458 T
* pImpl
= dynamic_page_cast
<T
>(m_xPage
.get());
459 OSL_PRECOND(pImpl
!= nullptr, "store::PageHolder<T>::operator*(): Null pointer");
463 T
const * operator->() const
465 T
const * pImpl
= dynamic_page_cast
<T
>(m_xPage
.get());
466 OSL_PRECOND(pImpl
!= nullptr, "store::PageHolder<T>::operator*(): Null pointer");
472 T
* pImpl
= dynamic_page_cast
<T
>(m_xPage
.get());
473 OSL_PRECOND(pImpl
!= nullptr, "store::PageHolder<T>::operator*(): Null pointer");
477 T
const & operator*() const
479 T
const * pImpl
= dynamic_page_cast
<T
>(m_xPage
.get());
480 OSL_PRECOND(pImpl
!= nullptr, "store::PageHolder<T>::operator*(): Null pointer");
484 static storeError
guard (std::shared_ptr
<PageData
> const & rxPage
, sal_uInt32 nAddr
)
486 PageData
* pHead
= rxPage
.get();
488 return store_E_InvalidAccess
;
491 T
* pImpl
= dynamic_page_cast
<T
>(pHead
);
492 OSL_PRECOND(pImpl
!= nullptr, "store::PageHolder<T>::guard(): Null pointer");
498 static storeError
verify (std::shared_ptr
<PageData
> const & rxPage
, sal_uInt32 nAddr
)
500 PageData
const * pHead
= rxPage
.get();
502 return store_E_InvalidAccess
;
504 storeError eErrCode
= pHead
->verify(nAddr
);
505 if (eErrCode
!= store_E_None
)
508 T
const * pImpl
= dynamic_page_cast
<T
>(pHead
);
510 return store_E_WrongVersion
;
512 return pImpl
->verify();
516 class OStorePageObject
518 typedef PageData page
;
523 static void * operator new (size_t n
)
525 return std::malloc(sal_uInt32(n
));
527 static void operator delete (void * p
)
534 inline bool dirty() const;
540 inline sal_uInt32
location() const;
545 std::shared_ptr
<PageData
> m_xPage
;
550 explicit OStorePageObject (std::shared_ptr
<PageData
> const & rxPage
)
551 : m_xPage (rxPage
), m_bDirty (false)
556 virtual ~OStorePageObject();
560 PageHolderObject
<U
> makeHolder() const
562 return PageHolderObject
<U
>(m_xPage
);
566 storeError
construct (rtl::Reference
< PageData::Allocator
> const & rxAllocator
)
568 if (!rxAllocator
.is())
569 return store_E_InvalidAccess
;
571 std::shared_ptr
<PageData
> tmp (rxAllocator
->construct
<U
>(), PageData::Deallocate(rxAllocator
));
573 return store_E_OutOfMemory
;
579 std::shared_ptr
<PageData
> & get() { return m_xPage
; }
581 virtual storeError
guard (sal_uInt32 nAddr
) = 0;
582 virtual storeError
verify (sal_uInt32 nAddr
) const = 0;
585 inline bool OStorePageObject::dirty() const
590 inline void OStorePageObject::clean()
595 inline void OStorePageObject::touch()
600 inline sal_uInt32
OStorePageObject::location() const
602 return m_xPage
->location();
607 #endif // INCLUDED_STORE_SOURCE_STORBASE_HXX
609 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */