1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: storlckb.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_store.hxx"
34 #include "storlckb.hxx"
36 #include "sal/types.h"
37 #include "sal/macros.h"
38 #include "rtl/string.h"
39 #include "rtl/ref.hxx"
40 #include "osl/mutex.hxx"
42 #include "store/types.h"
45 #include "storbase.hxx"
46 #include "stordata.hxx"
47 #include "storpage.hxx"
49 using namespace store
;
51 /*========================================================================
53 * OStoreLockBytes implementation.
55 *======================================================================*/
56 const sal_uInt32
OStoreLockBytes::m_nTypeId
= sal_uInt32(0x94190310);
61 OStoreLockBytes::OStoreLockBytes (void)
71 OStoreLockBytes::~OStoreLockBytes (void)
77 OStorePageDescriptor
aDescr (m_xNode
->m_aDescr
);
79 m_xManager
->releasePage (aDescr
, store_AccessReadWrite
);
81 m_xManager
->releasePage (aDescr
, store_AccessReadOnly
);
89 sal_Bool SAL_CALL
OStoreLockBytes::isKindOf (sal_uInt32 nTypeId
)
91 return (nTypeId
== m_nTypeId
);
97 storeError
OStoreLockBytes::create (
98 OStorePageManager
*pManager
,
101 storeAccessMode eMode
)
103 rtl::Reference
<OStorePageManager
> xManager (pManager
);
105 return store_E_InvalidAccess
;
107 if (!(pPath
&& pName
))
108 return store_E_InvalidParameter
;
110 OStoreDirectoryPageObject aPage
;
111 storeError eErrCode
= xManager
->iget (
112 aPage
, STORE_ATTRIB_ISFILE
,
113 pPath
, pName
, eMode
);
114 if (eErrCode
!= store_E_None
)
117 if (!(aPage
.attrib() & STORE_ATTRIB_ISFILE
))
119 // No ISFILE in older versions (backward compatibility).
120 if (aPage
.attrib() & STORE_ATTRIB_ISLINK
)
121 return store_E_NotFile
;
125 inode_holder_type
xNode (aPage
.get());
126 if (eMode
!= store_AccessReadOnly
)
127 eErrCode
= xManager
->acquirePage (xNode
->m_aDescr
, store_AccessReadWrite
);
129 eErrCode
= xManager
->acquirePage (xNode
->m_aDescr
, store_AccessReadOnly
);
130 if (eErrCode
!= store_E_None
)
134 m_xManager
= xManager
;
136 m_bWriteable
= (eMode
!= store_AccessReadOnly
);
138 // Check for truncation.
139 if (eMode
== store_AccessCreate
)
141 // Truncate to zero length.
142 eErrCode
= setSize(0);
150 storeError
OStoreLockBytes::readAt (
158 if (!m_xManager
.is())
159 return store_E_InvalidAccess
;
162 return store_E_InvalidParameter
;
166 // Acquire exclusive access.
167 osl::MutexGuard
aGuard (*m_xManager
);
169 // Determine data length.
170 OStoreDirectoryPageObject
aPage (m_xNode
.get());
172 sal_uInt32 nDataLen
= aPage
.dataLength();
173 if ((nOffset
+ nBytes
) > nDataLen
)
174 nBytes
= nDataLen
- nOffset
;
177 OStoreDataPageObject aData
;
178 sal_uInt8
*pData
= (sal_uInt8
*)pBuffer
;
179 while ((0 < nBytes
) && (nOffset
< nDataLen
))
181 // Determine 'Offset' scope.
182 inode::ChunkScope eScope
= m_xNode
->scope (nOffset
);
183 if (eScope
== inode::SCOPE_INTERNAL
)
185 // Read from inode page (internal scope).
186 inode::ChunkDescriptor
aDescr (
187 nOffset
, m_xNode
->capacity());
189 sal_uInt32 nLength
= sal_uInt32(aDescr
.m_nLength
);
190 nLength
= SAL_MIN(nLength
, nBytes
);
194 &m_xNode
->m_pData
[aDescr
.m_nOffset
],
204 // Read from data page (external scope).
205 inode::ChunkDescriptor
aDescr (
206 nOffset
- m_xNode
->capacity(), OStoreDataPageData::capacity(m_xNode
->m_aDescr
)); // @@@
208 sal_uInt32 nLength
= sal_uInt32(aDescr
.m_nLength
);
209 nLength
= SAL_MIN(nLength
, nBytes
);
211 storeError eErrCode
= aPage
.read (aDescr
.m_nPage
, aData
, *m_xManager
);
212 if (eErrCode
!= store_E_None
)
214 if (eErrCode
!= store_E_NotExists
)
224 PageHolderObject
< data
> xData (aData
.makeHolder
<data
>());
227 &xData
->m_pData
[aDescr
.m_nOffset
],
245 storeError
OStoreLockBytes::writeAt (
253 if (!m_xManager
.is())
254 return store_E_InvalidAccess
;
256 return store_E_AccessViolation
;
259 return store_E_InvalidParameter
;
263 // Acquire exclusive access.
264 osl::MutexGuard
aGuard (*m_xManager
);
267 OStoreDirectoryPageObject
aPage (m_xNode
.get());
268 const sal_uInt8
*pData
= (const sal_uInt8
*)pBuffer
;
270 storeError eErrCode
= store_E_None
;
273 // Determine 'Offset' scope.
274 inode::ChunkScope eScope
= m_xNode
->scope (nOffset
);
275 if (eScope
== inode::SCOPE_INTERNAL
)
277 // Write to inode page (internal scope).
278 inode::ChunkDescriptor
aDescr (
279 nOffset
, m_xNode
->capacity());
281 sal_uInt32 nLength
= sal_uInt32(aDescr
.m_nLength
);
282 nLength
= SAL_MIN(nLength
, nBytes
);
285 &m_xNode
->m_pData
[aDescr
.m_nOffset
],
286 &pData
[rnDone
], nLength
);
296 // Adjust data length.
297 if (aPage
.dataLength() < nOffset
)
298 aPage
.dataLength (nOffset
);
302 // Write to data page (external scope).
303 OStoreDataPageObject aData
;
305 inode::ChunkDescriptor
aDescr (
306 nOffset
- m_xNode
->capacity(), OStoreDataPageData::capacity(m_xNode
->m_aDescr
)); // @@@
308 sal_uInt32 nLength
= sal_uInt32(aDescr
.m_nLength
);
309 if ((aDescr
.m_nOffset
> 0) || (nBytes
< nLength
))
311 // Unaligned. Need to load/create data page.
312 // @@@ loadOrCreate()
313 eErrCode
= aPage
.read (aDescr
.m_nPage
, aData
, *m_xManager
);
314 if (eErrCode
!= store_E_None
)
316 if (eErrCode
!= store_E_NotExists
)
319 eErrCode
= aData
.construct
<data
>(m_xManager
->allocator());
320 if (eErrCode
!= store_E_None
)
325 PageHolderObject
< data
> xData (aData
.makeHolder
<data
>());
328 eErrCode
= aData
.construct
<data
>(m_xManager
->allocator());
329 if (eErrCode
!= store_E_None
)
331 xData
= aData
.makeHolder
<data
>();
335 nLength
= SAL_MIN(nLength
, nBytes
);
337 &xData
->m_pData
[aDescr
.m_nOffset
],
338 &pData
[rnDone
], nLength
);
341 eErrCode
= aPage
.write (aDescr
.m_nPage
, aData
, *m_xManager
);
342 if (eErrCode
!= store_E_None
)
350 // Adjust data length.
351 if (aPage
.dataLength() < nOffset
)
352 aPage
.dataLength (nOffset
);
356 // Check for modified inode.
358 return m_xManager
->saveObjectAt (aPage
, aPage
.location());
366 storeError
OStoreLockBytes::flush (void)
368 if (!m_xManager
.is())
369 return store_E_InvalidAccess
;
371 return m_xManager
->flush();
377 storeError
OStoreLockBytes::setSize (sal_uInt32 nSize
)
379 if (!m_xManager
.is())
380 return store_E_InvalidAccess
;
382 return store_E_AccessViolation
;
384 // Acquire exclusive access.
385 osl::MutexGuard
aGuard (*m_xManager
);
387 // Determine current length.
388 OStoreDirectoryPageObject
aPage (m_xNode
.get());
389 sal_uInt32 nDataLen
= aPage
.dataLength();
391 if (nSize
== nDataLen
)
394 if (nSize
< nDataLen
)
397 storeError eErrCode
= store_E_None
;
399 // Determine 'Size' scope.
400 inode::ChunkScope eSizeScope
= m_xNode
->scope (nSize
);
401 if (eSizeScope
== inode::SCOPE_INTERNAL
)
403 // Internal 'Size' scope. Determine 'Data' scope.
404 inode::ChunkScope eDataScope
= m_xNode
->scope (nDataLen
);
405 if (eDataScope
== inode::SCOPE_EXTERNAL
)
407 // External 'Data' scope. Truncate all external data pages.
408 eErrCode
= aPage
.truncate (0, *m_xManager
);
409 if (eErrCode
!= store_E_None
)
413 // Truncate internal data page.
414 inode::ChunkDescriptor
aDescr (nSize
, m_xNode
->capacity());
416 &(m_xNode
->m_pData
[aDescr
.m_nOffset
]),
417 0, aDescr
.m_nLength
);
421 // External 'Size' scope. Truncate external data pages.
422 inode::ChunkDescriptor
aDescr (
423 nSize
- m_xNode
->capacity(), OStoreDataPageData::capacity(m_xNode
->m_aDescr
)); // @@@
425 sal_uInt32 nPage
= aDescr
.m_nPage
;
426 if (aDescr
.m_nOffset
) nPage
+= 1;
428 eErrCode
= aPage
.truncate (nPage
, *m_xManager
);
429 if (eErrCode
!= store_E_None
)
434 // Set (extended or truncated) size.
435 aPage
.dataLength (nSize
);
437 // Save modified inode.
438 return m_xManager
->saveObjectAt (aPage
, aPage
.location());
444 storeError
OStoreLockBytes::stat (sal_uInt32
&rnSize
)
448 if (!m_xManager
.is())
449 return store_E_InvalidAccess
;
451 OStoreDirectoryPageObject
aPage (m_xNode
.get());
452 rnSize
= aPage
.dataLength();