From 57a7bf2f20f38b27b854ecbc1554af047fc40b85 Mon Sep 17 00:00:00 2001
From: tmadlener <thomas.madlener@desy.de>
Date: Fri, 19 May 2023 19:21:10 +0200
Subject: [PATCH] Remove the Frame re-implementation and use the one from podio

---
 CMakeLists.txt                 |   2 +-
 DDDigi/io/DigiEdm4hepInput.cpp |   8 +-
 DDDigi/io/DigiFrame.h          | 420 ---------------------------------
 3 files changed, 5 insertions(+), 425 deletions(-)
 delete mode 100644 DDDigi/io/DigiFrame.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 099ae74a6..04acc1723 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -151,7 +151,7 @@ endif()
 
 if(DD4HEP_USE_EDM4HEP)
   find_package(EDM4HEP REQUIRED)
-  find_package(podio 0.16.0 REQUIRED)
+  find_package(podio 0.16.3 REQUIRED)
 #  DD4HEP_SETUP_EDM4HEP_TARGETS()
 endif()
 
diff --git a/DDDigi/io/DigiEdm4hepInput.cpp b/DDDigi/io/DigiEdm4hepInput.cpp
index fae54e153..848896081 100644
--- a/DDDigi/io/DigiEdm4hepInput.cpp
+++ b/DDDigi/io/DigiEdm4hepInput.cpp
@@ -16,9 +16,9 @@
 #include "DigiIO.h"
 
 // podio/edm4hep include files
-#include "DigiFrame.h"
-//#include <podio/Frame.h>
+#include <podio/Frame.h>
 #include <podio/ROOTFrameReader.h>
+
 #include <edm4hep/SimTrackerHit.h>
 #include <edm4hep/SimCalorimeterHit.h>
 #include <edm4hep/MCParticleCollection.h>
@@ -44,7 +44,7 @@ namespace dd4hep {
     public:
       podio::Frame frame { };
       edm4hep_read_frame_t(podio::Frame&& frm) : frame(std::move(frm)) { }
-      const podio::CollectionBase* get(const std::string& nam) const { return frame.self()->get(nam); }
+      const podio::CollectionBase* get(const std::string& nam) const { return frame.get(nam); }
     };
     
     using reader_t = podio::ROOTFrameReader;
