Loading [MathJax]/extensions/tex2jax.js
The Gaudi Framework  master (da3d77e1)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
FileSvc.cpp
Go to the documentation of this file.
1 /***********************************************************************************\
2 * (c) Copyright 2024 CERN for the benefit of the LHCb and ATLAS collaborations *
3 * *
4 * This software is distributed under the terms of the Apache version 2 licence, *
5 * copied verbatim in the file "LICENSE". *
6 * *
7 * In applying this licence, CERN does not waive the privileges and immunities *
8 * granted to it by virtue of its status as an Intergovernmental Organization *
9 * or submit itself to any jurisdiction. *
10 \***********************************************************************************/
12 #include <Gaudi/Parsers/Factory.h>
13 #include <GaudiKernel/Service.h>
14 #include <GaudiKernel/StatusCode.h>
15 #include <TFile.h>
16 #include <boost/algorithm/string.hpp>
17 #include <memory>
18 #include <optional>
19 #include <string>
20 #include <unordered_map>
21 #include <vector>
22 
23 class FileSvc : public extends<Service, Gaudi::Interfaces::IFileSvc> {
24 public:
25  // Constructor
26  FileSvc( const std::string& name, ISvcLocator* svc );
27 
28  virtual StatusCode initialize() override;
29 
30  virtual StatusCode finalize() override;
31 
37  virtual std::shared_ptr<TFile> getFile( const std::string& identifier ) override;
38 
39 public:
40  // Property to map file identifiers to file paths
42  this, "Config", {}, "Map of keywords to file paths for file access" };
43 
44 private:
51  std::shared_ptr<TFile> openFile( const std::string& filePath, const std::string& option );
52 
58 
59 private:
60  // Map holding file identifiers to file indices in the m_files vector
62 
63  // Vector to hold all files unique pointers
65 };
66 
68 
69 namespace {
76  std::map<std::string, std::string> parseFilePath( const std::string& path ) {
78  boost::split( parts, path, boost::is_any_of( "?" ) );
80  if ( parts.size() > 1 ) {
82  boost::split( params, parts[1], boost::is_any_of( "&" ) );
83  for ( auto& param : params ) {
85  boost::split( kv, param, boost::is_any_of( "=" ) );
86  if ( kv.size() == 2 ) { result[boost::trim_copy( kv[0] )] = boost::trim_copy( kv[1] ); }
87  }
88  }
89  result["mode"] = ( result.find( "mode" ) == result.end() ) ? "CREATE" : result["mode"];
90  result["path"] = boost::trim_copy( parts[0] );
91  return result;
92  }
93 
103  StatusCode checkConfig( const std::map<std::string, std::string>& configMap, const FileSvc& svc ) {
105  for ( const auto& [identifier, path] : configMap ) {
106  auto params = parseFilePath( path );
107 
108  auto& existingParams = fileParams[params["path"]];
109  if ( !existingParams.empty() ) {
110  if ( existingParams != params ) {
111  svc.error() << "Conflicting configurations for file path: " << params["path"] << endmsg;
112  return StatusCode::FAILURE;
113  }
114  } else {
115  existingParams = std::move( params );
116  }
117  }
118  return StatusCode::SUCCESS;
119  }
120 
128  std::optional<size_t> findFileIndex( const std::vector<std::shared_ptr<TFile>>& files, const std::string& filePath ) {
129  auto it = std::find_if( files.begin(), files.end(),
130  [&filePath]( const auto& file ) { return file && file->GetName() == filePath; } );
131  if ( it != files.end() ) { return std::distance( files.begin(), it ); }
132  return std::nullopt;
133  }
134 } // namespace
135 
137 
139  return Service::initialize().andThen( [this]() {
140  if ( checkConfig( m_config, *this ).isFailure() ) { return StatusCode::FAILURE; }
141 
142  for ( const auto& [identifier, path] : m_config ) {
143  auto params = parseFilePath( path );
144 
145  // Check if this file is already opened and mapped
146  if ( auto fileIndex = findFileIndex( m_files, params["path"] ) ) {
147  // File already opened, just map the identifier to the existing index
148  m_identifiers[boost::to_lower_copy( identifier )] = *fileIndex;
149  } else {
150  // File not found, open a new one
151  if ( auto file = openFile( path, params["mode"] ) ) {
152  m_files.push_back( std::move( file ) );
153  m_identifiers[boost::to_lower_copy( identifier )] = m_files.size() - 1;
154  } else {
155  error() << "Failed to open file: " << params["path"] << endmsg;
156  return StatusCode::FAILURE;
157  }
158  }
159  }
160 
161  return StatusCode::SUCCESS;
162  } );
163 }
164 
166 
168  auto it = m_identifiers.find( boost::to_lower_copy( identifier ) );
169  if ( it != m_identifiers.end() && it->second < m_files.size() ) { return m_files[it->second]; }
170  error() << "No file associated with identifier: " << identifier << endmsg;
171  return nullptr;
172 }
173 
175  auto file = std::make_shared<TFile>( filePath.c_str(), option.c_str() );
176  if ( !file || file->IsZombie() ) { return nullptr; }
177  return file;
178 }
179 
181  for ( const auto& file : m_files ) {
182  if ( file ) { file->Close(); }
183  }
184  m_files.clear();
186  return StatusCode::SUCCESS;
187 }
FileSvc::FileSvc
FileSvc(const std::string &name, ISvcLocator *svc)
Definition: FileSvc.cpp:136
FileSvc
Definition: FileSvc.cpp:23
Service::initialize
StatusCode initialize() override
Definition: Service.cpp:118
std::string
STL class.
std::shared_ptr< TFile >
FileSvc::finalize
virtual StatusCode finalize() override
Definition: FileSvc.cpp:165
StatusCode::andThen
StatusCode andThen(F &&f, ARGS &&... args) const
Chain code blocks making the execution conditional a success result.
Definition: StatusCode.h:163
std::move
T move(T... args)
FileSvc::getFile
virtual std::shared_ptr< TFile > getFile(const std::string &identifier) override
Get a TFile pointer based on an identifier.
Definition: FileSvc.cpp:167
AtlasMCRecoFullPrecedenceDump.path
path
Definition: AtlasMCRecoFullPrecedenceDump.py:49
FileSvc::closeFiles
StatusCode closeFiles()
Close all files.
Definition: FileSvc.cpp:180
std::vector
STL class.
std::map::find
T find(T... args)
std::vector::size
T size(T... args)
ISvcLocator
Definition: ISvcLocator.h:46
std::distance
T distance(T... args)
FileSvc::initialize
virtual StatusCode initialize() override
Definition: FileSvc.cpp:138
StatusCode.h
std::vector::clear
T clear(T... args)
std::vector::push_back
T push_back(T... args)
FileSvc::openFile
std::shared_ptr< TFile > openFile(const std::string &filePath, const std::string &option)
Open a file based on a specified path and opening mode.
Definition: FileSvc.cpp:174
Service::name
const std::string & name() const override
Retrieve name of the service
Definition: Service.cpp:332
StatusCode
Definition: StatusCode.h:65
CommonMessaging
Definition: CommonMessaging.h:66
IFileSvc.h
std::string::c_str
T c_str(T... args)
FileSvc::m_config
Gaudi::Property< std::map< std::string, std::string > > m_config
Definition: FileSvc.cpp:41
endmsg
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:202
std::map< std::string, std::string >
extends
Base class used to extend a class implementing other interfaces.
Definition: extends.h:20
Service.h
Factory.h
ConditionsStallTest.name
name
Definition: ConditionsStallTest.py:77
StatusCode::SUCCESS
constexpr static const auto SUCCESS
Definition: StatusCode.h:100
DECLARE_COMPONENT
#define DECLARE_COMPONENT(type)
Definition: PluginServiceV1.h:46
std::map::end
T end(T... args)
StatusCode::FAILURE
constexpr static const auto FAILURE
Definition: StatusCode.h:101
std::unordered_map< std::string, size_t >
FileSvc::m_identifiers
std::unordered_map< std::string, size_t > m_identifiers
Definition: FileSvc.cpp:61
Gaudi::Property
Implementation of property with value of concrete type.
Definition: Property.h:37
FileSvc::m_files
std::vector< std::shared_ptr< TFile > > m_files
Definition: FileSvc.cpp:64