File indexing completed on 2025-09-15 09:11:34
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 {
0028
0029 namespace RDF {
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040 template <typename... ColumnTypes>
0041 class RLazyDS final : public ROOT::RDF::RDataSource {
0042 using PointerHolderPtrs_t = std::vector<ROOT::Internal::TDS::TPointerHolder *>;
0043
0044 std::tuple<RResultPtr<std::vector<ColumnTypes>>...> fColumns;
0045 const std::vector<std::string> fColNames;
0046 const std::map<std::string, std::string> fColTypesMap;
0047
0048
0049
0050
0051 const PointerHolderPtrs_t fPointerHoldersModels;
0052 std::vector<PointerHolderPtrs_t> fPointerHolders;
0053 std::vector<std::pair<ULong64_t, ULong64_t>> fEntryRanges{};
0054
0055 Record_t GetColumnReadersImpl(std::string_view colName, const std::type_info &id) final
0056 {
0057 auto colNameStr = std::string(colName);
0058
0059 const auto idName = ROOT::Internal::RDF::TypeID2TypeName(id);
0060 auto it = fColTypesMap.find(colNameStr);
0061 if (fColTypesMap.end() == it) {
0062 std::string err = "The specified column name, \"" + colNameStr + "\" is not known to the data source.";
0063 throw std::runtime_error(err);
0064 }
0065
0066 const auto colIdName = it->second;
0067 if (colIdName != idName) {
0068 std::string err = "Column " + colNameStr + " has type " + colIdName +
0069 " while the id specified is associated to type " + idName;
0070 throw std::runtime_error(err);
0071 }
0072
0073 const auto colBegin = fColNames.begin();
0074 const auto colEnd = fColNames.end();
0075 const auto namesIt = std::find(colBegin, colEnd, colName);
0076 const auto index = std::distance(colBegin, namesIt);
0077
0078 Record_t ret(fNSlots);
0079 for (auto slot : ROOT::TSeqU(fNSlots)) {
0080 ret[slot] = fPointerHolders[index][slot]->GetPointerAddr();
0081 }
0082 return ret;
0083 }
0084
0085 size_t GetEntriesNumber() { return std::get<0>(fColumns)->size(); }
0086 template <std::size_t... S>
0087 void SetEntryHelper(unsigned int slot, ULong64_t entry, std::index_sequence<S...>)
0088 {
0089 std::initializer_list<int> expander{
0090 (*static_cast<ColumnTypes *>(fPointerHolders[S][slot]->GetPointer()) = (*std::get<S>(fColumns))[entry], 0)...};
0091 (void)expander;
0092 }
0093
0094 template <std::size_t... S>
0095 void ColLengthChecker(std::index_sequence<S...>)
0096 {
0097 if (sizeof...(S) < 2)
0098 return;
0099
0100 const std::vector<size_t> colLengths{std::get<S>(fColumns)->size()...};
0101 const auto expectedLen = colLengths[0];
0102 std::string err;
0103 for (auto i : TSeqI(1, colLengths.size())) {
0104 if (expectedLen != colLengths[i]) {
0105 err += "Column \"" + fColNames[i] + "\" and column \"" + fColNames[0] +
0106 "\" have different lengths: " + std::to_string(expectedLen) + " and " +
0107 std::to_string(colLengths[i]);
0108 }
0109 }
0110 if (!err.empty()) {
0111 throw std::runtime_error(err);
0112 }
0113 }
0114
0115 protected:
0116 std::string AsString() final { return "lazy data source"; };
0117
0118 public:
0119 RLazyDS(std::pair<std::string, RResultPtr<std::vector<ColumnTypes>>>... colsNameVals)
0120 : fColumns(std::tuple<RResultPtr<std::vector<ColumnTypes>>...>(colsNameVals.second...)),
0121 fColNames({colsNameVals.first...}),
0122 fColTypesMap({{colsNameVals.first, ROOT::Internal::RDF::TypeID2TypeName(typeid(ColumnTypes))}...}),
0123 fPointerHoldersModels({new ROOT::Internal::TDS::TTypedPointerHolder<ColumnTypes>(new ColumnTypes())...})
0124 {
0125 }
0126
0127
0128 RLazyDS(const RLazyDS &) = delete;
0129 RLazyDS &operator=(const RLazyDS &) = delete;
0130 RLazyDS(RLazyDS &&) = delete;
0131 RLazyDS &operator=(RLazyDS &&) = delete;
0132 ~RLazyDS() final
0133 {
0134 for (auto &&ptrHolderv : fPointerHolders) {
0135 for (auto &&ptrHolder : ptrHolderv) {
0136 delete ptrHolder;
0137 }
0138 }
0139 }
0140
0141 const std::vector<std::string> &GetColumnNames() const final { return fColNames; }
0142
0143 std::vector<std::pair<ULong64_t, ULong64_t>> GetEntryRanges() final
0144 {
0145 auto entryRanges(std::move(fEntryRanges));
0146 return entryRanges;
0147 }
0148
0149 std::string GetTypeName(std::string_view colName) const final
0150 {
0151 const auto key = std::string(colName);
0152 return fColTypesMap.at(key);
0153 }
0154
0155 bool HasColumn(std::string_view colName) const final
0156 {
0157 const auto key = std::string(colName);
0158 const auto endIt = fColTypesMap.end();
0159 return endIt != fColTypesMap.find(key);
0160 }
0161
0162 bool SetEntry(unsigned int slot, ULong64_t entry) final
0163 {
0164 SetEntryHelper(slot, entry, std::index_sequence_for<ColumnTypes...>());
0165 return true;
0166 }
0167
0168 void SetNSlots(unsigned int nSlots) final
0169 {
0170 fNSlots = nSlots;
0171 const auto nCols = fColNames.size();
0172 fPointerHolders.resize(nCols);
0173 auto colIndex = 0U;
0174 for (auto &&ptrHolderv : fPointerHolders) {
0175 for (auto slot : ROOT::TSeqI(fNSlots)) {
0176 auto ptrHolder = fPointerHoldersModels[colIndex]->GetDeepCopy();
0177 ptrHolderv.emplace_back(ptrHolder);
0178 (void)slot;
0179 }
0180 colIndex++;
0181 }
0182 for (auto &&ptrHolder : fPointerHoldersModels)
0183 delete ptrHolder;
0184 }
0185
0186 void Initialize() final
0187 {
0188 ColLengthChecker(std::index_sequence_for<ColumnTypes...>());
0189 const auto nEntries = GetEntriesNumber();
0190 const auto nEntriesInRange = nEntries / fNSlots;
0191 auto reminder = 1U == fNSlots ? 0 : nEntries % fNSlots;
0192 fEntryRanges.resize(fNSlots);
0193 auto init = 0ULL;
0194 auto end = 0ULL;
0195 for (auto &&range : fEntryRanges) {
0196 end = init + nEntriesInRange;
0197 if (0 != reminder) {
0198 reminder--;
0199 end += 1;
0200 }
0201 range.first = init;
0202 range.second = end;
0203 init = end;
0204 }
0205 }
0206
0207 std::string GetLabel() final { return "LazyDS"; }
0208 };
0209
0210 }
0211
0212 }
0213
0214 #endif