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