1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #include "storpage.hxx"
32 #include "sal/types.h"
33 #include "rtl/string.h"
34 #include "rtl/ref.hxx"
35 #include "osl/diagnose.h"
36 #include "osl/mutex.hxx"
38 #include "store/types.h"
41 #include "lockbyte.hxx"
43 #include "storbase.hxx"
44 #include "stordata.hxx"
45 #include "stortree.hxx"
47 using namespace store
;
49 /*========================================================================
51 * OStorePageManager implementation.
53 *======================================================================*/
54 const sal_uInt32
OStorePageManager::m_nTypeId
= sal_uInt32(0x62190120);
59 OStorePageManager::OStorePageManager (void)
66 OStorePageManager::~OStorePageManager (void)
73 sal_Bool SAL_CALL
OStorePageManager::isKindOf (sal_uInt32 nTypeId
)
75 return (nTypeId
== m_nTypeId
);
79 * initialize (two-phase construction).
82 storeError
OStorePageManager::initialize (
83 ILockBytes
* pLockBytes
,
84 storeAccessMode eAccessMode
,
85 sal_uInt16
& rnPageSize
)
87 // Acquire exclusive access.
88 osl::MutexGuard
aGuard(*this);
92 return store_E_InvalidParameter
;
95 storeError eErrCode
= base::initialize (pLockBytes
, eAccessMode
, rnPageSize
);
96 if (eErrCode
!= store_E_None
)
99 // Check for (not) writeable.
100 if (!base::isWriteable())
102 // Readonly. Load RootNode.
103 return base::loadObjectAt (m_aRoot
, rnPageSize
);
106 // Writeable. Load or Create RootNode.
107 eErrCode
= m_aRoot
.loadOrCreate (rnPageSize
, *this);
108 if (eErrCode
== store_E_Pending
)
110 // Creation notification.
111 PageHolderObject
< page
> xRoot (m_aRoot
.get());
113 // Pre-allocate left most entry (ugly, but we can't insert to left).
114 OStorePageKey
aKey (rtl_crc32 (0, "/", 1), 0);
115 xRoot
->insert (0, entry(aKey
));
118 eErrCode
= base::saveObjectAt (m_aRoot
, rnPageSize
);
126 * find_lookup (w/o split()).
127 * Internal: Precond: initialized, readable, exclusive access.
129 storeError
OStorePageManager::find_lookup (
130 OStoreBTreeNodeObject
& rNode
,
132 OStorePageKey
const & rKey
)
134 // Find Node and Index.
135 storeError eErrCode
= m_aRoot
.find_lookup (rNode
, rIndex
, rKey
, *this);
136 if (eErrCode
!= store_E_None
)
140 PageHolderObject
< page
> xPage (rNode
.get());
141 OSL_POSTCOND(rIndex
< xPage
->usageCount(), "store::PageManager::find_lookup(): logic error");
142 entry
e (xPage
->m_pData
[rIndex
]);
144 // Check for exact match.
145 if (e
.compare(entry(rKey
)) != entry::COMPARE_EQUAL
)
148 return store_E_NotExists
;
152 if (e
.m_aLink
.location() == STORE_PAGE_NULL
)
155 return store_E_NotExists
;
162 * remove_Impl (possibly down from root).
163 * Internal: Precond: initialized, writeable, exclusive access.
166 storeError
OStorePageManager::remove_Impl (entry
& rEntry
)
168 OStoreBTreeNodeObject
aNode (m_aRoot
.get());
170 // Check current page index.
171 PageHolderObject
< page
> xPage (aNode
.get());
172 sal_uInt16 i
= xPage
->find (rEntry
), n
= xPage
->usageCount();
175 // Path to entry not exists (Must not happen(?)).
176 return store_E_NotExists
;
180 entry::CompareResult result
= rEntry
.compare (xPage
->m_pData
[i
]);
182 // Iterate down until equal match.
183 while ((result
== entry::COMPARE_GREATER
) && (xPage
->depth() > 0))
185 // Check link address.
186 sal_uInt32
const nAddr
= xPage
->m_pData
[i
].m_aLink
.location();
187 if (nAddr
== STORE_PAGE_NULL
)
189 // Path to entry not exists (Must not happen(?)).
190 return store_E_NotExists
;
194 storeError eErrCode
= loadObjectAt (aNode
, nAddr
);
195 if (eErrCode
!= store_E_None
)
198 PageHolderObject
< page
> xNext (aNode
.get());
202 i
= xPage
->find (rEntry
), n
= xPage
->usageCount();
205 // Path to entry not exists (Must not happen(?)).
206 return store_E_NotExists
;
210 result
= rEntry
.compare (xPage
->m_pData
[i
]);
214 result
!= entry::COMPARE_LESS
,
215 "OStorePageManager::remove(): find failed");
217 // Check entry comparison.
218 if (result
== entry::COMPARE_LESS
)
221 return store_E_Unknown
;
224 // Remove down from current page (recursive).
225 return aNode
.remove (i
, rEntry
, *this);
230 * Precond: none (static).
232 storeError
OStorePageManager::namei (
233 const rtl_String
*pPath
, const rtl_String
*pName
, OStorePageKey
&rKey
)
236 if (!(pPath
&& pName
))
237 return store_E_InvalidParameter
;
239 // Check name length.
240 if (!(pName
->length
< STORE_MAXIMUM_NAMESIZE
))
241 return store_E_NameTooLong
;
243 // Transform pathname into key.
244 rKey
.m_nLow
= store::htonl(rtl_crc32 (0, pName
->buffer
, pName
->length
));
245 rKey
.m_nHigh
= store::htonl(rtl_crc32 (0, pPath
->buffer
, pPath
->length
));
253 * Precond: initialized.
255 storeError
OStorePageManager::iget (
256 OStoreDirectoryPageObject
& rPage
,
258 const rtl_String
* pPath
,
259 const rtl_String
* pName
,
260 storeAccessMode eMode
)
262 // Acquire exclusive access.
263 osl::MutexGuard
aGuard(*this);
266 if (!self::isValid())
267 return store_E_InvalidAccess
;
269 // Setup inode page key.
271 storeError eErrCode
= namei (pPath
, pName
, aKey
);
272 if (eErrCode
!= store_E_None
)
275 // Check for directory.
276 if (nAttrib
& STORE_ATTRIB_ISDIR
)
278 // Ugly, but necessary (backward compatibility).
279 aKey
.m_nLow
= store::htonl(rtl_crc32 (store::ntohl(aKey
.m_nLow
), "/", 1));
283 eErrCode
= load_dirpage_Impl (aKey
, rPage
);
284 if (eErrCode
!= store_E_None
)
286 // Check mode and reason.
287 if (eErrCode
!= store_E_NotExists
)
290 if (eMode
== store_AccessReadWrite
)
291 return store_E_NotExists
;
292 if (eMode
== store_AccessReadOnly
)
293 return store_E_NotExists
;
295 if (!base::isWriteable())
296 return store_E_AccessViolation
;
298 // Create inode page.
299 eErrCode
= rPage
.construct
< inode
>(base::allocator());
300 if (eErrCode
!= store_E_None
)
303 // Setup inode nameblock.
304 PageHolderObject
< inode
> xPage (rPage
.get());
307 rPage
.attrib (nAttrib
);
310 &(xPage
->m_aNameBlock
.m_pData
[0]),
311 pName
->buffer
, pName
->length
);
314 eErrCode
= save_dirpage_Impl (aKey
, rPage
);
315 if (eErrCode
!= store_E_None
)
319 // Check for symbolic link.
320 if (rPage
.attrib() & STORE_ATTRIB_ISLINK
)
322 // Obtain 'Destination' page key.
323 PageHolderObject
< inode
> xPage (rPage
.get());
324 OStorePageKey aDstKey
;
325 memcpy (&aDstKey
, &(xPage
->m_pData
[0]), sizeof(aDstKey
));
327 // Load 'Destination' inode.
328 eErrCode
= load_dirpage_Impl (aDstKey
, rPage
);
329 if (eErrCode
!= store_E_None
)
339 * Precond: initialized.
340 * ToDo: skip hardlink entries.
342 storeError
OStorePageManager::iterate (
343 OStorePageKey
& rKey
,
344 OStorePageLink
& rLink
,
345 sal_uInt32
& rAttrib
)
347 // Acquire exclusive access.
348 osl::MutexGuard
aGuard(*this);
351 if (!self::isValid())
352 return store_E_InvalidAccess
;
354 // Find NodePage and Index.
355 OStoreBTreeNodeObject aNode
;
357 storeError eErrCode
= m_aRoot
.find_lookup (aNode
, i
, rKey
, *this);
358 if (eErrCode
!= store_E_None
)
361 // GreaterEqual. Found next entry.
362 PageHolderObject
< page
> xNode (aNode
.get());
363 entry
e (xNode
->m_pData
[i
]);
368 rAttrib
= store::ntohl(e
.m_nAttrib
);
375 * load => private: iget() @@@
376 * Internal: Precond: initialized, exclusive access.
378 storeError
OStorePageManager::load_dirpage_Impl (
379 const OStorePageKey
&rKey
,
380 OStoreDirectoryPageObject
&rPage
)
382 // Find Node and Index.
383 OStoreBTreeNodeObject aNode
;
385 storeError eErrCode
= find_lookup (aNode
, i
, rKey
);
386 if (eErrCode
!= store_E_None
)
389 // Existing entry. Load page.
390 PageHolderObject
< page
> xNode (aNode
.get());
391 entry
e (xNode
->m_pData
[i
]);
392 return loadObjectAt (rPage
, e
.m_aLink
.location());
396 * save => private: iget(), rebuild() @@@
397 * Internal: Precond: initialized, writeable, exclusive access.
399 storeError
OStorePageManager::save_dirpage_Impl (
400 const OStorePageKey
&rKey
,
401 OStoreDirectoryPageObject
&rPage
)
403 // Find NodePage and Index.
407 storeError eErrCode
= m_aRoot
.find_insert (aNode
, i
, rKey
, *this);
408 PageHolderObject
< page
> xNode (aNode
.get());
409 if (eErrCode
!= store_E_None
)
411 if (eErrCode
!= store_E_AlreadyExists
)
415 entry
e (xNode
->m_pData
[i
]);
416 if (e
.m_aLink
.location() != STORE_PAGE_NULL
)
418 // Save page to existing location.
419 return saveObjectAt (rPage
, e
.m_aLink
.location());
423 eErrCode
= base::allocate (rPage
);
424 if (eErrCode
!= store_E_None
)
427 // Update page location.
428 xNode
->m_pData
[i
].m_aLink
= rPage
.location();
430 // Save modified NodePage.
431 return saveObjectAt (aNode
, aNode
.location());
435 eErrCode
= base::allocate (rPage
);
436 if (eErrCode
!= store_E_None
)
440 OStorePageLink
aLink (rPage
.location());
441 xNode
->insert (i
+ 1, entry (rKey
, aLink
));
443 // Save modified NodePage.
444 return saveObjectAt (aNode
, aNode
.location());
448 * attrib [nAttrib = ((nAttrib & ~nMask1) | nMask2)].
449 * Precond: initialized.
451 storeError
OStorePageManager::attrib (
452 const OStorePageKey
&rKey
,
457 // Acquire exclusive access.
458 osl::MutexGuard
aGuard(*this);
461 if (!self::isValid())
462 return store_E_InvalidAccess
;
464 // Find NodePage and index.
465 OStoreBTreeNodeObject aNode
;
467 storeError eErrCode
= find_lookup (aNode
, i
, rKey
);
468 if (eErrCode
!= store_E_None
)
472 PageHolderObject
< page
> xNode (aNode
.get());
473 entry
e (xNode
->m_pData
[i
]);
474 if (nMask1
!= nMask2
)
476 // Evaluate new attributes.
477 sal_uInt32 nAttrib
= store::ntohl(e
.m_nAttrib
);
482 if (store::htonl(nAttrib
) != e
.m_nAttrib
)
484 // Check access mode.
485 if (base::isWriteable())
487 // Set new attributes.
488 e
.m_nAttrib
= store::htonl(nAttrib
);
489 xNode
->m_pData
[i
] = e
;
491 // Save modified NodePage.
492 eErrCode
= saveObjectAt (aNode
, aNode
.location());
497 eErrCode
= store_E_AccessViolation
;
502 // Obtain current attributes.
503 rAttrib
= store::ntohl(e
.m_nAttrib
);
508 * link (insert 'Source' as hardlink to 'Destination').
509 * Precond: initialized, writeable.
511 storeError
OStorePageManager::link (
512 const OStorePageKey
&rSrcKey
,
513 const OStorePageKey
&rDstKey
)
515 // Acquire exclusive access.
516 osl::MutexGuard
aGuard(*this);
519 if (!self::isValid())
520 return store_E_InvalidAccess
;
522 if (!base::isWriteable())
523 return store_E_AccessViolation
;
525 // Find 'Destination' NodePage and Index.
526 OStoreBTreeNodeObject aDstNode
;
528 storeError eErrCode
= find_lookup (aDstNode
, i
, rDstKey
);
529 if (eErrCode
!= store_E_None
)
532 // Existing 'Destination' entry.
533 PageHolderObject
< page
> xDstNode (aDstNode
.get());
534 entry
e (xDstNode
->m_pData
[i
]);
535 OStorePageLink
aDstLink (e
.m_aLink
);
537 // Find 'Source' NodePage and Index.
538 OStoreBTreeNodeObject aSrcNode
;
539 eErrCode
= m_aRoot
.find_insert (aSrcNode
, i
, rSrcKey
, *this);
540 if (eErrCode
!= store_E_None
)
543 // Insert 'Source' entry.
544 PageHolderObject
< page
> xSrcNode (aSrcNode
.get());
545 xSrcNode
->insert (i
+ 1, entry (rSrcKey
, aDstLink
, STORE_ATTRIB_ISLINK
));
546 return saveObjectAt (aSrcNode
, aSrcNode
.location());
550 * symlink (insert 'Source' DirectoryPage as symlink to 'Destination').
551 * Precond: initialized, writeable.
553 storeError
OStorePageManager::symlink (
554 const rtl_String
*pSrcPath
,
555 const rtl_String
*pSrcName
,
556 const OStorePageKey
&rDstKey
)
558 // Acquire exclusive access.
559 osl::MutexGuard
aGuard(*this);
562 if (!self::isValid())
563 return store_E_InvalidAccess
;
565 if (!base::isWriteable())
566 return store_E_AccessViolation
;
568 // Check 'Source' parameter.
569 storeError eErrCode
= store_E_InvalidParameter
;
570 if (!(pSrcPath
&& pSrcName
))
573 // Setup 'Source' page key.
574 OStorePageKey aSrcKey
;
575 eErrCode
= namei (pSrcPath
, pSrcName
, aSrcKey
);
576 if (eErrCode
!= store_E_None
)
579 // Find 'Source' NodePage and Index.
580 OStoreBTreeNodeObject aSrcNode
;
582 eErrCode
= m_aRoot
.find_insert (aSrcNode
, i
, aSrcKey
, *this);
583 if (eErrCode
!= store_E_None
)
586 // Initialize directory page.
587 OStoreDirectoryPageObject aPage
;
588 eErrCode
= aPage
.construct
< inode
>(base::allocator());
589 if (eErrCode
!= store_E_None
)
592 // Setup as 'Source' directory page.
593 inode_holder_type
xNode (aPage
.get());
596 &(xNode
->m_aNameBlock
.m_pData
[0]),
597 pSrcName
->buffer
, pSrcName
->length
);
599 // Store 'Destination' page key.
600 OStorePageKey
aDstKey (rDstKey
);
601 memcpy (&(xNode
->m_pData
[0]), &aDstKey
, sizeof(aDstKey
));
603 // Mark 'Source' as symbolic link to 'Destination'.
604 aPage
.attrib (STORE_ATTRIB_ISLINK
);
605 aPage
.dataLength (sal_uInt32(sizeof(aDstKey
)));
607 // Allocate and save 'Source' directory page.
608 eErrCode
= base::allocate (aPage
);
609 if (eErrCode
!= store_E_None
)
612 // Insert 'Source' entry.
613 PageHolderObject
< page
> xSrcNode (aSrcNode
.get());
614 OStorePageLink
aSrcLink (aPage
.location());
615 xSrcNode
->insert (i
+ 1, entry(aSrcKey
, aSrcLink
));
617 // Save modified NodePage.
618 return saveObjectAt (aSrcNode
, aSrcNode
.location());
623 * Precond: initialized, writeable.
625 storeError
OStorePageManager::rename (
626 const OStorePageKey
&rSrcKey
,
627 const rtl_String
*pDstPath
,
628 const rtl_String
*pDstName
)
630 // Acquire exclusive access.
631 osl::MutexGuard
aGuard(*this);
634 if (!self::isValid())
635 return store_E_InvalidAccess
;
637 if (!base::isWriteable())
638 return store_E_AccessViolation
;
640 // Check 'Destination' parameter.
641 storeError eErrCode
= store_E_InvalidParameter
;
642 if (!(pDstPath
&& pDstName
))
645 // Setup 'Destination' page key.
646 OStorePageKey aDstKey
;
647 eErrCode
= namei (pDstPath
, pDstName
, aDstKey
);
648 if (eErrCode
!= store_E_None
)
651 // Find 'Source' NodePage and Index.
652 OStoreBTreeNodeObject aSrcNode
;
654 eErrCode
= find_lookup (aSrcNode
, i
, rSrcKey
);
655 if (eErrCode
!= store_E_None
)
658 // Existing 'Source' entry.
659 PageHolderObject
< page
> xSrcNode (aSrcNode
.get());
660 entry
e (xSrcNode
->m_pData
[i
]);
662 // Check for (not a) hardlink.
663 OStoreDirectoryPageObject aPage
;
664 if (!(store::ntohl(e
.m_nAttrib
) & STORE_ATTRIB_ISLINK
))
666 // Load directory page.
667 eErrCode
= base::loadObjectAt (aPage
, e
.m_aLink
.location());
668 if (eErrCode
!= store_E_None
)
671 // Check for directory.
672 if (aPage
.attrib() & STORE_ATTRIB_ISDIR
)
674 // Ugly, but necessary (backward compatibility).
675 aDstKey
.m_nLow
= store::htonl(rtl_crc32 (store::ntohl(aDstKey
.m_nLow
), "/", 1));
679 // Let 'Source' entry be 'Destination' entry.
682 // Find 'Destination' NodePage and Index.
683 OStoreBTreeNodeObject aDstNode
;
684 eErrCode
= m_aRoot
.find_insert (aDstNode
, i
, e
.m_aKey
, *this);
685 if (eErrCode
!= store_E_None
)
688 // Insert 'Destination' entry.
689 PageHolderObject
< page
> xDstNode (aDstNode
.get());
690 xDstNode
->insert (i
+ 1, e
);
692 eErrCode
= saveObjectAt (aDstNode
, aDstNode
.location());
693 if (eErrCode
!= store_E_None
)
696 // Check for (not a) hardlink.
697 if (!(store::ntohl(e
.m_nAttrib
) & STORE_ATTRIB_ISLINK
))
699 // Modify 'Source' directory page.
700 inode_holder_type
xNode (aPage
.get());
702 // Setup 'Destination' NameBlock.
703 sal_Int32 nDstLen
= pDstName
->length
;
705 &(xNode
->m_aNameBlock
.m_pData
[0]),
706 pDstName
->buffer
, pDstName
->length
);
708 &(xNode
->m_aNameBlock
.m_pData
[nDstLen
]),
709 0, STORE_MAXIMUM_NAMESIZE
- nDstLen
);
710 aPage
.key (e
.m_aKey
);
712 // Save directory page.
713 eErrCode
= base::saveObjectAt (aPage
, e
.m_aLink
.location());
714 if (eErrCode
!= store_E_None
)
718 // Remove 'Source' entry.
720 return remove_Impl (e
);
725 * Precond: initialized, writeable.
727 storeError
OStorePageManager::remove (const OStorePageKey
&rKey
)
729 // Acquire exclusive access.
730 osl::MutexGuard
aGuard(*this);
733 if (!self::isValid())
734 return store_E_InvalidAccess
;
736 if (!base::isWriteable())
737 return store_E_AccessViolation
;
739 // Find NodePage and index.
740 OStoreBTreeNodeObject aNodePage
;
742 storeError eErrCode
= find_lookup (aNodePage
, i
, rKey
);
743 if (eErrCode
!= store_E_None
)
747 PageHolderObject
< page
> xNodePage (aNodePage
.get());
748 entry
e (xNodePage
->m_pData
[i
]);
750 // Check for (not a) hardlink.
751 if (!(store::ntohl(e
.m_nAttrib
) & STORE_ATTRIB_ISLINK
))
753 // Load directory page.
754 OStoreDirectoryPageObject aPage
;
755 eErrCode
= base::loadObjectAt (aPage
, e
.m_aLink
.location());
756 if (eErrCode
!= store_E_None
)
759 inode_holder_type
xNode (aPage
.get());
761 // Acquire page write access.
762 OStorePageDescriptor
aDescr (xNode
->m_aDescr
);
763 eErrCode
= base::acquirePage (aDescr
, store_AccessReadWrite
);
764 if (eErrCode
!= store_E_None
)
767 // Check for symbolic link.
768 if (!(aPage
.attrib() & STORE_ATTRIB_ISLINK
))
770 // Ordinary inode. Determine 'Data' scope.
771 inode::ChunkScope eScope
= xNode
->scope (aPage
.dataLength());
772 if (eScope
== inode::SCOPE_EXTERNAL
)
774 // External 'Data' scope. Truncate all external data pages.
775 eErrCode
= aPage
.truncate (0, *this);
776 if (eErrCode
!= store_E_None
)
780 // Truncate internal data page.
781 memset (&(xNode
->m_pData
[0]), 0, xNode
->capacity());
782 aPage
.dataLength (0);
785 // Release page write access.
786 eErrCode
= base::releasePage (aDescr
);
788 // Release and free directory page.
789 eErrCode
= base::free (aPage
.location());
793 return remove_Impl (e
);
799 struct RebuildContext
803 rtl::Reference
<OStorePageBIOS
> m_xBIOS
;
804 OStorePageBIOS::ScanContext m_aCtx
;
805 sal_uInt16 m_nPageSize
;
809 RebuildContext (void)
810 : m_xBIOS (new OStorePageBIOS()),
814 /** initialize (PageBIOS and ScanContext).
816 storeError
initialize (ILockBytes
*pLockBytes
, sal_uInt32 nMagic
= 0)
818 storeError eErrCode
= store_E_InvalidParameter
;
821 m_xBIOS
->initialize (pLockBytes
, store_AccessReadOnly
, m_nPageSize
);
822 eErrCode
= m_xBIOS
->scanBegin (m_aCtx
, nMagic
);
827 /** initialize (ScanContext).
829 storeError
initialize (sal_uInt32 nMagic
= 0)
831 return m_xBIOS
->scanBegin (m_aCtx
, nMagic
);
834 /** load (next ScanContext matching page).
836 storeError
load (OStorePageObject
&rPage
)
838 if (m_aCtx
.isValid())
839 return m_xBIOS
->scanNext (m_aCtx
, rPage
);
841 return store_E_CantSeek
;
849 storeError
OStorePageManager::rebuild (
850 ILockBytes
*pSrcLB
, ILockBytes
*pDstLB
)
852 // Acquire exclusive access.
853 osl::MutexGuard
aGuard(*this);
856 storeError eErrCode
= store_E_InvalidParameter
;
857 if (!(pSrcLB
&& pDstLB
))
860 // Initialize 'Source' rebuild context.
862 eErrCode
= aCtx
.initialize (pSrcLB
, STORE_MAGIC_DIRECTORYPAGE
);
863 if (eErrCode
!= store_E_None
)
865 rtl::Reference
<OStorePageBIOS
> xSrcBIOS (aCtx
.m_xBIOS
);
867 // Initialize as 'Destination' with 'Source' page size.
868 eErrCode
= self::initialize (pDstLB
, store_AccessCreate
, aCtx
.m_nPageSize
);
869 if (eErrCode
!= store_E_None
)
872 // Pass One: Scan 'Source' directory pages.
874 // Scan 'Source' directory pages.
875 OStoreDirectoryPageObject aSrcPage
;
876 while ((eErrCode
= aCtx
.load(aSrcPage
)) == store_E_None
)
878 OStoreDirectoryPageObject aDstPage
;
879 eErrCode
= aDstPage
.construct
< inode
>(base::allocator());
880 if (eErrCode
!= store_E_None
)
883 inode_holder_type
xSrcDir (aSrcPage
.get());
884 inode_holder_type
xDstDir (aDstPage
.get());
886 // Copy NameBlock @@@ OLD @@@
887 memcpy (&(xDstDir
->m_aNameBlock
), &(xSrcDir
->m_aNameBlock
), sizeof(xSrcDir
->m_aNameBlock
));
889 // Obtain 'Source' data length.
890 sal_uInt32 nDataLen
= aSrcPage
.dataLength();
893 // Copy internal data area @@@ OLD @@@
894 memcpy (&(xDstDir
->m_pData
[0]), &(xSrcDir
->m_pData
[0]), xSrcDir
->capacity());
897 // Insert 'Destination' directory page.
898 eErrCode
= save_dirpage_Impl (aDstPage
.key(), aDstPage
);
899 if (eErrCode
!= store_E_None
)
902 // Check for external data page scope.
903 if (xSrcDir
->scope(nDataLen
) != inode::SCOPE_INTERNAL
)
905 // Initialize 'Destination' data page.
906 typedef OStoreDataPageData data
;
907 PageHolderObject
< data
> xData
;
908 if (!xData
.construct(base::allocator()))
909 return store_E_OutOfMemory
;
911 // Determine data page count.
912 inode::ChunkDescriptor
aDescr (
913 nDataLen
- xDstDir
->capacity(), xData
->capacity());
915 sal_uInt32 i
, n
= aDescr
.m_nPage
;
916 if (aDescr
.m_nOffset
) n
+= 1;
919 OStoreDataPageObject aData
;
920 for (i
= 0; i
< n
; i
++)
922 // Read 'Source' data page.
923 osl::MutexGuard
aSrcGuard (*xSrcBIOS
);
925 eErrCode
= aSrcPage
.read (i
, aData
, *xSrcBIOS
);
926 if (eErrCode
!= store_E_None
)
929 // Write 'Destination' data page. @@@ READONLY @@@
930 eErrCode
= aDstPage
.write (i
, aData
, *this);
934 // Update 'Destination' directory page.
935 aDstPage
.dataLength (nDataLen
);
936 eErrCode
= base::saveObjectAt (aDstPage
, aDstPage
.location());
939 // Save directory scan results.
943 // Pass Two: Scan 'Source' BTree nodes.
945 // Re-start 'Source' rebuild context.
946 aCtx
.initialize (STORE_MAGIC_BTREENODE
);
948 // Scan 'Source' BTree nodes.
949 OStoreBTreeNodeObject aNode
;
950 while ((eErrCode
= aCtx
.load(aNode
)) == store_E_None
)
952 // Check for leaf node.
953 PageHolderObject
< page
> xNode (aNode
.get());
954 if (xNode
->depth() == 0)
956 sal_uInt16 i
, n
= xNode
->usageCount();
957 for (i
= 0; i
< n
; i
++)
959 entry
e (xNode
->m_pData
[i
]);
961 // Check for Hard link.
962 if (e
.m_nAttrib
& STORE_ATTRIB_ISLINK
)
964 // Load the hard link destination.
965 OStoreDirectoryPageObject aSrcPage
;
966 eErrCode
= xSrcBIOS
->loadObjectAt (aSrcPage
, e
.m_aLink
.location());
967 if (eErrCode
== store_E_None
)
969 OStorePageKey
aDstKey (aSrcPage
.key());
970 eErrCode
= link (e
.m_aKey
, aDstKey
);
972 e
.m_nAttrib
&= ~STORE_ATTRIB_ISLINK
;
977 // Ordinary attributes.
978 sal_uInt32 nAttrib
= 0;
979 eErrCode
= attrib (e
.m_aKey
, 0, e
.m_nAttrib
, nAttrib
);
985 // Save BTree node scan results.
993 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */