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 .
22 #include <sal/config.h>
23 #include <salhelper/simplereferenceobject.hxx>
25 #include <sal/types.h>
28 #include <rtl/ref.hxx>
30 #include <osl/diagnose.h>
31 #include <osl/endian.h>
33 #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;
288 sal_uInt16 nSize
= 0;
289 if (allocate (&page
, &nSize
))
291 return new(page
) T(nSize
);
296 bool allocate (void ** ppPage
, sal_uInt16
* pnSize
)
298 allocate_Impl (ppPage
, pnSize
);
299 return ((*ppPage
!= nullptr) && (*pnSize
!= 0));
302 void deallocate (void * pPage
)
304 if (pPage
!= nullptr)
305 deallocate_Impl (pPage
);
308 static storeError
createInstance (
309 rtl::Reference
< PageData::Allocator
> & rxAllocator
, sal_uInt16 nPageSize
);
312 virtual ~Allocator() override
{}
315 /** Implementation (abstract).
317 virtual void allocate_Impl (void ** ppPage
, sal_uInt16
* pnSize
) = 0;
318 virtual void deallocate_Impl (void * pPage
) = 0;
323 explicit Deallocate(rtl::Reference
<Allocator
> allocator
):
324 allocator_(std::move(allocator
)) {};
326 void operator ()(void * page
) const { allocator_
->deallocate(page
); }
329 rtl::Reference
<Allocator
> allocator_
;
332 static void* operator new (size_t, void * p
) { return p
; }
333 static void operator delete (void * , void *) {}
337 explicit PageData (sal_uInt16 nPageSize
= thePageSize
)
339 m_aDescr(STORE_PAGE_NULL
, nPageSize
, thePageSize
),
344 void swap (PageData
& rhs
) // nothrow
346 m_aGuard
.swap(rhs
.m_aGuard
);
347 m_aDescr
.swap(rhs
.m_aDescr
);
348 m_aMarked
.swap(rhs
.m_aMarked
);
349 m_aUnused
.swap(rhs
.m_aUnused
);
352 PageData (PageData
const & rhs
) // nothrow
353 : m_aGuard (rhs
.m_aGuard
),
354 m_aDescr (rhs
.m_aDescr
),
355 m_aMarked(rhs
.m_aMarked
),
356 m_aUnused(rhs
.m_aUnused
)
359 PageData
& operator= (PageData
const & rhs
) // nothrow
366 /** guard (external representation).
368 void guard (sal_uInt32 nAddr
)
370 sal_uInt32 nCRC32
= rtl_crc32 (0, &m_aGuard
.m_nMagic
, sizeof(sal_uInt32
));
371 m_aDescr
.m_nAddr
= store::htonl(nAddr
);
372 nCRC32
= rtl_crc32 (nCRC32
, &m_aDescr
, static_cast<sal_uInt32
>(theSize
- sizeof(G
)));
373 m_aGuard
.m_nCRC32
= store::htonl(nCRC32
);
376 /** verify (external representation).
378 storeError
verify (sal_uInt32 nAddr
) const
380 sal_uInt32 nCRC32
= rtl_crc32 (0, &m_aGuard
.m_nMagic
, sizeof(sal_uInt32
));
381 nCRC32
= rtl_crc32 (nCRC32
, &m_aDescr
, static_cast<sal_uInt32
>(theSize
- sizeof(G
)));
382 if (m_aGuard
.m_nCRC32
!= store::htonl(nCRC32
))
383 return store_E_InvalidChecksum
;
384 if (m_aDescr
.m_nAddr
!= store::htonl(nAddr
))
385 return store_E_InvalidAccess
;
392 class PageHolderObject
396 std::shared_ptr
<PageData
> m_xPage
;
401 static bool isA (PageData
const * p
)
403 return ((p
!= nullptr) && (p
->type() == U::theTypeId
));
407 static U
* dynamic_page_cast (PageData
* p
)
409 return isA
<U
>(p
) ? static_cast<U
*>(p
) : nullptr;
413 static U
const * dynamic_page_cast (PageData
const * p
)
415 return isA
<U
>(p
) ? static_cast<U
const *>(p
) : nullptr;
419 bool construct (rtl::Reference
< PageData::Allocator
> const & rxAllocator
)
421 if (!m_xPage
&& rxAllocator
.is())
423 std::shared_ptr
<PageData
> tmp (rxAllocator
->construct
<T
>(), PageData::Deallocate(rxAllocator
));
426 return bool(m_xPage
);
429 explicit PageHolderObject (std::shared_ptr
<PageData
> xPage
= std::shared_ptr
<PageData
>())
430 : m_xPage (std::move(xPage
))
433 void swap (PageHolderObject
<T
> & rhs
)
435 m_xPage
.swap (rhs
.m_xPage
);
438 PageHolderObject (PageHolderObject
<T
> const & rhs
)
439 : m_xPage (rhs
.m_xPage
)
442 PageHolderObject
<T
> & operator= (PageHolderObject
<T
> const & rhs
)
444 PageHolderObject
<T
> tmp (rhs
);
451 return bool(m_xPage
);
454 std::shared_ptr
<PageData
> & get() { return m_xPage
; }
455 std::shared_ptr
<PageData
> const & get() const { return m_xPage
; }
459 T
* pImpl
= dynamic_page_cast
<T
>(m_xPage
.get());
460 OSL_PRECOND(pImpl
!= nullptr, "store::PageHolder<T>::operator*(): Null pointer");
464 T
const * operator->() const
466 T
const * pImpl
= dynamic_page_cast
<T
>(m_xPage
.get());
467 OSL_PRECOND(pImpl
!= nullptr, "store::PageHolder<T>::operator*(): Null pointer");
473 T
* pImpl
= dynamic_page_cast
<T
>(m_xPage
.get());
474 OSL_PRECOND(pImpl
!= nullptr, "store::PageHolder<T>::operator*(): Null pointer");
478 T
const & operator*() const
480 T
const * pImpl
= dynamic_page_cast
<T
>(m_xPage
.get());
481 OSL_PRECOND(pImpl
!= nullptr, "store::PageHolder<T>::operator*(): Null pointer");
485 static storeError
guard (std::shared_ptr
<PageData
> const & rxPage
, sal_uInt32 nAddr
)
487 PageData
* pHead
= rxPage
.get();
489 return store_E_InvalidAccess
;
492 T
* pImpl
= dynamic_page_cast
<T
>(pHead
);
493 OSL_PRECOND(pImpl
!= nullptr, "store::PageHolder<T>::guard(): Null pointer");
499 static storeError
verify (std::shared_ptr
<PageData
> const & rxPage
, sal_uInt32 nAddr
)
501 PageData
const * pHead
= rxPage
.get();
503 return store_E_InvalidAccess
;
505 storeError eErrCode
= pHead
->verify(nAddr
);
506 if (eErrCode
!= store_E_None
)
509 T
const * pImpl
= dynamic_page_cast
<T
>(pHead
);
511 return store_E_WrongVersion
;
513 return pImpl
->verify();
517 class OStorePageObject
519 typedef PageData page
;
524 static void * operator new (size_t n
)
526 return std::malloc(sal_uInt32(n
));
528 static void operator delete (void * p
)
535 inline bool dirty() const;
541 inline sal_uInt32
location() const;
546 std::shared_ptr
<PageData
> m_xPage
;
551 explicit OStorePageObject (std::shared_ptr
<PageData
> rxPage
)
552 : m_xPage (std::move(rxPage
)), m_bDirty (false)
557 virtual ~OStorePageObject();
561 PageHolderObject
<U
> makeHolder() const
563 return PageHolderObject
<U
>(m_xPage
);
567 storeError
construct (rtl::Reference
< PageData::Allocator
> const & rxAllocator
)
569 if (!rxAllocator
.is())
570 return store_E_InvalidAccess
;
572 std::shared_ptr
<PageData
> tmp (rxAllocator
->construct
<U
>(), PageData::Deallocate(rxAllocator
));
574 return store_E_OutOfMemory
;
580 std::shared_ptr
<PageData
> & get() { return m_xPage
; }
582 virtual storeError
guard (sal_uInt32 nAddr
) = 0;
583 virtual storeError
verify (sal_uInt32 nAddr
) const = 0;
586 inline bool OStorePageObject::dirty() const
591 inline void OStorePageObject::clean()
596 inline void OStorePageObject::touch()
601 inline sal_uInt32
OStorePageObject::location() const
603 return m_xPage
->location();
608 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */