25 #include <TBranchElement.h>
29 #include <TStreamerElement.h>
30 #include <TStreamerInfo.h>
33 #include <TVirtualCollectionProxy.h>
44 bool isPrimitiveBranch(TBranch&
br) {
47 ::TClass*
cl =
nullptr;
48 ::EDataType dType = kOther_t;
51 if (
br.GetExpectedType(
cl, dType)) {
60 return ((dType != kOther_t) && (dType != kNoType_t) && (dType != kVoid_t));
89 ::TClass*
cl =
nullptr;
90 ::EDataType dType = kOther_t;
93 if (
br.GetExpectedType(
cl, dType)) {
95 XAOD_MESSAGE(
"Couldn't determine the type of branch \"%s\""),
108 const std::type_info* root_ti =
cl->GetTypeInfo();
116 typeName.ReplaceAll(
"basic_string<char>",
"string");
117 ::TClass* newCl = ::TClass::GetClass(
typeName);
119 root_ti = newCl->GetTypeInfo();
124 XAOD_MESSAGE(
"Couldn't get an std::type_info object out of "
125 "branch \"%s\" of type \"%s\""),
126 br.GetName(),
cl->GetName());
131 const std::type_info* aux_obj_ti =
137 static_cast<int>(auxid));
140 const std::type_info* aux_vec_ti =
146 static_cast<int>(auxid));
151 if (*root_ti == *aux_obj_ti) {
154 }
else if (*root_ti == *aux_vec_ti) {
162 if (
cl->GetCollectionProxy() && (*aux_vec_ti ==
typeid(std::vector<int>))) {
168 if (*cl2->GetTypeInfo() == *aux_vec_ti) {
184 aux_vec_cl->GetConversionStreamerInfo(
cl,
cl->GetClassVersion())) {
190 aux_obj_cl->GetConversionStreamerInfo(
cl,
cl->GetClassVersion())) {
196 XAOD_MESSAGE(
"Couldn't determine if branch describes a single "
197 "object or a container"));
212 class TBranchHandle {
216 TBranchHandle(
bool staticBranch,
bool primitiveBranch,
222 m_static(staticBranch),
223 m_primitive(primitiveBranch),
251 if (!m_branch->GetTree()) {
253 "xAOD::TAuxStore::TBranchHandle::getEntry",
254 XAOD_MESSAGE(
"Branch=%s is not associated to any tree while reading "
255 "of branches within this class relies on that"),
256 m_branch->GetName());
266 ::Long64_t
entry = m_branch->GetTree()->GetReadEntry();
274 Error(
"xAOD::TAuxStore::TBranchHandle::getEntry",
276 "Entry to read is not set for branch=%s from tree=%s. "
277 "It is either because TTree::LoadTree(entry) was not called "
278 "beforehand in the TEvent class OR "
279 "the entry requested to be read for the main tree is not "
280 "corresponding to an event for the friend tree"),
281 m_branch->GetName(), m_branch->GetTree()->GetName());
286 if ((
entry == m_entry) && (!m_needsRead)) {
292 if ((m_branch->GetMakeClass() != m_static) &&
293 (!m_branch->SetMakeClass(m_static))) {
294 ::Error(
"xAOD::TAuxStore::TBranchHandle::getEntry",
297 static_cast<int>(m_static), m_branch->GetName());
303 const ::Int_t nbytes = m_branch->GetEntry(
entry);
324 ::TBranch** branchPtr() {
return &m_branch; }
334 void* objectPtr() {
return m_object; }
353 void* inputObjectPtr() {
355 if (m_static || m_primitive) {
372 void* outputObjectPtr() {
381 const std::type_info* typeInfo()
const {
return m_typeInfo; }
395 void reset() { m_needsRead =
true; }
409 const std::type_info* m_typeInfo;
415 std::string_view m_prefix;
447 return StatusCode::SUCCESS;
452 return StatusCode::SUCCESS;
459 for (Int_t
i = 0;
i <
branches->GetEntriesFast(); ++
i) {
465 TBranch*
br =
dynamic_cast<TBranch*
>(
branches->At(
i));
467 ::Fatal(
"xAOD::TAuxStore::impl::scanInputTree",
479 TObjArray* sbranches =
br->GetListOfBranches();
482 for (Int_t j = 0; j < sbranches->GetEntriesFast(); ++j) {
485 const TString
brName = sbranches->At(j)->GetName();
488 const TString auxName =
492 if (auxName.BeginsWith(
"xAOD::") || auxName.BeginsWith(
"SG::") ||
493 (auxName ==
"ILockable")) {
498 ::TBranch* sbr =
dynamic_cast< ::TBranch*
>(sbranches->At(j));
500 ::Fatal(
"xAOD::TAuxStore::impl::scanInputTree",
522 ::Warning(
"xAOD::TAuxStore::impl::scanInputTree",
523 "Dynamic branch with empty name found on container: %s",
541 return StatusCode::SUCCESS;
546 ::TBranch&
br, std::string_view auxName,
bool staticBranch,
547 std::string* expectedClassName =
nullptr) {
550 ::TClass* expectedClass =
nullptr;
551 ::EDataType expectedType = kOther_t;
552 if (
br.GetExpectedType(expectedClass, expectedType) &&
553 ((!staticBranch) || (!auxName.starts_with(
"m_")))) {
554 ::Warning(
"xAOD::TAuxStore::impl::auxBranchType",
555 "Couldn't get the type of branch \"%s\"",
br.GetName());
563 if (TBranchElement* bre =
dynamic_cast<TBranchElement*
>(&
br)) {
564 TClass* newClass = bre->GetCurrentClass();
565 if (newClass && newClass != expectedClass) {
566 expectedClass = newClass;
569 if (expectedClassName) {
570 *expectedClassName = expectedClass->GetName();
576 if ((!expectedClass) &&
582 const std::type_info* ti =
nullptr;
585 ti = expectedClass->GetTypeInfo();
590 if (!expectedClass) {
591 if ((!staticBranch) || (!auxName.starts_with(
"m_"))) {
592 ::Warning(
"xAOD::TAuxStore::impl::auxBranchType",
593 "Couldn't get the type of branch \"%s\"",
br.GetName());
596 ::TVirtualCollectionProxy* prox = expectedClass->GetCollectionProxy();
601 prox = cl2->GetCollectionProxy();
606 if ((!staticBranch) || (!auxName.starts_with(
"m_"))) {
607 ::Warning(
"xAOD::TAuxStore::impl::auxBranchType",
608 "Couldn't get the type of branch \"%s\"",
br.GetName());
611 if (prox->GetValueClass()) {
612 ti = prox->GetValueClass()->GetTypeInfo();
645 std::string expectedClassName;
646 const std::type_info* ti =
650 return StatusCode::SUCCESS;
660 regAuxid != SG::null_auxid) {
662 return StatusCode::SUCCESS;
671 std::string linkedAttr =
674 ::TBranch* lbr =
m_inTree->GetBranch(linkedBranch.c_str());
675 const std::type_info* lti =
nullptr;
681 *lti, linkedAttr,
"",
684 if (linked_auxid == SG::null_auxid) {
685 ::Error(
"xAOD::TAuxStore::impl::setupAuxBranch",
686 "Could not find linked variable for %s type %s", auxName.data(),
687 expectedClassName.c_str());
693 registry.getAuxID(*ti, std::string{auxName},
"",
flags, linked_auxid);
696 if (auxid == SG::null_auxid) {
704 if (tn.starts_with(
"std::vector<")) {
707 std::string fac_class_name =
708 "SG::AuxTypeVectorFactory<" + tn +
",allocator<" + tn;
709 if (fac_class_name[fac_class_name.size() - 1] ==
'>') {
710 fac_class_name +=
' ';
712 fac_class_name +=
"> >";
715 ::TClass* fac_class = TClass::GetClass(fac_class_name.c_str());
716 if (fac_class && fac_class->IsLoaded()) {
717 ::TClass* base_class = ::TClass::GetClass(
"SG::IAuxTypeVectorFactory");
718 if (base_class && base_class->IsLoaded()) {
719 const Int_t offs = fac_class->GetBaseClassOffset(base_class);
721 void* fac_vp = fac_class->New();
724 reinterpret_cast<unsigned long>(fac_vp) + offs;
729 std::unique_ptr<SG::IAuxTypeVectorFactory>(fac));
730 auxid =
registry.getAuxID(*ti, std::string{auxName},
"",
flags,
739 if (auxid == SG::null_auxid && linked_auxid == SG::null_auxid) {
743 if (vec_class_name[vec_class_name.size() - 1] ==
'>') {
744 vec_class_name +=
' ';
746 vec_class_name +=
'>';
749 ::TClass* vec_class = ::TClass::GetClass(vec_class_name.c_str());
750 if (vec_class && vec_class->IsLoaded()) {
751 auto fac = std::make_unique<TAuxVectorFactory>(vec_class);
752 if (fac->tiAlloc()) {
753 const std::type_info* tiAlloc = fac->tiAlloc();
754 registry.addFactory(*ti, *tiAlloc, std::move(fac));
756 std::string tiAllocName = fac->tiAllocName();
757 registry.addFactory(*ti, tiAllocName, std::move(fac));
759 auxid =
registry.getAuxID(*ti, std::string{auxName},
"",
762 ::Warning(
"xAOD::TAuxStore::impl::setupAuxBranch",
763 "Couldn't find dictionary for type: %s",
764 vec_class_name.c_str());
769 if (auxid == SG::null_auxid) {
770 if (linked_auxid != SG::null_auxid) {
771 ::Error(
"xAOD::TAuxStore::impl::setupAuxBranch",
772 XAOD_MESSAGE(
"Dynamic ROOT vector factory not implemented for "
773 "linked types; branch "
777 ::Error(
"xAOD::TAuxStore::impl::setupAuxBranch",
782 return StatusCode::FAILURE;
787 return StatusCode::SUCCESS;
819 int basketSize,
int splitLevel)
838 return m_impl->m_basketSize;
850 return m_impl->m_splitLevel;
872 m_impl->m_missingBranches.clear();
882 assert(
m_impl->m_inTree !=
nullptr);
887 return StatusCode::SUCCESS;
893 ::Warning(
"xAOD::TAuxStore::readFrom",
894 "Static branch (%s) with split level %i discovered",
896 ::Warning(
"xAOD::TAuxStore::readFrom",
897 "The reading of complex variables from it may/will fail!");
901 return StatusCode::SUCCESS;
928 return StatusCode::SUCCESS;
969 for (
auto& branchHandle :
m_impl->m_branches) {
971 bytesRead += branchHandle->getEntry();
981 for (
auto& branchHandle :
m_impl->m_branches) {
983 branchHandle->reset();
986 m_impl->m_inputScanned =
false;
992 return ((
m_impl->m_branches.size() > auxid) &&
m_impl->m_branches[auxid]);
998 assert(
m_impl->m_branches.size() > auxid);
999 assert(
m_impl->m_branches[auxid]);
1000 const ::Int_t readBytes =
m_impl->m_branches[auxid]->getEntry();
1001 if (readBytes < 0) {
1002 ::Error(
"xAOD::TAuxStore::getEntryFor",
1005 return StatusCode::FAILURE;
1007 return StatusCode::SUCCESS;
1013 return (
m_impl->m_outTree !=
nullptr);
1031 if ((auxid < m_impl->m_missingBranches.size()) &&
1032 m_impl->m_missingBranches[auxid]) {
1033 return StatusCode::RECOVERABLE;
1040 if (
m_impl->m_branches.size() <= auxid) {
1041 m_impl->m_branches.resize(auxid + 1);
1046 return StatusCode::SUCCESS;
1050 if (
m_impl->m_inTree ==
nullptr) {
1051 ::Error(
"xAOD::TAuxStore::setupInputData",
1053 return StatusCode::FAILURE;
1058 ::Error(
"xAOD::TAuxStore::setupInputData",
1060 return StatusCode::FAILURE;
1067 const TString statBrName =
1069 const TString dynBrName =
1073 Bool_t staticBranch =
true;
1074 TString
brName = statBrName;
1076 TBranch*
br =
m_impl->m_inTree->GetBranch(statBrName);
1078 br =
m_impl->m_inTree->GetBranch(dynBrName);
1082 if (
m_impl->m_missingBranches.size() <= auxid) {
1083 m_impl->m_missingBranches.resize(auxid + 1);
1085 m_impl->m_missingBranches[auxid] =
true;
1088 return StatusCode::RECOVERABLE;
1091 staticBranch =
false;
1096 const Bool_t primitiveBranch = isPrimitiveBranch(*
br);
1098 const Bool_t containerBranch =
1099 (primitiveBranch ? false : isContainerBranch(*
br, auxid));
1108 if ((containerBranch &&
1110 !
r.isLinked(auxid)) ||
1111 ((!containerBranch) &&
1113 ::Error(
"xAOD::TAuxStore::setupInputData",
1114 XAOD_MESSAGE(
"Branch type and requested structure mode "
1115 "differ for branch: %s"),
1117 return StatusCode::FAILURE;
1121 ::TClass* clDummy = 0;
1122 ::EDataType dType = kOther_t;
1123 if (
br->GetExpectedType(clDummy, dType)) {
1124 ::Error(
"xAOD::TAuxStore::setupInputData",
1125 XAOD_MESSAGE(
"Couldn't determine the type of branch \"%s\""),
1127 return StatusCode::FAILURE;
1131 const std::type_info* brType = 0;
1134 brType = (containerBranch ?
r.getVecType(auxid) :
r.getType(auxid));
1140 ::Error(
"xAOD::TAuxStore::setupInputData",
1142 clDummy->GetName());
1143 return StatusCode::RECOVERABLE;
1148 ::TClass* brClass = 0;
1149 if (!primitiveBranch) {
1151 brClass = ::TClass::GetClass(*brType,
true,
true);
1153 brClass = ::TClass::GetClass(brTypeName);
1156 ::Error(
"xAOD::TAuxStore::setupInputData",
1157 XAOD_MESSAGE(
"No dictionary available for class \"%s\""),
1159 return StatusCode::FAILURE;
1165 m_data.
m_vecs[auxid] =
r.makeVector(auxid, (
size_t)0, (
size_t)0);
1166 if (!containerBranch) {
1170 strncmp(clDummy->GetName(),
"SG::PackedContainer<", 20) == 0) {
1171 std::unique_ptr<SG::IAuxTypeVector>
packed =
1176 ::Error(
"xAOD::TAuxStore::setupInputData",
1178 "variable %s (%i)"),
1179 brName.Data(),
static_cast<int>(auxid));
1180 return StatusCode::FAILURE;
1184 const std::type_info* objType = brType;
1185 if (containerBranch) {
1188 objType =
r.getType(auxid);
1190 m_impl->m_branches[auxid] = std::make_unique<TBranchHandle>(
1191 staticBranch, primitiveBranch, objType,
1203 if (clDummy && ::TString(clDummy->GetName()).Contains(
"basic_string<char>")) {
1212 m_impl->m_branches[auxid]->branchPtr());
1216 m_impl->m_branches[auxid]->branchPtr(), brClass, dType,
1217 ((!staticBranch) && (!primitiveBranch)));
1220 ::Error(
"xAOD::TAuxStore::setupInputData",
1222 ::Error(
"xAOD::TAuxStore::setupInputData",
XAOD_MESSAGE(
"Return code: %i"),
1225 m_impl->m_branches[auxid].reset();
1226 return StatusCode::FAILURE;
1230 m_impl->m_branches[auxid]->getEntry();
1238 const std::string auxname =
r.getName(auxid);
1250 const std::string testname =
r.getName(
i);
1252 if (testname != auxname) {
1257 ::Error(
"xAOD::TAuxStore::setupInputData",
1263 m_impl->m_branches[
i].reset();
1269 if (linked_auxid != SG::null_auxid) {
1274 return StatusCode::SUCCESS;
1291 if (!
m_impl->m_outTree) {
1292 return StatusCode::SUCCESS;
1297 return StatusCode::SUCCESS;
1304 if (
m_impl->m_branches.size() <= auxid) {
1305 m_impl->m_branches.resize(auxid + 1);
1307 if (
m_impl->m_branchesWritten.size() <= auxid) {
1308 m_impl->m_branchesWritten.resize(auxid + 1);
1312 if (
m_impl->m_branchesWritten[auxid]) {
1313 return StatusCode::SUCCESS;
1327 ::Fatal(
"xAOD::TAuxStore::setupOutputData",
1329 return StatusCode::FAILURE;
1336 ::Error(
"xAOD::TAuxStore::setupOutputData",
1339 return StatusCode::FAILURE;
1345 ::Error(
"xAOD::TAuxStore::setupOutputData",
1348 static_cast<int>(auxid));
1349 return StatusCode::FAILURE;
1354 ::Error(
"xAOD::TAuxStore::setupOutputData",
1355 XAOD_MESSAGE(
"No factory found for transient variable "
1357 static_cast<int>(auxid));
1358 return StatusCode::FAILURE;
1376 (!
m_impl->m_branches[auxid])) {
1383 ::Error(
"xAOD::TAuxStore::setupOutputData",
1384 XAOD_MESSAGE(
"Structure mode unknown for variable %s"),
1386 return StatusCode::FAILURE;
1399 if (!
m_impl->m_branches[auxid]) {
1401 const std::type_info* brType =
1406 bool primitiveBranch = (strlen(brType->name()) == 1);
1407 m_impl->m_branches[auxid] = std::make_unique<TBranchHandle>(
1408 false, (strlen(brType->name()) == 1),
1409 (primitiveBranch ? brType :
m_data.
m_vecs[auxid]->objType()),
1428 br->SetAddress(
m_impl->m_branches[auxid]->outputObjectPtr());
1432 m_impl->m_branchesWritten[auxid] =
true;
1434 return StatusCode::SUCCESS;
1438 const std::type_info* brType =
m_impl->m_branches[auxid]->typeInfo();
1440 ::Error(
"xAOD::TAuxStore::setupOutputData",
1443 return StatusCode::FAILURE;
1448 const Bool_t primitiveBranch = (strlen(brType->name()) == 1);
1451 if (primitiveBranch) {
1456 ::Error(
"xAOD::TAuxStore::setupOutputData",
1459 brName.Data(), brTypeName.c_str());
1460 return StatusCode::FAILURE;
1464 std::ostringstream typeDesc;
1470 typeDesc.str().c_str(),
m_impl->m_basketSize);
1475 TClass*
cl = TClass::GetClass(*brType);
1477 cl = TClass::GetClass(brTypeName.c_str());
1480 ::Error(
"xAOD::TAuxStore::setupOutputData",
1482 brTypeName.c_str());
1483 return StatusCode::FAILURE;
1485 if (!
cl->GetStreamerInfo()) {
1486 ::Error(
"xAOD::TAuxStore::setupOutputData",
1487 XAOD_MESSAGE(
"No streamer info available for type %s"),
1489 return StatusCode::FAILURE;
1494 m_impl->m_branches[auxid]->outputObjectPtr(),
1500 ::Error(
"xAOD::TAuxStore::setupOutputData",
1503 brName.Data(), brTypeName.c_str());
1504 return StatusCode::FAILURE;
1509 for (Long64_t
i = 0;
i <
m_impl->m_outTree->GetEntries(); ++
i) {
1514 m_impl->m_branchesWritten[auxid] =
true;
1520 return StatusCode::SUCCESS;
1526 assert(
m_impl->m_branches.size() > auxid);
1527 assert(
m_impl->m_branches[auxid]);
1528 return m_impl->m_branches[auxid]->objectPtr();
1534 assert(
m_impl->m_branches.size() > auxid);
1535 assert(
m_impl->m_branches[auxid]);
1536 return m_impl->m_branches[auxid]->typeInfo();