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