1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_store.hxx" 30 31 #include "stordata.hxx" 32 33 #include "sal/types.h" 34 #include "osl/diagnose.h" 35 36 #include "store/types.h" 37 #include "storbase.hxx" 38 #include "storbios.hxx" 39 40 using namespace store; 41 42 /*======================================================================== 43 * 44 * OStoreDataPageObject implementation. 45 * 46 *======================================================================*/ 47 /* 48 * guard. 49 */ 50 storeError OStoreDataPageObject::guard (sal_uInt32 nAddr) 51 { 52 return PageHolderObject< page >::guard (m_xPage, nAddr); 53 } 54 55 /* 56 * verify. 57 */ 58 storeError OStoreDataPageObject::verify (sal_uInt32 nAddr) const 59 { 60 return PageHolderObject< page >::verify (m_xPage, nAddr); 61 } 62 63 /*======================================================================== 64 * 65 * OStoreIndirectionPageObject implementation. 66 * 67 *======================================================================*/ 68 /* 69 * store_truncate_Impl (single indirect page). 70 */ 71 static storeError store_truncate_Impl ( 72 sal_uInt32 nAddr, 73 sal_uInt16 nSingle, 74 OStorePageBIOS &rBIOS) 75 { 76 if (nAddr != STORE_PAGE_NULL) 77 { 78 // Load single indirect page. 79 OStoreIndirectionPageObject aSingle; 80 storeError eErrCode = rBIOS.loadObjectAt (aSingle, nAddr); 81 if (eErrCode == store_E_None) 82 { 83 // Truncate to 'nSingle' direct pages. 84 eErrCode = aSingle.truncate (nSingle, rBIOS); 85 if (eErrCode != store_E_None) 86 return eErrCode; 87 } 88 else 89 { 90 if (eErrCode != store_E_InvalidChecksum) 91 return eErrCode; 92 } 93 94 // Check for complete truncation. 95 if (nSingle == 0) 96 { 97 // Free single indirect page. 98 eErrCode = rBIOS.free (nAddr); 99 if (eErrCode != store_E_None) 100 return eErrCode; 101 } 102 } 103 return store_E_None; 104 } 105 106 /* 107 * store_truncate_Impl (double indirect page). 108 */ 109 static storeError store_truncate_Impl ( 110 sal_uInt32 nAddr, 111 sal_uInt16 nDouble, 112 sal_uInt16 nSingle, 113 OStorePageBIOS &rBIOS) 114 { 115 if (nAddr != STORE_PAGE_NULL) 116 { 117 // Load double indirect page. 118 OStoreIndirectionPageObject aDouble; 119 storeError eErrCode = rBIOS.loadObjectAt (aDouble, nAddr); 120 if (eErrCode == store_E_None) 121 { 122 // Truncate to 'nDouble', 'nSingle' pages. 123 eErrCode = aDouble.truncate (nDouble, nSingle, rBIOS); 124 if (eErrCode != store_E_None) 125 return eErrCode; 126 } 127 else 128 { 129 if (eErrCode != store_E_InvalidChecksum) 130 return eErrCode; 131 } 132 133 // Check for complete truncation. 134 if ((nDouble + nSingle) == 0) 135 { 136 // Free double indirect page. 137 eErrCode = rBIOS.free (nAddr); 138 if (eErrCode != store_E_None) 139 return eErrCode; 140 } 141 } 142 return store_E_None; 143 } 144 145 /* 146 * store_truncate_Impl (triple indirect page). 147 */ 148 static storeError store_truncate_Impl ( 149 sal_uInt32 nAddr, 150 sal_uInt16 nTriple, 151 sal_uInt16 nDouble, 152 sal_uInt16 nSingle, 153 OStorePageBIOS &rBIOS) 154 { 155 if (nAddr != STORE_PAGE_NULL) 156 { 157 // Load triple indirect page. 158 OStoreIndirectionPageObject aTriple; 159 storeError eErrCode = rBIOS.loadObjectAt (aTriple, nAddr); 160 if (eErrCode != store_E_None) 161 return eErrCode; 162 163 // Truncate to 'nTriple', 'nDouble', 'nSingle' pages. 164 eErrCode = aTriple.truncate (nTriple, nDouble, nSingle, rBIOS); 165 if (eErrCode != store_E_None) 166 return eErrCode; 167 168 // Check for complete truncation. 169 if ((nTriple + nDouble + nSingle) == 0) 170 { 171 // Free triple indirect page. 172 eErrCode = rBIOS.free (nAddr); 173 if (eErrCode != store_E_None) 174 return eErrCode; 175 } 176 } 177 return store_E_None; 178 } 179 180 /* 181 * loadOrCreate. 182 */ 183 storeError OStoreIndirectionPageObject::loadOrCreate ( 184 sal_uInt32 nAddr, 185 OStorePageBIOS & rBIOS) 186 { 187 if (nAddr == STORE_PAGE_NULL) 188 { 189 storeError eErrCode = construct<page>(rBIOS.allocator()); 190 if (eErrCode != store_E_None) 191 return eErrCode; 192 193 eErrCode = rBIOS.allocate (*this); 194 if (eErrCode != store_E_None) 195 return eErrCode; 196 197 // Save location pending at caller. 198 return store_E_Pending; 199 } 200 return rBIOS.loadObjectAt (*this, nAddr); 201 } 202 203 /* 204 * guard. 205 */ 206 storeError OStoreIndirectionPageObject::guard (sal_uInt32 nAddr) 207 { 208 return PageHolderObject< page >::guard (m_xPage, nAddr); 209 } 210 211 /* 212 * verify. 213 */ 214 storeError OStoreIndirectionPageObject::verify (sal_uInt32 nAddr) const 215 { 216 return PageHolderObject< page >::verify (m_xPage, nAddr); 217 } 218 219 /* 220 * read (single indirect). 221 */ 222 storeError OStoreIndirectionPageObject::read ( 223 sal_uInt16 nSingle, 224 OStoreDataPageObject &rData, 225 OStorePageBIOS &rBIOS) 226 { 227 PageHolderObject< page > xImpl (m_xPage); 228 page const & rPage = (*xImpl); 229 230 // Check arguments. 231 sal_uInt16 const nLimit = rPage.capacityCount(); 232 if (!(nSingle < nLimit)) 233 return store_E_InvalidAccess; 234 235 // Obtain data page location. 236 sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nSingle]); 237 if (nAddr == STORE_PAGE_NULL) 238 return store_E_NotExists; 239 240 // Load data page and leave. 241 return rBIOS.loadObjectAt (rData, nAddr); 242 } 243 244 /* 245 * read (double indirect). 246 */ 247 storeError OStoreIndirectionPageObject::read ( 248 sal_uInt16 nDouble, 249 sal_uInt16 nSingle, 250 OStoreDataPageObject &rData, 251 OStorePageBIOS &rBIOS) 252 { 253 PageHolderObject< page > xImpl (m_xPage); 254 page const & rPage = (*xImpl); 255 256 // Check arguments. 257 sal_uInt16 const nLimit = rPage.capacityCount(); 258 if (!((nDouble < nLimit) && (nSingle < nLimit))) 259 return store_E_InvalidAccess; 260 261 // Check single indirect page location. 262 sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nDouble]); 263 if (nAddr == STORE_PAGE_NULL) 264 return store_E_NotExists; 265 266 // Load single indirect page. 267 OStoreIndirectionPageObject aSingle; 268 storeError eErrCode = rBIOS.loadObjectAt (aSingle, nAddr); 269 if (eErrCode != store_E_None) 270 return eErrCode; 271 272 // Read single indirect and leave. 273 return aSingle.read (nSingle, rData, rBIOS); 274 } 275 276 /* 277 * read (triple indirect). 278 */ 279 storeError OStoreIndirectionPageObject::read ( 280 sal_uInt16 nTriple, 281 sal_uInt16 nDouble, 282 sal_uInt16 nSingle, 283 OStoreDataPageObject &rData, 284 OStorePageBIOS &rBIOS) 285 { 286 PageHolderObject< page > xImpl (m_xPage); 287 page const & rPage = (*xImpl); 288 289 // Check arguments. 290 sal_uInt16 const nLimit = rPage.capacityCount(); 291 if (!((nTriple < nLimit) && (nDouble < nLimit) && (nSingle < nLimit))) 292 return store_E_InvalidAccess; 293 294 // Check double indirect page location. 295 sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nTriple]); 296 if (nAddr == STORE_PAGE_NULL) 297 return store_E_NotExists; 298 299 // Load double indirect page. 300 OStoreIndirectionPageObject aDouble; 301 storeError eErrCode = rBIOS.loadObjectAt (aDouble, nAddr); 302 if (eErrCode != store_E_None) 303 return eErrCode; 304 305 // Read double indirect and leave. 306 return aDouble.read (nDouble, nSingle, rData, rBIOS); 307 } 308 309 /* 310 * write (single indirect). 311 */ 312 storeError OStoreIndirectionPageObject::write ( 313 sal_uInt16 nSingle, 314 OStoreDataPageObject &rData, 315 OStorePageBIOS &rBIOS) 316 { 317 PageHolderObject< page > xImpl (m_xPage); 318 page & rPage = (*xImpl); 319 320 // Check arguments. 321 sal_uInt16 const nLimit = rPage.capacityCount(); 322 if (!(nSingle < nLimit)) 323 return store_E_InvalidAccess; 324 325 // Obtain data page location. 326 sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nSingle]); 327 if (nAddr == STORE_PAGE_NULL) 328 { 329 // Allocate data page. 330 storeError eErrCode = rBIOS.allocate (rData); 331 if (eErrCode != store_E_None) 332 return eErrCode; 333 334 // Store data page location. 335 rPage.m_pData[nSingle] = store::htonl(rData.location()); 336 337 // Save this page. 338 return rBIOS.saveObjectAt (*this, location()); 339 } 340 else 341 { 342 // Save data page. 343 return rBIOS.saveObjectAt (rData, nAddr); 344 } 345 } 346 347 /* 348 * write (double indirect). 349 */ 350 storeError OStoreIndirectionPageObject::write ( 351 sal_uInt16 nDouble, 352 sal_uInt16 nSingle, 353 OStoreDataPageObject &rData, 354 OStorePageBIOS &rBIOS) 355 { 356 PageHolderObject< page > xImpl (m_xPage); 357 page & rPage = (*xImpl); 358 359 // Check arguments. 360 sal_uInt16 const nLimit = rPage.capacityCount(); 361 if (!((nDouble < nLimit) && (nSingle < nLimit))) 362 return store_E_InvalidAccess; 363 364 // Load or create single indirect page. 365 OStoreIndirectionPageObject aSingle; 366 storeError eErrCode = aSingle.loadOrCreate (store::ntohl(rPage.m_pData[nDouble]), rBIOS); 367 if (eErrCode != store_E_None) 368 { 369 if (eErrCode != store_E_Pending) 370 return eErrCode; 371 rPage.m_pData[nDouble] = store::htonl(aSingle.location()); 372 373 eErrCode = rBIOS.saveObjectAt (*this, location()); 374 if (eErrCode != store_E_None) 375 return eErrCode; 376 } 377 378 // Write single indirect and leave. 379 return aSingle.write (nSingle, rData, rBIOS); 380 } 381 382 /* 383 * write (triple indirect). 384 */ 385 storeError OStoreIndirectionPageObject::write ( 386 sal_uInt16 nTriple, 387 sal_uInt16 nDouble, 388 sal_uInt16 nSingle, 389 OStoreDataPageObject &rData, 390 OStorePageBIOS &rBIOS) 391 { 392 PageHolderObject< page > xImpl (m_xPage); 393 page & rPage = (*xImpl); 394 395 // Check arguments. 396 sal_uInt16 const nLimit = rPage.capacityCount(); 397 if (!((nTriple < nLimit) && (nDouble < nLimit) && (nSingle < nLimit))) 398 return store_E_InvalidAccess; 399 400 // Load or create double indirect page. 401 OStoreIndirectionPageObject aDouble; 402 storeError eErrCode = aDouble.loadOrCreate (store::ntohl(rPage.m_pData[nTriple]), rBIOS); 403 if (eErrCode != store_E_None) 404 { 405 if (eErrCode != store_E_Pending) 406 return eErrCode; 407 rPage.m_pData[nTriple] = store::htonl(aDouble.location()); 408 409 eErrCode = rBIOS.saveObjectAt (*this, location()); 410 if (eErrCode != store_E_None) 411 return eErrCode; 412 } 413 414 // Write double indirect and leave. 415 return aDouble.write (nDouble, nSingle, rData, rBIOS); 416 } 417 418 /* 419 * truncate (single indirect). 420 */ 421 storeError OStoreIndirectionPageObject::truncate ( 422 sal_uInt16 nSingle, 423 OStorePageBIOS & rBIOS) 424 { 425 PageHolderObject< page > xImpl (m_xPage); 426 page & rPage = (*xImpl); 427 428 // Check arguments. 429 sal_uInt16 const nLimit = rPage.capacityCount(); 430 if (!(nSingle < nLimit)) 431 return store_E_InvalidAccess; 432 433 // Truncate. 434 storeError eErrCode = store_E_None; 435 for (sal_uInt16 i = nLimit; i > nSingle; i--) 436 { 437 // Obtain data page location. 438 sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[i - 1]); 439 if (nAddr != STORE_PAGE_NULL) 440 { 441 // Free data page. 442 eErrCode = rBIOS.free (nAddr); 443 if (eErrCode != store_E_None) 444 return eErrCode; 445 446 // Clear pointer to data page. 447 rPage.m_pData[i - 1] = STORE_PAGE_NULL; 448 touch(); 449 } 450 } 451 452 // Check for modified page. 453 if (dirty()) 454 { 455 // Save this page. 456 eErrCode = rBIOS.saveObjectAt (*this, location()); 457 } 458 459 // Done. 460 return eErrCode; 461 } 462 463 /* 464 * truncate (double indirect). 465 */ 466 storeError OStoreIndirectionPageObject::truncate ( 467 sal_uInt16 nDouble, 468 sal_uInt16 nSingle, 469 OStorePageBIOS &rBIOS) 470 { 471 PageHolderObject< page > xImpl (m_xPage); 472 page & rPage = (*xImpl); 473 474 // Check arguments. 475 sal_uInt16 const nLimit = rPage.capacityCount(); 476 if (!((nDouble < nLimit) && (nSingle < nLimit))) 477 return store_E_InvalidAccess; 478 479 // Truncate. 480 storeError eErrCode = store_E_None; 481 for (sal_uInt16 i = nLimit; i > nDouble + 1; i--) 482 { 483 // Truncate single indirect page to zero direct pages. 484 eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[i - 1]), 0, rBIOS); 485 if (eErrCode != store_E_None) 486 return eErrCode; 487 488 // Clear pointer to single indirect page. 489 rPage.m_pData[i - 1] = STORE_PAGE_NULL; 490 touch(); 491 } 492 493 // Truncate last single indirect page to 'nSingle' direct pages. 494 eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[nDouble]), nSingle, rBIOS); 495 if (eErrCode != store_E_None) 496 return eErrCode; 497 498 // Check for complete truncation. 499 if (nSingle == 0) 500 { 501 // Clear pointer to last single indirect page. 502 rPage.m_pData[nDouble] = STORE_PAGE_NULL; 503 touch(); 504 } 505 506 // Check for modified page. 507 if (dirty()) 508 { 509 // Save this page. 510 eErrCode = rBIOS.saveObjectAt (*this, location()); 511 } 512 513 // Done. 514 return eErrCode; 515 } 516 517 /* 518 * truncate (triple indirect). 519 */ 520 storeError OStoreIndirectionPageObject::truncate ( 521 sal_uInt16 nTriple, 522 sal_uInt16 nDouble, 523 sal_uInt16 nSingle, 524 OStorePageBIOS &rBIOS) 525 { 526 PageHolderObject< page > xImpl (m_xPage); 527 page & rPage = (*xImpl); 528 529 // Check arguments. 530 sal_uInt16 const nLimit = rPage.capacityCount(); 531 if (!((nTriple < nLimit) && (nDouble < nLimit) && (nSingle < nLimit))) 532 return store_E_InvalidAccess; 533 534 // Truncate. 535 storeError eErrCode = store_E_None; 536 for (sal_uInt16 i = nLimit; i > nTriple + 1; i--) 537 { 538 // Truncate double indirect page to zero single indirect pages. 539 eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[i - 1]), 0, 0, rBIOS); 540 if (eErrCode != store_E_None) 541 return eErrCode; 542 543 // Clear pointer to double indirect page. 544 rPage.m_pData[i - 1] = STORE_PAGE_NULL; 545 touch(); 546 } 547 548 // Truncate last double indirect page to 'nDouble', 'nSingle' pages. 549 eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[nTriple]), nDouble, nSingle, rBIOS); 550 if (eErrCode != store_E_None) 551 return eErrCode; 552 553 // Check for complete truncation. 554 if ((nDouble + nSingle) == 0) 555 { 556 // Clear pointer to last double indirect page. 557 rPage.m_pData[nTriple] = STORE_PAGE_NULL; 558 touch(); 559 } 560 561 // Check for modified page. 562 if (dirty()) 563 { 564 // Save this page. 565 eErrCode = rBIOS.saveObjectAt (*this, location()); 566 } 567 568 // Done. 569 return eErrCode; 570 } 571 572 /*======================================================================== 573 * 574 * OStoreDirectoryPageObject implementation. 575 * 576 *======================================================================*/ 577 /* 578 * guard. 579 */ 580 storeError OStoreDirectoryPageObject::guard (sal_uInt32 nAddr) 581 { 582 return PageHolderObject< page >::guard (m_xPage, nAddr); 583 } 584 585 /* 586 * verify. 587 */ 588 storeError OStoreDirectoryPageObject::verify (sal_uInt32 nAddr) const 589 { 590 return PageHolderObject< page >::verify (m_xPage, nAddr); 591 // OLD: m_rPage.verifyVersion (STORE_MAGIC_DIRECTORYPAGE); 592 } 593 594 /* 595 * scope (external data page; private). 596 */ 597 OStoreDirectoryPageData::ChunkScope 598 OStoreDirectoryPageObject::scope ( 599 sal_uInt32 nPage, 600 page::DataBlock::LinkDescriptor &rDescr) const 601 { 602 page const & rPage = PAGE(); 603 OStoreDirectoryDataBlock const & rDataBlock = rPage.m_aDataBlock; 604 605 sal_uInt32 index0, index1, index2, index3; 606 607 // direct. 608 sal_uInt32 nCount = rDataBlock.directCount(); 609 sal_uInt32 nLimit = nCount; 610 if (nPage < nLimit) 611 { 612 // Page to index reduction. 613 index0 = nPage; 614 615 // Setup LinkDescriptor indices. 616 rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff); 617 618 // Done. 619 return page::SCOPE_DIRECT; 620 } 621 nPage -= nLimit; 622 623 // single indirect. 624 sal_uInt32 const nCapacity = indirect::capacityCount(rPage.m_aDescr); 625 nCount = rDataBlock.singleCount(); 626 nLimit = nCount * nCapacity; 627 if (nPage < nLimit) 628 { 629 // Page to index reduction. 630 sal_uInt32 n = nPage; 631 632 // Reduce to single indirect i(1), direct n = i(0). 633 index1 = n / nCapacity; 634 index0 = n % nCapacity; 635 636 // Verify reduction. 637 n = index1 * nCapacity + index0; 638 OSL_POSTCOND(n == nPage, "wrong math on indirect indices"); 639 if (n != nPage) 640 return page::SCOPE_UNKNOWN; 641 642 // Setup LinkDescriptor indices. 643 rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff); 644 rDescr.m_nIndex1 = (sal_uInt16)(index1 & 0xffff); 645 646 // Done. 647 return page::SCOPE_SINGLE; 648 } 649 nPage -= nLimit; 650 651 // double indirect. 652 nCount = rDataBlock.doubleCount(); 653 nLimit = nCount * nCapacity * nCapacity; 654 if (nPage < nLimit) 655 { 656 // Page to index reduction. 657 sal_uInt32 n = nPage; 658 659 // Reduce to double indirect i(2), single indirect n = i(0). 660 index2 = n / (nCapacity * nCapacity); 661 n = n % (nCapacity * nCapacity); 662 663 // Reduce to single indirect i(1), direct n = i(0). 664 index1 = n / nCapacity; 665 index0 = n % nCapacity; 666 667 // Verify reduction. 668 n = index2 * nCapacity * nCapacity + 669 index1 * nCapacity + index0; 670 OSL_POSTCOND(n == nPage, "wrong math on double indirect indices"); 671 if (n != nPage) 672 return page::SCOPE_UNKNOWN; 673 674 // Setup LinkDescriptor indices. 675 rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff); 676 rDescr.m_nIndex1 = (sal_uInt16)(index1 & 0xffff); 677 rDescr.m_nIndex2 = (sal_uInt16)(index2 & 0xffff); 678 679 // Done. 680 return page::SCOPE_DOUBLE; 681 } 682 nPage -= nLimit; 683 684 // triple indirect. 685 nCount = rDataBlock.tripleCount(); 686 nLimit = nCount * nCapacity * nCapacity * nCapacity; 687 if (nPage < nLimit) 688 { 689 // Page to index reduction. 690 sal_uInt32 n = nPage; 691 692 // Reduce to triple indirect i(3), double indirect n. 693 index3 = n / (nCapacity * nCapacity * nCapacity); 694 n = n % (nCapacity * nCapacity * nCapacity); 695 696 // Reduce to double indirect i(2), single indirect n. 697 index2 = n / (nCapacity * nCapacity); 698 n = n % (nCapacity * nCapacity); 699 700 // Reduce to single indirect i(1), direct n = i(0). 701 index1 = n / nCapacity; 702 index0 = n % nCapacity; 703 704 // Verify reduction. 705 n = index3 * nCapacity * nCapacity * nCapacity + 706 index2 * nCapacity * nCapacity + 707 index1 * nCapacity + index0; 708 OSL_POSTCOND(n == nPage, "wrong math on triple indirect indices"); 709 if (n != nPage) 710 return page::SCOPE_UNKNOWN; 711 712 // Setup LinkDescriptor indices. 713 rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff); 714 rDescr.m_nIndex1 = (sal_uInt16)(index1 & 0xffff); 715 rDescr.m_nIndex2 = (sal_uInt16)(index2 & 0xffff); 716 rDescr.m_nIndex3 = (sal_uInt16)(index3 & 0xffff); 717 718 // Done. 719 return page::SCOPE_TRIPLE; 720 } 721 722 // Unreachable (more than triple indirect). 723 return page::SCOPE_UNREACHABLE; 724 } 725 726 #if 0 /* NYI */ 727 /* 728 * chunk (external data page). 729 */ 730 inode::ChunkDescriptor OStoreDirectoryPageObject::chunk (sal_uInt32 nOffset) 731 { 732 // @@@ INSUFFICIENT: NEED SCOPE AS WELL @@@ 733 sal_uInt32 nCapacity = m_rPage.capacity(); 734 if (nOffset < nCapacity) 735 // Internal scope (inode page). 736 return inode::ChunkDescriptor (nOffset, nCapacity); 737 else 738 // External scope (data page). 739 return inode::ChunkDescriptor (nOffset - nCapacity, data::capacity(m_rPage.m_aDescr)); 740 741 inode::ChunkScope eScope = m_rPage.scope(nOffset); 742 if (eScope == inode::SCOPE_INTERNAL) 743 // Inode page (internal scope). 744 return inode::ChunkDescriptor (nOffset, m_rPage.capacity()); 745 else 746 // Data page (external scope). 747 return inode::ChunkDescriptor (nOffset - m_rPage.capacity(), data::capacity(m_rPage.m_aDescr)); 748 } 749 #endif /* NYI */ 750 751 /* 752 * read (external data page). 753 */ 754 storeError OStoreDirectoryPageObject::read ( 755 sal_uInt32 nPage, 756 OStoreDataPageObject &rData, 757 OStorePageBIOS &rBIOS) 758 { 759 // Determine scope and link indices. 760 page::DataBlock::LinkDescriptor aLink; 761 page::ChunkScope eScope = scope (nPage, aLink); 762 763 storeError eErrCode = store_E_None; 764 if (eScope == page::SCOPE_DIRECT) 765 { 766 sal_uInt32 const nAddr = directLink (aLink.m_nIndex0); 767 if (nAddr == STORE_PAGE_NULL) 768 return store_E_NotExists; 769 770 eErrCode = rBIOS.loadObjectAt (rData, nAddr); 771 } 772 else if (eScope == page::SCOPE_SINGLE) 773 { 774 sal_uInt32 const nAddr = singleLink (aLink.m_nIndex1); 775 if (nAddr == STORE_PAGE_NULL) 776 return store_E_NotExists; 777 778 OStoreIndirectionPageObject aSingle; 779 eErrCode = rBIOS.loadObjectAt (aSingle, nAddr); 780 if (eErrCode != store_E_None) 781 return eErrCode; 782 783 eErrCode = aSingle.read (aLink.m_nIndex0, rData, rBIOS); 784 } 785 else if (eScope == page::SCOPE_DOUBLE) 786 { 787 sal_uInt32 const nAddr = doubleLink (aLink.m_nIndex2); 788 if (nAddr == STORE_PAGE_NULL) 789 return store_E_NotExists; 790 791 OStoreIndirectionPageObject aDouble; 792 eErrCode = rBIOS.loadObjectAt (aDouble, nAddr); 793 if (eErrCode != store_E_None) 794 return eErrCode; 795 796 eErrCode = aDouble.read (aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS); 797 } 798 else if (eScope == page::SCOPE_TRIPLE) 799 { 800 sal_uInt32 const nAddr = tripleLink (aLink.m_nIndex3); 801 if (nAddr == STORE_PAGE_NULL) 802 return store_E_NotExists; 803 804 OStoreIndirectionPageObject aTriple; 805 eErrCode = rBIOS.loadObjectAt (aTriple, nAddr); 806 if (eErrCode != store_E_None) 807 return eErrCode; 808 809 eErrCode = aTriple.read (aLink.m_nIndex2, aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS); 810 } 811 else if (eScope == page::SCOPE_UNREACHABLE) 812 { 813 // Out of scope. 814 eErrCode = store_E_CantSeek; 815 } 816 else 817 { 818 // Unknown scope. 819 OSL_TRACE("OStoreDirectoryPageObject::get(): scope failed"); 820 eErrCode = store_E_Unknown; 821 } 822 823 // Leave. 824 return eErrCode; 825 } 826 827 /* 828 * write (external data page). 829 */ 830 storeError OStoreDirectoryPageObject::write ( 831 sal_uInt32 nPage, 832 OStoreDataPageObject &rData, 833 OStorePageBIOS &rBIOS) 834 { 835 // Determine scope and link indices. 836 page::DataBlock::LinkDescriptor aLink; 837 page::ChunkScope eScope = scope (nPage, aLink); 838 839 storeError eErrCode = store_E_None; 840 if (eScope == page::SCOPE_DIRECT) 841 { 842 sal_uInt32 const nAddr = directLink (aLink.m_nIndex0); 843 if (nAddr == STORE_PAGE_NULL) 844 { 845 // Allocate data page. 846 eErrCode = rBIOS.allocate (rData); 847 if (eErrCode != store_E_None) 848 return eErrCode; 849 850 // Store data page location. 851 directLink (aLink.m_nIndex0, rData.location()); 852 } 853 else 854 { 855 // Save data page. 856 eErrCode = rBIOS.saveObjectAt (rData, nAddr); 857 } 858 } 859 else if (eScope == page::SCOPE_SINGLE) 860 { 861 OStoreIndirectionPageObject aSingle; 862 eErrCode = aSingle.loadOrCreate (singleLink (aLink.m_nIndex1), rBIOS); 863 if (eErrCode != store_E_None) 864 { 865 if (eErrCode != store_E_Pending) 866 return eErrCode; 867 singleLink (aLink.m_nIndex1, aSingle.location()); 868 } 869 870 eErrCode = aSingle.write (aLink.m_nIndex0, rData, rBIOS); 871 } 872 else if (eScope == page::SCOPE_DOUBLE) 873 { 874 OStoreIndirectionPageObject aDouble; 875 eErrCode = aDouble.loadOrCreate (doubleLink (aLink.m_nIndex2), rBIOS); 876 if (eErrCode != store_E_None) 877 { 878 if (eErrCode != store_E_Pending) 879 return eErrCode; 880 doubleLink (aLink.m_nIndex2, aDouble.location()); 881 } 882 883 eErrCode = aDouble.write (aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS); 884 } 885 else if (eScope == page::SCOPE_TRIPLE) 886 { 887 OStoreIndirectionPageObject aTriple; 888 eErrCode = aTriple.loadOrCreate (tripleLink (aLink.m_nIndex3), rBIOS); 889 if (eErrCode != store_E_None) 890 { 891 if (eErrCode != store_E_Pending) 892 return eErrCode; 893 tripleLink (aLink.m_nIndex3, aTriple.location()); 894 } 895 896 eErrCode = aTriple.write (aLink.m_nIndex2, aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS); 897 } 898 else if (eScope == page::SCOPE_UNREACHABLE) 899 { 900 // Out of scope. 901 eErrCode = store_E_CantSeek; 902 } 903 else 904 { 905 // Unknown scope. 906 OSL_TRACE("OStoreDirectoryPageObject::put(): scope failed"); 907 eErrCode = store_E_Unknown; 908 } 909 910 // Leave. 911 return eErrCode; 912 } 913 914 /* 915 * truncate (external data page). 916 */ 917 storeError OStoreDirectoryPageObject::truncate ( 918 sal_uInt32 nPage, 919 OStorePageBIOS &rBIOS) 920 { 921 // Determine scope and link indices. 922 page::DataBlock::LinkDescriptor aLink; 923 page::ChunkScope eScope = scope (nPage, aLink); 924 925 storeError eErrCode = store_E_None; 926 if (eScope == page::SCOPE_DIRECT) 927 { 928 // Truncate all triple indirect pages. 929 eErrCode = truncate (page::SCOPE_TRIPLE, 0, rBIOS); 930 if (eErrCode != store_E_None) 931 return eErrCode; 932 933 // Truncate all double indirect pages. 934 eErrCode = truncate (page::SCOPE_DOUBLE, 0, rBIOS); 935 if (eErrCode != store_E_None) 936 return eErrCode; 937 938 // Truncate all single indirect pages. 939 eErrCode = truncate (page::SCOPE_SINGLE, 0, rBIOS); 940 if (eErrCode != store_E_None) 941 return eErrCode; 942 943 // Truncate direct pages, including 'aLink.m_nIndex0'. 944 eErrCode = truncate (eScope, aLink.m_nIndex0, rBIOS); 945 } 946 else if (eScope == page::SCOPE_SINGLE) 947 { 948 // Truncate all triple indirect pages. 949 eErrCode = truncate (page::SCOPE_TRIPLE, 0, rBIOS); 950 if (eErrCode != store_E_None) 951 return eErrCode; 952 953 // Truncate all double indirect pages. 954 eErrCode = truncate (page::SCOPE_DOUBLE, 0, rBIOS); 955 if (eErrCode != store_E_None) 956 return eErrCode; 957 958 // Truncate single indirect pages, downto 'aLink.m_nIndex1'. 959 eErrCode = truncate (eScope, aLink.m_nIndex1 + 1, rBIOS); 960 if (eErrCode != store_E_None) 961 return eErrCode; 962 963 // Truncate last single indirect page to ... pages. 964 eErrCode = store_truncate_Impl (singleLink (aLink.m_nIndex1), aLink.m_nIndex0, rBIOS); 965 if (eErrCode != store_E_None) 966 return eErrCode; 967 968 // Check for complete truncation. 969 if (aLink.m_nIndex0 == 0) 970 { 971 // Clear pointer to last single indirect page. 972 singleLink (aLink.m_nIndex1, STORE_PAGE_NULL); 973 } 974 } 975 else if (eScope == page::SCOPE_DOUBLE) 976 { 977 // Truncate all triple indirect pages. 978 eErrCode = truncate (page::SCOPE_TRIPLE, 0, rBIOS); 979 if (eErrCode != store_E_None) 980 return eErrCode; 981 982 // Truncate double indirect pages, downto 'aLink.m_nIndex2'. 983 eErrCode = truncate (eScope, aLink.m_nIndex2 + 1, rBIOS); 984 if (eErrCode != store_E_None) 985 return eErrCode; 986 987 // Truncate last double indirect page to ... pages. 988 eErrCode = store_truncate_Impl ( 989 doubleLink (aLink.m_nIndex2), aLink.m_nIndex1, aLink.m_nIndex0, rBIOS); 990 if (eErrCode != store_E_None) 991 return eErrCode; 992 993 // Check for complete truncation. 994 if ((aLink.m_nIndex1 + aLink.m_nIndex0) == 0) 995 { 996 // Clear pointer to last double indirect page. 997 doubleLink (aLink.m_nIndex2, STORE_PAGE_NULL); 998 } 999 } 1000 else if (eScope == page::SCOPE_TRIPLE) 1001 { 1002 // Truncate triple indirect pages, downto 'aLink.m_nIndex3'. 1003 eErrCode = truncate (eScope, aLink.m_nIndex3 + 1, rBIOS); 1004 if (eErrCode != store_E_None) 1005 return eErrCode; 1006 1007 // Truncate last triple indirect page to ... pages. 1008 eErrCode = store_truncate_Impl ( 1009 tripleLink (aLink.m_nIndex3), aLink.m_nIndex2, aLink.m_nIndex1, aLink.m_nIndex0, rBIOS); 1010 if (eErrCode != store_E_None) 1011 return eErrCode; 1012 1013 // Check for complete truncation. 1014 if ((aLink.m_nIndex2 + aLink.m_nIndex1 + aLink.m_nIndex0) == 0) 1015 { 1016 // Clear pointer to last triple indirect page. 1017 tripleLink (aLink.m_nIndex3, STORE_PAGE_NULL); 1018 } 1019 } 1020 else if (eScope == page::SCOPE_UNREACHABLE) 1021 { 1022 // Out of scope. 1023 eErrCode = store_E_CantSeek; 1024 } 1025 else 1026 { 1027 // Unknown scope. 1028 OSL_TRACE("OStoreDirectoryPageObject::put(): scope failed"); 1029 eErrCode = store_E_Unknown; 1030 } 1031 1032 // Leave. 1033 return eErrCode; 1034 } 1035 1036 /* 1037 * truncate (external data page scope; private). 1038 */ 1039 storeError OStoreDirectoryPageObject::truncate ( 1040 page::ChunkScope eScope, 1041 sal_uInt16 nRemain, 1042 OStorePageBIOS &rBIOS) 1043 { 1044 OStoreDirectoryDataBlock const & rDataBlock = PAGE().m_aDataBlock; 1045 1046 // Enter. 1047 storeError eErrCode = store_E_None; 1048 if (eScope == page::SCOPE_DIRECT) 1049 { 1050 // Truncate direct data pages. 1051 sal_uInt16 i, n = rDataBlock.directCount(); 1052 for (i = n; i > nRemain; i--) 1053 { 1054 // Obtain data page location. 1055 sal_uInt32 nAddr = directLink (i - 1); 1056 if (nAddr == STORE_PAGE_NULL) continue; 1057 1058 // Free data page. 1059 eErrCode = rBIOS.free (nAddr); 1060 if (eErrCode != store_E_None) 1061 break; 1062 1063 // Clear pointer to data page. 1064 directLink (i - 1, STORE_PAGE_NULL); 1065 } 1066 1067 // Done. 1068 return eErrCode; 1069 } 1070 1071 if (eScope == page::SCOPE_SINGLE) 1072 { 1073 // Truncate single indirect pages. 1074 sal_uInt16 i, n = rDataBlock.singleCount(); 1075 for (i = n; i > nRemain; i--) 1076 { 1077 // Truncate single indirect page to zero data pages. 1078 eErrCode = store_truncate_Impl (singleLink (i - 1), 0, rBIOS); 1079 if (eErrCode != store_E_None) 1080 break; 1081 1082 // Clear pointer to single indirect page. 1083 singleLink (i - 1, STORE_PAGE_NULL); 1084 } 1085 1086 // Done. 1087 return eErrCode; 1088 } 1089 1090 if (eScope == page::SCOPE_DOUBLE) 1091 { 1092 // Truncate double indirect pages. 1093 sal_uInt16 i, n = rDataBlock.doubleCount(); 1094 for (i = n; i > nRemain; i--) 1095 { 1096 // Truncate double indirect page to zero single indirect pages. 1097 eErrCode = store_truncate_Impl (doubleLink (i - 1), 0, 0, rBIOS); 1098 if (eErrCode != store_E_None) 1099 break; 1100 1101 // Clear pointer to double indirect page. 1102 doubleLink (i - 1, STORE_PAGE_NULL); 1103 } 1104 1105 // Done. 1106 return eErrCode; 1107 } 1108 1109 if (eScope == page::SCOPE_TRIPLE) 1110 { 1111 // Truncate triple indirect pages. 1112 sal_uInt16 i, n = rDataBlock.tripleCount(); 1113 for (i = n; i > nRemain; i--) 1114 { 1115 // Truncate to zero double indirect pages. 1116 eErrCode = store_truncate_Impl (tripleLink (i - 1), 0, 0, 0, rBIOS); 1117 if (eErrCode != store_E_None) 1118 break; 1119 1120 // Clear pointer to triple indirect page. 1121 tripleLink (i - 1, STORE_PAGE_NULL); 1122 } 1123 1124 // Done. 1125 return eErrCode; 1126 } 1127 1128 // Invalid scope. 1129 return store_E_InvalidAccess; 1130 } 1131