ATLAS Offline Software
ColumnVectorWrapper.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 //
9 // includes
10 //
11 
13 
17 
18 #include <boost/core/demangle.hpp>
19 
20 #include <stdexcept>
21 
22 //
23 // method implementations
24 //
25 
26 namespace columnar
27 {
30  {
31  m_elements.resize (numFixedColumns);
32 
33  // we always reserve the first column as having a null value
34  m_elements.at(nullIndex).debugName = "<null>";
35  m_elements.at(nullIndex).isOptional = true;
36 
37  // we always reserve the second column as the size column
38  m_elements.at(sizeIndex).debugName = "<size>";
39  m_elements.at(sizeIndex).type = &typeid(std::size_t);
40  m_elements.at(sizeIndex).isOptional = false;
41  m_elements.at(sizeIndex).readOnly = true;
42  }
43 
44 
45 
46  [[nodiscard]] std::size_t ColumnVectorHeader ::
47  addColumn (const ColumnInfo& columnInfo)
48  {
49  m_elements.emplace_back();
50  m_elements.at(sizeIndex).arraySize = m_elements.size();
51 
52  auto& header = m_elements.back();
53  header.debugName = columnInfo.name;
54  header.type = columnInfo.type;
55 
56  switch (columnInfo.accessMode)
57  {
59  break;
61  header.readOnly = false;
62  break;
64  header.readOnly = false;
65  break;
66  }
67  for (unsigned dim : columnInfo.fixedDimensions)
68  header.arraySize *= dim;
69  header.isOffset = columnInfo.isOffset;
70  if (!columnInfo.isOptional)
71  header.isOptional = false;
72  if (!columnInfo.offsetName.empty())
73  header.offsetIndex = unsetIndex;
74  return m_elements.size() - 1;
75  }
76 
77 
78 
80  setOffsetColumn (std::size_t columnIndex, std::size_t offsetIndex)
81  {
82  if (columnIndex >= m_elements.size())
83  throw std::logic_error ("column index out of range");
84  if (offsetIndex >= m_elements.size())
85  throw std::logic_error ("offset index out of range");
86  auto& column = m_elements.at(columnIndex);
87  auto& offset = m_elements.at(offsetIndex);
88  if (!offset.isOffset)
89  throw std::runtime_error ("trying to set " + offset.debugName + " as offset column for " + column.debugName + ", but it is not marked as offset column");
90  if (column.offsetIndex != unsetIndex && column.offsetIndex != offsetIndex)
91  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);
92  column.offsetIndex = offsetIndex;
93  }
94 
95 
96 
98  checkSelf () const
99  {
100  if (m_elements.size() < numFixedColumns)
101  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()));
102  if (m_elements[sizeIndex].arraySize != m_elements.size())
103  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));
104 
105  // skipping the first column, which is always the null column
106  // and behaves in a funny manner
107  for (std::size_t columnIndex = 1u; columnIndex != m_elements.size(); ++ columnIndex)
108  {
109  const auto& column = m_elements[columnIndex];
110  if (column.debugName.empty())
111  throw std::logic_error ("column " + std::to_string(columnIndex) + " has no name");
112  if (column.type == nullptr)
113  throw std::logic_error ("column " + column.debugName + " has no type");
114  if (column.isOffset && *column.type != typeid(ColumnarOffsetType))
115  throw std::logic_error ("column " + column.debugName + " is an offset column that is of type " + boost::core::demangle(column.type->name()) + " instead of ColumnarOffsetType");
116  }
117 
118  for (std::size_t columnIndex = 1u; columnIndex != m_elements.size(); ++ columnIndex)
119  {
120  const auto& column = m_elements[columnIndex];
121  if (column.offsetIndex != nullIndex)
122  {
123  if (column.offsetIndex == unsetIndex)
124  throw std::logic_error ("column " + column.debugName + " has an offset index that was never set");
125  if (column.offsetIndex >= m_elements.size())
126  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) + ")");
127  const auto& offsetElement = m_elements[column.offsetIndex];
128  if (!offsetElement.isOffset)
129  throw std::logic_error ("column " + column.debugName + " has offset index that is not marked as offset");
130  }
131  }
132  }
133 
134 
135 
137  checkData (std::span<const void* const> data) const
138  {
139  if (data.size() != m_elements.size())
140  throw std::logic_error ("data vector has wrong size, expected " + std::to_string(m_elements.size()) + " but got " + std::to_string(data.size()));
141  if (data[nullIndex] != nullptr)
142  throw std::logic_error ("null column is not set to a nullptr value");
143  const auto* sizeVector = static_cast<const std::size_t*>(data[sizeIndex]);
144  for (std::size_t columnIndex = 0u; columnIndex != m_elements.size(); ++ columnIndex)
145  {
146  const auto& column = m_elements[columnIndex];
147  if (data[columnIndex] == nullptr)
148  {
149  if (column.isOptional)
150  continue;
151  if (column.offsetIndex != nullIndex && data[column.offsetIndex] == nullptr)
152  continue;
153  throw std::logic_error ("column " + column.debugName + " was not set");
154  }
155  if (column.isOffset)
156  {
157  const auto size = sizeVector[columnIndex];
158  if (size < 1)
159  throw std::runtime_error ("offset column " + column.debugName + " has size " + std::to_string(size) + ", but needs at least 1 element");
160  auto *offsets = static_cast<const ColumnarOffsetType*>(data[columnIndex]);
161  if (offsets[0] != 0)
162  throw std::runtime_error ("offset column doesn't start with 0: " + column.debugName);
163  for (std::size_t i = 1u; i != size; ++ i)
164  {
165  if (offsets[i] < offsets[i-1])
166  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]));
167  }
168  }
169  }
170  for (std::size_t columnIndex = 0u; columnIndex != m_elements.size(); ++ columnIndex)
171  {
172  if (data[columnIndex] == nullptr)
173  continue;
174  const auto& column = m_elements[columnIndex];
175  std::size_t expectedSize = 1u;
176  if (column.offsetIndex != ColumnVectorHeader::nullIndex)
177  {
178  if (data[column.offsetIndex] == nullptr)
179  throw std::runtime_error ("column " + column.debugName + " uses offset column " + m_elements[column.offsetIndex].debugName + " that is not set");
180  const auto offsetIndex = column.offsetIndex;
181  auto *offsetsPtr = static_cast<const ColumnarOffsetType*>(data[offsetIndex]);
182  expectedSize = offsetsPtr[sizeVector[offsetIndex]-1];
183  }
184  expectedSize *= column.arraySize;
185 
186  if (column.isOffset)
187  expectedSize += 1u;
188 
189  if (sizeVector[columnIndex] != expectedSize)
190  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));
191  }
192  }
193 
194 
195 
197  ColumnVectorData (const ColumnVectorHeader *val_header)
198  : m_header (val_header),
199  m_data (val_header->numColumns(), nullptr),
200  m_dataSize (val_header->numColumns(), 0u)
201  {
203  }
204 
205 
206 
208  setColumnVoid (std::size_t columnIndex, std::size_t size, const void *dataPtr, const std::type_info& type, bool isConst)
209  {
210  if (columnIndex == ColumnVectorHeader::nullIndex)
211  throw std::logic_error ("cannot set the null column");
212  if (columnIndex >= m_header->numColumns())
213  throw std::logic_error ("invalid column index: " + std::to_string(columnIndex) + " (max is " + std::to_string(m_header->numColumns()-1) + ")");
214  auto& header = m_header->getColumn (columnIndex);
215 
216  // If dataPtr is null, we use a dummy value to avoid issues in which
217  // we check whether a column exists by checking for a null pointer,
218  // which would return false for columns that were set with a
219  // nullptr.
220  if (dataPtr == nullptr)
221  {
222  if (size != 0) [[unlikely]]
223  throw std::logic_error ("dataPtr is null but size is not zero for column: " + header.debugName);
224  static const unsigned dummyValue = 0;
225  dataPtr = &dummyValue;
226  }
227 
228  if (type != *header.type)
229  throw std::runtime_error ("invalid type for column: " + header.debugName);
230  if (isConst && !header.readOnly)
231  throw std::runtime_error ("assigning const vector to a column that is not read-only: " + header.debugName);
232  if (m_data[columnIndex] != nullptr)
233  throw std::runtime_error ("column filled multiple times: " + header.debugName);
234  auto *castDataPtr ATLAS_THREAD_SAFE = const_cast<void*>(dataPtr);
235  m_data[columnIndex] = castDataPtr;
236  m_dataSize[columnIndex] = size;
237  }
238 
239 
240 
241  std::pair<std::size_t,const void*> ColumnVectorData ::
242  getColumnVoid (std::size_t columnIndex, const std::type_info *type, bool isConst)
243  {
244  if (columnIndex >= m_header->numColumns())
245  throw std::runtime_error ("invalid column index: " + std::to_string(columnIndex) + " (max is " + std::to_string(m_header->numColumns()-1) + ")");
246 
247  auto& header = m_header->getColumn (columnIndex);
248  if (*type != *header.type)
249  throw std::runtime_error ("invalid type for column: " + header.debugName);
250  if (!isConst && header.readOnly)
251  throw std::runtime_error ("retrieving non-const vector from a read-only column: " + header.debugName);
252  if (m_data[columnIndex] != nullptr)
253  return std::make_pair (m_dataSize[columnIndex], m_data[columnIndex]);
254  else
255  return std::make_pair (0u, nullptr);
256  }
257 
258 
259 
262  {
263  tool.callVoid (m_data.data());
264  }
265 }
data
char data[hepevt_bytes_allocation_ATLAS]
Definition: HepEvt.cxx:11
columnar::IColumnarTool
an interface for tools that operate on columnar data
Definition: IColumnarTool.h:214
columnar::ColumnAccessMode::input
@ input
an input column
columnar::ColumnInfo::accessMode
ColumnAccessMode accessMode
the access mode for the column
Definition: ColumnInfo.h:58
yodamerge_tmp.dim
dim
Definition: yodamerge_tmp.py:239
columnar::ColumnInfo::name
std::string name
the name of the column
Definition: ColumnInfo.h:42
header
Definition: hcg.cxx:526
columnar::ColumnInfo::offsetName
std::string offsetName
the name of the offset column used for this column (or empty string for none)
Definition: ColumnInfo.h:74
columnar::ColumnVectorData::setColumn
void setColumn(std::size_t columnIndex, std::size_t size, CT *dataPtr)
set the data for the given column
Definition: ColumnVectorWrapper.h:169
columnar::ColumnVectorData::ColumnVectorData
ColumnVectorData(const ColumnVectorHeader *val_header)
standard constructor
Definition: ColumnVectorWrapper.cxx:197
columnar::ColumnVectorHeader::checkSelf
void checkSelf() const
check the self-consistency of the header
Definition: ColumnVectorWrapper.cxx:98
m_data
std::vector< T > m_data
Definition: TrackTruthMatchingBaseAlg.cxx:660
columnar::ColumnVectorHeader
the header information for the entire columnar data vector
Definition: ColumnVectorWrapper.h:97
DeMoUpdate.column
dictionary column
Definition: DeMoUpdate.py:1110
columnar::ColumnVectorHeader::nullIndex
static constexpr std::size_t nullIndex
the index used for an invalid index (always has to be 0)
Definition: ColumnVectorWrapper.h:103
columnar::ColumnInfo::type
const std::type_info * type
the type of the individual entries in the column
Definition: ColumnInfo.h:54
columnar::ColumnInfo::isOffset
bool isOffset
whether this is an offset column
Definition: ColumnInfo.h:92
columnar::ColumnVectorHeader::unsetIndex
static constexpr std::size_t unsetIndex
the number used for an unset but non-null index
Definition: ColumnVectorWrapper.h:109
Analysis::dummyValue
const double dummyValue
Definition: CalibrationDataInterfaceBase.h:33
Trk::u
@ u
Enums for curvilinear frames.
Definition: ParamDefs.h:77
python.CaloAddPedShiftConfig.type
type
Definition: CaloAddPedShiftConfig.py:42
columnar::ColumnAccessMode::output
@ output
an output column
columnar::ColumnVectorData::callNoCheck
void callNoCheck(const IColumnarTool &tool)
call the tool with the assembled data, without performing any checks on the data
Definition: ColumnVectorWrapper.cxx:261
columnar::ColumnVectorData::m_data
std::vector< void * > m_data
Definition: ColumnVectorWrapper.h:206
columnar::ColumnVectorHeader::addColumn
std::size_t addColumn(const ColumnInfo &columnInfo)
add a column for the given ColumnInfo, returning its index
Definition: ColumnVectorWrapper.cxx:47
columnar::ColumnVectorData::getColumnVoid
std::pair< std::size_t, const void * > getColumnVoid(std::size_t columnIndex, const std::type_info *type, bool isConst)
Definition: ColumnVectorWrapper.cxx:242
columnar::ColumnInfo
a struct that contains meta-information about each column that's needed to interface the column with ...
Definition: ColumnInfo.h:35
IColumnarTool.h
lumiFormat.i
int i
Definition: lumiFormat.py:85
columnar::ColumnVectorData::setColumnVoid
void setColumnVoid(std::size_t columnIndex, std::size_t size, const void *dataPtr, const std::type_info &type, bool isConst)
Definition: ColumnVectorWrapper.cxx:208
columnar::ColumnVectorHeader::numColumns
std::size_t numColumns() const noexcept
the number of columns in the columnar data vector
Definition: ColumnVectorWrapper.h:126
columnar::ColumnInfo::isOptional
bool isOptional
whether this column is optional
Definition: ColumnInfo.h:121
columnar::ColumnVectorData::m_dataSize
std::vector< std::size_t > m_dataSize
Definition: ColumnVectorWrapper.h:207
ColumnVectorWrapper.h
columnar::size
std::size_t size() const noexcept
Definition: ObjectRange.h:166
columnar::ColumnAccessMode::update
@ update
an updateable column
columnar::ColumnVectorHeader::sizeIndex
static constexpr std::size_t sizeIndex
the index used for the column size column
Definition: ColumnVectorWrapper.h:106
columnar::ColumnVectorHeader::numFixedColumns
static constexpr std::size_t numFixedColumns
the number of fix elements in the columnar data vector
Definition: ColumnVectorWrapper.h:112
ActsTrk::to_string
std::string to_string(const DetectorType &type)
Definition: GeometryDefs.h:34
AtlCoolConsole.tool
tool
Definition: AtlCoolConsole.py:452
unlikely
#define unlikely(x)
Definition: dictionary.h:41
columnar
Definition: ClusterDef.h:16
columnar::ColumnVectorHeader::getColumn
const ColumnVectorElementHeader & getColumn(std::size_t index) const
get the column for the given index
Definition: ColumnVectorWrapper.h:131
columnar::ColumnVectorHeader::m_elements
std::vector< ColumnVectorElementHeader > m_elements
the elements in the columnar data vector
Definition: ColumnVectorWrapper.h:147
convertTimingResiduals.offset
offset
Definition: convertTimingResiduals.py:71
columnar::ColumnVectorHeader::setOffsetColumn
void setOffsetColumn(std::size_t columnIndex, std::size_t offsetIndex)
set the index of the offset column for the given column
Definition: ColumnVectorWrapper.cxx:80
ATLAS_THREAD_SAFE
#define ATLAS_THREAD_SAFE
Definition: checker_macros.h:211
ColumnInfo.h
columnar::ColumnVectorHeader::checkData
void checkData(std::span< const void *const > data) const
do a basic check of the data vector
Definition: ColumnVectorWrapper.cxx:137
checker_macros.h
Define macros for attributes used to control the static checker.
columnar::ColumnarOffsetType
std::size_t ColumnarOffsetType
the type used for the size and offsets in the columnar data
Definition: IColumnarTool.h:20
columnar::ColumnInfo::fixedDimensions
std::vector< unsigned > fixedDimensions
the fixed dimensions this column has (if any)
Definition: ColumnInfo.h:82
columnar::ColumnVectorHeader::ColumnVectorHeader
ColumnVectorHeader()
standard contructor
Definition: ColumnVectorWrapper.cxx:29
columnar::ColumnVectorData::m_header
const ColumnVectorHeader * m_header
Definition: ColumnVectorWrapper.h:205