mmapdatf.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:14k
源码类别:

Symbian

开发平台:

C/C++

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