ATLAS Offline Software
Loading...
Searching...
No Matches
columnar::ColumnVectorHeader Class Referencefinal

the header information for the entire columnar data vector More...

#include <ColumnVectorWrapper.h>

Collaboration diagram for columnar::ColumnVectorHeader:

Public Member Functions

 ColumnVectorHeader ()
 standard contructor
std::size_t addColumn (const ColumnInfo &columnInfo)
 add a column for the given ColumnInfo, returning its index
void setOffsetColumn (std::size_t columnIndex, std::size_t offsetIndex)
 set the index of the offset column for the given column
std::size_t numColumns () const noexcept
 the number of columns in the columnar data vector
const ColumnVectorElementHeadergetColumn (std::size_t index) const
 get the column for the given index
std::size_t getColumnIndex (const std::string &name) const noexcept
 get the column index for the given name, or nullIndex if not found
std::unordered_map< std::string, ColumnInfogetAllColumnInfo () const
 get all columns as a map of ColumnInfo for use with IColumnData::connect
void checkSelf () const
 check the self-consistency of the header
void checkData (std::span< const void *const > data) const
 do a basic check of the data vector

Static Public Attributes

static constexpr std::size_t nullIndex = 0u
 the index used for an invalid index (always has to be 0)
static constexpr std::size_t sizeIndex = 1u
 the index used for the column size column
static constexpr std::size_t unsetIndex = static_cast<std::size_t>(-1)
 the number used for an unset but non-null index
static constexpr std::size_t numFixedColumns = 2u
 the number of fix elements in the columnar data vector

Private Attributes

std::vector< ColumnVectorElementHeaderm_elements
 the elements in the columnar data vector
std::unordered_map< std::string, std::size_t > m_nameToIndex
 map from column name to index for deduplication

Detailed Description

the header information for the entire columnar data vector

At its core this is just a vector of ColumnVectorElementHeader, with some extra helper functions. Note that this is completely independent of the tool used, and can indeed be used with multiple tools.

Definition at line 114 of file ColumnVectorWrapper.h.

Constructor & Destructor Documentation

◆ ColumnVectorHeader()

columnar::ColumnVectorHeader::ColumnVectorHeader ( )

standard contructor

Definition at line 29 of file ColumnVectorWrapper.cxx.

31 {
33
34 // we always reserve the first column as having a null value
35 m_elements.at(nullIndex).debugName = "<null>";
36 m_elements.at(nullIndex).isOptional = true;
37
38 // we always reserve the second column as the size column
39 m_elements.at(sizeIndex).debugName = "<size>";
40 m_elements.at(sizeIndex).type = &typeid(std::size_t);
41 m_elements.at(sizeIndex).isOptional = false;
42 m_elements.at(sizeIndex).readOnly = true;
43 }
static constexpr std::size_t nullIndex
the index used for an invalid index (always has to be 0)
static constexpr std::size_t numFixedColumns
the number of fix elements in the columnar data vector
std::vector< ColumnVectorElementHeader > m_elements
the elements in the columnar data vector
static constexpr std::size_t sizeIndex
the index used for the column size column

Member Function Documentation

◆ addColumn()

std::size_t columnar::ColumnVectorHeader::addColumn ( const ColumnInfo & columnInfo)
nodiscard

add a column for the given ColumnInfo, returning its index

Definition at line 47 of file ColumnVectorWrapper.cxx.

49 {
50 // Check for existing column with the same name (deduplication for multi-tool support)
51 auto iter = m_nameToIndex.find(columnInfo.name);
52 if (iter != m_nameToIndex.end())
53 {
54 auto& existingHeader = m_elements.at(iter->second);
55
56 // Check that relevant fields match
57 if (existingHeader.type != columnInfo.type)
58 throw std::runtime_error("column " + columnInfo.name + " type mismatch");
59 if (existingHeader.offsetName != columnInfo.offsetName)
60 throw std::runtime_error("column " + columnInfo.name + " offset name mismatch: " + existingHeader.offsetName + " vs " + columnInfo.offsetName);
61 if (existingHeader.isOffset != columnInfo.isOffset)
62 throw std::runtime_error("column " + columnInfo.name + " isOffset mismatch");
63 if (existingHeader.fixedDimensions != columnInfo.fixedDimensions)
64 throw std::runtime_error("column " + columnInfo.name + " fixed dimensions mismatch");
65 if (existingHeader.linkTargetNames != columnInfo.linkTargetNames)
66 throw std::runtime_error("column " + columnInfo.name + " link target names mismatch");
67 if (existingHeader.variantLinkKeyColumn != columnInfo.variantLinkKeyColumn)
68 throw std::runtime_error("column " + columnInfo.name + " variant link key column mismatch");
69
70 // Handle access mode conflicts
71 if (columnInfo.accessMode == ColumnAccessMode::output && existingHeader.readOnly)
72 throw std::runtime_error("column " + columnInfo.name + " already registered as input, cannot register as output");
73 // Promote to read-write if new column needs write access (update mode)
74 if (columnInfo.accessMode == ColumnAccessMode::update)
75 existingHeader.readOnly = false;
76 // If existing is already non-readOnly (output or update), keep it that way
77 return iter->second;
78 }
79
80 m_elements.emplace_back();
81 m_elements.at(sizeIndex).arraySize = m_elements.size();
82
83 auto& header = m_elements.back();
84 header.debugName = columnInfo.name;
85 header.type = columnInfo.type;
86 header.accessMode = columnInfo.accessMode;
87 header.offsetName = columnInfo.offsetName;
88 header.linkTargetNames = columnInfo.linkTargetNames;
89 header.variantLinkKeyColumn = columnInfo.variantLinkKeyColumn;
90 header.fixedDimensions = columnInfo.fixedDimensions;
91
92 switch (columnInfo.accessMode)
93 {
95 break;
97 header.readOnly = false;
98 break;
100 header.readOnly = false;
101 break;
102 }
103 for (unsigned dim : columnInfo.fixedDimensions)
104 header.arraySize *= dim;
105 header.isOffset = columnInfo.isOffset;
106 if (!columnInfo.isOptional)
107 header.isOptional = false;
108 if (!columnInfo.offsetName.empty())
109 header.offsetIndex = unsetIndex;
110
111 const std::size_t newIndex = m_elements.size() - 1;
112 m_nameToIndex.emplace(columnInfo.name, newIndex);
113 return newIndex;
114 }
std::unordered_map< std::string, std::size_t > m_nameToIndex
map from column name to index for deduplication
static constexpr std::size_t unsetIndex
the number used for an unset but non-null index
@ update
an updateable column
Definition ColumnInfo.h:27
@ output
an output column
Definition ColumnInfo.h:24
@ input
an input column
Definition ColumnInfo.h:21

◆ checkData()

void columnar::ColumnVectorHeader::checkData ( std::span< const void *const > data) const

do a basic check of the data vector

Definition at line 175 of file ColumnVectorWrapper.cxx.

177 {
178 if (data.size() != m_elements.size())
179 throw std::logic_error ("data vector has wrong size, expected " + std::to_string(m_elements.size()) + " but got " + std::to_string(data.size()));
180 if (data[nullIndex] != nullptr)
181 throw std::logic_error ("null column is not set to a nullptr value");
182 const auto* sizeVector = static_cast<const std::size_t*>(data[sizeIndex]);
183 for (std::size_t columnIndex = 0u; columnIndex != m_elements.size(); ++ columnIndex)
184 {
185 const auto& column = m_elements[columnIndex];
186 if (data[columnIndex] == nullptr)
187 {
188 if (column.isOptional)
189 continue;
190 if (column.offsetIndex != nullIndex && data[column.offsetIndex] == nullptr)
191 continue;
192 throw std::logic_error ("column " + column.debugName + " was not set");
193 }
194 if (column.isOffset)
195 {
196 const auto size = sizeVector[columnIndex];
197 if (size < 1)
198 throw std::runtime_error ("offset column " + column.debugName + " has size " + std::to_string(size) + ", but needs at least 1 element");
199 auto *offsets = static_cast<const ColumnarOffsetType*>(data[columnIndex]);
200 if (offsets[0] != 0)
201 throw std::runtime_error ("offset column doesn't start with 0: " + column.debugName);
202 for (std::size_t i = 1u; i != size; ++ i)
203 {
204 if (offsets[i] < offsets[i-1])
205 throw std::runtime_error ("offset column " + column.debugName + " is not monotonically increasing at index " + std::to_string(i) + ": " + std::to_string(offsets[i-1]) + " > " + std::to_string(offsets[i]));
206 }
207 }
208 }
209 for (std::size_t columnIndex = 0u; columnIndex != m_elements.size(); ++ columnIndex)
210 {
211 if (data[columnIndex] == nullptr)
212 continue;
213 const auto& column = m_elements[columnIndex];
214 std::size_t expectedSize = 1u;
215 if (column.offsetIndex != ColumnVectorHeader::nullIndex)
216 {
217 if (data[column.offsetIndex] == nullptr)
218 throw std::runtime_error ("column " + column.debugName + " uses offset column " + m_elements[column.offsetIndex].debugName + " that is not set");
219 const auto offsetIndex = column.offsetIndex;
220 auto *offsetsPtr = static_cast<const ColumnarOffsetType*>(data[offsetIndex]);
221 expectedSize = offsetsPtr[sizeVector[offsetIndex]-1];
222 }
223 expectedSize *= column.arraySize;
224
225 if (column.isOffset)
226 expectedSize += 1u;
227
228 if (sizeVector[columnIndex] != expectedSize)
229 throw std::runtime_error ("column size doesn't match expected size: " + column.debugName + ", found " + std::to_string (sizeVector[columnIndex]) + " vs exptected=" + std::to_string (expectedSize) + " isOffset=" + std::to_string (column.isOffset));
230 }
231 }
char data[hepevt_bytes_allocation_ATLAS]
Definition HepEvt.cxx:11
std::size_t ColumnarOffsetType
the type used for the size and offsets in the columnar data

◆ checkSelf()

void columnar::ColumnVectorHeader::checkSelf ( ) const

check the self-consistency of the header

Definition at line 136 of file ColumnVectorWrapper.cxx.

138 {
139 if (m_elements.size() < numFixedColumns)
140 throw std::logic_error ("header has too few m_elements, expected at least " + std::to_string(numFixedColumns) + " but got " + std::to_string(m_elements.size()));
141 if (m_elements[sizeIndex].arraySize != m_elements.size())
142 throw std::logic_error ("size column has wrong array size, expected " + std::to_string(m_elements.size()) + " but got " + std::to_string(m_elements[sizeIndex].arraySize));
143
144 // skipping the first column, which is always the null column
145 // and behaves in a funny manner
146 for (std::size_t columnIndex = 1u; columnIndex != m_elements.size(); ++ columnIndex)
147 {
148 const auto& column = m_elements[columnIndex];
149 if (column.debugName.empty())
150 throw std::logic_error ("column " + std::to_string(columnIndex) + " has no name");
151 if (column.type == nullptr)
152 throw std::logic_error ("column " + column.debugName + " has no type");
153 if (column.isOffset && *column.type != typeid(ColumnarOffsetType))
154 throw std::logic_error ("column " + column.debugName + " is an offset column that is of type " + boost::core::demangle(column.type->name()) + " instead of ColumnarOffsetType");
155 }
156
157 for (std::size_t columnIndex = 1u; columnIndex != m_elements.size(); ++ columnIndex)
158 {
159 const auto& column = m_elements[columnIndex];
160 if (column.offsetIndex != nullIndex)
161 {
162 if (column.offsetIndex == unsetIndex)
163 throw std::logic_error ("column " + column.debugName + " has an offset index that was never set");
164 if (column.offsetIndex >= m_elements.size())
165 throw std::logic_error ("column " + column.debugName + " has invalid offset index " + std::to_string(column.offsetIndex) + " (max is " + std::to_string(m_elements.size()-1) + ")");
166 const auto& offsetElement = m_elements[column.offsetIndex];
167 if (!offsetElement.isOffset)
168 throw std::logic_error ("column " + column.debugName + " has offset index that is not marked as offset");
169 }
170 }
171 }

◆ getAllColumnInfo()

std::unordered_map< std::string, ColumnInfo > columnar::ColumnVectorHeader::getAllColumnInfo ( ) const
nodiscard

get all columns as a map of ColumnInfo for use with IColumnData::connect

Definition at line 307 of file ColumnVectorWrapper.cxx.

