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