Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
RPageStorage.cxx
Go to the documentation of this file.
1 /// \file RPageStorage.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/RPageStorage.hxx>
17 #include <ROOT/RColumn.hxx>
18 #include <ROOT/RField.hxx>
19 #include <ROOT/RNTupleModel.hxx>
20 #include <ROOT/RPagePool.hxx>
21 #include <ROOT/RPageStorageRaw.hxx>
23 #include <ROOT/RStringView.hxx>
24 
25 #include <Compression.h>
26 #include <TError.h>
27 
28 #include <unordered_map>
29 #include <utility>
30 
31 namespace {
32 
33 bool StrEndsWith(const std::string &str, const std::string &suffix)
34 {
35  if (str.size() < suffix.size())
36  return false;
37  return (str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0);
38 }
39 
40 } // anonymous namespace
41 
42 ROOT::Experimental::Detail::RPageStorage::RPageStorage(std::string_view name) : fNTupleName(name)
43 {
44 }
45 
46 ROOT::Experimental::Detail::RPageStorage::~RPageStorage()
47 {
48 }
49 
50 
51 //------------------------------------------------------------------------------
52 
53 
54 ROOT::Experimental::Detail::RPageSource::RPageSource(std::string_view name, const RNTupleReadOptions &options)
55  : RPageStorage(name), fOptions(options)
56 {
57 }
58 
59 ROOT::Experimental::Detail::RPageSource::~RPageSource()
60 {
61 }
62 
63 std::unique_ptr<ROOT::Experimental::Detail::RPageSource> ROOT::Experimental::Detail::RPageSource::Create(
64  std::string_view ntupleName, std::string_view location, const RNTupleReadOptions &options)
65 {
66  if (StrEndsWith(std::string(location), ".root"))
67  return std::make_unique<RPageSourceRoot>(ntupleName, location, options);
68  return std::make_unique<RPageSourceRaw>(ntupleName, location, options);
69 }
70 
71 ROOT::Experimental::Detail::RPageStorage::ColumnHandle_t
72 ROOT::Experimental::Detail::RPageSource::AddColumn(DescriptorId_t fieldId, const RColumn &column)
73 {
74  R__ASSERT(fieldId != kInvalidDescriptorId);
75  auto columnId = fDescriptor.FindColumnId(fieldId, column.GetIndex());
76  R__ASSERT(columnId != kInvalidDescriptorId);
77  return ColumnHandle_t(columnId, &column);
78 }
79 
80 ROOT::Experimental::NTupleSize_t ROOT::Experimental::Detail::RPageSource::GetNEntries()
81 {
82  return fDescriptor.GetNEntries();
83 }
84 
85 ROOT::Experimental::NTupleSize_t ROOT::Experimental::Detail::RPageSource::GetNElements(ColumnHandle_t columnHandle)
86 {
87  return fDescriptor.GetNElements(columnHandle.fId);
88 }
89 
90 ROOT::Experimental::ColumnId_t ROOT::Experimental::Detail::RPageSource::GetColumnId(ColumnHandle_t columnHandle)
91 {
92  // TODO(jblomer) distinguish trees
93  return columnHandle.fId;
94 }
95 
96 
97 //------------------------------------------------------------------------------
98 
99 
100 ROOT::Experimental::Detail::RPageSink::RPageSink(std::string_view name, const RNTupleWriteOptions &options)
101  : RPageStorage(name), fOptions(options)
102 {
103 }
104 
105 ROOT::Experimental::Detail::RPageSink::~RPageSink()
106 {
107 }
108 
109 std::unique_ptr<ROOT::Experimental::Detail::RPageSink> ROOT::Experimental::Detail::RPageSink::Create(
110  std::string_view ntupleName, std::string_view location, const RNTupleWriteOptions &options)
111 {
112  if (StrEndsWith(std::string(location), ".root"))
113  return std::make_unique<RPageSinkRoot>(ntupleName, location, options);
114  return std::make_unique<RPageSinkRaw>(ntupleName, location, options);
115 }
116 
117 ROOT::Experimental::Detail::RPageStorage::ColumnHandle_t
118 ROOT::Experimental::Detail::RPageSink::AddColumn(DescriptorId_t fieldId, const RColumn &column)
119 {
120  auto columnId = fLastColumnId++;
121  fDescriptorBuilder.AddColumn(columnId, fieldId, column.GetVersion(), column.GetModel(), column.GetIndex());
122  return ColumnHandle_t(columnId, &column);
123 }
124 
125 
126 void ROOT::Experimental::Detail::RPageSink::Create(RNTupleModel &model)
127 {
128  fDescriptorBuilder.SetNTuple(fNTupleName, model.GetDescription(), "undefined author",
129  model.GetVersion(), model.GetUuid());
130 
131  std::unordered_map<const RFieldBase *, DescriptorId_t> fieldPtr2Id; // necessary to find parent field ids
132  const auto &rootField = *model.GetRootField();
133  fDescriptorBuilder.AddField(fLastFieldId, rootField.GetFieldVersion(), rootField.GetTypeVersion(),
134  rootField.GetName(), rootField.GetType(), rootField.GetNRepetitions(), rootField.GetStructure());
135  fieldPtr2Id[&rootField] = fLastFieldId++;
136  for (auto& f : *model.GetRootField()) {
137  fDescriptorBuilder.AddField(fLastFieldId, f.GetFieldVersion(), f.GetTypeVersion(), f.GetName(), f.GetType(),
138  f.GetNRepetitions(), f.GetStructure());
139  fDescriptorBuilder.AddFieldLink(fieldPtr2Id[f.GetParent()], fLastFieldId);
140 
141  Detail::RFieldFuse::Connect(fLastFieldId, *this, f); // issues in turn one or several calls to AddColumn()
142  fieldPtr2Id[&f] = fLastFieldId++;
143  }
144 
145  auto nColumns = fLastColumnId;
146  for (DescriptorId_t i = 0; i < nColumns; ++i) {
147  RClusterDescriptor::RColumnRange columnRange;
148  columnRange.fColumnId = i;
149  columnRange.fFirstElementIndex = 0;
150  columnRange.fNElements = 0;
151  columnRange.fCompressionSettings = fOptions.GetCompression();
152  fOpenColumnRanges.emplace_back(columnRange);
153  RClusterDescriptor::RPageRange pageRange;
154  pageRange.fColumnId = i;
155  fOpenPageRanges.emplace_back(std::move(pageRange));
156  }
157 
158  DoCreate(model);
159 }
160 
161 
162 void ROOT::Experimental::Detail::RPageSink::CommitPage(ColumnHandle_t columnHandle, const RPage &page)
163 {
164  auto locator = DoCommitPage(columnHandle, page);
165 
166  auto columnId = columnHandle.fId;
167  fOpenColumnRanges[columnId].fNElements += page.GetNElements();
168  RClusterDescriptor::RPageRange::RPageInfo pageInfo;
169  pageInfo.fNElements = page.GetNElements();
170  pageInfo.fLocator = locator;
171  fOpenPageRanges[columnId].fPageInfos.emplace_back(pageInfo);
172 }
173 
174 
175 void ROOT::Experimental::Detail::RPageSink::CommitCluster(ROOT::Experimental::NTupleSize_t nEntries)
176 {
177  auto locator = DoCommitCluster(nEntries);
178 
179  R__ASSERT((nEntries - fPrevClusterNEntries) < ClusterSize_t(-1));
180  fDescriptorBuilder.AddCluster(fLastClusterId, RNTupleVersion(), fPrevClusterNEntries,
181  ClusterSize_t(nEntries - fPrevClusterNEntries));
182  fDescriptorBuilder.SetClusterLocator(fLastClusterId, locator);
183  for (auto &range : fOpenColumnRanges) {
184  fDescriptorBuilder.AddClusterColumnRange(fLastClusterId, range);
185  range.fFirstElementIndex += range.fNElements;
186  range.fNElements = 0;
187  }
188  for (auto &range : fOpenPageRanges) {
189  RClusterDescriptor::RPageRange fullRange;
190  std::swap(fullRange, range);
191  range.fColumnId = fullRange.fColumnId;
192  fDescriptorBuilder.AddClusterPageRange(fLastClusterId, std::move(fullRange));
193  }
194  ++fLastClusterId;
195  fPrevClusterNEntries = nEntries;
196 }