File indexing completed on 2025-12-24 10:29:54
0001
0002
0003
0004
0005
0006
0007
0008
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 }
0036
0037 namespace ROOT {
0038
0039 namespace RDF {
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
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
0058
0059
0060
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
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;
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
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));
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);
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;
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) {
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 }
0221
0222 }
0223
0224 #endif