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 "storlckb.hxx"
22 : :
23 : : #include "sal/types.h"
24 : : #include "sal/macros.h"
25 : : #include "rtl/string.h"
26 : : #include "rtl/ref.hxx"
27 : : #include "osl/mutex.hxx"
28 : :
29 : : #include "store/types.h"
30 : : #include "object.hxx"
31 : :
32 : : #include "storbase.hxx"
33 : : #include "stordata.hxx"
34 : : #include "storpage.hxx"
35 : :
36 : : using namespace store;
37 : :
38 : : /*========================================================================
39 : : *
40 : : * OStoreLockBytes implementation.
41 : : *
42 : : *======================================================================*/
43 : : const sal_uInt32 OStoreLockBytes::m_nTypeId = sal_uInt32(0x94190310);
44 : :
45 : : /*
46 : : * OStoreLockBytes.
47 : : */
48 : 651740 : OStoreLockBytes::OStoreLockBytes (void)
49 : : : m_xManager (),
50 : : m_xNode (),
51 [ + - ][ + - ]: 651740 : m_bWriteable (false)
[ + - ][ + - ]
52 : : {
53 : 651740 : }
54 : :
55 : : /*
56 : : * ~OStoreLockBytes.
57 : : */
58 [ + - ][ + - ]: 651740 : OStoreLockBytes::~OStoreLockBytes (void)
59 : : {
60 [ + + ][ + - ]: 651740 : if (m_xManager.is() && m_xNode.is())
[ + + ]
61 : : {
62 [ + - ][ + - ]: 639554 : m_xManager->releasePage(m_xNode->m_aDescr);
63 : : }
64 [ - + ]: 1303480 : }
65 : :
66 : : /*
67 : : * isKindOf.
68 : : */
69 : 919348 : sal_Bool SAL_CALL OStoreLockBytes::isKindOf (sal_uInt32 nTypeId)
70 : : {
71 : 919348 : return (nTypeId == m_nTypeId);
72 : : }
73 : :
74 : : /*
75 : : * create.
76 : : */
77 : 651740 : storeError OStoreLockBytes::create (
78 : : OStorePageManager *pManager,
79 : : rtl_String *pPath,
80 : : rtl_String *pName,
81 : : storeAccessMode eMode)
82 : : {
83 [ + - ]: 651740 : rtl::Reference<OStorePageManager> xManager (pManager);
84 [ - + ]: 651740 : if (!xManager.is())
85 : 0 : return store_E_InvalidAccess;
86 : :
87 [ + - ][ - + ]: 651740 : if (!(pPath && pName))
88 : 0 : return store_E_InvalidParameter;
89 : :
90 [ + - ][ + - ]: 651740 : OStoreDirectoryPageObject aPage;
[ + - ][ + - ]
91 : : storeError eErrCode = xManager->iget (
92 : : aPage, STORE_ATTRIB_ISFILE,
93 [ + - ]: 651740 : pPath, pName, eMode);
94 [ + + ]: 651740 : if (eErrCode != store_E_None)
95 : 12186 : return eErrCode;
96 : :
97 [ + - ][ - + ]: 639554 : if (!(aPage.attrib() & STORE_ATTRIB_ISFILE))
98 : : {
99 : : // No ISFILE in older versions (backward compatibility).
100 [ # # ][ # # ]: 0 : if (aPage.attrib() & STORE_ATTRIB_ISLINK)
101 : 0 : return store_E_NotFile;
102 : : }
103 : :
104 : : // ...
105 [ + - ]: 639554 : inode_holder_type xNode (aPage.get());
106 [ + + ]: 639554 : if (eMode != store_AccessReadOnly)
107 [ + - ][ + - ]: 138656 : eErrCode = xManager->acquirePage (xNode->m_aDescr, store_AccessReadWrite);
108 : : else
109 [ + - ][ + - ]: 500898 : eErrCode = xManager->acquirePage (xNode->m_aDescr, store_AccessReadOnly);
110 [ - + ]: 639554 : if (eErrCode != store_E_None)
111 : 0 : return eErrCode;
112 : :
113 : : // ...
114 [ + - ]: 639554 : m_xManager = xManager;
115 [ + - ]: 639554 : m_xNode = xNode;
116 : 639554 : m_bWriteable = (eMode != store_AccessReadOnly);
117 : :
118 : : // Check for truncation.
119 [ + + ]: 639554 : if (eMode == store_AccessCreate)
120 : : {
121 : : // Truncate to zero length.
122 [ + - ]: 90103 : eErrCode = setSize(0);
123 : : }
124 [ + - ][ + - ]: 651740 : return eErrCode;
[ + - ]
125 : : }
126 : :
127 : : /*
128 : : * readAt.
129 : : */
130 : 829245 : storeError OStoreLockBytes::readAt (
131 : : sal_uInt32 nOffset,
132 : : void *pBuffer,
133 : : sal_uInt32 nBytes,
134 : : sal_uInt32 &rnDone)
135 : : {
136 : 829245 : rnDone = 0;
137 : :
138 [ - + ]: 829245 : if (!m_xManager.is())
139 : 0 : return store_E_InvalidAccess;
140 : :
141 [ - + ]: 829245 : if (!pBuffer)
142 : 0 : return store_E_InvalidParameter;
143 [ - + ]: 829245 : if (!nBytes)
144 : 0 : return store_E_None;
145 : :
146 : : // Acquire exclusive access.
147 [ + - ]: 829245 : osl::MutexGuard aGuard (*m_xManager);
148 : :
149 : : // Determine data length.
150 [ + - ]: 829245 : OStoreDirectoryPageObject aPage (m_xNode.get());
151 : :
152 [ + - ]: 829245 : sal_uInt32 nDataLen = aPage.dataLength();
153 [ - + ]: 829245 : if ((nOffset + nBytes) > nDataLen)
154 : 0 : nBytes = nDataLen - nOffset;
155 : :
156 : : // Read data.
157 [ + - ][ + - ]: 829245 : OStoreDataPageObject aData;
[ + - ][ + - ]
158 : 829245 : sal_uInt8 *pData = (sal_uInt8*)pBuffer;
159 [ + + ][ + - ]: 1942371 : while ((0 < nBytes) && (nOffset < nDataLen))
[ + + ]
160 : : {
161 : : // Determine 'Offset' scope.
162 [ + - ]: 1113126 : inode::ChunkScope eScope = m_xNode->scope (nOffset);
163 [ + + ]: 1113126 : if (eScope == inode::SCOPE_INTERNAL)
164 : : {
165 : : // Read from inode page (internal scope).
166 : : inode::ChunkDescriptor aDescr (
167 [ + - ]: 829245 : nOffset, m_xNode->capacity());
168 : :
169 : 829245 : sal_uInt32 nLength = sal_uInt32(aDescr.m_nLength);
170 [ + + ]: 829245 : nLength = SAL_MIN(nLength, nBytes);
171 : :
172 : : memcpy (
173 : 829245 : &pData[rnDone],
174 [ + - ]: 829245 : &m_xNode->m_pData[aDescr.m_nOffset],
175 : 1658490 : nLength);
176 : :
177 : : // Adjust counters.
178 : 829245 : rnDone += nLength;
179 : 829245 : nOffset += nLength;
180 : 829245 : nBytes -= nLength;
181 : : }
182 : : else
183 : : {
184 : : // Read from data page (external scope).
185 : : inode::ChunkDescriptor aDescr (
186 [ + - ][ + - ]: 283881 : nOffset - m_xNode->capacity(), OStoreDataPageData::capacity(m_xNode->m_aDescr)); // @@@
187 : :
188 : 283881 : sal_uInt32 nLength = sal_uInt32(aDescr.m_nLength);
189 [ + + ]: 283881 : nLength = SAL_MIN(nLength, nBytes);
190 : :
191 [ + - ]: 283881 : storeError eErrCode = aPage.read (aDescr.m_nPage, aData, *m_xManager);
192 [ - + ]: 283881 : if (eErrCode != store_E_None)
193 : : {
194 [ # # ]: 0 : if (eErrCode != store_E_NotExists)
195 : 0 : return eErrCode;
196 : :
197 : : memset (
198 : 0 : &pData[rnDone],
199 : : 0,
200 : 0 : nLength);
201 : : }
202 : : else
203 : : {
204 [ + - ]: 283881 : PageHolderObject< data > xData (aData.makeHolder<data>());
205 : : memcpy (
206 : 283881 : &pData[rnDone],
207 [ + - ]: 283881 : &xData->m_pData[aDescr.m_nOffset],
208 [ + - ]: 283881 : nLength);
209 : : }
210 : :
211 : : // Adjust counters.
212 : 283881 : rnDone += nLength;
213 : 283881 : nOffset += nLength;
214 : 283881 : nBytes -= nLength;
215 : : }
216 : : }
217 : :
218 : : // Done.
219 [ + - ][ + - ]: 829245 : return store_E_None;
[ + - ]
220 : : }
221 : :
222 : : /*
223 : : * writeAt.
224 : : */
225 : 90103 : storeError OStoreLockBytes::writeAt (
226 : : sal_uInt32 nOffset,
227 : : const void *pBuffer,
228 : : sal_uInt32 nBytes,
229 : : sal_uInt32 &rnDone)
230 : : {
231 : 90103 : rnDone = 0;
232 : :
233 [ - + ]: 90103 : if (!m_xManager.is())
234 : 0 : return store_E_InvalidAccess;
235 [ - + ]: 90103 : if (!m_bWriteable)
236 : 0 : return store_E_AccessViolation;
237 : :
238 [ - + ]: 90103 : if (!pBuffer)
239 : 0 : return store_E_InvalidParameter;
240 [ - + ]: 90103 : if (!nBytes)
241 : 0 : return store_E_None;
242 : :
243 : : // Acquire exclusive access.
244 [ + - ]: 90103 : osl::MutexGuard aGuard (*m_xManager);
245 : :
246 : : // Write data.
247 [ + - ]: 90103 : OStoreDirectoryPageObject aPage (m_xNode.get());
248 : 90103 : const sal_uInt8 *pData = (const sal_uInt8*)pBuffer;
249 : :
250 : 90103 : storeError eErrCode = store_E_None;
251 [ + + ]: 216205 : while (nBytes > 0)
252 : : {
253 : : // Determine 'Offset' scope.
254 [ + - ]: 126102 : inode::ChunkScope eScope = m_xNode->scope (nOffset);
255 [ + + ]: 126102 : if (eScope == inode::SCOPE_INTERNAL)
256 : : {
257 : : // Write to inode page (internal scope).
258 : : inode::ChunkDescriptor aDescr (
259 [ + - ]: 90103 : nOffset, m_xNode->capacity());
260 : :
261 : 90103 : sal_uInt32 nLength = sal_uInt32(aDescr.m_nLength);
262 [ + + ]: 90103 : nLength = SAL_MIN(nLength, nBytes);
263 : :
264 : : memcpy (
265 [ + - ]: 90103 : &m_xNode->m_pData[aDescr.m_nOffset],
266 : 180206 : &pData[rnDone], nLength);
267 : :
268 : : // Mark inode dirty.
269 : 90103 : aPage.touch();
270 : :
271 : : // Adjust counters.
272 : 90103 : rnDone += nLength;
273 : 90103 : nOffset += nLength;
274 : 90103 : nBytes -= nLength;
275 : :
276 : : // Adjust data length.
277 [ + - ][ + - ]: 90103 : if (aPage.dataLength() < nOffset)
278 [ + - ]: 90103 : aPage.dataLength (nOffset);
279 : : }
280 : : else
281 : : {
282 : : // Write to data page (external scope).
283 [ + - ][ + - ]: 35999 : OStoreDataPageObject aData;
[ + - ][ + - ]
284 : :
285 : : inode::ChunkDescriptor aDescr (
286 [ + - ][ + - ]: 35999 : nOffset - m_xNode->capacity(), OStoreDataPageData::capacity(m_xNode->m_aDescr)); // @@@
287 : :
288 : 35999 : sal_uInt32 nLength = sal_uInt32(aDescr.m_nLength);
289 [ + + ][ + - ]: 35999 : if ((aDescr.m_nOffset > 0) || (nBytes < nLength))
290 : : {
291 : : // Unaligned. Need to load/create data page.
292 : : // @@@ loadOrCreate()
293 [ + - ]: 26481 : eErrCode = aPage.read (aDescr.m_nPage, aData, *m_xManager);
294 [ + - ]: 26481 : if (eErrCode != store_E_None)
295 : : {
296 [ - + ]: 26481 : if (eErrCode != store_E_NotExists)
297 : 0 : return eErrCode;
298 : :
299 [ + - ]: 26481 : eErrCode = aData.construct<data>(m_xManager->allocator());
300 [ - + ]: 26481 : if (eErrCode != store_E_None)
301 : 0 : return eErrCode;
302 : : }
303 : : }
304 : :
305 [ + - ]: 35999 : PageHolderObject< data > xData (aData.makeHolder<data>());
306 [ + + ]: 35999 : if (!xData.is())
307 : : {
308 [ + - ]: 9518 : eErrCode = aData.construct<data>(m_xManager->allocator());
309 [ - + ]: 9518 : if (eErrCode != store_E_None)
310 : 0 : return eErrCode;
311 [ + - ][ + - ]: 9518 : xData = aData.makeHolder<data>();
[ + - ]
312 : : }
313 : :
314 : : // Modify data page.
315 [ + + ]: 35999 : nLength = SAL_MIN(nLength, nBytes);
316 : : memcpy (
317 [ + - ]: 35999 : &xData->m_pData[aDescr.m_nOffset],
318 : 71998 : &pData[rnDone], nLength);
319 : :
320 : : // Save data page.
321 [ + - ]: 35999 : eErrCode = aPage.write (aDescr.m_nPage, aData, *m_xManager);
322 [ - + ]: 35999 : if (eErrCode != store_E_None)
323 : 0 : return eErrCode;
324 : :
325 : : // Adjust counters.
326 : 35999 : rnDone += nLength;
327 : 35999 : nOffset += nLength;
328 : 35999 : nBytes -= nLength;
329 : :
330 : : // Adjust data length.
331 [ + - ][ + - ]: 35999 : if (aPage.dataLength() < nOffset)
332 [ + - ][ + - ]: 35999 : aPage.dataLength (nOffset);
[ - + ][ + - ]
[ + - ]
333 : : }
334 : : }
335 : :
336 : : // Check for modified inode.
337 [ + - ]: 90103 : if (aPage.dirty())
338 [ + - ]: 90103 : return m_xManager->saveObjectAt (aPage, aPage.location());
339 : : else
340 [ + - ][ + - ]: 90103 : return store_E_None;
341 : : }
342 : :
343 : : /*
344 : : * flush.
345 : : */
346 : 0 : storeError OStoreLockBytes::flush (void)
347 : : {
348 [ # # ]: 0 : if (!m_xManager.is())
349 : 0 : return store_E_InvalidAccess;
350 : :
351 : 0 : return m_xManager->flush();
352 : : }
353 : :
354 : : /*
355 : : * setSize.
356 : : */
357 : 90103 : storeError OStoreLockBytes::setSize (sal_uInt32 nSize)
358 : : {
359 [ - + ]: 90103 : if (!m_xManager.is())
360 : 0 : return store_E_InvalidAccess;
361 [ - + ]: 90103 : if (!m_bWriteable)
362 : 0 : return store_E_AccessViolation;
363 : :
364 : : // Acquire exclusive access.
365 [ + - ]: 90103 : osl::MutexGuard aGuard (*m_xManager);
366 : :
367 : : // Determine current length.
368 [ + - ]: 90103 : OStoreDirectoryPageObject aPage (m_xNode.get());
369 [ + - ]: 90103 : sal_uInt32 nDataLen = aPage.dataLength();
370 : :
371 [ + + ]: 90103 : if (nSize == nDataLen)
372 : 42436 : return store_E_None;
373 : :
374 [ + - ]: 47667 : if (nSize < nDataLen)
375 : : {
376 : : // Truncate.
377 : 47667 : storeError eErrCode = store_E_None;
378 : :
379 : : // Determine 'Size' scope.
380 [ + - ]: 47667 : inode::ChunkScope eSizeScope = m_xNode->scope (nSize);
381 [ + - ]: 47667 : if (eSizeScope == inode::SCOPE_INTERNAL)
382 : : {
383 : : // Internal 'Size' scope. Determine 'Data' scope.
384 [ + - ]: 47667 : inode::ChunkScope eDataScope = m_xNode->scope (nDataLen);
385 [ + + ]: 47667 : if (eDataScope == inode::SCOPE_EXTERNAL)
386 : : {
387 : : // External 'Data' scope. Truncate all external data pages.
388 [ + - ]: 9074 : eErrCode = aPage.truncate (0, *m_xManager);
389 [ - + ]: 9074 : if (eErrCode != store_E_None)
390 : 0 : return eErrCode;
391 : : }
392 : :
393 : : // Truncate internal data page.
394 [ + - ]: 47667 : inode::ChunkDescriptor aDescr (nSize, m_xNode->capacity());
395 : : memset (
396 [ + - ]: 47667 : &(m_xNode->m_pData[aDescr.m_nOffset]),
397 : 47667 : 0, aDescr.m_nLength);
398 : : }
399 : : else
400 : : {
401 : : // External 'Size' scope. Truncate external data pages.
402 : : inode::ChunkDescriptor aDescr (
403 [ # # ][ # # ]: 0 : nSize - m_xNode->capacity(), OStoreDataPageData::capacity(m_xNode->m_aDescr)); // @@@
404 : :
405 : 0 : sal_uInt32 nPage = aDescr.m_nPage;
406 [ # # ]: 0 : if (aDescr.m_nOffset) nPage += 1;
407 : :
408 [ # # ]: 0 : eErrCode = aPage.truncate (nPage, *m_xManager);
409 [ # # ]: 0 : if (eErrCode != store_E_None)
410 : 0 : return eErrCode;
411 : : }
412 : : }
413 : :
414 : : // Set (extended or truncated) size.
415 [ + - ]: 47667 : aPage.dataLength (nSize);
416 : :
417 : : // Save modified inode.
418 [ + - ][ + - ]: 90103 : return m_xManager->saveObjectAt (aPage, aPage.location());
[ + - ]
419 : : }
420 : :
421 : : /*
422 : : * stat.
423 : : */
424 : 0 : storeError OStoreLockBytes::stat (sal_uInt32 &rnSize)
425 : : {
426 : 0 : rnSize = 0;
427 : :
428 [ # # ]: 0 : if (!m_xManager.is())
429 : 0 : return store_E_InvalidAccess;
430 : :
431 [ # # ]: 0 : OStoreDirectoryPageObject aPage (m_xNode.get());
432 [ # # ]: 0 : rnSize = aPage.dataLength();
433 [ # # ]: 0 : return store_E_None;
434 : : }
435 : :
436 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|