Introduce osgDB::FileCache, and updated osgfilecache and DatabasePager to use it.
This commit is contained in:
@@ -17,6 +17,7 @@ SET(LIB_PUBLIC_HEADERS
|
||||
${HEADER_PATH}/Field
|
||||
${HEADER_PATH}/FieldReader
|
||||
${HEADER_PATH}/FieldReaderIterator
|
||||
${HEADER_PATH}/FileCache
|
||||
${HEADER_PATH}/FileNameUtils
|
||||
${HEADER_PATH}/FileUtils
|
||||
${HEADER_PATH}/ImageOptions
|
||||
@@ -28,8 +29,8 @@ SET(LIB_PUBLIC_HEADERS
|
||||
${HEADER_PATH}/ReaderWriter
|
||||
${HEADER_PATH}/ReadFile
|
||||
${HEADER_PATH}/Registry
|
||||
${HEADER_PATH}/SharedStateManager
|
||||
${HEADER_PATH}/Serializer
|
||||
${HEADER_PATH}/SharedStateManager
|
||||
${HEADER_PATH}/Version
|
||||
${HEADER_PATH}/WriteFile
|
||||
)
|
||||
@@ -46,6 +47,7 @@ ADD_LIBRARY(${LIB_NAME}
|
||||
Field.cpp
|
||||
FieldReader.cpp
|
||||
FieldReaderIterator.cpp
|
||||
FileCache.cpp
|
||||
FileNameUtils.cpp
|
||||
FileUtils.cpp
|
||||
ImageOptions.cpp
|
||||
|
||||
@@ -398,17 +398,6 @@ int DatabasePager::DatabaseThread::cancel()
|
||||
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Node> DatabasePager::DatabaseThread::dpReadRefNodeFile(const std::string& fileName,const ReaderWriter::Options* options)
|
||||
{
|
||||
ReaderWriter::ReadResult rr = Registry::instance()->getReadFileCallback() ?
|
||||
Registry::instance()->getReadFileCallback()->readNode(fileName,options) :
|
||||
Registry::instance()->readNodeImplementation(fileName,options);
|
||||
|
||||
if (rr.validNode()) return rr.getNode();
|
||||
if (rr.error()) osg::notify(osg::WARN) << rr.message() << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DatabasePager::DatabaseThread::run()
|
||||
{
|
||||
osg::notify(osg::INFO)<<_name<<": DatabasePager::DatabaseThread::run"<<std::endl;
|
||||
@@ -447,11 +436,7 @@ void DatabasePager::DatabaseThread::run()
|
||||
}
|
||||
|
||||
//Getting CURL Environment Variables (If found rewrite OSG Options)
|
||||
std::string cacheFilePath;
|
||||
const char* fileCachePath = getenv("OSG_FILE_CACHE");
|
||||
if (fileCachePath) //Env Cache Directory
|
||||
cacheFilePath = std::string(fileCachePath);
|
||||
|
||||
osg::ref_ptr<FileCache> fileCache = osgDB::Registry::instance()->getFileCache();
|
||||
|
||||
do
|
||||
{
|
||||
@@ -480,6 +465,8 @@ void DatabasePager::DatabaseThread::run()
|
||||
//
|
||||
osg::ref_ptr<DatabaseRequest> databaseRequest;
|
||||
read_queue->takeFirst(databaseRequest);
|
||||
|
||||
bool readFromFileCache = false;
|
||||
|
||||
if (databaseRequest.valid())
|
||||
{
|
||||
@@ -494,57 +481,24 @@ void DatabasePager::DatabaseThread::run()
|
||||
// do nothing as this thread can handle the load
|
||||
if (osgDB::containsServerAddress(databaseRequest->_fileName))
|
||||
{
|
||||
std::string cacheFileName;
|
||||
if (!cacheFilePath.empty())
|
||||
if (fileCache.valid() && fileCache->existsInCache(databaseRequest->_fileName))
|
||||
{
|
||||
cacheFileName = cacheFilePath + "/" +
|
||||
osgDB::getServerAddress(databaseRequest->_fileName) + "/" +
|
||||
osgDB::getServerFileName(databaseRequest->_fileName);
|
||||
|
||||
std::string path = osgDB::getFilePath(cacheFileName);
|
||||
|
||||
if (!osgDB::fileExists(path))
|
||||
{
|
||||
cacheFileName.clear();
|
||||
}
|
||||
}
|
||||
|
||||
if (!cacheFilePath.empty() && osgDB::fileExists(cacheFileName))
|
||||
{
|
||||
osg::notify(osg::INFO)<<_name<<": Reading cache file " << cacheFileName <<", previous path "<<osgDB::getFilePath(databaseRequest->_fileName)<<std::endl;
|
||||
databaseRequest->_fileName = cacheFileName;
|
||||
readFromFileCache = true;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case(HANDLE_NON_HTTP):
|
||||
// check the cache first
|
||||
if (osgDB::containsServerAddress(databaseRequest->_fileName))
|
||||
{
|
||||
std::string cacheFileName;
|
||||
if (!cacheFilePath.empty())
|
||||
if (fileCache.valid() && fileCache->existsInCache(databaseRequest->_fileName))
|
||||
{
|
||||
cacheFileName = cacheFilePath + "/" +
|
||||
osgDB::getServerAddress(databaseRequest->_fileName) + "/" +
|
||||
osgDB::getServerFileName(databaseRequest->_fileName);
|
||||
|
||||
std::string path = osgDB::getFilePath(cacheFileName);
|
||||
|
||||
if (!osgDB::fileExists(path))
|
||||
{
|
||||
cacheFileName.clear();
|
||||
}
|
||||
}
|
||||
|
||||
if (!cacheFilePath.empty() && osgDB::fileExists(cacheFileName))
|
||||
{
|
||||
osg::notify(osg::INFO)<<_name<<": Reading cache file " << cacheFileName <<", previous path "<<osgDB::getFilePath(databaseRequest->_fileName)<<std::endl;
|
||||
databaseRequest->_fileName = cacheFileName;
|
||||
readFromFileCache = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify(osg::INFO)<<_name<<": Passing http requests over "<<databaseRequest->_fileName<<" cacheFileName="<<cacheFileName<<std::endl;
|
||||
osg::notify(osg::INFO)<<_name<<": Passing http requests over "<<databaseRequest->_fileName<<std::endl;
|
||||
out_queue->add(databaseRequest.get());
|
||||
databaseRequest = 0;
|
||||
}
|
||||
@@ -577,46 +531,20 @@ void DatabasePager::DatabaseThread::run()
|
||||
//osg::Timer_t before = osg::Timer::instance()->tick();
|
||||
|
||||
|
||||
bool serialize_readNodeFile = false;
|
||||
if (serialize_readNodeFile)
|
||||
{
|
||||
// do *not* assume that we only have one DatabasePager, or that reaNodeFile is thread safe...
|
||||
static OpenThreads::Mutex s_serialize_readNodeFile_mutex;
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_serialize_readNodeFile_mutex);
|
||||
databaseRequest->_loadedModel = dpReadRefNodeFile(databaseRequest->_fileName,
|
||||
databaseRequest->_loadOptions.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
// assume that we only have one DatabasePager, or that readNodeFile is thread safe...
|
||||
databaseRequest->_loadedModel = dpReadRefNodeFile(databaseRequest->_fileName,
|
||||
databaseRequest->_loadOptions.get());
|
||||
}
|
||||
// assume that readNode is thread safe...
|
||||
ReaderWriter::ReadResult rr = readFromFileCache ?
|
||||
fileCache->readNode(databaseRequest->_fileName, databaseRequest->_loadOptions.get(), false) :
|
||||
Registry::instance()->readNode(databaseRequest->_fileName, databaseRequest->_loadOptions.get(), false);
|
||||
|
||||
if (rr.validNode()) databaseRequest->_loadedModel = rr.getNode();
|
||||
if (rr.error()) osg::notify(osg::WARN) << rr.message() << std::endl;
|
||||
|
||||
if (databaseRequest->_loadedModel.valid() &&
|
||||
osgDB::containsServerAddress(databaseRequest->_fileName) &&
|
||||
!cacheFilePath.empty())
|
||||
fileCache.valid() &&
|
||||
!readFromFileCache)
|
||||
{
|
||||
std::string cacheFileName = cacheFilePath + "/" +
|
||||
osgDB::getServerAddress(databaseRequest->_fileName) + "/" +
|
||||
osgDB::getServerFileName(databaseRequest->_fileName);
|
||||
|
||||
std::string path = osgDB::getFilePath(cacheFileName);
|
||||
|
||||
if (!osgDB::fileExists(path) && !osgDB::makeDirectory(path))
|
||||
{
|
||||
cacheFileName.clear();
|
||||
}
|
||||
|
||||
if (!cacheFileName.empty() && osgDB::fileExists(cacheFileName))
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<_name<<": Warning, file already in cache file, shouldn't have needed to be reloaded. cache file=" << cacheFileName <<", previous path "<<osgDB::getFilePath(databaseRequest->_fileName)<<std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify(osg::INFO)<<_name<<": Write to cache "<<cacheFileName<<std::endl;
|
||||
osgDB::writeNodeFile(*(databaseRequest->_loadedModel), cacheFileName, databaseRequest->_loadOptions.get());
|
||||
}
|
||||
fileCache->writeNode(*(databaseRequest->_loadedModel), databaseRequest->_fileName, databaseRequest->_loadOptions.get());
|
||||
}
|
||||
|
||||
if ((_pager->_frameNumber-databaseRequest->_frameNumberLastRequest)>1)
|
||||
|
||||
80
src/osgDB/FileCache.cpp
Normal file
80
src/osgDB/FileCache.cpp
Normal file
@@ -0,0 +1,80 @@
|
||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
|
||||
*
|
||||
* This library is open source and may be redistributed and/or modified under
|
||||
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||
* (at your option) any later version. The full license is in LICENSE file
|
||||
* included with this distribution, and on the openscenegraph.org website.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* OpenSceneGraph Public License for more details.
|
||||
*/
|
||||
|
||||
#include <osgDB/FileCache>
|
||||
#include <osgDB/FileUtils>
|
||||
#include <osgDB/FileNameUtils>
|
||||
#include <osgDB/ReadFile>
|
||||
#include <osgDB/WriteFile>
|
||||
|
||||
using namespace osgDB;
|
||||
|
||||
FileCache::FileCache(const std::string& path):
|
||||
_fileCachePath(path)
|
||||
{
|
||||
osg::notify(osg::INFO)<<"Constructed FileCache : "<<path<<std::endl;
|
||||
}
|
||||
|
||||
FileCache::~FileCache()
|
||||
{
|
||||
osg::notify(osg::INFO)<<"Destructed FileCache "<<std::endl;
|
||||
}
|
||||
|
||||
std::string FileCache::createCacheFileName(const std::string& originalFileName) const
|
||||
{
|
||||
std::string cacheFileName = _fileCachePath + "/" +
|
||||
osgDB::getServerAddress(originalFileName) + "/" +
|
||||
osgDB::getServerFileName(originalFileName);
|
||||
|
||||
osg::notify(osg::INFO)<<"FileCache::createCacheFileName("<<originalFileName<<") = "<<cacheFileName<<std::endl;
|
||||
|
||||
return cacheFileName;
|
||||
}
|
||||
|
||||
bool FileCache::existsInCache(const std::string& originalFileName) const
|
||||
{
|
||||
return osgDB::fileExists(createCacheFileName(originalFileName));
|
||||
}
|
||||
|
||||
ReaderWriter::ReadResult FileCache::readNode(const std::string& originalFileName, const osgDB::ReaderWriter::Options* options, bool buildKdTreeIfRequired) const
|
||||
{
|
||||
std::string cacheFileName = createCacheFileName(originalFileName);
|
||||
if (!cacheFileName.empty() && osgDB::fileExists(cacheFileName))
|
||||
{
|
||||
osg::notify(osg::INFO)<<"FileCache::readNodeFromCache("<<originalFileName<<") as "<<cacheFileName<<std::endl;
|
||||
return osgDB::Registry::instance()->readNode(cacheFileName, options, buildKdTreeIfRequired);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
ReaderWriter::WriteResult FileCache::writeNode(const osg::Node& node, const std::string& originalFileName, const osgDB::ReaderWriter::Options* options) const
|
||||
{
|
||||
std::string cacheFileName = createCacheFileName(originalFileName);
|
||||
if (!cacheFileName.empty())
|
||||
{
|
||||
std::string path = osgDB::getFilePath(cacheFileName);
|
||||
|
||||
if (!osgDB::fileExists(path) && !osgDB::makeDirectory(path))
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<"Could not create cache directory: "<<path<<std::endl;
|
||||
return ReaderWriter::WriteResult::ERROR_IN_WRITING_FILE;
|
||||
}
|
||||
|
||||
osg::notify(osg::INFO)<<"FileCache::writeNodeToCache("<<originalFileName<<") as "<<cacheFileName<<std::endl;
|
||||
return osgDB::Registry::instance()->writeNode(node, cacheFileName, options);
|
||||
}
|
||||
return ReaderWriter::WriteResult::FILE_NOT_HANDLED;
|
||||
}
|
||||
@@ -131,10 +131,7 @@ Node* osgDB::readNodeFiles(osg::ArgumentParser& arguments,const ReaderWriter::Op
|
||||
|
||||
while (arguments.read("--file-cache",filename))
|
||||
{
|
||||
std::string str("OSG_FILE_CACHE=");
|
||||
str += filename;
|
||||
|
||||
putenv(strdup((char*)str.c_str()));
|
||||
osgDB::Registry::instance()->setFileCache(new osgDB::FileCache(filename));
|
||||
}
|
||||
|
||||
while (arguments.read("--image",filename))
|
||||
|
||||
@@ -178,6 +178,12 @@ Registry::Registry()
|
||||
else _buildKdTreesHint = ReaderWriter::Options::BUILD_KDTREES;
|
||||
}
|
||||
|
||||
const char* fileCachePath = getenv("OSG_FILE_CACHE");
|
||||
if (fileCachePath)
|
||||
{
|
||||
_fileCache = new FileCache(fileCachePath);
|
||||
}
|
||||
|
||||
_createNodeFromImage = false;
|
||||
_openingLibrary = false;
|
||||
|
||||
@@ -326,6 +332,10 @@ void Registry::destruct()
|
||||
_sharedStateManager = 0;
|
||||
|
||||
|
||||
// clean up the FileCache
|
||||
_fileCache = 0;
|
||||
|
||||
|
||||
// object cache clear needed here to prevent crash in unref() of
|
||||
// the objects it contains when running the TXP plugin.
|
||||
// Not sure why, but perhaps there is is something in a TXP plugin
|
||||
|
||||
Reference in New Issue
Block a user