309 {
310 std::unordered_map<std::string, ColumnInfo> result;
311 // Skip the fixed columns (null and size)
312 for (std::size_t i = numFixedColumns; i < m_elements.size(); ++i)
313 {
314 const auto& header = m_elements[i];
315 ColumnInfo info;
316 info.name = header.debugName;
317 info.index = static_cast<unsigned>(i);
318 info.type = header.type;
319 info.accessMode = header.accessMode;
320 info.offsetName = header.offsetName;
321 info.fixedDimensions = header.fixedDimensions;
322 info.isOffset = header.isOffset;
323 info.isOptional = header.isOptional;
324 info.linkTargetNames = header.linkTargetNames;
325 info.variantLinkKeyColumn = header.variantLinkKeyColumn;
326 result.emplace(info.name, std::move(info));
327 }
328 return result;
329 }

◆ getColumn()

const ColumnVectorElementHeader & columnar::ColumnVectorHeader::getColumn ( std::size_t index) const
inlinenodiscard

get the column for the given index

Definition at line 149 of file ColumnVectorWrapper.h.

149 {
150 return m_elements.at (index); }

◆ getColumnIndex()

std::size_t columnar::ColumnVectorHeader::getColumnIndex ( const std::string & name) const
inlinenodiscardnoexcept

get the column index for the given name, or nullIndex if not found

Definition at line 154 of file ColumnVectorWrapper.h.

154 {
155 auto iter = m_nameToIndex.find(name);
156 return (iter != m_nameToIndex.end()) ? iter->second : nullIndex; }

◆ numColumns()

std::size_t columnar::ColumnVectorHeader::numColumns ( ) const
inlinenodiscardnoexcept

the number of columns in the columnar data vector

Definition at line 144 of file ColumnVectorWrapper.h.

144 {
145 return m_elements.size(); }

◆ setOffsetColumn()

void columnar::ColumnVectorHeader::setOffsetColumn ( std::size_t columnIndex,
std::size_t offsetIndex )

set the index of the offset column for the given column

Definition at line 118 of file ColumnVectorWrapper.cxx.

120 {
121 if (columnIndex >= m_elements.size())
122 throw std::logic_error ("column index out of range");
123 if (offsetIndex >= m_elements.size())
124 throw std::logic_error ("offset index out of range");
125 auto& column = m_elements.at(columnIndex);
126 auto& offset = m_elements.at(offsetIndex);
127 if (!offset.isOffset)
128 throw std::runtime_error ("trying to set " + offset.debugName + " as offset column for " + column.debugName + ", but it is not marked as offset column");
129 if (column.offsetIndex != unsetIndex && column.offsetIndex != offsetIndex)
130 throw std::runtime_error ("trying to set " + offset.debugName + " as offset column for " + column.debugName + ", but it is already set to " + m_elements.at(column.offsetIndex).debugName);
131 column.offsetIndex = offsetIndex;
132 }

Member Data Documentation

◆ m_elements

std::vector<ColumnVectorElementHeader> columnar::ColumnVectorHeader::m_elements
private

the elements in the columnar data vector

Private Members

Definition at line 174 of file ColumnVectorWrapper.h.

◆ m_nameToIndex

std::unordered_map<std::string, std::size_t> columnar::ColumnVectorHeader::m_nameToIndex
private

map from column name to index for deduplication

Definition at line 177 of file ColumnVectorWrapper.h.

◆ nullIndex

std::size_t columnar::ColumnVectorHeader::nullIndex = 0u
staticconstexpr

the index used for an invalid index (always has to be 0)

Public Members

Definition at line 121 of file ColumnVectorWrapper.h.

◆ numFixedColumns

std::size_t columnar::ColumnVectorHeader::numFixedColumns = 2u
staticconstexpr

the number of fix elements in the columnar data vector

Definition at line 130 of file ColumnVectorWrapper.h.

◆ sizeIndex

std::size_t columnar::ColumnVectorHeader::sizeIndex = 1u
staticconstexpr

the index used for the column size column

Definition at line 124 of file ColumnVectorWrapper.h.

◆ unsetIndex

std::size_t columnar::ColumnVectorHeader::unsetIndex = static_cast<std::size_t>(-1)
staticconstexpr

the number used for an unset but non-null index

Definition at line 127 of file ColumnVectorWrapper.h.


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