diff --git a/Database/APR/RootStorageSvc/src/RootTreeContainer.cpp b/Database/APR/RootStorageSvc/src/RootTreeContainer.cpp index 694dec0587e05648ed4f8ba95b098668b59b72c0..30ee7f659d6a3fd388af3cecd611d2eff42e6129 100755 --- a/Database/APR/RootStorageSvc/src/RootTreeContainer.cpp +++ b/Database/APR/RootStorageSvc/src/RootTreeContainer.cpp @@ -206,7 +206,11 @@ DbStatus RootTreeContainer::writeObject( ActionList::value_type& action ) if( dsc.rows_written ) { // catch up with the rows written by other branches newBrDsc.object = nullptr; - newBrDsc.branch->SetAddress( nullptr ); + // As of root 6.22, calling SetAddress with nullptr + // may not work as expected if the address had + // previously been set to something non-null. + // So we need to create the temp object ourselves. + newBrDsc.branch->SetAddress( newBrDsc.dummyAddr() ); for( size_t r=0; r<dsc.rows_written; ++r ) { num_bytes += newBrDsc.branch->BackFill(); } @@ -261,8 +265,12 @@ DbStatus RootTreeContainer::writeObject( ActionList::value_type& action ) BranchDesc& dsc = descMapElem.second; if( !dsc.written ) { dsc.object = nullptr; - dsc.branch->SetAddress( nullptr ); - // cout << " Branch " << SG::AuxTypeRegistry::instance().getName(descMapElem.first) << " filled out with NULL" << endl; + // As of root 6.22, calling SetAddress with nullptr + // may not work as expected if the address had + // previously been set to something non-null. + // So we need to create the temp object ourselves. + dsc.branch->SetAddress( dsc.dummyAddr() ); + // cout << " aaa Branch " << SG::AuxTypeRegistry::instance().getName(descMapElem.first) << " filled out with NULL" << endl; if( isBranchContainer() && !m_treeFillMode ) { size_t bytes_out = dsc.branch->Fill(); num_bytes += bytes_out; diff --git a/Database/APR/RootStorageSvc/src/RootTreeContainer.h b/Database/APR/RootStorageSvc/src/RootTreeContainer.h index aa1c3ee351806671987ee4928ed79c11fe29fe56..106e01a0dab679736d7107869324cf289c176efb 100755 --- a/Database/APR/RootStorageSvc/src/RootTreeContainer.h +++ b/Database/APR/RootStorageSvc/src/RootTreeContainer.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration */ //==================================================================== @@ -22,6 +22,7 @@ #include <map> #include <vector> #include <set> +#include <functional> // Forward declarations class TObject; @@ -76,6 +77,13 @@ namespace pool { bool is_basic_type = false; bool written = false; + // Dummy object instance; used when there was no request to write + // this branch but we need to write it anyway (for example, + // a dynamic variable that wasn't written on this event). + using dummy_ptr_t = std::unique_ptr<void, std::function<void(void*)> >; + dummy_ptr_t dummyptr; + void* dummy = 0; + BranchDesc() : clazz(nullptr), branch(nullptr), @@ -99,6 +107,20 @@ namespace pool { {} // difference for branch.setAddress() for objects and basic types, used by Aux dynamic void* objectAddr() { return is_basic_type? object : &object; } + + void* dummyAddr() + { + if (clazz) { + if (!dummy) { + using std::placeholders::_1; + std::function<void(void*)> del = std::bind (&TClass::Destructor, clazz, _1, false); + dummyptr = dummy_ptr_t (clazz->New(), std::move(del)); + dummy = dummyptr.get(); + } + return &dummy; + } + return nullptr; + } }; /// Definition of the branch container