xref: /AOO41X/main/store/source/storlckb.cxx (revision 73d9b18ad12b526a229c2c5ca3fb0f85a41c2f42)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_store.hxx"
26 
27 #include "storlckb.hxx"
28 
29 #include "sal/types.h"
30 #include "sal/macros.h"
31 #include "rtl/string.h"
32 #include "rtl/ref.hxx"
33 #include "osl/mutex.hxx"
34 
35 #include "store/types.h"
36 #include "object.hxx"
37 
38 #include "storbase.hxx"
39 #include "stordata.hxx"
40 #include "storpage.hxx"
41 
42 using namespace store;
43 
44 /*========================================================================
45  *
46  * OStoreLockBytes implementation.
47  *
48  *======================================================================*/
49 const sal_uInt32 OStoreLockBytes::m_nTypeId = sal_uInt32(0x94190310);
50 
51 /*
52  * OStoreLockBytes.
53  */
OStoreLockBytes(void)54 OStoreLockBytes::OStoreLockBytes (void)
55     : m_xManager   (),
56       m_xNode      (),
57       m_bWriteable (false)
58 {
59 }
60 
61 /*
62  * ~OStoreLockBytes.
63  */
~OStoreLockBytes(void)64 OStoreLockBytes::~OStoreLockBytes (void)
65 {
66     if (m_xManager.is())
67     {
68         if (m_xNode.is())
69         {
70             OStorePageDescriptor aDescr (m_xNode->m_aDescr);
71             if (m_bWriteable)
72                 m_xManager->releasePage (aDescr, store_AccessReadWrite);
73             else
74                 m_xManager->releasePage (aDescr, store_AccessReadOnly);
75         }
76     }
77 }
78 
79 /*
80  * isKindOf.
81  */
isKindOf(sal_uInt32 nTypeId)82 sal_Bool SAL_CALL OStoreLockBytes::isKindOf (sal_uInt32 nTypeId)
83 {
84     return (nTypeId == m_nTypeId);
85 }
86 
87 /*
88  * create.
89  */
create(OStorePageManager * pManager,rtl_String * pPath,rtl_String * pName,storeAccessMode eMode)90 storeError OStoreLockBytes::create (
91     OStorePageManager *pManager,
92     rtl_String        *pPath,
93     rtl_String        *pName,
94     storeAccessMode    eMode)
95 {
96     rtl::Reference<OStorePageManager> xManager (pManager);
97     if (!xManager.is())
98         return store_E_InvalidAccess;
99 
100     if (!(pPath && pName))
101         return store_E_InvalidParameter;
102 
103     OStoreDirectoryPageObject aPage;
104     storeError eErrCode = xManager->iget (
105         aPage, STORE_ATTRIB_ISFILE,
106         pPath, pName, eMode);
107     if (eErrCode != store_E_None)
108         return eErrCode;
109 
110     if (!(aPage.attrib() & STORE_ATTRIB_ISFILE))
111     {
112         // No ISFILE in older versions (backward compatibility).
113         if (aPage.attrib() & STORE_ATTRIB_ISLINK)
114             return store_E_NotFile;
115     }
116 
117     // ...
118     inode_holder_type xNode (aPage.get());
119     if (eMode != store_AccessReadOnly)
120         eErrCode = xManager->acquirePage (xNode->m_aDescr, store_AccessReadWrite);
121     else
122         eErrCode = xManager->acquirePage (xNode->m_aDescr, store_AccessReadOnly);
123     if (eErrCode != store_E_None)
124         return eErrCode;
125 
126     // ...
127     m_xManager   = xManager;
128     m_xNode      = xNode;
129     m_bWriteable = (eMode != store_AccessReadOnly);
130 
131     // Check for truncation.
132     if (eMode == store_AccessCreate)
133     {
134         // Truncate to zero length.
135         eErrCode = setSize(0);
136     }
137     return eErrCode;
138 }
139 
140 /*
141  * readAt.
142  */
readAt(sal_uInt32 nOffset,void * pBuffer,sal_uInt32 nBytes,sal_uInt32 & rnDone)143 storeError OStoreLockBytes::readAt (
144     sal_uInt32  nOffset,
145     void       *pBuffer,
146     sal_uInt32  nBytes,
147     sal_uInt32 &rnDone)
148 {
149     rnDone = 0;
150 
151     if (!m_xManager.is())
152         return store_E_InvalidAccess;
153 
154     if (!pBuffer)
155         return store_E_InvalidParameter;
156     if (!nBytes)
157         return store_E_None;
158 
159     // Acquire exclusive access.
160     osl::MutexGuard aGuard (*m_xManager);
161 
162     // Determine data length.
163     OStoreDirectoryPageObject aPage (m_xNode.get());
164 
165     sal_uInt32 nDataLen = aPage.dataLength();
166     if ((nOffset + nBytes) > nDataLen)
167         nBytes = nDataLen - nOffset;
168 
169     // Read data.
170     OStoreDataPageObject aData;
171     sal_uInt8 *pData = (sal_uInt8*)pBuffer;
172     while ((0 < nBytes) && (nOffset < nDataLen))
173     {
174         // Determine 'Offset' scope.
175         inode::ChunkScope eScope = m_xNode->scope (nOffset);
176         if (eScope == inode::SCOPE_INTERNAL)
177         {
178             // Read from inode page (internal scope).
179             inode::ChunkDescriptor aDescr (
180                 nOffset, m_xNode->capacity());
181 
182             sal_uInt32 nLength = sal_uInt32(aDescr.m_nLength);
183             nLength = SAL_MIN(nLength, nBytes);
184 
185             memcpy (
186                 &pData[rnDone],
187                 &m_xNode->m_pData[aDescr.m_nOffset],
188                 nLength);
189 
190             // Adjust counters.
191             rnDone  += nLength;
192             nOffset += nLength;
193             nBytes  -= nLength;
194         }
195         else
196         {
197             // Read from data page (external scope).
198             inode::ChunkDescriptor aDescr (
199                 nOffset - m_xNode->capacity(), OStoreDataPageData::capacity(m_xNode->m_aDescr)); // @@@
200 
201             sal_uInt32 nLength = sal_uInt32(aDescr.m_nLength);
202             nLength = SAL_MIN(nLength, nBytes);
203 
204             storeError eErrCode = aPage.read (aDescr.m_nPage, aData, *m_xManager);
205             if (eErrCode != store_E_None)
206             {
207                 if (eErrCode != store_E_NotExists)
208                     return eErrCode;
209 
210                 memset (
211                     &pData[rnDone],
212                     0,
213                     nLength);
214             }
215             else
216             {
217                 PageHolderObject< data > xData (aData.makeHolder<data>());
218                 memcpy (
219                     &pData[rnDone],
220                     &xData->m_pData[aDescr.m_nOffset],
221                     nLength);
222             }
223 
224             // Adjust counters.
225             rnDone  += nLength;
226             nOffset += nLength;
227             nBytes  -= nLength;
228         }
229     }
230 
231     // Done.
232     return store_E_None;
233 }
234 
235 /*
236  * writeAt.
237  */
writeAt(sal_uInt32 nOffset,const void * pBuffer,sal_uInt32 nBytes,sal_uInt32 & rnDone)238 storeError OStoreLockBytes::writeAt (
239     sal_uInt32  nOffset,
240     const void *pBuffer,
241     sal_uInt32  nBytes,
242     sal_uInt32 &rnDone)
243 {
244     rnDone = 0;
245 
246     if (!m_xManager.is())
247         return store_E_InvalidAccess;
248     if (!m_bWriteable)
249         return store_E_AccessViolation;
250 
251     if (!pBuffer)
252         return store_E_InvalidParameter;
253     if (!nBytes)
254         return store_E_None;
255 
256     // Acquire exclusive access.
257     osl::MutexGuard aGuard (*m_xManager);
258 
259     // Write data.
260     OStoreDirectoryPageObject aPage (m_xNode.get());
261     const sal_uInt8 *pData = (const sal_uInt8*)pBuffer;
262 
263     storeError eErrCode = store_E_None;
264     while (nBytes > 0)
265     {
266         // Determine 'Offset' scope.
267         inode::ChunkScope eScope = m_xNode->scope (nOffset);
268         if (eScope == inode::SCOPE_INTERNAL)
269         {
270             // Write to inode page (internal scope).
271             inode::ChunkDescriptor aDescr (
272                 nOffset, m_xNode->capacity());
273 
274             sal_uInt32 nLength = sal_uInt32(aDescr.m_nLength);
275             nLength = SAL_MIN(nLength, nBytes);
276 
277             memcpy (
278                 &m_xNode->m_pData[aDescr.m_nOffset],
279                 &pData[rnDone], nLength);
280 
281             // Mark inode dirty.
282             aPage.touch();
283 
284             // Adjust counters.
285             rnDone  += nLength;
286             nOffset += nLength;
287             nBytes  -= nLength;
288 
289             // Adjust data length.
290             if (aPage.dataLength() < nOffset)
291                 aPage.dataLength (nOffset);
292         }
293         else
294         {
295             // Write to data page (external scope).
296             OStoreDataPageObject aData;
297 
298             inode::ChunkDescriptor aDescr (
299                 nOffset - m_xNode->capacity(), OStoreDataPageData::capacity(m_xNode->m_aDescr)); // @@@
300 
301             sal_uInt32 nLength = sal_uInt32(aDescr.m_nLength);
302             if ((aDescr.m_nOffset > 0) || (nBytes < nLength))
303             {
304                 // Unaligned. Need to load/create data page.
305 // @@@ loadOrCreate()
306                 eErrCode = aPage.read (aDescr.m_nPage, aData, *m_xManager);
307                 if (eErrCode != store_E_None)
308                 {
309                     if (eErrCode != store_E_NotExists)
310                         return eErrCode;
311 
312                     eErrCode = aData.construct<data>(m_xManager->allocator());
313                     if (eErrCode != store_E_None)
314                         return eErrCode;
315                 }
316             }
317 
318             PageHolderObject< data > xData (aData.makeHolder<data>());
319             if (!xData.is())
320             {
321                 eErrCode = aData.construct<data>(m_xManager->allocator());
322                 if (eErrCode != store_E_None)
323                     return eErrCode;
324                 xData = aData.makeHolder<data>();
325             }
326 
327             // Modify data page.
328             nLength = SAL_MIN(nLength, nBytes);
329             memcpy (
330                 &xData->m_pData[aDescr.m_nOffset],
331                 &pData[rnDone], nLength);
332 
333             // Save data page.
334             eErrCode = aPage.write (aDescr.m_nPage, aData, *m_xManager);
335             if (eErrCode != store_E_None)
336                 return eErrCode;
337 
338             // Adjust counters.
339             rnDone  += nLength;
340             nOffset += nLength;
341             nBytes  -= nLength;
342 
343             // Adjust data length.
344             if (aPage.dataLength() < nOffset)
345                 aPage.dataLength (nOffset);
346         }
347     }
348 
349     // Check for modified inode.
350     if (aPage.dirty())
351         return m_xManager->saveObjectAt (aPage, aPage.location());
352     else
353         return store_E_None;
354 }
355 
356 /*
357  * flush.
358  */
flush(void)359 storeError OStoreLockBytes::flush (void)
360 {
361     if (!m_xManager.is())
362         return store_E_InvalidAccess;
363 
364     return m_xManager->flush();
365 }
366 
367 /*
368  * setSize.
369  */
setSize(sal_uInt32 nSize)370 storeError OStoreLockBytes::setSize (sal_uInt32 nSize)
371 {
372     if (!m_xManager.is())
373         return store_E_InvalidAccess;
374     if (!m_bWriteable)
375         return store_E_AccessViolation;
376 
377     // Acquire exclusive access.
378     osl::MutexGuard aGuard (*m_xManager);
379 
380     // Determine current length.
381     OStoreDirectoryPageObject aPage (m_xNode.get());
382     sal_uInt32 nDataLen = aPage.dataLength();
383 
384     if (nSize == nDataLen)
385         return store_E_None;
386 
387     if (nSize < nDataLen)
388     {
389         // Truncate.
390         storeError eErrCode = store_E_None;
391 
392         // Determine 'Size' scope.
393         inode::ChunkScope eSizeScope = m_xNode->scope (nSize);
394         if (eSizeScope == inode::SCOPE_INTERNAL)
395         {
396             // Internal 'Size' scope. Determine 'Data' scope.
397             inode::ChunkScope eDataScope = m_xNode->scope (nDataLen);
398             if (eDataScope == inode::SCOPE_EXTERNAL)
399             {
400                 // External 'Data' scope. Truncate all external data pages.
401                 eErrCode = aPage.truncate (0, *m_xManager);
402                 if (eErrCode != store_E_None)
403                     return eErrCode;
404             }
405 
406             // Truncate internal data page.
407             inode::ChunkDescriptor aDescr (nSize, m_xNode->capacity());
408             memset (
409                 &(m_xNode->m_pData[aDescr.m_nOffset]),
410                 0, aDescr.m_nLength);
411         }
412         else
413         {
414             // External 'Size' scope. Truncate external data pages.
415             inode::ChunkDescriptor aDescr (
416                 nSize - m_xNode->capacity(), OStoreDataPageData::capacity(m_xNode->m_aDescr)); // @@@
417 
418             sal_uInt32 nPage = aDescr.m_nPage;
419             if (aDescr.m_nOffset) nPage += 1;
420 
421             eErrCode = aPage.truncate (nPage, *m_xManager);
422             if (eErrCode != store_E_None)
423                 return eErrCode;
424         }
425     }
426 
427     // Set (extended or truncated) size.
428     aPage.dataLength (nSize);
429 
430     // Save modified inode.
431     return m_xManager->saveObjectAt (aPage, aPage.location());
432 }
433 
434 /*
435  * stat.
436  */
stat(sal_uInt32 & rnSize)437 storeError OStoreLockBytes::stat (sal_uInt32 &rnSize)
438 {
439     rnSize = 0;
440 
441     if (!m_xManager.is())
442         return store_E_InvalidAccess;
443 
444     OStoreDirectoryPageObject aPage (m_xNode.get());
445     rnSize = aPage.dataLength();
446     return store_E_None;
447 }
448