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