1 /*************************************************************************
3 * OpenOffice.org - a multi-platform office productivity suite
5 * $RCSfile: storbios.cxx,v $
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,
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"
52 #include "lockbyte.hxx"
53 #include "storcach.hxx"
55 using namespace store
;
57 /*========================================================================
61 *======================================================================*/
62 #define STORE_MAGIC_SUPERBLOCK sal_uInt32(0x484D5343)
64 struct OStoreSuperBlock
66 typedef OStorePageGuard G
;
67 typedef OStorePageDescriptor D
;
68 typedef OStorePageLink L
;
81 static const size_t theSize
= sizeof(G
) + sizeof(D
) + 2 * (sizeof(L
) + sizeof(sal_uInt32
));
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)),
90 m_nUnused (store::htonl(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
;
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
136 void unusedInsert (const L
& rLink
)
138 sal_uInt32 nUnused
= unusedCount();
139 m_nUnused
= store::htonl(nUnused
+ 1);
142 void unusedRemove (const L
& rLink
)
144 sal_uInt32 nUnused
= unusedCount();
145 m_nUnused
= store::htonl(nUnused
- 1);
148 void unusedReset (void)
150 m_nUnused
= store::htonl(0);
154 /** guard (external representation).
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
;
182 /*========================================================================
186 *======================================================================*/
187 struct OStoreStateBlock
192 STATE_CLOSE_WAIT
= 1,
202 static const size_t theSize
= sizeof(sal_uInt32
);
207 : m_nState (store::htonl(STATE_CLEAN
))
212 bool closePending (void) const
214 sal_uInt32 nState
= store::ntohl(m_nState
);
215 return ((nState
& STATE_CLOSE_WAIT
) == STATE_CLOSE_WAIT
);
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
);
231 sal_uInt32 nState
= store::ntohl(m_nState
);
232 nState
&= ~STATE_FLUSH_WAIT
;
233 m_nState
= store::htonl(nState
);
238 sal_uInt32 nState
= store::ntohl(m_nState
);
239 nState
|= (STATE_CLOSE_WAIT
| STATE_FLUSH_WAIT
);
240 m_nState
= store::htonl(nState
);
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 *======================================================================*/
258 struct OStoreSuperBlockPage
260 typedef OStoreSuperBlock SuperBlock
;
261 typedef OStoreStateBlock StateBlock
;
265 SuperBlock m_aSuperOne
;
266 SuperBlock m_aSuperTwo
;
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
);
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(())
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(())
297 explicit OStoreSuperBlockPage (sal_uInt16 nPageSize
= thePageSize
)
298 : m_aSuperOne(nPageSize
),
299 m_aSuperTwo(nPageSize
),
303 /** guard (external representation).
313 storeError
save (OStorePageBIOS
&rBIOS
)
319 return rBIOS
.write (0, this, theSize
);
325 OStorePageBIOS
&rBIOS
);
330 OStorePageBIOS
&rBIOS
);
334 storeError
modified (
335 OStorePageBIOS
&rBIOS
);
337 /** verify (with repair).
340 OStorePageBIOS
&rBIOS
);
345 /*========================================================================
347 * OStoreSuperBlockPage implementation.
349 *======================================================================*/
353 storeError
OStoreSuperBlockPage::close (OStorePageBIOS
&rBIOS
)
355 storeError eErrCode
= store_E_None
;
356 if (m_aState
.closePending())
361 // Check access mode.
362 if (rBIOS
.isWriteable())
365 StateBlock
aState (m_aState
);
370 // Write behind SuperBlock.
371 sal_uInt32 nAddr
= 2 * SuperBlock::theSize
;
372 eErrCode
= rBIOS
.write (nAddr
, &aState
, StateBlock::theSize
);
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())
393 StateBlock
aState (m_aState
);
398 // Write behind SuperBlock.
399 sal_uInt32 nAddr
= 2 * SuperBlock::theSize
;
400 eErrCode
= rBIOS
.write (nAddr
, &aState
, StateBlock::theSize
);
412 storeError
OStoreSuperBlockPage::modified (OStorePageBIOS
&rBIOS
)
414 storeError eErrCode
= store_E_None
;
415 if (!m_aState
.flushPending())
420 // Check access mode.
421 if (rBIOS
.isWriteable())
424 StateBlock
aState (m_aState
);
426 // Write behind SuperBlock.
427 sal_uInt32 nAddr
= 2 * SuperBlock::theSize
;
428 eErrCode
= rBIOS
.write (nAddr
, &aState
, StateBlock::theSize
);
435 * verify (with repair).
437 storeError
OStoreSuperBlockPage::verify (OStorePageBIOS
&rBIOS
)
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
;
454 if (rBIOS
.isWriteable())
455 eErrCode
= rBIOS
.write (0, this, theSize
);
457 eErrCode
= store_E_None
;
462 // Failure. Replace 2nd copy with 1st copy.
463 m_aSuperTwo
= m_aSuperOne
;
466 if (rBIOS
.isWriteable())
467 eErrCode
= rBIOS
.write (0, this, theSize
);
469 eErrCode
= store_E_None
;
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
;
482 if (rBIOS
.isWriteable())
483 eErrCode
= rBIOS
.write (0, this, theSize
);
485 eErrCode
= store_E_None
;
490 OSL_TRACE("OStoreSuperBlockPage::verify(): double failure.\n");
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
;
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
)
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 *======================================================================*/
550 class OStorePageBIOS::AceCache
552 rtl_cache_type
* m_ace_cache
;
555 static AceCache
& get();
557 OStorePageBIOS::Ace
*
558 create (sal_uInt32 addr
, sal_uInt32 used
= 1);
561 destroy (OStorePageBIOS::Ace
* ace
);
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
;
584 OStorePageBIOS::AceCache::AceCache()
586 m_ace_cache
= rtl_cache_create (
588 sizeof (OStorePageBIOS::Ace
),
590 reinterpret_cast<ace_constructor_type
>( OStorePageBIOS::Ace::constructor
),
594 0, // default source,
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
));
610 // verify invariant state.
611 OSL_ASSERT((ace
->m_next
== ace
) && (ace
->m_prev
== ace
));
621 OStorePageBIOS::AceCache::destroy (OStorePageBIOS::Ace
* ace
)
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
;
632 rtl_cache_free (m_ace_cache
, ace
);
636 /*========================================================================
638 * OStorePageBIOS implementation.
640 *======================================================================*/
644 OStorePageBIOS::OStorePageBIOS (void)
645 : m_xLockBytes (NULL
),
647 m_bModified (sal_False
),
648 m_bWriteable (sal_False
)
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.
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
)
678 delete rpSuper
, rpSuper
= 0;
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
)
701 storeError eErrCode
= acquireLock (0, SuperPage::theSize
);
702 if (eErrCode
!= store_E_None
)
705 // Verify SuperBlock page (with repair).
706 eErrCode
= verify (rpSuper
);
707 if (eErrCode
!= store_E_None
)
710 releaseLock (0, SuperPage::theSize
);
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");
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));
733 storeError eErrCode
= acquireLock (0, nPageSize
);
734 if (eErrCode
!= store_E_None
)
737 // Allocate SuperBlock page.
738 delete m_pSuper
, m_pSuper
= 0;
739 if ((m_pSuper
= new(nPageSize
) SuperPage(nPageSize
)) == 0)
742 releaseLock (0, nPageSize
);
743 return store_E_OutOfMemory
;
747 // Create initial page (w/ SuperBlock).
748 eErrCode
= m_xLockBytes
->writeAt (0, m_pSuper
, nPageSize
);
749 if (eErrCode
!= store_E_None
)
752 releaseLock (0, nPageSize
);
756 #ifdef STORE_FEATURE_COMMIT
758 eErrCode
= m_xLockBytes
->flush();
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
);
775 storeError
OStorePageBIOS::initialize (
776 ILockBytes
* pLockBytes
,
777 storeAccessMode eAccessMode
,
778 sal_uInt16
& rnPageSize
)
780 // Acquire exclusive access.
781 osl::MutexGuard
aGuard (m_aMutex
);
784 storeError eErrCode
= store_E_InvalidParameter
;
790 __STORE_DELETEZ (m_pAcl
); /* @@@ */
792 delete m_pSuper
, m_pSuper
= 0;
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
);
812 // Truncate to zero length.
813 eErrCode
= m_xLockBytes
->setSize(0);
814 if (eErrCode
!= store_E_None
)
817 #ifdef STORE_FEATURE_COMMIT
819 eErrCode
= m_xLockBytes
->flush();
820 if (eErrCode
!= store_E_None
)
822 #endif /* STORE_FEATURE_COMMIT */
824 // Mark as not existing.
825 eErrCode
= store_E_NotExists
;
828 if (eErrCode
!= store_E_None
)
831 if (eErrCode
!= store_E_NotExists
)
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();
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
)
856 // Create page cache.
857 eErrCode
= PageCache_createInstance (m_xCache
, rnPageSize
);
864 * Low Level: Precond: initialized, exclusive access.
866 storeError
OStorePageBIOS::acquireLock (
867 sal_uInt32 nAddr
, sal_uInt32 nSize
)
870 if (!m_xLockBytes
.is())
871 return store_E_InvalidAccess
;
874 return m_xLockBytes
->lockRange (nAddr
, nSize
);
879 * Low Level: Precond: initialized, exclusive access.
881 storeError
OStorePageBIOS::releaseLock (
882 sal_uInt32 nAddr
, sal_uInt32 nSize
)
885 if (!m_xLockBytes
.is())
886 return store_E_InvalidAccess
;
889 return m_xLockBytes
->unlockRange (nAddr
, nSize
);
894 * Low Level: Precond: initialized, exclusive access.
896 storeError
OStorePageBIOS::read (
897 sal_uInt32 nAddr
, void *pData
, sal_uInt32 nSize
)
900 if (!m_xLockBytes
.is())
901 return store_E_InvalidAccess
;
904 return m_xLockBytes
->readAt (nAddr
, pData
, nSize
);
909 * Low Level: Precond: initialized, writeable, exclusive access.
911 storeError
OStorePageBIOS::write (
912 sal_uInt32 nAddr
, const void *pData
, sal_uInt32 nSize
)
915 if (!m_xLockBytes
.is())
916 return store_E_InvalidAccess
;
918 return store_E_AccessViolation
;
920 // Check modified state.
924 m_bModified
= sal_True
;
926 // Mark SuperBlock modified.
927 storeError eErrCode
= m_pSuper
->modified (*this);
928 if (eErrCode
!= store_E_None
)
933 return m_xLockBytes
->writeAt (nAddr
, pData
, nSize
);
938 * Precond: initialized.
940 storeError
OStorePageBIOS::acquirePage (
941 const OStorePageDescriptor
& rDescr
, storeAccessMode eMode
)
943 // Acquire exclusive access.
944 osl::MutexGuard
aGuard (m_aMutex
);
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
)
962 return store_E_AccessViolation
;
967 Ace
* entry
= AceCache::get().create (rDescr
.m_nAddr
, 1);
969 return store_E_OutOfMemory
;
970 Ace::insert (ace
, entry
);
973 // Increment total referer count and finish.
974 m_ace_head
.m_used
+= 1;
980 * Precond: initialized.
982 storeError
OStorePageBIOS::releasePage (
983 const OStorePageDescriptor
& rDescr
, storeAccessMode
/* eMode */)
985 // Acquire exclusive access.
986 osl::MutexGuard
aGuard (m_aMutex
);
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.
1001 AceCache::get().destroy (ace
);
1003 // Decrement total referer count and finish.
1004 m_ace_head
.m_used
-= 1;
1005 return store_E_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
;
1023 * Precond: initialized, writeable.
1025 storeError
OStorePageBIOS::allocate (
1026 OStorePageObject
& rPage
, Allocation eAlloc
)
1028 // Acquire exclusive access.
1029 osl::MutexGuard
aGuard (m_aMutex
);
1032 if (!m_xLockBytes
.is())
1033 return store_E_InvalidAccess
;
1035 return store_E_AccessViolation
;
1037 // Acquire SuperBlock Lock.
1038 storeError eErrCode
= acquireLock (0, SuperPage::theSize
);
1039 if (eErrCode
!= store_E_None
)
1042 // Load SuperBlock and require good health.
1043 eErrCode
= verify (m_pSuper
);
1044 if (eErrCode
!= store_E_None
)
1046 releaseLock (0, SuperPage::theSize
);
1050 // Check allocation.
1051 if (eAlloc
!= ALLOCATE_EOF
)
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());
1062 eErrCode
= peek (aPageHead
);
1063 if (eErrCode
!= store_E_None
)
1065 releaseLock (0, SuperPage::theSize
);
1069 // Verify FreeList head.
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
);
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
);
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);
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
);
1127 // Obtain logical EOF.
1128 OStorePageDescriptor
aDescr (m_pSuper
->m_aSuperTwo
.m_aDescr
);
1129 sal_uInt32 nLogLen
= store::ntohl(aDescr
.m_nAddr
);
1131 nLogLen
= nPhysLen
; /* backward compatibility */
1133 if (!(nLogLen
< nPhysLen
))
1135 // Check modified state.
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
);
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
);
1162 // Save page at logical EOF.
1163 eErrCode
= saveObjectAt_Impl (rPage
, nLogLen
);
1164 if (eErrCode
!= store_E_None
)
1166 releaseLock (0, SuperPage::theSize
);
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);
1179 eErrCode
== store_E_None
,
1180 "OStorePageBIOS::allocate(): SuperBlock save failed");
1182 // Release SuperBlock Lock and finish.
1183 return releaseLock (0, SuperPage::theSize
);
1188 * Precond: initialized, writeable.
1190 storeError
OStorePageBIOS::free (OStorePageData
& /* rData */, sal_uInt32 nAddr
)
1192 // Acquire exclusive access.
1193 osl::MutexGuard
aGuard (m_aMutex
);
1196 if (!m_xLockBytes
.is())
1197 return store_E_InvalidAccess
;
1199 return store_E_AccessViolation
;
1201 // Acquire SuperBlock Lock.
1202 storeError eErrCode
= acquireLock (0, SuperPage::theSize
);
1203 if (eErrCode
!= store_E_None
)
1206 // Load SuperBlock and require good health.
1207 eErrCode
= verify (m_pSuper
);
1208 if (eErrCode
!= store_E_None
)
1210 releaseLock (0, SuperPage::theSize
);
1215 OStorePageData
aPageHead(OStorePageData::theSize
);
1216 aPageHead
.location (nAddr
);
1218 eErrCode
= peek (aPageHead
);
1219 if (eErrCode
!= store_E_None
)
1221 releaseLock (0, SuperPage::theSize
);
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
;
1235 eErrCode
= poke (aPageHead
);
1236 if (eErrCode
!= store_E_None
)
1238 releaseLock (0, SuperPage::theSize
);
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);
1248 eErrCode
== store_E_None
,
1249 "OStorePageBIOS::free(): SuperBlock save failed");
1251 // Release SuperBlock Lock and finish.
1252 return releaseLock (0, SuperPage::theSize
);
1257 * Precond: initialized, readable.
1259 storeError
OStorePageBIOS::loadObjectAt (OStorePageObject
& rPage
, sal_uInt32 nAddr
)
1261 // Acquire exclusive access.
1262 osl::MutexGuard
aGuard (m_aMutex
);
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
)
1282 eErrCode
= m_xLockBytes
->readPageAt (rPage
.get(), nAddr
);
1283 if (eErrCode
!= store_E_None
)
1287 eErrCode
= rPage
.verify (nAddr
);
1288 if (eErrCode
!= store_E_None
)
1291 // Mark page as clean.
1295 return m_xCache
->insertPageAt (rPage
.get(), nAddr
);
1300 * Precond: initialized, writeable.
1302 storeError
OStorePageBIOS::saveObjectAt (OStorePageObject
& rPage
, sal_uInt32 nAddr
)
1304 // Acquire exclusive access.
1305 osl::MutexGuard
aGuard (m_aMutex
);
1308 if (!m_xLockBytes
.is())
1309 return store_E_InvalidAccess
;
1311 return store_E_AccessViolation
;
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
)
1329 eErrCode
= m_xLockBytes
->writePageAt(rPage
.get(), nAddr
);
1330 if (eErrCode
!= store_E_None
)
1333 // Mark page as clean.
1337 return m_xCache
->updatePageAt (rPage
.get(), nAddr
);
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
);
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");
1364 // Check SuperBlock page.
1365 storeError eErrCode
= store_E_None
;
1368 // Release SuperBlock page.
1369 eErrCode
= m_pSuper
->close (*this);
1370 delete m_pSuper
, m_pSuper
= 0;
1373 // Release PageCache.
1377 if (m_xLockBytes
.is())
1379 #ifdef STORE_FEATURE_COMMIT
1381 storeError result
= m_xLockBytes
->flush();
1382 if (eErrCode
== store_E_None
)
1384 // Previous result(s) okay. Propagate next result.
1387 #endif /* STORE_FEATURE_COMMIT */
1389 // Release LockBytes.
1390 m_xLockBytes
.clear();
1399 * Precond: initialized.
1401 storeError
OStorePageBIOS::flush (void)
1403 // Acquire exclusive access.
1404 osl::MutexGuard
aGuard (m_aMutex
);
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
))
1415 // Flush SuperBlock page.
1416 eErrCode
= m_pSuper
->flush (*this);
1419 storeError result
= m_xLockBytes
->flush();
1420 if (eErrCode
== store_E_None
)
1422 // Previous result(s) okay. Propagate next result.
1426 // Adjust modified state.
1427 m_bModified
= (eErrCode
!= store_E_None
);
1435 * Precond: initialized.
1437 storeError
OStorePageBIOS::size (sal_uInt32
&rnSize
)
1439 // Acquire exclusive access.
1440 osl::MutexGuard
aGuard (m_aMutex
);
1442 // Initialize [out] param.
1446 if (!m_xLockBytes
.is())
1447 return store_E_InvalidAccess
;
1449 // Obtain LockBytes size.
1450 return m_xLockBytes
->getSize (rnSize
);
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);
1466 rCtx
.m_nMagic
= nMagic
;
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");
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));
1491 return store_E_None
;
1496 * Precond: initialized.
1498 storeError
OStorePageBIOS::scanNext (
1499 ScanContext
&rCtx
, OStorePageObject
&rPage
)
1501 // Acquire exclusive access.
1502 osl::MutexGuard
aGuard (m_aMutex
);
1505 if (!m_xLockBytes
.is())
1506 return store_E_InvalidAccess
;
1509 OStorePageData
aPageHead (OStorePageData::theSize
);
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
;
1519 storeError eErrCode
= peek (aPageHead
);
1520 if (eErrCode
!= store_E_None
)
1523 // Check PageHead Magic number.
1524 if (aPageHead
.m_aGuard
.m_nMagic
!= rCtx
.m_nMagic
)
1527 // Check PageHead Unused link.
1528 if (aPageHead
.m_aUnused
.m_nAddr
!= STORE_PAGE_NULL
)
1532 eErrCode
= loadObjectAt_Impl (rPage
, aPageHead
.location());
1533 if (eErrCode
!= store_E_None
)
1537 return store_E_None
;
1541 return store_E_CantSeek
;
1546 * Internal: Precond: initialized, readable, exclusive access.
1548 storeError
OStorePageBIOS::peek (OStorePageData
&rData
)
1551 storeError eErrCode
= read (rData
.location(), &rData
, OStorePageData::theSize
);
1552 if (eErrCode
!= store_E_None
)
1556 return rData
.verify();
1561 * Internal: Precond: initialized, writeable, exclusive access.
1563 storeError
OStorePageBIOS::poke (OStorePageData
&rData
)
1569 return write (rData
.location(), &rData
, OStorePageData::theSize
);