LibreOffice Module store (master) 1
storpage.cxx
Go to the documentation of this file.
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#include "storpage.hxx"
21
22#include <sal/types.h>
23#include <sal/log.hxx>
24#include <rtl/string.h>
25#include <osl/mutex.hxx>
26
27#include <store/types.h>
28
29#include "storbase.hxx"
30#include "stordata.hxx"
31#include "stortree.hxx"
32
33using namespace store;
34
35const sal_uInt32 OStorePageManager::m_nTypeId = sal_uInt32(0x62190120);
36
37OStorePageManager::OStorePageManager()
38{
39}
40
42{
43}
44
45bool OStorePageManager::isKindOf (sal_uInt32 nTypeId)
46{
47 return (nTypeId == m_nTypeId);
48}
49
50/*
51 * initialize (two-phase construction).
52 * Precond: none.
53 */
55 ILockBytes * pLockBytes,
56 storeAccessMode eAccessMode,
57 sal_uInt16 & rnPageSize)
58{
59 // Acquire exclusive access.
60 osl::MutexGuard aGuard(*this);
61
62 // Check arguments.
63 if (!pLockBytes)
65
66 // Initialize base.
67 storeError eErrCode = base::initialize (pLockBytes, eAccessMode, rnPageSize);
68 if (eErrCode != store_E_None)
69 return eErrCode;
70
71 // Check for (not) writeable.
72 if (!base::isWriteable())
73 {
74 // Readonly. Load RootNode.
75 return base::loadObjectAt (m_aRoot, rnPageSize);
76 }
77
78 // Writeable. Load or Create RootNode.
79 eErrCode = m_aRoot.loadOrCreate (rnPageSize, *this);
80 if (eErrCode == store_E_Pending)
81 {
82 // Creation notification.
84
85 // Pre-allocate left most entry (ugly, but we can't insert to left).
86 OStorePageKey aKey (rtl_crc32 (0, "/", 1), 0);
87 xRoot->insert (0, entry(aKey));
88
89 // Save RootNode.
90 eErrCode = base::saveObjectAt (m_aRoot, rnPageSize);
91 }
92
93 // Done.
94 return eErrCode;
95}
96
97/*
98 * find_lookup (w/o split()).
99 * Internal: Precond: initialized, readable, exclusive access.
100 */
102 OStoreBTreeNodeObject & rNode,
103 sal_uInt16 & rIndex,
104 OStorePageKey const & rKey)
105{
106 // Find Node and Index.
107 storeError eErrCode = m_aRoot.find_lookup (rNode, rIndex, rKey, *this);
108 if (eErrCode != store_E_None)
109 return eErrCode;
110
111 // Greater or Equal.
112 PageHolderObject< page > xPage (rNode.get());
113 SAL_WARN_IF(rIndex >= xPage->usageCount(), "store", "store::PageManager::find_lookup(): logic error");
114 entry e (xPage->m_pData[rIndex]);
115
116 // Check for exact match.
117 if (e.compare(entry(rKey)) != entry::COMPARE_EQUAL)
118 {
119 // Page not present.
120 return store_E_NotExists;
121 }
122
123 // Check address.
125 {
126 // Page not present.
127 return store_E_NotExists;
128 }
129
130 return store_E_None;
131}
132
133/*
134 * remove_Impl (possibly down from root).
135 * Internal: Precond: initialized, writeable, exclusive access.
136 */
137
139{
141
142 // Check current page index.
143 PageHolderObject< page > xPage (aNode.get());
144 sal_uInt16 i = xPage->find (rEntry), n = xPage->usageCount();
145 if (i >= n)
146 {
147 // Path to entry not exists (Must not happen(?)).
148 return store_E_NotExists;
149 }
150
151 // Compare entry.
152 entry::CompareResult result = rEntry.compare (xPage->m_pData[i]);
153
154 // Iterate down until equal match.
155 while ((result == entry::COMPARE_GREATER) && (xPage->depth() > 0))
156 {
157 // Check link address.
158 sal_uInt32 const nAddr = xPage->m_pData[i].m_aLink.location();
159 if (nAddr == STORE_PAGE_NULL)
160 {
161 // Path to entry not exists (Must not happen(?)).
162 return store_E_NotExists;
163 }
164
165 // Load link page.
166 storeError eErrCode = loadObjectAt (aNode, nAddr);
167 if (eErrCode != store_E_None)
168 return eErrCode;
169
170 PageHolderObject< page > xNext (aNode.get());
171 xNext.swap (xPage);
172
173 // Check index.
174 i = xPage->find (rEntry);
175 n = xPage->usageCount();
176 if (i >= n)
177 {
178 // Path to entry not exists (Must not happen(?)).
179 return store_E_NotExists;
180 }
181
182 // Compare entry.
183 result = rEntry.compare (xPage->m_pData[i]);
184 }
185
188 "store",
189 "OStorePageManager::remove(): find failed");
190
191 // Check entry comparison.
193 {
194 // Must not happen.
195 return store_E_Unknown;
196 }
197
198 // Remove down from current page (recursive).
199 return aNode.remove (i, rEntry, *this);
200}
201
202/*
203 * namei.
204 * Precond: none (static).
205 */
207 const rtl_String *pPath, const rtl_String *pName, OStorePageKey &rKey)
208{
209 // Check parameter.
210 if (!(pPath && pName))
212
213 // Check name length.
214 if (pName->length >= STORE_MAXIMUM_NAMESIZE)
215 return store_E_NameTooLong;
216
217 // Transform pathname into key.
218 rKey.m_nLow = store::htonl(rtl_crc32 (0, pName->buffer, pName->length));
219 rKey.m_nHigh = store::htonl(rtl_crc32 (0, pPath->buffer, pPath->length));
220
221 // Done.
222 return store_E_None;
223}
224
225/*
226 * iget.
227 * Precond: initialized.
228 */
231 sal_uInt32 nAttrib,
232 const rtl_String * pPath,
233 const rtl_String * pName,
234 storeAccessMode eMode)
235{
236 // Acquire exclusive access.
237 osl::MutexGuard aGuard(*this);
238
239 // Check precond.
240 if (!self::isValid())
242
243 // Setup inode page key.
244 OStorePageKey aKey;
245 storeError eErrCode = namei (pPath, pName, aKey);
246 if (eErrCode != store_E_None)
247 return eErrCode;
248
249 // Check for directory.
250 if (nAttrib & STORE_ATTRIB_ISDIR)
251 {
252 // Ugly, but necessary (backward compatibility).
253 aKey.m_nLow = store::htonl(rtl_crc32 (store::ntohl(aKey.m_nLow), "/", 1));
254 }
255
256 // Load inode page.
257 eErrCode = load_dirpage_Impl (aKey, rPage);
258 if (eErrCode != store_E_None)
259 {
260 // Check mode and reason.
261 if (eErrCode != store_E_NotExists)
262 return eErrCode;
263
265 return store_E_NotExists;
267 return store_E_NotExists;
268
269 if (!base::isWriteable())
271
272 // Create inode page.
273 eErrCode = rPage.construct< inode >(base::allocator());
274 if (eErrCode != store_E_None)
275 return eErrCode;
276
277 // Setup inode nameblock.
278 PageHolderObject< inode > xPage (rPage.get());
279
280 rPage.key (aKey);
281 rPage.attrib (nAttrib);
282
283 memcpy (
284 &(xPage->m_aNameBlock.m_pData[0]),
285 pName->buffer, pName->length);
286
287 // Save inode page.
288 eErrCode = save_dirpage_Impl (aKey, rPage);
289 if (eErrCode != store_E_None)
290 return eErrCode;
291 }
292
293 // Check for symbolic link.
294 if (rPage.attrib() & STORE_ATTRIB_ISLINK)
295 {
296 // Obtain 'Destination' page key.
297 PageHolderObject< inode > xPage (rPage.get());
298 OStorePageKey aDstKey;
299 memcpy (&aDstKey, &(xPage->m_pData[0]), sizeof(aDstKey));
300
301 // Load 'Destination' inode.
302 eErrCode = load_dirpage_Impl (aDstKey, rPage);
303 if (eErrCode != store_E_None)
304 return eErrCode;
305 }
306
307 // Done.
308 return store_E_None;
309}
310
311/*
312 * iterate.
313 * Precond: initialized.
314 * ToDo: skip hardlink entries.
315 */
317 OStorePageKey & rKey,
318 OStorePageLink & rLink,
319 sal_uInt32 & rAttrib)
320{
321 // Acquire exclusive access.
322 osl::MutexGuard aGuard(*this);
323
324 // Check precond.
325 if (!self::isValid())
327
328 // Find NodePage and Index.
330 sal_uInt16 i = 0;
331 storeError eErrCode = m_aRoot.find_lookup (aNode, i, rKey, *this);
332 if (eErrCode != store_E_None)
333 return eErrCode;
334
335 // GreaterEqual. Found next entry.
336 PageHolderObject< page > xNode (aNode.get());
337 entry e (xNode->m_pData[i]);
338
339 // Setup result.
340 rKey = e.m_aKey;
341 rLink = e.m_aLink;
342 rAttrib = store::ntohl(e.m_nAttrib);
343
344 // Done.
345 return store_E_None;
346}
347
348/*
349 * load => private: iget() @@@
350 * Internal: Precond: initialized, exclusive access.
351 */
353 const OStorePageKey &rKey,
355{
356 // Find Node and Index.
358 sal_uInt16 i = 0;
359 storeError eErrCode = find_lookup (aNode, i, rKey);
360 if (eErrCode != store_E_None)
361 return eErrCode;
362
363 // Existing entry. Load page.
364 PageHolderObject< page > xNode (aNode.get());
365 entry e (xNode->m_pData[i]);
366 return loadObjectAt (rPage, e.m_aLink.location());
367}
368
369/*
370 * save => private: iget(), rebuild() @@@
371 * Internal: Precond: initialized, writeable, exclusive access.
372 */
374 const OStorePageKey &rKey,
376{
377 // Find NodePage and Index.
378 node aNode;
379 sal_uInt16 i = 0;
380
381 storeError eErrCode = m_aRoot.find_insert (aNode, i, rKey, *this);
382 PageHolderObject< page > xNode (aNode.get());
383 if (eErrCode != store_E_None)
384 {
385 if (eErrCode != store_E_AlreadyExists)
386 return eErrCode;
387
388 // Existing entry.
389 entry e (xNode->m_pData[i]);
391 {
392 // Save page to existing location.
393 return saveObjectAt (rPage, e.m_aLink.location());
394 }
395
396 // Allocate page.
397 eErrCode = base::allocate (rPage);
398 if (eErrCode != store_E_None)
399 return eErrCode;
400
401 // Update page location.
402 xNode->m_pData[i].m_aLink = rPage.location();
403
404 // Save modified NodePage.
405 return saveObjectAt (aNode, aNode.location());
406 }
407
408 // Allocate page.
409 eErrCode = base::allocate (rPage);
410 if (eErrCode != store_E_None)
411 return eErrCode;
412
413 // Insert.
414 OStorePageLink aLink (rPage.location());
415 xNode->insert (i + 1, entry (rKey, aLink));
416
417 // Save modified NodePage.
418 return saveObjectAt (aNode, aNode.location());
419}
420
421/*
422 * remove.
423 * Precond: initialized, writeable.
424 */
426{
427 // Acquire exclusive access.
428 osl::MutexGuard aGuard(*this);
429
430 // Check precond.
431 if (!self::isValid())
433
434 if (!base::isWriteable())
436
437 // Find NodePage and index.
438 OStoreBTreeNodeObject aNodePage;
439 sal_uInt16 i = 0;
440 storeError eErrCode = find_lookup (aNodePage, i, rKey);
441 if (eErrCode != store_E_None)
442 return eErrCode;
443
444 // Existing entry.
445 PageHolderObject< page > xNodePage (aNodePage.get());
446 entry e (xNodePage->m_pData[i]);
447
448 // Check for (not a) hardlink.
450 {
451 // Load directory page.
453 eErrCode = base::loadObjectAt (aPage, e.m_aLink.location());
454 if (eErrCode != store_E_None)
455 return eErrCode;
456
457 inode_holder_type xNode (aPage.get());
458
459 // Acquire page write access.
460 OStorePageDescriptor aDescr (xNode->m_aDescr);
462 if (eErrCode != store_E_None)
463 return eErrCode;
464
465 // Check for symbolic link.
466 if (!(aPage.attrib() & STORE_ATTRIB_ISLINK))
467 {
468 // Ordinary inode. Determine 'Data' scope.
469 inode::ChunkScope eScope = xNode->scope (aPage.dataLength());
470 if (eScope == inode::SCOPE_EXTERNAL)
471 {
472 // External 'Data' scope. Truncate all external data pages.
473 eErrCode = aPage.truncate (0, *this);
474 if (eErrCode != store_E_None)
475 return eErrCode;
476 }
477
478 // Truncate internal data page.
479 memset (&(xNode->m_pData[0]), 0, xNode->capacity());
480 aPage.dataLength (0);
481 }
482
483 // Release page write access.
484 base::releasePage (aDescr);
485
486 // Release and free directory page.
487 (void)base::free (aPage.location());
488 }
489
490 // Remove entry.
491 return remove_Impl (e);
492}
493
494/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const char * pName
storeError remove(sal_uInt16 nIndexL, OStoreBTreeEntry &rEntryL, OStorePageBIOS &rBIOS)
remove (down to leaf node, recursive).
Definition: stortree.cxx:191
storeError loadOrCreate(sal_uInt32 nAddr, OStorePageBIOS &rBIOS)
Definition: stortree.cxx:275
storeError find_lookup(OStoreBTreeNodeObject &rNode, sal_uInt16 &rIndex, OStorePageKey const &rKey, OStorePageBIOS &rBIOS) const
find_lookup (w/o split()).
Definition: stortree.cxx:338
storeError find_insert(OStoreBTreeNodeObject &rNode, sal_uInt16 &rIndex, OStorePageKey const &rKey, OStorePageBIOS &rBIOS)
find_insert (possibly with split()).
Definition: stortree.cxx:405
sal_uInt32 attrib() const
attrib.
Definition: stordata.hxx:608
void key(OStorePageKey const &rKey)
key.
Definition: stordata.hxx:620
sal_uInt32 dataLength() const
dataLength.
Definition: stordata.hxx:638
storeError truncate(sal_uInt32 nPage, OStorePageBIOS &rBIOS)
truncate (external data page).
Definition: stordata.cxx:834
storeError acquirePage(const OStorePageDescriptor &rDescr, storeAccessMode eMode)
Definition: storbios.cxx:646
rtl::Reference< PageData::Allocator > & allocator()
Definition: storbios.hxx:57
storeError saveObjectAt(OStorePageObject &rPage, sal_uInt32 nAddr)
Definition: storbios.cxx:822
storeError loadObjectAt(OStorePageObject &rPage, sal_uInt32 nAddr)
Page I/O.
Definition: storbios.cxx:781
storeError free(sal_uInt32 nAddr)
Definition: storbios.cxx:760
storeError allocate(OStorePageObject &rPage)
Definition: storbios.cxx:715
bool isWriteable() const
Definition: storbios.hxx:158
storeError releasePage(const OStorePageDescriptor &rDescr)
Definition: storbios.cxx:687
virtual storeError initialize(ILockBytes *pLockBytes, storeAccessMode eAccessMode, sal_uInt16 &rnPageSize)
Initialization.
Definition: storbios.cxx:484
OStoreBTreeRootObject m_aRoot
Representation.
Definition: storpage.hxx:111
bool isValid() const
isValid.
Definition: storpage.hxx:138
storeError remove(const OStorePageKey &rKey)
remove.
Definition: storpage.cxx:425
storeError iterate(OStorePageKey &rKey, OStorePageLink &rLink, sal_uInt32 &rAttrib)
Definition: storpage.cxx:316
virtual storeError initialize(ILockBytes *pLockBytes, storeAccessMode eAccessMode, sal_uInt16 &rnPageSize) override
Initialization (two-phase construction).
Definition: storpage.cxx:54
static const sal_uInt32 m_nTypeId
IStoreHandle TypeId.
Definition: storpage.hxx:102
virtual bool isKindOf(sal_uInt32 nTypeId) override
IStoreHandle.
Definition: storpage.cxx:45
storeError load_dirpage_Impl(const OStorePageKey &rKey, OStoreDirectoryPageObject &rPage)
DirectoryPage I/O (managed).
Definition: storpage.cxx:352
storeError remove_Impl(entry &rEntry)
remove (possibly down from root).
Definition: storpage.cxx:138
virtual ~OStorePageManager() override
Definition: storpage.cxx:41
static storeError namei(const rtl_String *pPath, const rtl_String *pName, OStorePageKey &rKey)
DirectoryPage I/O (managed).
Definition: storpage.cxx:206
storeError save_dirpage_Impl(const OStorePageKey &rKey, OStoreDirectoryPageObject &rPage)
Definition: storpage.cxx:373
storeError iget(OStoreDirectoryPageObject &rPage, sal_uInt32 nAttrib, const rtl_String *pPath, const rtl_String *pName, storeAccessMode eMode)
Definition: storpage.cxx:229
OStoreBTreeEntry entry
Definition: storpage.hxx:93
storeError find_lookup(OStoreBTreeNodeObject &rNode, sal_uInt16 &rIndex, OStorePageKey const &rKey)
find_lookup (node page and index, w/o split).
Definition: storpage.cxx:101
storeError construct(rtl::Reference< PageData::Allocator > const &rxAllocator)
Definition: storbase.hxx:567
sal_uInt32 location() const
Location.
Definition: storbase.hxx:601
std::shared_ptr< PageData > & get()
Definition: storbase.hxx:580
void swap(PageHolderObject< T > &rhs)
Definition: storbase.hxx:433
Mode eMode
sal_Int64 n
#define SAL_WARN_IF(condition, area, stream)
int i
Old OStorePageCache implementation.
Definition: lockbyte.cxx:133
sal_uInt32 htonl(sal_uInt32 h)
Definition: storbase.hxx:69
sal_uInt32 ntohl(sal_uInt32 n)
Definition: storbase.hxx:70
#define STORE_PAGE_NULL
Definition: storbase.hxx:114
CompareResult compare(const OStoreBTreeEntry &rOther) const
Definition: stortree.hxx:61
sal_uInt16 capacity() const
capacity.
Definition: stordata.hxx:507
NameBlock m_aNameBlock
Representation.
Definition: stordata.hxx:491
ChunkScope scope(sal_uInt32 nPosition) const
scope (internal).
Definition: stordata.hxx:576
sal_uInt32 m_nLow
Representation.
Definition: storbase.hxx:169
sal_uInt32 m_nHigh
Definition: storbase.hxx:170
char m_pData[STORE_MAXIMUM_NAMESIZE]
Definition: stordata.hxx:281
constexpr sal_uInt32 STORE_ATTRIB_ISDIR
Definition: types.h:52
storeAccessMode
Access Mode enumeration.
Definition: types.h:62
storeError
Error Code enumeration.
Definition: types.h:73
@ store_E_InvalidParameter
Definition: types.h:82
@ store_E_Unknown
Definition: types.h:95
@ store_E_None
Definition: types.h:74
@ store_E_InvalidAccess
Definition: types.h:80
@ store_E_AlreadyExists
Definition: types.h:84
@ store_E_AccessViolation
Definition: types.h:75
@ store_E_NotExists
Definition: types.h:85
@ store_E_Pending
Definition: types.h:92
@ store_E_NameTooLong
Definition: types.h:89
constexpr sal_uInt32 STORE_ATTRIB_ISLINK
Attributes (predefined).
Definition: types.h:51
constexpr auto STORE_MAXIMUM_NAMESIZE
NameSize (enforced) limit.
Definition: types.h:45
Any result