From d1ca5bd941ebd33ab8dfea9edebc88eff3324c22 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Wed, 18 Nov 2015 01:15:58 -0500 Subject: [PATCH] More cleanup of SpiceManager --- include/openspace/util/spicemanager.h | 48 +++++----- src/util/spicemanager.cpp | 133 ++++++++++++++------------ 2 files changed, 96 insertions(+), 85 deletions(-) diff --git a/include/openspace/util/spicemanager.h b/include/openspace/util/spicemanager.h index 6c521e257d..5e0ab83759 100644 --- a/include/openspace/util/spicemanager.h +++ b/include/openspace/util/spicemanager.h @@ -57,7 +57,10 @@ public: * binary, text-kernel, or meta-kernel which gets loaded into the kernel pool. The * loading is done by passing the \p filePath to the furnsh_c * function. http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/furnsh_c.html - * \param filePath The path to the kernel that should be loaded + * Kernels can safely be loaded multiple times and are reference counted + * \param filePath The path to the kernel that should be loaded. This path will be + * passed to absPath to convert a relative path to an absolute path + * before usage * \return The loaded kernel's unique identifier that can be used to unload the kernel * \pre \p filePath is a non-empty absolute or relative path pointing to an * existing file that contains a SPICE kernel @@ -67,26 +70,6 @@ public: */ KernelHandle loadKernel(std::string filePath); - /** - * Function to find and store the intervals covered by a ck file, this is done - * by using mainly the ckcov_c and ckobj_c functions. - * http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/ckobj_c.html , - * http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/ckcov_c.html - * \param filePath The path to the kernel that should be examined - * \return true if the operation was successful - */ - bool findCkCoverage(const std::string& path); - - /** - * Function to find and store the intervals covered by a spk file, this is done - * by using mainly the spkcov_c and spkobj_c functions. - * http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/spkobj_c.html , - * http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/spkcov_c.html - * \param filePath The path to the kernel that should be examined - * \return true if the operation was successful - */ - bool findSpkCoverage(const std::string& path); - /** * \return true if SPK kernels have been loaded to cover target * for time et @@ -708,6 +691,27 @@ protected: SpiceManager& operator=(const SpiceManager& r) = delete; SpiceManager(SpiceManager&& r) = delete; ~SpiceManager(); + + /** + * Function to find and store the intervals covered by a ck file, this is done + * by using mainly the ckcov_c and ckobj_c functions. + * http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/ckobj_c.html , + * http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/ckcov_c.html + * \param filePath The path to the kernel that should be examined + * \return true if the operation was successful + */ + bool findCkCoverage(const std::string& path); + + /** + * Function to find and store the intervals covered by a spk file, this is done + * by using mainly the spkcov_c and spkobj_c functions. + * http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/spkobj_c.html , + * http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/spkcov_c.html + * \param filePath The path to the kernel that should be examined + * \return true if the operation was successful + */ + bool findSpkCoverage(const std::string& path); + /// A list of all loaded kernels std::vector _loadedKernels; @@ -722,7 +726,7 @@ protected: const static bool _showErrors = false; /// The last assigned kernel-id, used to determine the next free kernel id - KernelHandle _lastAssignedKernel; + KernelHandle _lastAssignedKernel = KernelHandle(0); }; } // namespace openspace diff --git a/src/util/spicemanager.cpp b/src/util/spicemanager.cpp index 61aa4b984a..702227b526 100644 --- a/src/util/spicemanager.cpp +++ b/src/util/spicemanager.cpp @@ -39,13 +39,16 @@ namespace { const std::string _loggerCat = "SpiceManager"; + + // The value comes from + // http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/getmsg_c.html + // as the maximum message length + const unsigned SpiceErrorBufferSize = 1841; } namespace openspace { -SpiceManager::SpiceManager() - : _lastAssignedKernel(0) -{ +SpiceManager::SpiceManager() { // Set the SPICE library to not exit the program if an error occurs erract_c("SET", 0, const_cast("REPORT")); // But we do not want SPICE to print the errors, we will fetch them ourselves @@ -63,111 +66,116 @@ SpiceManager::~SpiceManager() { SpiceManager::KernelHandle SpiceManager::loadKernel(std::string filePath) { + // Preconditions: + // !filePath.empty() + // filePath exists + // Directory(filePath) exists ghoul_assert(!filePath.empty(), "Empty file path"); - ghoul_assert(FileSys.fileExists(filePath), - fmt::format("File '{}' does not exist", filePath) + ghoul_assert( + FileSys.fileExists(filePath), + fmt::format( + "File '{}' ('{}') does not exist", + filePath, + absPath(filePath) + ) + ); + ghoul_assert( + FileSys.directoryExists(ghoul::filesystem::File(filePath).directoryName()), + fmt::format( + "File '{}' exists, but directory '{}' doesn't", + absPath(filePath), + ghoul::filesystem::File(filePath).directoryName() + ) ); std::string path = absPath(filePath); - - if (!FileSys.fileExists(path)) { - LERROR("Kernel file '" << path << "' does not exist"); - return InvalidKernel; - } - - // We need to set the current directory as meta-kernels are usually defined relative - // to the directory they reside in. The directory change is not necessary for regular - // kernels - - ghoul::filesystem::Directory currentDirectory = FileSys.currentDirectory(); - std::string&& fileDirectory = ghoul::filesystem::File(path).directoryName(); - - if (!FileSys.directoryExists(fileDirectory)) { - LERROR("Could not find directory for kernel '" << path << "'"); - return InvalidKernel; - } - auto it = std::find_if( _loadedKernels.begin(), _loadedKernels.end(), [path](const KernelInformation& info) { return info.path == path; }); - if (it != _loadedKernels.end()) - { + if (it != _loadedKernels.end()) { it->refCount++; - LDEBUG("Kernel '" << path << "' was already loaded. " - "New reference count: " << it->refCount); + LDEBUG( + fmt::format( + "Kernel '{}' was already loaded. New reference count: {}", + path, + it->refCount + ) + ); return it->id; } - KernelHandle kernelId = ++_lastAssignedKernel; - + // We need to set the current directory as meta-kernels are usually defined relative + // to the directory they reside in. The directory change is not necessary for regular + // kernels + ghoul::filesystem::Directory currentDirectory = FileSys.currentDirectory(); + std::string fileDirectory = ghoul::filesystem::File(path, true).directoryName(); FileSys.setCurrentDirectory(fileDirectory); LINFO("Loading SPICE kernel '" << path << "'"); - // Load the kernel + // Load the kernel furnsh_c(path.c_str()); - std::string fileExtension = path.substr(path.size() - 3); - if (fileExtension == ".bc" || fileExtension == ".BC") { // binary ck kernel - findCkCoverage(path); - } - else if (fileExtension == "bsp" || fileExtension == "BSP") { // binary spk kernel - findSpkCoverage(path); - } + // Reset the current directory to the previous one + FileSys.setCurrentDirectory(currentDirectory); - - // Reset the current directory to the previous one - FileSys.setCurrentDirectory(currentDirectory); - int failed = failed_c(); + SpiceBoolean failed = failed_c(); if (failed) { - char msg[1024]; - getmsg_c ( "LONG", 1024, msg ); - LERROR("Error loading kernel '" + path + "'"); - LERROR("Spice reported: " + std::string(msg)); + char* buffer = new char[SpiceErrorBufferSize]; + getmsg_c("LONG", SpiceErrorBufferSize, buffer); + LERROR(fmt::format("Error loading kernel '{}'", path)); + LERROR(fmt::format("Spice reported: {}", buffer)); reset_c(); + delete[] buffer; return InvalidKernel; } + + std::string fileExtension = ghoul::filesystem::File(path, true).fileExtension(); + bool success = true; + if (fileExtension == ".bc" || fileExtension == ".BC") + success = findCkCoverage(path); // binary ck kernel + else if (fileExtension == "bsp" || fileExtension == "BSP") + success = findSpkCoverage(path); // binary spk kernel - bool hasError = checkForError("Error loading kernel '" + path + "'"); - if (hasError) - return InvalidKernel; + if (!success) + return InvalidKernel; else { - KernelInformation&& info = { path, std::move(kernelId), 1 }; - _loadedKernels.push_back(info); + KernelHandle kernelId = ++_lastAssignedKernel; + ghoul_assert(kernelId != 0, fmt::format("Kernel Handle wrapped around to 0")); + _loadedKernels.push_back({std::move(path), kernelId, 1}); return kernelId; } } bool SpiceManager::findCkCoverage(const std::string& path) { - SpiceInt frame, numberOfIntervals; - SpiceDouble b, e; - std::pair tempInterval; SPICEINT_CELL(ids, MAXOBJ); SPICEDOUBLE_CELL(cover, WINSIZ); ckobj_c(path.c_str(), &ids); for (SpiceInt i = 0; i < card_c(&ids); ++i) { - frame = SPICE_CELL_ELEM_I(&ids, i); + SpiceInt frame = SPICE_CELL_ELEM_I(&ids, i); scard_c(0, &cover); ckcov_c(path.c_str(), frame, SPICEFALSE, "SEGMENT", 0.0, "TDB", &cover); //Get the number of intervals in the coverage window. - numberOfIntervals = wncard_c(&cover); + SpiceInt numberOfIntervals = wncard_c(&cover); for (SpiceInt j = 0; j < numberOfIntervals; ++j) { //Get the endpoints of the jth interval. + SpiceDouble b, e; wnfetd_c(&cover, j, &b, &e); - tempInterval = std::make_pair(b, e); _ckCoverageTimes[frame].insert(e); _ckCoverageTimes[frame].insert(b); - _ckIntervals[frame].push_back(tempInterval); + _ckIntervals[frame].emplace_back(b, e); } } - return true; + + bool success = checkForError("Error finding Ck Converage"); + return success; } bool SpiceManager::findSpkCoverage(const std::string& path) { @@ -196,11 +204,11 @@ bool SpiceManager::findSpkCoverage(const std::string& path) { _spkIntervals[obj].push_back(tempInterval); } } - return true; + bool success = checkForError("Error finding Spk Converage"); + return success; } -bool SpiceManager::hasSpkCoverage(std::string target, double& et) const -{ +bool SpiceManager::hasSpkCoverage(std::string target, double& et) const { int id; bool idSuccess = getNaifId(target, id); bool hasCoverage = false; @@ -221,8 +229,7 @@ bool SpiceManager::hasSpkCoverage(std::string target, double& et) const return idSuccess && hasCoverage; } -bool SpiceManager::hasCkCoverage(std::string frame, double& et) const -{ +bool SpiceManager::hasCkCoverage(std::string frame, double& et) const { int id; bool idSuccess = getFrameId(frame, id); bool hasCoverage = false;