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
10cdf0e10cSrcweir *
11*73d9b18aSAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir *
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.
19cdf0e10cSrcweir *
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