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 <rtl/string.h>
24 #include <rtl/ref.hxx>
25 #include <osl/mutex.hxx>
27 #include <store/types.h>
29 #include "storbase.hxx"
30 #include "stordata.hxx"
31 #include "storpage.hxx"
33 using namespace store
;
35 /*========================================================================
37 * OStoreLockBytes implementation.
39 *======================================================================*/
40 const sal_uInt32
OStoreLockBytes::m_nTypeId(0x94190310);
45 OStoreLockBytes::OStoreLockBytes()
55 OStoreLockBytes::~OStoreLockBytes()
57 if (m_xManager
.is() && m_xNode
.is())
59 m_xManager
->releasePage(m_xNode
->m_aDescr
);
66 bool OStoreLockBytes::isKindOf (sal_uInt32 nTypeId
)
68 return (nTypeId
== m_nTypeId
);
74 storeError
OStoreLockBytes::create (
75 OStorePageManager
*pManager
,
76 rtl_String
const *pPath
,
77 rtl_String
const *pName
,
78 storeAccessMode eMode
)
80 rtl::Reference
<OStorePageManager
> xManager (pManager
);
82 return store_E_InvalidAccess
;
84 if (!(pPath
&& pName
))
85 return store_E_InvalidParameter
;
87 OStoreDirectoryPageObject aPage
;
88 storeError eErrCode
= xManager
->iget (
89 aPage
, STORE_ATTRIB_ISFILE
,
91 if (eErrCode
!= store_E_None
)
94 if (!(aPage
.attrib() & STORE_ATTRIB_ISFILE
))
96 // No ISFILE in older versions (backward compatibility).
97 if (aPage
.attrib() & STORE_ATTRIB_ISLINK
)
98 return store_E_NotFile
;
101 inode_holder_type
xNode (aPage
.get());
102 if (eMode
!= storeAccessMode::ReadOnly
)
103 eErrCode
= xManager
->acquirePage (xNode
->m_aDescr
, storeAccessMode::ReadWrite
);
105 eErrCode
= xManager
->acquirePage (xNode
->m_aDescr
, storeAccessMode::ReadOnly
);
106 if (eErrCode
!= store_E_None
)
109 m_xManager
= xManager
;
111 m_bWriteable
= (eMode
!= storeAccessMode::ReadOnly
);
113 // Check for truncation.
114 if (eMode
== storeAccessMode::Create
)
116 // Truncate to zero length.
117 eErrCode
= setSize(0);
125 storeError
OStoreLockBytes::readAt (
133 if (!m_xManager
.is())
134 return store_E_InvalidAccess
;
137 return store_E_InvalidParameter
;
141 // Acquire exclusive access.
142 osl::MutexGuard
aGuard (*m_xManager
);
144 // Determine data length.
145 OStoreDirectoryPageObject
aPage (m_xNode
.get());
147 sal_uInt32 nDataLen
= aPage
.dataLength();
148 if ((nOffset
+ nBytes
) > nDataLen
)
149 nBytes
= nDataLen
- nOffset
;
152 OStoreDataPageObject aData
;
153 sal_uInt8
*pData
= static_cast<sal_uInt8
*>(pBuffer
);
154 while ((0 < nBytes
) && (nOffset
< nDataLen
))
156 // Determine 'Offset' scope.
157 inode::ChunkScope eScope
= m_xNode
->scope (nOffset
);
158 if (eScope
== inode::SCOPE_INTERNAL
)
160 // Read from inode page (internal scope).
161 inode::ChunkDescriptor
aDescr (
162 nOffset
, m_xNode
->capacity());
164 sal_uInt32 nLength
= sal_uInt32(aDescr
.m_nLength
);
171 &m_xNode
->m_pData
[aDescr
.m_nOffset
],
181 // Read from data page (external scope).
182 inode::ChunkDescriptor
aDescr (
183 nOffset
- m_xNode
->capacity(), OStoreDataPageData::capacity(m_xNode
->m_aDescr
)); // @@@
185 sal_uInt32 nLength
= sal_uInt32(aDescr
.m_nLength
);
191 storeError eErrCode
= aPage
.read (aDescr
.m_nPage
, aData
, *m_xManager
);
192 if (eErrCode
!= store_E_None
)
194 if (eErrCode
!= store_E_NotExists
)
204 PageHolderObject
< data
> xData (aData
.makeHolder
<data
>());
207 &xData
->m_pData
[aDescr
.m_nOffset
],
225 storeError
OStoreLockBytes::writeAt (
233 if (!m_xManager
.is())
234 return store_E_InvalidAccess
;
236 return store_E_AccessViolation
;
239 return store_E_InvalidParameter
;
243 // Acquire exclusive access.
244 osl::MutexGuard
aGuard (*m_xManager
);
247 OStoreDirectoryPageObject
aPage (m_xNode
.get());
248 const sal_uInt8
*pData
= static_cast<const sal_uInt8
*>(pBuffer
);
250 storeError eErrCode
= store_E_None
;
253 // Determine 'Offset' scope.
254 inode::ChunkScope eScope
= m_xNode
->scope (nOffset
);
255 if (eScope
== inode::SCOPE_INTERNAL
)
257 // Write to inode page (internal scope).
258 inode::ChunkDescriptor
aDescr (
259 nOffset
, m_xNode
->capacity());
261 sal_uInt32 nLength
= sal_uInt32(aDescr
.m_nLength
);
268 &m_xNode
->m_pData
[aDescr
.m_nOffset
],
269 &pData
[rnDone
], nLength
);
279 // Adjust data length.
280 if (aPage
.dataLength() < nOffset
)
281 aPage
.dataLength (nOffset
);
285 // Write to data page (external scope).
286 OStoreDataPageObject aData
;
288 inode::ChunkDescriptor
aDescr (
289 nOffset
- m_xNode
->capacity(), OStoreDataPageData::capacity(m_xNode
->m_aDescr
)); // @@@
291 sal_uInt32 nLength
= sal_uInt32(aDescr
.m_nLength
);
292 if ((aDescr
.m_nOffset
> 0) || (nBytes
< nLength
))
294 // Unaligned. Need to load/create data page.
295 // @@@ loadOrCreate()
296 eErrCode
= aPage
.read (aDescr
.m_nPage
, aData
, *m_xManager
);
297 if (eErrCode
!= store_E_None
)
299 if (eErrCode
!= store_E_NotExists
)
302 eErrCode
= aData
.construct
<data
>(m_xManager
->allocator());
303 if (eErrCode
!= store_E_None
)
308 PageHolderObject
< data
> xData (aData
.makeHolder
<data
>());
311 eErrCode
= aData
.construct
<data
>(m_xManager
->allocator());
312 if (eErrCode
!= store_E_None
)
314 xData
= aData
.makeHolder
<data
>();
323 &xData
->m_pData
[aDescr
.m_nOffset
],
324 &pData
[rnDone
], nLength
);
327 eErrCode
= aPage
.write (aDescr
.m_nPage
, aData
, *m_xManager
);
328 if (eErrCode
!= store_E_None
)
336 // Adjust data length.
337 if (aPage
.dataLength() < nOffset
)
338 aPage
.dataLength (nOffset
);
342 // Check for modified inode.
344 return m_xManager
->saveObjectAt (aPage
, aPage
.location());
352 storeError
OStoreLockBytes::setSize (sal_uInt32 nSize
)
354 if (!m_xManager
.is())
355 return store_E_InvalidAccess
;
357 return store_E_AccessViolation
;
359 // Acquire exclusive access.
360 osl::MutexGuard
aGuard (*m_xManager
);
362 // Determine current length.
363 OStoreDirectoryPageObject
aPage (m_xNode
.get());
364 sal_uInt32 nDataLen
= aPage
.dataLength();
366 if (nSize
== nDataLen
)
369 if (nSize
< nDataLen
)
372 storeError eErrCode
= store_E_None
;
374 // Determine 'Size' scope.
375 inode::ChunkScope eSizeScope
= m_xNode
->scope (nSize
);
376 if (eSizeScope
== inode::SCOPE_INTERNAL
)
378 // Internal 'Size' scope. Determine 'Data' scope.
379 inode::ChunkScope eDataScope
= m_xNode
->scope (nDataLen
);
380 if (eDataScope
== inode::SCOPE_EXTERNAL
)
382 // External 'Data' scope. Truncate all external data pages.
383 eErrCode
= aPage
.truncate (0, *m_xManager
);
384 if (eErrCode
!= store_E_None
)
388 // Truncate internal data page.
389 inode::ChunkDescriptor
aDescr (nSize
, m_xNode
->capacity());
391 &(m_xNode
->m_pData
[aDescr
.m_nOffset
]),
392 0, aDescr
.m_nLength
);
396 // External 'Size' scope. Truncate external data pages.
397 inode::ChunkDescriptor
aDescr (
398 nSize
- m_xNode
->capacity(), OStoreDataPageData::capacity(m_xNode
->m_aDescr
)); // @@@
400 sal_uInt32 nPage
= aDescr
.m_nPage
;
401 if (aDescr
.m_nOffset
) nPage
+= 1;
403 eErrCode
= aPage
.truncate (nPage
, *m_xManager
);
404 if (eErrCode
!= store_E_None
)
409 // Set (extended or truncated) size.
410 aPage
.dataLength (nSize
);
412 // Save modified inode.
413 return m_xManager
->saveObjectAt (aPage
, aPage
.location());
416 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */