📄 smplfsys.cpp
字号:
resultInitDone =
m_pFileResponse->InitDone(lReturnVal);
lReturnVal = resultInitDone;
DPRINTF(0x5d000000, ("CSFO::Init() "
"-- resultInitDone(0x%x), m_nFd(%d)\n",
resultInitDone, m_nFd));
return (lReturnVal);
}
/************************************************************************
* Method:
* 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_RESULT
CSimpleFileObject::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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -