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