LCOV - code coverage report
Current view: top level - store/source - lockbyte.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 212 336 63.1 %
Date: 2015-06-13 12:38:46 Functions: 50 76 65.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       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/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      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 .
      18             :  */
      19             : 
      20             : #include "lockbyte.hxx"
      21             : 
      22             : #include "boost/noncopyable.hpp"
      23             : #include "sal/types.h"
      24             : #include "osl/diagnose.h"
      25             : #include "osl/file.h"
      26             : #include "osl/process.h"
      27             : #include "rtl/alloc.h"
      28             : #include "rtl/ustring.hxx"
      29             : #include "sal/log.hxx"
      30             : 
      31             : #include "object.hxx"
      32             : #include "storbase.hxx"
      33             : 
      34             : #include <string.h>
      35             : 
      36             : using namespace store;
      37             : 
      38             : /*========================================================================
      39             :  *
      40             :  * ILockBytes (non-virtual interface) implementation.
      41             :  *
      42             :  *======================================================================*/
      43             : 
      44         148 : storeError ILockBytes::initialize (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize)
      45             : {
      46             :     OSL_PRECOND((STORE_MINIMUM_PAGESIZE <= nPageSize) && (nPageSize <= STORE_MAXIMUM_PAGESIZE), "invalid PageSize");
      47         148 :     return initialize_Impl (rxAllocator, nPageSize);
      48             : }
      49             : 
      50         148 : storeError ILockBytes::readPageAt (PageHolder & rPage, sal_uInt32 nOffset)
      51             : {
      52             :     OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::ILockBytes::readPageAt(): invalid Offset");
      53         148 :     if (nOffset == STORE_PAGE_NULL)
      54           0 :         return store_E_CantSeek;
      55             : 
      56         148 :     return readPageAt_Impl (rPage, nOffset);
      57             : }
      58             : 
      59        2740 : storeError ILockBytes::writePageAt (PageHolder const & rPage, sal_uInt32 nOffset)
      60             : {
      61             :     // [SECURITY:ValInput]
      62        2740 :     PageData const * pagedata = rPage.get();
      63             :     OSL_PRECOND(!(pagedata == 0), "store::ILockBytes::writePageAt(): invalid Page");
      64        2740 :     if (pagedata == 0)
      65           0 :         return store_E_InvalidParameter;
      66             : 
      67        2740 :     sal_uInt32 const offset = pagedata->location();
      68             :     OSL_PRECOND(!(nOffset != offset), "store::ILockBytes::writePageAt(): inconsistent Offset");
      69        2740 :     if (nOffset != offset)
      70           0 :         return store_E_InvalidParameter;
      71             : 
      72             :     OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::ILockBytes::writePageAt(): invalid Offset");
      73        2740 :     if (nOffset == STORE_PAGE_NULL)
      74           0 :         return store_E_CantSeek;
      75             : 
      76        2740 :     return writePageAt_Impl (rPage, nOffset);
      77             : }
      78             : 
      79          12 : storeError ILockBytes::readAt (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes)
      80             : {
      81             :     // [SECURITY:ValInput]
      82          12 :     sal_uInt8 * dst_lo = static_cast<sal_uInt8*>(pBuffer);
      83          12 :     if (!(dst_lo != 0))
      84           0 :         return store_E_InvalidParameter;
      85             : 
      86          12 :     sal_uInt8 * dst_hi = dst_lo + nBytes;
      87          12 :     if (!(dst_lo < dst_hi))
      88           0 :         return (dst_lo > dst_hi) ? store_E_InvalidParameter : store_E_None;
      89             : 
      90             :     OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::ILockBytes::readAt(): invalid Offset");
      91          12 :     if (nOffset == STORE_PAGE_NULL)
      92           0 :         return store_E_CantSeek;
      93             : 
      94          12 :     sal_uInt64 const src_size = static_cast<sal_uInt64>(nOffset) + nBytes;
      95          12 :     if (src_size > SAL_MAX_UINT32)
      96           0 :         return store_E_CantSeek;
      97             : 
      98          12 :     return readAt_Impl (nOffset, dst_lo, (dst_hi - dst_lo));
      99             : }
     100             : 
     101         168 : storeError ILockBytes::writeAt (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes)
     102             : {
     103             :     // [SECURITY:ValInput]
     104         168 :     sal_uInt8 const * src_lo = static_cast<sal_uInt8 const*>(pBuffer);
     105         168 :     if (!(src_lo != 0))
     106           0 :         return store_E_InvalidParameter;
     107             : 
     108         168 :     sal_uInt8 const * src_hi = src_lo + nBytes;
     109         168 :     if (!(src_lo < src_hi))
     110           0 :         return (src_lo > src_hi) ? store_E_InvalidParameter : store_E_None;
     111             : 
     112             :     OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::ILockBytes::writeAt(): invalid Offset");
     113         168 :     if (nOffset == STORE_PAGE_NULL)
     114           0 :         return store_E_CantSeek;
     115             : 
     116         168 :     sal_uInt64 const dst_size = static_cast<sal_uInt64>(nOffset) + nBytes;
     117         168 :     if (dst_size > SAL_MAX_UINT32)
     118           0 :         return store_E_CantSeek;
     119             : 
     120         168 :     return writeAt_Impl (nOffset, src_lo, (src_hi - src_lo));
     121             : }
     122             : 
     123        1226 : storeError ILockBytes::getSize (sal_uInt32 & rnSize)
     124             : {
     125        1226 :     rnSize = 0;
     126        1226 :     return getSize_Impl (rnSize);
     127             : }
     128             : 
     129         148 : storeError ILockBytes::setSize (sal_uInt32 nSize)
     130             : {
     131         148 :     return setSize_Impl (nSize);
     132             : }
     133             : 
     134           2 : storeError ILockBytes::flush()
     135             : {
     136           2 :     return flush_Impl();
     137             : }
     138             : 
     139             : /*========================================================================
     140             :  *
     141             :  * FileLockBytes implementation.
     142             :  *
     143             :  *======================================================================*/
     144             : namespace store
     145             : {
     146             : 
     147             : struct FileHandle
     148             : {
     149             :     oslFileHandle m_handle;
     150             : 
     151         448 :     FileHandle() : m_handle(0) {}
     152             : 
     153         150 :     bool operator != (FileHandle const & rhs)
     154             :     {
     155         150 :         return (m_handle != rhs.m_handle);
     156             :     }
     157             : 
     158           2 :     static storeError errorFromNative (oslFileError eErrno)
     159             :     {
     160           2 :         switch (eErrno)
     161             :         {
     162             :         case osl_File_E_None:
     163           0 :             return store_E_None;
     164             : 
     165             :         case osl_File_E_NOENT:
     166           2 :             return store_E_NotExists;
     167             : 
     168             :         case osl_File_E_ACCES:
     169             :         case osl_File_E_PERM:
     170           0 :             return store_E_AccessViolation;
     171             : 
     172             :         case osl_File_E_AGAIN:
     173             :         case osl_File_E_DEADLK:
     174           0 :             return store_E_LockingViolation;
     175             : 
     176             :         case osl_File_E_BADF:
     177           0 :             return store_E_InvalidHandle;
     178             : 
     179             :         case osl_File_E_INVAL:
     180           0 :             return store_E_InvalidParameter;
     181             : 
     182             :         case osl_File_E_NOMEM:
     183           0 :             return store_E_OutOfMemory;
     184             : 
     185             :         case osl_File_E_NOSPC:
     186           0 :             return store_E_OutOfSpace;
     187             : 
     188             :         case osl_File_E_OVERFLOW:
     189           0 :             return store_E_CantSeek;
     190             : 
     191             :         default:
     192           0 :             return store_E_Unknown;
     193             :         }
     194             :     }
     195             : 
     196         150 :     static sal_uInt32 modeToNative (storeAccessMode eAccessMode)
     197             :     {
     198         150 :         sal_uInt32 nFlags = 0;
     199         150 :         switch (eAccessMode)
     200             :         {
     201             :         case store_AccessCreate:
     202             :         case store_AccessReadCreate:
     203         146 :             nFlags |= osl_File_OpenFlag_Create;
     204             :             // fall through
     205             :         case store_AccessReadWrite:
     206         148 :             nFlags |= osl_File_OpenFlag_Write;
     207             :             // fall through
     208             :         case store_AccessReadOnly:
     209         150 :             nFlags |= osl_File_OpenFlag_Read;
     210         150 :             break;
     211             :         default:
     212             :             OSL_PRECOND(false, "store::FileHandle: unknown storeAccessMode");
     213             :         }
     214         150 :         return nFlags;
     215             :     }
     216             : 
     217         150 :     storeError initialize (rtl_uString * pFilename, storeAccessMode eAccessMode)
     218             :     {
     219             :         // Verify arguments.
     220         150 :         sal_uInt32 nFlags = modeToNative (eAccessMode);
     221         150 :         if (!pFilename || !nFlags)
     222           0 :             return store_E_InvalidParameter;
     223             : 
     224             :         // Convert into FileUrl.
     225         150 :         OUString aFileUrl;
     226         150 :         if (osl_getFileURLFromSystemPath (pFilename, &(aFileUrl.pData)) != osl_File_E_None)
     227             :         {
     228             :             // Not system path. Assume file url.
     229         150 :             rtl_uString_assign (&(aFileUrl.pData), pFilename);
     230             :         }
     231         150 :         if (!aFileUrl.startsWith("file://"))
     232             :         {
     233             :             // Not file url. Assume relative path.
     234           0 :             OUString aCwdUrl;
     235           0 :             (void) osl_getProcessWorkingDir (&(aCwdUrl.pData));
     236             : 
     237             :             // Absolute file url.
     238           0 :             (void) osl_getAbsoluteFileURL (aCwdUrl.pData, aFileUrl.pData, &(aFileUrl.pData));
     239             :         }
     240             : 
     241             :         // Acquire handle.
     242         150 :         oslFileError result = osl_openFile (aFileUrl.pData, &m_handle, nFlags);
     243         150 :         if (result == osl_File_E_EXIST)
     244             :         {
     245             :             // Already existing (O_CREAT | O_EXCL).
     246           0 :             result = osl_openFile (aFileUrl.pData, &m_handle, osl_File_OpenFlag_Read | osl_File_OpenFlag_Write);
     247           0 :             if ((result == osl_File_E_None) && (eAccessMode == store_AccessCreate))
     248             :             {
     249             :                 // Truncate existing file.
     250           0 :                 result = osl_setFileSize (m_handle, 0);
     251             :             }
     252             :         }
     253         150 :         if (result != osl_File_E_None)
     254           2 :             return errorFromNative(result);
     255         148 :         return store_E_None;
     256             :     }
     257             : 
     258             :     /** @see FileLockBytes destructor
     259             :      */
     260         148 :     static void closeFile (oslFileHandle hFile)
     261             :     {
     262         148 :         (void) osl_closeFile (hFile);
     263         148 :     }
     264             : 
     265             :     /** @see ResourceHolder<T>::destructor_type
     266             :      */
     267             :     struct CloseFile
     268             :     {
     269           0 :         void operator()(FileHandle & rFile) const
     270             :         {
     271             :             // Release handle.
     272           0 :             closeFile (rFile.m_handle);
     273           0 :             rFile.m_handle = 0;
     274           0 :         }
     275             :     };
     276             :     typedef CloseFile destructor_type;
     277             : };
     278             : 
     279             : class FileLockBytes :
     280             :     public store::OStoreObject,
     281             :     public store::ILockBytes,
     282             :     private boost::noncopyable
     283             : {
     284             :     /** Representation.
     285             :      */
     286             :     oslFileHandle                         m_hFile;
     287             :     sal_uInt32                            m_nSize;
     288             :     rtl::Reference< PageData::Allocator > m_xAllocator;
     289             : 
     290             :     storeError initSize_Impl (sal_uInt32 & rnSize);
     291             : 
     292             :     /** ILockBytes implementation.
     293             :      */
     294             :     virtual storeError initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize) SAL_OVERRIDE;
     295             : 
     296             :     virtual storeError readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset) SAL_OVERRIDE;
     297             :     virtual storeError writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset) SAL_OVERRIDE;
     298             : 
     299             :     virtual storeError readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes) SAL_OVERRIDE;
     300             :     virtual storeError writeAt_Impl (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes) SAL_OVERRIDE;
     301             : 
     302             :     virtual storeError getSize_Impl (sal_uInt32 & rnSize) SAL_OVERRIDE;
     303             :     virtual storeError setSize_Impl (sal_uInt32 nSize) SAL_OVERRIDE;
     304             : 
     305             :     virtual storeError flush_Impl() SAL_OVERRIDE;
     306             : 
     307             : public:
     308             :     /** Construction.
     309             :      */
     310             :     explicit FileLockBytes (FileHandle & rFile);
     311             : 
     312             : protected:
     313             :     /** Destruction.
     314             :      */
     315             :     virtual ~FileLockBytes();
     316             : };
     317             : 
     318             : } // namespace store
     319             : 
     320         148 : FileLockBytes::FileLockBytes (FileHandle & rFile)
     321         148 :     : m_hFile (rFile.m_handle), m_nSize (SAL_MAX_UINT32), m_xAllocator()
     322             : {
     323         148 : }
     324             : 
     325         592 : FileLockBytes::~FileLockBytes()
     326             : {
     327         148 :     FileHandle::closeFile (m_hFile);
     328         444 : }
     329             : 
     330         146 : storeError FileLockBytes::initSize_Impl (sal_uInt32 & rnSize)
     331             : {
     332             :     /* osl_getFileSize() uses slow 'fstat(h, &size)',
     333             :      * instead of fast 'size = lseek(h, 0, SEEK_END)'.
     334             :      * so, init size here, and track changes.
     335             :      */
     336         146 :     sal_uInt64 uSize = 0;
     337         146 :     oslFileError result = osl_getFileSize (m_hFile, &uSize);
     338         146 :     if (result != osl_File_E_None)
     339           0 :         return FileHandle::errorFromNative(result);
     340         146 :     if (uSize > SAL_MAX_UINT32)
     341           0 :         return store_E_CantSeek;
     342             : 
     343         146 :     rnSize = sal::static_int_cast<sal_uInt32>(uSize);
     344         146 :     return store_E_None;
     345             : }
     346             : 
     347         146 : storeError FileLockBytes::initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize)
     348             : {
     349         146 :     storeError result = initSize_Impl (m_nSize);
     350         146 :     if (result != store_E_None)
     351           0 :         return result;
     352             : 
     353         146 :     result = PageData::Allocator::createInstance (rxAllocator, nPageSize);
     354         146 :     if (result != store_E_None)
     355           0 :         return result;
     356             : 
     357             :     // @see readPageAt_Impl().
     358         146 :     m_xAllocator = rxAllocator;
     359         146 :     return store_E_None;
     360             : }
     361             : 
     362         146 : storeError FileLockBytes::readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset)
     363             : {
     364         146 :     if (m_xAllocator.is())
     365             :     {
     366         146 :         PageHolder page (m_xAllocator->construct<PageData>(), m_xAllocator);
     367         146 :         page.swap (rPage);
     368             :     }
     369             : 
     370         146 :     if (!m_xAllocator.is())
     371           0 :         return store_E_InvalidAccess;
     372         146 :     if (!rPage.get())
     373           0 :         return store_E_OutOfMemory;
     374             : 
     375         146 :     PageData * pagedata = rPage.get();
     376         146 :     return readAt_Impl (nOffset, pagedata, pagedata->size());
     377             : }
     378             : 
     379        2704 : storeError FileLockBytes::writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset)
     380             : {
     381        2704 :     PageData const * pagedata = rPage.get();
     382             :     OSL_PRECOND(pagedata != 0, "contract violation");
     383        2704 :     return writeAt_Impl (nOffset, pagedata, pagedata->size());
     384             : }
     385             : 
     386         158 : storeError FileLockBytes::readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes)
     387             : {
     388         158 :     sal_uInt64 nDone = 0;
     389         158 :     oslFileError result = osl_readFileAt (m_hFile, nOffset, pBuffer, nBytes, &nDone);
     390         158 :     if (result != osl_File_E_None)
     391           0 :         return FileHandle::errorFromNative(result);
     392         158 :     if (nDone != nBytes)
     393         148 :         return (nDone != 0) ? store_E_CantRead : store_E_NotExists;
     394          10 :     return store_E_None;
     395             : }
     396             : 
     397        2870 : storeError FileLockBytes::writeAt_Impl (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes)
     398             : {
     399        2870 :     sal_uInt64 nDone = 0;
     400        2870 :     oslFileError result = osl_writeFileAt (m_hFile, nOffset, pBuffer, nBytes, &nDone);
     401        2870 :     if (result != osl_File_E_None)
     402           0 :         return FileHandle::errorFromNative(result);
     403        2870 :     if (nDone != nBytes)
     404           0 :         return store_E_CantWrite;
     405             : 
     406        2870 :     sal_uInt64 const uSize = nOffset + nBytes;
     407             :     OSL_PRECOND(uSize < SAL_MAX_UINT32, "store::ILockBytes::writeAt() contract violation");
     408        2870 :     if (uSize > m_nSize)
     409        1355 :         m_nSize = sal::static_int_cast<sal_uInt32>(uSize);
     410        2870 :     return store_E_None;
     411             : }
     412             : 
     413        1209 : storeError FileLockBytes::getSize_Impl (sal_uInt32 & rnSize)
     414             : {
     415        1209 :     rnSize = m_nSize;
     416        1209 :     return store_E_None;
     417             : }
     418             : 
     419         146 : storeError FileLockBytes::setSize_Impl (sal_uInt32 nSize)
     420             : {
     421         146 :     oslFileError result = osl_setFileSize (m_hFile, nSize);
     422         146 :     if (result != osl_File_E_None)
     423           0 :         return FileHandle::errorFromNative(result);
     424             : 
     425         146 :     m_nSize = nSize;
     426         146 :     return store_E_None;
     427             : }
     428             : 
     429           2 : storeError FileLockBytes::flush_Impl()
     430             : {
     431           2 :     oslFileError result = osl_syncFile (m_hFile);
     432           2 :     if (result != osl_File_E_None)
     433           0 :         return FileHandle::errorFromNative(result);
     434           2 :     return store_E_None;
     435             : }
     436             : 
     437             : /*========================================================================
     438             :  *
     439             :  * MappedLockBytes implementation.
     440             :  *
     441             :  *======================================================================*/
     442             : namespace store
     443             : {
     444             : 
     445             : struct FileMapping
     446             : {
     447             :     sal_uInt8 * m_pAddr;
     448             :     sal_uInt32  m_nSize;
     449             :     oslFileHandle m_hFile;
     450             : 
     451           4 :     FileMapping() : m_pAddr(0), m_nSize(0), m_hFile(0) {}
     452             : 
     453           2 :     bool operator != (FileMapping const & rhs) const
     454             :     {
     455           2 :         return ((m_pAddr != rhs.m_pAddr) || (m_nSize != rhs.m_nSize));
     456             :     }
     457             : 
     458           2 :     oslFileError initialize (oslFileHandle hFile)
     459             :     {
     460             :         // Determine mapping size.
     461           2 :         sal_uInt64   uSize  = 0;
     462           2 :         oslFileError result = osl_getFileSize (hFile, &uSize);
     463           2 :         if (result != osl_File_E_None)
     464           0 :             return result;
     465             : 
     466             :         // [SECURITY:IntOver]
     467           2 :         if (uSize > SAL_MAX_UINT32)
     468           0 :             return osl_File_E_OVERFLOW;
     469           2 :         m_nSize = sal::static_int_cast<sal_uInt32>(uSize);
     470             : 
     471           2 :         m_hFile = hFile;
     472             : 
     473             :         // Acquire mapping.
     474           2 :         return osl_mapFile (hFile, reinterpret_cast<void**>(&m_pAddr), m_nSize, 0, osl_File_MapFlag_RandomAccess);
     475             :     }
     476             : 
     477             :     /** @see MappedLockBytes::destructor.
     478             :      */
     479           0 :     static void unmapFile (oslFileHandle hFile, sal_uInt8 * pAddr, sal_uInt32 nSize)
     480             :     {
     481           0 :         (void) osl_unmapMappedFile (hFile, pAddr, nSize);
     482           0 :         (void) osl_closeFile (hFile);
     483           0 :     }
     484             : 
     485             :     /** @see ResourceHolder<T>::destructor_type
     486             :      */
     487             :     struct UnmapFile
     488             :     {
     489           0 :         void operator ()(FileMapping & rMapping) const
     490             :         {
     491             :             // Release mapping.
     492           0 :             unmapFile (rMapping.m_hFile, rMapping.m_pAddr, rMapping.m_nSize);
     493           0 :             rMapping.m_pAddr = 0, rMapping.m_nSize = 0;
     494           0 :         }
     495             :     };
     496             :     typedef UnmapFile destructor_type;
     497             : };
     498             : 
     499             : class MappedLockBytes :
     500             :     public store::OStoreObject,
     501             :     public store::PageData::Allocator,
     502             :     public store::ILockBytes,
     503             :     private boost::noncopyable
     504             : {
     505             :     /** Representation.
     506             :      */
     507             :     sal_uInt8 * m_pData;
     508             :     sal_uInt32  m_nSize;
     509             :     sal_uInt16  m_nPageSize;
     510             :     oslFileHandle m_hFile;
     511             : 
     512             :     /** PageData::Allocator implementation.
     513             :      */
     514             :     virtual void allocate_Impl (void ** ppPage, sal_uInt16 * pnSize) SAL_OVERRIDE;
     515             :     virtual void deallocate_Impl (void * pPage) SAL_OVERRIDE;
     516             : 
     517             :     /** ILockBytes implementation.
     518             :      */
     519             :     virtual storeError initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize) SAL_OVERRIDE;
     520             : 
     521             :     virtual storeError readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset) SAL_OVERRIDE;
     522             :     virtual storeError writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset) SAL_OVERRIDE;
     523             : 
     524             :     virtual storeError readAt_Impl  (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes) SAL_OVERRIDE;
     525             :     virtual storeError writeAt_Impl (sal_uInt32 nOffset, const void * pBuffer, sal_uInt32 nBytes) SAL_OVERRIDE;
     526             : 
     527             :     virtual storeError getSize_Impl (sal_uInt32 & rnSize) SAL_OVERRIDE;
     528             :     virtual storeError setSize_Impl (sal_uInt32 nSize) SAL_OVERRIDE;
     529             : 
     530             :     virtual storeError flush_Impl() SAL_OVERRIDE;
     531             : 
     532             : public:
     533             :     /** Construction.
     534             :      */
     535             :     explicit MappedLockBytes (FileMapping & rMapping);
     536             : 
     537             : protected:
     538             :     /* Destruction.
     539             :      */
     540             :     virtual ~MappedLockBytes();
     541             : };
     542             : 
     543             : } // namespace store
     544             : 
     545           0 : MappedLockBytes::MappedLockBytes (FileMapping & rMapping)
     546           0 :     : m_pData (rMapping.m_pAddr), m_nSize (rMapping.m_nSize), m_nPageSize(0), m_hFile (rMapping.m_hFile)
     547             : {
     548           0 : }
     549             : 
     550           0 : MappedLockBytes::~MappedLockBytes()
     551             : {
     552           0 :     FileMapping::unmapFile (m_hFile, m_pData, m_nSize);
     553           0 : }
     554             : 
     555           0 : void MappedLockBytes::allocate_Impl (void ** ppPage, sal_uInt16 * pnSize)
     556             : {
     557             :     OSL_PRECOND((ppPage != 0) && (pnSize != 0), "contract violation");
     558           0 :     if ((ppPage != 0) && (pnSize != 0))
     559           0 :         *ppPage = 0, *pnSize = m_nPageSize;
     560           0 : }
     561             : 
     562           0 : void MappedLockBytes::deallocate_Impl (void * pPage)
     563             : {
     564             :     OSL_PRECOND((m_pData <= pPage) && (pPage < m_pData + m_nSize), "contract violation");
     565             :     (void)pPage; // UNUSED
     566           0 : }
     567             : 
     568           0 : storeError MappedLockBytes::initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize)
     569             : {
     570           0 :     rxAllocator = this;
     571           0 :     m_nPageSize = nPageSize;
     572           0 :     return store_E_None;
     573             : }
     574             : 
     575           0 : storeError MappedLockBytes::readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset)
     576             : {
     577           0 :     sal_uInt8 * src_lo = m_pData + nOffset;
     578           0 :     if ((m_pData > src_lo) || (src_lo >= m_pData + m_nSize))
     579           0 :         return store_E_NotExists;
     580             : 
     581           0 :     sal_uInt8 * src_hi = src_lo + m_nPageSize;
     582           0 :     if ((m_pData > src_hi) || (src_hi > m_pData + m_nSize))
     583           0 :         return store_E_CantRead;
     584             : 
     585           0 :     PageHolder page (reinterpret_cast< PageData* >(src_lo), static_cast< PageData::Allocator* >(this));
     586           0 :     page.swap (rPage);
     587             : 
     588           0 :     return store_E_None;
     589             : }
     590             : 
     591           0 : storeError MappedLockBytes::writePageAt_Impl (PageHolder const & /*rPage*/, sal_uInt32 /*nOffset*/)
     592             : {
     593           0 :     return store_E_AccessViolation;
     594             : }
     595             : 
     596           0 : storeError MappedLockBytes::readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes)
     597             : {
     598           0 :     sal_uInt8 const * src_lo = m_pData + nOffset;
     599           0 :     if ((m_pData > src_lo) || (src_lo >= m_pData + m_nSize))
     600           0 :         return store_E_NotExists;
     601             : 
     602           0 :     sal_uInt8 const * src_hi = src_lo + nBytes;
     603           0 :     if ((m_pData > src_hi) || (src_hi > m_pData + m_nSize))
     604           0 :         return store_E_CantRead;
     605             : 
     606           0 :     memcpy (pBuffer, src_lo, (src_hi - src_lo));
     607           0 :     return store_E_None;
     608             : }
     609             : 
     610           0 : storeError MappedLockBytes::writeAt_Impl (sal_uInt32 /*nOffset*/, void const * /*pBuffer*/, sal_uInt32 /*nBytes*/)
     611             : {
     612           0 :     return store_E_AccessViolation;
     613             : }
     614             : 
     615           0 : storeError MappedLockBytes::getSize_Impl (sal_uInt32 & rnSize)
     616             : {
     617           0 :     rnSize = m_nSize;
     618           0 :     return store_E_None;
     619             : }
     620             : 
     621           0 : storeError MappedLockBytes::setSize_Impl (sal_uInt32 /*nSize*/)
     622             : {
     623           0 :     return store_E_AccessViolation;
     624             : }
     625             : 
     626           0 : storeError MappedLockBytes::flush_Impl()
     627             : {
     628           0 :     return store_E_None;
     629             : }
     630             : 
     631             : /*========================================================================
     632             :  *
     633             :  * MemoryLockBytes implementation.
     634             :  *
     635             :  *======================================================================*/
     636             : namespace store
     637             : {
     638             : 
     639             : class MemoryLockBytes :
     640             :     public store::OStoreObject,
     641             :     public store::ILockBytes,
     642             :     private boost::noncopyable
     643             : {
     644             :     /** Representation.
     645             :      */
     646             :     sal_uInt8 * m_pData;
     647             :     sal_uInt32  m_nSize;
     648             :     rtl::Reference< PageData::Allocator > m_xAllocator;
     649             : 
     650             :     /** ILockBytes implementation.
     651             :      */
     652             :     virtual storeError initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize) SAL_OVERRIDE;
     653             : 
     654             :     virtual storeError readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset) SAL_OVERRIDE;
     655             :     virtual storeError writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset) SAL_OVERRIDE;
     656             : 
     657             :     virtual storeError readAt_Impl  (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes) SAL_OVERRIDE;
     658             :     virtual storeError writeAt_Impl (sal_uInt32 nOffset, const void * pBuffer, sal_uInt32 nBytes) SAL_OVERRIDE;
     659             : 
     660             :     virtual storeError getSize_Impl (sal_uInt32 & rnSize) SAL_OVERRIDE;
     661             :     virtual storeError setSize_Impl (sal_uInt32 nSize) SAL_OVERRIDE;
     662             : 
     663             :     virtual storeError flush_Impl() SAL_OVERRIDE;
     664             : 
     665             : public:
     666             :     /** Construction.
     667             :      */
     668             :     MemoryLockBytes();
     669             : 
     670             : protected:
     671             :     /** Destruction.
     672             :      */
     673             :     virtual ~MemoryLockBytes();
     674             : };
     675             : 
     676             : } // namespace store
     677             : 
     678           2 : MemoryLockBytes::MemoryLockBytes()
     679           2 :     : m_pData (0), m_nSize (0), m_xAllocator()
     680           2 : {}
     681             : 
     682           0 : MemoryLockBytes::~MemoryLockBytes()
     683             : {
     684           0 :     rtl_freeMemory (m_pData);
     685           0 : }
     686             : 
     687           2 : storeError MemoryLockBytes::initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize)
     688             : {
     689           2 :     storeError result = PageData::Allocator::createInstance (rxAllocator, nPageSize);
     690           2 :     if (result == store_E_None)
     691             :     {
     692             :         // @see readPageAt_Impl().
     693           2 :         m_xAllocator = rxAllocator;
     694             :     }
     695           2 :     return result;
     696             : }
     697             : 
     698           2 : storeError MemoryLockBytes::readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset)
     699             : {
     700           2 :     if (m_xAllocator.is())
     701             :     {
     702           2 :         PageHolder page (m_xAllocator->construct<PageData>(), m_xAllocator);
     703           2 :         page.swap (rPage);
     704             :     }
     705             : 
     706           2 :     if (!m_xAllocator.is())
     707           0 :         return store_E_InvalidAccess;
     708           2 :     if (!rPage.get())
     709           0 :         return store_E_OutOfMemory;
     710             : 
     711           2 :     PageData * pagedata = rPage.get();
     712           2 :     return readAt_Impl (nOffset, pagedata, pagedata->size());
     713             : }
     714             : 
     715          36 : storeError MemoryLockBytes::writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset)
     716             : {
     717          36 :     PageData const * pagedata = rPage.get();
     718             :     OSL_PRECOND(!(pagedata == 0), "contract violation");
     719          36 :     return writeAt_Impl (nOffset, pagedata, pagedata->size());
     720             : }
     721             : 
     722           2 : storeError MemoryLockBytes::readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes)
     723             : {
     724           2 :     sal_uInt8 const * src_lo = m_pData + nOffset;
     725           2 :     if ((m_pData > src_lo) || (src_lo >= m_pData + m_nSize))
     726           2 :         return store_E_NotExists;
     727             : 
     728           0 :     sal_uInt8 const * src_hi = src_lo + nBytes;
     729           0 :     if ((m_pData > src_hi) || (src_hi > m_pData + m_nSize))
     730           0 :         return store_E_CantRead;
     731             : 
     732           0 :     memcpy (pBuffer, src_lo, (src_hi - src_lo));
     733           0 :     return store_E_None;
     734             : }
     735             : 
     736          38 : storeError MemoryLockBytes::writeAt_Impl (sal_uInt32 nOffset, const void * pBuffer, sal_uInt32 nBytes)
     737             : {
     738          38 :     sal_uInt64 const dst_size = nOffset + nBytes;
     739             :     OSL_PRECOND(dst_size < SAL_MAX_UINT32, "store::ILockBytes::writeAt() contract violation");
     740          38 :     if (dst_size > m_nSize)
     741             :     {
     742          19 :         storeError eErrCode = setSize_Impl (sal::static_int_cast<sal_uInt32>(dst_size));
     743          19 :         if (eErrCode != store_E_None)
     744           0 :             return eErrCode;
     745             :     }
     746             :     SAL_WARN_IF(dst_size > m_nSize, "store", "store::MemoryLockBytes::setSize_Impl() contract violation");
     747             : 
     748          38 :     sal_uInt8 * dst_lo = m_pData + nOffset;
     749          38 :     if (dst_lo >= m_pData + m_nSize)
     750           0 :         return store_E_CantSeek;
     751             : 
     752          38 :     sal_uInt8 * dst_hi = dst_lo + nBytes;
     753          38 :     if (dst_hi > m_pData + m_nSize)
     754           0 :         return store_E_CantWrite;
     755             : 
     756          38 :     memcpy (dst_lo, pBuffer, (dst_hi - dst_lo));
     757          38 :     return store_E_None;
     758             : }
     759             : 
     760          17 : storeError MemoryLockBytes::getSize_Impl (sal_uInt32 & rnSize)
     761             : {
     762          17 :     rnSize = m_nSize;
     763          17 :     return store_E_None;
     764             : }
     765             : 
     766          21 : storeError MemoryLockBytes::setSize_Impl (sal_uInt32 nSize)
     767             : {
     768          21 :     if (nSize != m_nSize)
     769             :     {
     770          19 :         sal_uInt8 * pData = static_cast<sal_uInt8*>(rtl_reallocateMemory (m_pData, nSize));
     771          19 :         if (pData != 0)
     772             :         {
     773          19 :             if (nSize > m_nSize)
     774          19 :                 memset (pData + m_nSize, 0, sal::static_int_cast<size_t>(nSize - m_nSize));
     775             :         }
     776             :         else
     777             :         {
     778           0 :             if (nSize != 0)
     779           0 :                 return store_E_OutOfMemory;
     780             :         }
     781          19 :         m_pData = pData, m_nSize = nSize;
     782             :     }
     783          21 :     return store_E_None;
     784             : }
     785             : 
     786           0 : storeError MemoryLockBytes::flush_Impl()
     787             : {
     788           0 :     return store_E_None;
     789             : }
     790             : 
     791             : /*========================================================================
     792             :  *
     793             :  * ILockBytes factory implementations.
     794             :  *
     795             :  *======================================================================*/
     796             : namespace store
     797             : {
     798             : 
     799             : template< class T > struct ResourceHolder
     800             : {
     801             :     typedef typename T::destructor_type destructor_type;
     802             : 
     803             :     T m_value;
     804             : 
     805         152 :     explicit ResourceHolder (T const & value = T()) : m_value (value) {}
     806         152 :     ~ResourceHolder() { reset(); }
     807             : 
     808         302 :     T & get() { return m_value; }
     809             :     T const & get() const { return m_value; }
     810             : 
     811         300 :     void set (T const & value) { m_value = value; }
     812         152 :     void reset (T const & value = T())
     813             :     {
     814         152 :         T tmp (m_value);
     815         152 :         if (tmp != value)
     816           0 :             destructor_type()(tmp);
     817         152 :         set (value);
     818         152 :     }
     819         148 :     T release()
     820             :     {
     821         148 :         T tmp (m_value);
     822         148 :         set (T());
     823         148 :         return tmp;
     824             :     }
     825             : 
     826             :     ResourceHolder (ResourceHolder & rhs)
     827             :     {
     828             :         set (rhs.release());
     829             :     }
     830             :     ResourceHolder & operator= (ResourceHolder & rhs)
     831             :     {
     832             :         reset (rhs.release());
     833             :         return *this;
     834             :     }
     835             : };
     836             : 
     837             : storeError
     838         150 : FileLockBytes_createInstance (
     839             :     rtl::Reference< ILockBytes > & rxLockBytes,
     840             :     rtl_uString *                  pFilename,
     841             :     storeAccessMode                eAccessMode
     842             : )
     843             : {
     844             :     // Acquire file handle.
     845         150 :     ResourceHolder<FileHandle> xFile;
     846         150 :     storeError result = xFile.get().initialize (pFilename, eAccessMode);
     847         150 :     if (result != store_E_None)
     848           2 :         return result;
     849             : 
     850         148 :     if (eAccessMode == store_AccessReadOnly)
     851             :     {
     852           2 :         ResourceHolder<FileMapping> xMapping;
     853           2 :         if (xMapping.get().initialize (xFile.get().m_handle) == osl_File_E_None)
     854             :         {
     855           0 :             rxLockBytes = new MappedLockBytes (xMapping.get());
     856           0 :             if (!rxLockBytes.is())
     857           0 :                 return store_E_OutOfMemory;
     858           0 :             (void) xFile.release();
     859           0 :             (void) xMapping.release();
     860           2 :         }
     861             :     }
     862         148 :     if (!rxLockBytes.is())
     863             :     {
     864         148 :         rxLockBytes = new FileLockBytes (xFile.get());
     865         148 :         if (!rxLockBytes.is())
     866           0 :             return store_E_OutOfMemory;
     867         148 :         (void) xFile.release();
     868             :     }
     869             : 
     870         148 :     return store_E_None;
     871             : }
     872             : 
     873             : storeError
     874           2 : MemoryLockBytes_createInstance (
     875             :     rtl::Reference< ILockBytes > & rxLockBytes
     876             : )
     877             : {
     878           2 :     rxLockBytes = new MemoryLockBytes();
     879           2 :     if (!rxLockBytes.is())
     880           0 :         return store_E_OutOfMemory;
     881             : 
     882           2 :     return store_E_None;
     883             : }
     884             : 
     885             : } // namespace store
     886             : 
     887             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11