xref: /aoo41x/main/store/source/storbios.cxx (revision 73d9b18a)
1*73d9b18aSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*73d9b18aSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*73d9b18aSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*73d9b18aSAndrew Rist  * distributed with this work for additional information
6*73d9b18aSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*73d9b18aSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*73d9b18aSAndrew Rist  * "License"); you may not use this file except in compliance
9*73d9b18aSAndrew Rist  * with the License.  You may obtain a copy of the License at
10*73d9b18aSAndrew Rist  *
11*73d9b18aSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*73d9b18aSAndrew Rist  *
13*73d9b18aSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*73d9b18aSAndrew Rist  * software distributed under the License is distributed on an
15*73d9b18aSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*73d9b18aSAndrew Rist  * KIND, either express or implied.  See the License for the
17*73d9b18aSAndrew Rist  * specific language governing permissions and limitations
18*73d9b18aSAndrew Rist  * under the License.
19*73d9b18aSAndrew Rist  *
20*73d9b18aSAndrew Rist  *************************************************************/
21*73d9b18aSAndrew Rist 
22*73d9b18aSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_store.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include "storbios.hxx"
28cdf0e10cSrcweir 
29cdf0e10cSrcweir #include "sal/types.h"
30cdf0e10cSrcweir #include "sal/macros.h"
31cdf0e10cSrcweir 
32cdf0e10cSrcweir #include "rtl/alloc.h"
33cdf0e10cSrcweir #include "rtl/ref.hxx"
34cdf0e10cSrcweir 
35cdf0e10cSrcweir #include "osl/diagnose.h"
36cdf0e10cSrcweir #include "osl/mutex.hxx"
37cdf0e10cSrcweir 
38cdf0e10cSrcweir #include "store/types.h"
39cdf0e10cSrcweir #include "object.hxx"
40cdf0e10cSrcweir #include "lockbyte.hxx"
41cdf0e10cSrcweir #include "storcach.hxx"
42cdf0e10cSrcweir 
43cdf0e10cSrcweir using namespace store;
44cdf0e10cSrcweir 
45cdf0e10cSrcweir /*========================================================================
46cdf0e10cSrcweir  *
47cdf0e10cSrcweir  * OStoreSuperBlock.
48cdf0e10cSrcweir  *
49cdf0e10cSrcweir  *======================================================================*/
50cdf0e10cSrcweir #define STORE_MAGIC_SUPERBLOCK sal_uInt32(0x484D5343)
51cdf0e10cSrcweir 
52cdf0e10cSrcweir struct OStoreSuperBlock
53cdf0e10cSrcweir {
54cdf0e10cSrcweir 	typedef OStorePageGuard      G;
55cdf0e10cSrcweir 	typedef OStorePageDescriptor D;
56cdf0e10cSrcweir 	typedef OStorePageLink       L;
57cdf0e10cSrcweir 
58cdf0e10cSrcweir 	/** Representation.
59cdf0e10cSrcweir 	 */
60cdf0e10cSrcweir 	G          m_aGuard;
61cdf0e10cSrcweir 	D          m_aDescr;
62cdf0e10cSrcweir 	sal_uInt32 m_nMarked;
63cdf0e10cSrcweir 	L          m_aMarked;
64cdf0e10cSrcweir 	sal_uInt32 m_nUnused;
65cdf0e10cSrcweir 	L          m_aUnused;
66cdf0e10cSrcweir 
67cdf0e10cSrcweir 	/** theSize.
68cdf0e10cSrcweir 	 */
69cdf0e10cSrcweir 	static const size_t theSize = sizeof(G) + sizeof(D) + 2 * (sizeof(L) + sizeof(sal_uInt32));
70cdf0e10cSrcweir 
71cdf0e10cSrcweir 	/** Construction.
72cdf0e10cSrcweir 	 */
OStoreSuperBlockOStoreSuperBlock73cdf0e10cSrcweir 	explicit OStoreSuperBlock (sal_uInt16 nPageSize)
74cdf0e10cSrcweir 		: m_aGuard  (STORE_MAGIC_SUPERBLOCK),
75cdf0e10cSrcweir           m_aDescr  (nPageSize, nPageSize, STORE_MINIMUM_PAGESIZE),
76cdf0e10cSrcweir 		  m_nMarked (store::htonl(0)),
77cdf0e10cSrcweir 		  m_aMarked (0),
78cdf0e10cSrcweir 		  m_nUnused (store::htonl(0)),
79cdf0e10cSrcweir 		  m_aUnused (0)
80cdf0e10cSrcweir 	{}
81cdf0e10cSrcweir 
OStoreSuperBlockOStoreSuperBlock82cdf0e10cSrcweir 	OStoreSuperBlock (const OStoreSuperBlock & rhs)
83cdf0e10cSrcweir 		: m_aGuard  (rhs.m_aGuard),
84cdf0e10cSrcweir 		  m_aDescr  (rhs.m_aDescr),
85cdf0e10cSrcweir 		  m_nMarked (rhs.m_nMarked),
86cdf0e10cSrcweir 		  m_aMarked (rhs.m_aMarked),
87cdf0e10cSrcweir 		  m_nUnused (rhs.m_nUnused),
88cdf0e10cSrcweir 		  m_aUnused (rhs.m_aUnused)
89cdf0e10cSrcweir 	{}
90cdf0e10cSrcweir 
operator =OStoreSuperBlock91cdf0e10cSrcweir 	OStoreSuperBlock& operator= (const OStoreSuperBlock & rhs)
92cdf0e10cSrcweir 	{
93cdf0e10cSrcweir 		m_aGuard  = rhs.m_aGuard;
94cdf0e10cSrcweir 		m_aDescr  = rhs.m_aDescr;
95cdf0e10cSrcweir 		m_nMarked = rhs.m_nMarked;
96cdf0e10cSrcweir 		m_aMarked = rhs.m_aMarked;
97cdf0e10cSrcweir 		m_nUnused = rhs.m_nUnused;
98cdf0e10cSrcweir 		m_aUnused = rhs.m_aUnused;
99cdf0e10cSrcweir 		return *this;
100cdf0e10cSrcweir 	}
101cdf0e10cSrcweir 
102cdf0e10cSrcweir 	/** Comparison.
103cdf0e10cSrcweir 	 */
operator ==OStoreSuperBlock104cdf0e10cSrcweir 	sal_Bool operator== (const OStoreSuperBlock & rhs) const
105cdf0e10cSrcweir 	{
106cdf0e10cSrcweir 		return ((m_aGuard  == rhs.m_aGuard ) &&
107cdf0e10cSrcweir 				(m_aDescr  == rhs.m_aDescr ) &&
108cdf0e10cSrcweir 				(m_nMarked == rhs.m_nMarked) &&
109cdf0e10cSrcweir 				(m_aMarked == rhs.m_aMarked) &&
110cdf0e10cSrcweir 				(m_nUnused == rhs.m_nUnused) &&
111cdf0e10cSrcweir 				(m_aUnused == rhs.m_aUnused)    );
112cdf0e10cSrcweir 	}
113cdf0e10cSrcweir 
114cdf0e10cSrcweir 	/** unused(Count|Head|Insert|Remove|Reset).
115cdf0e10cSrcweir 	 */
unusedCountOStoreSuperBlock116cdf0e10cSrcweir 	sal_uInt32 unusedCount (void) const
117cdf0e10cSrcweir 	{
118cdf0e10cSrcweir 		return store::ntohl(m_nUnused);
119cdf0e10cSrcweir 	}
unusedHeadOStoreSuperBlock120cdf0e10cSrcweir 	const L& unusedHead (void) const
121cdf0e10cSrcweir 	{
122cdf0e10cSrcweir 		return m_aUnused;
123cdf0e10cSrcweir 	}
unusedInsertOStoreSuperBlock124cdf0e10cSrcweir 	void unusedInsert (const L& rLink)
125cdf0e10cSrcweir 	{
126cdf0e10cSrcweir         sal_uInt32 nUnused = unusedCount();
127cdf0e10cSrcweir         m_nUnused = store::htonl(nUnused + 1);
128cdf0e10cSrcweir 		m_aUnused = rLink;
129cdf0e10cSrcweir 	}
unusedRemoveOStoreSuperBlock130cdf0e10cSrcweir 	void unusedRemove (const L& rLink)
131cdf0e10cSrcweir 	{
132cdf0e10cSrcweir         sal_uInt32 nUnused = unusedCount();
133cdf0e10cSrcweir         m_nUnused = store::htonl(nUnused - 1);
134cdf0e10cSrcweir 		m_aUnused = rLink;
135cdf0e10cSrcweir 	}
unusedResetOStoreSuperBlock136cdf0e10cSrcweir 	void unusedReset (void)
137cdf0e10cSrcweir 	{
138cdf0e10cSrcweir 		m_nUnused = store::htonl(0);
139cdf0e10cSrcweir 		m_aUnused = L(0);
140cdf0e10cSrcweir 	}
141cdf0e10cSrcweir 
142cdf0e10cSrcweir 	/** guard (external representation).
143cdf0e10cSrcweir 	 */
guardOStoreSuperBlock144cdf0e10cSrcweir 	void guard()
145cdf0e10cSrcweir 	{
146cdf0e10cSrcweir 		sal_uInt32 nCRC32 = 0;
147cdf0e10cSrcweir 		nCRC32 = rtl_crc32 (nCRC32, &m_aGuard.m_nMagic, sizeof(sal_uInt32));
148cdf0e10cSrcweir 		nCRC32 = rtl_crc32 (nCRC32, &m_aDescr, theSize - sizeof(G));
149cdf0e10cSrcweir 		m_aGuard.m_nCRC32 = store::htonl(nCRC32);
150cdf0e10cSrcweir 	}
151cdf0e10cSrcweir 
152cdf0e10cSrcweir 	/** verify (external representation).
153cdf0e10cSrcweir 	 */
verifyOStoreSuperBlock154cdf0e10cSrcweir 	storeError verify() const
155cdf0e10cSrcweir 	{
156cdf0e10cSrcweir 		sal_uInt32 nMagic = store::ntohl(m_aGuard.m_nMagic);
157cdf0e10cSrcweir 		if (nMagic != STORE_MAGIC_SUPERBLOCK)
158cdf0e10cSrcweir 			return store_E_WrongFormat;
159cdf0e10cSrcweir 
160cdf0e10cSrcweir 		sal_uInt32 nCRC32 = 0;
161cdf0e10cSrcweir 		nCRC32 = rtl_crc32 (nCRC32, &m_aGuard.m_nMagic, sizeof(sal_uInt32));
162cdf0e10cSrcweir 		nCRC32 = rtl_crc32 (nCRC32, &m_aDescr, theSize - sizeof(G));
163cdf0e10cSrcweir 		if (m_aGuard.m_nCRC32 != store::htonl(nCRC32))
164cdf0e10cSrcweir 			return store_E_InvalidChecksum;
165cdf0e10cSrcweir 		else
166cdf0e10cSrcweir 			return store_E_None;
167cdf0e10cSrcweir 	}
168cdf0e10cSrcweir };
169cdf0e10cSrcweir 
170cdf0e10cSrcweir /*========================================================================
171cdf0e10cSrcweir  *
172cdf0e10cSrcweir  * SuperBlockPage interface.
173cdf0e10cSrcweir  *
174cdf0e10cSrcweir  *======================================================================*/
175cdf0e10cSrcweir namespace store
176cdf0e10cSrcweir {
177cdf0e10cSrcweir 
178cdf0e10cSrcweir struct SuperBlockPage
179cdf0e10cSrcweir {
180cdf0e10cSrcweir 	typedef OStoreSuperBlock SuperBlock;
181cdf0e10cSrcweir 
182cdf0e10cSrcweir 	/** Representation.
183cdf0e10cSrcweir 	 */
184cdf0e10cSrcweir 	SuperBlock m_aSuperOne;
185cdf0e10cSrcweir 	SuperBlock m_aSuperTwo;
186cdf0e10cSrcweir 
187cdf0e10cSrcweir 	/** theSize.
188cdf0e10cSrcweir 	 */
189cdf0e10cSrcweir 	static const size_t     theSize     = 2 * SuperBlock::theSize;
190cdf0e10cSrcweir     static const sal_uInt16 thePageSize = theSize;
191cdf0e10cSrcweir 	STORE_STATIC_ASSERT(STORE_MINIMUM_PAGESIZE >= thePageSize);
192cdf0e10cSrcweir 
193cdf0e10cSrcweir 	/** Allocation.
194cdf0e10cSrcweir 	 */
operator newstore::SuperBlockPage195cdf0e10cSrcweir 	static void * operator new (size_t n) SAL_THROW(())
196cdf0e10cSrcweir 	{
197cdf0e10cSrcweir 		return rtl_allocateMemory (sal::static_int_cast<sal_Size>(n));
198cdf0e10cSrcweir 	}
operator deletestore::SuperBlockPage199cdf0e10cSrcweir 	static void operator delete (void * p, size_t) SAL_THROW(())
200cdf0e10cSrcweir 	{
201cdf0e10cSrcweir 		rtl_freeMemory (p);
202cdf0e10cSrcweir 	}
203cdf0e10cSrcweir 
operator newstore::SuperBlockPage204cdf0e10cSrcweir     static void * operator new (size_t, sal_uInt16 nPageSize) SAL_THROW(())
205cdf0e10cSrcweir     {
206cdf0e10cSrcweir         return rtl_allocateZeroMemory (sal::static_int_cast<sal_Size>(nPageSize));
207cdf0e10cSrcweir     }
operator deletestore::SuperBlockPage208cdf0e10cSrcweir     static void operator delete (void * p, sal_uInt16) SAL_THROW(())
209cdf0e10cSrcweir     {
210cdf0e10cSrcweir         rtl_freeMemory (p);
211cdf0e10cSrcweir     }
212cdf0e10cSrcweir 
213cdf0e10cSrcweir 	/** Construction.
214cdf0e10cSrcweir 	 */
SuperBlockPagestore::SuperBlockPage215cdf0e10cSrcweir 	explicit SuperBlockPage (sal_uInt16 nPageSize = thePageSize)
216cdf0e10cSrcweir         : m_aSuperOne(nPageSize),
217cdf0e10cSrcweir           m_aSuperTwo(nPageSize)
218cdf0e10cSrcweir 	{}
219cdf0e10cSrcweir 
220cdf0e10cSrcweir 	/** save.
221cdf0e10cSrcweir 	 */
savestore::SuperBlockPage222cdf0e10cSrcweir 	storeError save (OStorePageBIOS & rBIOS, sal_uInt32 nSize = theSize)
223cdf0e10cSrcweir 	{
224cdf0e10cSrcweir         m_aSuperOne.guard();
225cdf0e10cSrcweir         m_aSuperTwo = m_aSuperOne;
226cdf0e10cSrcweir 		return rBIOS.write (0, this, nSize);
227cdf0e10cSrcweir 	}
228cdf0e10cSrcweir 
229cdf0e10cSrcweir     /** Page allocation.
230cdf0e10cSrcweir      */
231cdf0e10cSrcweir     storeError unusedHead (
232cdf0e10cSrcweir         OStorePageBIOS & rBIOS,
233cdf0e10cSrcweir         PageData &       rPageHead);
234cdf0e10cSrcweir 
235cdf0e10cSrcweir     storeError unusedPop (
236cdf0e10cSrcweir         OStorePageBIOS & rBIOS,
237cdf0e10cSrcweir         PageData const & rPageHead);
238cdf0e10cSrcweir 
239cdf0e10cSrcweir     storeError unusedPush (
240cdf0e10cSrcweir         OStorePageBIOS & rBIOS,
241cdf0e10cSrcweir         sal_uInt32       nAddr);
242cdf0e10cSrcweir 
243cdf0e10cSrcweir 	/** verify (with repair).
244cdf0e10cSrcweir 	 */
245cdf0e10cSrcweir 	storeError verify (OStorePageBIOS & rBIOS);
246cdf0e10cSrcweir };
247cdf0e10cSrcweir 
248cdf0e10cSrcweir } // namespace store
249cdf0e10cSrcweir 
250cdf0e10cSrcweir /*========================================================================
251cdf0e10cSrcweir  *
252cdf0e10cSrcweir  * SuperBlockPage implementation.
253cdf0e10cSrcweir  *
254cdf0e10cSrcweir  *======================================================================*/
255cdf0e10cSrcweir /*
256cdf0e10cSrcweir  * unusedHead(): get freelist head (alloc page, step 1).
257cdf0e10cSrcweir  */
unusedHead(OStorePageBIOS & rBIOS,PageData & rPageHead)258cdf0e10cSrcweir storeError SuperBlockPage::unusedHead (OStorePageBIOS & rBIOS, PageData & rPageHead)
259cdf0e10cSrcweir {
260cdf0e10cSrcweir     storeError eErrCode = verify (rBIOS);
261cdf0e10cSrcweir     if (eErrCode != store_E_None)
262cdf0e10cSrcweir         return eErrCode;
263cdf0e10cSrcweir 
264cdf0e10cSrcweir     // Check freelist head.
265cdf0e10cSrcweir     OStorePageLink const aListHead (m_aSuperOne.unusedHead());
266cdf0e10cSrcweir     if (aListHead.location() == 0)
267cdf0e10cSrcweir     {
268cdf0e10cSrcweir         // Freelist empty, see SuperBlock::ctor().
269cdf0e10cSrcweir         rPageHead.location (STORE_PAGE_NULL);
270cdf0e10cSrcweir         return store_E_None;
271cdf0e10cSrcweir     }
272cdf0e10cSrcweir 
273cdf0e10cSrcweir     // Load PageHead.
274cdf0e10cSrcweir     eErrCode = rBIOS.read (aListHead.location(), &rPageHead, PageData::theSize);
275cdf0e10cSrcweir     if (eErrCode != store_E_None)
276cdf0e10cSrcweir         return eErrCode;
277cdf0e10cSrcweir 
278cdf0e10cSrcweir     eErrCode = rPageHead.verify (aListHead.location());
279cdf0e10cSrcweir     if (eErrCode != store_E_None)
280cdf0e10cSrcweir         return eErrCode;
281cdf0e10cSrcweir 
282cdf0e10cSrcweir     // Verify page is unused.
283cdf0e10cSrcweir     sal_uInt32 const nAddr = rPageHead.m_aUnused.location();
284cdf0e10cSrcweir     OSL_POSTCOND(nAddr != STORE_PAGE_NULL, "store::SuperBlock::unusedHead(): page not free");
285cdf0e10cSrcweir     if (nAddr == STORE_PAGE_NULL)
286cdf0e10cSrcweir     {
287cdf0e10cSrcweir         // Page in use.
288cdf0e10cSrcweir         rPageHead.location (STORE_PAGE_NULL);
289cdf0e10cSrcweir 
290cdf0e10cSrcweir         // Recovery: Reset freelist to empty.
291cdf0e10cSrcweir         m_aSuperOne.unusedReset();
292cdf0e10cSrcweir         eErrCode = save (rBIOS);
293cdf0e10cSrcweir     }
294cdf0e10cSrcweir     return eErrCode;
295cdf0e10cSrcweir }
296cdf0e10cSrcweir 
297cdf0e10cSrcweir /*
298cdf0e10cSrcweir  * unusedPop(): pop freelist head (alloc page, step 2).
299cdf0e10cSrcweir  */
unusedPop(OStorePageBIOS & rBIOS,PageData const & rPageHead)300cdf0e10cSrcweir storeError SuperBlockPage::unusedPop (OStorePageBIOS & rBIOS, PageData const & rPageHead)
301cdf0e10cSrcweir {
302cdf0e10cSrcweir     sal_uInt32 const nAddr = rPageHead.m_aUnused.location();
303cdf0e10cSrcweir     OSL_PRECOND(nAddr != STORE_PAGE_NULL, "store::SuperBlock::unusedPop(): page not free");
304cdf0e10cSrcweir     if (nAddr == STORE_PAGE_NULL)
305cdf0e10cSrcweir         return store_E_CantSeek;
306cdf0e10cSrcweir 
307cdf0e10cSrcweir     // Pop from FreeList.
308cdf0e10cSrcweir     OStorePageLink const aListHead (nAddr);
309cdf0e10cSrcweir     m_aSuperOne.unusedRemove (aListHead);
310cdf0e10cSrcweir     return save (rBIOS);
311cdf0e10cSrcweir }
312cdf0e10cSrcweir 
313cdf0e10cSrcweir /*
314cdf0e10cSrcweir  * unusedPush(): push new freelist head.
315cdf0e10cSrcweir  */
unusedPush(OStorePageBIOS & rBIOS,sal_uInt32 nAddr)316cdf0e10cSrcweir storeError SuperBlockPage::unusedPush (OStorePageBIOS & rBIOS, sal_uInt32 nAddr)
317cdf0e10cSrcweir {
318cdf0e10cSrcweir     storeError eErrCode = verify (rBIOS);
319cdf0e10cSrcweir     if (eErrCode != store_E_None)
320cdf0e10cSrcweir         return eErrCode;
321cdf0e10cSrcweir 
322cdf0e10cSrcweir     PageData aPageHead;
323cdf0e10cSrcweir     eErrCode = rBIOS.read (nAddr, &aPageHead, PageData::theSize);
324cdf0e10cSrcweir     if (eErrCode != store_E_None)
325cdf0e10cSrcweir         return eErrCode;
326cdf0e10cSrcweir 
327cdf0e10cSrcweir     eErrCode = aPageHead.verify (nAddr);
328cdf0e10cSrcweir     if (eErrCode != store_E_None)
329cdf0e10cSrcweir         return eErrCode;
330cdf0e10cSrcweir 
331cdf0e10cSrcweir     aPageHead.m_aUnused = m_aSuperOne.unusedHead();
332cdf0e10cSrcweir     aPageHead.guard (nAddr);
333cdf0e10cSrcweir 
334cdf0e10cSrcweir     eErrCode = rBIOS.write (nAddr, &aPageHead, PageData::theSize);
335cdf0e10cSrcweir     if (eErrCode != store_E_None)
336cdf0e10cSrcweir         return eErrCode;
337cdf0e10cSrcweir 
338cdf0e10cSrcweir     OStorePageLink const aListHead (nAddr);
339cdf0e10cSrcweir     m_aSuperOne.unusedInsert(aListHead);
340cdf0e10cSrcweir     return save (rBIOS);
341cdf0e10cSrcweir }
342cdf0e10cSrcweir 
343cdf0e10cSrcweir /*
344cdf0e10cSrcweir  * verify (with repair).
345cdf0e10cSrcweir  */
verify(OStorePageBIOS & rBIOS)346cdf0e10cSrcweir storeError SuperBlockPage::verify (OStorePageBIOS & rBIOS)
347cdf0e10cSrcweir {
348cdf0e10cSrcweir 	// Verify 1st copy.
349cdf0e10cSrcweir 	storeError eErrCode = m_aSuperOne.verify();
350cdf0e10cSrcweir 	if (eErrCode == store_E_None)
351cdf0e10cSrcweir 	{
352cdf0e10cSrcweir 		// Ok. Verify 2nd copy.
353cdf0e10cSrcweir 		eErrCode = m_aSuperTwo.verify();
354cdf0e10cSrcweir 		if (eErrCode == store_E_None)
355cdf0e10cSrcweir 		{
356cdf0e10cSrcweir 			// Ok. Ensure identical copies (1st copy wins).
357cdf0e10cSrcweir 			if (!(m_aSuperOne == m_aSuperTwo))
358cdf0e10cSrcweir 			{
359cdf0e10cSrcweir 				// Different. Replace 2nd copy with 1st copy.
360cdf0e10cSrcweir 				m_aSuperTwo = m_aSuperOne;
361cdf0e10cSrcweir 
362cdf0e10cSrcweir 				// Write back.
363cdf0e10cSrcweir 				if (rBIOS.isWriteable())
364cdf0e10cSrcweir 					eErrCode = rBIOS.write (0, this, theSize);
365cdf0e10cSrcweir 				else
366cdf0e10cSrcweir 					eErrCode = store_E_None;
367cdf0e10cSrcweir 			}
368cdf0e10cSrcweir 		}
369cdf0e10cSrcweir 		else
370cdf0e10cSrcweir 		{
371cdf0e10cSrcweir 			// Failure. Replace 2nd copy with 1st copy.
372cdf0e10cSrcweir 			m_aSuperTwo = m_aSuperOne;
373cdf0e10cSrcweir 
374cdf0e10cSrcweir 			// Write back.
375cdf0e10cSrcweir 			if (rBIOS.isWriteable())
376cdf0e10cSrcweir 				eErrCode = rBIOS.write (0, this, theSize);
377cdf0e10cSrcweir 			else
378cdf0e10cSrcweir 				eErrCode = store_E_None;
379cdf0e10cSrcweir 		}
380cdf0e10cSrcweir 	}
381cdf0e10cSrcweir 	else
382cdf0e10cSrcweir 	{
383cdf0e10cSrcweir 		// Failure. Verify 2nd copy.
384cdf0e10cSrcweir 		eErrCode = m_aSuperTwo.verify();
385cdf0e10cSrcweir 		if (eErrCode == store_E_None)
386cdf0e10cSrcweir 		{
387cdf0e10cSrcweir 			// Ok. Replace 1st copy with 2nd copy.
388cdf0e10cSrcweir 			m_aSuperOne = m_aSuperTwo;
389cdf0e10cSrcweir 
390cdf0e10cSrcweir 			// Write back.
391cdf0e10cSrcweir 			if (rBIOS.isWriteable())
392cdf0e10cSrcweir 				eErrCode = rBIOS.write (0, this, theSize);
393cdf0e10cSrcweir 			else
394cdf0e10cSrcweir 				eErrCode = store_E_None;
395cdf0e10cSrcweir 		}
396cdf0e10cSrcweir 		else
397cdf0e10cSrcweir 		{
398cdf0e10cSrcweir 			// Double Failure.
399cdf0e10cSrcweir 			OSL_TRACE("OStoreSuperBlockPage::verify(): double failure.\n");
400cdf0e10cSrcweir 		}
401cdf0e10cSrcweir 	}
402cdf0e10cSrcweir 
403cdf0e10cSrcweir 	// Done.
404cdf0e10cSrcweir 	return eErrCode;
405cdf0e10cSrcweir }
406cdf0e10cSrcweir 
407cdf0e10cSrcweir /*========================================================================
408cdf0e10cSrcweir  *
409cdf0e10cSrcweir  * OStorePageBIOS::Ace implementation.
410cdf0e10cSrcweir  *
411cdf0e10cSrcweir  *======================================================================*/
Ace()412cdf0e10cSrcweir OStorePageBIOS::Ace::Ace()
413cdf0e10cSrcweir   : m_next (this), m_prev (this), m_addr (STORE_PAGE_NULL), m_used (0)
414cdf0e10cSrcweir {}
415cdf0e10cSrcweir 
~Ace()416cdf0e10cSrcweir OStorePageBIOS::Ace::~Ace()
417cdf0e10cSrcweir {
418cdf0e10cSrcweir   m_next->m_prev = m_prev, m_prev->m_next = m_next;
419cdf0e10cSrcweir }
420cdf0e10cSrcweir 
421cdf0e10cSrcweir int
constructor(void * obj,void *)422cdf0e10cSrcweir SAL_CALL OStorePageBIOS::Ace::constructor (void * obj, void * /* arg */)
423cdf0e10cSrcweir {
424cdf0e10cSrcweir   Ace * ace = static_cast<Ace*>(obj);
425cdf0e10cSrcweir   ace->m_next = ace->m_prev = ace;
426cdf0e10cSrcweir   return 1;
427cdf0e10cSrcweir }
428cdf0e10cSrcweir 
429cdf0e10cSrcweir OStorePageBIOS::Ace *
find(OStorePageBIOS::Ace * head,sal_uInt32 addr)430cdf0e10cSrcweir OStorePageBIOS::Ace::find (OStorePageBIOS::Ace * head, sal_uInt32 addr)
431cdf0e10cSrcweir {
432cdf0e10cSrcweir   OStorePageBIOS::Ace * entry;
433cdf0e10cSrcweir   for (entry = head->m_next; entry != head; entry = entry->m_next)
434cdf0e10cSrcweir   {
435cdf0e10cSrcweir     if (entry->m_addr >= addr)
436cdf0e10cSrcweir       return entry;
437cdf0e10cSrcweir   }
438cdf0e10cSrcweir   return head;
439cdf0e10cSrcweir }
440cdf0e10cSrcweir 
441cdf0e10cSrcweir void
insert(OStorePageBIOS::Ace * head,OStorePageBIOS::Ace * entry)442cdf0e10cSrcweir OStorePageBIOS::Ace::insert (OStorePageBIOS::Ace * head, OStorePageBIOS::Ace * entry)
443cdf0e10cSrcweir {
444cdf0e10cSrcweir   // insert entry at queue tail (before head).
445cdf0e10cSrcweir   entry->m_next = head;
446cdf0e10cSrcweir   entry->m_prev = head->m_prev;
447cdf0e10cSrcweir   head->m_prev = entry;
448cdf0e10cSrcweir   entry->m_prev->m_next = entry;
449cdf0e10cSrcweir }
450cdf0e10cSrcweir 
451cdf0e10cSrcweir /*========================================================================
452cdf0e10cSrcweir  *
453cdf0e10cSrcweir  * OStorePageBIOS::AceCache interface.
454cdf0e10cSrcweir  *
455cdf0e10cSrcweir  *======================================================================*/
456cdf0e10cSrcweir namespace store
457cdf0e10cSrcweir {
458cdf0e10cSrcweir 
459cdf0e10cSrcweir class OStorePageBIOS::AceCache
460cdf0e10cSrcweir {
461cdf0e10cSrcweir   rtl_cache_type * m_ace_cache;
462cdf0e10cSrcweir 
463cdf0e10cSrcweir public:
464cdf0e10cSrcweir   static AceCache & get();
465cdf0e10cSrcweir 
466cdf0e10cSrcweir   OStorePageBIOS::Ace *
467cdf0e10cSrcweir   create (sal_uInt32 addr, sal_uInt32 used = 1);
468cdf0e10cSrcweir 
469cdf0e10cSrcweir   void
470cdf0e10cSrcweir   destroy (OStorePageBIOS::Ace * ace);
471cdf0e10cSrcweir 
472cdf0e10cSrcweir protected:
473cdf0e10cSrcweir   AceCache();
474cdf0e10cSrcweir   ~AceCache();
475cdf0e10cSrcweir };
476cdf0e10cSrcweir 
477cdf0e10cSrcweir } // namespace store
478cdf0e10cSrcweir 
479cdf0e10cSrcweir /*========================================================================
480cdf0e10cSrcweir  *
481cdf0e10cSrcweir  * OStorePageBIOS::AceCache implementation.
482cdf0e10cSrcweir  *
483cdf0e10cSrcweir  *======================================================================*/
484cdf0e10cSrcweir extern "C"  typedef  int (SAL_CALL * ace_constructor_type)(void*,void*);
485cdf0e10cSrcweir 
486cdf0e10cSrcweir OStorePageBIOS::AceCache &
get()487cdf0e10cSrcweir OStorePageBIOS::AceCache::get()
488cdf0e10cSrcweir {
489cdf0e10cSrcweir   static AceCache g_ace_cache;
490cdf0e10cSrcweir   return g_ace_cache;
491cdf0e10cSrcweir }
492cdf0e10cSrcweir 
AceCache()493cdf0e10cSrcweir OStorePageBIOS::AceCache::AceCache()
494cdf0e10cSrcweir {
495cdf0e10cSrcweir   m_ace_cache = rtl_cache_create (
496cdf0e10cSrcweir     "store_ace_cache",
497cdf0e10cSrcweir     sizeof (OStorePageBIOS::Ace),
498cdf0e10cSrcweir     0, // objalign
499cdf0e10cSrcweir    reinterpret_cast<ace_constructor_type>( OStorePageBIOS::Ace::constructor),
500cdf0e10cSrcweir     0, // destructor,
501cdf0e10cSrcweir     0, // reclaim,
502cdf0e10cSrcweir     0, // userarg,
503cdf0e10cSrcweir     0, // default source,
504cdf0e10cSrcweir     0  // flags
505cdf0e10cSrcweir     );
506cdf0e10cSrcweir }
507cdf0e10cSrcweir 
~AceCache()508cdf0e10cSrcweir OStorePageBIOS::AceCache::~AceCache()
509cdf0e10cSrcweir {
510cdf0e10cSrcweir   rtl_cache_destroy (m_ace_cache), m_ace_cache = 0;
511cdf0e10cSrcweir }
512cdf0e10cSrcweir 
513cdf0e10cSrcweir OStorePageBIOS::Ace *
create(sal_uInt32 addr,sal_uInt32 used)514cdf0e10cSrcweir OStorePageBIOS::AceCache::create (sal_uInt32 addr, sal_uInt32 used)
515cdf0e10cSrcweir {
516cdf0e10cSrcweir   Ace * ace = static_cast<Ace*>(rtl_cache_alloc (m_ace_cache));
517cdf0e10cSrcweir   if (ace != 0)
518cdf0e10cSrcweir   {
519cdf0e10cSrcweir     // verify invariant state.
520cdf0e10cSrcweir     OSL_ASSERT((ace->m_next == ace) && (ace->m_prev == ace));
521cdf0e10cSrcweir 
522cdf0e10cSrcweir     // initialize.
523cdf0e10cSrcweir     ace->m_addr = addr;
524cdf0e10cSrcweir     ace->m_used = used;
525cdf0e10cSrcweir   }
526cdf0e10cSrcweir   return ace;
527cdf0e10cSrcweir }
528cdf0e10cSrcweir 
529cdf0e10cSrcweir void
destroy(OStorePageBIOS::Ace * ace)530cdf0e10cSrcweir OStorePageBIOS::AceCache::destroy (OStorePageBIOS::Ace * ace)
531cdf0e10cSrcweir {
532cdf0e10cSrcweir   if (ace != 0)
533cdf0e10cSrcweir   {
534cdf0e10cSrcweir     // remove from queue (if any).
535cdf0e10cSrcweir     ace->m_next->m_prev = ace->m_prev, ace->m_prev->m_next = ace->m_next;
536cdf0e10cSrcweir 
537cdf0e10cSrcweir     // restore invariant state.
538cdf0e10cSrcweir     ace->m_next = ace->m_prev = ace;
539cdf0e10cSrcweir 
540cdf0e10cSrcweir     // return to cache.
541cdf0e10cSrcweir     rtl_cache_free (m_ace_cache, ace);
542cdf0e10cSrcweir   }
543cdf0e10cSrcweir }
544cdf0e10cSrcweir 
545cdf0e10cSrcweir /*========================================================================
546cdf0e10cSrcweir  *
547cdf0e10cSrcweir  * OStorePageBIOS implementation.
548cdf0e10cSrcweir  *
549cdf0e10cSrcweir  *======================================================================*/
550cdf0e10cSrcweir /*
551cdf0e10cSrcweir  * OStorePageBIOS.
552cdf0e10cSrcweir  */
OStorePageBIOS(void)553cdf0e10cSrcweir OStorePageBIOS::OStorePageBIOS (void)
554cdf0e10cSrcweir 	: m_xLockBytes (NULL),
555cdf0e10cSrcweir 	  m_pSuper     (NULL),
556cdf0e10cSrcweir 	  m_bWriteable (false)
557cdf0e10cSrcweir {
558cdf0e10cSrcweir }
559cdf0e10cSrcweir 
560cdf0e10cSrcweir /*
561cdf0e10cSrcweir  * ~OStorePageBIOS.
562cdf0e10cSrcweir  */
~OStorePageBIOS(void)563cdf0e10cSrcweir OStorePageBIOS::~OStorePageBIOS (void)
564cdf0e10cSrcweir {
565cdf0e10cSrcweir 	cleanup_Impl();
566cdf0e10cSrcweir }
567cdf0e10cSrcweir 
568cdf0e10cSrcweir /*
569cdf0e10cSrcweir  * initialize.
570cdf0e10cSrcweir  * Precond: none.
571cdf0e10cSrcweir  */
initialize(ILockBytes * pLockBytes,storeAccessMode eAccessMode,sal_uInt16 & rnPageSize)572cdf0e10cSrcweir storeError OStorePageBIOS::initialize (
573cdf0e10cSrcweir 	ILockBytes *    pLockBytes,
574cdf0e10cSrcweir 	storeAccessMode eAccessMode,
575cdf0e10cSrcweir 	sal_uInt16 &    rnPageSize)
576cdf0e10cSrcweir {
577cdf0e10cSrcweir 	// Acquire exclusive access.
578cdf0e10cSrcweir     osl::MutexGuard aGuard (m_aMutex);
579cdf0e10cSrcweir 
580cdf0e10cSrcweir     // Initialize.
581cdf0e10cSrcweir     storeError eErrCode = initialize_Impl (pLockBytes, eAccessMode, rnPageSize);
582cdf0e10cSrcweir     if (eErrCode != store_E_None)
583cdf0e10cSrcweir     {
584cdf0e10cSrcweir         // Cleanup.
585cdf0e10cSrcweir         cleanup_Impl();
586cdf0e10cSrcweir     }
587cdf0e10cSrcweir     return eErrCode;
588cdf0e10cSrcweir }
589cdf0e10cSrcweir 
590cdf0e10cSrcweir /*
591cdf0e10cSrcweir  * initialize_Impl.
592cdf0e10cSrcweir  * Internal: Precond: exclusive access.
593cdf0e10cSrcweir  */
initialize_Impl(ILockBytes * pLockBytes,storeAccessMode eAccessMode,sal_uInt16 & rnPageSize)594cdf0e10cSrcweir storeError OStorePageBIOS::initialize_Impl (
595cdf0e10cSrcweir 	ILockBytes *    pLockBytes,
596cdf0e10cSrcweir 	storeAccessMode eAccessMode,
597cdf0e10cSrcweir 	sal_uInt16 &    rnPageSize)
598cdf0e10cSrcweir {
599cdf0e10cSrcweir     // Cleanup.
600cdf0e10cSrcweir     cleanup_Impl();
601cdf0e10cSrcweir 
602cdf0e10cSrcweir     // Initialize.
603cdf0e10cSrcweir     m_xLockBytes = pLockBytes;
604cdf0e10cSrcweir     if (!m_xLockBytes.is())
605cdf0e10cSrcweir         return store_E_InvalidParameter;
606cdf0e10cSrcweir     m_bWriteable = (eAccessMode != store_AccessReadOnly);
607cdf0e10cSrcweir 
608cdf0e10cSrcweir     // Check access mode.
609cdf0e10cSrcweir     storeError eErrCode = store_E_None;
610cdf0e10cSrcweir     if (eAccessMode != store_AccessCreate)
611cdf0e10cSrcweir     {
612cdf0e10cSrcweir         // Load SuperBlock page.
613cdf0e10cSrcweir         if ((m_pSuper = new SuperBlockPage()) == 0)
614cdf0e10cSrcweir             return store_E_OutOfMemory;
615cdf0e10cSrcweir 
616cdf0e10cSrcweir         eErrCode = read (0, m_pSuper, SuperBlockPage::theSize);
617cdf0e10cSrcweir         if (eErrCode == store_E_None)
618cdf0e10cSrcweir         {
619cdf0e10cSrcweir             // Verify SuperBlock page (with repair).
620cdf0e10cSrcweir             eErrCode = m_pSuper->verify (*this);
621cdf0e10cSrcweir         }
622cdf0e10cSrcweir     }
623cdf0e10cSrcweir     else
624cdf0e10cSrcweir     {
625cdf0e10cSrcweir         // Truncate to zero length.
626cdf0e10cSrcweir         eErrCode = m_xLockBytes->setSize(0);
627cdf0e10cSrcweir         if (eErrCode != store_E_None)
628cdf0e10cSrcweir             return eErrCode;
629cdf0e10cSrcweir 
630cdf0e10cSrcweir         // Mark as not existing.
631cdf0e10cSrcweir         eErrCode = store_E_NotExists;
632cdf0e10cSrcweir     }
633cdf0e10cSrcweir 
634cdf0e10cSrcweir     if (eErrCode != store_E_None)
635cdf0e10cSrcweir     {
636cdf0e10cSrcweir         // Check reason.
637cdf0e10cSrcweir         if (eErrCode != store_E_NotExists)
638cdf0e10cSrcweir             return eErrCode;
639cdf0e10cSrcweir 
640cdf0e10cSrcweir         // Check mode.
641cdf0e10cSrcweir         if (eAccessMode == store_AccessReadOnly)
642cdf0e10cSrcweir             return store_E_NotExists;
643cdf0e10cSrcweir         if (eAccessMode == store_AccessReadWrite)
644cdf0e10cSrcweir             return store_E_NotExists;
645cdf0e10cSrcweir 
646cdf0e10cSrcweir         // Check PageSize.
647cdf0e10cSrcweir         if ((STORE_MINIMUM_PAGESIZE > rnPageSize) || (rnPageSize > STORE_MAXIMUM_PAGESIZE))
648cdf0e10cSrcweir             return store_E_InvalidParameter;
649cdf0e10cSrcweir         rnPageSize = ((rnPageSize + STORE_MINIMUM_PAGESIZE - 1) & ~(STORE_MINIMUM_PAGESIZE - 1));
650cdf0e10cSrcweir 
651cdf0e10cSrcweir         // Create initial page (w/ SuperBlock).
652cdf0e10cSrcweir         if ((m_pSuper = new(rnPageSize) SuperBlockPage(rnPageSize)) == 0)
653cdf0e10cSrcweir             return store_E_OutOfMemory;
654cdf0e10cSrcweir         eErrCode = m_pSuper->save (*this, rnPageSize);
655cdf0e10cSrcweir     }
656cdf0e10cSrcweir     if (eErrCode == store_E_None)
657cdf0e10cSrcweir     {
658cdf0e10cSrcweir         // Obtain page size.
659cdf0e10cSrcweir         rnPageSize = store::ntohs(m_pSuper->m_aSuperOne.m_aDescr.m_nSize);
660cdf0e10cSrcweir 
661cdf0e10cSrcweir         // Create page allocator.
662cdf0e10cSrcweir         eErrCode = m_xLockBytes->initialize (m_xAllocator, rnPageSize);
663cdf0e10cSrcweir         if (eErrCode != store_E_None)
664cdf0e10cSrcweir             return eErrCode;
665cdf0e10cSrcweir 
666cdf0e10cSrcweir         // Create page cache.
667cdf0e10cSrcweir         eErrCode = PageCache_createInstance (m_xCache, rnPageSize);
668cdf0e10cSrcweir     }
669cdf0e10cSrcweir 	return eErrCode;
670cdf0e10cSrcweir }
671cdf0e10cSrcweir 
672cdf0e10cSrcweir /*
673cdf0e10cSrcweir  * cleanup_Impl.
674cdf0e10cSrcweir  * Internal: Precond: exclusive access.
675cdf0e10cSrcweir  */
cleanup_Impl()676cdf0e10cSrcweir void OStorePageBIOS::cleanup_Impl()
677cdf0e10cSrcweir {
678cdf0e10cSrcweir 	// Check referer count.
679cdf0e10cSrcweir 	if (m_ace_head.m_used > 0)
680cdf0e10cSrcweir 	{
681cdf0e10cSrcweir 		// Report remaining referer count.
682cdf0e10cSrcweir 		OSL_TRACE("store::PageBIOS::cleanup_Impl(): referer count: %d\n", m_ace_head.m_used);
683cdf0e10cSrcweir         for (Ace * ace = m_ace_head.m_next; ace != &m_ace_head; ace = m_ace_head.m_next)
684cdf0e10cSrcweir         {
685cdf0e10cSrcweir             m_ace_head.m_used -= ace->m_used;
686cdf0e10cSrcweir             AceCache::get().destroy (ace);
687cdf0e10cSrcweir         }
688cdf0e10cSrcweir         OSL_ENSURE(m_ace_head.m_used == 0, "store::PageBIOS::cleanup_Impl(): logic error");
689cdf0e10cSrcweir 	}
690cdf0e10cSrcweir 
691cdf0e10cSrcweir     // Release SuperBlock page.
692cdf0e10cSrcweir     delete m_pSuper, m_pSuper = 0;
693cdf0e10cSrcweir 
694cdf0e10cSrcweir     // Release PageCache.
695cdf0e10cSrcweir     m_xCache.clear();
696cdf0e10cSrcweir 
697cdf0e10cSrcweir     // Release PageAllocator.
698cdf0e10cSrcweir     m_xAllocator.clear();
699cdf0e10cSrcweir 
700cdf0e10cSrcweir     // Release LockBytes.
701cdf0e10cSrcweir     m_xLockBytes.clear();
702cdf0e10cSrcweir }
703cdf0e10cSrcweir 
704cdf0e10cSrcweir /*
705cdf0e10cSrcweir  * read.
706cdf0e10cSrcweir  * Low Level: Precond: initialized, exclusive access.
707cdf0e10cSrcweir  */
read(sal_uInt32 nAddr,void * pData,sal_uInt32 nSize)708cdf0e10cSrcweir storeError OStorePageBIOS::read (
709cdf0e10cSrcweir 	sal_uInt32 nAddr, void *pData, sal_uInt32 nSize)
710cdf0e10cSrcweir {
711cdf0e10cSrcweir 	// Check precond.
712cdf0e10cSrcweir 	if (!m_xLockBytes.is())
713cdf0e10cSrcweir 		return store_E_InvalidAccess;
714cdf0e10cSrcweir 
715cdf0e10cSrcweir 	// Read Data.
716cdf0e10cSrcweir 	return m_xLockBytes->readAt (nAddr, pData, nSize);
717cdf0e10cSrcweir }
718cdf0e10cSrcweir 
719cdf0e10cSrcweir /*
720cdf0e10cSrcweir  * write.
721cdf0e10cSrcweir  * Low Level: Precond: initialized, writeable, exclusive access.
722cdf0e10cSrcweir  */
write(sal_uInt32 nAddr,const void * pData,sal_uInt32 nSize)723cdf0e10cSrcweir storeError OStorePageBIOS::write (
724cdf0e10cSrcweir 	sal_uInt32 nAddr, const void *pData, sal_uInt32 nSize)
725cdf0e10cSrcweir {
726cdf0e10cSrcweir 	// Check precond.
727cdf0e10cSrcweir 	if (!m_xLockBytes.is())
728cdf0e10cSrcweir 		return store_E_InvalidAccess;
729cdf0e10cSrcweir 	if (!m_bWriteable)
730cdf0e10cSrcweir 		return store_E_AccessViolation;
731cdf0e10cSrcweir 
732cdf0e10cSrcweir 	// Write Data.
733cdf0e10cSrcweir 	return m_xLockBytes->writeAt (nAddr, pData, nSize);
734cdf0e10cSrcweir }
735cdf0e10cSrcweir 
736cdf0e10cSrcweir /*
737cdf0e10cSrcweir  * acquirePage.
738cdf0e10cSrcweir  * Precond: initialized.
739cdf0e10cSrcweir  */
acquirePage(const OStorePageDescriptor & rDescr,storeAccessMode eMode)740cdf0e10cSrcweir storeError OStorePageBIOS::acquirePage (
741cdf0e10cSrcweir 	const OStorePageDescriptor& rDescr, storeAccessMode eMode)
742cdf0e10cSrcweir {
743cdf0e10cSrcweir 	// Acquire exclusive access.
744cdf0e10cSrcweir 	osl::MutexGuard aGuard (m_aMutex);
745cdf0e10cSrcweir 
746cdf0e10cSrcweir 	// Check precond.
747cdf0e10cSrcweir 	if (!m_xLockBytes.is())
748cdf0e10cSrcweir 		return store_E_InvalidAccess;
749cdf0e10cSrcweir 
750cdf0e10cSrcweir 	// Check access mode.
751cdf0e10cSrcweir 	if (!(m_bWriteable || (eMode == store_AccessReadOnly)))
752cdf0e10cSrcweir 		return store_E_AccessViolation;
753cdf0e10cSrcweir 
754cdf0e10cSrcweir 	// Find access control list entry.
755cdf0e10cSrcweir 	Ace * ace = Ace::find (&m_ace_head, rDescr.m_nAddr);
756cdf0e10cSrcweir 	if (ace->m_addr == rDescr.m_nAddr)
757cdf0e10cSrcweir 	{
758cdf0e10cSrcweir 	  // Acquire existing entry (with ShareDenyWrite).
759cdf0e10cSrcweir 	  if (eMode == store_AccessReadOnly)
760cdf0e10cSrcweir 	    ace->m_used += 1;
761cdf0e10cSrcweir 	  else
762cdf0e10cSrcweir 	    return store_E_AccessViolation;
763cdf0e10cSrcweir 	}
764cdf0e10cSrcweir 	else
765cdf0e10cSrcweir 	{
766cdf0e10cSrcweir 	  // Insert new entry.
767cdf0e10cSrcweir 	  Ace * entry = AceCache::get().create (rDescr.m_nAddr, 1);
768cdf0e10cSrcweir 	  if (!entry)
769cdf0e10cSrcweir 	    return store_E_OutOfMemory;
770cdf0e10cSrcweir 	  Ace::insert (ace, entry);
771cdf0e10cSrcweir 	}
772cdf0e10cSrcweir 
773cdf0e10cSrcweir 	// Increment total referer count and finish.
774cdf0e10cSrcweir 	m_ace_head.m_used += 1;
775cdf0e10cSrcweir 	return store_E_None;
776cdf0e10cSrcweir }
777cdf0e10cSrcweir 
778cdf0e10cSrcweir /*
779cdf0e10cSrcweir  * releasePage.
780cdf0e10cSrcweir  * Precond: initialized.
781cdf0e10cSrcweir  */
releasePage(const OStorePageDescriptor & rDescr,storeAccessMode)782cdf0e10cSrcweir storeError OStorePageBIOS::releasePage (
783cdf0e10cSrcweir 	const OStorePageDescriptor& rDescr, storeAccessMode /* eMode */)
784cdf0e10cSrcweir {
785cdf0e10cSrcweir 	// Acquire exclusive access.
786cdf0e10cSrcweir 	osl::MutexGuard aGuard (m_aMutex);
787cdf0e10cSrcweir 
788cdf0e10cSrcweir 	// Check precond.
789cdf0e10cSrcweir 	if (!m_xLockBytes.is())
790cdf0e10cSrcweir 		return store_E_InvalidAccess;
791cdf0e10cSrcweir 
792cdf0e10cSrcweir 	// Find access control list entry.
793cdf0e10cSrcweir 	Ace * ace = Ace::find (&m_ace_head, rDescr.m_nAddr);
794cdf0e10cSrcweir 	if (ace->m_addr != rDescr.m_nAddr)
795cdf0e10cSrcweir 	  return store_E_NotExists;
796cdf0e10cSrcweir 
797cdf0e10cSrcweir 	// Release existing entry.
798cdf0e10cSrcweir 	if (ace->m_used > 1)
799cdf0e10cSrcweir 	  ace->m_used -= 1;
800cdf0e10cSrcweir 	else
801cdf0e10cSrcweir 	  AceCache::get().destroy (ace);
802cdf0e10cSrcweir 
803cdf0e10cSrcweir 	// Decrement total referer count and finish.
804cdf0e10cSrcweir 	m_ace_head.m_used -= 1;
805cdf0e10cSrcweir 	return store_E_None;
806cdf0e10cSrcweir }
807cdf0e10cSrcweir 
808cdf0e10cSrcweir /*
809cdf0e10cSrcweir  * getRefererCount.
810cdf0e10cSrcweir  * Precond: none.
811cdf0e10cSrcweir  */
getRefererCount(void)812cdf0e10cSrcweir sal_uInt32 OStorePageBIOS::getRefererCount (void)
813cdf0e10cSrcweir {
814cdf0e10cSrcweir 	// Acquire exclusive access.
815cdf0e10cSrcweir 	osl::MutexGuard aGuard (m_aMutex);
816cdf0e10cSrcweir 
817cdf0e10cSrcweir 	// Obtain total referer count.
818cdf0e10cSrcweir 	return m_ace_head.m_used;
819cdf0e10cSrcweir }
820cdf0e10cSrcweir 
821cdf0e10cSrcweir /*
822cdf0e10cSrcweir  * allocate.
823cdf0e10cSrcweir  * Precond: initialized, writeable.
824cdf0e10cSrcweir  */
allocate(OStorePageObject & rPage,Allocation eAlloc)825cdf0e10cSrcweir storeError OStorePageBIOS::allocate (
826cdf0e10cSrcweir 	OStorePageObject& rPage, Allocation eAlloc)
827cdf0e10cSrcweir {
828cdf0e10cSrcweir 	// Acquire exclusive access.
829cdf0e10cSrcweir 	osl::MutexGuard aGuard (m_aMutex);
830cdf0e10cSrcweir 
831cdf0e10cSrcweir 	// Check precond.
832cdf0e10cSrcweir 	if (!m_xLockBytes.is())
833cdf0e10cSrcweir 		return store_E_InvalidAccess;
834cdf0e10cSrcweir 	if (!m_bWriteable)
835cdf0e10cSrcweir 		return store_E_AccessViolation;
836cdf0e10cSrcweir 
837cdf0e10cSrcweir 	// Check allocation type.
838cdf0e10cSrcweir 	storeError eErrCode = store_E_None;
839cdf0e10cSrcweir 	if (eAlloc != ALLOCATE_EOF)
840cdf0e10cSrcweir 	{
841cdf0e10cSrcweir         // Try freelist head.
842cdf0e10cSrcweir         PageData aPageHead;
843cdf0e10cSrcweir         eErrCode = m_pSuper->unusedHead (*this, aPageHead);
844cdf0e10cSrcweir         if (eErrCode != store_E_None)
845cdf0e10cSrcweir             return eErrCode;
846cdf0e10cSrcweir 
847cdf0e10cSrcweir         sal_uInt32 const nAddr = aPageHead.location();
848cdf0e10cSrcweir         if (nAddr != STORE_PAGE_NULL)
849cdf0e10cSrcweir         {
850cdf0e10cSrcweir             // Save page.
851cdf0e10cSrcweir             eErrCode = saveObjectAt_Impl (rPage, nAddr);
852cdf0e10cSrcweir 			if (eErrCode != store_E_None)
853cdf0e10cSrcweir 				return eErrCode;
854cdf0e10cSrcweir 
855cdf0e10cSrcweir 			// Pop freelist head and finish.
856cdf0e10cSrcweir             return m_pSuper->unusedPop (*this, aPageHead);
857cdf0e10cSrcweir         }
858cdf0e10cSrcweir 	}
859cdf0e10cSrcweir 
860cdf0e10cSrcweir 	// Allocate from EOF. Determine current size.
861cdf0e10cSrcweir 	sal_uInt32 nSize = STORE_PAGE_NULL;
862cdf0e10cSrcweir 	eErrCode = m_xLockBytes->getSize (nSize);
863cdf0e10cSrcweir 	if (eErrCode != store_E_None)
864cdf0e10cSrcweir 		return eErrCode;
865cdf0e10cSrcweir 
866cdf0e10cSrcweir 	// Save page at current EOF.
867cdf0e10cSrcweir     return saveObjectAt_Impl (rPage, nSize);
868cdf0e10cSrcweir }
869cdf0e10cSrcweir 
870cdf0e10cSrcweir /*
871cdf0e10cSrcweir  * free.
872cdf0e10cSrcweir  * Precond: initialized, writeable.
873cdf0e10cSrcweir  */
free(sal_uInt32 nAddr)874cdf0e10cSrcweir storeError OStorePageBIOS::free (sal_uInt32 nAddr)
875cdf0e10cSrcweir {
876cdf0e10cSrcweir 	// Acquire exclusive access.
877cdf0e10cSrcweir 	osl::MutexGuard aGuard (m_aMutex);
878cdf0e10cSrcweir 
879cdf0e10cSrcweir 	// Check precond.
880cdf0e10cSrcweir 	if (!m_xLockBytes.is())
881cdf0e10cSrcweir 		return store_E_InvalidAccess;
882cdf0e10cSrcweir 	if (!m_bWriteable)
883cdf0e10cSrcweir 		return store_E_AccessViolation;
884cdf0e10cSrcweir 
885cdf0e10cSrcweir     // Invalidate cache.
886cdf0e10cSrcweir     (void) m_xCache->removePageAt (nAddr);
887cdf0e10cSrcweir 
888cdf0e10cSrcweir 	// Push onto freelist.
889cdf0e10cSrcweir     return m_pSuper->unusedPush (*this, nAddr);
890cdf0e10cSrcweir }
891cdf0e10cSrcweir 
892cdf0e10cSrcweir /*
893cdf0e10cSrcweir  * loadObjectAt.
894cdf0e10cSrcweir  * Precond: initialized, readable.
895cdf0e10cSrcweir  */
loadObjectAt(OStorePageObject & rPage,sal_uInt32 nAddr)896cdf0e10cSrcweir storeError OStorePageBIOS::loadObjectAt (OStorePageObject & rPage, sal_uInt32 nAddr)
897cdf0e10cSrcweir {
898cdf0e10cSrcweir 	// Acquire exclusive access.
899cdf0e10cSrcweir 	osl::MutexGuard aGuard (m_aMutex);
900cdf0e10cSrcweir 
901cdf0e10cSrcweir 	// Check precond.
902cdf0e10cSrcweir 	if (!m_xLockBytes.is())
903cdf0e10cSrcweir 		return store_E_InvalidAccess;
904cdf0e10cSrcweir 
905cdf0e10cSrcweir     return loadObjectAt_Impl (rPage, nAddr);
906cdf0e10cSrcweir }
907cdf0e10cSrcweir 
908cdf0e10cSrcweir /*
909cdf0e10cSrcweir  * loadObjectAt_Impl.
910cdf0e10cSrcweir  * Internal: Precond: initialized, readable, exclusive access.
911cdf0e10cSrcweir  */
loadObjectAt_Impl(OStorePageObject & rPage,sal_uInt32 nAddr)912cdf0e10cSrcweir storeError OStorePageBIOS::loadObjectAt_Impl (OStorePageObject & rPage, sal_uInt32 nAddr)
913cdf0e10cSrcweir {
914cdf0e10cSrcweir     storeError eErrCode = m_xCache->lookupPageAt (rPage.get(), nAddr);
915cdf0e10cSrcweir     if (eErrCode != store_E_NotExists)
916cdf0e10cSrcweir         return eErrCode;
917cdf0e10cSrcweir 
918cdf0e10cSrcweir     // Read page.
919cdf0e10cSrcweir     eErrCode = m_xLockBytes->readPageAt (rPage.get(), nAddr);
920cdf0e10cSrcweir     if (eErrCode != store_E_None)
921cdf0e10cSrcweir         return eErrCode;
922cdf0e10cSrcweir 
923cdf0e10cSrcweir     // Verify page.
924cdf0e10cSrcweir     eErrCode = rPage.verify (nAddr);
925cdf0e10cSrcweir     if (eErrCode != store_E_None)
926cdf0e10cSrcweir         return eErrCode;
927cdf0e10cSrcweir 
928cdf0e10cSrcweir     // Mark page as clean.
929cdf0e10cSrcweir     rPage.clean();
930cdf0e10cSrcweir 
931cdf0e10cSrcweir     // Cache page.
932cdf0e10cSrcweir     return m_xCache->insertPageAt (rPage.get(), nAddr);
933cdf0e10cSrcweir }
934cdf0e10cSrcweir 
935cdf0e10cSrcweir /*
936cdf0e10cSrcweir  * saveObjectAt.
937cdf0e10cSrcweir  * Precond: initialized, writeable.
938cdf0e10cSrcweir  */
saveObjectAt(OStorePageObject & rPage,sal_uInt32 nAddr)939cdf0e10cSrcweir storeError OStorePageBIOS::saveObjectAt (OStorePageObject & rPage, sal_uInt32 nAddr)
940cdf0e10cSrcweir {
941cdf0e10cSrcweir 	// Acquire exclusive access.
942cdf0e10cSrcweir 	osl::MutexGuard aGuard (m_aMutex);
943cdf0e10cSrcweir 
944cdf0e10cSrcweir 	// Check precond.
945cdf0e10cSrcweir 	if (!m_xLockBytes.is())
946cdf0e10cSrcweir 		return store_E_InvalidAccess;
947cdf0e10cSrcweir 	if (!m_bWriteable)
948cdf0e10cSrcweir 		return store_E_AccessViolation;
949cdf0e10cSrcweir 
950cdf0e10cSrcweir 	// Save Page.
951cdf0e10cSrcweir 	return saveObjectAt_Impl (rPage, nAddr);
952cdf0e10cSrcweir }
953cdf0e10cSrcweir 
954cdf0e10cSrcweir /*
955cdf0e10cSrcweir  * saveObjectAt_Impl.
956cdf0e10cSrcweir  * Internal: Precond: initialized, writeable, exclusive access.
957cdf0e10cSrcweir  */
saveObjectAt_Impl(OStorePageObject & rPage,sal_uInt32 nAddr)958cdf0e10cSrcweir storeError OStorePageBIOS::saveObjectAt_Impl (OStorePageObject & rPage, sal_uInt32 nAddr)
959cdf0e10cSrcweir {
960cdf0e10cSrcweir     // Guard page (incl. set location).
961cdf0e10cSrcweir     storeError eErrCode = rPage.guard (nAddr);
962cdf0e10cSrcweir     if (eErrCode != store_E_None)
963cdf0e10cSrcweir         return eErrCode;
964cdf0e10cSrcweir 
965cdf0e10cSrcweir     // Write page.
966cdf0e10cSrcweir     eErrCode = m_xLockBytes->writePageAt(rPage.get(), nAddr);
967cdf0e10cSrcweir     if (eErrCode != store_E_None)
968cdf0e10cSrcweir         return eErrCode;
969cdf0e10cSrcweir 
970cdf0e10cSrcweir     // Mark page as clean.
971cdf0e10cSrcweir     rPage.clean();
972cdf0e10cSrcweir 
973cdf0e10cSrcweir     // Cache page.
974cdf0e10cSrcweir     return m_xCache->updatePageAt (rPage.get(), nAddr);
975cdf0e10cSrcweir }
976cdf0e10cSrcweir 
977cdf0e10cSrcweir /*
978cdf0e10cSrcweir  * close.
979cdf0e10cSrcweir  * Precond: none.
980cdf0e10cSrcweir  */
close()981cdf0e10cSrcweir storeError OStorePageBIOS::close()
982cdf0e10cSrcweir {
983cdf0e10cSrcweir 	// Acquire exclusive access.
984cdf0e10cSrcweir     osl::MutexGuard aGuard (m_aMutex);
985cdf0e10cSrcweir 
986cdf0e10cSrcweir     // Cleanup.
987cdf0e10cSrcweir     cleanup_Impl();
988cdf0e10cSrcweir 
989cdf0e10cSrcweir 	// Done.
990cdf0e10cSrcweir     return store_E_None;
991cdf0e10cSrcweir }
992cdf0e10cSrcweir 
993cdf0e10cSrcweir /*
994cdf0e10cSrcweir  * flush.
995cdf0e10cSrcweir  * Precond: initialized.
996cdf0e10cSrcweir  */
flush(void)997cdf0e10cSrcweir storeError OStorePageBIOS::flush (void)
998cdf0e10cSrcweir {
999cdf0e10cSrcweir 	// Acquire exclusive access.
1000cdf0e10cSrcweir 	osl::MutexGuard aGuard (m_aMutex);
1001cdf0e10cSrcweir 
1002cdf0e10cSrcweir 	// Check precond.
1003cdf0e10cSrcweir 	if (!m_xLockBytes.is())
1004cdf0e10cSrcweir 		return store_E_InvalidAccess;
1005cdf0e10cSrcweir 
1006cdf0e10cSrcweir 	// Flush LockBytes and finish.
1007cdf0e10cSrcweir 	return m_xLockBytes->flush();
1008cdf0e10cSrcweir }
1009cdf0e10cSrcweir 
1010cdf0e10cSrcweir /*
1011cdf0e10cSrcweir  * size.
1012cdf0e10cSrcweir  * Precond: initialized.
1013cdf0e10cSrcweir  */
size(sal_uInt32 & rnSize)1014cdf0e10cSrcweir storeError OStorePageBIOS::size (sal_uInt32 &rnSize)
1015cdf0e10cSrcweir {
1016cdf0e10cSrcweir 	// Acquire exclusive access.
1017cdf0e10cSrcweir 	osl::MutexGuard aGuard (m_aMutex);
1018cdf0e10cSrcweir 
1019cdf0e10cSrcweir 	// Initialize [out] param.
1020cdf0e10cSrcweir 	rnSize = 0;
1021cdf0e10cSrcweir 
1022cdf0e10cSrcweir 	// Check precond.
1023cdf0e10cSrcweir 	if (!m_xLockBytes.is())
1024cdf0e10cSrcweir 		return store_E_InvalidAccess;
1025cdf0e10cSrcweir 
1026cdf0e10cSrcweir 	// Obtain LockBytes size.
1027cdf0e10cSrcweir 	return m_xLockBytes->getSize (rnSize);
1028cdf0e10cSrcweir }
1029cdf0e10cSrcweir 
1030cdf0e10cSrcweir /*
1031cdf0e10cSrcweir  * scanBegin.
1032cdf0e10cSrcweir  * Precond: initialized.
1033cdf0e10cSrcweir  */
scanBegin(ScanContext & rCtx,sal_uInt32 nMagic)1034cdf0e10cSrcweir storeError OStorePageBIOS::scanBegin (
1035cdf0e10cSrcweir 	ScanContext &rCtx, sal_uInt32 nMagic)
1036cdf0e10cSrcweir {
1037cdf0e10cSrcweir 	// Acquire exclusive access.
1038cdf0e10cSrcweir 	osl::MutexGuard aGuard (m_aMutex);
1039cdf0e10cSrcweir 
1040cdf0e10cSrcweir 	// Initialize [out] param.
1041cdf0e10cSrcweir 	rCtx.m_aDescr = OStorePageDescriptor(0, 0, 0);
1042cdf0e10cSrcweir 	rCtx.m_nSize  = 0;
1043cdf0e10cSrcweir 	rCtx.m_nMagic = nMagic;
1044cdf0e10cSrcweir 
1045cdf0e10cSrcweir 	// Check precond.
1046cdf0e10cSrcweir 	if (!m_xLockBytes.is())
1047cdf0e10cSrcweir 		return store_E_InvalidAccess;
1048cdf0e10cSrcweir 
1049cdf0e10cSrcweir 	// Check SuperBlock page.
1050cdf0e10cSrcweir 	storeError eErrCode = m_pSuper->verify (*this);
1051cdf0e10cSrcweir 	if (eErrCode != store_E_None)
1052cdf0e10cSrcweir 	{
1053cdf0e10cSrcweir 		// Damaged. Determine page size (NYI).
1054cdf0e10cSrcweir 		OSL_TRACE ("OStorePageBIOS::scanBegin(): damaged.\n");
1055cdf0e10cSrcweir 		return eErrCode;
1056cdf0e10cSrcweir 	}
1057cdf0e10cSrcweir 
1058cdf0e10cSrcweir 	// Setup Context descriptor.
1059cdf0e10cSrcweir 	rCtx.m_aDescr = m_pSuper->m_aSuperOne.m_aDescr;
1060cdf0e10cSrcweir 	rCtx.m_aDescr.m_nSize = store::ntohs(rCtx.m_aDescr.m_nSize);
1061cdf0e10cSrcweir 	rCtx.m_aDescr.m_nAddr = rCtx.m_aDescr.m_nSize;
1062cdf0e10cSrcweir 
1063cdf0e10cSrcweir 	// Setup Context size.
1064cdf0e10cSrcweir 	eErrCode = size (rCtx.m_nSize);
1065cdf0e10cSrcweir 	if (eErrCode != store_E_None)
1066cdf0e10cSrcweir 		rCtx.m_nSize = ((sal_uInt32)(~0));
1067cdf0e10cSrcweir 
1068cdf0e10cSrcweir 	// Done.
1069cdf0e10cSrcweir 	return store_E_None;
1070cdf0e10cSrcweir }
1071cdf0e10cSrcweir 
1072cdf0e10cSrcweir /*
1073cdf0e10cSrcweir  * scanNext.
1074cdf0e10cSrcweir  * Precond: initialized.
1075cdf0e10cSrcweir  */
scanNext(ScanContext & rCtx,OStorePageObject & rPage)1076cdf0e10cSrcweir storeError OStorePageBIOS::scanNext (
1077cdf0e10cSrcweir 	ScanContext &rCtx, OStorePageObject &rPage)
1078cdf0e10cSrcweir {
1079cdf0e10cSrcweir 	// Acquire exclusive access.
1080cdf0e10cSrcweir 	osl::MutexGuard aGuard (m_aMutex);
1081cdf0e10cSrcweir 
1082cdf0e10cSrcweir 	// Check precond.
1083cdf0e10cSrcweir 	if (!m_xLockBytes.is())
1084cdf0e10cSrcweir 		return store_E_InvalidAccess;
1085cdf0e10cSrcweir 
1086cdf0e10cSrcweir 	// Setup PageHead.
1087cdf0e10cSrcweir 	PageData aPageHead;
1088cdf0e10cSrcweir 
1089cdf0e10cSrcweir 	// Check context.
1090cdf0e10cSrcweir 	while (rCtx.isValid())
1091cdf0e10cSrcweir 	{
1092cdf0e10cSrcweir 		// Assign next location.
1093cdf0e10cSrcweir 		sal_uInt32 nAddr = rCtx.m_aDescr.m_nAddr;
1094cdf0e10cSrcweir 		rCtx.m_aDescr.m_nAddr += rCtx.m_aDescr.m_nSize;
1095cdf0e10cSrcweir 
1096cdf0e10cSrcweir         // Read PageHead.
1097cdf0e10cSrcweir         storeError eErrCode = read (nAddr, &aPageHead, PageData::theSize);
1098cdf0e10cSrcweir         if (eErrCode != store_E_None)
1099cdf0e10cSrcweir 			continue;
1100cdf0e10cSrcweir 
1101cdf0e10cSrcweir         // Verify PageHead.
1102cdf0e10cSrcweir         eErrCode = aPageHead.verify (nAddr);
1103cdf0e10cSrcweir         if (eErrCode != store_E_None)
1104cdf0e10cSrcweir 			continue;
1105cdf0e10cSrcweir 
1106cdf0e10cSrcweir 		// Check PageHead Magic number.
1107cdf0e10cSrcweir 		if (aPageHead.m_aGuard.m_nMagic != rCtx.m_nMagic)
1108cdf0e10cSrcweir 			continue;
1109cdf0e10cSrcweir 
1110cdf0e10cSrcweir 		// Check PageHead Unused link.
1111cdf0e10cSrcweir 		if (aPageHead.m_aUnused.m_nAddr != STORE_PAGE_NULL)
1112cdf0e10cSrcweir 			continue;
1113cdf0e10cSrcweir 
1114cdf0e10cSrcweir 		// Load page.
1115cdf0e10cSrcweir 		eErrCode = loadObjectAt_Impl (rPage, nAddr);
1116cdf0e10cSrcweir 		if (eErrCode != store_E_None)
1117cdf0e10cSrcweir 			continue;
1118cdf0e10cSrcweir 
1119cdf0e10cSrcweir 		// Deliver page.
1120cdf0e10cSrcweir 		return store_E_None;
1121cdf0e10cSrcweir 	}
1122cdf0e10cSrcweir 
1123cdf0e10cSrcweir 	// Done.
1124cdf0e10cSrcweir 	return store_E_CantSeek;
1125cdf0e10cSrcweir }
1126