update dev300-m58
[ooovba.git] / store / source / storbios.cxx
blobd1f15dcda247e491a592a028d80c825eba317ad0
1 /*************************************************************************
3 * OpenOffice.org - a multi-platform office productivity suite
5 * $RCSfile: storbios.cxx,v $
7 * $Revision: 1.1.2.3 $
9 * last change: $Author: mhu $ $Date: 2008/10/31 18:28:18 $
11 * The Contents of this file are made available subject to
12 * the terms of GNU Lesser General Public License Version 2.1.
15 * GNU Lesser General Public License Version 2.1
16 * =============================================
17 * Copyright 2005 by Sun Microsystems, Inc.
18 * 901 San Antonio Road, Palo Alto, CA 94303, USA
20 * This library is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU Lesser General Public
22 * License version 2.1, as published by the Free Software Foundation.
24 * This library is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 * Lesser General Public License for more details.
29 * You should have received a copy of the GNU Lesser General Public
30 * License along with this library; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
32 * MA 02111-1307 USA
34 ************************************************************************/
36 // MARKER(update_precomp.py): autogen include statement, do not remove
37 #include "precompiled_store.hxx"
39 #include "storbios.hxx"
41 #include "sal/types.h"
42 #include "sal/macros.h"
44 #include "rtl/alloc.h"
45 #include "rtl/ref.hxx"
47 #include "osl/diagnose.h"
48 #include "osl/mutex.hxx"
50 #include "store/types.h"
51 #include "object.hxx"
52 #include "lockbyte.hxx"
53 #include "storcach.hxx"
55 using namespace store;
57 /*========================================================================
59 * OStoreSuperBlock.
61 *======================================================================*/
62 #define STORE_MAGIC_SUPERBLOCK sal_uInt32(0x484D5343)
64 struct OStoreSuperBlock
66 typedef OStorePageGuard G;
67 typedef OStorePageDescriptor D;
68 typedef OStorePageLink L;
70 /** Representation.
72 G m_aGuard;
73 D m_aDescr;
74 sal_uInt32 m_nMarked;
75 L m_aMarked;
76 sal_uInt32 m_nUnused;
77 L m_aUnused;
79 /** theSize.
81 static const size_t theSize = sizeof(G) + sizeof(D) + 2 * (sizeof(L) + sizeof(sal_uInt32));
83 /** Construction.
85 explicit OStoreSuperBlock (sal_uInt16 nPageSize)
86 : m_aGuard (STORE_MAGIC_SUPERBLOCK),
87 m_aDescr (nPageSize, nPageSize, STORE_MINIMUM_PAGESIZE),
88 m_nMarked (store::htonl(0)),
89 m_aMarked (0),
90 m_nUnused (store::htonl(0)),
91 m_aUnused (0)
94 OStoreSuperBlock (const OStoreSuperBlock& rOther)
95 : m_aGuard (rOther.m_aGuard),
96 m_aDescr (rOther.m_aDescr),
97 m_nMarked (rOther.m_nMarked),
98 m_aMarked (rOther.m_aMarked),
99 m_nUnused (rOther.m_nUnused),
100 m_aUnused (rOther.m_aUnused)
103 OStoreSuperBlock& operator= (const OStoreSuperBlock& rOther)
105 m_aGuard = rOther.m_aGuard;
106 m_aDescr = rOther.m_aDescr;
107 m_nMarked = rOther.m_nMarked;
108 m_aMarked = rOther.m_aMarked;
109 m_nUnused = rOther.m_nUnused;
110 m_aUnused = rOther.m_aUnused;
111 return *this;
114 /** Comparison.
116 sal_Bool operator== (const OStoreSuperBlock& rOther) const
118 return ((m_aGuard == rOther.m_aGuard ) &&
119 (m_aDescr == rOther.m_aDescr ) &&
120 (m_nMarked == rOther.m_nMarked) &&
121 (m_aMarked == rOther.m_aMarked) &&
122 (m_nUnused == rOther.m_nUnused) &&
123 (m_aUnused == rOther.m_aUnused) );
126 /** unused(Count|Head|Insert|Remove|Reset).
128 sal_uInt32 unusedCount (void) const
130 return store::ntohl(m_nUnused);
132 const L& unusedHead (void) const
134 return m_aUnused;
136 void unusedInsert (const L& rLink)
138 sal_uInt32 nUnused = unusedCount();
139 m_nUnused = store::htonl(nUnused + 1);
140 m_aUnused = rLink;
142 void unusedRemove (const L& rLink)
144 sal_uInt32 nUnused = unusedCount();
145 m_nUnused = store::htonl(nUnused - 1);
146 m_aUnused = rLink;
148 void unusedReset (void)
150 m_nUnused = store::htonl(0);
151 m_aUnused = L(0);
154 /** guard (external representation).
156 void guard()
158 sal_uInt32 nCRC32 = 0;
159 nCRC32 = rtl_crc32 (nCRC32, &m_aGuard.m_nMagic, sizeof(sal_uInt32));
160 nCRC32 = rtl_crc32 (nCRC32, &m_aDescr, theSize - sizeof(G));
161 m_aGuard.m_nCRC32 = store::htonl(nCRC32);
164 /** verify (external representation).
166 storeError verify() const
168 sal_uInt32 nMagic = store::ntohl(m_aGuard.m_nMagic);
169 if (nMagic != STORE_MAGIC_SUPERBLOCK)
170 return store_E_WrongFormat;
172 sal_uInt32 nCRC32 = 0;
173 nCRC32 = rtl_crc32 (nCRC32, &m_aGuard.m_nMagic, sizeof(sal_uInt32));
174 nCRC32 = rtl_crc32 (nCRC32, &m_aDescr, theSize - sizeof(G));
175 if (m_aGuard.m_nCRC32 != store::htonl(nCRC32))
176 return store_E_InvalidChecksum;
177 else
178 return store_E_None;
182 /*========================================================================
184 * OStoreStateBlock.
186 *======================================================================*/
187 struct OStoreStateBlock
189 enum StateBits
191 STATE_CLEAN = 0,
192 STATE_CLOSE_WAIT = 1,
193 STATE_FLUSH_WAIT = 2
196 /** Representation.
198 sal_uInt32 m_nState;
200 /** theSize.
202 static const size_t theSize = sizeof(sal_uInt32);
204 /** Construction.
206 OStoreStateBlock()
207 : m_nState (store::htonl(STATE_CLEAN))
210 /** Operation.
212 bool closePending (void) const
214 sal_uInt32 nState = store::ntohl(m_nState);
215 return ((nState & STATE_CLOSE_WAIT) == STATE_CLOSE_WAIT);
217 void closed (void)
219 sal_uInt32 nState = store::ntohl(m_nState);
220 nState &= ~STATE_CLOSE_WAIT;
221 m_nState = store::htonl(nState);
224 bool flushPending (void) const
226 sal_uInt32 nState = store::ntohl(m_nState);
227 return ((nState & STATE_FLUSH_WAIT) == STATE_FLUSH_WAIT);
229 void flushed (void)
231 sal_uInt32 nState = store::ntohl(m_nState);
232 nState &= ~STATE_FLUSH_WAIT;
233 m_nState = store::htonl(nState);
236 void modified (void)
238 sal_uInt32 nState = store::ntohl(m_nState);
239 nState |= (STATE_CLOSE_WAIT | STATE_FLUSH_WAIT);
240 m_nState = store::htonl(nState);
242 void clean (void)
244 sal_uInt32 nState = store::ntohl(m_nState);
245 nState &= ~(STATE_CLOSE_WAIT | STATE_FLUSH_WAIT);
246 m_nState = store::htonl(nState);
250 /*========================================================================
252 * OStoreSuperBlockPage interface.
254 *======================================================================*/
255 namespace store
258 struct OStoreSuperBlockPage
260 typedef OStoreSuperBlock SuperBlock;
261 typedef OStoreStateBlock StateBlock;
263 /** Representation.
265 SuperBlock m_aSuperOne;
266 SuperBlock m_aSuperTwo;
267 StateBlock m_aState;
269 /** theSize.
271 static const size_t theSize = 2 * SuperBlock::theSize + StateBlock::theSize;
272 static const sal_uInt16 thePageSize = theSize;
273 STORE_STATIC_ASSERT(STORE_MINIMUM_PAGESIZE >= thePageSize);
275 /** Allocation.
277 static void * operator new (size_t n) SAL_THROW(())
279 return rtl_allocateMemory (sal::static_int_cast<sal_Size>(n));
281 static void operator delete (void * p, size_t) SAL_THROW(())
283 rtl_freeMemory (p);
286 static void * operator new (size_t, sal_uInt16 nPageSize) SAL_THROW(())
288 return rtl_allocateZeroMemory (sal::static_int_cast<sal_Size>(nPageSize));
290 static void operator delete (void * p, sal_uInt16) SAL_THROW(())
292 rtl_freeMemory (p);
295 /** Construction.
297 explicit OStoreSuperBlockPage (sal_uInt16 nPageSize = thePageSize)
298 : m_aSuperOne(nPageSize),
299 m_aSuperTwo(nPageSize),
300 m_aState()
303 /** guard (external representation).
305 void guard()
307 m_aSuperOne.guard();
308 m_aSuperTwo.guard();
311 /** save.
313 storeError save (OStorePageBIOS &rBIOS)
315 // Guard.
316 guard();
318 // Write.
319 return rBIOS.write (0, this, theSize);
322 /** close.
324 storeError close (
325 OStorePageBIOS &rBIOS);
327 /** flush.
329 storeError flush (
330 OStorePageBIOS &rBIOS);
332 /** modified.
334 storeError modified (
335 OStorePageBIOS &rBIOS);
337 /** verify (with repair).
339 storeError verify (
340 OStorePageBIOS &rBIOS);
343 } // namespace store
345 /*========================================================================
347 * OStoreSuperBlockPage implementation.
349 *======================================================================*/
351 * close.
353 storeError OStoreSuperBlockPage::close (OStorePageBIOS &rBIOS)
355 storeError eErrCode = store_E_None;
356 if (m_aState.closePending())
358 // Mark as modified.
359 m_aState.modified();
361 // Check access mode.
362 if (rBIOS.isWriteable())
364 // Save StateBlock.
365 StateBlock aState (m_aState);
367 // Mark as clean.
368 aState.clean();
370 // Write behind SuperBlock.
371 sal_uInt32 nAddr = 2 * SuperBlock::theSize;
372 eErrCode = rBIOS.write (nAddr, &aState, StateBlock::theSize);
375 // Mark as clean.
376 m_aState.clean();
378 return eErrCode;
382 * flush.
384 storeError OStoreSuperBlockPage::flush (OStorePageBIOS &rBIOS)
386 storeError eErrCode = store_E_None;
387 if (m_aState.flushPending())
389 // Check access mode.
390 if (rBIOS.isWriteable())
392 // Save StateBlock.
393 StateBlock aState (m_aState);
395 // Mark as flushed.
396 aState.flushed();
398 // Write behind SuperBlock.
399 sal_uInt32 nAddr = 2 * SuperBlock::theSize;
400 eErrCode = rBIOS.write (nAddr, &aState, StateBlock::theSize);
403 // Mark as flushed.
404 m_aState.flushed();
406 return eErrCode;
410 * modified.
412 storeError OStoreSuperBlockPage::modified (OStorePageBIOS &rBIOS)
414 storeError eErrCode = store_E_None;
415 if (!m_aState.flushPending())
417 // Mark as modified.
418 m_aState.modified();
420 // Check access mode.
421 if (rBIOS.isWriteable())
423 // Save StateBlock.
424 StateBlock aState (m_aState);
426 // Write behind SuperBlock.
427 sal_uInt32 nAddr = 2 * SuperBlock::theSize;
428 eErrCode = rBIOS.write (nAddr, &aState, StateBlock::theSize);
431 return eErrCode;
435 * verify (with repair).
437 storeError OStoreSuperBlockPage::verify (OStorePageBIOS &rBIOS)
439 // Verify 1st copy.
440 storeError eErrCode = m_aSuperOne.verify();
441 if (eErrCode == store_E_None)
443 // Ok. Verify 2nd copy.
444 eErrCode = m_aSuperTwo.verify();
445 if (eErrCode == store_E_None)
447 // Ok. Ensure identical copies (1st copy wins).
448 if (!(m_aSuperOne == m_aSuperTwo))
450 // Different. Replace 2nd copy with 1st copy.
451 m_aSuperTwo = m_aSuperOne;
453 // Write back.
454 if (rBIOS.isWriteable())
455 eErrCode = rBIOS.write (0, this, theSize);
456 else
457 eErrCode = store_E_None;
460 else
462 // Failure. Replace 2nd copy with 1st copy.
463 m_aSuperTwo = m_aSuperOne;
465 // Write back.
466 if (rBIOS.isWriteable())
467 eErrCode = rBIOS.write (0, this, theSize);
468 else
469 eErrCode = store_E_None;
472 else
474 // Failure. Verify 2nd copy.
475 eErrCode = m_aSuperTwo.verify();
476 if (eErrCode == store_E_None)
478 // Ok. Replace 1st copy with 2nd copy.
479 m_aSuperOne = m_aSuperTwo;
481 // Write back.
482 if (rBIOS.isWriteable())
483 eErrCode = rBIOS.write (0, this, theSize);
484 else
485 eErrCode = store_E_None;
487 else
489 // Double Failure.
490 OSL_TRACE("OStoreSuperBlockPage::verify(): double failure.\n");
494 // Done.
495 return eErrCode;
498 /*========================================================================
500 * OStorePageBIOS::Ace implementation.
502 *======================================================================*/
503 OStorePageBIOS::Ace::Ace()
504 : m_next (this), m_prev (this), m_addr (STORE_PAGE_NULL), m_used (0)
507 OStorePageBIOS::Ace::~Ace()
509 m_next->m_prev = m_prev, m_prev->m_next = m_next;
513 SAL_CALL OStorePageBIOS::Ace::constructor (void * obj, void * /* arg */)
515 Ace * ace = static_cast<Ace*>(obj);
516 ace->m_next = ace->m_prev = ace;
517 return 1;
520 OStorePageBIOS::Ace *
521 OStorePageBIOS::Ace::find (OStorePageBIOS::Ace * head, sal_uInt32 addr)
523 OStorePageBIOS::Ace * entry;
524 for (entry = head->m_next; entry != head; entry = entry->m_next)
526 if (entry->m_addr >= addr)
527 return entry;
529 return head;
532 void
533 OStorePageBIOS::Ace::insert (OStorePageBIOS::Ace * head, OStorePageBIOS::Ace * entry)
535 // insert entry at queue tail (before head).
536 entry->m_next = head;
537 entry->m_prev = head->m_prev;
538 head->m_prev = entry;
539 entry->m_prev->m_next = entry;
542 /*========================================================================
544 * OStorePageBIOS::AceCache interface.
546 *======================================================================*/
547 namespace store
550 class OStorePageBIOS::AceCache
552 rtl_cache_type * m_ace_cache;
554 public:
555 static AceCache & get();
557 OStorePageBIOS::Ace *
558 create (sal_uInt32 addr, sal_uInt32 used = 1);
560 void
561 destroy (OStorePageBIOS::Ace * ace);
563 protected:
564 AceCache();
565 ~AceCache();
568 } // namespace store
570 /*========================================================================
572 * OStorePageBIOS::AceCache implementation.
574 *======================================================================*/
575 extern "C" typedef int (SAL_CALL * ace_constructor_type)(void*,void*);
577 OStorePageBIOS::AceCache &
578 OStorePageBIOS::AceCache::get()
580 static AceCache g_ace_cache;
581 return g_ace_cache;
584 OStorePageBIOS::AceCache::AceCache()
586 m_ace_cache = rtl_cache_create (
587 "store_ace_cache",
588 sizeof (OStorePageBIOS::Ace),
589 0, // objalign
590 reinterpret_cast<ace_constructor_type>( OStorePageBIOS::Ace::constructor),
591 0, // destructor,
592 0, // reclaim,
593 0, // userarg,
594 0, // default source,
595 0 // flags
599 OStorePageBIOS::AceCache::~AceCache()
601 rtl_cache_destroy (m_ace_cache), m_ace_cache = 0;
604 OStorePageBIOS::Ace *
605 OStorePageBIOS::AceCache::create (sal_uInt32 addr, sal_uInt32 used)
607 Ace * ace = static_cast<Ace*>(rtl_cache_alloc (m_ace_cache));
608 if (ace != 0)
610 // verify invariant state.
611 OSL_ASSERT((ace->m_next == ace) && (ace->m_prev == ace));
613 // initialize.
614 ace->m_addr = addr;
615 ace->m_used = used;
617 return ace;
620 void
621 OStorePageBIOS::AceCache::destroy (OStorePageBIOS::Ace * ace)
623 if (ace != 0)
625 // remove from queue (if any).
626 ace->m_next->m_prev = ace->m_prev, ace->m_prev->m_next = ace->m_next;
628 // restore invariant state.
629 ace->m_next = ace->m_prev = ace;
631 // return to cache.
632 rtl_cache_free (m_ace_cache, ace);
636 /*========================================================================
638 * OStorePageBIOS implementation.
640 *======================================================================*/
642 * OStorePageBIOS.
644 OStorePageBIOS::OStorePageBIOS (void)
645 : m_xLockBytes (NULL),
646 m_pSuper (NULL),
647 m_bModified (sal_False),
648 m_bWriteable (sal_False)
653 * ~OStorePageBIOS.
655 OStorePageBIOS::~OStorePageBIOS (void)
657 OStorePageBIOS::close();
661 * verify (SuperBlock with repair).
662 * Internal: Precond: initialized, exclusive access.
664 storeError OStorePageBIOS::verify (SuperPage *&rpSuper)
666 // Check SuperBlock page allocation.
667 if (rpSuper == 0)
669 // Allocate.
670 if ((rpSuper = new SuperPage()) == 0)
671 return store_E_OutOfMemory;
673 // Load (w/o verification).
674 storeError eErrCode = read (0, rpSuper, SuperPage::theSize);
675 if (eErrCode != store_E_None)
677 // Cleanup and fail.
678 delete rpSuper, rpSuper = 0;
679 return eErrCode;
682 // Check SuperBlock state.
683 if (rpSuper->m_aState.closePending())
684 OSL_TRACE("OStorePageBIOS::verify(): close pending.\n");
686 if (rpSuper->m_aState.flushPending())
687 OSL_TRACE("OStorePageBIOS::verify(): flush pending.\n");
690 // Verify SuperBlock page (with repair).
691 return rpSuper->verify (*this);
695 * repair (SuperBlock).
696 * Internal: Precond: initialized, exclusive access.
698 storeError OStorePageBIOS::repair (SuperPage *&rpSuper)
700 // Acquire Lock.
701 storeError eErrCode = acquireLock (0, SuperPage::theSize);
702 if (eErrCode != store_E_None)
703 return eErrCode;
705 // Verify SuperBlock page (with repair).
706 eErrCode = verify (rpSuper);
707 if (eErrCode != store_E_None)
709 // Failure.
710 releaseLock (0, SuperPage::theSize);
711 return eErrCode;
714 // ReleaseLock.
715 return releaseLock (0, SuperPage::theSize);
719 * create (SuperBlock).
720 * Internal: Precond: initialized, exclusive access.
722 storeError OStorePageBIOS::create (sal_uInt16 nPageSize)
724 // Check (internal) precond.
725 OSL_PRECOND(m_xLockBytes.is(), "store::PageBIOS::create(): contract violation");
727 // Check PageSize.
728 if ((STORE_MINIMUM_PAGESIZE > nPageSize) || (nPageSize > STORE_MAXIMUM_PAGESIZE))
729 return store_E_InvalidParameter;
730 nPageSize = ((nPageSize + STORE_MINIMUM_PAGESIZE - 1) & ~(STORE_MINIMUM_PAGESIZE - 1));
732 // Acquire Lock.
733 storeError eErrCode = acquireLock (0, nPageSize);
734 if (eErrCode != store_E_None)
735 return eErrCode;
737 // Allocate SuperBlock page.
738 delete m_pSuper, m_pSuper = 0;
739 if ((m_pSuper = new(nPageSize) SuperPage(nPageSize)) == 0)
741 // Cleanup and fail.
742 releaseLock (0, nPageSize);
743 return store_E_OutOfMemory;
745 m_pSuper->guard();
747 // Create initial page (w/ SuperBlock).
748 eErrCode = m_xLockBytes->writeAt (0, m_pSuper, nPageSize);
749 if (eErrCode != store_E_None)
751 // Cleanup and fail.
752 releaseLock (0, nPageSize);
753 return eErrCode;
756 #ifdef STORE_FEATURE_COMMIT
757 // Commit.
758 eErrCode = m_xLockBytes->flush();
759 OSL_POSTCOND(
760 eErrCode == store_E_None,
761 "OStorePageBIOS::create(): flush failed");
762 #endif /* STORE_FEATURE_COMMIT */
764 // Adjust modified state.
765 m_bModified = (eErrCode != store_E_None);
767 // Release Lock and finish.
768 return releaseLock (0, nPageSize);
772 * initialize.
773 * Precond: none.
775 storeError OStorePageBIOS::initialize (
776 ILockBytes * pLockBytes,
777 storeAccessMode eAccessMode,
778 sal_uInt16 & rnPageSize)
780 // Acquire exclusive access.
781 osl::MutexGuard aGuard (m_aMutex);
783 // Check arguments.
784 storeError eErrCode = store_E_InvalidParameter;
785 if (!pLockBytes)
786 return eErrCode;
788 // Cleanup.
789 #if 0 /* OLD */
790 __STORE_DELETEZ (m_pAcl); /* @@@ */
791 #endif /* OLD */
792 delete m_pSuper, m_pSuper = 0;
794 // Initialize.
795 m_xLockBytes = pLockBytes;
796 m_bModified = sal_False;
797 m_bWriteable = (!(eAccessMode == store_AccessReadOnly));
799 // Check access mode.
800 if (eAccessMode == store_AccessReadOnly)
802 // Verify SuperBlock page.
803 eErrCode = verify (m_pSuper);
805 else if (eAccessMode != store_AccessCreate)
807 // Verify (w/ repair) SuperBlock page.
808 eErrCode = repair (m_pSuper);
810 else
812 // Truncate to zero length.
813 eErrCode = m_xLockBytes->setSize(0);
814 if (eErrCode != store_E_None)
815 return eErrCode;
817 #ifdef STORE_FEATURE_COMMIT
818 // Commit.
819 eErrCode = m_xLockBytes->flush();
820 if (eErrCode != store_E_None)
821 return eErrCode;
822 #endif /* STORE_FEATURE_COMMIT */
824 // Mark as not existing.
825 eErrCode = store_E_NotExists;
828 if (eErrCode != store_E_None)
830 // Check reason.
831 if (eErrCode != store_E_NotExists)
832 return eErrCode;
834 // Check mode.
835 if (eAccessMode == store_AccessReadOnly)
836 return store_E_NotExists;
837 if (eAccessMode == store_AccessReadWrite)
838 return store_E_NotExists;
840 // Create SuperBlock page.
841 eErrCode = create (rnPageSize);
843 if (eErrCode == store_E_None)
845 // Obtain modified state.
846 m_bModified = m_pSuper->m_aState.flushPending();
848 // Obtain page size.
849 rnPageSize = store::ntohs(m_pSuper->m_aSuperOne.m_aDescr.m_nSize);
851 // Create page allocator.
852 eErrCode = m_xLockBytes->initialize (m_xAllocator, rnPageSize);
853 if (eErrCode != store_E_None)
854 return eErrCode;
856 // Create page cache.
857 eErrCode = PageCache_createInstance (m_xCache, rnPageSize);
859 return eErrCode;
863 * acquireLock.
864 * Low Level: Precond: initialized, exclusive access.
866 storeError OStorePageBIOS::acquireLock (
867 sal_uInt32 nAddr, sal_uInt32 nSize)
869 // Check precond.
870 if (!m_xLockBytes.is())
871 return store_E_InvalidAccess;
873 // Acquire Lock.
874 return m_xLockBytes->lockRange (nAddr, nSize);
878 * releaseLock.
879 * Low Level: Precond: initialized, exclusive access.
881 storeError OStorePageBIOS::releaseLock (
882 sal_uInt32 nAddr, sal_uInt32 nSize)
884 // Check precond.
885 if (!m_xLockBytes.is())
886 return store_E_InvalidAccess;
888 // Release Lock.
889 return m_xLockBytes->unlockRange (nAddr, nSize);
893 * read.
894 * Low Level: Precond: initialized, exclusive access.
896 storeError OStorePageBIOS::read (
897 sal_uInt32 nAddr, void *pData, sal_uInt32 nSize)
899 // Check precond.
900 if (!m_xLockBytes.is())
901 return store_E_InvalidAccess;
903 // Read Page.
904 return m_xLockBytes->readAt (nAddr, pData, nSize);
908 * write.
909 * Low Level: Precond: initialized, writeable, exclusive access.
911 storeError OStorePageBIOS::write (
912 sal_uInt32 nAddr, const void *pData, sal_uInt32 nSize)
914 // Check precond.
915 if (!m_xLockBytes.is())
916 return store_E_InvalidAccess;
917 if (!m_bWriteable)
918 return store_E_AccessViolation;
920 // Check modified state.
921 if (!m_bModified)
923 // Mark as modified.
924 m_bModified = sal_True;
926 // Mark SuperBlock modified.
927 storeError eErrCode = m_pSuper->modified (*this);
928 if (eErrCode != store_E_None)
929 return eErrCode;
932 // Write Data.
933 return m_xLockBytes->writeAt (nAddr, pData, nSize);
937 * acquirePage.
938 * Precond: initialized.
940 storeError OStorePageBIOS::acquirePage (
941 const OStorePageDescriptor& rDescr, storeAccessMode eMode)
943 // Acquire exclusive access.
944 osl::MutexGuard aGuard (m_aMutex);
946 // Check precond.
947 if (!m_xLockBytes.is())
948 return store_E_InvalidAccess;
950 // Check access mode.
951 if (!(m_bWriteable || (eMode == store_AccessReadOnly)))
952 return store_E_AccessViolation;
954 // Find access control list entry.
955 Ace * ace = Ace::find (&m_ace_head, rDescr.m_nAddr);
956 if (ace->m_addr == rDescr.m_nAddr)
958 // Acquire existing entry (with ShareDenyWrite).
959 if (eMode == store_AccessReadOnly)
960 ace->m_used += 1;
961 else
962 return store_E_AccessViolation;
964 else
966 // Insert new entry.
967 Ace * entry = AceCache::get().create (rDescr.m_nAddr, 1);
968 if (!entry)
969 return store_E_OutOfMemory;
970 Ace::insert (ace, entry);
973 // Increment total referer count and finish.
974 m_ace_head.m_used += 1;
975 return store_E_None;
979 * releasePage.
980 * Precond: initialized.
982 storeError OStorePageBIOS::releasePage (
983 const OStorePageDescriptor& rDescr, storeAccessMode /* eMode */)
985 // Acquire exclusive access.
986 osl::MutexGuard aGuard (m_aMutex);
988 // Check precond.
989 if (!m_xLockBytes.is())
990 return store_E_InvalidAccess;
992 // Find access control list entry.
993 Ace * ace = Ace::find (&m_ace_head, rDescr.m_nAddr);
994 if (ace->m_addr != rDescr.m_nAddr)
995 return store_E_NotExists;
997 // Release existing entry.
998 if (ace->m_used > 1)
999 ace->m_used -= 1;
1000 else
1001 AceCache::get().destroy (ace);
1003 // Decrement total referer count and finish.
1004 m_ace_head.m_used -= 1;
1005 return store_E_None;
1009 * getRefererCount.
1010 * Precond: none.
1012 sal_uInt32 OStorePageBIOS::getRefererCount (void)
1014 // Acquire exclusive access.
1015 osl::MutexGuard aGuard (m_aMutex);
1017 // Obtain total referer count.
1018 return m_ace_head.m_used;
1022 * allocate.
1023 * Precond: initialized, writeable.
1025 storeError OStorePageBIOS::allocate (
1026 OStorePageObject& rPage, Allocation eAlloc)
1028 // Acquire exclusive access.
1029 osl::MutexGuard aGuard (m_aMutex);
1031 // Check precond.
1032 if (!m_xLockBytes.is())
1033 return store_E_InvalidAccess;
1034 if (!m_bWriteable)
1035 return store_E_AccessViolation;
1037 // Acquire SuperBlock Lock.
1038 storeError eErrCode = acquireLock (0, SuperPage::theSize);
1039 if (eErrCode != store_E_None)
1040 return eErrCode;
1042 // Load SuperBlock and require good health.
1043 eErrCode = verify (m_pSuper);
1044 if (eErrCode != store_E_None)
1046 releaseLock (0, SuperPage::theSize);
1047 return eErrCode;
1050 // Check allocation.
1051 if (eAlloc != ALLOCATE_EOF)
1053 // Check FreeList.
1054 OStorePageLink aListHead (m_pSuper->m_aSuperTwo.unusedHead());
1055 if (aListHead.location())
1057 // Allocate from FreeList.
1058 OStorePageData aPageHead (OStorePageData::theSize);
1059 aPageHead.location (aListHead.location());
1061 // Load PageHead.
1062 eErrCode = peek (aPageHead);
1063 if (eErrCode != store_E_None)
1065 releaseLock (0, SuperPage::theSize);
1066 return eErrCode;
1069 // Verify FreeList head.
1070 OSL_PRECOND(
1071 aPageHead.m_aUnused.m_nAddr != STORE_PAGE_NULL,
1072 "OStorePageBIOS::allocate(): page not free");
1073 if (aPageHead.m_aUnused.location() == STORE_PAGE_NULL)
1075 // Recovery: Reset FreeList.
1076 m_pSuper->m_aSuperTwo.unusedReset();
1077 m_pSuper->m_aSuperOne = m_pSuper->m_aSuperTwo;
1079 // Save SuperBlock page.
1080 eErrCode = m_pSuper->save (*this);
1082 // Release SuperBlock Lock.
1083 releaseLock (0, SuperPage::theSize);
1085 // Recovery: Allocate from EOF.
1086 if (eErrCode == store_E_None)
1087 return allocate (rPage, ALLOCATE_EOF);
1088 else
1089 return store_E_Unknown;
1092 // Pop from FreeList.
1093 aListHead = aPageHead.m_aUnused.location();
1094 rPage.get()->m_aUnused = STORE_PAGE_NULL;
1096 // Save page at PageHead location.
1097 eErrCode = saveObjectAt_Impl (rPage, aPageHead.location());
1098 if (eErrCode != store_E_None)
1100 releaseLock (0, SuperPage::theSize);
1101 return eErrCode;
1104 // Save SuperBlock page.
1105 m_pSuper->m_aSuperTwo.unusedRemove (aListHead);
1106 m_pSuper->m_aSuperOne = m_pSuper->m_aSuperTwo;
1108 eErrCode = m_pSuper->save (*this);
1109 OSL_POSTCOND(
1110 eErrCode == store_E_None,
1111 "OStorePageBIOS::allocate(): SuperBlock save failed");
1113 // Release SuperBlock Lock and finish.
1114 return releaseLock (0, SuperPage::theSize);
1118 // Allocate from logical EOF. Determine physical EOF.
1119 sal_uInt32 nPhysLen = STORE_PAGE_NULL;
1120 eErrCode = m_xLockBytes->getSize (nPhysLen);
1121 if (eErrCode != store_E_None)
1123 releaseLock (0, SuperPage::theSize);
1124 return eErrCode;
1127 // Obtain logical EOF.
1128 OStorePageDescriptor aDescr (m_pSuper->m_aSuperTwo.m_aDescr);
1129 sal_uInt32 nLogLen = store::ntohl(aDescr.m_nAddr);
1130 if (nLogLen == 0)
1131 nLogLen = nPhysLen; /* backward compatibility */
1133 if (!(nLogLen < nPhysLen))
1135 // Check modified state.
1136 if (!m_bModified)
1138 // Mark modified.
1139 m_bModified = sal_True;
1141 // Mark SuperBlock modified.
1142 eErrCode = m_pSuper->modified (*this);
1143 if (eErrCode != store_E_None)
1145 releaseLock (0, SuperPage::theSize);
1146 return eErrCode;
1150 // Resize.
1151 sal_uInt32 nAlign = SAL_MIN (nPhysLen, STORE_MAXIMUM_PAGESIZE);
1152 nPhysLen = ((nPhysLen + nAlign) / nAlign) * nAlign;
1154 eErrCode = m_xLockBytes->setSize (nPhysLen);
1155 if (eErrCode != store_E_None)
1157 releaseLock (0, SuperPage::theSize);
1158 return eErrCode;
1162 // Save page at logical EOF.
1163 eErrCode = saveObjectAt_Impl (rPage, nLogLen);
1164 if (eErrCode != store_E_None)
1166 releaseLock (0, SuperPage::theSize);
1167 return eErrCode;
1170 // Save SuperBlock page.
1171 nLogLen += store::ntohs(aDescr.m_nSize);
1172 aDescr.m_nAddr = store::htonl(nLogLen);
1174 m_pSuper->m_aSuperTwo.m_aDescr = aDescr;
1175 m_pSuper->m_aSuperOne = m_pSuper->m_aSuperTwo;
1177 eErrCode = m_pSuper->save (*this);
1178 OSL_POSTCOND(
1179 eErrCode == store_E_None,
1180 "OStorePageBIOS::allocate(): SuperBlock save failed");
1182 // Release SuperBlock Lock and finish.
1183 return releaseLock (0, SuperPage::theSize);
1187 * free.
1188 * Precond: initialized, writeable.
1190 storeError OStorePageBIOS::free (OStorePageData & /* rData */, sal_uInt32 nAddr)
1192 // Acquire exclusive access.
1193 osl::MutexGuard aGuard (m_aMutex);
1195 // Check precond.
1196 if (!m_xLockBytes.is())
1197 return store_E_InvalidAccess;
1198 if (!m_bWriteable)
1199 return store_E_AccessViolation;
1201 // Acquire SuperBlock Lock.
1202 storeError eErrCode = acquireLock (0, SuperPage::theSize);
1203 if (eErrCode != store_E_None)
1204 return eErrCode;
1206 // Load SuperBlock and require good health.
1207 eErrCode = verify (m_pSuper);
1208 if (eErrCode != store_E_None)
1210 releaseLock (0, SuperPage::theSize);
1211 return eErrCode;
1214 // Load PageHead.
1215 OStorePageData aPageHead(OStorePageData::theSize);
1216 aPageHead.location (nAddr);
1218 eErrCode = peek (aPageHead);
1219 if (eErrCode != store_E_None)
1221 releaseLock (0, SuperPage::theSize);
1222 return eErrCode;
1225 // Invalidate cache.
1226 (void) m_xCache->removePageAt (nAddr);
1228 // Push onto FreeList.
1229 OStorePageLink aListHead (m_pSuper->m_aSuperTwo.unusedHead());
1231 aPageHead.m_aUnused.m_nAddr = aListHead.m_nAddr;
1232 aListHead.m_nAddr = aPageHead.m_aDescr.m_nAddr;
1234 // Save PageHead.
1235 eErrCode = poke (aPageHead);
1236 if (eErrCode != store_E_None)
1238 releaseLock (0, SuperPage::theSize);
1239 return eErrCode;
1242 // Save SuperBlock page.
1243 m_pSuper->m_aSuperTwo.unusedInsert (aListHead);
1244 m_pSuper->m_aSuperOne = m_pSuper->m_aSuperTwo;
1246 eErrCode = m_pSuper->save (*this);
1247 OSL_POSTCOND(
1248 eErrCode == store_E_None,
1249 "OStorePageBIOS::free(): SuperBlock save failed");
1251 // Release SuperBlock Lock and finish.
1252 return releaseLock (0, SuperPage::theSize);
1256 * loadObjectAt.
1257 * Precond: initialized, readable.
1259 storeError OStorePageBIOS::loadObjectAt (OStorePageObject & rPage, sal_uInt32 nAddr)
1261 // Acquire exclusive access.
1262 osl::MutexGuard aGuard (m_aMutex);
1264 // Check precond.
1265 if (!m_xLockBytes.is())
1266 return store_E_InvalidAccess;
1268 return loadObjectAt_Impl (rPage, nAddr);
1272 * loadObjectAt_Impl.
1273 * Internal: Precond: initialized, readable, exclusive access.
1275 storeError OStorePageBIOS::loadObjectAt_Impl (OStorePageObject & rPage, sal_uInt32 nAddr)
1277 storeError eErrCode = m_xCache->lookupPageAt (rPage.get(), nAddr);
1278 if (eErrCode != store_E_NotExists)
1279 return eErrCode;
1281 // Read page.
1282 eErrCode = m_xLockBytes->readPageAt (rPage.get(), nAddr);
1283 if (eErrCode != store_E_None)
1284 return eErrCode;
1286 // Verify page.
1287 eErrCode = rPage.verify (nAddr);
1288 if (eErrCode != store_E_None)
1289 return eErrCode;
1291 // Mark page as clean.
1292 rPage.clean();
1294 // Cache page.
1295 return m_xCache->insertPageAt (rPage.get(), nAddr);
1299 * saveObjectAt.
1300 * Precond: initialized, writeable.
1302 storeError OStorePageBIOS::saveObjectAt (OStorePageObject & rPage, sal_uInt32 nAddr)
1304 // Acquire exclusive access.
1305 osl::MutexGuard aGuard (m_aMutex);
1307 // Check precond.
1308 if (!m_xLockBytes.is())
1309 return store_E_InvalidAccess;
1310 if (!m_bWriteable)
1311 return store_E_AccessViolation;
1313 // Save Page.
1314 return saveObjectAt_Impl (rPage, nAddr);
1318 * saveObjectAt_Impl.
1319 * Internal: Precond: initialized, writeable, exclusive access.
1321 storeError OStorePageBIOS::saveObjectAt_Impl (OStorePageObject & rPage, sal_uInt32 nAddr)
1323 // Guard page (incl. set location).
1324 storeError eErrCode = rPage.guard (nAddr);
1325 if (eErrCode != store_E_None)
1326 return eErrCode;
1328 // Write page.
1329 eErrCode = m_xLockBytes->writePageAt(rPage.get(), nAddr);
1330 if (eErrCode != store_E_None)
1331 return eErrCode;
1333 // Mark page as clean.
1334 rPage.clean();
1336 // Cache page.
1337 return m_xCache->updatePageAt (rPage.get(), nAddr);
1341 * close.
1342 * Precond: none.
1344 storeError OStorePageBIOS::close (void)
1346 // Acquire exclusive access.
1347 osl::MutexGuard aGuard (m_aMutex);
1349 // Check referer count.
1350 if (m_ace_head.m_used > 0)
1352 // Report remaining referer count.
1353 OSL_TRACE("store::PageBIOS::close(): referer count: %d\n", m_ace_head.m_used);
1354 #if 1 /* NEW */
1355 for (Ace * ace = m_ace_head.m_next; ace != &m_ace_head; ace = m_ace_head.m_next)
1357 m_ace_head.m_used -= ace->m_used;
1358 AceCache::get().destroy (ace);
1360 OSL_ENSURE(m_ace_head.m_used == 0, "store::PageBIOS::close(): logic error");
1361 #endif /* NEW */
1364 // Check SuperBlock page.
1365 storeError eErrCode = store_E_None;
1366 if (m_pSuper)
1368 // Release SuperBlock page.
1369 eErrCode = m_pSuper->close (*this);
1370 delete m_pSuper, m_pSuper = 0;
1373 // Release PageCache.
1374 m_xCache.clear();
1376 // Check LockBytes.
1377 if (m_xLockBytes.is())
1379 #ifdef STORE_FEATURE_COMMIT
1380 // Commit.
1381 storeError result = m_xLockBytes->flush();
1382 if (eErrCode == store_E_None)
1384 // Previous result(s) okay. Propagate next result.
1385 eErrCode = result;
1387 #endif /* STORE_FEATURE_COMMIT */
1389 // Release LockBytes.
1390 m_xLockBytes.clear();
1393 // Done.
1394 return eErrCode;
1398 * flush.
1399 * Precond: initialized.
1401 storeError OStorePageBIOS::flush (void)
1403 // Acquire exclusive access.
1404 osl::MutexGuard aGuard (m_aMutex);
1406 // Check precond.
1407 if (!m_xLockBytes.is())
1408 return store_E_InvalidAccess;
1410 // Check mode and state.
1411 storeError eErrCode = store_E_None;
1412 if (!(m_bWriteable && m_bModified))
1413 return eErrCode;
1415 // Flush SuperBlock page.
1416 eErrCode = m_pSuper->flush (*this);
1418 // Flush LockBytes.
1419 storeError result = m_xLockBytes->flush();
1420 if (eErrCode == store_E_None)
1422 // Previous result(s) okay. Propagate next result.
1423 eErrCode = result;
1426 // Adjust modified state.
1427 m_bModified = (eErrCode != store_E_None);
1429 // Done.
1430 return eErrCode;
1434 * size.
1435 * Precond: initialized.
1437 storeError OStorePageBIOS::size (sal_uInt32 &rnSize)
1439 // Acquire exclusive access.
1440 osl::MutexGuard aGuard (m_aMutex);
1442 // Initialize [out] param.
1443 rnSize = 0;
1445 // Check precond.
1446 if (!m_xLockBytes.is())
1447 return store_E_InvalidAccess;
1449 // Obtain LockBytes size.
1450 return m_xLockBytes->getSize (rnSize);
1454 * scanBegin.
1455 * Precond: initialized.
1457 storeError OStorePageBIOS::scanBegin (
1458 ScanContext &rCtx, sal_uInt32 nMagic)
1460 // Acquire exclusive access.
1461 osl::MutexGuard aGuard (m_aMutex);
1463 // Initialize [out] param.
1464 rCtx.m_aDescr = OStorePageDescriptor(0, 0, 0);
1465 rCtx.m_nSize = 0;
1466 rCtx.m_nMagic = nMagic;
1468 // Check precond.
1469 if (!m_xLockBytes.is())
1470 return store_E_InvalidAccess;
1472 // Check SuperBlock page.
1473 storeError eErrCode = verify (m_pSuper);
1474 if (eErrCode != store_E_None)
1476 // Damaged. Determine page size (NYI).
1477 OSL_TRACE ("OStorePageBIOS::scanBegin(): damaged.\n");
1478 return eErrCode;
1481 // Setup Context descriptor.
1482 rCtx.m_aDescr = m_pSuper->m_aSuperOne.m_aDescr;
1483 rCtx.m_aDescr.m_nAddr = rCtx.m_aDescr.m_nSize; // @@@ ntoh @@@
1485 // Setup Context size.
1486 eErrCode = size (rCtx.m_nSize);
1487 if (eErrCode != store_E_None)
1488 rCtx.m_nSize = ((sal_uInt32)(~0));
1490 // Done.
1491 return store_E_None;
1495 * scanNext.
1496 * Precond: initialized.
1498 storeError OStorePageBIOS::scanNext (
1499 ScanContext &rCtx, OStorePageObject &rPage)
1501 // Acquire exclusive access.
1502 osl::MutexGuard aGuard (m_aMutex);
1504 // Check precond.
1505 if (!m_xLockBytes.is())
1506 return store_E_InvalidAccess;
1508 // Setup PageHead.
1509 OStorePageData aPageHead (OStorePageData::theSize);
1511 // Check context.
1512 while (rCtx.isValid())
1514 // Assign next location.
1515 aPageHead.location (rCtx.m_aDescr.m_nAddr);
1516 rCtx.m_aDescr.m_nAddr += rCtx.m_aDescr.m_nSize;
1518 // Load PageHead.
1519 storeError eErrCode = peek (aPageHead);
1520 if (eErrCode != store_E_None)
1521 continue;
1523 // Check PageHead Magic number.
1524 if (aPageHead.m_aGuard.m_nMagic != rCtx.m_nMagic)
1525 continue;
1527 // Check PageHead Unused link.
1528 if (aPageHead.m_aUnused.m_nAddr != STORE_PAGE_NULL)
1529 continue;
1531 // Load page.
1532 eErrCode = loadObjectAt_Impl (rPage, aPageHead.location());
1533 if (eErrCode != store_E_None)
1534 continue;
1536 // Deliver page.
1537 return store_E_None;
1540 // Done.
1541 return store_E_CantSeek;
1545 * peek (PageHead).
1546 * Internal: Precond: initialized, readable, exclusive access.
1548 storeError OStorePageBIOS::peek (OStorePageData &rData)
1550 // Read PageHead.
1551 storeError eErrCode = read (rData.location(), &rData, OStorePageData::theSize);
1552 if (eErrCode != store_E_None)
1553 return eErrCode;
1555 // Verify PageHead.
1556 return rData.verify();
1560 * poke (PageHead).
1561 * Internal: Precond: initialized, writeable, exclusive access.
1563 storeError OStorePageBIOS::poke (OStorePageData &rData)
1565 // Guard PageHead.
1566 rData.guard();
1568 // Write PageHead.
1569 return write (rData.location(), &rData, OStorePageData::theSize);