11#ifndef FRAMEWORK_ROOTTREEREADER_H
12#define FRAMEWORK_ROOTTREEREADER_H
140template <
typename KeyType>
174 static_assert(std::is_same<KeyType, const char*>::value ==
false,
"the key type must not be const char*");
220 template <
typename DataT,
typename BASE>
227 static const size_t STAGE = BASE::STAGE + 1;
255 if constexpr (
STAGE > 1) {
256 PrevT::setupInstance(
tree, publishhook);
258 mPublishHook = publishhook;
261 mBranch =
tree.GetBranch(mName.c_str());
263 std::string sizebranchName = std::string(mName) +
"Size";
264 auto sizebranch =
tree.GetBranch(sizebranchName.c_str());
265 auto* classinfo = TClass::GetClass(mBranch->GetClassName());
266 if constexpr (not std::is_void<value_type>::value) {
268 auto* storedclass = TClass::GetClass(
typeid(
value_type));
269 if (classinfo != storedclass) {
270 throw std::runtime_error(std::string(
"Configured type ") +
271 (storedclass !=
nullptr ? storedclass->GetName() :
typeid(
value_type).
name()) +
272 " does not match the stored data type " +
273 (classinfo !=
nullptr ? classinfo->GetName() :
"") +
274 " in branch " + mName);
278 if (classinfo ==
nullptr) {
279 throw std::runtime_error(std::string(
"can not find class description for branch ") + mName);
281 LOG(info) <<
"branch set up: " << mName;
284 throw std::runtime_error(
"mismatching class type, expecting std::vector<char> for binary branch");
286 mSizeBranch = sizebranch;
287 LOG(info) <<
"binary branch set up: " << mName;
289 mClassInfo = classinfo;
291 throw std::runtime_error(std::string(
"can not find branch ") + mName);
300 if constexpr (
STAGE > 1) {
301 PrevT::process(context,
entry, stackcreator);
304 auto snapshot = [&context, &stackcreator](
const KeyType&
key,
const auto&
object) {
312 char*
data =
nullptr;
314 mBranch->SetAddress(&
data);
315 mBranch->GetEntry(
entry);
317 data =
reinterpret_cast<char*
>(mClassInfo->New());
318 if (
data ==
nullptr) {
319 LOG(error) <<
"branch " << mName <<
": cannot create an empty " << mClassInfo->GetName() <<
", nothing published";
325 if (mPublishHook !=
nullptr && (*mPublishHook).
hook(mName, context,
Output{mKey.origin, mKey.description, mKey.subSpec, std::move(stackcreator())},
data)) {
330 if (mSizeBranch !=
nullptr) {
333 mSizeBranch->SetAddress(&datasize);
334 mSizeBranch->GetEntry(
entry);
337 if (
buffer->size() == datasize) {
338 LOG(
debug) <<
"branch " << mName <<
": publishing binary chunk of " << datasize <<
" bytes(s)";
339 snapshot(mKey, std::move(*
buffer));
341 LOG(error) <<
"branch " << mName <<
": inconsitent size of binary chunk "
342 <<
buffer->size() <<
" vs " << datasize;
344 snapshot(mKey,
empty);
347 if constexpr (std::is_void<value_type>::value ==
true) {
358 auto* delfunc = mClassInfo->GetDelete();
363 mBranch->DropBaskets(
"all");
370 TBranch* mBranch =
nullptr;
371 TBranch* mSizeBranch =
nullptr;
372 TClass* mClassInfo =
nullptr;
380 template <
typename T>
383 template <
typename U>
388 template <
typename U>
393 template <
typename U>
410 template <
typename... Args>
415 mInput.SetCacheSize(0);
416 parseConstructorArgs<0>(std::forward<Args>(args)...);
417 mBranchConfiguration->setup(mInput, mPublishHook);
423 mInput.AddFile(fileName);
424 mNEntries = mInput.GetEntries();
431 if (mNEntries == 0) {
434 if (mNofPublished >= 0) {
440 if ((mReadEntry + 1) >= mNEntries) {
443 if (mReadEntry < mNEntries) {
444 mReadEntry = mNEntries;
451 if (mMaxEntries > 0 && (mNofPublished + 1) >= mMaxEntries) {
452 if (mReadEntry < mNEntries) {
453 mReadEntry = mNEntries;
482 template <
typename ContextType,
typename... HeaderTypes>
484 HeaderTypes&&... headers)
const
486 if (mNEntries == 0) {
487 if (mNofPublished != 0) {
490 }
else if (mReadEntry >= mNEntries || (mMaxEntries > 0 && mNofPublished >= mMaxEntries)) {
494 auto stackcreator = [&headers...]() {
498 mBranchConfiguration->exec(context, mReadEntry, stackcreator);
505 return mNofPublished + 1;
510 template <
typename T,
typename... Args>
511 const char* getCharArg(T arg, Args&&...)
513 static_assert(std::is_same<T, const char*>::value,
"missing branch name after publishing key, use const char* argument right after the key");
518 template <
size_t skip,
typename U,
typename... Args>
519 void parseConstructorArgs(U
key, Args&&... args)
522 mBranchConfiguration = createBranchConfiguration<0, BranchConfigurationInterface>({}, std::forward<U>(
key), std::forward<Args>(args)...);
528 template <
size_t skip,
typename BASE,
typename U,
typename... Args>
529 std::unique_ptr<BranchConfigurationInterface> createBranchConfiguration(
ConstructorArgs&& cargs, U def, Args&&... args)
531 if constexpr (skip > 0) {
532 return createBranchConfiguration<skip - 1,
BASE>(std::move(cargs), std::forward<Args>(args)...);
533 }
else if constexpr (std::is_same<U, const char*>::value) {
535 }
else if constexpr (std::is_same<U, int>::value) {
537 }
else if constexpr (std::is_same<U, PublishingMode>::value) {
538 mPublishingMode = def;
539 }
else if constexpr (std::is_same<U, SpecialPublishHook*>::value) {
541 }
else if constexpr (is_specialization_v<U, BranchDefinition>) {
542 cargs.emplace_back(
key_type(def.key), def.name);
543 using type = BranchConfigurationElement<typename U::type, BASE>;
544 return std::move(createBranchConfiguration<0, type>(std::move(cargs), std::forward<Args>(args)...));
545 }
else if constexpr (
sizeof...(Args) > 0) {
546 const char* arg = getCharArg(std::forward<Args>(args)...);
547 if (arg !=
nullptr && *arg != 0) {
548 cargs.emplace_back(
key_type(def), arg);
549 using type = BranchConfigurationElement<void, BASE>;
550 return std::move(createBranchConfiguration<1, type>(std::move(cargs), std::forward<Args>(args)...));
552 throw std::runtime_error(
"expecting valid branch name string after key");
554 static_assert(always_static_assert<U>::value,
"argument mismatch, define branches either as argument pairs of key and branchname or using the BranchDefinition helper struct");
556 return createBranchConfiguration<0, BASE>(std::move(cargs), std::forward<Args>(args)...);
561 template <
size_t skip,
typename T>
562 std::unique_ptr<BranchConfigurationInterface> createBranchConfiguration(
ConstructorArgs&& cargs)
564 static_assert(skip == 0);
565 return std::move(std::make_unique<T>(cargs));
571 std::unique_ptr<BranchConfigurationInterface> mBranchConfiguration;
577 int mNofPublished = -1;
579 int mMaxEntries = -1;
583 SpecialPublishHook* mPublishHook =
nullptr;
Class for time synchronization of RawReader instances.
void snapshot(const Output &spec, T const &object)
void process(ProcessingContext &context, int entry, std::function< o2::header::Stack()> &stackcreator)
Run the reader, first recursively for all lower stages, and then the current stage.
void exec(ProcessingContext &ctx, int entry, std::function< o2::header::Stack()> stackcreator) override
BranchConfigurationElement()=default
static const size_t STAGE
BranchConfigurationElement(ConstructorArgs const &args)
void setupInstance(TTree &tree, SpecialPublishHook *publishhook=nullptr)
~BranchConfigurationElement() override=default
void setup(TTree &tree, SpecialPublishHook *publishhook=nullptr) override
virtual ~BranchConfigurationInterface()=default
BranchConfigurationInterface(ConstructorArgs const &)
virtual void setup(TTree &, SpecialPublishHook *h=nullptr)
Setup the branch configuration, namely get the branch and class information from the tree.
static const size_t STAGE
virtual void exec(ProcessingContext &ctx, int entry, std::function< o2::header::Stack()> stackcreator)
BranchConfigurationInterface()=default
bool operator()(ContextType &context, HeaderTypes &&... headers) const
self_type & operator++(int)=delete
postfix increment forbidden
void addFile(const char *fileName)
add a file as source for the tree
self_type & operator++()
prefix increment, move to the next entry
o2::framework::ROOTSerialized< char, TClass > ROOTSerializedByClass
PublishingMode
Publishing mode determines what to do when the number of entries in the tree is reached.
@ Single
no more data after end of tree
@ Loop
start over at entry 0
GenericRootTreeReader(const char *treename, Args &&... args)
GenericRootTreeReader()
default constructor
int getCount() const
return the number of published entries
std::vector< ConstructorArg > ConstructorArgs
std::vector< char > BinaryDataStoreType
DataAllocator & outputs()
The data allocator is used to allocate memory for the output data.
GLuint const GLchar * name
GLint GLint GLsizei GLint GLenum GLenum type
typedef void(APIENTRYP PFNGLCULLFACEPROC)(GLenum mode)
Defining ITS Vertex explicitly as messageable.
Lifetime
Possible Lifetime of objects being exchanged by the DPL.
BranchDefinition(U _key, std::string &&_name)
BranchDefinition(U _key, const char *_name)
BranchDefinition(U _key, std::string const &_name)
helper structure to hold the constructor arguments for BranchConfigurationElement stages
ConstructorArg(key_type _key, const char *_name)
ConstructorArg(key_type _key, std::string const &_name)
std::function< bool(std::string_view name, ProcessingContext &context, Output const &, char *data)> hook
header::DataOrigin origin
header::DataHeader::SubSpecificationType subSpec
header::DataOrigin origin
DefaultKey(const Output &desc)
header::DataDescription description
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::unique_ptr< TTree > tree((TTree *) flIn.Get(std::string(o2::base::NameConf::CTFTREENAME).c_str()))