@@ -271,7 +271,7 @@ namespace dd4hep {
     {
       DataParameters parameters(nam, mask);
       data_io<edm4hep_input>()._to_digi(Key(nam, segment.id, mask), *collection, parameters);
-      data_io<edm4hep_input>()._to_digi(Key(nam, segment.id, mask), frame.getGenericParameters(), parameters);
+      data_io<edm4hep_input>()._to_digi(Key(nam, segment.id, mask), frame.getParameters(), parameters);
       debug("%s+++ Converted %ld Edm4hep transient", context.event->id(), parameters.size());
       put_data(segment, Key(nam, mask), std::move(parameters));
     }
diff --git a/DDDigi/io/DigiFrame.h b/DDDigi/io/DigiFrame.h
deleted file mode 100644
index a8e8e9c86..000000000
--- a/DDDigi/io/DigiFrame.h
+++ /dev/null
@@ -1,420 +0,0 @@
-#ifndef PODIO_FRAME_H
-#define PODIO_FRAME_H
-
-#include "podio/CollectionBase.h"
-#include "podio/CollectionIDTable.h"
-#include "podio/GenericParameters.h"
-#include "podio/ICollectionProvider.h"
-#include "podio/utilities/TypeHelpers.h"
-
-#include <initializer_list>
-#include <memory>
-#include <mutex>
-#include <optional>
-#include <set>
-#include <string>
-#include <type_traits>
-#include <unordered_map>
-#include <vector>
-
-namespace podio {
-
-/// Alias template for enabling overloads only for Collections
-template <typename T>
-using EnableIfCollection = typename std::enable_if_t<isCollection<T>>;
-
-/// Alias template for enabling overloads only for Collection r-values
-template <typename T>
-using EnableIfCollectionRValue = typename std::enable_if_t<isCollection<T> && !std::is_lvalue_reference_v<T>>;
-
-namespace detail {
-  /** The minimal interface for raw data types
-   */
-  struct EmptyFrameData {
-    podio::CollectionIDTable getIDTable() const {
-      return {};
-    }
-
-    std::optional<podio::CollectionReadBuffers> getCollectionBuffers(const std::string&) {
-      return std::nullopt;
-    }
-
-    /** Get the still available, i.e. yet unpacked, collections from the raw data
-     */
-    std::vector<std::string> getAvailableCollections() const {
-      return {};
-    }
-
-    /** Get the parameters that are stored in the raw data
-     */
-    std::unique_ptr<podio::GenericParameters> getParameters() {
-      return std::make_unique<podio::GenericParameters>();
-    }
-  };
-} // namespace detail
-
-template <typename FrameDataT>
-std::optional<podio::CollectionReadBuffers> unpack(FrameDataT* data, const std::string& name) {
-  return data->getCollectionBuffers(name);
-}
-
-/**
- * Frame class that serves as a container of collection and meta data.
- */
-class Frame {
-  /**
-   * Internal abstract interface for the type-erased implementation of the Frame
-   * class
-   */
-  struct FrameConcept {
-    virtual ~FrameConcept() = default;
-    virtual const podio::CollectionBase* get(const std::string& name) const = 0;
-    virtual const podio::CollectionBase* put(std::unique_ptr<podio::CollectionBase> coll, const std::string& name) = 0;
-    virtual podio::GenericParameters& parameters() = 0;
-    virtual const podio::GenericParameters& parameters() const = 0;
-
-    virtual std::vector<std::string> availableCollections() const = 0;
-
-    // Writing interface. Need this to be able to store all necessary information
-    // TODO: Figure out whether this can be "hidden" somehow
-    virtual podio::CollectionIDTable getIDTable() const = 0;
-  };
-
-  /**
-   * The interface implementation of the abstract FrameConcept that is necessary
-   * for a type-erased implementation of the Frame class
-   */
-  template <typename FrameDataT>
-  struct FrameModel final : FrameConcept, public ICollectionProvider {
-
-    FrameModel(std::unique_ptr<FrameDataT> data);
-    ~FrameModel() = default;
-    FrameModel(const FrameModel&) = delete;
-    FrameModel& operator=(const FrameModel&) = delete;
-    FrameModel(FrameModel&&) = default;
-    FrameModel& operator=(FrameModel&&) = default;
-
-    /** Try and get the collection from the internal storage and return a
-     * pointer to it if found. Otherwise return a nullptr
-     */
-    const podio::CollectionBase* get(const std::string& name) const final;
-
-    /** Try and place the collection into the internal storage and return a
-     * pointer to it. If a collection already exists or insertion fails, return
-     * a nullptr
-     */
-    const podio::CollectionBase* put(std::unique_ptr<CollectionBase> coll, const std::string& name) final;
-
-    /** Get a reference to the internally used GenericParameters
-     */
-    podio::GenericParameters& parameters() override {
-      return *m_parameters;
-    }
-    /** Get a const reference to the internally used GenericParameters
-     */
-    const podio::GenericParameters& parameters() const override {
-      return *m_parameters;
-    };
-
-    bool get(int collectionID, podio::CollectionBase*& collection) const override;
-
-    podio::CollectionIDTable getIDTable() const override {
-      // Make a copy
-      return {m_idTable.ids(), m_idTable.names()};
-    }
-
-    std::vector<std::string> availableCollections() const override;
-
-  private:
-    podio::CollectionBase* doGet(const std::string& name, bool setReferences = true) const;
-
-    using CollectionMapT = std::unordered_map<std::string, std::unique_ptr<podio::CollectionBase>>;
-
-    mutable CollectionMapT m_collections{};                 ///< The internal map for storing unpacked collections
-    mutable std::unique_ptr<std::mutex> m_mapMtx{nullptr};  ///< The mutex for guarding the internal collection map
-    std::unique_ptr<FrameDataT> m_data{nullptr};            ///< The raw data read from file
-    mutable std::unique_ptr<std::mutex> m_dataMtx{nullptr}; ///< The mutex for guarding the raw data
-    podio::CollectionIDTable m_idTable{};                   ///< The collection ID table
-    std::unique_ptr<podio::GenericParameters> m_parameters{nullptr}; ///< The generic parameter store for this frame
-    mutable std::set<int> m_retrievedIDs{}; ///< The IDs of the collections that we have already read (but not yet put
-                                            ///< into the map)
-  };
-
-  std::unique_ptr<FrameConcept> m_self; ///< The internal concept pointer through which all the work is done
-
-public:
-  /** Empty Frame constructor
-   */
-  Frame();
-
-  /** Frame constructor from (almost) arbitrary raw data
-   */
-  template <typename FrameDataT>
-  Frame(std::unique_ptr<FrameDataT>);
-
-  // The frame is a non-copyable type
-  Frame(const Frame&) = delete;
-  Frame& operator=(const Frame&) = delete;
-
-  Frame(Frame&&) = default;
-  Frame& operator=(Frame&&) = default;
-
-  /** Frame destructor */
-  ~Frame() = default;
-
-  const std::unique_ptr<FrameConcept>& self() const  { return m_self; }
-
-  /** Get a collection from the Frame
-   */
-  template <typename CollT, typename = EnableIfCollection<CollT>>
-  const CollT& get(const std::string& name) const;
-
-  /** (Destructively) move a collection into the Frame and get a const reference
-   * back for further use
-   */
-  template <typename CollT, typename = EnableIfCollectionRValue<CollT>>
-  const CollT& put(CollT&& coll, const std::string& name);
-
-  /** Move a collection into the Frame handing over ownership to the Frame
-   */
-  void put(std::unique_ptr<podio::CollectionBase> coll, const std::string& name);
-
-  /** Add a value to the parameters of the Frame (if the type is supported).
-   * Copy the value into the internal store
-   */
-  template <typename T, typename = podio::EnableIfValidGenericDataType<T>>
-  void putParameter(const std::string& key, T value) {
-    m_self->parameters().setValue(key, value);
-  }
-
-  /** Add a string value to the parameters of the Frame by copying it. Dedicated
-   * overload for enabling the on-the-fly conversion on the string literals.
-   */
-  void putParameter(const std::string& key, std::string value) {
-    putParameter<std::string>(key, std::move(value));
-  }
-
-  /** Add a vector of strings to the parameters of the Frame (via copy).
-   * Dedicated overload for enabling on-the-fly conversions of initializer_list
-   * of string literals.
-   */
-  void putParameter(const std::string& key, std::vector<std::string> values) {
-    putParameter<std::vector<std::string>>(key, std::move(values));
-  }
-
-  /** Add a vector of values into the parameters of the Frame. Overload for
-   * catching on-the-fly conversions of initializer_lists of values.
-   */
-  template <typename T, typename = std::enable_if_t<detail::isInTuple<T, SupportedGenericDataTypes>>>
-  void putParameter(const std::string& key, std::initializer_list<T>&& values) {
-    putParameter<std::vector<T>>(key, std::move(values));
-  }
-
-  /** Retrieve parameters via key from the internal store. Return type will
-   * either by a const reference or a value depending on the desired type.
-   */
-  template <typename T, typename = podio::EnableIfValidGenericDataType<T>>
-  podio::GenericDataReturnType<T> getParameter(const std::string& key) const {
-    return m_self->parameters().getValue<T>(key);
-  }
-
-  /** Get all **currently** available collections (including potentially
-   * unpacked ones from raw data)
-   */
-  std::vector<std::string> getAvailableCollections() const {
-    return m_self->availableCollections();
-  }
-
-  // Interfaces for writing below
-  // TODO: Hide this from the public interface somehow?
-
-  /**
-   * Get the GenericParameters for writing
-   */
-  const podio::GenericParameters& getGenericParametersForWrite() const {
-    return m_self->parameters();
-  }
-  /// MSF: Added by me.
-  const podio::GenericParameters& getGenericParameters() const {
-    return m_self->parameters();
-  }
-
-  /**
-   * Get a collection for writing (in a prepared and "ready-to-write" state)
-   */
-  const podio::CollectionBase* getCollectionForWrite(const std::string& name) const {
-    const auto* coll = m_self->get(name);
-    if (coll) {
-      coll->prepareForWrite();
-    }
-
-    return coll;
-  }
-
-  podio::CollectionIDTable getCollectionIDTableForWrite() const {
-    return m_self->getIDTable();
-  }
-};
-
-// implementations below
-
-Frame::Frame() : Frame(std::make_unique<detail::EmptyFrameData>()) {
-}
-
-template <typename FrameDataT>
-Frame::Frame(std::unique_ptr<FrameDataT> data) : m_self(std::make_unique<FrameModel<FrameDataT>>(std::move(data))) {
-}
-
-template <typename CollT, typename>
-const CollT& Frame::get(const std::string& name) const {
-  const auto* coll = dynamic_cast<const CollT*>(m_self->get(name));
-  if (coll) {
-    return *coll;
-  }
-  // TODO: Handle non-existing collections
-  static const auto emptyColl = CollT();
-  return emptyColl;
-}
-
-void Frame::put(std::unique_ptr<podio::CollectionBase> coll, const std::string& name) {
-  const auto* retColl = m_self->put(std::move(coll), name);
-  if (!retColl) {
-    // TODO: Handle collisions
-  }
-}
-
-template <typename CollT, typename>
-const CollT& Frame::put(CollT&& coll, const std::string& name) {
-  const auto* retColl = static_cast<const CollT*>(m_self->put(std::make_unique<CollT>(std::move(coll)), name));
-  if (retColl) {
-    return *retColl;
-  }
-  // TODO: Handle collision case
-  static const auto emptyColl = CollT();
-  return emptyColl;
-}
-
-template <typename FrameDataT>
-Frame::FrameModel<FrameDataT>::FrameModel(std::unique_ptr<FrameDataT> data) :
-    m_mapMtx(std::make_unique<std::mutex>()),
-    m_data(std::move(data)),
-    m_dataMtx(std::make_unique<std::mutex>()),
-    m_idTable(std::move(m_data->getIDTable())),
-    m_parameters(std::move(m_data->getParameters())) {
-}
-
-template <typename FrameDataT>
-const podio::CollectionBase* Frame::FrameModel<FrameDataT>::get(const std::string& name) const {
-  return doGet(name);
-}
-
-template <typename FrameDataT>
-podio::CollectionBase* Frame::FrameModel<FrameDataT>::doGet(const std::string& name, bool setReferences) const {
-  {
-    // First check whether the collection is in the map already
-    //
-    // Collections only land here if they are fully unpacked, i.e.
-    // prepareAfterRead has been called or it has been put into the Frame
-    std::lock_guard lock{*m_mapMtx};
-    if (const auto it = m_collections.find(name); it != m_collections.end()) {
-      return it->second.get();
-    }
-  }
-
-  podio::CollectionBase* retColl = nullptr;
-
-  // Now try to get it from the raw data if we have the possibility
-  if (m_data) {
-    // Have the buffers in the outer scope here to hold the raw data lock as
-    // briefly as possible
-    auto buffers = std::optional<podio::CollectionReadBuffers>{std::nullopt};
-    {
-      std::lock_guard lock{*m_dataMtx};
-      buffers = unpack(m_data.get(), name);
-    }
-    if (buffers) {
-      auto coll = buffers->createCollection(buffers.value(), buffers->data == nullptr);
-      coll->prepareAfterRead();
-      coll->setID(m_idTable.collectionID(name));
-      {
-        std::lock_guard mapLock{*m_mapMtx};
-        auto [it, success] = m_collections.emplace(name, std::move(coll));
-        // TODO: Check success? Or simply assume that everything is fine at this point?
-        // TODO: Collision handling?
-        retColl = it->second.get();
-      }
-
-      if (setReferences) {
-        retColl->setReferences(this);
-      }
-    }
-  }
-
-  return retColl;
-}
-
-template <typename FrameDataT>
-bool Frame::FrameModel<FrameDataT>::get(int collectionID, CollectionBase*& collection) const {
-  const auto& name = m_idTable.name(collectionID);
-  const auto& [_, inserted] = m_retrievedIDs.insert(collectionID);
-
-  if (!inserted) {
-    auto coll = doGet(name);
-    if (coll) {
-      collection = coll;
-      return true;
-    }
-  } else {
-    auto coll = doGet(name, false);
-    if (coll) {
-      collection = coll;
-      return true;
-    }
-  }
-
-  return false;
-}
-
-template <typename FrameDataT>
-const podio::CollectionBase* Frame::FrameModel<FrameDataT>::put(std::unique_ptr<podio::CollectionBase> coll,
-                                                                const std::string& name) {
-  {
-    std::lock_guard lock{*m_mapMtx};
-    auto [it, success] = m_collections.try_emplace(name, std::move(coll));
-    if (success) {
-      // TODO: Check whether this collection is already known to the idTable
-      // -> What to do on collision?
-      // -> Check before we emplace it into the internal map to prevent possible
-      //    collisions from collections that are potentially present from rawdata?
-      it->second->setID(m_idTable.add(name));
-      return it->second.get();
-    }
-  }
-
-  return nullptr;
-}
-
-template <typename FrameDataT>
-std::vector<std::string> Frame::FrameModel<FrameDataT>::availableCollections() const {
-  // TODO: Check if there is a more efficient way to do this. Currently this is
-  // done very conservatively, but in a way that should always work, regardless
-  // of assumptions. It might be possible to simply return what is in the
-  // idTable here, because that should in principle encompass everything that is
-  // in the raw data as well as things that have been put into the frame
-
-  // Lock both the internal map and the rawdata for this
-  std::scoped_lock lock{*m_mapMtx, *m_dataMtx};
-
-  auto collections = m_data->getAvailableCollections();
-  collections.reserve(collections.size() + m_collections.size());
-
-  for (const auto& [name, _] : m_collections) {
-    collections.push_back(name);
-  }
-
-  return collections;
-}
-
-} // namespace podio
-
-#endif // PODIO_FRAME_H
-- 
GitLab