Branch libreoffice-5-0-4
[LibreOffice.git] / store / source / stordata.cxx
blob75562aa14deae8d99c64ae77444e79bf6ed178ab
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"
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();
594 sal_uInt32 index0, index1, index2, index3;
596 // direct.
597 sal_uInt32 nCount = OStoreDirectoryDataBlock::directCount;
598 sal_uInt32 nLimit = nCount;
599 if (nPage < nLimit)
601 // Page to index reduction.
602 index0 = nPage;
604 // Setup LinkDescriptor indices.
605 rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff);
607 // Done.
608 return page::SCOPE_DIRECT;
610 nPage -= nLimit;
612 // single indirect.
613 sal_uInt32 const nCapacity = indirect::capacityCount(rPage.m_aDescr);
614 nCount = OStoreDirectoryDataBlock::singleCount;
615 nLimit = nCount * nCapacity;
616 if (nPage < nLimit)
618 // Page to index reduction.
619 sal_uInt32 n = nPage;
621 // Reduce to single indirect i(1), direct n = i(0).
622 index1 = n / nCapacity;
623 index0 = n % nCapacity;
625 // Verify reduction.
626 n = index1 * nCapacity + index0;
627 if (n != nPage)
629 SAL_WARN("store", "wrong math on indirect indices");
630 return page::SCOPE_UNKNOWN;
633 // Setup LinkDescriptor indices.
634 rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff);
635 rDescr.m_nIndex1 = (sal_uInt16)(index1 & 0xffff);
637 // Done.
638 return page::SCOPE_SINGLE;
640 nPage -= nLimit;
642 // double indirect.
643 nCount = OStoreDirectoryDataBlock::doubleCount;
644 nLimit = nCount * nCapacity * nCapacity;
645 if (nPage < nLimit)
647 // Page to index reduction.
648 sal_uInt32 n = nPage;
650 // Reduce to double indirect i(2), single indirect n = i(0).
651 index2 = n / (nCapacity * nCapacity);
652 n = n % (nCapacity * nCapacity);
654 // Reduce to single indirect i(1), direct n = i(0).
655 index1 = n / nCapacity;
656 index0 = n % nCapacity;
658 // Verify reduction.
659 n = index2 * nCapacity * nCapacity +
660 index1 * nCapacity + index0;
661 if (n != nPage)
663 SAL_WARN("store", "wrong math on double indirect indices");
664 return page::SCOPE_UNKNOWN;
667 // Setup LinkDescriptor indices.
668 rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff);
669 rDescr.m_nIndex1 = (sal_uInt16)(index1 & 0xffff);
670 rDescr.m_nIndex2 = (sal_uInt16)(index2 & 0xffff);
672 // Done.
673 return page::SCOPE_DOUBLE;
675 nPage -= nLimit;
677 // triple indirect.
678 nCount = OStoreDirectoryDataBlock::tripleCount;
679 nLimit = nCount * nCapacity * nCapacity * nCapacity;
680 if (nPage < nLimit)
682 // Page to index reduction.
683 sal_uInt32 n = nPage;
685 // Reduce to triple indirect i(3), double indirect n.
686 index3 = n / (nCapacity * nCapacity * nCapacity);
687 n = n % (nCapacity * nCapacity * nCapacity);
689 // Reduce to double indirect i(2), single indirect n.
690 index2 = n / (nCapacity * nCapacity);
691 n = n % (nCapacity * nCapacity);
693 // Reduce to single indirect i(1), direct n = i(0).
694 index1 = n / nCapacity;
695 index0 = n % nCapacity;
697 // Verify reduction.
698 n = index3 * nCapacity * nCapacity * nCapacity +
699 index2 * nCapacity * nCapacity +
700 index1 * nCapacity + index0;
701 if (n != nPage)
703 SAL_WARN("store", "wrong math on triple indirect indices");
704 return page::SCOPE_UNKNOWN;
707 // Setup LinkDescriptor indices.
708 rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff);
709 rDescr.m_nIndex1 = (sal_uInt16)(index1 & 0xffff);
710 rDescr.m_nIndex2 = (sal_uInt16)(index2 & 0xffff);
711 rDescr.m_nIndex3 = (sal_uInt16)(index3 & 0xffff);
713 // Done.
714 return page::SCOPE_TRIPLE;
717 // Unreachable (more than triple indirect).
718 return page::SCOPE_UNREACHABLE;
722 * read (external data page).
724 storeError OStoreDirectoryPageObject::read (
725 sal_uInt32 nPage,
726 OStoreDataPageObject &rData,
727 OStorePageBIOS &rBIOS)
729 // Determine scope and link indices.
730 page::DataBlock::LinkDescriptor aLink;
731 page::ChunkScope eScope = scope (nPage, aLink);
733 storeError eErrCode = store_E_None;
734 if (eScope == page::SCOPE_DIRECT)
736 sal_uInt32 const nAddr = directLink (aLink.m_nIndex0);
737 if (nAddr == STORE_PAGE_NULL)
738 return store_E_NotExists;
740 eErrCode = rBIOS.loadObjectAt (rData, nAddr);
742 else if (eScope == page::SCOPE_SINGLE)
744 sal_uInt32 const nAddr = singleLink (aLink.m_nIndex1);
745 if (nAddr == STORE_PAGE_NULL)
746 return store_E_NotExists;
748 OStoreIndirectionPageObject aSingle;
749 eErrCode = rBIOS.loadObjectAt (aSingle, nAddr);
750 if (eErrCode != store_E_None)
751 return eErrCode;
753 eErrCode = aSingle.read (aLink.m_nIndex0, rData, rBIOS);
755 else if (eScope == page::SCOPE_DOUBLE)
757 sal_uInt32 const nAddr = doubleLink (aLink.m_nIndex2);
758 if (nAddr == STORE_PAGE_NULL)
759 return store_E_NotExists;
761 OStoreIndirectionPageObject aDouble;
762 eErrCode = rBIOS.loadObjectAt (aDouble, nAddr);
763 if (eErrCode != store_E_None)
764 return eErrCode;
766 eErrCode = aDouble.read (aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS);
768 else if (eScope == page::SCOPE_TRIPLE)
770 sal_uInt32 const nAddr = tripleLink (aLink.m_nIndex3);
771 if (nAddr == STORE_PAGE_NULL)
772 return store_E_NotExists;
774 OStoreIndirectionPageObject aTriple;
775 eErrCode = rBIOS.loadObjectAt (aTriple, nAddr);
776 if (eErrCode != store_E_None)
777 return eErrCode;
779 eErrCode = aTriple.read (aLink.m_nIndex2, aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS);
781 else if (eScope == page::SCOPE_UNREACHABLE)
783 // Out of scope.
784 eErrCode = store_E_CantSeek;
786 else
788 // Unknown scope.
789 OSL_TRACE("OStoreDirectoryPageObject::get(): scope failed");
790 eErrCode = store_E_Unknown;
793 // Leave.
794 return eErrCode;
798 * write (external data page).
800 storeError OStoreDirectoryPageObject::write (
801 sal_uInt32 nPage,
802 OStoreDataPageObject &rData,
803 OStorePageBIOS &rBIOS)
805 // Determine scope and link indices.
806 page::DataBlock::LinkDescriptor aLink;
807 page::ChunkScope eScope = scope (nPage, aLink);
809 storeError eErrCode = store_E_None;
810 if (eScope == page::SCOPE_DIRECT)
812 sal_uInt32 const nAddr = directLink (aLink.m_nIndex0);
813 if (nAddr == STORE_PAGE_NULL)
815 // Allocate data page.
816 eErrCode = rBIOS.allocate (rData);
817 if (eErrCode != store_E_None)
818 return eErrCode;
820 // Store data page location.
821 directLink (aLink.m_nIndex0, rData.location());
823 else
825 // Save data page.
826 eErrCode = rBIOS.saveObjectAt (rData, nAddr);
829 else if (eScope == page::SCOPE_SINGLE)
831 OStoreIndirectionPageObject aSingle;
832 eErrCode = aSingle.loadOrCreate (singleLink (aLink.m_nIndex1), rBIOS);
833 if (eErrCode != store_E_None)
835 if (eErrCode != store_E_Pending)
836 return eErrCode;
837 singleLink (aLink.m_nIndex1, aSingle.location());
840 eErrCode = aSingle.write (aLink.m_nIndex0, rData, rBIOS);
842 else if (eScope == page::SCOPE_DOUBLE)
844 OStoreIndirectionPageObject aDouble;
845 eErrCode = aDouble.loadOrCreate (doubleLink (aLink.m_nIndex2), rBIOS);
846 if (eErrCode != store_E_None)
848 if (eErrCode != store_E_Pending)
849 return eErrCode;
850 doubleLink (aLink.m_nIndex2, aDouble.location());
853 eErrCode = aDouble.write (aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS);
855 else if (eScope == page::SCOPE_TRIPLE)
857 OStoreIndirectionPageObject aTriple;
858 eErrCode = aTriple.loadOrCreate (tripleLink (aLink.m_nIndex3), rBIOS);
859 if (eErrCode != store_E_None)
861 if (eErrCode != store_E_Pending)
862 return eErrCode;
863 tripleLink (aLink.m_nIndex3, aTriple.location());
866 eErrCode = aTriple.write (aLink.m_nIndex2, aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS);
868 else if (eScope == page::SCOPE_UNREACHABLE)
870 // Out of scope.
871 eErrCode = store_E_CantSeek;
873 else
875 // Unknown scope.
876 OSL_TRACE("OStoreDirectoryPageObject::put(): scope failed");
877 eErrCode = store_E_Unknown;
880 // Leave.
881 return eErrCode;
885 * truncate (external data page).
887 storeError OStoreDirectoryPageObject::truncate (
888 sal_uInt32 nPage,
889 OStorePageBIOS &rBIOS)
891 // Determine scope and link indices.
892 page::DataBlock::LinkDescriptor aLink;
893 page::ChunkScope eScope = scope (nPage, aLink);
895 storeError eErrCode = store_E_None;
896 if (eScope == page::SCOPE_DIRECT)
898 // Truncate all triple indirect pages.
899 eErrCode = truncate (page::SCOPE_TRIPLE, 0, rBIOS);
900 if (eErrCode != store_E_None)
901 return eErrCode;
903 // Truncate all double indirect pages.
904 eErrCode = truncate (page::SCOPE_DOUBLE, 0, rBIOS);
905 if (eErrCode != store_E_None)
906 return eErrCode;
908 // Truncate all single indirect pages.
909 eErrCode = truncate (page::SCOPE_SINGLE, 0, rBIOS);
910 if (eErrCode != store_E_None)
911 return eErrCode;
913 // Truncate direct pages, including 'aLink.m_nIndex0'.
914 eErrCode = truncate (eScope, aLink.m_nIndex0, rBIOS);
916 else if (eScope == page::SCOPE_SINGLE)
918 // Truncate all triple indirect pages.
919 eErrCode = truncate (page::SCOPE_TRIPLE, 0, rBIOS);
920 if (eErrCode != store_E_None)
921 return eErrCode;
923 // Truncate all double indirect pages.
924 eErrCode = truncate (page::SCOPE_DOUBLE, 0, rBIOS);
925 if (eErrCode != store_E_None)
926 return eErrCode;
928 // Truncate single indirect pages, downto 'aLink.m_nIndex1'.
929 eErrCode = truncate (eScope, aLink.m_nIndex1 + 1, rBIOS);
930 if (eErrCode != store_E_None)
931 return eErrCode;
933 // Truncate last single indirect page to ... pages.
934 eErrCode = store_truncate_Impl (singleLink (aLink.m_nIndex1), aLink.m_nIndex0, rBIOS);
935 if (eErrCode != store_E_None)
936 return eErrCode;
938 // Check for complete truncation.
939 if (aLink.m_nIndex0 == 0)
941 // Clear pointer to last single indirect page.
942 singleLink (aLink.m_nIndex1, STORE_PAGE_NULL);
945 else if (eScope == page::SCOPE_DOUBLE)
947 // Truncate all triple indirect pages.
948 eErrCode = truncate (page::SCOPE_TRIPLE, 0, rBIOS);
949 if (eErrCode != store_E_None)
950 return eErrCode;
952 // Truncate double indirect pages, downto 'aLink.m_nIndex2'.
953 eErrCode = truncate (eScope, aLink.m_nIndex2 + 1, rBIOS);
954 if (eErrCode != store_E_None)
955 return eErrCode;
957 // Truncate last double indirect page to ... pages.
958 eErrCode = store_truncate_Impl (
959 doubleLink (aLink.m_nIndex2), aLink.m_nIndex1, aLink.m_nIndex0, rBIOS);
960 if (eErrCode != store_E_None)
961 return eErrCode;
963 // Check for complete truncation.
964 if ((aLink.m_nIndex1 + aLink.m_nIndex0) == 0)
966 // Clear pointer to last double indirect page.
967 doubleLink (aLink.m_nIndex2, STORE_PAGE_NULL);
970 else if (eScope == page::SCOPE_TRIPLE)
972 // Truncate triple indirect pages, downto 'aLink.m_nIndex3'.
973 eErrCode = truncate (eScope, aLink.m_nIndex3 + 1, rBIOS);
974 if (eErrCode != store_E_None)
975 return eErrCode;
977 // Truncate last triple indirect page to ... pages.
978 eErrCode = store_truncate_Impl (
979 tripleLink (aLink.m_nIndex3), aLink.m_nIndex2, aLink.m_nIndex1, aLink.m_nIndex0, rBIOS);
980 if (eErrCode != store_E_None)
981 return eErrCode;
983 // Check for complete truncation.
984 if ((aLink.m_nIndex2 + aLink.m_nIndex1 + aLink.m_nIndex0) == 0)
986 // Clear pointer to last triple indirect page.
987 tripleLink (aLink.m_nIndex3, STORE_PAGE_NULL);
990 else if (eScope == page::SCOPE_UNREACHABLE)
992 // Out of scope.
993 eErrCode = store_E_CantSeek;
995 else
997 // Unknown scope.
998 OSL_TRACE("OStoreDirectoryPageObject::put(): scope failed");
999 eErrCode = store_E_Unknown;
1002 // Leave.
1003 return eErrCode;
1007 * truncate (external data page scope; private).
1009 storeError OStoreDirectoryPageObject::truncate (
1010 page::ChunkScope eScope,
1011 sal_uInt16 nRemain,
1012 OStorePageBIOS &rBIOS)
1014 // Enter.
1015 storeError eErrCode = store_E_None;
1016 if (eScope == page::SCOPE_DIRECT)
1018 // Truncate direct data pages.
1019 sal_uInt16 i, n = OStoreDirectoryDataBlock::directCount;
1020 for (i = n; i > nRemain; i--)
1022 // Obtain data page location.
1023 sal_uInt32 nAddr = directLink (i - 1);
1024 if (nAddr == STORE_PAGE_NULL) continue;
1026 // Free data page.
1027 eErrCode = rBIOS.free (nAddr);
1028 if (eErrCode != store_E_None)
1029 break;
1031 // Clear pointer to data page.
1032 directLink (i - 1, STORE_PAGE_NULL);
1035 // Done.
1036 return eErrCode;
1039 if (eScope == page::SCOPE_SINGLE)
1041 // Truncate single indirect pages.
1042 sal_uInt16 i, n = OStoreDirectoryDataBlock::singleCount;
1043 for (i = n; i > nRemain; i--)
1045 // Truncate single indirect page to zero data pages.
1046 eErrCode = store_truncate_Impl (singleLink (i - 1), 0, rBIOS);
1047 if (eErrCode != store_E_None)
1048 break;
1050 // Clear pointer to single indirect page.
1051 singleLink (i - 1, STORE_PAGE_NULL);
1054 // Done.
1055 return eErrCode;
1058 if (eScope == page::SCOPE_DOUBLE)
1060 // Truncate double indirect pages.
1061 sal_uInt16 i, n = OStoreDirectoryDataBlock::doubleCount;
1062 for (i = n; i > nRemain; i--)
1064 // Truncate double indirect page to zero single indirect pages.
1065 eErrCode = store_truncate_Impl (doubleLink (i - 1), 0, 0, rBIOS);
1066 if (eErrCode != store_E_None)
1067 break;
1069 // Clear pointer to double indirect page.
1070 doubleLink (i - 1, STORE_PAGE_NULL);
1073 // Done.
1074 return eErrCode;
1077 if (eScope == page::SCOPE_TRIPLE)
1079 // Truncate triple indirect pages.
1080 sal_uInt16 i, n = OStoreDirectoryDataBlock::tripleCount;
1081 for (i = n; i > nRemain; i--)
1083 // Truncate to zero double indirect pages.
1084 eErrCode = store_truncate_Impl (tripleLink (i - 1), 0, 0, 0, rBIOS);
1085 if (eErrCode != store_E_None)
1086 break;
1088 // Clear pointer to triple indirect page.
1089 tripleLink (i - 1, STORE_PAGE_NULL);
1092 // Done.
1093 return eErrCode;
1096 // Invalid scope.
1097 return store_E_InvalidAccess;
1100 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */