Project
Loading...
Searching...
No Matches
AODInputFile.cxx
Go to the documentation of this file.
1// Copyright 2019-2026 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
12#include "AODInputFile.h"
13#include "NativeAOD.h"
14#include "AODNative/Errors.h"
15#include "Framework/Logger.h"
16#include <TDirectory.h>
17#include <TFile.h>
18#include <TGrid.h>
19#include <TGridResult.h>
20#include <TKey.h>
21#include <TMap.h>
22#include <TObjString.h>
23#include <TUrl.h>
24#include <fmt/format.h>
25#include <chrono>
26#if __has_include(<TJAlienFile.h>)
27#include <TJAlienFile.h>
28#endif
29
30namespace o2::framework
31{
32
33std::shared_ptr<RootAODInputFile> RootAODInputFile::open(std::string const& name, RootObjectReadingFactory& factory, TFile* external)
34{
35 TFile* file = external ? external : TFile::Open(name.c_str());
36 if (!file || file->IsZombie()) {
37 if (file && !external) {
38 delete file;
39 }
40 return nullptr;
41 }
42 auto filesystem = std::make_shared<TFileFileSystem>(file, 50 * 1024 * 1024, factory, external == nullptr);
43 return std::shared_ptr<RootAODInputFile>(new RootAODInputFile(file, std::move(filesystem)));
44}
45
46RootAODInputFile::RootAODInputFile(TFile* file, std::shared_ptr<TFileFileSystem> filesystem)
47 : mFile(file), mFilesystem(std::move(filesystem))
48{
49}
50
51std::string RootAODInputFile::name() const { return mFile->GetName(); }
52uint64_t RootAODInputFile::size() const { return mFile->GetSize(); }
53uint64_t RootAODInputFile::bytesRead() const { return mFile->GetBytesRead(); }
54uint64_t RootAODInputFile::readCalls() const { return mFile->GetReadCalls(); }
55
56std::vector<AODInputFile::Key> RootAODInputFile::topLevelKeys()
57{
58 std::vector<Key> keys;
59 for (auto* obj : *mFile->GetListOfKeys()) {
60 auto* key = (TKey*)obj;
61 keys.push_back({key->GetName(), key->GetClassName()});
62 }
63 return keys;
64}
65
66std::vector<std::string> RootAODInputFile::keysIn(std::string const& dir)
67{
68 std::vector<std::string> names;
69 auto* d = (TDirectory*)mFile->GetObjectChecked(dir.c_str(), TClass::GetClass("TDirectory"));
70 if (!d) {
71 return names;
72 }
73 for (auto* key : *d->GetListOfKeys()) {
74 names.emplace_back(key->GetName());
75 }
76 return names;
77}
78
79std::map<std::string, std::string> RootAODInputFile::readStringMap(char const* key)
80{
81 std::map<std::string, std::string> result;
82 std::unique_ptr<TMap> map{(TMap*)mFile->Get(key)};
83 if (!map) {
84 return result;
85 }
86 map->SetOwnerKeyValue(true, true);
87 std::unique_ptr<TIterator> it{map->MakeIterator()};
88 while (auto* key = it->Next()) {
89 auto* value = (TObjString*)map->GetValue(key);
90 result[key->GetName()] = value ? value->String().Data() : "";
91 }
92 return result;
93}
94
95std::map<std::string, std::string> RootAODInputFile::parentFiles() { return readStringMap("parentFiles"); }
96std::map<std::string, std::string> RootAODInputFile::metaData() { return readStringMap("metaData"); }
97
99{
100#if __has_include(<TJAlienFile.h>)
101 if (auto* alienFile = dynamic_cast<TJAlienFile*>(mFile)) {
102 return fmt::format(",se={},open_time={:.1f}", alienFile->GetSE(), alienFile->GetElapsed());
103 }
104#endif
105 return "";
106}
107
108std::vector<GridReplica> gridReplicas(std::string const& lfn)
109{
110 TUrl url(lfn.c_str());
111 if (url.GetAnchor() && url.GetAnchor()[0] != '\0') {
112 return {};
113 }
114 if (!gGrid) {
115 TGrid::Connect("alien://");
116 }
117 if (!gGrid) {
118 return {};
119 }
120 // As TJAlienFile::Open does for reading.
121 std::unique_ptr<TGridResult> result(gGrid->Command(fmt::format("access read {}", url.GetFile()).c_str()));
122 if (!result) {
123 return {};
124 }
125 std::vector<GridReplica> replicas;
126 for (auto* object : *result) {
127 auto* map = dynamic_cast<TMap*>(object);
128 if (!map) {
129 continue;
130 }
131 auto value = [map](char const* key) -> std::string {
132 auto* v = map->GetValue(key);
133 return v ? v->GetName() : "";
134 };
135 auto pfn = value("url");
136 auto envelope = value("envelope");
137 if (pfn.empty() || envelope.empty() || pfn.find('#') != std::string::npos) {
138 continue;
139 }
140 replicas.push_back({pfn + "?&authz=" + envelope, value("se")});
141 }
142 return replicas;
143}
144
145std::shared_ptr<AODInputFile> openNativeAOD(std::string const& filename, RootObjectReadingFactory& factory, o2::aod::native::Options const& options)
146{
147 if (!filename.starts_with("alien://")) {
148 return NativeAODInputFile::open(filename, factory, options);
149 }
150 auto start = std::chrono::steady_clock::now();
151 auto replicas = gridReplicas(filename);
152 if (replicas.empty()) {
153 throw o2::aod::native::IoError(filename, "no replica the native reader can read");
154 }
155 // The file is read from the first replica which opens; a read error later on
156 // is retried and then continues on the next replica (FailoverByteSource).
157 std::vector<o2::aod::native::Replica> list;
158 for (auto const& replica : replicas) {
159 list.push_back({replica.url, replica.se});
160 }
161 auto source = o2::aod::native::ByteSource::openReplicas(std::move(list), options, [filename](std::string const& message) {
162 LOGP(info, "\"{}\": {}", filename, message);
163 });
164 auto se = source->replicaLabel();
165 auto file = NativeAODInputFile::open(std::move(source), factory, options, filename);
166 file->setGridInfo(se, std::chrono::duration<double>(std::chrono::steady_clock::now() - start).count());
167 return file;
168}
169
170} // namespace o2::framework
std::string url
std::vector< std::string > keys
StringRef key
static std::unique_ptr< ByteSource > openReplicas(std::vector< Replica > replicas, const Options &, std::function< void(std::string const &)> log={})
static std::shared_ptr< NativeAODInputFile > open(std::string const &url, RootObjectReadingFactory &factory, o2::aod::native::Options const &options, std::string const &name={})
An AO2D read with ROOT.
uint64_t size() const override
std::shared_ptr< VirtualRootFileSystemBase > filesystem() override
std::map< std::string, std::string > metaData() override
std::string monitoringDetails() const override
Extra key=value pairs for the file monitoring metrics, starting with a comma.
std::map< std::string, std::string > parentFiles() override
DF_<n> to parent file path. Empty if the file has no parentFiles.
std::string name() const override
uint64_t readCalls() const override
uint64_t bytesRead() const override
std::vector< std::string > keysIn(std::string const &dir) override
Names of the keys inside the top-level directory dir, empty if there is none.
static std::shared_ptr< RootAODInputFile > open(std::string const &name, RootObjectReadingFactory &factory, TFile *external=nullptr)
std::vector< Key > topLevelKeys() override
Top-level keys, in the order the file lists them, all cycles.
GLint GLsizei count
Definition glcorearb.h:399
GLuint64EXT * result
Definition glcorearb.h:5662
const GLdouble * v
Definition glcorearb.h:832
GLuint const GLchar * name
Definition glcorearb.h:781
GLsizei GLsizei GLchar * source
Definition glcorearb.h:798
GLsizei const GLfloat * value
Definition glcorearb.h:819
GLuint object
Definition glcorearb.h:4041
GLuint GLsizei const GLchar * message
Definition glcorearb.h:2517
Defining ITS Vertex explicitly as messageable.
Definition Cartesian.h:288
std::shared_ptr< AODInputFile > openNativeAOD(std::string const &filename, RootObjectReadingFactory &factory, o2::aod::native::Options const &options)
std::vector< GridReplica > gridReplicas(std::string const &lfn)
std::string filename()
Failure of the underlying transport.
Definition Errors.h:69