diff --git a/include/osgDB/ReaderWriter b/include/osgDB/ReaderWriter index f6aca6cbd..5a48b491c 100644 --- a/include/osgDB/ReaderWriter +++ b/include/osgDB/ReaderWriter @@ -90,17 +90,21 @@ class OSGDB_EXPORT ReaderWriter : public osg::Object Options(): osg::Object(true), - _objectCacheHint(CACHE_ARCHIVES) {} + _objectCacheHint(CACHE_ARCHIVES), + _asynchronousFileReadHint(false) {} + Options(const std::string& str): osg::Object(true), _str(str), - _objectCacheHint(CACHE_ARCHIVES) {} + _objectCacheHint(CACHE_ARCHIVES), + _asynchronousFileReadHint(false) {} Options(const Options& options,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY): osg::Object(options,copyop), _str(options._str), _databasePaths(options._databasePaths), - _objectCacheHint(options._objectCacheHint) {} + _objectCacheHint(options._objectCacheHint), + _asynchronousFileReadHint(options._asynchronousFileReadHint) {} META_Object(osgDB,Options); @@ -119,12 +123,29 @@ class OSGDB_EXPORT ReaderWriter : public osg::Object /** Get the const database path which is used a hint of where to look when loading models.*/ const FilePathList& getDatabasePathList() const { return _databasePaths; } + /** Set whether the Registry::ObjectCache should be used by default.*/ void setObjectCacheHint(CacheHintOptions useObjectCache) { _objectCacheHint = useObjectCache; } /** Get whether the Registry::ObjectCache should be used by default.*/ CacheHintOptions getObjectCacheHint() const { return _objectCacheHint; } + + /** Set Asynchrnous file read hint. + * This hint is used by plugins like the libcurl http reader plugin to inform them that + * they should make an internal file read requests to their background threads to load files, + * with the plugin returning immediately with a ReadResult::FILE_REQUESTED status. It is + * assumed that calls will continue to be made to the plugin until the background threads + * have read or failed to read the request file, at which point the return status which change + * to FILE_LOADED and the objects will be returned. + * Note, this facility is particular useful when using DatabasePager in conjunction with + * internet based databases where file load latency is relatively high.*/ + void setAsynchronousFileReadHint(bool flag) { _asynchronousFileReadHint = flag; } + + /** Get Asynchrnous file read hint. */ + bool getAsynchronousFileReadHint() const { return _asynchronousFileReadHint; } + + /** Sets a plugindata value PluginData with a string */ void setPluginData(const std::string& s, void* v) const { _pluginData[s] = v; } @@ -148,6 +169,7 @@ class OSGDB_EXPORT ReaderWriter : public osg::Object std::string _str; FilePathList _databasePaths; CacheHintOptions _objectCacheHint; + bool _asynchronousFileReadHint; typedef std::map PluginDataMap; mutable PluginDataMap _pluginData; @@ -160,11 +182,12 @@ class OSGDB_EXPORT ReaderWriter : public osg::Object enum ReadStatus { - FILE_NOT_HANDLED, //!< file is not appropriate for this file reader, due to some incompatibility, but *not* a read error - FILE_NOT_FOUND, //!< file could not be found or could not be read - FILE_LOADED, //!< file successfully found, loaded, and converted into osg - FILE_LOADED_FROM_CACHE, //!< file found in cache and returned - ERROR_IN_READING_FILE //!< file found, loaded, but an error was encountered during processing + FILE_NOT_HANDLED, //!< File is not appropriate for this file reader, due to some incompatibility, but *not* a read error. + FILE_NOT_FOUND, //!< File could not be found or could not be read. + FILE_LOADED, //!< File successfully found, loaded, and converted into osg. + FILE_LOADED_FROM_CACHE, //!< File found in cache and returned. + ERROR_IN_READING_FILE, //!< File found, loaded, but an error was encountered during processing. + FILE_REQUESTED, //!< Asyncronous file read has been requested, but returning immediatiely, keep polling plugin till file read has been completed. }; ReadResult(ReadStatus status=FILE_NOT_HANDLED):_status(status) {} diff --git a/src/osgDB/DatabasePager.cpp b/src/osgDB/DatabasePager.cpp index 14a31f171..7130051a4 100644 --- a/src/osgDB/DatabasePager.cpp +++ b/src/osgDB/DatabasePager.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -419,7 +420,22 @@ void DatabasePager::requestNodeFile(const std::string& fileName,osg::Group* grou databaseRequest->_timestampLastRequest = timestamp; databaseRequest->_priorityLastRequest = priority; databaseRequest->_groupForAddingLoadedSubgraph = group; - databaseRequest->_loadOptions = loadOptions; + + if ((Registry::instance()->getOptions()==loadOptions) && + (loadOptions ? !loadOptions->getAsynchronousFileReadHint() : true) && + osgDB::containsServerAddress(fileName)) + { + // we need to enable asynchronous file reading. + databaseRequest->_loadOptions = loadOptions ? + dynamic_cast(loadOptions->clone(osg::CopyOp::SHALLOW_COPY)) : + new osgDB::ReaderWriter::Options; + + databaseRequest->_loadOptions->setAsynchronousFileReadHint(true); + } + else + { + databaseRequest->_loadOptions = loadOptions; + } _fileRequestList.push_back(databaseRequest); diff --git a/src/osgPlugins/curl/ReaderWriterCURL.cpp b/src/osgPlugins/curl/ReaderWriterCURL.cpp index 804f33779..7b3948a13 100644 --- a/src/osgPlugins/curl/ReaderWriterCURL.cpp +++ b/src/osgPlugins/curl/ReaderWriterCURL.cpp @@ -316,6 +316,11 @@ class ReaderWriterCURL : public osgDB::ReaderWriter proxyAddress = std::string(proxyEnvAddress) + ":8080"; //Default } + bool asyncFileRead = options ? options->getAsynchronousFileReadHint() : false; + + osg::notify(osg::INFO)<<"AsynchronousFileReadHint= "<