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 #include "sal/config.h"
22 #include "boost/static_assert.hpp"
24 #include "storbios.hxx"
26 #include "sal/types.h"
27 #include "sal/macros.h"
29 #include "rtl/alloc.h"
30 #include "rtl/ref.hxx"
32 #include "osl/diagnose.h"
33 #include "osl/mutex.hxx"
35 #include "store/types.h"
37 #include "lockbyte.hxx"
38 #include "storcach.hxx"
40 using namespace store
;
42 /*========================================================================
46 *======================================================================*/
47 #define STORE_MAGIC_SUPERBLOCK sal_uInt32(0x484D5343)
49 struct OStoreSuperBlock
51 typedef OStorePageGuard G
;
52 typedef OStorePageDescriptor D
;
53 typedef OStorePageLink L
;
66 static const size_t theSize
= sizeof(G
) + sizeof(D
) + 2 * (sizeof(L
) + sizeof(sal_uInt32
));
70 explicit OStoreSuperBlock (sal_uInt16 nPageSize
)
71 : m_aGuard (STORE_MAGIC_SUPERBLOCK
),
72 m_aDescr (nPageSize
, nPageSize
, STORE_MINIMUM_PAGESIZE
),
73 m_nMarked (store::htonl(0)),
75 m_nUnused (store::htonl(0)),
79 OStoreSuperBlock (const OStoreSuperBlock
& rhs
)
80 : m_aGuard (rhs
.m_aGuard
),
81 m_aDescr (rhs
.m_aDescr
),
82 m_nMarked (rhs
.m_nMarked
),
83 m_aMarked (rhs
.m_aMarked
),
84 m_nUnused (rhs
.m_nUnused
),
85 m_aUnused (rhs
.m_aUnused
)
88 OStoreSuperBlock
& operator= (const OStoreSuperBlock
& rhs
)
90 m_aGuard
= rhs
.m_aGuard
;
91 m_aDescr
= rhs
.m_aDescr
;
92 m_nMarked
= rhs
.m_nMarked
;
93 m_aMarked
= rhs
.m_aMarked
;
94 m_nUnused
= rhs
.m_nUnused
;
95 m_aUnused
= rhs
.m_aUnused
;
101 sal_Bool
operator== (const OStoreSuperBlock
& rhs
) const
103 return ((m_aGuard
== rhs
.m_aGuard
) &&
104 (m_aDescr
== rhs
.m_aDescr
) &&
105 (m_nMarked
== rhs
.m_nMarked
) &&
106 (m_aMarked
== rhs
.m_aMarked
) &&
107 (m_nUnused
== rhs
.m_nUnused
) &&
108 (m_aUnused
== rhs
.m_aUnused
) );
111 /** unused(Count|Head|Insert|Remove|Reset).
113 sal_uInt32
unusedCount (void) const
115 return store::ntohl(m_nUnused
);
117 const L
& unusedHead (void) const
121 void unusedInsert (const L
& rLink
)
123 sal_uInt32 nUnused
= unusedCount();
124 m_nUnused
= store::htonl(nUnused
+ 1);
127 void unusedRemove (const L
& rLink
)
129 sal_uInt32 nUnused
= unusedCount();
130 m_nUnused
= store::htonl(nUnused
- 1);
133 void unusedReset (void)
135 m_nUnused
= store::htonl(0);
139 /** guard (external representation).
143 sal_uInt32 nCRC32
= 0;
144 nCRC32
= rtl_crc32 (nCRC32
, &m_aGuard
.m_nMagic
, sizeof(sal_uInt32
));
145 nCRC32
= rtl_crc32 (nCRC32
, &m_aDescr
, theSize
- sizeof(G
));
146 m_aGuard
.m_nCRC32
= store::htonl(nCRC32
);
149 /** verify (external representation).
151 storeError
verify() const
153 sal_uInt32 nMagic
= store::ntohl(m_aGuard
.m_nMagic
);
154 if (nMagic
!= STORE_MAGIC_SUPERBLOCK
)
155 return store_E_WrongFormat
;
157 sal_uInt32 nCRC32
= 0;
158 nCRC32
= rtl_crc32 (nCRC32
, &m_aGuard
.m_nMagic
, sizeof(sal_uInt32
));
159 nCRC32
= rtl_crc32 (nCRC32
, &m_aDescr
, theSize
- sizeof(G
));
160 if (m_aGuard
.m_nCRC32
!= store::htonl(nCRC32
))
161 return store_E_InvalidChecksum
;
167 /*========================================================================
169 * SuperBlockPage interface.
171 *======================================================================*/
175 struct SuperBlockPage
177 typedef OStoreSuperBlock SuperBlock
;
181 SuperBlock m_aSuperOne
;
182 SuperBlock m_aSuperTwo
;
186 static const size_t theSize
= 2 * SuperBlock::theSize
;
187 static const sal_uInt16 thePageSize
= theSize
;
188 BOOST_STATIC_ASSERT(STORE_MINIMUM_PAGESIZE
>= thePageSize
);
192 static void * operator new (size_t n
) SAL_THROW(())
194 return rtl_allocateMemory (sal::static_int_cast
<sal_Size
>(n
));
196 static void operator delete (void * p
) SAL_THROW(())
201 static void * operator new (SAL_UNUSED_PARAMETER
size_t, sal_uInt16 nPageSize
) SAL_THROW(())
203 return rtl_allocateZeroMemory (sal::static_int_cast
<sal_Size
>(nPageSize
));
205 static void operator delete (void * p
, SAL_UNUSED_PARAMETER sal_uInt16
) SAL_THROW(())
212 explicit SuperBlockPage (sal_uInt16 nPageSize
= thePageSize
)
213 : m_aSuperOne(nPageSize
),
214 m_aSuperTwo(nPageSize
)
219 storeError
save (OStorePageBIOS
& rBIOS
, sal_uInt32 nSize
= theSize
)
222 m_aSuperTwo
= m_aSuperOne
;
223 return rBIOS
.write (0, this, nSize
);
228 storeError
unusedHead (
229 OStorePageBIOS
& rBIOS
,
230 PageData
& rPageHead
);
232 storeError
unusedPop (
233 OStorePageBIOS
& rBIOS
,
234 PageData
const & rPageHead
);
236 storeError
unusedPush (
237 OStorePageBIOS
& rBIOS
,
240 /** verify (with repair).
242 storeError
verify (OStorePageBIOS
& rBIOS
);
247 /*========================================================================
249 * SuperBlockPage implementation.
251 *======================================================================*/
253 * unusedHead(): get freelist head (alloc page, step 1).
255 storeError
SuperBlockPage::unusedHead (OStorePageBIOS
& rBIOS
, PageData
& rPageHead
)
257 storeError eErrCode
= verify (rBIOS
);
258 if (eErrCode
!= store_E_None
)
261 // Check freelist head.
262 OStorePageLink
const aListHead (m_aSuperOne
.unusedHead());
263 if (aListHead
.location() == 0)
265 // Freelist empty, see SuperBlock::ctor().
266 rPageHead
.location (STORE_PAGE_NULL
);
271 eErrCode
= rBIOS
.read (aListHead
.location(), &rPageHead
, PageData::theSize
);
272 if (eErrCode
!= store_E_None
)
275 eErrCode
= rPageHead
.verify (aListHead
.location());
276 if (eErrCode
!= store_E_None
)
279 // Verify page is unused.
280 sal_uInt32
const nAddr
= rPageHead
.m_aUnused
.location();
281 OSL_POSTCOND(nAddr
!= STORE_PAGE_NULL
, "store::SuperBlock::unusedHead(): page not free");
282 if (nAddr
== STORE_PAGE_NULL
)
285 rPageHead
.location (STORE_PAGE_NULL
);
287 // Recovery: Reset freelist to empty.
288 m_aSuperOne
.unusedReset();
289 eErrCode
= save (rBIOS
);
295 * unusedPop(): pop freelist head (alloc page, step 2).
297 storeError
SuperBlockPage::unusedPop (OStorePageBIOS
& rBIOS
, PageData
const & rPageHead
)
299 sal_uInt32
const nAddr
= rPageHead
.m_aUnused
.location();
300 OSL_PRECOND(nAddr
!= STORE_PAGE_NULL
, "store::SuperBlock::unusedPop(): page not free");
301 if (nAddr
== STORE_PAGE_NULL
)
302 return store_E_CantSeek
;
304 // Pop from FreeList.
305 OStorePageLink
const aListHead (nAddr
);
306 m_aSuperOne
.unusedRemove (aListHead
);
311 * unusedPush(): push new freelist head.
313 storeError
SuperBlockPage::unusedPush (OStorePageBIOS
& rBIOS
, sal_uInt32 nAddr
)
315 storeError eErrCode
= verify (rBIOS
);
316 if (eErrCode
!= store_E_None
)
320 eErrCode
= rBIOS
.read (nAddr
, &aPageHead
, PageData::theSize
);
321 if (eErrCode
!= store_E_None
)
324 eErrCode
= aPageHead
.verify (nAddr
);
325 if (eErrCode
!= store_E_None
)
328 aPageHead
.m_aUnused
= m_aSuperOne
.unusedHead();
329 aPageHead
.guard (nAddr
);
331 eErrCode
= rBIOS
.write (nAddr
, &aPageHead
, PageData::theSize
);
332 if (eErrCode
!= store_E_None
)
335 OStorePageLink
const aListHead (nAddr
);
336 m_aSuperOne
.unusedInsert(aListHead
);
341 * verify (with repair).
343 storeError
SuperBlockPage::verify (OStorePageBIOS
& rBIOS
)
346 storeError eErrCode
= m_aSuperOne
.verify();
347 if (eErrCode
== store_E_None
)
349 // Ok. Verify 2nd copy.
350 eErrCode
= m_aSuperTwo
.verify();
351 if (eErrCode
== store_E_None
)
353 // Ok. Ensure identical copies (1st copy wins).
354 if (!(m_aSuperOne
== m_aSuperTwo
))
356 // Different. Replace 2nd copy with 1st copy.
357 m_aSuperTwo
= m_aSuperOne
;
360 if (rBIOS
.isWriteable())
361 eErrCode
= rBIOS
.write (0, this, theSize
);
363 eErrCode
= store_E_None
;
368 // Failure. Replace 2nd copy with 1st copy.
369 m_aSuperTwo
= m_aSuperOne
;
372 if (rBIOS
.isWriteable())
373 eErrCode
= rBIOS
.write (0, this, theSize
);
375 eErrCode
= store_E_None
;
380 // Failure. Verify 2nd copy.
381 eErrCode
= m_aSuperTwo
.verify();
382 if (eErrCode
== store_E_None
)
384 // Ok. Replace 1st copy with 2nd copy.
385 m_aSuperOne
= m_aSuperTwo
;
388 if (rBIOS
.isWriteable())
389 eErrCode
= rBIOS
.write (0, this, theSize
);
391 eErrCode
= store_E_None
;
396 OSL_TRACE("OStoreSuperBlockPage::verify(): double failure.");
404 /*========================================================================
406 * OStorePageBIOS::Ace implementation.
408 *======================================================================*/
409 OStorePageBIOS::Ace::Ace()
410 : m_next (this), m_prev (this), m_addr (STORE_PAGE_NULL
), m_used (0)
413 OStorePageBIOS::Ace::~Ace()
415 m_next
->m_prev
= m_prev
, m_prev
->m_next
= m_next
;
419 SAL_CALL
OStorePageBIOS::Ace::constructor (
420 void * obj
, SAL_UNUSED_PARAMETER
void * /* arg */)
422 Ace
* ace
= static_cast<Ace
*>(obj
);
423 ace
->m_next
= ace
->m_prev
= ace
;
427 OStorePageBIOS::Ace
*
428 OStorePageBIOS::Ace::find (OStorePageBIOS::Ace
* head
, sal_uInt32 addr
)
430 OStorePageBIOS::Ace
* entry
;
431 for (entry
= head
->m_next
; entry
!= head
; entry
= entry
->m_next
)
433 if (entry
->m_addr
>= addr
)
440 OStorePageBIOS::Ace::insert (OStorePageBIOS::Ace
* head
, OStorePageBIOS::Ace
* entry
)
442 // insert entry at queue tail (before head).
443 entry
->m_next
= head
;
444 entry
->m_prev
= head
->m_prev
;
445 head
->m_prev
= entry
;
446 entry
->m_prev
->m_next
= entry
;
449 /*========================================================================
451 * OStorePageBIOS::AceCache interface.
453 *======================================================================*/
457 class OStorePageBIOS::AceCache
459 rtl_cache_type
* m_ace_cache
;
462 static AceCache
& get();
464 OStorePageBIOS::Ace
*
465 create (sal_uInt32 addr
, sal_uInt32 used
= 1);
468 destroy (OStorePageBIOS::Ace
* ace
);
477 /*========================================================================
479 * OStorePageBIOS::AceCache implementation.
481 *======================================================================*/
482 extern "C" typedef int (SAL_CALL
* ace_constructor_type
)(void*,void*);
484 OStorePageBIOS::AceCache
&
485 OStorePageBIOS::AceCache::get()
487 static AceCache g_ace_cache
;
491 OStorePageBIOS::AceCache::AceCache()
493 m_ace_cache
= rtl_cache_create (
495 sizeof (OStorePageBIOS::Ace
),
497 reinterpret_cast<ace_constructor_type
>( OStorePageBIOS::Ace::constructor
),
501 0, // default source,
506 OStorePageBIOS::AceCache::~AceCache()
508 rtl_cache_destroy (m_ace_cache
), m_ace_cache
= 0;
511 OStorePageBIOS::Ace
*
512 OStorePageBIOS::AceCache::create (sal_uInt32 addr
, sal_uInt32 used
)
514 Ace
* ace
= static_cast<Ace
*>(rtl_cache_alloc (m_ace_cache
));
517 // verify invariant state.
518 OSL_ASSERT((ace
->m_next
== ace
) && (ace
->m_prev
== ace
));
528 OStorePageBIOS::AceCache::destroy (OStorePageBIOS::Ace
* ace
)
532 // remove from queue (if any).
533 ace
->m_next
->m_prev
= ace
->m_prev
, ace
->m_prev
->m_next
= ace
->m_next
;
535 // restore invariant state.
536 ace
->m_next
= ace
->m_prev
= ace
;
539 rtl_cache_free (m_ace_cache
, ace
);
543 /*========================================================================
545 * OStorePageBIOS implementation.
547 *======================================================================*/
551 OStorePageBIOS::OStorePageBIOS (void)
552 : m_xLockBytes (NULL
),
561 OStorePageBIOS::~OStorePageBIOS (void)
570 storeError
OStorePageBIOS::initialize (
571 ILockBytes
* pLockBytes
,
572 storeAccessMode eAccessMode
,
573 sal_uInt16
& rnPageSize
)
575 // Acquire exclusive access.
576 osl::MutexGuard
aGuard (m_aMutex
);
579 storeError eErrCode
= initialize_Impl (pLockBytes
, eAccessMode
, rnPageSize
);
580 if (eErrCode
!= store_E_None
)
590 * Internal: Precond: exclusive access.
592 storeError
OStorePageBIOS::initialize_Impl (
593 ILockBytes
* pLockBytes
,
594 storeAccessMode eAccessMode
,
595 sal_uInt16
& rnPageSize
)
601 m_xLockBytes
= pLockBytes
;
602 if (!m_xLockBytes
.is())
603 return store_E_InvalidParameter
;
604 m_bWriteable
= (eAccessMode
!= store_AccessReadOnly
);
606 // Check access mode.
607 storeError eErrCode
= store_E_None
;
608 if (eAccessMode
!= store_AccessCreate
)
610 // Load SuperBlock page.
611 if ((m_pSuper
= new SuperBlockPage()) == 0)
612 return store_E_OutOfMemory
;
614 eErrCode
= read (0, m_pSuper
, SuperBlockPage::theSize
);
615 if (eErrCode
== store_E_None
)
617 // Verify SuperBlock page (with repair).
618 eErrCode
= m_pSuper
->verify (*this);
623 // Truncate to zero length.
624 eErrCode
= m_xLockBytes
->setSize(0);
625 if (eErrCode
!= store_E_None
)
628 // Mark as not existing.
629 eErrCode
= store_E_NotExists
;
632 if (eErrCode
!= store_E_None
)
635 if (eErrCode
!= store_E_NotExists
)
639 if (eAccessMode
== store_AccessReadOnly
)
640 return store_E_NotExists
;
641 if (eAccessMode
== store_AccessReadWrite
)
642 return store_E_NotExists
;
645 if ((STORE_MINIMUM_PAGESIZE
> rnPageSize
) || (rnPageSize
> STORE_MAXIMUM_PAGESIZE
))
646 return store_E_InvalidParameter
;
647 rnPageSize
= ((rnPageSize
+ STORE_MINIMUM_PAGESIZE
- 1) & ~(STORE_MINIMUM_PAGESIZE
- 1));
649 // Create initial page (w/ SuperBlock).
650 if ((m_pSuper
= new(rnPageSize
) SuperBlockPage(rnPageSize
)) == 0)
651 return store_E_OutOfMemory
;
652 eErrCode
= m_pSuper
->save (*this, rnPageSize
);
654 if (eErrCode
== store_E_None
)
657 rnPageSize
= store::ntohs(m_pSuper
->m_aSuperOne
.m_aDescr
.m_nSize
);
659 // Create page allocator.
660 eErrCode
= m_xLockBytes
->initialize (m_xAllocator
, rnPageSize
);
661 if (eErrCode
!= store_E_None
)
664 // Create page cache.
665 eErrCode
= PageCache_createInstance (m_xCache
, rnPageSize
);
672 * Internal: Precond: exclusive access.
674 void OStorePageBIOS::cleanup_Impl()
676 // Check referer count.
677 if (m_ace_head
.m_used
> 0)
679 // Report remaining referer count.
680 OSL_TRACE("store::PageBIOS::cleanup_Impl(): referer count: %d", m_ace_head
.m_used
);
681 for (Ace
* ace
= m_ace_head
.m_next
; ace
!= &m_ace_head
; ace
= m_ace_head
.m_next
)
683 m_ace_head
.m_used
-= ace
->m_used
;
684 AceCache::get().destroy (ace
);
686 OSL_ENSURE(m_ace_head
.m_used
== 0, "store::PageBIOS::cleanup_Impl(): logic error");
689 // Release SuperBlock page.
690 delete m_pSuper
, m_pSuper
= 0;
692 // Release PageCache.
695 // Release PageAllocator.
696 m_xAllocator
.clear();
698 // Release LockBytes.
699 m_xLockBytes
.clear();
704 * Low Level: Precond: initialized, exclusive access.
706 storeError
OStorePageBIOS::read (
707 sal_uInt32 nAddr
, void *pData
, sal_uInt32 nSize
)
710 if (!m_xLockBytes
.is())
711 return store_E_InvalidAccess
;
714 return m_xLockBytes
->readAt (nAddr
, pData
, nSize
);
719 * Low Level: Precond: initialized, writeable, exclusive access.
721 storeError
OStorePageBIOS::write (
722 sal_uInt32 nAddr
, const void *pData
, sal_uInt32 nSize
)
725 if (!m_xLockBytes
.is())
726 return store_E_InvalidAccess
;
728 return store_E_AccessViolation
;
731 return m_xLockBytes
->writeAt (nAddr
, pData
, nSize
);
736 * Precond: initialized.
738 storeError
OStorePageBIOS::acquirePage (
739 const OStorePageDescriptor
& rDescr
, storeAccessMode eMode
)
741 // Acquire exclusive access.
742 osl::MutexGuard
aGuard (m_aMutex
);
745 if (!m_xLockBytes
.is())
746 return store_E_InvalidAccess
;
748 // Check access mode.
749 if (!(m_bWriteable
|| (eMode
== store_AccessReadOnly
)))
750 return store_E_AccessViolation
;
752 // Find access control list entry.
753 Ace
* ace
= Ace::find (&m_ace_head
, rDescr
.m_nAddr
);
754 if (ace
->m_addr
== rDescr
.m_nAddr
)
756 // Acquire existing entry (with ShareDenyWrite).
757 if (eMode
== store_AccessReadOnly
)
760 return store_E_AccessViolation
;
765 Ace
* entry
= AceCache::get().create (rDescr
.m_nAddr
, 1);
767 return store_E_OutOfMemory
;
768 Ace::insert (ace
, entry
);
771 // Increment total referer count and finish.
772 m_ace_head
.m_used
+= 1;
778 * Precond: initialized.
780 storeError
OStorePageBIOS::releasePage (const OStorePageDescriptor
& rDescr
)
782 // Acquire exclusive access.
783 osl::MutexGuard
aGuard (m_aMutex
);
786 if (!m_xLockBytes
.is())
787 return store_E_InvalidAccess
;
789 // Find access control list entry.
790 Ace
* ace
= Ace::find (&m_ace_head
, rDescr
.m_nAddr
);
791 if (ace
->m_addr
!= rDescr
.m_nAddr
)
792 return store_E_NotExists
;
794 // Release existing entry.
798 AceCache::get().destroy (ace
);
800 // Decrement total referer count and finish.
801 m_ace_head
.m_used
-= 1;
809 sal_uInt32
OStorePageBIOS::getRefererCount (void)
811 // Acquire exclusive access.
812 osl::MutexGuard
aGuard (m_aMutex
);
814 // Obtain total referer count.
815 return m_ace_head
.m_used
;
820 * Precond: initialized, writeable.
822 storeError
OStorePageBIOS::allocate (
823 OStorePageObject
& rPage
, Allocation eAlloc
)
825 // Acquire exclusive access.
826 osl::MutexGuard
aGuard (m_aMutex
);
829 if (!m_xLockBytes
.is())
830 return store_E_InvalidAccess
;
832 return store_E_AccessViolation
;
834 // Check allocation type.
835 storeError eErrCode
= store_E_None
;
836 if (eAlloc
!= ALLOCATE_EOF
)
838 // Try freelist head.
840 eErrCode
= m_pSuper
->unusedHead (*this, aPageHead
);
841 if (eErrCode
!= store_E_None
)
844 sal_uInt32
const nAddr
= aPageHead
.location();
845 if (nAddr
!= STORE_PAGE_NULL
)
848 eErrCode
= saveObjectAt_Impl (rPage
, nAddr
);
849 if (eErrCode
!= store_E_None
)
852 // Pop freelist head and finish.
853 return m_pSuper
->unusedPop (*this, aPageHead
);
857 // Allocate from EOF. Determine current size.
858 sal_uInt32 nSize
= STORE_PAGE_NULL
;
859 eErrCode
= m_xLockBytes
->getSize (nSize
);
860 if (eErrCode
!= store_E_None
)
863 // Save page at current EOF.
864 return saveObjectAt_Impl (rPage
, nSize
);
869 * Precond: initialized, writeable.
871 storeError
OStorePageBIOS::free (sal_uInt32 nAddr
)
873 // Acquire exclusive access.
874 osl::MutexGuard
aGuard (m_aMutex
);
877 if (!m_xLockBytes
.is())
878 return store_E_InvalidAccess
;
880 return store_E_AccessViolation
;
883 (void) m_xCache
->removePageAt (nAddr
);
885 // Push onto freelist.
886 return m_pSuper
->unusedPush (*this, nAddr
);
891 * Precond: initialized, readable.
893 storeError
OStorePageBIOS::loadObjectAt (OStorePageObject
& rPage
, sal_uInt32 nAddr
)
895 // Acquire exclusive access.
896 osl::MutexGuard
aGuard (m_aMutex
);
899 if (!m_xLockBytes
.is())
900 return store_E_InvalidAccess
;
902 return loadObjectAt_Impl (rPage
, nAddr
);
907 * Internal: Precond: initialized, readable, exclusive access.
909 storeError
OStorePageBIOS::loadObjectAt_Impl (OStorePageObject
& rPage
, sal_uInt32 nAddr
)
911 storeError eErrCode
= m_xCache
->lookupPageAt (rPage
.get(), nAddr
);
912 if (eErrCode
!= store_E_NotExists
)
916 eErrCode
= m_xLockBytes
->readPageAt (rPage
.get(), nAddr
);
917 if (eErrCode
!= store_E_None
)
921 eErrCode
= rPage
.verify (nAddr
);
922 if (eErrCode
!= store_E_None
)
925 // Mark page as clean.
929 return m_xCache
->insertPageAt (rPage
.get(), nAddr
);
934 * Precond: initialized, writeable.
936 storeError
OStorePageBIOS::saveObjectAt (OStorePageObject
& rPage
, sal_uInt32 nAddr
)
938 // Acquire exclusive access.
939 osl::MutexGuard
aGuard (m_aMutex
);
942 if (!m_xLockBytes
.is())
943 return store_E_InvalidAccess
;
945 return store_E_AccessViolation
;
948 return saveObjectAt_Impl (rPage
, nAddr
);
953 * Internal: Precond: initialized, writeable, exclusive access.
955 storeError
OStorePageBIOS::saveObjectAt_Impl (OStorePageObject
& rPage
, sal_uInt32 nAddr
)
957 // Guard page (incl. set location).
958 storeError eErrCode
= rPage
.guard (nAddr
);
959 if (eErrCode
!= store_E_None
)
963 eErrCode
= m_xLockBytes
->writePageAt(rPage
.get(), nAddr
);
964 if (eErrCode
!= store_E_None
)
967 // Mark page as clean.
971 return m_xCache
->updatePageAt (rPage
.get(), nAddr
);
978 storeError
OStorePageBIOS::close()
980 // Acquire exclusive access.
981 osl::MutexGuard
aGuard (m_aMutex
);
992 * Precond: initialized.
994 storeError
OStorePageBIOS::flush (void)
996 // Acquire exclusive access.
997 osl::MutexGuard
aGuard (m_aMutex
);
1000 if (!m_xLockBytes
.is())
1001 return store_E_InvalidAccess
;
1003 // Flush LockBytes and finish.
1004 return m_xLockBytes
->flush();
1009 * Precond: initialized.
1011 storeError
OStorePageBIOS::size (sal_uInt32
&rnSize
)
1013 // Acquire exclusive access.
1014 osl::MutexGuard
aGuard (m_aMutex
);
1016 // Initialize [out] param.
1020 if (!m_xLockBytes
.is())
1021 return store_E_InvalidAccess
;
1023 // Obtain LockBytes size.
1024 return m_xLockBytes
->getSize (rnSize
);
1029 * Precond: initialized.
1031 storeError
OStorePageBIOS::scanBegin (
1032 ScanContext
&rCtx
, sal_uInt32 nMagic
)
1034 // Acquire exclusive access.
1035 osl::MutexGuard
aGuard (m_aMutex
);
1037 // Initialize [out] param.
1038 rCtx
.m_aDescr
= OStorePageDescriptor(0, 0, 0);
1040 rCtx
.m_nMagic
= nMagic
;
1043 if (!m_xLockBytes
.is())
1044 return store_E_InvalidAccess
;
1046 // Check SuperBlock page.
1047 storeError eErrCode
= m_pSuper
->verify (*this);
1048 if (eErrCode
!= store_E_None
)
1050 // Damaged. Determine page size (NYI).
1051 OSL_TRACE ("OStorePageBIOS::scanBegin(): damaged.\n");
1055 // Setup Context descriptor.
1056 rCtx
.m_aDescr
= m_pSuper
->m_aSuperOne
.m_aDescr
;
1057 rCtx
.m_aDescr
.m_nSize
= store::ntohs(rCtx
.m_aDescr
.m_nSize
);
1058 rCtx
.m_aDescr
.m_nAddr
= rCtx
.m_aDescr
.m_nSize
;
1060 // Setup Context size.
1061 eErrCode
= size (rCtx
.m_nSize
);
1062 if (eErrCode
!= store_E_None
)
1063 rCtx
.m_nSize
= ((sal_uInt32
)(~0));
1066 return store_E_None
;
1071 * Precond: initialized.
1073 storeError
OStorePageBIOS::scanNext (
1074 ScanContext
&rCtx
, OStorePageObject
&rPage
)
1076 // Acquire exclusive access.
1077 osl::MutexGuard
aGuard (m_aMutex
);
1080 if (!m_xLockBytes
.is())
1081 return store_E_InvalidAccess
;
1087 while (rCtx
.isValid())
1089 // Assign next location.
1090 sal_uInt32 nAddr
= rCtx
.m_aDescr
.m_nAddr
;
1091 rCtx
.m_aDescr
.m_nAddr
+= rCtx
.m_aDescr
.m_nSize
;
1094 storeError eErrCode
= read (nAddr
, &aPageHead
, PageData::theSize
);
1095 if (eErrCode
!= store_E_None
)
1099 eErrCode
= aPageHead
.verify (nAddr
);
1100 if (eErrCode
!= store_E_None
)
1103 // Check PageHead Magic number.
1104 if (aPageHead
.m_aGuard
.m_nMagic
!= rCtx
.m_nMagic
)
1107 // Check PageHead Unused link.
1108 if (aPageHead
.m_aUnused
.m_nAddr
!= STORE_PAGE_NULL
)
1112 eErrCode
= loadObjectAt_Impl (rPage
, nAddr
);
1113 if (eErrCode
!= store_E_None
)
1117 return store_E_None
;
1121 return store_E_CantSeek
;
1124 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */