Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-24 10:29:54

0001 // Author: Enrico Guiraud, Danilo Piparo CERN  02/2018
0002 
0003 /*************************************************************************
0004  * Copyright (C) 1995-2018, Rene Brun and Fons Rademakers.               *
0005  * All rights reserved.                                                  *
0006  *                                                                       *
0007  * For the licensing terms see $ROOTSYS/LICENSE.                         *
0008  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
0009  *************************************************************************/
0010 
0011 #ifndef ROOT_RLAZYDSIMPL
0012 #define ROOT_RLAZYDSIMPL
0013 
0014 #include "ROOT/RDataSource.hxx"
0015 #include "ROOT/RResultPtr.hxx"
0016 #include "ROOT/TSeq.hxx"
0017 
0018 #include <algorithm>
0019 #include <map>
0020 #include <memory>
0021 #include <tuple>
0022 #include <string>
0023 #include <typeinfo>
0024 #include <utility> // std::index_sequence
0025 #include <vector>
0026 
0027 namespace ROOT::Internal::RDF {
0028 class R__CLING_PTRCHECK(off) RLazyDSColumnReader final : public ROOT::Detail::RDF::RColumnReaderBase {
0029    ROOT::Internal::RDF::TPointerHolder *fPtr;
0030    void *GetImpl(Long64_t) final { return fPtr->GetPointer(); }
0031 
0032 public:
0033    RLazyDSColumnReader(ROOT::Internal::RDF::TPointerHolder *ptr) : fPtr(ptr) {}
0034 };
0035 } // namespace ROOT::Internal::RDF
0036 
0037 namespace ROOT {
0038 
0039 namespace RDF {
0040 ////////////////////////////////////////////////////////////////////////////////////////////////
0041 /// \brief A RDataSource implementation which is built on top of result proxies
0042 ///
0043 /// This component allows to create a data source on a set of columns coming from
0044 /// one or multiple data frames. The processing of the parent data frames starts
0045 /// only when the event loop is triggered in the data frame initialized with a
0046 /// RLazyDS.
0047 ///
0048 /// The implementation takes care of matching compile time information with runtime
0049 /// information, e.g. expanding in a smart way the template parameters packs.
0050 template <typename... ColumnTypes>
0051 class RLazyDS final : public ROOT::RDF::RDataSource {
0052    using PointerHolderPtrs_t = std::vector<ROOT::Internal::RDF::TPointerHolder *>;
0053 
0054    std::tuple<RResultPtr<std::vector<ColumnTypes>>...> fColumns;
0055    const std::vector<std::string> fColNames;
0056    const std::map<std::string, std::string> fColTypesMap;
0057    // The role of the fPointerHoldersModels is to be initialized with the pack
0058    // of arguments in the constrcutor signature at construction time
0059    // Once the number of slots is known, the fPointerHolders are initialized
0060    // according to the models.
0061    const PointerHolderPtrs_t fPointerHoldersModels;
0062    std::vector<PointerHolderPtrs_t> fPointerHolders;
0063    std::vector<std::pair<ULong64_t, ULong64_t>> fEntryRanges{};
0064 
0065    Record_t GetColumnReadersImpl(std::string_view, const std::type_info &) final
0066    {
0067       // We use the new API
0068       return {};
0069    }
0070 
0071    size_t GetEntriesNumber() { return std::get<0>(fColumns)->size(); }
0072    template <std::size_t... S>
0073    void SetEntryHelper(unsigned int slot, ULong64_t entry, std::index_sequence<S...>)
0074    {
0075       std::initializer_list<int> expander{
0076          (*static_cast<ColumnTypes *>(fPointerHolders[S][slot]->GetPointer()) = (*std::get<S>(fColumns))[entry], 0)...};
0077       (void)expander; // avoid unused variable warnings
0078    }
0079 
0080    template <std::size_t... S>
0081    void ColLengthChecker(std::index_sequence<S...>)
0082    {
0083       if (sizeof...(S) < 2)
0084          return;
0085 
0086       const std::vector<size_t> colLengths{std::get<S>(fColumns)->size()...};
0087       const auto expectedLen = colLengths[0];
0088       std::string err;
0089       for (auto i : TSeqI(1, colLengths.size())) {
0090          if (expectedLen != colLengths[i]) {
0091             err += "Column \"" + fColNames[i] + "\" and column \"" + fColNames[0] +
0092                    "\" have different lengths: " + std::to_string(expectedLen) + " and " +
0093                    std::to_string(colLengths[i]);
0094          }
0095       }
0096       if (!err.empty()) {
0097          throw std::runtime_error(err);
0098       }
0099    }
0100 
0101 protected:
0102    std::string AsString() final { return "lazy data source"; };
0103 
0104 public:
0105    RLazyDS(std::pair<std::string, RResultPtr<std::vector<ColumnTypes>>>... colsNameVals)
0106       : fColumns(std::tuple<RResultPtr<std::vector<ColumnTypes>>...>(colsNameVals.second...)),
0107         fColNames({colsNameVals.first...}),
0108         fColTypesMap({{colsNameVals.first, ROOT::Internal::RDF::TypeID2TypeName(typeid(ColumnTypes))}...}),
0109         fPointerHoldersModels({new ROOT::Internal::RDF::TTypedPointerHolder<ColumnTypes>(new ColumnTypes())...})
0110    {
0111    }
0112 
0113    // Rule of five
0114    RLazyDS(const RLazyDS &) = delete;
0115    RLazyDS &operator=(const RLazyDS &) = delete;
0116    RLazyDS(RLazyDS &&) = delete;
0117    RLazyDS &operator=(RLazyDS &&) = delete;
0118    ~RLazyDS() final
0119    {
0120       for (auto &&ptrHolderv : fPointerHolders) {
0121          for (auto &&ptrHolder : ptrHolderv) {
0122             delete ptrHolder;
0123          }
0124       }
0125    }
0126 
0127    const std::vector<std::string> &GetColumnNames() const final { return fColNames; }
0128 
0129    std::vector<std::pair<ULong64_t, ULong64_t>> GetEntryRanges() final
0130    {
0131       auto entryRanges(std::move(fEntryRanges)); // empty fEntryRanges
0132       return entryRanges;
0133    }
0134 
0135    std::string GetTypeName(std::string_view colName) const final
0136    {
0137       const auto key = std::string(colName);
0138       return fColTypesMap.at(key);
0139    }
0140 
0141    bool HasColumn(std::string_view colName) const final
0142    {
0143       const auto key = std::string(colName);
0144       const auto endIt = fColTypesMap.end();
0145       return endIt != fColTypesMap.find(key);
0146    }
0147 
0148    bool SetEntry(unsigned int slot, ULong64_t entry) final
0149    {
0150       SetEntryHelper(slot, entry, std::index_sequence_for<ColumnTypes...>());
0151       return true;
0152    }
0153 
0154    void SetNSlots(unsigned int nSlots) final
0155    {
0156       fNSlots = nSlots;
0157       const auto nCols = fColNames.size();
0158       fPointerHolders.resize(nCols); // now we need to fill it with the slots, all of the same type
0159       auto colIndex = 0U;
0160       for (auto &&ptrHolderv : fPointerHolders) {
0161          for (auto slot : ROOT::TSeqI(fNSlots)) {
0162             auto ptrHolder = fPointerHoldersModels[colIndex]->GetDeepCopy();
0163             ptrHolderv.emplace_back(ptrHolder);
0164             (void)slot;
0165          }
0166          colIndex++;
0167       }
0168       for (auto &&ptrHolder : fPointerHoldersModels)
0169          delete ptrHolder;
0170    }
0171 
0172    void Initialize() final
0173    {
0174       ColLengthChecker(std::index_sequence_for<ColumnTypes...>());
0175       const auto nEntries = GetEntriesNumber();
0176       const auto nEntriesInRange = nEntries / fNSlots; // between integers. Should make smaller?
0177       auto reminder = 1U == fNSlots ? 0 : nEntries % fNSlots;
0178       fEntryRanges.resize(fNSlots);
0179       auto init = 0ULL;
0180       auto end = 0ULL;
0181       for (auto &&range : fEntryRanges) {
0182          end = init + nEntriesInRange;
0183          if (0 != reminder) { // Distribute the reminder among the first chunks
0184             reminder--;
0185             end += 1;
0186          }
0187          range.first = init;
0188          range.second = end;
0189          init = end;
0190       }
0191    }
0192 
0193    std::string GetLabel() final { return "LazyDS"; }
0194 
0195    std::unique_ptr<ROOT::Detail::RDF::RColumnReaderBase>
0196    GetColumnReaders(unsigned int slot, std::string_view colName, const std::type_info &tid) final
0197    {
0198       auto colTypeIt = fColTypesMap.find(std::string(colName));
0199       if (colTypeIt == fColTypesMap.end()) {
0200          throw std::runtime_error("The specified column name, \"" + std::string(colName) +
0201                                   "\" is not known to the data source.");
0202       }
0203 
0204       const auto typeName = ROOT::Internal::RDF::TypeID2TypeName(tid);
0205       if (colTypeIt->second != typeName) {
0206          throw std::runtime_error("Column " + std::string(colName) + " has type " + colTypeIt->second +
0207                                   " while the id specified is associated to type " + typeName);
0208       }
0209 
0210       if (auto colNameIt = std::find(fColNames.begin(), fColNames.end(), colName); colNameIt != fColNames.end()) {
0211          const auto index = std::distance(fColNames.begin(), colNameIt);
0212          return std::make_unique<ROOT::Internal::RDF::RLazyDSColumnReader>(fPointerHolders[index][slot]);
0213       }
0214 
0215       throw std::runtime_error("Could not find column name \"" + std::string(colName) +
0216                                "\" in available column names.");
0217    }
0218 };
0219 
0220 } // ns RDF
0221 
0222 } // ns ROOT
0223 
0224 #endif