various commits from SM4 SVN, courtesy of Glenn and Vyhd.
This commit is contained in:
@@ -0,0 +1,174 @@
|
||||
#include "global.h"
|
||||
#include "RageFileManager_ReadAhead.h"
|
||||
#include "RageThreads.h"
|
||||
#include "RageLog.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <cerrno>
|
||||
#if defined(WIN32)
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_POSIX_FADVISE)
|
||||
void RageFileManagerReadAhead::Init() { }
|
||||
void RageFileManagerReadAhead::Shutdown() { }
|
||||
void RageFileManagerReadAhead::ReadAhead( RageFileBasic *pFile, int iBytes )
|
||||
{
|
||||
int iFD = pFile->GetFD();
|
||||
if( iFD == -1 )
|
||||
return;
|
||||
|
||||
int iStart = lseek( iFD, 0, SEEK_CUR );
|
||||
posix_fadvise( iFD, iStart, iBytes, POSIX_FADV_WILLNEED );
|
||||
}
|
||||
|
||||
#else
|
||||
#if 0
|
||||
/* This doesn't currently work, because dup() locks the file position of the new FD with the old
|
||||
* (which makes no sense at all), so it's not easy to read from a copy of the FD without
|
||||
* interfering with the original. */
|
||||
class RageFileReadAheadThread
|
||||
{
|
||||
public:
|
||||
RageFileReadAheadThread( int iFD, int iFrom, int iBytes )
|
||||
{
|
||||
m_iFD = iFD;
|
||||
m_iFrom = iFrom;
|
||||
m_iBytes = iBytes;
|
||||
m_bFinished = false;
|
||||
|
||||
m_WorkerThread.SetName( "Read-ahead thread" );
|
||||
m_WorkerThread.Create( StartWorkerMain, this );
|
||||
}
|
||||
|
||||
~RageFileReadAheadThread()
|
||||
{
|
||||
close( m_iFD );
|
||||
m_WorkerThread.Wait();
|
||||
}
|
||||
bool IsFinished() const { return m_bFinished; }
|
||||
|
||||
private:
|
||||
static int StartWorkerMain( void *pThis )
|
||||
{
|
||||
((RageFileReadAheadThread *) (pThis))->WorkerMain();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void WorkerMain()
|
||||
{
|
||||
RString sBuffer;
|
||||
int iFDCopy = dup( m_iFD );
|
||||
if( iFDCopy != -1 )
|
||||
{
|
||||
char *pBuf = sBuffer.GetBuffer( m_iBytes );
|
||||
lseek( iFDCopy, m_iFrom, SEEK_SET );
|
||||
read( iFDCopy, pBuf, m_iBytes );
|
||||
sBuffer.ReleaseBuffer( m_iBytes );
|
||||
|
||||
close( iFDCopy );
|
||||
LOG->Trace("read");
|
||||
}
|
||||
|
||||
m_bFinished = true;
|
||||
}
|
||||
|
||||
RageThread m_WorkerThread;
|
||||
|
||||
bool m_bFinished;
|
||||
int m_iFD;
|
||||
int m_iFrom;
|
||||
int m_iBytes;
|
||||
};
|
||||
|
||||
|
||||
static vector<RageFileReadAheadThread *> g_apReadAheads;
|
||||
|
||||
void RageFileManagerReadAhead::Init() { }
|
||||
void RageFileManagerReadAhead::Shutdown()
|
||||
{
|
||||
for( size_t i = 0; i < g_apReadAheads.size(); ++i )
|
||||
delete g_apReadAheads[i];
|
||||
g_apReadAheads.clear();
|
||||
}
|
||||
|
||||
/* This emulates posix_fadvise(POSIX_FADV_WILLNEED), to force data into cache and hint the
|
||||
* kernel to start read-ahead from that point. */
|
||||
void RageFileManagerReadAhead::ReadAhead( RageFileBasic *pFile, int iBytes )
|
||||
{
|
||||
int iFD = pFile->GetFD();
|
||||
if( iFD == -1 )
|
||||
return;
|
||||
|
||||
iFD = dup( iFD );
|
||||
if( iFD == -1 )
|
||||
{
|
||||
LOG->Trace( "error: dup(): %s", strerror(errno) );
|
||||
return;
|
||||
}
|
||||
|
||||
int iStart = lseek( iFD, 0, SEEK_CUR );
|
||||
|
||||
RageFileReadAheadThread *pReadAhead = new RageFileReadAheadThread( iFD, iStart, iBytes );
|
||||
g_apReadAheads.push_back( pReadAhead );
|
||||
|
||||
for( size_t i = 0; i < g_apReadAheads.size(); ++i )
|
||||
{
|
||||
if( g_apReadAheads[i]->IsFinished() )
|
||||
{
|
||||
LOG->Trace("cleaned");
|
||||
delete g_apReadAheads[i];
|
||||
g_apReadAheads.erase( g_apReadAheads.begin()+i, g_apReadAheads.begin()+i+1 );
|
||||
--i;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
void RageFileManagerReadAhead::Init() { }
|
||||
void RageFileManagerReadAhead::Shutdown() { }
|
||||
void RageFileManagerReadAhead::ReadAhead( RageFileBasic *pFile, int iBytes ) { }
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_POSIX_FADVISE)
|
||||
void RageFileManagerReadAhead::CacheHintStreaming( RageFileBasic *pFile )
|
||||
{
|
||||
/* This guesses at the actual size of the file on disk, which may be smaller if this file is compressed.
|
||||
* Since this is usually used on music and video files, it generally shouldn't be. */
|
||||
int iFD = pFile->GetFD();
|
||||
if( iFD == -1 )
|
||||
return;
|
||||
int iPos = pFile->Tell();
|
||||
int iFrom = lseek( iFD, 0, SEEK_CUR );
|
||||
int iBytes = pFile->GetFileSize() - iPos;
|
||||
posix_fadvise( iFD, iFrom, iBytes, POSIX_FADV_SEQUENTIAL );
|
||||
}
|
||||
#else
|
||||
void RageFileManagerReadAhead::CacheHintStreaming( RageFileBasic *pFile ) { }
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Copyright (c) 2010 Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
Reference in New Issue
Block a user