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 "sal/log.hxx"
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 238 : storeError OStoreDataPageObject::guard (sal_uInt32 nAddr)
41 : {
42 238 : return PageHolderObject< page >::guard (m_xPage, nAddr);
43 : }
44 :
45 : /*
46 : * verify.
47 : */
48 0 : storeError OStoreDataPageObject::verify (sal_uInt32 nAddr) const
49 : {
50 0 : 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 16 : static storeError store_truncate_Impl (
62 : sal_uInt32 nAddr,
63 : sal_uInt16 nSingle,
64 : OStorePageBIOS &rBIOS)
65 : {
66 16 : 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 16 : return store_E_None;
94 : }
95 :
96 : /*
97 : * store_truncate_Impl (double indirect page).
98 : */
99 2 : static storeError store_truncate_Impl (
100 : sal_uInt32 nAddr,
101 : sal_uInt16 nDouble,
102 : sal_uInt16 nSingle,
103 : OStorePageBIOS &rBIOS)
104 : {
105 2 : 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 2 : return store_E_None;
133 : }
134 :
135 : /*
136 : * store_truncate_Impl (triple indirect page).
137 : */
138 2 : 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 2 : 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 2 : return store_E_None;
168 : }
169 :
170 : /*
171 : * loadOrCreate.
172 : */
173 0 : storeError OStoreIndirectionPageObject::loadOrCreate (
174 : sal_uInt32 nAddr,
175 : OStorePageBIOS & rBIOS)
176 : {
177 0 : if (nAddr == STORE_PAGE_NULL)
178 : {
179 0 : storeError eErrCode = construct<page>(rBIOS.allocator());
180 0 : if (eErrCode != store_E_None)
181 0 : return eErrCode;
182 :
183 0 : eErrCode = rBIOS.allocate (*this);
184 0 : if (eErrCode != store_E_None)
185 0 : return eErrCode;
186 :
187 : // Save location pending at caller.
188 0 : return store_E_Pending;
189 : }
190 0 : return rBIOS.loadObjectAt (*this, nAddr);
191 : }
192 :
193 : /*
194 : * guard.
195 : */
196 0 : storeError OStoreIndirectionPageObject::guard (sal_uInt32 nAddr)
197 : {
198 0 : return PageHolderObject< page >::guard (m_xPage, nAddr);
199 : }
200 :
201 : /*
202 : * verify.
203 : */
204 0 : storeError OStoreIndirectionPageObject::verify (sal_uInt32 nAddr) const
205 : {
206 0 : return PageHolderObject< page >::verify (m_xPage, nAddr);
207 : }
208 :
209 : /*
210 : * read (single indirect).
211 : */
212 0 : storeError OStoreIndirectionPageObject::read (
213 : sal_uInt16 nSingle,
214 : OStoreDataPageObject &rData,
215 : OStorePageBIOS &rBIOS)
216 : {
217 0 : PageHolderObject< page > xImpl (m_xPage);
218 0 : page const & rPage = (*xImpl);
219 :
220 : // Check arguments.
221 0 : sal_uInt16 const nLimit = rPage.capacityCount();
222 0 : if (!(nSingle < nLimit))
223 0 : return store_E_InvalidAccess;
224 :
225 : // Obtain data page location.
226 0 : sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nSingle]);
227 0 : if (nAddr == STORE_PAGE_NULL)
228 0 : return store_E_NotExists;
229 :
230 : // Load data page and leave.
231 0 : 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 0 : storeError OStoreIndirectionPageObject::write (
303 : sal_uInt16 nSingle,
304 : OStoreDataPageObject &rData,
305 : OStorePageBIOS &rBIOS)
306 : {
307 0 : PageHolderObject< page > xImpl (m_xPage);
308 0 : page & rPage = (*xImpl);
309 :
310 : // Check arguments.
311 0 : sal_uInt16 const nLimit = rPage.capacityCount();
312 0 : if (!(nSingle < nLimit))
313 0 : return store_E_InvalidAccess;
314 :
315 : // Obtain data page location.
316 0 : sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nSingle]);
317 0 : if (nAddr == STORE_PAGE_NULL)
318 : {
319 : // Allocate data page.
320 0 : storeError eErrCode = rBIOS.allocate (rData);
321 0 : if (eErrCode != store_E_None)
322 0 : return eErrCode;
323 :
324 : // Store data page location.
325 0 : rPage.m_pData[nSingle] = store::htonl(rData.location());
326 :
327 : // Save this page.
328 0 : return rBIOS.saveObjectAt (*this, location());
329 : }
330 : else
331 : {
332 : // Save data page.
333 0 : return rBIOS.saveObjectAt (rData, nAddr);
334 0 : }
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 2714 : storeError OStoreDirectoryPageObject::guard (sal_uInt32 nAddr)
571 : {
572 2714 : return PageHolderObject< page >::guard (m_xPage, nAddr);
573 : }
574 :
575 : /*
576 : * verify.
577 : */
578 0 : storeError OStoreDirectoryPageObject::verify (sal_uInt32 nAddr) const
579 : {
580 0 : 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 474 : OStoreDirectoryPageObject::scope (
589 : sal_uInt32 nPage,
590 : page::DataBlock::LinkDescriptor &rDescr) const
591 : {
592 474 : page const & rPage = PAGE();
593 :
594 : sal_uInt32 index0, index1, index2, index3;
595 :
596 : // direct.
597 474 : sal_uInt32 nCount = OStoreDirectoryDataBlock::directCount();
598 474 : sal_uInt32 nLimit = nCount;
599 474 : if (nPage < nLimit)
600 : {
601 : // Page to index reduction.
602 474 : index0 = nPage;
603 :
604 : // Setup LinkDescriptor indices.
605 474 : rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff);
606 :
607 : // Done.
608 474 : 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 = OStoreDirectoryDataBlock::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 0 : if (n != nPage)
628 : {
629 : SAL_WARN("store", "wrong math on indirect indices");
630 0 : return page::SCOPE_UNKNOWN;
631 : }
632 :
633 : // Setup LinkDescriptor indices.
634 0 : rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff);
635 0 : rDescr.m_nIndex1 = (sal_uInt16)(index1 & 0xffff);
636 :
637 : // Done.
638 0 : return page::SCOPE_SINGLE;
639 : }
640 0 : nPage -= nLimit;
641 :
642 : // double indirect.
643 0 : nCount = OStoreDirectoryDataBlock::doubleCount();
644 0 : nLimit = nCount * nCapacity * nCapacity;
645 0 : if (nPage < nLimit)
646 : {
647 : // Page to index reduction.
648 0 : sal_uInt32 n = nPage;
649 :
650 : // Reduce to double indirect i(2), single indirect n = i(0).
651 0 : index2 = n / (nCapacity * nCapacity);
652 0 : n = n % (nCapacity * nCapacity);
653 :
654 : // Reduce to single indirect i(1), direct n = i(0).
655 0 : index1 = n / nCapacity;
656 0 : index0 = n % nCapacity;
657 :
658 : // Verify reduction.
659 0 : n = index2 * nCapacity * nCapacity +
660 0 : index1 * nCapacity + index0;
661 0 : if (n != nPage)
662 : {
663 : SAL_WARN("store", "wrong math on double indirect indices");
664 0 : return page::SCOPE_UNKNOWN;
665 : }
666 :
667 : // Setup LinkDescriptor indices.
668 0 : rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff);
669 0 : rDescr.m_nIndex1 = (sal_uInt16)(index1 & 0xffff);
670 0 : rDescr.m_nIndex2 = (sal_uInt16)(index2 & 0xffff);
671 :
672 : // Done.
673 0 : return page::SCOPE_DOUBLE;
674 : }
675 0 : nPage -= nLimit;
676 :
677 : // triple indirect.
678 0 : nCount = OStoreDirectoryDataBlock::tripleCount();
679 0 : nLimit = nCount * nCapacity * nCapacity * nCapacity;
680 0 : if (nPage < nLimit)
681 : {
682 : // Page to index reduction.
683 0 : sal_uInt32 n = nPage;
684 :
685 : // Reduce to triple indirect i(3), double indirect n.
686 0 : index3 = n / (nCapacity * nCapacity * nCapacity);
687 0 : n = n % (nCapacity * nCapacity * nCapacity);
688 :
689 : // Reduce to double indirect i(2), single indirect n.
690 0 : index2 = n / (nCapacity * nCapacity);
691 0 : n = n % (nCapacity * nCapacity);
692 :
693 : // Reduce to single indirect i(1), direct n = i(0).
694 0 : index1 = n / nCapacity;
695 0 : index0 = n % nCapacity;
696 :
697 : // Verify reduction.
698 0 : n = index3 * nCapacity * nCapacity * nCapacity +
699 0 : index2 * nCapacity * nCapacity +
700 0 : index1 * nCapacity + index0;
701 0 : if (n != nPage)
702 : {
703 : SAL_WARN("store", "wrong math on triple indirect indices");
704 0 : return page::SCOPE_UNKNOWN;
705 : }
706 :
707 : // Setup LinkDescriptor indices.
708 0 : rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff);
709 0 : rDescr.m_nIndex1 = (sal_uInt16)(index1 & 0xffff);
710 0 : rDescr.m_nIndex2 = (sal_uInt16)(index2 & 0xffff);
711 0 : rDescr.m_nIndex3 = (sal_uInt16)(index3 & 0xffff);
712 :
713 : // Done.
714 0 : return page::SCOPE_TRIPLE;
715 : }
716 :
717 : // Unreachable (more than triple indirect).
718 0 : return page::SCOPE_UNREACHABLE;
719 : }
720 :
721 : /*
722 : * read (external data page).
723 : */
724 234 : storeError OStoreDirectoryPageObject::read (
725 : sal_uInt32 nPage,
726 : OStoreDataPageObject &rData,
727 : OStorePageBIOS &rBIOS)
728 : {
729 : // Determine scope and link indices.
730 234 : page::DataBlock::LinkDescriptor aLink;
731 234 : page::ChunkScope eScope = scope (nPage, aLink);
732 :
733 234 : storeError eErrCode = store_E_None;
734 234 : if (eScope == page::SCOPE_DIRECT)
735 : {
736 234 : sal_uInt32 const nAddr = directLink (aLink.m_nIndex0);
737 234 : if (nAddr == STORE_PAGE_NULL)
738 232 : return store_E_NotExists;
739 :
740 2 : eErrCode = rBIOS.loadObjectAt (rData, nAddr);
741 : }
742 0 : else if (eScope == page::SCOPE_SINGLE)
743 : {
744 0 : sal_uInt32 const nAddr = singleLink (aLink.m_nIndex1);
745 0 : if (nAddr == STORE_PAGE_NULL)
746 0 : return store_E_NotExists;
747 :
748 0 : OStoreIndirectionPageObject aSingle;
749 0 : eErrCode = rBIOS.loadObjectAt (aSingle, nAddr);
750 0 : if (eErrCode != store_E_None)
751 0 : return eErrCode;
752 :
753 0 : eErrCode = aSingle.read (aLink.m_nIndex0, rData, rBIOS);
754 : }
755 0 : else if (eScope == page::SCOPE_DOUBLE)
756 : {
757 0 : sal_uInt32 const nAddr = doubleLink (aLink.m_nIndex2);
758 0 : if (nAddr == STORE_PAGE_NULL)
759 0 : return store_E_NotExists;
760 :
761 0 : OStoreIndirectionPageObject aDouble;
762 0 : eErrCode = rBIOS.loadObjectAt (aDouble, nAddr);
763 0 : if (eErrCode != store_E_None)
764 0 : return eErrCode;
765 :
766 0 : eErrCode = aDouble.read (aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS);
767 : }
768 0 : else if (eScope == page::SCOPE_TRIPLE)
769 : {
770 0 : sal_uInt32 const nAddr = tripleLink (aLink.m_nIndex3);
771 0 : if (nAddr == STORE_PAGE_NULL)
772 0 : return store_E_NotExists;
773 :
774 0 : OStoreIndirectionPageObject aTriple;
775 0 : eErrCode = rBIOS.loadObjectAt (aTriple, nAddr);
776 0 : if (eErrCode != store_E_None)
777 0 : return eErrCode;
778 :
779 0 : eErrCode = aTriple.read (aLink.m_nIndex2, aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS);
780 : }
781 0 : else if (eScope == page::SCOPE_UNREACHABLE)
782 : {
783 : // Out of scope.
784 0 : eErrCode = store_E_CantSeek;
785 : }
786 : else
787 : {
788 : // Unknown scope.
789 : OSL_TRACE("OStoreDirectoryPageObject::get(): scope failed");
790 0 : eErrCode = store_E_Unknown;
791 : }
792 :
793 : // Leave.
794 2 : return eErrCode;
795 : }
796 :
797 : /*
798 : * write (external data page).
799 : */
800 238 : storeError OStoreDirectoryPageObject::write (
801 : sal_uInt32 nPage,
802 : OStoreDataPageObject &rData,
803 : OStorePageBIOS &rBIOS)
804 : {
805 : // Determine scope and link indices.
806 238 : page::DataBlock::LinkDescriptor aLink;
807 238 : page::ChunkScope eScope = scope (nPage, aLink);
808 :
809 238 : storeError eErrCode = store_E_None;
810 238 : if (eScope == page::SCOPE_DIRECT)
811 : {
812 238 : sal_uInt32 const nAddr = directLink (aLink.m_nIndex0);
813 238 : if (nAddr == STORE_PAGE_NULL)
814 : {
815 : // Allocate data page.
816 238 : eErrCode = rBIOS.allocate (rData);
817 238 : if (eErrCode != store_E_None)
818 0 : return eErrCode;
819 :
820 : // Store data page location.
821 238 : directLink (aLink.m_nIndex0, rData.location());
822 : }
823 : else
824 : {
825 : // Save data page.
826 0 : eErrCode = rBIOS.saveObjectAt (rData, nAddr);
827 : }
828 : }
829 0 : else if (eScope == page::SCOPE_SINGLE)
830 : {
831 0 : OStoreIndirectionPageObject aSingle;
832 0 : eErrCode = aSingle.loadOrCreate (singleLink (aLink.m_nIndex1), rBIOS);
833 0 : if (eErrCode != store_E_None)
834 : {
835 0 : if (eErrCode != store_E_Pending)
836 0 : return eErrCode;
837 0 : singleLink (aLink.m_nIndex1, aSingle.location());
838 : }
839 :
840 0 : eErrCode = aSingle.write (aLink.m_nIndex0, rData, rBIOS);
841 : }
842 0 : else if (eScope == page::SCOPE_DOUBLE)
843 : {
844 0 : OStoreIndirectionPageObject aDouble;
845 0 : eErrCode = aDouble.loadOrCreate (doubleLink (aLink.m_nIndex2), rBIOS);
846 0 : if (eErrCode != store_E_None)
847 : {
848 0 : if (eErrCode != store_E_Pending)
849 0 : return eErrCode;
850 0 : doubleLink (aLink.m_nIndex2, aDouble.location());
851 : }
852 :
853 0 : eErrCode = aDouble.write (aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS);
854 : }
855 0 : else if (eScope == page::SCOPE_TRIPLE)
856 : {
857 0 : OStoreIndirectionPageObject aTriple;
858 0 : eErrCode = aTriple.loadOrCreate (tripleLink (aLink.m_nIndex3), rBIOS);
859 0 : if (eErrCode != store_E_None)
860 : {
861 0 : if (eErrCode != store_E_Pending)
862 0 : return eErrCode;
863 0 : tripleLink (aLink.m_nIndex3, aTriple.location());
864 : }
865 :
866 0 : eErrCode = aTriple.write (aLink.m_nIndex2, aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS);
867 : }
868 0 : else if (eScope == page::SCOPE_UNREACHABLE)
869 : {
870 : // Out of scope.
871 0 : eErrCode = store_E_CantSeek;
872 : }
873 : else
874 : {
875 : // Unknown scope.
876 : OSL_TRACE("OStoreDirectoryPageObject::put(): scope failed");
877 0 : eErrCode = store_E_Unknown;
878 : }
879 :
880 : // Leave.
881 238 : return eErrCode;
882 : }
883 :
884 : /*
885 : * truncate (external data page).
886 : */
887 2 : storeError OStoreDirectoryPageObject::truncate (
888 : sal_uInt32 nPage,
889 : OStorePageBIOS &rBIOS)
890 : {
891 : // Determine scope and link indices.
892 2 : page::DataBlock::LinkDescriptor aLink;
893 2 : page::ChunkScope eScope = scope (nPage, aLink);
894 :
895 2 : storeError eErrCode = store_E_None;
896 2 : if (eScope == page::SCOPE_DIRECT)
897 : {
898 : // Truncate all triple indirect pages.
899 2 : eErrCode = truncate (page::SCOPE_TRIPLE, 0, rBIOS);
900 2 : if (eErrCode != store_E_None)
901 0 : return eErrCode;
902 :
903 : // Truncate all double indirect pages.
904 2 : eErrCode = truncate (page::SCOPE_DOUBLE, 0, rBIOS);
905 2 : if (eErrCode != store_E_None)
906 0 : return eErrCode;
907 :
908 : // Truncate all single indirect pages.
909 2 : eErrCode = truncate (page::SCOPE_SINGLE, 0, rBIOS);
910 2 : if (eErrCode != store_E_None)
911 0 : return eErrCode;
912 :
913 : // Truncate direct pages, including 'aLink.m_nIndex0'.
914 2 : eErrCode = truncate (eScope, aLink.m_nIndex0, rBIOS);
915 : }
916 0 : else if (eScope == page::SCOPE_SINGLE)
917 : {
918 : // Truncate all triple indirect pages.
919 0 : eErrCode = truncate (page::SCOPE_TRIPLE, 0, rBIOS);
920 0 : if (eErrCode != store_E_None)
921 0 : return eErrCode;
922 :
923 : // Truncate all double indirect pages.
924 0 : eErrCode = truncate (page::SCOPE_DOUBLE, 0, rBIOS);
925 0 : if (eErrCode != store_E_None)
926 0 : return eErrCode;
927 :
928 : // Truncate single indirect pages, downto 'aLink.m_nIndex1'.
929 0 : eErrCode = truncate (eScope, aLink.m_nIndex1 + 1, rBIOS);
930 0 : if (eErrCode != store_E_None)
931 0 : return eErrCode;
932 :
933 : // Truncate last single indirect page to ... pages.
934 0 : eErrCode = store_truncate_Impl (singleLink (aLink.m_nIndex1), aLink.m_nIndex0, rBIOS);
935 0 : if (eErrCode != store_E_None)
936 0 : return eErrCode;
937 :
938 : // Check for complete truncation.
939 0 : if (aLink.m_nIndex0 == 0)
940 : {
941 : // Clear pointer to last single indirect page.
942 0 : singleLink (aLink.m_nIndex1, STORE_PAGE_NULL);
943 : }
944 : }
945 0 : else if (eScope == page::SCOPE_DOUBLE)
946 : {
947 : // Truncate all triple indirect pages.
948 0 : eErrCode = truncate (page::SCOPE_TRIPLE, 0, rBIOS);
949 0 : if (eErrCode != store_E_None)
950 0 : return eErrCode;
951 :
952 : // Truncate double indirect pages, downto 'aLink.m_nIndex2'.
953 0 : eErrCode = truncate (eScope, aLink.m_nIndex2 + 1, rBIOS);
954 0 : if (eErrCode != store_E_None)
955 0 : return eErrCode;
956 :
957 : // Truncate last double indirect page to ... pages.
958 : eErrCode = store_truncate_Impl (
959 0 : doubleLink (aLink.m_nIndex2), aLink.m_nIndex1, aLink.m_nIndex0, rBIOS);
960 0 : if (eErrCode != store_E_None)
961 0 : return eErrCode;
962 :
963 : // Check for complete truncation.
964 0 : if ((aLink.m_nIndex1 + aLink.m_nIndex0) == 0)
965 : {
966 : // Clear pointer to last double indirect page.
967 0 : doubleLink (aLink.m_nIndex2, STORE_PAGE_NULL);
968 : }
969 : }
970 0 : else if (eScope == page::SCOPE_TRIPLE)
971 : {
972 : // Truncate triple indirect pages, downto 'aLink.m_nIndex3'.
973 0 : eErrCode = truncate (eScope, aLink.m_nIndex3 + 1, rBIOS);
974 0 : if (eErrCode != store_E_None)
975 0 : return eErrCode;
976 :
977 : // Truncate last triple indirect page to ... pages.
978 : eErrCode = store_truncate_Impl (
979 0 : tripleLink (aLink.m_nIndex3), aLink.m_nIndex2, aLink.m_nIndex1, aLink.m_nIndex0, rBIOS);
980 0 : if (eErrCode != store_E_None)
981 0 : return eErrCode;
982 :
983 : // Check for complete truncation.
984 0 : if ((aLink.m_nIndex2 + aLink.m_nIndex1 + aLink.m_nIndex0) == 0)
985 : {
986 : // Clear pointer to last triple indirect page.
987 0 : tripleLink (aLink.m_nIndex3, STORE_PAGE_NULL);
988 : }
989 : }
990 0 : else if (eScope == page::SCOPE_UNREACHABLE)
991 : {
992 : // Out of scope.
993 0 : eErrCode = store_E_CantSeek;
994 : }
995 : else
996 : {
997 : // Unknown scope.
998 : OSL_TRACE("OStoreDirectoryPageObject::put(): scope failed");
999 0 : eErrCode = store_E_Unknown;
1000 : }
1001 :
1002 : // Leave.
1003 2 : return eErrCode;
1004 : }
1005 :
1006 : /*
1007 : * truncate (external data page scope; private).
1008 : */
1009 8 : storeError OStoreDirectoryPageObject::truncate (
1010 : page::ChunkScope eScope,
1011 : sal_uInt16 nRemain,
1012 : OStorePageBIOS &rBIOS)
1013 : {
1014 : // Enter.
1015 8 : storeError eErrCode = store_E_None;
1016 8 : if (eScope == page::SCOPE_DIRECT)
1017 : {
1018 : // Truncate direct data pages.
1019 2 : sal_uInt16 i, n = OStoreDirectoryDataBlock::directCount();
1020 34 : for (i = n; i > nRemain; i--)
1021 : {
1022 : // Obtain data page location.
1023 32 : sal_uInt32 nAddr = directLink (i - 1);
1024 32 : if (nAddr == STORE_PAGE_NULL) continue;
1025 :
1026 : // Free data page.
1027 2 : eErrCode = rBIOS.free (nAddr);
1028 2 : if (eErrCode != store_E_None)
1029 0 : break;
1030 :
1031 : // Clear pointer to data page.
1032 2 : directLink (i - 1, STORE_PAGE_NULL);
1033 : }
1034 :
1035 : // Done.
1036 2 : return eErrCode;
1037 : }
1038 :
1039 6 : if (eScope == page::SCOPE_SINGLE)
1040 : {
1041 : // Truncate single indirect pages.
1042 2 : sal_uInt16 i, n = OStoreDirectoryDataBlock::singleCount();
1043 18 : for (i = n; i > nRemain; i--)
1044 : {
1045 : // Truncate single indirect page to zero data pages.
1046 16 : eErrCode = store_truncate_Impl (singleLink (i - 1), 0, rBIOS);
1047 16 : if (eErrCode != store_E_None)
1048 0 : break;
1049 :
1050 : // Clear pointer to single indirect page.
1051 16 : singleLink (i - 1, STORE_PAGE_NULL);
1052 : }
1053 :
1054 : // Done.
1055 2 : return eErrCode;
1056 : }
1057 :
1058 4 : if (eScope == page::SCOPE_DOUBLE)
1059 : {
1060 : // Truncate double indirect pages.
1061 2 : sal_uInt16 i, n = OStoreDirectoryDataBlock::doubleCount();
1062 4 : for (i = n; i > nRemain; i--)
1063 : {
1064 : // Truncate double indirect page to zero single indirect pages.
1065 2 : eErrCode = store_truncate_Impl (doubleLink (i - 1), 0, 0, rBIOS);
1066 2 : if (eErrCode != store_E_None)
1067 0 : break;
1068 :
1069 : // Clear pointer to double indirect page.
1070 2 : doubleLink (i - 1, STORE_PAGE_NULL);
1071 : }
1072 :
1073 : // Done.
1074 2 : return eErrCode;
1075 : }
1076 :
1077 2 : if (eScope == page::SCOPE_TRIPLE)
1078 : {
1079 : // Truncate triple indirect pages.
1080 2 : sal_uInt16 i, n = OStoreDirectoryDataBlock::tripleCount();
1081 4 : for (i = n; i > nRemain; i--)
1082 : {
1083 : // Truncate to zero double indirect pages.
1084 2 : eErrCode = store_truncate_Impl (tripleLink (i - 1), 0, 0, 0, rBIOS);
1085 2 : if (eErrCode != store_E_None)
1086 0 : break;
1087 :
1088 : // Clear pointer to triple indirect page.
1089 2 : tripleLink (i - 1, STORE_PAGE_NULL);
1090 : }
1091 :
1092 : // Done.
1093 2 : return eErrCode;
1094 : }
1095 :
1096 : // Invalid scope.
1097 0 : return store_E_InvalidAccess;
1098 : }
1099 :
1100 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|