diff --git a/algo/base/Exceptions.h b/algo/base/Exceptions.h index 002795e1ab4b834934caef81fa15adf53cbdfb43..a5ab73ee02c1ae73223ff00fa3ae06f71976c85c 100644 --- a/algo/base/Exceptions.h +++ b/algo/base/Exceptions.h @@ -5,18 +5,20 @@ #define CBM_ALGO_BASE_EXCEPTIONS_H #include <exception> +#include <string_view> #include <fmt/format.h> namespace cbm::algo { /** - * @brief Base class for exceptions + * @brief Base class for exceptions. + * + * @note Should not be thrown directly. Use one of the derived classes instead. */ - class Exception : public std::runtime_error { - public: + struct Exception : std::runtime_error { template<typename... Args> - Exception(const char* fmt, Args&&... args) : std::runtime_error(fmt::format(fmt, std::forward<Args>(args)...)) + Exception(std::string_view fmt, Args&&... args) : std::runtime_error(fmt::format(fmt, std::forward<Args>(args)...)) { } }; @@ -24,7 +26,7 @@ namespace cbm::algo /** * @brief Indicates an unrecoverable error. Should tear down the process. */ - class FatalError : public Exception { + struct FatalError : Exception { using Exception::Exception; }; @@ -32,7 +34,7 @@ namespace cbm::algo * Indicates an error during timeslice processing. Timeslice will be discarded. * Processing can continue with new timeslice. */ - class ProcessingError : public Exception { + struct ProcessingError : Exception { using Exception::Exception; }; diff --git a/algo/base/Options.cxx b/algo/base/Options.cxx index 93354ae3866025caf14757b4982266a9e2300931..800714fe793f98555a5ead24ba2e815aa0c2ed0a 100644 --- a/algo/base/Options.cxx +++ b/algo/base/Options.cxx @@ -72,7 +72,7 @@ Options::Options(int argc, char** argv) ("histogram", po::value(&fHistogramUri)->value_name("<uri>"), "URI to specify histogram server") ("log-file,L", po::value(&fLogFile)->value_name("<file>"), "write log messages to file") - ("output-types,O", po::value(&fOutputTypes)->multitoken()->default_value({RecoData::Hit})->value_name("<types>"), + ("output-types,O", po::value(&fOutputTypes)->multitoken()->value_name("<types>"), "comma seperated list of reconstruction output types (hit, digi, ...)") ("steps", po::value(&fRecoSteps)->multitoken()->default_value({Step::Unpack, Step::DigiTrigger, Step::LocalReco, Step::Tracking})->value_name("<steps>"), "comma seperated list of reconstruction steps (upack, digitrigger, localreco, ...)") diff --git a/algo/global/Reco.cxx b/algo/global/Reco.cxx index 2392645e35f1163d70774123e074876a29eeb6ef..796ce31e1832dc386dc7af80883882c9a60025ca 100644 --- a/algo/global/Reco.cxx +++ b/algo/global/Reco.cxx @@ -10,6 +10,7 @@ #include <xpu/host.h> +#include "Exceptions.h" #include "compat/OpenMP.h" #include "config/Yaml.h" #include "evbuild/Config.h" @@ -24,14 +25,20 @@ Reco::~Reco() {} void Reco::Validate(const Options& opts) { - if (!fs::exists(opts.ParamsDir())) { - throw std::runtime_error("ParamsDir does not exist: " + opts.ParamsDir().string()); - } + if (!fs::exists(opts.ParamsDir())) throw FatalError("ParamsDir does not exist: {}", opts.ParamsDir().string()); + + if (opts.HasOutput(RecoData::Digi)) throw FatalError("Storing raw digis via 'Digi' option not supported"); + if (opts.HasOutput(RecoData::Cluster)) throw FatalError("Storing clusters via 'Cluster' option not supported"); - if (opts.HasOutput(RecoData::Digi)) { throw std::runtime_error("Storing raw digis via 'Digi' option not supported"); } + bool hasOutputFile = !opts.OutputFile().empty(); + bool hasOutputType = !opts.OutputTypes().empty(); + + if (!hasOutputFile && hasOutputType) { + throw FatalError("Output types specified, but no output file given: -o <file> missing"); + } - if (opts.HasOutput(RecoData::Cluster)) { - throw std::runtime_error("Storing clusters via 'Cluster' option not supported"); + if (hasOutputFile && !hasOutputType) { + throw FatalError("Output file specified, but no output types given: -O <types> missing"); } }