1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: storpage.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_store.hxx"
34 #include "storpage.hxx"
36 #include "sal/types.h"
37 #include "rtl/string.h"
38 #include "rtl/ref.hxx"
39 #include "osl/diagnose.h"
40 #include "osl/mutex.hxx"
42 #include "store/types.h"
45 #include "lockbyte.hxx"
47 #include "storbase.hxx"
48 #include "stordata.hxx"
49 #include "stortree.hxx"
51 using namespace store
;
53 /*========================================================================
55 * OStorePageManager implementation.
57 *======================================================================*/
58 const sal_uInt32
OStorePageManager::m_nTypeId
= sal_uInt32(0x62190120);
63 OStorePageManager::OStorePageManager (void)
70 OStorePageManager::~OStorePageManager (void)
77 sal_Bool SAL_CALL
OStorePageManager::isKindOf (sal_uInt32 nTypeId
)
79 return (nTypeId
== m_nTypeId
);
83 * initialize (two-phase construction).
86 storeError
OStorePageManager::initialize (
87 ILockBytes
* pLockBytes
,
88 storeAccessMode eAccessMode
,
89 sal_uInt16
& rnPageSize
)
91 // Acquire exclusive access.
92 osl::MutexGuard
aGuard(*this);
96 return store_E_InvalidParameter
;
99 storeError eErrCode
= base::initialize (pLockBytes
, eAccessMode
, rnPageSize
);
100 if (eErrCode
!= store_E_None
)
103 // Check for (not) writeable.
104 if (!base::isWriteable())
106 // Readonly. Load RootNode.
107 return base::loadObjectAt (m_aRoot
, rnPageSize
);
110 // Writeable. Load or Create RootNode.
111 eErrCode
= m_aRoot
.loadOrCreate (rnPageSize
, *this);
112 if (eErrCode
== store_E_Pending
)
114 // Creation notification.
115 PageHolderObject
< page
> xRoot (m_aRoot
.get());
117 // Pre-allocate left most entry (ugly, but we can't insert to left).
118 OStorePageKey
aKey (rtl_crc32 (0, "/", 1), 0);
119 xRoot
->insert (0, entry(aKey
));
122 eErrCode
= base::saveObjectAt (m_aRoot
, rnPageSize
);
123 if (eErrCode
!= store_E_None
)
126 // Flush for robustness.
127 (void) base::flush();
135 * find_lookup (w/o split()).
136 * Internal: Precond: initialized, readable, exclusive access.
138 storeError
OStorePageManager::find_lookup (
139 OStoreBTreeNodeObject
& rNode
,
141 OStorePageKey
const & rKey
)
143 // Find Node and Index.
144 storeError eErrCode
= m_aRoot
.find_lookup (rNode
, rIndex
, rKey
, *this);
145 if (eErrCode
!= store_E_None
)
149 PageHolderObject
< page
> xPage (rNode
.get());
150 OSL_POSTCOND(rIndex
< xPage
->usageCount(), "store::PageManager::find_lookup(): logic error");
151 entry
e (xPage
->m_pData
[rIndex
]);
153 // Check for exact match.
154 if (e
.compare(entry(rKey
)) != entry::COMPARE_EQUAL
)
157 return store_E_NotExists
;
161 if (e
.m_aLink
.location() == STORE_PAGE_NULL
)
164 return store_E_NotExists
;
171 * remove_Impl (possibly down from root).
172 * Internal: Precond: initialized, writeable, exclusive access.
175 storeError
OStorePageManager::remove_Impl (entry
& rEntry
)
177 // Find Node and Index.
178 OStoreBTreeNodeObject aNode
;
179 sal_uInt16 nIndex
= 0;
180 eErrCode
= m_aRoot
.find_lookup (aNode
, nIndex
, entry::CompareGreater(rEntry
), *this);
184 PageHolderObject
< page
> xPage (aNode
.get());
185 page
& rPage
= (*xPage
);
187 // Check current page index.
188 sal_uInt16 i
= rPage
.find (rEntry
), n
= rPage
.usageCount();
191 // Path to entry not exists (Must not happen(?)).
192 return store_E_NotExists
;
196 entry::CompareResult result
= rEntry
.compare (rPage
.m_pData
[i
]);
198 for (; result
== entry::COMPARE_GREATER
&& xPage
->depth() > 0; )
200 // Check next node address.
201 sal_uInt32
const nAddr
= rPage
.m_pData
[i
].m_aLink
.location();
202 if (nAddr
== STORE_PAGE_NULL
)
204 // Path to entry not exists (Must not happen(?)).
205 return store_E_NotExists
;
208 // Load next node page.
209 eErrCode
= loadObjectAt (aNode
, nAddr
);
211 PageHolderObject
< page
> xNext (aNode
.get());
215 aNode
.remove (nIndex
, rEntry
, *this);
220 // Load next node page.
221 eErrCode
= loadObjectAt (aNode
, nAddr
);
223 page
const & rPage
= (*xPage
);
225 // Check current page index.
226 sal_uInt16 i
= rPage
.find (rEntry
), n
= rPage
.usageCount();
229 // Path to entry not exists (Must not happen(?)).
230 return store_E_NotExists
;
234 result
= rEntry
.compare (rPage
.m_pData
[i
]);
236 } while (result
== entry::COMPATE_GREATER
);
240 storeError
OStorePageManager::remove_Impl (entry
& rEntry
)
242 OStoreBTreeNodeObject
aNode (m_aRoot
.get());
244 // Check current page index.
245 PageHolderObject
< page
> xPage (aNode
.get());
246 sal_uInt16 i
= xPage
->find (rEntry
), n
= xPage
->usageCount();
249 // Path to entry not exists (Must not happen(?)).
250 return store_E_NotExists
;
254 entry::CompareResult result
= rEntry
.compare (xPage
->m_pData
[i
]);
256 // Iterate down until equal match.
257 while ((result
== entry::COMPARE_GREATER
) && (xPage
->depth() > 0))
259 // Check link address.
260 sal_uInt32
const nAddr
= xPage
->m_pData
[i
].m_aLink
.location();
261 if (nAddr
== STORE_PAGE_NULL
)
263 // Path to entry not exists (Must not happen(?)).
264 return store_E_NotExists
;
268 storeError eErrCode
= loadObjectAt (aNode
, nAddr
);
269 if (eErrCode
!= store_E_None
)
272 PageHolderObject
< page
> xNext (aNode
.get());
276 i
= xPage
->find (rEntry
), n
= xPage
->usageCount();
279 // Path to entry not exists (Must not happen(?)).
280 return store_E_NotExists
;
284 result
= rEntry
.compare (xPage
->m_pData
[i
]);
288 result
!= entry::COMPARE_LESS
,
289 "OStorePageManager::remove(): find failed");
291 // Check entry comparison.
292 if (result
== entry::COMPARE_LESS
)
295 return store_E_Unknown
;
298 // Remove down from current page (recursive).
299 return aNode
.remove (i
, rEntry
, *this);
304 * Precond: none (static).
306 storeError
OStorePageManager::namei (
307 const rtl_String
*pPath
, const rtl_String
*pName
, OStorePageKey
&rKey
)
310 if (!(pPath
&& pName
))
311 return store_E_InvalidParameter
;
313 // Check name length.
314 if (!(pName
->length
< STORE_MAXIMUM_NAMESIZE
))
315 return store_E_NameTooLong
;
317 // Transform pathname into key.
318 rKey
.m_nLow
= store::htonl(rtl_crc32 (0, pName
->buffer
, pName
->length
));
319 rKey
.m_nHigh
= store::htonl(rtl_crc32 (0, pPath
->buffer
, pPath
->length
));
327 * Precond: initialized.
329 storeError
OStorePageManager::iget (
330 OStoreDirectoryPageObject
& rPage
,
332 const rtl_String
* pPath
,
333 const rtl_String
* pName
,
334 storeAccessMode eMode
)
336 // Acquire exclusive access.
337 osl::MutexGuard
aGuard(*this);
340 if (!self::isValid())
341 return store_E_InvalidAccess
;
343 // Setup inode page key.
345 storeError eErrCode
= namei (pPath
, pName
, aKey
);
346 if (eErrCode
!= store_E_None
)
349 // Check for directory.
350 if (nAttrib
& STORE_ATTRIB_ISDIR
)
352 // Ugly, but necessary (backward compatibility).
353 aKey
.m_nLow
= store::htonl(rtl_crc32 (store::ntohl(aKey
.m_nLow
), "/", 1));
357 eErrCode
= load_dirpage_Impl (aKey
, rPage
);
358 if (eErrCode
!= store_E_None
)
360 // Check mode and reason.
361 if (eErrCode
!= store_E_NotExists
)
364 if (eMode
== store_AccessReadWrite
)
365 return store_E_NotExists
;
366 if (eMode
== store_AccessReadOnly
)
367 return store_E_NotExists
;
369 if (!base::isWriteable())
370 return store_E_AccessViolation
;
372 // Create inode page.
373 eErrCode
= rPage
.construct
< inode
>(base::allocator());
374 if (eErrCode
!= store_E_None
)
377 // Setup inode nameblock.
378 PageHolderObject
< inode
> xPage (rPage
.get());
381 rPage
.attrib (nAttrib
);
384 &(xPage
->m_aNameBlock
.m_pData
[0]),
385 pName
->buffer
, pName
->length
);
388 eErrCode
= save_dirpage_Impl (aKey
, rPage
);
389 if (eErrCode
!= store_E_None
)
393 // Check for symbolic link.
394 if (rPage
.attrib() & STORE_ATTRIB_ISLINK
)
396 // Obtain 'Destination' page key.
397 PageHolderObject
< inode
> xPage (rPage
.get());
398 OStorePageKey aDstKey
;
399 memcpy (&aDstKey
, &(xPage
->m_pData
[0]), sizeof(aDstKey
));
401 // Load 'Destination' inode.
402 eErrCode
= load_dirpage_Impl (aDstKey
, rPage
);
403 if (eErrCode
!= store_E_None
)
413 * Precond: initialized.
414 * ToDo: skip hardlink entries.
416 storeError
OStorePageManager::iterate (
417 OStorePageKey
& rKey
,
418 OStorePageLink
& rLink
,
419 sal_uInt32
& rAttrib
)
421 // Acquire exclusive access.
422 osl::MutexGuard
aGuard(*this);
425 if (!self::isValid())
426 return store_E_InvalidAccess
;
428 // Find NodePage and Index.
429 OStoreBTreeNodeObject aNode
;
431 storeError eErrCode
= m_aRoot
.find_lookup (aNode
, i
, rKey
, *this);
432 if (eErrCode
!= store_E_None
)
435 // GreaterEqual. Found next entry.
436 PageHolderObject
< page
> xNode (aNode
.get());
437 entry
e (xNode
->m_pData
[i
]);
442 rAttrib
= store::ntohl(e
.m_nAttrib
);
449 * load => private: iget() @@@
450 * Internal: Precond: initialized, exclusive access.
452 storeError
OStorePageManager::load_dirpage_Impl (
453 const OStorePageKey
&rKey
,
454 OStoreDirectoryPageObject
&rPage
)
456 // Find Node and Index.
457 OStoreBTreeNodeObject aNode
;
459 storeError eErrCode
= find_lookup (aNode
, i
, rKey
);
460 if (eErrCode
!= store_E_None
)
463 // Existing entry. Load page.
464 PageHolderObject
< page
> xNode (aNode
.get());
465 entry
e (xNode
->m_pData
[i
]);
466 return loadObjectAt (rPage
, e
.m_aLink
.location());
470 * save => private: iget(), rebuild() @@@
471 * Internal: Precond: initialized, writeable, exclusive access.
473 storeError
OStorePageManager::save_dirpage_Impl (
474 const OStorePageKey
&rKey
,
475 OStoreDirectoryPageObject
&rPage
)
477 // Find NodePage and Index.
481 storeError eErrCode
= m_aRoot
.find_insert (aNode
, i
, rKey
, *this);
482 PageHolderObject
< page
> xNode (aNode
.get());
483 if (eErrCode
!= store_E_None
)
485 if (eErrCode
!= store_E_AlreadyExists
)
489 entry
e (xNode
->m_pData
[i
]);
490 if (e
.m_aLink
.location() != STORE_PAGE_NULL
)
492 // Save page to existing location.
493 return saveObjectAt (rPage
, e
.m_aLink
.location());
497 eErrCode
= base::allocate (rPage
);
498 if (eErrCode
!= store_E_None
)
501 // Update page location.
502 xNode
->m_pData
[i
].m_aLink
= rPage
.location();
504 // Save modified NodePage.
505 return saveObjectAt (aNode
, aNode
.location());
509 eErrCode
= base::allocate (rPage
);
510 if (eErrCode
!= store_E_None
)
514 OStorePageLink
aLink (rPage
.location());
515 xNode
->insert (i
+ 1, entry (rKey
, aLink
));
517 // Save modified NodePage.
518 return saveObjectAt (aNode
, aNode
.location());
522 * attrib [nAttrib = ((nAttrib & ~nMask1) | nMask2)].
523 * Precond: initialized.
525 storeError
OStorePageManager::attrib (
526 const OStorePageKey
&rKey
,
531 // Acquire exclusive access.
532 osl::MutexGuard
aGuard(*this);
535 if (!self::isValid())
536 return store_E_InvalidAccess
;
538 // Find NodePage and index.
539 OStoreBTreeNodeObject aNode
;
541 storeError eErrCode
= find_lookup (aNode
, i
, rKey
);
542 if (eErrCode
!= store_E_None
)
546 PageHolderObject
< page
> xNode (aNode
.get());
547 entry
e (xNode
->m_pData
[i
]);
548 if (nMask1
!= nMask2
)
550 // Evaluate new attributes.
551 sal_uInt32 nAttrib
= store::ntohl(e
.m_nAttrib
);
556 if (store::htonl(nAttrib
) != e
.m_nAttrib
)
558 // Check access mode.
559 if (base::isWriteable())
561 // Set new attributes.
562 e
.m_nAttrib
= store::htonl(nAttrib
);
563 xNode
->m_pData
[i
] = e
;
565 // Save modified NodePage.
566 eErrCode
= saveObjectAt (aNode
, aNode
.location());
571 eErrCode
= store_E_AccessViolation
;
576 // Obtain current attributes.
577 rAttrib
= store::ntohl(e
.m_nAttrib
);
582 * link (insert 'Source' as hardlink to 'Destination').
583 * Precond: initialized, writeable.
585 storeError
OStorePageManager::link (
586 const OStorePageKey
&rSrcKey
,
587 const OStorePageKey
&rDstKey
)
589 // Acquire exclusive access.
590 osl::MutexGuard
aGuard(*this);
593 if (!self::isValid())
594 return store_E_InvalidAccess
;
596 if (!base::isWriteable())
597 return store_E_AccessViolation
;
599 // Find 'Destination' NodePage and Index.
600 OStoreBTreeNodeObject aDstNode
;
602 storeError eErrCode
= find_lookup (aDstNode
, i
, rDstKey
);
603 if (eErrCode
!= store_E_None
)
606 // Existing 'Destination' entry.
607 PageHolderObject
< page
> xDstNode (aDstNode
.get());
608 entry
e (xDstNode
->m_pData
[i
]);
609 OStorePageLink
aDstLink (e
.m_aLink
);
611 // Find 'Source' NodePage and Index.
612 OStoreBTreeNodeObject aSrcNode
;
613 eErrCode
= m_aRoot
.find_insert (aSrcNode
, i
, rSrcKey
, *this);
614 if (eErrCode
!= store_E_None
)
617 // Insert 'Source' entry.
618 PageHolderObject
< page
> xSrcNode (aSrcNode
.get());
619 xSrcNode
->insert (i
+ 1, entry (rSrcKey
, aDstLink
, STORE_ATTRIB_ISLINK
));
620 return saveObjectAt (aSrcNode
, aSrcNode
.location());
624 * symlink (insert 'Source' DirectoryPage as symlink to 'Destination').
625 * Precond: initialized, writeable.
627 storeError
OStorePageManager::symlink (
628 const rtl_String
*pSrcPath
,
629 const rtl_String
*pSrcName
,
630 const OStorePageKey
&rDstKey
)
632 // Acquire exclusive access.
633 osl::MutexGuard
aGuard(*this);
636 if (!self::isValid())
637 return store_E_InvalidAccess
;
639 if (!base::isWriteable())
640 return store_E_AccessViolation
;
642 // Check 'Source' parameter.
643 storeError eErrCode
= store_E_InvalidParameter
;
644 if (!(pSrcPath
&& pSrcName
))
647 // Setup 'Source' page key.
648 OStorePageKey aSrcKey
;
649 eErrCode
= namei (pSrcPath
, pSrcName
, aSrcKey
);
650 if (eErrCode
!= store_E_None
)
653 // Find 'Source' NodePage and Index.
654 OStoreBTreeNodeObject aSrcNode
;
656 eErrCode
= m_aRoot
.find_insert (aSrcNode
, i
, aSrcKey
, *this);
657 if (eErrCode
!= store_E_None
)
660 // Initialize directory page.
661 OStoreDirectoryPageObject aPage
;
662 eErrCode
= aPage
.construct
< inode
>(base::allocator());
663 if (eErrCode
!= store_E_None
)
666 // Setup as 'Source' directory page.
667 inode_holder_type
xNode (aPage
.get());
670 &(xNode
->m_aNameBlock
.m_pData
[0]),
671 pSrcName
->buffer
, pSrcName
->length
);
673 // Store 'Destination' page key.
674 OStorePageKey
aDstKey (rDstKey
);
675 memcpy (&(xNode
->m_pData
[0]), &aDstKey
, sizeof(aDstKey
));
677 // Mark 'Source' as symbolic link to 'Destination'.
678 aPage
.attrib (STORE_ATTRIB_ISLINK
);
679 aPage
.dataLength (sal_uInt32(sizeof(aDstKey
)));
681 // Allocate and save 'Source' directory page.
682 eErrCode
= base::allocate (aPage
);
683 if (eErrCode
!= store_E_None
)
686 // Insert 'Source' entry.
687 PageHolderObject
< page
> xSrcNode (aSrcNode
.get());
688 OStorePageLink
aSrcLink (aPage
.location());
689 xSrcNode
->insert (i
+ 1, entry(aSrcKey
, aSrcLink
));
691 // Save modified NodePage.
692 return saveObjectAt (aSrcNode
, aSrcNode
.location());
697 * Precond: initialized, writeable.
699 storeError
OStorePageManager::rename (
700 const OStorePageKey
&rSrcKey
,
701 const rtl_String
*pDstPath
,
702 const rtl_String
*pDstName
)
704 // Acquire exclusive access.
705 osl::MutexGuard
aGuard(*this);
708 if (!self::isValid())
709 return store_E_InvalidAccess
;
711 if (!base::isWriteable())
712 return store_E_AccessViolation
;
714 // Check 'Destination' parameter.
715 storeError eErrCode
= store_E_InvalidParameter
;
716 if (!(pDstPath
&& pDstName
))
719 // Setup 'Destination' page key.
720 OStorePageKey aDstKey
;
721 eErrCode
= namei (pDstPath
, pDstName
, aDstKey
);
722 if (eErrCode
!= store_E_None
)
725 // Find 'Source' NodePage and Index.
726 OStoreBTreeNodeObject aSrcNode
;
728 eErrCode
= find_lookup (aSrcNode
, i
, rSrcKey
);
729 if (eErrCode
!= store_E_None
)
732 // Existing 'Source' entry.
733 PageHolderObject
< page
> xSrcNode (aSrcNode
.get());
734 entry
e (xSrcNode
->m_pData
[i
]);
736 // Check for (not a) hardlink.
737 OStoreDirectoryPageObject aPage
;
738 if (!(store::ntohl(e
.m_nAttrib
) & STORE_ATTRIB_ISLINK
))
740 // Load directory page.
741 eErrCode
= base::loadObjectAt (aPage
, e
.m_aLink
.location());
742 if (eErrCode
!= store_E_None
)
745 // Check for directory.
746 if (aPage
.attrib() & STORE_ATTRIB_ISDIR
)
748 // Ugly, but necessary (backward compatibility).
749 aDstKey
.m_nLow
= store::htonl(rtl_crc32 (store::ntohl(aDstKey
.m_nLow
), "/", 1));
753 // Let 'Source' entry be 'Destination' entry.
756 // Find 'Destination' NodePage and Index.
757 OStoreBTreeNodeObject aDstNode
;
758 eErrCode
= m_aRoot
.find_insert (aDstNode
, i
, e
.m_aKey
, *this);
759 if (eErrCode
!= store_E_None
)
762 // Insert 'Destination' entry.
763 PageHolderObject
< page
> xDstNode (aDstNode
.get());
764 xDstNode
->insert (i
+ 1, e
);
766 eErrCode
= saveObjectAt (aDstNode
, aDstNode
.location());
767 if (eErrCode
!= store_E_None
)
770 // Check for (not a) hardlink.
771 if (!(store::ntohl(e
.m_nAttrib
) & STORE_ATTRIB_ISLINK
))
773 // Modify 'Source' directory page.
774 inode_holder_type
xNode (aPage
.get());
776 // Setup 'Destination' NameBlock.
777 sal_Int32 nDstLen
= pDstName
->length
;
779 &(xNode
->m_aNameBlock
.m_pData
[0]),
780 pDstName
->buffer
, pDstName
->length
);
782 &(xNode
->m_aNameBlock
.m_pData
[nDstLen
]),
783 0, STORE_MAXIMUM_NAMESIZE
- nDstLen
);
784 aPage
.key (e
.m_aKey
);
786 // Save directory page.
787 eErrCode
= base::saveObjectAt (aPage
, e
.m_aLink
.location());
788 if (eErrCode
!= store_E_None
)
792 // Remove 'Source' entry.
794 return remove_Impl (e
);
799 * Precond: initialized, writeable.
801 storeError
OStorePageManager::remove (const OStorePageKey
&rKey
)
803 // Acquire exclusive access.
804 osl::MutexGuard
aGuard(*this);
807 if (!self::isValid())
808 return store_E_InvalidAccess
;
810 if (!base::isWriteable())
811 return store_E_AccessViolation
;
813 // Find NodePage and index.
814 OStoreBTreeNodeObject aNodePage
;
816 storeError eErrCode
= find_lookup (aNodePage
, i
, rKey
);
817 if (eErrCode
!= store_E_None
)
821 PageHolderObject
< page
> xNodePage (aNodePage
.get());
822 entry
e (xNodePage
->m_pData
[i
]);
824 // Check for (not a) hardlink.
825 if (!(store::ntohl(e
.m_nAttrib
) & STORE_ATTRIB_ISLINK
))
827 // Load directory page.
828 OStoreDirectoryPageObject aPage
;
829 eErrCode
= base::loadObjectAt (aPage
, e
.m_aLink
.location());
830 if (eErrCode
!= store_E_None
)
833 inode_holder_type
xNode (aPage
.get());
835 // Acquire page write access.
836 OStorePageDescriptor
aDescr (xNode
->m_aDescr
);
837 eErrCode
= base::acquirePage (aDescr
, store_AccessReadWrite
);
838 if (eErrCode
!= store_E_None
)
841 // Check for symbolic link.
842 if (!(aPage
.attrib() & STORE_ATTRIB_ISLINK
))
844 // Ordinary inode. Determine 'Data' scope.
845 inode::ChunkScope eScope
= xNode
->scope (aPage
.dataLength());
846 if (eScope
== inode::SCOPE_EXTERNAL
)
848 // External 'Data' scope. Truncate all external data pages.
849 eErrCode
= aPage
.truncate (0, *this);
850 if (eErrCode
!= store_E_None
)
854 // Truncate internal data page.
855 memset (&(xNode
->m_pData
[0]), 0, xNode
->capacity());
856 aPage
.dataLength (0);
859 // Release page write access.
860 eErrCode
= base::releasePage (aDescr
, store_AccessReadWrite
);
862 // Release and free directory page.
863 OStorePageData aPageHead
;
864 eErrCode
= base::free (aPageHead
, aPage
.location());
868 return remove_Impl (e
);
874 struct RebuildContext
878 rtl::Reference
<OStorePageBIOS
> m_xBIOS
;
879 OStorePageBIOS::ScanContext m_aCtx
;
880 sal_uInt16 m_nPageSize
;
884 RebuildContext (void)
885 : m_xBIOS (new OStorePageBIOS()),
889 /** initialize (PageBIOS and ScanContext).
891 storeError
initialize (ILockBytes
*pLockBytes
, sal_uInt32 nMagic
= 0)
893 storeError eErrCode
= store_E_InvalidParameter
;
896 m_xBIOS
->initialize (pLockBytes
, store_AccessReadOnly
, m_nPageSize
);
897 eErrCode
= m_xBIOS
->scanBegin (m_aCtx
, nMagic
);
902 /** initialize (ScanContext).
904 storeError
initialize (sal_uInt32 nMagic
= 0)
906 return m_xBIOS
->scanBegin (m_aCtx
, nMagic
);
909 /** load (next ScanContext matching page).
911 storeError
load (OStorePageObject
&rPage
)
913 if (m_aCtx
.isValid())
914 return m_xBIOS
->scanNext (m_aCtx
, rPage
);
916 return store_E_CantSeek
;
924 storeError
OStorePageManager::rebuild (
925 ILockBytes
*pSrcLB
, ILockBytes
*pDstLB
)
927 // Acquire exclusive access.
928 osl::MutexGuard
aGuard(*this);
931 storeError eErrCode
= store_E_InvalidParameter
;
932 if (!(pSrcLB
&& pDstLB
))
935 // Initialize 'Source' rebuild context.
937 eErrCode
= aCtx
.initialize (pSrcLB
, STORE_MAGIC_DIRECTORYPAGE
);
938 if (eErrCode
!= store_E_None
)
940 rtl::Reference
<OStorePageBIOS
> xSrcBIOS (aCtx
.m_xBIOS
);
942 // Initialize as 'Destination' with 'Source' page size.
943 eErrCode
= self::initialize (pDstLB
, store_AccessCreate
, aCtx
.m_nPageSize
);
944 if (eErrCode
!= store_E_None
)
947 // Pass One: Scan 'Source' directory pages.
949 // Scan 'Source' directory pages.
950 OStoreDirectoryPageObject aSrcPage
;
951 while ((eErrCode
= aCtx
.load(aSrcPage
)) == store_E_None
)
953 OStoreDirectoryPageObject aDstPage
;
954 eErrCode
= aDstPage
.construct
< inode
>(base::allocator());
955 if (eErrCode
!= store_E_None
)
958 inode_holder_type
xSrcDir (aSrcPage
.get());
959 inode_holder_type
xDstDir (aDstPage
.get());
961 // Copy NameBlock @@@ OLD @@@
962 memcpy (&(xDstDir
->m_aNameBlock
), &(xSrcDir
->m_aNameBlock
), sizeof(xSrcDir
->m_aNameBlock
));
964 // Obtain 'Source' data length.
965 sal_uInt32 nDataLen
= aSrcPage
.dataLength();
968 // Copy internal data area @@@ OLD @@@
969 memcpy (&(xDstDir
->m_pData
[0]), &(xSrcDir
->m_pData
[0]), xSrcDir
->capacity());
972 // Insert 'Destination' directory page.
973 eErrCode
= save_dirpage_Impl (aDstPage
.key(), aDstPage
);
974 if (eErrCode
!= store_E_None
)
977 // Check for external data page scope.
978 if (xSrcDir
->scope(nDataLen
) != inode::SCOPE_INTERNAL
)
980 // Initialize 'Destination' data page.
981 typedef OStoreDataPageData data
;
982 PageHolderObject
< data
> xData
;
983 if (!xData
.construct(base::allocator()))
984 return store_E_OutOfMemory
;
986 // Determine data page count.
987 inode::ChunkDescriptor
aDescr (
988 nDataLen
- xDstDir
->capacity(), xData
->capacity());
990 sal_uInt32 i
, n
= aDescr
.m_nPage
;
991 if (aDescr
.m_nOffset
) n
+= 1;
994 OStoreDataPageObject aData
;
995 for (i
= 0; i
< n
; i
++)
997 // Read 'Source' data page.
998 osl::MutexGuard
aSrcGuard (*xSrcBIOS
);
1000 eErrCode
= aSrcPage
.read (i
, aData
, *xSrcBIOS
);
1001 if (eErrCode
!= store_E_None
)
1004 // Write 'Destination' data page. @@@ READONLY @@@
1005 eErrCode
= aDstPage
.write (i
, aData
, *this);
1009 // Update 'Destination' directory page.
1010 aDstPage
.dataLength (nDataLen
);
1011 eErrCode
= base::saveObjectAt (aDstPage
, aDstPage
.location());
1014 // Save directory scan results.
1018 // Pass Two: Scan 'Source' BTree nodes.
1020 // Re-start 'Source' rebuild context.
1021 aCtx
.initialize (STORE_MAGIC_BTREENODE
);
1023 // Scan 'Source' BTree nodes.
1024 OStoreBTreeNodeObject aNode
;
1025 while ((eErrCode
= aCtx
.load(aNode
)) == store_E_None
)
1027 // Check for leaf node.
1028 PageHolderObject
< page
> xNode (aNode
.get());
1029 if (xNode
->depth() == 0)
1031 sal_uInt16 i
, n
= xNode
->usageCount();
1032 for (i
= 0; i
< n
; i
++)
1034 entry
e (xNode
->m_pData
[i
]);
1036 // Check for Hard link.
1037 if (e
.m_nAttrib
& STORE_ATTRIB_ISLINK
)
1039 // Load the hard link destination.
1040 OStoreDirectoryPageObject aSrcPage
;
1041 eErrCode
= xSrcBIOS
->loadObjectAt (aSrcPage
, e
.m_aLink
.location());
1042 if (eErrCode
== store_E_None
)
1044 OStorePageKey
aDstKey (aSrcPage
.key());
1045 eErrCode
= link (e
.m_aKey
, aDstKey
);
1047 e
.m_nAttrib
&= ~STORE_ATTRIB_ISLINK
;
1052 // Ordinary attributes.
1053 sal_uInt32 nAttrib
= 0;
1054 eErrCode
= attrib (e
.m_aKey
, 0, e
.m_nAttrib
, nAttrib
);
1060 // Save BTree node scan results.
1065 return store_E_None
;