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 .
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"
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);
48 OStoreLockBytes::OStoreLockBytes (void)
58 OStoreLockBytes::~OStoreLockBytes (void)
60 if (m_xManager
.is() && m_xNode
.is())
62 m_xManager
->releasePage(m_xNode
->m_aDescr
);
69 sal_Bool SAL_CALL
OStoreLockBytes::isKindOf (sal_uInt32 nTypeId
)
71 return (nTypeId
== m_nTypeId
);
77 storeError
OStoreLockBytes::create (
78 OStorePageManager
*pManager
,
81 storeAccessMode eMode
)
83 rtl::Reference
<OStorePageManager
> xManager (pManager
);
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
,
94 if (eErrCode
!= store_E_None
)
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
;
105 inode_holder_type
xNode (aPage
.get());
106 if (eMode
!= store_AccessReadOnly
)
107 eErrCode
= xManager
->acquirePage (xNode
->m_aDescr
, store_AccessReadWrite
);
109 eErrCode
= xManager
->acquirePage (xNode
->m_aDescr
, store_AccessReadOnly
);
110 if (eErrCode
!= store_E_None
)
114 m_xManager
= xManager
;
116 m_bWriteable
= (eMode
!= store_AccessReadOnly
);
118 // Check for truncation.
119 if (eMode
== store_AccessCreate
)
121 // Truncate to zero length.
122 eErrCode
= setSize(0);
130 storeError
OStoreLockBytes::readAt (
138 if (!m_xManager
.is())
139 return store_E_InvalidAccess
;
142 return store_E_InvalidParameter
;
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
;
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
);
176 &m_xNode
->m_pData
[aDescr
.m_nOffset
],
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
);
196 storeError eErrCode
= aPage
.read (aDescr
.m_nPage
, aData
, *m_xManager
);
197 if (eErrCode
!= store_E_None
)
199 if (eErrCode
!= store_E_NotExists
)
209 PageHolderObject
< data
> xData (aData
.makeHolder
<data
>());
212 &xData
->m_pData
[aDescr
.m_nOffset
],
230 storeError
OStoreLockBytes::writeAt (
238 if (!m_xManager
.is())
239 return store_E_InvalidAccess
;
241 return store_E_AccessViolation
;
244 return store_E_InvalidParameter
;
248 // Acquire exclusive access.
249 osl::MutexGuard
aGuard (*m_xManager
);
252 OStoreDirectoryPageObject
aPage (m_xNode
.get());
253 const sal_uInt8
*pData
= (const sal_uInt8
*)pBuffer
;
255 storeError eErrCode
= store_E_None
;
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
);
273 &m_xNode
->m_pData
[aDescr
.m_nOffset
],
274 &pData
[rnDone
], nLength
);
284 // Adjust data length.
285 if (aPage
.dataLength() < nOffset
)
286 aPage
.dataLength (nOffset
);
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
)
307 eErrCode
= aData
.construct
<data
>(m_xManager
->allocator());
308 if (eErrCode
!= store_E_None
)
313 PageHolderObject
< data
> xData (aData
.makeHolder
<data
>());
316 eErrCode
= aData
.construct
<data
>(m_xManager
->allocator());
317 if (eErrCode
!= store_E_None
)
319 xData
= aData
.makeHolder
<data
>();
328 &xData
->m_pData
[aDescr
.m_nOffset
],
329 &pData
[rnDone
], nLength
);
332 eErrCode
= aPage
.write (aDescr
.m_nPage
, aData
, *m_xManager
);
333 if (eErrCode
!= store_E_None
)
341 // Adjust data length.
342 if (aPage
.dataLength() < nOffset
)
343 aPage
.dataLength (nOffset
);
347 // Check for modified inode.
349 return m_xManager
->saveObjectAt (aPage
, aPage
.location());
357 storeError
OStoreLockBytes::flush (void)
359 if (!m_xManager
.is())
360 return store_E_InvalidAccess
;
362 return m_xManager
->flush();
368 storeError
OStoreLockBytes::setSize (sal_uInt32 nSize
)
370 if (!m_xManager
.is())
371 return store_E_InvalidAccess
;
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
)
385 if (nSize
< nDataLen
)
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
)
404 // Truncate internal data page.
405 inode::ChunkDescriptor
aDescr (nSize
, m_xNode
->capacity());
407 &(m_xNode
->m_pData
[aDescr
.m_nOffset
]),
408 0, aDescr
.m_nLength
);
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
)
425 // Set (extended or truncated) size.
426 aPage
.dataLength (nSize
);
428 // Save modified inode.
429 return m_xManager
->saveObjectAt (aPage
, aPage
.location());
435 storeError
OStoreLockBytes::stat (sal_uInt32
&rnSize
)
439 if (!m_xManager
.is())
440 return store_E_InvalidAccess
;
442 OStoreDirectoryPageObject
aPage (m_xNode
.get());
443 rnSize
= aPage
.dataLength();
447 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */