mmapdatf.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:15k
源码类别:

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: mmapdatf.cpp,v 1.4.36.4 2004/07/09 01:44:23 hubbe Exp $
  3.  * 
  4.  * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
  5.  * 
  6.  * The contents of this file, and the files included with this file,
  7.  * are subject to the current version of the RealNetworks Public
  8.  * Source License (the "RPSL") available at
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed
  10.  * the file under the current version of the RealNetworks Community
  11.  * Source License (the "RCSL") available at
  12.  * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
  13.  * will apply. You may also obtain the license terms directly from
  14.  * RealNetworks.  You may not use this file except in compliance with
  15.  * the RPSL or, if you have a valid RCSL with RealNetworks applicable
  16.  * to this file, the RCSL.  Please see the applicable RPSL or RCSL for
  17.  * the rights, obligations and limitations governing use of the
  18.  * contents of the file.
  19.  * 
  20.  * Alternatively, the contents of this file may be used under the
  21.  * terms of the GNU General Public License Version 2 or later (the
  22.  * "GPL") in which case the provisions of the GPL are applicable
  23.  * instead of those above. If you wish to allow use of your version of
  24.  * this file only under the terms of the GPL, and not to allow others
  25.  * to use your version of this file under the terms of either the RPSL
  26.  * or RCSL, indicate your decision by deleting the provisions above
  27.  * and replace them with the notice and other provisions required by
  28.  * the GPL. If you do not delete the provisions above, a recipient may
  29.  * use your version of this file under the terms of any one of the
  30.  * RPSL, the RCSL or the GPL.
  31.  * 
  32.  * This file is part of the Helix DNA Technology. RealNetworks is the
  33.  * developer of the Original Code and owns the copyrights in the
  34.  * portions it created.
  35.  * 
  36.  * This file, and the files included with this file, is distributed
  37.  * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
  38.  * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
  39.  * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
  40.  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
  41.  * ENJOYMENT OR NON-INFRINGEMENT.
  42.  * 
  43.  * Technology Compatibility Kit Test Suite(s) Location:
  44.  *    http://www.helixcommunity.org/content/tck
  45.  * 
  46.  * Contributor(s):
  47.  * 
  48.  * ***** END LICENSE BLOCK ***** */
  49. #include <stdio.h>
  50. #include <sys/stat.h>
  51. #include <sys/types.h>
  52. #include <fcntl.h>
  53. #include <unistd.h>
  54. #include <errno.h>
  55. #include "hxtypes.h"
  56. #include "hxcom.h"
  57. #include "hxresult.h"
  58. #include "ihxpckts.h"
  59. #include "hxbuffer.h"
  60. #include "debug.h"
  61. #include "hxdataf.h"
  62. #include "datffact.h"
  63. #include "mmapdatf.h"
  64. #include "mmapmgr.h"
  65. #include "filespec.h"
  66. /////////////////////////////////////////////////////////////////////////
  67. //  Method:
  68. //      MemoryMapDataFile::QueryInterface
  69. //  Purpose:
  70. //      Implement this to export the interfaces supported by your
  71. //      object.
  72. //
  73. STDMETHODIMP
  74. MemoryMapDataFile::QueryInterface(REFIID riid, void** ppvObj)
  75. {
  76.     if (IsEqualIID(riid, IID_IHXDataFile))
  77.     {
  78.         AddRef();
  79.         *ppvObj = (IHXDataFile*)this;
  80.         return HXR_OK;
  81.     }
  82.     
  83.     *ppvObj = NULL;
  84.     return HXR_NOINTERFACE;
  85. }   
  86. /////////////////////////////////////////////////////////////////////////
  87. //  Method:
  88. //      MemoryMapDataFile::AddRef
  89. //  Purpose:
  90. //      Everyone usually implements this the same... feel free to use
  91. //      this implementation.
  92. //
  93. STDMETHODIMP_(ULONG32)
  94. MemoryMapDataFile::AddRef()
  95. {
  96.     DPRINTF(0x5d000000, ("UBDF::AddRef() = %ldn", m_lRefCount+1));
  97.     return InterlockedIncrement(&m_lRefCount);
  98. }   
  99. /////////////////////////////////////////////////////////////////////////
  100. //  Method:
  101. //      MemoryMapDataFile::Release
  102. //  Purpose:
  103. //      Everyone usually implements this the same... feel free to use
  104. //      this implementation.
  105. //
  106. STDMETHODIMP_(ULONG32)
  107. MemoryMapDataFile::Release()
  108. {
  109.     DPRINTF(0x5d000000, ("UBDF::Release() = %ldn", m_lRefCount-1));
  110.     if (InterlockedDecrement(&m_lRefCount) > 0)
  111.     {
  112.         return m_lRefCount;
  113.     }
  114.     
  115.     delete this;
  116.     return 0;
  117. }   
  118. MemoryMapDataFile::MemoryMapDataFile(IUnknown* pContext,
  119.     REF(IUnknown*) pPersistantObject, BOOL bDisableMemoryMappedIO,
  120.     UINT32 ulChunkSize, BOOL bEnableFileLocking)
  121. : m_lRefCount(0)
  122. , m_ulLastError(HXR_OK)
  123. , m_pFilename(new CHXBuffer)
  124. , m_nFD(-1)
  125. , m_ulPos(0)
  126. , m_ulFilePointerPos(0)
  127. , MmapHandle(0)
  128. , m_pMMM((MemoryMapManager*)pPersistantObject)
  129. , m_ulChunkSize(ulChunkSize)
  130. , m_bEnableFileLocking(bEnableFileLocking)
  131. , m_bLockedIt(FALSE)
  132. {
  133.     m_pContext = pContext;
  134.     m_pContext->AddRef();
  135.     m_pFilename->AddRef();
  136.     DPRINTF(0x5d000000, ("MemoryMapDataFile::MemoryMapDataFile()n"));
  137.     if (m_pMMM == NULL)
  138.     {
  139. /* Create one Memory Map Manager per process */
  140. m_pMMM = new MemoryMapManager(pContext, bDisableMemoryMappedIO,
  141. m_ulChunkSize);
  142. pPersistantObject = m_pMMM;
  143. pPersistantObject->AddRef();
  144.     }
  145.     m_pMMM->AddRef();
  146. }
  147. // ~CHXFile should close the file if it is open
  148. MemoryMapDataFile::~MemoryMapDataFile()
  149.     // close the file if it is open
  150.     if (m_nFD > 0)
  151.     {
  152.        if (m_bEnableFileLocking)
  153.        {
  154.    UnlockFile();
  155.        }
  156.        close(m_nFD);
  157.        m_nFD = -1;
  158.     }
  159.     HX_RELEASE(m_pFilename);
  160.     HX_RELEASE(m_pMMM);
  161.     HX_RELEASE(m_pContext);
  162.     DPRINTF(0x5d000000, ("MemoryMapDataFile::~MemoryMapDataFile()n"));
  163. }
  164. /*
  165.  *  IHXDataFile methods
  166.  */
  167. /* Bind DataFile Object with FileName */
  168. STDMETHODIMP_(void)
  169. MemoryMapDataFile::Bind(const char* pFilename)
  170. {
  171.     m_pFilename->Set((BYTE *)pFilename, strlen(pFilename)+1);
  172.     DPRINTF(0x5d000000, ("MemoryMapDataFile::Bind(%s)n", 
  173.     (const char *)m_pFilename->GetBuffer()));
  174. }
  175. /* Creates a datafile using the specified mode
  176.  * uOpenMode --- File Open mode - HX_FILEFLAG_READ/HX_FILEFLAG_WRITE/HX_FILEFLAG_BINARY
  177.  */
  178. STDMETHODIMP
  179. MemoryMapDataFile::Create(UINT16 uOpenMode)
  180. {
  181.     return HXR_NOTIMPL;
  182. }
  183. /* Open will open a file with the specified mode
  184.  */
  185. STDMETHODIMP
  186. MemoryMapDataFile::Open(UINT16 uOpenMode)
  187. {
  188.     DPRINTF(0x5d000000, ("MemoryMapDataFile::Open()n"));
  189.     m_ulLastError = HXR_OK;
  190.     int mode = 0;
  191.     if (uOpenMode & HX_FILEFLAG_WRITE)
  192.     {
  193.         mode |= (O_CREAT | O_RDWR);
  194. if (!(uOpenMode & HX_FILEFLAG_NOTRUNC))
  195. {
  196.     mode |= O_TRUNC;
  197. }
  198.     }
  199.     else if (uOpenMode & HX_FILEFLAG_READ)
  200.     {
  201. mode |= O_RDONLY;
  202.     }
  203.     // close previous file if necessary
  204.     if (m_nFD > 0)
  205.     {
  206. if (m_bEnableFileLocking)
  207. {
  208.     UnlockFile();
  209. }
  210. if (close(m_nFD) < 0)
  211.         {
  212.             m_ulLastError = errno;
  213.             return HXR_FAIL;
  214.         }
  215.     }
  216.     // open file
  217.     m_ulLastError = HXR_OK;
  218. #define FILEPERM (S_IREAD | S_IWRITE)
  219.     if ((m_nFD = open((const char *)m_pFilename->GetBuffer(), 
  220. mode, FILEPERM)) < 0)
  221.     {
  222. m_ulLastError = errno;
  223. return HXR_DOC_MISSING;
  224.     }
  225.     // change permissions to allow everyone to read the file and owner to write
  226.     // only if I have to create this file
  227. #ifndef _BEOS
  228.     if (mode & O_CREAT)
  229. fchmod(m_nFD, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
  230. #endif
  231.     if (m_bEnableFileLocking)
  232.     {
  233. BOOL bRet = LockFile();
  234. HX_ASSERT(bRet);
  235.     }
  236.     if (MmapHandle)
  237.     {
  238. m_pMMM->CloseMap(MmapHandle);
  239. MmapHandle = 0;
  240.     }
  241.     MmapHandle = m_pMMM->OpenMap(m_nFD, m_pContext);
  242.     /*
  243.      * XXXSMP
  244.      * This class doesn't need to keep the original file open if we 
  245.      * are using mmap() on the file.
  246.      */
  247.     m_ulPos = 0;
  248.     m_ulFilePointerPos = 0;
  249.     return HXR_OK;
  250. }
  251. /* Delete File */
  252. STDMETHODIMP
  253. MemoryMapDataFile::Delete()
  254. {
  255.     Close();
  256.     if (unlink((const char*)m_pFilename->GetBuffer()) != 0)
  257.     {
  258. return HXR_FAIL;
  259.     }
  260.     return HXR_OK;
  261. }
  262. /* Close closes a file 
  263.  * If the reference count on the IHXDataFile object is greater than 1, 
  264.  * then the underlying file cannot be safely closed, so Close() becomes 
  265.  * a noop in that case. Close it only when the object is destroyed. 
  266.  * This would be safe, but could lead to a file descriptor leak.
  267.  */
  268. STDMETHODIMP
  269. MemoryMapDataFile::Close()
  270. {
  271.     m_ulLastError = HXR_OK;
  272.     if (m_nFD > 0)
  273.     {
  274. if (m_bEnableFileLocking)
  275. {
  276.     UnlockFile();
  277. }
  278. if (close(m_nFD) < 0)
  279.         {
  280.             m_ulLastError = errno;
  281.         }
  282. m_nFD = -1;
  283. if (MmapHandle)
  284. {
  285.     m_pMMM->CloseMap(MmapHandle);
  286.     MmapHandle = 0;
  287. }
  288.     }
  289.     return HXR_OK;
  290. }
  291. /* Name returns the currently bound file name in FileName.
  292.  * and returns TRUE, if the a name has been bound.  Otherwise
  293.  * FALSE is returned.
  294.  */
  295. STDMETHODIMP_(BOOL)
  296. MemoryMapDataFile::Name(REF(IHXBuffer*) pFileName)
  297. {
  298.     return FALSE;
  299. }
  300. /*
  301.  * IsOpen returns TRUE if file is open.  Otherwise FALSE.
  302.  */
  303. inline BOOL
  304. MemoryMapDataFile::IsOpen()
  305. {
  306.     return (m_nFD > 0 ? TRUE : FALSE);
  307. }
  308. /* Seek moves the current file position to the offset from the
  309.  * fromWhere specifier returns current position of file or -1 on
  310.  * error.
  311.  */
  312. STDMETHODIMP
  313. MemoryMapDataFile::Seek(ULONG32 offset, UINT16 fromWhere)
  314. {
  315.     ULONG32 offset2 = 0;
  316.     m_ulLastError = HXR_OK;
  317.     switch (fromWhere)
  318.     {
  319.     case SEEK_CUR:
  320. m_ulPos += offset;
  321. m_ulFilePointerPos += offset;
  322. break;
  323.     case SEEK_SET:
  324. if (((LONG32) offset) < 0)
  325. {
  326.     offset2 = (offset & 0x01);
  327.     offset = (offset >> 1);
  328.     offset2 += offset;
  329. }
  330. m_ulPos = offset;
  331. m_ulFilePointerPos = offset;
  332. break;
  333.     default:
  334. ASSERT(0);
  335. break;
  336.     }
  337.     if (m_nFD > 0)
  338.     {
  339. if (lseek(m_nFD, offset, fromWhere) < 0)
  340. {
  341.     m_ulLastError = errno;
  342.     return HXR_INVALID_FILE;
  343. }
  344. if (offset2 == 0)
  345. {
  346.     return HXR_OK;
  347. }
  348. else
  349. {
  350.     if (((LONG32) offset2) > 0)
  351.     {
  352. return Seek(offset2, SEEK_CUR);
  353.     }
  354. }
  355.     }
  356.     return HXR_INVALID_FILE;
  357. }
  358. /* Tell returns the current file position in the file */
  359. STDMETHODIMP_(ULONG32)
  360. MemoryMapDataFile::Tell()
  361. {
  362.     INT32 offset = -1;
  363.     if (MmapHandle)
  364.     {
  365. return m_ulPos;
  366.     }
  367.     if (m_nFD > 0)
  368.     {
  369. m_ulLastError = HXR_OK;       
  370. // so we do this instead....
  371. if ((offset = lseek(m_nFD, 0, SEEK_CUR)) < 0)
  372. {
  373.     m_ulLastError = errno;
  374. }
  375.     }
  376.     return (ULONG32)offset;
  377. }
  378. void
  379. MemoryMapDataFile::StopMmap()
  380. {
  381.     if (MmapHandle == NULL)
  382. return;
  383.     m_pMMM->CloseMap(MmapHandle);
  384.     MmapHandle = 0;
  385.     Seek(m_ulPos, SEEK_SET);
  386. }
  387. /* Read reads up to count bytes of data into buf.
  388.  * returns the number of bytes read, EOF, or -1 if the read failed 
  389.  */
  390. STDMETHODIMP_(ULONG32)
  391. MemoryMapDataFile::Read(REF(IHXBuffer *) pBuf, ULONG32 count)
  392. {
  393.     UINT32 ncnt = 0;           // number of bytes read
  394.     m_ulLastError = HXR_OK;
  395.     if (MmapHandle)
  396.     {
  397. ncnt = m_pMMM->GetBlock(pBuf, MmapHandle, m_ulPos, count);
  398. if (ncnt >= MMAP_EXCEPTION)
  399. {
  400.     if (ncnt != MMAP_EOF_EXCEPTION)
  401.     {
  402. StopMmap();
  403.     }
  404.     else
  405.     {
  406. Seek(m_ulPos, SEEK_SET);
  407.     }
  408.     goto normal_read;
  409. }
  410. if (ncnt > 0)
  411. {
  412.     m_ulPos += ncnt;
  413.     m_ulFilePointerPos += ncnt;
  414. }
  415. return (ULONG32)ncnt;
  416.     }
  417. normal_read:
  418.     pBuf = new CHXBuffer();
  419.     pBuf->AddRef();
  420.     pBuf->SetSize(count);
  421.     if (m_nFD > 0)
  422.     { 
  423. ULONG32 tmpCheck = Tell();
  424. if (tmpCheck != m_ulPos)
  425. {
  426.     if (lseek(m_nFD, m_ulPos, SEEK_SET) < 0)
  427.             {
  428.                 m_ulLastError = errno;
  429.                 return 0;
  430.             }
  431. }
  432. if ((int)(ncnt = read(m_nFD, (void *)pBuf->GetBuffer(), count)) < 0)
  433. {
  434.     m_ulLastError = errno;
  435.     pBuf->Release();
  436.     pBuf = NULL;
  437.     /*
  438.     * XXX PM Have to return 0 here because it is unsigned
  439.     * return value.
  440.     */
  441.     return 0;
  442. }
  443. else
  444. {
  445.     m_ulPos += ncnt;
  446. }
  447. if (ncnt < count)
  448. {
  449.     pBuf->SetSize(ncnt);
  450. }
  451.     }
  452.     return (ULONG32)ncnt;
  453. }
  454. /* Write writes up to count bytes of data from buf.
  455.  * returns the number of bytes written, or -1 if the write failed 
  456.  */
  457. STDMETHODIMP_(ULONG32)
  458. MemoryMapDataFile::Write(REF(IHXBuffer *) pBuf)
  459. {
  460.     if (m_ulPos != m_ulFilePointerPos)
  461.     {
  462. Seek(m_ulPos, SEEK_SET);
  463.     }
  464.     /*
  465.      * XXXSMP
  466.      * This is silly.  This routine should create a buffer and pass it
  467.      * back, just like read().
  468.      */
  469.     HX_ASSERT(pBuf);
  470.     pBuf->AddRef();
  471.     int ncnt = -1;           // number of bytes written
  472.     int count = pBuf->GetSize();
  473.     if (m_nFD > 0)
  474.     {
  475. m_ulLastError = HXR_OK;
  476. if ((ncnt = write(m_nFD, (const char *)pBuf->GetBuffer(), count)) < 0)
  477. {
  478.     m_ulLastError = errno;
  479. }
  480. else
  481. {
  482.     m_ulPos += ncnt;
  483.     m_ulFilePointerPos += ncnt;
  484. }
  485.     }
  486.     pBuf->Release();
  487.     return (ULONG32)ncnt;
  488. }
  489. /* Flush out the data in case of unbuffered I/O
  490.  */
  491. STDMETHODIMP
  492. MemoryMapDataFile::Flush()
  493. {
  494.     StopMmap();
  495.     return HXR_OK;
  496. }
  497. /*
  498.  * Return info about the data file such as permissions, time of creation
  499.  * size in bytes, etc.
  500.  */
  501. STDMETHODIMP
  502. MemoryMapDataFile::Stat(struct stat* statbuf)
  503. {
  504.     //
  505.     // XXXtbradley : we can't set m_ulLastError in this function because
  506.     // the thing is defined as const
  507.     //
  508.     if (m_nFD > 0)
  509.     {
  510. if (!fstat(m_nFD, statbuf))
  511.     return HXR_OK;
  512.     }
  513.     else if (m_pFilename->GetSize())
  514.     {
  515. if (!stat((const char *)m_pFilename->GetBuffer(), statbuf))
  516.     return HXR_OK;
  517.     }
  518.     //
  519.     // XXXtbradley : so we do this instead
  520.     //
  521.     if (errno == ETIMEDOUT)
  522.     {
  523.         return HXR_SERVER_TIMEOUT;
  524.     }
  525.     return HXR_FAIL;
  526. }
  527. /* Return the file descriptor */
  528. inline INT16
  529. MemoryMapDataFile::GetFd()
  530. {
  531.     return m_nFD;
  532. }
  533. /* GetLastError returns the platform specific file error */
  534. STDMETHODIMP
  535. MemoryMapDataFile::GetLastError()
  536. {
  537.     if (m_ulLastError == ETIMEDOUT)
  538.     {
  539. return HXR_SERVER_TIMEOUT;
  540.     }
  541.     if (m_ulLastError != HXR_OK)
  542.     {
  543. return HXR_FAIL;
  544.     }
  545.     return HXR_OK;
  546. }
  547. /* GetLastError returns the platform specific file error in
  548.  * string form.
  549.  */
  550. STDMETHODIMP_(void)
  551. MemoryMapDataFile::GetLastError(REF(IHXBuffer*) err)
  552. {
  553. }
  554. BOOL
  555. MemoryMapDataFile::LockFile()
  556. {
  557.     struct flock lock;
  558.     lock.l_type = F_RDLCK;
  559.     lock.l_whence = SEEK_SET;
  560.     lock.l_start = 0;
  561.     lock.l_len = 0;
  562.     int ret;
  563.     ret = fcntl(m_nFD, F_SETLK, &lock);
  564.     HX_ASSERT(ret != -1);
  565.     if (ret != -1)
  566.     {
  567. m_bLockedIt = TRUE;
  568.     }
  569.     return m_bLockedIt;
  570. }
  571. BOOL
  572. MemoryMapDataFile::UnlockFile()
  573. {
  574.     if (m_bLockedIt)
  575.     {
  576. struct flock lock;
  577. lock.l_type = F_UNLCK;
  578. lock.l_whence = SEEK_SET;
  579. lock.l_start = 0;
  580. lock.l_len = 0;
  581. fcntl(m_nFD, F_SETLK, &lock);
  582. m_bLockedIt = FALSE;
  583.     }
  584.     return TRUE;
  585. }