CppunitTest_sc_tiledrendering2: move to tiledrendering folder
[LibreOffice.git] / store / source / stordata.cxx
blob5eaf531aedd965375a830c2a84ac4cf6f03d8491
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 .
20 #include "stordata.hxx"
22 #include <sal/types.h>
23 #include <sal/log.hxx>
25 #include <store/types.h>
26 #include "storbase.hxx"
27 #include "storbios.hxx"
29 using namespace store;
31 storeError OStoreDataPageObject::guard (sal_uInt32 nAddr)
33 return PageHolderObject< page >::guard (m_xPage, nAddr);
36 storeError OStoreDataPageObject::verify (sal_uInt32 nAddr) const
38 return PageHolderObject< page >::verify (m_xPage, nAddr);
41 /**
42 store_truncate_Impl (single indirect page).
44 static storeError store_truncate_Impl (
45 sal_uInt32 nAddr,
46 sal_uInt16 nSingle,
47 OStorePageBIOS &rBIOS)
49 if (nAddr != STORE_PAGE_NULL)
51 // Load single indirect page.
52 OStoreIndirectionPageObject aSingle;
53 storeError eErrCode = rBIOS.loadObjectAt (aSingle, nAddr);
54 if (eErrCode == store_E_None)
56 // Truncate to 'nSingle' direct pages.
57 eErrCode = aSingle.truncate (nSingle, rBIOS);
58 if (eErrCode != store_E_None)
59 return eErrCode;
61 else
63 if (eErrCode != store_E_InvalidChecksum)
64 return eErrCode;
67 // Check for complete truncation.
68 if (nSingle == 0)
70 // Free single indirect page.
71 eErrCode = rBIOS.free (nAddr);
72 if (eErrCode != store_E_None)
73 return eErrCode;
76 return store_E_None;
80 * store_truncate_Impl (double indirect page).
82 static storeError store_truncate_Impl (
83 sal_uInt32 nAddr,
84 sal_uInt16 nDouble,
85 sal_uInt16 nSingle,
86 OStorePageBIOS &rBIOS)
88 if (nAddr != STORE_PAGE_NULL)
90 // Load double indirect page.
91 OStoreIndirectionPageObject aDouble;
92 storeError eErrCode = rBIOS.loadObjectAt (aDouble, nAddr);
93 if (eErrCode == store_E_None)
95 // Truncate to 'nDouble', 'nSingle' pages.
96 eErrCode = aDouble.truncate (nDouble, nSingle, rBIOS);
97 if (eErrCode != store_E_None)
98 return eErrCode;
100 else
102 if (eErrCode != store_E_InvalidChecksum)
103 return eErrCode;
106 // Check for complete truncation.
107 if ((nDouble + nSingle) == 0)
109 // Free double indirect page.
110 eErrCode = rBIOS.free (nAddr);
111 if (eErrCode != store_E_None)
112 return eErrCode;
115 return store_E_None;
119 * store_truncate_Impl (triple indirect page).
121 static storeError store_truncate_Impl (
122 sal_uInt32 nAddr,
123 sal_uInt16 nTriple,
124 sal_uInt16 nDouble,
125 sal_uInt16 nSingle,
126 OStorePageBIOS &rBIOS)
128 if (nAddr != STORE_PAGE_NULL)
130 // Load triple indirect page.
131 OStoreIndirectionPageObject aTriple;
132 storeError eErrCode = rBIOS.loadObjectAt (aTriple, nAddr);
133 if (eErrCode != store_E_None)
134 return eErrCode;
136 // Truncate to 'nTriple', 'nDouble', 'nSingle' pages.
137 eErrCode = aTriple.truncate (nTriple, nDouble, nSingle, rBIOS);
138 if (eErrCode != store_E_None)
139 return eErrCode;
141 // Check for complete truncation.
142 if ((nTriple + nDouble + nSingle) == 0)
144 // Free triple indirect page.
145 eErrCode = rBIOS.free (nAddr);
146 if (eErrCode != store_E_None)
147 return eErrCode;
150 return store_E_None;
153 storeError OStoreIndirectionPageObject::loadOrCreate (
154 sal_uInt32 nAddr,
155 OStorePageBIOS & rBIOS)
157 if (nAddr == STORE_PAGE_NULL)
159 storeError eErrCode = construct<page>(rBIOS.allocator());
160 if (eErrCode != store_E_None)
161 return eErrCode;
163 eErrCode = rBIOS.allocate (*this);
164 if (eErrCode != store_E_None)
165 return eErrCode;
167 // Save location pending at caller.
168 return store_E_Pending;
170 return rBIOS.loadObjectAt (*this, nAddr);
173 storeError OStoreIndirectionPageObject::guard (sal_uInt32 nAddr)
175 return PageHolderObject< page >::guard (m_xPage, nAddr);
178 storeError OStoreIndirectionPageObject::verify (sal_uInt32 nAddr) const
180 return PageHolderObject< page >::verify (m_xPage, nAddr);
183 storeError OStoreIndirectionPageObject::read (
184 sal_uInt16 nSingle,
185 OStoreDataPageObject &rData,
186 OStorePageBIOS &rBIOS) const
188 PageHolderObject< page > xImpl (m_xPage);
189 page const & rPage = *xImpl;
191 // Check arguments.
192 sal_uInt16 const nLimit = rPage.capacityCount();
193 if (nSingle >= nLimit)
194 return store_E_InvalidAccess;
196 // Obtain data page location.
197 sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nSingle]);
198 if (nAddr == STORE_PAGE_NULL)
199 return store_E_NotExists;
201 // Load data page and leave.
202 return rBIOS.loadObjectAt (rData, nAddr);
206 * read (double indirect).
208 storeError OStoreIndirectionPageObject::read (
209 sal_uInt16 nDouble,
210 sal_uInt16 nSingle,
211 OStoreDataPageObject &rData,
212 OStorePageBIOS &rBIOS) const
214 PageHolderObject< page > xImpl (m_xPage);
215 page const & rPage = *xImpl;
217 // Check arguments.
218 sal_uInt16 const nLimit = rPage.capacityCount();
219 if ((nDouble >= nLimit) || (nSingle >= nLimit))
220 return store_E_InvalidAccess;
222 // Check single indirect page location.
223 sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nDouble]);
224 if (nAddr == STORE_PAGE_NULL)
225 return store_E_NotExists;
227 // Load single indirect page.
228 OStoreIndirectionPageObject aSingle;
229 storeError eErrCode = rBIOS.loadObjectAt (aSingle, nAddr);
230 if (eErrCode != store_E_None)
231 return eErrCode;
233 // Read single indirect and leave.
234 return aSingle.read (nSingle, rData, rBIOS);
238 * read (triple indirect).
240 storeError OStoreIndirectionPageObject::read (
241 sal_uInt16 nTriple,
242 sal_uInt16 nDouble,
243 sal_uInt16 nSingle,
244 OStoreDataPageObject &rData,
245 OStorePageBIOS &rBIOS) const
247 PageHolderObject< page > xImpl (m_xPage);
248 page const & rPage = *xImpl;
250 // Check arguments.
251 sal_uInt16 const nLimit = rPage.capacityCount();
252 if (!((nTriple < nLimit) && (nDouble < nLimit) && (nSingle < nLimit)))
253 return store_E_InvalidAccess;
255 // Check double indirect page location.
256 sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nTriple]);
257 if (nAddr == STORE_PAGE_NULL)
258 return store_E_NotExists;
260 // Load double indirect page.
261 OStoreIndirectionPageObject aDouble;
262 storeError eErrCode = rBIOS.loadObjectAt (aDouble, nAddr);
263 if (eErrCode != store_E_None)
264 return eErrCode;
266 // Read double indirect and leave.
267 return aDouble.read (nDouble, nSingle, rData, rBIOS);
271 * write (single indirect).
273 storeError OStoreIndirectionPageObject::write (
274 sal_uInt16 nSingle,
275 OStoreDataPageObject &rData,
276 OStorePageBIOS &rBIOS)
278 PageHolderObject< page > xImpl (m_xPage);
279 page & rPage = *xImpl;
281 // Check arguments.
282 sal_uInt16 const nLimit = rPage.capacityCount();
283 if (nSingle >= nLimit)
284 return store_E_InvalidAccess;
286 // Obtain data page location.
287 sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nSingle]);
288 if (nAddr == STORE_PAGE_NULL)
290 // Allocate data page.
291 storeError eErrCode = rBIOS.allocate (rData);
292 if (eErrCode != store_E_None)
293 return eErrCode;
295 // Store data page location.
296 rPage.m_pData[nSingle] = store::htonl(rData.location());
298 // Save this page.
299 return rBIOS.saveObjectAt (*this, location());
301 else
303 // Save data page.
304 return rBIOS.saveObjectAt (rData, nAddr);
309 * write (double indirect).
311 storeError OStoreIndirectionPageObject::write (
312 sal_uInt16 nDouble,
313 sal_uInt16 nSingle,
314 OStoreDataPageObject &rData,
315 OStorePageBIOS &rBIOS)
317 PageHolderObject< page > xImpl (m_xPage);
318 page & rPage = *xImpl;
320 // Check arguments.
321 sal_uInt16 const nLimit = rPage.capacityCount();
322 if ((nDouble >= nLimit) || (nSingle >= nLimit))
323 return store_E_InvalidAccess;
325 // Load or create single indirect page.
326 OStoreIndirectionPageObject aSingle;
327 storeError eErrCode = aSingle.loadOrCreate (store::ntohl(rPage.m_pData[nDouble]), rBIOS);
328 if (eErrCode != store_E_None)
330 if (eErrCode != store_E_Pending)
331 return eErrCode;
332 rPage.m_pData[nDouble] = store::htonl(aSingle.location());
334 eErrCode = rBIOS.saveObjectAt (*this, location());
335 if (eErrCode != store_E_None)
336 return eErrCode;
339 // Write single indirect and leave.
340 return aSingle.write (nSingle, rData, rBIOS);
344 * write (triple indirect).
346 storeError OStoreIndirectionPageObject::write (
347 sal_uInt16 nTriple,
348 sal_uInt16 nDouble,
349 sal_uInt16 nSingle,
350 OStoreDataPageObject &rData,
351 OStorePageBIOS &rBIOS)
353 PageHolderObject< page > xImpl (m_xPage);
354 page & rPage = *xImpl;
356 // Check arguments.
357 sal_uInt16 const nLimit = rPage.capacityCount();
358 if (!((nTriple < nLimit) && (nDouble < nLimit) && (nSingle < nLimit)))
359 return store_E_InvalidAccess;
361 // Load or create double indirect page.
362 OStoreIndirectionPageObject aDouble;
363 storeError eErrCode = aDouble.loadOrCreate (store::ntohl(rPage.m_pData[nTriple]), rBIOS);
364 if (eErrCode != store_E_None)
366 if (eErrCode != store_E_Pending)
367 return eErrCode;
368 rPage.m_pData[nTriple] = store::htonl(aDouble.location());
370 eErrCode = rBIOS.saveObjectAt (*this, location());
371 if (eErrCode != store_E_None)
372 return eErrCode;
375 // Write double indirect and leave.
376 return aDouble.write (nDouble, nSingle, rData, rBIOS);
380 * truncate (single indirect).
382 storeError OStoreIndirectionPageObject::truncate (
383 sal_uInt16 nSingle,
384 OStorePageBIOS & rBIOS)
386 PageHolderObject< page > xImpl (m_xPage);
387 page & rPage = *xImpl;
389 // Check arguments.
390 sal_uInt16 const nLimit = rPage.capacityCount();
391 if (nSingle >= nLimit)
392 return store_E_InvalidAccess;
394 // Truncate.
395 storeError eErrCode = store_E_None;
396 for (sal_uInt16 i = nLimit; i > nSingle; i--)
398 // Obtain data page location.
399 sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[i - 1]);
400 if (nAddr != STORE_PAGE_NULL)
402 // Free data page.
403 eErrCode = rBIOS.free (nAddr);
404 if (eErrCode != store_E_None)
405 return eErrCode;
407 // Clear pointer to data page.
408 rPage.m_pData[i - 1] = STORE_PAGE_NULL;
409 touch();
413 // Check for modified page.
414 if (dirty())
416 // Save this page.
417 eErrCode = rBIOS.saveObjectAt (*this, location());
420 // Done.
421 return eErrCode;
425 * truncate (double indirect).
427 storeError OStoreIndirectionPageObject::truncate (
428 sal_uInt16 nDouble,
429 sal_uInt16 nSingle,
430 OStorePageBIOS &rBIOS)
432 PageHolderObject< page > xImpl (m_xPage);
433 page & rPage = *xImpl;
435 // Check arguments.
436 sal_uInt16 const nLimit = rPage.capacityCount();
437 if ((nDouble >= nLimit) || (nSingle >= nLimit))
438 return store_E_InvalidAccess;
440 // Truncate.
441 storeError eErrCode = store_E_None;
442 for (sal_uInt16 i = nLimit; i > nDouble + 1; i--)
444 // Truncate single indirect page to zero direct pages.
445 eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[i - 1]), 0, rBIOS);
446 if (eErrCode != store_E_None)
447 return eErrCode;
449 // Clear pointer to single indirect page.
450 rPage.m_pData[i - 1] = STORE_PAGE_NULL;
451 touch();
454 // Truncate last single indirect page to 'nSingle' direct pages.
455 eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[nDouble]), nSingle, rBIOS);
456 if (eErrCode != store_E_None)
457 return eErrCode;
459 // Check for complete truncation.
460 if (nSingle == 0)
462 // Clear pointer to last single indirect page.
463 rPage.m_pData[nDouble] = STORE_PAGE_NULL;
464 touch();
467 // Check for modified page.
468 if (dirty())
470 // Save this page.
471 eErrCode = rBIOS.saveObjectAt (*this, location());
474 // Done.
475 return eErrCode;
479 * truncate (triple indirect).
481 storeError OStoreIndirectionPageObject::truncate (
482 sal_uInt16 nTriple,
483 sal_uInt16 nDouble,
484 sal_uInt16 nSingle,
485 OStorePageBIOS &rBIOS)
487 PageHolderObject< page > xImpl (m_xPage);
488 page & rPage = *xImpl;
490 // Check arguments.
491 sal_uInt16 const nLimit = rPage.capacityCount();
492 if (!((nTriple < nLimit) && (nDouble < nLimit) && (nSingle < nLimit)))
493 return store_E_InvalidAccess;
495 // Truncate.
496 storeError eErrCode = store_E_None;
497 for (sal_uInt16 i = nLimit; i > nTriple + 1; i--)
499 // Truncate double indirect page to zero single indirect pages.
500 eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[i - 1]), 0, 0, rBIOS);
501 if (eErrCode != store_E_None)
502 return eErrCode;
504 // Clear pointer to double indirect page.
505 rPage.m_pData[i - 1] = STORE_PAGE_NULL;
506 touch();
509 // Truncate last double indirect page to 'nDouble', 'nSingle' pages.
510 eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[nTriple]), nDouble, nSingle, rBIOS);
511 if (eErrCode != store_E_None)
512 return eErrCode;
514 // Check for complete truncation.
515 if ((nDouble + nSingle) == 0)
517 // Clear pointer to last double indirect page.
518 rPage.m_pData[nTriple] = STORE_PAGE_NULL;
519 touch();
522 // Check for modified page.
523 if (dirty())
525 // Save this page.
526 eErrCode = rBIOS.saveObjectAt (*this, location());
529 // Done.
530 return eErrCode;
533 storeError OStoreDirectoryPageObject::guard (sal_uInt32 nAddr)
535 return PageHolderObject< page >::guard (m_xPage, nAddr);
538 storeError OStoreDirectoryPageObject::verify (sal_uInt32 nAddr) const
540 return PageHolderObject< page >::verify (m_xPage, nAddr);
543 OStoreDirectoryPageData::ChunkScope
544 OStoreDirectoryPageObject::scope (
545 sal_uInt32 nPage,
546 page::DataBlock::LinkDescriptor &rDescr) const
548 page const & rPage = PAGE();
550 sal_uInt32 index0, index1, index2;
552 // direct.
553 sal_uInt32 nCount = OStoreDirectoryDataBlock::directCount;
554 sal_uInt32 nLimit = nCount;
555 if (nPage < nLimit)
557 // Page to index reduction.
558 index0 = nPage;
560 // Setup LinkDescriptor indices.
561 rDescr.m_nIndex0 = static_cast<sal_uInt16>(index0 & 0xffff);
563 // Done.
564 return page::SCOPE_DIRECT;
566 nPage -= nLimit;
568 // single indirect.
569 sal_uInt32 const nCapacity = indirect::capacityCount(rPage.m_aDescr);
570 nCount = OStoreDirectoryDataBlock::singleCount;
571 nLimit = nCount * nCapacity;
572 if (nPage < nLimit)
574 // Page to index reduction.
575 sal_uInt32 n = nPage;
577 // Reduce to single indirect i(1), direct n = i(0).
578 index1 = n / nCapacity;
579 index0 = n % nCapacity;
581 // Verify reduction.
582 n = index1 * nCapacity + index0;
583 if (n != nPage)
585 SAL_WARN("store", "wrong math on indirect indices");
586 return page::SCOPE_UNKNOWN;
589 // Setup LinkDescriptor indices.
590 rDescr.m_nIndex0 = static_cast<sal_uInt16>(index0 & 0xffff);
591 rDescr.m_nIndex1 = static_cast<sal_uInt16>(index1 & 0xffff);
593 // Done.
594 return page::SCOPE_SINGLE;
596 nPage -= nLimit;
598 // double indirect.
599 nCount = OStoreDirectoryDataBlock::doubleCount;
600 nLimit = nCount * nCapacity * nCapacity;
601 if (nPage < nLimit)
603 // Page to index reduction.
604 sal_uInt32 n = nPage;
606 // Reduce to double indirect i(2), single indirect n = i(0).
607 index2 = n / (nCapacity * nCapacity);
608 n = n % (nCapacity * nCapacity);
610 // Reduce to single indirect i(1), direct n = i(0).
611 index1 = n / nCapacity;
612 index0 = n % nCapacity;
614 // Verify reduction.
615 n = index2 * nCapacity * nCapacity +
616 index1 * nCapacity + index0;
617 if (n != nPage)
619 SAL_WARN("store", "wrong math on double indirect indices");
620 return page::SCOPE_UNKNOWN;
623 // Setup LinkDescriptor indices.
624 rDescr.m_nIndex0 = static_cast<sal_uInt16>(index0 & 0xffff);
625 rDescr.m_nIndex1 = static_cast<sal_uInt16>(index1 & 0xffff);
626 rDescr.m_nIndex2 = static_cast<sal_uInt16>(index2 & 0xffff);
628 // Done.
629 return page::SCOPE_DOUBLE;
631 nPage -= nLimit;
633 // triple indirect.
634 nCount = OStoreDirectoryDataBlock::tripleCount;
635 nLimit = nCount * nCapacity * nCapacity * nCapacity;
636 if (nPage < nLimit)
638 // Page to index reduction.
639 sal_uInt32 n = nPage;
641 // Reduce to triple indirect i(3), double indirect n.
642 sal_uInt32 index3 = n / (nCapacity * nCapacity * nCapacity);
643 n = n % (nCapacity * nCapacity * nCapacity);
645 // Reduce to double indirect i(2), single indirect n.
646 index2 = n / (nCapacity * nCapacity);
647 n = n % (nCapacity * nCapacity);
649 // Reduce to single indirect i(1), direct n = i(0).
650 index1 = n / nCapacity;
651 index0 = n % nCapacity;
653 // Verify reduction.
654 n = index3 * nCapacity * nCapacity * nCapacity +
655 index2 * nCapacity * nCapacity +
656 index1 * nCapacity + index0;
657 if (n != nPage)
659 SAL_WARN("store", "wrong math on triple indirect indices");
660 return page::SCOPE_UNKNOWN;
663 // Setup LinkDescriptor indices.
664 rDescr.m_nIndex0 = static_cast<sal_uInt16>(index0 & 0xffff);
665 rDescr.m_nIndex1 = static_cast<sal_uInt16>(index1 & 0xffff);
666 rDescr.m_nIndex2 = static_cast<sal_uInt16>(index2 & 0xffff);
667 rDescr.m_nIndex3 = static_cast<sal_uInt16>(index3 & 0xffff);
669 // Done.
670 return page::SCOPE_TRIPLE;
673 // Unreachable (more than triple indirect).
674 return page::SCOPE_UNREACHABLE;
677 storeError OStoreDirectoryPageObject::read (
678 sal_uInt32 nPage,
679 OStoreDataPageObject &rData,
680 OStorePageBIOS &rBIOS) const
682 // Determine scope and link indices.
683 page::DataBlock::LinkDescriptor aLink;
684 page::ChunkScope eScope = scope (nPage, aLink);
686 storeError eErrCode = store_E_None;
687 if (eScope == page::SCOPE_DIRECT)
689 sal_uInt32 const nAddr = directLink (aLink.m_nIndex0);
690 if (nAddr == STORE_PAGE_NULL)
691 return store_E_NotExists;
693 eErrCode = rBIOS.loadObjectAt (rData, nAddr);
695 else if (eScope == page::SCOPE_SINGLE)
697 sal_uInt32 const nAddr = singleLink (aLink.m_nIndex1);
698 if (nAddr == STORE_PAGE_NULL)
699 return store_E_NotExists;
701 OStoreIndirectionPageObject aSingle;
702 eErrCode = rBIOS.loadObjectAt (aSingle, nAddr);
703 if (eErrCode != store_E_None)
704 return eErrCode;
706 eErrCode = aSingle.read (aLink.m_nIndex0, rData, rBIOS);
708 else if (eScope == page::SCOPE_DOUBLE)
710 sal_uInt32 const nAddr = doubleLink (aLink.m_nIndex2);
711 if (nAddr == STORE_PAGE_NULL)
712 return store_E_NotExists;
714 OStoreIndirectionPageObject aDouble;
715 eErrCode = rBIOS.loadObjectAt (aDouble, nAddr);
716 if (eErrCode != store_E_None)
717 return eErrCode;
719 eErrCode = aDouble.read (aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS);
721 else if (eScope == page::SCOPE_TRIPLE)
723 sal_uInt32 const nAddr = tripleLink (aLink.m_nIndex3);
724 if (nAddr == STORE_PAGE_NULL)
725 return store_E_NotExists;
727 OStoreIndirectionPageObject aTriple;
728 eErrCode = rBIOS.loadObjectAt (aTriple, nAddr);
729 if (eErrCode != store_E_None)
730 return eErrCode;
732 eErrCode = aTriple.read (aLink.m_nIndex2, aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS);
734 else if (eScope == page::SCOPE_UNREACHABLE)
736 // Out of scope.
737 eErrCode = store_E_CantSeek;
739 else
741 // Unknown scope.
742 SAL_WARN("store", "OStoreDirectoryPageObject::get(): scope failed");
743 eErrCode = store_E_Unknown;
746 // Leave.
747 return eErrCode;
750 storeError OStoreDirectoryPageObject::write (
751 sal_uInt32 nPage,
752 OStoreDataPageObject &rData,
753 OStorePageBIOS &rBIOS)
755 // Determine scope and link indices.
756 page::DataBlock::LinkDescriptor aLink;
757 page::ChunkScope eScope = scope (nPage, aLink);
759 storeError eErrCode = store_E_None;
760 if (eScope == page::SCOPE_DIRECT)
762 sal_uInt32 const nAddr = directLink (aLink.m_nIndex0);
763 if (nAddr == STORE_PAGE_NULL)
765 // Allocate data page.
766 eErrCode = rBIOS.allocate (rData);
767 if (eErrCode != store_E_None)
768 return eErrCode;
770 // Store data page location.
771 directLink (aLink.m_nIndex0, rData.location());
773 else
775 // Save data page.
776 eErrCode = rBIOS.saveObjectAt (rData, nAddr);
779 else if (eScope == page::SCOPE_SINGLE)
781 OStoreIndirectionPageObject aSingle;
782 eErrCode = aSingle.loadOrCreate (singleLink (aLink.m_nIndex1), rBIOS);
783 if (eErrCode != store_E_None)
785 if (eErrCode != store_E_Pending)
786 return eErrCode;
787 singleLink (aLink.m_nIndex1, aSingle.location());
790 eErrCode = aSingle.write (aLink.m_nIndex0, rData, rBIOS);
792 else if (eScope == page::SCOPE_DOUBLE)
794 OStoreIndirectionPageObject aDouble;
795 eErrCode = aDouble.loadOrCreate (doubleLink (aLink.m_nIndex2), rBIOS);
796 if (eErrCode != store_E_None)
798 if (eErrCode != store_E_Pending)
799 return eErrCode;
800 doubleLink (aLink.m_nIndex2, aDouble.location());
803 eErrCode = aDouble.write (aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS);
805 else if (eScope == page::SCOPE_TRIPLE)
807 OStoreIndirectionPageObject aTriple;
808 eErrCode = aTriple.loadOrCreate (tripleLink (aLink.m_nIndex3), rBIOS);
809 if (eErrCode != store_E_None)
811 if (eErrCode != store_E_Pending)
812 return eErrCode;
813 tripleLink (aLink.m_nIndex3, aTriple.location());
816 eErrCode = aTriple.write (aLink.m_nIndex2, aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS);
818 else if (eScope == page::SCOPE_UNREACHABLE)
820 // Out of scope.
821 eErrCode = store_E_CantSeek;
823 else
825 // Unknown scope.
826 SAL_WARN("store", "OStoreDirectoryPageObject::put(): scope failed");
827 eErrCode = store_E_Unknown;
830 // Leave.
831 return eErrCode;
834 storeError OStoreDirectoryPageObject::truncate (
835 sal_uInt32 nPage,
836 OStorePageBIOS &rBIOS)
838 // Determine scope and link indices.
839 page::DataBlock::LinkDescriptor aLink;
840 page::ChunkScope eScope = scope (nPage, aLink);
842 storeError eErrCode = store_E_None;
843 if (eScope == page::SCOPE_DIRECT)
845 // Truncate all triple indirect pages.
846 eErrCode = truncate (page::SCOPE_TRIPLE, 0, rBIOS);
847 if (eErrCode != store_E_None)
848 return eErrCode;
850 // Truncate all double indirect pages.
851 eErrCode = truncate (page::SCOPE_DOUBLE, 0, rBIOS);
852 if (eErrCode != store_E_None)
853 return eErrCode;
855 // Truncate all single indirect pages.
856 eErrCode = truncate (page::SCOPE_SINGLE, 0, rBIOS);
857 if (eErrCode != store_E_None)
858 return eErrCode;
860 // Truncate direct pages, including 'aLink.m_nIndex0'.
861 eErrCode = truncate (eScope, aLink.m_nIndex0, rBIOS);
863 else if (eScope == page::SCOPE_SINGLE)
865 // Truncate all triple indirect pages.
866 eErrCode = truncate (page::SCOPE_TRIPLE, 0, rBIOS);
867 if (eErrCode != store_E_None)
868 return eErrCode;
870 // Truncate all double indirect pages.
871 eErrCode = truncate (page::SCOPE_DOUBLE, 0, rBIOS);
872 if (eErrCode != store_E_None)
873 return eErrCode;
875 // Truncate single indirect pages, downto 'aLink.m_nIndex1'.
876 eErrCode = truncate (eScope, aLink.m_nIndex1 + 1, rBIOS);
877 if (eErrCode != store_E_None)
878 return eErrCode;
880 // Truncate last single indirect page to ... pages.
881 eErrCode = store_truncate_Impl (singleLink (aLink.m_nIndex1), aLink.m_nIndex0, rBIOS);
882 if (eErrCode != store_E_None)
883 return eErrCode;
885 // Check for complete truncation.
886 if (aLink.m_nIndex0 == 0)
888 // Clear pointer to last single indirect page.
889 singleLink (aLink.m_nIndex1, STORE_PAGE_NULL);
892 else if (eScope == page::SCOPE_DOUBLE)
894 // Truncate all triple indirect pages.
895 eErrCode = truncate (page::SCOPE_TRIPLE, 0, rBIOS);
896 if (eErrCode != store_E_None)
897 return eErrCode;
899 // Truncate double indirect pages, downto 'aLink.m_nIndex2'.
900 eErrCode = truncate (eScope, aLink.m_nIndex2 + 1, rBIOS);
901 if (eErrCode != store_E_None)
902 return eErrCode;
904 // Truncate last double indirect page to ... pages.
905 eErrCode = store_truncate_Impl (
906 doubleLink (aLink.m_nIndex2), aLink.m_nIndex1, aLink.m_nIndex0, rBIOS);
907 if (eErrCode != store_E_None)
908 return eErrCode;
910 // Check for complete truncation.
911 if ((aLink.m_nIndex1 + aLink.m_nIndex0) == 0)
913 // Clear pointer to last double indirect page.
914 doubleLink (aLink.m_nIndex2, STORE_PAGE_NULL);
917 else if (eScope == page::SCOPE_TRIPLE)
919 // Truncate triple indirect pages, downto 'aLink.m_nIndex3'.
920 eErrCode = truncate (eScope, aLink.m_nIndex3 + 1, rBIOS);
921 if (eErrCode != store_E_None)
922 return eErrCode;
924 // Truncate last triple indirect page to ... pages.
925 eErrCode = store_truncate_Impl (
926 tripleLink (aLink.m_nIndex3), aLink.m_nIndex2, aLink.m_nIndex1, aLink.m_nIndex0, rBIOS);
927 if (eErrCode != store_E_None)
928 return eErrCode;
930 // Check for complete truncation.
931 if ((aLink.m_nIndex2 + aLink.m_nIndex1 + aLink.m_nIndex0) == 0)
933 // Clear pointer to last triple indirect page.
934 tripleLink (aLink.m_nIndex3, STORE_PAGE_NULL);
937 else if (eScope == page::SCOPE_UNREACHABLE)
939 // Out of scope.
940 eErrCode = store_E_CantSeek;
942 else
944 // Unknown scope.
945 SAL_WARN("store", "OStoreDirectoryPageObject::put(): scope failed");
946 eErrCode = store_E_Unknown;
949 // Leave.
950 return eErrCode;
954 * truncate (external data page scope; private).
956 storeError OStoreDirectoryPageObject::truncate (
957 page::ChunkScope eScope,
958 sal_uInt16 nRemain,
959 OStorePageBIOS &rBIOS)
961 // Enter.
962 storeError eErrCode = store_E_None;
963 if (eScope == page::SCOPE_DIRECT)
965 // Truncate direct data pages.
966 for (sal_uInt16 i = OStoreDirectoryDataBlock::directCount; i > nRemain; i--)
968 // Obtain data page location.
969 sal_uInt32 nAddr = directLink (i - 1);
970 if (nAddr == STORE_PAGE_NULL) continue;
972 // Free data page.
973 eErrCode = rBIOS.free (nAddr);
974 if (eErrCode != store_E_None)
975 break;
977 // Clear pointer to data page.
978 directLink (i - 1, STORE_PAGE_NULL);
981 // Done.
982 return eErrCode;
985 if (eScope == page::SCOPE_SINGLE)
987 // Truncate single indirect pages.
988 for (sal_uInt16 i = OStoreDirectoryDataBlock::singleCount; i > nRemain; i--)
990 // Truncate single indirect page to zero data pages.
991 eErrCode = store_truncate_Impl (singleLink (i - 1), 0, rBIOS);
992 if (eErrCode != store_E_None)
993 break;
995 // Clear pointer to single indirect page.
996 singleLink (i - 1, STORE_PAGE_NULL);
999 // Done.
1000 return eErrCode;
1003 if (eScope == page::SCOPE_DOUBLE)
1005 // Truncate double indirect pages.
1006 for (sal_uInt16 i = OStoreDirectoryDataBlock::doubleCount; i > nRemain; i--)
1008 // Truncate double indirect page to zero single indirect pages.
1009 eErrCode = store_truncate_Impl (doubleLink (i - 1), 0, 0, rBIOS);
1010 if (eErrCode != store_E_None)
1011 break;
1013 // Clear pointer to double indirect page.
1014 doubleLink (i - 1, STORE_PAGE_NULL);
1017 // Done.
1018 return eErrCode;
1021 if (eScope == page::SCOPE_TRIPLE)
1023 // Truncate triple indirect pages.
1024 for (sal_uInt16 i = OStoreDirectoryDataBlock::tripleCount; i > nRemain; i--)
1026 // Truncate to zero double indirect pages.
1027 eErrCode = store_truncate_Impl (tripleLink (i - 1), 0, 0, 0, rBIOS);
1028 if (eErrCode != store_E_None)
1029 break;
1031 // Clear pointer to triple indirect page.
1032 tripleLink (i - 1, STORE_PAGE_NULL);
1035 // Done.
1036 return eErrCode;
1039 // Invalid scope.
1040 return store_E_InvalidAccess;
1043 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */