diff --git a/include/osgDB/DatabasePager b/include/osgDB/DatabasePager index 1c9efd9b8..77ad479cc 100644 --- a/include/osgDB/DatabasePager +++ b/include/osgDB/DatabasePager @@ -311,8 +311,7 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl _timestampLastRequest(0.0), _priorityLastRequest(0.0f), _numOfRequests(0), - _groupExpired(false), - _insertLoadedSubgraphIntoObjectCache(false) + _groupExpired(false) {} void invalidate(); @@ -324,26 +323,25 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl return _valid && (frameNumber - _frameNumberLastRequest <= 1); } - bool _valid; - std::string _fileName; - unsigned int _frameNumberFirstRequest; - double _timestampFirstRequest; - float _priorityFirstRequest; - unsigned int _frameNumberLastRequest; - double _timestampLastRequest; - float _priorityLastRequest; - unsigned int _numOfRequests; + bool _valid; + std::string _fileName; + unsigned int _frameNumberFirstRequest; + double _timestampFirstRequest; + float _priorityFirstRequest; + unsigned int _frameNumberLastRequest; + double _timestampLastRequest; + float _priorityLastRequest; + unsigned int _numOfRequests; osg::observer_ptr _terrain; osg::observer_ptr _group; osg::ref_ptr _loadedModel; osg::ref_ptr _loadOptions; + osg::ref_ptr _objectCache; osg::observer_ptr _compileSet; - bool _groupExpired; // flag used only in update thread - - bool _insertLoadedSubgraphIntoObjectCache; + bool _groupExpired; // flag used only in update thread }; diff --git a/include/osgDB/ObjectCache b/include/osgDB/ObjectCache index a27aec17f..624356d14 100644 --- a/include/osgDB/ObjectCache +++ b/include/osgDB/ObjectCache @@ -46,6 +46,9 @@ class OSGDB_EXPORT ObjectCache : public osg::Referenced /** Remove all objects in the cache regardless of having external references or expiry times.*/ void clear(); + /** Add contents of specified ObjectCache to this object cache.*/ + void addObjectCache(ObjectCache* object); + /** Add a filename,object,timestamp triple to the Registry::ObjectCache.*/ void addEntryToObjectCache(const std::string& filename, osg::Object* object, double timestamp = 0.0); diff --git a/include/osgDB/Options b/include/osgDB/Options index 5ed4acefd..d361b5d2e 100644 --- a/include/osgDB/Options +++ b/include/osgDB/Options @@ -15,6 +15,7 @@ #define OSGDB_OPTIONS 1 #include +#include #include #include @@ -138,6 +139,13 @@ class OSGDB_EXPORT Options : public osg::Object /** Get whether the Registry::ObjectCache should be used by default.*/ CacheHintOptions getObjectCacheHint() const { return _objectCacheHint; } + /** Set the ObjectCache that is used to cache previously loaded data.*/ + void setObjectCache(ObjectCache* objectCache) { _objectCache = objectCache; } + + /** Get the ObjectCache that is used to cache previously loaded data.*/ + ObjectCache* getObjectCache() const { return _objectCache.get(); } + + /** Set which geometry attributes plugins should import at double precision. */ void setPrecisionHint(PrecisionHint hint) { _precisionHint = hint; } @@ -248,7 +256,10 @@ class OSGDB_EXPORT Options : public osg::Object std::string _str; FilePathList _databasePaths; + CacheHintOptions _objectCacheHint; + osg::ref_ptr _objectCache; + PrecisionHint _precisionHint; BuildKdTreesHint _buildKdTreesHint; osg::ref_ptr _authenticationMap; diff --git a/src/osgDB/DatabasePager.cpp b/src/osgDB/DatabasePager.cpp index d62ec262b..3854df224 100644 --- a/src/osgDB/DatabasePager.cpp +++ b/src/osgDB/DatabasePager.cpp @@ -421,6 +421,7 @@ void DatabasePager::DatabaseRequest::invalidate() _valid = false; _loadedModel = 0; _compileSet = 0; + _objectCache = 0; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -772,15 +773,35 @@ void DatabasePager::DatabaseThread::run() frameNumberLastRequest = databaseRequest->_frameNumberLastRequest; } + + if (dr_loadOptions->getFileCache()) fileCache = dr_loadOptions->getFileCache(); + if (dr_loadOptions->getFileLocationCallback()) fileLocationCallback = dr_loadOptions->getFileLocationCallback(); + + // disable the FileCache if the fileLocationCallback tells us that it isn't required for this request. + if (fileLocationCallback.valid() && !fileLocationCallback->useFileCache()) fileCache = 0; + + cacheNodes = (dr_loadOptions->getObjectCacheHint() & osgDB::Options::CACHE_NODES)!=0; if (cacheNodes) { + //OSG_NOTICE<<"Checking main ObjectCache"< objectFromCache = osgDB::Registry::instance()->getRefFromObjectCache(fileName); + + // if no object with fileName in ObjectCache then try the filename appropriate for fileCache + if (!objectFromCache && (fileCache.valid() && fileCache->isFileAppropriateForFileCache(fileName))) + { + if (fileCache->existsInCache(fileName)) + { + objectFromCache = osgDB::Registry::instance()->getRefFromObjectCache(fileCache->createCacheFileName(fileName)); + } + } + + osg::Node* modelFromCache = dynamic_cast(objectFromCache.get()); if (modelFromCache) { - // OSG_NOTICE<<"Found object in cache "<setObjectCacheHint(static_cast(dr_loadOptions->getObjectCacheHint() & ~osgDB::Options::CACHE_NODES)); + { + OpenThreads::ScopedLock drLock(_pager->_dr_mutex); + databaseRequest->_objectCache = new ObjectCache; + dr_loadOptions->setObjectCache(databaseRequest->_objectCache.get()); + } } - if (dr_loadOptions->getFileCache()) fileCache = dr_loadOptions->getFileCache(); - if (dr_loadOptions->getFileLocationCallback()) fileLocationCallback = dr_loadOptions->getFileLocationCallback(); - - - // disable the FileCache if the fileLocationCallback tells us that it isn't required for this request. - if (fileLocationCallback.valid() && !fileLocationCallback->useFileCache()) fileCache = 0; - // check if databaseRequest is still relevant if ((_pager->_frameNumber-frameNumberLastRequest)<=1) @@ -915,31 +937,40 @@ void DatabasePager::DatabaseThread::run() { loadedModel->getBound(); - // find all the compileable rendering objects - DatabasePager::FindCompileableGLObjectsVisitor stateToCompile(_pager, _pager->getMarkerObject()); - loadedModel->accept(stateToCompile); - - bool loadedObjectsNeedToBeCompiled = _pager->_doPreCompile && - _pager->_incrementalCompileOperation.valid() && - _pager->_incrementalCompileOperation->requiresCompile(stateToCompile); - - // move the databaseRequest from the front of the fileRequest to the end of - // dataToCompile or dataToMerge lists. + bool loadedObjectsNeedToBeCompiled = false; osg::ref_ptr compileSet = 0; - if (loadedObjectsNeedToBeCompiled) + if (!rr.loadedFromCache()) { - // OSG_NOTICE<<"Using IncrementalCompileOperation"<getMarkerObject()); + loadedModel->accept(stateToCompile); - compileSet = new osgUtil::IncrementalCompileOperation::CompileSet(loadedModel.get()); - compileSet->buildCompileMap(_pager->_incrementalCompileOperation->getContextSet(), stateToCompile); - compileSet->_compileCompletedCallback = new DatabasePagerCompileCompletedCallback(_pager, databaseRequest.get()); - _pager->_incrementalCompileOperation->add(compileSet.get(), false); + loadedObjectsNeedToBeCompiled = _pager->_doPreCompile && + _pager->_incrementalCompileOperation.valid() && + _pager->_incrementalCompileOperation->requiresCompile(stateToCompile); + + // move the databaseRequest from the front of the fileRequest to the end of + // dataToCompile or dataToMerge lists. + if (loadedObjectsNeedToBeCompiled) + { + // OSG_NOTICE<<"Using IncrementalCompileOperation"<buildCompileMap(_pager->_incrementalCompileOperation->getContextSet(), stateToCompile); + compileSet->_compileCompletedCallback = new DatabasePagerCompileCompletedCallback(_pager, databaseRequest.get()); + _pager->_incrementalCompileOperation->add(compileSet.get(), false); + } } + else + { + OSG_NOTICE<<"Loaded from ObjectCache"< drLock(_pager->_dr_mutex); databaseRequest->_loadedModel = loadedModel; databaseRequest->_compileSet = compileSet; - databaseRequest->_insertLoadedSubgraphIntoObjectCache = cacheNodes; } // Dereference the databaseRequest while the queue is // locked. This prevents the request from being @@ -1451,7 +1482,7 @@ void DatabasePager::requestNodeFile(const std::string& fileName, osg::NodePath& databaseRequest->_group = group; databaseRequest->_terrain = terrain; databaseRequest->_loadOptions = loadOptions; - databaseRequest->_insertLoadedSubgraphIntoObjectCache = false; + databaseRequest->_objectCache = 0; requeue = true; } @@ -1484,7 +1515,7 @@ void DatabasePager::requestNodeFile(const std::string& fileName, osg::NodePath& databaseRequest->_group = group; databaseRequest->_terrain = terrain; databaseRequest->_loadOptions = loadOptions; - databaseRequest->_insertLoadedSubgraphIntoObjectCache = false; + databaseRequest->_objectCache = 0; _fileRequestQueue->addNoLock(databaseRequest.get()); } @@ -1663,11 +1694,10 @@ void DatabasePager::addLoadedDataToSceneGraph(const osg::FrameStamp &frameStamp) registerPagedLODs(databaseRequest->_loadedModel.get(), frameNumber); } - if (databaseRequest->_insertLoadedSubgraphIntoObjectCache) + if (databaseRequest->_objectCache.valid() && osgDB::Registry::instance()->getObjectCache()) { // insert loaded model into Registry ObjectCache - // OSG_NOTICE<<"Inserting loaded Model ("<_fileName<<") into ObjectCache"<addEntryToObjectCache( databaseRequest->_fileName, databaseRequest->_loadedModel.get(), timeStamp); + osgDB::Registry::instance()->getObjectCache()->addObjectCache( databaseRequest->_objectCache.get()); } // OSG_NOTICE<<"merged subgraph"<_fileName<<" after "<_numOfRequests<<" requests and time="<<(timeStamp-databaseRequest->_timestampFirstRequest)*1000.0< lock1(_objectCacheMutex); + OpenThreads::ScopedLock lock2(objectCache->_objectCacheMutex); + + // OSG_NOTICE<<"Inserting objects to main ObjectCache "<_objectCache.size()<_objectCache.begin(), objectCache->_objectCache.end()); +} void ObjectCache::addEntryToObjectCache(const std::string& filename, osg::Object* object, double timestamp) @@ -50,7 +63,11 @@ osg::ref_ptr ObjectCache::getRefFromObjectCache(const std::string& { OpenThreads::ScopedLock lock(_objectCacheMutex); ObjectCacheMap::iterator itr = _objectCache.find(fileName); - if (itr!=_objectCache.end()) return itr->second.first; + if (itr!=_objectCache.end()) + { + // OSG_NOTICE<<"Found "<second.first; + } else return 0; } diff --git a/src/osgDB/Options.cpp b/src/osgDB/Options.cpp index da981c822..51ccb89b5 100644 --- a/src/osgDB/Options.cpp +++ b/src/osgDB/Options.cpp @@ -21,6 +21,7 @@ Options::Options(const Options& options,const osg::CopyOp& copyop): _str(options._str), _databasePaths(options._databasePaths), _objectCacheHint(options._objectCacheHint), + _objectCache(options._objectCache), _precisionHint(options._precisionHint), _buildKdTreesHint(options._buildKdTreesHint), _pluginData(options._pluginData), diff --git a/src/osgDB/Registry.cpp b/src/osgDB/Registry.cpp index 45545da31..3dcec90ba 100644 --- a/src/osgDB/Registry.cpp +++ b/src/osgDB/Registry.cpp @@ -1245,43 +1245,46 @@ ReaderWriter::ReadResult Registry::readImplementation(const ReadFunctor& readFun { std::string file(readFunctor._filename); - bool useObjectCache=false; + bool useObjectCache = false; + const Options* options = readFunctor._options; + ObjectCache* optionsCache = options ? options->getObjectCache() : 0; //Note CACHE_ARCHIVES has a different object that it caches to so it will never be used here - if (_objectCache.valid() && cacheHint!=Options::CACHE_ARCHIVES) + if ((optionsCache || _objectCache.valid()) && cacheHint!=Options::CACHE_ARCHIVES) { - const Options* options=readFunctor._options; - useObjectCache=options ? (options->getObjectCacheHint()&cacheHint)!=0: false; + useObjectCache= options ? (options->getObjectCacheHint()&cacheHint)!=0: false; } if (useObjectCache) { // search for entry in the object cache. + osg::ref_ptr object = optionsCache ? optionsCache->getRefFromObjectCache(file) : 0; + + if (!object && _objectCache.valid()) object = _objectCache->getRefFromObjectCache(file); + + if (object.valid()) { - osg::ref_ptr object = _objectCache->getRefFromObjectCache(file); - if (object.valid()) - { - OSG_INFO<<"returning cached instanced of "< object = _objectCache->getRefFromObjectCache(file); + object = _objectCache->getRefFromObjectCache(file); if (object.valid()) { - OSG_INFO << "returning cached instanced of " << file << std::endl; if (readFunctor.isValid(object.get())) return ReaderWriter::ReadResult(object.get(), ReaderWriter::ReadResult::FILE_LOADED_FROM_CACHE); - else return ReaderWriter::ReadResult("Error file does not contain an osg::Object"); + else + { + return ReaderWriter::ReadResult("Error file does not contain an osg::Object"); + } } // update cache with new entry. - OSG_INFO<<"Adding to object cache "<addEntryToObjectCache(file, rr.getObject(), 0.0); + if (optionsCache) optionsCache->addEntryToObjectCache(file, rr.getObject(), 0.0); + else if (_objectCache.valid()) _objectCache->addEntryToObjectCache(file, rr.getObject(), 0.0); } else {