1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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"
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);
47 OStoreLockBytes::OStoreLockBytes()
57 OStoreLockBytes::~OStoreLockBytes()
59 if (m_xManager
.is() && m_xNode
.is())
61 m_xManager
->releasePage(m_xNode
->m_aDescr
);
68 bool OStoreLockBytes::isKindOf (sal_uInt32 nTypeId
)
70 return (nTypeId
== m_nTypeId
);
76 storeError
OStoreLockBytes::create (
77 OStorePageManager
*pManager
,
80 storeAccessMode eMode
)
82 rtl::Reference
<OStorePageManager
> xManager (pManager
);
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
,
93 if (eErrCode
!= store_E_None
)
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
);
107 eErrCode
= xManager
->acquirePage (xNode
->m_aDescr
, store_AccessReadOnly
);
108 if (eErrCode
!= store_E_None
)
111 m_xManager
= xManager
;
113 m_bWriteable
= (eMode
!= store_AccessReadOnly
);
115 // Check for truncation.
116 if (eMode
== store_AccessCreate
)
118 // Truncate to zero length.
119 eErrCode
= setSize(0);
127 storeError
OStoreLockBytes::readAt (
135 if (!m_xManager
.is())
136 return store_E_InvalidAccess
;
139 return store_E_InvalidParameter
;
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
;
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
);
173 &m_xNode
->m_pData
[aDescr
.m_nOffset
],
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
);
193 storeError eErrCode
= aPage
.read (aDescr
.m_nPage
, aData
, *m_xManager
);
194 if (eErrCode
!= store_E_None
)
196 if (eErrCode
!= store_E_NotExists
)
206 PageHolderObject
< data
> xData (aData
.makeHolder
<data
>());
209 &xData
->m_pData
[aDescr
.m_nOffset
],
227 storeError
OStoreLockBytes::writeAt (
235 if (!m_xManager
.is())
236 return store_E_InvalidAccess
;
238 return store_E_AccessViolation
;
241 return store_E_InvalidParameter
;
245 // Acquire exclusive access.
246 osl::MutexGuard
aGuard (*m_xManager
);
249 OStoreDirectoryPageObject
aPage (m_xNode
.get());
250 const sal_uInt8
*pData
= static_cast<const sal_uInt8
*>(pBuffer
);
252 storeError eErrCode
= store_E_None
;
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
);
270 &m_xNode
->m_pData
[aDescr
.m_nOffset
],
271 &pData
[rnDone
], nLength
);
281 // Adjust data length.
282 if (aPage
.dataLength() < nOffset
)
283 aPage
.dataLength (nOffset
);
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
)
304 eErrCode
= aData
.construct
<data
>(m_xManager
->allocator());
305 if (eErrCode
!= store_E_None
)
310 PageHolderObject
< data
> xData (aData
.makeHolder
<data
>());
313 eErrCode
= aData
.construct
<data
>(m_xManager
->allocator());
314 if (eErrCode
!= store_E_None
)
316 xData
= aData
.makeHolder
<data
>();
325 &xData
->m_pData
[aDescr
.m_nOffset
],
326 &pData
[rnDone
], nLength
);
329 eErrCode
= aPage
.write (aDescr
.m_nPage
, aData
, *m_xManager
);
330 if (eErrCode
!= store_E_None
)
338 // Adjust data length.
339 if (aPage
.dataLength() < nOffset
)
340 aPage
.dataLength (nOffset
);
344 // Check for modified inode.
346 return m_xManager
->saveObjectAt (aPage
, aPage
.location());
354 storeError
OStoreLockBytes::flush()
356 if (!m_xManager
.is())
357 return store_E_InvalidAccess
;
359 return m_xManager
->flush();
365 storeError
OStoreLockBytes::setSize (sal_uInt32 nSize
)
367 if (!m_xManager
.is())
368 return store_E_InvalidAccess
;
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
)
382 if (nSize
< nDataLen
)
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
)
401 // Truncate internal data page.
402 inode::ChunkDescriptor
aDescr (nSize
, m_xNode
->capacity());
404 &(m_xNode
->m_pData
[aDescr
.m_nOffset
]),
405 0, aDescr
.m_nLength
);
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
)
422 // Set (extended or truncated) size.
423 aPage
.dataLength (nSize
);
425 // Save modified inode.
426 return m_xManager
->saveObjectAt (aPage
, aPage
.location());
432 storeError
OStoreLockBytes::stat (sal_uInt32
&rnSize
)
436 if (!m_xManager
.is())
437 return store_E_InvalidAccess
;
439 OStoreDirectoryPageObject
aPage (m_xNode
.get());
440 rnSize
= aPage
.dataLength();
444 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */