1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "storpage.hxx"
23 #include "sal/types.h"
24 #include "rtl/string.h"
25 #include "rtl/ref.hxx"
26 #include "osl/diagnose.h"
27 #include "osl/mutex.hxx"
29 #include "store/types.h"
32 #include "lockbyte.hxx"
34 #include "storbase.hxx"
35 #include "stordata.hxx"
36 #include "stortree.hxx"
38 using namespace store
;
40 /*========================================================================
42 * OStorePageManager implementation.
44 *======================================================================*/
45 const sal_uInt32
OStorePageManager::m_nTypeId
= sal_uInt32(0x62190120);
50 OStorePageManager::OStorePageManager (void)
57 OStorePageManager::~OStorePageManager (void)
64 sal_Bool SAL_CALL
OStorePageManager::isKindOf (sal_uInt32 nTypeId
)
66 return (nTypeId
== m_nTypeId
);
70 * initialize (two-phase construction).
73 storeError
OStorePageManager::initialize (
74 ILockBytes
* pLockBytes
,
75 storeAccessMode eAccessMode
,
76 sal_uInt16
& rnPageSize
)
78 // Acquire exclusive access.
79 osl::MutexGuard
aGuard(*this);
83 return store_E_InvalidParameter
;
86 storeError eErrCode
= base::initialize (pLockBytes
, eAccessMode
, rnPageSize
);
87 if (eErrCode
!= store_E_None
)
90 // Check for (not) writeable.
91 if (!base::isWriteable())
93 // Readonly. Load RootNode.
94 return base::loadObjectAt (m_aRoot
, rnPageSize
);
97 // Writeable. Load or Create RootNode.
98 eErrCode
= m_aRoot
.loadOrCreate (rnPageSize
, *this);
99 if (eErrCode
== store_E_Pending
)
101 // Creation notification.
102 PageHolderObject
< page
> xRoot (m_aRoot
.get());
104 // Pre-allocate left most entry (ugly, but we can't insert to left).
105 OStorePageKey
aKey (rtl_crc32 (0, "/", 1), 0);
106 xRoot
->insert (0, entry(aKey
));
109 eErrCode
= base::saveObjectAt (m_aRoot
, rnPageSize
);
117 * find_lookup (w/o split()).
118 * Internal: Precond: initialized, readable, exclusive access.
120 storeError
OStorePageManager::find_lookup (
121 OStoreBTreeNodeObject
& rNode
,
123 OStorePageKey
const & rKey
)
125 // Find Node and Index.
126 storeError eErrCode
= m_aRoot
.find_lookup (rNode
, rIndex
, rKey
, *this);
127 if (eErrCode
!= store_E_None
)
131 PageHolderObject
< page
> xPage (rNode
.get());
132 OSL_POSTCOND(rIndex
< xPage
->usageCount(), "store::PageManager::find_lookup(): logic error");
133 entry
e (xPage
->m_pData
[rIndex
]);
135 // Check for exact match.
136 if (e
.compare(entry(rKey
)) != entry::COMPARE_EQUAL
)
139 return store_E_NotExists
;
143 if (e
.m_aLink
.location() == STORE_PAGE_NULL
)
146 return store_E_NotExists
;
153 * remove_Impl (possibly down from root).
154 * Internal: Precond: initialized, writeable, exclusive access.
157 storeError
OStorePageManager::remove_Impl (entry
& rEntry
)
159 OStoreBTreeNodeObject
aNode (m_aRoot
.get());
161 // Check current page index.
162 PageHolderObject
< page
> xPage (aNode
.get());
163 sal_uInt16 i
= xPage
->find (rEntry
), n
= xPage
->usageCount();
166 // Path to entry not exists (Must not happen(?)).
167 return store_E_NotExists
;
171 entry::CompareResult result
= rEntry
.compare (xPage
->m_pData
[i
]);
173 // Iterate down until equal match.
174 while ((result
== entry::COMPARE_GREATER
) && (xPage
->depth() > 0))
176 // Check link address.
177 sal_uInt32
const nAddr
= xPage
->m_pData
[i
].m_aLink
.location();
178 if (nAddr
== STORE_PAGE_NULL
)
180 // Path to entry not exists (Must not happen(?)).
181 return store_E_NotExists
;
185 storeError eErrCode
= loadObjectAt (aNode
, nAddr
);
186 if (eErrCode
!= store_E_None
)
189 PageHolderObject
< page
> xNext (aNode
.get());
193 i
= xPage
->find (rEntry
), n
= xPage
->usageCount();
196 // Path to entry not exists (Must not happen(?)).
197 return store_E_NotExists
;
201 result
= rEntry
.compare (xPage
->m_pData
[i
]);
205 result
!= entry::COMPARE_LESS
,
206 "OStorePageManager::remove(): find failed");
208 // Check entry comparison.
209 if (result
== entry::COMPARE_LESS
)
212 return store_E_Unknown
;
215 // Remove down from current page (recursive).
216 return aNode
.remove (i
, rEntry
, *this);
221 * Precond: none (static).
223 storeError
OStorePageManager::namei (
224 const rtl_String
*pPath
, const rtl_String
*pName
, OStorePageKey
&rKey
)
227 if (!(pPath
&& pName
))
228 return store_E_InvalidParameter
;
230 // Check name length.
231 if (!(pName
->length
< STORE_MAXIMUM_NAMESIZE
))
232 return store_E_NameTooLong
;
234 // Transform pathname into key.
235 rKey
.m_nLow
= store::htonl(rtl_crc32 (0, pName
->buffer
, pName
->length
));
236 rKey
.m_nHigh
= store::htonl(rtl_crc32 (0, pPath
->buffer
, pPath
->length
));
244 * Precond: initialized.
246 storeError
OStorePageManager::iget (
247 OStoreDirectoryPageObject
& rPage
,
249 const rtl_String
* pPath
,
250 const rtl_String
* pName
,
251 storeAccessMode eMode
)
253 // Acquire exclusive access.
254 osl::MutexGuard
aGuard(*this);
257 if (!self::isValid())
258 return store_E_InvalidAccess
;
260 // Setup inode page key.
262 storeError eErrCode
= namei (pPath
, pName
, aKey
);
263 if (eErrCode
!= store_E_None
)
266 // Check for directory.
267 if (nAttrib
& STORE_ATTRIB_ISDIR
)
269 // Ugly, but necessary (backward compatibility).
270 aKey
.m_nLow
= store::htonl(rtl_crc32 (store::ntohl(aKey
.m_nLow
), "/", 1));
274 eErrCode
= load_dirpage_Impl (aKey
, rPage
);
275 if (eErrCode
!= store_E_None
)
277 // Check mode and reason.
278 if (eErrCode
!= store_E_NotExists
)
281 if (eMode
== store_AccessReadWrite
)
282 return store_E_NotExists
;
283 if (eMode
== store_AccessReadOnly
)
284 return store_E_NotExists
;
286 if (!base::isWriteable())
287 return store_E_AccessViolation
;
289 // Create inode page.
290 eErrCode
= rPage
.construct
< inode
>(base::allocator());
291 if (eErrCode
!= store_E_None
)
294 // Setup inode nameblock.
295 PageHolderObject
< inode
> xPage (rPage
.get());
298 rPage
.attrib (nAttrib
);
301 &(xPage
->m_aNameBlock
.m_pData
[0]),
302 pName
->buffer
, pName
->length
);
305 eErrCode
= save_dirpage_Impl (aKey
, rPage
);
306 if (eErrCode
!= store_E_None
)
310 // Check for symbolic link.
311 if (rPage
.attrib() & STORE_ATTRIB_ISLINK
)
313 // Obtain 'Destination' page key.
314 PageHolderObject
< inode
> xPage (rPage
.get());
315 OStorePageKey aDstKey
;
316 memcpy (&aDstKey
, &(xPage
->m_pData
[0]), sizeof(aDstKey
));
318 // Load 'Destination' inode.
319 eErrCode
= load_dirpage_Impl (aDstKey
, rPage
);
320 if (eErrCode
!= store_E_None
)
330 * Precond: initialized.
331 * ToDo: skip hardlink entries.
333 storeError
OStorePageManager::iterate (
334 OStorePageKey
& rKey
,
335 OStorePageLink
& rLink
,
336 sal_uInt32
& rAttrib
)
338 // Acquire exclusive access.
339 osl::MutexGuard
aGuard(*this);
342 if (!self::isValid())
343 return store_E_InvalidAccess
;
345 // Find NodePage and Index.
346 OStoreBTreeNodeObject aNode
;
348 storeError eErrCode
= m_aRoot
.find_lookup (aNode
, i
, rKey
, *this);
349 if (eErrCode
!= store_E_None
)
352 // GreaterEqual. Found next entry.
353 PageHolderObject
< page
> xNode (aNode
.get());
354 entry
e (xNode
->m_pData
[i
]);
359 rAttrib
= store::ntohl(e
.m_nAttrib
);
366 * load => private: iget() @@@
367 * Internal: Precond: initialized, exclusive access.
369 storeError
OStorePageManager::load_dirpage_Impl (
370 const OStorePageKey
&rKey
,
371 OStoreDirectoryPageObject
&rPage
)
373 // Find Node and Index.
374 OStoreBTreeNodeObject aNode
;
376 storeError eErrCode
= find_lookup (aNode
, i
, rKey
);
377 if (eErrCode
!= store_E_None
)
380 // Existing entry. Load page.
381 PageHolderObject
< page
> xNode (aNode
.get());
382 entry
e (xNode
->m_pData
[i
]);
383 return loadObjectAt (rPage
, e
.m_aLink
.location());
387 * save => private: iget(), rebuild() @@@
388 * Internal: Precond: initialized, writeable, exclusive access.
390 storeError
OStorePageManager::save_dirpage_Impl (
391 const OStorePageKey
&rKey
,
392 OStoreDirectoryPageObject
&rPage
)
394 // Find NodePage and Index.
398 storeError eErrCode
= m_aRoot
.find_insert (aNode
, i
, rKey
, *this);
399 PageHolderObject
< page
> xNode (aNode
.get());
400 if (eErrCode
!= store_E_None
)
402 if (eErrCode
!= store_E_AlreadyExists
)
406 entry
e (xNode
->m_pData
[i
]);
407 if (e
.m_aLink
.location() != STORE_PAGE_NULL
)
409 // Save page to existing location.
410 return saveObjectAt (rPage
, e
.m_aLink
.location());
414 eErrCode
= base::allocate (rPage
);
415 if (eErrCode
!= store_E_None
)
418 // Update page location.
419 xNode
->m_pData
[i
].m_aLink
= rPage
.location();
421 // Save modified NodePage.
422 return saveObjectAt (aNode
, aNode
.location());
426 eErrCode
= base::allocate (rPage
);
427 if (eErrCode
!= store_E_None
)
431 OStorePageLink
aLink (rPage
.location());
432 xNode
->insert (i
+ 1, entry (rKey
, aLink
));
434 // Save modified NodePage.
435 return saveObjectAt (aNode
, aNode
.location());
439 * attrib [nAttrib = ((nAttrib & ~nMask1) | nMask2)].
440 * Precond: initialized.
442 storeError
OStorePageManager::attrib (
443 const OStorePageKey
&rKey
,
448 // Acquire exclusive access.
449 osl::MutexGuard
aGuard(*this);
452 if (!self::isValid())
453 return store_E_InvalidAccess
;
455 // Find NodePage and index.
456 OStoreBTreeNodeObject aNode
;
458 storeError eErrCode
= find_lookup (aNode
, i
, rKey
);
459 if (eErrCode
!= store_E_None
)
463 PageHolderObject
< page
> xNode (aNode
.get());
464 entry
e (xNode
->m_pData
[i
]);
465 if (nMask1
!= nMask2
)
467 // Evaluate new attributes.
468 sal_uInt32 nAttrib
= store::ntohl(e
.m_nAttrib
);
473 if (store::htonl(nAttrib
) != e
.m_nAttrib
)
475 // Check access mode.
476 if (base::isWriteable())
478 // Set new attributes.
479 e
.m_nAttrib
= store::htonl(nAttrib
);
480 xNode
->m_pData
[i
] = e
;
482 // Save modified NodePage.
483 eErrCode
= saveObjectAt (aNode
, aNode
.location());
488 eErrCode
= store_E_AccessViolation
;
493 // Obtain current attributes.
494 rAttrib
= store::ntohl(e
.m_nAttrib
);
499 * link (insert 'Source' as hardlink to 'Destination').
500 * Precond: initialized, writeable.
502 storeError
OStorePageManager::link (
503 const OStorePageKey
&rSrcKey
,
504 const OStorePageKey
&rDstKey
)
506 // Acquire exclusive access.
507 osl::MutexGuard
aGuard(*this);
510 if (!self::isValid())
511 return store_E_InvalidAccess
;
513 if (!base::isWriteable())
514 return store_E_AccessViolation
;
516 // Find 'Destination' NodePage and Index.
517 OStoreBTreeNodeObject aDstNode
;
519 storeError eErrCode
= find_lookup (aDstNode
, i
, rDstKey
);
520 if (eErrCode
!= store_E_None
)
523 // Existing 'Destination' entry.
524 PageHolderObject
< page
> xDstNode (aDstNode
.get());
525 entry
e (xDstNode
->m_pData
[i
]);
526 OStorePageLink
aDstLink (e
.m_aLink
);
528 // Find 'Source' NodePage and Index.
529 OStoreBTreeNodeObject aSrcNode
;
530 eErrCode
= m_aRoot
.find_insert (aSrcNode
, i
, rSrcKey
, *this);
531 if (eErrCode
!= store_E_None
)
534 // Insert 'Source' entry.
535 PageHolderObject
< page
> xSrcNode (aSrcNode
.get());
536 xSrcNode
->insert (i
+ 1, entry (rSrcKey
, aDstLink
, STORE_ATTRIB_ISLINK
));
537 return saveObjectAt (aSrcNode
, aSrcNode
.location());
541 * symlink (insert 'Source' DirectoryPage as symlink to 'Destination').
542 * Precond: initialized, writeable.
544 storeError
OStorePageManager::symlink (
545 const rtl_String
*pSrcPath
,
546 const rtl_String
*pSrcName
,
547 const OStorePageKey
&rDstKey
)
549 // Acquire exclusive access.
550 osl::MutexGuard
aGuard(*this);
553 if (!self::isValid())
554 return store_E_InvalidAccess
;
556 if (!base::isWriteable())
557 return store_E_AccessViolation
;
559 // Check 'Source' parameter.
560 storeError eErrCode
= store_E_InvalidParameter
;
561 if (!(pSrcPath
&& pSrcName
))
564 // Setup 'Source' page key.
565 OStorePageKey aSrcKey
;
566 eErrCode
= namei (pSrcPath
, pSrcName
, aSrcKey
);
567 if (eErrCode
!= store_E_None
)
570 // Find 'Source' NodePage and Index.
571 OStoreBTreeNodeObject aSrcNode
;
573 eErrCode
= m_aRoot
.find_insert (aSrcNode
, i
, aSrcKey
, *this);
574 if (eErrCode
!= store_E_None
)
577 // Initialize directory page.
578 OStoreDirectoryPageObject aPage
;
579 eErrCode
= aPage
.construct
< inode
>(base::allocator());
580 if (eErrCode
!= store_E_None
)
583 // Setup as 'Source' directory page.
584 inode_holder_type
xNode (aPage
.get());
587 &(xNode
->m_aNameBlock
.m_pData
[0]),
588 pSrcName
->buffer
, pSrcName
->length
);
590 // Store 'Destination' page key.
591 OStorePageKey
aDstKey (rDstKey
);
592 memcpy (&(xNode
->m_pData
[0]), &aDstKey
, sizeof(aDstKey
));
594 // Mark 'Source' as symbolic link to 'Destination'.
595 aPage
.attrib (STORE_ATTRIB_ISLINK
);
596 aPage
.dataLength (sal_uInt32(sizeof(aDstKey
)));
598 // Allocate and save 'Source' directory page.
599 eErrCode
= base::allocate (aPage
);
600 if (eErrCode
!= store_E_None
)
603 // Insert 'Source' entry.
604 PageHolderObject
< page
> xSrcNode (aSrcNode
.get());
605 OStorePageLink
aSrcLink (aPage
.location());
606 xSrcNode
->insert (i
+ 1, entry(aSrcKey
, aSrcLink
));
608 // Save modified NodePage.
609 return saveObjectAt (aSrcNode
, aSrcNode
.location());
614 * Precond: initialized, writeable.
616 storeError
OStorePageManager::rename (
617 const OStorePageKey
&rSrcKey
,
618 const rtl_String
*pDstPath
,
619 const rtl_String
*pDstName
)
621 // Acquire exclusive access.
622 osl::MutexGuard
aGuard(*this);
625 if (!self::isValid())
626 return store_E_InvalidAccess
;
628 if (!base::isWriteable())
629 return store_E_AccessViolation
;
631 // Check 'Destination' parameter.
632 storeError eErrCode
= store_E_InvalidParameter
;
633 if (!(pDstPath
&& pDstName
))
636 // Setup 'Destination' page key.
637 OStorePageKey aDstKey
;
638 eErrCode
= namei (pDstPath
, pDstName
, aDstKey
);
639 if (eErrCode
!= store_E_None
)
642 // Find 'Source' NodePage and Index.
643 OStoreBTreeNodeObject aSrcNode
;
645 eErrCode
= find_lookup (aSrcNode
, i
, rSrcKey
);
646 if (eErrCode
!= store_E_None
)
649 // Existing 'Source' entry.
650 PageHolderObject
< page
> xSrcNode (aSrcNode
.get());
651 entry
e (xSrcNode
->m_pData
[i
]);
653 // Check for (not a) hardlink.
654 OStoreDirectoryPageObject aPage
;
655 if (!(store::ntohl(e
.m_nAttrib
) & STORE_ATTRIB_ISLINK
))
657 // Load directory page.
658 eErrCode
= base::loadObjectAt (aPage
, e
.m_aLink
.location());
659 if (eErrCode
!= store_E_None
)
662 // Check for directory.
663 if (aPage
.attrib() & STORE_ATTRIB_ISDIR
)
665 // Ugly, but necessary (backward compatibility).
666 aDstKey
.m_nLow
= store::htonl(rtl_crc32 (store::ntohl(aDstKey
.m_nLow
), "/", 1));
670 // Let 'Source' entry be 'Destination' entry.
673 // Find 'Destination' NodePage and Index.
674 OStoreBTreeNodeObject aDstNode
;
675 eErrCode
= m_aRoot
.find_insert (aDstNode
, i
, e
.m_aKey
, *this);
676 if (eErrCode
!= store_E_None
)
679 // Insert 'Destination' entry.
680 PageHolderObject
< page
> xDstNode (aDstNode
.get());
681 xDstNode
->insert (i
+ 1, e
);
683 eErrCode
= saveObjectAt (aDstNode
, aDstNode
.location());
684 if (eErrCode
!= store_E_None
)
687 // Check for (not a) hardlink.
688 if (!(store::ntohl(e
.m_nAttrib
) & STORE_ATTRIB_ISLINK
))
690 // Modify 'Source' directory page.
691 inode_holder_type
xNode (aPage
.get());
693 // Setup 'Destination' NameBlock.
694 sal_Int32 nDstLen
= pDstName
->length
;
696 &(xNode
->m_aNameBlock
.m_pData
[0]),
697 pDstName
->buffer
, pDstName
->length
);
699 &(xNode
->m_aNameBlock
.m_pData
[nDstLen
]),
700 0, STORE_MAXIMUM_NAMESIZE
- nDstLen
);
701 aPage
.key (e
.m_aKey
);
703 // Save directory page.
704 eErrCode
= base::saveObjectAt (aPage
, e
.m_aLink
.location());
705 if (eErrCode
!= store_E_None
)
709 // Remove 'Source' entry.
711 return remove_Impl (e
);
716 * Precond: initialized, writeable.
718 storeError
OStorePageManager::remove (const OStorePageKey
&rKey
)
720 // Acquire exclusive access.
721 osl::MutexGuard
aGuard(*this);
724 if (!self::isValid())
725 return store_E_InvalidAccess
;
727 if (!base::isWriteable())
728 return store_E_AccessViolation
;
730 // Find NodePage and index.
731 OStoreBTreeNodeObject aNodePage
;
733 storeError eErrCode
= find_lookup (aNodePage
, i
, rKey
);
734 if (eErrCode
!= store_E_None
)
738 PageHolderObject
< page
> xNodePage (aNodePage
.get());
739 entry
e (xNodePage
->m_pData
[i
]);
741 // Check for (not a) hardlink.
742 if (!(store::ntohl(e
.m_nAttrib
) & STORE_ATTRIB_ISLINK
))
744 // Load directory page.
745 OStoreDirectoryPageObject aPage
;
746 eErrCode
= base::loadObjectAt (aPage
, e
.m_aLink
.location());
747 if (eErrCode
!= store_E_None
)
750 inode_holder_type
xNode (aPage
.get());
752 // Acquire page write access.
753 OStorePageDescriptor
aDescr (xNode
->m_aDescr
);
754 eErrCode
= base::acquirePage (aDescr
, store_AccessReadWrite
);
755 if (eErrCode
!= store_E_None
)
758 // Check for symbolic link.
759 if (!(aPage
.attrib() & STORE_ATTRIB_ISLINK
))
761 // Ordinary inode. Determine 'Data' scope.
762 inode::ChunkScope eScope
= xNode
->scope (aPage
.dataLength());
763 if (eScope
== inode::SCOPE_EXTERNAL
)
765 // External 'Data' scope. Truncate all external data pages.
766 eErrCode
= aPage
.truncate (0, *this);
767 if (eErrCode
!= store_E_None
)
771 // Truncate internal data page.
772 memset (&(xNode
->m_pData
[0]), 0, xNode
->capacity());
773 aPage
.dataLength (0);
776 // Release page write access.
777 eErrCode
= base::releasePage (aDescr
);
779 // Release and free directory page.
780 eErrCode
= base::free (aPage
.location());
784 return remove_Impl (e
);
790 struct RebuildContext
794 rtl::Reference
<OStorePageBIOS
> m_xBIOS
;
795 OStorePageBIOS::ScanContext m_aCtx
;
796 sal_uInt16 m_nPageSize
;
800 RebuildContext (void)
801 : m_xBIOS (new OStorePageBIOS()),
805 /** initialize (PageBIOS and ScanContext).
807 storeError
initialize (ILockBytes
*pLockBytes
, sal_uInt32 nMagic
= 0)
809 storeError eErrCode
= store_E_InvalidParameter
;
812 m_xBIOS
->initialize (pLockBytes
, store_AccessReadOnly
, m_nPageSize
);
813 eErrCode
= m_xBIOS
->scanBegin (m_aCtx
, nMagic
);
818 /** initialize (ScanContext).
820 storeError
initialize (sal_uInt32 nMagic
= 0)
822 return m_xBIOS
->scanBegin (m_aCtx
, nMagic
);
825 /** load (next ScanContext matching page).
827 storeError
load (OStorePageObject
&rPage
)
829 if (m_aCtx
.isValid())
830 return m_xBIOS
->scanNext (m_aCtx
, rPage
);
832 return store_E_CantSeek
;
840 storeError
OStorePageManager::rebuild (
841 ILockBytes
*pSrcLB
, ILockBytes
*pDstLB
)
843 // Acquire exclusive access.
844 osl::MutexGuard
aGuard(*this);
847 storeError eErrCode
= store_E_InvalidParameter
;
848 if (!(pSrcLB
&& pDstLB
))
851 // Initialize 'Source' rebuild context.
853 eErrCode
= aCtx
.initialize (pSrcLB
, STORE_MAGIC_DIRECTORYPAGE
);
854 if (eErrCode
!= store_E_None
)
856 rtl::Reference
<OStorePageBIOS
> xSrcBIOS (aCtx
.m_xBIOS
);
858 // Initialize as 'Destination' with 'Source' page size.
859 eErrCode
= self::initialize (pDstLB
, store_AccessCreate
, aCtx
.m_nPageSize
);
860 if (eErrCode
!= store_E_None
)
863 // Pass One: Scan 'Source' directory pages.
865 // Scan 'Source' directory pages.
866 OStoreDirectoryPageObject aSrcPage
;
867 while ((eErrCode
= aCtx
.load(aSrcPage
)) == store_E_None
)
869 OStoreDirectoryPageObject aDstPage
;
870 eErrCode
= aDstPage
.construct
< inode
>(base::allocator());
871 if (eErrCode
!= store_E_None
)
874 inode_holder_type
xSrcDir (aSrcPage
.get());
875 inode_holder_type
xDstDir (aDstPage
.get());
877 // Copy NameBlock @@@ OLD @@@
878 memcpy (&(xDstDir
->m_aNameBlock
), &(xSrcDir
->m_aNameBlock
), sizeof(xSrcDir
->m_aNameBlock
));
880 // Obtain 'Source' data length.
881 sal_uInt32 nDataLen
= aSrcPage
.dataLength();
884 // Copy internal data area @@@ OLD @@@
885 memcpy (&(xDstDir
->m_pData
[0]), &(xSrcDir
->m_pData
[0]), xSrcDir
->capacity());
888 // Insert 'Destination' directory page.
889 eErrCode
= save_dirpage_Impl (aDstPage
.key(), aDstPage
);
890 if (eErrCode
!= store_E_None
)
893 // Check for external data page scope.
894 if (xSrcDir
->scope(nDataLen
) != inode::SCOPE_INTERNAL
)
896 // Initialize 'Destination' data page.
897 typedef OStoreDataPageData data
;
898 PageHolderObject
< data
> xData
;
899 if (!xData
.construct(base::allocator()))
900 return store_E_OutOfMemory
;
902 // Determine data page count.
903 inode::ChunkDescriptor
aDescr (
904 nDataLen
- xDstDir
->capacity(), xData
->capacity());
906 sal_uInt32 i
, n
= aDescr
.m_nPage
;
907 if (aDescr
.m_nOffset
) n
+= 1;
910 OStoreDataPageObject aData
;
911 for (i
= 0; i
< n
; i
++)
913 // Read 'Source' data page.
914 osl::MutexGuard
aSrcGuard (*xSrcBIOS
);
916 eErrCode
= aSrcPage
.read (i
, aData
, *xSrcBIOS
);
917 if (eErrCode
!= store_E_None
)
920 // Write 'Destination' data page. @@@ READONLY @@@
921 eErrCode
= aDstPage
.write (i
, aData
, *this);
925 // Update 'Destination' directory page.
926 aDstPage
.dataLength (nDataLen
);
927 eErrCode
= base::saveObjectAt (aDstPage
, aDstPage
.location());
930 // Save directory scan results.
934 // Pass Two: Scan 'Source' BTree nodes.
936 // Re-start 'Source' rebuild context.
937 aCtx
.initialize (STORE_MAGIC_BTREENODE
);
939 // Scan 'Source' BTree nodes.
940 OStoreBTreeNodeObject aNode
;
941 while ((eErrCode
= aCtx
.load(aNode
)) == store_E_None
)
943 // Check for leaf node.
944 PageHolderObject
< page
> xNode (aNode
.get());
945 if (xNode
->depth() == 0)
947 sal_uInt16 i
, n
= xNode
->usageCount();
948 for (i
= 0; i
< n
; i
++)
950 entry
e (xNode
->m_pData
[i
]);
952 // Check for Hard link.
953 if (e
.m_nAttrib
& STORE_ATTRIB_ISLINK
)
955 // Load the hard link destination.
956 OStoreDirectoryPageObject aSrcPage
;
957 eErrCode
= xSrcBIOS
->loadObjectAt (aSrcPage
, e
.m_aLink
.location());
958 if (eErrCode
== store_E_None
)
960 OStorePageKey
aDstKey (aSrcPage
.key());
961 eErrCode
= link (e
.m_aKey
, aDstKey
);
963 e
.m_nAttrib
&= ~STORE_ATTRIB_ISLINK
;
968 // Ordinary attributes.
969 sal_uInt32 nAttrib
= 0;
970 eErrCode
= attrib (e
.m_aKey
, 0, e
.m_nAttrib
, nAttrib
);
976 // Save BTree node scan results.
984 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */