xref: /aoo4110/main/store/source/storpage.cxx (revision b1cdbd2c)
1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski  *
3*b1cdbd2cSJim Jagielski  * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski  * or more contributor license agreements.  See the NOTICE file
5*b1cdbd2cSJim Jagielski  * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski  * regarding copyright ownership.  The ASF licenses this file
7*b1cdbd2cSJim Jagielski  * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski  * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski  * with the License.  You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski  *
11*b1cdbd2cSJim Jagielski  *   http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski  *
13*b1cdbd2cSJim Jagielski  * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski  * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski  * KIND, either express or implied.  See the License for the
17*b1cdbd2cSJim Jagielski  * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski  * under the License.
19*b1cdbd2cSJim Jagielski  *
20*b1cdbd2cSJim Jagielski  *************************************************************/
21*b1cdbd2cSJim Jagielski 
22*b1cdbd2cSJim Jagielski 
23*b1cdbd2cSJim Jagielski 
24*b1cdbd2cSJim Jagielski // MARKER(update_precomp.py): autogen include statement, do not remove
25*b1cdbd2cSJim Jagielski #include "precompiled_store.hxx"
26*b1cdbd2cSJim Jagielski 
27*b1cdbd2cSJim Jagielski #include "storpage.hxx"
28*b1cdbd2cSJim Jagielski 
29*b1cdbd2cSJim Jagielski #include "sal/types.h"
30*b1cdbd2cSJim Jagielski #include "rtl/string.h"
31*b1cdbd2cSJim Jagielski #include "rtl/ref.hxx"
32*b1cdbd2cSJim Jagielski #include "osl/diagnose.h"
33*b1cdbd2cSJim Jagielski #include "osl/mutex.hxx"
34*b1cdbd2cSJim Jagielski 
35*b1cdbd2cSJim Jagielski #include "store/types.h"
36*b1cdbd2cSJim Jagielski 
37*b1cdbd2cSJim Jagielski #include "object.hxx"
38*b1cdbd2cSJim Jagielski #include "lockbyte.hxx"
39*b1cdbd2cSJim Jagielski 
40*b1cdbd2cSJim Jagielski #include "storbase.hxx"
41*b1cdbd2cSJim Jagielski #include "stordata.hxx"
42*b1cdbd2cSJim Jagielski #include "stortree.hxx"
43*b1cdbd2cSJim Jagielski 
44*b1cdbd2cSJim Jagielski using namespace store;
45*b1cdbd2cSJim Jagielski 
46*b1cdbd2cSJim Jagielski /*========================================================================
47*b1cdbd2cSJim Jagielski  *
48*b1cdbd2cSJim Jagielski  * OStorePageManager implementation.
49*b1cdbd2cSJim Jagielski  *
50*b1cdbd2cSJim Jagielski  *======================================================================*/
51*b1cdbd2cSJim Jagielski const sal_uInt32 OStorePageManager::m_nTypeId = sal_uInt32(0x62190120);
52*b1cdbd2cSJim Jagielski 
53*b1cdbd2cSJim Jagielski /*
54*b1cdbd2cSJim Jagielski  * OStorePageManager.
55*b1cdbd2cSJim Jagielski  */
OStorePageManager(void)56*b1cdbd2cSJim Jagielski OStorePageManager::OStorePageManager (void)
57*b1cdbd2cSJim Jagielski {
58*b1cdbd2cSJim Jagielski }
59*b1cdbd2cSJim Jagielski 
60*b1cdbd2cSJim Jagielski /*
61*b1cdbd2cSJim Jagielski  * ~OStorePageManager.
62*b1cdbd2cSJim Jagielski  */
~OStorePageManager(void)63*b1cdbd2cSJim Jagielski OStorePageManager::~OStorePageManager (void)
64*b1cdbd2cSJim Jagielski {
65*b1cdbd2cSJim Jagielski }
66*b1cdbd2cSJim Jagielski 
67*b1cdbd2cSJim Jagielski /*
68*b1cdbd2cSJim Jagielski  * isKindOf.
69*b1cdbd2cSJim Jagielski  */
isKindOf(sal_uInt32 nTypeId)70*b1cdbd2cSJim Jagielski sal_Bool SAL_CALL OStorePageManager::isKindOf (sal_uInt32 nTypeId)
71*b1cdbd2cSJim Jagielski {
72*b1cdbd2cSJim Jagielski 	return (nTypeId == m_nTypeId);
73*b1cdbd2cSJim Jagielski }
74*b1cdbd2cSJim Jagielski 
75*b1cdbd2cSJim Jagielski /*
76*b1cdbd2cSJim Jagielski  * initialize (two-phase construction).
77*b1cdbd2cSJim Jagielski  * Precond: none.
78*b1cdbd2cSJim Jagielski  */
initialize(ILockBytes * pLockBytes,storeAccessMode eAccessMode,sal_uInt16 & rnPageSize)79*b1cdbd2cSJim Jagielski storeError OStorePageManager::initialize (
80*b1cdbd2cSJim Jagielski 	ILockBytes *    pLockBytes,
81*b1cdbd2cSJim Jagielski 	storeAccessMode eAccessMode,
82*b1cdbd2cSJim Jagielski 	sal_uInt16 &    rnPageSize)
83*b1cdbd2cSJim Jagielski {
84*b1cdbd2cSJim Jagielski 	// Acquire exclusive access.
85*b1cdbd2cSJim Jagielski 	osl::MutexGuard aGuard(*this);
86*b1cdbd2cSJim Jagielski 
87*b1cdbd2cSJim Jagielski 	// Check arguments.
88*b1cdbd2cSJim Jagielski 	if (!pLockBytes)
89*b1cdbd2cSJim Jagielski 		return store_E_InvalidParameter;
90*b1cdbd2cSJim Jagielski 
91*b1cdbd2cSJim Jagielski 	// Initialize base.
92*b1cdbd2cSJim Jagielski 	storeError eErrCode = base::initialize (pLockBytes, eAccessMode, rnPageSize);
93*b1cdbd2cSJim Jagielski 	if (eErrCode != store_E_None)
94*b1cdbd2cSJim Jagielski 		return eErrCode;
95*b1cdbd2cSJim Jagielski 
96*b1cdbd2cSJim Jagielski 	// Check for (not) writeable.
97*b1cdbd2cSJim Jagielski     if (!base::isWriteable())
98*b1cdbd2cSJim Jagielski     {
99*b1cdbd2cSJim Jagielski         // Readonly. Load RootNode.
100*b1cdbd2cSJim Jagielski         return base::loadObjectAt (m_aRoot, rnPageSize);
101*b1cdbd2cSJim Jagielski     }
102*b1cdbd2cSJim Jagielski 
103*b1cdbd2cSJim Jagielski     // Writeable. Load or Create RootNode.
104*b1cdbd2cSJim Jagielski     eErrCode = m_aRoot.loadOrCreate (rnPageSize, *this);
105*b1cdbd2cSJim Jagielski     if (eErrCode == store_E_Pending)
106*b1cdbd2cSJim Jagielski     {
107*b1cdbd2cSJim Jagielski         // Creation notification.
108*b1cdbd2cSJim Jagielski         PageHolderObject< page > xRoot (m_aRoot.get());
109*b1cdbd2cSJim Jagielski 
110*b1cdbd2cSJim Jagielski 		// Pre-allocate left most entry (ugly, but we can't insert to left).
111*b1cdbd2cSJim Jagielski         OStorePageKey aKey (rtl_crc32 (0, "/", 1), 0);
112*b1cdbd2cSJim Jagielski         xRoot->insert (0, entry(aKey));
113*b1cdbd2cSJim Jagielski 
114*b1cdbd2cSJim Jagielski 		// Save RootNode.
115*b1cdbd2cSJim Jagielski 		eErrCode = base::saveObjectAt (m_aRoot, rnPageSize);
116*b1cdbd2cSJim Jagielski     }
117*b1cdbd2cSJim Jagielski 
118*b1cdbd2cSJim Jagielski 	// Done.
119*b1cdbd2cSJim Jagielski 	return eErrCode;
120*b1cdbd2cSJim Jagielski }
121*b1cdbd2cSJim Jagielski 
122*b1cdbd2cSJim Jagielski /*
123*b1cdbd2cSJim Jagielski  * find_lookup (w/o split()).
124*b1cdbd2cSJim Jagielski  * Internal: Precond: initialized, readable, exclusive access.
125*b1cdbd2cSJim Jagielski  */
find_lookup(OStoreBTreeNodeObject & rNode,sal_uInt16 & rIndex,OStorePageKey const & rKey)126*b1cdbd2cSJim Jagielski storeError OStorePageManager::find_lookup (
127*b1cdbd2cSJim Jagielski     OStoreBTreeNodeObject & rNode,
128*b1cdbd2cSJim Jagielski     sal_uInt16 &            rIndex,
129*b1cdbd2cSJim Jagielski     OStorePageKey const &   rKey)
130*b1cdbd2cSJim Jagielski {
131*b1cdbd2cSJim Jagielski     // Find Node and Index.
132*b1cdbd2cSJim Jagielski     storeError eErrCode = m_aRoot.find_lookup (rNode, rIndex, rKey, *this);
133*b1cdbd2cSJim Jagielski 	if (eErrCode != store_E_None)
134*b1cdbd2cSJim Jagielski 		return eErrCode;
135*b1cdbd2cSJim Jagielski 
136*b1cdbd2cSJim Jagielski     // Greater or Equal.
137*b1cdbd2cSJim Jagielski     PageHolderObject< page > xPage (rNode.get());
138*b1cdbd2cSJim Jagielski     OSL_POSTCOND(rIndex < xPage->usageCount(), "store::PageManager::find_lookup(): logic error");
139*b1cdbd2cSJim Jagielski     entry e (xPage->m_pData[rIndex]);
140*b1cdbd2cSJim Jagielski 
141*b1cdbd2cSJim Jagielski     // Check for exact match.
142*b1cdbd2cSJim Jagielski     if (e.compare(entry(rKey)) != entry::COMPARE_EQUAL)
143*b1cdbd2cSJim Jagielski     {
144*b1cdbd2cSJim Jagielski         // Page not present.
145*b1cdbd2cSJim Jagielski         return store_E_NotExists;
146*b1cdbd2cSJim Jagielski     }
147*b1cdbd2cSJim Jagielski 
148*b1cdbd2cSJim Jagielski     // Check address.
149*b1cdbd2cSJim Jagielski     if (e.m_aLink.location() == STORE_PAGE_NULL)
150*b1cdbd2cSJim Jagielski     {
151*b1cdbd2cSJim Jagielski         // Page not present.
152*b1cdbd2cSJim Jagielski         return store_E_NotExists;
153*b1cdbd2cSJim Jagielski     }
154*b1cdbd2cSJim Jagielski 
155*b1cdbd2cSJim Jagielski     return store_E_None;
156*b1cdbd2cSJim Jagielski }
157*b1cdbd2cSJim Jagielski 
158*b1cdbd2cSJim Jagielski /*
159*b1cdbd2cSJim Jagielski  * remove_Impl (possibly down from root).
160*b1cdbd2cSJim Jagielski  * Internal: Precond: initialized, writeable, exclusive access.
161*b1cdbd2cSJim Jagielski  */
162*b1cdbd2cSJim Jagielski #if 0  /* EXP */
163*b1cdbd2cSJim Jagielski storeError OStorePageManager::remove_Impl (entry & rEntry)
164*b1cdbd2cSJim Jagielski {
165*b1cdbd2cSJim Jagielski     // Find Node and Index.
166*b1cdbd2cSJim Jagielski     OStoreBTreeNodeObject aNode;
167*b1cdbd2cSJim Jagielski     sal_uInt16 nIndex = 0;
168*b1cdbd2cSJim Jagielski     eErrCode = m_aRoot.find_lookup (aNode, nIndex, entry::CompareGreater(rEntry), *this);
169*b1cdbd2cSJim Jagielski 
170*b1cdbd2cSJim Jagielski     // @@@
171*b1cdbd2cSJim Jagielski 
172*b1cdbd2cSJim Jagielski     PageHolderObject< page > xPage (aNode.get());
173*b1cdbd2cSJim Jagielski     page & rPage = (*xPage);
174*b1cdbd2cSJim Jagielski 
175*b1cdbd2cSJim Jagielski     // Check current page index.
176*b1cdbd2cSJim Jagielski     sal_uInt16 i = rPage.find (rEntry), n = rPage.usageCount();
177*b1cdbd2cSJim Jagielski     if (!(i < n))
178*b1cdbd2cSJim Jagielski     {
179*b1cdbd2cSJim Jagielski         // Path to entry not exists (Must not happen(?)).
180*b1cdbd2cSJim Jagielski         return store_E_NotExists;
181*b1cdbd2cSJim Jagielski     }
182*b1cdbd2cSJim Jagielski 
183*b1cdbd2cSJim Jagielski     // Compare entry.
184*b1cdbd2cSJim Jagielski 	entry::CompareResult result = rEntry.compare (rPage.m_pData[i]);
185*b1cdbd2cSJim Jagielski 
186*b1cdbd2cSJim Jagielski     for (; result == entry::COMPARE_GREATER && xPage->depth() > 0; )
187*b1cdbd2cSJim Jagielski     {
188*b1cdbd2cSJim Jagielski         // Check next node address.
189*b1cdbd2cSJim Jagielski         sal_uInt32 const nAddr = rPage.m_pData[i].m_aLink.location();
190*b1cdbd2cSJim Jagielski         if (nAddr == STORE_PAGE_NULL)
191*b1cdbd2cSJim Jagielski         {
192*b1cdbd2cSJim Jagielski             // Path to entry not exists (Must not happen(?)).
193*b1cdbd2cSJim Jagielski             return store_E_NotExists;
194*b1cdbd2cSJim Jagielski         }
195*b1cdbd2cSJim Jagielski 
196*b1cdbd2cSJim Jagielski         // Load next node page.
197*b1cdbd2cSJim Jagielski         eErrCode = loadObjectAt (aNode, nAddr);
198*b1cdbd2cSJim Jagielski 
199*b1cdbd2cSJim Jagielski         PageHolderObject< page > xNext (aNode.get());
200*b1cdbd2cSJim Jagielski         xNext.swap (xPage);
201*b1cdbd2cSJim Jagielski     }
202*b1cdbd2cSJim Jagielski 
203*b1cdbd2cSJim Jagielski     aNode.remove (nIndex, rEntry, *this);
204*b1cdbd2cSJim Jagielski 
205*b1cdbd2cSJim Jagielski 
206*b1cdbd2cSJim Jagielski     do
207*b1cdbd2cSJim Jagielski     {
208*b1cdbd2cSJim Jagielski         // Load next node page.
209*b1cdbd2cSJim Jagielski         eErrCode = loadObjectAt (aNode, nAddr);
210*b1cdbd2cSJim Jagielski 
211*b1cdbd2cSJim Jagielski         page const & rPage = (*xPage);
212*b1cdbd2cSJim Jagielski 
213*b1cdbd2cSJim Jagielski         // Check current page index.
214*b1cdbd2cSJim Jagielski         sal_uInt16 i = rPage.find (rEntry), n = rPage.usageCount();
215*b1cdbd2cSJim Jagielski         if (!(i < n))
216*b1cdbd2cSJim Jagielski         {
217*b1cdbd2cSJim Jagielski             // Path to entry not exists (Must not happen(?)).
218*b1cdbd2cSJim Jagielski             return store_E_NotExists;
219*b1cdbd2cSJim Jagielski         }
220*b1cdbd2cSJim Jagielski 
221*b1cdbd2cSJim Jagielski         // Compare entry.
222*b1cdbd2cSJim Jagielski         result = rEntry.compare (rPage.m_pData[i]);
223*b1cdbd2cSJim Jagielski 
224*b1cdbd2cSJim Jagielski     } while (result == entry::COMPATE_GREATER);
225*b1cdbd2cSJim Jagielski }
226*b1cdbd2cSJim Jagielski #endif /* EXP */
227*b1cdbd2cSJim Jagielski 
remove_Impl(entry & rEntry)228*b1cdbd2cSJim Jagielski storeError OStorePageManager::remove_Impl (entry & rEntry)
229*b1cdbd2cSJim Jagielski {
230*b1cdbd2cSJim Jagielski     OStoreBTreeNodeObject aNode (m_aRoot.get());
231*b1cdbd2cSJim Jagielski 
232*b1cdbd2cSJim Jagielski 	// Check current page index.
233*b1cdbd2cSJim Jagielski     PageHolderObject< page > xPage (aNode.get());
234*b1cdbd2cSJim Jagielski 	sal_uInt16 i = xPage->find (rEntry), n = xPage->usageCount();
235*b1cdbd2cSJim Jagielski 	if (!(i < n))
236*b1cdbd2cSJim Jagielski 	{
237*b1cdbd2cSJim Jagielski 		// Path to entry not exists (Must not happen(?)).
238*b1cdbd2cSJim Jagielski 		return store_E_NotExists;
239*b1cdbd2cSJim Jagielski 	}
240*b1cdbd2cSJim Jagielski 
241*b1cdbd2cSJim Jagielski 	// Compare entry.
242*b1cdbd2cSJim Jagielski 	entry::CompareResult result = rEntry.compare (xPage->m_pData[i]);
243*b1cdbd2cSJim Jagielski 
244*b1cdbd2cSJim Jagielski 	// Iterate down until equal match.
245*b1cdbd2cSJim Jagielski 	while ((result == entry::COMPARE_GREATER) && (xPage->depth() > 0))
246*b1cdbd2cSJim Jagielski 	{
247*b1cdbd2cSJim Jagielski 		// Check link address.
248*b1cdbd2cSJim Jagielski 		sal_uInt32 const nAddr = xPage->m_pData[i].m_aLink.location();
249*b1cdbd2cSJim Jagielski 		if (nAddr == STORE_PAGE_NULL)
250*b1cdbd2cSJim Jagielski 		{
251*b1cdbd2cSJim Jagielski 			// Path to entry not exists (Must not happen(?)).
252*b1cdbd2cSJim Jagielski 			return store_E_NotExists;
253*b1cdbd2cSJim Jagielski 		}
254*b1cdbd2cSJim Jagielski 
255*b1cdbd2cSJim Jagielski 		// Load link page.
256*b1cdbd2cSJim Jagielski 		storeError eErrCode = loadObjectAt (aNode, nAddr);
257*b1cdbd2cSJim Jagielski 		if (eErrCode != store_E_None)
258*b1cdbd2cSJim Jagielski 			return eErrCode;
259*b1cdbd2cSJim Jagielski 
260*b1cdbd2cSJim Jagielski         PageHolderObject< page > xNext (aNode.get());
261*b1cdbd2cSJim Jagielski         xNext.swap (xPage);
262*b1cdbd2cSJim Jagielski 
263*b1cdbd2cSJim Jagielski 		// Check index.
264*b1cdbd2cSJim Jagielski 		i = xPage->find (rEntry), n = xPage->usageCount();
265*b1cdbd2cSJim Jagielski 		if (!(i < n))
266*b1cdbd2cSJim Jagielski 		{
267*b1cdbd2cSJim Jagielski 			// Path to entry not exists (Must not happen(?)).
268*b1cdbd2cSJim Jagielski 			return store_E_NotExists;
269*b1cdbd2cSJim Jagielski 		}
270*b1cdbd2cSJim Jagielski 
271*b1cdbd2cSJim Jagielski 		// Compare entry.
272*b1cdbd2cSJim Jagielski 		result = rEntry.compare (xPage->m_pData[i]);
273*b1cdbd2cSJim Jagielski 	}
274*b1cdbd2cSJim Jagielski 
275*b1cdbd2cSJim Jagielski 	OSL_POSTCOND(
276*b1cdbd2cSJim Jagielski 		result != entry::COMPARE_LESS,
277*b1cdbd2cSJim Jagielski 		"OStorePageManager::remove(): find failed");
278*b1cdbd2cSJim Jagielski 
279*b1cdbd2cSJim Jagielski 	// Check entry comparison.
280*b1cdbd2cSJim Jagielski 	if (result == entry::COMPARE_LESS)
281*b1cdbd2cSJim Jagielski 	{
282*b1cdbd2cSJim Jagielski 		// Must not happen.
283*b1cdbd2cSJim Jagielski 		return store_E_Unknown;
284*b1cdbd2cSJim Jagielski 	}
285*b1cdbd2cSJim Jagielski 
286*b1cdbd2cSJim Jagielski 	// Remove down from current page (recursive).
287*b1cdbd2cSJim Jagielski 	return aNode.remove (i, rEntry, *this);
288*b1cdbd2cSJim Jagielski }
289*b1cdbd2cSJim Jagielski 
290*b1cdbd2cSJim Jagielski /*
291*b1cdbd2cSJim Jagielski  * namei.
292*b1cdbd2cSJim Jagielski  * Precond: none (static).
293*b1cdbd2cSJim Jagielski  */
namei(const rtl_String * pPath,const rtl_String * pName,OStorePageKey & rKey)294*b1cdbd2cSJim Jagielski storeError OStorePageManager::namei (
295*b1cdbd2cSJim Jagielski 	const rtl_String *pPath, const rtl_String *pName, OStorePageKey &rKey)
296*b1cdbd2cSJim Jagielski {
297*b1cdbd2cSJim Jagielski 	// Check parameter.
298*b1cdbd2cSJim Jagielski 	if (!(pPath && pName))
299*b1cdbd2cSJim Jagielski 		return store_E_InvalidParameter;
300*b1cdbd2cSJim Jagielski 
301*b1cdbd2cSJim Jagielski 	// Check name length.
302*b1cdbd2cSJim Jagielski 	if (!(pName->length < STORE_MAXIMUM_NAMESIZE))
303*b1cdbd2cSJim Jagielski 		return store_E_NameTooLong;
304*b1cdbd2cSJim Jagielski 
305*b1cdbd2cSJim Jagielski 	// Transform pathname into key.
306*b1cdbd2cSJim Jagielski 	rKey.m_nLow  = store::htonl(rtl_crc32 (0, pName->buffer, pName->length));
307*b1cdbd2cSJim Jagielski 	rKey.m_nHigh = store::htonl(rtl_crc32 (0, pPath->buffer, pPath->length));
308*b1cdbd2cSJim Jagielski 
309*b1cdbd2cSJim Jagielski 	// Done.
310*b1cdbd2cSJim Jagielski 	return store_E_None;
311*b1cdbd2cSJim Jagielski }
312*b1cdbd2cSJim Jagielski 
313*b1cdbd2cSJim Jagielski /*
314*b1cdbd2cSJim Jagielski  * iget.
315*b1cdbd2cSJim Jagielski  * Precond: initialized.
316*b1cdbd2cSJim Jagielski  */
iget(OStoreDirectoryPageObject & rPage,sal_uInt32 nAttrib,const rtl_String * pPath,const rtl_String * pName,storeAccessMode eMode)317*b1cdbd2cSJim Jagielski storeError OStorePageManager::iget (
318*b1cdbd2cSJim Jagielski     OStoreDirectoryPageObject & rPage,
319*b1cdbd2cSJim Jagielski     sal_uInt32                  nAttrib,
320*b1cdbd2cSJim Jagielski     const rtl_String          * pPath,
321*b1cdbd2cSJim Jagielski     const rtl_String          * pName,
322*b1cdbd2cSJim Jagielski     storeAccessMode             eMode)
323*b1cdbd2cSJim Jagielski {
324*b1cdbd2cSJim Jagielski 	// Acquire exclusive access.
325*b1cdbd2cSJim Jagielski 	osl::MutexGuard aGuard(*this);
326*b1cdbd2cSJim Jagielski 
327*b1cdbd2cSJim Jagielski 	// Check precond.
328*b1cdbd2cSJim Jagielski 	if (!self::isValid())
329*b1cdbd2cSJim Jagielski 		return store_E_InvalidAccess;
330*b1cdbd2cSJim Jagielski 
331*b1cdbd2cSJim Jagielski 	// Setup inode page key.
332*b1cdbd2cSJim Jagielski 	OStorePageKey aKey;
333*b1cdbd2cSJim Jagielski 	storeError eErrCode = namei (pPath, pName, aKey);
334*b1cdbd2cSJim Jagielski 	if (eErrCode != store_E_None)
335*b1cdbd2cSJim Jagielski 		return eErrCode;
336*b1cdbd2cSJim Jagielski 
337*b1cdbd2cSJim Jagielski 	// Check for directory.
338*b1cdbd2cSJim Jagielski 	if (nAttrib & STORE_ATTRIB_ISDIR)
339*b1cdbd2cSJim Jagielski 	{
340*b1cdbd2cSJim Jagielski 		// Ugly, but necessary (backward compatibility).
341*b1cdbd2cSJim Jagielski 		aKey.m_nLow = store::htonl(rtl_crc32 (store::ntohl(aKey.m_nLow), "/", 1));
342*b1cdbd2cSJim Jagielski 	}
343*b1cdbd2cSJim Jagielski 
344*b1cdbd2cSJim Jagielski 	// Load inode page.
345*b1cdbd2cSJim Jagielski 	eErrCode = load_dirpage_Impl (aKey, rPage);
346*b1cdbd2cSJim Jagielski 	if (eErrCode != store_E_None)
347*b1cdbd2cSJim Jagielski 	{
348*b1cdbd2cSJim Jagielski 		// Check mode and reason.
349*b1cdbd2cSJim Jagielski 		if (eErrCode != store_E_NotExists)
350*b1cdbd2cSJim Jagielski 			return eErrCode;
351*b1cdbd2cSJim Jagielski 
352*b1cdbd2cSJim Jagielski 		if (eMode == store_AccessReadWrite)
353*b1cdbd2cSJim Jagielski 			return store_E_NotExists;
354*b1cdbd2cSJim Jagielski 		if (eMode == store_AccessReadOnly)
355*b1cdbd2cSJim Jagielski 			return store_E_NotExists;
356*b1cdbd2cSJim Jagielski 
357*b1cdbd2cSJim Jagielski 		if (!base::isWriteable())
358*b1cdbd2cSJim Jagielski 			return store_E_AccessViolation;
359*b1cdbd2cSJim Jagielski 
360*b1cdbd2cSJim Jagielski         // Create inode page.
361*b1cdbd2cSJim Jagielski         eErrCode = rPage.construct< inode >(base::allocator());
362*b1cdbd2cSJim Jagielski 		if (eErrCode != store_E_None)
363*b1cdbd2cSJim Jagielski 			return eErrCode;
364*b1cdbd2cSJim Jagielski 
365*b1cdbd2cSJim Jagielski 		// Setup inode nameblock.
366*b1cdbd2cSJim Jagielski         PageHolderObject< inode > xPage (rPage.get());
367*b1cdbd2cSJim Jagielski 
368*b1cdbd2cSJim Jagielski 		rPage.key (aKey);
369*b1cdbd2cSJim Jagielski 		rPage.attrib (nAttrib);
370*b1cdbd2cSJim Jagielski 
371*b1cdbd2cSJim Jagielski 		memcpy (
372*b1cdbd2cSJim Jagielski 			&(xPage->m_aNameBlock.m_pData[0]),
373*b1cdbd2cSJim Jagielski 			pName->buffer, pName->length);
374*b1cdbd2cSJim Jagielski 
375*b1cdbd2cSJim Jagielski 		// Save inode page.
376*b1cdbd2cSJim Jagielski 		eErrCode = save_dirpage_Impl (aKey, rPage);
377*b1cdbd2cSJim Jagielski 		if (eErrCode != store_E_None)
378*b1cdbd2cSJim Jagielski 			return eErrCode;
379*b1cdbd2cSJim Jagielski 	}
380*b1cdbd2cSJim Jagielski 
381*b1cdbd2cSJim Jagielski 	// Check for symbolic link.
382*b1cdbd2cSJim Jagielski 	if (rPage.attrib() & STORE_ATTRIB_ISLINK)
383*b1cdbd2cSJim Jagielski 	{
384*b1cdbd2cSJim Jagielski 		// Obtain 'Destination' page key.
385*b1cdbd2cSJim Jagielski         PageHolderObject< inode > xPage (rPage.get());
386*b1cdbd2cSJim Jagielski 		OStorePageKey aDstKey;
387*b1cdbd2cSJim Jagielski 		memcpy (&aDstKey, &(xPage->m_pData[0]), sizeof(aDstKey));
388*b1cdbd2cSJim Jagielski 
389*b1cdbd2cSJim Jagielski 		// Load 'Destination' inode.
390*b1cdbd2cSJim Jagielski 		eErrCode = load_dirpage_Impl (aDstKey, rPage);
391*b1cdbd2cSJim Jagielski 		if (eErrCode != store_E_None)
392*b1cdbd2cSJim Jagielski 			return eErrCode;
393*b1cdbd2cSJim Jagielski 	}
394*b1cdbd2cSJim Jagielski 
395*b1cdbd2cSJim Jagielski 	// Done.
396*b1cdbd2cSJim Jagielski 	return store_E_None;
397*b1cdbd2cSJim Jagielski }
398*b1cdbd2cSJim Jagielski 
399*b1cdbd2cSJim Jagielski /*
400*b1cdbd2cSJim Jagielski  * iterate.
401*b1cdbd2cSJim Jagielski  * Precond: initialized.
402*b1cdbd2cSJim Jagielski  * ToDo: skip hardlink entries.
403*b1cdbd2cSJim Jagielski  */
iterate(OStorePageKey & rKey,OStorePageLink & rLink,sal_uInt32 & rAttrib)404*b1cdbd2cSJim Jagielski storeError OStorePageManager::iterate (
405*b1cdbd2cSJim Jagielski 	OStorePageKey &  rKey,
406*b1cdbd2cSJim Jagielski 	OStorePageLink & rLink,
407*b1cdbd2cSJim Jagielski 	sal_uInt32 &     rAttrib)
408*b1cdbd2cSJim Jagielski {
409*b1cdbd2cSJim Jagielski 	// Acquire exclusive access.
410*b1cdbd2cSJim Jagielski 	osl::MutexGuard aGuard(*this);
411*b1cdbd2cSJim Jagielski 
412*b1cdbd2cSJim Jagielski 	// Check precond.
413*b1cdbd2cSJim Jagielski 	if (!self::isValid())
414*b1cdbd2cSJim Jagielski 		return store_E_InvalidAccess;
415*b1cdbd2cSJim Jagielski 
416*b1cdbd2cSJim Jagielski 	// Find NodePage and Index.
417*b1cdbd2cSJim Jagielski     OStoreBTreeNodeObject aNode;
418*b1cdbd2cSJim Jagielski     sal_uInt16 i = 0;
419*b1cdbd2cSJim Jagielski     storeError eErrCode = m_aRoot.find_lookup (aNode, i, rKey, *this);
420*b1cdbd2cSJim Jagielski 	if (eErrCode != store_E_None)
421*b1cdbd2cSJim Jagielski 		return eErrCode;
422*b1cdbd2cSJim Jagielski 
423*b1cdbd2cSJim Jagielski 	// GreaterEqual. Found next entry.
424*b1cdbd2cSJim Jagielski     PageHolderObject< page > xNode (aNode.get());
425*b1cdbd2cSJim Jagielski 	entry e (xNode->m_pData[i]);
426*b1cdbd2cSJim Jagielski 
427*b1cdbd2cSJim Jagielski 	// Setup result.
428*b1cdbd2cSJim Jagielski 	rKey    = e.m_aKey;
429*b1cdbd2cSJim Jagielski     rLink   = e.m_aLink;
430*b1cdbd2cSJim Jagielski 	rAttrib = store::ntohl(e.m_nAttrib);
431*b1cdbd2cSJim Jagielski 
432*b1cdbd2cSJim Jagielski 	// Done.
433*b1cdbd2cSJim Jagielski 	return store_E_None;
434*b1cdbd2cSJim Jagielski }
435*b1cdbd2cSJim Jagielski 
436*b1cdbd2cSJim Jagielski /*
437*b1cdbd2cSJim Jagielski  * load => private: iget() @@@
438*b1cdbd2cSJim Jagielski  * Internal: Precond: initialized, exclusive access.
439*b1cdbd2cSJim Jagielski  */
load_dirpage_Impl(const OStorePageKey & rKey,OStoreDirectoryPageObject & rPage)440*b1cdbd2cSJim Jagielski storeError OStorePageManager::load_dirpage_Impl (
441*b1cdbd2cSJim Jagielski 	const OStorePageKey       &rKey,
442*b1cdbd2cSJim Jagielski 	OStoreDirectoryPageObject &rPage)
443*b1cdbd2cSJim Jagielski {
444*b1cdbd2cSJim Jagielski 	// Find Node and Index.
445*b1cdbd2cSJim Jagielski     OStoreBTreeNodeObject aNode;
446*b1cdbd2cSJim Jagielski     sal_uInt16 i = 0;
447*b1cdbd2cSJim Jagielski     storeError eErrCode = find_lookup (aNode, i, rKey);
448*b1cdbd2cSJim Jagielski 	if (eErrCode != store_E_None)
449*b1cdbd2cSJim Jagielski 		return eErrCode;
450*b1cdbd2cSJim Jagielski 
451*b1cdbd2cSJim Jagielski 	// Existing entry. Load page.
452*b1cdbd2cSJim Jagielski     PageHolderObject< page > xNode (aNode.get());
453*b1cdbd2cSJim Jagielski     entry e (xNode->m_pData[i]);
454*b1cdbd2cSJim Jagielski 	return loadObjectAt (rPage, e.m_aLink.location());
455*b1cdbd2cSJim Jagielski }
456*b1cdbd2cSJim Jagielski 
457*b1cdbd2cSJim Jagielski /*
458*b1cdbd2cSJim Jagielski  * save => private: iget(), rebuild() @@@
459*b1cdbd2cSJim Jagielski  * Internal: Precond: initialized, writeable, exclusive access.
460*b1cdbd2cSJim Jagielski  */
save_dirpage_Impl(const OStorePageKey & rKey,OStoreDirectoryPageObject & rPage)461*b1cdbd2cSJim Jagielski storeError OStorePageManager::save_dirpage_Impl (
462*b1cdbd2cSJim Jagielski 	const OStorePageKey       &rKey,
463*b1cdbd2cSJim Jagielski 	OStoreDirectoryPageObject &rPage)
464*b1cdbd2cSJim Jagielski {
465*b1cdbd2cSJim Jagielski     // Find NodePage and Index.
466*b1cdbd2cSJim Jagielski     node aNode;
467*b1cdbd2cSJim Jagielski     sal_uInt16 i = 0;
468*b1cdbd2cSJim Jagielski 
469*b1cdbd2cSJim Jagielski     storeError eErrCode = m_aRoot.find_insert (aNode, i, rKey, *this);
470*b1cdbd2cSJim Jagielski     PageHolderObject< page > xNode (aNode.get());
471*b1cdbd2cSJim Jagielski     if (eErrCode != store_E_None)
472*b1cdbd2cSJim Jagielski     {
473*b1cdbd2cSJim Jagielski         if (eErrCode != store_E_AlreadyExists)
474*b1cdbd2cSJim Jagielski             return eErrCode;
475*b1cdbd2cSJim Jagielski 
476*b1cdbd2cSJim Jagielski         // Existing entry.
477*b1cdbd2cSJim Jagielski         entry e (xNode->m_pData[i]);
478*b1cdbd2cSJim Jagielski         if (e.m_aLink.location() != STORE_PAGE_NULL)
479*b1cdbd2cSJim Jagielski         {
480*b1cdbd2cSJim Jagielski             // Save page to existing location.
481*b1cdbd2cSJim Jagielski             return saveObjectAt (rPage, e.m_aLink.location());
482*b1cdbd2cSJim Jagielski         }
483*b1cdbd2cSJim Jagielski 
484*b1cdbd2cSJim Jagielski         // Allocate page.
485*b1cdbd2cSJim Jagielski         eErrCode = base::allocate (rPage);
486*b1cdbd2cSJim Jagielski         if (eErrCode != store_E_None)
487*b1cdbd2cSJim Jagielski             return eErrCode;
488*b1cdbd2cSJim Jagielski 
489*b1cdbd2cSJim Jagielski         // Update page location.
490*b1cdbd2cSJim Jagielski         xNode->m_pData[i].m_aLink = rPage.location();
491*b1cdbd2cSJim Jagielski 
492*b1cdbd2cSJim Jagielski         // Save modified NodePage.
493*b1cdbd2cSJim Jagielski         return saveObjectAt (aNode, aNode.location());
494*b1cdbd2cSJim Jagielski     }
495*b1cdbd2cSJim Jagielski 
496*b1cdbd2cSJim Jagielski     // Allocate page.
497*b1cdbd2cSJim Jagielski     eErrCode = base::allocate (rPage);
498*b1cdbd2cSJim Jagielski     if (eErrCode != store_E_None)
499*b1cdbd2cSJim Jagielski         return eErrCode;
500*b1cdbd2cSJim Jagielski 
501*b1cdbd2cSJim Jagielski 	// Insert.
502*b1cdbd2cSJim Jagielski     OStorePageLink aLink (rPage.location());
503*b1cdbd2cSJim Jagielski     xNode->insert (i + 1, entry (rKey, aLink));
504*b1cdbd2cSJim Jagielski 
505*b1cdbd2cSJim Jagielski 	// Save modified NodePage.
506*b1cdbd2cSJim Jagielski 	return saveObjectAt (aNode, aNode.location());
507*b1cdbd2cSJim Jagielski }
508*b1cdbd2cSJim Jagielski 
509*b1cdbd2cSJim Jagielski /*
510*b1cdbd2cSJim Jagielski  * attrib [nAttrib = ((nAttrib & ~nMask1) | nMask2)].
511*b1cdbd2cSJim Jagielski  * Precond: initialized.
512*b1cdbd2cSJim Jagielski  */
attrib(const OStorePageKey & rKey,sal_uInt32 nMask1,sal_uInt32 nMask2,sal_uInt32 & rAttrib)513*b1cdbd2cSJim Jagielski storeError OStorePageManager::attrib (
514*b1cdbd2cSJim Jagielski 	const OStorePageKey &rKey,
515*b1cdbd2cSJim Jagielski 	sal_uInt32           nMask1,
516*b1cdbd2cSJim Jagielski 	sal_uInt32           nMask2,
517*b1cdbd2cSJim Jagielski 	sal_uInt32          &rAttrib)
518*b1cdbd2cSJim Jagielski {
519*b1cdbd2cSJim Jagielski 	// Acquire exclusive access.
520*b1cdbd2cSJim Jagielski 	osl::MutexGuard aGuard(*this);
521*b1cdbd2cSJim Jagielski 
522*b1cdbd2cSJim Jagielski 	// Check precond.
523*b1cdbd2cSJim Jagielski 	if (!self::isValid())
524*b1cdbd2cSJim Jagielski 		return store_E_InvalidAccess;
525*b1cdbd2cSJim Jagielski 
526*b1cdbd2cSJim Jagielski 	// Find NodePage and index.
527*b1cdbd2cSJim Jagielski     OStoreBTreeNodeObject aNode;
528*b1cdbd2cSJim Jagielski     sal_uInt16 i = 0;
529*b1cdbd2cSJim Jagielski 	storeError eErrCode = find_lookup (aNode, i, rKey);
530*b1cdbd2cSJim Jagielski 	if (eErrCode != store_E_None)
531*b1cdbd2cSJim Jagielski 		return eErrCode;
532*b1cdbd2cSJim Jagielski 
533*b1cdbd2cSJim Jagielski 	// Existing entry.
534*b1cdbd2cSJim Jagielski     PageHolderObject< page > xNode (aNode.get());
535*b1cdbd2cSJim Jagielski 	entry e (xNode->m_pData[i]);
536*b1cdbd2cSJim Jagielski 	if (nMask1 != nMask2)
537*b1cdbd2cSJim Jagielski 	{
538*b1cdbd2cSJim Jagielski 		// Evaluate new attributes.
539*b1cdbd2cSJim Jagielski 		sal_uInt32 nAttrib = store::ntohl(e.m_nAttrib);
540*b1cdbd2cSJim Jagielski 
541*b1cdbd2cSJim Jagielski 		nAttrib &= ~nMask1;
542*b1cdbd2cSJim Jagielski 		nAttrib |=  nMask2;
543*b1cdbd2cSJim Jagielski 
544*b1cdbd2cSJim Jagielski 		if (store::htonl(nAttrib) != e.m_nAttrib)
545*b1cdbd2cSJim Jagielski 		{
546*b1cdbd2cSJim Jagielski 			// Check access mode.
547*b1cdbd2cSJim Jagielski 			if (base::isWriteable())
548*b1cdbd2cSJim Jagielski 			{
549*b1cdbd2cSJim Jagielski 				// Set new attributes.
550*b1cdbd2cSJim Jagielski 				e.m_nAttrib = store::htonl(nAttrib);
551*b1cdbd2cSJim Jagielski 				xNode->m_pData[i] = e;
552*b1cdbd2cSJim Jagielski 
553*b1cdbd2cSJim Jagielski 				// Save modified NodePage.
554*b1cdbd2cSJim Jagielski 				eErrCode = saveObjectAt (aNode, aNode.location());
555*b1cdbd2cSJim Jagielski 			}
556*b1cdbd2cSJim Jagielski 			else
557*b1cdbd2cSJim Jagielski 			{
558*b1cdbd2cSJim Jagielski 				// Access denied.
559*b1cdbd2cSJim Jagielski 				eErrCode = store_E_AccessViolation;
560*b1cdbd2cSJim Jagielski 			}
561*b1cdbd2cSJim Jagielski 		}
562*b1cdbd2cSJim Jagielski 	}
563*b1cdbd2cSJim Jagielski 
564*b1cdbd2cSJim Jagielski 	// Obtain current attributes.
565*b1cdbd2cSJim Jagielski 	rAttrib = store::ntohl(e.m_nAttrib);
566*b1cdbd2cSJim Jagielski 	return eErrCode;
567*b1cdbd2cSJim Jagielski }
568*b1cdbd2cSJim Jagielski 
569*b1cdbd2cSJim Jagielski /*
570*b1cdbd2cSJim Jagielski  * link (insert 'Source' as hardlink to 'Destination').
571*b1cdbd2cSJim Jagielski  * Precond: initialized, writeable.
572*b1cdbd2cSJim Jagielski  */
link(const OStorePageKey & rSrcKey,const OStorePageKey & rDstKey)573*b1cdbd2cSJim Jagielski storeError OStorePageManager::link (
574*b1cdbd2cSJim Jagielski 	const OStorePageKey &rSrcKey,
575*b1cdbd2cSJim Jagielski 	const OStorePageKey &rDstKey)
576*b1cdbd2cSJim Jagielski {
577*b1cdbd2cSJim Jagielski 	// Acquire exclusive access.
578*b1cdbd2cSJim Jagielski 	osl::MutexGuard aGuard(*this);
579*b1cdbd2cSJim Jagielski 
580*b1cdbd2cSJim Jagielski 	// Check precond.
581*b1cdbd2cSJim Jagielski 	if (!self::isValid())
582*b1cdbd2cSJim Jagielski 		return store_E_InvalidAccess;
583*b1cdbd2cSJim Jagielski 
584*b1cdbd2cSJim Jagielski 	if (!base::isWriteable())
585*b1cdbd2cSJim Jagielski 		return store_E_AccessViolation;
586*b1cdbd2cSJim Jagielski 
587*b1cdbd2cSJim Jagielski 	// Find 'Destination' NodePage and Index.
588*b1cdbd2cSJim Jagielski     OStoreBTreeNodeObject aDstNode;
589*b1cdbd2cSJim Jagielski     sal_uInt16 i = 0;
590*b1cdbd2cSJim Jagielski 	storeError eErrCode = find_lookup (aDstNode, i, rDstKey);
591*b1cdbd2cSJim Jagielski 	if (eErrCode != store_E_None)
592*b1cdbd2cSJim Jagielski 		return eErrCode;
593*b1cdbd2cSJim Jagielski 
594*b1cdbd2cSJim Jagielski     // Existing 'Destination' entry.
595*b1cdbd2cSJim Jagielski     PageHolderObject< page > xDstNode (aDstNode.get());
596*b1cdbd2cSJim Jagielski     entry e (xDstNode->m_pData[i]);
597*b1cdbd2cSJim Jagielski     OStorePageLink aDstLink (e.m_aLink);
598*b1cdbd2cSJim Jagielski 
599*b1cdbd2cSJim Jagielski 	// Find 'Source' NodePage and Index.
600*b1cdbd2cSJim Jagielski     OStoreBTreeNodeObject aSrcNode;
601*b1cdbd2cSJim Jagielski     eErrCode = m_aRoot.find_insert (aSrcNode, i, rSrcKey, *this);
602*b1cdbd2cSJim Jagielski 	if (eErrCode != store_E_None)
603*b1cdbd2cSJim Jagielski 		return eErrCode;
604*b1cdbd2cSJim Jagielski 
605*b1cdbd2cSJim Jagielski 	// Insert 'Source' entry.
606*b1cdbd2cSJim Jagielski     PageHolderObject< page > xSrcNode (aSrcNode.get());
607*b1cdbd2cSJim Jagielski 	xSrcNode->insert (i + 1, entry (rSrcKey, aDstLink, STORE_ATTRIB_ISLINK));
608*b1cdbd2cSJim Jagielski 	return saveObjectAt (aSrcNode, aSrcNode.location());
609*b1cdbd2cSJim Jagielski }
610*b1cdbd2cSJim Jagielski 
611*b1cdbd2cSJim Jagielski /*
612*b1cdbd2cSJim Jagielski  * symlink (insert 'Source' DirectoryPage as symlink to 'Destination').
613*b1cdbd2cSJim Jagielski  * Precond: initialized, writeable.
614*b1cdbd2cSJim Jagielski  */
symlink(const rtl_String * pSrcPath,const rtl_String * pSrcName,const OStorePageKey & rDstKey)615*b1cdbd2cSJim Jagielski storeError OStorePageManager::symlink (
616*b1cdbd2cSJim Jagielski 	const rtl_String    *pSrcPath,
617*b1cdbd2cSJim Jagielski 	const rtl_String    *pSrcName,
618*b1cdbd2cSJim Jagielski 	const OStorePageKey &rDstKey)
619*b1cdbd2cSJim Jagielski {
620*b1cdbd2cSJim Jagielski 	// Acquire exclusive access.
621*b1cdbd2cSJim Jagielski 	osl::MutexGuard aGuard(*this);
622*b1cdbd2cSJim Jagielski 
623*b1cdbd2cSJim Jagielski 	// Check precond.
624*b1cdbd2cSJim Jagielski 	if (!self::isValid())
625*b1cdbd2cSJim Jagielski 		return store_E_InvalidAccess;
626*b1cdbd2cSJim Jagielski 
627*b1cdbd2cSJim Jagielski 	if (!base::isWriteable())
628*b1cdbd2cSJim Jagielski 		return store_E_AccessViolation;
629*b1cdbd2cSJim Jagielski 
630*b1cdbd2cSJim Jagielski 	// Check 'Source' parameter.
631*b1cdbd2cSJim Jagielski 	storeError eErrCode = store_E_InvalidParameter;
632*b1cdbd2cSJim Jagielski 	if (!(pSrcPath && pSrcName))
633*b1cdbd2cSJim Jagielski 		return eErrCode;
634*b1cdbd2cSJim Jagielski 
635*b1cdbd2cSJim Jagielski 	// Setup 'Source' page key.
636*b1cdbd2cSJim Jagielski 	OStorePageKey aSrcKey;
637*b1cdbd2cSJim Jagielski 	eErrCode = namei (pSrcPath, pSrcName, aSrcKey);
638*b1cdbd2cSJim Jagielski 	if (eErrCode != store_E_None)
639*b1cdbd2cSJim Jagielski 		return eErrCode;
640*b1cdbd2cSJim Jagielski 
641*b1cdbd2cSJim Jagielski 	// Find 'Source' NodePage and Index.
642*b1cdbd2cSJim Jagielski     OStoreBTreeNodeObject aSrcNode;
643*b1cdbd2cSJim Jagielski     sal_uInt16 i = 0;
644*b1cdbd2cSJim Jagielski     eErrCode = m_aRoot.find_insert (aSrcNode, i, aSrcKey, *this);
645*b1cdbd2cSJim Jagielski 	if (eErrCode != store_E_None)
646*b1cdbd2cSJim Jagielski 		return eErrCode;
647*b1cdbd2cSJim Jagielski 
648*b1cdbd2cSJim Jagielski 	// Initialize directory page.
649*b1cdbd2cSJim Jagielski 	OStoreDirectoryPageObject aPage;
650*b1cdbd2cSJim Jagielski     eErrCode = aPage.construct< inode >(base::allocator());
651*b1cdbd2cSJim Jagielski 	if (eErrCode != store_E_None)
652*b1cdbd2cSJim Jagielski 		return eErrCode;
653*b1cdbd2cSJim Jagielski 
654*b1cdbd2cSJim Jagielski 	// Setup as 'Source' directory page.
655*b1cdbd2cSJim Jagielski     inode_holder_type xNode (aPage.get());
656*b1cdbd2cSJim Jagielski 	aPage.key (aSrcKey);
657*b1cdbd2cSJim Jagielski 	memcpy (
658*b1cdbd2cSJim Jagielski 		&(xNode->m_aNameBlock.m_pData[0]),
659*b1cdbd2cSJim Jagielski 		pSrcName->buffer, pSrcName->length);
660*b1cdbd2cSJim Jagielski 
661*b1cdbd2cSJim Jagielski 	// Store 'Destination' page key.
662*b1cdbd2cSJim Jagielski 	OStorePageKey aDstKey (rDstKey);
663*b1cdbd2cSJim Jagielski 	memcpy (&(xNode->m_pData[0]), &aDstKey, sizeof(aDstKey));
664*b1cdbd2cSJim Jagielski 
665*b1cdbd2cSJim Jagielski 	// Mark 'Source' as symbolic link to 'Destination'.
666*b1cdbd2cSJim Jagielski 	aPage.attrib (STORE_ATTRIB_ISLINK);
667*b1cdbd2cSJim Jagielski 	aPage.dataLength (sal_uInt32(sizeof(aDstKey)));
668*b1cdbd2cSJim Jagielski 
669*b1cdbd2cSJim Jagielski 	// Allocate and save 'Source' directory page.
670*b1cdbd2cSJim Jagielski 	eErrCode = base::allocate (aPage);
671*b1cdbd2cSJim Jagielski 	if (eErrCode != store_E_None)
672*b1cdbd2cSJim Jagielski 		return eErrCode;
673*b1cdbd2cSJim Jagielski 
674*b1cdbd2cSJim Jagielski 	// Insert 'Source' entry.
675*b1cdbd2cSJim Jagielski     PageHolderObject< page > xSrcNode (aSrcNode.get());
676*b1cdbd2cSJim Jagielski 	OStorePageLink aSrcLink (aPage.location());
677*b1cdbd2cSJim Jagielski 	xSrcNode->insert (i + 1, entry(aSrcKey, aSrcLink));
678*b1cdbd2cSJim Jagielski 
679*b1cdbd2cSJim Jagielski 	// Save modified NodePage.
680*b1cdbd2cSJim Jagielski 	return saveObjectAt (aSrcNode, aSrcNode.location());
681*b1cdbd2cSJim Jagielski }
682*b1cdbd2cSJim Jagielski 
683*b1cdbd2cSJim Jagielski /*
684*b1cdbd2cSJim Jagielski  * rename.
685*b1cdbd2cSJim Jagielski  * Precond: initialized, writeable.
686*b1cdbd2cSJim Jagielski  */
rename(const OStorePageKey & rSrcKey,const rtl_String * pDstPath,const rtl_String * pDstName)687*b1cdbd2cSJim Jagielski storeError OStorePageManager::rename (
688*b1cdbd2cSJim Jagielski 	const OStorePageKey &rSrcKey,
689*b1cdbd2cSJim Jagielski 	const rtl_String    *pDstPath,
690*b1cdbd2cSJim Jagielski 	const rtl_String    *pDstName)
691*b1cdbd2cSJim Jagielski {
692*b1cdbd2cSJim Jagielski 	// Acquire exclusive access.
693*b1cdbd2cSJim Jagielski 	osl::MutexGuard aGuard(*this);
694*b1cdbd2cSJim Jagielski 
695*b1cdbd2cSJim Jagielski 	// Check precond.
696*b1cdbd2cSJim Jagielski 	if (!self::isValid())
697*b1cdbd2cSJim Jagielski 		return store_E_InvalidAccess;
698*b1cdbd2cSJim Jagielski 
699*b1cdbd2cSJim Jagielski 	if (!base::isWriteable())
700*b1cdbd2cSJim Jagielski 		return store_E_AccessViolation;
701*b1cdbd2cSJim Jagielski 
702*b1cdbd2cSJim Jagielski 	// Check 'Destination' parameter.
703*b1cdbd2cSJim Jagielski 	storeError eErrCode = store_E_InvalidParameter;
704*b1cdbd2cSJim Jagielski 	if (!(pDstPath && pDstName))
705*b1cdbd2cSJim Jagielski 		return eErrCode;
706*b1cdbd2cSJim Jagielski 
707*b1cdbd2cSJim Jagielski 	// Setup 'Destination' page key.
708*b1cdbd2cSJim Jagielski 	OStorePageKey aDstKey;
709*b1cdbd2cSJim Jagielski 	eErrCode = namei (pDstPath, pDstName, aDstKey);
710*b1cdbd2cSJim Jagielski 	if (eErrCode != store_E_None)
711*b1cdbd2cSJim Jagielski 		return eErrCode;
712*b1cdbd2cSJim Jagielski 
713*b1cdbd2cSJim Jagielski 	// Find 'Source' NodePage and Index.
714*b1cdbd2cSJim Jagielski     OStoreBTreeNodeObject aSrcNode;
715*b1cdbd2cSJim Jagielski     sal_uInt16 i = 0;
716*b1cdbd2cSJim Jagielski 	eErrCode = find_lookup (aSrcNode, i, rSrcKey);
717*b1cdbd2cSJim Jagielski 	if (eErrCode != store_E_None)
718*b1cdbd2cSJim Jagielski 		return eErrCode;
719*b1cdbd2cSJim Jagielski 
720*b1cdbd2cSJim Jagielski 	// Existing 'Source' entry.
721*b1cdbd2cSJim Jagielski     PageHolderObject< page > xSrcNode (aSrcNode.get());
722*b1cdbd2cSJim Jagielski 	entry e (xSrcNode->m_pData[i]);
723*b1cdbd2cSJim Jagielski 
724*b1cdbd2cSJim Jagielski 	// Check for (not a) hardlink.
725*b1cdbd2cSJim Jagielski     OStoreDirectoryPageObject aPage;
726*b1cdbd2cSJim Jagielski 	if (!(store::ntohl(e.m_nAttrib) & STORE_ATTRIB_ISLINK))
727*b1cdbd2cSJim Jagielski 	{
728*b1cdbd2cSJim Jagielski 		// Load directory page.
729*b1cdbd2cSJim Jagielski 		eErrCode = base::loadObjectAt (aPage, e.m_aLink.location());
730*b1cdbd2cSJim Jagielski 		if (eErrCode != store_E_None)
731*b1cdbd2cSJim Jagielski 			return eErrCode;
732*b1cdbd2cSJim Jagielski 
733*b1cdbd2cSJim Jagielski 		// Check for directory.
734*b1cdbd2cSJim Jagielski 		if (aPage.attrib() & STORE_ATTRIB_ISDIR)
735*b1cdbd2cSJim Jagielski 		{
736*b1cdbd2cSJim Jagielski 			// Ugly, but necessary (backward compatibility).
737*b1cdbd2cSJim Jagielski 			aDstKey.m_nLow = store::htonl(rtl_crc32 (store::ntohl(aDstKey.m_nLow), "/", 1));
738*b1cdbd2cSJim Jagielski 		}
739*b1cdbd2cSJim Jagielski 	}
740*b1cdbd2cSJim Jagielski 
741*b1cdbd2cSJim Jagielski 	// Let 'Source' entry be 'Destination' entry.
742*b1cdbd2cSJim Jagielski 	e.m_aKey = aDstKey;
743*b1cdbd2cSJim Jagielski 
744*b1cdbd2cSJim Jagielski 	// Find 'Destination' NodePage and Index.
745*b1cdbd2cSJim Jagielski 	OStoreBTreeNodeObject aDstNode;
746*b1cdbd2cSJim Jagielski     eErrCode = m_aRoot.find_insert (aDstNode, i, e.m_aKey, *this);
747*b1cdbd2cSJim Jagielski 	if (eErrCode != store_E_None)
748*b1cdbd2cSJim Jagielski 		return eErrCode;
749*b1cdbd2cSJim Jagielski 
750*b1cdbd2cSJim Jagielski 	// Insert 'Destination' entry.
751*b1cdbd2cSJim Jagielski     PageHolderObject< page > xDstNode (aDstNode.get());
752*b1cdbd2cSJim Jagielski 	xDstNode->insert (i + 1, e);
753*b1cdbd2cSJim Jagielski 
754*b1cdbd2cSJim Jagielski 	eErrCode = saveObjectAt (aDstNode, aDstNode.location());
755*b1cdbd2cSJim Jagielski 	if (eErrCode != store_E_None)
756*b1cdbd2cSJim Jagielski 		return eErrCode;
757*b1cdbd2cSJim Jagielski 
758*b1cdbd2cSJim Jagielski 	// Check for (not a) hardlink.
759*b1cdbd2cSJim Jagielski 	if (!(store::ntohl(e.m_nAttrib) & STORE_ATTRIB_ISLINK))
760*b1cdbd2cSJim Jagielski 	{
761*b1cdbd2cSJim Jagielski         // Modify 'Source' directory page.
762*b1cdbd2cSJim Jagielski         inode_holder_type xNode (aPage.get());
763*b1cdbd2cSJim Jagielski 
764*b1cdbd2cSJim Jagielski 		// Setup 'Destination' NameBlock.
765*b1cdbd2cSJim Jagielski 		sal_Int32 nDstLen = pDstName->length;
766*b1cdbd2cSJim Jagielski 		memcpy (
767*b1cdbd2cSJim Jagielski 			&(xNode->m_aNameBlock.m_pData[0]),
768*b1cdbd2cSJim Jagielski 			pDstName->buffer, pDstName->length);
769*b1cdbd2cSJim Jagielski 		memset (
770*b1cdbd2cSJim Jagielski 			&(xNode->m_aNameBlock.m_pData[nDstLen]),
771*b1cdbd2cSJim Jagielski 			0, STORE_MAXIMUM_NAMESIZE - nDstLen);
772*b1cdbd2cSJim Jagielski 		aPage.key (e.m_aKey);
773*b1cdbd2cSJim Jagielski 
774*b1cdbd2cSJim Jagielski 		// Save directory page.
775*b1cdbd2cSJim Jagielski 		eErrCode = base::saveObjectAt (aPage, e.m_aLink.location());
776*b1cdbd2cSJim Jagielski 		if (eErrCode != store_E_None)
777*b1cdbd2cSJim Jagielski 			return eErrCode;
778*b1cdbd2cSJim Jagielski 	}
779*b1cdbd2cSJim Jagielski 
780*b1cdbd2cSJim Jagielski 	// Remove 'Source' entry.
781*b1cdbd2cSJim Jagielski 	e.m_aKey = rSrcKey;
782*b1cdbd2cSJim Jagielski 	return remove_Impl (e);
783*b1cdbd2cSJim Jagielski }
784*b1cdbd2cSJim Jagielski 
785*b1cdbd2cSJim Jagielski /*
786*b1cdbd2cSJim Jagielski  * remove.
787*b1cdbd2cSJim Jagielski  * Precond: initialized, writeable.
788*b1cdbd2cSJim Jagielski  */
remove(const OStorePageKey & rKey)789*b1cdbd2cSJim Jagielski storeError OStorePageManager::remove (const OStorePageKey &rKey)
790*b1cdbd2cSJim Jagielski {
791*b1cdbd2cSJim Jagielski 	// Acquire exclusive access.
792*b1cdbd2cSJim Jagielski 	osl::MutexGuard aGuard(*this);
793*b1cdbd2cSJim Jagielski 
794*b1cdbd2cSJim Jagielski 	// Check precond.
795*b1cdbd2cSJim Jagielski 	if (!self::isValid())
796*b1cdbd2cSJim Jagielski 		return store_E_InvalidAccess;
797*b1cdbd2cSJim Jagielski 
798*b1cdbd2cSJim Jagielski 	if (!base::isWriteable())
799*b1cdbd2cSJim Jagielski 		return store_E_AccessViolation;
800*b1cdbd2cSJim Jagielski 
801*b1cdbd2cSJim Jagielski 	// Find NodePage and index.
802*b1cdbd2cSJim Jagielski     OStoreBTreeNodeObject aNodePage;
803*b1cdbd2cSJim Jagielski     sal_uInt16 i = 0;
804*b1cdbd2cSJim Jagielski 	storeError eErrCode = find_lookup (aNodePage, i, rKey);
805*b1cdbd2cSJim Jagielski 	if (eErrCode != store_E_None)
806*b1cdbd2cSJim Jagielski 		return eErrCode;
807*b1cdbd2cSJim Jagielski 
808*b1cdbd2cSJim Jagielski 	// Existing entry.
809*b1cdbd2cSJim Jagielski     PageHolderObject< page > xNodePage (aNodePage.get());
810*b1cdbd2cSJim Jagielski 	entry e (xNodePage->m_pData[i]);
811*b1cdbd2cSJim Jagielski 
812*b1cdbd2cSJim Jagielski 	// Check for (not a) hardlink.
813*b1cdbd2cSJim Jagielski 	if (!(store::ntohl(e.m_nAttrib) & STORE_ATTRIB_ISLINK))
814*b1cdbd2cSJim Jagielski 	{
815*b1cdbd2cSJim Jagielski 		// Load directory page.
816*b1cdbd2cSJim Jagielski 		OStoreDirectoryPageObject aPage;
817*b1cdbd2cSJim Jagielski 		eErrCode = base::loadObjectAt (aPage, e.m_aLink.location());
818*b1cdbd2cSJim Jagielski 		if (eErrCode != store_E_None)
819*b1cdbd2cSJim Jagielski 			return eErrCode;
820*b1cdbd2cSJim Jagielski 
821*b1cdbd2cSJim Jagielski         inode_holder_type xNode (aPage.get());
822*b1cdbd2cSJim Jagielski 
823*b1cdbd2cSJim Jagielski 		// Acquire page write access.
824*b1cdbd2cSJim Jagielski 		OStorePageDescriptor aDescr (xNode->m_aDescr);
825*b1cdbd2cSJim Jagielski 		eErrCode = base::acquirePage (aDescr, store_AccessReadWrite);
826*b1cdbd2cSJim Jagielski 		if (eErrCode != store_E_None)
827*b1cdbd2cSJim Jagielski 			return eErrCode;
828*b1cdbd2cSJim Jagielski 
829*b1cdbd2cSJim Jagielski 		// Check for symbolic link.
830*b1cdbd2cSJim Jagielski 		if (!(aPage.attrib() & STORE_ATTRIB_ISLINK))
831*b1cdbd2cSJim Jagielski 		{
832*b1cdbd2cSJim Jagielski 			// Ordinary inode. Determine 'Data' scope.
833*b1cdbd2cSJim Jagielski 			inode::ChunkScope eScope = xNode->scope (aPage.dataLength());
834*b1cdbd2cSJim Jagielski 			if (eScope == inode::SCOPE_EXTERNAL)
835*b1cdbd2cSJim Jagielski 			{
836*b1cdbd2cSJim Jagielski 				// External 'Data' scope. Truncate all external data pages.
837*b1cdbd2cSJim Jagielski 				eErrCode = aPage.truncate (0, *this);
838*b1cdbd2cSJim Jagielski 				if (eErrCode != store_E_None)
839*b1cdbd2cSJim Jagielski 					return eErrCode;
840*b1cdbd2cSJim Jagielski 			}
841*b1cdbd2cSJim Jagielski 
842*b1cdbd2cSJim Jagielski 			// Truncate internal data page.
843*b1cdbd2cSJim Jagielski 			memset (&(xNode->m_pData[0]), 0, xNode->capacity());
844*b1cdbd2cSJim Jagielski 			aPage.dataLength (0);
845*b1cdbd2cSJim Jagielski 		}
846*b1cdbd2cSJim Jagielski 
847*b1cdbd2cSJim Jagielski 		// Release page write access.
848*b1cdbd2cSJim Jagielski 		eErrCode = base::releasePage (aDescr, store_AccessReadWrite);
849*b1cdbd2cSJim Jagielski 
850*b1cdbd2cSJim Jagielski 		// Release and free directory page.
851*b1cdbd2cSJim Jagielski 		eErrCode = base::free (aPage.location());
852*b1cdbd2cSJim Jagielski 	}
853*b1cdbd2cSJim Jagielski 
854*b1cdbd2cSJim Jagielski 	// Remove entry.
855*b1cdbd2cSJim Jagielski 	return remove_Impl (e);
856*b1cdbd2cSJim Jagielski }
857*b1cdbd2cSJim Jagielski 
858*b1cdbd2cSJim Jagielski /*
859*b1cdbd2cSJim Jagielski  * RebuildContext.
860*b1cdbd2cSJim Jagielski  */
861*b1cdbd2cSJim Jagielski struct RebuildContext
862*b1cdbd2cSJim Jagielski {
863*b1cdbd2cSJim Jagielski 	/** Representation.
864*b1cdbd2cSJim Jagielski 	*/
865*b1cdbd2cSJim Jagielski 	rtl::Reference<OStorePageBIOS> m_xBIOS;
866*b1cdbd2cSJim Jagielski 	OStorePageBIOS::ScanContext    m_aCtx;
867*b1cdbd2cSJim Jagielski     sal_uInt16                     m_nPageSize;
868*b1cdbd2cSJim Jagielski 
869*b1cdbd2cSJim Jagielski 	/** Construction.
870*b1cdbd2cSJim Jagielski 	 */
RebuildContextRebuildContext871*b1cdbd2cSJim Jagielski 	RebuildContext (void)
872*b1cdbd2cSJim Jagielski 		: m_xBIOS     (new OStorePageBIOS()),
873*b1cdbd2cSJim Jagielski           m_nPageSize (0)
874*b1cdbd2cSJim Jagielski 	{}
875*b1cdbd2cSJim Jagielski 
876*b1cdbd2cSJim Jagielski 	/** initialize (PageBIOS and ScanContext).
877*b1cdbd2cSJim Jagielski 	*/
initializeRebuildContext878*b1cdbd2cSJim Jagielski 	storeError initialize (ILockBytes *pLockBytes, sal_uInt32 nMagic = 0)
879*b1cdbd2cSJim Jagielski 	{
880*b1cdbd2cSJim Jagielski 		storeError eErrCode = store_E_InvalidParameter;
881*b1cdbd2cSJim Jagielski 		if (pLockBytes)
882*b1cdbd2cSJim Jagielski 		{
883*b1cdbd2cSJim Jagielski 			m_xBIOS->initialize (pLockBytes, store_AccessReadOnly, m_nPageSize);
884*b1cdbd2cSJim Jagielski 			eErrCode = m_xBIOS->scanBegin (m_aCtx, nMagic);
885*b1cdbd2cSJim Jagielski 		}
886*b1cdbd2cSJim Jagielski 		return eErrCode;
887*b1cdbd2cSJim Jagielski 	}
888*b1cdbd2cSJim Jagielski 
889*b1cdbd2cSJim Jagielski 	/** initialize (ScanContext).
890*b1cdbd2cSJim Jagielski 	*/
initializeRebuildContext891*b1cdbd2cSJim Jagielski 	storeError initialize (sal_uInt32 nMagic = 0)
892*b1cdbd2cSJim Jagielski 	{
893*b1cdbd2cSJim Jagielski 		return m_xBIOS->scanBegin (m_aCtx, nMagic);
894*b1cdbd2cSJim Jagielski 	}
895*b1cdbd2cSJim Jagielski 
896*b1cdbd2cSJim Jagielski 	/** load (next ScanContext matching page).
897*b1cdbd2cSJim Jagielski 	*/
loadRebuildContext898*b1cdbd2cSJim Jagielski 	storeError load (OStorePageObject &rPage)
899*b1cdbd2cSJim Jagielski 	{
900*b1cdbd2cSJim Jagielski 		if (m_aCtx.isValid())
901*b1cdbd2cSJim Jagielski 			return m_xBIOS->scanNext (m_aCtx, rPage);
902*b1cdbd2cSJim Jagielski 		else
903*b1cdbd2cSJim Jagielski 			return store_E_CantSeek;
904*b1cdbd2cSJim Jagielski 	}
905*b1cdbd2cSJim Jagielski };
906*b1cdbd2cSJim Jagielski 
907*b1cdbd2cSJim Jagielski /*
908*b1cdbd2cSJim Jagielski  * rebuild.
909*b1cdbd2cSJim Jagielski  * Precond: none.
910*b1cdbd2cSJim Jagielski  */
rebuild(ILockBytes * pSrcLB,ILockBytes * pDstLB)911*b1cdbd2cSJim Jagielski storeError OStorePageManager::rebuild (
912*b1cdbd2cSJim Jagielski 	ILockBytes *pSrcLB, ILockBytes *pDstLB)
913*b1cdbd2cSJim Jagielski {
914*b1cdbd2cSJim Jagielski 	// Acquire exclusive access.
915*b1cdbd2cSJim Jagielski 	osl::MutexGuard aGuard(*this);
916*b1cdbd2cSJim Jagielski 
917*b1cdbd2cSJim Jagielski 	// Check arguments.
918*b1cdbd2cSJim Jagielski 	storeError eErrCode = store_E_InvalidParameter;
919*b1cdbd2cSJim Jagielski 	if (!(pSrcLB && pDstLB))
920*b1cdbd2cSJim Jagielski 		return eErrCode;
921*b1cdbd2cSJim Jagielski 
922*b1cdbd2cSJim Jagielski 	// Initialize 'Source' rebuild context.
923*b1cdbd2cSJim Jagielski 	RebuildContext aCtx;
924*b1cdbd2cSJim Jagielski 	eErrCode = aCtx.initialize (pSrcLB, STORE_MAGIC_DIRECTORYPAGE);
925*b1cdbd2cSJim Jagielski 	if (eErrCode != store_E_None)
926*b1cdbd2cSJim Jagielski 		return eErrCode;
927*b1cdbd2cSJim Jagielski     rtl::Reference<OStorePageBIOS> xSrcBIOS (aCtx.m_xBIOS);
928*b1cdbd2cSJim Jagielski 
929*b1cdbd2cSJim Jagielski 	// Initialize as 'Destination' with 'Source' page size.
930*b1cdbd2cSJim Jagielski 	eErrCode = self::initialize (pDstLB, store_AccessCreate, aCtx.m_nPageSize);
931*b1cdbd2cSJim Jagielski 	if (eErrCode != store_E_None)
932*b1cdbd2cSJim Jagielski 		return eErrCode;
933*b1cdbd2cSJim Jagielski 
934*b1cdbd2cSJim Jagielski 	// Pass One: Scan 'Source' directory pages.
935*b1cdbd2cSJim Jagielski     {
936*b1cdbd2cSJim Jagielski         // Scan 'Source' directory pages.
937*b1cdbd2cSJim Jagielski         OStoreDirectoryPageObject aSrcPage;
938*b1cdbd2cSJim Jagielski         while ((eErrCode = aCtx.load(aSrcPage)) == store_E_None)
939*b1cdbd2cSJim Jagielski         {
940*b1cdbd2cSJim Jagielski             OStoreDirectoryPageObject aDstPage;
941*b1cdbd2cSJim Jagielski             eErrCode = aDstPage.construct< inode >(base::allocator());
942*b1cdbd2cSJim Jagielski             if (eErrCode != store_E_None)
943*b1cdbd2cSJim Jagielski                 break;
944*b1cdbd2cSJim Jagielski 
945*b1cdbd2cSJim Jagielski             inode_holder_type xSrcDir (aSrcPage.get());
946*b1cdbd2cSJim Jagielski             inode_holder_type xDstDir (aDstPage.get());
947*b1cdbd2cSJim Jagielski 
948*b1cdbd2cSJim Jagielski             // Copy NameBlock @@@ OLD @@@
949*b1cdbd2cSJim Jagielski             memcpy (&(xDstDir->m_aNameBlock), &(xSrcDir->m_aNameBlock), sizeof(xSrcDir->m_aNameBlock));
950*b1cdbd2cSJim Jagielski 
951*b1cdbd2cSJim Jagielski             // Obtain 'Source' data length.
952*b1cdbd2cSJim Jagielski             sal_uInt32 nDataLen = aSrcPage.dataLength();
953*b1cdbd2cSJim Jagielski             if (nDataLen > 0)
954*b1cdbd2cSJim Jagielski             {
955*b1cdbd2cSJim Jagielski                 // Copy internal data area @@@ OLD @@@
956*b1cdbd2cSJim Jagielski                 memcpy (&(xDstDir->m_pData[0]), &(xSrcDir->m_pData[0]), xSrcDir->capacity());
957*b1cdbd2cSJim Jagielski             }
958*b1cdbd2cSJim Jagielski 
959*b1cdbd2cSJim Jagielski             // Insert 'Destination' directory page.
960*b1cdbd2cSJim Jagielski             eErrCode = save_dirpage_Impl (aDstPage.key(), aDstPage);
961*b1cdbd2cSJim Jagielski             if (eErrCode != store_E_None)
962*b1cdbd2cSJim Jagielski                 break;
963*b1cdbd2cSJim Jagielski 
964*b1cdbd2cSJim Jagielski             // Check for external data page scope.
965*b1cdbd2cSJim Jagielski             if (xSrcDir->scope(nDataLen) != inode::SCOPE_INTERNAL)
966*b1cdbd2cSJim Jagielski             {
967*b1cdbd2cSJim Jagielski                 // Initialize 'Destination' data page.
968*b1cdbd2cSJim Jagielski                 typedef OStoreDataPageData data;
969*b1cdbd2cSJim Jagielski                 PageHolderObject< data > xData;
970*b1cdbd2cSJim Jagielski                 if (!xData.construct(base::allocator()))
971*b1cdbd2cSJim Jagielski                     return store_E_OutOfMemory;
972*b1cdbd2cSJim Jagielski 
973*b1cdbd2cSJim Jagielski                 // Determine data page count.
974*b1cdbd2cSJim Jagielski                 inode::ChunkDescriptor aDescr (
975*b1cdbd2cSJim Jagielski                     nDataLen - xDstDir->capacity(), xData->capacity());
976*b1cdbd2cSJim Jagielski 
977*b1cdbd2cSJim Jagielski                 sal_uInt32 i, n = aDescr.m_nPage;
978*b1cdbd2cSJim Jagielski                 if (aDescr.m_nOffset) n += 1;
979*b1cdbd2cSJim Jagielski 
980*b1cdbd2cSJim Jagielski                 // Copy data pages.
981*b1cdbd2cSJim Jagielski                 OStoreDataPageObject aData;
982*b1cdbd2cSJim Jagielski                 for (i = 0; i < n; i++)
983*b1cdbd2cSJim Jagielski                 {
984*b1cdbd2cSJim Jagielski                     // Read 'Source' data page.
985*b1cdbd2cSJim Jagielski                     osl::MutexGuard aSrcGuard (*xSrcBIOS);
986*b1cdbd2cSJim Jagielski 
987*b1cdbd2cSJim Jagielski                     eErrCode = aSrcPage.read (i, aData, *xSrcBIOS);
988*b1cdbd2cSJim Jagielski                     if (eErrCode != store_E_None)
989*b1cdbd2cSJim Jagielski                         continue;
990*b1cdbd2cSJim Jagielski 
991*b1cdbd2cSJim Jagielski                     // Write 'Destination' data page. @@@ READONLY @@@
992*b1cdbd2cSJim Jagielski                     eErrCode = aDstPage.write (i, aData, *this);
993*b1cdbd2cSJim Jagielski                 }
994*b1cdbd2cSJim Jagielski             }
995*b1cdbd2cSJim Jagielski 
996*b1cdbd2cSJim Jagielski             // Update 'Destination' directory page.
997*b1cdbd2cSJim Jagielski             aDstPage.dataLength (nDataLen);
998*b1cdbd2cSJim Jagielski             eErrCode = base::saveObjectAt (aDstPage, aDstPage.location());
999*b1cdbd2cSJim Jagielski         }
1000*b1cdbd2cSJim Jagielski 
1001*b1cdbd2cSJim Jagielski         // Save directory scan results.
1002*b1cdbd2cSJim Jagielski         flush();
1003*b1cdbd2cSJim Jagielski     }
1004*b1cdbd2cSJim Jagielski 
1005*b1cdbd2cSJim Jagielski     // Pass Two: Scan 'Source' BTree nodes.
1006*b1cdbd2cSJim Jagielski     {
1007*b1cdbd2cSJim Jagielski         // Re-start 'Source' rebuild context.
1008*b1cdbd2cSJim Jagielski         aCtx.initialize (STORE_MAGIC_BTREENODE);
1009*b1cdbd2cSJim Jagielski 
1010*b1cdbd2cSJim Jagielski         // Scan 'Source' BTree nodes.
1011*b1cdbd2cSJim Jagielski         OStoreBTreeNodeObject aNode;
1012*b1cdbd2cSJim Jagielski         while ((eErrCode = aCtx.load(aNode)) == store_E_None)
1013*b1cdbd2cSJim Jagielski         {
1014*b1cdbd2cSJim Jagielski             // Check for leaf node.
1015*b1cdbd2cSJim Jagielski             PageHolderObject< page > xNode (aNode.get());
1016*b1cdbd2cSJim Jagielski             if (xNode->depth() == 0)
1017*b1cdbd2cSJim Jagielski             {
1018*b1cdbd2cSJim Jagielski                 sal_uInt16 i, n = xNode->usageCount();
1019*b1cdbd2cSJim Jagielski                 for (i = 0; i < n; i++)
1020*b1cdbd2cSJim Jagielski                 {
1021*b1cdbd2cSJim Jagielski                     entry e (xNode->m_pData[i]);
1022*b1cdbd2cSJim Jagielski 
1023*b1cdbd2cSJim Jagielski                     // Check for Hard link.
1024*b1cdbd2cSJim Jagielski                     if (e.m_nAttrib & STORE_ATTRIB_ISLINK)
1025*b1cdbd2cSJim Jagielski                     {
1026*b1cdbd2cSJim Jagielski                         // Load the hard link destination.
1027*b1cdbd2cSJim Jagielski                         OStoreDirectoryPageObject aSrcPage;
1028*b1cdbd2cSJim Jagielski                         eErrCode = xSrcBIOS->loadObjectAt (aSrcPage, e.m_aLink.location());
1029*b1cdbd2cSJim Jagielski                         if (eErrCode == store_E_None)
1030*b1cdbd2cSJim Jagielski                         {
1031*b1cdbd2cSJim Jagielski                             OStorePageKey aDstKey (aSrcPage.key());
1032*b1cdbd2cSJim Jagielski                             eErrCode = link (e.m_aKey, aDstKey);
1033*b1cdbd2cSJim Jagielski                         }
1034*b1cdbd2cSJim Jagielski                         e.m_nAttrib &= ~STORE_ATTRIB_ISLINK;
1035*b1cdbd2cSJim Jagielski                     }
1036*b1cdbd2cSJim Jagielski 
1037*b1cdbd2cSJim Jagielski                     if (e.m_nAttrib)
1038*b1cdbd2cSJim Jagielski                     {
1039*b1cdbd2cSJim Jagielski                         // Ordinary attributes.
1040*b1cdbd2cSJim Jagielski                         sal_uInt32 nAttrib = 0;
1041*b1cdbd2cSJim Jagielski                         eErrCode = attrib (e.m_aKey, 0, e.m_nAttrib, nAttrib);
1042*b1cdbd2cSJim Jagielski                     }
1043*b1cdbd2cSJim Jagielski                 }
1044*b1cdbd2cSJim Jagielski             }
1045*b1cdbd2cSJim Jagielski         }
1046*b1cdbd2cSJim Jagielski 
1047*b1cdbd2cSJim Jagielski         // Save BTree node scan results.
1048*b1cdbd2cSJim Jagielski         flush();
1049*b1cdbd2cSJim Jagielski     }
1050*b1cdbd2cSJim Jagielski 
1051*b1cdbd2cSJim Jagielski 	// Done.
1052*b1cdbd2cSJim Jagielski 	return store_E_None;
1053*b1cdbd2cSJim Jagielski }
1054