10#include "GaudiKernel/IAlgManager.h"
22#include "TServerSocket.h"
32 if (!cl)
return nullptr;
34 void*& map_ptr = cache[cl];
48 std::unordered_map<TClass*, void*> *
m_cache;
50 ParallelFileMerger(
const char *filename, std::unordered_map<TClass*, void*>* cache,
int compress = ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault
53 fMerger.OutputFile(filename,
"RECREATE", compress);
74 const TObjArray* fromBranches = fromTree->GetListOfBranches();
75 const TObjArray* toBranches = toTree->GetListOfBranches();
76 int nBranches = fromBranches->GetEntriesFast();
77 int nEntries = toTree->GetEntries();
78 for (
int k = 0; k < nBranches; ++k) {
79 TBranch* branch =
static_cast<TBranch*
>(fromBranches->UncheckedAt(k));
80 if (toBranches->FindObject(branch->GetName()) ==
nullptr) {
81 TBranch* newBranch =
nullptr;
82 TClass* cl = TClass::GetClass(branch->GetClassName());
84 newBranch = toTree->Branch(branch->GetName(), branch->GetClassName(),
nullptr, branch->GetBasketSize(), branch->GetSplitLevel());
86 newBranch->SetAddress(
empty);
88 TObjArray* outLeaves = branch->GetListOfLeaves();
89 TLeaf* leaf =
static_cast<TLeaf*
>(outLeaves->UncheckedAt(0));
90 std::string_view attr = leaf->GetName();
91 std::string_view
type = leaf->GetTypeName();
92 std::string branchSpec(attr);
94 if (
type ==
"Int_t") branchSpec +=
'I';
95 else if (
type ==
"Short_t") branchSpec +=
'S';
96 else if (
type ==
"Long_t") branchSpec +=
'L';
97 else if (
type ==
"UInt_t") branchSpec +=
'i';
98 else if (
type ==
"UShort_t") branchSpec+=
's';
99 else if (
type ==
"ULong_t") branchSpec +=
'l';
100 else if (
type ==
"Float_t") branchSpec +=
'F';
101 else if (
type ==
"Double_t") branchSpec+=
'D';
102 else if (
type ==
"Char_t") branchSpec +=
'B';
103 else if (
type ==
"UChar_t") branchSpec +=
'b';
104 else if (
type ==
"Bool_t") branchSpec +=
'O';
105 else { branchSpec +=
type; }
106 newBranch = toTree->Branch(branch->GetName(),
static_cast<void*
>(
nullptr), branchSpec.c_str(), 2048);
108 for (
int m = 0; m < nEntries; ++m) {
109 newBranch->BackFill();
120 TIter nextKey(input->GetListOfKeys());
121 while (TKey* key =
static_cast<TKey*
>(nextKey())) {
122 TClass* cl = TClass::GetClass(key->GetClassName());
123 if (cl !=
nullptr && cl->InheritsFrom(
"TTree")) {
124 TTree* outCollTree =
static_cast<TTree*
>(
fMerger.GetOutputFile()->
Get(key->GetName()));
125 TTree* inCollTree =
static_cast<TTree*
>(input->Get(key->GetName()));
126 if (inCollTree !=
nullptr && outCollTree !=
nullptr) {
135 Bool_t result =
fMerger.PartialMerge(TFileMerger::kIncremental | TFileMerger::kResetable | TFileMerger::kKeepCompression);
136 nextKey = input->GetListOfKeys();
137 while (TKey* key =
static_cast<TKey*
>(nextKey())) {
138 TClass* cl = TClass::GetClass(key->GetClassName());
139 if (cl !=
nullptr && 0 != cl->GetResetAfterMerge()) {
141 input->GetListOfKeys()->Remove(key);
151 : base_class(name, pSvcLocator)
160 IProperty* propertyServer =
dynamic_cast<IProperty*
>(
m_cnvSvc.get());
161 if (propertyServer ==
nullptr) {
162 ATH_MSG_ERROR(
"Unable to cast conversion service to IProperty");
163 return StatusCode::FAILURE;
165 std::string propertyName =
"ParallelCompression";
166 bool parallelCompression(
false);
167 BooleanProperty parallelCompressionProp(propertyName, parallelCompression);
168 if (propertyServer->getProperty(¶llelCompressionProp).isFailure()) {
169 ATH_MSG_INFO(
"Conversion service does not have ParallelCompression property");
170 }
else if (parallelCompressionProp.value()) {
172 propertyName =
"StreamPortString";
173 std::string streamPortString(
"");
174 StringProperty streamPortStringProp(propertyName, streamPortString);
175 if (propertyServer->getProperty(&streamPortStringProp).isFailure()) {
176 ATH_MSG_INFO(
"Conversion service does not have StreamPortString property, using default: " << streamPort);
178 streamPort = atoi(streamPortStringProp.value().substr(streamPortStringProp.value().find(
':') + 1).c_str());
180 m_rootServerSocket =
new TServerSocket(streamPort, (streamPort == 0 ?
false :
true), 100, -1, ESocketBindOption::kInaddrLoopback);
182 ATH_MSG_FATAL(
"Could not create ROOT TServerSocket: " << streamPort);
183 return StatusCode::FAILURE;
186 const std::string newStreamPortString{streamPortStringProp.value().substr(0,streamPortStringProp.value().find(
':')+1) + std::to_string(streamPort)};
187 if (propertyServer->setProperty(propertyName,newStreamPortString).isFailure()) {
188 ATH_MSG_FATAL(
"Could not set Conversion Service property " << propertyName <<
" from " << streamPortString <<
" to " << newStreamPortString);
189 return StatusCode::FAILURE;
193 ATH_MSG_DEBUG(
"Successfully created ROOT TServerSocket and added it to TMonitor: ready to accept connections, " << streamPort);
197 const IAlgManager* algMgr = Gaudi::svcLocator()->as<IAlgManager>();
198 for (
const auto& alg : algMgr->getAlgorithms()) {
199 if (alg->type() ==
"AthenaOutputStream") {
200 ATH_MSG_DEBUG(
"Counting " << alg->name() <<
" as an output stream algorithm");
205 ATH_MSG_WARNING(
"No output stream algorithm found, setting the number of streams to 1");
211 return StatusCode::SUCCESS;
216 StatusCode
sc =
m_cnvSvc->commitOutput(
"",
false);
221 while (
sc.isSuccess() ||
sc.isRecoverable() || anyActiveClients) {
222 if (
sc.isSuccess()) {
226 if (socket !=
nullptr && socket != (TSocket*)-1) {
228 if (socket->IsA() == TServerSocket::Class()) {
229 TSocket* client = (
static_cast<TServerSocket*
>(socket))->
Accept();
239 client->Close(
"force");
243 TMessage* message =
nullptr;
244 Int_t result = socket->Recv(message);
246 ATH_MSG_ERROR(
"ROOT Monitor got an error while receiving the message from the socket: " << result);
247 return StatusCode::FAILURE;
249 if (message ==
nullptr) {
250 ATH_MSG_WARNING(
"ROOT Monitor got no message from socket: " << socket);
251 }
else if (message->What() == kMESS_STRING) {
253 message->ReadString(
str, 64);
256 ATH_MSG_DEBUG(
"ROOT Monitor client: " << socket <<
", " << socket->GetBytesRecv() <<
", " << socket->GetBytesSent());
261 anyActiveClients =
false;
262 ATH_MSG_INFO(
"ROOT Monitor: No more active clients...");
264 motherClient =
false;
265 ATH_MSG_INFO(
"ROOT Monitor: Mother process is done...");
266 if (!
m_cnvSvc->commitCatalog().isSuccess()) {
268 return StatusCode::FAILURE;
272 }
else if (message->What() == kMESS_ANY) {
276 message->ReadInt(clientId);
277 message->ReadTString(filename);
278 message->ReadLong64(
length);
279 ATH_MSG_DEBUG(
"ROOT Monitor client: " << socket <<
", " << clientId <<
": " << filename <<
", " <<
length);
280 std::unique_ptr<TMemFile> transient(
new TMemFile(filename, message->Buffer() + message->Length(),
length,
"UPDATE"));
281 message->SetBufferOffset(message->Length() +
length);
286 ATH_MSG_INFO(
"ROOT Monitor ParallelFileMerger: " << info <<
", for: " << filename);
288 info->MergeTrees(transient.get());
290 delete message; message =
nullptr;
297 if (
sc.isSuccess() ||
sc.isRecoverable()) {
299 if (
sc.isFailure() && !
sc.isRecoverable()) {
302 ATH_MSG_INFO(
"ROOT Monitor: No clients, terminating the loop...");
303 anyActiveClients =
false;
309 return StatusCode::SUCCESS;
314 return StatusCode::SUCCESS;
323 cl->Destructor(ptr,
false);
327 return StatusCode::SUCCESS;
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
void * getCachedDummyAddress(TClass *cl, std::unordered_map< TClass *, void * > &cache)
This file contains the class definition for the AthenaRootSharedWriterSvc class.
static const Attributes_t empty
Templated class containing a cut, name of cut and description of cut(optional) Typically,...
virtual StatusCode stop() override
virtual StatusCode finalize() override
virtual StatusCode share(int numClients=0, bool motherClient=false) override
virtual StatusCode initialize() override
Gaudi Service Interface method implementations:
std::unordered_map< TClass *, void * > m_dummyCache
AthenaRootSharedWriterSvc(const std::string &name, ISvcLocator *pSvcLocator)
Standard Service Constructor.
TServerSocket * m_rootServerSocket
ServiceHandle< AthenaPoolSharedIOCnvSvc > m_cnvSvc
T * Get(TFile &f, const std::string &n, const std::string &dir="", const chainmap_t *chainmap=0, std::vector< std::string > *saved=0)
get a histogram given a path, and an optional initial directory if histogram is not found,...
const char * GetName() const
bool syncBranches(TTree *fromTree, TTree *toTree)
ParallelFileMerger(const char *filename, std::unordered_map< TClass *, void * > *cache, int compress=ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault)
std::unordered_map< TClass *, void * > * m_cache
Bool_t MergeTrees(TFile *input)