Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / store / source / storbios.cxx
blobaf74091632ca2cade21e400781f8125a432a8640
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/log.hxx>
27 #include <rtl/alloc.h>
28 #include <rtl/ref.hxx>
30 #include <osl/diagnose.h>
31 #include <osl/mutex.hxx>
33 #include <store/types.h>
34 #include "lockbyte.hxx"
35 #include "storcach.hxx"
37 using namespace store;
39 constexpr sal_uInt32 STORE_MAGIC_SUPERBLOCK = 0x484D5343;
41 namespace {
43 struct OStoreSuperBlock
45 typedef OStorePageGuard G;
46 typedef OStorePageDescriptor D;
47 typedef OStorePageLink L;
49 G m_aGuard;
50 D m_aDescr;
51 sal_uInt32 m_nMarked;
52 L m_aMarked;
53 sal_uInt32 m_nUnused;
54 L m_aUnused;
56 static const size_t theSize = sizeof(G) + sizeof(D) + 2 * (sizeof(L) + sizeof(sal_uInt32));
58 explicit OStoreSuperBlock (sal_uInt16 nPageSize)
59 : m_aGuard (STORE_MAGIC_SUPERBLOCK),
60 m_aDescr (nPageSize, nPageSize, STORE_MINIMUM_PAGESIZE),
61 m_nMarked (store::htonl(0)),
62 m_aMarked (0),
63 m_nUnused (store::htonl(0)),
64 m_aUnused (0)
67 bool operator== (const OStoreSuperBlock & rhs) const
69 return ((m_aGuard == rhs.m_aGuard ) &&
70 (m_aDescr == rhs.m_aDescr ) &&
71 (m_nMarked == rhs.m_nMarked) &&
72 (m_aMarked == rhs.m_aMarked) &&
73 (m_nUnused == rhs.m_nUnused) &&
74 (m_aUnused == rhs.m_aUnused) );
77 sal_uInt32 unusedCount() const
79 return store::ntohl(m_nUnused);
82 const L& unusedHead() const
84 return m_aUnused;
87 void unusedInsert (const L& rLink)
89 sal_uInt32 nUnused = unusedCount();
90 m_nUnused = store::htonl(nUnused + 1);
91 m_aUnused = rLink;
94 void unusedRemove (const L& rLink)
96 sal_uInt32 nUnused = unusedCount();
97 m_nUnused = store::htonl(nUnused - 1);
98 m_aUnused = rLink;
101 void unusedReset()
103 m_nUnused = store::htonl(0);
104 m_aUnused = L(0);
107 void guard()
109 sal_uInt32 nCRC32 = rtl_crc32 (0, &m_aGuard.m_nMagic, sizeof(sal_uInt32));
110 nCRC32 = rtl_crc32 (nCRC32, &m_aDescr, static_cast<sal_uInt32>(theSize - sizeof(G)));
111 m_aGuard.m_nCRC32 = store::htonl(nCRC32);
114 storeError verify() const
116 sal_uInt32 nMagic = store::ntohl(m_aGuard.m_nMagic);
117 if (nMagic != STORE_MAGIC_SUPERBLOCK)
118 return store_E_WrongFormat;
120 sal_uInt32 nCRC32 = rtl_crc32 (0, &m_aGuard.m_nMagic, sizeof(sal_uInt32));
121 nCRC32 = rtl_crc32 (nCRC32, &m_aDescr, static_cast<sal_uInt32>(theSize - sizeof(G)));
122 if (m_aGuard.m_nCRC32 != store::htonl(nCRC32))
123 return store_E_InvalidChecksum;
124 else
125 return store_E_None;
131 namespace store
134 struct SuperBlockPage
136 typedef OStoreSuperBlock SuperBlock;
138 SuperBlock m_aSuperOne;
139 SuperBlock m_aSuperTwo;
141 static const size_t theSize = 2 * SuperBlock::theSize;
142 static const sal_uInt16 thePageSize = theSize;
143 static_assert(STORE_MINIMUM_PAGESIZE >= thePageSize, "must be at least thePageSize");
145 static void * operator new (size_t n)
147 return std::malloc(sal::static_int_cast<sal_Size>(n));
150 static void operator delete (void * p)
152 std::free (p);
155 static void * operator new (SAL_UNUSED_PARAMETER size_t, sal_uInt16 nPageSize)
157 return rtl_allocateZeroMemory (sal::static_int_cast<sal_Size>(nPageSize));
160 static void operator delete (void * p, SAL_UNUSED_PARAMETER sal_uInt16)
162 std::free (p);
165 explicit SuperBlockPage (sal_uInt16 nPageSize = thePageSize)
166 : m_aSuperOne(nPageSize),
167 m_aSuperTwo(nPageSize)
170 storeError save (OStorePageBIOS const & rBIOS, sal_uInt32 nSize = theSize)
172 m_aSuperOne.guard();
173 m_aSuperTwo = m_aSuperOne;
174 return rBIOS.write (0, this, nSize);
177 /** Page allocation.
179 storeError unusedHead (
180 OStorePageBIOS const & rBIOS,
181 PageData & rPageHead);
183 storeError unusedPop (
184 OStorePageBIOS const & rBIOS,
185 PageData const & rPageHead);
187 storeError unusedPush (
188 OStorePageBIOS const & rBIOS,
189 sal_uInt32 nAddr);
191 storeError verify (OStorePageBIOS const & rBIOS);
194 } // namespace store
197 Get freelist head (alloc page, step 1).
199 storeError SuperBlockPage::unusedHead (OStorePageBIOS const & rBIOS, PageData & rPageHead)
201 storeError eErrCode = verify (rBIOS);
202 if (eErrCode != store_E_None)
203 return eErrCode;
205 // Check freelist head.
206 OStorePageLink const aListHead (m_aSuperOne.unusedHead());
207 if (aListHead.location() == 0)
209 // Freelist empty, see SuperBlock::ctor().
210 rPageHead.location (STORE_PAGE_NULL);
211 return store_E_None;
214 // Load PageHead.
215 eErrCode = rBIOS.read (aListHead.location(), &rPageHead, PageData::theSize);
216 if (eErrCode != store_E_None)
217 return eErrCode;
219 eErrCode = rPageHead.verify (aListHead.location());
220 if (eErrCode != store_E_None)
221 return eErrCode;
223 // Verify page is unused.
224 sal_uInt32 const nAddr = rPageHead.m_aUnused.location();
225 if (nAddr == STORE_PAGE_NULL)
227 SAL_WARN("store", "store::SuperBlock::unusedHead(): page not free");
229 // Page in use.
230 rPageHead.location (STORE_PAGE_NULL);
232 // Recovery: Reset freelist to empty.
233 m_aSuperOne.unusedReset();
234 eErrCode = save (rBIOS);
236 return eErrCode;
240 Pop freelist head (alloc page, step 2).
242 storeError SuperBlockPage::unusedPop (OStorePageBIOS const & rBIOS, PageData const & rPageHead)
244 sal_uInt32 const nAddr = rPageHead.m_aUnused.location();
245 OSL_PRECOND(nAddr != STORE_PAGE_NULL, "store::SuperBlock::unusedPop(): page not free");
246 if (nAddr == STORE_PAGE_NULL)
247 return store_E_CantSeek;
249 // Pop from FreeList.
250 OStorePageLink const aListHead (nAddr);
251 m_aSuperOne.unusedRemove (aListHead);
252 return save (rBIOS);
256 Push new freelist head.
258 storeError SuperBlockPage::unusedPush (OStorePageBIOS const & rBIOS, sal_uInt32 nAddr)
260 storeError eErrCode = verify (rBIOS);
261 if (eErrCode != store_E_None)
262 return eErrCode;
264 PageData aPageHead;
265 eErrCode = rBIOS.read (nAddr, &aPageHead, PageData::theSize);
266 if (eErrCode != store_E_None)
267 return eErrCode;
269 eErrCode = aPageHead.verify (nAddr);
270 if (eErrCode != store_E_None)
271 return eErrCode;
273 aPageHead.m_aUnused = m_aSuperOne.unusedHead();
274 aPageHead.guard (nAddr);
276 eErrCode = rBIOS.write (nAddr, &aPageHead, PageData::theSize);
277 if (eErrCode != store_E_None)
278 return eErrCode;
280 OStorePageLink const aListHead (nAddr);
281 m_aSuperOne.unusedInsert(aListHead);
282 return save (rBIOS);
286 Verify (with repair).
288 storeError SuperBlockPage::verify (OStorePageBIOS const & rBIOS)
290 // Verify 1st copy.
291 storeError eErrCode = m_aSuperOne.verify();
292 if (eErrCode == store_E_None)
294 // Ok. Verify 2nd copy.
295 eErrCode = m_aSuperTwo.verify();
296 if (eErrCode == store_E_None)
298 // Ok. Ensure identical copies (1st copy wins).
299 if (!(m_aSuperOne == m_aSuperTwo))
301 // Different. Replace 2nd copy with 1st copy.
302 m_aSuperTwo = m_aSuperOne;
304 // Write back.
305 if (rBIOS.isWriteable())
306 eErrCode = rBIOS.write (0, this, theSize);
307 else
308 eErrCode = store_E_None;
311 else
313 // Failure. Replace 2nd copy with 1st copy.
314 m_aSuperTwo = m_aSuperOne;
316 // Write back.
317 if (rBIOS.isWriteable())
318 eErrCode = rBIOS.write (0, this, theSize);
319 else
320 eErrCode = store_E_None;
323 else
325 // Failure. Verify 2nd copy.
326 eErrCode = m_aSuperTwo.verify();
327 if (eErrCode == store_E_None)
329 // Ok. Replace 1st copy with 2nd copy.
330 m_aSuperOne = m_aSuperTwo;
332 // Write back.
333 if (rBIOS.isWriteable())
334 eErrCode = rBIOS.write (0, this, theSize);
335 else
336 eErrCode = store_E_None;
338 else
340 // Double Failure.
341 SAL_WARN("store", "OStoreSuperBlockPage::verify(): double failure.");
345 // Done.
346 return eErrCode;
349 OStorePageBIOS::Ace::Ace()
350 : m_next (this), m_prev (this), m_addr (STORE_PAGE_NULL), m_used (0)
353 OStorePageBIOS::Ace::~Ace()
355 m_next->m_prev = m_prev;
356 m_prev->m_next = m_next;
360 SAL_CALL OStorePageBIOS::Ace::constructor (
361 void * obj, SAL_UNUSED_PARAMETER void*)
363 Ace * ace = static_cast<Ace*>(obj);
364 ace->m_next = ace->m_prev = ace;
365 return 1;
368 OStorePageBIOS::Ace *
369 OStorePageBIOS::Ace::find (OStorePageBIOS::Ace * head, sal_uInt32 addr)
371 OStorePageBIOS::Ace * entry;
372 for (entry = head->m_next; entry != head; entry = entry->m_next)
374 if (entry->m_addr >= addr)
375 return entry;
377 return head;
380 void
381 OStorePageBIOS::Ace::insert (OStorePageBIOS::Ace * head, OStorePageBIOS::Ace * entry)
383 // insert entry at queue tail (before head).
384 entry->m_next = head;
385 entry->m_prev = head->m_prev;
386 head->m_prev = entry;
387 entry->m_prev->m_next = entry;
390 namespace store
393 class OStorePageBIOS::AceCache
395 rtl_cache_type * m_ace_cache;
397 public:
398 static AceCache & get();
400 OStorePageBIOS::Ace *
401 create (sal_uInt32 addr);
403 void
404 destroy (OStorePageBIOS::Ace * ace);
406 protected:
407 AceCache();
408 ~AceCache();
411 } // namespace store
413 OStorePageBIOS::AceCache &
414 OStorePageBIOS::AceCache::get()
416 static AceCache g_ace_cache;
417 return g_ace_cache;
420 OStorePageBIOS::AceCache::AceCache()
422 m_ace_cache = rtl_cache_create (
423 "store_ace_cache",
424 sizeof (OStorePageBIOS::Ace),
425 0, // objalign
426 OStorePageBIOS::Ace::constructor,
427 nullptr, // destructor,
428 nullptr, // reclaim,
429 nullptr, // userarg,
430 nullptr, // default source,
431 0 // flags
435 OStorePageBIOS::AceCache::~AceCache()
437 rtl_cache_destroy (m_ace_cache);
438 m_ace_cache = nullptr;
441 OStorePageBIOS::Ace *
442 OStorePageBIOS::AceCache::create (sal_uInt32 addr)
444 Ace * ace = static_cast<Ace*>(rtl_cache_alloc (m_ace_cache));
445 if (ace != nullptr)
447 // verify invariant state.
448 OSL_ASSERT((ace->m_next == ace) && (ace->m_prev == ace));
450 // initialize.
451 ace->m_addr = addr;
452 ace->m_used = 1;
454 return ace;
457 void
458 OStorePageBIOS::AceCache::destroy (OStorePageBIOS::Ace * ace)
460 if (ace != nullptr)
462 // remove from queue (if any).
463 ace->m_next->m_prev = ace->m_prev;
464 ace->m_prev->m_next = ace->m_next;
466 // restore invariant state.
467 ace->m_next = ace->m_prev = ace;
469 // return to cache.
470 rtl_cache_free (m_ace_cache, ace);
474 OStorePageBIOS::OStorePageBIOS()
475 : m_bWriteable (false)
479 OStorePageBIOS::~OStorePageBIOS()
481 cleanup_Impl();
484 storeError OStorePageBIOS::initialize (
485 ILockBytes * pLockBytes,
486 storeAccessMode eAccessMode,
487 sal_uInt16 & rnPageSize)
489 // Acquire exclusive access.
490 osl::MutexGuard aGuard (m_aMutex);
492 // Initialize.
493 storeError eErrCode = initialize_Impl (pLockBytes, eAccessMode, rnPageSize);
494 if (eErrCode != store_E_None)
496 // Cleanup.
497 cleanup_Impl();
499 return eErrCode;
503 initialize_Impl.
504 @pre exclusive access
506 storeError OStorePageBIOS::initialize_Impl (
507 ILockBytes * pLockBytes,
508 storeAccessMode eAccessMode,
509 sal_uInt16 & rnPageSize)
511 // Cleanup.
512 cleanup_Impl();
514 // Initialize.
515 m_xLockBytes = pLockBytes;
516 if (!m_xLockBytes.is())
517 return store_E_InvalidParameter;
518 m_bWriteable = (eAccessMode != storeAccessMode::ReadOnly);
520 // Check access mode.
521 storeError eErrCode = store_E_None;
522 if (eAccessMode != storeAccessMode::Create)
524 // Load SuperBlock page.
525 m_pSuper.reset(new SuperBlockPage());
527 eErrCode = read (0, m_pSuper.get(), SuperBlockPage::theSize);
528 if (eErrCode == store_E_None)
530 // Verify SuperBlock page (with repair).
531 eErrCode = m_pSuper->verify (*this);
534 else
536 // Truncate to zero length.
537 eErrCode = m_xLockBytes->setSize(0);
538 if (eErrCode != store_E_None)
539 return eErrCode;
541 // Mark as not existing.
542 eErrCode = store_E_NotExists;
545 if (eErrCode != store_E_None)
547 // Check reason.
548 if (eErrCode != store_E_NotExists)
549 return eErrCode;
551 // Check mode.
552 if (eAccessMode == storeAccessMode::ReadOnly)
553 return store_E_NotExists;
554 if (eAccessMode == storeAccessMode::ReadWrite)
555 return store_E_NotExists;
557 // Check PageSize.
558 if ((STORE_MINIMUM_PAGESIZE > rnPageSize) || (rnPageSize > STORE_MAXIMUM_PAGESIZE))
559 return store_E_InvalidParameter;
560 rnPageSize = ((rnPageSize + STORE_MINIMUM_PAGESIZE - 1) & ~(STORE_MINIMUM_PAGESIZE - 1));
562 // Create initial page (w/ SuperBlock).
563 m_pSuper.reset(new(rnPageSize) SuperBlockPage(rnPageSize));
564 eErrCode = m_pSuper->save (*this, rnPageSize);
566 if (eErrCode == store_E_None)
568 // Obtain page size.
569 rnPageSize = store::ntohs(m_pSuper->m_aSuperOne.m_aDescr.m_nSize);
571 // Create page allocator.
572 eErrCode = m_xLockBytes->initialize (m_xAllocator, rnPageSize);
573 if (eErrCode != store_E_None)
574 return eErrCode;
576 // Create page cache.
577 eErrCode = PageCache_createInstance (m_xCache, rnPageSize);
579 return eErrCode;
583 @pre exclusive access.
585 void OStorePageBIOS::cleanup_Impl()
587 // Check referer count.
588 if (m_ace_head.m_used > 0)
590 // Report remaining referer count.
591 SAL_INFO("store", "referer count: " << m_ace_head.m_used);
592 for (Ace * ace = m_ace_head.m_next; ace != &m_ace_head; ace = m_ace_head.m_next)
594 m_ace_head.m_used -= ace->m_used;
595 AceCache::get().destroy (ace);
597 OSL_ENSURE(m_ace_head.m_used == 0, "store::PageBIOS::cleanup_Impl(): logic error");
600 // Release SuperBlock page.
601 m_pSuper.reset();
603 // Release PageCache.
604 m_xCache.clear();
606 // Release PageAllocator.
607 m_xAllocator.clear();
609 // Release LockBytes.
610 m_xLockBytes.clear();
614 @pre initialized, exclusive access.
616 storeError OStorePageBIOS::read (
617 sal_uInt32 nAddr, void *pData, sal_uInt32 nSize) const
619 // Check precond.
620 if (!m_xLockBytes.is())
621 return store_E_InvalidAccess;
623 // Read Data.
624 return m_xLockBytes->readAt (nAddr, pData, nSize);
628 @pre initialized, writeable, exclusive access.
630 storeError OStorePageBIOS::write (
631 sal_uInt32 nAddr, const void *pData, sal_uInt32 nSize) const
633 // Check precond.
634 if (!m_xLockBytes.is())
635 return store_E_InvalidAccess;
636 if (!m_bWriteable)
637 return store_E_AccessViolation;
639 // Write Data.
640 return m_xLockBytes->writeAt (nAddr, pData, nSize);
644 @pre initialized.
646 storeError OStorePageBIOS::acquirePage (
647 const OStorePageDescriptor& rDescr, storeAccessMode eMode)
649 // Acquire exclusive access.
650 osl::MutexGuard aGuard (m_aMutex);
652 // Check precond.
653 if (!m_xLockBytes.is())
654 return store_E_InvalidAccess;
656 // Check access mode.
657 if (!(m_bWriteable || (eMode == storeAccessMode::ReadOnly)))
658 return store_E_AccessViolation;
660 // Find access control list entry.
661 Ace * ace = Ace::find (&m_ace_head, rDescr.m_nAddr);
662 if (ace->m_addr == rDescr.m_nAddr)
664 // Acquire existing entry (with ShareDenyWrite).
665 if (eMode == storeAccessMode::ReadOnly)
666 ace->m_used += 1;
667 else
668 return store_E_AccessViolation;
670 else
672 // Insert new entry.
673 Ace * entry = AceCache::get().create (rDescr.m_nAddr);
674 if (!entry)
675 return store_E_OutOfMemory;
676 Ace::insert (ace, entry);
679 // Increment total referer count and finish.
680 m_ace_head.m_used += 1;
681 return store_E_None;
685 @pre initialized.
687 storeError OStorePageBIOS::releasePage (const OStorePageDescriptor& rDescr)
689 // Acquire exclusive access.
690 osl::MutexGuard aGuard (m_aMutex);
692 // Check precond.
693 if (!m_xLockBytes.is())
694 return store_E_InvalidAccess;
696 // Find access control list entry.
697 Ace * ace = Ace::find (&m_ace_head, rDescr.m_nAddr);
698 if (ace->m_addr != rDescr.m_nAddr)
699 return store_E_NotExists;
701 // Release existing entry.
702 if (ace->m_used > 1)
703 ace->m_used -= 1;
704 else
705 AceCache::get().destroy (ace);
707 // Decrement total referer count and finish.
708 m_ace_head.m_used -= 1;
709 return store_E_None;
713 @pre initialized, writeable.
715 storeError OStorePageBIOS::allocate (
716 OStorePageObject& rPage)
718 // Acquire exclusive access.
719 osl::MutexGuard aGuard (m_aMutex);
721 // Check precond.
722 if (!m_xLockBytes.is())
723 return store_E_InvalidAccess;
724 if (!m_bWriteable)
725 return store_E_AccessViolation;
727 // Check allocation type.
728 storeError eErrCode = store_E_None;
729 // Try freelist head.
730 PageData aPageHead;
731 eErrCode = m_pSuper->unusedHead (*this, aPageHead);
732 if (eErrCode != store_E_None)
733 return eErrCode;
735 sal_uInt32 const nAddr = aPageHead.location();
736 if (nAddr != STORE_PAGE_NULL)
738 // Save page.
739 eErrCode = saveObjectAt_Impl (rPage, nAddr);
740 if (eErrCode != store_E_None)
741 return eErrCode;
743 // Pop freelist head and finish.
744 return m_pSuper->unusedPop (*this, aPageHead);
747 // Allocate from EOF. Determine current size.
748 sal_uInt32 nSize = STORE_PAGE_NULL;
749 eErrCode = m_xLockBytes->getSize (nSize);
750 if (eErrCode != store_E_None)
751 return eErrCode;
753 // Save page at current EOF.
754 return saveObjectAt_Impl (rPage, nSize);
758 @pre initialized, writeable.
760 storeError OStorePageBIOS::free (sal_uInt32 nAddr)
762 // Acquire exclusive access.
763 osl::MutexGuard aGuard (m_aMutex);
765 // Check precond.
766 if (!m_xLockBytes.is())
767 return store_E_InvalidAccess;
768 if (!m_bWriteable)
769 return store_E_AccessViolation;
771 // Invalidate cache.
772 (void) m_xCache->removePageAt (nAddr);
774 // Push onto freelist.
775 return m_pSuper->unusedPush (*this, nAddr);
779 @pre initialized, readable.
781 storeError OStorePageBIOS::loadObjectAt (OStorePageObject & rPage, sal_uInt32 nAddr)
783 // Acquire exclusive access.
784 osl::MutexGuard aGuard (m_aMutex);
786 // Check precond.
787 if (!m_xLockBytes.is())
788 return store_E_InvalidAccess;
790 return loadObjectAt_Impl (rPage, nAddr);
794 @pre initialized, readable, exclusive access.
796 storeError OStorePageBIOS::loadObjectAt_Impl (OStorePageObject & rPage, sal_uInt32 nAddr) const
798 storeError eErrCode = m_xCache->lookupPageAt (rPage.get(), nAddr);
799 if (eErrCode != store_E_NotExists)
800 return eErrCode;
802 // Read page.
803 eErrCode = m_xLockBytes->readPageAt (rPage.get(), nAddr);
804 if (eErrCode != store_E_None)
805 return eErrCode;
807 // Verify page.
808 eErrCode = rPage.verify (nAddr);
809 if (eErrCode != store_E_None)
810 return eErrCode;
812 // Mark page as clean.
813 rPage.clean();
815 // Cache page.
816 return m_xCache->insertPageAt (rPage.get(), nAddr);
820 @pre initialized, writeable.
822 storeError OStorePageBIOS::saveObjectAt (OStorePageObject & rPage, sal_uInt32 nAddr)
824 // Acquire exclusive access.
825 osl::MutexGuard aGuard (m_aMutex);
827 // Check precond.
828 if (!m_xLockBytes.is())
829 return store_E_InvalidAccess;
830 if (!m_bWriteable)
831 return store_E_AccessViolation;
833 // Save Page.
834 return saveObjectAt_Impl (rPage, nAddr);
838 @pre initialized, writeable, exclusive access.
840 storeError OStorePageBIOS::saveObjectAt_Impl (OStorePageObject & rPage, sal_uInt32 nAddr) const
842 // Guard page (incl. set location).
843 storeError eErrCode = rPage.guard (nAddr);
844 if (eErrCode != store_E_None)
845 return eErrCode;
847 // Write page.
848 eErrCode = m_xLockBytes->writePageAt(rPage.get(), nAddr);
849 if (eErrCode != store_E_None)
850 return eErrCode;
852 // Mark page as clean.
853 rPage.clean();
855 // Cache page.
856 return m_xCache->updatePageAt (rPage.get(), nAddr);
860 @pre none.
862 storeError OStorePageBIOS::close()
864 // Acquire exclusive access.
865 osl::MutexGuard aGuard (m_aMutex);
867 // Cleanup.
868 cleanup_Impl();
870 // Done.
871 return store_E_None;
875 @pre initialized.
877 storeError OStorePageBIOS::flush()
879 // Acquire exclusive access.
880 osl::MutexGuard aGuard (m_aMutex);
882 // Check precond.
883 if (!m_xLockBytes.is())
884 return store_E_InvalidAccess;
886 // Flush LockBytes and finish.
887 return m_xLockBytes->flush();
890 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */