Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion roottest/root/ntuple/evolution/NtplEvolv_v3_LinkDef.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#pragma link C++ class NtplEvolv+;

#pragma read sourceClass="NtplEvolv" version="[1-]" source="" targetClass="NtplEvolv" target="fA" code = "{ fA = 13; }"
#pragma read sourceClass="NtplEvolv" version="[1-]" source="int fA;" targetClass="NtplEvolv" target="fA" \
code = "{ fA = onfile.fA + 13; }"

#endif
25 changes: 24 additions & 1 deletion roottest/root/ntuple/evolution/read_ntplevolv.cxx
Original file line number Diff line number Diff line change
@@ -1,17 +1,40 @@
#include <ROOT/RNTupleReader.hxx>

#include <TObject.h>
#include <TROOT.h>
#include <TSeqCollection.h>

#include "NtplEvolv_v3.hxx"

#include <iostream>
#include <string>

int main()
{
// At this point, we expect NtplEvolv _not_ being present in the global streamer infos
for (auto si : TRangeDynCast<TObject>(gROOT->GetListOfStreamerInfo())) {
if (std::string(si->GetName()) == "NtplEvolv")
return 2;
}

auto reader = ROOT::RNTupleReader::Open("ntpl", "root_test_ntpl_evolution.root");

reader->GetModel();
// Now, reader should have loaded the streamer info for NtplEvolv
bool streamerInfoFound = false;
for (auto si : TRangeDynCast<TObject>(gROOT->GetListOfStreamerInfo())) {
if (std::string(si->GetName()) == "NtplEvolv") {
streamerInfoFound = true;
break;
}
}
if (!streamerInfoFound)
return 3;

reader->LoadEntry(0);

auto a = reader->GetModel().GetDefaultEntry().GetPtr<NtplEvolv>("event")->fA;
std::cout << "Result of event.fA: " << a << std::endl;

return a != 13;
return a != 14;
}
38 changes: 38 additions & 0 deletions roottest/root/ntuple/unversioned/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
ROOTTEST_GENERATE_DICTIONARY(
ntplhit_old_dict
${CMAKE_CURRENT_SOURCE_DIR}/NtplHit_Old.hxx
LINKDEF ${CMAKE_CURRENT_SOURCE_DIR}/NtplHit_Old_LinkDef.h
NO_ROOTMAP NO_CXXMODULE
FIXTURES_SETUP generated_ntplhit_old_dictionary
)

ROOTTEST_GENERATE_EXECUTABLE(
write_ntplhit
write_ntplhit.cxx ntplhit_old_dict.cxx
LIBRARIES Core RIO ROOTNTuple
FIXTURES_REQUIRED generated_ntplhit_old_dictionary
FIXTURES_SETUP write_ntplhit_excutable)

ROOTTEST_ADD_TEST(write_ntplhit
EXEC ./write_ntplhit
FIXTURES_REQUIRED write_ntplhit_excutable
FIXTURES_SETUP write_ntplhit_done)

ROOTTEST_GENERATE_DICTIONARY(
ntplhit_new_dict
${CMAKE_CURRENT_SOURCE_DIR}/NtplHit_New.hxx
LINKDEF ${CMAKE_CURRENT_SOURCE_DIR}/NtplHit_New_LinkDef.h
NO_ROOTMAP NO_CXXMODULE
FIXTURES_SETUP generated_ntplhit_new_dictionary
)

ROOTTEST_GENERATE_EXECUTABLE(
read_ntplhit
read_ntplhit.cxx ntplhit_new_dict.cxx
LIBRARIES Core RIO ROOTNTuple
FIXTURES_REQUIRED generated_ntplhit_new_dictionary
FIXTURES_SETUP read_ntplhit_excutable)

ROOTTEST_ADD_TEST(read_ntplhit
EXEC ./read_ntplhit
FIXTURES_REQUIRED read_ntplhit_excutable write_ntplhit_done)
11 changes: 11 additions & 0 deletions roottest/root/ntuple/unversioned/NtplHit_New.hxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#ifndef NTPL_HIT_NEW_H
#define NTPL_HIT_NEW_H

struct Hit {
int fA_r{0};
int fB_r{0};
double fX_r{0};
double fY_r{0};
};

#endif // NTPL_HIT_NEW_H
9 changes: 9 additions & 0 deletions roottest/root/ntuple/unversioned/NtplHit_New_LinkDef.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#ifdef __ROOTCLING__

#pragma link C++ class Hit+;

#pragma read sourceClass="Hit" targetClass="Hit" checksum="[2391364433]" \
source="int fA; int fB; double fX; double fY" target="fA_r,fB_r,fX_r,fY_r" \
code="{ fA_r = onfile.fA; fB_r = onfile.fB; fX_r = onfile.fX; fY_r = onfile.fY; }"

#endif
11 changes: 11 additions & 0 deletions roottest/root/ntuple/unversioned/NtplHit_Old.hxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#ifndef NTPL_HIT_OLD_H
#define NTPL_HIT_OLD_H

struct Hit {
int fA{0};
int fB{0};
double fX{0};
double fY{0};
};

#endif // NTPL_HIT_OLD_H
5 changes: 5 additions & 0 deletions roottest/root/ntuple/unversioned/NtplHit_Old_LinkDef.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#ifdef __ROOTCLING__

#pragma link C++ class Hit+;

#endif
31 changes: 31 additions & 0 deletions roottest/root/ntuple/unversioned/read_ntplhit.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#include <ROOT/RNTupleReader.hxx>

#include <cstdio>
#include <vector>

#include "NtplHit_New.hxx"

static int gFails = 0;

static void Check(char const *m, double want, double got)
{
bool ok = want == got;
if (!ok)
++gFails;
printf("%-4s want %-4g got %-22.17g %s\n", m, want, got, ok ? "ok" : "WRONG");
}

int main()
{
auto r = ROOT::RNTupleReader::Open("r", "root_test_ntpl_unversioned.root");
auto v = r->GetModel().GetDefaultEntry().GetPtr<std::vector<Hit>>("hits");

r->LoadEntry(0);

Check("fA_r", 1, v->at(0).fA_r);
Check("fB_r", 2, v->at(0).fB_r);
Check("fX_r", 1.5, v->at(0).fX_r);
Check("fY_r", 2.5, v->at(0).fY_r);

return gFails;
}
25 changes: 25 additions & 0 deletions roottest/root/ntuple/unversioned/write_ntplhit.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include <ROOT/RNTupleModel.hxx>
#include <ROOT/RNTupleWriter.hxx>

#include <TClass.h>

#include <cstdio>
#include <vector>

#include "NtplHit_Old.hxx"

int main()
{
Hit h;
h.fA = 1;
h.fB = 2;
h.fX = 1.5;
h.fY = 2.5;
auto model = ROOT::RNTupleModel::Create();
auto pv = model->MakeField<std::vector<Hit>>("hits");
auto w = ROOT::RNTupleWriter::Recreate(std::move(model), "r", "root_test_ntpl_unversioned.root");
*pv = {h};
w->Fill();
printf("CHECKSUM %u\n", TClass::GetClass("Hit")->GetCheckSum());
return 0;
}
2 changes: 2 additions & 0 deletions tree/ntuple/inc/ROOT/RPageStorageFile.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@ private:
RNTupleDescriptorBuilder fDescriptorBuilder;
/// Tracks the last read offset for seek distance calculation
std::uint64_t fLastOffset = 0;
/// Set to true after the first call to LoadStreamerInfo()
bool fHasStreamerInfo = false;

/// File-specific I/O performance counters
struct RFileCounters {
Expand Down
18 changes: 17 additions & 1 deletion tree/ntuple/src/RFieldMeta.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -552,7 +552,23 @@ std::unique_ptr<ROOT::RFieldBase> ROOT::RClassField::BeforeConnectPageSource(ROO
// A staging class (conversion streamer info) only exists if there is at least one rule that has an
// on disk source member defined.
if (hasSources) {
SetStagingClass(fieldDesc.GetTypeName(), fieldDesc.GetTypeVersion());
// For unversioned classes, the in-memory layout may by chance have the same transient version number
// than the recorded (transient, at the time of writing) on-disk version. Therefore, we also need to compare
// the checksums to find out if we need a conversion streamer info.
std::uint32_t assignedVersionForOnDiskLayout = fieldDesc.GetTypeVersion();
R__ASSERT(fieldDesc.GetTypeChecksum());
if (fieldDesc.GetTypeVersion() != GetTypeVersion() || *fieldDesc.GetTypeChecksum() != fClass->GetCheckSum() ||
fieldDesc.GetTypeName() != GetTypeName()) {
// We need the on-disk streamer info for the conversion streamer info
pageSource.LoadStreamerInfo();

auto oldCl = TClass::GetClass(fieldDesc.GetTypeName().c_str());
R__ASSERT(oldCl);
auto onDiskStreamerInfo = oldCl->FindStreamerInfo(*fieldDesc.GetTypeChecksum());
R__ASSERT(onDiskStreamerInfo);
assignedVersionForOnDiskLayout = onDiskStreamerInfo->GetClassVersion();
}
SetStagingClass(fieldDesc.GetTypeName(), assignedVersionForOnDiskLayout);
PrepareStagingArea(rules, desc, fieldDesc);
for (auto &[_, si] : fStagingItems) {
Internal::CallConnectPageSourceOnField(*si.fField, pageSource);
Expand Down
5 changes: 5 additions & 0 deletions tree/ntuple/src/RPageStorageFile.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,7 @@ std::unique_ptr<ROOT::Internal::RPageSource> ROOT::Internal::RPageSourceFile::Cl
auto clone = new RPageSourceFile(fNTupleName, fOptions);
clone->fFile = fFile->Clone();
clone->fReader = ROOT::Internal::RMiniFileReader(clone->fFile.get());
clone->fHasStreamerInfo = fHasStreamerInfo;
return std::unique_ptr<RPageSourceFile>(clone);
}

Expand Down Expand Up @@ -714,5 +715,9 @@ ROOT::Internal::RPageSourceFile::LoadClusters(std::span<RCluster::RKey> clusterK

void ROOT::Internal::RPageSourceFile::LoadStreamerInfo()
{
if (fHasStreamerInfo)
return;

fReader.LoadStreamerInfo();
fHasStreamerInfo = true;
}
Loading