bump product version to 4.1.6.2
[LibreOffice.git] / store / source / stordata.cxx
blobdd1bb5de9401936438b81380a1c5126a90978e0d
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "stordata.hxx"
23 #include "sal/types.h"
24 #include "osl/diagnose.h"
26 #include "store/types.h"
27 #include "storbase.hxx"
28 #include "storbios.hxx"
30 using namespace store;
32 /*========================================================================
34 * OStoreDataPageObject implementation.
36 *======================================================================*/
38 * guard.
40 storeError OStoreDataPageObject::guard (sal_uInt32 nAddr)
42 return PageHolderObject< page >::guard (m_xPage, nAddr);
46 * verify.
48 storeError OStoreDataPageObject::verify (sal_uInt32 nAddr) const
50 return PageHolderObject< page >::verify (m_xPage, nAddr);
53 /*========================================================================
55 * OStoreIndirectionPageObject implementation.
57 *======================================================================*/
59 * store_truncate_Impl (single indirect page).
61 static storeError store_truncate_Impl (
62 sal_uInt32 nAddr,
63 sal_uInt16 nSingle,
64 OStorePageBIOS &rBIOS)
66 if (nAddr != STORE_PAGE_NULL)
68 // Load single indirect page.
69 OStoreIndirectionPageObject aSingle;
70 storeError eErrCode = rBIOS.loadObjectAt (aSingle, nAddr);
71 if (eErrCode == store_E_None)
73 // Truncate to 'nSingle' direct pages.
74 eErrCode = aSingle.truncate (nSingle, rBIOS);
75 if (eErrCode != store_E_None)
76 return eErrCode;
78 else
80 if (eErrCode != store_E_InvalidChecksum)
81 return eErrCode;
84 // Check for complete truncation.
85 if (nSingle == 0)
87 // Free single indirect page.
88 eErrCode = rBIOS.free (nAddr);
89 if (eErrCode != store_E_None)
90 return eErrCode;
93 return store_E_None;
97 * store_truncate_Impl (double indirect page).
99 static storeError store_truncate_Impl (
100 sal_uInt32 nAddr,
101 sal_uInt16 nDouble,
102 sal_uInt16 nSingle,
103 OStorePageBIOS &rBIOS)
105 if (nAddr != STORE_PAGE_NULL)
107 // Load double indirect page.
108 OStoreIndirectionPageObject aDouble;
109 storeError eErrCode = rBIOS.loadObjectAt (aDouble, nAddr);
110 if (eErrCode == store_E_None)
112 // Truncate to 'nDouble', 'nSingle' pages.
113 eErrCode = aDouble.truncate (nDouble, nSingle, rBIOS);
114 if (eErrCode != store_E_None)
115 return eErrCode;
117 else
119 if (eErrCode != store_E_InvalidChecksum)
120 return eErrCode;
123 // Check for complete truncation.
124 if ((nDouble + nSingle) == 0)
126 // Free double indirect page.
127 eErrCode = rBIOS.free (nAddr);
128 if (eErrCode != store_E_None)
129 return eErrCode;
132 return store_E_None;
136 * store_truncate_Impl (triple indirect page).
138 static storeError store_truncate_Impl (
139 sal_uInt32 nAddr,
140 sal_uInt16 nTriple,
141 sal_uInt16 nDouble,
142 sal_uInt16 nSingle,
143 OStorePageBIOS &rBIOS)
145 if (nAddr != STORE_PAGE_NULL)
147 // Load triple indirect page.
148 OStoreIndirectionPageObject aTriple;
149 storeError eErrCode = rBIOS.loadObjectAt (aTriple, nAddr);
150 if (eErrCode != store_E_None)
151 return eErrCode;
153 // Truncate to 'nTriple', 'nDouble', 'nSingle' pages.
154 eErrCode = aTriple.truncate (nTriple, nDouble, nSingle, rBIOS);
155 if (eErrCode != store_E_None)
156 return eErrCode;
158 // Check for complete truncation.
159 if ((nTriple + nDouble + nSingle) == 0)
161 // Free triple indirect page.
162 eErrCode = rBIOS.free (nAddr);
163 if (eErrCode != store_E_None)
164 return eErrCode;
167 return store_E_None;
171 * loadOrCreate.
173 storeError OStoreIndirectionPageObject::loadOrCreate (
174 sal_uInt32 nAddr,
175 OStorePageBIOS & rBIOS)
177 if (nAddr == STORE_PAGE_NULL)
179 storeError eErrCode = construct<page>(rBIOS.allocator());
180 if (eErrCode != store_E_None)
181 return eErrCode;
183 eErrCode = rBIOS.allocate (*this);
184 if (eErrCode != store_E_None)
185 return eErrCode;
187 // Save location pending at caller.
188 return store_E_Pending;
190 return rBIOS.loadObjectAt (*this, nAddr);
194 * guard.
196 storeError OStoreIndirectionPageObject::guard (sal_uInt32 nAddr)
198 return PageHolderObject< page >::guard (m_xPage, nAddr);
202 * verify.
204 storeError OStoreIndirectionPageObject::verify (sal_uInt32 nAddr) const
206 return PageHolderObject< page >::verify (m_xPage, nAddr);
210 * read (single indirect).
212 storeError OStoreIndirectionPageObject::read (
213 sal_uInt16 nSingle,
214 OStoreDataPageObject &rData,
215 OStorePageBIOS &rBIOS)
217 PageHolderObject< page > xImpl (m_xPage);
218 page const & rPage = (*xImpl);
220 // Check arguments.
221 sal_uInt16 const nLimit = rPage.capacityCount();
222 if (!(nSingle < nLimit))
223 return store_E_InvalidAccess;
225 // Obtain data page location.
226 sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nSingle]);
227 if (nAddr == STORE_PAGE_NULL)
228 return store_E_NotExists;
230 // Load data page and leave.
231 return rBIOS.loadObjectAt (rData, nAddr);
235 * read (double indirect).
237 storeError OStoreIndirectionPageObject::read (
238 sal_uInt16 nDouble,
239 sal_uInt16 nSingle,
240 OStoreDataPageObject &rData,
241 OStorePageBIOS &rBIOS)
243 PageHolderObject< page > xImpl (m_xPage);
244 page const & rPage = (*xImpl);
246 // Check arguments.
247 sal_uInt16 const nLimit = rPage.capacityCount();
248 if (!((nDouble < nLimit) && (nSingle < nLimit)))
249 return store_E_InvalidAccess;
251 // Check single indirect page location.
252 sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nDouble]);
253 if (nAddr == STORE_PAGE_NULL)
254 return store_E_NotExists;
256 // Load single indirect page.
257 OStoreIndirectionPageObject aSingle;
258 storeError eErrCode = rBIOS.loadObjectAt (aSingle, nAddr);
259 if (eErrCode != store_E_None)
260 return eErrCode;
262 // Read single indirect and leave.
263 return aSingle.read (nSingle, rData, rBIOS);
267 * read (triple indirect).
269 storeError OStoreIndirectionPageObject::read (
270 sal_uInt16 nTriple,
271 sal_uInt16 nDouble,
272 sal_uInt16 nSingle,
273 OStoreDataPageObject &rData,
274 OStorePageBIOS &rBIOS)
276 PageHolderObject< page > xImpl (m_xPage);
277 page const & rPage = (*xImpl);
279 // Check arguments.
280 sal_uInt16 const nLimit = rPage.capacityCount();
281 if (!((nTriple < nLimit) && (nDouble < nLimit) && (nSingle < nLimit)))
282 return store_E_InvalidAccess;
284 // Check double indirect page location.
285 sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nTriple]);
286 if (nAddr == STORE_PAGE_NULL)
287 return store_E_NotExists;
289 // Load double indirect page.
290 OStoreIndirectionPageObject aDouble;
291 storeError eErrCode = rBIOS.loadObjectAt (aDouble, nAddr);
292 if (eErrCode != store_E_None)
293 return eErrCode;
295 // Read double indirect and leave.
296 return aDouble.read (nDouble, nSingle, rData, rBIOS);
300 * write (single indirect).
302 storeError OStoreIndirectionPageObject::write (
303 sal_uInt16 nSingle,
304 OStoreDataPageObject &rData,
305 OStorePageBIOS &rBIOS)
307 PageHolderObject< page > xImpl (m_xPage);
308 page & rPage = (*xImpl);
310 // Check arguments.
311 sal_uInt16 const nLimit = rPage.capacityCount();
312 if (!(nSingle < nLimit))
313 return store_E_InvalidAccess;
315 // Obtain data page location.
316 sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nSingle]);
317 if (nAddr == STORE_PAGE_NULL)
319 // Allocate data page.
320 storeError eErrCode = rBIOS.allocate (rData);
321 if (eErrCode != store_E_None)
322 return eErrCode;
324 // Store data page location.
325 rPage.m_pData[nSingle] = store::htonl(rData.location());
327 // Save this page.
328 return rBIOS.saveObjectAt (*this, location());
330 else
332 // Save data page.
333 return rBIOS.saveObjectAt (rData, nAddr);
338 * write (double indirect).
340 storeError OStoreIndirectionPageObject::write (
341 sal_uInt16 nDouble,
342 sal_uInt16 nSingle,
343 OStoreDataPageObject &rData,
344 OStorePageBIOS &rBIOS)
346 PageHolderObject< page > xImpl (m_xPage);
347 page & rPage = (*xImpl);
349 // Check arguments.
350 sal_uInt16 const nLimit = rPage.capacityCount();
351 if (!((nDouble < nLimit) && (nSingle < nLimit)))
352 return store_E_InvalidAccess;
354 // Load or create single indirect page.
355 OStoreIndirectionPageObject aSingle;
356 storeError eErrCode = aSingle.loadOrCreate (store::ntohl(rPage.m_pData[nDouble]), rBIOS);
357 if (eErrCode != store_E_None)
359 if (eErrCode != store_E_Pending)
360 return eErrCode;
361 rPage.m_pData[nDouble] = store::htonl(aSingle.location());
363 eErrCode = rBIOS.saveObjectAt (*this, location());
364 if (eErrCode != store_E_None)
365 return eErrCode;
368 // Write single indirect and leave.
369 return aSingle.write (nSingle, rData, rBIOS);
373 * write (triple indirect).
375 storeError OStoreIndirectionPageObject::write (
376 sal_uInt16 nTriple,
377 sal_uInt16 nDouble,
378 sal_uInt16 nSingle,
379 OStoreDataPageObject &rData,
380 OStorePageBIOS &rBIOS)
382 PageHolderObject< page > xImpl (m_xPage);
383 page & rPage = (*xImpl);
385 // Check arguments.
386 sal_uInt16 const nLimit = rPage.capacityCount();
387 if (!((nTriple < nLimit) && (nDouble < nLimit) && (nSingle < nLimit)))
388 return store_E_InvalidAccess;
390 // Load or create double indirect page.
391 OStoreIndirectionPageObject aDouble;
392 storeError eErrCode = aDouble.loadOrCreate (store::ntohl(rPage.m_pData[nTriple]), rBIOS);
393 if (eErrCode != store_E_None)
395 if (eErrCode != store_E_Pending)
396 return eErrCode;
397 rPage.m_pData[nTriple] = store::htonl(aDouble.location());
399 eErrCode = rBIOS.saveObjectAt (*this, location());
400 if (eErrCode != store_E_None)
401 return eErrCode;
404 // Write double indirect and leave.
405 return aDouble.write (nDouble, nSingle, rData, rBIOS);
409 * truncate (single indirect).
411 storeError OStoreIndirectionPageObject::truncate (
412 sal_uInt16 nSingle,
413 OStorePageBIOS & rBIOS)
415 PageHolderObject< page > xImpl (m_xPage);
416 page & rPage = (*xImpl);
418 // Check arguments.
419 sal_uInt16 const nLimit = rPage.capacityCount();
420 if (!(nSingle < nLimit))
421 return store_E_InvalidAccess;
423 // Truncate.
424 storeError eErrCode = store_E_None;
425 for (sal_uInt16 i = nLimit; i > nSingle; i--)
427 // Obtain data page location.
428 sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[i - 1]);
429 if (nAddr != STORE_PAGE_NULL)
431 // Free data page.
432 eErrCode = rBIOS.free (nAddr);
433 if (eErrCode != store_E_None)
434 return eErrCode;
436 // Clear pointer to data page.
437 rPage.m_pData[i - 1] = STORE_PAGE_NULL;
438 touch();
442 // Check for modified page.
443 if (dirty())
445 // Save this page.
446 eErrCode = rBIOS.saveObjectAt (*this, location());
449 // Done.
450 return eErrCode;
454 * truncate (double indirect).
456 storeError OStoreIndirectionPageObject::truncate (
457 sal_uInt16 nDouble,
458 sal_uInt16 nSingle,
459 OStorePageBIOS &rBIOS)
461 PageHolderObject< page > xImpl (m_xPage);
462 page & rPage = (*xImpl);
464 // Check arguments.
465 sal_uInt16 const nLimit = rPage.capacityCount();
466 if (!((nDouble < nLimit) && (nSingle < nLimit)))
467 return store_E_InvalidAccess;
469 // Truncate.
470 storeError eErrCode = store_E_None;
471 for (sal_uInt16 i = nLimit; i > nDouble + 1; i--)
473 // Truncate single indirect page to zero direct pages.
474 eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[i - 1]), 0, rBIOS);
475 if (eErrCode != store_E_None)
476 return eErrCode;
478 // Clear pointer to single indirect page.
479 rPage.m_pData[i - 1] = STORE_PAGE_NULL;
480 touch();
483 // Truncate last single indirect page to 'nSingle' direct pages.
484 eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[nDouble]), nSingle, rBIOS);
485 if (eErrCode != store_E_None)
486 return eErrCode;
488 // Check for complete truncation.
489 if (nSingle == 0)
491 // Clear pointer to last single indirect page.
492 rPage.m_pData[nDouble] = STORE_PAGE_NULL;
493 touch();
496 // Check for modified page.
497 if (dirty())
499 // Save this page.
500 eErrCode = rBIOS.saveObjectAt (*this, location());
503 // Done.
504 return eErrCode;
508 * truncate (triple indirect).
510 storeError OStoreIndirectionPageObject::truncate (
511 sal_uInt16 nTriple,
512 sal_uInt16 nDouble,
513 sal_uInt16 nSingle,
514 OStorePageBIOS &rBIOS)
516 PageHolderObject< page > xImpl (m_xPage);
517 page & rPage = (*xImpl);
519 // Check arguments.
520 sal_uInt16 const nLimit = rPage.capacityCount();
521 if (!((nTriple < nLimit) && (nDouble < nLimit) && (nSingle < nLimit)))
522 return store_E_InvalidAccess;
524 // Truncate.
525 storeError eErrCode = store_E_None;
526 for (sal_uInt16 i = nLimit; i > nTriple + 1; i--)
528 // Truncate double indirect page to zero single indirect pages.
529 eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[i - 1]), 0, 0, rBIOS);
530 if (eErrCode != store_E_None)
531 return eErrCode;
533 // Clear pointer to double indirect page.
534 rPage.m_pData[i - 1] = STORE_PAGE_NULL;
535 touch();
538 // Truncate last double indirect page to 'nDouble', 'nSingle' pages.
539 eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[nTriple]), nDouble, nSingle, rBIOS);
540 if (eErrCode != store_E_None)
541 return eErrCode;
543 // Check for complete truncation.
544 if ((nDouble + nSingle) == 0)
546 // Clear pointer to last double indirect page.
547 rPage.m_pData[nTriple] = STORE_PAGE_NULL;
548 touch();
551 // Check for modified page.
552 if (dirty())
554 // Save this page.
555 eErrCode = rBIOS.saveObjectAt (*this, location());
558 // Done.
559 return eErrCode;
562 /*========================================================================
564 * OStoreDirectoryPageObject implementation.
566 *======================================================================*/
568 * guard.
570 storeError OStoreDirectoryPageObject::guard (sal_uInt32 nAddr)
572 return PageHolderObject< page >::guard (m_xPage, nAddr);
576 * verify.
578 storeError OStoreDirectoryPageObject::verify (sal_uInt32 nAddr) const
580 return PageHolderObject< page >::verify (m_xPage, nAddr);
581 // OLD: m_rPage.verifyVersion (STORE_MAGIC_DIRECTORYPAGE);
585 * scope (external data page; private).
587 OStoreDirectoryPageData::ChunkScope
588 OStoreDirectoryPageObject::scope (
589 sal_uInt32 nPage,
590 page::DataBlock::LinkDescriptor &rDescr) const
592 page const & rPage = PAGE();
593 OStoreDirectoryDataBlock const & rDataBlock = rPage.m_aDataBlock;
595 sal_uInt32 index0, index1, index2, index3;
597 // direct.
598 sal_uInt32 nCount = rDataBlock.directCount();
599 sal_uInt32 nLimit = nCount;
600 if (nPage < nLimit)
602 // Page to index reduction.
603 index0 = nPage;
605 // Setup LinkDescriptor indices.
606 rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff);
608 // Done.
609 return page::SCOPE_DIRECT;
611 nPage -= nLimit;
613 // single indirect.
614 sal_uInt32 const nCapacity = indirect::capacityCount(rPage.m_aDescr);
615 nCount = rDataBlock.singleCount();
616 nLimit = nCount * nCapacity;
617 if (nPage < nLimit)
619 // Page to index reduction.
620 sal_uInt32 n = nPage;
622 // Reduce to single indirect i(1), direct n = i(0).
623 index1 = n / nCapacity;
624 index0 = n % nCapacity;
626 // Verify reduction.
627 n = index1 * nCapacity + index0;
628 OSL_POSTCOND(n == nPage, "wrong math on indirect indices");
629 if (n != nPage)
630 return page::SCOPE_UNKNOWN;
632 // Setup LinkDescriptor indices.
633 rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff);
634 rDescr.m_nIndex1 = (sal_uInt16)(index1 & 0xffff);
636 // Done.
637 return page::SCOPE_SINGLE;
639 nPage -= nLimit;
641 // double indirect.
642 nCount = rDataBlock.doubleCount();
643 nLimit = nCount * nCapacity * nCapacity;
644 if (nPage < nLimit)
646 // Page to index reduction.
647 sal_uInt32 n = nPage;
649 // Reduce to double indirect i(2), single indirect n = i(0).
650 index2 = n / (nCapacity * nCapacity);
651 n = n % (nCapacity * nCapacity);
653 // Reduce to single indirect i(1), direct n = i(0).
654 index1 = n / nCapacity;
655 index0 = n % nCapacity;
657 // Verify reduction.
658 n = index2 * nCapacity * nCapacity +
659 index1 * nCapacity + index0;
660 OSL_POSTCOND(n == nPage, "wrong math on double indirect indices");
661 if (n != nPage)
662 return page::SCOPE_UNKNOWN;
664 // Setup LinkDescriptor indices.
665 rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff);
666 rDescr.m_nIndex1 = (sal_uInt16)(index1 & 0xffff);
667 rDescr.m_nIndex2 = (sal_uInt16)(index2 & 0xffff);
669 // Done.
670 return page::SCOPE_DOUBLE;
672 nPage -= nLimit;
674 // triple indirect.
675 nCount = rDataBlock.tripleCount();
676 nLimit = nCount * nCapacity * nCapacity * nCapacity;
677 if (nPage < nLimit)
679 // Page to index reduction.
680 sal_uInt32 n = nPage;
682 // Reduce to triple indirect i(3), double indirect n.
683 index3 = n / (nCapacity * nCapacity * nCapacity);
684 n = n % (nCapacity * nCapacity * nCapacity);
686 // Reduce to double indirect i(2), single indirect n.
687 index2 = n / (nCapacity * nCapacity);
688 n = n % (nCapacity * nCapacity);
690 // Reduce to single indirect i(1), direct n = i(0).
691 index1 = n / nCapacity;
692 index0 = n % nCapacity;
694 // Verify reduction.
695 n = index3 * nCapacity * nCapacity * nCapacity +
696 index2 * nCapacity * nCapacity +
697 index1 * nCapacity + index0;
698 OSL_POSTCOND(n == nPage, "wrong math on triple indirect indices");
699 if (n != nPage)
700 return page::SCOPE_UNKNOWN;
702 // Setup LinkDescriptor indices.
703 rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff);
704 rDescr.m_nIndex1 = (sal_uInt16)(index1 & 0xffff);
705 rDescr.m_nIndex2 = (sal_uInt16)(index2 & 0xffff);
706 rDescr.m_nIndex3 = (sal_uInt16)(index3 & 0xffff);
708 // Done.
709 return page::SCOPE_TRIPLE;
712 // Unreachable (more than triple indirect).
713 return page::SCOPE_UNREACHABLE;
717 * read (external data page).
719 storeError OStoreDirectoryPageObject::read (
720 sal_uInt32 nPage,
721 OStoreDataPageObject &rData,
722 OStorePageBIOS &rBIOS)
724 // Determine scope and link indices.
725 page::DataBlock::LinkDescriptor aLink;
726 page::ChunkScope eScope = scope (nPage, aLink);
728 storeError eErrCode = store_E_None;
729 if (eScope == page::SCOPE_DIRECT)
731 sal_uInt32 const nAddr = directLink (aLink.m_nIndex0);
732 if (nAddr == STORE_PAGE_NULL)
733 return store_E_NotExists;
735 eErrCode = rBIOS.loadObjectAt (rData, nAddr);
737 else if (eScope == page::SCOPE_SINGLE)
739 sal_uInt32 const nAddr = singleLink (aLink.m_nIndex1);
740 if (nAddr == STORE_PAGE_NULL)
741 return store_E_NotExists;
743 OStoreIndirectionPageObject aSingle;
744 eErrCode = rBIOS.loadObjectAt (aSingle, nAddr);
745 if (eErrCode != store_E_None)
746 return eErrCode;
748 eErrCode = aSingle.read (aLink.m_nIndex0, rData, rBIOS);
750 else if (eScope == page::SCOPE_DOUBLE)
752 sal_uInt32 const nAddr = doubleLink (aLink.m_nIndex2);
753 if (nAddr == STORE_PAGE_NULL)
754 return store_E_NotExists;
756 OStoreIndirectionPageObject aDouble;
757 eErrCode = rBIOS.loadObjectAt (aDouble, nAddr);
758 if (eErrCode != store_E_None)
759 return eErrCode;
761 eErrCode = aDouble.read (aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS);
763 else if (eScope == page::SCOPE_TRIPLE)
765 sal_uInt32 const nAddr = tripleLink (aLink.m_nIndex3);
766 if (nAddr == STORE_PAGE_NULL)
767 return store_E_NotExists;
769 OStoreIndirectionPageObject aTriple;
770 eErrCode = rBIOS.loadObjectAt (aTriple, nAddr);
771 if (eErrCode != store_E_None)
772 return eErrCode;
774 eErrCode = aTriple.read (aLink.m_nIndex2, aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS);
776 else if (eScope == page::SCOPE_UNREACHABLE)
778 // Out of scope.
779 eErrCode = store_E_CantSeek;
781 else
783 // Unknown scope.
784 OSL_TRACE("OStoreDirectoryPageObject::get(): scope failed");
785 eErrCode = store_E_Unknown;
788 // Leave.
789 return eErrCode;
793 * write (external data page).
795 storeError OStoreDirectoryPageObject::write (
796 sal_uInt32 nPage,
797 OStoreDataPageObject &rData,
798 OStorePageBIOS &rBIOS)
800 // Determine scope and link indices.
801 page::DataBlock::LinkDescriptor aLink;
802 page::ChunkScope eScope = scope (nPage, aLink);
804 storeError eErrCode = store_E_None;
805 if (eScope == page::SCOPE_DIRECT)
807 sal_uInt32 const nAddr = directLink (aLink.m_nIndex0);
808 if (nAddr == STORE_PAGE_NULL)
810 // Allocate data page.
811 eErrCode = rBIOS.allocate (rData);
812 if (eErrCode != store_E_None)
813 return eErrCode;
815 // Store data page location.
816 directLink (aLink.m_nIndex0, rData.location());
818 else
820 // Save data page.
821 eErrCode = rBIOS.saveObjectAt (rData, nAddr);
824 else if (eScope == page::SCOPE_SINGLE)
826 OStoreIndirectionPageObject aSingle;
827 eErrCode = aSingle.loadOrCreate (singleLink (aLink.m_nIndex1), rBIOS);
828 if (eErrCode != store_E_None)
830 if (eErrCode != store_E_Pending)
831 return eErrCode;
832 singleLink (aLink.m_nIndex1, aSingle.location());
835 eErrCode = aSingle.write (aLink.m_nIndex0, rData, rBIOS);
837 else if (eScope == page::SCOPE_DOUBLE)
839 OStoreIndirectionPageObject aDouble;
840 eErrCode = aDouble.loadOrCreate (doubleLink (aLink.m_nIndex2), rBIOS);
841 if (eErrCode != store_E_None)
843 if (eErrCode != store_E_Pending)
844 return eErrCode;
845 doubleLink (aLink.m_nIndex2, aDouble.location());
848 eErrCode = aDouble.write (aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS);
850 else if (eScope == page::SCOPE_TRIPLE)
852 OStoreIndirectionPageObject aTriple;
853 eErrCode = aTriple.loadOrCreate (tripleLink (aLink.m_nIndex3), rBIOS);
854 if (eErrCode != store_E_None)
856 if (eErrCode != store_E_Pending)
857 return eErrCode;
858 tripleLink (aLink.m_nIndex3, aTriple.location());
861 eErrCode = aTriple.write (aLink.m_nIndex2, aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS);
863 else if (eScope == page::SCOPE_UNREACHABLE)
865 // Out of scope.
866 eErrCode = store_E_CantSeek;
868 else
870 // Unknown scope.
871 OSL_TRACE("OStoreDirectoryPageObject::put(): scope failed");
872 eErrCode = store_E_Unknown;
875 // Leave.
876 return eErrCode;
880 * truncate (external data page).
882 storeError OStoreDirectoryPageObject::truncate (
883 sal_uInt32 nPage,
884 OStorePageBIOS &rBIOS)
886 // Determine scope and link indices.
887 page::DataBlock::LinkDescriptor aLink;
888 page::ChunkScope eScope = scope (nPage, aLink);
890 storeError eErrCode = store_E_None;
891 if (eScope == page::SCOPE_DIRECT)
893 // Truncate all triple indirect pages.
894 eErrCode = truncate (page::SCOPE_TRIPLE, 0, rBIOS);
895 if (eErrCode != store_E_None)
896 return eErrCode;
898 // Truncate all double indirect pages.
899 eErrCode = truncate (page::SCOPE_DOUBLE, 0, rBIOS);
900 if (eErrCode != store_E_None)
901 return eErrCode;
903 // Truncate all single indirect pages.
904 eErrCode = truncate (page::SCOPE_SINGLE, 0, rBIOS);
905 if (eErrCode != store_E_None)
906 return eErrCode;
908 // Truncate direct pages, including 'aLink.m_nIndex0'.
909 eErrCode = truncate (eScope, aLink.m_nIndex0, rBIOS);
911 else if (eScope == page::SCOPE_SINGLE)
913 // Truncate all triple indirect pages.
914 eErrCode = truncate (page::SCOPE_TRIPLE, 0, rBIOS);
915 if (eErrCode != store_E_None)
916 return eErrCode;
918 // Truncate all double indirect pages.
919 eErrCode = truncate (page::SCOPE_DOUBLE, 0, rBIOS);
920 if (eErrCode != store_E_None)
921 return eErrCode;
923 // Truncate single indirect pages, downto 'aLink.m_nIndex1'.
924 eErrCode = truncate (eScope, aLink.m_nIndex1 + 1, rBIOS);
925 if (eErrCode != store_E_None)
926 return eErrCode;
928 // Truncate last single indirect page to ... pages.
929 eErrCode = store_truncate_Impl (singleLink (aLink.m_nIndex1), aLink.m_nIndex0, rBIOS);
930 if (eErrCode != store_E_None)
931 return eErrCode;
933 // Check for complete truncation.
934 if (aLink.m_nIndex0 == 0)
936 // Clear pointer to last single indirect page.
937 singleLink (aLink.m_nIndex1, STORE_PAGE_NULL);
940 else if (eScope == page::SCOPE_DOUBLE)
942 // Truncate all triple indirect pages.
943 eErrCode = truncate (page::SCOPE_TRIPLE, 0, rBIOS);
944 if (eErrCode != store_E_None)
945 return eErrCode;
947 // Truncate double indirect pages, downto 'aLink.m_nIndex2'.
948 eErrCode = truncate (eScope, aLink.m_nIndex2 + 1, rBIOS);
949 if (eErrCode != store_E_None)
950 return eErrCode;
952 // Truncate last double indirect page to ... pages.
953 eErrCode = store_truncate_Impl (
954 doubleLink (aLink.m_nIndex2), aLink.m_nIndex1, aLink.m_nIndex0, rBIOS);
955 if (eErrCode != store_E_None)
956 return eErrCode;
958 // Check for complete truncation.
959 if ((aLink.m_nIndex1 + aLink.m_nIndex0) == 0)
961 // Clear pointer to last double indirect page.
962 doubleLink (aLink.m_nIndex2, STORE_PAGE_NULL);
965 else if (eScope == page::SCOPE_TRIPLE)
967 // Truncate triple indirect pages, downto 'aLink.m_nIndex3'.
968 eErrCode = truncate (eScope, aLink.m_nIndex3 + 1, rBIOS);
969 if (eErrCode != store_E_None)
970 return eErrCode;
972 // Truncate last triple indirect page to ... pages.
973 eErrCode = store_truncate_Impl (
974 tripleLink (aLink.m_nIndex3), aLink.m_nIndex2, aLink.m_nIndex1, aLink.m_nIndex0, rBIOS);
975 if (eErrCode != store_E_None)
976 return eErrCode;
978 // Check for complete truncation.
979 if ((aLink.m_nIndex2 + aLink.m_nIndex1 + aLink.m_nIndex0) == 0)
981 // Clear pointer to last triple indirect page.
982 tripleLink (aLink.m_nIndex3, STORE_PAGE_NULL);
985 else if (eScope == page::SCOPE_UNREACHABLE)
987 // Out of scope.
988 eErrCode = store_E_CantSeek;
990 else
992 // Unknown scope.
993 OSL_TRACE("OStoreDirectoryPageObject::put(): scope failed");
994 eErrCode = store_E_Unknown;
997 // Leave.
998 return eErrCode;
1002 * truncate (external data page scope; private).
1004 storeError OStoreDirectoryPageObject::truncate (
1005 page::ChunkScope eScope,
1006 sal_uInt16 nRemain,
1007 OStorePageBIOS &rBIOS)
1009 OStoreDirectoryDataBlock const & rDataBlock = PAGE().m_aDataBlock;
1011 // Enter.
1012 storeError eErrCode = store_E_None;
1013 if (eScope == page::SCOPE_DIRECT)
1015 // Truncate direct data pages.
1016 sal_uInt16 i, n = rDataBlock.directCount();
1017 for (i = n; i > nRemain; i--)
1019 // Obtain data page location.
1020 sal_uInt32 nAddr = directLink (i - 1);
1021 if (nAddr == STORE_PAGE_NULL) continue;
1023 // Free data page.
1024 eErrCode = rBIOS.free (nAddr);
1025 if (eErrCode != store_E_None)
1026 break;
1028 // Clear pointer to data page.
1029 directLink (i - 1, STORE_PAGE_NULL);
1032 // Done.
1033 return eErrCode;
1036 if (eScope == page::SCOPE_SINGLE)
1038 // Truncate single indirect pages.
1039 sal_uInt16 i, n = rDataBlock.singleCount();
1040 for (i = n; i > nRemain; i--)
1042 // Truncate single indirect page to zero data pages.
1043 eErrCode = store_truncate_Impl (singleLink (i - 1), 0, rBIOS);
1044 if (eErrCode != store_E_None)
1045 break;
1047 // Clear pointer to single indirect page.
1048 singleLink (i - 1, STORE_PAGE_NULL);
1051 // Done.
1052 return eErrCode;
1055 if (eScope == page::SCOPE_DOUBLE)
1057 // Truncate double indirect pages.
1058 sal_uInt16 i, n = rDataBlock.doubleCount();
1059 for (i = n; i > nRemain; i--)
1061 // Truncate double indirect page to zero single indirect pages.
1062 eErrCode = store_truncate_Impl (doubleLink (i - 1), 0, 0, rBIOS);
1063 if (eErrCode != store_E_None)
1064 break;
1066 // Clear pointer to double indirect page.
1067 doubleLink (i - 1, STORE_PAGE_NULL);
1070 // Done.
1071 return eErrCode;
1074 if (eScope == page::SCOPE_TRIPLE)
1076 // Truncate triple indirect pages.
1077 sal_uInt16 i, n = rDataBlock.tripleCount();
1078 for (i = n; i > nRemain; i--)
1080 // Truncate to zero double indirect pages.
1081 eErrCode = store_truncate_Impl (tripleLink (i - 1), 0, 0, 0, rBIOS);
1082 if (eErrCode != store_E_None)
1083 break;
1085 // Clear pointer to triple indirect page.
1086 tripleLink (i - 1, STORE_PAGE_NULL);
1089 // Done.
1090 return eErrCode;
1093 // Invalid scope.
1094 return store_E_InvalidAccess;
1097 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */