7#include <chai/Container.h>
8#include <chai/VectorContainer.h>
10#include "CoralBase/Attribute.h"
11#include "CoralBase/AttributeList.h"
12#include "CoralBase/AttributeListSpecification.h"
13#include "CoralBase/AttributeSpecification.h"
14#include "CoralBase/Blob.h"
23#include <unordered_map>
29 void operator()(coral::AttributeListSpecification* spec)
const {
35 using SpecHolder = std::unique_ptr<coral::AttributeListSpecification, SpecReleaser>;
39 chai::Type chaiTypeFor(
const coral::AttributeSpecification& spec) {
40 static const std::unordered_map<std::type_index, chai::Type>
table{
41 {std::type_index(
typeid(
bool)), chai::Bool},
42 {std::type_index(
typeid(
char)), chai::Int8},
43 {std::type_index(
typeid(
unsigned char)), chai::UInt8},
44 {std::type_index(
typeid(
short)), chai::Int16},
45 {std::type_index(
typeid(
unsigned short)), chai::UInt16},
46 {std::type_index(
typeid(
int)), chai::Int32},
47 {std::type_index(
typeid(
unsigned int)), chai::UInt32},
48 {std::type_index(
typeid(
long long)), chai::Int64},
49 {std::type_index(
typeid(
unsigned long long)), chai::UInt64},
50 {std::type_index(
typeid(
float)), chai::Float},
51 {std::type_index(
typeid(
double)), chai::Double},
52 {std::type_index(
typeid(std::string)), chai::String},
53 {std::type_index(
typeid(coral::Blob)), chai::Blob},
55 const auto it =
table.find(std::type_index(
spec.type()));
56 if (it ==
table.end()) {
57 throw std::runtime_error(
58 "ChaiCoralConverter: unsupported CORAL type '" +
spec.typeName() +
"' for field '" +
spec.name() +
"'");
75 auto* pSpec =
new coral::AttributeListSpecification();
77 for (
const auto& field : fields.fields()) {
79 case chai::Bool: pSpec->extend(field.name,
typeid(
bool));
break;
80 case chai::Int8: pSpec->extend(field.name,
typeid(
char));
break;
81 case chai::UInt8: pSpec->extend(field.name,
typeid(
unsigned char));
break;
82 case chai::Int16: pSpec->extend(field.name,
typeid(
short));
break;
83 case chai::UInt16: pSpec->extend(field.name,
typeid(
unsigned short));
break;
84 case chai::Int32: pSpec->extend(field.name,
typeid(
int));
break;
85 case chai::UInt32: pSpec->extend(field.name,
typeid(
unsigned int));
break;
86 case chai::Int64: pSpec->extend(field.name,
typeid(
long long));
break;
87 case chai::UInt64: pSpec->extend(field.name,
typeid(
unsigned long long));
break;
88 case chai::Float: pSpec->extend(field.name,
typeid(
float));
break;
89 case chai::Double: pSpec->extend(field.name,
typeid(
double));
break;
90 case chai::String: pSpec->extend(field.name,
typeid(std::string));
break;
91 case chai::Blob: pSpec->extend(field.name,
typeid(coral::Blob));
break;
94 throw std::runtime_error(
95 "ChaiCoralConverter::toCoralSpec: unrecognised CHAI type for field '" + field.name +
"'");
106 std::vector<chai::Field> fields;
107 fields.reserve(spec.size());
108 const unsigned int s = spec.size();
109 for (
unsigned int i = 0; i != s; ++i) {
110 const auto& attrSpec = spec[i];
111 fields.push_back({attrSpec.name(), chaiTypeFor(attrSpec)});
113 return chai::FieldSpec(std::move(fields));
117 const chai::Values& values) {
120 if (values.size() != spec.size()) {
121 throw std::runtime_error(
"ChaiCoralConverter::toAttributeList: field count mismatch, payload "
122 + std::to_string(values.size()) +
" vs specification " + std::to_string(spec.size()));
124 coral::AttributeList attr(spec,
true);
125 const unsigned int s = attr.size();
126 for (
unsigned int i = 0; i != s; ++i) {
129 const std::string& fieldName = att.specification().name();
130 const std::size_t idx = values.fieldIndex(fieldName);
131 if (values.isNull(idx)) {
135 switch (values.type(idx)) {
137 att.setValue<
bool>(values.get<
bool>(idx));
140 att.setValue<
char>(values.get<int8_t>(idx));
143 att.setValue<
unsigned char>(values.get<uint8_t>(idx));
146 att.setValue<
short>(values.get<int16_t>(idx));
149 att.setValue<
unsigned short>(values.get<uint16_t>(idx));
152 att.setValue<
int>(values.get<int32_t>(idx));
155 att.setValue<
unsigned int>(values.get<uint32_t>(idx));
158 att.setValue<
long long>(values.get<int64_t>(idx));
161 att.setValue<
unsigned long long>(values.get<uint64_t>(idx));
164 att.setValue<
float>(values.get<
float>(idx));
167 att.setValue<
double>(values.get<
double>(idx));
170 att.setValue<std::string>(values.get<std::string>(idx));
173 const auto& bytes = values.get<chai::BlobData>(idx).m_bytes;
174 coral::Blob blob(bytes.size());
176 if (!bytes.empty()) {
177 std::memcpy(blob.startingAddress(), bytes.data(), bytes.size());
179 att.setValue<coral::Blob>(blob);
184 throw std::runtime_error(
185 "ChaiCoralConverter::toAttributeList: unrecognised CHAI type for field '" + fieldName +
"'");
192 const std::vector<chai::ValuesPtr>& rows) {
193 std::vector<coral::AttributeList> result;
194 result.reserve(rows.size());
195 for (std::size_t i = 0; i != rows.size(); ++i) {
197 throw std::invalid_argument(
198 "ChaiCoralConverter::toAttributeListVec: null row at index " + std::to_string(i));
207 throw std::invalid_argument(
"ChaiCoralConverter::toValues: null field specification");
209 if (fields->size() != attrList.size()) {
210 throw std::runtime_error(
"ChaiCoralConverter::toValues: field count mismatch, specification "
211 + std::to_string(fields->size()) +
" vs payload " + std::to_string(attrList.size()));
213 auto values = std::make_shared<chai::Values>(fields);
214 const std::size_t n = fields->size();
215 for (std::size_t i = 0; i != n; ++i) {
216 const chai::Field& field = (*fields)[i];
217 const int idx = attrList.specification().index(field.name);
219 throw std::runtime_error(
220 "ChaiCoralConverter::toValues: field '" + field.name +
"' not found in payload");
222 const auto& att = attrList[
static_cast<unsigned int>(idx)];
223 const chai::Type payloadType = chaiTypeFor(att.specification());
224 if (payloadType != field.type) {
225 throw std::runtime_error(
226 "ChaiCoralConverter::toValues: type mismatch for field '" + field.name +
"': specification "
227 + field.typeString() +
" vs payload " + chai::typeToString(payloadType));
234 switch (field.type) {
236 values->push(att.data<
bool>());
239 values->push(
static_cast<int8_t
>(att.data<
char>()));
242 values->push(
static_cast<uint8_t
>(att.data<
unsigned char>()));
245 values->push(
static_cast<int16_t
>(att.data<
short>()));
248 values->push(
static_cast<uint16_t
>(att.data<
unsigned short>()));
251 values->push(
static_cast<int32_t
>(att.data<
int>()));
254 values->push(
static_cast<uint32_t
>(att.data<
unsigned int>()));
257 values->push(
static_cast<int64_t
>(att.data<
long long>()));
260 values->push(
static_cast<uint64_t
>(att.data<
unsigned long long>()));
263 values->push(att.data<
float>());
266 values->push(att.data<
double>());
269 values->push(att.data<std::string>());
272 const coral::Blob& blob = att.data<coral::Blob>();
273 std::vector<uint8_t> bytes(blob.size());
275 if (blob.size() != 0) {
276 std::memcpy(bytes.data(), blob.startingAddress(), blob.size());
278 values->push(chai::BlobData(std::move(bytes)));
283 throw std::runtime_error(
284 "ChaiCoralConverter::toValues: unrecognised CHAI type for field '" + field.name +
"'");
291 const std::vector<coral::AttributeList>& rows) {
293 throw std::invalid_argument(
"ChaiCoralConverter::toValuesVec: null field specification");
295 std::vector<chai::ValuesPtr> result;
296 result.reserve(rows.size());
297 for (std::size_t i = 0; i != rows.size(); ++i) {
298 result.push_back(
toValues(fields, rows[i]));
304 const auto ids = container.channelIds();
305 if (ids.size() != 1) {
306 throw std::runtime_error(
307 "ChaiCoralConverter::toAthenaAttributeList: expected exactly one populated channel, found "
308 + std::to_string(ids.size()));
310 const SpecHolder spec(
toCoralSpec(container.fieldSpec()));
311 return std::make_unique<AthenaAttributeList>(
toAttributeList(*spec, container[ids[0]]));
315 const std::string& channelName) {
316 const coral::AttributeListSpecification& coralSpec = attrList.specification();
317 if (coralSpec.size() == 0) {
318 throw std::runtime_error(
"ChaiCoralConverter::toContainer: zero-attribute specification");
320 const auto fields = std::make_shared<const chai::FieldSpec>(
toFieldSpec(coralSpec));
321 chai::Container container(chai::PayloadSpec(*fields, chai::ChannelSpec({{channelId, channelName}})));
322 container.add(channelId,
toValues(fields, attrList));
327 const chai::Container& container,
bool hasRunLumiBlockTime) {
328 const SpecHolder spec(
toCoralSpec(container.fieldSpec()));
329 auto collection = std::make_unique<CondAttrListCollection>(hasRunLumiBlockTime);
330 const auto names = container.channelSpec().channelNames();
331 for (
const auto id : container.channelIds()) {
333 if (
id > std::numeric_limits<CondAttrListCollection::ChanNum>::max()) {
334 throw std::runtime_error(
335 "ChaiCoralConverter::toCondAttrListCollection: channel id " + std::to_string(
id)
336 +
" exceeds ChanNum range");
340 const auto nameIt = names.find(
id);
341 if (nameIt != names.end() && !nameIt->second.empty()) {
342 collection->add(chan, nameIt->second);
349 if (collection.
size() == 0) {
350 throw std::runtime_error(
"ChaiCoralConverter::toContainer: empty collection");
352 const coral::AttributeListSpecification& coralSpec = collection.
begin()->second.specification();
353 if (coralSpec.size() == 0) {
354 throw std::runtime_error(
"ChaiCoralConverter::toContainer: zero-attribute specification");
357 std::map<uint64_t, std::string> channelNames;
358 for (
const auto&
pair : collection) {
359 channelNames[
static_cast<uint64_t
>(
pair.first)] = collection.
chanName(
pair.first);
361 const auto fields = std::make_shared<const chai::FieldSpec>(
toFieldSpec(coralSpec));
362 chai::Container container(chai::PayloadSpec(*fields, chai::ChannelSpec(channelNames)));
363 for (
const auto& [chan, attrList] : collection) {
364 const uint64_t
id = chan;
365 container.add(
id,
toValues(fields, attrList));
371 unsigned int total = 0;
372 const std::size_t n = values.size();
373 for (std::size_t i = 0; i != n; ++i) {
374 if (values.isNull(i))
continue;
375 switch (values.type(i)) {
376 case chai::Bool: total +=
sizeof(bool);
break;
377 case chai::Int8: total +=
sizeof(int8_t);
break;
378 case chai::UInt8: total +=
sizeof(uint8_t);
break;
379 case chai::Int16: total +=
sizeof(int16_t);
break;
380 case chai::UInt16: total +=
sizeof(uint16_t);
break;
381 case chai::Int32: total +=
sizeof(int32_t);
break;
382 case chai::UInt32: total +=
sizeof(uint32_t);
break;
383 case chai::Int64: total +=
sizeof(int64_t);
break;
384 case chai::UInt64: total +=
sizeof(uint64_t);
break;
385 case chai::Float: total +=
sizeof(float);
break;
386 case chai::Double: total +=
sizeof(double);
break;
388 total += values.get<std::string>(i).
size();
391 total += values.get<chai::BlobData>(i).m_bytes.size();
395 throw std::runtime_error(
396 "ChaiCoralConverter::valuesSize: unrecognised CHAI type at field index " + std::to_string(i));
403 unsigned int total = 0;
404 for (
const auto channelId : container.channelIds()) {
411 unsigned int total = 0;
412 for (
const auto channelId : container.channelIds()) {
413 const auto& rows = container.rows(channelId);
414 for (std::size_t i = 0; i != rows.size(); ++i) {
416 throw std::invalid_argument(
417 "ChaiCoralConverter::payloadSize: null row at channel " + std::to_string(channelId)
418 +
" index " + std::to_string(i));
Converts between CHAI payload containers and CORAL objects.
size_t size() const
Number of registered mappings.
An AttributeList represents a logical row of attributes in a metadata table.
static coral::AttributeList toAttributeList(const coral::AttributeListSpecification &spec, const chai::Values &values)
Convert one channel's CHAI Values to a coral::AttributeList, one attribute per field in spec order.
static unsigned int valuesSize(const chai::Values &values)
Total byte size of one channel's field values, using the same type mapping as toAttributeList().
static unsigned int payloadSize(const chai::Container &container)
Total byte size of every populated channel in a scalar payload.
static std::vector< coral::AttributeList > toAttributeListVec(const coral::AttributeListSpecification &spec, const std::vector< chai::ValuesPtr > &rows)
Convert one channel's CHAI vector-payload rows to a coral::AttributeList per row, in row order,...
static coral::AttributeListSpecification * toCoralSpec(const chai::FieldSpec &fields)
Build a coral::AttributeListSpecification from a CHAI FieldSpec, one attribute per field in field ord...
static chai::FieldSpec toFieldSpec(const coral::AttributeListSpecification &spec)
Build a chai::FieldSpec from a coral::AttributeListSpecification, one field per attribute in spec ord...
static chai::Container toContainer(const AthenaAttributeList &attrList, uint64_t channelId=0, const std::string &channelName="")
Convert an AthenaAttributeList to a single-channel chai::Container.
static std::unique_ptr< AthenaAttributeList > toAthenaAttributeList(const chai::Container &container)
Convert a chai::Container's single populated channel to an AthenaAttributeList.
static std::unique_ptr< CondAttrListCollection > toCondAttrListCollection(const chai::Container &container, bool hasRunLumiBlockTime)
Convert a chai::Container to a CondAttrListCollection, one row per populated channel.
static chai::ValuesPtr toValues(chai::FieldSpecPtr fields, const coral::AttributeList &attrList)
Convert one coral::AttributeList to CHAI Values, one value per field in FieldSpec order.
static std::vector< chai::ValuesPtr > toValuesVec(chai::FieldSpecPtr fields, const std::vector< coral::AttributeList > &rows)
Convert a coral::AttributeList per row, in row order, to CHAI Values sharing one FieldSpecPtr,...
This class is a collection of AttributeLists where each one is associated with a channel number.
const_iterator begin() const
Access to Chan/AttributeList pairs via iterators.
const std::string & chanName(ChanNum chanNum) const
find name for particular channel
size_type size() const
number of Chan/AttributeList pairs