Revert "lok: sc: make hi-dpi/zoom compatible with retrieving cell cursor"
[LibreOffice.git] / store / source / stordata.cxx
blob7ce39a9c1208b30828cbf0f9d6f497365d312246
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 /*========================================================================
33 * OStoreDataPageObject implementation.
35 *======================================================================*/
37 * guard.
39 storeError OStoreDataPageObject::guard (sal_uInt32 nAddr)
41 return PageHolderObject< page >::guard (m_xPage, nAddr);
45 * verify.
47 storeError OStoreDataPageObject::verify (sal_uInt32 nAddr) const
49 return PageHolderObject< page >::verify (m_xPage, nAddr);
52 /*========================================================================
54 * OStoreIndirectionPageObject implementation.
56 *======================================================================*/
58 * store_truncate_Impl (single indirect page).
60 static storeError store_truncate_Impl (
61 sal_uInt32 nAddr,
62 sal_uInt16 nSingle,
63 OStorePageBIOS &rBIOS)
65 if (nAddr != STORE_PAGE_NULL)
67 // Load single indirect page.
68 OStoreIndirectionPageObject aSingle;
69 storeError eErrCode = rBIOS.loadObjectAt (aSingle, nAddr);
70 if (eErrCode == store_E_None)
72 // Truncate to 'nSingle' direct pages.
73 eErrCode = aSingle.truncate (nSingle, rBIOS);
74 if (eErrCode != store_E_None)
75 return eErrCode;
77 else
79 if (eErrCode != store_E_InvalidChecksum)
80 return eErrCode;
83 // Check for complete truncation.
84 if (nSingle == 0)
86 // Free single indirect page.
87 eErrCode = rBIOS.free (nAddr);
88 if (eErrCode != store_E_None)
89 return eErrCode;
92 return store_E_None;
96 * store_truncate_Impl (double indirect page).
98 static storeError store_truncate_Impl (
99 sal_uInt32 nAddr,
100 sal_uInt16 nDouble,
101 sal_uInt16 nSingle,
102 OStorePageBIOS &rBIOS)
104 if (nAddr != STORE_PAGE_NULL)
106 // Load double indirect page.
107 OStoreIndirectionPageObject aDouble;
108 storeError eErrCode = rBIOS.loadObjectAt (aDouble, nAddr);
109 if (eErrCode == store_E_None)
111 // Truncate to 'nDouble', 'nSingle' pages.
112 eErrCode = aDouble.truncate (nDouble, nSingle, rBIOS);
113 if (eErrCode != store_E_None)
114 return eErrCode;
116 else
118 if (eErrCode != store_E_InvalidChecksum)
119 return eErrCode;
122 // Check for complete truncation.
123 if ((nDouble + nSingle) == 0)
125 // Free double indirect page.
126 eErrCode = rBIOS.free (nAddr);
127 if (eErrCode != store_E_None)
128 return eErrCode;
131 return store_E_None;
135 * store_truncate_Impl (triple indirect page).
137 static storeError store_truncate_Impl (
138 sal_uInt32 nAddr,
139 sal_uInt16 nTriple,
140 sal_uInt16 nDouble,
141 sal_uInt16 nSingle,
142 OStorePageBIOS &rBIOS)
144 if (nAddr != STORE_PAGE_NULL)
146 // Load triple indirect page.
147 OStoreIndirectionPageObject aTriple;
148 storeError eErrCode = rBIOS.loadObjectAt (aTriple, nAddr);
149 if (eErrCode != store_E_None)
150 return eErrCode;
152 // Truncate to 'nTriple', 'nDouble', 'nSingle' pages.
153 eErrCode = aTriple.truncate (nTriple, nDouble, nSingle, rBIOS);
154 if (eErrCode != store_E_None)
155 return eErrCode;
157 // Check for complete truncation.
158 if ((nTriple + nDouble + nSingle) == 0)
160 // Free triple indirect page.
161 eErrCode = rBIOS.free (nAddr);
162 if (eErrCode != store_E_None)
163 return eErrCode;
166 return store_E_None;
170 * loadOrCreate.
172 storeError OStoreIndirectionPageObject::loadOrCreate (
173 sal_uInt32 nAddr,
174 OStorePageBIOS & rBIOS)
176 if (nAddr == STORE_PAGE_NULL)
178 storeError eErrCode = construct<page>(rBIOS.allocator());
179 if (eErrCode != store_E_None)
180 return eErrCode;
182 eErrCode = rBIOS.allocate (*this);
183 if (eErrCode != store_E_None)
184 return eErrCode;
186 // Save location pending at caller.
187 return store_E_Pending;
189 return rBIOS.loadObjectAt (*this, nAddr);
193 * guard.
195 storeError OStoreIndirectionPageObject::guard (sal_uInt32 nAddr)
197 return PageHolderObject< page >::guard (m_xPage, nAddr);
201 * verify.
203 storeError OStoreIndirectionPageObject::verify (sal_uInt32 nAddr) const
205 return PageHolderObject< page >::verify (m_xPage, nAddr);
209 * read (single indirect).
211 storeError OStoreIndirectionPageObject::read (
212 sal_uInt16 nSingle,
213 OStoreDataPageObject &rData,
214 OStorePageBIOS &rBIOS) const
216 PageHolderObject< page > xImpl (m_xPage);
217 page const & rPage = *xImpl;
219 // Check arguments.
220 sal_uInt16 const nLimit = rPage.capacityCount();
221 if (nSingle >= nLimit)
222 return store_E_InvalidAccess;
224 // Obtain data page location.
225 sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nSingle]);
226 if (nAddr == STORE_PAGE_NULL)
227 return store_E_NotExists;
229 // Load data page and leave.
230 return rBIOS.loadObjectAt (rData, nAddr);
234 * read (double indirect).
236 storeError OStoreIndirectionPageObject::read (
237 sal_uInt16 nDouble,
238 sal_uInt16 nSingle,
239 OStoreDataPageObject &rData,
240 OStorePageBIOS &rBIOS) const
242 PageHolderObject< page > xImpl (m_xPage);
243 page const & rPage = *xImpl;
245 // Check arguments.
246 sal_uInt16 const nLimit = rPage.capacityCount();
247 if (!((nDouble < nLimit) && (nSingle < nLimit)))
248 return store_E_InvalidAccess;
250 // Check single indirect page location.
251 sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nDouble]);
252 if (nAddr == STORE_PAGE_NULL)
253 return store_E_NotExists;
255 // Load single indirect page.
256 OStoreIndirectionPageObject aSingle;
257 storeError eErrCode = rBIOS.loadObjectAt (aSingle, nAddr);
258 if (eErrCode != store_E_None)
259 return eErrCode;
261 // Read single indirect and leave.
262 return aSingle.read (nSingle, rData, rBIOS);
266 * read (triple indirect).
268 storeError OStoreIndirectionPageObject::read (
269 sal_uInt16 nTriple,
270 sal_uInt16 nDouble,
271 sal_uInt16 nSingle,
272 OStoreDataPageObject &rData,
273 OStorePageBIOS &rBIOS) const
275 PageHolderObject< page > xImpl (m_xPage);
276 page const & rPage = *xImpl;
278 // Check arguments.
279 sal_uInt16 const nLimit = rPage.capacityCount();
280 if (!((nTriple < nLimit) && (nDouble < nLimit) && (nSingle < nLimit)))
281 return store_E_InvalidAccess;
283 // Check double indirect page location.
284 sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nTriple]);
285 if (nAddr == STORE_PAGE_NULL)
286 return store_E_NotExists;
288 // Load double indirect page.
289 OStoreIndirectionPageObject aDouble;
290 storeError eErrCode = rBIOS.loadObjectAt (aDouble, nAddr);
291 if (eErrCode != store_E_None)
292 return eErrCode;
294 // Read double indirect and leave.
295 return aDouble.read (nDouble, nSingle, rData, rBIOS);
299 * write (single indirect).
301 storeError OStoreIndirectionPageObject::write (
302 sal_uInt16 nSingle,
303 OStoreDataPageObject &rData,
304 OStorePageBIOS &rBIOS)
306 PageHolderObject< page > xImpl (m_xPage);
307 page & rPage = *xImpl;
309 // Check arguments.
310 sal_uInt16 const nLimit = rPage.capacityCount();
311 if (nSingle >= nLimit)
312 return store_E_InvalidAccess;
314 // Obtain data page location.
315 sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nSingle]);
316 if (nAddr == STORE_PAGE_NULL)
318 // Allocate data page.
319 storeError eErrCode = rBIOS.allocate (rData);
320 if (eErrCode != store_E_None)
321 return eErrCode;
323 // Store data page location.
324 rPage.m_pData[nSingle] = store::htonl(rData.location());
326 // Save this page.
327 return rBIOS.saveObjectAt (*this, location());
329 else
331 // Save data page.
332 return rBIOS.saveObjectAt (rData, nAddr);
337 * write (double indirect).
339 storeError OStoreIndirectionPageObject::write (
340 sal_uInt16 nDouble,
341 sal_uInt16 nSingle,
342 OStoreDataPageObject &rData,
343 OStorePageBIOS &rBIOS)
345 PageHolderObject< page > xImpl (m_xPage);
346 page & rPage = *xImpl;
348 // Check arguments.
349 sal_uInt16 const nLimit = rPage.capacityCount();
350 if (!((nDouble < nLimit) && (nSingle < nLimit)))
351 return store_E_InvalidAccess;
353 // Load or create single indirect page.
354 OStoreIndirectionPageObject aSingle;
355 storeError eErrCode = aSingle.loadOrCreate (store::ntohl(rPage.m_pData[nDouble]), rBIOS);
356 if (eErrCode != store_E_None)
358 if (eErrCode != store_E_Pending)
359 return eErrCode;
360 rPage.m_pData[nDouble] = store::htonl(aSingle.location());
362 eErrCode = rBIOS.saveObjectAt (*this, location());
363 if (eErrCode != store_E_None)
364 return eErrCode;
367 // Write single indirect and leave.
368 return aSingle.write (nSingle, rData, rBIOS);
372 * write (triple indirect).
374 storeError OStoreIndirectionPageObject::write (
375 sal_uInt16 nTriple,
376 sal_uInt16 nDouble,
377 sal_uInt16 nSingle,
378 OStoreDataPageObject &rData,
379 OStorePageBIOS &rBIOS)
381 PageHolderObject< page > xImpl (m_xPage);
382 page & rPage = *xImpl;
384 // Check arguments.
385 sal_uInt16 const nLimit = rPage.capacityCount();
386 if (!((nTriple < nLimit) && (nDouble < nLimit) && (nSingle < nLimit)))
387 return store_E_InvalidAccess;
389 // Load or create double indirect page.
390 OStoreIndirectionPageObject aDouble;
391 storeError eErrCode = aDouble.loadOrCreate (store::ntohl(rPage.m_pData[nTriple]), rBIOS);
392 if (eErrCode != store_E_None)
394 if (eErrCode != store_E_Pending)
395 return eErrCode;
396 rPage.m_pData[nTriple] = store::htonl(aDouble.location());
398 eErrCode = rBIOS.saveObjectAt (*this, location());
399 if (eErrCode != store_E_None)
400 return eErrCode;
403 // Write double indirect and leave.
404 return aDouble.write (nDouble, nSingle, rData, rBIOS);
408 * truncate (single indirect).
410 storeError OStoreIndirectionPageObject::truncate (
411 sal_uInt16 nSingle,
412 OStorePageBIOS & rBIOS)
414 PageHolderObject< page > xImpl (m_xPage);
415 page & rPage = *xImpl;
417 // Check arguments.
418 sal_uInt16 const nLimit = rPage.capacityCount();
419 if (nSingle >= nLimit)
420 return store_E_InvalidAccess;
422 // Truncate.
423 storeError eErrCode = store_E_None;
424 for (sal_uInt16 i = nLimit; i > nSingle; i--)
426 // Obtain data page location.
427 sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[i - 1]);
428 if (nAddr != STORE_PAGE_NULL)
430 // Free data page.
431 eErrCode = rBIOS.free (nAddr);
432 if (eErrCode != store_E_None)
433 return eErrCode;
435 // Clear pointer to data page.
436 rPage.m_pData[i - 1] = STORE_PAGE_NULL;
437 touch();
441 // Check for modified page.
442 if (dirty())
444 // Save this page.
445 eErrCode = rBIOS.saveObjectAt (*this, location());
448 // Done.
449 return eErrCode;
453 * truncate (double indirect).
455 storeError OStoreIndirectionPageObject::truncate (
456 sal_uInt16 nDouble,
457 sal_uInt16 nSingle,
458 OStorePageBIOS &rBIOS)
460 PageHolderObject< page > xImpl (m_xPage);
461 page & rPage = *xImpl;
463 // Check arguments.
464 sal_uInt16 const nLimit = rPage.capacityCount();
465 if (!((nDouble < nLimit) && (nSingle < nLimit)))
466 return store_E_InvalidAccess;
468 // Truncate.
469 storeError eErrCode = store_E_None;
470 for (sal_uInt16 i = nLimit; i > nDouble + 1; i--)
472 // Truncate single indirect page to zero direct pages.
473 eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[i - 1]), 0, rBIOS);
474 if (eErrCode != store_E_None)
475 return eErrCode;
477 // Clear pointer to single indirect page.
478 rPage.m_pData[i - 1] = STORE_PAGE_NULL;
479 touch();
482 // Truncate last single indirect page to 'nSingle' direct pages.
483 eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[nDouble]), nSingle, rBIOS);
484 if (eErrCode != store_E_None)
485 return eErrCode;
487 // Check for complete truncation.
488 if (nSingle == 0)
490 // Clear pointer to last single indirect page.
491 rPage.m_pData[nDouble] = STORE_PAGE_NULL;
492 touch();
495 // Check for modified page.
496 if (dirty())
498 // Save this page.
499 eErrCode = rBIOS.saveObjectAt (*this, location());
502 // Done.
503 return eErrCode;
507 * truncate (triple indirect).
509 storeError OStoreIndirectionPageObject::truncate (
510 sal_uInt16 nTriple,
511 sal_uInt16 nDouble,
512 sal_uInt16 nSingle,
513 OStorePageBIOS &rBIOS)
515 PageHolderObject< page > xImpl (m_xPage);
516 page & rPage = *xImpl;
518 // Check arguments.
519 sal_uInt16 const nLimit = rPage.capacityCount();
520 if (!((nTriple < nLimit) && (nDouble < nLimit) && (nSingle < nLimit)))
521 return store_E_InvalidAccess;
523 // Truncate.
524 storeError eErrCode = store_E_None;
525 for (sal_uInt16 i = nLimit; i > nTriple + 1; i--)
527 // Truncate double indirect page to zero single indirect pages.
528 eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[i - 1]), 0, 0, rBIOS);
529 if (eErrCode != store_E_None)
530 return eErrCode;
532 // Clear pointer to double indirect page.
533 rPage.m_pData[i - 1] = STORE_PAGE_NULL;
534 touch();
537 // Truncate last double indirect page to 'nDouble', 'nSingle' pages.
538 eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[nTriple]), nDouble, nSingle, rBIOS);
539 if (eErrCode != store_E_None)
540 return eErrCode;
542 // Check for complete truncation.
543 if ((nDouble + nSingle) == 0)
545 // Clear pointer to last double indirect page.
546 rPage.m_pData[nTriple] = STORE_PAGE_NULL;
547 touch();
550 // Check for modified page.
551 if (dirty())
553 // Save this page.
554 eErrCode = rBIOS.saveObjectAt (*this, location());
557 // Done.
558 return eErrCode;
561 /*========================================================================
563 * OStoreDirectoryPageObject implementation.
565 *======================================================================*/
567 * guard.
569 storeError OStoreDirectoryPageObject::guard (sal_uInt32 nAddr)
571 return PageHolderObject< page >::guard (m_xPage, nAddr);
575 * verify.
577 storeError OStoreDirectoryPageObject::verify (sal_uInt32 nAddr) const
579 return PageHolderObject< page >::verify (m_xPage, nAddr);
580 // OLD: m_rPage.verifyVersion (STORE_MAGIC_DIRECTORYPAGE);
584 * scope (external data page; private).
586 OStoreDirectoryPageData::ChunkScope
587 OStoreDirectoryPageObject::scope (
588 sal_uInt32 nPage,
589 page::DataBlock::LinkDescriptor &rDescr) const
591 page const & rPage = PAGE();
593 sal_uInt32 index0, index1, index2, index3;
595 // direct.
596 sal_uInt32 nCount = OStoreDirectoryDataBlock::directCount;
597 sal_uInt32 nLimit = nCount;
598 if (nPage < nLimit)
600 // Page to index reduction.
601 index0 = nPage;
603 // Setup LinkDescriptor indices.
604 rDescr.m_nIndex0 = static_cast<sal_uInt16>(index0 & 0xffff);
606 // Done.
607 return page::SCOPE_DIRECT;
609 nPage -= nLimit;
611 // single indirect.
612 sal_uInt32 const nCapacity = indirect::capacityCount(rPage.m_aDescr);
613 nCount = OStoreDirectoryDataBlock::singleCount;
614 nLimit = nCount * nCapacity;
615 if (nPage < nLimit)
617 // Page to index reduction.
618 sal_uInt32 n = nPage;
620 // Reduce to single indirect i(1), direct n = i(0).
621 index1 = n / nCapacity;
622 index0 = n % nCapacity;
624 // Verify reduction.
625 n = index1 * nCapacity + index0;
626 if (n != nPage)
628 SAL_WARN("store", "wrong math on indirect indices");
629 return page::SCOPE_UNKNOWN;
632 // Setup LinkDescriptor indices.
633 rDescr.m_nIndex0 = static_cast<sal_uInt16>(index0 & 0xffff);
634 rDescr.m_nIndex1 = static_cast<sal_uInt16>(index1 & 0xffff);
636 // Done.
637 return page::SCOPE_SINGLE;
639 nPage -= nLimit;
641 // double indirect.
642 nCount = OStoreDirectoryDataBlock::doubleCount;
643 nLimit = nCount * nCapacity * nCapacity;
644 if (nPage < nLimit)
646 // Page to index reduction.
647 sal_uInt32 n = nPage;
649 // Reduce to double indirect i(2), single indirect n = i(0).
650 index2 = n / (nCapacity * nCapacity);
651 n = n % (nCapacity * nCapacity);
653 // Reduce to single indirect i(1), direct n = i(0).
654 index1 = n / nCapacity;
655 index0 = n % nCapacity;
657 // Verify reduction.
658 n = index2 * nCapacity * nCapacity +
659 index1 * nCapacity + index0;
660 if (n != nPage)
662 SAL_WARN("store", "wrong math on double indirect indices");
663 return page::SCOPE_UNKNOWN;
666 // Setup LinkDescriptor indices.
667 rDescr.m_nIndex0 = static_cast<sal_uInt16>(index0 & 0xffff);
668 rDescr.m_nIndex1 = static_cast<sal_uInt16>(index1 & 0xffff);
669 rDescr.m_nIndex2 = static_cast<sal_uInt16>(index2 & 0xffff);
671 // Done.
672 return page::SCOPE_DOUBLE;
674 nPage -= nLimit;
676 // triple indirect.
677 nCount = OStoreDirectoryDataBlock::tripleCount;
678 nLimit = nCount * nCapacity * nCapacity * nCapacity;
679 if (nPage < nLimit)
681 // Page to index reduction.
682 sal_uInt32 n = nPage;
684 // Reduce to triple indirect i(3), double indirect n.
685 index3 = n / (nCapacity * nCapacity * nCapacity);
686 n = n % (nCapacity * nCapacity * nCapacity);
688 // Reduce to double indirect i(2), single indirect n.
689 index2 = n / (nCapacity * nCapacity);
690 n = n % (nCapacity * nCapacity);
692 // Reduce to single indirect i(1), direct n = i(0).
693 index1 = n / nCapacity;
694 index0 = n % nCapacity;
696 // Verify reduction.
697 n = index3 * nCapacity * nCapacity * nCapacity +
698 index2 * nCapacity * nCapacity +
699 index1 * nCapacity + index0;
700 if (n != nPage)
702 SAL_WARN("store", "wrong math on triple indirect indices");
703 return page::SCOPE_UNKNOWN;
706 // Setup LinkDescriptor indices.
707 rDescr.m_nIndex0 = static_cast<sal_uInt16>(index0 & 0xffff);
708 rDescr.m_nIndex1 = static_cast<sal_uInt16>(index1 & 0xffff);
709 rDescr.m_nIndex2 = static_cast<sal_uInt16>(index2 & 0xffff);
710 rDescr.m_nIndex3 = static_cast<sal_uInt16>(index3 & 0xffff);
712 // Done.
713 return page::SCOPE_TRIPLE;
716 // Unreachable (more than triple indirect).
717 return page::SCOPE_UNREACHABLE;
721 * read (external data page).
723 storeError OStoreDirectoryPageObject::read (
724 sal_uInt32 nPage,
725 OStoreDataPageObject &rData,
726 OStorePageBIOS &rBIOS) const
728 // Determine scope and link indices.
729 page::DataBlock::LinkDescriptor aLink;
730 page::ChunkScope eScope = scope (nPage, aLink);
732 storeError eErrCode = store_E_None;
733 if (eScope == page::SCOPE_DIRECT)
735 sal_uInt32 const nAddr = directLink (aLink.m_nIndex0);
736 if (nAddr == STORE_PAGE_NULL)
737 return store_E_NotExists;
739 eErrCode = rBIOS.loadObjectAt (rData, nAddr);
741 else if (eScope == page::SCOPE_SINGLE)
743 sal_uInt32 const nAddr = singleLink (aLink.m_nIndex1);
744 if (nAddr == STORE_PAGE_NULL)
745 return store_E_NotExists;
747 OStoreIndirectionPageObject aSingle;
748 eErrCode = rBIOS.loadObjectAt (aSingle, nAddr);
749 if (eErrCode != store_E_None)
750 return eErrCode;
752 eErrCode = aSingle.read (aLink.m_nIndex0, rData, rBIOS);
754 else if (eScope == page::SCOPE_DOUBLE)
756 sal_uInt32 const nAddr = doubleLink (aLink.m_nIndex2);
757 if (nAddr == STORE_PAGE_NULL)
758 return store_E_NotExists;
760 OStoreIndirectionPageObject aDouble;
761 eErrCode = rBIOS.loadObjectAt (aDouble, nAddr);
762 if (eErrCode != store_E_None)
763 return eErrCode;
765 eErrCode = aDouble.read (aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS);
767 else if (eScope == page::SCOPE_TRIPLE)
769 sal_uInt32 const nAddr = tripleLink (aLink.m_nIndex3);
770 if (nAddr == STORE_PAGE_NULL)
771 return store_E_NotExists;
773 OStoreIndirectionPageObject aTriple;
774 eErrCode = rBIOS.loadObjectAt (aTriple, nAddr);
775 if (eErrCode != store_E_None)
776 return eErrCode;
778 eErrCode = aTriple.read (aLink.m_nIndex2, aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS);
780 else if (eScope == page::SCOPE_UNREACHABLE)
782 // Out of scope.
783 eErrCode = store_E_CantSeek;
785 else
787 // Unknown scope.
788 SAL_WARN("store", "OStoreDirectoryPageObject::get(): scope failed");
789 eErrCode = store_E_Unknown;
792 // Leave.
793 return eErrCode;
797 * write (external data page).
799 storeError OStoreDirectoryPageObject::write (
800 sal_uInt32 nPage,
801 OStoreDataPageObject &rData,
802 OStorePageBIOS &rBIOS)
804 // Determine scope and link indices.
805 page::DataBlock::LinkDescriptor aLink;
806 page::ChunkScope eScope = scope (nPage, aLink);
808 storeError eErrCode = store_E_None;
809 if (eScope == page::SCOPE_DIRECT)
811 sal_uInt32 const nAddr = directLink (aLink.m_nIndex0);
812 if (nAddr == STORE_PAGE_NULL)
814 // Allocate data page.
815 eErrCode = rBIOS.allocate (rData);
816 if (eErrCode != store_E_None)
817 return eErrCode;
819 // Store data page location.
820 directLink (aLink.m_nIndex0, rData.location());
822 else
824 // Save data page.
825 eErrCode = rBIOS.saveObjectAt (rData, nAddr);
828 else if (eScope == page::SCOPE_SINGLE)
830 OStoreIndirectionPageObject aSingle;
831 eErrCode = aSingle.loadOrCreate (singleLink (aLink.m_nIndex1), rBIOS);
832 if (eErrCode != store_E_None)
834 if (eErrCode != store_E_Pending)
835 return eErrCode;
836 singleLink (aLink.m_nIndex1, aSingle.location());
839 eErrCode = aSingle.write (aLink.m_nIndex0, rData, rBIOS);
841 else if (eScope == page::SCOPE_DOUBLE)
843 OStoreIndirectionPageObject aDouble;
844 eErrCode = aDouble.loadOrCreate (doubleLink (aLink.m_nIndex2), rBIOS);
845 if (eErrCode != store_E_None)
847 if (eErrCode != store_E_Pending)
848 return eErrCode;
849 doubleLink (aLink.m_nIndex2, aDouble.location());
852 eErrCode = aDouble.write (aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS);
854 else if (eScope == page::SCOPE_TRIPLE)
856 OStoreIndirectionPageObject aTriple;
857 eErrCode = aTriple.loadOrCreate (tripleLink (aLink.m_nIndex3), rBIOS);
858 if (eErrCode != store_E_None)
860 if (eErrCode != store_E_Pending)
861 return eErrCode;
862 tripleLink (aLink.m_nIndex3, aTriple.location());
865 eErrCode = aTriple.write (aLink.m_nIndex2, aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS);
867 else if (eScope == page::SCOPE_UNREACHABLE)
869 // Out of scope.
870 eErrCode = store_E_CantSeek;
872 else
874 // Unknown scope.
875 SAL_WARN("store", "OStoreDirectoryPageObject::put(): scope failed");
876 eErrCode = store_E_Unknown;
879 // Leave.
880 return eErrCode;
884 * truncate (external data page).
886 storeError OStoreDirectoryPageObject::truncate (
887 sal_uInt32 nPage,
888 OStorePageBIOS &rBIOS)
890 // Determine scope and link indices.
891 page::DataBlock::LinkDescriptor aLink;
892 page::ChunkScope eScope = scope (nPage, aLink);
894 storeError eErrCode = store_E_None;
895 if (eScope == page::SCOPE_DIRECT)
897 // Truncate all triple indirect pages.
898 eErrCode = truncate (page::SCOPE_TRIPLE, 0, rBIOS);
899 if (eErrCode != store_E_None)
900 return eErrCode;
902 // Truncate all double indirect pages.
903 eErrCode = truncate (page::SCOPE_DOUBLE, 0, rBIOS);
904 if (eErrCode != store_E_None)
905 return eErrCode;
907 // Truncate all single indirect pages.
908 eErrCode = truncate (page::SCOPE_SINGLE, 0, rBIOS);
909 if (eErrCode != store_E_None)
910 return eErrCode;
912 // Truncate direct pages, including 'aLink.m_nIndex0'.
913 eErrCode = truncate (eScope, aLink.m_nIndex0, rBIOS);
915 else if (eScope == page::SCOPE_SINGLE)
917 // Truncate all triple indirect pages.
918 eErrCode = truncate (page::SCOPE_TRIPLE, 0, rBIOS);
919 if (eErrCode != store_E_None)
920 return eErrCode;
922 // Truncate all double indirect pages.
923 eErrCode = truncate (page::SCOPE_DOUBLE, 0, rBIOS);
924 if (eErrCode != store_E_None)
925 return eErrCode;
927 // Truncate single indirect pages, downto 'aLink.m_nIndex1'.
928 eErrCode = truncate (eScope, aLink.m_nIndex1 + 1, rBIOS);
929 if (eErrCode != store_E_None)
930 return eErrCode;
932 // Truncate last single indirect page to ... pages.
933 eErrCode = store_truncate_Impl (singleLink (aLink.m_nIndex1), aLink.m_nIndex0, rBIOS);
934 if (eErrCode != store_E_None)
935 return eErrCode;
937 // Check for complete truncation.
938 if (aLink.m_nIndex0 == 0)
940 // Clear pointer to last single indirect page.
941 singleLink (aLink.m_nIndex1, STORE_PAGE_NULL);
944 else if (eScope == page::SCOPE_DOUBLE)
946 // Truncate all triple indirect pages.
947 eErrCode = truncate (page::SCOPE_TRIPLE, 0, rBIOS);
948 if (eErrCode != store_E_None)
949 return eErrCode;
951 // Truncate double indirect pages, downto 'aLink.m_nIndex2'.
952 eErrCode = truncate (eScope, aLink.m_nIndex2 + 1, rBIOS);
953 if (eErrCode != store_E_None)
954 return eErrCode;
956 // Truncate last double indirect page to ... pages.
957 eErrCode = store_truncate_Impl (
958 doubleLink (aLink.m_nIndex2), aLink.m_nIndex1, aLink.m_nIndex0, rBIOS);
959 if (eErrCode != store_E_None)
960 return eErrCode;
962 // Check for complete truncation.
963 if ((aLink.m_nIndex1 + aLink.m_nIndex0) == 0)
965 // Clear pointer to last double indirect page.
966 doubleLink (aLink.m_nIndex2, STORE_PAGE_NULL);
969 else if (eScope == page::SCOPE_TRIPLE)
971 // Truncate triple indirect pages, downto 'aLink.m_nIndex3'.
972 eErrCode = truncate (eScope, aLink.m_nIndex3 + 1, rBIOS);
973 if (eErrCode != store_E_None)
974 return eErrCode;
976 // Truncate last triple indirect page to ... pages.
977 eErrCode = store_truncate_Impl (
978 tripleLink (aLink.m_nIndex3), aLink.m_nIndex2, aLink.m_nIndex1, aLink.m_nIndex0, rBIOS);
979 if (eErrCode != store_E_None)
980 return eErrCode;
982 // Check for complete truncation.
983 if ((aLink.m_nIndex2 + aLink.m_nIndex1 + aLink.m_nIndex0) == 0)
985 // Clear pointer to last triple indirect page.
986 tripleLink (aLink.m_nIndex3, STORE_PAGE_NULL);
989 else if (eScope == page::SCOPE_UNREACHABLE)
991 // Out of scope.
992 eErrCode = store_E_CantSeek;
994 else
996 // Unknown scope.
997 SAL_WARN("store", "OStoreDirectoryPageObject::put(): scope failed");
998 eErrCode = store_E_Unknown;
1001 // Leave.
1002 return eErrCode;
1006 * truncate (external data page scope; private).
1008 storeError OStoreDirectoryPageObject::truncate (
1009 page::ChunkScope eScope,
1010 sal_uInt16 nRemain,
1011 OStorePageBIOS &rBIOS)
1013 // Enter.
1014 storeError eErrCode = store_E_None;
1015 if (eScope == page::SCOPE_DIRECT)
1017 // Truncate direct data pages.
1018 for (sal_uInt16 i = OStoreDirectoryDataBlock::directCount; i > nRemain; i--)
1020 // Obtain data page location.
1021 sal_uInt32 nAddr = directLink (i - 1);
1022 if (nAddr == STORE_PAGE_NULL) continue;
1024 // Free data page.
1025 eErrCode = rBIOS.free (nAddr);
1026 if (eErrCode != store_E_None)
1027 break;
1029 // Clear pointer to data page.
1030 directLink (i - 1, STORE_PAGE_NULL);
1033 // Done.
1034 return eErrCode;
1037 if (eScope == page::SCOPE_SINGLE)
1039 // Truncate single indirect pages.
1040 for (sal_uInt16 i = OStoreDirectoryDataBlock::singleCount; i > nRemain; i--)
1042 // Truncate single indirect page to zero data pages.
1043 eErrCode = store_truncate_Impl (singleLink (i - 1), 0, rBIOS);
1044 if (eErrCode != store_E_None)
1045 break;
1047 // Clear pointer to single indirect page.
1048 singleLink (i - 1, STORE_PAGE_NULL);
1051 // Done.
1052 return eErrCode;
1055 if (eScope == page::SCOPE_DOUBLE)
1057 // Truncate double indirect pages.
1058 for (sal_uInt16 i = OStoreDirectoryDataBlock::doubleCount; i > nRemain; i--)
1060 // Truncate double indirect page to zero single indirect pages.
1061 eErrCode = store_truncate_Impl (doubleLink (i - 1), 0, 0, rBIOS);
1062 if (eErrCode != store_E_None)
1063 break;
1065 // Clear pointer to double indirect page.
1066 doubleLink (i - 1, STORE_PAGE_NULL);
1069 // Done.
1070 return eErrCode;
1073 if (eScope == page::SCOPE_TRIPLE)
1075 // Truncate triple indirect pages.
1076 for (sal_uInt16 i = OStoreDirectoryDataBlock::tripleCount; i > nRemain; i--)
1078 // Truncate to zero double indirect pages.
1079 eErrCode = store_truncate_Impl (tripleLink (i - 1), 0, 0, 0, rBIOS);
1080 if (eErrCode != store_E_None)
1081 break;
1083 // Clear pointer to triple indirect page.
1084 tripleLink (i - 1, STORE_PAGE_NULL);
1087 // Done.
1088 return eErrCode;
1091 // Invalid scope.
1092 return store_E_InvalidAccess;
1095 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */