Public Member Functions | Static Public Member Functions | Private Attributes | List of all members
art::RootOutputTree Class Reference

#include <RootOutputTree.h>

Public Member Functions

template<typename Aux >
 RootOutputTree (cet::exempt_ptr< TFile > filePtr, BranchType const branchType, Aux const *&pAux, ProductProvenances *&pProductProvenanceVector, int const bufSize, int const splitLevel, int64_t const treeMaxVirtualSize, int64_t const saveMemoryObjectThreshold)
 
 RootOutputTree (RootOutputTree const &)=delete
 
RootOutputTreeoperator= (RootOutputTree const &)=delete
 
bool isValid () const
 
void resetOutputBranchAddress (BranchDescription const &)
 
void addOutputBranch (BranchDescription const &, void const *&pProd)
 
bool checkSplitLevelAndBasketSize (cet::exempt_ptr< TTree const >) const
 
bool fastCloneTree (cet::exempt_ptr< TTree const >)
 
void fillTree ()
 
void writeTree () const
 
TTree * tree () const
 
TTree * metaTree () const
 
void setEntries ()
 
void beginInputFile (bool fastCloning)
 
bool uncloned (std::string const &branchName) const
 

Static Public Member Functions

static TTree * makeTTree (TFile *, std::string const &name, int splitLevel)
 
static void writeTTree (TTree *) noexcept(false)
 

Private Attributes

cet::exempt_ptr< TFile > filePtr_
 
std::atomic< TTree * > tree_
 
std::atomic< TTree * > metaTree_
 
std::vector< TBranch * > producedBranches_ {}
 
std::vector< TBranch * > metaBranches_ {}
 
std::vector< TBranch * > readBranches_ {}
 
std::vector< TBranch * > unclonedReadBranches_ {}
 
std::set< std::stringunclonedReadBranchNames_ {}
 
std::atomic< bool > fastCloningEnabled_
 
std::atomic< int > basketSize_
 
std::atomic< int > splitLevel_
 
std::atomic< int64_tsaveMemoryObjectThreshold_
 
std::atomic< int > nEntries_
 

Detailed Description

Definition at line 24 of file RootOutputTree.h.

Constructor & Destructor Documentation

template<typename Aux >
art::RootOutputTree::RootOutputTree ( cet::exempt_ptr< TFile >  filePtr,
BranchType const  branchType,
Aux const *&  pAux,
ProductProvenances *&  pProductProvenanceVector,
int const  bufSize,
int const  splitLevel,
int64_t const  treeMaxVirtualSize,
int64_t const  saveMemoryObjectThreshold 
)
inline

Definition at line 34 of file RootOutputTree.h.

42  : filePtr_{filePtr}
43  {
44  tree_ = makeTTree(
45  filePtr.get(), BranchTypeToProductTreeName(branchType), splitLevel);
46  metaTree_ =
47  makeTTree(filePtr.get(), BranchTypeToMetaDataTreeName(branchType), 0);
48  fastCloningEnabled_ = false;
49  basketSize_ = bufSize;
50  splitLevel_ = splitLevel;
51  saveMemoryObjectThreshold_ = saveMemoryObjectThreshold;
52  nEntries_ = 0;
53  if (treeMaxVirtualSize >= 0) {
54  tree_.load()->SetMaxVirtualSize(treeMaxVirtualSize);
55  }
56  auto auxBranch = tree_.load()->Branch(
57  BranchTypeToAuxiliaryBranchName(branchType).c_str(), &pAux, bufSize, 0);
58  delete pAux;
59  pAux = nullptr;
60  readBranches_.push_back(auxBranch);
61  auto productProvenanceBranch = metaTree_.load()->Branch(
62  productProvenanceBranchName(branchType).c_str(),
63  &pProductProvenanceVector,
64  bufSize,
65  0);
66  metaBranches_.push_back(productProvenanceBranch);
67  }
std::string const & BranchTypeToProductTreeName(BranchType const bt)
Definition: BranchType.cc:71
std::string const & productProvenanceBranchName(BranchType const bt)
Definition: BranchType.cc:91
std::vector< TBranch * > readBranches_
std::string const & BranchTypeToMetaDataTreeName(BranchType const bt)
Definition: BranchType.cc:77
cet::exempt_ptr< TFile > filePtr_
pointer get() const noexcept
Definition: exempt_ptr.h:147
std::atomic< bool > fastCloningEnabled_
std::string const & BranchTypeToAuxiliaryBranchName(BranchType const bt)
Definition: BranchType.cc:83
std::atomic< int > nEntries_
std::atomic< int > splitLevel_
std::atomic< TTree * > tree_
static TTree * makeTTree(TFile *, std::string const &name, int splitLevel)
std::atomic< int > basketSize_
std::atomic< TTree * > metaTree_
std::vector< TBranch * > metaBranches_
std::atomic< int64_t > saveMemoryObjectThreshold_
art::RootOutputTree::RootOutputTree ( RootOutputTree const &  )
delete

Member Function Documentation

void art::RootOutputTree::addOutputBranch ( BranchDescription const &  bd,
void const *&  pProd 
)

Definition at line 192 of file RootOutputTree.cc.

194  {
195  TClassRef cls = TClass::GetClass(bd.wrappedName().c_str());
196  if (TBranch* br = tree_.load()->GetBranch(bd.branchName().c_str())) {
197  // Already have this branch, possibly update the branch address.
198  if (pProd == nullptr) {
199  // The OutputItem is freshly constructed and has
200  // not been passed to SetAddress yet.
201  // If selectProducts has just been called, we
202  // get here just after the branch object has been
203  // deleted with a ResetBranchAddress() to prepare
204  // for the OutputItem being replaced, and the
205  // OutputItem has just been recreated.
206  EDProduct* prod = reinterpret_cast<EDProduct*>(cls->New());
207  pProd = prod;
208  br->SetAddress(&pProd);
209  pProd = nullptr;
210  delete prod;
211  }
212  return;
213  }
214  auto bsize = bd.basketSize();
216  bsize = basketSize_.load();
217  }
218  auto splitlvl = bd.splitLevel();
219  if (splitlvl == BranchDescription::invalidSplitLevel) {
220  splitlvl = splitLevel_.load();
221  }
222  if (pProd != nullptr) {
224  << "OutputItem product pointer is not nullptr!\n";
225  }
226  EDProduct* prod = reinterpret_cast<EDProduct*>(cls->New());
227  pProd = prod;
228  TBranch* branch = tree_.load()->Branch(bd.branchName().c_str(),
229  bd.wrappedName().c_str(),
230  &pProd,
231  bsize,
232  splitlvl);
233  // Note that root will have just allocated a dummy product
234  // as the I/O buffer for the branch we have created. We will
235  // replace this I/O buffer in RootOutputFile::fillBranches()
236  // with the actual product or our own dummy using
237  // TBranchElement::SetAddress(), which will cause root to
238  // automatically delete the dummy product it allocated here.
239  pProd = nullptr;
240  delete prod;
241  if (bd.compression() != BranchDescription::invalidCompression) {
242  branch->SetCompressionSettings(bd.compression());
243  }
244  if (nEntries_.load() > 0) {
245  // Backfill the branch with dummy entries to match the number
246  // of entries already written to the data tree.
247  std::unique_ptr<EDProduct> dummy(static_cast<EDProduct*>(cls->New()));
248  pProd = dummy.get();
249  int bytesWritten{};
250  for (auto i = nEntries_.load(); i > 0; --i) {
251  auto cnt = branch->Fill();
252  if (cnt <= 0) {
253  // FIXME: Throw a fatal error here!
254  }
255  bytesWritten += cnt;
256  if ((saveMemoryObjectThreshold_.load() > -1) &&
257  (bytesWritten > saveMemoryObjectThreshold_.load())) {
258  branch->FlushBaskets();
259  branch->DropBaskets("all");
260  }
261  }
262  }
263  if (bd.produced()) {
264  producedBranches_.push_back(branch);
265  } else {
266  readBranches_.push_back(branch);
267  }
268  }
std::vector< TBranch * > readBranches_
static int constexpr invalidCompression
std::vector< TBranch * > producedBranches_
std::atomic< int > nEntries_
static int constexpr invalidSplitLevel
std::atomic< int > splitLevel_
std::atomic< TTree * > tree_
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
cet::LibraryManager dummy("noplugin")
std::atomic< int > basketSize_
static int constexpr invalidBasketSize
std::atomic< int64_t > saveMemoryObjectThreshold_
void art::RootOutputTree::beginInputFile ( bool  fastCloning)
inline

Definition at line 105 of file RootOutputTree.h.

106  {
107  fastCloningEnabled_ = fastCloning;
108  }
std::atomic< bool > fastCloningEnabled_
bool art::RootOutputTree::checkSplitLevelAndBasketSize ( cet::exempt_ptr< TTree const >  inputTree) const

Definition at line 49 of file RootOutputTree.cc.

51  {
52  // Do the split level and basket size match in the input and output?
53  if (inputTree == nullptr) {
54  return false;
55  }
56  for (auto outputBranch : readBranches_) {
57  if (outputBranch == nullptr) {
58  continue;
59  }
60  TBranch* inputBranch =
61  const_cast<TTree*>(inputTree.get())->GetBranch(outputBranch->GetName());
62  if (inputBranch == nullptr) {
63  continue;
64  }
65  if ((inputBranch->GetSplitLevel() != outputBranch->GetSplitLevel()) ||
66  (inputBranch->GetBasketSize() != outputBranch->GetBasketSize())) {
67  mf::LogInfo("FastCloning")
68  << "Fast Cloning disabled because split level or basket size "
69  "do not match";
70  return false;
71  }
72  }
73  return true;
74  }
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
std::vector< TBranch * > readBranches_
pointer get() const noexcept
Definition: exempt_ptr.h:147
bool art::RootOutputTree::fastCloneTree ( cet::exempt_ptr< TTree const >  intree)

Definition at line 98 of file RootOutputTree.cc.

99  {
100  unclonedReadBranches_.clear();
101  unclonedReadBranchNames_.clear();
102  if (!fastCloningEnabled_.load()) {
103  return false;
104  }
105 
106  bool cloned{false};
107  if (intree->GetEntries() != 0) {
108  TTreeCloner cloner(const_cast<TTree*>(intree.get()),
109  tree_.load(),
110  "",
111  TTreeCloner::kIgnoreMissingTopLevel |
112  TTreeCloner::kNoWarnings |
113  TTreeCloner::kNoFileCache);
114  if (cloner.IsValid()) {
115  tree_.load()->SetEntries(tree_.load()->GetEntries() +
116  intree->GetEntries());
117  cloner.Exec();
118  cloned = true;
119  } else {
120  fastCloningEnabled_ = false;
121  mf::LogInfo("fastCloneTree")
122  << "INFO: Unable to fast clone tree " << intree->GetName() << '\n'
123  << "INFO: ROOT reason is:\n"
124  << "INFO: " << cloner.GetWarning() << '\n'
125  << "INFO: Processing will continue, tree will be slow cloned.";
126  }
127  }
128  for (auto const& val : readBranches_) {
129  if (val->GetEntries() != tree_.load()->GetEntries()) {
130  unclonedReadBranches_.push_back(val);
131  unclonedReadBranchNames_.insert(string(val->GetName()));
132  }
133  }
134  return cloned;
135  }
std::set< std::string > unclonedReadBranchNames_
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
std::vector< TBranch * > readBranches_
pointer get() const noexcept
Definition: exempt_ptr.h:147
std::atomic< bool > fastCloningEnabled_
std::vector< TBranch * > unclonedReadBranches_
std::atomic< TTree * > tree_
void art::RootOutputTree::fillTree ( )

Definition at line 153 of file RootOutputTree.cc.

154  {
157  false,
159  bool saveMemory = (saveMemoryObjectThreshold_.load() > -1);
160  fillTreeBranches(tree_.load(),
162  saveMemory,
164  if (fastCloningEnabled_.load()) {
165  fillTreeBranches(tree_.load(),
167  saveMemory,
169  } else {
170  fillTreeBranches(tree_.load(),
172  saveMemory,
174  }
175  ++nEntries_;
176  }
std::vector< TBranch * > readBranches_
std::atomic< bool > fastCloningEnabled_
static void fillTreeBranches(TTree *, vector< TBranch * > const &branches, bool saveMemory, int64_t threshold)
std::vector< TBranch * > producedBranches_
std::atomic< int > nEntries_
std::vector< TBranch * > unclonedReadBranches_
std::atomic< TTree * > tree_
std::atomic< TTree * > metaTree_
std::vector< TBranch * > metaBranches_
std::atomic< int64_t > saveMemoryObjectThreshold_
bool art::RootOutputTree::isValid ( ) const
TTree * art::RootOutputTree::makeTTree ( TFile *  filePtr,
std::string const &  name,
int  splitLevel 
)
static

Definition at line 30 of file RootOutputTree.cc.

31  {
32  TTree* tree = new TTree(name.c_str(), "", splitLevel);
33  if (!tree) {
35  << "Failed to create the tree: " << name << "\n";
36  }
37  if (tree->IsZombie()) {
39  << "Tree: " << name << " is a zombie.\n";
40  }
41  tree->SetDirectory(filePtr);
42  // Turn off autosave because it leaves too many deleted tree
43  // keys in the output file.
44  tree->SetAutoSave(numeric_limits<Long64_t>::max());
45  return tree;
46  }
TTree * tree() const
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
TTree* art::RootOutputTree::metaTree ( ) const
inline

Definition at line 85 of file RootOutputTree.h.

86  {
87  return metaTree_.load();
88  }
std::atomic< TTree * > metaTree_
RootOutputTree& art::RootOutputTree::operator= ( RootOutputTree const &  )
delete
void art::RootOutputTree::resetOutputBranchAddress ( BranchDescription const &  bd)

Definition at line 179 of file RootOutputTree.cc.

180  {
181  TBranch* br = tree_.load()->GetBranch(bd.branchName().c_str());
182  if (br == nullptr) {
183  return;
184  }
185  tree_.load()->ResetBranchAddress(br);
186  }
std::atomic< TTree * > tree_
void art::RootOutputTree::setEntries ( )
inline

Definition at line 90 of file RootOutputTree.h.

91  {
92  // The member trees are filled by filling their
93  // branches individually, which ends up not setting
94  // the tree entry count. Tell the trees to set their
95  // entry count based on their branches (all branches
96  // must have the same number of entries).
97  if (tree_.load()->GetNbranches() != 0) {
98  tree_.load()->SetEntries(-1);
99  }
100  if (metaTree_.load()->GetNbranches() != 0) {
101  metaTree_.load()->SetEntries(-1);
102  }
103  }
std::atomic< TTree * > tree_
std::atomic< TTree * > metaTree_
TTree* art::RootOutputTree::tree ( ) const
inline

Definition at line 80 of file RootOutputTree.h.

81  {
82  return tree_.load();
83  }
std::atomic< TTree * > tree_
bool art::RootOutputTree::uncloned ( std::string const &  branchName) const
inline

Definition at line 110 of file RootOutputTree.h.

111  {
112  return unclonedReadBranchNames_.find(branchName) !=
114  }
std::set< std::string > unclonedReadBranchNames_
void art::RootOutputTree::writeTree ( ) const

Definition at line 91 of file RootOutputTree.cc.

92  {
93  writeTTree(tree_.load());
94  writeTTree(metaTree_.load());
95  }
static void writeTTree(TTree *) noexcept(false)
std::atomic< TTree * > tree_
std::atomic< TTree * > metaTree_
void art::RootOutputTree::writeTTree ( TTree *  tree)
staticnoexcept

Definition at line 77 of file RootOutputTree.cc.

78  {
79  // Update the tree-level entry count because we have been
80  // using branch fill instead of tree fill.
81  if (tree->GetNbranches() != 0) {
82  tree->SetEntries(-1);
83  }
84  // Use auto save here instead of write because it deletes
85  // the old tree key from the file, does not flush the
86  // baskets, and writes out the streamer infos, unlike write.
87  tree->AutoSave();
88  }
TTree * tree() const

Member Data Documentation

std::atomic<int> art::RootOutputTree::basketSize_
private

Definition at line 130 of file RootOutputTree.h.

std::atomic<bool> art::RootOutputTree::fastCloningEnabled_
private

Definition at line 129 of file RootOutputTree.h.

cet::exempt_ptr<TFile> art::RootOutputTree::filePtr_
private

Definition at line 117 of file RootOutputTree.h.

std::vector<TBranch*> art::RootOutputTree::metaBranches_ {}
private

Definition at line 122 of file RootOutputTree.h.

std::atomic<TTree*> art::RootOutputTree::metaTree_
private

Definition at line 119 of file RootOutputTree.h.

std::atomic<int> art::RootOutputTree::nEntries_
private

Definition at line 133 of file RootOutputTree.h.

std::vector<TBranch*> art::RootOutputTree::producedBranches_ {}
private

Definition at line 121 of file RootOutputTree.h.

std::vector<TBranch*> art::RootOutputTree::readBranches_ {}
private

Definition at line 123 of file RootOutputTree.h.

std::atomic<int64_t> art::RootOutputTree::saveMemoryObjectThreshold_
private

Definition at line 132 of file RootOutputTree.h.

std::atomic<int> art::RootOutputTree::splitLevel_
private

Definition at line 131 of file RootOutputTree.h.

std::atomic<TTree*> art::RootOutputTree::tree_
private

Definition at line 118 of file RootOutputTree.h.

std::vector<TBranch*> art::RootOutputTree::unclonedReadBranches_ {}
private

Definition at line 124 of file RootOutputTree.h.

std::set<std::string> art::RootOutputTree::unclonedReadBranchNames_ {}
private

Definition at line 125 of file RootOutputTree.h.


The documentation for this class was generated from the following files: