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