Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
RNTuple.cxx
Go to the documentation of this file.
1 /// \file RNTuple.cxx
2 /// \ingroup NTuple ROOT7
3 /// \author Jakob Blomer <jblomer@cern.ch>
4 /// \date 2018-10-04
5 /// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
6 /// is welcome!
7 
8 /*************************************************************************
9  * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. *
10  * All rights reserved. *
11  * *
12  * For the licensing terms see $ROOTSYS/LICENSE. *
13  * For the list of contributors see $ROOTSYS/README/CREDITS. *
14  *************************************************************************/
15 
16 #include "ROOT/RNTuple.hxx"
17 
18 #include "ROOT/RFieldVisitor.hxx"
19 #include "ROOT/RNTupleModel.hxx"
20 #include "ROOT/RPageStorage.hxx"
21 
22 #include <algorithm>
23 #include <iomanip>
24 #include <iostream>
25 #include <sstream>
26 #include <string>
27 #include <unordered_map>
28 #include <utility>
29 
30 #include <TFile.h>
32 
33 
34 ROOT::Experimental::Detail::RNTuple::RNTuple(std::unique_ptr<ROOT::Experimental::RNTupleModel> model)
35  : fModel(std::move(model))
36  , fNEntries(0)
37 {
38 }
39 
40 ROOT::Experimental::Detail::RNTuple::~RNTuple()
41 {
42 }
43 
44 //------------------------------------------------------------------------------
45 
46 void ROOT::Experimental::RNTupleReader::ConnectModel() {
47  std::unordered_map<const Detail::RFieldBase *, DescriptorId_t> fieldPtr2Id;
48  fieldPtr2Id[fModel->GetRootField()] = fSource->GetDescriptor().FindFieldId("", kInvalidDescriptorId);
49  for (auto &field : *fModel->GetRootField()) {
50  auto parentId = fieldPtr2Id[field.GetParent()];
51  auto fieldId = fSource->GetDescriptor().FindFieldId(field.GetName(), parentId);
52  R__ASSERT(fieldId != kInvalidDescriptorId);
53  fieldPtr2Id[&field] = fieldId;
54  Detail::RFieldFuse::Connect(fieldId, *fSource, field);
55  }
56 }
57 
58 ROOT::Experimental::RNTupleReader::RNTupleReader(
59  std::unique_ptr<ROOT::Experimental::RNTupleModel> model,
60  std::unique_ptr<ROOT::Experimental::Detail::RPageSource> source)
61  : ROOT::Experimental::Detail::RNTuple(std::move(model))
62  , fSource(std::move(source))
63  , fMetrics("RNTupleReader")
64 {
65  fSource->Attach();
66  ConnectModel();
67  fNEntries = fSource->GetNEntries();
68  fMetrics.ObserveMetrics(fSource->GetMetrics());
69 }
70 
71 ROOT::Experimental::RNTupleReader::RNTupleReader(std::unique_ptr<ROOT::Experimental::Detail::RPageSource> source)
72  : ROOT::Experimental::Detail::RNTuple(nullptr)
73  , fSource(std::move(source))
74  , fMetrics("RNTupleReader")
75 {
76  fSource->Attach();
77  fModel = fSource->GetDescriptor().GenerateModel();
78  ConnectModel();
79  fNEntries = fSource->GetNEntries();
80  fMetrics.ObserveMetrics(fSource->GetMetrics());
81 }
82 
83 ROOT::Experimental::RNTupleReader::~RNTupleReader()
84 {
85  // needs to be destructed before the page source
86  fModel = nullptr;
87 }
88 
89 std::unique_ptr<ROOT::Experimental::RNTupleReader> ROOT::Experimental::RNTupleReader::Open(
90  std::unique_ptr<RNTupleModel> model,
91  std::string_view ntupleName,
92  std::string_view storage)
93 {
94  return std::make_unique<RNTupleReader>(std::move(model), Detail::RPageSource::Create(ntupleName, storage));
95 }
96 
97 std::unique_ptr<ROOT::Experimental::RNTupleReader> ROOT::Experimental::RNTupleReader::Open(
98  std::string_view ntupleName,
99  std::string_view storage)
100 {
101  return std::make_unique<RNTupleReader>(Detail::RPageSource::Create(ntupleName, storage));
102 }
103 
104 void ROOT::Experimental::RNTupleReader::PrintInfo(const ENTupleInfo what, std::ostream &output)
105 {
106  // TODO(lesimon): In a later version, these variables may be defined by the user or the ideal width may be read out from the terminal.
107  char frameSymbol = '*';
108  int width = 80;
109  /*
110  if (width < 30) {
111  output << "The width is too small! Should be at least 30." << std::endl;
112  return;
113  }
114  */
115  std::string name = fSource->GetDescriptor().GetName();
116  //prepVisitor traverses through all fields to gather information needed for printing.
117  RPrepareVisitor prepVisitor;
118  //printVisitor traverses through all fields to do the actual printing.
119  RPrintVisitor printVisitor(output);
120  switch (what) {
121  case ENTupleInfo::kSummary:
122  for (int i = 0; i < (width/2 + width%2 - 4); ++i)
123  output << frameSymbol;
124  output << " NTUPLE ";
125  for (int i = 0; i < (width/2 - 4); ++i)
126  output << frameSymbol;
127  output << std::endl;
128  // FitString defined in RFieldVisitor.cxx
129  output << frameSymbol << " N-Tuple : " << RNTupleFormatter::FitString(name, width-13) << frameSymbol << std::endl; // prints line with name of ntuple
130  output << frameSymbol << " Entries : " << RNTupleFormatter::FitString(std::to_string(GetNEntries()), width - 13) << frameSymbol << std::endl; // prints line with number of entries
131  GetModel()->GetRootField()->TraverseVisitor(prepVisitor);
132 
133  printVisitor.SetFrameSymbol(frameSymbol);
134  printVisitor.SetWidth(width);
135  printVisitor.SetDeepestLevel(prepVisitor.GetDeepestLevel());
136  printVisitor.SetNumFields(prepVisitor.GetNumFields());
137  GetModel()->GetRootField()->TraverseVisitor(printVisitor);
138 
139  for (int i = 0; i < width; ++i)
140  output << frameSymbol;
141  output << std::endl;
142  break;
143  case ENTupleInfo::kStorageDetails:
144  fSource->GetDescriptor().PrintInfo(output);
145  break;
146  case ENTupleInfo::kMetrics:
147  fMetrics.Print(output);
148  break;
149  default:
150  // Unhandled case, internal error
151  assert(false);
152  }
153 }
154 //------------------------------------------------------------------------------
155 
156 ROOT::Experimental::RNTupleWriter::RNTupleWriter(
157  std::unique_ptr<ROOT::Experimental::RNTupleModel> model,
158  std::unique_ptr<ROOT::Experimental::Detail::RPageSink> sink)
159  : ROOT::Experimental::Detail::RNTuple(std::move(model))
160  , fSink(std::move(sink))
161  , fClusterSizeEntries(kDefaultClusterSizeEntries)
162  , fLastCommitted(0)
163 {
164  fSink->Create(*fModel.get());
165 }
166 
167 ROOT::Experimental::RNTupleWriter::~RNTupleWriter()
168 {
169  CommitCluster();
170  fSink->CommitDataset();
171  // needs to be destructed before the page sink
172  fModel = nullptr;
173 }
174 
175 std::unique_ptr<ROOT::Experimental::RNTupleWriter> ROOT::Experimental::RNTupleWriter::Recreate(
176  std::unique_ptr<RNTupleModel> model,
177  std::string_view ntupleName,
178  std::string_view storage,
179  const RNTupleWriteOptions &options)
180 {
181  return std::make_unique<RNTupleWriter>(std::move(model), Detail::RPageSink::Create(ntupleName, storage, options));
182 }
183 
184 
185 void ROOT::Experimental::RNTupleWriter::CommitCluster()
186 {
187  if (fNEntries == fLastCommitted) return;
188  for (auto& field : *fModel->GetRootField()) {
189  field.Flush();
190  field.CommitCluster();
191  }
192  fSink->CommitCluster(fNEntries);
193  fLastCommitted = fNEntries;
194 }
195 
196 
197 //------------------------------------------------------------------------------
198 
199 
200 ROOT::Experimental::RCollectionNTuple::RCollectionNTuple(std::unique_ptr<REntry> defaultEntry)
201  : fOffset(0), fDefaultEntry(std::move(defaultEntry))
202 {
203 }