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