Project
Loading...
Searching...
No Matches
RootTableBuilderHelpers.h
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
12#ifndef o2_framework_RootTableBuilderHelpers_H_INCLUDED
13#define o2_framework_RootTableBuilderHelpers_H_INCLUDED
14
16#include "Framework/Logger.h"
17
18#include <Rtypes.h>
19#include <arrow/stl.h>
20#include <arrow/type_traits.h>
21#include <arrow/table.h>
22#include <arrow/builder.h>
23
24#include <TTreeReader.h>
25#include <TTreeReaderValue.h>
26#include <TTreeReaderArray.h>
27#include <TBuffer.h>
28#include <TBufferFile.h>
29
30#include <vector>
31#include <string>
32#include <memory>
33#include <tuple>
34
35namespace o2::framework
36{
37
38template <typename T>
41
44template <typename T>
45struct TreeReaderValueTraits<TTreeReaderValue<T>> {
46 using Type = typename TTreeReaderValue<T>::NonConstT_t;
48 using BuilderType = typename arrow::TypeTraits<ArrowType>::BuilderType;
49};
50
51template <typename VALUE>
52struct TreeReaderValueTraits<TTreeReaderArray<VALUE>> {
53 using Iterator = typename TTreeReaderArray<VALUE>::iterator;
54 using Type = std::pair<Iterator, Iterator>;
55 using ArrowType = arrow::ListType;
56};
57
58static constexpr int PREBUFFER_SIZE = 32 * 1024;
59
60// When reading from a ROOT file special care must happen
61// because uint64_t is platform specific while ULong64_t is
62// always long long unsigned int (same for the signed version).
63// By using this traits we make sure that any 64 bit quantity
64// read from a root file uses the ROOT datatype, not the platform one.
65template <typename T>
66struct Remap64Bit {
67 using type = T;
68};
69
70template <>
71struct Remap64Bit<int64_t> {
72 using type = Long64_t;
73};
74
75template <>
76struct Remap64Bit<uint64_t> {
77 using type = ULong64_t;
78};
79
80template <int N>
81struct Remap64Bit<int64_t[N]> {
82 using type = Long64_t[N];
83};
84
85template <int N>
86struct Remap64Bit<uint64_t[N]> {
87 using type = ULong64_t[N];
88};
89
90template <typename T>
92
93template <typename T>
95 using Reader = TTreeReaderValue<T>;
96 using Type = T;
97
98 ReaderHolder(TBranch* branch, std::unique_ptr<Reader> reader_)
99 : reader{std::move(reader_)}
100 {
101 }
102
104 : reader{std::move(other.reader)},
105 pos{other.pos}
106 {
107 }
108
110
111 std::unique_ptr<Reader> reader;
112 int pos = 0;
113 Remap64Bit_t<T> buffer[PREBUFFER_SIZE];
114 int itemSize = sizeof(T);
115};
116
117template <typename T, int N>
118struct ReaderHolder<T[N]> {
119 using Reader = TTreeReaderArray<T>;
120 using Type = T (&)[N];
121
122 ReaderHolder(TBranch* branch, std::unique_ptr<Reader> reader_)
123 : reader{std::move(reader_)}
124 {
125 }
126
128 : reader{std::move(other.reader)},
129 pos{other.pos}
130 {
131 }
132
134
135 std::unique_ptr<Reader> reader;
136 int pos = 0;
137 Remap64Bit_t<T> buffer[PREBUFFER_SIZE * N];
138 int itemSize = sizeof(T) * N;
139};
140
142 template <typename T>
143 static auto deref(ReaderHolder<T>& holder, size_t maxSize)
144 {
145 holder.buffer[holder.pos % PREBUFFER_SIZE] = **holder.reader;
146 holder.pos++;
147 if (holder.pos == maxSize) {
148 return BulkInfo<Remap64Bit_t<T> const*>{holder.buffer, maxSize % PREBUFFER_SIZE};
149 }
150 // We flush only after PREBUFFER_SIZE items have been inserted
151 if ((holder.pos % PREBUFFER_SIZE) != 0) {
152 return BulkInfo<Remap64Bit_t<T> const*>{nullptr, 0};
153 }
154 return BulkInfo<Remap64Bit_t<T> const*>{holder.buffer, PREBUFFER_SIZE};
155 }
156
157 template <typename T, int N>
158 static auto deref(ReaderHolder<T[N]>& holder, size_t maxSize)
159 {
160 memcpy(&holder.buffer[(holder.pos % PREBUFFER_SIZE) * N], &((*holder.reader)[0]), N * sizeof(T));
161 holder.pos++;
162 if (holder.pos == maxSize) {
163 return BulkInfo<Remap64Bit_t<T> const*>{holder.buffer, maxSize % PREBUFFER_SIZE};
164 }
165 // We flush only after PREBUFFER_SIZE items have been inserted
166 if ((holder.pos % PREBUFFER_SIZE) != 0) {
167 return BulkInfo<Remap64Bit_t<T> const*>{nullptr, 0};
168 }
169 return BulkInfo<Remap64Bit_t<T> const*>{reinterpret_cast<T const*>(holder.buffer), PREBUFFER_SIZE};
170 }
171};
172
173template <typename T>
175 static auto make(TTreeReader& reader, char const* branchName)
176 {
177 using Reader = TTreeReaderValue<T>;
178 return ReaderHolder<T>{reader.GetTree()->GetBranch(branchName), std::move(std::make_unique<Reader>(reader, branchName))};
179 }
180};
181
182template <typename T, int N>
183struct HolderMaker<T[N]> {
184 static auto make(TTreeReader& reader, char const* branchName)
185 {
186 using Reader = TTreeReaderArray<T>;
187 return ReaderHolder<T[N]>{reader.GetTree()->GetBranch(branchName), std::move(std::make_unique<Reader>(reader, branchName))};
188 }
189};
190
191template <typename C>
193 static auto createReader(TTreeReader& reader)
194 {
195 return HolderMaker<Remap64Bit_t<typename C::type>>::make(reader, C::base::columnLabel());
196 }
197};
198
201 template <typename... T>
202 static void convertTTree(TableBuilder& builder,
203 TTreeReader& reader,
204 ReaderHolder<T>... holders)
205 {
206 std::array<char const*, sizeof...(T)> branchNames = {holders.reader->GetBranchName()...};
207 TTree* tree = reader.GetTree();
208 size_t maxExtries = reader.GetEntries(true);
209 tree->SetCacheSize(maxExtries * (holders.itemSize + ...));
210 (tree->AddBranchToCache(tree->GetBranch(holders.reader->GetBranchName()), true), ...);
211 tree->StopCacheLearningPhase();
212
213 auto filler = builder.bulkPersistChunked<Remap64Bit_t<typename std::decay_t<decltype(holders)>::Type>...>(branchNames, maxExtries);
214 while (reader.Next()) {
215 filler(0, BulkExtractor::deref(holders, maxExtries)...);
216 }
217 }
218
219 template <typename... C>
220 static void convertASoAColumns(TableBuilder& builder, TTreeReader& reader, pack<C...>)
221 {
222 return convertTTree(builder, reader, ColumnReaderTrait<C>::createReader(reader)...);
223 }
224
225 template <typename T>
226 static void convertASoA(TableBuilder& builder, TTreeReader& reader)
227 {
228 return convertASoAColumns(builder, reader, typename T::persistent_columns_t{});
229 }
230};
231
232} // namespace o2
233#endif // FRAMEWORK_ROOTTABLEBUILDERHELPERS_H
auto bulkPersistChunked(std::array< char const *, NCOLUMNS > const &columnNames, size_t nRows)
GLuint buffer
Definition glcorearb.h:655
Defining PrimaryVertex explicitly as messageable.
Definition TFIDInfo.h:20
typename Remap64Bit< T >::type Remap64Bit_t
Defining DataPointCompositeObject explicitly as copiable.
static auto deref(ReaderHolder< T > &holder, size_t maxSize)
static auto deref(ReaderHolder< T[N]> &holder, size_t maxSize)
static auto createReader(TTreeReader &reader)
static auto make(TTreeReader &reader, char const *branchName)
static auto make(TTreeReader &reader, char const *branchName)
ReaderHolder(TBranch *branch, std::unique_ptr< Reader > reader_)
ReaderHolder & operator=(ReaderHolder &&other)=delete
Remap64Bit_t< T > buffer[PREBUFFER_SIZE]
ReaderHolder(TBranch *branch, std::unique_ptr< Reader > reader_)
ReaderHolder & operator=(ReaderHolder &&other)=delete
std::unique_ptr< Reader > reader
static void convertASoAColumns(TableBuilder &builder, TTreeReader &reader, pack< C... >)
static void convertTTree(TableBuilder &builder, TTreeReader &reader, ReaderHolder< T >... holders)
Use bulk insertion when TTreeReaderValue everywhere.
static void convertASoA(TableBuilder &builder, TTreeReader &reader)
typename arrow::TypeTraits< ArrowType >::BuilderType BuilderType
typename o2::framework::detail::ConversionTraits< Type >::ArrowType ArrowType
FIXME: adapt type conversion to new arrow.
VectorOfTObjectPtrs other
std::unique_ptr< TTree > tree((TTree *) flIn.Get(std::string(o2::base::NameConf::CTFTREENAME).c_str()))