Version 3.6.0.4, tag libreoffice-3.6.0.4
[LibreOffice.git] / store / source / stordata.cxx
blob770dcb6cc49920d304d22bceff993e39ab67e2a7
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #include "stordata.hxx"
32 #include "sal/types.h"
33 #include "osl/diagnose.h"
35 #include "store/types.h"
36 #include "storbase.hxx"
37 #include "storbios.hxx"
39 using namespace store;
41 /*========================================================================
43 * OStoreDataPageObject implementation.
45 *======================================================================*/
47 * guard.
49 storeError OStoreDataPageObject::guard (sal_uInt32 nAddr)
51 return PageHolderObject< page >::guard (m_xPage, nAddr);
55 * verify.
57 storeError OStoreDataPageObject::verify (sal_uInt32 nAddr) const
59 return PageHolderObject< page >::verify (m_xPage, nAddr);
62 /*========================================================================
64 * OStoreIndirectionPageObject implementation.
66 *======================================================================*/
68 * store_truncate_Impl (single indirect page).
70 static storeError store_truncate_Impl (
71 sal_uInt32 nAddr,
72 sal_uInt16 nSingle,
73 OStorePageBIOS &rBIOS)
75 if (nAddr != STORE_PAGE_NULL)
77 // Load single indirect page.
78 OStoreIndirectionPageObject aSingle;
79 storeError eErrCode = rBIOS.loadObjectAt (aSingle, nAddr);
80 if (eErrCode == store_E_None)
82 // Truncate to 'nSingle' direct pages.
83 eErrCode = aSingle.truncate (nSingle, rBIOS);
84 if (eErrCode != store_E_None)
85 return eErrCode;
87 else
89 if (eErrCode != store_E_InvalidChecksum)
90 return eErrCode;
93 // Check for complete truncation.
94 if (nSingle == 0)
96 // Free single indirect page.
97 eErrCode = rBIOS.free (nAddr);
98 if (eErrCode != store_E_None)
99 return eErrCode;
102 return store_E_None;
106 * store_truncate_Impl (double indirect page).
108 static storeError store_truncate_Impl (
109 sal_uInt32 nAddr,
110 sal_uInt16 nDouble,
111 sal_uInt16 nSingle,
112 OStorePageBIOS &rBIOS)
114 if (nAddr != STORE_PAGE_NULL)
116 // Load double indirect page.
117 OStoreIndirectionPageObject aDouble;
118 storeError eErrCode = rBIOS.loadObjectAt (aDouble, nAddr);
119 if (eErrCode == store_E_None)
121 // Truncate to 'nDouble', 'nSingle' pages.
122 eErrCode = aDouble.truncate (nDouble, nSingle, rBIOS);
123 if (eErrCode != store_E_None)
124 return eErrCode;
126 else
128 if (eErrCode != store_E_InvalidChecksum)
129 return eErrCode;
132 // Check for complete truncation.
133 if ((nDouble + nSingle) == 0)
135 // Free double indirect page.
136 eErrCode = rBIOS.free (nAddr);
137 if (eErrCode != store_E_None)
138 return eErrCode;
141 return store_E_None;
145 * store_truncate_Impl (triple indirect page).
147 static storeError store_truncate_Impl (
148 sal_uInt32 nAddr,
149 sal_uInt16 nTriple,
150 sal_uInt16 nDouble,
151 sal_uInt16 nSingle,
152 OStorePageBIOS &rBIOS)
154 if (nAddr != STORE_PAGE_NULL)
156 // Load triple indirect page.
157 OStoreIndirectionPageObject aTriple;
158 storeError eErrCode = rBIOS.loadObjectAt (aTriple, nAddr);
159 if (eErrCode != store_E_None)
160 return eErrCode;
162 // Truncate to 'nTriple', 'nDouble', 'nSingle' pages.
163 eErrCode = aTriple.truncate (nTriple, nDouble, nSingle, rBIOS);
164 if (eErrCode != store_E_None)
165 return eErrCode;
167 // Check for complete truncation.
168 if ((nTriple + nDouble + nSingle) == 0)
170 // Free triple indirect page.
171 eErrCode = rBIOS.free (nAddr);
172 if (eErrCode != store_E_None)
173 return eErrCode;
176 return store_E_None;
180 * loadOrCreate.
182 storeError OStoreIndirectionPageObject::loadOrCreate (
183 sal_uInt32 nAddr,
184 OStorePageBIOS & rBIOS)
186 if (nAddr == STORE_PAGE_NULL)
188 storeError eErrCode = construct<page>(rBIOS.allocator());
189 if (eErrCode != store_E_None)
190 return eErrCode;
192 eErrCode = rBIOS.allocate (*this);
193 if (eErrCode != store_E_None)
194 return eErrCode;
196 // Save location pending at caller.
197 return store_E_Pending;
199 return rBIOS.loadObjectAt (*this, nAddr);
203 * guard.
205 storeError OStoreIndirectionPageObject::guard (sal_uInt32 nAddr)
207 return PageHolderObject< page >::guard (m_xPage, nAddr);
211 * verify.
213 storeError OStoreIndirectionPageObject::verify (sal_uInt32 nAddr) const
215 return PageHolderObject< page >::verify (m_xPage, nAddr);
219 * read (single indirect).
221 storeError OStoreIndirectionPageObject::read (
222 sal_uInt16 nSingle,
223 OStoreDataPageObject &rData,
224 OStorePageBIOS &rBIOS)
226 PageHolderObject< page > xImpl (m_xPage);
227 page const & rPage = (*xImpl);
229 // Check arguments.
230 sal_uInt16 const nLimit = rPage.capacityCount();
231 if (!(nSingle < nLimit))
232 return store_E_InvalidAccess;
234 // Obtain data page location.
235 sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nSingle]);
236 if (nAddr == STORE_PAGE_NULL)
237 return store_E_NotExists;
239 // Load data page and leave.
240 return rBIOS.loadObjectAt (rData, nAddr);
244 * read (double indirect).
246 storeError OStoreIndirectionPageObject::read (
247 sal_uInt16 nDouble,
248 sal_uInt16 nSingle,
249 OStoreDataPageObject &rData,
250 OStorePageBIOS &rBIOS)
252 PageHolderObject< page > xImpl (m_xPage);
253 page const & rPage = (*xImpl);
255 // Check arguments.
256 sal_uInt16 const nLimit = rPage.capacityCount();
257 if (!((nDouble < nLimit) && (nSingle < nLimit)))
258 return store_E_InvalidAccess;
260 // Check single indirect page location.
261 sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nDouble]);
262 if (nAddr == STORE_PAGE_NULL)
263 return store_E_NotExists;
265 // Load single indirect page.
266 OStoreIndirectionPageObject aSingle;
267 storeError eErrCode = rBIOS.loadObjectAt (aSingle, nAddr);
268 if (eErrCode != store_E_None)
269 return eErrCode;
271 // Read single indirect and leave.
272 return aSingle.read (nSingle, rData, rBIOS);
276 * read (triple indirect).
278 storeError OStoreIndirectionPageObject::read (
279 sal_uInt16 nTriple,
280 sal_uInt16 nDouble,
281 sal_uInt16 nSingle,
282 OStoreDataPageObject &rData,
283 OStorePageBIOS &rBIOS)
285 PageHolderObject< page > xImpl (m_xPage);
286 page const & rPage = (*xImpl);
288 // Check arguments.
289 sal_uInt16 const nLimit = rPage.capacityCount();
290 if (!((nTriple < nLimit) && (nDouble < nLimit) && (nSingle < nLimit)))
291 return store_E_InvalidAccess;
293 // Check double indirect page location.
294 sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nTriple]);
295 if (nAddr == STORE_PAGE_NULL)
296 return store_E_NotExists;
298 // Load double indirect page.
299 OStoreIndirectionPageObject aDouble;
300 storeError eErrCode = rBIOS.loadObjectAt (aDouble, nAddr);
301 if (eErrCode != store_E_None)
302 return eErrCode;
304 // Read double indirect and leave.
305 return aDouble.read (nDouble, nSingle, rData, rBIOS);
309 * write (single indirect).
311 storeError OStoreIndirectionPageObject::write (
312 sal_uInt16 nSingle,
313 OStoreDataPageObject &rData,
314 OStorePageBIOS &rBIOS)
316 PageHolderObject< page > xImpl (m_xPage);
317 page & rPage = (*xImpl);
319 // Check arguments.
320 sal_uInt16 const nLimit = rPage.capacityCount();
321 if (!(nSingle < nLimit))
322 return store_E_InvalidAccess;
324 // Obtain data page location.
325 sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nSingle]);
326 if (nAddr == STORE_PAGE_NULL)
328 // Allocate data page.
329 storeError eErrCode = rBIOS.allocate (rData);
330 if (eErrCode != store_E_None)
331 return eErrCode;
333 // Store data page location.
334 rPage.m_pData[nSingle] = store::htonl(rData.location());
336 // Save this page.
337 return rBIOS.saveObjectAt (*this, location());
339 else
341 // Save data page.
342 return rBIOS.saveObjectAt (rData, nAddr);
347 * write (double indirect).
349 storeError OStoreIndirectionPageObject::write (
350 sal_uInt16 nDouble,
351 sal_uInt16 nSingle,
352 OStoreDataPageObject &rData,
353 OStorePageBIOS &rBIOS)
355 PageHolderObject< page > xImpl (m_xPage);
356 page & rPage = (*xImpl);
358 // Check arguments.
359 sal_uInt16 const nLimit = rPage.capacityCount();
360 if (!((nDouble < nLimit) && (nSingle < nLimit)))
361 return store_E_InvalidAccess;
363 // Load or create single indirect page.
364 OStoreIndirectionPageObject aSingle;
365 storeError eErrCode = aSingle.loadOrCreate (store::ntohl(rPage.m_pData[nDouble]), rBIOS);
366 if (eErrCode != store_E_None)
368 if (eErrCode != store_E_Pending)
369 return eErrCode;
370 rPage.m_pData[nDouble] = store::htonl(aSingle.location());
372 eErrCode = rBIOS.saveObjectAt (*this, location());
373 if (eErrCode != store_E_None)
374 return eErrCode;
377 // Write single indirect and leave.
378 return aSingle.write (nSingle, rData, rBIOS);
382 * write (triple indirect).
384 storeError OStoreIndirectionPageObject::write (
385 sal_uInt16 nTriple,
386 sal_uInt16 nDouble,
387 sal_uInt16 nSingle,
388 OStoreDataPageObject &rData,
389 OStorePageBIOS &rBIOS)
391 PageHolderObject< page > xImpl (m_xPage);
392 page & rPage = (*xImpl);
394 // Check arguments.
395 sal_uInt16 const nLimit = rPage.capacityCount();
396 if (!((nTriple < nLimit) && (nDouble < nLimit) && (nSingle < nLimit)))
397 return store_E_InvalidAccess;
399 // Load or create double indirect page.
400 OStoreIndirectionPageObject aDouble;
401 storeError eErrCode = aDouble.loadOrCreate (store::ntohl(rPage.m_pData[nTriple]), rBIOS);
402 if (eErrCode != store_E_None)
404 if (eErrCode != store_E_Pending)
405 return eErrCode;
406 rPage.m_pData[nTriple] = store::htonl(aDouble.location());
408 eErrCode = rBIOS.saveObjectAt (*this, location());
409 if (eErrCode != store_E_None)
410 return eErrCode;
413 // Write double indirect and leave.
414 return aDouble.write (nDouble, nSingle, rData, rBIOS);
418 * truncate (single indirect).
420 storeError OStoreIndirectionPageObject::truncate (
421 sal_uInt16 nSingle,
422 OStorePageBIOS & rBIOS)
424 PageHolderObject< page > xImpl (m_xPage);
425 page & rPage = (*xImpl);
427 // Check arguments.
428 sal_uInt16 const nLimit = rPage.capacityCount();
429 if (!(nSingle < nLimit))
430 return store_E_InvalidAccess;
432 // Truncate.
433 storeError eErrCode = store_E_None;
434 for (sal_uInt16 i = nLimit; i > nSingle; i--)
436 // Obtain data page location.
437 sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[i - 1]);
438 if (nAddr != STORE_PAGE_NULL)
440 // Free data page.
441 eErrCode = rBIOS.free (nAddr);
442 if (eErrCode != store_E_None)
443 return eErrCode;
445 // Clear pointer to data page.
446 rPage.m_pData[i - 1] = STORE_PAGE_NULL;
447 touch();
451 // Check for modified page.
452 if (dirty())
454 // Save this page.
455 eErrCode = rBIOS.saveObjectAt (*this, location());
458 // Done.
459 return eErrCode;
463 * truncate (double indirect).
465 storeError OStoreIndirectionPageObject::truncate (
466 sal_uInt16 nDouble,
467 sal_uInt16 nSingle,
468 OStorePageBIOS &rBIOS)
470 PageHolderObject< page > xImpl (m_xPage);
471 page & rPage = (*xImpl);
473 // Check arguments.
474 sal_uInt16 const nLimit = rPage.capacityCount();
475 if (!((nDouble < nLimit) && (nSingle < nLimit)))
476 return store_E_InvalidAccess;
478 // Truncate.
479 storeError eErrCode = store_E_None;
480 for (sal_uInt16 i = nLimit; i > nDouble + 1; i--)
482 // Truncate single indirect page to zero direct pages.
483 eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[i - 1]), 0, rBIOS);
484 if (eErrCode != store_E_None)
485 return eErrCode;
487 // Clear pointer to single indirect page.
488 rPage.m_pData[i - 1] = STORE_PAGE_NULL;
489 touch();
492 // Truncate last single indirect page to 'nSingle' direct pages.
493 eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[nDouble]), nSingle, rBIOS);
494 if (eErrCode != store_E_None)
495 return eErrCode;
497 // Check for complete truncation.
498 if (nSingle == 0)
500 // Clear pointer to last single indirect page.
501 rPage.m_pData[nDouble] = STORE_PAGE_NULL;
502 touch();
505 // Check for modified page.
506 if (dirty())
508 // Save this page.
509 eErrCode = rBIOS.saveObjectAt (*this, location());
512 // Done.
513 return eErrCode;
517 * truncate (triple indirect).
519 storeError OStoreIndirectionPageObject::truncate (
520 sal_uInt16 nTriple,
521 sal_uInt16 nDouble,
522 sal_uInt16 nSingle,
523 OStorePageBIOS &rBIOS)
525 PageHolderObject< page > xImpl (m_xPage);
526 page & rPage = (*xImpl);
528 // Check arguments.
529 sal_uInt16 const nLimit = rPage.capacityCount();
530 if (!((nTriple < nLimit) && (nDouble < nLimit) && (nSingle < nLimit)))
531 return store_E_InvalidAccess;
533 // Truncate.
534 storeError eErrCode = store_E_None;
535 for (sal_uInt16 i = nLimit; i > nTriple + 1; i--)
537 // Truncate double indirect page to zero single indirect pages.
538 eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[i - 1]), 0, 0, rBIOS);
539 if (eErrCode != store_E_None)
540 return eErrCode;
542 // Clear pointer to double indirect page.
543 rPage.m_pData[i - 1] = STORE_PAGE_NULL;
544 touch();
547 // Truncate last double indirect page to 'nDouble', 'nSingle' pages.
548 eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[nTriple]), nDouble, nSingle, rBIOS);
549 if (eErrCode != store_E_None)
550 return eErrCode;
552 // Check for complete truncation.
553 if ((nDouble + nSingle) == 0)
555 // Clear pointer to last double indirect page.
556 rPage.m_pData[nTriple] = STORE_PAGE_NULL;
557 touch();
560 // Check for modified page.
561 if (dirty())
563 // Save this page.
564 eErrCode = rBIOS.saveObjectAt (*this, location());
567 // Done.
568 return eErrCode;
571 /*========================================================================
573 * OStoreDirectoryPageObject implementation.
575 *======================================================================*/
577 * guard.
579 storeError OStoreDirectoryPageObject::guard (sal_uInt32 nAddr)
581 return PageHolderObject< page >::guard (m_xPage, nAddr);
585 * verify.
587 storeError OStoreDirectoryPageObject::verify (sal_uInt32 nAddr) const
589 return PageHolderObject< page >::verify (m_xPage, nAddr);
590 // OLD: m_rPage.verifyVersion (STORE_MAGIC_DIRECTORYPAGE);
594 * scope (external data page; private).
596 OStoreDirectoryPageData::ChunkScope
597 OStoreDirectoryPageObject::scope (
598 sal_uInt32 nPage,
599 page::DataBlock::LinkDescriptor &rDescr) const
601 page const & rPage = PAGE();
602 OStoreDirectoryDataBlock const & rDataBlock = rPage.m_aDataBlock;
604 sal_uInt32 index0, index1, index2, index3;
606 // direct.
607 sal_uInt32 nCount = rDataBlock.directCount();
608 sal_uInt32 nLimit = nCount;
609 if (nPage < nLimit)
611 // Page to index reduction.
612 index0 = nPage;
614 // Setup LinkDescriptor indices.
615 rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff);
617 // Done.
618 return page::SCOPE_DIRECT;
620 nPage -= nLimit;
622 // single indirect.
623 sal_uInt32 const nCapacity = indirect::capacityCount(rPage.m_aDescr);
624 nCount = rDataBlock.singleCount();
625 nLimit = nCount * nCapacity;
626 if (nPage < nLimit)
628 // Page to index reduction.
629 sal_uInt32 n = nPage;
631 // Reduce to single indirect i(1), direct n = i(0).
632 index1 = n / nCapacity;
633 index0 = n % nCapacity;
635 // Verify reduction.
636 n = index1 * nCapacity + index0;
637 OSL_POSTCOND(n == nPage, "wrong math on indirect indices");
638 if (n != nPage)
639 return page::SCOPE_UNKNOWN;
641 // Setup LinkDescriptor indices.
642 rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff);
643 rDescr.m_nIndex1 = (sal_uInt16)(index1 & 0xffff);
645 // Done.
646 return page::SCOPE_SINGLE;
648 nPage -= nLimit;
650 // double indirect.
651 nCount = rDataBlock.doubleCount();
652 nLimit = nCount * nCapacity * nCapacity;
653 if (nPage < nLimit)
655 // Page to index reduction.
656 sal_uInt32 n = nPage;
658 // Reduce to double indirect i(2), single indirect n = i(0).
659 index2 = n / (nCapacity * nCapacity);
660 n = n % (nCapacity * nCapacity);
662 // Reduce to single indirect i(1), direct n = i(0).
663 index1 = n / nCapacity;
664 index0 = n % nCapacity;
666 // Verify reduction.
667 n = index2 * nCapacity * nCapacity +
668 index1 * nCapacity + index0;
669 OSL_POSTCOND(n == nPage, "wrong math on double indirect indices");
670 if (n != nPage)
671 return page::SCOPE_UNKNOWN;
673 // Setup LinkDescriptor indices.
674 rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff);
675 rDescr.m_nIndex1 = (sal_uInt16)(index1 & 0xffff);
676 rDescr.m_nIndex2 = (sal_uInt16)(index2 & 0xffff);
678 // Done.
679 return page::SCOPE_DOUBLE;
681 nPage -= nLimit;
683 // triple indirect.
684 nCount = rDataBlock.tripleCount();
685 nLimit = nCount * nCapacity * nCapacity * nCapacity;
686 if (nPage < nLimit)
688 // Page to index reduction.
689 sal_uInt32 n = nPage;
691 // Reduce to triple indirect i(3), double indirect n.
692 index3 = n / (nCapacity * nCapacity * nCapacity);
693 n = n % (nCapacity * nCapacity * nCapacity);
695 // Reduce to double indirect i(2), single indirect n.
696 index2 = n / (nCapacity * nCapacity);
697 n = n % (nCapacity * nCapacity);
699 // Reduce to single indirect i(1), direct n = i(0).
700 index1 = n / nCapacity;
701 index0 = n % nCapacity;
703 // Verify reduction.
704 n = index3 * nCapacity * nCapacity * nCapacity +
705 index2 * nCapacity * nCapacity +
706 index1 * nCapacity + index0;
707 OSL_POSTCOND(n == nPage, "wrong math on triple indirect indices");
708 if (n != nPage)
709 return page::SCOPE_UNKNOWN;
711 // Setup LinkDescriptor indices.
712 rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff);
713 rDescr.m_nIndex1 = (sal_uInt16)(index1 & 0xffff);
714 rDescr.m_nIndex2 = (sal_uInt16)(index2 & 0xffff);
715 rDescr.m_nIndex3 = (sal_uInt16)(index3 & 0xffff);
717 // Done.
718 return page::SCOPE_TRIPLE;
721 // Unreachable (more than triple indirect).
722 return page::SCOPE_UNREACHABLE;
726 * read (external data page).
728 storeError OStoreDirectoryPageObject::read (
729 sal_uInt32 nPage,
730 OStoreDataPageObject &rData,
731 OStorePageBIOS &rBIOS)
733 // Determine scope and link indices.
734 page::DataBlock::LinkDescriptor aLink;
735 page::ChunkScope eScope = scope (nPage, aLink);
737 storeError eErrCode = store_E_None;
738 if (eScope == page::SCOPE_DIRECT)
740 sal_uInt32 const nAddr = directLink (aLink.m_nIndex0);
741 if (nAddr == STORE_PAGE_NULL)
742 return store_E_NotExists;
744 eErrCode = rBIOS.loadObjectAt (rData, nAddr);
746 else if (eScope == page::SCOPE_SINGLE)
748 sal_uInt32 const nAddr = singleLink (aLink.m_nIndex1);
749 if (nAddr == STORE_PAGE_NULL)
750 return store_E_NotExists;
752 OStoreIndirectionPageObject aSingle;
753 eErrCode = rBIOS.loadObjectAt (aSingle, nAddr);
754 if (eErrCode != store_E_None)
755 return eErrCode;
757 eErrCode = aSingle.read (aLink.m_nIndex0, rData, rBIOS);
759 else if (eScope == page::SCOPE_DOUBLE)
761 sal_uInt32 const nAddr = doubleLink (aLink.m_nIndex2);
762 if (nAddr == STORE_PAGE_NULL)
763 return store_E_NotExists;
765 OStoreIndirectionPageObject aDouble;
766 eErrCode = rBIOS.loadObjectAt (aDouble, nAddr);
767 if (eErrCode != store_E_None)
768 return eErrCode;
770 eErrCode = aDouble.read (aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS);
772 else if (eScope == page::SCOPE_TRIPLE)
774 sal_uInt32 const nAddr = tripleLink (aLink.m_nIndex3);
775 if (nAddr == STORE_PAGE_NULL)
776 return store_E_NotExists;
778 OStoreIndirectionPageObject aTriple;
779 eErrCode = rBIOS.loadObjectAt (aTriple, nAddr);
780 if (eErrCode != store_E_None)
781 return eErrCode;
783 eErrCode = aTriple.read (aLink.m_nIndex2, aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS);
785 else if (eScope == page::SCOPE_UNREACHABLE)
787 // Out of scope.
788 eErrCode = store_E_CantSeek;
790 else
792 // Unknown scope.
793 OSL_TRACE("OStoreDirectoryPageObject::get(): scope failed");
794 eErrCode = store_E_Unknown;
797 // Leave.
798 return eErrCode;
802 * write (external data page).
804 storeError OStoreDirectoryPageObject::write (
805 sal_uInt32 nPage,
806 OStoreDataPageObject &rData,
807 OStorePageBIOS &rBIOS)
809 // Determine scope and link indices.
810 page::DataBlock::LinkDescriptor aLink;
811 page::ChunkScope eScope = scope (nPage, aLink);
813 storeError eErrCode = store_E_None;
814 if (eScope == page::SCOPE_DIRECT)
816 sal_uInt32 const nAddr = directLink (aLink.m_nIndex0);
817 if (nAddr == STORE_PAGE_NULL)
819 // Allocate data page.
820 eErrCode = rBIOS.allocate (rData);
821 if (eErrCode != store_E_None)
822 return eErrCode;
824 // Store data page location.
825 directLink (aLink.m_nIndex0, rData.location());
827 else
829 // Save data page.
830 eErrCode = rBIOS.saveObjectAt (rData, nAddr);
833 else if (eScope == page::SCOPE_SINGLE)
835 OStoreIndirectionPageObject aSingle;
836 eErrCode = aSingle.loadOrCreate (singleLink (aLink.m_nIndex1), rBIOS);
837 if (eErrCode != store_E_None)
839 if (eErrCode != store_E_Pending)
840 return eErrCode;
841 singleLink (aLink.m_nIndex1, aSingle.location());
844 eErrCode = aSingle.write (aLink.m_nIndex0, rData, rBIOS);
846 else if (eScope == page::SCOPE_DOUBLE)
848 OStoreIndirectionPageObject aDouble;
849 eErrCode = aDouble.loadOrCreate (doubleLink (aLink.m_nIndex2), rBIOS);
850 if (eErrCode != store_E_None)
852 if (eErrCode != store_E_Pending)
853 return eErrCode;
854 doubleLink (aLink.m_nIndex2, aDouble.location());
857 eErrCode = aDouble.write (aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS);
859 else if (eScope == page::SCOPE_TRIPLE)
861 OStoreIndirectionPageObject aTriple;
862 eErrCode = aTriple.loadOrCreate (tripleLink (aLink.m_nIndex3), rBIOS);
863 if (eErrCode != store_E_None)
865 if (eErrCode != store_E_Pending)
866 return eErrCode;
867 tripleLink (aLink.m_nIndex3, aTriple.location());
870 eErrCode = aTriple.write (aLink.m_nIndex2, aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS);
872 else if (eScope == page::SCOPE_UNREACHABLE)
874 // Out of scope.
875 eErrCode = store_E_CantSeek;
877 else
879 // Unknown scope.
880 OSL_TRACE("OStoreDirectoryPageObject::put(): scope failed");
881 eErrCode = store_E_Unknown;
884 // Leave.
885 return eErrCode;
889 * truncate (external data page).
891 storeError OStoreDirectoryPageObject::truncate (
892 sal_uInt32 nPage,
893 OStorePageBIOS &rBIOS)
895 // Determine scope and link indices.
896 page::DataBlock::LinkDescriptor aLink;
897 page::ChunkScope eScope = scope (nPage, aLink);
899 storeError eErrCode = store_E_None;
900 if (eScope == page::SCOPE_DIRECT)
902 // Truncate all triple indirect pages.
903 eErrCode = truncate (page::SCOPE_TRIPLE, 0, rBIOS);
904 if (eErrCode != store_E_None)
905 return eErrCode;
907 // Truncate all double indirect pages.
908 eErrCode = truncate (page::SCOPE_DOUBLE, 0, rBIOS);
909 if (eErrCode != store_E_None)
910 return eErrCode;
912 // Truncate all single indirect pages.
913 eErrCode = truncate (page::SCOPE_SINGLE, 0, rBIOS);
914 if (eErrCode != store_E_None)
915 return eErrCode;
917 // Truncate direct pages, including 'aLink.m_nIndex0'.
918 eErrCode = truncate (eScope, aLink.m_nIndex0, rBIOS);
920 else if (eScope == page::SCOPE_SINGLE)
922 // Truncate all triple indirect pages.
923 eErrCode = truncate (page::SCOPE_TRIPLE, 0, rBIOS);
924 if (eErrCode != store_E_None)
925 return eErrCode;
927 // Truncate all double indirect pages.
928 eErrCode = truncate (page::SCOPE_DOUBLE, 0, rBIOS);
929 if (eErrCode != store_E_None)
930 return eErrCode;
932 // Truncate single indirect pages, downto 'aLink.m_nIndex1'.
933 eErrCode = truncate (eScope, aLink.m_nIndex1 + 1, rBIOS);
934 if (eErrCode != store_E_None)
935 return eErrCode;
937 // Truncate last single indirect page to ... pages.
938 eErrCode = store_truncate_Impl (singleLink (aLink.m_nIndex1), aLink.m_nIndex0, rBIOS);
939 if (eErrCode != store_E_None)
940 return eErrCode;
942 // Check for complete truncation.
943 if (aLink.m_nIndex0 == 0)
945 // Clear pointer to last single indirect page.
946 singleLink (aLink.m_nIndex1, STORE_PAGE_NULL);
949 else if (eScope == page::SCOPE_DOUBLE)
951 // Truncate all triple indirect pages.
952 eErrCode = truncate (page::SCOPE_TRIPLE, 0, rBIOS);
953 if (eErrCode != store_E_None)
954 return eErrCode;
956 // Truncate double indirect pages, downto 'aLink.m_nIndex2'.
957 eErrCode = truncate (eScope, aLink.m_nIndex2 + 1, rBIOS);
958 if (eErrCode != store_E_None)
959 return eErrCode;
961 // Truncate last double indirect page to ... pages.
962 eErrCode = store_truncate_Impl (
963 doubleLink (aLink.m_nIndex2), aLink.m_nIndex1, aLink.m_nIndex0, rBIOS);
964 if (eErrCode != store_E_None)
965 return eErrCode;
967 // Check for complete truncation.
968 if ((aLink.m_nIndex1 + aLink.m_nIndex0) == 0)
970 // Clear pointer to last double indirect page.
971 doubleLink (aLink.m_nIndex2, STORE_PAGE_NULL);
974 else if (eScope == page::SCOPE_TRIPLE)
976 // Truncate triple indirect pages, downto 'aLink.m_nIndex3'.
977 eErrCode = truncate (eScope, aLink.m_nIndex3 + 1, rBIOS);
978 if (eErrCode != store_E_None)
979 return eErrCode;
981 // Truncate last triple indirect page to ... pages.
982 eErrCode = store_truncate_Impl (
983 tripleLink (aLink.m_nIndex3), aLink.m_nIndex2, aLink.m_nIndex1, aLink.m_nIndex0, rBIOS);
984 if (eErrCode != store_E_None)
985 return eErrCode;
987 // Check for complete truncation.
988 if ((aLink.m_nIndex2 + aLink.m_nIndex1 + aLink.m_nIndex0) == 0)
990 // Clear pointer to last triple indirect page.
991 tripleLink (aLink.m_nIndex3, STORE_PAGE_NULL);
994 else if (eScope == page::SCOPE_UNREACHABLE)
996 // Out of scope.
997 eErrCode = store_E_CantSeek;
999 else
1001 // Unknown scope.
1002 OSL_TRACE("OStoreDirectoryPageObject::put(): scope failed");
1003 eErrCode = store_E_Unknown;
1006 // Leave.
1007 return eErrCode;
1011 * truncate (external data page scope; private).
1013 storeError OStoreDirectoryPageObject::truncate (
1014 page::ChunkScope eScope,
1015 sal_uInt16 nRemain,
1016 OStorePageBIOS &rBIOS)
1018 OStoreDirectoryDataBlock const & rDataBlock = PAGE().m_aDataBlock;
1020 // Enter.
1021 storeError eErrCode = store_E_None;
1022 if (eScope == page::SCOPE_DIRECT)
1024 // Truncate direct data pages.
1025 sal_uInt16 i, n = rDataBlock.directCount();
1026 for (i = n; i > nRemain; i--)
1028 // Obtain data page location.
1029 sal_uInt32 nAddr = directLink (i - 1);
1030 if (nAddr == STORE_PAGE_NULL) continue;
1032 // Free data page.
1033 eErrCode = rBIOS.free (nAddr);
1034 if (eErrCode != store_E_None)
1035 break;
1037 // Clear pointer to data page.
1038 directLink (i - 1, STORE_PAGE_NULL);
1041 // Done.
1042 return eErrCode;
1045 if (eScope == page::SCOPE_SINGLE)
1047 // Truncate single indirect pages.
1048 sal_uInt16 i, n = rDataBlock.singleCount();
1049 for (i = n; i > nRemain; i--)
1051 // Truncate single indirect page to zero data pages.
1052 eErrCode = store_truncate_Impl (singleLink (i - 1), 0, rBIOS);
1053 if (eErrCode != store_E_None)
1054 break;
1056 // Clear pointer to single indirect page.
1057 singleLink (i - 1, STORE_PAGE_NULL);
1060 // Done.
1061 return eErrCode;
1064 if (eScope == page::SCOPE_DOUBLE)
1066 // Truncate double indirect pages.
1067 sal_uInt16 i, n = rDataBlock.doubleCount();
1068 for (i = n; i > nRemain; i--)
1070 // Truncate double indirect page to zero single indirect pages.
1071 eErrCode = store_truncate_Impl (doubleLink (i - 1), 0, 0, rBIOS);
1072 if (eErrCode != store_E_None)
1073 break;
1075 // Clear pointer to double indirect page.
1076 doubleLink (i - 1, STORE_PAGE_NULL);
1079 // Done.
1080 return eErrCode;
1083 if (eScope == page::SCOPE_TRIPLE)
1085 // Truncate triple indirect pages.
1086 sal_uInt16 i, n = rDataBlock.tripleCount();
1087 for (i = n; i > nRemain; i--)
1089 // Truncate to zero double indirect pages.
1090 eErrCode = store_truncate_Impl (tripleLink (i - 1), 0, 0, 0, rBIOS);
1091 if (eErrCode != store_E_None)
1092 break;
1094 // Clear pointer to triple indirect page.
1095 tripleLink (i - 1, STORE_PAGE_NULL);
1098 // Done.
1099 return eErrCode;
1102 // Invalid scope.
1103 return store_E_InvalidAccess;
1106 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */