📄 httpfsys.cpp
字号:
if (m_uRecursionCount > 0) { m_uRecursionCount--; }}/************************************************************************ * Method: * IHXFileObject::Read * Purpose: * Reads a buffer of data of the specified length from the file * and asynchronously returns it to the caller via the * IHXFileResponse interface passed in to Init. */STDMETHODIMP CHTTPFileObject::Read(ULONG32 ulCount){ HX_RESULT lResult = HXR_OK; static UINT32 ulReadCount = 0; LOGX((szDbgTemp, "Read #%03lu, Size is %4lu, Recurs is %2u, FileObj is '%s'", ++ulReadCount, ulCount, m_uRecursionCount + 1, NULLOK(m_pFilename))); #ifdef CREATE_LOG_DUMP FILE *fp = fopen(LOG_DUMP_FILE, "a+"); if (fp) { fprintf(fp, "Read %lx from %ld %ld\n", m_pChunkyRes, m_ulCurrentReadPosition, ulCount); fclose(fp); } #endif if (m_LastError) { return m_LastError; } /* It is illegal to call read if a seek is pending */ if (m_bSeekPending) { #ifdef CREATE_LOG_DUMP FILE *fp = fopen(LOG_DUMP_FILE, "a+"); if (fp) { fprintf(fp, "Cancel Read: Seek Pending %lx %ld\n", m_pChunkyRes, ulCount); fclose(fp); } #endif CallReadDone(HXR_SEEK_PENDING ,NULL); return HXR_UNEXPECTED; } /* mark it as a pending read request.. * We do this since a call to readdone may result in a call to read * which may mess up the sequence in which we read data and pass it to * the caller (specially when some reads are pendiing */ m_PendingReadList.AddTail((void*) ulCount); if (m_bInReadDone) { m_uRecursionCount++; } if (m_uRecursionCount > m_uMaxRecursionLevel) { if (m_pCallback && !m_pCallback->m_bCallbackPending) { m_pCallback->m_bCallbackPending = TRUE; m_pCallback->m_ulPendingCallbackID = m_pScheduler->RelativeEnter(m_pCallback, 0); } return HXR_OK; } // This adds greatly to the stack depth when Read()s are recursed --fnh#ifdef _MACINTOSH /* * We do not call ProcessPending reads at interrupt time on Mac * This is because we use ChunkyRes which writes/reads data to * disk. We do not want it to happen at interrupt time since * chunkyres has synchronous interface and it makes synchronous * file io calls. We should someday change chunkyres interface to * be async and also modify it to use aysnc file io to read/write */ if (m_pInterruptState && m_pInterruptState->AtInterruptTime()) { if (m_pCallback && !m_pCallback->m_bCallbackPending) { m_pCallback->m_bCallbackPending = TRUE; m_pCallback->m_ulPendingCallbackID = m_pScheduler->RelativeEnter(m_pCallback, 0); } return HXR_OK; } else { lResult = ProcessPendingReads(); }#else lResult = ProcessPendingReads();#endif return lResult;}/************************************************************************ * Method: * IHXFileObject::Write * Purpose: * Writes a buffer of data to the file and asynchronously notifies * the caller via the IHXFileResponse interface passed in to Init, * of the completeness of the operation. */STDMETHODIMP CHTTPFileObject::Write(IHXBuffer* pBuffer){ HX_RESULT nRetVal = HXR_FAILED; if (m_pSocket && m_nPostDataSize && pBuffer) { nRetVal = m_pSocket->Write(pBuffer); if(nRetVal == HXR_OK) { if(m_nPostDataSize >= pBuffer->GetSize()) m_nPostDataSize -= pBuffer->GetSize(); else m_nPostDataSize = 0; } } return nRetVal;}/************************************************************************ * Method: * IHXFileObject::Seek * Purpose: * Seeks to an offset in the file and asynchronously notifies * the caller via the IHXFileResponse interface passed in to Init, * of the completeness of the operation. */STDMETHODIMP CHTTPFileObject::Seek(ULONG32 ulOffset, BOOL bRelative){ #ifdef CREATE_LOG_DUMP FILE *fp = fopen(LOG_DUMP_FILE, "a+"); if (fp) { fprintf(fp, "Seek %lx %ld\n", m_pChunkyRes, ulOffset); fclose(fp); } #endif if (m_LastError) { return m_LastError; } #ifdef CREATE_LOG_DUMP if (m_PendingReadList.GetCount()) { FILE *fp = fopen(LOG_DUMP_FILE, "a+"); if (fp) { fprintf(fp, "_Reopen %lx pending reads %ld\n", m_pChunkyRes, m_PendingReadList.GetCount()); fclose(fp); } } #endif while (m_PendingReadList.GetCount()) { m_PendingReadList.RemoveHead(); m_pFileResponse->ReadDone(HXR_CANCELLED, NULL); } if (bRelative) { m_ulCurrentReadPosition += ulOffset; } else { m_ulCurrentReadPosition = ulOffset; } /* check if there were any pending reads */ if (m_bSeekPending || m_bReadPending) { #ifdef CREATE_LOG_DUMP FILE *fp = fopen(LOG_DUMP_FILE, "a+"); if (fp) { fprintf(fp, "Cancel Seek: Seek Pending %lx %ld\n", m_pChunkyRes, ulOffset); fclose(fp); } #endif m_bSeekPending = FALSE; m_pFileResponse->SeekDone(HXR_CANCELLED); } if (m_pChunkyRes->HasPartialData(1, m_ulCurrentReadPosition)) { // Don't call SeekDone until we are actaully done with the seek if (m_bSupportsByteRanges) { _EnsureThatWeAreReadingWisely(); // m_bByteRangeSeekPending means we reconnecting the socket // a new location. if (m_bByteRangeSeekPending) m_bSeekPending = TRUE; else { #ifdef CREATE_LOG_DUMP FILE *fp = fopen(LOG_DUMP_FILE, "a+"); if (fp) { fprintf(fp, "SeekDone no reconnect %lx %ld\n", m_pChunkyRes, m_ulCurrentReadPosition); fclose(fp); } #endif m_pFileResponse->SeekDone(HXR_OK); } } else { #ifdef CREATE_LOG_DUMP FILE *fp = fopen(LOG_DUMP_FILE, "a+"); if (fp) { fprintf(fp, "SeekDone %lx %ld\n", m_pChunkyRes, m_ulCurrentReadPosition); fclose(fp); } #endif m_pFileResponse->SeekDone(HXR_OK); } } else { if (m_bSupportsByteRanges) { // signal the caller about the end of content if (m_ulCurrentReadPosition == m_nContentRead) { #ifdef CREATE_LOG_DUMP FILE *fp = fopen(LOG_DUMP_FILE, "a+"); if (fp) { fprintf(fp, "SeekDone Gaps read=write %lx %ld\n", m_pChunkyRes, m_ulCurrentReadPosition); fclose(fp); } #endif m_pFileResponse->SeekDone(HXR_OK); } else if (m_bKnowContentSize && m_ulCurrentReadPosition == m_nContentSize) { #ifdef CREATE_LOG_DUMP FILE *fp = fopen(LOG_DUMP_FILE, "a+"); if (fp) { fprintf(fp, "SeekDone gaps read=end %lx %ld\n", m_pChunkyRes, m_ulCurrentReadPosition); fclose(fp); } #endif m_pFileResponse->SeekDone(HXR_OK); } else { // We need to reconnect if: // 1. The read pointer is behind the write pointer and there are gaps OR // 2. The write pointer is behind the read pointer with too many bytes to simply wait for if (!m_bByteRangeSeekPending) { if (m_ulCurrentReadPosition < m_nContentRead || m_ulCurrentReadPosition - m_nContentRead > BYTE_RANGE_SEEK_THRESHHOLD) { _HandleByteRangeSeek(m_ulCurrentReadPosition); } } m_bSeekPending = TRUE; } } else { /* is it a valid value to seek to?*/ if (m_bReadContentsDone) { // signal the caller about the end of content if (m_ulCurrentReadPosition == m_nContentRead) { m_pFileResponse->SeekDone(HXR_OK); } else { HX_ASSERT(m_ulCurrentReadPosition > m_nContentRead); m_pFileResponse->SeekDone(HXR_FAILED); } } else /* add it to the seek pending queue...*/ { m_bSeekPending = TRUE; } } } return (HXR_OK);}/************************************************************************ * Method: * IHXFileObject::Stat * Purpose: * Collects information about the file that is returned to the * caller in an IHXStat object */STDMETHODIMP CHTTPFileObject::Stat(IHXFileStatResponse* pFileStatResponse){ LOGX ((szDbgTemp, "Stat(%s)", m_pFilename)); /* * XXXGH...Need to get real statistics */ if(!m_bReadHeaderDone) { m_bStatPending = TRUE; m_pFileStatResponse = pFileStatResponse; m_pFileStatResponse->AddRef(); } else { pFileStatResponse->StatDone(HXR_OK, m_nContentSize, 0, 0, 0, 0); } return HXR_OK;}/************************************************************************ * Method: * IHXFileObject::Advise * Purpose: * To pass information to the File Object */STDMETHODIMP CHTTPFileObject::Advise(ULONG32 ulInfo){ HX_RESULT pnr = HXR_OK; // XXXJEFFA it's possible that for cached HTTP we want to // return HXR_OK from this instead of prefer linear since // the file is local in the cache but that's an optimization // we can make later JEFFA 11/8/98 // disable the HTTP1.1 support if the file format // doesn't support async seek(i.e. AVI) if (ulInfo == HXR_ADVISE_NOASYNC_SEEK) { m_bDisableByteRanges = TRUE; m_bSupportsByteRanges = FALSE; } else if (ulInfo == HX_FILEADVISE_RANDOMACCESS) { if (m_bSupportsByteRanges && !IsLiveStream(m_strMimeType)) pnr = HXR_OK; else pnr = HXR_ADVISE_PREFER_LINEAR; } else if (HX_FILEADVISE_RANDOMACCESSONLY == ulInfo) { m_bConvertFailedSeeksToLinear = FALSE; } else if (HX_FILEADVISE_ANYACCESS == ulInfo) { m_bConvertFailedSeeksToLinear = TRUE; } return pnr;}/************************************************************************ * Method: * IHXFileObject::GetFileObjectFromPool * Purpose: * To get another FileObject from the same pool. */STDMETHODIMP CHTTPFileObject::GetFileObjectFromPool( IHXGetFileFromSamePoolResponse* response){ LOGX ((szDbgTemp, "GetFileObjectFromPool(%s)", m_pFilename)); HX_RESULT lReturnVal = HXR_FAIL; CHTTPFileObject* pFileObject = NULL; IUnknown* pUnknown = NULL; CHXString sBaseURL; INT32 nBeforeFile; sBaseURL = m_pFilename; nBeforeFile = max ( sBaseURL.ReverseFind('\\'), sBaseURL.ReverseFind('/') ); if(nBeforeFile > -1) { sBaseURL = sBaseURL.Left(nBeforeFile); pFileObject = CHTTPFileObject::CreateObject(); if (pFileObject) { pFileObject->InitObject ( sBaseURL.GetBuffer(1), m_pFileSystem, m_pContext, m_pOptions ); lReturnVal = pFileObject->QueryInterface ( IID_IUnknown, (void**)&pUnknown ); } else { response->FileObjectReady(HXR_OUTOFMEMORY, NULL); return HXR_OUTOFMEMORY; } } response->FileObjectReady ( lReturnVal == HXR_OK ? HXR_OK : HXR_FAIL, pUnknown ); HX_RELEASE(pUnknown); return lReturnVal;}// IHXFileExists interface/************************************************************************ * Method: * IHXFileExists::DoesExist * Purpose: */STDMETHODIMP CHTTPFileObject::DoesExist( const char* /*IN*/ pPath, IHXFileExistsResponse* /*IN*/ pFileExistsResponse){ LOGX ((szDbgTemp, "DoesExist(%s)", pPath));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -