Skip to content

Commit cbcf123

Browse files
authored
Merge 5ea5aae into sapling-pr-archive-ktf
2 parents 8a792ec + 5ea5aae commit cbcf123

File tree

20 files changed

+328
-214
lines changed

20 files changed

+328
-214
lines changed

Detectors/Upgrades/ALICE3/TRK/reconstruction/CMakeLists.txt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ o2_add_library(TRKReconstruction
1818
SOURCES src/TimeFrame.cxx
1919
src/Clusterer.cxx
2020
$<$<BOOL:${Acts_FOUND}>:src/ClustererACTS.cxx>
21-
$<$<BOOL:${Acts_FOUND}>:src/TrackerACTS.cxx>
2221
PUBLIC_LINK_LIBRARIES
2322
O2::ITStracking
2423
O2::GPUCommon
@@ -46,8 +45,7 @@ set(dictHeaders include/TRKReconstruction/TimeFrame.h
4645
include/TRKReconstruction/Clusterer.h)
4746

4847
if(Acts_FOUND)
49-
list(APPEND dictHeaders include/TRKReconstruction/ClustererACTS.h
50-
include/TRKReconstruction/TrackerACTS.h)
48+
list(APPEND dictHeaders include/TRKReconstruction/ClustererACTS.h)
5149
endif()
5250

5351
o2_target_root_dictionary(TRKReconstruction

Framework/AODMerger/src/aodMerger.cxx

Lines changed: 41 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ int main(int argc, char* argv[])
3838
long maxDirSize = 100000000;
3939
bool skipNonExistingFiles = false;
4040
bool skipParentFilesList = false;
41+
bool mergeByName = false;
4142
int verbosity = 2;
4243
int exitCode = 0; // 0: success, >0: failure
4344
int compression = 505;
@@ -50,6 +51,7 @@ int main(int argc, char* argv[])
5051
{"skip-non-existing-files", no_argument, nullptr, 3},
5152
{"skip-parent-files-list", no_argument, nullptr, 4},
5253
{"compression", required_argument, nullptr, 5},
54+
{"merge-by-name", no_argument, nullptr, 6},
5355
{"verbosity", required_argument, nullptr, 'v'},
5456
{"help", no_argument, nullptr, 'h'},
5557
{nullptr, 0, nullptr, 0}};
@@ -70,6 +72,8 @@ int main(int argc, char* argv[])
7072
skipParentFilesList = true;
7173
} else if (c == 5) {
7274
compression = atoi(optarg);
75+
} else if (c == 6) {
76+
mergeByName = true;
7377
} else if (c == 'v') {
7478
verbosity = atoi(optarg);
7579
} else if (c == 'h') {
@@ -80,6 +84,7 @@ int main(int argc, char* argv[])
8084
printf(" --skip-non-existing-files Flag to allow skipping of non-existing files in the input list.\n");
8185
printf(" --skip-parent-files-list Flag to allow skipping the merging of the parent files list.\n");
8286
printf(" --compression <root compression id> Compression algorithm / level to use (default: %d)\n", compression);
87+
printf(" --merge-by-name Only merge TTrees from folders with the same name.\n");
8388
printf(" --verbosity <flag> Verbosity of output (default: %d).\n", verbosity);
8489
return -1;
8590
} else {
@@ -94,6 +99,9 @@ int main(int argc, char* argv[])
9499
if (skipNonExistingFiles) {
95100
printf(" WARNING: Skipping non-existing files.\n");
96101
}
102+
if (mergeByName) {
103+
printf(" Merging only folders with the same name.\n");
104+
}
97105

98106
std::map<std::string, TTree*> trees;
99107
std::map<std::string, uint64_t> sizeCompressed;
@@ -112,6 +120,28 @@ int main(int argc, char* argv[])
112120
TMap* parentFiles = nullptr;
113121
int totalMergedDFs = 0;
114122
int mergedDFs = 0;
123+
124+
// Write all accumulated trees to outputDir, update stats, and clean up state.
125+
auto flushTrees = [&](bool resetState) {
126+
if (!outputDir) {
127+
return;
128+
}
129+
for (auto const& tree : trees) {
130+
outputDir->cd();
131+
tree.second->Write();
132+
sizeCompressed[tree.first] += tree.second->GetZipBytes();
133+
sizeUncompressed[tree.first] += tree.second->GetTotBytes();
134+
delete tree.second;
135+
}
136+
if (resetState) {
137+
outputDir = nullptr;
138+
trees.clear();
139+
offsets.clear();
140+
mergedDFs = 0;
141+
currentDirSize = 0;
142+
}
143+
};
144+
115145
while (in.good() && exitCode == 0) {
116146
in >> line;
117147

@@ -182,6 +212,14 @@ int main(int argc, char* argv[])
182212

183213
auto dfName = ((TObjString*)key1)->GetString().Data();
184214

215+
// If merge-by-name is active, flush accumulated trees when the folder name changes
216+
if (mergeByName && outputDir && std::string(outputDir->GetName()) != std::string(dfName)) {
217+
if (verbosity > 0) {
218+
printf("Folder name changed: closing folder %s.\n", outputDir->GetName());
219+
}
220+
flushTrees(true);
221+
}
222+
185223
if (verbosity > 0) {
186224
printf(" Processing folder %s\n", dfName);
187225
}
@@ -396,21 +434,7 @@ int main(int argc, char* argv[])
396434
if (verbosity > 0) {
397435
printf("Maximum size reached: %ld. Closing folder %s.\n", currentDirSize, dfName);
398436
}
399-
for (auto const& tree : trees) {
400-
// printf("Writing %s\n", tree.first.c_str());
401-
outputDir->cd();
402-
tree.second->Write();
403-
404-
// stats
405-
sizeCompressed[tree.first] += tree.second->GetZipBytes();
406-
sizeUncompressed[tree.first] += tree.second->GetTotBytes();
407-
408-
delete tree.second;
409-
}
410-
outputDir = nullptr;
411-
trees.clear();
412-
offsets.clear();
413-
mergedDFs = 0;
437+
flushTrees(true);
414438
}
415439
}
416440
inputFile->Close();
@@ -421,16 +445,7 @@ int main(int argc, char* argv[])
421445
parentFiles->Write("parentFiles", TObject::kSingleKey);
422446
}
423447

424-
for (auto const& tree : trees) {
425-
outputDir->cd();
426-
tree.second->Write();
427-
428-
// stats
429-
sizeCompressed[tree.first] += tree.second->GetZipBytes();
430-
sizeUncompressed[tree.first] += tree.second->GetTotBytes();
431-
432-
delete tree.second;
433-
}
448+
flushTrees(false);
434449

435450
outputFile->Write();
436451
outputFile->Close();
@@ -462,4 +477,4 @@ int main(int argc, char* argv[])
462477
printf("\n");
463478

464479
return exitCode;
465-
}
480+
}

Framework/Core/include/Framework/DataModelViews.h

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "DomainInfoHeader.h"
1717
#include "SourceInfoHeader.h"
1818
#include "Headers/DataHeader.h"
19+
#include "Framework/DataRef.h"
1920
#include "Framework/TimesliceSlot.h"
2021
#include <ranges>
2122
#include <span>
@@ -80,10 +81,7 @@ struct count_parts {
8081
}
8182
};
8283

83-
struct DataRefIndices {
84-
size_t headerIdx;
85-
size_t payloadIdx;
86-
};
84+
// DataRefIndices is defined in Framework/DataRef.h
8785

8886
struct get_pair {
8987
size_t pairId;
@@ -127,6 +125,43 @@ struct get_pair {
127125
}
128126
};
129127

128+
// Advance from a DataRefIndices to the next one in O(1), reading only the
129+
// current header. Intended for use in iterators so that ++ is O(1) rather
130+
// than the O(n) while-loop that get_pair requires.
131+
//
132+
// New-style block (splitPayloadIndex == splitPayloadParts > 1):
133+
// layout: [header, payload_0, payload_1, ..., payload_{N-1}]
134+
// advance within block while payloads remain, then jump to the next block.
135+
//
136+
// Old-style block (splitPayloadIndex != splitPayloadParts, splitPayloadParts > 1)
137+
// or single pair (splitPayloadParts == 0):
138+
// layout: [header, payload] – always advance by two messages.
139+
struct get_next_pair {
140+
DataRefIndices current;
141+
template <typename R>
142+
requires std::ranges::random_access_range<R> && std::ranges::sized_range<R>
143+
friend DataRefIndices operator|(R&& r, get_next_pair self)
144+
{
145+
size_t hIdx = self.current.headerIdx;
146+
auto* header = o2::header::get<o2::header::DataHeader*>(r[hIdx]->GetData());
147+
if (!header) {
148+
throw std::runtime_error("Not a DataHeader");
149+
}
150+
if (header->splitPayloadParts > 1 && header->splitPayloadIndex == header->splitPayloadParts) {
151+
// New-style block: one header followed by splitPayloadParts contiguous payloads.
152+
if (self.current.payloadIdx < hIdx + header->splitPayloadParts) {
153+
// More sub-payloads remain in this block.
154+
return {hIdx, self.current.payloadIdx + 1};
155+
}
156+
// Last sub-payload consumed; move to the first pair of the next block.
157+
size_t nextHIdx = hIdx + header->splitPayloadParts + 1;
158+
return {nextHIdx, nextHIdx + 1};
159+
}
160+
// Old-style [header, payload] pairs or a single pair: advance by two messages.
161+
return {hIdx + 2, hIdx + 3};
162+
}
163+
};
164+
130165
struct get_dataref_indices {
131166
size_t part;
132167
size_t subPart;

Framework/Core/include/Framework/DataRef.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#define FRAMEWORK_DATAREF_H
1313

1414
#include <cstddef> // for size_t
15+
#include <compare>
1516

1617
namespace o2
1718
{
@@ -29,6 +30,15 @@ struct DataRef {
2930
size_t payloadSize = 0;
3031
};
3132

33+
/// Raw indices into the message vector for one (header, payload) pair.
34+
/// Kept in a lightweight header so InputSpan can use it without pulling in FairMQ.
35+
struct DataRefIndices {
36+
size_t headerIdx;
37+
size_t payloadIdx;
38+
bool operator==(const DataRefIndices&) const = default;
39+
auto operator<=>(const DataRefIndices&) const = default;
40+
};
41+
3242
} // namespace framework
3343
} // namespace o2
3444

Framework/Core/include/Framework/InputRecord.h

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
#include "Framework/DataRef.h"
1515
#include "Framework/DataRefUtils.h"
16+
#include "Framework/InputSpan.h"
1617
#include "Framework/InputRoute.h"
1718
#include "Framework/TypeTraits.h"
1819
#include "Framework/TableConsumer.h"
@@ -202,6 +203,15 @@ class InputRecord
202203

203204
[[nodiscard]] size_t getNofParts(int pos) const;
204205

206+
/// O(1) access to the part described by @a indices in slot @a pos.
207+
[[nodiscard]] DataRef getAtIndices(int pos, DataRefIndices indices) const;
208+
209+
/// O(1) advance from @a current to the next part's indices in slot @a pos.
210+
[[nodiscard]] DataRefIndices nextIndices(int pos, DataRefIndices current) const
211+
{
212+
return mSpan.nextIndices(pos, current);
213+
}
214+
205215
// Given a binding by string, return the associated DataRef
206216
DataRef getDataRefByString(const char* bindingName, int part = 0) const
207217
{
@@ -568,8 +578,8 @@ class InputRecord
568578

569579
Iterator() = delete;
570580

571-
Iterator(ParentType const* parent, size_t position = 0, size_t size = 0)
572-
: mPosition(position), mSize(size > position ? size : position), mParent(parent), mElement{nullptr, nullptr, nullptr}
581+
Iterator(ParentType const* parent, bool isEnd = false)
582+
: mPosition(isEnd ? parent->size() : 0), mSize(parent->size()), mParent(parent), mElement{nullptr, nullptr, nullptr}
573583
{
574584
if (mPosition < mSize) {
575585
if (mParent->isValid(mPosition)) {
@@ -678,18 +688,29 @@ class InputRecord
678688
using reference = typename BaseType::reference;
679689
using pointer = typename BaseType::pointer;
680690
using ElementType = typename std::remove_const<value_type>::type;
681-
using iterator = Iterator<SelfType, T>;
682-
using const_iterator = Iterator<SelfType, const T>;
691+
using iterator = InputSpan::Iterator<SelfType, T>;
692+
using const_iterator = InputSpan::Iterator<SelfType, const T>;
693+
694+
InputRecordIterator(InputRecord const* parent, bool isEnd = false)
695+
: BaseType(parent, isEnd)
696+
{
697+
}
698+
699+
/// Initial indices for part-level iteration: first part starts at {headerIdx=0, payloadIdx=1}.
700+
[[nodiscard]] DataRefIndices initialIndices() const { return {0, 1}; }
701+
/// Sentinel used by nextIndicesGetter to signal end-of-slot.
702+
[[nodiscard]] DataRefIndices endIndices() const { return {size_t(-1), size_t(-1)}; }
683703

684-
InputRecordIterator(InputRecord const* parent, size_t position = 0, size_t size = 0)
685-
: BaseType(parent, position, size)
704+
/// Get element at the given raw message indices in O(1).
705+
[[nodiscard]] ElementType getAtIndices(DataRefIndices indices) const
686706
{
707+
return this->parent()->getAtIndices(this->position(), indices);
687708
}
688709

689-
/// Get element at {slotindex, partindex}
690-
[[nodiscard]] ElementType getByPos(size_t pos) const
710+
/// Advance @a current to the next part's indices in O(1).
711+
[[nodiscard]] DataRefIndices nextIndices(DataRefIndices current) const
691712
{
692-
return this->parent()->getByPos(this->position(), pos);
713+
return this->parent()->nextIndices(this->position(), current);
693714
}
694715

695716
/// Check if slot is valid, index of part is not used
@@ -709,12 +730,12 @@ class InputRecord
709730

710731
[[nodiscard]] const_iterator begin() const
711732
{
712-
return const_iterator(this, 0, size());
733+
return const_iterator(this, size() == 0);
713734
}
714735

715736
[[nodiscard]] const_iterator end() const
716737
{
717-
return const_iterator(this, size());
738+
return const_iterator(this, true);
718739
}
719740
};
720741

@@ -723,12 +744,12 @@ class InputRecord
723744

724745
[[nodiscard]] const_iterator begin() const
725746
{
726-
return {this, 0, size()};
747+
return {this, false};
727748
}
728749

729750
[[nodiscard]] const_iterator end() const
730751
{
731-
return {this, size()};
752+
return {this, true};
732753
}
733754

734755
InputSpan& span()

0 commit comments

Comments
 (0)