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