Version 3.6.0.4, tag libreoffice-3.6.0.4
[LibreOffice.git] / store / source / lockbyte.cxx
blob7c02c22b0e01c05c03cbc558d1c12b1e15f7a678
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 "lockbyte.hxx"
32 #include "sal/types.h"
33 #include "osl/diagnose.h"
34 #include "osl/file.h"
35 #include "osl/process.h"
36 #include "rtl/alloc.h"
37 #include "rtl/ustring.hxx"
39 #include "object.hxx"
40 #include "storbase.hxx"
42 #ifndef INCLUDED_STRING_H
43 #include <string.h>
44 #define INCLUDED_STRING_H
45 #endif
47 using namespace store;
49 /*========================================================================
51 * ILockBytes (non-virtual interface) implementation.
53 *======================================================================*/
55 storeError ILockBytes::initialize (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize)
57 OSL_PRECOND((STORE_MINIMUM_PAGESIZE <= nPageSize) && (nPageSize <= STORE_MAXIMUM_PAGESIZE), "invalid PageSize");
58 return initialize_Impl (rxAllocator, nPageSize);
61 storeError ILockBytes::readPageAt (PageHolder & rPage, sal_uInt32 nOffset)
63 OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::ILockBytes::readPageAt(): invalid Offset");
64 if (nOffset == STORE_PAGE_NULL)
65 return store_E_CantSeek;
67 return readPageAt_Impl (rPage, nOffset);
70 storeError ILockBytes::writePageAt (PageHolder const & rPage, sal_uInt32 nOffset)
72 // [SECURITY:ValInput]
73 PageData const * pagedata = rPage.get();
74 OSL_PRECOND(!(pagedata == 0), "store::ILockBytes::writePageAt(): invalid Page");
75 if (pagedata == 0)
76 return store_E_InvalidParameter;
78 sal_uInt32 const offset = pagedata->location();
79 OSL_PRECOND(!(nOffset != offset), "store::ILockBytes::writePageAt(): inconsistent Offset");
80 if (nOffset != offset)
81 return store_E_InvalidParameter;
83 OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::ILockBytes::writePageAt(): invalid Offset");
84 if (nOffset == STORE_PAGE_NULL)
85 return store_E_CantSeek;
87 return writePageAt_Impl (rPage, nOffset);
90 storeError ILockBytes::readAt (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes)
92 // [SECURITY:ValInput]
93 sal_uInt8 * dst_lo = static_cast<sal_uInt8*>(pBuffer);
94 if (!(dst_lo != 0))
95 return store_E_InvalidParameter;
97 sal_uInt8 * dst_hi = dst_lo + nBytes;
98 if (!(dst_lo < dst_hi))
99 return (dst_lo > dst_hi) ? store_E_InvalidParameter : store_E_None;
101 OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::ILockBytes::readAt(): invalid Offset");
102 if (nOffset == STORE_PAGE_NULL)
103 return store_E_CantSeek;
105 sal_uInt64 const src_size = nOffset + nBytes;
106 if (src_size > SAL_MAX_UINT32)
107 return store_E_CantSeek;
109 return readAt_Impl (nOffset, dst_lo, (dst_hi - dst_lo));
112 storeError ILockBytes::writeAt (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes)
114 // [SECURITY:ValInput]
115 sal_uInt8 const * src_lo = static_cast<sal_uInt8 const*>(pBuffer);
116 if (!(src_lo != 0))
117 return store_E_InvalidParameter;
119 sal_uInt8 const * src_hi = src_lo + nBytes;
120 if (!(src_lo < src_hi))
121 return (src_lo > src_hi) ? store_E_InvalidParameter : store_E_None;
123 OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::ILockBytes::writeAt(): invalid Offset");
124 if (nOffset == STORE_PAGE_NULL)
125 return store_E_CantSeek;
127 sal_uInt64 const dst_size = nOffset + nBytes;
128 if (dst_size > SAL_MAX_UINT32)
129 return store_E_CantSeek;
131 return writeAt_Impl (nOffset, src_lo, (src_hi - src_lo));
134 storeError ILockBytes::getSize (sal_uInt32 & rnSize)
136 rnSize = 0;
137 return getSize_Impl (rnSize);
140 storeError ILockBytes::setSize (sal_uInt32 nSize)
142 return setSize_Impl (nSize);
145 storeError ILockBytes::flush()
147 return flush_Impl();
150 /*========================================================================
152 * FileLockBytes implementation.
154 *======================================================================*/
155 namespace store
158 struct FileHandle
160 oslFileHandle m_handle;
162 FileHandle() : m_handle(0) {}
164 bool operator != (FileHandle const & rhs)
166 return (m_handle != rhs.m_handle);
169 static storeError errorFromNative (oslFileError eErrno)
171 switch (eErrno)
173 case osl_File_E_None:
174 return store_E_None;
176 case osl_File_E_NOENT:
177 return store_E_NotExists;
179 case osl_File_E_ACCES:
180 case osl_File_E_PERM:
181 return store_E_AccessViolation;
183 case osl_File_E_AGAIN:
184 case osl_File_E_DEADLK:
185 return store_E_LockingViolation;
187 case osl_File_E_BADF:
188 return store_E_InvalidHandle;
190 case osl_File_E_INVAL:
191 return store_E_InvalidParameter;
193 case osl_File_E_NOMEM:
194 return store_E_OutOfMemory;
196 case osl_File_E_NOSPC:
197 return store_E_OutOfSpace;
199 case osl_File_E_OVERFLOW:
200 return store_E_CantSeek;
202 default:
203 return store_E_Unknown;
207 static sal_uInt32 modeToNative (storeAccessMode eAccessMode)
209 sal_uInt32 nFlags = 0;
210 switch (eAccessMode)
212 case store_AccessCreate:
213 case store_AccessReadCreate:
214 nFlags |= osl_File_OpenFlag_Create;
215 // fall through
216 case store_AccessReadWrite:
217 nFlags |= osl_File_OpenFlag_Write;
218 // fall through
219 case store_AccessReadOnly:
220 nFlags |= osl_File_OpenFlag_Read;
221 break;
222 default:
223 OSL_PRECOND(0, "store::FileHandle: unknown storeAccessMode");
225 return nFlags;
228 storeError initialize (rtl_uString * pFilename, storeAccessMode eAccessMode)
230 // Verify arguments.
231 sal_uInt32 nFlags = modeToNative (eAccessMode);
232 if (!pFilename || !nFlags)
233 return store_E_InvalidParameter;
235 // Convert into FileUrl.
236 rtl::OUString aFileUrl;
237 if (osl_getFileURLFromSystemPath (pFilename, &(aFileUrl.pData)) != osl_File_E_None)
239 // Not system path. Assume file url.
240 rtl_uString_assign (&(aFileUrl.pData), pFilename);
242 if (aFileUrl.compareToAscii("file://", 7) != 0)
244 // Not file url. Assume relative path.
245 rtl::OUString aCwdUrl;
246 (void) osl_getProcessWorkingDir (&(aCwdUrl.pData));
248 // Absolute file url.
249 (void) osl_getAbsoluteFileURL (aCwdUrl.pData, aFileUrl.pData, &(aFileUrl.pData));
252 // Acquire handle.
253 oslFileError result = osl_openFile (aFileUrl.pData, &m_handle, nFlags);
254 if (result == osl_File_E_EXIST)
256 // Already existing (O_CREAT | O_EXCL).
257 result = osl_openFile (aFileUrl.pData, &m_handle, osl_File_OpenFlag_Read | osl_File_OpenFlag_Write);
258 if ((result == osl_File_E_None) && (eAccessMode == store_AccessCreate))
260 // Truncate existing file.
261 result = osl_setFileSize (m_handle, 0);
264 if (result != osl_File_E_None)
265 return errorFromNative(result);
266 return store_E_None;
269 /** @see FileLockBytes destructor
271 static void closeFile (oslFileHandle hFile)
273 (void) osl_closeFile (hFile);
276 /** @see ResourceHolder<T>::destructor_type
278 struct CloseFile
280 void operator()(FileHandle & rFile) const
282 // Release handle.
283 closeFile (rFile.m_handle);
284 rFile.m_handle = 0;
287 typedef CloseFile destructor_type;
290 class FileLockBytes :
291 public store::OStoreObject,
292 public store::ILockBytes
294 /** Representation.
296 oslFileHandle m_hFile;
297 sal_uInt32 m_nSize;
298 rtl::Reference< PageData::Allocator > m_xAllocator;
300 storeError initSize_Impl (sal_uInt32 & rnSize);
302 /** ILockBytes implementation.
304 virtual storeError initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize);
306 virtual storeError readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset);
307 virtual storeError writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset);
309 virtual storeError readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes);
310 virtual storeError writeAt_Impl (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes);
312 virtual storeError getSize_Impl (sal_uInt32 & rnSize);
313 virtual storeError setSize_Impl (sal_uInt32 nSize);
315 virtual storeError flush_Impl();
317 /** Not implemented.
319 FileLockBytes (FileLockBytes const &);
320 FileLockBytes & operator= (FileLockBytes const &);
322 public:
323 /** Construction.
325 explicit FileLockBytes (FileHandle & rFile);
327 /** Delegate multiple inherited IReference.
329 virtual oslInterlockedCount SAL_CALL acquire();
330 virtual oslInterlockedCount SAL_CALL release();
332 protected:
333 /** Destruction.
335 virtual ~FileLockBytes();
338 } // namespace store
340 FileLockBytes::FileLockBytes (FileHandle & rFile)
341 : m_hFile (rFile.m_handle), m_nSize (SAL_MAX_UINT32), m_xAllocator()
345 FileLockBytes::~FileLockBytes()
347 FileHandle::closeFile (m_hFile);
350 oslInterlockedCount SAL_CALL FileLockBytes::acquire()
352 return OStoreObject::acquire();
355 oslInterlockedCount SAL_CALL FileLockBytes::release()
357 return OStoreObject::release();
360 storeError FileLockBytes::initSize_Impl (sal_uInt32 & rnSize)
362 /* osl_getFileSize() uses slow 'fstat(h, &size)',
363 * instead of fast 'size = lseek(h, 0, SEEK_END)'.
364 * so, init size here, and track changes.
366 sal_uInt64 uSize = 0;
367 oslFileError result = osl_getFileSize (m_hFile, &uSize);
368 if (result != osl_File_E_None)
369 return FileHandle::errorFromNative(result);
370 if (uSize > SAL_MAX_UINT32)
371 return store_E_CantSeek;
373 rnSize = sal::static_int_cast<sal_uInt32>(uSize);
374 return store_E_None;
377 storeError FileLockBytes::initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize)
379 storeError result = initSize_Impl (m_nSize);
380 if (result != store_E_None)
381 return (result);
383 result = PageData::Allocator::createInstance (rxAllocator, nPageSize);
384 if (result != store_E_None)
385 return (result);
387 // @see readPageAt_Impl().
388 m_xAllocator = rxAllocator;
389 return store_E_None;
392 storeError FileLockBytes::readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset)
394 if (m_xAllocator.is())
396 PageHolder page (m_xAllocator->construct<PageData>(), m_xAllocator);
397 page.swap (rPage);
400 if (!m_xAllocator.is())
401 return store_E_InvalidAccess;
402 if (!rPage.get())
403 return store_E_OutOfMemory;
405 PageData * pagedata = rPage.get();
406 return readAt_Impl (nOffset, pagedata, pagedata->size());
409 storeError FileLockBytes::writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset)
411 PageData const * pagedata = rPage.get();
412 OSL_PRECOND(pagedata != 0, "contract violation");
413 return writeAt_Impl (nOffset, pagedata, pagedata->size());
416 storeError FileLockBytes::readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes)
418 sal_uInt64 nDone = 0;
419 oslFileError result = osl_readFileAt (m_hFile, nOffset, pBuffer, nBytes, &nDone);
420 if (result != osl_File_E_None)
421 return FileHandle::errorFromNative(result);
422 if (nDone != nBytes)
423 return (nDone != 0) ? store_E_CantRead : store_E_NotExists;
424 return store_E_None;
427 storeError FileLockBytes::writeAt_Impl (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes)
429 sal_uInt64 nDone = 0;
430 oslFileError result = osl_writeFileAt (m_hFile, nOffset, pBuffer, nBytes, &nDone);
431 if (result != osl_File_E_None)
432 return FileHandle::errorFromNative(result);
433 if (nDone != nBytes)
434 return store_E_CantWrite;
436 sal_uInt64 const uSize = nOffset + nBytes;
437 OSL_PRECOND(uSize < SAL_MAX_UINT32, "store::ILockBytes::writeAt() contract violation");
438 if (uSize > m_nSize)
439 m_nSize = sal::static_int_cast<sal_uInt32>(uSize);
440 return store_E_None;
443 storeError FileLockBytes::getSize_Impl (sal_uInt32 & rnSize)
445 rnSize = m_nSize;
446 return store_E_None;
449 storeError FileLockBytes::setSize_Impl (sal_uInt32 nSize)
451 oslFileError result = osl_setFileSize (m_hFile, nSize);
452 if (result != osl_File_E_None)
453 return FileHandle::errorFromNative(result);
455 m_nSize = nSize;
456 return store_E_None;
459 storeError FileLockBytes::flush_Impl()
461 oslFileError result = osl_syncFile (m_hFile);
462 if (result != osl_File_E_None)
463 return FileHandle::errorFromNative(result);
464 return store_E_None;
467 /*========================================================================
469 * MappedLockBytes implementation.
471 *======================================================================*/
472 namespace store
475 struct FileMapping
477 sal_uInt8 * m_pAddr;
478 sal_uInt32 m_nSize;
479 oslFileHandle m_hFile;
481 FileMapping() : m_pAddr(0), m_nSize(0), m_hFile(0) {}
483 bool operator != (FileMapping const & rhs) const
485 return ((m_pAddr != rhs.m_pAddr) || (m_nSize != rhs.m_nSize));
488 oslFileError initialize (oslFileHandle hFile)
490 // Determine mapping size.
491 sal_uInt64 uSize = 0;
492 oslFileError result = osl_getFileSize (hFile, &uSize);
493 if (result != osl_File_E_None)
494 return result;
496 // [SECURITY:IntOver]
497 if (uSize > SAL_MAX_UINT32)
498 return osl_File_E_OVERFLOW;
499 m_nSize = sal::static_int_cast<sal_uInt32>(uSize);
501 m_hFile = hFile;
503 // Acquire mapping.
504 return osl_mapFile (hFile, reinterpret_cast<void**>(&m_pAddr), m_nSize, 0, osl_File_MapFlag_RandomAccess);
507 /** @see MappedLockBytes::destructor.
509 static void unmapFile (oslFileHandle hFile, sal_uInt8 * pAddr, sal_uInt32 nSize)
511 (void) osl_unmapMappedFile (hFile, pAddr, nSize);
512 (void) osl_closeFile (hFile);
515 /** @see ResourceHolder<T>::destructor_type
517 struct UnmapFile
519 void operator ()(FileMapping & rMapping) const
521 // Release mapping.
522 unmapFile (rMapping.m_hFile, rMapping.m_pAddr, rMapping.m_nSize);
523 rMapping.m_pAddr = 0, rMapping.m_nSize = 0;
526 typedef UnmapFile destructor_type;
529 class MappedLockBytes :
530 public store::OStoreObject,
531 public store::PageData::Allocator,
532 public store::ILockBytes
534 /** Representation.
536 sal_uInt8 * m_pData;
537 sal_uInt32 m_nSize;
538 sal_uInt16 m_nPageSize;
539 oslFileHandle m_hFile;
541 /** PageData::Allocator implementation.
543 virtual void allocate_Impl (void ** ppPage, sal_uInt16 * pnSize);
544 virtual void deallocate_Impl (void * pPage);
546 /** ILockBytes implementation.
548 virtual storeError initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize);
550 virtual storeError readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset);
551 virtual storeError writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset);
553 virtual storeError readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes);
554 virtual storeError writeAt_Impl (sal_uInt32 nOffset, const void * pBuffer, sal_uInt32 nBytes);
556 virtual storeError getSize_Impl (sal_uInt32 & rnSize);
557 virtual storeError setSize_Impl (sal_uInt32 nSize);
559 virtual storeError flush_Impl();
561 /** Not implemented.
563 MappedLockBytes (MappedLockBytes const &);
564 MappedLockBytes & operator= (MappedLockBytes const &);
566 public:
567 /** Construction.
569 explicit MappedLockBytes (FileMapping & rMapping);
571 /** Delegate multiple inherited IReference.
573 virtual oslInterlockedCount SAL_CALL acquire();
574 virtual oslInterlockedCount SAL_CALL release();
576 protected:
577 /* Destruction.
579 virtual ~MappedLockBytes();
582 } // namespace store
584 MappedLockBytes::MappedLockBytes (FileMapping & rMapping)
585 : m_pData (rMapping.m_pAddr), m_nSize (rMapping.m_nSize), m_nPageSize(0), m_hFile (rMapping.m_hFile)
589 MappedLockBytes::~MappedLockBytes()
591 FileMapping::unmapFile (m_hFile, m_pData, m_nSize);
594 oslInterlockedCount SAL_CALL MappedLockBytes::acquire()
596 return OStoreObject::acquire();
599 oslInterlockedCount SAL_CALL MappedLockBytes::release()
601 return OStoreObject::release();
604 void MappedLockBytes::allocate_Impl (void ** ppPage, sal_uInt16 * pnSize)
606 OSL_PRECOND((ppPage != 0) && (pnSize != 0), "contract violation");
607 if ((ppPage != 0) && (pnSize != 0))
608 *ppPage = 0, *pnSize = m_nPageSize;
611 void MappedLockBytes::deallocate_Impl (void * pPage)
613 OSL_PRECOND((m_pData <= pPage) && (pPage < m_pData + m_nSize), "contract violation");
614 (void)pPage; // UNUSED
617 storeError MappedLockBytes::initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize)
619 rxAllocator = this;
620 m_nPageSize = nPageSize;
621 return store_E_None;
624 storeError MappedLockBytes::readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset)
626 sal_uInt8 * src_lo = m_pData + nOffset;
627 if ((m_pData > src_lo) || (src_lo >= m_pData + m_nSize))
628 return store_E_NotExists;
630 sal_uInt8 * src_hi = src_lo + m_nPageSize;
631 if ((m_pData > src_hi) || (src_hi > m_pData + m_nSize))
632 return store_E_CantRead;
634 PageHolder page (reinterpret_cast< PageData* >(src_lo), static_cast< PageData::Allocator* >(this));
635 page.swap (rPage);
637 return store_E_None;
640 storeError MappedLockBytes::writePageAt_Impl (PageHolder const & /*rPage*/, sal_uInt32 /*nOffset*/)
642 return store_E_AccessViolation;
645 storeError MappedLockBytes::readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes)
647 sal_uInt8 const * src_lo = m_pData + nOffset;
648 if ((m_pData > src_lo) || (src_lo >= m_pData + m_nSize))
649 return store_E_NotExists;
651 sal_uInt8 const * src_hi = src_lo + nBytes;
652 if ((m_pData > src_hi) || (src_hi > m_pData + m_nSize))
653 return store_E_CantRead;
655 memcpy (pBuffer, src_lo, (src_hi - src_lo));
656 return store_E_None;
659 storeError MappedLockBytes::writeAt_Impl (sal_uInt32 /*nOffset*/, void const * /*pBuffer*/, sal_uInt32 /*nBytes*/)
661 return store_E_AccessViolation;
664 storeError MappedLockBytes::getSize_Impl (sal_uInt32 & rnSize)
666 rnSize = m_nSize;
667 return store_E_None;
670 storeError MappedLockBytes::setSize_Impl (sal_uInt32 /*nSize*/)
672 return store_E_AccessViolation;
675 storeError MappedLockBytes::flush_Impl()
677 return store_E_None;
680 /*========================================================================
682 * MemoryLockBytes implementation.
684 *======================================================================*/
685 namespace store
688 class MemoryLockBytes :
689 public store::OStoreObject,
690 public store::ILockBytes
692 /** Representation.
694 sal_uInt8 * m_pData;
695 sal_uInt32 m_nSize;
696 rtl::Reference< PageData::Allocator > m_xAllocator;
698 /** ILockBytes implementation.
700 virtual storeError initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize);
702 virtual storeError readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset);
703 virtual storeError writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset);
705 virtual storeError readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes);
706 virtual storeError writeAt_Impl (sal_uInt32 nOffset, const void * pBuffer, sal_uInt32 nBytes);
708 virtual storeError getSize_Impl (sal_uInt32 & rnSize);
709 virtual storeError setSize_Impl (sal_uInt32 nSize);
711 virtual storeError flush_Impl();
713 /** Not implemented.
715 MemoryLockBytes (MemoryLockBytes const &);
716 MemoryLockBytes& operator= (MemoryLockBytes const &);
718 public:
719 /** Construction.
721 MemoryLockBytes();
723 /** Delegate multiple inherited IReference.
725 virtual oslInterlockedCount SAL_CALL acquire();
726 virtual oslInterlockedCount SAL_CALL release();
728 protected:
729 /** Destruction.
731 virtual ~MemoryLockBytes();
734 } // namespace store
736 MemoryLockBytes::MemoryLockBytes()
737 : m_pData (0), m_nSize (0), m_xAllocator()
740 MemoryLockBytes::~MemoryLockBytes()
742 rtl_freeMemory (m_pData);
745 oslInterlockedCount SAL_CALL MemoryLockBytes::acquire (void)
747 return OStoreObject::acquire();
750 oslInterlockedCount SAL_CALL MemoryLockBytes::release (void)
752 return OStoreObject::release();
755 storeError MemoryLockBytes::initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize)
757 storeError result = PageData::Allocator::createInstance (rxAllocator, nPageSize);
758 if (result == store_E_None)
760 // @see readPageAt_Impl().
761 m_xAllocator = rxAllocator;
763 return result;
766 storeError MemoryLockBytes::readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset)
768 if (m_xAllocator.is())
770 PageHolder page (m_xAllocator->construct<PageData>(), m_xAllocator);
771 page.swap (rPage);
774 if (!m_xAllocator.is())
775 return store_E_InvalidAccess;
776 if (!rPage.get())
777 return store_E_OutOfMemory;
779 PageData * pagedata = rPage.get();
780 return readAt_Impl (nOffset, pagedata, pagedata->size());
783 storeError MemoryLockBytes::writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset)
785 PageData const * pagedata = rPage.get();
786 OSL_PRECOND(!(pagedata == 0), "contract violation");
787 return writeAt_Impl (nOffset, pagedata, pagedata->size());
790 storeError MemoryLockBytes::readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes)
792 sal_uInt8 const * src_lo = m_pData + nOffset;
793 if ((m_pData > src_lo) || (src_lo >= m_pData + m_nSize))
794 return store_E_NotExists;
796 sal_uInt8 const * src_hi = src_lo + nBytes;
797 if ((m_pData > src_hi) || (src_hi > m_pData + m_nSize))
798 return store_E_CantRead;
800 memcpy (pBuffer, src_lo, (src_hi - src_lo));
801 return store_E_None;
804 storeError MemoryLockBytes::writeAt_Impl (sal_uInt32 nOffset, const void * pBuffer, sal_uInt32 nBytes)
806 sal_uInt64 const dst_size = nOffset + nBytes;
807 OSL_PRECOND(dst_size < SAL_MAX_UINT32, "store::ILockBytes::writeAt() contract violation");
808 if (dst_size > m_nSize)
810 storeError eErrCode = setSize_Impl (sal::static_int_cast<sal_uInt32>(dst_size));
811 if (eErrCode != store_E_None)
812 return eErrCode;
814 OSL_POSTCOND(dst_size <= m_nSize, "store::MemoryLockBytes::setSize_Impl() contract violation");
816 sal_uInt8 * dst_lo = m_pData + nOffset;
817 if (dst_lo >= m_pData + m_nSize)
818 return store_E_CantSeek;
820 sal_uInt8 * dst_hi = dst_lo + nBytes;
821 if (dst_hi > m_pData + m_nSize)
822 return store_E_CantWrite;
824 memcpy (dst_lo, pBuffer, (dst_hi - dst_lo));
825 return store_E_None;
828 storeError MemoryLockBytes::getSize_Impl (sal_uInt32 & rnSize)
830 rnSize = m_nSize;
831 return store_E_None;
834 storeError MemoryLockBytes::setSize_Impl (sal_uInt32 nSize)
836 if (nSize != m_nSize)
838 sal_uInt8 * pData = reinterpret_cast<sal_uInt8*>(rtl_reallocateMemory (m_pData, nSize));
839 if (pData != 0)
841 if (nSize > m_nSize)
842 memset (pData + m_nSize, 0, sal::static_int_cast<size_t>(nSize - m_nSize));
844 else
846 if (nSize != 0)
847 return store_E_OutOfMemory;
849 m_pData = pData, m_nSize = nSize;
851 return store_E_None;
854 storeError MemoryLockBytes::flush_Impl()
856 return store_E_None;
859 /*========================================================================
861 * ILockBytes factory implementations.
863 *======================================================================*/
864 namespace store
867 template< class T > struct ResourceHolder
869 typedef typename T::destructor_type destructor_type;
871 T m_value;
873 explicit ResourceHolder (T const & value = T()) : m_value (value) {}
874 ~ResourceHolder() { reset(); }
876 T & get() { return m_value; }
877 T const & get() const { return m_value; }
879 void set (T const & value) { m_value = value; }
880 void reset (T const & value = T())
882 T tmp (m_value);
883 if (tmp != value)
884 destructor_type()(tmp);
885 set (value);
887 T release()
889 T tmp (m_value);
890 set (T());
891 return tmp;
894 ResourceHolder (ResourceHolder & rhs)
896 set (rhs.release());
898 ResourceHolder & operator= (ResourceHolder & rhs)
900 reset (rhs.release());
901 return *this;
905 storeError
906 FileLockBytes_createInstance (
907 rtl::Reference< ILockBytes > & rxLockBytes,
908 rtl_uString * pFilename,
909 storeAccessMode eAccessMode
912 // Acquire file handle.
913 ResourceHolder<FileHandle> xFile;
914 storeError result = xFile.get().initialize (pFilename, eAccessMode);
915 if (result != store_E_None)
916 return (result);
918 if (eAccessMode == store_AccessReadOnly)
920 ResourceHolder<FileMapping> xMapping;
921 if (xMapping.get().initialize (xFile.get().m_handle) == osl_File_E_None)
923 rxLockBytes = new MappedLockBytes (xMapping.get());
924 if (!rxLockBytes.is())
925 return store_E_OutOfMemory;
926 (void) xFile.release();
927 (void) xMapping.release();
930 if (!rxLockBytes.is())
932 rxLockBytes = new FileLockBytes (xFile.get());
933 if (!rxLockBytes.is())
934 return store_E_OutOfMemory;
935 (void) xFile.release();
938 return store_E_None;
941 storeError
942 MemoryLockBytes_createInstance (
943 rtl::Reference< ILockBytes > & rxLockBytes
946 rxLockBytes = new MemoryLockBytes();
947 if (!rxLockBytes.is())
948 return store_E_OutOfMemory;
950 return store_E_None;
953 } // namespace store
955 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */