build fix
[LibreOffice.git] / store / source / storbios.cxx
blob00648ce170e3f5c7692723f83e3b87d72fc5ef8c
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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"
35 #include "object.hxx"
36 #include "lockbyte.hxx"
37 #include "storcach.hxx"
39 using namespace store;
41 /*========================================================================
43 * OStoreSuperBlock.
45 *======================================================================*/
46 #define STORE_MAGIC_SUPERBLOCK sal_uInt32(0x484D5343)
48 struct OStoreSuperBlock
50 typedef OStorePageGuard G;
51 typedef OStorePageDescriptor D;
52 typedef OStorePageLink L;
54 /** Representation.
56 G m_aGuard;
57 D m_aDescr;
58 sal_uInt32 m_nMarked;
59 L m_aMarked;
60 sal_uInt32 m_nUnused;
61 L m_aUnused;
63 /** theSize.
65 static const size_t theSize = sizeof(G) + sizeof(D) + 2 * (sizeof(L) + sizeof(sal_uInt32));
67 /** Construction.
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)),
73 m_aMarked (0),
74 m_nUnused (store::htonl(0)),
75 m_aUnused (0)
78 /** Comparison.
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
98 return m_aUnused;
100 void unusedInsert (const L& rLink)
102 sal_uInt32 nUnused = unusedCount();
103 m_nUnused = store::htonl(nUnused + 1);
104 m_aUnused = rLink;
106 void unusedRemove (const L& rLink)
108 sal_uInt32 nUnused = unusedCount();
109 m_nUnused = store::htonl(nUnused - 1);
110 m_aUnused = rLink;
112 void unusedReset()
114 m_nUnused = store::htonl(0);
115 m_aUnused = L(0);
118 /** guard (external representation).
120 void guard()
122 sal_uInt32 nCRC32 = 0;
123 nCRC32 = rtl_crc32 (nCRC32, &m_aGuard.m_nMagic, sizeof(sal_uInt32));
124 nCRC32 = rtl_crc32 (nCRC32, &m_aDescr, static_cast<sal_uInt32>(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, static_cast<sal_uInt32>(theSize - sizeof(G)));
139 if (m_aGuard.m_nCRC32 != store::htonl(nCRC32))
140 return store_E_InvalidChecksum;
141 else
142 return store_E_None;
146 /*========================================================================
148 * SuperBlockPage interface.
150 *======================================================================*/
151 namespace store
154 struct SuperBlockPage
156 typedef OStoreSuperBlock SuperBlock;
158 /** Representation.
160 SuperBlock m_aSuperOne;
161 SuperBlock m_aSuperTwo;
163 /** theSize.
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");
169 /** Allocation.
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)
177 rtl_freeMemory (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)
186 rtl_freeMemory (p);
189 /** Construction.
191 explicit SuperBlockPage (sal_uInt16 nPageSize = thePageSize)
192 : m_aSuperOne(nPageSize),
193 m_aSuperTwo(nPageSize)
196 /** save.
198 storeError save (OStorePageBIOS & rBIOS, sal_uInt32 nSize = theSize)
200 m_aSuperOne.guard();
201 m_aSuperTwo = m_aSuperOne;
202 return rBIOS.write (0, this, nSize);
205 /** Page allocation.
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,
217 sal_uInt32 nAddr);
219 /** verify (with repair).
221 storeError verify (OStorePageBIOS & rBIOS);
224 } // namespace store
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)
238 return eErrCode;
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);
246 return store_E_None;
249 // Load PageHead.
250 eErrCode = rBIOS.read (aListHead.location(), &rPageHead, PageData::theSize);
251 if (eErrCode != store_E_None)
252 return eErrCode;
254 eErrCode = rPageHead.verify (aListHead.location());
255 if (eErrCode != store_E_None)
256 return eErrCode;
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");
264 // Page in use.
265 rPageHead.location (STORE_PAGE_NULL);
267 // Recovery: Reset freelist to empty.
268 m_aSuperOne.unusedReset();
269 eErrCode = save (rBIOS);
271 return eErrCode;
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);
287 return save (rBIOS);
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)
297 return eErrCode;
299 PageData aPageHead;
300 eErrCode = rBIOS.read (nAddr, &aPageHead, PageData::theSize);
301 if (eErrCode != store_E_None)
302 return eErrCode;
304 eErrCode = aPageHead.verify (nAddr);
305 if (eErrCode != store_E_None)
306 return eErrCode;
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)
313 return eErrCode;
315 OStorePageLink const aListHead (nAddr);
316 m_aSuperOne.unusedInsert(aListHead);
317 return save (rBIOS);
321 * verify (with repair).
323 storeError SuperBlockPage::verify (OStorePageBIOS & rBIOS)
325 // Verify 1st copy.
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;
339 // Write back.
340 if (rBIOS.isWriteable())
341 eErrCode = rBIOS.write (0, this, theSize);
342 else
343 eErrCode = store_E_None;
346 else
348 // Failure. Replace 2nd copy with 1st copy.
349 m_aSuperTwo = m_aSuperOne;
351 // Write back.
352 if (rBIOS.isWriteable())
353 eErrCode = rBIOS.write (0, this, theSize);
354 else
355 eErrCode = store_E_None;
358 else
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;
367 // Write back.
368 if (rBIOS.isWriteable())
369 eErrCode = rBIOS.write (0, this, theSize);
370 else
371 eErrCode = store_E_None;
373 else
375 // Double Failure.
376 OSL_TRACE("OStoreSuperBlockPage::verify(): double failure.");
380 // Done.
381 return eErrCode;
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;
396 m_prev->m_next = m_next;
400 SAL_CALL OStorePageBIOS::Ace::constructor (
401 void * obj, SAL_UNUSED_PARAMETER void * /* arg */)
403 Ace * ace = static_cast<Ace*>(obj);
404 ace->m_next = ace->m_prev = ace;
405 return 1;
408 OStorePageBIOS::Ace *
409 OStorePageBIOS::Ace::find (OStorePageBIOS::Ace * head, sal_uInt32 addr)
411 OStorePageBIOS::Ace * entry;
412 for (entry = head->m_next; entry != head; entry = entry->m_next)
414 if (entry->m_addr >= addr)
415 return entry;
417 return head;
420 void
421 OStorePageBIOS::Ace::insert (OStorePageBIOS::Ace * head, OStorePageBIOS::Ace * entry)
423 // insert entry at queue tail (before head).
424 entry->m_next = head;
425 entry->m_prev = head->m_prev;
426 head->m_prev = entry;
427 entry->m_prev->m_next = entry;
430 /*========================================================================
432 * OStorePageBIOS::AceCache interface.
434 *======================================================================*/
435 namespace store
438 class OStorePageBIOS::AceCache
440 rtl_cache_type * m_ace_cache;
442 public:
443 static AceCache & get();
445 OStorePageBIOS::Ace *
446 create (sal_uInt32 addr);
448 void
449 destroy (OStorePageBIOS::Ace * ace);
451 protected:
452 AceCache();
453 ~AceCache();
456 } // namespace store
458 /*========================================================================
460 * OStorePageBIOS::AceCache implementation.
462 *======================================================================*/
463 extern "C" typedef int (SAL_CALL * ace_constructor_type)(void*,void*);
465 OStorePageBIOS::AceCache &
466 OStorePageBIOS::AceCache::get()
468 static AceCache g_ace_cache;
469 return g_ace_cache;
472 OStorePageBIOS::AceCache::AceCache()
474 m_ace_cache = rtl_cache_create (
475 "store_ace_cache",
476 sizeof (OStorePageBIOS::Ace),
477 0, // objalign
478 reinterpret_cast<ace_constructor_type>( OStorePageBIOS::Ace::constructor),
479 nullptr, // destructor,
480 nullptr, // reclaim,
481 nullptr, // userarg,
482 nullptr, // default source,
483 0 // flags
487 OStorePageBIOS::AceCache::~AceCache()
489 rtl_cache_destroy (m_ace_cache);
490 m_ace_cache = nullptr;
493 OStorePageBIOS::Ace *
494 OStorePageBIOS::AceCache::create (sal_uInt32 addr)
496 Ace * ace = static_cast<Ace*>(rtl_cache_alloc (m_ace_cache));
497 if (ace != nullptr)
499 // verify invariant state.
500 OSL_ASSERT((ace->m_next == ace) && (ace->m_prev == ace));
502 // initialize.
503 ace->m_addr = addr;
504 ace->m_used = 1;
506 return ace;
509 void
510 OStorePageBIOS::AceCache::destroy (OStorePageBIOS::Ace * ace)
512 if (ace != nullptr)
514 // remove from queue (if any).
515 ace->m_next->m_prev = ace->m_prev;
516 ace->m_prev->m_next = ace->m_next;
518 // restore invariant state.
519 ace->m_next = ace->m_prev = ace;
521 // return to cache.
522 rtl_cache_free (m_ace_cache, ace);
526 /*========================================================================
528 * OStorePageBIOS implementation.
530 *======================================================================*/
532 * OStorePageBIOS.
534 OStorePageBIOS::OStorePageBIOS()
535 : m_xLockBytes (nullptr),
536 m_pSuper (nullptr),
537 m_bWriteable (false)
542 * ~OStorePageBIOS.
544 OStorePageBIOS::~OStorePageBIOS()
546 cleanup_Impl();
550 * initialize.
551 * Precond: none.
553 storeError OStorePageBIOS::initialize (
554 ILockBytes * pLockBytes,
555 storeAccessMode eAccessMode,
556 sal_uInt16 & rnPageSize)
558 // Acquire exclusive access.
559 osl::MutexGuard aGuard (m_aMutex);
561 // Initialize.
562 storeError eErrCode = initialize_Impl (pLockBytes, eAccessMode, rnPageSize);
563 if (eErrCode != store_E_None)
565 // Cleanup.
566 cleanup_Impl();
568 return eErrCode;
572 * initialize_Impl.
573 * Internal: Precond: exclusive access.
575 storeError OStorePageBIOS::initialize_Impl (
576 ILockBytes * pLockBytes,
577 storeAccessMode eAccessMode,
578 sal_uInt16 & rnPageSize)
580 // Cleanup.
581 cleanup_Impl();
583 // Initialize.
584 m_xLockBytes = pLockBytes;
585 if (!m_xLockBytes.is())
586 return store_E_InvalidParameter;
587 m_bWriteable = (eAccessMode != storeAccessMode::ReadOnly);
589 // Check access mode.
590 storeError eErrCode = store_E_None;
591 if (eAccessMode != storeAccessMode::Create)
593 // Load SuperBlock page.
594 if ((m_pSuper = new SuperBlockPage()) == nullptr)
595 return store_E_OutOfMemory;
597 eErrCode = read (0, m_pSuper, SuperBlockPage::theSize);
598 if (eErrCode == store_E_None)
600 // Verify SuperBlock page (with repair).
601 eErrCode = m_pSuper->verify (*this);
604 else
606 // Truncate to zero length.
607 eErrCode = m_xLockBytes->setSize(0);
608 if (eErrCode != store_E_None)
609 return eErrCode;
611 // Mark as not existing.
612 eErrCode = store_E_NotExists;
615 if (eErrCode != store_E_None)
617 // Check reason.
618 if (eErrCode != store_E_NotExists)
619 return eErrCode;
621 // Check mode.
622 if (eAccessMode == storeAccessMode::ReadOnly)
623 return store_E_NotExists;
624 if (eAccessMode == storeAccessMode::ReadWrite)
625 return store_E_NotExists;
627 // Check PageSize.
628 if ((STORE_MINIMUM_PAGESIZE > rnPageSize) || (rnPageSize > STORE_MAXIMUM_PAGESIZE))
629 return store_E_InvalidParameter;
630 rnPageSize = ((rnPageSize + STORE_MINIMUM_PAGESIZE - 1) & ~(STORE_MINIMUM_PAGESIZE - 1));
632 // Create initial page (w/ SuperBlock).
633 if ((m_pSuper = new(rnPageSize) SuperBlockPage(rnPageSize)) == nullptr)
634 return store_E_OutOfMemory;
635 eErrCode = m_pSuper->save (*this, rnPageSize);
637 if (eErrCode == store_E_None)
639 // Obtain page size.
640 rnPageSize = store::ntohs(m_pSuper->m_aSuperOne.m_aDescr.m_nSize);
642 // Create page allocator.
643 eErrCode = m_xLockBytes->initialize (m_xAllocator, rnPageSize);
644 if (eErrCode != store_E_None)
645 return eErrCode;
647 // Create page cache.
648 eErrCode = PageCache_createInstance (m_xCache, rnPageSize);
650 return eErrCode;
654 * cleanup_Impl.
655 * Internal: Precond: exclusive access.
657 void OStorePageBIOS::cleanup_Impl()
659 // Check referer count.
660 if (m_ace_head.m_used > 0)
662 // Report remaining referer count.
663 SAL_INFO("store", "referer count: " << m_ace_head.m_used);
664 for (Ace * ace = m_ace_head.m_next; ace != &m_ace_head; ace = m_ace_head.m_next)
666 m_ace_head.m_used -= ace->m_used;
667 AceCache::get().destroy (ace);
669 OSL_ENSURE(m_ace_head.m_used == 0, "store::PageBIOS::cleanup_Impl(): logic error");
672 // Release SuperBlock page.
673 delete m_pSuper;
674 m_pSuper = nullptr;
676 // Release PageCache.
677 m_xCache.clear();
679 // Release PageAllocator.
680 m_xAllocator.clear();
682 // Release LockBytes.
683 m_xLockBytes.clear();
687 * read.
688 * Low Level: Precond: initialized, exclusive access.
690 storeError OStorePageBIOS::read (
691 sal_uInt32 nAddr, void *pData, sal_uInt32 nSize)
693 // Check precond.
694 if (!m_xLockBytes.is())
695 return store_E_InvalidAccess;
697 // Read Data.
698 return m_xLockBytes->readAt (nAddr, pData, nSize);
702 * write.
703 * Low Level: Precond: initialized, writeable, exclusive access.
705 storeError OStorePageBIOS::write (
706 sal_uInt32 nAddr, const void *pData, sal_uInt32 nSize)
708 // Check precond.
709 if (!m_xLockBytes.is())
710 return store_E_InvalidAccess;
711 if (!m_bWriteable)
712 return store_E_AccessViolation;
714 // Write Data.
715 return m_xLockBytes->writeAt (nAddr, pData, nSize);
719 * acquirePage.
720 * Precond: initialized.
722 storeError OStorePageBIOS::acquirePage (
723 const OStorePageDescriptor& rDescr, storeAccessMode eMode)
725 // Acquire exclusive access.
726 osl::MutexGuard aGuard (m_aMutex);
728 // Check precond.
729 if (!m_xLockBytes.is())
730 return store_E_InvalidAccess;
732 // Check access mode.
733 if (!(m_bWriteable || (eMode == storeAccessMode::ReadOnly)))
734 return store_E_AccessViolation;
736 // Find access control list entry.
737 Ace * ace = Ace::find (&m_ace_head, rDescr.m_nAddr);
738 if (ace->m_addr == rDescr.m_nAddr)
740 // Acquire existing entry (with ShareDenyWrite).
741 if (eMode == storeAccessMode::ReadOnly)
742 ace->m_used += 1;
743 else
744 return store_E_AccessViolation;
746 else
748 // Insert new entry.
749 Ace * entry = AceCache::get().create (rDescr.m_nAddr);
750 if (!entry)
751 return store_E_OutOfMemory;
752 Ace::insert (ace, entry);
755 // Increment total referer count and finish.
756 m_ace_head.m_used += 1;
757 return store_E_None;
761 * releasePage.
762 * Precond: initialized.
764 storeError OStorePageBIOS::releasePage (const OStorePageDescriptor& rDescr)
766 // Acquire exclusive access.
767 osl::MutexGuard aGuard (m_aMutex);
769 // Check precond.
770 if (!m_xLockBytes.is())
771 return store_E_InvalidAccess;
773 // Find access control list entry.
774 Ace * ace = Ace::find (&m_ace_head, rDescr.m_nAddr);
775 if (ace->m_addr != rDescr.m_nAddr)
776 return store_E_NotExists;
778 // Release existing entry.
779 if (ace->m_used > 1)
780 ace->m_used -= 1;
781 else
782 AceCache::get().destroy (ace);
784 // Decrement total referer count and finish.
785 m_ace_head.m_used -= 1;
786 return store_E_None;
790 * allocate.
791 * Precond: initialized, writeable.
793 storeError OStorePageBIOS::allocate (
794 OStorePageObject& rPage)
796 // Acquire exclusive access.
797 osl::MutexGuard aGuard (m_aMutex);
799 // Check precond.
800 if (!m_xLockBytes.is())
801 return store_E_InvalidAccess;
802 if (!m_bWriteable)
803 return store_E_AccessViolation;
805 // Check allocation type.
806 storeError eErrCode = store_E_None;
807 // Try freelist head.
808 PageData aPageHead;
809 eErrCode = m_pSuper->unusedHead (*this, aPageHead);
810 if (eErrCode != store_E_None)
811 return eErrCode;
813 sal_uInt32 const nAddr = aPageHead.location();
814 if (nAddr != STORE_PAGE_NULL)
816 // Save page.
817 eErrCode = saveObjectAt_Impl (rPage, nAddr);
818 if (eErrCode != store_E_None)
819 return eErrCode;
821 // Pop freelist head and finish.
822 return m_pSuper->unusedPop (*this, aPageHead);
825 // Allocate from EOF. Determine current size.
826 sal_uInt32 nSize = STORE_PAGE_NULL;
827 eErrCode = m_xLockBytes->getSize (nSize);
828 if (eErrCode != store_E_None)
829 return eErrCode;
831 // Save page at current EOF.
832 return saveObjectAt_Impl (rPage, nSize);
836 * free.
837 * Precond: initialized, writeable.
839 storeError OStorePageBIOS::free (sal_uInt32 nAddr)
841 // Acquire exclusive access.
842 osl::MutexGuard aGuard (m_aMutex);
844 // Check precond.
845 if (!m_xLockBytes.is())
846 return store_E_InvalidAccess;
847 if (!m_bWriteable)
848 return store_E_AccessViolation;
850 // Invalidate cache.
851 (void) m_xCache->removePageAt (nAddr);
853 // Push onto freelist.
854 return m_pSuper->unusedPush (*this, nAddr);
858 * loadObjectAt.
859 * Precond: initialized, readable.
861 storeError OStorePageBIOS::loadObjectAt (OStorePageObject & rPage, sal_uInt32 nAddr)
863 // Acquire exclusive access.
864 osl::MutexGuard aGuard (m_aMutex);
866 // Check precond.
867 if (!m_xLockBytes.is())
868 return store_E_InvalidAccess;
870 return loadObjectAt_Impl (rPage, nAddr);
874 * loadObjectAt_Impl.
875 * Internal: Precond: initialized, readable, exclusive access.
877 storeError OStorePageBIOS::loadObjectAt_Impl (OStorePageObject & rPage, sal_uInt32 nAddr)
879 storeError eErrCode = m_xCache->lookupPageAt (rPage.get(), nAddr);
880 if (eErrCode != store_E_NotExists)
881 return eErrCode;
883 // Read page.
884 eErrCode = m_xLockBytes->readPageAt (rPage.get(), nAddr);
885 if (eErrCode != store_E_None)
886 return eErrCode;
888 // Verify page.
889 eErrCode = rPage.verify (nAddr);
890 if (eErrCode != store_E_None)
891 return eErrCode;
893 // Mark page as clean.
894 rPage.clean();
896 // Cache page.
897 return m_xCache->insertPageAt (rPage.get(), nAddr);
901 * saveObjectAt.
902 * Precond: initialized, writeable.
904 storeError OStorePageBIOS::saveObjectAt (OStorePageObject & rPage, sal_uInt32 nAddr)
906 // Acquire exclusive access.
907 osl::MutexGuard aGuard (m_aMutex);
909 // Check precond.
910 if (!m_xLockBytes.is())
911 return store_E_InvalidAccess;
912 if (!m_bWriteable)
913 return store_E_AccessViolation;
915 // Save Page.
916 return saveObjectAt_Impl (rPage, nAddr);
920 * saveObjectAt_Impl.
921 * Internal: Precond: initialized, writeable, exclusive access.
923 storeError OStorePageBIOS::saveObjectAt_Impl (OStorePageObject & rPage, sal_uInt32 nAddr)
925 // Guard page (incl. set location).
926 storeError eErrCode = rPage.guard (nAddr);
927 if (eErrCode != store_E_None)
928 return eErrCode;
930 // Write page.
931 eErrCode = m_xLockBytes->writePageAt(rPage.get(), nAddr);
932 if (eErrCode != store_E_None)
933 return eErrCode;
935 // Mark page as clean.
936 rPage.clean();
938 // Cache page.
939 return m_xCache->updatePageAt (rPage.get(), nAddr);
943 * close.
944 * Precond: none.
946 storeError OStorePageBIOS::close()
948 // Acquire exclusive access.
949 osl::MutexGuard aGuard (m_aMutex);
951 // Cleanup.
952 cleanup_Impl();
954 // Done.
955 return store_E_None;
959 * flush.
960 * Precond: initialized.
962 storeError OStorePageBIOS::flush()
964 // Acquire exclusive access.
965 osl::MutexGuard aGuard (m_aMutex);
967 // Check precond.
968 if (!m_xLockBytes.is())
969 return store_E_InvalidAccess;
971 // Flush LockBytes and finish.
972 return m_xLockBytes->flush();
975 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */