Version 3.6.0.4, tag libreoffice-3.6.0.4
[LibreOffice.git] / store / source / storlckb.cxx
blob9dca65e7cb7b926c19095598fcab4b895b1a8532
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #include "storlckb.hxx"
32 #include "sal/types.h"
33 #include "sal/macros.h"
34 #include "rtl/string.h"
35 #include "rtl/ref.hxx"
36 #include "osl/mutex.hxx"
38 #include "store/types.h"
39 #include "object.hxx"
41 #include "storbase.hxx"
42 #include "stordata.hxx"
43 #include "storpage.hxx"
45 using namespace store;
47 /*========================================================================
49 * OStoreLockBytes implementation.
51 *======================================================================*/
52 const sal_uInt32 OStoreLockBytes::m_nTypeId = sal_uInt32(0x94190310);
55 * OStoreLockBytes.
57 OStoreLockBytes::OStoreLockBytes (void)
58 : m_xManager (),
59 m_xNode (),
60 m_bWriteable (false)
65 * ~OStoreLockBytes.
67 OStoreLockBytes::~OStoreLockBytes (void)
69 if (m_xManager.is() && m_xNode.is())
71 m_xManager->releasePage(m_xNode->m_aDescr);
76 * isKindOf.
78 sal_Bool SAL_CALL OStoreLockBytes::isKindOf (sal_uInt32 nTypeId)
80 return (nTypeId == m_nTypeId);
84 * create.
86 storeError OStoreLockBytes::create (
87 OStorePageManager *pManager,
88 rtl_String *pPath,
89 rtl_String *pName,
90 storeAccessMode eMode)
92 rtl::Reference<OStorePageManager> xManager (pManager);
93 if (!xManager.is())
94 return store_E_InvalidAccess;
96 if (!(pPath && pName))
97 return store_E_InvalidParameter;
99 OStoreDirectoryPageObject aPage;
100 storeError eErrCode = xManager->iget (
101 aPage, STORE_ATTRIB_ISFILE,
102 pPath, pName, eMode);
103 if (eErrCode != store_E_None)
104 return eErrCode;
106 if (!(aPage.attrib() & STORE_ATTRIB_ISFILE))
108 // No ISFILE in older versions (backward compatibility).
109 if (aPage.attrib() & STORE_ATTRIB_ISLINK)
110 return store_E_NotFile;
113 // ...
114 inode_holder_type xNode (aPage.get());
115 if (eMode != store_AccessReadOnly)
116 eErrCode = xManager->acquirePage (xNode->m_aDescr, store_AccessReadWrite);
117 else
118 eErrCode = xManager->acquirePage (xNode->m_aDescr, store_AccessReadOnly);
119 if (eErrCode != store_E_None)
120 return eErrCode;
122 // ...
123 m_xManager = xManager;
124 m_xNode = xNode;
125 m_bWriteable = (eMode != store_AccessReadOnly);
127 // Check for truncation.
128 if (eMode == store_AccessCreate)
130 // Truncate to zero length.
131 eErrCode = setSize(0);
133 return eErrCode;
137 * readAt.
139 storeError OStoreLockBytes::readAt (
140 sal_uInt32 nOffset,
141 void *pBuffer,
142 sal_uInt32 nBytes,
143 sal_uInt32 &rnDone)
145 rnDone = 0;
147 if (!m_xManager.is())
148 return store_E_InvalidAccess;
150 if (!pBuffer)
151 return store_E_InvalidParameter;
152 if (!nBytes)
153 return store_E_None;
155 // Acquire exclusive access.
156 osl::MutexGuard aGuard (*m_xManager);
158 // Determine data length.
159 OStoreDirectoryPageObject aPage (m_xNode.get());
161 sal_uInt32 nDataLen = aPage.dataLength();
162 if ((nOffset + nBytes) > nDataLen)
163 nBytes = nDataLen - nOffset;
165 // Read data.
166 OStoreDataPageObject aData;
167 sal_uInt8 *pData = (sal_uInt8*)pBuffer;
168 while ((0 < nBytes) && (nOffset < nDataLen))
170 // Determine 'Offset' scope.
171 inode::ChunkScope eScope = m_xNode->scope (nOffset);
172 if (eScope == inode::SCOPE_INTERNAL)
174 // Read from inode page (internal scope).
175 inode::ChunkDescriptor aDescr (
176 nOffset, m_xNode->capacity());
178 sal_uInt32 nLength = sal_uInt32(aDescr.m_nLength);
179 nLength = SAL_MIN(nLength, nBytes);
181 memcpy (
182 &pData[rnDone],
183 &m_xNode->m_pData[aDescr.m_nOffset],
184 nLength);
186 // Adjust counters.
187 rnDone += nLength;
188 nOffset += nLength;
189 nBytes -= nLength;
191 else
193 // Read from data page (external scope).
194 inode::ChunkDescriptor aDescr (
195 nOffset - m_xNode->capacity(), OStoreDataPageData::capacity(m_xNode->m_aDescr)); // @@@
197 sal_uInt32 nLength = sal_uInt32(aDescr.m_nLength);
198 nLength = SAL_MIN(nLength, nBytes);
200 storeError eErrCode = aPage.read (aDescr.m_nPage, aData, *m_xManager);
201 if (eErrCode != store_E_None)
203 if (eErrCode != store_E_NotExists)
204 return eErrCode;
206 memset (
207 &pData[rnDone],
209 nLength);
211 else
213 PageHolderObject< data > xData (aData.makeHolder<data>());
214 memcpy (
215 &pData[rnDone],
216 &xData->m_pData[aDescr.m_nOffset],
217 nLength);
220 // Adjust counters.
221 rnDone += nLength;
222 nOffset += nLength;
223 nBytes -= nLength;
227 // Done.
228 return store_E_None;
232 * writeAt.
234 storeError OStoreLockBytes::writeAt (
235 sal_uInt32 nOffset,
236 const void *pBuffer,
237 sal_uInt32 nBytes,
238 sal_uInt32 &rnDone)
240 rnDone = 0;
242 if (!m_xManager.is())
243 return store_E_InvalidAccess;
244 if (!m_bWriteable)
245 return store_E_AccessViolation;
247 if (!pBuffer)
248 return store_E_InvalidParameter;
249 if (!nBytes)
250 return store_E_None;
252 // Acquire exclusive access.
253 osl::MutexGuard aGuard (*m_xManager);
255 // Write data.
256 OStoreDirectoryPageObject aPage (m_xNode.get());
257 const sal_uInt8 *pData = (const sal_uInt8*)pBuffer;
259 storeError eErrCode = store_E_None;
260 while (nBytes > 0)
262 // Determine 'Offset' scope.
263 inode::ChunkScope eScope = m_xNode->scope (nOffset);
264 if (eScope == inode::SCOPE_INTERNAL)
266 // Write to inode page (internal scope).
267 inode::ChunkDescriptor aDescr (
268 nOffset, m_xNode->capacity());
270 sal_uInt32 nLength = sal_uInt32(aDescr.m_nLength);
271 nLength = SAL_MIN(nLength, nBytes);
273 memcpy (
274 &m_xNode->m_pData[aDescr.m_nOffset],
275 &pData[rnDone], nLength);
277 // Mark inode dirty.
278 aPage.touch();
280 // Adjust counters.
281 rnDone += nLength;
282 nOffset += nLength;
283 nBytes -= nLength;
285 // Adjust data length.
286 if (aPage.dataLength() < nOffset)
287 aPage.dataLength (nOffset);
289 else
291 // Write to data page (external scope).
292 OStoreDataPageObject aData;
294 inode::ChunkDescriptor aDescr (
295 nOffset - m_xNode->capacity(), OStoreDataPageData::capacity(m_xNode->m_aDescr)); // @@@
297 sal_uInt32 nLength = sal_uInt32(aDescr.m_nLength);
298 if ((aDescr.m_nOffset > 0) || (nBytes < nLength))
300 // Unaligned. Need to load/create data page.
301 // @@@ loadOrCreate()
302 eErrCode = aPage.read (aDescr.m_nPage, aData, *m_xManager);
303 if (eErrCode != store_E_None)
305 if (eErrCode != store_E_NotExists)
306 return eErrCode;
308 eErrCode = aData.construct<data>(m_xManager->allocator());
309 if (eErrCode != store_E_None)
310 return eErrCode;
314 PageHolderObject< data > xData (aData.makeHolder<data>());
315 if (!xData.is())
317 eErrCode = aData.construct<data>(m_xManager->allocator());
318 if (eErrCode != store_E_None)
319 return eErrCode;
320 xData = aData.makeHolder<data>();
323 // Modify data page.
324 nLength = SAL_MIN(nLength, nBytes);
325 memcpy (
326 &xData->m_pData[aDescr.m_nOffset],
327 &pData[rnDone], nLength);
329 // Save data page.
330 eErrCode = aPage.write (aDescr.m_nPage, aData, *m_xManager);
331 if (eErrCode != store_E_None)
332 return eErrCode;
334 // Adjust counters.
335 rnDone += nLength;
336 nOffset += nLength;
337 nBytes -= nLength;
339 // Adjust data length.
340 if (aPage.dataLength() < nOffset)
341 aPage.dataLength (nOffset);
345 // Check for modified inode.
346 if (aPage.dirty())
347 return m_xManager->saveObjectAt (aPage, aPage.location());
348 else
349 return store_E_None;
353 * flush.
355 storeError OStoreLockBytes::flush (void)
357 if (!m_xManager.is())
358 return store_E_InvalidAccess;
360 return m_xManager->flush();
364 * setSize.
366 storeError OStoreLockBytes::setSize (sal_uInt32 nSize)
368 if (!m_xManager.is())
369 return store_E_InvalidAccess;
370 if (!m_bWriteable)
371 return store_E_AccessViolation;
373 // Acquire exclusive access.
374 osl::MutexGuard aGuard (*m_xManager);
376 // Determine current length.
377 OStoreDirectoryPageObject aPage (m_xNode.get());
378 sal_uInt32 nDataLen = aPage.dataLength();
380 if (nSize == nDataLen)
381 return store_E_None;
383 if (nSize < nDataLen)
385 // Truncate.
386 storeError eErrCode = store_E_None;
388 // Determine 'Size' scope.
389 inode::ChunkScope eSizeScope = m_xNode->scope (nSize);
390 if (eSizeScope == inode::SCOPE_INTERNAL)
392 // Internal 'Size' scope. Determine 'Data' scope.
393 inode::ChunkScope eDataScope = m_xNode->scope (nDataLen);
394 if (eDataScope == inode::SCOPE_EXTERNAL)
396 // External 'Data' scope. Truncate all external data pages.
397 eErrCode = aPage.truncate (0, *m_xManager);
398 if (eErrCode != store_E_None)
399 return eErrCode;
402 // Truncate internal data page.
403 inode::ChunkDescriptor aDescr (nSize, m_xNode->capacity());
404 memset (
405 &(m_xNode->m_pData[aDescr.m_nOffset]),
406 0, aDescr.m_nLength);
408 else
410 // External 'Size' scope. Truncate external data pages.
411 inode::ChunkDescriptor aDescr (
412 nSize - m_xNode->capacity(), OStoreDataPageData::capacity(m_xNode->m_aDescr)); // @@@
414 sal_uInt32 nPage = aDescr.m_nPage;
415 if (aDescr.m_nOffset) nPage += 1;
417 eErrCode = aPage.truncate (nPage, *m_xManager);
418 if (eErrCode != store_E_None)
419 return eErrCode;
423 // Set (extended or truncated) size.
424 aPage.dataLength (nSize);
426 // Save modified inode.
427 return m_xManager->saveObjectAt (aPage, aPage.location());
431 * stat.
433 storeError OStoreLockBytes::stat (sal_uInt32 &rnSize)
435 rnSize = 0;
437 if (!m_xManager.is())
438 return store_E_InvalidAccess;
440 OStoreDirectoryPageObject aPage (m_xNode.get());
441 rnSize = aPage.dataLength();
442 return store_E_None;
445 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */