1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #include "storbios.hxx"
32 #include "sal/types.h"
33 #include "sal/macros.h"
35 #include "rtl/alloc.h"
36 #include "rtl/ref.hxx"
38 #include "osl/diagnose.h"
39 #include "osl/mutex.hxx"
41 #include "store/types.h"
43 #include "lockbyte.hxx"
44 #include "storcach.hxx"
46 using namespace store
;
48 /*========================================================================
52 *======================================================================*/
53 #define STORE_MAGIC_SUPERBLOCK sal_uInt32(0x484D5343)
55 struct OStoreSuperBlock
57 typedef OStorePageGuard G
;
58 typedef OStorePageDescriptor D
;
59 typedef OStorePageLink L
;
72 static const size_t theSize
= sizeof(G
) + sizeof(D
) + 2 * (sizeof(L
) + sizeof(sal_uInt32
));
76 explicit OStoreSuperBlock (sal_uInt16 nPageSize
)
77 : m_aGuard (STORE_MAGIC_SUPERBLOCK
),
78 m_aDescr (nPageSize
, nPageSize
, STORE_MINIMUM_PAGESIZE
),
79 m_nMarked (store::htonl(0)),
81 m_nUnused (store::htonl(0)),
85 OStoreSuperBlock (const OStoreSuperBlock
& rhs
)
86 : m_aGuard (rhs
.m_aGuard
),
87 m_aDescr (rhs
.m_aDescr
),
88 m_nMarked (rhs
.m_nMarked
),
89 m_aMarked (rhs
.m_aMarked
),
90 m_nUnused (rhs
.m_nUnused
),
91 m_aUnused (rhs
.m_aUnused
)
94 OStoreSuperBlock
& operator= (const OStoreSuperBlock
& rhs
)
96 m_aGuard
= rhs
.m_aGuard
;
97 m_aDescr
= rhs
.m_aDescr
;
98 m_nMarked
= rhs
.m_nMarked
;
99 m_aMarked
= rhs
.m_aMarked
;
100 m_nUnused
= rhs
.m_nUnused
;
101 m_aUnused
= rhs
.m_aUnused
;
107 sal_Bool
operator== (const OStoreSuperBlock
& rhs
) const
109 return ((m_aGuard
== rhs
.m_aGuard
) &&
110 (m_aDescr
== rhs
.m_aDescr
) &&
111 (m_nMarked
== rhs
.m_nMarked
) &&
112 (m_aMarked
== rhs
.m_aMarked
) &&
113 (m_nUnused
== rhs
.m_nUnused
) &&
114 (m_aUnused
== rhs
.m_aUnused
) );
117 /** unused(Count|Head|Insert|Remove|Reset).
119 sal_uInt32
unusedCount (void) const
121 return store::ntohl(m_nUnused
);
123 const L
& unusedHead (void) const
127 void unusedInsert (const L
& rLink
)
129 sal_uInt32 nUnused
= unusedCount();
130 m_nUnused
= store::htonl(nUnused
+ 1);
133 void unusedRemove (const L
& rLink
)
135 sal_uInt32 nUnused
= unusedCount();
136 m_nUnused
= store::htonl(nUnused
- 1);
139 void unusedReset (void)
141 m_nUnused
= store::htonl(0);
145 /** guard (external representation).
149 sal_uInt32 nCRC32
= 0;
150 nCRC32
= rtl_crc32 (nCRC32
, &m_aGuard
.m_nMagic
, sizeof(sal_uInt32
));
151 nCRC32
= rtl_crc32 (nCRC32
, &m_aDescr
, theSize
- sizeof(G
));
152 m_aGuard
.m_nCRC32
= store::htonl(nCRC32
);
155 /** verify (external representation).
157 storeError
verify() const
159 sal_uInt32 nMagic
= store::ntohl(m_aGuard
.m_nMagic
);
160 if (nMagic
!= STORE_MAGIC_SUPERBLOCK
)
161 return store_E_WrongFormat
;
163 sal_uInt32 nCRC32
= 0;
164 nCRC32
= rtl_crc32 (nCRC32
, &m_aGuard
.m_nMagic
, sizeof(sal_uInt32
));
165 nCRC32
= rtl_crc32 (nCRC32
, &m_aDescr
, theSize
- sizeof(G
));
166 if (m_aGuard
.m_nCRC32
!= store::htonl(nCRC32
))
167 return store_E_InvalidChecksum
;
173 /*========================================================================
175 * SuperBlockPage interface.
177 *======================================================================*/
181 struct SuperBlockPage
183 typedef OStoreSuperBlock SuperBlock
;
187 SuperBlock m_aSuperOne
;
188 SuperBlock m_aSuperTwo
;
192 static const size_t theSize
= 2 * SuperBlock::theSize
;
193 static const sal_uInt16 thePageSize
= theSize
;
194 STORE_STATIC_ASSERT(STORE_MINIMUM_PAGESIZE
>= thePageSize
);
198 static void * operator new (size_t n
) SAL_THROW(())
200 return rtl_allocateMemory (sal::static_int_cast
<sal_Size
>(n
));
202 static void operator delete (void * p
) SAL_THROW(())
207 static void * operator new (SAL_UNUSED_PARAMETER
size_t, sal_uInt16 nPageSize
) SAL_THROW(())
209 return rtl_allocateZeroMemory (sal::static_int_cast
<sal_Size
>(nPageSize
));
211 static void operator delete (void * p
, SAL_UNUSED_PARAMETER sal_uInt16
) SAL_THROW(())
218 explicit SuperBlockPage (sal_uInt16 nPageSize
= thePageSize
)
219 : m_aSuperOne(nPageSize
),
220 m_aSuperTwo(nPageSize
)
225 storeError
save (OStorePageBIOS
& rBIOS
, sal_uInt32 nSize
= theSize
)
228 m_aSuperTwo
= m_aSuperOne
;
229 return rBIOS
.write (0, this, nSize
);
234 storeError
unusedHead (
235 OStorePageBIOS
& rBIOS
,
236 PageData
& rPageHead
);
238 storeError
unusedPop (
239 OStorePageBIOS
& rBIOS
,
240 PageData
const & rPageHead
);
242 storeError
unusedPush (
243 OStorePageBIOS
& rBIOS
,
246 /** verify (with repair).
248 storeError
verify (OStorePageBIOS
& rBIOS
);
253 /*========================================================================
255 * SuperBlockPage implementation.
257 *======================================================================*/
259 * unusedHead(): get freelist head (alloc page, step 1).
261 storeError
SuperBlockPage::unusedHead (OStorePageBIOS
& rBIOS
, PageData
& rPageHead
)
263 storeError eErrCode
= verify (rBIOS
);
264 if (eErrCode
!= store_E_None
)
267 // Check freelist head.
268 OStorePageLink
const aListHead (m_aSuperOne
.unusedHead());
269 if (aListHead
.location() == 0)
271 // Freelist empty, see SuperBlock::ctor().
272 rPageHead
.location (STORE_PAGE_NULL
);
277 eErrCode
= rBIOS
.read (aListHead
.location(), &rPageHead
, PageData::theSize
);
278 if (eErrCode
!= store_E_None
)
281 eErrCode
= rPageHead
.verify (aListHead
.location());
282 if (eErrCode
!= store_E_None
)
285 // Verify page is unused.
286 sal_uInt32
const nAddr
= rPageHead
.m_aUnused
.location();
287 OSL_POSTCOND(nAddr
!= STORE_PAGE_NULL
, "store::SuperBlock::unusedHead(): page not free");
288 if (nAddr
== STORE_PAGE_NULL
)
291 rPageHead
.location (STORE_PAGE_NULL
);
293 // Recovery: Reset freelist to empty.
294 m_aSuperOne
.unusedReset();
295 eErrCode
= save (rBIOS
);
301 * unusedPop(): pop freelist head (alloc page, step 2).
303 storeError
SuperBlockPage::unusedPop (OStorePageBIOS
& rBIOS
, PageData
const & rPageHead
)
305 sal_uInt32
const nAddr
= rPageHead
.m_aUnused
.location();
306 OSL_PRECOND(nAddr
!= STORE_PAGE_NULL
, "store::SuperBlock::unusedPop(): page not free");
307 if (nAddr
== STORE_PAGE_NULL
)
308 return store_E_CantSeek
;
310 // Pop from FreeList.
311 OStorePageLink
const aListHead (nAddr
);
312 m_aSuperOne
.unusedRemove (aListHead
);
317 * unusedPush(): push new freelist head.
319 storeError
SuperBlockPage::unusedPush (OStorePageBIOS
& rBIOS
, sal_uInt32 nAddr
)
321 storeError eErrCode
= verify (rBIOS
);
322 if (eErrCode
!= store_E_None
)
326 eErrCode
= rBIOS
.read (nAddr
, &aPageHead
, PageData::theSize
);
327 if (eErrCode
!= store_E_None
)
330 eErrCode
= aPageHead
.verify (nAddr
);
331 if (eErrCode
!= store_E_None
)
334 aPageHead
.m_aUnused
= m_aSuperOne
.unusedHead();
335 aPageHead
.guard (nAddr
);
337 eErrCode
= rBIOS
.write (nAddr
, &aPageHead
, PageData::theSize
);
338 if (eErrCode
!= store_E_None
)
341 OStorePageLink
const aListHead (nAddr
);
342 m_aSuperOne
.unusedInsert(aListHead
);
347 * verify (with repair).
349 storeError
SuperBlockPage::verify (OStorePageBIOS
& rBIOS
)
352 storeError eErrCode
= m_aSuperOne
.verify();
353 if (eErrCode
== store_E_None
)
355 // Ok. Verify 2nd copy.
356 eErrCode
= m_aSuperTwo
.verify();
357 if (eErrCode
== store_E_None
)
359 // Ok. Ensure identical copies (1st copy wins).
360 if (!(m_aSuperOne
== m_aSuperTwo
))
362 // Different. Replace 2nd copy with 1st copy.
363 m_aSuperTwo
= m_aSuperOne
;
366 if (rBIOS
.isWriteable())
367 eErrCode
= rBIOS
.write (0, this, theSize
);
369 eErrCode
= store_E_None
;
374 // Failure. Replace 2nd copy with 1st copy.
375 m_aSuperTwo
= m_aSuperOne
;
378 if (rBIOS
.isWriteable())
379 eErrCode
= rBIOS
.write (0, this, theSize
);
381 eErrCode
= store_E_None
;
386 // Failure. Verify 2nd copy.
387 eErrCode
= m_aSuperTwo
.verify();
388 if (eErrCode
== store_E_None
)
390 // Ok. Replace 1st copy with 2nd copy.
391 m_aSuperOne
= m_aSuperTwo
;
394 if (rBIOS
.isWriteable())
395 eErrCode
= rBIOS
.write (0, this, theSize
);
397 eErrCode
= store_E_None
;
402 OSL_TRACE("OStoreSuperBlockPage::verify(): double failure.");
410 /*========================================================================
412 * OStorePageBIOS::Ace implementation.
414 *======================================================================*/
415 OStorePageBIOS::Ace::Ace()
416 : m_next (this), m_prev (this), m_addr (STORE_PAGE_NULL
), m_used (0)
419 OStorePageBIOS::Ace::~Ace()
421 m_next
->m_prev
= m_prev
, m_prev
->m_next
= m_next
;
425 SAL_CALL
OStorePageBIOS::Ace::constructor (
426 void * obj
, SAL_UNUSED_PARAMETER
void * /* arg */)
428 Ace
* ace
= static_cast<Ace
*>(obj
);
429 ace
->m_next
= ace
->m_prev
= ace
;
433 OStorePageBIOS::Ace
*
434 OStorePageBIOS::Ace::find (OStorePageBIOS::Ace
* head
, sal_uInt32 addr
)
436 OStorePageBIOS::Ace
* entry
;
437 for (entry
= head
->m_next
; entry
!= head
; entry
= entry
->m_next
)
439 if (entry
->m_addr
>= addr
)
446 OStorePageBIOS::Ace::insert (OStorePageBIOS::Ace
* head
, OStorePageBIOS::Ace
* entry
)
448 // insert entry at queue tail (before head).
449 entry
->m_next
= head
;
450 entry
->m_prev
= head
->m_prev
;
451 head
->m_prev
= entry
;
452 entry
->m_prev
->m_next
= entry
;
455 /*========================================================================
457 * OStorePageBIOS::AceCache interface.
459 *======================================================================*/
463 class OStorePageBIOS::AceCache
465 rtl_cache_type
* m_ace_cache
;
468 static AceCache
& get();
470 OStorePageBIOS::Ace
*
471 create (sal_uInt32 addr
, sal_uInt32 used
= 1);
474 destroy (OStorePageBIOS::Ace
* ace
);
483 /*========================================================================
485 * OStorePageBIOS::AceCache implementation.
487 *======================================================================*/
488 extern "C" typedef int (SAL_CALL
* ace_constructor_type
)(void*,void*);
490 OStorePageBIOS::AceCache
&
491 OStorePageBIOS::AceCache::get()
493 static AceCache g_ace_cache
;
497 OStorePageBIOS::AceCache::AceCache()
499 m_ace_cache
= rtl_cache_create (
501 sizeof (OStorePageBIOS::Ace
),
503 reinterpret_cast<ace_constructor_type
>( OStorePageBIOS::Ace::constructor
),
507 0, // default source,
512 OStorePageBIOS::AceCache::~AceCache()
514 rtl_cache_destroy (m_ace_cache
), m_ace_cache
= 0;
517 OStorePageBIOS::Ace
*
518 OStorePageBIOS::AceCache::create (sal_uInt32 addr
, sal_uInt32 used
)
520 Ace
* ace
= static_cast<Ace
*>(rtl_cache_alloc (m_ace_cache
));
523 // verify invariant state.
524 OSL_ASSERT((ace
->m_next
== ace
) && (ace
->m_prev
== ace
));
534 OStorePageBIOS::AceCache::destroy (OStorePageBIOS::Ace
* ace
)
538 // remove from queue (if any).
539 ace
->m_next
->m_prev
= ace
->m_prev
, ace
->m_prev
->m_next
= ace
->m_next
;
541 // restore invariant state.
542 ace
->m_next
= ace
->m_prev
= ace
;
545 rtl_cache_free (m_ace_cache
, ace
);
549 /*========================================================================
551 * OStorePageBIOS implementation.
553 *======================================================================*/
557 OStorePageBIOS::OStorePageBIOS (void)
558 : m_xLockBytes (NULL
),
567 OStorePageBIOS::~OStorePageBIOS (void)
576 storeError
OStorePageBIOS::initialize (
577 ILockBytes
* pLockBytes
,
578 storeAccessMode eAccessMode
,
579 sal_uInt16
& rnPageSize
)
581 // Acquire exclusive access.
582 osl::MutexGuard
aGuard (m_aMutex
);
585 storeError eErrCode
= initialize_Impl (pLockBytes
, eAccessMode
, rnPageSize
);
586 if (eErrCode
!= store_E_None
)
596 * Internal: Precond: exclusive access.
598 storeError
OStorePageBIOS::initialize_Impl (
599 ILockBytes
* pLockBytes
,
600 storeAccessMode eAccessMode
,
601 sal_uInt16
& rnPageSize
)
607 m_xLockBytes
= pLockBytes
;
608 if (!m_xLockBytes
.is())
609 return store_E_InvalidParameter
;
610 m_bWriteable
= (eAccessMode
!= store_AccessReadOnly
);
612 // Check access mode.
613 storeError eErrCode
= store_E_None
;
614 if (eAccessMode
!= store_AccessCreate
)
616 // Load SuperBlock page.
617 if ((m_pSuper
= new SuperBlockPage()) == 0)
618 return store_E_OutOfMemory
;
620 eErrCode
= read (0, m_pSuper
, SuperBlockPage::theSize
);
621 if (eErrCode
== store_E_None
)
623 // Verify SuperBlock page (with repair).
624 eErrCode
= m_pSuper
->verify (*this);
629 // Truncate to zero length.
630 eErrCode
= m_xLockBytes
->setSize(0);
631 if (eErrCode
!= store_E_None
)
634 // Mark as not existing.
635 eErrCode
= store_E_NotExists
;
638 if (eErrCode
!= store_E_None
)
641 if (eErrCode
!= store_E_NotExists
)
645 if (eAccessMode
== store_AccessReadOnly
)
646 return store_E_NotExists
;
647 if (eAccessMode
== store_AccessReadWrite
)
648 return store_E_NotExists
;
651 if ((STORE_MINIMUM_PAGESIZE
> rnPageSize
) || (rnPageSize
> STORE_MAXIMUM_PAGESIZE
))
652 return store_E_InvalidParameter
;
653 rnPageSize
= ((rnPageSize
+ STORE_MINIMUM_PAGESIZE
- 1) & ~(STORE_MINIMUM_PAGESIZE
- 1));
655 // Create initial page (w/ SuperBlock).
656 if ((m_pSuper
= new(rnPageSize
) SuperBlockPage(rnPageSize
)) == 0)
657 return store_E_OutOfMemory
;
658 eErrCode
= m_pSuper
->save (*this, rnPageSize
);
660 if (eErrCode
== store_E_None
)
663 rnPageSize
= store::ntohs(m_pSuper
->m_aSuperOne
.m_aDescr
.m_nSize
);
665 // Create page allocator.
666 eErrCode
= m_xLockBytes
->initialize (m_xAllocator
, rnPageSize
);
667 if (eErrCode
!= store_E_None
)
670 // Create page cache.
671 eErrCode
= PageCache_createInstance (m_xCache
, rnPageSize
);
678 * Internal: Precond: exclusive access.
680 void OStorePageBIOS::cleanup_Impl()
682 // Check referer count.
683 if (m_ace_head
.m_used
> 0)
685 // Report remaining referer count.
686 OSL_TRACE("store::PageBIOS::cleanup_Impl(): referer count: %d", m_ace_head
.m_used
);
687 for (Ace
* ace
= m_ace_head
.m_next
; ace
!= &m_ace_head
; ace
= m_ace_head
.m_next
)
689 m_ace_head
.m_used
-= ace
->m_used
;
690 AceCache::get().destroy (ace
);
692 OSL_ENSURE(m_ace_head
.m_used
== 0, "store::PageBIOS::cleanup_Impl(): logic error");
695 // Release SuperBlock page.
696 delete m_pSuper
, m_pSuper
= 0;
698 // Release PageCache.
701 // Release PageAllocator.
702 m_xAllocator
.clear();
704 // Release LockBytes.
705 m_xLockBytes
.clear();
710 * Low Level: Precond: initialized, exclusive access.
712 storeError
OStorePageBIOS::read (
713 sal_uInt32 nAddr
, void *pData
, sal_uInt32 nSize
)
716 if (!m_xLockBytes
.is())
717 return store_E_InvalidAccess
;
720 return m_xLockBytes
->readAt (nAddr
, pData
, nSize
);
725 * Low Level: Precond: initialized, writeable, exclusive access.
727 storeError
OStorePageBIOS::write (
728 sal_uInt32 nAddr
, const void *pData
, sal_uInt32 nSize
)
731 if (!m_xLockBytes
.is())
732 return store_E_InvalidAccess
;
734 return store_E_AccessViolation
;
737 return m_xLockBytes
->writeAt (nAddr
, pData
, nSize
);
742 * Precond: initialized.
744 storeError
OStorePageBIOS::acquirePage (
745 const OStorePageDescriptor
& rDescr
, storeAccessMode eMode
)
747 // Acquire exclusive access.
748 osl::MutexGuard
aGuard (m_aMutex
);
751 if (!m_xLockBytes
.is())
752 return store_E_InvalidAccess
;
754 // Check access mode.
755 if (!(m_bWriteable
|| (eMode
== store_AccessReadOnly
)))
756 return store_E_AccessViolation
;
758 // Find access control list entry.
759 Ace
* ace
= Ace::find (&m_ace_head
, rDescr
.m_nAddr
);
760 if (ace
->m_addr
== rDescr
.m_nAddr
)
762 // Acquire existing entry (with ShareDenyWrite).
763 if (eMode
== store_AccessReadOnly
)
766 return store_E_AccessViolation
;
771 Ace
* entry
= AceCache::get().create (rDescr
.m_nAddr
, 1);
773 return store_E_OutOfMemory
;
774 Ace::insert (ace
, entry
);
777 // Increment total referer count and finish.
778 m_ace_head
.m_used
+= 1;
784 * Precond: initialized.
786 storeError
OStorePageBIOS::releasePage (const OStorePageDescriptor
& rDescr
)
788 // Acquire exclusive access.
789 osl::MutexGuard
aGuard (m_aMutex
);
792 if (!m_xLockBytes
.is())
793 return store_E_InvalidAccess
;
795 // Find access control list entry.
796 Ace
* ace
= Ace::find (&m_ace_head
, rDescr
.m_nAddr
);
797 if (ace
->m_addr
!= rDescr
.m_nAddr
)
798 return store_E_NotExists
;
800 // Release existing entry.
804 AceCache::get().destroy (ace
);
806 // Decrement total referer count and finish.
807 m_ace_head
.m_used
-= 1;
815 sal_uInt32
OStorePageBIOS::getRefererCount (void)
817 // Acquire exclusive access.
818 osl::MutexGuard
aGuard (m_aMutex
);
820 // Obtain total referer count.
821 return m_ace_head
.m_used
;
826 * Precond: initialized, writeable.
828 storeError
OStorePageBIOS::allocate (
829 OStorePageObject
& rPage
, Allocation eAlloc
)
831 // Acquire exclusive access.
832 osl::MutexGuard
aGuard (m_aMutex
);
835 if (!m_xLockBytes
.is())
836 return store_E_InvalidAccess
;
838 return store_E_AccessViolation
;
840 // Check allocation type.
841 storeError eErrCode
= store_E_None
;
842 if (eAlloc
!= ALLOCATE_EOF
)
844 // Try freelist head.
846 eErrCode
= m_pSuper
->unusedHead (*this, aPageHead
);
847 if (eErrCode
!= store_E_None
)
850 sal_uInt32
const nAddr
= aPageHead
.location();
851 if (nAddr
!= STORE_PAGE_NULL
)
854 eErrCode
= saveObjectAt_Impl (rPage
, nAddr
);
855 if (eErrCode
!= store_E_None
)
858 // Pop freelist head and finish.
859 return m_pSuper
->unusedPop (*this, aPageHead
);
863 // Allocate from EOF. Determine current size.
864 sal_uInt32 nSize
= STORE_PAGE_NULL
;
865 eErrCode
= m_xLockBytes
->getSize (nSize
);
866 if (eErrCode
!= store_E_None
)
869 // Save page at current EOF.
870 return saveObjectAt_Impl (rPage
, nSize
);
875 * Precond: initialized, writeable.
877 storeError
OStorePageBIOS::free (sal_uInt32 nAddr
)
879 // Acquire exclusive access.
880 osl::MutexGuard
aGuard (m_aMutex
);
883 if (!m_xLockBytes
.is())
884 return store_E_InvalidAccess
;
886 return store_E_AccessViolation
;
889 (void) m_xCache
->removePageAt (nAddr
);
891 // Push onto freelist.
892 return m_pSuper
->unusedPush (*this, nAddr
);
897 * Precond: initialized, readable.
899 storeError
OStorePageBIOS::loadObjectAt (OStorePageObject
& rPage
, sal_uInt32 nAddr
)
901 // Acquire exclusive access.
902 osl::MutexGuard
aGuard (m_aMutex
);
905 if (!m_xLockBytes
.is())
906 return store_E_InvalidAccess
;
908 return loadObjectAt_Impl (rPage
, nAddr
);
913 * Internal: Precond: initialized, readable, exclusive access.
915 storeError
OStorePageBIOS::loadObjectAt_Impl (OStorePageObject
& rPage
, sal_uInt32 nAddr
)
917 storeError eErrCode
= m_xCache
->lookupPageAt (rPage
.get(), nAddr
);
918 if (eErrCode
!= store_E_NotExists
)
922 eErrCode
= m_xLockBytes
->readPageAt (rPage
.get(), nAddr
);
923 if (eErrCode
!= store_E_None
)
927 eErrCode
= rPage
.verify (nAddr
);
928 if (eErrCode
!= store_E_None
)
931 // Mark page as clean.
935 return m_xCache
->insertPageAt (rPage
.get(), nAddr
);
940 * Precond: initialized, writeable.
942 storeError
OStorePageBIOS::saveObjectAt (OStorePageObject
& rPage
, sal_uInt32 nAddr
)
944 // Acquire exclusive access.
945 osl::MutexGuard
aGuard (m_aMutex
);
948 if (!m_xLockBytes
.is())
949 return store_E_InvalidAccess
;
951 return store_E_AccessViolation
;
954 return saveObjectAt_Impl (rPage
, nAddr
);
959 * Internal: Precond: initialized, writeable, exclusive access.
961 storeError
OStorePageBIOS::saveObjectAt_Impl (OStorePageObject
& rPage
, sal_uInt32 nAddr
)
963 // Guard page (incl. set location).
964 storeError eErrCode
= rPage
.guard (nAddr
);
965 if (eErrCode
!= store_E_None
)
969 eErrCode
= m_xLockBytes
->writePageAt(rPage
.get(), nAddr
);
970 if (eErrCode
!= store_E_None
)
973 // Mark page as clean.
977 return m_xCache
->updatePageAt (rPage
.get(), nAddr
);
984 storeError
OStorePageBIOS::close()
986 // Acquire exclusive access.
987 osl::MutexGuard
aGuard (m_aMutex
);
998 * Precond: initialized.
1000 storeError
OStorePageBIOS::flush (void)
1002 // Acquire exclusive access.
1003 osl::MutexGuard
aGuard (m_aMutex
);
1006 if (!m_xLockBytes
.is())
1007 return store_E_InvalidAccess
;
1009 // Flush LockBytes and finish.
1010 return m_xLockBytes
->flush();
1015 * Precond: initialized.
1017 storeError
OStorePageBIOS::size (sal_uInt32
&rnSize
)
1019 // Acquire exclusive access.
1020 osl::MutexGuard
aGuard (m_aMutex
);
1022 // Initialize [out] param.
1026 if (!m_xLockBytes
.is())
1027 return store_E_InvalidAccess
;
1029 // Obtain LockBytes size.
1030 return m_xLockBytes
->getSize (rnSize
);
1035 * Precond: initialized.
1037 storeError
OStorePageBIOS::scanBegin (
1038 ScanContext
&rCtx
, sal_uInt32 nMagic
)
1040 // Acquire exclusive access.
1041 osl::MutexGuard
aGuard (m_aMutex
);
1043 // Initialize [out] param.
1044 rCtx
.m_aDescr
= OStorePageDescriptor(0, 0, 0);
1046 rCtx
.m_nMagic
= nMagic
;
1049 if (!m_xLockBytes
.is())
1050 return store_E_InvalidAccess
;
1052 // Check SuperBlock page.
1053 storeError eErrCode
= m_pSuper
->verify (*this);
1054 if (eErrCode
!= store_E_None
)
1056 // Damaged. Determine page size (NYI).
1057 OSL_TRACE ("OStorePageBIOS::scanBegin(): damaged.\n");
1061 // Setup Context descriptor.
1062 rCtx
.m_aDescr
= m_pSuper
->m_aSuperOne
.m_aDescr
;
1063 rCtx
.m_aDescr
.m_nSize
= store::ntohs(rCtx
.m_aDescr
.m_nSize
);
1064 rCtx
.m_aDescr
.m_nAddr
= rCtx
.m_aDescr
.m_nSize
;
1066 // Setup Context size.
1067 eErrCode
= size (rCtx
.m_nSize
);
1068 if (eErrCode
!= store_E_None
)
1069 rCtx
.m_nSize
= ((sal_uInt32
)(~0));
1072 return store_E_None
;
1077 * Precond: initialized.
1079 storeError
OStorePageBIOS::scanNext (
1080 ScanContext
&rCtx
, OStorePageObject
&rPage
)
1082 // Acquire exclusive access.
1083 osl::MutexGuard
aGuard (m_aMutex
);
1086 if (!m_xLockBytes
.is())
1087 return store_E_InvalidAccess
;
1093 while (rCtx
.isValid())
1095 // Assign next location.
1096 sal_uInt32 nAddr
= rCtx
.m_aDescr
.m_nAddr
;
1097 rCtx
.m_aDescr
.m_nAddr
+= rCtx
.m_aDescr
.m_nSize
;
1100 storeError eErrCode
= read (nAddr
, &aPageHead
, PageData::theSize
);
1101 if (eErrCode
!= store_E_None
)
1105 eErrCode
= aPageHead
.verify (nAddr
);
1106 if (eErrCode
!= store_E_None
)
1109 // Check PageHead Magic number.
1110 if (aPageHead
.m_aGuard
.m_nMagic
!= rCtx
.m_nMagic
)
1113 // Check PageHead Unused link.
1114 if (aPageHead
.m_aUnused
.m_nAddr
!= STORE_PAGE_NULL
)
1118 eErrCode
= loadObjectAt_Impl (rPage
, nAddr
);
1119 if (eErrCode
!= store_E_None
)
1123 return store_E_None
;
1127 return store_E_CantSeek
;
1130 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */