📄 smplfsys.cpp
字号:
* IHXFileObject::GetFilename * Purpose: * Returns the filename (without any path information) associated * with a file object. */STDMETHODIMP CSimpleFileObject::GetFilename( REF(const char*) /*OUT*/ pFilename){ UpdateFileNameMember(); // Find the separator character before the file name pFilename = ::strrchr(m_pFilename, OS_SEPARATOR_CHAR); if (pFilename != NULL) // Found { // File name starts after the separator charactor pFilename++; } else // Not found { pFilename = m_pFilename; } return HXR_OK;}/************************************************************************ * Method: * IHXFileObject::Close * Purpose: * Closes the file resource and releases all resources associated * with the object. */STDMETHODIMP CSimpleFileObject::Close(){ MLOG_GEN(NULL, "CSimpleFileObject::Close() this=0x%08x\n", this); HX_LOG_BLOCK( "CSimpleFileObject::Close" ); // If there is a pending callback, be sure to remove it! if (m_pStackCallback) m_pStackCallback->Cancel(m_pScheduler); HX_RELEASE(m_pStackCallback); HX_RELEASE(m_pScheduler); HX_RELEASE(m_pUnknownUserContext); if (m_pContext) { m_pContext->Release(); m_pContext = NULL; } if (m_pCommonClassFactory) { m_pCommonClassFactory->Release(); m_pCommonClassFactory = NULL; } if (m_pFileSystem) { m_pFileSystem->Release(); m_pFileSystem = NULL; } if (m_pRequest) { m_pRequest->Release(); m_pRequest = NULL; } if (m_pDescriptorReg && (m_nFd != -1)) { m_pDescriptorReg->UnRegisterDescriptors(1); m_pDescriptorReg->Release(); m_pDescriptorReg = 0; }#if defined(HELIX_FEATURE_PROGDOWN) // XXXMEH // IMPORTANT!! // Since the progressive download monitor does now not // hold a ref on m_pDataFile, then we MUST make sure // and call m_pProgDownMon->Close() BEFORE we close // and release m_pDataFile. This is because there could // be pending callbacks which will attempt to use // the IHXDataFile. Callling m_pProgDownMon->Close() // will cancel these pending callbacks. if (m_pProgDownMon) { // Close the progressive download monitor. Closing // also cancels any pending callbacks m_pProgDownMon->Close(); } HX_DELETE(m_pProgDownMon);#endif /* #if defined(HELIX_FEATURE_PROGDOWN) */ if (m_pDataFile) {#if defined _MACINTOSH HX_RELEASE(m_pDataFile); HX_DELETE(m_pAsyncFileResponse); HX_RELEASE(m_pInterruptState); HX_RELEASE(m_pFileStatResponse);#else DPRINTF(0x5d000000, ("CSFO::Close() -- m_pDataFile->Close()\n")); m_pDataFile->Close(); HX_RELEASE(m_pDataFile);#endif } m_nFd = -1; if(m_pFilename) { HX_VECTOR_DELETE(m_pFilename); m_pFilename = NULL; } if (m_pDirResponse) { m_pDirResponse->Release(); m_pDirResponse = NULL; } if (m_pDirList) { delete m_pDirList; m_pDirList = NULL; } // Make sure we do not attempt to schedule any more replies which // would result in a crash after this point m_bReadPending = FALSE; // It is vitally important that the CloseDone be the last step in // this method, as the last reference to this object may be // released inside CloseDone! Do not place code after this if block! // MBO: Access to stack variables after CloseDone is OK. if (!m_bLocalClose) { if(m_pFileResponse) { // This keeps us from getting into an infinite loop when // CSimpleFileObject::Close() calls m_pFileResponse->Release() // which calls ~CRIFFReader() which calls Close() and so on, // never hitting the line that sets m_pFileResponse to NULL... IHXFileResponse* pTempFileResponse = m_pFileResponse; m_pFileResponse = NULL; pTempFileResponse->CloseDone(HXR_OK); pTempFileResponse->Release(); } } else if (m_pFileResponse) { m_pFileResponse->Release(); m_pFileResponse = NULL; } return HXR_OK;}/************************************************************************ * 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 CSimpleFileObject::Read(ULONG32 ulCount){ MLOG_GEN(NULL, "CSimpleFileObject::Read(%lu) this=0x%08x tick=%lu\n", ulCount, this, HX_GET_BETTERTICKCOUNT()); HX_LOG_BLOCK( "CSimpleFileObject::Read" ); // XXXBHG, For now, you cant read more than 1MB at a time! if (ulCount > 0x000FFFFF) { //Force the system to recognize a failed Read so infinite // buffering does not occur with the core waiting for EOF: ActualAsyncReadDone(HXR_FAIL, NULL); return HXR_INVALID_PARAMETER; } if((m_nFd == -1) && m_bCanBeReOpened) { DPRINTF(0x5d000000, ("CSFO::Read() -- _OpenFile()\n")); _OpenFile(m_ulFlags); m_bCanBeReOpened = FALSE;#ifndef _MACINTOSH m_pDataFile->Seek(m_ulPos, SEEK_SET);#endif } if (m_nFd != -1) { if(!(m_ulFlags & HX_FILE_READ)) return HXR_UNEXPECTED; if (m_bReadPending) { return HXR_UNEXPECTED; } m_bReadPending = TRUE; m_ulPendingReadCount = ulCount; if (m_bInRead && m_bAsyncAccess) { return HXR_OK; } m_bInRead = TRUE; HX_RESULT theErr = HXR_OK; UINT16 uIterationCount; uIterationCount = 0; AddRef(); // Make sure we do not destruct in ReadDone() BOOL bProgFail = FALSE; do { bProgFail = FALSE; theErr = DoRead(bProgFail); uIterationCount++; } while (m_bReadPending && !m_bAsyncReadPending && !theErr && uIterationCount < m_ulMaxIterationLevel && !bProgFail); /* have we exceeded our iteration count? */ if (m_bReadPending && !m_bAsyncReadPending && !theErr && m_bAsyncAccess && !bProgFail) { MLOG_PD(NULL, "\tScheduling stack callback\n"); HX_ASSERT(!m_pStackCallback->IsCallbackPending() && uIterationCount >= m_ulMaxIterationLevel); // Schedule a callback if there is not one already scheduled m_pStackCallback->ScheduleRelative(m_pScheduler, 0); } m_bInRead = FALSE; Release(); return theErr; } return HXR_UNEXPECTED;}HX_RESULTCSimpleFileObject::DoRead(REF(BOOL) rbProgFail){ MLOG_PD(NULL, "CSimpleFileObject::DoRead() this=0x%08x tick=%lu curoffset=%lu\n", this, HX_GET_BETTERTICKCOUNT(), m_ulPos); HX_LOG_BLOCK( "CSimpleFileObject::DoRead" ); HX_ASSERT(m_bReadPending); HX_RESULT theErr = HXR_OK; UINT32 ulCount = m_ulPendingReadCount;#ifndef _MACINTOSH // Create buffer object here, notice that we call the // CreateInstance method of the controller, but we could // have implemented our own object that exposed the IHXBuffer // interface. IHXBuffer* pBuffer = NULL; ULONG32 actual = m_pDataFile->Read(pBuffer, ulCount);#if defined(HELIX_FEATURE_PROGDOWN) MLOG_PD(NULL, "\tulCount = %lu actual = %lu\n", ulCount, actual); // Sanity check. Unlikely we'd even make it here // if we failed to allocate m_pProgDownMon, but // if so, then just behave like HELIX_FEATURE_PROGDOWN // is not defined if (m_pProgDownMon && m_bProgDownEnabled) { // Did we read all the bytes we were asked for? if (actual < ulCount) { MLOG_PD(NULL, "\t\t******** FAILED to read requested bytes\n"); // The read failed to read all the requested bytes // // Do we have a history of progressive download // with this file? if (m_pProgDownMon->HasBeenProgressive()) { MLOG_PD(NULL, "\t\t\tFile HAS been progressive\n"); // This file has been progressive sometime in // the past. However, we need to // check the *current* state. if (m_pProgDownMon->IsProgressive()) { MLOG_PD(NULL, "\t\t\t\tFile currently IS progressive\n"); // The file is still currently downloading. // // Can we callback asynchronously? if (m_bAsyncAccess) { // Set the flag saying we failed due to // progressive download rbProgFail = TRUE; // Schedule the callback return FinishDoReadWithCallback(actual); } else { // Try synchronously return FinishDoReadWithoutCallback(actual); } } else { MLOG_PD(NULL, "\t\t\t\tFile currently is NOT progressive\n"); // The file has been progressive in the past // but the current state is NOT progressive. // That could mean that either the download has // finished or that the download agent is paused. // With our current implementation we can't tell // the difference (we would need to know the "true" // file size to know for sure). Therefore, we will // ask the fileformat whether or not it would "expect" // a failure at this point. The fileformat should have // knowledge to know whether or not a failure of this // read would indicate failure or not. Sometimes fileformats // read in large chunks and *expect* to get a failure. // On the other hand, file formats sometimes do a read // and are NOT expecting it to fail. if (RequireFullRead()) { MLOG_PD(NULL, "\t\t\t\tFileResponse requires full reads\n"); // The response says it requires full reads // // Can we callback asynchronously? if (m_bAsyncAccess) { // Set the flag saying we failed due to // progressive download rbProgFail = TRUE; // Schedule the callback return FinishDoReadWithCallback(actual); } else { // Try synchronously return FinishDoReadWithoutCallback(actual); } } else if (m_pProgDownMon->GetFormerProgressiveRetryCount() > 0) { MLOG_PD(NULL, "\t\t\t\tRetrying former progressive, count = %lu\n", m_pProgDownMon->GetFormerProgressiveRetryCount()); // We do not require a full read, but we are going // to retry a certain number of times before calling // back with ReadDone(). // // Decrement the retry count. If the file becomes // progressive again, then this count gets reset. m_pProgDownMon->DecrementFormerProgressiveRetryCount(); // Can we callback asynchronously? if (m_bAsyncAccess) { // Set the flag saying we failed due to // progressive download rbProgFail = TRUE; // Schedule the callback return FinishDoReadWithCallback(actual); } else { // Try synchronously return FinishDoReadWithoutCallback(actual); } } else { MLOG_PD(NULL, "\t\t\t\tCannot retry former progressive any more\n"); // We have retried on this formerly progressive // file as long as we can, so just call back // with ReadDone(). // // Clear the progressive download failure flag rbProgFail = FALSE; // Finish the DoRead return FinishDoRead(actual, pBuffer); } } } else /* if (m_pProgDownMon->HasBeenProgressive()) */ { MLOG_PD(NULL, "\t\t\tFile has NOT been progressive, checking file size\n"); // This file has never yet been progressive // // Do a filesize check. This will check // the filesize against the filesize at // the time that m_pProgDownMon->Init() // was called. If the filesize has changed, // then the m_pProgDownMon->HasBeenProgressive() // flag will change. m_pProgDownMon->MonitorFileSize(); // Has the filesize changed? if (m_pProgDownMon->HasBeenProgressive()) { MLOG_PD(NULL, "\t\t\t\tFile size HAS changed, beginning size monitoring and retrying\n"); // The filesize has indeed changed. // // Begin the monitoring of the file size m_pProgDownMon->BeginSizeMonitoring(); // Can we callback asynchronously? if (m_bAsyncAccess) { // Set the flag saying we failed due to // progressive download rbProgFail = TRUE; // Schedule the callback return FinishDoReadWithCallback(actual); } else { // Try synchronously return FinishDoReadWithoutCallback(actual); } } else { MLOG_PD(NULL, "\t\t\t\tFile size has NOT changed.\n"); // The filesize has NOT changed. This is most likely // just a normal file and the fileformat has attempted // to read past the end of the file. However, we will // first ask the fileformat if it expected a failure. if (RequireFullRead() && m_pProgDownMon->GetNotProgressiveRetryCount() > 0) { MLOG_PD(NULL, "\t\t\t\t\tRetrying not progressive, count = %lu\n", m_pProgDownMon->GetNotProgressiveRetryCount()); // Decrement the retry count. If the file becomes // progressive, then this count gets reset. m_pProgDownMon->DecrementNotProgressiveRetryCount(); // The fileformat had the Advise interface and // said it did not expect a failure here. Also, // we have not retried our maximum number of attempts // yet, so we will retry the read. // // Can we callback asynchronously? if (m_bAsyncAccess) { // Set the flag saying we failed due to // progressive download rbProgFail = TRUE; // Schedule the callback return FinishDoReadWithCallback(actual); } else { // Try synchronously return FinishDoReadWithoutCallback(actual); } } else { // Either: // a) the fileformat either didn't have the Advise interface; // b) the fileformat did have the interface and said it // was expecting a failure; or // c) the fileformat had the Advise interface and said it // wasn't expecting a failure, but we've retried all the // times we can.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -