From 33bbde0d17a162decdfc22537a2875f3d70aa377 Mon Sep 17 00:00:00 2001
From: Felix Weiglhofer <weiglhofer@fias.uni-frankfurt.de>
Date: Sun, 29 Oct 2023 12:35:51 +0100
Subject: [PATCH] algo: Raise error if only one of output-file and output-type
 is specified.

---
 algo/base/Exceptions.h | 14 ++++++++------
 algo/base/Options.cxx  |  2 +-
 algo/global/Reco.cxx   | 19 +++++++++++++------
 3 files changed, 22 insertions(+), 13 deletions(-)

diff --git a/algo/base/Exceptions.h b/algo/base/Exceptions.h
index 002795e1ab..a5ab73ee02 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 93354ae386..800714fe79 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 2392645e35..796ce31e18 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");
   }
 }
 
-- 
GitLab