|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Qt includes
|
|
Toshihiro Shimizu |
890ddd |
#include <qmap></qmap>
|
|
Toshihiro Shimizu |
890ddd |
#include <qsettings></qsettings>
|
|
Toshihiro Shimizu |
890ddd |
#include <qdate></qdate>
|
|
Toshihiro Shimizu |
890ddd |
#include <qdir></qdir>
|
|
Toshihiro Shimizu |
890ddd |
#include <qfileinfo></qfileinfo>
|
|
Toshihiro Shimizu |
890ddd |
#include <qfileinfolist></qfileinfolist>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//#define USE_SQLITE_HDPOOL
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#ifdef USE_SQLITE_HDPOOL
|
|
Toshihiro Shimizu |
890ddd |
//SQLite include
|
|
Toshihiro Shimizu |
890ddd |
#include "sqlite/sqlite3.h"
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "tcacheresourcepool.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Debug
|
|
Toshihiro Shimizu |
890ddd |
//#define DIAGNOSTICS
|
|
Toshihiro Shimizu |
890ddd |
//#include "diagnostics.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//******************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// Cache Resource Pool BACKED ON DISK
|
|
Toshihiro Shimizu |
890ddd |
//******************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//STILL UNDER DEVELOPMENT...
|
|
Toshihiro Shimizu |
890ddd |
class THDCacheResourcePool
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
THDCacheResourcePool() {}
|
|
Toshihiro Shimizu |
890ddd |
~THDCacheResourcePool() {}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//*************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// Cache resource pool methods involved with HD Pool management
|
|
Toshihiro Shimizu |
890ddd |
//*************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
inline bool TCacheResourcePool::isHDActive()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
#ifdef USE_SQLITE_HDPOOL
|
|
Toshihiro Shimizu |
890ddd |
return m_hdPool && m_hdPool->isActive();
|
|
Toshihiro Shimizu |
890ddd |
#else
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void TCacheResourcePool::reset()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
setPath("", "", "");
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//----------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Prevents the resources in memory from backing to disk. Observe that
|
|
Toshihiro Shimizu |
890ddd |
// the actual content of the resource is NOT invalidated - since resources
|
|
Toshihiro Shimizu |
890ddd |
// are intended as 'reference-protected' material which is expected to last
|
|
Toshihiro Shimizu |
890ddd |
// as long as references are held.
|
|
Toshihiro Shimizu |
890ddd |
void TCacheResourcePool::invalidateAll()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
QMutexLocker locker(&m_memMutex);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
MemResources::iterator it;
|
|
Toshihiro Shimizu |
890ddd |
for (it = m_memResources.begin(); it != m_memResources.end(); ++it)
|
|
Toshihiro Shimizu |
890ddd |
it->second->invalidate();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//----------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
inline QString TCacheResourcePool::getPoolRoot(QString cacheRoot, QString projectName, QString sceneName)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return QString(cacheRoot + "/render/" + projectName + "/" + sceneName + "/");
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//----------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//! Connects to the pool associated to the given project/scene pair.
|
|
Toshihiro Shimizu |
890ddd |
//! \warning As this closes the current connection before opening a new one,
|
|
Toshihiro Shimizu |
890ddd |
//! make sure that no pool access happens at this point. You should also
|
|
Toshihiro Shimizu |
890ddd |
//! verify that no resource from the old pair still exists.
|
|
Toshihiro Shimizu |
890ddd |
void TCacheResourcePool::setPath(QString cacheRoot, QString projectName, QString sceneName)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
//There should be no resource in memory.
|
|
Toshihiro Shimizu |
890ddd |
assert(m_memResources.empty());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//However, just in case, invalidate all resources so that no more resource backing
|
|
Toshihiro Shimizu |
890ddd |
//operation take place for current resources, from now on.
|
|
Toshihiro Shimizu |
890ddd |
//No care is paid as to whether active transactions currently exist. You
|
|
Toshihiro Shimizu |
890ddd |
//have been warned by the way....
|
|
Toshihiro Shimizu |
890ddd |
invalidateAll();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
delete m_hdPool;
|
|
Toshihiro Shimizu |
890ddd |
m_hdPool = 0;
|
|
Toshihiro Shimizu |
890ddd |
m_path = TFilePath();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#ifdef USE_SQLITE_HDPOOL
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!(cacheRoot.isEmpty() || projectName.isEmpty() || sceneName.isEmpty())) {
|
|
Toshihiro Shimizu |
890ddd |
QString hdPoolRoot(getPoolRoot(cacheRoot, projectName, sceneName));
|
|
Toshihiro Shimizu |
890ddd |
m_hdPool = new THDCacheResourcePool(hdPoolRoot);
|
|
Toshihiro Shimizu |
890ddd |
m_path = m_hdPool->getResourcesFilePath();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void TCacheResourcePool::startBacking(TCacheResource *resource)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
assert(isHDActive());
|
|
Toshihiro Shimizu |
890ddd |
if (!isHDActive())
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#ifdef USE_SQLITE_HDPOOL
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
resource->m_backEnabled = true;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_hdPool->buildBackingPath(resource);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//******************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// Cache resource pool implementation
|
|
Toshihiro Shimizu |
890ddd |
//******************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TCacheResourcePool *TCacheResourcePool::instance()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
static TCacheResourcePool theInstance;
|
|
Toshihiro Shimizu |
890ddd |
return &theInstance;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//----------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TCacheResourcePool::TCacheResourcePool()
|
|
Toshihiro Shimizu |
890ddd |
: m_memMutex(QMutex::Recursive), m_searchCount(0), m_foundIterator(false), m_searchIterator(m_memResources.end()), m_hdPool(0), m_path()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
//Open the settings for cache retrieval
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//----------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TCacheResourcePool::~TCacheResourcePool()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
//Temporary
|
|
Toshihiro Shimizu |
890ddd |
//performAutomaticCleanup();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
delete m_hdPool;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//----------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const TFilePath &TCacheResourcePool::getPath() const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return m_path;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//----------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//! Initializes an optimized search on the pool for a specific resource, caching successive
|
|
Toshihiro Shimizu |
890ddd |
//! results.
|
|
Toshihiro Shimizu |
890ddd |
//! \note Pool searches are serialized, and calls to this method lock the pool's mutex until a
|
|
Toshihiro Shimizu |
890ddd |
//! corresponding number of endCachedSearch() methods are invoked.
|
|
Toshihiro Shimizu |
890ddd |
void TCacheResourcePool::beginCachedSearch()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_memMutex.lock();
|
|
Toshihiro Shimizu |
890ddd |
m_searchCount++;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//----------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//! The inverse to beginCachedSearch(). This method \b MUST be called in correspondence to
|
|
Toshihiro Shimizu |
890ddd |
//! beginCachedSearch() calls.
|
|
Toshihiro Shimizu |
890ddd |
void TCacheResourcePool::endCachedSearch()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (--m_searchCount <= 0) {
|
|
Toshihiro Shimizu |
890ddd |
m_foundIterator = false;
|
|
Toshihiro Shimizu |
890ddd |
m_searchIterator = m_memResources.end();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
m_memMutex.unlock();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//----------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//! Attempts retrieval of the resource with specified name, and eventually creates it if
|
|
Toshihiro Shimizu |
890ddd |
//! the createIfNone parameter is set.
|
|
Toshihiro Shimizu |
890ddd |
TCacheResource *TCacheResourcePool::getResource(const std::string &name, bool createIfNone)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
//DIAGNOSTICS_TIMER("#times.txt | getResource Overall time");
|
|
Toshihiro Shimizu |
890ddd |
//DIAGNOSTICS_MEANTIMER("#times.txt | getResource Mean time");
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TCacheResource *result = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//NOTA: Passa ad un oggetto lockatore. Quello e' in grado di gestire i casi di eccezioni ecc..
|
|
Toshihiro Shimizu |
890ddd |
beginCachedSearch();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Search for an already allocated resource
|
|
Toshihiro Shimizu |
890ddd |
if (m_searchIterator == m_memResources.end()) {
|
|
Toshihiro Shimizu |
890ddd |
m_searchIterator = m_memResources.lower_bound(name);
|
|
Toshihiro Shimizu |
890ddd |
if (m_searchIterator != m_memResources.end())
|
|
Toshihiro Shimizu |
890ddd |
if (!(name < m_searchIterator->first))
|
|
Toshihiro Shimizu |
890ddd |
m_foundIterator = true;
|
|
Toshihiro Shimizu |
890ddd |
else if (m_searchIterator != m_memResources.begin())
|
|
Toshihiro Shimizu |
890ddd |
m_searchIterator--;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (m_foundIterator) {
|
|
Toshihiro Shimizu |
890ddd |
result = m_searchIterator->second;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
endCachedSearch();
|
|
Toshihiro Shimizu |
890ddd |
return result;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
QString resourcePath;
|
|
Toshihiro Shimizu |
890ddd |
QString resourceFlags;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (isHDActive()) {
|
|
Toshihiro Shimizu |
890ddd |
#ifdef USE_SQLITE_HDPOOL
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//DIAGNOSTICS_TIMER("#times.txt | HDPOOL getResource Overall time");
|
|
Toshihiro Shimizu |
890ddd |
//DIAGNOSTICS_MEANTIMER("#times.txt | HDPOOL getResource Mean time");
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Search in the HD pool
|
|
Toshihiro Shimizu |
890ddd |
ReadQuery query(m_hdPool);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool ret = query.prepare(
|
|
Toshihiro Shimizu |
890ddd |
"SELECT Path, Flags FROM Resources WHERE Name = '" + QString::fromStdString(name) + "';");
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//If an error occurred, assume the resource does not exist. Doing nothing works fine.
|
|
Toshihiro Shimizu |
890ddd |
assert(ret);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (query.step()) {
|
|
Toshihiro Shimizu |
890ddd |
resourcePath = query.value(0);
|
|
Toshihiro Shimizu |
890ddd |
resourceFlags = query.value(1);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!resourcePath.isEmpty() || createIfNone) {
|
|
Toshihiro Shimizu |
890ddd |
TCacheResource *result = new TCacheResource;
|
|
Toshihiro Shimizu |
890ddd |
result->m_pos = m_searchIterator =
|
|
Toshihiro Shimizu |
890ddd |
m_memResources.insert(m_searchIterator, std::make_pair(name, result));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//DIAGNOSTICS_STRSET("#resources.txt | RISORSE | " + QString::number((UINT) result) + " | Name",
|
|
Toshihiro Shimizu |
890ddd |
//QString::fromStdString(name).left(70));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#ifdef USE_SQLITE_HDPOOL
|
|
Toshihiro Shimizu |
890ddd |
if (isHDActive())
|
|
Toshihiro Shimizu |
890ddd |
m_hdPool->loadResourceInfos(result, resourcePath);
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_foundIterator = true;
|
|
Toshihiro Shimizu |
890ddd |
endCachedSearch();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return result;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
endCachedSearch();
|
|
Toshihiro Shimizu |
890ddd |
return 0;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//----------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void TCacheResourcePool::releaseResource(TCacheResource *resource)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
QMutexLocker locker(&m_memMutex);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Re-check the resource's reference count. This is necessary since a concurrent
|
|
Toshihiro Shimizu |
890ddd |
//thread may have locked the memMutex for resource retrieval BEFORE this one.
|
|
Toshihiro Shimizu |
890ddd |
//If that is the case, the resource's refCount has increased back above 0.
|
|
Toshihiro Shimizu |
890ddd |
if (resource->m_refCount > 0)
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#ifdef USE_SQLITE_HDPOOL
|
|
Toshihiro Shimizu |
890ddd |
QMutexLocker flushLocker(isHDActive() ? &m_hdPool->m_flushMutex : 0);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (isHDActive()) {
|
|
Toshihiro Shimizu |
890ddd |
//Flush all resource updates as this resource is being destroyed
|
|
Toshihiro Shimizu |
890ddd |
m_hdPool->flushResources();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Save the resource infos
|
|
Toshihiro Shimizu |
890ddd |
m_hdPool->saveResourceInfos(resource);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_memResources.erase(resource->m_pos);
|
|
Toshihiro Shimizu |
890ddd |
delete resource;
|
|
Toshihiro Shimizu |
890ddd |
}
|