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