1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_store.hxx"
26
27 #include "stordata.hxx"
28
29 #include "sal/types.h"
30 #include "osl/diagnose.h"
31
32 #include "store/types.h"
33 #include "storbase.hxx"
34 #include "storbios.hxx"
35
36 using namespace store;
37
38 /*========================================================================
39 *
40 * OStoreDataPageObject implementation.
41 *
42 *======================================================================*/
43 /*
44 * guard.
45 */
guard(sal_uInt32 nAddr)46 storeError OStoreDataPageObject::guard (sal_uInt32 nAddr)
47 {
48 return PageHolderObject< page >::guard (m_xPage, nAddr);
49 }
50
51 /*
52 * verify.
53 */
verify(sal_uInt32 nAddr) const54 storeError OStoreDataPageObject::verify (sal_uInt32 nAddr) const
55 {
56 return PageHolderObject< page >::verify (m_xPage, nAddr);
57 }
58
59 /*========================================================================
60 *
61 * OStoreIndirectionPageObject implementation.
62 *
63 *======================================================================*/
64 /*
65 * store_truncate_Impl (single indirect page).
66 */
store_truncate_Impl(sal_uInt32 nAddr,sal_uInt16 nSingle,OStorePageBIOS & rBIOS)67 static storeError store_truncate_Impl (
68 sal_uInt32 nAddr,
69 sal_uInt16 nSingle,
70 OStorePageBIOS &rBIOS)
71 {
72 if (nAddr != STORE_PAGE_NULL)
73 {
74 // Load single indirect page.
75 OStoreIndirectionPageObject aSingle;
76 storeError eErrCode = rBIOS.loadObjectAt (aSingle, nAddr);
77 if (eErrCode == store_E_None)
78 {
79 // Truncate to 'nSingle' direct pages.
80 eErrCode = aSingle.truncate (nSingle, rBIOS);
81 if (eErrCode != store_E_None)
82 return eErrCode;
83 }
84 else
85 {
86 if (eErrCode != store_E_InvalidChecksum)
87 return eErrCode;
88 }
89
90 // Check for complete truncation.
91 if (nSingle == 0)
92 {
93 // Free single indirect page.
94 eErrCode = rBIOS.free (nAddr);
95 if (eErrCode != store_E_None)
96 return eErrCode;
97 }
98 }
99 return store_E_None;
100 }
101
102 /*
103 * store_truncate_Impl (double indirect page).
104 */
store_truncate_Impl(sal_uInt32 nAddr,sal_uInt16 nDouble,sal_uInt16 nSingle,OStorePageBIOS & rBIOS)105 static storeError store_truncate_Impl (
106 sal_uInt32 nAddr,
107 sal_uInt16 nDouble,
108 sal_uInt16 nSingle,
109 OStorePageBIOS &rBIOS)
110 {
111 if (nAddr != STORE_PAGE_NULL)
112 {
113 // Load double indirect page.
114 OStoreIndirectionPageObject aDouble;
115 storeError eErrCode = rBIOS.loadObjectAt (aDouble, nAddr);
116 if (eErrCode == store_E_None)
117 {
118 // Truncate to 'nDouble', 'nSingle' pages.
119 eErrCode = aDouble.truncate (nDouble, nSingle, rBIOS);
120 if (eErrCode != store_E_None)
121 return eErrCode;
122 }
123 else
124 {
125 if (eErrCode != store_E_InvalidChecksum)
126 return eErrCode;
127 }
128
129 // Check for complete truncation.
130 if ((nDouble + nSingle) == 0)
131 {
132 // Free double indirect page.
133 eErrCode = rBIOS.free (nAddr);
134 if (eErrCode != store_E_None)
135 return eErrCode;
136 }
137 }
138 return store_E_None;
139 }
140
141 /*
142 * store_truncate_Impl (triple indirect page).
143 */
store_truncate_Impl(sal_uInt32 nAddr,sal_uInt16 nTriple,sal_uInt16 nDouble,sal_uInt16 nSingle,OStorePageBIOS & rBIOS)144 static storeError store_truncate_Impl (
145 sal_uInt32 nAddr,
146 sal_uInt16 nTriple,
147 sal_uInt16 nDouble,
148 sal_uInt16 nSingle,
149 OStorePageBIOS &rBIOS)
150 {
151 if (nAddr != STORE_PAGE_NULL)
152 {
153 // Load triple indirect page.
154 OStoreIndirectionPageObject aTriple;
155 storeError eErrCode = rBIOS.loadObjectAt (aTriple, nAddr);
156 if (eErrCode != store_E_None)
157 return eErrCode;
158
159 // Truncate to 'nTriple', 'nDouble', 'nSingle' pages.
160 eErrCode = aTriple.truncate (nTriple, nDouble, nSingle, rBIOS);
161 if (eErrCode != store_E_None)
162 return eErrCode;
163
164 // Check for complete truncation.
165 if ((nTriple + nDouble + nSingle) == 0)
166 {
167 // Free triple indirect page.
168 eErrCode = rBIOS.free (nAddr);
169 if (eErrCode != store_E_None)
170 return eErrCode;
171 }
172 }
173 return store_E_None;
174 }
175
176 /*
177 * loadOrCreate.
178 */
loadOrCreate(sal_uInt32 nAddr,OStorePageBIOS & rBIOS)179 storeError OStoreIndirectionPageObject::loadOrCreate (
180 sal_uInt32 nAddr,
181 OStorePageBIOS & rBIOS)
182 {
183 if (nAddr == STORE_PAGE_NULL)
184 {
185 storeError eErrCode = construct<page>(rBIOS.allocator());
186 if (eErrCode != store_E_None)
187 return eErrCode;
188
189 eErrCode = rBIOS.allocate (*this);
190 if (eErrCode != store_E_None)
191 return eErrCode;
192
193 // Save location pending at caller.
194 return store_E_Pending;
195 }
196 return rBIOS.loadObjectAt (*this, nAddr);
197 }
198
199 /*
200 * guard.
201 */
guard(sal_uInt32 nAddr)202 storeError OStoreIndirectionPageObject::guard (sal_uInt32 nAddr)
203 {
204 return PageHolderObject< page >::guard (m_xPage, nAddr);
205 }
206
207 /*
208 * verify.
209 */
verify(sal_uInt32 nAddr) const210 storeError OStoreIndirectionPageObject::verify (sal_uInt32 nAddr) const
211 {
212 return PageHolderObject< page >::verify (m_xPage, nAddr);
213 }
214
215 /*
216 * read (single indirect).
217 */
read(sal_uInt16 nSingle,OStoreDataPageObject & rData,OStorePageBIOS & rBIOS)218 storeError OStoreIndirectionPageObject::read (
219 sal_uInt16 nSingle,
220 OStoreDataPageObject &rData,
221 OStorePageBIOS &rBIOS)
222 {
223 PageHolderObject< page > xImpl (m_xPage);
224 page const & rPage = (*xImpl);
225
226 // Check arguments.
227 sal_uInt16 const nLimit = rPage.capacityCount();
228 if (!(nSingle < nLimit))
229 return store_E_InvalidAccess;
230
231 // Obtain data page location.
232 sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nSingle]);
233 if (nAddr == STORE_PAGE_NULL)
234 return store_E_NotExists;
235
236 // Load data page and leave.
237 return rBIOS.loadObjectAt (rData, nAddr);
238 }
239
240 /*
241 * read (double indirect).
242 */
read(sal_uInt16 nDouble,sal_uInt16 nSingle,OStoreDataPageObject & rData,OStorePageBIOS & rBIOS)243 storeError OStoreIndirectionPageObject::read (
244 sal_uInt16 nDouble,
245 sal_uInt16 nSingle,
246 OStoreDataPageObject &rData,
247 OStorePageBIOS &rBIOS)
248 {
249 PageHolderObject< page > xImpl (m_xPage);
250 page const & rPage = (*xImpl);
251
252 // Check arguments.
253 sal_uInt16 const nLimit = rPage.capacityCount();
254 if (!((nDouble < nLimit) && (nSingle < nLimit)))
255 return store_E_InvalidAccess;
256
257 // Check single indirect page location.
258 sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nDouble]);
259 if (nAddr == STORE_PAGE_NULL)
260 return store_E_NotExists;
261
262 // Load single indirect page.
263 OStoreIndirectionPageObject aSingle;
264 storeError eErrCode = rBIOS.loadObjectAt (aSingle, nAddr);
265 if (eErrCode != store_E_None)
266 return eErrCode;
267
268 // Read single indirect and leave.
269 return aSingle.read (nSingle, rData, rBIOS);
270 }
271
272 /*
273 * read (triple indirect).
274 */
read(sal_uInt16 nTriple,sal_uInt16 nDouble,sal_uInt16 nSingle,OStoreDataPageObject & rData,OStorePageBIOS & rBIOS)275 storeError OStoreIndirectionPageObject::read (
276 sal_uInt16 nTriple,
277 sal_uInt16 nDouble,
278 sal_uInt16 nSingle,
279 OStoreDataPageObject &rData,
280 OStorePageBIOS &rBIOS)
281 {
282 PageHolderObject< page > xImpl (m_xPage);
283 page const & rPage = (*xImpl);
284
285 // Check arguments.
286 sal_uInt16 const nLimit = rPage.capacityCount();
287 if (!((nTriple < nLimit) && (nDouble < nLimit) && (nSingle < nLimit)))
288 return store_E_InvalidAccess;
289
290 // Check double indirect page location.
291 sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nTriple]);
292 if (nAddr == STORE_PAGE_NULL)
293 return store_E_NotExists;
294
295 // Load double indirect page.
296 OStoreIndirectionPageObject aDouble;
297 storeError eErrCode = rBIOS.loadObjectAt (aDouble, nAddr);
298 if (eErrCode != store_E_None)
299 return eErrCode;
300
301 // Read double indirect and leave.
302 return aDouble.read (nDouble, nSingle, rData, rBIOS);
303 }
304
305 /*
306 * write (single indirect).
307 */
write(sal_uInt16 nSingle,OStoreDataPageObject & rData,OStorePageBIOS & rBIOS)308 storeError OStoreIndirectionPageObject::write (
309 sal_uInt16 nSingle,
310 OStoreDataPageObject &rData,
311 OStorePageBIOS &rBIOS)
312 {
313 PageHolderObject< page > xImpl (m_xPage);
314 page & rPage = (*xImpl);
315
316 // Check arguments.
317 sal_uInt16 const nLimit = rPage.capacityCount();
318 if (!(nSingle < nLimit))
319 return store_E_InvalidAccess;
320
321 // Obtain data page location.
322 sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nSingle]);
323 if (nAddr == STORE_PAGE_NULL)
324 {
325 // Allocate data page.
326 storeError eErrCode = rBIOS.allocate (rData);
327 if (eErrCode != store_E_None)
328 return eErrCode;
329
330 // Store data page location.
331 rPage.m_pData[nSingle] = store::htonl(rData.location());
332
333 // Save this page.
334 return rBIOS.saveObjectAt (*this, location());
335 }
336 else
337 {
338 // Save data page.
339 return rBIOS.saveObjectAt (rData, nAddr);
340 }
341 }
342
343 /*
344 * write (double indirect).
345 */
write(sal_uInt16 nDouble,sal_uInt16 nSingle,OStoreDataPageObject & rData,OStorePageBIOS & rBIOS)346 storeError OStoreIndirectionPageObject::write (
347 sal_uInt16 nDouble,
348 sal_uInt16 nSingle,
349 OStoreDataPageObject &rData,
350 OStorePageBIOS &rBIOS)
351 {
352 PageHolderObject< page > xImpl (m_xPage);
353 page & rPage = (*xImpl);
354
355 // Check arguments.
356 sal_uInt16 const nLimit = rPage.capacityCount();
357 if (!((nDouble < nLimit) && (nSingle < nLimit)))
358 return store_E_InvalidAccess;
359
360 // Load or create single indirect page.
361 OStoreIndirectionPageObject aSingle;
362 storeError eErrCode = aSingle.loadOrCreate (store::ntohl(rPage.m_pData[nDouble]), rBIOS);
363 if (eErrCode != store_E_None)
364 {
365 if (eErrCode != store_E_Pending)
366 return eErrCode;
367 rPage.m_pData[nDouble] = store::htonl(aSingle.location());
368
369 eErrCode = rBIOS.saveObjectAt (*this, location());
370 if (eErrCode != store_E_None)
371 return eErrCode;
372 }
373
374 // Write single indirect and leave.
375 return aSingle.write (nSingle, rData, rBIOS);
376 }
377
378 /*
379 * write (triple indirect).
380 */
write(sal_uInt16 nTriple,sal_uInt16 nDouble,sal_uInt16 nSingle,OStoreDataPageObject & rData,OStorePageBIOS & rBIOS)381 storeError OStoreIndirectionPageObject::write (
382 sal_uInt16 nTriple,
383 sal_uInt16 nDouble,
384 sal_uInt16 nSingle,
385 OStoreDataPageObject &rData,
386 OStorePageBIOS &rBIOS)
387 {
388 PageHolderObject< page > xImpl (m_xPage);
389 page & rPage = (*xImpl);
390
391 // Check arguments.
392 sal_uInt16 const nLimit = rPage.capacityCount();
393 if (!((nTriple < nLimit) && (nDouble < nLimit) && (nSingle < nLimit)))
394 return store_E_InvalidAccess;
395
396 // Load or create double indirect page.
397 OStoreIndirectionPageObject aDouble;
398 storeError eErrCode = aDouble.loadOrCreate (store::ntohl(rPage.m_pData[nTriple]), rBIOS);
399 if (eErrCode != store_E_None)
400 {
401 if (eErrCode != store_E_Pending)
402 return eErrCode;
403 rPage.m_pData[nTriple] = store::htonl(aDouble.location());
404
405 eErrCode = rBIOS.saveObjectAt (*this, location());
406 if (eErrCode != store_E_None)
407 return eErrCode;
408 }
409
410 // Write double indirect and leave.
411 return aDouble.write (nDouble, nSingle, rData, rBIOS);
412 }
413
414 /*
415 * truncate (single indirect).
416 */
truncate(sal_uInt16 nSingle,OStorePageBIOS & rBIOS)417 storeError OStoreIndirectionPageObject::truncate (
418 sal_uInt16 nSingle,
419 OStorePageBIOS & rBIOS)
420 {
421 PageHolderObject< page > xImpl (m_xPage);
422 page & rPage = (*xImpl);
423
424 // Check arguments.
425 sal_uInt16 const nLimit = rPage.capacityCount();
426 if (!(nSingle < nLimit))
427 return store_E_InvalidAccess;
428
429 // Truncate.
430 storeError eErrCode = store_E_None;
431 for (sal_uInt16 i = nLimit; i > nSingle; i--)
432 {
433 // Obtain data page location.
434 sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[i - 1]);
435 if (nAddr != STORE_PAGE_NULL)
436 {
437 // Free data page.
438 eErrCode = rBIOS.free (nAddr);
439 if (eErrCode != store_E_None)
440 return eErrCode;
441
442 // Clear pointer to data page.
443 rPage.m_pData[i - 1] = STORE_PAGE_NULL;
444 touch();
445 }
446 }
447
448 // Check for modified page.
449 if (dirty())
450 {
451 // Save this page.
452 eErrCode = rBIOS.saveObjectAt (*this, location());
453 }
454
455 // Done.
456 return eErrCode;
457 }
458
459 /*
460 * truncate (double indirect).
461 */
truncate(sal_uInt16 nDouble,sal_uInt16 nSingle,OStorePageBIOS & rBIOS)462 storeError OStoreIndirectionPageObject::truncate (
463 sal_uInt16 nDouble,
464 sal_uInt16 nSingle,
465 OStorePageBIOS &rBIOS)
466 {
467 PageHolderObject< page > xImpl (m_xPage);
468 page & rPage = (*xImpl);
469
470 // Check arguments.
471 sal_uInt16 const nLimit = rPage.capacityCount();
472 if (!((nDouble < nLimit) && (nSingle < nLimit)))
473 return store_E_InvalidAccess;
474
475 // Truncate.
476 storeError eErrCode = store_E_None;
477 for (sal_uInt16 i = nLimit; i > nDouble + 1; i--)
478 {
479 // Truncate single indirect page to zero direct pages.
480 eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[i - 1]), 0, rBIOS);
481 if (eErrCode != store_E_None)
482 return eErrCode;
483
484 // Clear pointer to single indirect page.
485 rPage.m_pData[i - 1] = STORE_PAGE_NULL;
486 touch();
487 }
488
489 // Truncate last single indirect page to 'nSingle' direct pages.
490 eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[nDouble]), nSingle, rBIOS);
491 if (eErrCode != store_E_None)
492 return eErrCode;
493
494 // Check for complete truncation.
495 if (nSingle == 0)
496 {
497 // Clear pointer to last single indirect page.
498 rPage.m_pData[nDouble] = STORE_PAGE_NULL;
499 touch();
500 }
501
502 // Check for modified page.
503 if (dirty())
504 {
505 // Save this page.
506 eErrCode = rBIOS.saveObjectAt (*this, location());
507 }
508
509 // Done.
510 return eErrCode;
511 }
512
513 /*
514 * truncate (triple indirect).
515 */
truncate(sal_uInt16 nTriple,sal_uInt16 nDouble,sal_uInt16 nSingle,OStorePageBIOS & rBIOS)516 storeError OStoreIndirectionPageObject::truncate (
517 sal_uInt16 nTriple,
518 sal_uInt16 nDouble,
519 sal_uInt16 nSingle,
520 OStorePageBIOS &rBIOS)
521 {
522 PageHolderObject< page > xImpl (m_xPage);
523 page & rPage = (*xImpl);
524
525 // Check arguments.
526 sal_uInt16 const nLimit = rPage.capacityCount();
527 if (!((nTriple < nLimit) && (nDouble < nLimit) && (nSingle < nLimit)))
528 return store_E_InvalidAccess;
529
530 // Truncate.
531 storeError eErrCode = store_E_None;
532 for (sal_uInt16 i = nLimit; i > nTriple + 1; i--)
533 {
534 // Truncate double indirect page to zero single indirect pages.
535 eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[i - 1]), 0, 0, rBIOS);
536 if (eErrCode != store_E_None)
537 return eErrCode;
538
539 // Clear pointer to double indirect page.
540 rPage.m_pData[i - 1] = STORE_PAGE_NULL;
541 touch();
542 }
543
544 // Truncate last double indirect page to 'nDouble', 'nSingle' pages.
545 eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[nTriple]), nDouble, nSingle, rBIOS);
546 if (eErrCode != store_E_None)
547 return eErrCode;
548
549 // Check for complete truncation.
550 if ((nDouble + nSingle) == 0)
551 {
552 // Clear pointer to last double indirect page.
553 rPage.m_pData[nTriple] = STORE_PAGE_NULL;
554 touch();
555 }
556
557 // Check for modified page.
558 if (dirty())
559 {
560 // Save this page.
561 eErrCode = rBIOS.saveObjectAt (*this, location());
562 }
563
564 // Done.
565 return eErrCode;
566 }
567
568 /*========================================================================
569 *
570 * OStoreDirectoryPageObject implementation.
571 *
572 *======================================================================*/
573 /*
574 * guard.
575 */
guard(sal_uInt32 nAddr)576 storeError OStoreDirectoryPageObject::guard (sal_uInt32 nAddr)
577 {
578 return PageHolderObject< page >::guard (m_xPage, nAddr);
579 }
580
581 /*
582 * verify.
583 */
verify(sal_uInt32 nAddr) const584 storeError OStoreDirectoryPageObject::verify (sal_uInt32 nAddr) const
585 {
586 return PageHolderObject< page >::verify (m_xPage, nAddr);
587 // OLD: m_rPage.verifyVersion (STORE_MAGIC_DIRECTORYPAGE);
588 }
589
590 /*
591 * scope (external data page; private).
592 */
593 OStoreDirectoryPageData::ChunkScope
scope(sal_uInt32 nPage,page::DataBlock::LinkDescriptor & rDescr) const594 OStoreDirectoryPageObject::scope (
595 sal_uInt32 nPage,
596 page::DataBlock::LinkDescriptor &rDescr) const
597 {
598 page const & rPage = PAGE();
599 OStoreDirectoryDataBlock const & rDataBlock = rPage.m_aDataBlock;
600
601 sal_uInt32 index0, index1, index2, index3;
602
603 // direct.
604 sal_uInt32 nCount = rDataBlock.directCount();
605 sal_uInt32 nLimit = nCount;
606 if (nPage < nLimit)
607 {
608 // Page to index reduction.
609 index0 = nPage;
610
611 // Setup LinkDescriptor indices.
612 rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff);
613
614 // Done.
615 return page::SCOPE_DIRECT;
616 }
617 nPage -= nLimit;
618
619 // single indirect.
620 sal_uInt32 const nCapacity = indirect::capacityCount(rPage.m_aDescr);
621 nCount = rDataBlock.singleCount();
622 nLimit = nCount * nCapacity;
623 if (nPage < nLimit)
624 {
625 // Page to index reduction.
626 sal_uInt32 n = nPage;
627
628 // Reduce to single indirect i(1), direct n = i(0).
629 index1 = n / nCapacity;
630 index0 = n % nCapacity;
631
632 // Verify reduction.
633 n = index1 * nCapacity + index0;
634 OSL_POSTCOND(n == nPage, "wrong math on indirect indices");
635 if (n != nPage)
636 return page::SCOPE_UNKNOWN;
637
638 // Setup LinkDescriptor indices.
639 rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff);
640 rDescr.m_nIndex1 = (sal_uInt16)(index1 & 0xffff);
641
642 // Done.
643 return page::SCOPE_SINGLE;
644 }
645 nPage -= nLimit;
646
647 // double indirect.
648 nCount = rDataBlock.doubleCount();
649 nLimit = nCount * nCapacity * nCapacity;
650 if (nPage < nLimit)
651 {
652 // Page to index reduction.
653 sal_uInt32 n = nPage;
654
655 // Reduce to double indirect i(2), single indirect n = i(0).
656 index2 = n / (nCapacity * nCapacity);
657 n = n % (nCapacity * nCapacity);
658
659 // Reduce to single indirect i(1), direct n = i(0).
660 index1 = n / nCapacity;
661 index0 = n % nCapacity;
662
663 // Verify reduction.
664 n = index2 * nCapacity * nCapacity +
665 index1 * nCapacity + index0;
666 OSL_POSTCOND(n == nPage, "wrong math on double indirect indices");
667 if (n != nPage)
668 return page::SCOPE_UNKNOWN;
669
670 // Setup LinkDescriptor indices.
671 rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff);
672 rDescr.m_nIndex1 = (sal_uInt16)(index1 & 0xffff);
673 rDescr.m_nIndex2 = (sal_uInt16)(index2 & 0xffff);
674
675 // Done.
676 return page::SCOPE_DOUBLE;
677 }
678 nPage -= nLimit;
679
680 // triple indirect.
681 nCount = rDataBlock.tripleCount();
682 nLimit = nCount * nCapacity * nCapacity * nCapacity;
683 if (nPage < nLimit)
684 {
685 // Page to index reduction.
686 sal_uInt32 n = nPage;
687
688 // Reduce to triple indirect i(3), double indirect n.
689 index3 = n / (nCapacity * nCapacity * nCapacity);
690 n = n % (nCapacity * nCapacity * nCapacity);
691
692 // Reduce to double indirect i(2), single indirect n.
693 index2 = n / (nCapacity * nCapacity);
694 n = n % (nCapacity * nCapacity);
695
696 // Reduce to single indirect i(1), direct n = i(0).
697 index1 = n / nCapacity;
698 index0 = n % nCapacity;
699
700 // Verify reduction.
701 n = index3 * nCapacity * nCapacity * nCapacity +
702 index2 * nCapacity * nCapacity +
703 index1 * nCapacity + index0;
704 OSL_POSTCOND(n == nPage, "wrong math on triple indirect indices");
705 if (n != nPage)
706 return page::SCOPE_UNKNOWN;
707
708 // Setup LinkDescriptor indices.
709 rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff);
710 rDescr.m_nIndex1 = (sal_uInt16)(index1 & 0xffff);
711 rDescr.m_nIndex2 = (sal_uInt16)(index2 & 0xffff);
712 rDescr.m_nIndex3 = (sal_uInt16)(index3 & 0xffff);
713
714 // Done.
715 return page::SCOPE_TRIPLE;
716 }
717
718 // Unreachable (more than triple indirect).
719 return page::SCOPE_UNREACHABLE;
720 }
721
722 #if 0 /* NYI */
723 /*
724 * chunk (external data page).
725 */
726 inode::ChunkDescriptor OStoreDirectoryPageObject::chunk (sal_uInt32 nOffset)
727 {
728 // @@@ INSUFFICIENT: NEED SCOPE AS WELL @@@
729 sal_uInt32 nCapacity = m_rPage.capacity();
730 if (nOffset < nCapacity)
731 // Internal scope (inode page).
732 return inode::ChunkDescriptor (nOffset, nCapacity);
733 else
734 // External scope (data page).
735 return inode::ChunkDescriptor (nOffset - nCapacity, data::capacity(m_rPage.m_aDescr));
736
737 inode::ChunkScope eScope = m_rPage.scope(nOffset);
738 if (eScope == inode::SCOPE_INTERNAL)
739 // Inode page (internal scope).
740 return inode::ChunkDescriptor (nOffset, m_rPage.capacity());
741 else
742 // Data page (external scope).
743 return inode::ChunkDescriptor (nOffset - m_rPage.capacity(), data::capacity(m_rPage.m_aDescr));
744 }
745 #endif /* NYI */
746
747 /*
748 * read (external data page).
749 */
read(sal_uInt32 nPage,OStoreDataPageObject & rData,OStorePageBIOS & rBIOS)750 storeError OStoreDirectoryPageObject::read (
751 sal_uInt32 nPage,
752 OStoreDataPageObject &rData,
753 OStorePageBIOS &rBIOS)
754 {
755 // Determine scope and link indices.
756 page::DataBlock::LinkDescriptor aLink;
757 page::ChunkScope eScope = scope (nPage, aLink);
758
759 storeError eErrCode = store_E_None;
760 if (eScope == page::SCOPE_DIRECT)
761 {
762 sal_uInt32 const nAddr = directLink (aLink.m_nIndex0);
763 if (nAddr == STORE_PAGE_NULL)
764 return store_E_NotExists;
765
766 eErrCode = rBIOS.loadObjectAt (rData, nAddr);
767 }
768 else if (eScope == page::SCOPE_SINGLE)
769 {
770 sal_uInt32 const nAddr = singleLink (aLink.m_nIndex1);
771 if (nAddr == STORE_PAGE_NULL)
772 return store_E_NotExists;
773
774 OStoreIndirectionPageObject aSingle;
775 eErrCode = rBIOS.loadObjectAt (aSingle, nAddr);
776 if (eErrCode != store_E_None)
777 return eErrCode;
778
779 eErrCode = aSingle.read (aLink.m_nIndex0, rData, rBIOS);
780 }
781 else if (eScope == page::SCOPE_DOUBLE)
782 {
783 sal_uInt32 const nAddr = doubleLink (aLink.m_nIndex2);
784 if (nAddr == STORE_PAGE_NULL)
785 return store_E_NotExists;
786
787 OStoreIndirectionPageObject aDouble;
788 eErrCode = rBIOS.loadObjectAt (aDouble, nAddr);
789 if (eErrCode != store_E_None)
790 return eErrCode;
791
792 eErrCode = aDouble.read (aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS);
793 }
794 else if (eScope == page::SCOPE_TRIPLE)
795 {
796 sal_uInt32 const nAddr = tripleLink (aLink.m_nIndex3);
797 if (nAddr == STORE_PAGE_NULL)
798 return store_E_NotExists;
799
800 OStoreIndirectionPageObject aTriple;
801 eErrCode = rBIOS.loadObjectAt (aTriple, nAddr);
802 if (eErrCode != store_E_None)
803 return eErrCode;
804
805 eErrCode = aTriple.read (aLink.m_nIndex2, aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS);
806 }
807 else if (eScope == page::SCOPE_UNREACHABLE)
808 {
809 // Out of scope.
810 eErrCode = store_E_CantSeek;
811 }
812 else
813 {
814 // Unknown scope.
815 OSL_TRACE("OStoreDirectoryPageObject::get(): scope failed");
816 eErrCode = store_E_Unknown;
817 }
818
819 // Leave.
820 return eErrCode;
821 }
822
823 /*
824 * write (external data page).
825 */
write(sal_uInt32 nPage,OStoreDataPageObject & rData,OStorePageBIOS & rBIOS)826 storeError OStoreDirectoryPageObject::write (
827 sal_uInt32 nPage,
828 OStoreDataPageObject &rData,
829 OStorePageBIOS &rBIOS)
830 {
831 // Determine scope and link indices.
832 page::DataBlock::LinkDescriptor aLink;
833 page::ChunkScope eScope = scope (nPage, aLink);
834
835 storeError eErrCode = store_E_None;
836 if (eScope == page::SCOPE_DIRECT)
837 {
838 sal_uInt32 const nAddr = directLink (aLink.m_nIndex0);
839 if (nAddr == STORE_PAGE_NULL)
840 {
841 // Allocate data page.
842 eErrCode = rBIOS.allocate (rData);
843 if (eErrCode != store_E_None)
844 return eErrCode;
845
846 // Store data page location.
847 directLink (aLink.m_nIndex0, rData.location());
848 }
849 else
850 {
851 // Save data page.
852 eErrCode = rBIOS.saveObjectAt (rData, nAddr);
853 }
854 }
855 else if (eScope == page::SCOPE_SINGLE)
856 {
857 OStoreIndirectionPageObject aSingle;
858 eErrCode = aSingle.loadOrCreate (singleLink (aLink.m_nIndex1), rBIOS);
859 if (eErrCode != store_E_None)
860 {
861 if (eErrCode != store_E_Pending)
862 return eErrCode;
863 singleLink (aLink.m_nIndex1, aSingle.location());
864 }
865
866 eErrCode = aSingle.write (aLink.m_nIndex0, rData, rBIOS);
867 }
868 else if (eScope == page::SCOPE_DOUBLE)
869 {
870 OStoreIndirectionPageObject aDouble;
871 eErrCode = aDouble.loadOrCreate (doubleLink (aLink.m_nIndex2), rBIOS);
872 if (eErrCode != store_E_None)
873 {
874 if (eErrCode != store_E_Pending)
875 return eErrCode;
876 doubleLink (aLink.m_nIndex2, aDouble.location());
877 }
878
879 eErrCode = aDouble.write (aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS);
880 }
881 else if (eScope == page::SCOPE_TRIPLE)
882 {
883 OStoreIndirectionPageObject aTriple;
884 eErrCode = aTriple.loadOrCreate (tripleLink (aLink.m_nIndex3), rBIOS);
885 if (eErrCode != store_E_None)
886 {
887 if (eErrCode != store_E_Pending)
888 return eErrCode;
889 tripleLink (aLink.m_nIndex3, aTriple.location());
890 }
891
892 eErrCode = aTriple.write (aLink.m_nIndex2, aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS);
893 }
894 else if (eScope == page::SCOPE_UNREACHABLE)
895 {
896 // Out of scope.
897 eErrCode = store_E_CantSeek;
898 }
899 else
900 {
901 // Unknown scope.
902 OSL_TRACE("OStoreDirectoryPageObject::put(): scope failed");
903 eErrCode = store_E_Unknown;
904 }
905
906 // Leave.
907 return eErrCode;
908 }
909
910 /*
911 * truncate (external data page).
912 */
truncate(sal_uInt32 nPage,OStorePageBIOS & rBIOS)913 storeError OStoreDirectoryPageObject::truncate (
914 sal_uInt32 nPage,
915 OStorePageBIOS &rBIOS)
916 {
917 // Determine scope and link indices.
918 page::DataBlock::LinkDescriptor aLink;
919 page::ChunkScope eScope = scope (nPage, aLink);
920
921 storeError eErrCode = store_E_None;
922 if (eScope == page::SCOPE_DIRECT)
923 {
924 // Truncate all triple indirect pages.
925 eErrCode = truncate (page::SCOPE_TRIPLE, 0, rBIOS);
926 if (eErrCode != store_E_None)
927 return eErrCode;
928
929 // Truncate all double indirect pages.
930 eErrCode = truncate (page::SCOPE_DOUBLE, 0, rBIOS);
931 if (eErrCode != store_E_None)
932 return eErrCode;
933
934 // Truncate all single indirect pages.
935 eErrCode = truncate (page::SCOPE_SINGLE, 0, rBIOS);
936 if (eErrCode != store_E_None)
937 return eErrCode;
938
939 // Truncate direct pages, including 'aLink.m_nIndex0'.
940 eErrCode = truncate (eScope, aLink.m_nIndex0, rBIOS);
941 }
942 else if (eScope == page::SCOPE_SINGLE)
943 {
944 // Truncate all triple indirect pages.
945 eErrCode = truncate (page::SCOPE_TRIPLE, 0, rBIOS);
946 if (eErrCode != store_E_None)
947 return eErrCode;
948
949 // Truncate all double indirect pages.
950 eErrCode = truncate (page::SCOPE_DOUBLE, 0, rBIOS);
951 if (eErrCode != store_E_None)
952 return eErrCode;
953
954 // Truncate single indirect pages, downto 'aLink.m_nIndex1'.
955 eErrCode = truncate (eScope, aLink.m_nIndex1 + 1, rBIOS);
956 if (eErrCode != store_E_None)
957 return eErrCode;
958
959 // Truncate last single indirect page to ... pages.
960 eErrCode = store_truncate_Impl (singleLink (aLink.m_nIndex1), aLink.m_nIndex0, rBIOS);
961 if (eErrCode != store_E_None)
962 return eErrCode;
963
964 // Check for complete truncation.
965 if (aLink.m_nIndex0 == 0)
966 {
967 // Clear pointer to last single indirect page.
968 singleLink (aLink.m_nIndex1, STORE_PAGE_NULL);
969 }
970 }
971 else if (eScope == page::SCOPE_DOUBLE)
972 {
973 // Truncate all triple indirect pages.
974 eErrCode = truncate (page::SCOPE_TRIPLE, 0, rBIOS);
975 if (eErrCode != store_E_None)
976 return eErrCode;
977
978 // Truncate double indirect pages, downto 'aLink.m_nIndex2'.
979 eErrCode = truncate (eScope, aLink.m_nIndex2 + 1, rBIOS);
980 if (eErrCode != store_E_None)
981 return eErrCode;
982
983 // Truncate last double indirect page to ... pages.
984 eErrCode = store_truncate_Impl (
985 doubleLink (aLink.m_nIndex2), aLink.m_nIndex1, aLink.m_nIndex0, rBIOS);
986 if (eErrCode != store_E_None)
987 return eErrCode;
988
989 // Check for complete truncation.
990 if ((aLink.m_nIndex1 + aLink.m_nIndex0) == 0)
991 {
992 // Clear pointer to last double indirect page.
993 doubleLink (aLink.m_nIndex2, STORE_PAGE_NULL);
994 }
995 }
996 else if (eScope == page::SCOPE_TRIPLE)
997 {
998 // Truncate triple indirect pages, downto 'aLink.m_nIndex3'.
999 eErrCode = truncate (eScope, aLink.m_nIndex3 + 1, rBIOS);
1000 if (eErrCode != store_E_None)
1001 return eErrCode;
1002
1003 // Truncate last triple indirect page to ... pages.
1004 eErrCode = store_truncate_Impl (
1005 tripleLink (aLink.m_nIndex3), aLink.m_nIndex2, aLink.m_nIndex1, aLink.m_nIndex0, rBIOS);
1006 if (eErrCode != store_E_None)
1007 return eErrCode;
1008
1009 // Check for complete truncation.
1010 if ((aLink.m_nIndex2 + aLink.m_nIndex1 + aLink.m_nIndex0) == 0)
1011 {
1012 // Clear pointer to last triple indirect page.
1013 tripleLink (aLink.m_nIndex3, STORE_PAGE_NULL);
1014 }
1015 }
1016 else if (eScope == page::SCOPE_UNREACHABLE)
1017 {
1018 // Out of scope.
1019 eErrCode = store_E_CantSeek;
1020 }
1021 else
1022 {
1023 // Unknown scope.
1024 OSL_TRACE("OStoreDirectoryPageObject::put(): scope failed");
1025 eErrCode = store_E_Unknown;
1026 }
1027
1028 // Leave.
1029 return eErrCode;
1030 }
1031
1032 /*
1033 * truncate (external data page scope; private).
1034 */
truncate(page::ChunkScope eScope,sal_uInt16 nRemain,OStorePageBIOS & rBIOS)1035 storeError OStoreDirectoryPageObject::truncate (
1036 page::ChunkScope eScope,
1037 sal_uInt16 nRemain,
1038 OStorePageBIOS &rBIOS)
1039 {
1040 OStoreDirectoryDataBlock const & rDataBlock = PAGE().m_aDataBlock;
1041
1042 // Enter.
1043 storeError eErrCode = store_E_None;
1044 if (eScope == page::SCOPE_DIRECT)
1045 {
1046 // Truncate direct data pages.
1047 sal_uInt16 i, n = rDataBlock.directCount();
1048 for (i = n; i > nRemain; i--)
1049 {
1050 // Obtain data page location.
1051 sal_uInt32 nAddr = directLink (i - 1);
1052 if (nAddr == STORE_PAGE_NULL) continue;
1053
1054 // Free data page.
1055 eErrCode = rBIOS.free (nAddr);
1056 if (eErrCode != store_E_None)
1057 break;
1058
1059 // Clear pointer to data page.
1060 directLink (i - 1, STORE_PAGE_NULL);
1061 }
1062
1063 // Done.
1064 return eErrCode;
1065 }
1066
1067 if (eScope == page::SCOPE_SINGLE)
1068 {
1069 // Truncate single indirect pages.
1070 sal_uInt16 i, n = rDataBlock.singleCount();
1071 for (i = n; i > nRemain; i--)
1072 {
1073 // Truncate single indirect page to zero data pages.
1074 eErrCode = store_truncate_Impl (singleLink (i - 1), 0, rBIOS);
1075 if (eErrCode != store_E_None)
1076 break;
1077
1078 // Clear pointer to single indirect page.
1079 singleLink (i - 1, STORE_PAGE_NULL);
1080 }
1081
1082 // Done.
1083 return eErrCode;
1084 }
1085
1086 if (eScope == page::SCOPE_DOUBLE)
1087 {
1088 // Truncate double indirect pages.
1089 sal_uInt16 i, n = rDataBlock.doubleCount();
1090 for (i = n; i > nRemain; i--)
1091 {
1092 // Truncate double indirect page to zero single indirect pages.
1093 eErrCode = store_truncate_Impl (doubleLink (i - 1), 0, 0, rBIOS);
1094 if (eErrCode != store_E_None)
1095 break;
1096
1097 // Clear pointer to double indirect page.
1098 doubleLink (i - 1, STORE_PAGE_NULL);
1099 }
1100
1101 // Done.
1102 return eErrCode;
1103 }
1104
1105 if (eScope == page::SCOPE_TRIPLE)
1106 {
1107 // Truncate triple indirect pages.
1108 sal_uInt16 i, n = rDataBlock.tripleCount();
1109 for (i = n; i > nRemain; i--)
1110 {
1111 // Truncate to zero double indirect pages.
1112 eErrCode = store_truncate_Impl (tripleLink (i - 1), 0, 0, 0, rBIOS);
1113 if (eErrCode != store_E_None)
1114 break;
1115
1116 // Clear pointer to triple indirect page.
1117 tripleLink (i - 1, STORE_PAGE_NULL);
1118 }
1119
1120 // Done.
1121 return eErrCode;
1122 }
1123
1124 // Invalid scope.
1125 return store_E_InvalidAccess;
1126 }
1127