vcl: sfx2: LOK: Support per-view popup windows
[LibreOffice.git] / store / source / storbios.cxx
bloba98f4e9a35a373525a677e93d49328574efe4917
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 /*========================================================================
41 * OStoreSuperBlock.
43 *======================================================================*/
44 #define STORE_MAGIC_SUPERBLOCK sal_uInt32(0x484D5343)
46 namespace {
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 = rtl_crc32 (0, &m_aGuard.m_nMagic, sizeof(sal_uInt32));
123 nCRC32 = rtl_crc32 (nCRC32, &m_aDescr, static_cast<sal_uInt32>(theSize - sizeof(G)));
124 m_aGuard.m_nCRC32 = store::htonl(nCRC32);
127 /** verify (external representation).
129 storeError verify() const
131 sal_uInt32 nMagic = store::ntohl(m_aGuard.m_nMagic);
132 if (nMagic != STORE_MAGIC_SUPERBLOCK)
133 return store_E_WrongFormat;
135 sal_uInt32 nCRC32 = rtl_crc32 (0, &m_aGuard.m_nMagic, sizeof(sal_uInt32));
136 nCRC32 = rtl_crc32 (nCRC32, &m_aDescr, static_cast<sal_uInt32>(theSize - sizeof(G)));
137 if (m_aGuard.m_nCRC32 != store::htonl(nCRC32))
138 return store_E_InvalidChecksum;
139 else
140 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 std::malloc(sal::static_int_cast<sal_Size>(n));
175 static void operator delete (void * p)
177 std::free (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 std::free (p);
189 /** Construction.
191 explicit SuperBlockPage (sal_uInt16 nPageSize = thePageSize)
192 : m_aSuperOne(nPageSize),
193 m_aSuperTwo(nPageSize)
196 /** save.
198 storeError save (OStorePageBIOS const & 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 const & rBIOS,
209 PageData & rPageHead);
211 storeError unusedPop (
212 OStorePageBIOS const & rBIOS,
213 PageData const & rPageHead);
215 storeError unusedPush (
216 OStorePageBIOS const & rBIOS,
217 sal_uInt32 nAddr);
219 /** verify (with repair).
221 storeError verify (OStorePageBIOS const & rBIOS);
224 } // namespace store
226 /*========================================================================
228 * SuperBlockPage implementation.
230 *======================================================================*/
232 * unusedHead(): get freelist head (alloc page, step 1).
234 storeError SuperBlockPage::unusedHead (OStorePageBIOS const & 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 const & 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 const & 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 const & 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 SAL_WARN("store", "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 *======================================================================*/
464 OStorePageBIOS::AceCache &
465 OStorePageBIOS::AceCache::get()
467 static AceCache g_ace_cache;
468 return g_ace_cache;
471 OStorePageBIOS::AceCache::AceCache()
473 m_ace_cache = rtl_cache_create (
474 "store_ace_cache",
475 sizeof (OStorePageBIOS::Ace),
476 0, // objalign
477 OStorePageBIOS::Ace::constructor,
478 nullptr, // destructor,
479 nullptr, // reclaim,
480 nullptr, // userarg,
481 nullptr, // default source,
482 0 // flags
486 OStorePageBIOS::AceCache::~AceCache()
488 rtl_cache_destroy (m_ace_cache);
489 m_ace_cache = nullptr;
492 OStorePageBIOS::Ace *
493 OStorePageBIOS::AceCache::create (sal_uInt32 addr)
495 Ace * ace = static_cast<Ace*>(rtl_cache_alloc (m_ace_cache));
496 if (ace != nullptr)
498 // verify invariant state.
499 OSL_ASSERT((ace->m_next == ace) && (ace->m_prev == ace));
501 // initialize.
502 ace->m_addr = addr;
503 ace->m_used = 1;
505 return ace;
508 void
509 OStorePageBIOS::AceCache::destroy (OStorePageBIOS::Ace * ace)
511 if (ace != nullptr)
513 // remove from queue (if any).
514 ace->m_next->m_prev = ace->m_prev;
515 ace->m_prev->m_next = ace->m_next;
517 // restore invariant state.
518 ace->m_next = ace->m_prev = ace;
520 // return to cache.
521 rtl_cache_free (m_ace_cache, ace);
525 /*========================================================================
527 * OStorePageBIOS implementation.
529 *======================================================================*/
531 * OStorePageBIOS.
533 OStorePageBIOS::OStorePageBIOS()
534 : m_bWriteable (false)
539 * ~OStorePageBIOS.
541 OStorePageBIOS::~OStorePageBIOS()
543 cleanup_Impl();
547 * initialize.
548 * Precond: none.
550 storeError OStorePageBIOS::initialize (
551 ILockBytes * pLockBytes,
552 storeAccessMode eAccessMode,
553 sal_uInt16 & rnPageSize)
555 // Acquire exclusive access.
556 osl::MutexGuard aGuard (m_aMutex);
558 // Initialize.
559 storeError eErrCode = initialize_Impl (pLockBytes, eAccessMode, rnPageSize);
560 if (eErrCode != store_E_None)
562 // Cleanup.
563 cleanup_Impl();
565 return eErrCode;
569 * initialize_Impl.
570 * Internal: Precond: exclusive access.
572 storeError OStorePageBIOS::initialize_Impl (
573 ILockBytes * pLockBytes,
574 storeAccessMode eAccessMode,
575 sal_uInt16 & rnPageSize)
577 // Cleanup.
578 cleanup_Impl();
580 // Initialize.
581 m_xLockBytes = pLockBytes;
582 if (!m_xLockBytes.is())
583 return store_E_InvalidParameter;
584 m_bWriteable = (eAccessMode != storeAccessMode::ReadOnly);
586 // Check access mode.
587 storeError eErrCode = store_E_None;
588 if (eAccessMode != storeAccessMode::Create)
590 // Load SuperBlock page.
591 m_pSuper.reset(new SuperBlockPage());
593 eErrCode = read (0, m_pSuper.get(), SuperBlockPage::theSize);
594 if (eErrCode == store_E_None)
596 // Verify SuperBlock page (with repair).
597 eErrCode = m_pSuper->verify (*this);
600 else
602 // Truncate to zero length.
603 eErrCode = m_xLockBytes->setSize(0);
604 if (eErrCode != store_E_None)
605 return eErrCode;
607 // Mark as not existing.
608 eErrCode = store_E_NotExists;
611 if (eErrCode != store_E_None)
613 // Check reason.
614 if (eErrCode != store_E_NotExists)
615 return eErrCode;
617 // Check mode.
618 if (eAccessMode == storeAccessMode::ReadOnly)
619 return store_E_NotExists;
620 if (eAccessMode == storeAccessMode::ReadWrite)
621 return store_E_NotExists;
623 // Check PageSize.
624 if ((STORE_MINIMUM_PAGESIZE > rnPageSize) || (rnPageSize > STORE_MAXIMUM_PAGESIZE))
625 return store_E_InvalidParameter;
626 rnPageSize = ((rnPageSize + STORE_MINIMUM_PAGESIZE - 1) & ~(STORE_MINIMUM_PAGESIZE - 1));
628 // Create initial page (w/ SuperBlock).
629 m_pSuper.reset(new(rnPageSize) SuperBlockPage(rnPageSize));
630 eErrCode = m_pSuper->save (*this, rnPageSize);
632 if (eErrCode == store_E_None)
634 // Obtain page size.
635 rnPageSize = store::ntohs(m_pSuper->m_aSuperOne.m_aDescr.m_nSize);
637 // Create page allocator.
638 eErrCode = m_xLockBytes->initialize (m_xAllocator, rnPageSize);
639 if (eErrCode != store_E_None)
640 return eErrCode;
642 // Create page cache.
643 eErrCode = PageCache_createInstance (m_xCache, rnPageSize);
645 return eErrCode;
649 * cleanup_Impl.
650 * Internal: Precond: exclusive access.
652 void OStorePageBIOS::cleanup_Impl()
654 // Check referer count.
655 if (m_ace_head.m_used > 0)
657 // Report remaining referer count.
658 SAL_INFO("store", "referer count: " << m_ace_head.m_used);
659 for (Ace * ace = m_ace_head.m_next; ace != &m_ace_head; ace = m_ace_head.m_next)
661 m_ace_head.m_used -= ace->m_used;
662 AceCache::get().destroy (ace);
664 OSL_ENSURE(m_ace_head.m_used == 0, "store::PageBIOS::cleanup_Impl(): logic error");
667 // Release SuperBlock page.
668 m_pSuper.reset();
670 // Release PageCache.
671 m_xCache.clear();
673 // Release PageAllocator.
674 m_xAllocator.clear();
676 // Release LockBytes.
677 m_xLockBytes.clear();
681 * read.
682 * Low Level: Precond: initialized, exclusive access.
684 storeError OStorePageBIOS::read (
685 sal_uInt32 nAddr, void *pData, sal_uInt32 nSize) const
687 // Check precond.
688 if (!m_xLockBytes.is())
689 return store_E_InvalidAccess;
691 // Read Data.
692 return m_xLockBytes->readAt (nAddr, pData, nSize);
696 * write.
697 * Low Level: Precond: initialized, writeable, exclusive access.
699 storeError OStorePageBIOS::write (
700 sal_uInt32 nAddr, const void *pData, sal_uInt32 nSize) const
702 // Check precond.
703 if (!m_xLockBytes.is())
704 return store_E_InvalidAccess;
705 if (!m_bWriteable)
706 return store_E_AccessViolation;
708 // Write Data.
709 return m_xLockBytes->writeAt (nAddr, pData, nSize);
713 * acquirePage.
714 * Precond: initialized.
716 storeError OStorePageBIOS::acquirePage (
717 const OStorePageDescriptor& rDescr, storeAccessMode eMode)
719 // Acquire exclusive access.
720 osl::MutexGuard aGuard (m_aMutex);
722 // Check precond.
723 if (!m_xLockBytes.is())
724 return store_E_InvalidAccess;
726 // Check access mode.
727 if (!(m_bWriteable || (eMode == storeAccessMode::ReadOnly)))
728 return store_E_AccessViolation;
730 // Find access control list entry.
731 Ace * ace = Ace::find (&m_ace_head, rDescr.m_nAddr);
732 if (ace->m_addr == rDescr.m_nAddr)
734 // Acquire existing entry (with ShareDenyWrite).
735 if (eMode == storeAccessMode::ReadOnly)
736 ace->m_used += 1;
737 else
738 return store_E_AccessViolation;
740 else
742 // Insert new entry.
743 Ace * entry = AceCache::get().create (rDescr.m_nAddr);
744 if (!entry)
745 return store_E_OutOfMemory;
746 Ace::insert (ace, entry);
749 // Increment total referer count and finish.
750 m_ace_head.m_used += 1;
751 return store_E_None;
755 * releasePage.
756 * Precond: initialized.
758 storeError OStorePageBIOS::releasePage (const OStorePageDescriptor& rDescr)
760 // Acquire exclusive access.
761 osl::MutexGuard aGuard (m_aMutex);
763 // Check precond.
764 if (!m_xLockBytes.is())
765 return store_E_InvalidAccess;
767 // Find access control list entry.
768 Ace * ace = Ace::find (&m_ace_head, rDescr.m_nAddr);
769 if (ace->m_addr != rDescr.m_nAddr)
770 return store_E_NotExists;
772 // Release existing entry.
773 if (ace->m_used > 1)
774 ace->m_used -= 1;
775 else
776 AceCache::get().destroy (ace);
778 // Decrement total referer count and finish.
779 m_ace_head.m_used -= 1;
780 return store_E_None;
784 * allocate.
785 * Precond: initialized, writeable.
787 storeError OStorePageBIOS::allocate (
788 OStorePageObject& rPage)
790 // Acquire exclusive access.
791 osl::MutexGuard aGuard (m_aMutex);
793 // Check precond.
794 if (!m_xLockBytes.is())
795 return store_E_InvalidAccess;
796 if (!m_bWriteable)
797 return store_E_AccessViolation;
799 // Check allocation type.
800 storeError eErrCode = store_E_None;
801 // Try freelist head.
802 PageData aPageHead;
803 eErrCode = m_pSuper->unusedHead (*this, aPageHead);
804 if (eErrCode != store_E_None)
805 return eErrCode;
807 sal_uInt32 const nAddr = aPageHead.location();
808 if (nAddr != STORE_PAGE_NULL)
810 // Save page.
811 eErrCode = saveObjectAt_Impl (rPage, nAddr);
812 if (eErrCode != store_E_None)
813 return eErrCode;
815 // Pop freelist head and finish.
816 return m_pSuper->unusedPop (*this, aPageHead);
819 // Allocate from EOF. Determine current size.
820 sal_uInt32 nSize = STORE_PAGE_NULL;
821 eErrCode = m_xLockBytes->getSize (nSize);
822 if (eErrCode != store_E_None)
823 return eErrCode;
825 // Save page at current EOF.
826 return saveObjectAt_Impl (rPage, nSize);
830 * free.
831 * Precond: initialized, writeable.
833 storeError OStorePageBIOS::free (sal_uInt32 nAddr)
835 // Acquire exclusive access.
836 osl::MutexGuard aGuard (m_aMutex);
838 // Check precond.
839 if (!m_xLockBytes.is())
840 return store_E_InvalidAccess;
841 if (!m_bWriteable)
842 return store_E_AccessViolation;
844 // Invalidate cache.
845 (void) m_xCache->removePageAt (nAddr);
847 // Push onto freelist.
848 return m_pSuper->unusedPush (*this, nAddr);
852 * loadObjectAt.
853 * Precond: initialized, readable.
855 storeError OStorePageBIOS::loadObjectAt (OStorePageObject & rPage, sal_uInt32 nAddr)
857 // Acquire exclusive access.
858 osl::MutexGuard aGuard (m_aMutex);
860 // Check precond.
861 if (!m_xLockBytes.is())
862 return store_E_InvalidAccess;
864 return loadObjectAt_Impl (rPage, nAddr);
868 * loadObjectAt_Impl.
869 * Internal: Precond: initialized, readable, exclusive access.
871 storeError OStorePageBIOS::loadObjectAt_Impl (OStorePageObject & rPage, sal_uInt32 nAddr) const
873 storeError eErrCode = m_xCache->lookupPageAt (rPage.get(), nAddr);
874 if (eErrCode != store_E_NotExists)
875 return eErrCode;
877 // Read page.
878 eErrCode = m_xLockBytes->readPageAt (rPage.get(), nAddr);
879 if (eErrCode != store_E_None)
880 return eErrCode;
882 // Verify page.
883 eErrCode = rPage.verify (nAddr);
884 if (eErrCode != store_E_None)
885 return eErrCode;
887 // Mark page as clean.
888 rPage.clean();
890 // Cache page.
891 return m_xCache->insertPageAt (rPage.get(), nAddr);
895 * saveObjectAt.
896 * Precond: initialized, writeable.
898 storeError OStorePageBIOS::saveObjectAt (OStorePageObject & rPage, sal_uInt32 nAddr)
900 // Acquire exclusive access.
901 osl::MutexGuard aGuard (m_aMutex);
903 // Check precond.
904 if (!m_xLockBytes.is())
905 return store_E_InvalidAccess;
906 if (!m_bWriteable)
907 return store_E_AccessViolation;
909 // Save Page.
910 return saveObjectAt_Impl (rPage, nAddr);
914 * saveObjectAt_Impl.
915 * Internal: Precond: initialized, writeable, exclusive access.
917 storeError OStorePageBIOS::saveObjectAt_Impl (OStorePageObject & rPage, sal_uInt32 nAddr) const
919 // Guard page (incl. set location).
920 storeError eErrCode = rPage.guard (nAddr);
921 if (eErrCode != store_E_None)
922 return eErrCode;
924 // Write page.
925 eErrCode = m_xLockBytes->writePageAt(rPage.get(), nAddr);
926 if (eErrCode != store_E_None)
927 return eErrCode;
929 // Mark page as clean.
930 rPage.clean();
932 // Cache page.
933 return m_xCache->updatePageAt (rPage.get(), nAddr);
937 * close.
938 * Precond: none.
940 storeError OStorePageBIOS::close()
942 // Acquire exclusive access.
943 osl::MutexGuard aGuard (m_aMutex);
945 // Cleanup.
946 cleanup_Impl();
948 // Done.
949 return store_E_None;
953 * flush.
954 * Precond: initialized.
956 storeError OStorePageBIOS::flush()
958 // Acquire exclusive access.
959 osl::MutexGuard aGuard (m_aMutex);
961 // Check precond.
962 if (!m_xLockBytes.is())
963 return store_E_InvalidAccess;
965 // Flush LockBytes and finish.
966 return m_xLockBytes->flush();
969 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */