2016-03-19 06:57:51 +13:00
# include "tsystem.h"
# include "tcachedlevel.h"
# include "tcodec.h"
# include "texception.h"
//#include "tcachedlevel.h"
//#include "tcodec.h"
# include "tconvert.h"
# ifdef LINUX
# include "texception.h"
//#include "tsystem.h"
# include <unistd.h>
# include <sys/mman.h>
# include <sys/types.h>
# include <sys/stat.h>
# include <fcntl.h>
# endif
# ifdef MACOSX
# include "sys/mman.h"
# include "sys/errno.h"
# endif
//------------------------------------------------------------------------------
# define DWORDLONG_LO_DWORD(dwl64) ((DWORD)(dwl64))
# define DWORDLONG_HI_DWORD(dwl64) ((DWORD)(dwl64 >> 32))
//==============================================================================
//==============================================================================
//==============================================================================
// TDiskCachePersist
//------------------------------------------------------------------------------
class ImpPD
{
public :
ImpPD ( const TFilePath & fn )
: m_fname ( fn ) , m_chunkSize ( 0 ) , m_currentFileSize ( 0 ) , m_fileMapAddress ( 0 ) , m_mapOffset ( 0 )
{
TFileStatus fileStatus ( fn ) ;
if ( fileStatus . doesExist ( ) )
m_currentFileSize = fileStatus . getSize ( ) ;
else
m_currentFileSize = ImpPD : : m_defaultFileSize ;
} ;
virtual ~ ImpPD ( ) { }
virtual void openFile ( const TFilePath & , TINT64 fileSize ) = 0 ;
virtual void setCurrentView ( int pos , int & newLowPos , int & newHiPos ) = 0 ;
TFilePath m_fname ;
TINT64 m_chunkSize ;
TINT64 m_currentFileSize ;
void * m_fileMapAddress ;
TINT64 m_mapOffset ;
// quantita' espresse in byte
static TINT64 m_defaultFileSize ;
TUINT32 m_viewSize ;
TINT64 m_reallocSize ;
} ;
TINT64 ImpPD : : m_defaultFileSize ( 100 * 1024 * 1024 ) ;
//------------------------------------------------------------------------------
class TDiskCachePersist : : Imp
{
public :
Imp ( const TFilePath & fp ) ;
~ Imp ( ) ;
bool put ( int frame , UCHAR * data , TUINT32 dataSize ) ;
UCHAR * get ( int pos , TUINT32 * size ) ;
void openFile ( const TFilePath & fp , TINT64 fileSize ) ;
void setCurrentView ( int frame )
{
if ( ! m_force & & ( ( m_lowFrame < = frame ) & & ( frame < m_hiFrame ) ) )
return ; //la vista corrente gia' copre il frame
m_force = false ;
m_impPD - > setCurrentView ( frame , m_lowFrame , m_hiFrame ) ;
}
ImpPD * m_impPD ;
int m_lowFrame , m_hiFrame ;
TThread : : Mutex m_mutex ;
bool m_force ;
} ;
# ifdef WIN32
class ImpPDW : public ImpPD
{
private :
string getLastErrorMessage ( )
{
LPVOID lpMsgBuf ;
DWORD err = GetLastError ( ) ;
FormatMessage (
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS ,
NULL ,
err ,
MAKELANGID ( LANG_NEUTRAL , SUBLANG_DEFAULT ) , // Default language
( LPTSTR ) & lpMsgBuf ,
0 ,
NULL ) ;
string msg ( ( LPCTSTR ) lpMsgBuf ) ;
// Free the buffer.
LocalFree ( lpMsgBuf ) ;
return msg ;
}
public :
ImpPDW ( const TFilePath & fp ) ;
~ ImpPDW ( ) ;
void openFile ( const TFilePath & fname , TINT64 fileSize ) ;
void setCurrentView ( int pos , int & newLowPos , int & newHiPos ) ;
private :
HANDLE m_hFile ;
HANDLE m_hMap ;
SYSTEM_INFO m_systemInfo ;
} ;
# else
class ImpPDX : public ImpPD
{
private :
class TCachedLevelException : public TException
{
static string msgFromErrorCode ( int errorCode )
{
switch ( errorCode ) {
case EBADF :
return " fd is not a valid file descriptor (and MAP_ANONY MOUS was not set). " ;
break ;
/*
case EACCES_MAP_PRIVATE :
return " Map private was requested, but fd is not open for reading. Or MAP_SHARED was requested and PROT_WRITE is set, but fd is not open in read/write O_RDWR) mode. " ;
break ;
*/
case EINVAL :
return " We don't like start or length or offset. (E.g., they are too large, or not aligned on a PAGESIZE boundary.) " ;
break ;
case ETXTBSY :
return " MAP_DENYWRITE was set but the object specified by fd is open for writing. " ;
break ;
case EAGAIN :
return " The file has been locked, or too much memory has been locked. " ;
break ;
case ENOMEM :
return " No memory is available. " ;
break ;
default :
char * sysErr = strerror ( errorCode ) ;
2016-04-03 12:07:41 +12:00
ostringstream os ;
2016-03-19 06:57:51 +13:00
os < < errorCode < < ' \0 ' ;
os . freeze ( false ) ;
return string ( sysErr ) + " ( " + os . str ( ) + " ) " ;
break ;
}
return " " ;
}
public :
TCachedLevelException ( int errorCode )
: TException ( msgFromErrorCode ( errorCode ) )
{
}
~ TCachedLevelException ( ) { }
} ;
public :
ImpPDX ( const TFilePath & fp ) ;
~ ImpPDX ( ) ;
void openFile ( const TFilePath & fname , TINT64 fileSize ) ;
void setCurrentView ( int pos , int & newLowPos , int & newHiPos ) ;
private :
int m_fd ;
size_t m_pageSize ;
} ;
# endif
// HIGH
//------------------------------------------------------------------------------
TDiskCachePersist : : TDiskCachePersist ( TRasterCodec * codec , const TFilePath & fp )
: TCachePersist ( codec ) , m_imp ( new Imp ( fp ) )
{
}
//------------------------------------------------------------------------------
TDiskCachePersist : : ~ TDiskCachePersist ( )
{
delete m_imp ;
}
//------------------------------------------------------------------------------
void TDiskCachePersist : : setFrameSize ( int lx , int ly , int bpp )
{
m_imp - > m_impPD - > m_chunkSize = lx * ly * ( bpp > > 3 ) + m_codec - > getHeaderSize ( ) ;
m_imp - > m_force = true ;
}
//------------------------------------------------------------------------------
TRasterP TDiskCachePersist : : doGetRaster ( int frame )
{
TRasterP rasP ;
TUINT32 size ;
UCHAR * src = m_imp - > get ( frame , & size ) ;
m_codec - > decompress ( src , size , rasP ) ;
delete [ ] src ;
return rasP ;
}
//------------------------------------------------------------------------------
bool TDiskCachePersist : : doGetRaster ( int frame , TRaster32P & ras ) const
{
assert ( false ) ;
return false ;
}
//------------------------------------------------------------------------------
bool TDiskCachePersist : : doPutRaster ( int frame , const TRasterP & ras )
{
UCHAR * outData = 0 ;
TINT32 outDataSize = 0 ;
m_codec - > compress ( ras , 1 , & outData , outDataSize ) ;
bool cached = m_imp - > put ( frame , outData , outDataSize ) ;
delete [ ] outData ;
return cached ;
}
//------------------------------------------------------------------------------
UCHAR * TDiskCachePersist : : getRawData ( int frame , TINT32 & size , int & lx , int & ly )
{
TUINT32 inDataSize ;
UCHAR * src = m_imp - > get ( frame , & inDataSize ) ;
return m_codec - > removeHeader ( src , inDataSize , size , lx , ly ) ;
}
//------------------------------------------------------------------------------
// MEDIUM
TDiskCachePersist : : Imp : : Imp ( const TFilePath & fp )
: m_impPD ( 0 )
{
# ifdef WIN32
m_impPD = new ImpPDW ( fp ) ;
# else
m_impPD = new ImpPDX ( fp ) ;
# endif
m_impPD - > m_currentFileSize = TFileStatus ( fp ) . doesExist ( ) ? TFileStatus ( fp ) . getSize ( ) : 0 ; // per gli arrotondamenti...
}
//------------------------------------------------------------------------------
TDiskCachePersist : : Imp : : ~ Imp ( )
{
delete m_impPD ;
}
//------------------------------------------------------------------------------
// LOW
# ifdef WIN32
ImpPDW : : ImpPDW ( const TFilePath & fp )
: ImpPD ( fp ) , m_hFile ( 0 ) , m_hMap ( 0 )
{
GetSystemInfo ( & m_systemInfo ) ;
m_viewSize = 100 * 1024 * 1024 ;
m_reallocSize = 250 * 1024 * 1024 ;
TINT64 allocUnitCount = m_reallocSize / m_systemInfo . dwAllocationGranularity ;
// rendo m_reallocSize multiplo di m_systemInfo.dwAllocationGranularity
if ( ( m_reallocSize % m_systemInfo . dwAllocationGranularity ) ! = 0 )
+ + allocUnitCount ;
m_reallocSize = allocUnitCount * m_systemInfo . dwAllocationGranularity ;
TINT64 fileSize = m_defaultFileSize ;
TFileStatus fileStatus ( fp ) ;
if ( fileStatus . doesExist ( ) )
fileSize = fileStatus . getSize ( ) ;
try {
openFile ( fp , fileSize ) ;
} catch ( TException & e ) {
m_currentFileSize = 0 ;
throw e ;
}
m_currentFileSize = fileSize ;
}
//------------------------------------------------------------------------------
ImpPDW : : ~ ImpPDW ( )
{
if ( m_fileMapAddress )
UnmapViewOfFile ( m_fileMapAddress ) ;
CloseHandle ( m_hMap ) ;
CloseHandle ( m_hFile ) ;
}
//------------------------------------------------------------------------------
void ImpPDW : : openFile ( const TFilePath & fname , TINT64 fileSize )
{
DWORD dwDesiredAccess = GENERIC_READ | GENERIC_WRITE ;
DWORD dwShareMode = 0 ; // dwShareMode == 0 --> accesso esclusivo
// lpSecurityAttributes == NULL --> l'handle non puo' essere
// ereditato da processi figli
LPSECURITY_ATTRIBUTES lpSecurityAttributes = NULL ;
DWORD dwCreationDisposition = OPEN_ALWAYS ; //CREATE_ALWAYS;
DWORD dwFlagsAndAttributes = FILE_FLAG_SEQUENTIAL_SCAN ; //FILE_ATTRIBUTE_NORMAL;//
HANDLE hTemplateFile = NULL ;
m_hFile = CreateFileW (
fname . getWideString ( ) . c_str ( ) , // file name
dwDesiredAccess , // access mode
dwShareMode , // share mode
NULL , // SD
dwCreationDisposition , // how to create
dwFlagsAndAttributes , // file attributes
hTemplateFile // handle to template file
) ;
if ( m_hFile = = INVALID_HANDLE_VALUE ) {
string errMsg = getLastErrorMessage ( ) ;
throw TException ( wstring ( L " Unable to open cache file: " ) + fname . getWideString ( ) + L " \n " + toWideString ( errMsg ) ) ;
}
DWORD flProtect = PAGE_READWRITE ;
DWORD dwMaximumSizeHigh = DWORDLONG_HI_DWORD ( fileSize ) ;
DWORD dwMaximumSizeLow = DWORDLONG_LO_DWORD ( fileSize ) ;
LPCTSTR lpName = NULL ; // l'oggetto non ha nome
m_hMap = CreateFileMapping (
m_hFile , // handle to file
NULL , // security
flProtect , // protection
dwMaximumSizeHigh , // high-order DWORD of size
dwMaximumSizeLow , // low-order DWORD of size
lpName // object name
) ;
if ( m_hMap = = NULL ) {
string errMsg = getLastErrorMessage ( ) ;
CloseHandle ( m_hFile ) ;
m_hFile = 0 ;
throw TException ( " Unable to create file mapping. " + errMsg ) ;
}
}
//------------------------------------------------------------------------------
void ImpPDW : : setCurrentView ( int frame , int & newLowFrame , int & newHiFrame )
{
if ( m_fileMapAddress )
UnmapViewOfFile ( m_fileMapAddress ) ;
newLowFrame = frame ;
newHiFrame = newLowFrame + TINT32 ( m_viewSize / m_chunkSize ) ;
DWORD allocGranularity = m_systemInfo . dwAllocationGranularity ;
TINT64 viewOffset = ( TINT64 ( newLowFrame * m_chunkSize ) / allocGranularity ) * allocGranularity ;
m_mapOffset = newLowFrame * m_chunkSize - viewOffset ;
TINT64 fileSize = newHiFrame * m_chunkSize ;
if ( ( fileSize > m_currentFileSize ) | | ! m_hMap ) // devo riallocare!
{
CloseHandle ( m_hMap ) ;
m_hMap = 0 ;
CloseHandle ( m_hFile ) ;
m_hFile = 0 ;
TINT64 allocUnitCount = fileSize / m_reallocSize ;
// rendo fileSize multiplo di m_reallocSize
if ( ( fileSize % m_reallocSize ) ! = 0 )
+ + allocUnitCount ;
fileSize = allocUnitCount * m_reallocSize ;
openFile ( m_fname , fileSize ) ;
m_currentFileSize = fileSize ;
}
DWORD dwDesiredAccess = FILE_MAP_WRITE ;
m_fileMapAddress = MapViewOfFile ( m_hMap , // handle to file-mapping object
dwDesiredAccess , // access mode: Write permission
DWORDLONG_HI_DWORD ( viewOffset ) , // high-order DWORD of offset: Max. object size.
DWORDLONG_LO_DWORD ( viewOffset ) , // low-order DWORD of offset: Size of hFile.
m_viewSize ) ; // number of bytes to map
if ( m_fileMapAddress = = NULL ) {
string errMsg = getLastErrorMessage ( ) ;
CloseHandle ( m_hMap ) ;
m_hMap = 0 ;
CloseHandle ( m_hFile ) ;
m_hFile = 0 ;
throw TException ( " Unable to memory map cache file. " + errMsg ) ;
}
}
# else
ImpPDX : : ImpPDX ( const TFilePath & fp )
: ImpPD ( fp ) , m_fd ( - 1 )
{
//std::cout << "cache file " << toString(m_fname.getFullPath()) << std::endl;
m_pageSize = getpagesize ( ) ;
openFile ( m_fname , 0 ) ;
assert ( m_fd > = 0 ) ;
}
//------------------------------------------------------------------------------
ImpPDX : : ~ ImpPDX ( )
{
if ( m_fileMapAddress )
munmap ( m_fileMapAddress , m_viewSize ) ;
close ( m_fd ) ;
m_fd = 0 ;
}
//------------------------------------------------------------------------------
void ImpPDX : : openFile ( const TFilePath & fname , TINT64 fileSize )
{
assert ( 0 ) ;
/*
string fn ( toString ( fname . getWideString ( ) ) ) ;
std : : cout < < " open " < < fn < < std : : endl ;
m_fd = open ( fn . c_str ( ) , O_RDWR | O_CREAT , 00666 ) ;
assert ( m_fd > = 0 ) ;
*/
}
void ImpPDX : : setCurrentView ( int pos , int & newLowPos , int & newHiPos )
{
newLowPos = pos ;
newHiPos = newLowPos + ( m_viewSize / m_chunkSize ) ;
assert ( m_fd > = 0 ) ;
if ( m_fileMapAddress ) //previous view...
if ( munmap ( m_fileMapAddress , m_viewSize ) ! = 0 )
throw TCachedLevelException ( errno ) ;
void * start = 0 ;
int flags = MAP_SHARED ;
size_t viewOffset = ( ( newLowPos * m_chunkSize ) / m_pageSize ) * m_pageSize ;
m_mapOffset = newLowPos * m_chunkSize - viewOffset ;
assert ( ! " controllare le dimensioni " ) ;
unsigned long lastByte = ( unsigned long ) ( ( ( newHiPos * m_chunkSize ) / ( double ) m_pageSize + 0.5 ) * m_pageSize ) ;
if ( lastByte > m_currentFileSize ) // devo riallocare!
{
unsigned long bu = ( unsigned long ) ( ( lastByte / ( double ) m_reallocSize + 0.5 ) * m_reallocSize ) ;
bu = ( unsigned long ) ( ( bu / ( double ) m_pageSize + 0.5 ) * m_pageSize ) ;
//m_maxFileSize = tmax(m_maxFileSize + m_reallocFileSize, lastByte);
m_currentFileSize + = bu ;
std : : cout < < " new cache size " < < m_currentFileSize < < std : : endl ;
if ( lseek ( m_fd , m_currentFileSize , SEEK_SET ) = = - 1 )
throw TCachedLevelException ( errno ) ;
if ( write ( m_fd , " " , 1 ) = = - 1 )
throw TCachedLevelException ( errno ) ;
if ( ftruncate ( m_fd , m_currentFileSize ) = = - 1 )
throw TCachedLevelException ( errno ) ;
}
m_fileMapAddress = mmap ( start , m_viewSize , PROT_READ | PROT_WRITE , flags , m_fd , viewOffset ) ;
if ( m_fileMapAddress = = ( void * ) - 1 )
throw TCachedLevelException ( errno ) ;
}
# endif
//------------------------------------------------------------------------------
# ifndef WIN32
# define ULONGLONG unsigned long long
# endif
bool TDiskCachePersist : : Imp : : put ( int frame , UCHAR * data , TUINT32 dataSize )
{
if ( dataSize ! = m_impPD - > m_chunkSize )
return false ;
TThread : : ScopedLock sl ( m_mutex ) ;
setCurrentView ( frame ) ;
ULONGLONG offset = ( frame - m_lowFrame ) * m_impPD - > m_chunkSize ;
UCHAR * dst = ( UCHAR * ) m_impPD - > m_fileMapAddress + offset ;
memcpy ( dst + m_impPD - > m_mapOffset , data , dataSize ) ;
return true ;
}
//------------------------------------------------------------------------------
UCHAR * TDiskCachePersist : : Imp : : get ( int pos , TUINT32 * size )
{
UCHAR * ret = new UCHAR [ TINT32 ( m_impPD - > m_chunkSize ) ] ;
TThread : : ScopedLock sl ( m_mutex ) ;
setCurrentView ( pos ) ;
ULONGLONG offset = ( pos - m_lowFrame ) * m_impPD - > m_chunkSize ;
UCHAR * src = ( UCHAR * ) m_impPD - > m_fileMapAddress + offset + m_impPD - > m_mapOffset ;
memcpy ( ret , src , TINT32 ( m_impPD - > m_chunkSize ) ) ;
* size = TUINT32 ( m_impPD - > m_chunkSize ) ;
return ret ;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// TRasterCache
//------------------------------------------------------------------------------
class TRasterCache : : Data
{
public :
Data ( TCachePersist * cp )
: m_cp ( cp ) , m_size ( 0 , 0 ) , m_prefetchEnabled ( false ) , m_prefetchedFrame ( - 1 ) , m_frameToPrefetch ( - 1 ) , m_preLoader ( 1 , true )
{
}
~ Data ( ) { }
class FrameData
{
public :
bool m_valid ;
// int m_size; // dimensione in byte del raster codificato
~ FrameData ( ) { }
} ;
bool isFrameCached ( int frame ) const ;
TDimension m_size ; // dimensioni dei raster in cache
int m_bpp ;
typedef map < int , FrameData > Status ;
Status m_status ;
TCachePersist * m_cp ;
TThread : : Mutex m_accessMutex ;
TThread : : Executor m_preLoader ;
bool m_prefetchEnabled ;
int m_prefetchedFrame ;
int m_frameToPrefetch ;
TRasterP m_prefetchedRas ;
} ;
bool TRasterCache : : Data : : isFrameCached ( int frame ) const
{
// volutamente senza ScopedLock
Data : : Status : : const_iterator it = m_status . find ( frame ) ;
if ( it = = m_status . end ( ) )
return false ;
Data : : FrameData fd = it - > second ;
return fd . m_valid ;
}
//==============================================================================
namespace
{
class Load : public TThread : : Runnable
{
public :
Load ( int frameToPrefetch , TCachePersist * cp , int & prefetchedFrame , TRasterP & prefetchedRas )
: m_frame ( frameToPrefetch ) , m_cp ( cp ) , m_prefetchedFrame ( prefetchedFrame ) , m_prefetchedRas ( prefetchedRas ) { }
void run ( ) ;
private :
int m_frame ;
TCachePersist * m_cp ;
int & m_prefetchedFrame ;
TRasterP & m_prefetchedRas ;
} ;
void Load : : run ( )
{
m_prefetchedRas = m_cp - > doGetRaster ( m_frame ) ;
m_prefetchedFrame = m_frame ;
}
} ;
//==============================================================================
TRasterCache : : TRasterCache ( TCachePersist * cp )
: m_data ( new Data ( cp ) )
{
}
//------------------------------------------------------------------------------
TRasterCache : : ~ TRasterCache ( )
{
delete m_data ;
}
//------------------------------------------------------------------------------
void TRasterCache : : setMode ( const TDimension & size , int bpp )
{
TThread : : ScopedLock sl ( m_data - > m_accessMutex ) ;
m_data - > m_size = size ; // dimensioni dei raster in cache
m_data - > m_bpp = bpp ;
m_data - > m_cp - > setFrameSize ( size . lx , size . ly , bpp ) ;
invalidate ( ) ;
}
//------------------------------------------------------------------------------
void TRasterCache : : getMode ( TDimension & size , int & bpp ) const
{
size = m_data - > m_size ; // dimensioni dei raster in cache
bpp = m_data - > m_bpp ;
}
//------------------------------------------------------------------------------
TRasterP TRasterCache : : getRaster ( int frame ) const
{
TThread : : ScopedLock sl ( m_data - > m_accessMutex ) ;
if ( m_data - > m_prefetchEnabled ) {
/*
if ( frame = = m_data - > m_frameToPrefetch )
m_data - > m_preLoader . wait ( ) ;
else
*/
{
m_data - > m_preLoader . clear ( ) ;
//m_data->m_preLoader.cancel();
}
TRasterP ras ;
if ( frame = = m_data - > m_prefetchedFrame )
ras = m_data - > m_prefetchedRas ;
else
ras = m_data - > m_cp - > doGetRaster ( frame ) ;
if ( isFrameCached ( frame + 1 ) ) {
// il frame successivo a quello richiesto e' nella cache
// -> avvia il prefetch di tale raster
m_data - > m_frameToPrefetch = frame + 1 ;
m_data - > m_preLoader . addTask (
new Load ( m_data - > m_frameToPrefetch , m_data - > m_cp ,
m_data - > m_prefetchedFrame , m_data - > m_prefetchedRas ) ) ;
}
return ras ;
} else {
return m_data - > m_cp - > doGetRaster ( frame ) ;
}
}
//------------------------------------------------------------------------------
bool TRasterCache : : getRaster ( int frame , TRaster32P & ras ) const
{
TThread : : ScopedLock sl ( m_data - > m_accessMutex ) ;
if ( m_data - > isFrameCached ( frame ) ) {
bool rc = m_data - > m_cp - > doGetRaster ( frame , ras ) ;
assert ( rc ) ;
return true ;
} else
return false ;
}
//------------------------------------------------------------------------------
void TRasterCache : : putRaster ( int frame , const TRasterP & ras )
{
TThread : : ScopedLock sl ( m_data - > m_accessMutex ) ;
Data : : Status : : iterator it = m_data - > m_status . find ( frame ) ;
bool cached = false ;
try {
cached = m_data - > m_cp - > doPutRaster ( frame , ras ) ;
} catch ( TException & e ) {
if ( it ! = m_data - > m_status . end ( ) ) {
Data : : FrameData fd ;
fd . m_valid = false ;
m_data - > m_status [ frame ] = fd ;
}
throw e ;
}
if ( cached ) {
Data : : FrameData fd ;
fd . m_valid = true ;
m_data - > m_status [ frame ] = fd ;
}
}
//------------------------------------------------------------------------------
UCHAR * TRasterCache : : getRawData ( int frame , TINT32 & size , int & lx , int & ly ) const
{
return m_data - > m_cp - > getRawData ( frame , size , lx , ly ) ;
}
//------------------------------------------------------------------------------
bool TRasterCache : : isFrameCached ( int frame ) const
{
TThread : : ScopedLock sl ( m_data - > m_accessMutex ) ;
return m_data - > isFrameCached ( frame ) ;
}
//------------------------------------------------------------------------------
void TRasterCache : : invalidate ( )
{
TThread : : ScopedLock sl ( m_data - > m_accessMutex ) ;
m_data - > m_status . clear ( ) ;
m_data - > m_cp - > onInvalidate ( ) ;
}
//------------------------------------------------------------------------------
void TRasterCache : : invalidate ( int startFrame , int endFrame )
{
assert ( startFrame < = endFrame ) ;
TThread : : ScopedLock sl ( m_data - > m_accessMutex ) ;
Data : : Status : : iterator low = m_data - > m_status . lower_bound ( startFrame ) ;
Data : : Status : : iterator hi = m_data - > m_status . upper_bound ( endFrame ) ;
# ifdef _DEBUG
int count = m_data - > m_status . size ( ) ;
if ( low ! = m_data - > m_status . end ( ) & & hi ! = m_data - > m_status . end ( ) ) {
int ll = low - > first ;
int hh = hi - > first ;
assert ( ll < = hh ) ;
}
# endif
if ( low ! = m_data - > m_status . end ( ) ) {
m_data - > m_status . erase ( low , hi ) ;
m_data - > m_cp - > onInvalidate ( startFrame , endFrame ) ;
}
}
//------------------------------------------------------------------------------
void TRasterCache : : enablePrefetch ( bool newState )
{
m_data - > m_prefetchEnabled = newState ;
}
//------------------------------------------------------------------------------
bool TRasterCache : : isPrefetchEnabled ( ) const
{
return m_data - > m_prefetchEnabled ;
}
//------------------------------------------------------------------------------
TUINT64 TRasterCache : : getUsedSpace ( )
{
return m_data - > m_cp - > getUsedSpace ( ) ;
}
//==============================================================================
//==============================================================================
//==============================================================================
// TRamCachePersist
//------------------------------------------------------------------------------
class TRamCachePersist : : Imp
{
friend class TRamCachePersist ;
public :
Imp ( )
: m_cacheSize ( 0 ) , m_chunks ( )
{
}
~ Imp ( )
{
for ( CompressedChunks : : iterator it = m_chunks . begin ( ) ; it ! = m_chunks . end ( ) ; + + it ) {
CompressedChunk * cc = it - > second ;
m_cacheSize - = cc - > m_size ;
delete cc ;
}
assert ( m_cacheSize = = 0 ) ; // se m_cacheSize > 0 mi sono perso qualche chunk
// se m_cacheSize < 0 ho liberato 2 volte qualche chunk
m_chunks . clear ( ) ;
}
class CompressedChunk
{
public :
CompressedChunk ( UCHAR * buffer , int size ) : m_buffer ( buffer ) , m_size ( size ) { }
~ CompressedChunk ( )
{
delete [ ] m_buffer ;
}
UCHAR * m_buffer ;
int m_size ;
} ;
typedef map < int , CompressedChunk * > CompressedChunks ;
CompressedChunks m_chunks ;
TUINT64 m_cacheSize ;
} ;
TRamCachePersist : : TRamCachePersist ( TRasterCodec * codec )
: TCachePersist ( codec ) , m_imp ( new Imp )
{
}
//------------------------------------------------------------------------------
TRamCachePersist : : ~ TRamCachePersist ( )
{
delete m_imp ;
}
//------------------------------------------------------------------------------
TRasterP TRamCachePersist : : doGetRaster ( int frame )
//void TRamCachePersist::doGetRaster(int frame, const TRasterP &ras)
{
Imp : : CompressedChunks : : const_iterator it = m_imp - > m_chunks . find ( frame ) ;
if ( it = = m_imp - > m_chunks . end ( ) )
return TRasterP ( ) ;
Imp : : CompressedChunk * cc = it - > second ;
assert ( cc ) ;
TRasterP rasP ;
m_codec - > decompress ( cc - > m_buffer , cc - > m_size , rasP ) ;
return rasP ;
}
//------------------------------------------------------------------------------
bool TRamCachePersist : : doGetRaster ( int frame , TRaster32P & ras ) const
{
Imp : : CompressedChunks : : const_iterator it = m_imp - > m_chunks . find ( frame ) ;
if ( it = = m_imp - > m_chunks . end ( ) )
return false ;
Imp : : CompressedChunk * cc = it - > second ;
assert ( cc ) ;
TRasterP rasP ( ras ) ;
m_codec - > decompress ( cc - > m_buffer , cc - > m_size , rasP ) ;
return true ;
}
//------------------------------------------------------------------------------
bool TRamCachePersist : : doPutRaster ( int frame , const TRasterP & ras )
{
Imp : : CompressedChunks : : iterator it = m_imp - > m_chunks . find ( frame ) ;
if ( it ! = m_imp - > m_chunks . end ( ) ) {
m_imp - > m_cacheSize - = it - > second - > m_size ;
delete it - > second ;
m_imp - > m_chunks . erase ( it ) ;
}
UCHAR * outData = 0 ;
TINT32 outDataSize = 0 ;
m_codec - > compress ( ras , 1 , & outData , outDataSize ) ;
m_imp - > m_cacheSize + = outDataSize ;
Imp : : CompressedChunk * cc = new Imp : : CompressedChunk ( outData , outDataSize ) ;
m_imp - > m_chunks . insert ( Imp : : CompressedChunks : : value_type ( frame , cc ) ) ;
return true ;
}
//------------------------------------------------------------------------------
void TRamCachePersist : : onInvalidate ( )
{
for ( Imp : : CompressedChunks : : iterator it = m_imp - > m_chunks . begin ( ) ;
it ! = m_imp - > m_chunks . end ( ) ;
+ + it ) {
Imp : : CompressedChunk * cc = it - > second ;
m_imp - > m_cacheSize - = cc - > m_size ;
delete cc ;
}
m_imp - > m_chunks . clear ( ) ;
}
//------------------------------------------------------------------------------
void TRamCachePersist : : onInvalidate ( int startFrame , int endFrame )
{ // ottimizzabile
assert ( startFrame < = endFrame ) ;
for ( int frame = startFrame ; frame < = endFrame ; + + frame ) {
Imp : : CompressedChunks : : iterator it = m_imp - > m_chunks . find ( frame ) ;
if ( it ! = m_imp - > m_chunks . end ( ) ) {
m_imp - > m_cacheSize - = it - > second - > m_size ;
delete it - > second ;
m_imp - > m_chunks . erase ( it ) ;
}
}
}
//------------------------------------------------------------------------------
UCHAR * TRamCachePersist : : getRawData ( int frame , TINT32 & size , int & lx , int & ly )
{
Imp : : CompressedChunks : : const_iterator it = m_imp - > m_chunks . find ( frame ) ;
if ( it = = m_imp - > m_chunks . end ( ) )
return 0 ;
Imp : : CompressedChunk * cc = it - > second ;
assert ( cc ) ;
return m_codec - > removeHeader ( cc - > m_buffer , cc - > m_size , size , lx , ly ) ;
}
//------------------------------------------------------------------------------
TUINT64 TRamCachePersist : : getUsedSpace ( )
{
return m_imp - > m_cacheSize ;
}
//------------------------------------------------------------------------------
void TDiskCachePersist : : onInvalidate ( )
{
//m_imp->m_chunkSize = 0;
}
//------------------------------------------------------------------------------
void TDiskCachePersist : : onInvalidate ( int startFrame , int endFrame )
{
//m_imp->m_chunkSize = 0;
}
//------------------------------------------------------------------------------
TUINT64 TDiskCachePersist : : getUsedSpace ( )
{
assert ( 0 ) ;
return 0 ;
}
//==============================================================================
//==============================================================================
//==============================================================================
//
// TDiskCachePersist2
//
//------------------------------------------------------------------------------
# ifdef WIN32
namespace
{
class ZFile
{
public :
ZFile ( const TFilePath & fp , bool directIO , bool asyncIO ) ;
~ ZFile ( ) ;
void open ( ) ;
int read ( BYTE buf [ ] , int size , TINT64 qwOffset ) const ;
int write ( BYTE buf [ ] , int size , TINT64 qwOffset ) const ;
void waitForAsyncIOCompletion ( ) const ;
TFilePath getFilePath ( ) const
{
return m_filepath ;
}
int getBytesPerSector ( ) const
{
return m_bytesPerSector ;
}
static void CALLBACK FileIOCompletionRoutine (
DWORD errCode ,
DWORD byteTransferred ,
LPOVERLAPPED overlapped ) ;
private :
TFilePath m_filepath ;
bool m_directIO ;
bool m_asyncIO ;
DWORD m_bytesPerSector ;
HANDLE m_fileHandle ;
HANDLE m_writeNotPending ;
} ;
//-----------------------------------------------------------------------------
ZFile : : ZFile ( const TFilePath & fp , bool directIO , bool asyncIO )
: m_filepath ( fp ) , m_directIO ( directIO ) , m_asyncIO ( asyncIO ) , m_fileHandle ( 0 ) , m_writeNotPending ( 0 )
{
DWORD sectorsPerCluster ;
DWORD numberOfFreeClusters ;
DWORD totalNumberOfClusters ;
TFilePathSet disks = TSystem : : getDisks ( ) ;
TFilePath disk = fp ;
while ( std : : find ( disks . begin ( ) , disks . end ( ) , disk ) = = disks . end ( ) )
disk = disk . getParentDir ( ) ;
BOOL ret = GetDiskFreeSpaceW (
disk . getWideString ( ) . c_str ( ) , // root path
& sectorsPerCluster , // sectors per cluster
& m_bytesPerSector , // bytes per sector
& numberOfFreeClusters , // free clusters
& totalNumberOfClusters // total clusters
) ;
if ( m_asyncIO )
m_writeNotPending = CreateEvent ( NULL , TRUE , TRUE , NULL ) ;
}
//-----------------------------------------------------------------------------
ZFile : : ~ ZFile ( )
{
if ( m_fileHandle )
CloseHandle ( m_fileHandle ) ;
if ( m_writeNotPending )
CloseHandle ( m_writeNotPending ) ;
}
//-----------------------------------------------------------------------------
void ZFile : : open ( )
{
DWORD flagsAndAttributes = 0 ;
flagsAndAttributes = m_directIO ? FILE_FLAG_NO_BUFFERING : 0UL ;
flagsAndAttributes | = m_asyncIO ? FILE_FLAG_OVERLAPPED : 0UL ;
// Open the file for write access.
m_fileHandle = CreateFileW ( m_filepath . getWideString ( ) . c_str ( ) ,
GENERIC_READ | GENERIC_WRITE , // Read/Write access
0 , // no sharing allowed
NULL , // no security
OPEN_ALWAYS , // open it or create new if it doesn't exist
flagsAndAttributes ,
NULL ) ; // ignored
if ( m_fileHandle = = INVALID_HANDLE_VALUE ) {
m_fileHandle = 0 ;
char errorMessage [ 2048 ] ;
DWORD error = GetLastError ( ) ;
FormatMessage ( FORMAT_MESSAGE_FROM_SYSTEM , 0UL , error ,
MAKELANGID ( LANG_NEUTRAL , SUBLANG_DEFAULT ) , errorMessage , 2048 , NULL ) ;
throw TException ( errorMessage ) ;
}
}
//-----------------------------------------------------------------------------
int ZFile : : read ( BYTE buf [ ] , int size , TINT64 qwOffset ) const
{
assert ( size % m_bytesPerSector = = 0 ) ;
assert ( qwOffset % m_bytesPerSector = = 0 ) ;
char msg [ 2048 ] = " " ;
unsigned long bytesToRead ; // Padded number of bytes to read.
unsigned long bytesRead ; // count of bytes actually read
OVERLAPPED overLapped ;
memset ( & overLapped , 0 , sizeof ( overLapped ) ) ;
# define DWORDLONG_LO_DWORD(dwl64) ((DWORD)(dwl64))
# define DWORDLONG_HI_DWORD(dwl64) ((DWORD)(dwl64 >> 32))
// set the overlapped stucture with the offsets
overLapped . Offset = DWORDLONG_LO_DWORD ( qwOffset ) ;
overLapped . OffsetHigh = DWORDLONG_HI_DWORD ( qwOffset ) ;
if ( m_asyncIO ) {
overLapped . hEvent = CreateEvent (
NULL , // SD
TRUE , // manual reset
FALSE , // initial state is not signaled
NULL ) ; // object name
} else
overLapped . hEvent = NULL ;
bytesToRead = size ;
// Read a bunch of bytes and store in buf
int result = ReadFile (
m_fileHandle , // file handle
( void * ) buf , // buffer to store data
bytesToRead , // num bytes to read
& bytesRead , // bytes read
& overLapped ) ; // stucture for file offsets
if ( ! result ) {
DWORD error = GetLastError ( ) ;
if ( m_asyncIO & & ERROR_IO_PENDING = = error ) {
if ( ! GetOverlappedResult ( m_fileHandle , & overLapped , & bytesRead , TRUE ) ) {
char errorMessage [ 2048 ] ;
FormatMessage ( FORMAT_MESSAGE_FROM_SYSTEM , 0UL , error ,
MAKELANGID ( LANG_NEUTRAL , SUBLANG_DEFAULT ) , errorMessage , 2048 , NULL ) ;
throw TException ( errorMessage ) ;
}
} else {
char errorMessage [ 2048 ] ;
FormatMessage ( FORMAT_MESSAGE_FROM_SYSTEM , 0UL , error ,
MAKELANGID ( LANG_NEUTRAL , SUBLANG_DEFAULT ) , errorMessage , 2048 , NULL ) ;
throw TException ( errorMessage ) ;
}
}
return bytesRead ;
}
//-----------------------------------------------------------------------------
int ZFile : : write ( BYTE buf [ ] , int size , TINT64 qwOffset ) const
{
assert ( size % m_bytesPerSector = = 0 ) ;
assert ( qwOffset % m_bytesPerSector = = 0 ) ;
char msg [ 2048 ] = " " ;
unsigned long bytesToWrite ; // Padded number of bytes to write.
unsigned long bytesWritten = 0 ; // count of bytes actually writtten
int result ;
if ( m_asyncIO ) {
OVERLAPPED * overLapped = new OVERLAPPED ;
memset ( overLapped , 0 , sizeof ( OVERLAPPED ) ) ;
// set the overlapped stucture with the offsets
overLapped - > Offset = DWORDLONG_LO_DWORD ( qwOffset ) ;
overLapped - > OffsetHigh = DWORDLONG_HI_DWORD ( qwOffset ) ;
overLapped - > hEvent = NULL ;
bytesToWrite = size ;
result = WriteFileEx (
m_fileHandle , // file handle
( void * ) buf , // data buffer
bytesToWrite , // num bytes to write
overLapped , // stucture for file offsets
& ZFile : : FileIOCompletionRoutine ) ;
ResetEvent ( m_writeNotPending ) ;
} else {
OVERLAPPED overLapped ;
memset ( & overLapped , 0 , sizeof ( overLapped ) ) ;
// set the overlapped stucture with the offsets
overLapped . Offset = DWORDLONG_LO_DWORD ( qwOffset ) ;
overLapped . OffsetHigh = DWORDLONG_HI_DWORD ( qwOffset ) ;
overLapped . hEvent = NULL ;
bytesToWrite = size ;
result = WriteFile (
m_fileHandle , // file handle
( void * ) buf , // data buffer
bytesToWrite , // num bytes to read
& bytesWritten , // bytes read
& overLapped ) ; // stucture for file offsets
}
if ( ! result ) {
char errorMessage [ 2048 ] ;
DWORD error = GetLastError ( ) ;
FormatMessage ( FORMAT_MESSAGE_FROM_SYSTEM , 0UL , error ,
MAKELANGID ( LANG_NEUTRAL , SUBLANG_DEFAULT ) , errorMessage , 2048 , NULL ) ;
throw TException ( errorMessage ) ;
}
return bytesWritten ;
}
//------------------------------------------------------------------------------
void ZFile : : waitForAsyncIOCompletion ( ) const
{
if ( m_asyncIO ) {
WaitForSingleObjectEx ( m_writeNotPending , INFINITE , TRUE ) ;
SetEvent ( m_writeNotPending ) ;
}
}
//------------------------------------------------------------------------------
void CALLBACK ZFile : : FileIOCompletionRoutine (
DWORD errCode ,
DWORD byteTransferred ,
LPOVERLAPPED overlapped )
{
delete overlapped ;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
class BufferQueue
{
public :
class Item
{
public :
Item ( int frame , UCHAR * buffer , int bufferSize , int chunkSize )
: m_frame ( frame ) , m_buffer ( buffer ) , m_bufferSize ( bufferSize ) , m_chunkSize ( chunkSize )
{
}
int m_frame ;
UCHAR * m_buffer ;
int m_bufferSize ;
TINT64 m_chunkSize ;
} ;
BufferQueue ( int capacity , int allocUnit )
: m_capacity ( capacity ) , m_allocUnit ( allocUnit ) , m_notEmpty ( ) , m_notFull ( ) , m_mutex ( ) , m_bufferCount ( 0 ) , m_nextPutItem ( 0 ) , m_nextGetItem ( 0 )
{
for ( int i = 0 ; i < m_capacity ; + + i )
m_items . push_back ( Item ( - 1 , ( UCHAR * ) 0 , 0 , 0 ) ) ;
}
~ BufferQueue ( )
{
for ( int i = 0 ; i < m_capacity ; + + i )
delete [ ] m_items [ i ] . m_buffer ;
}
void put ( int frame , UCHAR * buffer , int bufferSize , int chunkSize )
{
TThread : : ScopedLock sl ( m_mutex ) ;
while ( m_bufferCount = = m_capacity )
m_notFull . wait ( sl ) ;
if ( m_items [ m_nextPutItem ] . m_chunkSize ! = chunkSize ) {
delete [ ] m_items [ m_nextPutItem ] . m_buffer ;
m_items [ m_nextPutItem ] . m_buffer = new UCHAR [ chunkSize ] ;
m_items [ m_nextPutItem ] . m_chunkSize = chunkSize ;
}
memcpy ( m_items [ m_nextPutItem ] . m_buffer , buffer , bufferSize ) ;
m_items [ m_nextPutItem ] . m_frame = frame ;
m_nextPutItem = ( m_nextPutItem + 1 ) % m_capacity ;
+ + m_bufferCount ;
m_notEmpty . notifyOne ( ) ;
}
BufferQueue : : Item get ( )
{
TThread : : ScopedLock sl ( m_mutex ) ;
while ( m_bufferCount = = 0 )
m_notEmpty . wait ( sl ) ;
m_notFull . notifyOne ( ) ;
BufferQueue : : Item item = m_items [ m_nextGetItem ] ;
m_nextGetItem = ( m_nextGetItem + 1 ) % m_capacity ;
- - m_bufferCount ;
return item ;
}
void saveOne ( ZFile * file )
{
TThread : : ScopedLock sl ( m_mutex ) ;
while ( m_bufferCount = = 0 )
m_notEmpty . wait ( sl ) ;
m_notFull . notifyOne ( ) ;
BufferQueue : : Item item = m_items [ m_nextGetItem ] ;
m_nextGetItem = ( m_nextGetItem + 1 ) % m_capacity ;
- - m_bufferCount ;
TINT64 pos = item . m_frame * item . m_chunkSize ;
TINT64 sectorCount = pos / m_allocUnit ;
if ( ( pos % m_allocUnit ) ! = 0 )
+ + sectorCount ;
pos = sectorCount * m_allocUnit ;
file - > write ( item . m_buffer , ( TINT32 ) item . m_chunkSize , pos ) ;
}
int size ( )
{
TThread : : ScopedLock sl ( m_mutex ) ;
return m_bufferCount ;
}
private :
int m_capacity ;
int m_allocUnit ;
TThread : : Condition m_notEmpty ;
TThread : : Condition m_notFull ;
TThread : : Mutex m_mutex ;
vector < Item > m_items ;
int m_bufferCount ;
int m_nextPutItem ;
int m_nextGetItem ;
} ;
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
class WriteBufferTask : public TThread : : Runnable
{
public :
WriteBufferTask ( ZFile * file , BufferQueue * bufferQueue )
: m_file ( file ) , m_bufferQueue ( bufferQueue )
{
}
void run ( ) ;
ZFile * m_file ;
BufferQueue * m_bufferQueue ;
} ;
//------------------------------------------------------------------------------
void WriteBufferTask : : run ( )
{
while ( true ) {
TThread : : milestone ( ) ;
try {
m_bufferQueue - > saveOne ( m_file ) ;
m_file - > waitForAsyncIOCompletion ( ) ;
} catch ( TException & /*e*/ ) {
} catch ( . . . ) {
}
}
}
} // anonymous namespace
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
class TDiskCachePersist2 : : Imp
{
public :
Imp ( const TFilePath & fp , bool asyncWrite )
: m_chunkSize ( 0 ) , m_readBuffer ( 0 ) , m_file ( new ZFile ( fp , true , asyncWrite ) ) , m_asyncWrite ( asyncWrite ) , m_executor ( 0 ) , m_bufferQueue ( 0 )
{
m_file - > open ( ) ;
m_allocUnit = m_file - > getBytesPerSector ( ) ;
if ( m_asyncWrite ) {
m_executor = new TThread : : Executor ( ) ;
m_bufferQueue = new BufferQueue ( 4 , m_allocUnit ) ;
m_executor - > addTask ( new WriteBufferTask ( m_file , m_bufferQueue ) ) ;
}
}
~ Imp ( )
{
delete m_file ;
delete [ ] m_readBuffer ;
if ( m_executor ) {
m_executor - > cancel ( ) ;
delete m_executor ;
}
delete m_bufferQueue ;
}
bool put ( int frame , UCHAR * data , TUINT32 dataSize ) ;
UCHAR * get ( int pos , TUINT32 * size ) ;
TThread : : Mutex m_mutex ;
TINT64 m_chunkSize ;
ZFile * m_file ;
int m_allocUnit ;
UCHAR * m_readBuffer ;
int m_lx ;
int m_ly ;
int m_bpp ;
bool m_asyncWrite ;
TThread : : Executor * m_executor ;
BufferQueue * m_bufferQueue ;
} ;
//------------------------------------------------------------------------------
bool TDiskCachePersist2 : : Imp : : put ( int frame , UCHAR * data , TUINT32 dataSize )
{
if ( dataSize ! = m_chunkSize )
return false ;
TINT64 pos = frame * m_chunkSize ;
TINT64 sectorCount = pos / m_allocUnit ;
if ( ( pos % m_allocUnit ) ! = 0 )
+ + sectorCount ;
pos = sectorCount * m_allocUnit ;
m_file - > write ( data , dataSize , pos ) ;
return true ;
}
//------------------------------------------------------------------------------
UCHAR * TDiskCachePersist2 : : Imp : : get ( int frame , TUINT32 * size )
{
UCHAR * ret = new UCHAR [ TINT32 ( m_chunkSize ) ] ;
TThread : : ScopedLock sl ( m_mutex ) ;
TINT64 pos = frame * m_chunkSize ;
TINT64 sectorCount = pos / m_allocUnit ;
if ( ( pos % m_allocUnit ) ! = 0 )
+ + sectorCount ;
pos = sectorCount * m_allocUnit ;
m_file - > read ( ret , TINT32 ( m_chunkSize ) , pos ) ;
* size = TUINT32 ( m_chunkSize ) ;
return ret ;
}
//------------------------------------------------------------------------------
TDiskCachePersist2 : : TDiskCachePersist2 ( TRasterCodec * codec , const TFilePath & fullpath )
: TCachePersist ( codec ) , m_imp ( new Imp ( fullpath , false /*true*/ ) )
{
}
//------------------------------------------------------------------------------
TDiskCachePersist2 : : ~ TDiskCachePersist2 ( )
{
delete m_imp ;
}
//------------------------------------------------------------------------------
void TDiskCachePersist2 : : setFrameSize ( int lx , int ly , int bpp )
{
m_imp - > m_lx = lx ;
m_imp - > m_ly = ly ;
m_imp - > m_bpp = bpp ;
// inizializza m_imp->m_chunkSize in modo che sia un multiplo di m_imp->m_allocUnit
if ( m_codec )
m_imp - > m_chunkSize = m_codec - > getMaxCompressionSize ( lx * ly * ( bpp > > 3 ) ) ;
else
m_imp - > m_chunkSize = lx * ly * ( bpp > > 3 ) ;
TINT64 allocUnitCount = m_imp - > m_chunkSize / m_imp - > m_allocUnit ;
if ( ( m_imp - > m_chunkSize % m_imp - > m_allocUnit ) ! = 0 )
+ + allocUnitCount ;
m_imp - > m_chunkSize = allocUnitCount * m_imp - > m_allocUnit ;
delete [ ] m_imp - > m_readBuffer ;
m_imp - > m_readBuffer = 0 ;
}
//------------------------------------------------------------------------------
TRasterP TDiskCachePersist2 : : doGetRaster ( int frame )
{
TRasterP outRas ;
TUINT32 size ;
if ( ! m_imp - > m_readBuffer )
m_imp - > m_readBuffer = new UCHAR [ TINT32 ( m_imp - > m_chunkSize ) ] ;
TINT64 pos = frame * m_imp - > m_chunkSize ;
TINT64 sectorCount = pos / m_imp - > m_allocUnit ;
if ( ( pos % m_imp - > m_allocUnit ) ! = 0 )
+ + sectorCount ;
pos = sectorCount * m_imp - > m_allocUnit ;
m_imp - > m_file - > read ( m_imp - > m_readBuffer , TINT32 ( m_imp - > m_chunkSize ) , pos ) ;
size = TUINT32 ( m_imp - > m_chunkSize ) ;
if ( m_codec )
m_codec - > decompress ( m_imp - > m_readBuffer , size , outRas ) ;
else {
switch ( m_imp - > m_bpp ) {
case 32 : {
TRaster32P ras ( m_imp - > m_lx , m_imp - > m_ly ) ;
outRas = ras ;
} break ;
case 64 : {
TRaster64P ras ( m_imp - > m_lx , m_imp - > m_ly ) ;
outRas = ras ;
} break ;
default :
throw TException ( " unsupported pixel format " ) ;
break ;
}
unsigned int rasSize = outRas - > getRowSize ( ) * outRas - > getLy ( ) ;
assert ( size > = rasSize ) ;
outRas - > lock ( ) ;
memcpy ( outRas - > getRawData ( ) , m_imp - > m_readBuffer , rasSize ) ;
outRas - > unlock ( ) ;
}
return outRas ;
}
//------------------------------------------------------------------------------
bool TDiskCachePersist2 : : doGetRaster ( int frame , TRaster32P & ras ) const
{
if ( ! m_imp - > m_readBuffer )
m_imp - > m_readBuffer = new UCHAR [ TINT32 ( m_imp - > m_chunkSize ) ] ;
TINT64 pos = frame * m_imp - > m_chunkSize ;
TINT64 sectorCount = pos / m_imp - > m_allocUnit ;
if ( ( pos % m_imp - > m_allocUnit ) ! = 0 )
+ + sectorCount ;
pos = sectorCount * m_imp - > m_allocUnit ;
TRasterP rasP = ras ;
if ( m_codec ) {
m_imp - > m_file - > read ( m_imp - > m_readBuffer , TINT32 ( m_imp - > m_chunkSize ) , pos ) ;
m_codec - > decompress ( m_imp - > m_readBuffer , TINT32 ( m_imp - > m_chunkSize ) , rasP ) ;
assert ( rasP - > getSize ( ) = = ras - > getSize ( ) ) ;
ras - > copy ( rasP ) ;
} else {
assert ( ras - > getLx ( ) = = ras - > getWrap ( ) ) ;
int rasSize = ras - > getRowSize ( ) * ras - > getLy ( ) ;
ras - > lock ( ) ;
if ( rasSize = = m_imp - > m_chunkSize )
m_imp - > m_file - > read ( ras - > getRawData ( ) , TINT32 ( m_imp - > m_chunkSize ) , pos ) ;
else {
assert ( rasSize < m_imp - > m_chunkSize ) ;
m_imp - > m_file - > read ( m_imp - > m_readBuffer , TINT32 ( m_imp - > m_chunkSize ) , pos ) ;
memcpy ( ras - > getRawData ( ) , m_imp - > m_readBuffer , rasSize ) ;
}
ras - > unlock ( ) ;
}
return true ;
}
//------------------------------------------------------------------------------
bool TDiskCachePersist2 : : doPutRaster ( int frame , const TRasterP & inRas )
{
UCHAR * outData = 0 ;
TINT32 outDataSize = 0 ;
int actualDataSize = 0 ;
bool deleteDataBuffer = false ;
if ( m_codec ) {
m_codec - > compress ( inRas , m_imp - > m_allocUnit , & outData , outDataSize ) ;
deleteDataBuffer = true ;
;
actualDataSize = outDataSize ;
} else {
assert ( inRas - > getLx ( ) = = inRas - > getWrap ( ) ) ;
int rasSize = inRas - > getLx ( ) * inRas - > getLy ( ) * inRas - > getPixelSize ( ) ;
outDataSize = TINT32 ( m_imp - > m_chunkSize ) ;
inRas - > lock ( ) ;
if ( rasSize = = m_imp - > m_chunkSize )
outData = inRas - > getRawData ( ) ;
else {
if ( ! m_imp - > m_readBuffer )
m_imp - > m_readBuffer = new UCHAR [ TINT32 ( m_imp - > m_chunkSize ) ] ;
memcpy ( m_imp - > m_readBuffer , inRas - > getRawData ( ) , rasSize ) ;
outData = m_imp - > m_readBuffer ;
}
inRas - > unlock ( ) ;
actualDataSize = rasSize ;
}
assert ( ( outDataSize % m_imp - > m_allocUnit ) = = 0 ) ;
bool cached = true ;
if ( m_imp - > m_asyncWrite )
m_imp - > m_bufferQueue - > put ( frame , outData , actualDataSize , outDataSize ) ;
else
cached = m_imp - > put ( frame , outData , outDataSize ) ;
if ( deleteDataBuffer )
delete [ ] outData ;
return cached ;
}
//------------------------------------------------------------------------------
UCHAR * TDiskCachePersist2 : : getRawData ( int frame , TINT32 & size , int & lx , int & ly )
{
TUINT32 inDataSize ;
UCHAR * src = m_imp - > get ( frame , & inDataSize ) ;
return m_codec - > removeHeader ( src , inDataSize , size , lx , ly ) ;
}
//------------------------------------------------------------------------------
void TDiskCachePersist2 : : onInvalidate ( )
{
}
//------------------------------------------------------------------------------
void TDiskCachePersist2 : : onInvalidate ( int startFrame , int endFrame )
{
}
//------------------------------------------------------------------------------
TUINT64 TDiskCachePersist2 : : getUsedSpace ( )
{
TFileStatus fs ( m_imp - > m_file - > getFilePath ( ) ) ;
return fs . getSize ( ) ;
}
//------------------------------------------------------------------------------
# endif //WIN32