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"
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);
57 OStoreLockBytes::OStoreLockBytes (void)
67 OStoreLockBytes::~OStoreLockBytes (void)
69 if (m_xManager
.is() && m_xNode
.is())
71 m_xManager
->releasePage(m_xNode
->m_aDescr
);
78 sal_Bool SAL_CALL
OStoreLockBytes::isKindOf (sal_uInt32 nTypeId
)
80 return (nTypeId
== m_nTypeId
);
86 storeError
OStoreLockBytes::create (
87 OStorePageManager
*pManager
,
90 storeAccessMode eMode
)
92 rtl::Reference
<OStorePageManager
> xManager (pManager
);
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
)
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
;
114 inode_holder_type
xNode (aPage
.get());
115 if (eMode
!= store_AccessReadOnly
)
116 eErrCode
= xManager
->acquirePage (xNode
->m_aDescr
, store_AccessReadWrite
);
118 eErrCode
= xManager
->acquirePage (xNode
->m_aDescr
, store_AccessReadOnly
);
119 if (eErrCode
!= store_E_None
)
123 m_xManager
= xManager
;
125 m_bWriteable
= (eMode
!= store_AccessReadOnly
);
127 // Check for truncation.
128 if (eMode
== store_AccessCreate
)
130 // Truncate to zero length.
131 eErrCode
= setSize(0);
139 storeError
OStoreLockBytes::readAt (
147 if (!m_xManager
.is())
148 return store_E_InvalidAccess
;
151 return store_E_InvalidParameter
;
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
;
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
);
183 &m_xNode
->m_pData
[aDescr
.m_nOffset
],
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
)
213 PageHolderObject
< data
> xData (aData
.makeHolder
<data
>());
216 &xData
->m_pData
[aDescr
.m_nOffset
],
234 storeError
OStoreLockBytes::writeAt (
242 if (!m_xManager
.is())
243 return store_E_InvalidAccess
;
245 return store_E_AccessViolation
;
248 return store_E_InvalidParameter
;
252 // Acquire exclusive access.
253 osl::MutexGuard
aGuard (*m_xManager
);
256 OStoreDirectoryPageObject
aPage (m_xNode
.get());
257 const sal_uInt8
*pData
= (const sal_uInt8
*)pBuffer
;
259 storeError eErrCode
= store_E_None
;
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
);
274 &m_xNode
->m_pData
[aDescr
.m_nOffset
],
275 &pData
[rnDone
], nLength
);
285 // Adjust data length.
286 if (aPage
.dataLength() < nOffset
)
287 aPage
.dataLength (nOffset
);
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
)
308 eErrCode
= aData
.construct
<data
>(m_xManager
->allocator());
309 if (eErrCode
!= store_E_None
)
314 PageHolderObject
< data
> xData (aData
.makeHolder
<data
>());
317 eErrCode
= aData
.construct
<data
>(m_xManager
->allocator());
318 if (eErrCode
!= store_E_None
)
320 xData
= aData
.makeHolder
<data
>();
324 nLength
= SAL_MIN(nLength
, nBytes
);
326 &xData
->m_pData
[aDescr
.m_nOffset
],
327 &pData
[rnDone
], nLength
);
330 eErrCode
= aPage
.write (aDescr
.m_nPage
, aData
, *m_xManager
);
331 if (eErrCode
!= store_E_None
)
339 // Adjust data length.
340 if (aPage
.dataLength() < nOffset
)
341 aPage
.dataLength (nOffset
);
345 // Check for modified inode.
347 return m_xManager
->saveObjectAt (aPage
, aPage
.location());
355 storeError
OStoreLockBytes::flush (void)
357 if (!m_xManager
.is())
358 return store_E_InvalidAccess
;
360 return m_xManager
->flush();
366 storeError
OStoreLockBytes::setSize (sal_uInt32 nSize
)
368 if (!m_xManager
.is())
369 return store_E_InvalidAccess
;
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
)
383 if (nSize
< nDataLen
)
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
)
402 // Truncate internal data page.
403 inode::ChunkDescriptor
aDescr (nSize
, m_xNode
->capacity());
405 &(m_xNode
->m_pData
[aDescr
.m_nOffset
]),
406 0, aDescr
.m_nLength
);
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
)
423 // Set (extended or truncated) size.
424 aPage
.dataLength (nSize
);
426 // Save modified inode.
427 return m_xManager
->saveObjectAt (aPage
, aPage
.location());
433 storeError
OStoreLockBytes::stat (sal_uInt32
&rnSize
)
437 if (!m_xManager
.is())
438 return store_E_InvalidAccess
;
440 OStoreDirectoryPageObject
aPage (m_xNode
.get());
441 rnSize
= aPage
.dataLength();
445 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */