update credits
[LibreOffice.git] / store / source / storlckb.cxx
blob539bf3707caca041af2afda6d66538d570c7eb99
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include "storlckb.hxx"
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"
29 #include "store/types.h"
30 #include "object.hxx"
32 #include "storbase.hxx"
33 #include "stordata.hxx"
34 #include "storpage.hxx"
36 using namespace store;
38 /*========================================================================
40 * OStoreLockBytes implementation.
42 *======================================================================*/
43 const sal_uInt32 OStoreLockBytes::m_nTypeId = sal_uInt32(0x94190310);
46 * OStoreLockBytes.
48 OStoreLockBytes::OStoreLockBytes (void)
49 : m_xManager (),
50 m_xNode (),
51 m_bWriteable (false)
56 * ~OStoreLockBytes.
58 OStoreLockBytes::~OStoreLockBytes (void)
60 if (m_xManager.is() && m_xNode.is())
62 m_xManager->releasePage(m_xNode->m_aDescr);
67 * isKindOf.
69 sal_Bool SAL_CALL OStoreLockBytes::isKindOf (sal_uInt32 nTypeId)
71 return (nTypeId == m_nTypeId);
75 * create.
77 storeError OStoreLockBytes::create (
78 OStorePageManager *pManager,
79 rtl_String *pPath,
80 rtl_String *pName,
81 storeAccessMode eMode)
83 rtl::Reference<OStorePageManager> xManager (pManager);
84 if (!xManager.is())
85 return store_E_InvalidAccess;
87 if (!(pPath && pName))
88 return store_E_InvalidParameter;
90 OStoreDirectoryPageObject aPage;
91 storeError eErrCode = xManager->iget (
92 aPage, STORE_ATTRIB_ISFILE,
93 pPath, pName, eMode);
94 if (eErrCode != store_E_None)
95 return eErrCode;
97 if (!(aPage.attrib() & STORE_ATTRIB_ISFILE))
99 // No ISFILE in older versions (backward compatibility).
100 if (aPage.attrib() & STORE_ATTRIB_ISLINK)
101 return store_E_NotFile;
104 // ...
105 inode_holder_type xNode (aPage.get());
106 if (eMode != store_AccessReadOnly)
107 eErrCode = xManager->acquirePage (xNode->m_aDescr, store_AccessReadWrite);
108 else
109 eErrCode = xManager->acquirePage (xNode->m_aDescr, store_AccessReadOnly);
110 if (eErrCode != store_E_None)
111 return eErrCode;
113 // ...
114 m_xManager = xManager;
115 m_xNode = xNode;
116 m_bWriteable = (eMode != store_AccessReadOnly);
118 // Check for truncation.
119 if (eMode == store_AccessCreate)
121 // Truncate to zero length.
122 eErrCode = setSize(0);
124 return eErrCode;
128 * readAt.
130 storeError OStoreLockBytes::readAt (
131 sal_uInt32 nOffset,
132 void *pBuffer,
133 sal_uInt32 nBytes,
134 sal_uInt32 &rnDone)
136 rnDone = 0;
138 if (!m_xManager.is())
139 return store_E_InvalidAccess;
141 if (!pBuffer)
142 return store_E_InvalidParameter;
143 if (!nBytes)
144 return store_E_None;
146 // Acquire exclusive access.
147 osl::MutexGuard aGuard (*m_xManager);
149 // Determine data length.
150 OStoreDirectoryPageObject aPage (m_xNode.get());
152 sal_uInt32 nDataLen = aPage.dataLength();
153 if ((nOffset + nBytes) > nDataLen)
154 nBytes = nDataLen - nOffset;
156 // Read data.
157 OStoreDataPageObject aData;
158 sal_uInt8 *pData = (sal_uInt8*)pBuffer;
159 while ((0 < nBytes) && (nOffset < nDataLen))
161 // Determine 'Offset' scope.
162 inode::ChunkScope eScope = m_xNode->scope (nOffset);
163 if (eScope == inode::SCOPE_INTERNAL)
165 // Read from inode page (internal scope).
166 inode::ChunkDescriptor aDescr (
167 nOffset, m_xNode->capacity());
169 sal_uInt32 nLength = sal_uInt32(aDescr.m_nLength);
170 if(nLength > nBytes)
172 nLength = nBytes;
174 memcpy (
175 &pData[rnDone],
176 &m_xNode->m_pData[aDescr.m_nOffset],
177 nLength);
179 // Adjust counters.
180 rnDone += nLength;
181 nOffset += nLength;
182 nBytes -= nLength;
184 else
186 // Read from data page (external scope).
187 inode::ChunkDescriptor aDescr (
188 nOffset - m_xNode->capacity(), OStoreDataPageData::capacity(m_xNode->m_aDescr)); // @@@
190 sal_uInt32 nLength = sal_uInt32(aDescr.m_nLength);
191 if(nLength > nBytes)
193 nLength = nBytes;
196 storeError eErrCode = aPage.read (aDescr.m_nPage, aData, *m_xManager);
197 if (eErrCode != store_E_None)
199 if (eErrCode != store_E_NotExists)
200 return eErrCode;
202 memset (
203 &pData[rnDone],
205 nLength);
207 else
209 PageHolderObject< data > xData (aData.makeHolder<data>());
210 memcpy (
211 &pData[rnDone],
212 &xData->m_pData[aDescr.m_nOffset],
213 nLength);
216 // Adjust counters.
217 rnDone += nLength;
218 nOffset += nLength;
219 nBytes -= nLength;
223 // Done.
224 return store_E_None;
228 * writeAt.
230 storeError OStoreLockBytes::writeAt (
231 sal_uInt32 nOffset,
232 const void *pBuffer,
233 sal_uInt32 nBytes,
234 sal_uInt32 &rnDone)
236 rnDone = 0;
238 if (!m_xManager.is())
239 return store_E_InvalidAccess;
240 if (!m_bWriteable)
241 return store_E_AccessViolation;
243 if (!pBuffer)
244 return store_E_InvalidParameter;
245 if (!nBytes)
246 return store_E_None;
248 // Acquire exclusive access.
249 osl::MutexGuard aGuard (*m_xManager);
251 // Write data.
252 OStoreDirectoryPageObject aPage (m_xNode.get());
253 const sal_uInt8 *pData = (const sal_uInt8*)pBuffer;
255 storeError eErrCode = store_E_None;
256 while (nBytes > 0)
258 // Determine 'Offset' scope.
259 inode::ChunkScope eScope = m_xNode->scope (nOffset);
260 if (eScope == inode::SCOPE_INTERNAL)
262 // Write to inode page (internal scope).
263 inode::ChunkDescriptor aDescr (
264 nOffset, m_xNode->capacity());
266 sal_uInt32 nLength = sal_uInt32(aDescr.m_nLength);
267 if(nLength > nBytes)
269 nLength = nBytes;
272 memcpy (
273 &m_xNode->m_pData[aDescr.m_nOffset],
274 &pData[rnDone], nLength);
276 // Mark inode dirty.
277 aPage.touch();
279 // Adjust counters.
280 rnDone += nLength;
281 nOffset += nLength;
282 nBytes -= nLength;
284 // Adjust data length.
285 if (aPage.dataLength() < nOffset)
286 aPage.dataLength (nOffset);
288 else
290 // Write to data page (external scope).
291 OStoreDataPageObject aData;
293 inode::ChunkDescriptor aDescr (
294 nOffset - m_xNode->capacity(), OStoreDataPageData::capacity(m_xNode->m_aDescr)); // @@@
296 sal_uInt32 nLength = sal_uInt32(aDescr.m_nLength);
297 if ((aDescr.m_nOffset > 0) || (nBytes < nLength))
299 // Unaligned. Need to load/create data page.
300 // @@@ loadOrCreate()
301 eErrCode = aPage.read (aDescr.m_nPage, aData, *m_xManager);
302 if (eErrCode != store_E_None)
304 if (eErrCode != store_E_NotExists)
305 return eErrCode;
307 eErrCode = aData.construct<data>(m_xManager->allocator());
308 if (eErrCode != store_E_None)
309 return eErrCode;
313 PageHolderObject< data > xData (aData.makeHolder<data>());
314 if (!xData.is())
316 eErrCode = aData.construct<data>(m_xManager->allocator());
317 if (eErrCode != store_E_None)
318 return eErrCode;
319 xData = aData.makeHolder<data>();
322 // Modify data page.
323 if(nLength > nBytes)
325 nLength = nBytes;
327 memcpy (
328 &xData->m_pData[aDescr.m_nOffset],
329 &pData[rnDone], nLength);
331 // Save data page.
332 eErrCode = aPage.write (aDescr.m_nPage, aData, *m_xManager);
333 if (eErrCode != store_E_None)
334 return eErrCode;
336 // Adjust counters.
337 rnDone += nLength;
338 nOffset += nLength;
339 nBytes -= nLength;
341 // Adjust data length.
342 if (aPage.dataLength() < nOffset)
343 aPage.dataLength (nOffset);
347 // Check for modified inode.
348 if (aPage.dirty())
349 return m_xManager->saveObjectAt (aPage, aPage.location());
350 else
351 return store_E_None;
355 * flush.
357 storeError OStoreLockBytes::flush (void)
359 if (!m_xManager.is())
360 return store_E_InvalidAccess;
362 return m_xManager->flush();
366 * setSize.
368 storeError OStoreLockBytes::setSize (sal_uInt32 nSize)
370 if (!m_xManager.is())
371 return store_E_InvalidAccess;
372 if (!m_bWriteable)
373 return store_E_AccessViolation;
375 // Acquire exclusive access.
376 osl::MutexGuard aGuard (*m_xManager);
378 // Determine current length.
379 OStoreDirectoryPageObject aPage (m_xNode.get());
380 sal_uInt32 nDataLen = aPage.dataLength();
382 if (nSize == nDataLen)
383 return store_E_None;
385 if (nSize < nDataLen)
387 // Truncate.
388 storeError eErrCode = store_E_None;
390 // Determine 'Size' scope.
391 inode::ChunkScope eSizeScope = m_xNode->scope (nSize);
392 if (eSizeScope == inode::SCOPE_INTERNAL)
394 // Internal 'Size' scope. Determine 'Data' scope.
395 inode::ChunkScope eDataScope = m_xNode->scope (nDataLen);
396 if (eDataScope == inode::SCOPE_EXTERNAL)
398 // External 'Data' scope. Truncate all external data pages.
399 eErrCode = aPage.truncate (0, *m_xManager);
400 if (eErrCode != store_E_None)
401 return eErrCode;
404 // Truncate internal data page.
405 inode::ChunkDescriptor aDescr (nSize, m_xNode->capacity());
406 memset (
407 &(m_xNode->m_pData[aDescr.m_nOffset]),
408 0, aDescr.m_nLength);
410 else
412 // External 'Size' scope. Truncate external data pages.
413 inode::ChunkDescriptor aDescr (
414 nSize - m_xNode->capacity(), OStoreDataPageData::capacity(m_xNode->m_aDescr)); // @@@
416 sal_uInt32 nPage = aDescr.m_nPage;
417 if (aDescr.m_nOffset) nPage += 1;
419 eErrCode = aPage.truncate (nPage, *m_xManager);
420 if (eErrCode != store_E_None)
421 return eErrCode;
425 // Set (extended or truncated) size.
426 aPage.dataLength (nSize);
428 // Save modified inode.
429 return m_xManager->saveObjectAt (aPage, aPage.location());
433 * stat.
435 storeError OStoreLockBytes::stat (sal_uInt32 &rnSize)
437 rnSize = 0;
439 if (!m_xManager.is())
440 return store_E_InvalidAccess;
442 OStoreDirectoryPageObject aPage (m_xNode.get());
443 rnSize = aPage.dataLength();
444 return store_E_None;
447 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */