27 if (options.bufferBudget == Options::kAutoBufferBudget) {
28 options.bufferBudget = (
file.source().isRemote() ? 64 : 16) *
size_t{1024 * 1024};
35 : mFile(
std::move(file)), mOptions(withBudget(options, *mFile)), mObjectFactory(factory), mPool(
std::make_shared<
ReadBufferPool>(mOptions.bufferBudget))
42std::pair<std::string, std::string> splitTreePath(std::string
const&
path)
44 size_t start =
path.starts_with(
"/") ? 1 : 0;
46 if (slash == std::string::npos) {
55 auto [df, treeName] = splitTreePath(
path);
59 std::lock_guard lock{mMutex};
60 return findTree(df, treeName);
65 auto [df, treeName] = splitTreePath(
path);
69 std::lock_guard lock{mMutex};
70 if (mFile->source().canMap()) {
75 auto previous = std::move(mPlanTrees);
83 if (mAdoptedDF == df) {
84 mPlan = std::move(mAdoptedPlan);
85 for (
auto&
name : mAdoptedTrees) {
86 mPlanOf[
name] = mPlan;
91 mPlanTrees = std::move(mAdoptedTrees);
93 mPlan = std::make_shared<ReadPlan>(mFile->sourcePtr(), mOptions, mPool);
96 auto trees = previous;
97 if (std::ranges::find(trees, treeName) == trees.end()) {
98 trees.push_back(treeName);
100 if (!previous.empty()) {
101 mFile->setTreesToPrefetch(trees);
103 for (
auto&
name : previous) {
107 if (!previous.empty() && mFile->source().isRemote() && mOptions.
prefetchDepth > 0) {
108 startLookahead(df, std::move(trees));
114 auto it = mPlanOf.find(treeName);
115 if (it == mPlanOf.end()) {
118 auto plan = std::move(it->second);
123void NativeAODFileSystem::releaseMappedDF(std::string
const& df)
125 if (df == mMappedDF) {
131 uint64_t begin = UINT64_MAX;
133 for (
auto it = mTrees.lower_bound(mMappedDF +
"/"); it != mTrees.end() && it->first.starts_with(mMappedDF +
"/"); ++it) {
134 for (
auto const& branch : it->second->
tree.branches) {
135 for (
auto const& basket : branch.baskets) {
136 if (!basket.embedded && basket.nbytes > 0) {
137 begin = std::min(begin, basket.seek);
138 end = std::max(
end, basket.seek + basket.nbytes);
143 if (!mMappedDF.empty() && begin <
end) {
144 mFile->source().dontNeed(begin,
end - begin);
149void NativeAODFileSystem::adoptLookahead(std::string
const& df)
151 if (!mLookahead.valid() || mLookaheadDF != df) {
154 auto lookahead = mLookahead.get();
158 mDirectories.emplace(df, std::move(lookahead->keys));
160 mAdoptedPlan = lookahead->plan;
161 mAdoptedTrees.clear();
162 for (
auto& [
name,
tree] : lookahead->trees) {
164 mTrees.emplace(df +
"/" +
name, std::make_unique<NativeTreeHandle>(
NativeTreeHandle{std::move(
tree), mFile->sourcePtr(), mOptions}));
165 mAdoptedTrees.push_back(
name);
169std::vector<KeyInfo>
const& NativeAODFileSystem::directory(std::string
const& df)
171 if (
auto it = mDirectories.find(df); it != mDirectories.end()) {
175 if (
auto it = mDirectories.find(df); it != mDirectories.end()) {
178 return mDirectories.emplace(df, mFile->keysOf(df)).
first->second;
183 std::lock_guard lock{mMutex};
184 return directory(df);
189 std::lock_guard lock{mMutex};
190 mDataFrames = std::move(dfs);
193void NativeAODFileSystem::startLookahead(std::string
const& afterDF, std::vector<std::string> trees)
195 if (mDataFrames.empty()) {
196 mDataFrames = mFile->dataFrames();
198 if (!mLookaheadFile) {
199 mLookaheadFile = std::make_shared<RootFile>(*mFile);
201 auto it = std::ranges::find(mDataFrames, afterDF);
202 if (it == mDataFrames.end() || ++it == mDataFrames.end()) {
207 mLookahead = std::async(std::launch::async, [
file = mLookaheadFile, df = *it, trees = std::move(trees), options = mOptions, pool = mPool]() -> std::optional<Lookahead> {
209 Lookahead lookahead{df, {}, {}, std::make_shared<ReadPlan>(
file->
sourcePtr(), options, pool)};
214 for (
auto const&
name : trees) {
215 for (
auto const&
key : lookahead.
keys) {
216 if (
key.name ==
name &&
key.className ==
"TTree") {
219 if (options.bufferBudget > 0 &&
bytes > 0 &&
bytes + treeBytes > options.bufferBudget) {
220 lookahead.plan->fetch();
224 lookahead.trees.emplace_back(
name, std::move(
tree));
225 lookahead.plan->add(lookahead.trees.back().second);
229 lookahead.plan->fetch();
231 }
catch (std::exception
const&) {
237void NativeAODFileSystem::addToPlan(std::string
const& treeName)
239 if (std::ranges::find(mPlanTrees, treeName) != mPlanTrees.end()) {
244 handle = findTree(mPlanDF, treeName);
245 }
catch (std::exception
const&) {
251 mPlan = std::make_shared<ReadPlan>(mFile->sourcePtr(), mOptions, mPool);
256 mPlanOf[treeName] = mPlan;
257 mPlanTrees.push_back(treeName);
261NativeTreeHandle* NativeAODFileSystem::findTree(std::string
const& df, std::string
const& treeName)
263 auto path = df +
"/" + treeName;
264 if (
auto it = mTrees.find(
path); it != mTrees.end()) {
265 return it->second.get();
267 if (!mDirectories.contains(df)) {
269 for (
auto& k : mFile->topKeys()) {
270 exists |= k.name == df;
276 for (
auto&
key : directory(df)) {
277 if (
key.name == treeName &&
key.className ==
"TTree") {
279 return mTrees.emplace(
path, std::move(
handle)).first->second.get();
288 if (capability.name !=
"native-ttree") {
291 auto objectPath = capability.lfn2objectPath(
source.path());
292 void*
handle = capability.getHandle(shared_from_this(), objectPath);
296 return std::make_shared<RootObjectHandler>(
handle, capability.factory().format());
304 if (capability.name ==
"native-ttree" && capability.getHandle(shared_from_this(), capability.lfn2objectPath(
source.path()))) {
313 arrow::fs::FileInfo
result;
315 result.set_type(arrow::fs::FileType::NotFound);
316 for (
auto& k : mFile->topKeys()) {
317 if (k.name ==
path) {
318 result.set_type(k.className ==
"TTree" ? arrow::fs::FileType::File : arrow::fs::FileType::Directory);
323 result.set_type(arrow::fs::FileType::File);
337 result->mFile = std::make_shared<RootFile>(std::move(
source));
338 result->mFilesystem = std::make_shared<NativeAODFileSystem>(
result->mFile, options, factory);
340 result->mParentFiles =
result->mFile->readStringMap(
"parentFiles");
341 result->mMetaData =
result->mFile->readStringMap(
"metaData");
344 auto dfs =
result->mFile->dataFrames();
346 for (
auto&
key :
result->mFile->keysOf(dfs.front())) {
347 if (
key.className ==
"TTree") {
348 result->mFilesystem->getTreeHandle(dfs.front() +
"/" +
key.name);
358 mOpenTime = openTime;
367 std::snprintf(openTime,
sizeof(openTime),
"%.1f", mOpenTime);
368 return ",se=" + mSE +
",open_time=" + openTime;
377 std::vector<Key>
keys;
378 for (
auto& k : mFile->topKeys()) {
379 keys.push_back({k.name, k.className});
386 std::vector<std::string> names;
387 for (
auto& k : mFile->topKeys()) {
388 if (k.name == dir && (k.className ==
"TDirectoryFile" || k.className ==
"TDirectory")) {
389 for (
auto&
key : mFilesystem->keysOf(dir)) {
390 names.push_back(
key.name);
std::vector< std::string > keys
static std::unique_ptr< ByteSource > open(std::string url, const Options &)
static uint64_t bytesOf(TreeInfo const &tree)
The bytes add(tree) registers.
TreeInfo readTree(const KeyInfo &)
std::shared_ptr< ByteSource > const & sourcePtr() const
void setTreesToPrefetch(std::vector< std::string > names)
The TTrees whose bytes keysOf() fetches along; all of them when empty.
std::vector< KeyInfo > keysOf(const std::string &df)
std::vector< o2::aod::native::KeyInfo > keysOf(std::string const &df)
The keys of DF df, read once (or prepared ahead) for all users.
void setReadOrder(std::vector< std::string > dfs)
arrow::Result< arrow::fs::FileInfo > GetFileInfo(const std::string &path) override
std::shared_ptr< o2::aod::native::ReadPlan > planFor(std::string const &path)
bool CheckSupport(arrow::dataset::FileSource source) override
o2::aod::native::RootFile & file()
NativeTreeHandle * getTreeHandle(std::string const &path)
NativeAODFileSystem(std::shared_ptr< o2::aod::native::RootFile > file, o2::aod::native::Options options, RootObjectReadingFactory &factory)
std::string const & name() const
std::shared_ptr< RootObjectHandler > GetObjectHandler(arrow::dataset::FileSource source) override
GLuint const GLchar * name
GLsizei GLsizei GLchar * source
GLsizei const GLchar *const * path
Defining ITS Vertex explicitly as messageable.
RuntimeErrorRef runtime_error_f(const char *,...)
int32_t const char * file
std::vector< RootObjectReadingCapability > capabilities
std::unique_ptr< TTree > tree((TTree *) flIn.Get(std::string(o2::base::NameConf::CTFTREENAME).c_str()))