The Gaudi Framework  master (37c0b60a)
VFSSvc.cpp
Go to the documentation of this file.
1 /***********************************************************************************\
2 * (c) Copyright 1998-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 \***********************************************************************************/
11 #include <GaudiKernel/HashMap.h>
12 #include <GaudiKernel/IAlgTool.h>
14 #include <GaudiKernel/IToolSvc.h>
15 #include <GaudiKernel/MsgStream.h>
16 #include <GaudiKernel/Service.h>
17 #include <list>
18 
30 class VFSSvc : public extends<Service, IFileAccess> {
31 public:
33  using extends::extends;
35  StatusCode initialize() override;
37  StatusCode finalize() override;
38 
40  std::unique_ptr<std::istream> open( std::string const& url ) override;
41 
43  const std::vector<std::string>& protocols() const override;
44 
45 private:
47  this, "FileAccessTools", { { "FileReadTool" } }, "List of tools implementing the IFileAccess interface." };
48  Gaudi::Property<std::string> m_fallBackProtocol{ this, "FallBackProtocol", "file",
49  "URL prefix to use if the prefix is not present." };
50 
53 
56 
59 
62 };
63 
65 
66 //------------------------------------------------------------------------------
67 StatusCode VFSSvc::initialize() {
69  if ( sc.isFailure() ) return sc;
70 
71  m_toolSvc = serviceLocator()->service( "ToolSvc" );
72  if ( !m_toolSvc ) {
73  error() << "Cannot locate ToolSvc" << endmsg;
74  return StatusCode::FAILURE;
75  }
76 
77  IAlgTool* tool;
78  for ( const auto& i : m_urlHandlersNames ) {
79  // retrieve the tool and the pointer to the interface
80  sc = m_toolSvc->retrieve( i, IAlgTool::interfaceID(), tool, nullptr, true );
81  if ( sc.isFailure() ) {
82  error() << "Cannot get tool " << i << endmsg;
83  return sc;
84  }
85  m_acquiredTools.push_back( tool ); // this is one tool that we will have to release
86  auto hndlr = SmartIF<IFileAccess>( tool );
87  if ( !hndlr ) {
88  error() << i << " does not implement IFileAccess" << endmsg;
89  return StatusCode::FAILURE;
90  }
91  // We do not need to increase the reference count for the IFileAccess interface
92  // because we hold the tool by its IAlgTool interface.
93  // loop over the list of supported protocols and add them to the map (for quick access)
94  for ( const auto& prot : hndlr->protocols() ) m_urlHandlers[prot].emplace_back( hndlr.get() );
95  }
96 
97  // Now let's check if we can handle the fallback protocol
98  if ( m_urlHandlers.find( m_fallBackProtocol ) == m_urlHandlers.end() ) {
99  error() << "No handler specified for fallback protocol prefix " << m_fallBackProtocol.value() << endmsg;
100  return StatusCode::FAILURE;
101  }
102 
103  // Note: the list of handled protocols will be filled only if requested
104 
105  return sc;
106 }
107 //------------------------------------------------------------------------------
109  m_urlHandlers.clear(); // clear the map
110  m_protocols.clear();
111 
112  if ( m_toolSvc ) {
113  // release the acquired tools (from the last acquired one)
114  while ( !m_acquiredTools.empty() ) {
115  m_toolSvc->releaseTool( m_acquiredTools.back() ).ignore();
117  }
118  m_toolSvc.reset(); // release the tool service
119  }
120  return Service::finalize();
121 }
122 //------------------------------------------------------------------------------
124  // get the url prefix endpos
125  auto pos = url.find( "://" );
126 
127  if ( url.npos == pos ) {
128  // no url prefix, try fallback protocol
129  return VFSSvc::open( std::string{ m_fallBackProtocol }.append( "://" ).append( url ) );
130  }
131 
132  const std::string url_prefix( url, 0, pos );
133  const auto handlers = m_urlHandlers.find( url_prefix );
134  if ( handlers == m_urlHandlers.end() ) {
135  // if we do not have a handler for the URL prefix,
136  // use the fall back one
137  return VFSSvc::open( std::string{ m_fallBackProtocol }.append( url.substr( pos ) ) );
138  }
139 
140  std::unique_ptr<std::istream> out; // this might help RVO
141  // try the hendlers for the protocol one after the other until one succeds
142  for ( auto hndlr : handlers->second ) {
143  out = hndlr->open( url );
144  if ( out ) break;
145  }
146  return out;
147 }
148 
149 //------------------------------------------------------------------------------
151  if ( m_protocols.empty() ) {
152  // prepare the list of handled protocols
154  std::back_inserter( const_cast<VFSSvc*>( this )->m_protocols ),
155  []( const auto& pair ) { return pair.first; } );
156  }
157  return m_protocols;
158 }
Service::initialize
StatusCode initialize() override
Definition: Service.cpp:118
std::string
STL class.
IAlgTool
Definition: IAlgTool.h:33
GaudiUtils::Map::find
iterator find(const key_type &key)
Definition: Map.h:157
VFSSvc::m_fallBackProtocol
Gaudi::Property< std::string > m_fallBackProtocol
Definition: VFSSvc.cpp:48
VFSSvc::open
std::unique_ptr< std::istream > open(std::string const &url) override
Definition: VFSSvc.cpp:123
std::vector< std::string >
SmartIF::reset
void reset(TYPE *ptr=nullptr)
Set the internal pointer to the passed one disposing of the old one.
Definition: SmartIF.h:96
std::string::find
T find(T... args)
std::back_inserter
T back_inserter(T... args)
std::vector::back
T back(T... args)
VFSSvc::protocols
const std::vector< std::string > & protocols() const override
Definition: VFSSvc.cpp:150
GaudiUtils::Map::begin
iterator begin()
Definition: Map.h:139
Service::finalize
StatusCode finalize() override
Definition: Service.cpp:222
HashMap.h
IFileAccess.h
std::vector::clear
T clear(T... args)
VFSSvc::finalize
StatusCode finalize() override
Finalize Service.
Definition: VFSSvc.cpp:108
IToolSvc.h
VFSSvc::m_urlHandlersNames
Gaudi::Property< std::vector< std::string > > m_urlHandlersNames
Definition: VFSSvc.cpp:46
VFSSvc::m_acquiredTools
std::vector< IAlgTool * > m_acquiredTools
List of acquired tools (needed to release them).
Definition: VFSSvc.cpp:61
VFSSvc::m_protocols
std::vector< std::string > m_protocols
Protocols registered.
Definition: VFSSvc.cpp:52
VFSSvc
Definition: VFSSvc.cpp:30
GaudiUtils::Map::clear
void clear()
Definition: Map.h:195
bug_34121.tool
tool
Definition: bug_34121.py:18
StatusCode
Definition: StatusCode.h:65
VFSSvc::m_urlHandlers
GaudiUtils::HashMap< std::string, std::vector< IFileAccess * > > m_urlHandlers
Map of the tools handling the known protocols.
Definition: VFSSvc.cpp:55
IInterface::interfaceID
static const InterfaceID & interfaceID()
Return an instance of InterfaceID identifying the interface.
Definition: IInterface.h:248
VFSSvc::m_toolSvc
SmartIF< IToolSvc > m_toolSvc
Handle to the tool service.
Definition: VFSSvc.cpp:58
IAlgTool.h
SmartIF< IToolSvc >
endmsg
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:202
std::vector::pop_back
T pop_back(T... args)
extends
Base class used to extend a class implementing other interfaces.
Definition: extends.h:20
std::transform
T transform(T... args)
GaudiUtils::Map::end
iterator end()
Definition: Map.h:140
Service.h
std::string::substr
T substr(T... args)
StatusCode::isFailure
bool isFailure() const
Definition: StatusCode.h:129
VFSSvc::initialize
StatusCode initialize() override
Initialize Service.
Definition: VFSSvc.cpp:67
DECLARE_COMPONENT
#define DECLARE_COMPONENT(type)
Definition: PluginServiceV1.h:46
std::vector::empty
T empty(T... args)
GaudiUtils::HashMap
Definition: HashMap.h:83
StatusCode::FAILURE
constexpr static const auto FAILURE
Definition: StatusCode.h:101
std::unique_ptr
STL class.
Gaudi::Property
Implementation of property with value of concrete type.
Definition: Property.h:37
MsgStream.h
PrepareBase.out
out
Definition: PrepareBase.py:20