Branch libreoffice-5-0-4
[LibreOffice.git] / store / source / storlckb.cxx
blobb6afa2d086c85facd2264c2f88e4b158a300f72a
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 .
20 #include "storlckb.hxx"
22 #include "sal/types.h"
23 #include "sal/macros.h"
24 #include "rtl/string.h"
25 #include "rtl/ref.hxx"
26 #include "osl/mutex.hxx"
28 #include "store/types.h"
29 #include "object.hxx"
31 #include "storbase.hxx"
32 #include "stordata.hxx"
33 #include "storpage.hxx"
35 using namespace store;
37 /*========================================================================
39 * OStoreLockBytes implementation.
41 *======================================================================*/
42 const sal_uInt32 OStoreLockBytes::m_nTypeId = sal_uInt32(0x94190310);
45 * OStoreLockBytes.
47 OStoreLockBytes::OStoreLockBytes()
48 : m_xManager (),
49 m_xNode (),
50 m_bWriteable (false)
55 * ~OStoreLockBytes.
57 OStoreLockBytes::~OStoreLockBytes()
59 if (m_xManager.is() && m_xNode.is())
61 m_xManager->releasePage(m_xNode->m_aDescr);
66 * isKindOf.
68 bool OStoreLockBytes::isKindOf (sal_uInt32 nTypeId)
70 return (nTypeId == m_nTypeId);
74 * create.
76 storeError OStoreLockBytes::create (
77 OStorePageManager *pManager,
78 rtl_String *pPath,
79 rtl_String *pName,
80 storeAccessMode eMode)
82 rtl::Reference<OStorePageManager> xManager (pManager);
83 if (!xManager.is())
84 return store_E_InvalidAccess;
86 if (!(pPath && pName))
87 return store_E_InvalidParameter;
89 OStoreDirectoryPageObject aPage;
90 storeError eErrCode = xManager->iget (
91 aPage, STORE_ATTRIB_ISFILE,
92 pPath, pName, eMode);
93 if (eErrCode != store_E_None)
94 return eErrCode;
96 if (!(aPage.attrib() & STORE_ATTRIB_ISFILE))
98 // No ISFILE in older versions (backward compatibility).
99 if (aPage.attrib() & STORE_ATTRIB_ISLINK)
100 return store_E_NotFile;
103 inode_holder_type xNode (aPage.get());
104 if (eMode != store_AccessReadOnly)
105 eErrCode = xManager->acquirePage (xNode->m_aDescr, store_AccessReadWrite);
106 else
107 eErrCode = xManager->acquirePage (xNode->m_aDescr, store_AccessReadOnly);
108 if (eErrCode != store_E_None)
109 return eErrCode;
111 m_xManager = xManager;
112 m_xNode = xNode;
113 m_bWriteable = (eMode != store_AccessReadOnly);
115 // Check for truncation.
116 if (eMode == store_AccessCreate)
118 // Truncate to zero length.
119 eErrCode = setSize(0);
121 return eErrCode;
125 * readAt.
127 storeError OStoreLockBytes::readAt (
128 sal_uInt32 nOffset,
129 void *pBuffer,
130 sal_uInt32 nBytes,
131 sal_uInt32 &rnDone)
133 rnDone = 0;
135 if (!m_xManager.is())
136 return store_E_InvalidAccess;
138 if (!pBuffer)
139 return store_E_InvalidParameter;
140 if (!nBytes)
141 return store_E_None;
143 // Acquire exclusive access.
144 osl::MutexGuard aGuard (*m_xManager);
146 // Determine data length.
147 OStoreDirectoryPageObject aPage (m_xNode.get());
149 sal_uInt32 nDataLen = aPage.dataLength();
150 if ((nOffset + nBytes) > nDataLen)
151 nBytes = nDataLen - nOffset;
153 // Read data.
154 OStoreDataPageObject aData;
155 sal_uInt8 *pData = static_cast<sal_uInt8*>(pBuffer);
156 while ((0 < nBytes) && (nOffset < nDataLen))
158 // Determine 'Offset' scope.
159 inode::ChunkScope eScope = m_xNode->scope (nOffset);
160 if (eScope == inode::SCOPE_INTERNAL)
162 // Read from inode page (internal scope).
163 inode::ChunkDescriptor aDescr (
164 nOffset, m_xNode->capacity());
166 sal_uInt32 nLength = sal_uInt32(aDescr.m_nLength);
167 if(nLength > nBytes)
169 nLength = nBytes;
171 memcpy (
172 &pData[rnDone],
173 &m_xNode->m_pData[aDescr.m_nOffset],
174 nLength);
176 // Adjust counters.
177 rnDone += nLength;
178 nOffset += nLength;
179 nBytes -= nLength;
181 else
183 // Read from data page (external scope).
184 inode::ChunkDescriptor aDescr (
185 nOffset - m_xNode->capacity(), OStoreDataPageData::capacity(m_xNode->m_aDescr)); // @@@
187 sal_uInt32 nLength = sal_uInt32(aDescr.m_nLength);
188 if(nLength > nBytes)
190 nLength = nBytes;
193 storeError eErrCode = aPage.read (aDescr.m_nPage, aData, *m_xManager);
194 if (eErrCode != store_E_None)
196 if (eErrCode != store_E_NotExists)
197 return eErrCode;
199 memset (
200 &pData[rnDone],
202 nLength);
204 else
206 PageHolderObject< data > xData (aData.makeHolder<data>());
207 memcpy (
208 &pData[rnDone],
209 &xData->m_pData[aDescr.m_nOffset],
210 nLength);
213 // Adjust counters.
214 rnDone += nLength;
215 nOffset += nLength;
216 nBytes -= nLength;
220 // Done.
221 return store_E_None;
225 * writeAt.
227 storeError OStoreLockBytes::writeAt (
228 sal_uInt32 nOffset,
229 const void *pBuffer,
230 sal_uInt32 nBytes,
231 sal_uInt32 &rnDone)
233 rnDone = 0;
235 if (!m_xManager.is())
236 return store_E_InvalidAccess;
237 if (!m_bWriteable)
238 return store_E_AccessViolation;
240 if (!pBuffer)
241 return store_E_InvalidParameter;
242 if (!nBytes)
243 return store_E_None;
245 // Acquire exclusive access.
246 osl::MutexGuard aGuard (*m_xManager);
248 // Write data.
249 OStoreDirectoryPageObject aPage (m_xNode.get());
250 const sal_uInt8 *pData = static_cast<const sal_uInt8*>(pBuffer);
252 storeError eErrCode = store_E_None;
253 while (nBytes > 0)
255 // Determine 'Offset' scope.
256 inode::ChunkScope eScope = m_xNode->scope (nOffset);
257 if (eScope == inode::SCOPE_INTERNAL)
259 // Write to inode page (internal scope).
260 inode::ChunkDescriptor aDescr (
261 nOffset, m_xNode->capacity());
263 sal_uInt32 nLength = sal_uInt32(aDescr.m_nLength);
264 if(nLength > nBytes)
266 nLength = nBytes;
269 memcpy (
270 &m_xNode->m_pData[aDescr.m_nOffset],
271 &pData[rnDone], nLength);
273 // Mark inode dirty.
274 aPage.touch();
276 // Adjust counters.
277 rnDone += nLength;
278 nOffset += nLength;
279 nBytes -= nLength;
281 // Adjust data length.
282 if (aPage.dataLength() < nOffset)
283 aPage.dataLength (nOffset);
285 else
287 // Write to data page (external scope).
288 OStoreDataPageObject aData;
290 inode::ChunkDescriptor aDescr (
291 nOffset - m_xNode->capacity(), OStoreDataPageData::capacity(m_xNode->m_aDescr)); // @@@
293 sal_uInt32 nLength = sal_uInt32(aDescr.m_nLength);
294 if ((aDescr.m_nOffset > 0) || (nBytes < nLength))
296 // Unaligned. Need to load/create data page.
297 // @@@ loadOrCreate()
298 eErrCode = aPage.read (aDescr.m_nPage, aData, *m_xManager);
299 if (eErrCode != store_E_None)
301 if (eErrCode != store_E_NotExists)
302 return eErrCode;
304 eErrCode = aData.construct<data>(m_xManager->allocator());
305 if (eErrCode != store_E_None)
306 return eErrCode;
310 PageHolderObject< data > xData (aData.makeHolder<data>());
311 if (!xData.is())
313 eErrCode = aData.construct<data>(m_xManager->allocator());
314 if (eErrCode != store_E_None)
315 return eErrCode;
316 xData = aData.makeHolder<data>();
319 // Modify data page.
320 if(nLength > nBytes)
322 nLength = nBytes;
324 memcpy (
325 &xData->m_pData[aDescr.m_nOffset],
326 &pData[rnDone], nLength);
328 // Save data page.
329 eErrCode = aPage.write (aDescr.m_nPage, aData, *m_xManager);
330 if (eErrCode != store_E_None)
331 return eErrCode;
333 // Adjust counters.
334 rnDone += nLength;
335 nOffset += nLength;
336 nBytes -= nLength;
338 // Adjust data length.
339 if (aPage.dataLength() < nOffset)
340 aPage.dataLength (nOffset);
344 // Check for modified inode.
345 if (aPage.dirty())
346 return m_xManager->saveObjectAt (aPage, aPage.location());
347 else
348 return store_E_None;
352 * flush.
354 storeError OStoreLockBytes::flush()
356 if (!m_xManager.is())
357 return store_E_InvalidAccess;
359 return m_xManager->flush();
363 * setSize.
365 storeError OStoreLockBytes::setSize (sal_uInt32 nSize)
367 if (!m_xManager.is())
368 return store_E_InvalidAccess;
369 if (!m_bWriteable)
370 return store_E_AccessViolation;
372 // Acquire exclusive access.
373 osl::MutexGuard aGuard (*m_xManager);
375 // Determine current length.
376 OStoreDirectoryPageObject aPage (m_xNode.get());
377 sal_uInt32 nDataLen = aPage.dataLength();
379 if (nSize == nDataLen)
380 return store_E_None;
382 if (nSize < nDataLen)
384 // Truncate.
385 storeError eErrCode = store_E_None;
387 // Determine 'Size' scope.
388 inode::ChunkScope eSizeScope = m_xNode->scope (nSize);
389 if (eSizeScope == inode::SCOPE_INTERNAL)
391 // Internal 'Size' scope. Determine 'Data' scope.
392 inode::ChunkScope eDataScope = m_xNode->scope (nDataLen);
393 if (eDataScope == inode::SCOPE_EXTERNAL)
395 // External 'Data' scope. Truncate all external data pages.
396 eErrCode = aPage.truncate (0, *m_xManager);
397 if (eErrCode != store_E_None)
398 return eErrCode;
401 // Truncate internal data page.
402 inode::ChunkDescriptor aDescr (nSize, m_xNode->capacity());
403 memset (
404 &(m_xNode->m_pData[aDescr.m_nOffset]),
405 0, aDescr.m_nLength);
407 else
409 // External 'Size' scope. Truncate external data pages.
410 inode::ChunkDescriptor aDescr (
411 nSize - m_xNode->capacity(), OStoreDataPageData::capacity(m_xNode->m_aDescr)); // @@@
413 sal_uInt32 nPage = aDescr.m_nPage;
414 if (aDescr.m_nOffset) nPage += 1;
416 eErrCode = aPage.truncate (nPage, *m_xManager);
417 if (eErrCode != store_E_None)
418 return eErrCode;
422 // Set (extended or truncated) size.
423 aPage.dataLength (nSize);
425 // Save modified inode.
426 return m_xManager->saveObjectAt (aPage, aPage.location());
430 * stat.
432 storeError OStoreLockBytes::stat (sal_uInt32 &rnSize)
434 rnSize = 0;
436 if (!m_xManager.is())
437 return store_E_InvalidAccess;
439 OStoreDirectoryPageObject aPage (m_xNode.get());
440 rnSize = aPage.dataLength();
441 return store_E_None;
444 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */