adapt hwpfilter unittests to separate RdbTarget makefile requirement
[LibreOffice.git] / store / source / stordata.cxx
blobdb85ce0eff139c70181880b7a93bb7ce45eb282d
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 ************************************************************************/
29 // MARKER(update_precomp.py): autogen include statement, do not remove
30 #include "precompiled_store.hxx"
32 #include "stordata.hxx"
34 #include "sal/types.h"
35 #include "osl/diagnose.h"
37 #include "store/types.h"
38 #include "storbase.hxx"
39 #include "storbios.hxx"
41 using namespace store;
43 /*========================================================================
45 * OStoreDataPageObject implementation.
47 *======================================================================*/
49 * guard.
51 storeError OStoreDataPageObject::guard (sal_uInt32 nAddr)
53 return PageHolderObject< page >::guard (m_xPage, nAddr);
57 * verify.
59 storeError OStoreDataPageObject::verify (sal_uInt32 nAddr) const
61 return PageHolderObject< page >::verify (m_xPage, nAddr);
64 /*========================================================================
66 * OStoreIndirectionPageObject implementation.
68 *======================================================================*/
70 * store_truncate_Impl (single indirect page).
72 static storeError store_truncate_Impl (
73 sal_uInt32 nAddr,
74 sal_uInt16 nSingle,
75 OStorePageBIOS &rBIOS)
77 if (nAddr != STORE_PAGE_NULL)
79 // Load single indirect page.
80 OStoreIndirectionPageObject aSingle;
81 storeError eErrCode = rBIOS.loadObjectAt (aSingle, nAddr);
82 if (eErrCode == store_E_None)
84 // Truncate to 'nSingle' direct pages.
85 eErrCode = aSingle.truncate (nSingle, rBIOS);
86 if (eErrCode != store_E_None)
87 return eErrCode;
89 else
91 if (eErrCode != store_E_InvalidChecksum)
92 return eErrCode;
95 // Check for complete truncation.
96 if (nSingle == 0)
98 // Free single indirect page.
99 eErrCode = rBIOS.free (nAddr);
100 if (eErrCode != store_E_None)
101 return eErrCode;
104 return store_E_None;
108 * store_truncate_Impl (double indirect page).
110 static storeError store_truncate_Impl (
111 sal_uInt32 nAddr,
112 sal_uInt16 nDouble,
113 sal_uInt16 nSingle,
114 OStorePageBIOS &rBIOS)
116 if (nAddr != STORE_PAGE_NULL)
118 // Load double indirect page.
119 OStoreIndirectionPageObject aDouble;
120 storeError eErrCode = rBIOS.loadObjectAt (aDouble, nAddr);
121 if (eErrCode == store_E_None)
123 // Truncate to 'nDouble', 'nSingle' pages.
124 eErrCode = aDouble.truncate (nDouble, nSingle, rBIOS);
125 if (eErrCode != store_E_None)
126 return eErrCode;
128 else
130 if (eErrCode != store_E_InvalidChecksum)
131 return eErrCode;
134 // Check for complete truncation.
135 if ((nDouble + nSingle) == 0)
137 // Free double indirect page.
138 eErrCode = rBIOS.free (nAddr);
139 if (eErrCode != store_E_None)
140 return eErrCode;
143 return store_E_None;
147 * store_truncate_Impl (triple indirect page).
149 static storeError store_truncate_Impl (
150 sal_uInt32 nAddr,
151 sal_uInt16 nTriple,
152 sal_uInt16 nDouble,
153 sal_uInt16 nSingle,
154 OStorePageBIOS &rBIOS)
156 if (nAddr != STORE_PAGE_NULL)
158 // Load triple indirect page.
159 OStoreIndirectionPageObject aTriple;
160 storeError eErrCode = rBIOS.loadObjectAt (aTriple, nAddr);
161 if (eErrCode != store_E_None)
162 return eErrCode;
164 // Truncate to 'nTriple', 'nDouble', 'nSingle' pages.
165 eErrCode = aTriple.truncate (nTriple, nDouble, nSingle, rBIOS);
166 if (eErrCode != store_E_None)
167 return eErrCode;
169 // Check for complete truncation.
170 if ((nTriple + nDouble + nSingle) == 0)
172 // Free triple indirect page.
173 eErrCode = rBIOS.free (nAddr);
174 if (eErrCode != store_E_None)
175 return eErrCode;
178 return store_E_None;
182 * loadOrCreate.
184 storeError OStoreIndirectionPageObject::loadOrCreate (
185 sal_uInt32 nAddr,
186 OStorePageBIOS & rBIOS)
188 if (nAddr == STORE_PAGE_NULL)
190 storeError eErrCode = construct<page>(rBIOS.allocator());
191 if (eErrCode != store_E_None)
192 return eErrCode;
194 eErrCode = rBIOS.allocate (*this);
195 if (eErrCode != store_E_None)
196 return eErrCode;
198 // Save location pending at caller.
199 return store_E_Pending;
201 return rBIOS.loadObjectAt (*this, nAddr);
205 * guard.
207 storeError OStoreIndirectionPageObject::guard (sal_uInt32 nAddr)
209 return PageHolderObject< page >::guard (m_xPage, nAddr);
213 * verify.
215 storeError OStoreIndirectionPageObject::verify (sal_uInt32 nAddr) const
217 return PageHolderObject< page >::verify (m_xPage, nAddr);
221 * read (single indirect).
223 storeError OStoreIndirectionPageObject::read (
224 sal_uInt16 nSingle,
225 OStoreDataPageObject &rData,
226 OStorePageBIOS &rBIOS)
228 PageHolderObject< page > xImpl (m_xPage);
229 page const & rPage = (*xImpl);
231 // Check arguments.
232 sal_uInt16 const nLimit = rPage.capacityCount();
233 if (!(nSingle < nLimit))
234 return store_E_InvalidAccess;
236 // Obtain data page location.
237 sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nSingle]);
238 if (nAddr == STORE_PAGE_NULL)
239 return store_E_NotExists;
241 // Load data page and leave.
242 return rBIOS.loadObjectAt (rData, nAddr);
246 * read (double indirect).
248 storeError OStoreIndirectionPageObject::read (
249 sal_uInt16 nDouble,
250 sal_uInt16 nSingle,
251 OStoreDataPageObject &rData,
252 OStorePageBIOS &rBIOS)
254 PageHolderObject< page > xImpl (m_xPage);
255 page const & rPage = (*xImpl);
257 // Check arguments.
258 sal_uInt16 const nLimit = rPage.capacityCount();
259 if (!((nDouble < nLimit) && (nSingle < nLimit)))
260 return store_E_InvalidAccess;
262 // Check single indirect page location.
263 sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nDouble]);
264 if (nAddr == STORE_PAGE_NULL)
265 return store_E_NotExists;
267 // Load single indirect page.
268 OStoreIndirectionPageObject aSingle;
269 storeError eErrCode = rBIOS.loadObjectAt (aSingle, nAddr);
270 if (eErrCode != store_E_None)
271 return eErrCode;
273 // Read single indirect and leave.
274 return aSingle.read (nSingle, rData, rBIOS);
278 * read (triple indirect).
280 storeError OStoreIndirectionPageObject::read (
281 sal_uInt16 nTriple,
282 sal_uInt16 nDouble,
283 sal_uInt16 nSingle,
284 OStoreDataPageObject &rData,
285 OStorePageBIOS &rBIOS)
287 PageHolderObject< page > xImpl (m_xPage);
288 page const & rPage = (*xImpl);
290 // Check arguments.
291 sal_uInt16 const nLimit = rPage.capacityCount();
292 if (!((nTriple < nLimit) && (nDouble < nLimit) && (nSingle < nLimit)))
293 return store_E_InvalidAccess;
295 // Check double indirect page location.
296 sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nTriple]);
297 if (nAddr == STORE_PAGE_NULL)
298 return store_E_NotExists;
300 // Load double indirect page.
301 OStoreIndirectionPageObject aDouble;
302 storeError eErrCode = rBIOS.loadObjectAt (aDouble, nAddr);
303 if (eErrCode != store_E_None)
304 return eErrCode;
306 // Read double indirect and leave.
307 return aDouble.read (nDouble, nSingle, rData, rBIOS);
311 * write (single indirect).
313 storeError OStoreIndirectionPageObject::write (
314 sal_uInt16 nSingle,
315 OStoreDataPageObject &rData,
316 OStorePageBIOS &rBIOS)
318 PageHolderObject< page > xImpl (m_xPage);
319 page & rPage = (*xImpl);
321 // Check arguments.
322 sal_uInt16 const nLimit = rPage.capacityCount();
323 if (!(nSingle < nLimit))
324 return store_E_InvalidAccess;
326 // Obtain data page location.
327 sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nSingle]);
328 if (nAddr == STORE_PAGE_NULL)
330 // Allocate data page.
331 storeError eErrCode = rBIOS.allocate (rData);
332 if (eErrCode != store_E_None)
333 return eErrCode;
335 // Store data page location.
336 rPage.m_pData[nSingle] = store::htonl(rData.location());
338 // Save this page.
339 return rBIOS.saveObjectAt (*this, location());
341 else
343 // Save data page.
344 return rBIOS.saveObjectAt (rData, nAddr);
349 * write (double indirect).
351 storeError OStoreIndirectionPageObject::write (
352 sal_uInt16 nDouble,
353 sal_uInt16 nSingle,
354 OStoreDataPageObject &rData,
355 OStorePageBIOS &rBIOS)
357 PageHolderObject< page > xImpl (m_xPage);
358 page & rPage = (*xImpl);
360 // Check arguments.
361 sal_uInt16 const nLimit = rPage.capacityCount();
362 if (!((nDouble < nLimit) && (nSingle < nLimit)))
363 return store_E_InvalidAccess;
365 // Load or create single indirect page.
366 OStoreIndirectionPageObject aSingle;
367 storeError eErrCode = aSingle.loadOrCreate (store::ntohl(rPage.m_pData[nDouble]), rBIOS);
368 if (eErrCode != store_E_None)
370 if (eErrCode != store_E_Pending)
371 return eErrCode;
372 rPage.m_pData[nDouble] = store::htonl(aSingle.location());
374 eErrCode = rBIOS.saveObjectAt (*this, location());
375 if (eErrCode != store_E_None)
376 return eErrCode;
379 // Write single indirect and leave.
380 return aSingle.write (nSingle, rData, rBIOS);
384 * write (triple indirect).
386 storeError OStoreIndirectionPageObject::write (
387 sal_uInt16 nTriple,
388 sal_uInt16 nDouble,
389 sal_uInt16 nSingle,
390 OStoreDataPageObject &rData,
391 OStorePageBIOS &rBIOS)
393 PageHolderObject< page > xImpl (m_xPage);
394 page & rPage = (*xImpl);
396 // Check arguments.
397 sal_uInt16 const nLimit = rPage.capacityCount();
398 if (!((nTriple < nLimit) && (nDouble < nLimit) && (nSingle < nLimit)))
399 return store_E_InvalidAccess;
401 // Load or create double indirect page.
402 OStoreIndirectionPageObject aDouble;
403 storeError eErrCode = aDouble.loadOrCreate (store::ntohl(rPage.m_pData[nTriple]), rBIOS);
404 if (eErrCode != store_E_None)
406 if (eErrCode != store_E_Pending)
407 return eErrCode;
408 rPage.m_pData[nTriple] = store::htonl(aDouble.location());
410 eErrCode = rBIOS.saveObjectAt (*this, location());
411 if (eErrCode != store_E_None)
412 return eErrCode;
415 // Write double indirect and leave.
416 return aDouble.write (nDouble, nSingle, rData, rBIOS);
420 * truncate (single indirect).
422 storeError OStoreIndirectionPageObject::truncate (
423 sal_uInt16 nSingle,
424 OStorePageBIOS & rBIOS)
426 PageHolderObject< page > xImpl (m_xPage);
427 page & rPage = (*xImpl);
429 // Check arguments.
430 sal_uInt16 const nLimit = rPage.capacityCount();
431 if (!(nSingle < nLimit))
432 return store_E_InvalidAccess;
434 // Truncate.
435 storeError eErrCode = store_E_None;
436 for (sal_uInt16 i = nLimit; i > nSingle; i--)
438 // Obtain data page location.
439 sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[i - 1]);
440 if (nAddr != STORE_PAGE_NULL)
442 // Free data page.
443 eErrCode = rBIOS.free (nAddr);
444 if (eErrCode != store_E_None)
445 return eErrCode;
447 // Clear pointer to data page.
448 rPage.m_pData[i - 1] = STORE_PAGE_NULL;
449 touch();
453 // Check for modified page.
454 if (dirty())
456 // Save this page.
457 eErrCode = rBIOS.saveObjectAt (*this, location());
460 // Done.
461 return eErrCode;
465 * truncate (double indirect).
467 storeError OStoreIndirectionPageObject::truncate (
468 sal_uInt16 nDouble,
469 sal_uInt16 nSingle,
470 OStorePageBIOS &rBIOS)
472 PageHolderObject< page > xImpl (m_xPage);
473 page & rPage = (*xImpl);
475 // Check arguments.
476 sal_uInt16 const nLimit = rPage.capacityCount();
477 if (!((nDouble < nLimit) && (nSingle < nLimit)))
478 return store_E_InvalidAccess;
480 // Truncate.
481 storeError eErrCode = store_E_None;
482 for (sal_uInt16 i = nLimit; i > nDouble + 1; i--)
484 // Truncate single indirect page to zero direct pages.
485 eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[i - 1]), 0, rBIOS);
486 if (eErrCode != store_E_None)
487 return eErrCode;
489 // Clear pointer to single indirect page.
490 rPage.m_pData[i - 1] = STORE_PAGE_NULL;
491 touch();
494 // Truncate last single indirect page to 'nSingle' direct pages.
495 eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[nDouble]), nSingle, rBIOS);
496 if (eErrCode != store_E_None)
497 return eErrCode;
499 // Check for complete truncation.
500 if (nSingle == 0)
502 // Clear pointer to last single indirect page.
503 rPage.m_pData[nDouble] = STORE_PAGE_NULL;
504 touch();
507 // Check for modified page.
508 if (dirty())
510 // Save this page.
511 eErrCode = rBIOS.saveObjectAt (*this, location());
514 // Done.
515 return eErrCode;
519 * truncate (triple indirect).
521 storeError OStoreIndirectionPageObject::truncate (
522 sal_uInt16 nTriple,
523 sal_uInt16 nDouble,
524 sal_uInt16 nSingle,
525 OStorePageBIOS &rBIOS)
527 PageHolderObject< page > xImpl (m_xPage);
528 page & rPage = (*xImpl);
530 // Check arguments.
531 sal_uInt16 const nLimit = rPage.capacityCount();
532 if (!((nTriple < nLimit) && (nDouble < nLimit) && (nSingle < nLimit)))
533 return store_E_InvalidAccess;
535 // Truncate.
536 storeError eErrCode = store_E_None;
537 for (sal_uInt16 i = nLimit; i > nTriple + 1; i--)
539 // Truncate double indirect page to zero single indirect pages.
540 eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[i - 1]), 0, 0, rBIOS);
541 if (eErrCode != store_E_None)
542 return eErrCode;
544 // Clear pointer to double indirect page.
545 rPage.m_pData[i - 1] = STORE_PAGE_NULL;
546 touch();
549 // Truncate last double indirect page to 'nDouble', 'nSingle' pages.
550 eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[nTriple]), nDouble, nSingle, rBIOS);
551 if (eErrCode != store_E_None)
552 return eErrCode;
554 // Check for complete truncation.
555 if ((nDouble + nSingle) == 0)
557 // Clear pointer to last double indirect page.
558 rPage.m_pData[nTriple] = STORE_PAGE_NULL;
559 touch();
562 // Check for modified page.
563 if (dirty())
565 // Save this page.
566 eErrCode = rBIOS.saveObjectAt (*this, location());
569 // Done.
570 return eErrCode;
573 /*========================================================================
575 * OStoreDirectoryPageObject implementation.
577 *======================================================================*/
579 * guard.
581 storeError OStoreDirectoryPageObject::guard (sal_uInt32 nAddr)
583 return PageHolderObject< page >::guard (m_xPage, nAddr);
587 * verify.
589 storeError OStoreDirectoryPageObject::verify (sal_uInt32 nAddr) const
591 return PageHolderObject< page >::verify (m_xPage, nAddr);
592 // OLD: m_rPage.verifyVersion (STORE_MAGIC_DIRECTORYPAGE);
596 * scope (external data page; private).
598 OStoreDirectoryPageData::ChunkScope
599 OStoreDirectoryPageObject::scope (
600 sal_uInt32 nPage,
601 page::DataBlock::LinkDescriptor &rDescr) const
603 page const & rPage = PAGE();
604 OStoreDirectoryDataBlock const & rDataBlock = rPage.m_aDataBlock;
606 sal_uInt32 index0, index1, index2, index3;
608 // direct.
609 sal_uInt32 nCount = rDataBlock.directCount();
610 sal_uInt32 nLimit = nCount;
611 if (nPage < nLimit)
613 // Page to index reduction.
614 index0 = nPage;
616 // Setup LinkDescriptor indices.
617 rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff);
619 // Done.
620 return page::SCOPE_DIRECT;
622 nPage -= nLimit;
624 // single indirect.
625 sal_uInt32 const nCapacity = indirect::capacityCount(rPage.m_aDescr);
626 nCount = rDataBlock.singleCount();
627 nLimit = nCount * nCapacity;
628 if (nPage < nLimit)
630 // Page to index reduction.
631 sal_uInt32 n = nPage;
633 // Reduce to single indirect i(1), direct n = i(0).
634 index1 = n / nCapacity;
635 index0 = n % nCapacity;
637 // Verify reduction.
638 n = index1 * nCapacity + index0;
639 OSL_POSTCOND(n == nPage, "wrong math on indirect indices");
640 if (n != nPage)
641 return page::SCOPE_UNKNOWN;
643 // Setup LinkDescriptor indices.
644 rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff);
645 rDescr.m_nIndex1 = (sal_uInt16)(index1 & 0xffff);
647 // Done.
648 return page::SCOPE_SINGLE;
650 nPage -= nLimit;
652 // double indirect.
653 nCount = rDataBlock.doubleCount();
654 nLimit = nCount * nCapacity * nCapacity;
655 if (nPage < nLimit)
657 // Page to index reduction.
658 sal_uInt32 n = nPage;
660 // Reduce to double indirect i(2), single indirect n = i(0).
661 index2 = n / (nCapacity * nCapacity);
662 n = n % (nCapacity * nCapacity);
664 // Reduce to single indirect i(1), direct n = i(0).
665 index1 = n / nCapacity;
666 index0 = n % nCapacity;
668 // Verify reduction.
669 n = index2 * nCapacity * nCapacity +
670 index1 * nCapacity + index0;
671 OSL_POSTCOND(n == nPage, "wrong math on double indirect indices");
672 if (n != nPage)
673 return page::SCOPE_UNKNOWN;
675 // Setup LinkDescriptor indices.
676 rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff);
677 rDescr.m_nIndex1 = (sal_uInt16)(index1 & 0xffff);
678 rDescr.m_nIndex2 = (sal_uInt16)(index2 & 0xffff);
680 // Done.
681 return page::SCOPE_DOUBLE;
683 nPage -= nLimit;
685 // triple indirect.
686 nCount = rDataBlock.tripleCount();
687 nLimit = nCount * nCapacity * nCapacity * nCapacity;
688 if (nPage < nLimit)
690 // Page to index reduction.
691 sal_uInt32 n = nPage;
693 // Reduce to triple indirect i(3), double indirect n.
694 index3 = n / (nCapacity * nCapacity * nCapacity);
695 n = n % (nCapacity * nCapacity * nCapacity);
697 // Reduce to double indirect i(2), single indirect n.
698 index2 = n / (nCapacity * nCapacity);
699 n = n % (nCapacity * nCapacity);
701 // Reduce to single indirect i(1), direct n = i(0).
702 index1 = n / nCapacity;
703 index0 = n % nCapacity;
705 // Verify reduction.
706 n = index3 * nCapacity * nCapacity * nCapacity +
707 index2 * nCapacity * nCapacity +
708 index1 * nCapacity + index0;
709 OSL_POSTCOND(n == nPage, "wrong math on triple indirect indices");
710 if (n != nPage)
711 return page::SCOPE_UNKNOWN;
713 // Setup LinkDescriptor indices.
714 rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff);
715 rDescr.m_nIndex1 = (sal_uInt16)(index1 & 0xffff);
716 rDescr.m_nIndex2 = (sal_uInt16)(index2 & 0xffff);
717 rDescr.m_nIndex3 = (sal_uInt16)(index3 & 0xffff);
719 // Done.
720 return page::SCOPE_TRIPLE;
723 // Unreachable (more than triple indirect).
724 return page::SCOPE_UNREACHABLE;
728 * read (external data page).
730 storeError OStoreDirectoryPageObject::read (
731 sal_uInt32 nPage,
732 OStoreDataPageObject &rData,
733 OStorePageBIOS &rBIOS)
735 // Determine scope and link indices.
736 page::DataBlock::LinkDescriptor aLink;
737 page::ChunkScope eScope = scope (nPage, aLink);
739 storeError eErrCode = store_E_None;
740 if (eScope == page::SCOPE_DIRECT)
742 sal_uInt32 const nAddr = directLink (aLink.m_nIndex0);
743 if (nAddr == STORE_PAGE_NULL)
744 return store_E_NotExists;
746 eErrCode = rBIOS.loadObjectAt (rData, nAddr);
748 else if (eScope == page::SCOPE_SINGLE)
750 sal_uInt32 const nAddr = singleLink (aLink.m_nIndex1);
751 if (nAddr == STORE_PAGE_NULL)
752 return store_E_NotExists;
754 OStoreIndirectionPageObject aSingle;
755 eErrCode = rBIOS.loadObjectAt (aSingle, nAddr);
756 if (eErrCode != store_E_None)
757 return eErrCode;
759 eErrCode = aSingle.read (aLink.m_nIndex0, rData, rBIOS);
761 else if (eScope == page::SCOPE_DOUBLE)
763 sal_uInt32 const nAddr = doubleLink (aLink.m_nIndex2);
764 if (nAddr == STORE_PAGE_NULL)
765 return store_E_NotExists;
767 OStoreIndirectionPageObject aDouble;
768 eErrCode = rBIOS.loadObjectAt (aDouble, nAddr);
769 if (eErrCode != store_E_None)
770 return eErrCode;
772 eErrCode = aDouble.read (aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS);
774 else if (eScope == page::SCOPE_TRIPLE)
776 sal_uInt32 const nAddr = tripleLink (aLink.m_nIndex3);
777 if (nAddr == STORE_PAGE_NULL)
778 return store_E_NotExists;
780 OStoreIndirectionPageObject aTriple;
781 eErrCode = rBIOS.loadObjectAt (aTriple, nAddr);
782 if (eErrCode != store_E_None)
783 return eErrCode;
785 eErrCode = aTriple.read (aLink.m_nIndex2, aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS);
787 else if (eScope == page::SCOPE_UNREACHABLE)
789 // Out of scope.
790 eErrCode = store_E_CantSeek;
792 else
794 // Unknown scope.
795 OSL_TRACE("OStoreDirectoryPageObject::get(): scope failed");
796 eErrCode = store_E_Unknown;
799 // Leave.
800 return eErrCode;
804 * write (external data page).
806 storeError OStoreDirectoryPageObject::write (
807 sal_uInt32 nPage,
808 OStoreDataPageObject &rData,
809 OStorePageBIOS &rBIOS)
811 // Determine scope and link indices.
812 page::DataBlock::LinkDescriptor aLink;
813 page::ChunkScope eScope = scope (nPage, aLink);
815 storeError eErrCode = store_E_None;
816 if (eScope == page::SCOPE_DIRECT)
818 sal_uInt32 const nAddr = directLink (aLink.m_nIndex0);
819 if (nAddr == STORE_PAGE_NULL)
821 // Allocate data page.
822 eErrCode = rBIOS.allocate (rData);
823 if (eErrCode != store_E_None)
824 return eErrCode;
826 // Store data page location.
827 directLink (aLink.m_nIndex0, rData.location());
829 else
831 // Save data page.
832 eErrCode = rBIOS.saveObjectAt (rData, nAddr);
835 else if (eScope == page::SCOPE_SINGLE)
837 OStoreIndirectionPageObject aSingle;
838 eErrCode = aSingle.loadOrCreate (singleLink (aLink.m_nIndex1), rBIOS);
839 if (eErrCode != store_E_None)
841 if (eErrCode != store_E_Pending)
842 return eErrCode;
843 singleLink (aLink.m_nIndex1, aSingle.location());
846 eErrCode = aSingle.write (aLink.m_nIndex0, rData, rBIOS);
848 else if (eScope == page::SCOPE_DOUBLE)
850 OStoreIndirectionPageObject aDouble;
851 eErrCode = aDouble.loadOrCreate (doubleLink (aLink.m_nIndex2), rBIOS);
852 if (eErrCode != store_E_None)
854 if (eErrCode != store_E_Pending)
855 return eErrCode;
856 doubleLink (aLink.m_nIndex2, aDouble.location());
859 eErrCode = aDouble.write (aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS);
861 else if (eScope == page::SCOPE_TRIPLE)
863 OStoreIndirectionPageObject aTriple;
864 eErrCode = aTriple.loadOrCreate (tripleLink (aLink.m_nIndex3), rBIOS);
865 if (eErrCode != store_E_None)
867 if (eErrCode != store_E_Pending)
868 return eErrCode;
869 tripleLink (aLink.m_nIndex3, aTriple.location());
872 eErrCode = aTriple.write (aLink.m_nIndex2, aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS);
874 else if (eScope == page::SCOPE_UNREACHABLE)
876 // Out of scope.
877 eErrCode = store_E_CantSeek;
879 else
881 // Unknown scope.
882 OSL_TRACE("OStoreDirectoryPageObject::put(): scope failed");
883 eErrCode = store_E_Unknown;
886 // Leave.
887 return eErrCode;
891 * truncate (external data page).
893 storeError OStoreDirectoryPageObject::truncate (
894 sal_uInt32 nPage,
895 OStorePageBIOS &rBIOS)
897 // Determine scope and link indices.
898 page::DataBlock::LinkDescriptor aLink;
899 page::ChunkScope eScope = scope (nPage, aLink);
901 storeError eErrCode = store_E_None;
902 if (eScope == page::SCOPE_DIRECT)
904 // Truncate all triple indirect pages.
905 eErrCode = truncate (page::SCOPE_TRIPLE, 0, rBIOS);
906 if (eErrCode != store_E_None)
907 return eErrCode;
909 // Truncate all double indirect pages.
910 eErrCode = truncate (page::SCOPE_DOUBLE, 0, rBIOS);
911 if (eErrCode != store_E_None)
912 return eErrCode;
914 // Truncate all single indirect pages.
915 eErrCode = truncate (page::SCOPE_SINGLE, 0, rBIOS);
916 if (eErrCode != store_E_None)
917 return eErrCode;
919 // Truncate direct pages, including 'aLink.m_nIndex0'.
920 eErrCode = truncate (eScope, aLink.m_nIndex0, rBIOS);
922 else if (eScope == page::SCOPE_SINGLE)
924 // Truncate all triple indirect pages.
925 eErrCode = truncate (page::SCOPE_TRIPLE, 0, rBIOS);
926 if (eErrCode != store_E_None)
927 return eErrCode;
929 // Truncate all double indirect pages.
930 eErrCode = truncate (page::SCOPE_DOUBLE, 0, rBIOS);
931 if (eErrCode != store_E_None)
932 return eErrCode;
934 // Truncate single indirect pages, downto 'aLink.m_nIndex1'.
935 eErrCode = truncate (eScope, aLink.m_nIndex1 + 1, rBIOS);
936 if (eErrCode != store_E_None)
937 return eErrCode;
939 // Truncate last single indirect page to ... pages.
940 eErrCode = store_truncate_Impl (singleLink (aLink.m_nIndex1), aLink.m_nIndex0, rBIOS);
941 if (eErrCode != store_E_None)
942 return eErrCode;
944 // Check for complete truncation.
945 if (aLink.m_nIndex0 == 0)
947 // Clear pointer to last single indirect page.
948 singleLink (aLink.m_nIndex1, STORE_PAGE_NULL);
951 else if (eScope == page::SCOPE_DOUBLE)
953 // Truncate all triple indirect pages.
954 eErrCode = truncate (page::SCOPE_TRIPLE, 0, rBIOS);
955 if (eErrCode != store_E_None)
956 return eErrCode;
958 // Truncate double indirect pages, downto 'aLink.m_nIndex2'.
959 eErrCode = truncate (eScope, aLink.m_nIndex2 + 1, rBIOS);
960 if (eErrCode != store_E_None)
961 return eErrCode;
963 // Truncate last double indirect page to ... pages.
964 eErrCode = store_truncate_Impl (
965 doubleLink (aLink.m_nIndex2), aLink.m_nIndex1, aLink.m_nIndex0, rBIOS);
966 if (eErrCode != store_E_None)
967 return eErrCode;
969 // Check for complete truncation.
970 if ((aLink.m_nIndex1 + aLink.m_nIndex0) == 0)
972 // Clear pointer to last double indirect page.
973 doubleLink (aLink.m_nIndex2, STORE_PAGE_NULL);
976 else if (eScope == page::SCOPE_TRIPLE)
978 // Truncate triple indirect pages, downto 'aLink.m_nIndex3'.
979 eErrCode = truncate (eScope, aLink.m_nIndex3 + 1, rBIOS);
980 if (eErrCode != store_E_None)
981 return eErrCode;
983 // Truncate last triple indirect page to ... pages.
984 eErrCode = store_truncate_Impl (
985 tripleLink (aLink.m_nIndex3), aLink.m_nIndex2, aLink.m_nIndex1, aLink.m_nIndex0, rBIOS);
986 if (eErrCode != store_E_None)
987 return eErrCode;
989 // Check for complete truncation.
990 if ((aLink.m_nIndex2 + aLink.m_nIndex1 + aLink.m_nIndex0) == 0)
992 // Clear pointer to last triple indirect page.
993 tripleLink (aLink.m_nIndex3, STORE_PAGE_NULL);
996 else if (eScope == page::SCOPE_UNREACHABLE)
998 // Out of scope.
999 eErrCode = store_E_CantSeek;
1001 else
1003 // Unknown scope.
1004 OSL_TRACE("OStoreDirectoryPageObject::put(): scope failed");
1005 eErrCode = store_E_Unknown;
1008 // Leave.
1009 return eErrCode;
1013 * truncate (external data page scope; private).
1015 storeError OStoreDirectoryPageObject::truncate (
1016 page::ChunkScope eScope,
1017 sal_uInt16 nRemain,
1018 OStorePageBIOS &rBIOS)
1020 OStoreDirectoryDataBlock const & rDataBlock = PAGE().m_aDataBlock;
1022 // Enter.
1023 storeError eErrCode = store_E_None;
1024 if (eScope == page::SCOPE_DIRECT)
1026 // Truncate direct data pages.
1027 sal_uInt16 i, n = rDataBlock.directCount();
1028 for (i = n; i > nRemain; i--)
1030 // Obtain data page location.
1031 sal_uInt32 nAddr = directLink (i - 1);
1032 if (nAddr == STORE_PAGE_NULL) continue;
1034 // Free data page.
1035 eErrCode = rBIOS.free (nAddr);
1036 if (eErrCode != store_E_None)
1037 break;
1039 // Clear pointer to data page.
1040 directLink (i - 1, STORE_PAGE_NULL);
1043 // Done.
1044 return eErrCode;
1047 if (eScope == page::SCOPE_SINGLE)
1049 // Truncate single indirect pages.
1050 sal_uInt16 i, n = rDataBlock.singleCount();
1051 for (i = n; i > nRemain; i--)
1053 // Truncate single indirect page to zero data pages.
1054 eErrCode = store_truncate_Impl (singleLink (i - 1), 0, rBIOS);
1055 if (eErrCode != store_E_None)
1056 break;
1058 // Clear pointer to single indirect page.
1059 singleLink (i - 1, STORE_PAGE_NULL);
1062 // Done.
1063 return eErrCode;
1066 if (eScope == page::SCOPE_DOUBLE)
1068 // Truncate double indirect pages.
1069 sal_uInt16 i, n = rDataBlock.doubleCount();
1070 for (i = n; i > nRemain; i--)
1072 // Truncate double indirect page to zero single indirect pages.
1073 eErrCode = store_truncate_Impl (doubleLink (i - 1), 0, 0, rBIOS);
1074 if (eErrCode != store_E_None)
1075 break;
1077 // Clear pointer to double indirect page.
1078 doubleLink (i - 1, STORE_PAGE_NULL);
1081 // Done.
1082 return eErrCode;
1085 if (eScope == page::SCOPE_TRIPLE)
1087 // Truncate triple indirect pages.
1088 sal_uInt16 i, n = rDataBlock.tripleCount();
1089 for (i = n; i > nRemain; i--)
1091 // Truncate to zero double indirect pages.
1092 eErrCode = store_truncate_Impl (tripleLink (i - 1), 0, 0, 0, rBIOS);
1093 if (eErrCode != store_E_None)
1094 break;
1096 // Clear pointer to triple indirect page.
1097 tripleLink (i - 1, STORE_PAGE_NULL);
1100 // Done.
1101 return eErrCode;
1104 // Invalid scope.
1105 return store_E_InvalidAccess;
1108 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */