Bug Summary

File:store/source/storbios.cxx
Location:line 960, column 16
Description:Called C++ object pointer is null

Annotated Source Code

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
37using namespace store;
38
39/*========================================================================
40 *
41 * OStoreSuperBlock.
42 *
43 *======================================================================*/
44#define STORE_MAGIC_SUPERBLOCKsal_uInt32(0x484D5343) sal_uInt32(0x484D5343)
45
46struct 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 *======================================================================*/
169namespace store
170{
171
172struct 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 */
252storeError 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 */
294storeError 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 */
310storeError 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 */
340storeError 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 *======================================================================*/
406OStorePageBIOS::Ace::Ace()
407 : m_next (this), m_prev (this), m_addr (STORE_PAGE_NULL((sal_uInt32)(~0))), m_used (0)
408{}
409
410OStorePageBIOS::Ace::~Ace()
411{
412 m_next->m_prev = m_prev, m_prev->m_next = m_next;
413}
414
415int
416SAL_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
424OStorePageBIOS::Ace *
425OStorePageBIOS::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
436void
437OStorePageBIOS::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 *======================================================================*/
451namespace store
452{
453
454class OStorePageBIOS::AceCache
455{
456 rtl_cache_type * m_ace_cache;
457
458public:
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
467protected:
468 AceCache();
469 ~AceCache();
470};
471
472} // namespace store
473
474/*========================================================================
475 *
476 * OStorePageBIOS::AceCache implementation.
477 *
478 *======================================================================*/
479extern "C" typedef int (SAL_CALL * ace_constructor_type)(void*,void*);
480
481OStorePageBIOS::AceCache &
482OStorePageBIOS::AceCache::get()
483{
484 static AceCache g_ace_cache;
485 return g_ace_cache;
486}
487
488OStorePageBIOS::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
503OStorePageBIOS::AceCache::~AceCache()
504{
505 rtl_cache_destroy (m_ace_cache), m_ace_cache = 0;
506}
507
508OStorePageBIOS::Ace *
509OStorePageBIOS::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
524void
525OStorePageBIOS::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 */
548OStorePageBIOS::OStorePageBIOS (void)
549 : m_xLockBytes (NULL__null),
550 m_pSuper (NULL__null),
551 m_bWriteable (false)
552{
553}
554
555/*
556 * ~OStorePageBIOS.
557 */
558OStorePageBIOS::~OStorePageBIOS (void)
559{
560 cleanup_Impl();
561}
562
563/*
564 * initialize.
565 * Precond: none.
566 */
567storeError 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 */
589storeError 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 */
671void 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 */
703storeError 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 */
718storeError 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 */
735storeError 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 */
777storeError 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 */
806sal_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 */
819storeError 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 */
868storeError 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 */
890storeError 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 */
906storeError 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 */
933storeError 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 */
952storeError 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)
1
Taking false branch
957 return eErrCode;
958
959 // Write page.
960 eErrCode = m_xLockBytes->writePageAt(rPage.get(), nAddr);
2
Called C++ object pointer is null
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 */
975storeError 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 */
991storeError 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 */
1008storeError 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 */
1028storeError 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 */
1070storeError 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: */