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 "storbios.hxx"
24 #include "sal/types.h"
25 #include "sal/macros.h"
26 #include "sal/log.hxx"
28 #include "rtl/alloc.h"
29 #include "rtl/ref.hxx"
31 #include "osl/diagnose.h"
32 #include "osl/mutex.hxx"
34 #include "store/types.h"
36 #include "lockbyte.hxx"
37 #include "storcach.hxx"
39 using namespace store
;
41 /*========================================================================
45 *======================================================================*/
46 #define STORE_MAGIC_SUPERBLOCK sal_uInt32(0x484D5343)
48 struct OStoreSuperBlock
50 typedef OStorePageGuard G
;
51 typedef OStorePageDescriptor D
;
52 typedef OStorePageLink L
;
65 static const size_t theSize
= sizeof(G
) + sizeof(D
) + 2 * (sizeof(L
) + sizeof(sal_uInt32
));
69 explicit OStoreSuperBlock (sal_uInt16 nPageSize
)
70 : m_aGuard (STORE_MAGIC_SUPERBLOCK
),
71 m_aDescr (nPageSize
, nPageSize
, STORE_MINIMUM_PAGESIZE
),
72 m_nMarked (store::htonl(0)),
74 m_nUnused (store::htonl(0)),
80 bool operator== (const OStoreSuperBlock
& rhs
) const
82 return ((m_aGuard
== rhs
.m_aGuard
) &&
83 (m_aDescr
== rhs
.m_aDescr
) &&
84 (m_nMarked
== rhs
.m_nMarked
) &&
85 (m_aMarked
== rhs
.m_aMarked
) &&
86 (m_nUnused
== rhs
.m_nUnused
) &&
87 (m_aUnused
== rhs
.m_aUnused
) );
90 /** unused(Count|Head|Insert|Remove|Reset).
92 sal_uInt32
unusedCount() const
94 return store::ntohl(m_nUnused
);
96 const L
& unusedHead() const
100 void unusedInsert (const L
& rLink
)
102 sal_uInt32 nUnused
= unusedCount();
103 m_nUnused
= store::htonl(nUnused
+ 1);
106 void unusedRemove (const L
& rLink
)
108 sal_uInt32 nUnused
= unusedCount();
109 m_nUnused
= store::htonl(nUnused
- 1);
114 m_nUnused
= store::htonl(0);
118 /** guard (external representation).
122 sal_uInt32 nCRC32
= 0;
123 nCRC32
= rtl_crc32 (nCRC32
, &m_aGuard
.m_nMagic
, sizeof(sal_uInt32
));
124 nCRC32
= rtl_crc32 (nCRC32
, &m_aDescr
, theSize
- sizeof(G
));
125 m_aGuard
.m_nCRC32
= store::htonl(nCRC32
);
128 /** verify (external representation).
130 storeError
verify() const
132 sal_uInt32 nMagic
= store::ntohl(m_aGuard
.m_nMagic
);
133 if (nMagic
!= STORE_MAGIC_SUPERBLOCK
)
134 return store_E_WrongFormat
;
136 sal_uInt32 nCRC32
= 0;
137 nCRC32
= rtl_crc32 (nCRC32
, &m_aGuard
.m_nMagic
, sizeof(sal_uInt32
));
138 nCRC32
= rtl_crc32 (nCRC32
, &m_aDescr
, theSize
- sizeof(G
));
139 if (m_aGuard
.m_nCRC32
!= store::htonl(nCRC32
))
140 return store_E_InvalidChecksum
;
146 /*========================================================================
148 * SuperBlockPage interface.
150 *======================================================================*/
154 struct SuperBlockPage
156 typedef OStoreSuperBlock SuperBlock
;
160 SuperBlock m_aSuperOne
;
161 SuperBlock m_aSuperTwo
;
165 static const size_t theSize
= 2 * SuperBlock::theSize
;
166 static const sal_uInt16 thePageSize
= theSize
;
167 static_assert(STORE_MINIMUM_PAGESIZE
>= thePageSize
, "must be at least thePageSize");
171 static void * operator new (size_t n
)
173 return rtl_allocateMemory (sal::static_int_cast
<sal_Size
>(n
));
175 static void operator delete (void * p
)
180 static void * operator new (SAL_UNUSED_PARAMETER
size_t, sal_uInt16 nPageSize
)
182 return rtl_allocateZeroMemory (sal::static_int_cast
<sal_Size
>(nPageSize
));
184 static void operator delete (void * p
, SAL_UNUSED_PARAMETER sal_uInt16
)
191 explicit SuperBlockPage (sal_uInt16 nPageSize
= thePageSize
)
192 : m_aSuperOne(nPageSize
),
193 m_aSuperTwo(nPageSize
)
198 storeError
save (OStorePageBIOS
& rBIOS
, sal_uInt32 nSize
= theSize
)
201 m_aSuperTwo
= m_aSuperOne
;
202 return rBIOS
.write (0, this, nSize
);
207 storeError
unusedHead (
208 OStorePageBIOS
& rBIOS
,
209 PageData
& rPageHead
);
211 storeError
unusedPop (
212 OStorePageBIOS
& rBIOS
,
213 PageData
const & rPageHead
);
215 storeError
unusedPush (
216 OStorePageBIOS
& rBIOS
,
219 /** verify (with repair).
221 storeError
verify (OStorePageBIOS
& rBIOS
);
226 /*========================================================================
228 * SuperBlockPage implementation.
230 *======================================================================*/
232 * unusedHead(): get freelist head (alloc page, step 1).
234 storeError
SuperBlockPage::unusedHead (OStorePageBIOS
& rBIOS
, PageData
& rPageHead
)
236 storeError eErrCode
= verify (rBIOS
);
237 if (eErrCode
!= store_E_None
)
240 // Check freelist head.
241 OStorePageLink
const aListHead (m_aSuperOne
.unusedHead());
242 if (aListHead
.location() == 0)
244 // Freelist empty, see SuperBlock::ctor().
245 rPageHead
.location (STORE_PAGE_NULL
);
250 eErrCode
= rBIOS
.read (aListHead
.location(), &rPageHead
, PageData::theSize
);
251 if (eErrCode
!= store_E_None
)
254 eErrCode
= rPageHead
.verify (aListHead
.location());
255 if (eErrCode
!= store_E_None
)
258 // Verify page is unused.
259 sal_uInt32
const nAddr
= rPageHead
.m_aUnused
.location();
260 if (nAddr
== STORE_PAGE_NULL
)
262 SAL_WARN("store", "store::SuperBlock::unusedHead(): page not free");
265 rPageHead
.location (STORE_PAGE_NULL
);
267 // Recovery: Reset freelist to empty.
268 m_aSuperOne
.unusedReset();
269 eErrCode
= save (rBIOS
);
275 * unusedPop(): pop freelist head (alloc page, step 2).
277 storeError
SuperBlockPage::unusedPop (OStorePageBIOS
& rBIOS
, PageData
const & rPageHead
)
279 sal_uInt32
const nAddr
= rPageHead
.m_aUnused
.location();
280 OSL_PRECOND(nAddr
!= STORE_PAGE_NULL
, "store::SuperBlock::unusedPop(): page not free");
281 if (nAddr
== STORE_PAGE_NULL
)
282 return store_E_CantSeek
;
284 // Pop from FreeList.
285 OStorePageLink
const aListHead (nAddr
);
286 m_aSuperOne
.unusedRemove (aListHead
);
291 * unusedPush(): push new freelist head.
293 storeError
SuperBlockPage::unusedPush (OStorePageBIOS
& rBIOS
, sal_uInt32 nAddr
)
295 storeError eErrCode
= verify (rBIOS
);
296 if (eErrCode
!= store_E_None
)
300 eErrCode
= rBIOS
.read (nAddr
, &aPageHead
, PageData::theSize
);
301 if (eErrCode
!= store_E_None
)
304 eErrCode
= aPageHead
.verify (nAddr
);
305 if (eErrCode
!= store_E_None
)
308 aPageHead
.m_aUnused
= m_aSuperOne
.unusedHead();
309 aPageHead
.guard (nAddr
);
311 eErrCode
= rBIOS
.write (nAddr
, &aPageHead
, PageData::theSize
);
312 if (eErrCode
!= store_E_None
)
315 OStorePageLink
const aListHead (nAddr
);
316 m_aSuperOne
.unusedInsert(aListHead
);
321 * verify (with repair).
323 storeError
SuperBlockPage::verify (OStorePageBIOS
& rBIOS
)
326 storeError eErrCode
= m_aSuperOne
.verify();
327 if (eErrCode
== store_E_None
)
329 // Ok. Verify 2nd copy.
330 eErrCode
= m_aSuperTwo
.verify();
331 if (eErrCode
== store_E_None
)
333 // Ok. Ensure identical copies (1st copy wins).
334 if (!(m_aSuperOne
== m_aSuperTwo
))
336 // Different. Replace 2nd copy with 1st copy.
337 m_aSuperTwo
= m_aSuperOne
;
340 if (rBIOS
.isWriteable())
341 eErrCode
= rBIOS
.write (0, this, theSize
);
343 eErrCode
= store_E_None
;
348 // Failure. Replace 2nd copy with 1st copy.
349 m_aSuperTwo
= m_aSuperOne
;
352 if (rBIOS
.isWriteable())
353 eErrCode
= rBIOS
.write (0, this, theSize
);
355 eErrCode
= store_E_None
;
360 // Failure. Verify 2nd copy.
361 eErrCode
= m_aSuperTwo
.verify();
362 if (eErrCode
== store_E_None
)
364 // Ok. Replace 1st copy with 2nd copy.
365 m_aSuperOne
= m_aSuperTwo
;
368 if (rBIOS
.isWriteable())
369 eErrCode
= rBIOS
.write (0, this, theSize
);
371 eErrCode
= store_E_None
;
376 OSL_TRACE("OStoreSuperBlockPage::verify(): double failure.");
384 /*========================================================================
386 * OStorePageBIOS::Ace implementation.
388 *======================================================================*/
389 OStorePageBIOS::Ace::Ace()
390 : m_next (this), m_prev (this), m_addr (STORE_PAGE_NULL
), m_used (0)
393 OStorePageBIOS::Ace::~Ace()
395 m_next
->m_prev
= m_prev
, m_prev
->m_next
= m_next
;
399 SAL_CALL
OStorePageBIOS::Ace::constructor (
400 void * obj
, SAL_UNUSED_PARAMETER
void * /* arg */)
402 Ace
* ace
= static_cast<Ace
*>(obj
);
403 ace
->m_next
= ace
->m_prev
= ace
;
407 OStorePageBIOS::Ace
*
408 OStorePageBIOS::Ace::find (OStorePageBIOS::Ace
* head
, sal_uInt32 addr
)
410 OStorePageBIOS::Ace
* entry
;
411 for (entry
= head
->m_next
; entry
!= head
; entry
= entry
->m_next
)
413 if (entry
->m_addr
>= addr
)
420 OStorePageBIOS::Ace::insert (OStorePageBIOS::Ace
* head
, OStorePageBIOS::Ace
* entry
)
422 // insert entry at queue tail (before head).
423 entry
->m_next
= head
;
424 entry
->m_prev
= head
->m_prev
;
425 head
->m_prev
= entry
;
426 entry
->m_prev
->m_next
= entry
;
429 /*========================================================================
431 * OStorePageBIOS::AceCache interface.
433 *======================================================================*/
437 class OStorePageBIOS::AceCache
439 rtl_cache_type
* m_ace_cache
;
442 static AceCache
& get();
444 OStorePageBIOS::Ace
*
445 create (sal_uInt32 addr
, sal_uInt32 used
= 1);
448 destroy (OStorePageBIOS::Ace
* ace
);
457 /*========================================================================
459 * OStorePageBIOS::AceCache implementation.
461 *======================================================================*/
462 extern "C" typedef int (SAL_CALL
* ace_constructor_type
)(void*,void*);
464 OStorePageBIOS::AceCache
&
465 OStorePageBIOS::AceCache::get()
467 static AceCache g_ace_cache
;
471 OStorePageBIOS::AceCache::AceCache()
473 m_ace_cache
= rtl_cache_create (
475 sizeof (OStorePageBIOS::Ace
),
477 reinterpret_cast<ace_constructor_type
>( OStorePageBIOS::Ace::constructor
),
481 0, // default source,
486 OStorePageBIOS::AceCache::~AceCache()
488 rtl_cache_destroy (m_ace_cache
), m_ace_cache
= 0;
491 OStorePageBIOS::Ace
*
492 OStorePageBIOS::AceCache::create (sal_uInt32 addr
, sal_uInt32 used
)
494 Ace
* ace
= static_cast<Ace
*>(rtl_cache_alloc (m_ace_cache
));
497 // verify invariant state.
498 OSL_ASSERT((ace
->m_next
== ace
) && (ace
->m_prev
== ace
));
508 OStorePageBIOS::AceCache::destroy (OStorePageBIOS::Ace
* ace
)
512 // remove from queue (if any).
513 ace
->m_next
->m_prev
= ace
->m_prev
, ace
->m_prev
->m_next
= ace
->m_next
;
515 // restore invariant state.
516 ace
->m_next
= ace
->m_prev
= ace
;
519 rtl_cache_free (m_ace_cache
, ace
);
523 /*========================================================================
525 * OStorePageBIOS implementation.
527 *======================================================================*/
531 OStorePageBIOS::OStorePageBIOS()
532 : m_xLockBytes (NULL
),
541 OStorePageBIOS::~OStorePageBIOS()
550 storeError
OStorePageBIOS::initialize (
551 ILockBytes
* pLockBytes
,
552 storeAccessMode eAccessMode
,
553 sal_uInt16
& rnPageSize
)
555 // Acquire exclusive access.
556 osl::MutexGuard
aGuard (m_aMutex
);
559 storeError eErrCode
= initialize_Impl (pLockBytes
, eAccessMode
, rnPageSize
);
560 if (eErrCode
!= store_E_None
)
570 * Internal: Precond: exclusive access.
572 storeError
OStorePageBIOS::initialize_Impl (
573 ILockBytes
* pLockBytes
,
574 storeAccessMode eAccessMode
,
575 sal_uInt16
& rnPageSize
)
581 m_xLockBytes
= pLockBytes
;
582 if (!m_xLockBytes
.is())
583 return store_E_InvalidParameter
;
584 m_bWriteable
= (eAccessMode
!= store_AccessReadOnly
);
586 // Check access mode.
587 storeError eErrCode
= store_E_None
;
588 if (eAccessMode
!= store_AccessCreate
)
590 // Load SuperBlock page.
591 if ((m_pSuper
= new SuperBlockPage()) == 0)
592 return store_E_OutOfMemory
;
594 eErrCode
= read (0, m_pSuper
, SuperBlockPage::theSize
);
595 if (eErrCode
== store_E_None
)
597 // Verify SuperBlock page (with repair).
598 eErrCode
= m_pSuper
->verify (*this);
603 // Truncate to zero length.
604 eErrCode
= m_xLockBytes
->setSize(0);
605 if (eErrCode
!= store_E_None
)
608 // Mark as not existing.
609 eErrCode
= store_E_NotExists
;
612 if (eErrCode
!= store_E_None
)
615 if (eErrCode
!= store_E_NotExists
)
619 if (eAccessMode
== store_AccessReadOnly
)
620 return store_E_NotExists
;
621 if (eAccessMode
== store_AccessReadWrite
)
622 return store_E_NotExists
;
625 if ((STORE_MINIMUM_PAGESIZE
> rnPageSize
) || (rnPageSize
> STORE_MAXIMUM_PAGESIZE
))
626 return store_E_InvalidParameter
;
627 rnPageSize
= ((rnPageSize
+ STORE_MINIMUM_PAGESIZE
- 1) & ~(STORE_MINIMUM_PAGESIZE
- 1));
629 // Create initial page (w/ SuperBlock).
630 if ((m_pSuper
= new(rnPageSize
) SuperBlockPage(rnPageSize
)) == 0)
631 return store_E_OutOfMemory
;
632 eErrCode
= m_pSuper
->save (*this, rnPageSize
);
634 if (eErrCode
== store_E_None
)
637 rnPageSize
= store::ntohs(m_pSuper
->m_aSuperOne
.m_aDescr
.m_nSize
);
639 // Create page allocator.
640 eErrCode
= m_xLockBytes
->initialize (m_xAllocator
, rnPageSize
);
641 if (eErrCode
!= store_E_None
)
644 // Create page cache.
645 eErrCode
= PageCache_createInstance (m_xCache
, rnPageSize
);
652 * Internal: Precond: exclusive access.
654 void OStorePageBIOS::cleanup_Impl()
656 // Check referer count.
657 if (m_ace_head
.m_used
> 0)
659 // Report remaining referer count.
660 SAL_INFO("store", "referer count: " << m_ace_head
.m_used
);
661 for (Ace
* ace
= m_ace_head
.m_next
; ace
!= &m_ace_head
; ace
= m_ace_head
.m_next
)
663 m_ace_head
.m_used
-= ace
->m_used
;
664 AceCache::get().destroy (ace
);
666 OSL_ENSURE(m_ace_head
.m_used
== 0, "store::PageBIOS::cleanup_Impl(): logic error");
669 // Release SuperBlock page.
670 delete m_pSuper
, m_pSuper
= 0;
672 // Release PageCache.
675 // Release PageAllocator.
676 m_xAllocator
.clear();
678 // Release LockBytes.
679 m_xLockBytes
.clear();
684 * Low Level: Precond: initialized, exclusive access.
686 storeError
OStorePageBIOS::read (
687 sal_uInt32 nAddr
, void *pData
, sal_uInt32 nSize
)
690 if (!m_xLockBytes
.is())
691 return store_E_InvalidAccess
;
694 return m_xLockBytes
->readAt (nAddr
, pData
, nSize
);
699 * Low Level: Precond: initialized, writeable, exclusive access.
701 storeError
OStorePageBIOS::write (
702 sal_uInt32 nAddr
, const void *pData
, sal_uInt32 nSize
)
705 if (!m_xLockBytes
.is())
706 return store_E_InvalidAccess
;
708 return store_E_AccessViolation
;
711 return m_xLockBytes
->writeAt (nAddr
, pData
, nSize
);
716 * Precond: initialized.
718 storeError
OStorePageBIOS::acquirePage (
719 const OStorePageDescriptor
& rDescr
, storeAccessMode eMode
)
721 // Acquire exclusive access.
722 osl::MutexGuard
aGuard (m_aMutex
);
725 if (!m_xLockBytes
.is())
726 return store_E_InvalidAccess
;
728 // Check access mode.
729 if (!(m_bWriteable
|| (eMode
== store_AccessReadOnly
)))
730 return store_E_AccessViolation
;
732 // Find access control list entry.
733 Ace
* ace
= Ace::find (&m_ace_head
, rDescr
.m_nAddr
);
734 if (ace
->m_addr
== rDescr
.m_nAddr
)
736 // Acquire existing entry (with ShareDenyWrite).
737 if (eMode
== store_AccessReadOnly
)
740 return store_E_AccessViolation
;
745 Ace
* entry
= AceCache::get().create (rDescr
.m_nAddr
, 1);
747 return store_E_OutOfMemory
;
748 Ace::insert (ace
, entry
);
751 // Increment total referer count and finish.
752 m_ace_head
.m_used
+= 1;
758 * Precond: initialized.
760 storeError
OStorePageBIOS::releasePage (const OStorePageDescriptor
& rDescr
)
762 // Acquire exclusive access.
763 osl::MutexGuard
aGuard (m_aMutex
);
766 if (!m_xLockBytes
.is())
767 return store_E_InvalidAccess
;
769 // Find access control list entry.
770 Ace
* ace
= Ace::find (&m_ace_head
, rDescr
.m_nAddr
);
771 if (ace
->m_addr
!= rDescr
.m_nAddr
)
772 return store_E_NotExists
;
774 // Release existing entry.
778 AceCache::get().destroy (ace
);
780 // Decrement total referer count and finish.
781 m_ace_head
.m_used
-= 1;
789 sal_uInt32
OStorePageBIOS::getRefererCount()
791 // Acquire exclusive access.
792 osl::MutexGuard
aGuard (m_aMutex
);
794 // Obtain total referer count.
795 return m_ace_head
.m_used
;
800 * Precond: initialized, writeable.
802 storeError
OStorePageBIOS::allocate (
803 OStorePageObject
& rPage
, Allocation eAlloc
)
805 // Acquire exclusive access.
806 osl::MutexGuard
aGuard (m_aMutex
);
809 if (!m_xLockBytes
.is())
810 return store_E_InvalidAccess
;
812 return store_E_AccessViolation
;
814 // Check allocation type.
815 storeError eErrCode
= store_E_None
;
816 if (eAlloc
!= ALLOCATE_EOF
)
818 // Try freelist head.
820 eErrCode
= m_pSuper
->unusedHead (*this, aPageHead
);
821 if (eErrCode
!= store_E_None
)
824 sal_uInt32
const nAddr
= aPageHead
.location();
825 if (nAddr
!= STORE_PAGE_NULL
)
828 eErrCode
= saveObjectAt_Impl (rPage
, nAddr
);
829 if (eErrCode
!= store_E_None
)
832 // Pop freelist head and finish.
833 return m_pSuper
->unusedPop (*this, aPageHead
);
837 // Allocate from EOF. Determine current size.
838 sal_uInt32 nSize
= STORE_PAGE_NULL
;
839 eErrCode
= m_xLockBytes
->getSize (nSize
);
840 if (eErrCode
!= store_E_None
)
843 // Save page at current EOF.
844 return saveObjectAt_Impl (rPage
, nSize
);
849 * Precond: initialized, writeable.
851 storeError
OStorePageBIOS::free (sal_uInt32 nAddr
)
853 // Acquire exclusive access.
854 osl::MutexGuard
aGuard (m_aMutex
);
857 if (!m_xLockBytes
.is())
858 return store_E_InvalidAccess
;
860 return store_E_AccessViolation
;
863 (void) m_xCache
->removePageAt (nAddr
);
865 // Push onto freelist.
866 return m_pSuper
->unusedPush (*this, nAddr
);
871 * Precond: initialized, readable.
873 storeError
OStorePageBIOS::loadObjectAt (OStorePageObject
& rPage
, sal_uInt32 nAddr
)
875 // Acquire exclusive access.
876 osl::MutexGuard
aGuard (m_aMutex
);
879 if (!m_xLockBytes
.is())
880 return store_E_InvalidAccess
;
882 return loadObjectAt_Impl (rPage
, nAddr
);
887 * Internal: Precond: initialized, readable, exclusive access.
889 storeError
OStorePageBIOS::loadObjectAt_Impl (OStorePageObject
& rPage
, sal_uInt32 nAddr
)
891 storeError eErrCode
= m_xCache
->lookupPageAt (rPage
.get(), nAddr
);
892 if (eErrCode
!= store_E_NotExists
)
896 eErrCode
= m_xLockBytes
->readPageAt (rPage
.get(), nAddr
);
897 if (eErrCode
!= store_E_None
)
901 eErrCode
= rPage
.verify (nAddr
);
902 if (eErrCode
!= store_E_None
)
905 // Mark page as clean.
909 return m_xCache
->insertPageAt (rPage
.get(), nAddr
);
914 * Precond: initialized, writeable.
916 storeError
OStorePageBIOS::saveObjectAt (OStorePageObject
& rPage
, sal_uInt32 nAddr
)
918 // Acquire exclusive access.
919 osl::MutexGuard
aGuard (m_aMutex
);
922 if (!m_xLockBytes
.is())
923 return store_E_InvalidAccess
;
925 return store_E_AccessViolation
;
928 return saveObjectAt_Impl (rPage
, nAddr
);
933 * Internal: Precond: initialized, writeable, exclusive access.
935 storeError
OStorePageBIOS::saveObjectAt_Impl (OStorePageObject
& rPage
, sal_uInt32 nAddr
)
937 // Guard page (incl. set location).
938 storeError eErrCode
= rPage
.guard (nAddr
);
939 if (eErrCode
!= store_E_None
)
943 eErrCode
= m_xLockBytes
->writePageAt(rPage
.get(), nAddr
);
944 if (eErrCode
!= store_E_None
)
947 // Mark page as clean.
951 return m_xCache
->updatePageAt (rPage
.get(), nAddr
);
958 storeError
OStorePageBIOS::close()
960 // Acquire exclusive access.
961 osl::MutexGuard
aGuard (m_aMutex
);
972 * Precond: initialized.
974 storeError
OStorePageBIOS::flush()
976 // Acquire exclusive access.
977 osl::MutexGuard
aGuard (m_aMutex
);
980 if (!m_xLockBytes
.is())
981 return store_E_InvalidAccess
;
983 // Flush LockBytes and finish.
984 return m_xLockBytes
->flush();
989 * Precond: initialized.
991 storeError
OStorePageBIOS::size (sal_uInt32
&rnSize
)
993 // Acquire exclusive access.
994 osl::MutexGuard
aGuard (m_aMutex
);
996 // Initialize [out] param.
1000 if (!m_xLockBytes
.is())
1001 return store_E_InvalidAccess
;
1003 // Obtain LockBytes size.
1004 return m_xLockBytes
->getSize (rnSize
);
1009 * Precond: initialized.
1011 storeError
OStorePageBIOS::scanBegin (
1012 ScanContext
&rCtx
, sal_uInt32 nMagic
)
1014 // Acquire exclusive access.
1015 osl::MutexGuard
aGuard (m_aMutex
);
1017 // Initialize [out] param.
1018 rCtx
.m_aDescr
= OStorePageDescriptor(0, 0, 0);
1020 rCtx
.m_nMagic
= nMagic
;
1023 if (!m_xLockBytes
.is())
1024 return store_E_InvalidAccess
;
1026 // Check SuperBlock page.
1027 storeError eErrCode
= m_pSuper
->verify (*this);
1028 if (eErrCode
!= store_E_None
)
1030 // Damaged. Determine page size (NYI).
1031 OSL_TRACE ("OStorePageBIOS::scanBegin(): damaged.\n");
1035 // Setup Context descriptor.
1036 rCtx
.m_aDescr
= m_pSuper
->m_aSuperOne
.m_aDescr
;
1037 rCtx
.m_aDescr
.m_nSize
= store::ntohs(rCtx
.m_aDescr
.m_nSize
);
1038 rCtx
.m_aDescr
.m_nAddr
= rCtx
.m_aDescr
.m_nSize
;
1040 // Setup Context size.
1041 eErrCode
= size (rCtx
.m_nSize
);
1042 if (eErrCode
!= store_E_None
)
1043 rCtx
.m_nSize
= ((sal_uInt32
)(~0));
1046 return store_E_None
;
1051 * Precond: initialized.
1053 storeError
OStorePageBIOS::scanNext (
1054 ScanContext
&rCtx
, OStorePageObject
&rPage
)
1056 // Acquire exclusive access.
1057 osl::MutexGuard
aGuard (m_aMutex
);
1060 if (!m_xLockBytes
.is())
1061 return store_E_InvalidAccess
;
1067 while (rCtx
.isValid())
1069 // Assign next location.
1070 sal_uInt32 nAddr
= rCtx
.m_aDescr
.m_nAddr
;
1071 rCtx
.m_aDescr
.m_nAddr
+= rCtx
.m_aDescr
.m_nSize
;
1074 storeError eErrCode
= read (nAddr
, &aPageHead
, PageData::theSize
);
1075 if (eErrCode
!= store_E_None
)
1079 eErrCode
= aPageHead
.verify (nAddr
);
1080 if (eErrCode
!= store_E_None
)
1083 // Check PageHead Magic number.
1084 if (aPageHead
.m_aGuard
.m_nMagic
!= rCtx
.m_nMagic
)
1087 // Check PageHead Unused link.
1088 if (aPageHead
.m_aUnused
.m_nAddr
!= STORE_PAGE_NULL
)
1092 eErrCode
= loadObjectAt_Impl (rPage
, nAddr
);
1093 if (eErrCode
!= store_E_None
)
1097 return store_E_None
;
1101 return store_E_CantSeek
;
1104 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */