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