update dev300-m58
[ooovba.git] / store / source / stordata.cxx
blob8f3761620302d48af9496f2001e3a69d2f0639c7
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: stordata.cxx,v $
10 * $Revision: 1.6 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_store.hxx"
34 #include "stordata.hxx"
36 #include "sal/types.h"
37 #include "osl/diagnose.h"
39 #include "store/types.h"
40 #include "storbase.hxx"
41 #include "storbios.hxx"
43 using namespace store;
45 /*========================================================================
47 * OStoreDataPageObject implementation.
49 *======================================================================*/
51 * guard.
53 storeError OStoreDataPageObject::guard (sal_uInt32 nAddr)
55 return PageHolderObject< page >::guard (m_xPage, nAddr);
59 * verify.
61 storeError OStoreDataPageObject::verify (sal_uInt32 nAddr) const
63 return PageHolderObject< page >::verify (m_xPage, nAddr);
66 /*========================================================================
68 * OStoreIndirectionPageObject implementation.
70 *======================================================================*/
72 * store_truncate_Impl (single indirect page).
74 static storeError store_truncate_Impl (
75 sal_uInt32 nAddr,
76 sal_uInt16 nSingle,
77 OStorePageBIOS &rBIOS)
79 if (nAddr != STORE_PAGE_NULL)
81 // Load single indirect page.
82 OStoreIndirectionPageObject aSingle;
83 storeError eErrCode = rBIOS.loadObjectAt (aSingle, nAddr);
84 if (eErrCode == store_E_None)
86 // Truncate to 'nSingle' direct pages.
87 eErrCode = aSingle.truncate (nSingle, rBIOS);
88 if (eErrCode != store_E_None)
89 return eErrCode;
91 else
93 if (eErrCode != store_E_InvalidChecksum)
94 return eErrCode;
97 // Check for complete truncation.
98 if (nSingle == 0)
100 // Free single indirect page.
101 OStorePageData aPageHead;
102 eErrCode = rBIOS.free (aPageHead, nAddr);
103 if (eErrCode != store_E_None)
104 return eErrCode;
107 return store_E_None;
111 * store_truncate_Impl (double indirect page).
113 static storeError store_truncate_Impl (
114 sal_uInt32 nAddr,
115 sal_uInt16 nDouble,
116 sal_uInt16 nSingle,
117 OStorePageBIOS &rBIOS)
119 if (nAddr != STORE_PAGE_NULL)
121 // Load double indirect page.
122 OStoreIndirectionPageObject aDouble;
123 storeError eErrCode = rBIOS.loadObjectAt (aDouble, nAddr);
124 if (eErrCode == store_E_None)
126 // Truncate to 'nDouble', 'nSingle' pages.
127 eErrCode = aDouble.truncate (nDouble, nSingle, rBIOS);
128 if (eErrCode != store_E_None)
129 return eErrCode;
131 else
133 if (eErrCode != store_E_InvalidChecksum)
134 return eErrCode;
137 // Check for complete truncation.
138 if ((nDouble + nSingle) == 0)
140 // Free double indirect page.
141 OStorePageData aPageHead;
142 eErrCode = rBIOS.free (aPageHead, nAddr);
143 if (eErrCode != store_E_None)
144 return eErrCode;
147 return store_E_None;
151 * store_truncate_Impl (triple indirect page).
153 static storeError store_truncate_Impl (
154 sal_uInt32 nAddr,
155 sal_uInt16 nTriple,
156 sal_uInt16 nDouble,
157 sal_uInt16 nSingle,
158 OStorePageBIOS &rBIOS)
160 if (nAddr != STORE_PAGE_NULL)
162 // Load triple indirect page.
163 OStoreIndirectionPageObject aTriple;
164 storeError eErrCode = rBIOS.loadObjectAt (aTriple, nAddr);
165 if (eErrCode != store_E_None)
166 return eErrCode;
168 // Truncate to 'nTriple', 'nDouble', 'nSingle' pages.
169 eErrCode = aTriple.truncate (nTriple, nDouble, nSingle, rBIOS);
170 if (eErrCode != store_E_None)
171 return eErrCode;
173 // Check for complete truncation.
174 if ((nTriple + nDouble + nSingle) == 0)
176 // Free triple indirect page.
177 OStorePageData aPageHead;
178 eErrCode = rBIOS.free (aPageHead, nAddr);
179 if (eErrCode != store_E_None)
180 return eErrCode;
183 return store_E_None;
187 * loadOrCreate.
189 storeError OStoreIndirectionPageObject::loadOrCreate (
190 sal_uInt32 nAddr,
191 OStorePageBIOS & rBIOS)
193 if (nAddr == STORE_PAGE_NULL)
195 storeError eErrCode = construct<page>(rBIOS.allocator());
196 if (eErrCode != store_E_None)
197 return eErrCode;
199 eErrCode = rBIOS.allocate (*this);
200 if (eErrCode != store_E_None)
201 return eErrCode;
203 // Save location pending at caller.
204 return store_E_Pending;
206 return rBIOS.loadObjectAt (*this, nAddr);
210 * guard.
212 storeError OStoreIndirectionPageObject::guard (sal_uInt32 nAddr)
214 return PageHolderObject< page >::guard (m_xPage, nAddr);
218 * verify.
220 storeError OStoreIndirectionPageObject::verify (sal_uInt32 nAddr) const
222 return PageHolderObject< page >::verify (m_xPage, nAddr);
226 * read (single indirect).
228 storeError OStoreIndirectionPageObject::read (
229 sal_uInt16 nSingle,
230 OStoreDataPageObject &rData,
231 OStorePageBIOS &rBIOS)
233 PageHolderObject< page > xImpl (m_xPage);
234 page const & rPage = (*xImpl);
236 // Check arguments.
237 sal_uInt16 const nLimit = rPage.capacityCount();
238 if (!(nSingle < nLimit))
239 return store_E_InvalidAccess;
241 // Obtain data page location.
242 sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nSingle]);
243 if (nAddr == STORE_PAGE_NULL)
244 return store_E_NotExists;
246 // Load data page and leave.
247 return rBIOS.loadObjectAt (rData, nAddr);
251 * read (double indirect).
253 storeError OStoreIndirectionPageObject::read (
254 sal_uInt16 nDouble,
255 sal_uInt16 nSingle,
256 OStoreDataPageObject &rData,
257 OStorePageBIOS &rBIOS)
259 PageHolderObject< page > xImpl (m_xPage);
260 page const & rPage = (*xImpl);
262 // Check arguments.
263 sal_uInt16 const nLimit = rPage.capacityCount();
264 if (!((nDouble < nLimit) && (nSingle < nLimit)))
265 return store_E_InvalidAccess;
267 // Check single indirect page location.
268 sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nDouble]);
269 if (nAddr == STORE_PAGE_NULL)
270 return store_E_NotExists;
272 // Load single indirect page.
273 OStoreIndirectionPageObject aSingle;
274 storeError eErrCode = rBIOS.loadObjectAt (aSingle, nAddr);
275 if (eErrCode != store_E_None)
276 return eErrCode;
278 // Read single indirect and leave.
279 return aSingle.read (nSingle, rData, rBIOS);
283 * read (triple indirect).
285 storeError OStoreIndirectionPageObject::read (
286 sal_uInt16 nTriple,
287 sal_uInt16 nDouble,
288 sal_uInt16 nSingle,
289 OStoreDataPageObject &rData,
290 OStorePageBIOS &rBIOS)
292 PageHolderObject< page > xImpl (m_xPage);
293 page const & rPage = (*xImpl);
295 // Check arguments.
296 sal_uInt16 const nLimit = rPage.capacityCount();
297 if (!((nTriple < nLimit) && (nDouble < nLimit) && (nSingle < nLimit)))
298 return store_E_InvalidAccess;
300 // Check double indirect page location.
301 sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nTriple]);
302 if (nAddr == STORE_PAGE_NULL)
303 return store_E_NotExists;
305 // Load double indirect page.
306 OStoreIndirectionPageObject aDouble;
307 storeError eErrCode = rBIOS.loadObjectAt (aDouble, nAddr);
308 if (eErrCode != store_E_None)
309 return eErrCode;
311 // Read double indirect and leave.
312 return aDouble.read (nDouble, nSingle, rData, rBIOS);
316 * write (single indirect).
318 storeError OStoreIndirectionPageObject::write (
319 sal_uInt16 nSingle,
320 OStoreDataPageObject &rData,
321 OStorePageBIOS &rBIOS)
323 PageHolderObject< page > xImpl (m_xPage);
324 page & rPage = (*xImpl);
326 // Check arguments.
327 sal_uInt16 const nLimit = rPage.capacityCount();
328 if (!(nSingle < nLimit))
329 return store_E_InvalidAccess;
331 // Obtain data page location.
332 sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nSingle]);
333 if (nAddr == STORE_PAGE_NULL)
335 // Allocate data page.
336 storeError eErrCode = rBIOS.allocate (rData);
337 if (eErrCode != store_E_None)
338 return eErrCode;
340 // Store data page location.
341 rPage.m_pData[nSingle] = store::htonl(rData.location());
343 // Save this page.
344 return rBIOS.saveObjectAt (*this, location());
346 else
348 // Save data page.
349 return rBIOS.saveObjectAt (rData, nAddr);
354 * write (double indirect).
356 storeError OStoreIndirectionPageObject::write (
357 sal_uInt16 nDouble,
358 sal_uInt16 nSingle,
359 OStoreDataPageObject &rData,
360 OStorePageBIOS &rBIOS)
362 PageHolderObject< page > xImpl (m_xPage);
363 page & rPage = (*xImpl);
365 // Check arguments.
366 sal_uInt16 const nLimit = rPage.capacityCount();
367 if (!((nDouble < nLimit) && (nSingle < nLimit)))
368 return store_E_InvalidAccess;
370 // Load or create single indirect page.
371 OStoreIndirectionPageObject aSingle;
372 storeError eErrCode = aSingle.loadOrCreate (store::ntohl(rPage.m_pData[nDouble]), rBIOS);
373 if (eErrCode != store_E_None)
375 if (eErrCode != store_E_Pending)
376 return eErrCode;
377 rPage.m_pData[nDouble] = store::htonl(aSingle.location());
379 eErrCode = rBIOS.saveObjectAt (*this, location());
380 if (eErrCode != store_E_None)
381 return eErrCode;
384 // Write single indirect and leave.
385 return aSingle.write (nSingle, rData, rBIOS);
389 * write (triple indirect).
391 storeError OStoreIndirectionPageObject::write (
392 sal_uInt16 nTriple,
393 sal_uInt16 nDouble,
394 sal_uInt16 nSingle,
395 OStoreDataPageObject &rData,
396 OStorePageBIOS &rBIOS)
398 PageHolderObject< page > xImpl (m_xPage);
399 page & rPage = (*xImpl);
401 // Check arguments.
402 sal_uInt16 const nLimit = rPage.capacityCount();
403 if (!((nTriple < nLimit) && (nDouble < nLimit) && (nSingle < nLimit)))
404 return store_E_InvalidAccess;
406 // Load or create double indirect page.
407 OStoreIndirectionPageObject aDouble;
408 storeError eErrCode = aDouble.loadOrCreate (store::ntohl(rPage.m_pData[nTriple]), rBIOS);
409 if (eErrCode != store_E_None)
411 if (eErrCode != store_E_Pending)
412 return eErrCode;
413 rPage.m_pData[nTriple] = store::htonl(aDouble.location());
415 eErrCode = rBIOS.saveObjectAt (*this, location());
416 if (eErrCode != store_E_None)
417 return eErrCode;
420 // Write double indirect and leave.
421 return aDouble.write (nDouble, nSingle, rData, rBIOS);
425 * truncate (single indirect).
427 storeError OStoreIndirectionPageObject::truncate (
428 sal_uInt16 nSingle,
429 OStorePageBIOS & rBIOS)
431 PageHolderObject< page > xImpl (m_xPage);
432 page & rPage = (*xImpl);
434 // Check arguments.
435 sal_uInt16 const nLimit = rPage.capacityCount();
436 if (!(nSingle < nLimit))
437 return store_E_InvalidAccess;
439 // Save PageDescriptor.
440 OStorePageDescriptor aDescr (rPage.m_aDescr);
441 aDescr.m_nAddr = store::ntohl(aDescr.m_nAddr);
442 aDescr.m_nSize = store::ntohs(aDescr.m_nSize);
444 // Acquire Lock.
445 storeError eErrCode = rBIOS.acquireLock (aDescr.m_nAddr, aDescr.m_nSize);
446 if (eErrCode != store_E_None)
447 return eErrCode;
449 // Truncate.
450 for (sal_uInt16 i = nLimit; i > nSingle; i--)
452 // Obtain data page location.
453 sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[i - 1]);
454 if (nAddr != STORE_PAGE_NULL)
456 // Free data page.
457 OStorePageData aPageHead;
458 eErrCode = rBIOS.free (aPageHead, nAddr);
459 if (eErrCode != store_E_None)
461 rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize);
462 return eErrCode;
465 // Clear pointer to data page.
466 rPage.m_pData[i - 1] = STORE_PAGE_NULL;
467 touch();
471 // Check for modified page.
472 if (dirty())
474 // Save this page.
475 eErrCode = rBIOS.saveObjectAt (*this, location());
476 if (eErrCode != store_E_None)
478 // Must not happen.
479 OSL_TRACE("OStoreIndirectionPageObject::truncate(): save failed");
481 // Release Lock and Leave.
482 rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize);
483 return eErrCode;
487 // Release Lock and Leave.
488 return rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize);
492 * truncate (double indirect).
494 storeError OStoreIndirectionPageObject::truncate (
495 sal_uInt16 nDouble,
496 sal_uInt16 nSingle,
497 OStorePageBIOS &rBIOS)
499 PageHolderObject< page > xImpl (m_xPage);
500 page & rPage = (*xImpl);
502 // Check arguments.
503 sal_uInt16 const nLimit = rPage.capacityCount();
504 if (!((nDouble < nLimit) && (nSingle < nLimit)))
505 return store_E_InvalidAccess;
507 // Save PageDescriptor.
508 OStorePageDescriptor aDescr (rPage.m_aDescr);
509 aDescr.m_nAddr = store::ntohl(aDescr.m_nAddr);
510 aDescr.m_nSize = store::ntohs(aDescr.m_nSize);
512 // Acquire Lock.
513 storeError eErrCode = rBIOS.acquireLock (aDescr.m_nAddr, aDescr.m_nSize);
514 if (eErrCode != store_E_None)
515 return eErrCode;
517 // Truncate.
518 for (sal_uInt16 i = nLimit; i > nDouble + 1; i--)
520 // Truncate single indirect page to zero direct pages.
521 eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[i - 1]), 0, rBIOS);
522 if (eErrCode != store_E_None)
524 rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize);
525 return eErrCode;
528 // Clear pointer to single indirect page.
529 rPage.m_pData[i - 1] = STORE_PAGE_NULL;
530 touch();
533 // Truncate last single indirect page to 'nSingle' direct pages.
534 eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[nDouble]), nSingle, rBIOS);
535 if (eErrCode != store_E_None)
537 rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize);
538 return eErrCode;
541 // Check for complete truncation.
542 if (nSingle == 0)
544 // Clear pointer to last single indirect page.
545 rPage.m_pData[nDouble] = STORE_PAGE_NULL;
546 touch();
549 // Check for modified page.
550 if (dirty())
552 // Save this page.
553 eErrCode = rBIOS.saveObjectAt (*this, location());
554 if (eErrCode != store_E_None)
556 // Must not happen.
557 OSL_TRACE("OStoreIndirectionPageObject::truncate(): save failed");
559 // Release Lock and Leave.
560 rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize);
561 return eErrCode;
565 // Release Lock and Leave.
566 return rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize);
570 * truncate (triple indirect).
572 storeError OStoreIndirectionPageObject::truncate (
573 sal_uInt16 nTriple,
574 sal_uInt16 nDouble,
575 sal_uInt16 nSingle,
576 OStorePageBIOS &rBIOS)
578 PageHolderObject< page > xImpl (m_xPage);
579 page & rPage = (*xImpl);
581 // Check arguments.
582 sal_uInt16 const nLimit = rPage.capacityCount();
583 if (!((nTriple < nLimit) && (nDouble < nLimit) && (nSingle < nLimit)))
584 return store_E_InvalidAccess;
586 // Save PageDescriptor.
587 OStorePageDescriptor aDescr (rPage.m_aDescr);
588 aDescr.m_nAddr = store::ntohl(aDescr.m_nAddr);
589 aDescr.m_nSize = store::ntohs(aDescr.m_nSize);
591 // Acquire Lock.
592 storeError eErrCode = rBIOS.acquireLock (aDescr.m_nAddr, aDescr.m_nSize);
593 if (eErrCode != store_E_None)
594 return eErrCode;
596 // Truncate.
597 for (sal_uInt16 i = nLimit; i > nTriple + 1; i--)
599 // Truncate double indirect page to zero single indirect pages.
600 eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[i - 1]), 0, 0, rBIOS);
601 if (eErrCode != store_E_None)
603 rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize);
604 return eErrCode;
607 // Clear pointer to double indirect page.
608 rPage.m_pData[i - 1] = STORE_PAGE_NULL;
609 touch();
612 // Truncate last double indirect page to 'nDouble', 'nSingle' pages.
613 eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[nTriple]), nDouble, nSingle, rBIOS);
614 if (eErrCode != store_E_None)
616 rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize);
617 return eErrCode;
620 // Check for complete truncation.
621 if ((nDouble + nSingle) == 0)
623 // Clear pointer to last double indirect page.
624 rPage.m_pData[nTriple] = STORE_PAGE_NULL;
625 touch();
628 // Check for modified page.
629 if (dirty())
631 // Save this page.
632 eErrCode = rBIOS.saveObjectAt (*this, location());
633 if (eErrCode != store_E_None)
635 // Must not happen.
636 OSL_TRACE("OStoreIndirectionPageObject::truncate(): save failed");
638 // Release Lock and Leave.
639 rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize);
640 return eErrCode;
644 // Release Lock and Leave.
645 return rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize);
648 /*========================================================================
650 * OStoreDirectoryPageObject implementation.
652 *======================================================================*/
654 * guard.
656 storeError OStoreDirectoryPageObject::guard (sal_uInt32 nAddr)
658 return PageHolderObject< page >::guard (m_xPage, nAddr);
662 * verify.
664 storeError OStoreDirectoryPageObject::verify (sal_uInt32 nAddr) const
666 return PageHolderObject< page >::verify (m_xPage, nAddr);
667 // OLD: m_rPage.verifyVersion (STORE_MAGIC_DIRECTORYPAGE);
671 * scope (external data page; private).
673 OStoreDirectoryPageData::ChunkScope
674 OStoreDirectoryPageObject::scope (
675 sal_uInt32 nPage,
676 page::DataBlock::LinkDescriptor &rDescr) const
678 page const & rPage = PAGE();
679 OStoreDirectoryDataBlock const & rDataBlock = rPage.m_aDataBlock;
681 sal_uInt32 index0, index1, index2, index3;
683 // direct.
684 sal_uInt32 nCount = rDataBlock.directCount();
685 sal_uInt32 nLimit = nCount;
686 if (nPage < nLimit)
688 // Page to index reduction.
689 index0 = nPage;
691 // Setup LinkDescriptor indices.
692 rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff);
694 // Done.
695 return page::SCOPE_DIRECT;
697 nPage -= nLimit;
699 // single indirect.
700 sal_uInt32 const nCapacity = indirect::capacityCount(rPage.m_aDescr);
701 nCount = rDataBlock.singleCount();
702 nLimit = nCount * nCapacity;
703 if (nPage < nLimit)
705 // Page to index reduction.
706 sal_uInt32 n = nPage;
708 // Reduce to single indirect i(1), direct n = i(0).
709 index1 = n / nCapacity;
710 index0 = n % nCapacity;
712 // Verify reduction.
713 n = index1 * nCapacity + index0;
714 OSL_POSTCOND(n == nPage, "wrong math on indirect indices");
715 if (n != nPage)
716 return page::SCOPE_UNKNOWN;
718 // Setup LinkDescriptor indices.
719 rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff);
720 rDescr.m_nIndex1 = (sal_uInt16)(index1 & 0xffff);
722 // Done.
723 return page::SCOPE_SINGLE;
725 nPage -= nLimit;
727 // double indirect.
728 nCount = rDataBlock.doubleCount();
729 nLimit = nCount * nCapacity * nCapacity;
730 if (nPage < nLimit)
732 // Page to index reduction.
733 sal_uInt32 n = nPage;
735 // Reduce to double indirect i(2), single indirect n = i(0).
736 index2 = n / (nCapacity * nCapacity);
737 n = n % (nCapacity * nCapacity);
739 // Reduce to single indirect i(1), direct n = i(0).
740 index1 = n / nCapacity;
741 index0 = n % nCapacity;
743 // Verify reduction.
744 n = index2 * nCapacity * nCapacity +
745 index1 * nCapacity + index0;
746 OSL_POSTCOND(n == nPage, "wrong math on double indirect indices");
747 if (n != nPage)
748 return page::SCOPE_UNKNOWN;
750 // Setup LinkDescriptor indices.
751 rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff);
752 rDescr.m_nIndex1 = (sal_uInt16)(index1 & 0xffff);
753 rDescr.m_nIndex2 = (sal_uInt16)(index2 & 0xffff);
755 // Done.
756 return page::SCOPE_DOUBLE;
758 nPage -= nLimit;
760 // triple indirect.
761 nCount = rDataBlock.tripleCount();
762 nLimit = nCount * nCapacity * nCapacity * nCapacity;
763 if (nPage < nLimit)
765 // Page to index reduction.
766 sal_uInt32 n = nPage;
768 // Reduce to triple indirect i(3), double indirect n.
769 index3 = n / (nCapacity * nCapacity * nCapacity);
770 n = n % (nCapacity * nCapacity * nCapacity);
772 // Reduce to double indirect i(2), single indirect n.
773 index2 = n / (nCapacity * nCapacity);
774 n = n % (nCapacity * nCapacity);
776 // Reduce to single indirect i(1), direct n = i(0).
777 index1 = n / nCapacity;
778 index0 = n % nCapacity;
780 // Verify reduction.
781 n = index3 * nCapacity * nCapacity * nCapacity +
782 index2 * nCapacity * nCapacity +
783 index1 * nCapacity + index0;
784 OSL_POSTCOND(n == nPage, "wrong math on triple indirect indices");
785 if (n != nPage)
786 return page::SCOPE_UNKNOWN;
788 // Setup LinkDescriptor indices.
789 rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff);
790 rDescr.m_nIndex1 = (sal_uInt16)(index1 & 0xffff);
791 rDescr.m_nIndex2 = (sal_uInt16)(index2 & 0xffff);
792 rDescr.m_nIndex3 = (sal_uInt16)(index3 & 0xffff);
794 // Done.
795 return page::SCOPE_TRIPLE;
798 // Unreachable (more than triple indirect).
799 return page::SCOPE_UNREACHABLE;
802 #if 0 /* NYI */
804 * chunk (external data page).
806 inode::ChunkDescriptor OStoreDirectoryPageObject::chunk (sal_uInt32 nOffset)
808 // @@@ INSUFFICIENT: NEED SCOPE AS WELL @@@
809 sal_uInt32 nCapacity = m_rPage.capacity();
810 if (nOffset < nCapacity)
811 // Internal scope (inode page).
812 return inode::ChunkDescriptor (nOffset, nCapacity);
813 else
814 // External scope (data page).
815 return inode::ChunkDescriptor (nOffset - nCapacity, data::capacity(m_rPage.m_aDescr));
817 inode::ChunkScope eScope = m_rPage.scope(nOffset);
818 if (eScope == inode::SCOPE_INTERNAL)
819 // Inode page (internal scope).
820 return inode::ChunkDescriptor (nOffset, m_rPage.capacity());
821 else
822 // Data page (external scope).
823 return inode::ChunkDescriptor (nOffset - m_rPage.capacity(), data::capacity(m_rPage.m_aDescr));
825 #endif /* NYI */
828 * read (external data page).
830 storeError OStoreDirectoryPageObject::read (
831 sal_uInt32 nPage,
832 OStoreDataPageObject &rData,
833 OStorePageBIOS &rBIOS)
835 // Determine scope and link indices.
836 page::DataBlock::LinkDescriptor aLink;
837 page::ChunkScope eScope = scope (nPage, aLink);
839 storeError eErrCode = store_E_None;
840 if (eScope == page::SCOPE_DIRECT)
842 sal_uInt32 const nAddr = directLink (aLink.m_nIndex0);
843 if (nAddr == STORE_PAGE_NULL)
844 return store_E_NotExists;
846 eErrCode = rBIOS.loadObjectAt (rData, nAddr);
848 else if (eScope == page::SCOPE_SINGLE)
850 sal_uInt32 const nAddr = singleLink (aLink.m_nIndex1);
851 if (nAddr == STORE_PAGE_NULL)
852 return store_E_NotExists;
854 OStoreIndirectionPageObject aSingle;
855 eErrCode = rBIOS.loadObjectAt (aSingle, nAddr);
856 if (eErrCode != store_E_None)
857 return eErrCode;
859 eErrCode = aSingle.read (aLink.m_nIndex0, rData, rBIOS);
861 else if (eScope == page::SCOPE_DOUBLE)
863 sal_uInt32 const nAddr = doubleLink (aLink.m_nIndex2);
864 if (nAddr == STORE_PAGE_NULL)
865 return store_E_NotExists;
867 OStoreIndirectionPageObject aDouble;
868 eErrCode = rBIOS.loadObjectAt (aDouble, nAddr);
869 if (eErrCode != store_E_None)
870 return eErrCode;
872 eErrCode = aDouble.read (aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS);
874 else if (eScope == page::SCOPE_TRIPLE)
876 sal_uInt32 const nAddr = tripleLink (aLink.m_nIndex3);
877 if (nAddr == STORE_PAGE_NULL)
878 return store_E_NotExists;
880 OStoreIndirectionPageObject aTriple;
881 eErrCode = rBIOS.loadObjectAt (aTriple, nAddr);
882 if (eErrCode != store_E_None)
883 return eErrCode;
885 eErrCode = aTriple.read (aLink.m_nIndex2, aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS);
887 else if (eScope == page::SCOPE_UNREACHABLE)
889 // Out of scope.
890 eErrCode = store_E_CantSeek;
892 else
894 // Unknown scope.
895 OSL_TRACE("OStoreDirectoryPageObject::get(): scope failed");
896 eErrCode = store_E_Unknown;
899 // Leave.
900 return eErrCode;
904 * write (external data page).
906 storeError OStoreDirectoryPageObject::write (
907 sal_uInt32 nPage,
908 OStoreDataPageObject &rData,
909 OStorePageBIOS &rBIOS)
911 // Determine scope and link indices.
912 page::DataBlock::LinkDescriptor aLink;
913 page::ChunkScope eScope = scope (nPage, aLink);
915 storeError eErrCode = store_E_None;
916 if (eScope == page::SCOPE_DIRECT)
918 sal_uInt32 const nAddr = directLink (aLink.m_nIndex0);
919 if (nAddr == STORE_PAGE_NULL)
921 // Allocate data page.
922 eErrCode = rBIOS.allocate (rData);
923 if (eErrCode != store_E_None)
924 return eErrCode;
926 // Store data page location.
927 directLink (aLink.m_nIndex0, rData.location());
929 else
931 // Save data page.
932 eErrCode = rBIOS.saveObjectAt (rData, nAddr);
935 else if (eScope == page::SCOPE_SINGLE)
937 OStoreIndirectionPageObject aSingle;
938 eErrCode = aSingle.loadOrCreate (singleLink (aLink.m_nIndex1), rBIOS);
939 if (eErrCode != store_E_None)
941 if (eErrCode != store_E_Pending)
942 return eErrCode;
943 singleLink (aLink.m_nIndex1, aSingle.location());
946 eErrCode = aSingle.write (aLink.m_nIndex0, rData, rBIOS);
948 else if (eScope == page::SCOPE_DOUBLE)
950 OStoreIndirectionPageObject aDouble;
951 eErrCode = aDouble.loadOrCreate (doubleLink (aLink.m_nIndex2), rBIOS);
952 if (eErrCode != store_E_None)
954 if (eErrCode != store_E_Pending)
955 return eErrCode;
956 doubleLink (aLink.m_nIndex2, aDouble.location());
959 eErrCode = aDouble.write (aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS);
961 else if (eScope == page::SCOPE_TRIPLE)
963 OStoreIndirectionPageObject aTriple;
964 eErrCode = aTriple.loadOrCreate (tripleLink (aLink.m_nIndex3), rBIOS);
965 if (eErrCode != store_E_None)
967 if (eErrCode != store_E_Pending)
968 return eErrCode;
969 tripleLink (aLink.m_nIndex3, aTriple.location());
972 eErrCode = aTriple.write (aLink.m_nIndex2, aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS);
974 else if (eScope == page::SCOPE_UNREACHABLE)
976 // Out of scope.
977 eErrCode = store_E_CantSeek;
979 else
981 // Unknown scope.
982 OSL_TRACE("OStoreDirectoryPageObject::put(): scope failed");
983 eErrCode = store_E_Unknown;
986 // Leave.
987 return eErrCode;
991 * truncate (external data page).
993 storeError OStoreDirectoryPageObject::truncate (
994 sal_uInt32 nPage,
995 OStorePageBIOS &rBIOS)
997 // Determine scope and link indices.
998 page::DataBlock::LinkDescriptor aLink;
999 page::ChunkScope eScope = scope (nPage, aLink);
1001 storeError eErrCode = store_E_None;
1002 if (eScope == page::SCOPE_DIRECT)
1004 // Truncate all triple indirect pages.
1005 eErrCode = truncate (page::SCOPE_TRIPLE, 0, rBIOS);
1006 if (eErrCode != store_E_None)
1007 return eErrCode;
1009 // Truncate all double indirect pages.
1010 eErrCode = truncate (page::SCOPE_DOUBLE, 0, rBIOS);
1011 if (eErrCode != store_E_None)
1012 return eErrCode;
1014 // Truncate all single indirect pages.
1015 eErrCode = truncate (page::SCOPE_SINGLE, 0, rBIOS);
1016 if (eErrCode != store_E_None)
1017 return eErrCode;
1019 // Truncate direct pages, including 'aLink.m_nIndex0'.
1020 eErrCode = truncate (eScope, aLink.m_nIndex0, rBIOS);
1022 else if (eScope == page::SCOPE_SINGLE)
1024 // Truncate all triple indirect pages.
1025 eErrCode = truncate (page::SCOPE_TRIPLE, 0, rBIOS);
1026 if (eErrCode != store_E_None)
1027 return eErrCode;
1029 // Truncate all double indirect pages.
1030 eErrCode = truncate (page::SCOPE_DOUBLE, 0, rBIOS);
1031 if (eErrCode != store_E_None)
1032 return eErrCode;
1034 // Truncate single indirect pages, downto 'aLink.m_nIndex1'.
1035 eErrCode = truncate (eScope, aLink.m_nIndex1 + 1, rBIOS);
1036 if (eErrCode != store_E_None)
1037 return eErrCode;
1039 // Truncate last single indirect page to ... pages.
1040 eErrCode = store_truncate_Impl (singleLink (aLink.m_nIndex1), aLink.m_nIndex0, rBIOS);
1041 if (eErrCode != store_E_None)
1042 return eErrCode;
1044 // Check for complete truncation.
1045 if (aLink.m_nIndex0 == 0)
1047 // Clear pointer to last single indirect page.
1048 singleLink (aLink.m_nIndex1, STORE_PAGE_NULL);
1051 else if (eScope == page::SCOPE_DOUBLE)
1053 // Truncate all triple indirect pages.
1054 eErrCode = truncate (page::SCOPE_TRIPLE, 0, rBIOS);
1055 if (eErrCode != store_E_None)
1056 return eErrCode;
1058 // Truncate double indirect pages, downto 'aLink.m_nIndex2'.
1059 eErrCode = truncate (eScope, aLink.m_nIndex2 + 1, rBIOS);
1060 if (eErrCode != store_E_None)
1061 return eErrCode;
1063 // Truncate last double indirect page to ... pages.
1064 eErrCode = store_truncate_Impl (
1065 doubleLink (aLink.m_nIndex2), aLink.m_nIndex1, aLink.m_nIndex0, rBIOS);
1066 if (eErrCode != store_E_None)
1067 return eErrCode;
1069 // Check for complete truncation.
1070 if ((aLink.m_nIndex1 + aLink.m_nIndex0) == 0)
1072 // Clear pointer to last double indirect page.
1073 doubleLink (aLink.m_nIndex2, STORE_PAGE_NULL);
1076 else if (eScope == page::SCOPE_TRIPLE)
1078 // Truncate triple indirect pages, downto 'aLink.m_nIndex3'.
1079 eErrCode = truncate (eScope, aLink.m_nIndex3 + 1, rBIOS);
1080 if (eErrCode != store_E_None)
1081 return eErrCode;
1083 // Truncate last triple indirect page to ... pages.
1084 eErrCode = store_truncate_Impl (
1085 tripleLink (aLink.m_nIndex3), aLink.m_nIndex2, aLink.m_nIndex1, aLink.m_nIndex0, rBIOS);
1086 if (eErrCode != store_E_None)
1087 return eErrCode;
1089 // Check for complete truncation.
1090 if ((aLink.m_nIndex2 + aLink.m_nIndex1 + aLink.m_nIndex0) == 0)
1092 // Clear pointer to last triple indirect page.
1093 tripleLink (aLink.m_nIndex3, STORE_PAGE_NULL);
1096 else if (eScope == page::SCOPE_UNREACHABLE)
1098 // Out of scope.
1099 eErrCode = store_E_CantSeek;
1101 else
1103 // Unknown scope.
1104 OSL_TRACE("OStoreDirectoryPageObject::put(): scope failed");
1105 eErrCode = store_E_Unknown;
1108 // Leave.
1109 return eErrCode;
1113 * truncate (external data page scope; private).
1115 storeError OStoreDirectoryPageObject::truncate (
1116 page::ChunkScope eScope,
1117 sal_uInt16 nRemain,
1118 OStorePageBIOS &rBIOS)
1120 OStoreDirectoryDataBlock const & rDataBlock = PAGE().m_aDataBlock;
1122 // Enter.
1123 storeError eErrCode = store_E_None;
1124 if (eScope == page::SCOPE_DIRECT)
1126 // Truncate direct data pages.
1127 sal_uInt16 i, n = rDataBlock.directCount();
1128 for (i = n; i > nRemain; i--)
1130 // Obtain data page location.
1131 sal_uInt32 nAddr = directLink (i - 1);
1132 if (nAddr == STORE_PAGE_NULL) continue;
1134 // Free data page.
1135 OStoreDataPageData aData;
1136 eErrCode = rBIOS.free (aData, nAddr);
1137 if (eErrCode != store_E_None)
1138 break;
1140 // Clear pointer to data page.
1141 directLink (i - 1, STORE_PAGE_NULL);
1144 // Done.
1145 return eErrCode;
1148 if (eScope == page::SCOPE_SINGLE)
1150 // Truncate single indirect pages.
1151 sal_uInt16 i, n = rDataBlock.singleCount();
1152 for (i = n; i > nRemain; i--)
1154 // Truncate single indirect page to zero data pages.
1155 eErrCode = store_truncate_Impl (singleLink (i - 1), 0, rBIOS);
1156 if (eErrCode != store_E_None)
1157 break;
1159 // Clear pointer to single indirect page.
1160 singleLink (i - 1, STORE_PAGE_NULL);
1163 // Done.
1164 return eErrCode;
1167 if (eScope == page::SCOPE_DOUBLE)
1169 // Truncate double indirect pages.
1170 sal_uInt16 i, n = rDataBlock.doubleCount();
1171 for (i = n; i > nRemain; i--)
1173 // Truncate double indirect page to zero single indirect pages.
1174 eErrCode = store_truncate_Impl (doubleLink (i - 1), 0, 0, rBIOS);
1175 if (eErrCode != store_E_None)
1176 break;
1178 // Clear pointer to double indirect page.
1179 doubleLink (i - 1, STORE_PAGE_NULL);
1182 // Done.
1183 return eErrCode;
1186 if (eScope == page::SCOPE_TRIPLE)
1188 // Truncate triple indirect pages.
1189 sal_uInt16 i, n = rDataBlock.tripleCount();
1190 for (i = n; i > nRemain; i--)
1192 // Truncate to zero double indirect pages.
1193 eErrCode = store_truncate_Impl (tripleLink (i - 1), 0, 0, 0, rBIOS);
1194 if (eErrCode != store_E_None)
1195 break;
1197 // Clear pointer to triple indirect page.
1198 tripleLink (i - 1, STORE_PAGE_NULL);
1201 // Done.
1202 return eErrCode;
1205 // Invalid scope.
1206 return store_E_InvalidAccess;