ATLAS Offline Software
Loading...
Searching...
No Matches
ColumnarToolArray.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7//
8// includes
9//
10
12
17
18//
19// method implementations
20//
21
22namespace columnar
23{
26 : m_data (std::make_shared<ColumnarToolDataArray> ())
27 {
28 m_data->mainTool = this;
29 m_data->sharedTools.push_back (this);
30
31 setContainerUserName (ContainerId::eventContext::idName, numberOfEventsName);
32
33 // this name matches the ContainerId::eventInfo::idName, make sure
34 // to keep them in sync. the reason for hard-coding this in two
35 // places is because ContainerId::eventInfo is defined in a separate
36 // package
37 setContainerUserName ("eventInfo", numberOfEventsName);
38 m_eventsData = std::make_unique<ColumnAccessorDataArray> (&m_eventsIndex, &m_eventsData, &typeid (ColumnarOffsetType), ColumnAccessMode::input);
39 addColumn (std::string (ContainerId::eventContext::idName), m_eventsData.get(), {.isOffset = true});
40 }
41
42 ColumnarTool<ColumnarModeArray> ::
43 ColumnarTool (ColumnarTool<ColumnarModeArray>* val_parent)
44 : m_data (val_parent->m_data)
45 {
46 m_eventsData = std::make_unique<ColumnAccessorDataArray> (&m_eventsIndex, &m_eventsData, &typeid (ColumnarOffsetType), ColumnAccessMode::input);
47 addColumn (numberOfEventsName, m_eventsData.get(), {.isOffset = true});
48 }
49
50 ColumnarTool<ColumnarModeArray> ::
51 ~ColumnarTool ()
52 {
53 if (m_data->mainTool == this)
54 m_data->mainTool = nullptr;
55
56 auto iter = std::find (m_data->sharedTools.begin(), m_data->sharedTools.end(), this);
57 if (iter != m_data->sharedTools.end())
58 m_data->sharedTools.erase (iter);
59 }
60
61 void ColumnarTool<ColumnarModeArray> ::
62 addSubtool (ColumnarTool<ColumnarModeArray>& subtool)
63 {
64 // make a copy of the shared data for the subtool, so that I don't
65 // accidentally release it when resetting the shared data pointer on
66 // the subtool
67 auto subtoolData = subtool.m_data;
68
69 if (m_data == subtoolData)
70 return;
71
72 if (subtoolData->mainTool != &subtool)
73 throw std::runtime_error ("subtool already has a different parent tool");
74
75 for (auto& containerName : subtoolData->containerInternalToUserNames)
76 {
77 auto [iter,success] = m_data->containerInternalToUserNames.emplace (containerName.first, containerName.second);
78 if (!success && iter->second != containerName.second)
79 throw std::runtime_error ("container assigned different name in subtool: " + iter->second + " vs " + containerName.second);
80 if (success)
81 m_data->containerUserToInternalNames[containerName.second].push_back (containerName.first);
82 }
83 for (auto& columnName : subtoolData->columnInternalToUserNames)
84 {
85 auto [iter,success] = m_data->columnInternalToUserNames.emplace (columnName.first, columnName.second);
86 if (!success && iter->second != columnName.second)
87 throw std::runtime_error ("column assigned different name in subtool: " + iter->second + " vs " + columnName.second);
88 if (success)
89 m_data->columnUserToInternalNames[columnName.second].push_back (columnName.first);
90 }
91
92 for (auto& column : subtoolData->columns)
93 {
94 auto [iter,success] = m_data->columns.try_emplace (column.first, std::move (column.second));
95 if (!success)
96 iter->second.mergeData (column.first, std::move (column.second));
97 }
98
99 m_data->sharedTools.insert (m_data->sharedTools.end(), subtoolData->sharedTools.begin(), subtoolData->sharedTools.end());
100 for (auto& tool : subtoolData->sharedTools)
101 tool->m_data = m_data;
102 }
103
104
105
106 StatusCode ColumnarTool<ColumnarModeArray> ::
107 initializeColumns ()
108 {
109 return StatusCode::SUCCESS;
110 }
111
112
113
114 void ColumnarTool<ColumnarModeArray> ::
115 callVoid (void **data) const
116 {
117 auto eventsOffset = static_cast<const ColumnarOffsetType*> (data[m_eventsIndex]);
118 callEvents (ObjectRange<ContainerId::eventContext,ColumnarModeArray> (data, eventsOffset[0], eventsOffset[1]));
119 }
120
121
122
123 std::vector<ColumnInfo> ColumnarTool<ColumnarModeArray> ::
124 getColumnInfo () const
125 {
126 std::vector<std::pair<std::string,std::string>> names;
127 names.reserve (m_data->columns.size());
128 for (auto& [name, column] : m_data->columns)
129 {
130 if (!column.empty())
131 names.emplace_back (name, m_data->convertInternalToUserName (name));
132 }
133 std::sort (names.begin(), names.end(), [] (const auto& a, const auto& b) { return a.second < b.second; });
134
135 std::vector<ColumnInfo> result;
136 result.reserve (names.size());
137 for (auto& name : names)
138 {
139 auto& column = m_data->columns.at (name.first);
140 auto info = column.info();
141 info.name = name.second;
142 info.offsetName = m_data->convertInternalToUserName (info.offsetName);
143 info.replacesColumn = m_data->convertInternalToUserName (info.replacesColumn);
144 for (auto& targetName : info.linkTargetNames)
145 targetName = m_data->convertInternalToUserName (targetName);
146 info.variantLinkKeyColumn = m_data->convertInternalToUserName (info.variantLinkKeyColumn);
147 if (result.empty() || result.back().name != info.name)
148 result.push_back (std::move(info));
149 else
150 mergeColumnInfo (result.back(), info);
151 }
152 return result;
153 }
154
155
156
157 void ColumnarTool<ColumnarModeArray> ::
158 renameColumn (const std::string& from, const std::string& to)
159 {
160 if (auto iter = m_data->columnUserToInternalNames.find (from);
161 iter != m_data->columnUserToInternalNames.end())
162 {
163 for (auto& internalName : iter->second)
164 m_data->columnInternalToUserNames[internalName] = to;
165 auto internalNames = iter->second;
166 m_data->columnUserToInternalNames.erase (iter);
167 m_data->columnUserToInternalNames[to].insert (m_data->columnUserToInternalNames[to].end(), internalNames.begin(), internalNames.end());
168 return;
169 }
170
171 auto internalNames = m_data->convertUserToInternalNames (from);
172 m_data->columnUserToInternalNames[to].insert (m_data->columnUserToInternalNames[to].end(), internalNames.begin(), internalNames.end());
173 for (auto& internalName : internalNames)
174 m_data->columnInternalToUserNames[internalName] = to;
175 }
176
177
178
179 void ColumnarTool<ColumnarModeArray> ::
180 setColumnIndex (const std::string& name, std::size_t index)
181 {
182 auto internalNames = m_data->convertUserToInternalNames (name);
183 bool wasSet = false;
184 for (auto& internalName : internalNames)
185 {
186 if (auto column = m_data->columns.find (internalName);
187 column != m_data->columns.end())
188 {
189 column->second.setIndex (index);
190 wasSet = true;
191 }
192 }
193 if (!wasSet)
194 throw std::runtime_error ("column not found: " + name);
195 }
196
197
198
199 void ColumnarTool<ColumnarModeArray> ::
200 callEvents (ObjectRange<ContainerId::eventContext,ColumnarModeArray> /*events*/) const
201 {
202 throw std::runtime_error ("tool didn't implement callEvents");
203 }
204
205
206
207 void ColumnarTool<ColumnarModeArray> ::
208 setContainerUserName (std::string_view container, const std::string& name)
209 {
210 auto [iter, success] = m_data->containerInternalToUserNames.emplace (container, name);
211 if (!success && iter->second != name)
212 throw std::runtime_error ("container already registered with different name: " + name + " vs " + iter->second);
213 m_data->containerUserToInternalNames[name].emplace_back (container);
214 }
215
216
217
218 void ColumnarTool<ColumnarModeArray> ::
219 addColumn (const std::string& name, ColumnAccessorDataArray *accessorData, ColumnInfo&& info)
220 {
221 info.type = accessorData->type;
222 info.accessMode = accessorData->accessMode;
223
224 m_data->columns[name].addAccessor (name, info, accessorData);
225 }
226
227
228
229 ColumnDataArray ::
230 ColumnDataArray (ColumnDataArray&& other) noexcept
231 : m_info (std::move (other.m_info))
232 , m_accessors (std::move (other.m_accessors))
233 {
234 for (auto *ptr : m_accessors)
235 {
236 if (ptr->dataRef == &other)
237 ptr->dataRef = this;
238 }
239 }
240
241
242
243 ColumnDataArray ::
244 ~ColumnDataArray () noexcept
245 {
246 for (auto *ptr : m_accessors)
247 {
248 if (ptr->dataRef == this)
249 ptr->dataRef = nullptr;
250 }
251 }
252
253
254
255 bool ColumnDataArray ::
256 empty () const noexcept
257 {
258 return m_accessors.empty();
259 }
260
261
262
263 const ColumnInfo& ColumnDataArray ::
264 info () const noexcept
265 {
266 return m_info;
267 }
268
269
270
271 void ColumnDataArray ::
272 addAccessor (const std::string& name, const ColumnInfo& val_info, ColumnAccessorDataArray* val_accessorData)
273 {
274 if (m_accessors.empty())
275 {
276 m_info = val_info;
277
278 // ensure that any index is not zero. zero is reserved for a
279 // nullptr, so that if an index has never been initialized, we
280 // get a segfault on access.
281 m_info.index = 0;
282 } else
283 {
284 if (val_info.type != m_info.type)
285 throw std::runtime_error ("multiple types for column: " + name);
287 m_info.accessMode = ColumnAccessMode::update;
288 else if (m_info.accessMode == ColumnAccessMode::output || val_info.accessMode == ColumnAccessMode::output)
289 m_info.accessMode = ColumnAccessMode::output;
290 if (!val_info.isOptional)
291 m_info.isOptional = false;
292 if (val_info.offsetName != m_info.offsetName)
293 throw std::runtime_error ("inconsistent offset map for column: " + name);
294 }
295
296 if (val_accessorData)
297 {
298 m_accessors.push_back (val_accessorData);
299 val_accessorData->dataRef = this;
300 }
301 }
302
303
304
305 void ColumnDataArray ::
306 removeAccessor (ColumnAccessorDataArray& val_accessorData)
307 {
308 auto iter = std::find (m_accessors.begin(), m_accessors.end(), &val_accessorData);
309 if (iter == m_accessors.end())
310 return;
311 m_accessors.erase (iter);
312 val_accessorData.dataRef = nullptr;
313 }
314
315
316
317 void ColumnDataArray ::
318 mergeData (const std::string& name, ColumnDataArray&& other)
319 {
320 mergeColumnInfo (m_info, other.m_info);
321 addAccessor (name, other.m_info, nullptr);
322 m_accessors.insert (m_accessors.end(), other.m_accessors.begin(), other.m_accessors.end());
323 for (auto *ptr : other.m_accessors)
324 ptr->dataRef = this;
325 other.m_accessors.clear();
326 }
327
328
329
330 void ColumnDataArray ::
331 setIndex (unsigned index) noexcept
332 {
333 m_info.index = index;
334 for (auto *ptr : m_accessors)
335 *ptr->dataIndexPtr = index;
336 }
337
338
339
340 std::string ColumnarToolDataArray ::
341 convertInternalToUserName (std::string_view name) const
342 {
343 if (name.empty())
344 return std::string{};
345 if (auto iter = columnInternalToUserNames.find (name);
346 iter != columnInternalToUserNames.end())
347 return iter->second;
348 auto split = name.find ('.');
349 if (split == std::string::npos)
350 split = name.size();
351 auto containerName = name.substr (0, split);
352 auto iter = containerInternalToUserNames.find (containerName);
353 if (iter == containerInternalToUserNames.end())
354 return std::string (name);
355 return iter->second + std::string (name.substr (split));
356 }
357
358
359
360 std::vector<std::string> ColumnarToolDataArray ::
361 convertUserToInternalNames (std::string_view name) const
362 {
363 if (auto iter = columnUserToInternalNames.find (name);
364 iter != columnUserToInternalNames.end())
365 return iter->second;
366 auto split = name.find ('.');
367 if (split == std::string::npos)
368 split = name.size();
369 auto containerName = name.substr (0, split);
370 auto iter = containerUserToInternalNames.find (containerName);
371 if (iter == containerUserToInternalNames.end())
372 return {std::string (name)};
373 std::vector<std::string> result;
374 for (auto& internalContainerName : iter->second)
375 result.push_back (internalContainerName + std::string (name.substr (split)));
376 if (result.empty())
377 result.push_back (std::string (name));
378 return result;
379 }
380}
char data[hepevt_bytes_allocation_ATLAS]
Definition HepEvt.cxx:11
static Double_t a
the base class for all columnar components
std::vector< std::string > split(const std::string &s, const std::string &t=":")
Definition hcg.cxx:177
CONT to(RANGE &&r)
Definition ranges.h:39
void mergeColumnInfo(ColumnInfo &target, const ColumnInfo &source)
@ update
an updateable column
Definition ColumnInfo.h:27
@ output
an output column
Definition ColumnInfo.h:24
std::size_t ColumnarOffsetType
the type used for the size and offsets in the columnar data
Definition index.py:1
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
all the data about a column accessor that the ColumnarTool needs to know about
ColumnDataArray * dataRef
the ColumnDataArray object that holds us
ColumnDataArray() noexcept=default
standard constructor
std::vector< ColumnAccessorDataArray * > m_accessors
the data on all accessors for this column
ColumnInfo m_info
the column info
void addAccessor(const std::string &name, const ColumnInfo &val_info, ColumnAccessorDataArray *val_accessorData)
add an info to the column
a struct that contains meta-information about each column that's needed to interface the column with ...
Definition ColumnInfo.h:35
std::string offsetName
the name of the offset column used for this column (or empty string for none)
Definition ColumnInfo.h:74
bool isOptional
whether this column is optional
Definition ColumnInfo.h:121
ColumnAccessMode accessMode
the access mode for the column
Definition ColumnInfo.h:58
const std::type_info * type
the type of the individual entries in the column
Definition ColumnInfo.h:54
std::unordered_map< std::string, std::string, StringHash, std::equal_to<> > containerInternalToUserNames
the names associated with all container ids
std::unordered_map< std::string, std::vector< std::string >, StringHash, std::equal_to<> > columnUserToInternalNames
std::unordered_map< std::string, std::vector< std::string >, StringHash, std::equal_to<> > containerUserToInternalNames
std::unordered_map< std::string, std::string, StringHash, std::equal_to<> > columnInternalToUserNames
an extra map, for mapping individual column names