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