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