ATLAS Offline Software
Loading...
Searching...
No Matches
AthenaRootSharedWriterSvc Class Reference

This class provides an example for writing event data objects to Pool. More...

#include <AthenaRootSharedWriterSvc.h>

Inheritance diagram for AthenaRootSharedWriterSvc:
Collaboration diagram for AthenaRootSharedWriterSvc:

Public Member Functions

 AthenaRootSharedWriterSvc (const std::string &name, ISvcLocator *pSvcLocator)
 Standard Service Constructor.
virtual ~AthenaRootSharedWriterSvc ()=default
 Destructor.
virtual StatusCode initialize () override
 Gaudi Service Interface method implementations:
virtual StatusCode stop () override
virtual StatusCode finalize () override
virtual StatusCode share (int numClients=0, bool motherClient=false) override

Private Attributes

ServiceHandle< AthenaPoolSharedIOCnvSvcm_cnvSvc {this,"AthenaPoolSharedIOCnvSvc","AthenaPoolSharedIOCnvSvc"}
TServerSocket * m_rootServerSocket
TMonitor * m_rootMonitor
std::string m_socketPath
 Path of the UNIX domain socket file, if used, removed on finalize.
THashTable m_rootMergers
std::unordered_map< TClass *, void * > m_cachedObjects
int m_rootClientIndex
int m_rootClientCount
int m_numberOfStreams

Friends

class SvcFactory< AthenaRootSharedWriterSvc >

Detailed Description

This class provides an example for writing event data objects to Pool.

Definition at line 26 of file AthenaRootSharedWriterSvc.h.

Constructor & Destructor Documentation

◆ AthenaRootSharedWriterSvc()

AthenaRootSharedWriterSvc::AthenaRootSharedWriterSvc ( const std::string & name,
ISvcLocator * pSvcLocator )

◆ ~AthenaRootSharedWriterSvc()

virtual AthenaRootSharedWriterSvc::~AthenaRootSharedWriterSvc ( )
virtualdefault

Destructor.

Member Function Documentation

◆ finalize()

StatusCode AthenaRootSharedWriterSvc::finalize ( )
overridevirtual

Definition at line 354 of file AthenaRootSharedWriterSvc.cxx.

354 {
355 ATH_MSG_INFO("in finalize()");
356 delete m_rootMonitor; m_rootMonitor = nullptr;
357 delete m_rootServerSocket; m_rootServerSocket = nullptr;
358 if (!m_socketPath.empty()) {
359 //coverity[CHECKED_RETURN]
360 std::remove(m_socketPath.c_str()); //returns 0 on success.
361 }
362 for (auto& [cl, ptr] : m_cachedObjects) {
363 if (cl && ptr) {
364 cl->Destructor(ptr, false);
365 }
366 }
367 m_cachedObjects.clear();
368 return StatusCode::SUCCESS;
369}
#define ATH_MSG_INFO(x,...)
std::unordered_map< TClass *, void * > m_cachedObjects
std::string m_socketPath
Path of the UNIX domain socket file, if used, removed on finalize.
cl
print [x.__class__ for x in toList(dqregion.getSubRegions()) ]
DataModel_detail::iterator< DVL > remove(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end, const T &value)
Specialization of remove for DataVector/List.

◆ initialize()

StatusCode AthenaRootSharedWriterSvc::initialize ( )
overridevirtual

Gaudi Service Interface method implementations:

Definition at line 156 of file AthenaRootSharedWriterSvc.cxx.

156 {
157 ATH_MSG_INFO("in initialize()");
158
159 // Initialize IConversionSvc
160 ATH_CHECK(m_cnvSvc.retrieve());
161 IProperty* propertyServer = dynamic_cast<IProperty*>(m_cnvSvc.get());
162 if (propertyServer == nullptr) {
163 ATH_MSG_ERROR("Unable to cast conversion service to IProperty");
164 return StatusCode::FAILURE;
165 } else {
166 std::string propertyName = "ParallelCompression";
167 bool parallelCompression(false);
168 BooleanProperty parallelCompressionProp(propertyName, parallelCompression);
169 if (propertyServer->getProperty(&parallelCompressionProp).isFailure()) {
170 ATH_MSG_INFO("Conversion service does not have ParallelCompression property");
171 } 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 TCP port: 0");
177 streamPortStringProp.setValue("?pmerge=localhost:0");
178 }
179 const std::string& pmergeProperty = streamPortStringProp.value();
180 const std::size_t eqPos = pmergeProperty.find('=');
181 if (eqPos == std::string::npos) {
182 ATH_MSG_FATAL("Malformed StreamPortString property (missing '='): " << pmergeProperty);
183 return StatusCode::FAILURE;
184 }
185 const std::string pmergePrefix = pmergeProperty.substr(0, eqPos + 1);
186 const std::string pmergeArg = pmergeProperty.substr(eqPos + 1);
187 if (pmergeArg.empty()) {
188 ATH_MSG_FATAL("Malformed StreamPortString property (empty value after '='): " << pmergeProperty);
189 return StatusCode::FAILURE;
190 }
191 std::string newStreamPortString;
192 // "?pmerge=<host>:<port>" (default) selects a TCP socket.
193 // Anything else (e.g. "?pmerge=<prefix>") is passed to gSystem->TempFileName() as a
194 // (possibly relative) prefix for a UNIX domain socket file, created as $TMPDIR/<prefix>XXXXXX.
195 if (pmergeArg.find(':') == std::string::npos) {
196 TString socketPath = pmergeArg.c_str();
197 FILE* reservedFile = gSystem->TempFileName(socketPath);
198 if (reservedFile == nullptr) {
199 ATH_MSG_FATAL("Could not create temporary file for UNIX domain socket: " << pmergeArg);
200 return StatusCode::FAILURE;
201 }
202 m_socketPath = socketPath.Data();
203 //coverity[CHECKED_RETURN]
204 std::remove(m_socketPath.c_str()); //returns 0 if ok.
205 std::fclose(reservedFile);
206 m_rootServerSocket = new TServerSocket(socketPath);
207 if (m_rootServerSocket == nullptr || !m_rootServerSocket->IsValid()) {
208 ATH_MSG_FATAL("Could not create ROOT TServerSocket (UNIX domain socket): " << m_socketPath);
209 return StatusCode::FAILURE;
210 }
211 newStreamPortString = pmergePrefix + m_socketPath;
212 ATH_MSG_DEBUG("Successfully created ROOT TServerSocket (UNIX domain socket) and added it to TMonitor: ready to accept connections, " << m_socketPath);
213 } else {
214 const std::size_t colonPos = pmergeArg.find(':');
215 int streamPort = atoi(pmergeArg.substr(colonPos + 1).c_str());
216 m_rootServerSocket = new TServerSocket(streamPort, (streamPort == 0 ? false : true), 100, -1, ESocketBindOption::kInaddrLoopback);
217 if (m_rootServerSocket == nullptr || !m_rootServerSocket->IsValid()) {
218 ATH_MSG_FATAL("Could not create ROOT TServerSocket: " << streamPort);
219 return StatusCode::FAILURE;
220 }
221 streamPort = m_rootServerSocket->GetLocalPort();
222 newStreamPortString = pmergePrefix + pmergeArg.substr(0, colonPos + 1) + std::to_string(streamPort);
223 ATH_MSG_DEBUG("Successfully created ROOT TServerSocket and added it to TMonitor: ready to accept connections, " << streamPort);
224 }
225 if (propertyServer->setProperty(propertyName,newStreamPortString).isFailure()) {
226 ATH_MSG_FATAL("Could not set Conversion Service property " << propertyName << " from " << streamPortString << " to " << newStreamPortString);
227 return StatusCode::FAILURE;
228 }
229 m_rootMonitor = new TMonitor;
231 }
232 }
233 // Count the number of output streams
234 const IAlgManager* algMgr = Gaudi::svcLocator()->as<IAlgManager>();
235 for (const auto& alg : algMgr->getAlgorithms()) {
236 if (alg->type() == "AthenaOutputStream") {
237 ATH_MSG_DEBUG("Counting " << alg->name() << " as an output stream algorithm");
239 }
240 }
241 if (m_numberOfStreams == 0) {
242 ATH_MSG_WARNING("No output stream algorithm found, setting the number of streams to 1");
244 } else {
245 ATH_MSG_INFO("Found a total of " << m_numberOfStreams << " output streams");
246 }
247
248 return StatusCode::SUCCESS;
249}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_ERROR(x,...)
#define ATH_MSG_WARNING(x,...)
#define ATH_MSG_FATAL(x,...)
ServiceHandle< AthenaPoolSharedIOCnvSvc > m_cnvSvc
int atoi(std::string_view str)
Helper functions to unpack numbers decoded in string into integers and doubles The strings are requir...

◆ share()

StatusCode AthenaRootSharedWriterSvc::share ( int numClients = 0,
bool motherClient = false )
overridevirtual

Definition at line 251 of file AthenaRootSharedWriterSvc.cxx.

251 {
252 ATH_MSG_DEBUG("Start commitOutput loop");
253 StatusCode sc = m_cnvSvc->commitOutput("", false);
254
255 // Allow ROOT clients to start up (by setting active clients)
256 // and wait to stop the ROOT server until all clients are done and metadata is written (commitOutput fail).
257 bool anyActiveClients = (m_rootServerSocket != nullptr);
258 while (sc.isSuccess() || sc.isRecoverable() || anyActiveClients) {
259 if (sc.isSuccess()) {
260 ATH_MSG_VERBOSE("Success in commitOutput loop");
261 } else if (m_rootMonitor != nullptr) {
262 TSocket* socket = m_rootMonitor->Select(1);
263 if (socket != nullptr && socket != (TSocket*)-1) {
264 ATH_MSG_DEBUG("ROOT Monitor got: " << socket);
265 if (socket->IsA() == TServerSocket::Class()) {
266 TSocket* client = (static_cast<TServerSocket*>(socket))->Accept();
267 client->Send(m_rootClientIndex, 0);
268 client->Send(1, 1);
271 if (m_rootClientCount < (numClients-1)*m_numberOfStreams + 1) {
272 m_rootMonitor->Add(client);
273 ATH_MSG_INFO("ROOT Monitor add client: " << m_rootClientIndex << ", " << client);
274 } else {
275 ATH_MSG_WARNING("ROOT Monitor do NOT add client: " << m_rootClientIndex << ", " << client);
276 client->Close("force");
278 }
279 } else {
280 TMessage* message = nullptr;
281 Int_t result = socket->Recv(message);
282 if (result < 0) {
283 ATH_MSG_ERROR("ROOT Monitor got an error while receiving the message from the socket: " << result);
284 return StatusCode::FAILURE;
285 }
286 if (message == nullptr) {
287 ATH_MSG_WARNING("ROOT Monitor got no message from socket: " << socket);
288 } else if (message->What() == kMESS_STRING) {
289 char str[64];
290 message->ReadString(str, 64);
291 ATH_MSG_INFO("ROOT Monitor client: " << socket << ", " << str);
292 m_rootMonitor->Remove(socket);
293 ATH_MSG_DEBUG("ROOT Monitor client: " << socket << ", " << socket->GetBytesRecv() << ", " << socket->GetBytesSent());
294 socket->Close();
296 if (m_rootMonitor->GetActive() == 0 || m_rootClientCount == 0) {
297 if (!motherClient) {
298 anyActiveClients = false;
299 ATH_MSG_INFO("ROOT Monitor: No more active clients...");
300 } else {
301 motherClient = false;
302 ATH_MSG_INFO("ROOT Monitor: Mother process is done...");
303 if (!m_cnvSvc->commitCatalog().isSuccess()) {
304 ATH_MSG_FATAL("Failed to commit file catalog.");
305 return StatusCode::FAILURE;
306 }
307 }
308 }
309 } else if (message->What() == kMESS_ANY) {
310 long long length;
311 TString filename;
312 int clientId;
313 message->ReadInt(clientId);
314 message->ReadTString(filename);
315 message->ReadLong64(length);
316 ATH_MSG_DEBUG("ROOT Monitor client: " << socket << ", " << clientId << ": " << filename << ", " << length);
317 std::unique_ptr<TMemFile> transient(new TMemFile(filename, message->Buffer() + message->Length(), length, "UPDATE"));
318 message->SetBufferOffset(message->Length() + length);
319 ParallelFileMerger* info = static_cast<ParallelFileMerger*>(m_rootMergers.FindObject(filename));
320 if (!info) {
321 info = new ParallelFileMerger(filename, &m_cachedObjects, transient->GetCompressionSettings());
322 m_rootMergers.Add(info);
323 ATH_MSG_INFO("ROOT Monitor ParallelFileMerger: " << info << ", for: " << filename);
324 }
325 info->MergeTrees(transient.get());
326 }
327 delete message; message = nullptr;
328 }
329 }
330 } else if (m_rootMonitor == nullptr) {
331 usleep(100);
332 }
333 // Once commitOutput failed all legacy clients are finished (writing metadata), do not call again.
334 if (sc.isSuccess() || sc.isRecoverable()) {
335 sc = m_cnvSvc->commitOutput("", false);
336 if (sc.isFailure() && !sc.isRecoverable()) {
337 ATH_MSG_INFO("commitOutput failed, metadata done.");
338 if (anyActiveClients && m_rootClientCount == 0) {
339 ATH_MSG_INFO("ROOT Monitor: No clients, terminating the loop...");
340 anyActiveClients = false;
341 }
342 }
343 }
344 }
345 ATH_MSG_INFO("End commitOutput loop");
346 return StatusCode::SUCCESS;
347}
#define ATH_MSG_VERBOSE(x,...)
double length(const pvec &v)
static Double_t sc
::StatusCode StatusCode
StatusCode definition for legacy code.

◆ stop()

StatusCode AthenaRootSharedWriterSvc::stop ( )
overridevirtual

Definition at line 349 of file AthenaRootSharedWriterSvc.cxx.

349 {
350 m_rootMergers.Delete();
351 return StatusCode::SUCCESS;
352}

◆ SvcFactory< AthenaRootSharedWriterSvc >

friend class SvcFactory< AthenaRootSharedWriterSvc >
friend

Definition at line 1 of file AthenaRootSharedWriterSvc.h.

Member Data Documentation

◆ m_cachedObjects

std::unordered_map<TClass*, void*> AthenaRootSharedWriterSvc::m_cachedObjects
private

Definition at line 52 of file AthenaRootSharedWriterSvc.h.

◆ m_cnvSvc

ServiceHandle<AthenaPoolSharedIOCnvSvc> AthenaRootSharedWriterSvc::m_cnvSvc {this,"AthenaPoolSharedIOCnvSvc","AthenaPoolSharedIOCnvSvc"}
private

Definition at line 45 of file AthenaRootSharedWriterSvc.h.

45{this,"AthenaPoolSharedIOCnvSvc","AthenaPoolSharedIOCnvSvc"};

◆ m_numberOfStreams

int AthenaRootSharedWriterSvc::m_numberOfStreams
private

Definition at line 55 of file AthenaRootSharedWriterSvc.h.

◆ m_rootClientCount

int AthenaRootSharedWriterSvc::m_rootClientCount
private

Definition at line 54 of file AthenaRootSharedWriterSvc.h.

◆ m_rootClientIndex

int AthenaRootSharedWriterSvc::m_rootClientIndex
private

Definition at line 53 of file AthenaRootSharedWriterSvc.h.

◆ m_rootMergers

THashTable AthenaRootSharedWriterSvc::m_rootMergers
private

Definition at line 51 of file AthenaRootSharedWriterSvc.h.

◆ m_rootMonitor

TMonitor* AthenaRootSharedWriterSvc::m_rootMonitor
private

Definition at line 48 of file AthenaRootSharedWriterSvc.h.

◆ m_rootServerSocket

TServerSocket* AthenaRootSharedWriterSvc::m_rootServerSocket
private

Definition at line 47 of file AthenaRootSharedWriterSvc.h.

◆ m_socketPath

std::string AthenaRootSharedWriterSvc::m_socketPath
private

Path of the UNIX domain socket file, if used, removed on finalize.

Definition at line 50 of file AthenaRootSharedWriterSvc.h.


The documentation for this class was generated from the following files: