1111
1212#include " AnalysisCCDBHelpers.h"
1313#include " CCDBFetcherHelper.h"
14+ #include " Framework/ArrowTypes.h"
1415#include " Framework/DataProcessingStats.h"
1516#include " Framework/DeviceSpec.h"
1617#include " Framework/TimingInfo.h"
2223#include " Framework/DanglingEdgesContext.h"
2324#include " Framework/ConfigContext.h"
2425#include " Framework/ConfigParamsHelper.h"
26+ #include < fairmq/Version.h>
2527#include < arrow/array/builder_binary.h>
2628#include < arrow/type.h>
2729#include < arrow/type_fwd.h>
@@ -109,20 +111,49 @@ AlgorithmSpec AnalysisCCDBHelpers::fetchFromCCDB(ConfigContext const& /*ctx*/)
109111 auto it = ccdbUrls.find (m.name );
110112 fieldMetadata->Append (" url" , it != ccdbUrls.end () ? it->second : m.defaultValue .asString ());
111113 auto columnName = m.name .substr (strlen (" ccdb:" ));
114+ #if (FAIRMQ_VERSION_DEC >= 111000)
115+ fields.emplace_back (std::make_shared<arrow::Field>(columnName, soa::asArrowDataType<int64_t [3 ]>(), false , fieldMetadata));
116+ #else
112117 fields.emplace_back (std::make_shared<arrow::Field>(columnName, arrow::binary_view (), false , fieldMetadata));
118+ #endif
113119 }
114120 schemas.emplace_back (std::make_shared<arrow::Schema>(fields, schemaMetadata));
115121 }
116122
123+ #if (FAIRMQ_VERSION_DEC >= 111000)
124+ std::vector<std::pair<uint32_t , std::shared_ptr<arrow::FixedSizeListBuilder>>> allbuilders;
125+ #else
126+ std::vector<std::pair<uint32_t , std::shared_ptr<arrow::BinaryViewBuilder>>> allbuilders;
127+ #endif
128+ allbuilders.resize ([&schemas]() { size_t size = 0 ; for (auto & schema : schemas) { size += schema->num_fields (); }; return size; }());
129+ auto * pool = arrow::default_memory_pool ();
130+
131+ int idx = 0 ;
132+ int sidx = 0 ;
133+ for (auto const & schema : schemas) {
134+ for (auto const & _ : schema->fields ()) {
135+ #if (FAIRMQ_VERSION_DEC >= 111000)
136+ auto value_builder = std::make_shared<arrow::Int64Builder>();
137+ allbuilders[idx] = std::make_pair (sidx, std::make_shared<arrow::FixedSizeListBuilder>(pool, std::move (value_builder), 3 ));
138+ #else
139+ allbuilders[idx] = std::make_pair (sidx, std::make_shared<arrow::BinaryViewBuilder>());
140+ #endif
141+ ++idx;
142+ }
143+ ++sidx;
144+ }
145+
117146 std::shared_ptr<CCDBFetcherHelper> helper = std::make_shared<CCDBFetcherHelper>();
118147 CCDBFetcherHelper::initialiseHelper (*helper, options);
119148 std::unordered_map<std::string, int > bindings;
120149 fillValidRoutes (*helper, spec.outputs , bindings);
121150
122- return adaptStateless ([schemas, bindings, helper](InputRecord& inputs, DataTakingContext& dtc, DataAllocator& allocator, TimingInfo& timingInfo, DataProcessingStats& stats) {
151+ return adaptStateless ([schemas, bindings, helper, allbuilders ](InputRecord& inputs, DataTakingContext& dtc, DataAllocator& allocator, TimingInfo& timingInfo, DataProcessingStats& stats) {
123152 O2_SIGNPOST_ID_GENERATE (sid, ccdb);
124153 O2_SIGNPOST_START (ccdb, sid, " fetchFromAnalysisCCDB" , " Fetching CCDB objects for analysis%" PRIu64, (uint64_t )timingInfo.timeslice );
125- for (auto & schema : schemas) {
154+ std::ranges::for_each (allbuilders, [](auto & builder) { builder.second ->Reset (); });
155+ for (auto i = 0U ; i < schemas.size (); ++i) {
156+ auto & schema = schemas[i];
126157 std::vector<CCDBFetcherHelper::FetchOp> ops;
127158 auto inputBinding = *schema->metadata ()->Get (" sourceTable" );
128159 auto inputMatcher = DataSpecUtils::fromString (*schema->metadata ()->Get (" sourceMatcher" ));
@@ -134,20 +165,32 @@ AlgorithmSpec AnalysisCCDBHelpers::fetchFromCCDB(ConfigContext const& /*ctx*/)
134165 auto table = inputs.get <TableConsumer>(inputMatcher)->asArrowTable ();
135166 // FIXME: make the fTimestamp column configurable.
136167 auto timestampColumn = table->GetColumnByName (" fTimestamp" );
168+ auto reserveSize = timestampColumn->length ();
137169 O2_SIGNPOST_EVENT_EMIT_INFO (ccdb, sid, " fetchFromAnalysisCCDB" ,
138170 " There are %zu bindings available" , bindings.size ());
139- for (auto & binding : bindings) {
171+ for (auto const & binding : bindings) {
140172 O2_SIGNPOST_EVENT_EMIT_INFO (ccdb, sid, " fetchFromAnalysisCCDB" ,
141173 " * %{public}s: %d" ,
142174 binding.first .c_str (), binding.second );
143175 }
144176 int outputRouteIndex = bindings.at (outRouteDesc);
145177 auto & spec = helper->routes [outputRouteIndex].matcher ;
146- std::vector<std::shared_ptr<arrow::BinaryViewBuilder>> builders;
147- for (auto const & _ : schema->fields ()) {
148- builders.emplace_back (std::make_shared<arrow::BinaryViewBuilder>());
178+ auto concrete = DataSpecUtils::asConcreteDataMatcher (spec);
179+ Output output{concrete.origin , concrete.description , concrete.subSpec };
180+ auto builders = allbuilders | std::views::filter ([&i](auto const & builder) { return builder.first == i; });
181+ unsigned int numBuilders = std::ranges::count_if (allbuilders, [&i](auto const & builder) { return builder.first == i; });
182+ arrow::Status status;
183+ std::ranges::for_each (builders, [&status, &reserveSize](auto & builder) {
184+ if (reserveSize > builder.second ->capacity ()) {
185+ status &= builder.second ->Reserve (reserveSize - builder.second ->capacity ());
186+ }
187+ });
188+ if (!status.ok ()) {
189+ throw framework::runtime_error_f (" Failed to reserve arrays: " , status.ToString ().c_str ());
149190 }
150191
192+ std::vector<DataAllocator::CacheId> lastIds (numBuilders, DataAllocator::CacheId{.value = -1 , .handle = -1 , .segment = -1 });
193+
151194 for (auto ci = 0 ; ci < timestampColumn->num_chunks (); ++ci) {
152195 std::shared_ptr<arrow::Array> chunk = timestampColumn->chunk (ci);
153196 auto const * timestamps = chunk->data ()->GetValuesSafe <size_t >(1 );
@@ -171,15 +214,30 @@ AlgorithmSpec AnalysisCCDBHelpers::fetchFromCCDB(ConfigContext const& /*ctx*/)
171214 O2_SIGNPOST_START (ccdb, sid, " handlingResponses" ,
172215 " Got %zu responses from server." ,
173216 responses.size ());
174- if (builders. size () != responses.size ()) {
175- LOGP (fatal, " Not enough responses (expected {}, found {})" , builders. size () , responses.size ());
217+ if (numBuilders != responses.size ()) {
218+ LOGP (fatal, " Not enough responses (expected {}, found {})" , numBuilders , responses.size ());
176219 }
177220 arrow::Status result;
178- for (size_t bi = 0 ; bi < responses.size (); bi++) {
179- auto & builder = builders[bi];
221+
222+ int bi = 0 ;
223+ for (auto & builder : builders) {
180224 auto & response = responses[bi];
225+ auto & lastId = lastIds[bi];
226+ if (response.id .value != lastId.value ) {
227+ lastId.value = response.id .value ;
228+ allocator.adoptFromCache (output, response.id , header::gSerializationMethodCCDB );
229+ }
230+ #if (FAIRMQ_VERSION_DEC >= 111000)
231+ result &= builder.second ->Append ();
232+ auto * value_builder = dynamic_cast <arrow::Int64Builder*>(builder.second ->value_builder ());
233+ result &= value_builder->Append (response.id .handle );
234+ result &= value_builder->Append (response.id .segment );
235+ result &= value_builder->Append (response.size );
236+ #else
181237 char const * address = reinterpret_cast <char const *>(response.id .value );
182- result &= builder->Append (std::string_view (address, response.size ));
238+ result &= builder.second ->Append (std::string_view (address, response.size ));
239+ #endif
240+ ++bi;
183241 }
184242 if (!result.ok ()) {
185243 LOGP (fatal, " Error adding results from CCDB" );
@@ -188,12 +246,9 @@ AlgorithmSpec AnalysisCCDBHelpers::fetchFromCCDB(ConfigContext const& /*ctx*/)
188246 }
189247 }
190248 arrow::ArrayVector arrays;
191- for (auto & builder : builders) {
192- arrays.push_back (*builder->Finish ());
193- }
249+ std::ranges::for_each (builders, [&arrays](auto & builder) { arrays.push_back (*builder.second ->Finish ()); });
194250 auto outTable = arrow::Table::Make (schema, arrays);
195- auto concrete = DataSpecUtils::asConcreteDataMatcher (spec);
196- allocator.adopt (Output{concrete.origin , concrete.description , concrete.subSpec }, outTable);
251+ allocator.adopt (output, outTable);
197252 }
198253
199254 stats.updateStats ({(int )ProcessingStatsId::CCDB_CACHE_FETCHED_BYTES , DataProcessingStats::Op::Set, (int64_t )helper->totalFetchedBytes });
0 commit comments