- Enable caching of TileProviders at startup time

- Enable path tokens in filename for temporal tile providers
 - Add support for relative paths in temporal tile providers
 - Set the GDAL temp dir to the BASE_PATH
 -
This commit is contained in:
Alexander Bock
2017-04-17 18:38:36 -04:00
parent 26e4354c40
commit 0db98afe6e
6 changed files with 91 additions and 6 deletions
@@ -54,13 +54,16 @@ std::ostream& operator<<(std::ostream& os, const PixelRegion& pr) {
", " << pr.numPixels.y;
}
GdalRawTileDataReader::GdalRawTileDataReader(
const std::string& filePath, const Configuration& config)
GdalRawTileDataReader::GdalRawTileDataReader(const std::string& filePath,
const Configuration& config,
const std::string& baseDirectory)
: RawTileDataReader(config)
, _dataset(nullptr)
{
_initData = { "", filePath, config.tilePixelSize, config.dataType };
_initData.initDirectory = CPLGetCurrentDir();
std::string initDir = baseDirectory.empty() ? CPLGetCurrentDir() : baseDirectory;
_initData = { initDir, filePath, config.tilePixelSize, config.dataType };
ensureInitialized();
}
@@ -303,6 +306,7 @@ GDALDataset* GdalRawTileDataReader::openGdalDataset(const std::string& filePath)
std::string correctedPath = FileSystem::ref().pathByAppendingComponent(
_initData.initDirectory, filePath
);
dataset = (GDALDataset *)GDALOpen(correctedPath.c_str(), GA_ReadOnly);
if (!dataset) {
throw ghoul::RuntimeError("Failed to load dataset:\n" + filePath);
@@ -60,8 +60,10 @@ public:
*
* \param filePath, a path to a specific file GDAL can read
* \param config, Configuration used for initialization
* \param baseDirectory, the base directory to use in future loading operations
*/
GdalRawTileDataReader(const std::string& filePath, const Configuration& config);
GdalRawTileDataReader(const std::string& filePath, const Configuration& config,
const std::string& baseDirectory = "");
virtual ~GdalRawTileDataReader() override;
@@ -105,6 +105,10 @@ GdalWrapper::GdalWrapper(size_t maximumCacheSize,
"GDAL_DATA",
absPath("${MODULE_GLOBEBROWSING}/gdal_data").c_str()
);
CPLSetConfigOption(
"CPL_TMPDIR",
absPath("${BASE_PATH}").c_str()
);
setGdalProxyConfiguration();
CPLSetErrorHandler(gdalErrorHandler);
@@ -40,7 +40,9 @@ namespace {
const char* KeyDoPreProcessing = "DoPreProcessing";
const char* KeyTilePixelSize = "TilePixelSize";
const char* KeyFilePath = "FilePath";
const char* KeyBasePath = "BasePath";
const char* KeyFlushInterval = "FlushInterval";
const char* KeyPreCacheLevel = "PreCacheLevel";
}
namespace openspace {
@@ -84,9 +86,12 @@ CachingTileProvider::CachingTileProvider(const ghoul::Dictionary& dictionary)
framesUntilRequestFlush);
}
std::string basePath;
dictionary.getValue(KeyBasePath, basePath);
// Initialize instance variables
#ifdef GLOBEBROWSING_USE_GDAL
auto tileDataset = std::make_shared<GdalRawTileDataReader>(filePath, config);
auto tileDataset = std::make_shared<GdalRawTileDataReader>(filePath, config, basePath);
#else // GLOBEBROWSING_USE_GDAL
auto tileDataset = std::make_shared<SimpleRawTileDataReader>(filePath, config);
#endif // GLOBEBROWSING_USE_GDAL
@@ -99,6 +104,18 @@ CachingTileProvider::CachingTileProvider(const ghoul::Dictionary& dictionary)
_asyncTextureDataProvider = std::make_shared<AsyncTileDataProvider>(
tileDataset, threadPool);
_framesUntilRequestFlush = framesUntilRequestFlush;
if (dictionary.hasKeyAndValue<double>(KeyPreCacheLevel)) {
int preCacheLevel = static_cast<int>(dictionary.value<double>(KeyPreCacheLevel));
LDEBUG("Precaching '" << filePath << "' with level '" << preCacheLevel << "'");
for (int level = 0; level <= preCacheLevel; ++level) {
for (int x = 0; x <= level * 2; ++x) {
for (int y = 0; y <= level; ++y) {
_asyncTextureDataProvider->enqueueTileIO({ x, y, level });
}
}
}
}
}
CachingTileProvider::CachingTileProvider(
@@ -41,8 +41,11 @@ namespace {
const char* KeyDoPreProcessing = "DoPreProcessing";
const char* KeyMinimumPixelSize = "MinimumPixelSize";
const char* KeyFilePath = "FilePath";
const char* KeyBasePath = "BasePath";
const char* KeyCacheSize = "CacheSize";
const char* KeyFlushInterval = "FlushInterval";
const char* KeyPreCacheStartTime = "PreCacheStartTime";
const char* KeyPreCacheEndTime = "PreCacheEndTime";
}
namespace openspace {
@@ -64,6 +67,8 @@ TemporalTileProvider::TemporalTileProvider(const ghoul::Dictionary& dictionary)
throw std::runtime_error(std::string("Must define key '") + KeyFilePath + "'");
}
_datasetFile = absPath(_datasetFile);
std::ifstream in(_datasetFile.c_str());
if (!in.is_open()) {
throw ghoul::FileNotFoundError(_datasetFile);
@@ -74,7 +79,29 @@ TemporalTileProvider::TemporalTileProvider(const ghoul::Dictionary& dictionary)
std::istreambuf_iterator<char>(in),
(std::istreambuf_iterator<char>())
);
_initDict.setValue<std::string>(
KeyBasePath,
ghoul::filesystem::File(_datasetFile).directoryName()
);
_gdalXmlTemplate = consumeTemporalMetaData(xml);
const bool hasStart = dictionary.hasKeyAndValue<std::string>(KeyPreCacheStartTime);
const bool hasEnd = dictionary.hasKeyAndValue<std::string>(KeyPreCacheEndTime);
if (hasStart && hasEnd) {
const std::string start = dictionary.value<std::string>(KeyPreCacheStartTime);
const std::string end = dictionary.value<std::string>(KeyPreCacheEndTime);
std::vector<Time> preCacheTimes = _timeQuantizer.quantized(
Time(Time::convertTime(start)),
Time(Time::convertTime(end))
);
LINFO("Preloading: " << _datasetFile);
for (Time& t : preCacheTimes) {
getTileProvider(t);
}
}
}
std::string TemporalTileProvider::consumeTemporalMetaData(const std::string& xml) {
@@ -378,6 +405,28 @@ bool TimeQuantizer::quantize(Time& t, bool clamp) const {
}
}
std::vector<Time> TimeQuantizer::quantized(const Time& start, const Time& end) const {
Time s = start;
quantize(s, true);
Time e = end;
quantize(e, true);
const double startSeconds = s.j2000Seconds();
const double endSeconds = e.j2000Seconds();
const double delta = endSeconds - startSeconds;
ghoul_assert(int(delta) % int(_resolution) == 0, "Quantization error");
const int nSteps = delta / _resolution;
std::vector<Time> result(nSteps + 1);
for (int i = 0; i <= nSteps; ++i) {
result[i].setTime(startSeconds + i * _resolution, false);
}
return result;
}
} // namespace tileprovider
} // namespace globebrowsing
} // namespace openspace
@@ -151,6 +151,15 @@ struct TimeQuantizer {
*/
bool quantize(Time& t, bool clamp) const;
/**
* Returns a list of quantized Time objects that represent all the valid quantized
* Time%s between \p start and \p end.
* \param start The start time for the time range quantization
* \param end The end time for the time range quantization
* \return A list of quantized times between \p start and \end
*/
std::vector<Time> quantized(const Time& start, const Time& end) const;
private:
TimeRange _timerange;
double _resolution;