8 #define ON_DEBUG if ( msgLevel( MSG::DEBUG ) ) 9 #define ON_VERBOSE if ( msgLevel( MSG::VERBOSE ) ) 22 bool get_bit(
int f,
unsigned int b ) {
return f & ( 1 << b ); }
26 constexpr
struct to_name_t {
31 const auto select1st = [](
auto&& x ) -> decltype(
auto ) {
return std::get<0>( std::forward<decltype( x )>( x ) ); };
33 const auto select2nd = [](
auto&& x ) -> decltype(
auto ) {
return std::get<1>( std::forward<decltype( x )>( x ) ); };
35 template <
typename InputIterator,
typename OutputIterator,
typename UnaryOperation,
typename UnaryPredicate>
36 OutputIterator transform_if( InputIterator first, InputIterator last, OutputIterator result, UnaryOperation op,
39 while ( first != last ) {
40 if ( pred( *first ) ) *result++ = op( *first );
46 template <
typename InputIterator,
typename OutputIterator,
typename UnaryOperation,
typename UnaryPredicate>
47 OutputIterator transform_copy_if( InputIterator first, InputIterator last, OutputIterator result, UnaryOperation op,
50 while ( first != last ) {
51 auto t = op( *first );
52 if ( pred( t ) ) *result++ =
std::move( t );
76 debug() <<
"Failed to initialize the base class (Service)" <<
endmsg;
83 if ( m_loadRootHandler.value() ) {
87 msgSvc()->setOutputLevel(
"RootFileHandler", m_outputLevel.value() );
88 m_rfh.emplace( msgSvc(), m_ssl_proxy, m_ssl_cert );
90 auto& rfh = m_rfh.value();
93 void*& ptr ) ->
Io::open_t {
return rfh.openRootFile( n, f, desc, fd, ptr ); },
94 [&rfh](
void* ptr ) ->
Io::close_t {
return rfh.closeRootFile( ptr ); },
97 if ( regHandler( hdlr ).isFailure() ) {
98 error() <<
"unable to register ROOT file handler with FileMgr" <<
endmsg;
102 if ( m_loadPosixHandler.value() ) {
106 msgSvc()->setOutputLevel(
"POSIXFileHandler", m_outputLevel.value() );
107 m_pfh.emplace( msgSvc() );
109 auto& pfh = m_pfh.value();
112 void*& ptr ) ->
Io::open_t {
return pfh.openPOSIXFile( n, f, desc, fd, ptr ); },
116 if ( regHandler( hdlp ).isFailure() ) {
117 error() <<
"unable to register ROOT file handler with FileMgr" <<
endmsg;
131 if ( m_printSummary || msgLevel(
MSG::DEBUG ) ) {
138 if ( !m_files.empty() ) {
139 auto&
log = warning();
140 log <<
"At finalize, the following files remained open:" <<
endl;
141 for (
const auto& itr : m_files )
log << *( itr.second ) << endl;
145 if ( m_logfile.value() !=
"" ) {
147 ofs.
open( m_logfile.value().c_str() );
149 error() <<
"Unable to open output file \"" << m_logfile.value() <<
"\" for writing" <<
endmsg;
152 debug() <<
"Saving log to \"" << m_logfile.value() <<
"\"" <<
endmsg;
153 for (
const auto& itr : m_files ) {
154 ofs << itr.second->name() <<
" " << itr.second->tech() <<
" " << itr.second->desc() <<
" " 155 << itr.second->iflags() <<
endl;
159 for (
const auto& it2 : m_oldFiles ) fs.
insert( *it2 );
160 for (
const auto& it3 : fs ) {
161 ofs << it3.name() <<
" " << it3.tech() <<
" " << it3.desc() <<
" " << it3.iflags()
162 << ( it3.isShared() ?
" SHARED" :
"" ) <<
endl;
177 if ( status.
isSuccess() ) debug() <<
"Service finalised successfully" <<
endmsg;
193 if ( m_handlers.find( tech ) != m_handlers.end() ) {
194 warning() <<
"Handler for IoTech " << tech <<
" already registered. Ignoring." <<
endmsg;
199 error() <<
"open handler for tech " << tech <<
" is NULL" <<
endmsg;
204 error() <<
"no close handler for tech " << tech <<
" registered" <<
endmsg;
209 error() <<
"no reopen handler for tech " << tech <<
" registered" <<
endmsg;
214 debug() <<
"Successfully registered handler for tech \"" << tech <<
"\"" <<
endmsg;
216 m_handlers[tech] = fh;
227 auto itr = m_handlers.find( tech );
228 if ( itr == m_handlers.end() ) {
229 error() <<
"Can't de-register tech " << tech <<
" as it hasn't been registered!" <<
endmsg;
233 m_handlers.erase( itr );
241 auto itr = m_handlers.find( tech );
251 return open( tech, caller, fname, desc, flags, fd, ptr, sh );
260 return open( tech, caller, fname, desc, flags, fd, dummy, sh );
269 return open( tech, caller, fname, desc, flags, dummy, ptr, sh );
275 const IoFlags& flags,
Fd&
fd,
void*& ptr,
bool shared )
294 verbose() <<
"open(" << tech <<
"," << caller <<
",\"" << fname <<
"\",\"" << desc <<
"\"," << flags
295 << ( shared ?
",shared" :
",unshared" ) <<
")" <<
endmsg;
299 if ( getHandler( tech, fh ).isFailure() )
return r;
301 auto fitr = m_files.equal_range( fname );
306 std::find_if( fitr.first, fitr.second, [&]( fileMap::const_reference i ) { return i.second->tech() != tech; } );
307 if ( itr != fitr.second ) {
308 error() <<
"when calling open on " << fname <<
" with tech " << tech <<
", file already opened with different tech " 309 << itr->second->tech() <<
endmsg;
318 bool shareable(
true );
320 for (
auto itr = fitr.first; itr != fitr.second; ++itr ) {
323 if ( !fa->
isShared() ) shareable =
false;
326 if ( shareable && fa->
flags().
match( flags,
false ) ) {
329 debug() <<
" found shared file: " << *fa <<
endmsg;
350 error() <<
"when calling open handler for " << tech <<
" on file " << fname <<
" caught " << err.
what() <<
endmsg;
353 error() <<
"when calling open handler for " << tech <<
" on file " << fname <<
" caught an unknown exception." 359 warning() <<
"open of file \"" << fname <<
"\", tech: \"" << tech <<
"\", flags: \"" << flags
360 <<
"\" requested by " << caller <<
" failed. return code: " << r <<
endmsg;
362 FileAttr xfa( -1, fname, desc, tech, flags, 0,
false );
375 debug() <<
"opened file " << *fa <<
endmsg;
377 if (
fd == -1 && ptr == 0 ) {
378 warning() <<
"when opening " << *fa <<
" both File Descriptor" 379 <<
" and File Ptr are invalid" <<
endmsg;
383 for (
auto itr = fitr.first; itr != fitr.second; ++itr ) {
386 }
else if ( *fa == *( itr->second ) ) {
387 warning() <<
"open call for file \"" << fname <<
"\" returned a pre-existing file with identical" 388 <<
" FileAttributes: " << *fa <<
endmsg;
391 warning() <<
"open call for file \"" << fname <<
"\" returned a pre-existing file with different" 392 <<
" FileAttributes -" <<
endl 393 <<
"old: " << *( itr->second ) <<
endl 394 <<
"new: " << *fa << endmsg;
399 m_files.emplace( fname, fa );
402 if ( execAction( fa, caller,
Io::OPEN ).isFailure() ) {
403 warning() <<
"at least one open callback action failed" <<
endmsg;
426 [&]( fileMap::const_reference i ) {
return i.second->fd() ==
fd; } );
429 error() <<
"unknown file descriptor \"" <<
fd <<
"\" when calling close()" <<
endmsg;
433 IoTech tech = itr->second->tech();
437 if ( getHandler( tech, fh ).isFailure() ) {
442 error() <<
"no close(" << tech <<
",Fd) function registered" <<
endmsg;
449 auto fitr = m_files.equal_range( fa->
name() );
450 int i =
std::count_if( fitr.first, fitr.second, [&]( fileMap::const_reference f ) { return f.second->fd() == fd; } );
458 debug() <<
"closing file " << fa->
name() <<
" opened " << i <<
" times with Fd " <<
fd <<
endmsg;
459 m_files.erase( itr );
463 }
else if ( i == 1 || ( i > 1 && !fa->
isShared() ) ) {
465 debug() <<
"closing " << *fa <<
endmsg;
470 error() <<
"when calling close handler for " << tech <<
" on file descriptor " <<
fd <<
" caught " << err.
what()
475 error() <<
"when calling close handler for " << tech <<
" on file descriptor " <<
fd 476 <<
" caught an unknown exception." <<
endmsg;
482 warning() <<
"close of file with FD \"" <<
fd <<
"\", name: \"" << fa->
name() <<
"\", tech: \"" << tech
490 m_files.erase( itr );
492 }
else if ( i <= 0 ) {
494 error() <<
"ref count < 0 when closing " << fa <<
". This should never happen" <<
endmsg;
502 m_oldFiles.push_back( fa );
505 if ( execAction( fa, caller,
Io::CLOSE ).isFailure() ) {
506 warning() <<
"at least one close callback action failed" <<
endmsg;
528 [&]( fileMap::const_reference i ) {
return i.second->fptr() == vp; } );
530 if ( itr == m_files.end() ) {
531 error() <<
"unknown file ptr \"" << vp <<
"\" when calling close()" <<
endmsg;
535 IoTech tech = itr->second->tech();
539 if ( getHandler( tech, fh ).isFailure() ) {
543 error() <<
"no close(" << tech <<
",void*) function registered" <<
endmsg;
553 std::count_if( fitr.first, fitr.second, [&]( fileMap::const_reference f ) { return f.second->fptr() == vp; } );
561 debug() <<
"closing file " << fa->
name() <<
" opened " << i <<
" times with fptr " << vp <<
endmsg;
562 m_files.erase( itr );
566 }
else if ( i == 1 || ( i > 1 && !fa->
isShared() ) ) {
568 debug() <<
"closing: " << *fa <<
endmsg;
573 error() <<
"when calling close handler for " << tech <<
" on file " << fa->
name() <<
" caught " << err.
what()
575 execAction( fa, caller,
CLOSE_ERR ).ignore();
578 error() <<
"when calling close handler for " << tech <<
" on file " << fa->
name()
579 <<
" caught an unknown exception." <<
endmsg;
580 execAction( fa, caller,
CLOSE_ERR ).ignore();
585 warning() <<
"close of file with ptr \"" << vp <<
"\", name: \"" << fa->
name() <<
"\", tech: \"" << tech
591 m_files.erase( itr );
595 error() <<
"ref count: " << i <<
" < 0 when closing " << fa <<
". This should never happen" <<
endmsg;
603 m_oldFiles.push_back( fa );
606 if ( execAction( fa, caller,
CLOSE ).isFailure() ) {
607 warning() <<
"at least one close callback action failed" <<
endmsg;
619 verbose() <<
"reopen(" <<
fd <<
"," << flags <<
"," << caller <<
")" <<
endmsg;
624 [&]( fileMap::const_reference f ) {
return f.second->fd() ==
fd; } );
626 if ( itr == m_files.end() ) {
627 error() <<
"unregistered FD \"" <<
fd <<
"\" when calling reopen()" <<
endmsg;
636 if ( getHandler( tech, fh ).isFailure() ) {
643 error() <<
"no reopen(" << tech <<
",Fd) function registered" <<
endmsg;
652 error() <<
"when calling reopen handler for " << tech <<
" on file descriptor " <<
fd <<
" with flags " << flags
656 error() <<
"when calling reopen handler for " << tech <<
" on file descriptor " <<
fd <<
" with flags " << flags
657 <<
" caught an unknown exception." <<
endmsg;
662 warning() <<
"reopen of file with FD \"" <<
fd <<
"\", name: \"" << fa->
name() <<
"\", tech: \"" << tech
663 <<
"\", flags: \"" << flags <<
"\" failed" <<
endmsg;
674 if ( execAction( fa, caller,
Io::REOPEN ).isFailure() ) {
675 warning() <<
"at least one reopen callback action failed" <<
endmsg;
686 verbose() <<
"reopen(" << vp <<
"," << flags <<
"," << caller <<
")" <<
endmsg;
691 [&]( fileMap::const_reference f ) {
return f.second->fptr() == vp; } );
692 if ( itr == m_files.end() ) {
693 error() <<
"unregistered file ptr \"" << vp <<
"\" when calling reopen()" <<
endmsg;
701 if ( getHandler( tech, fh ).isFailure() ) {
706 error() <<
"no reopen(" << tech <<
",void*) function registered" <<
endmsg;
713 error() <<
"when calling reopen handler for " << tech <<
" on file " << fa->
name() <<
" with flags " << flags
717 error() <<
"when calling reopen handler for " << tech <<
" on file " << fa->
name() <<
" with flags " << flags
718 <<
" caught an unknown exception." <<
endmsg;
723 warning() <<
"reopen of file with ptr \"" << vp <<
"\", name: \"" << fa->
name() <<
"\", tech: \"" << tech
724 <<
"\", flags: \"" << flags <<
"\" failed" <<
endmsg;
735 if ( execAction( fa, caller,
Io::REOPEN ).isFailure() ) {
736 warning() <<
"at least one reopen callback action failed" <<
endmsg;
749 auto fitr = m_files.equal_range( fname );
753 [&](
const FileAttr* f ) {
return f->
name() == fname; } );
764 [&]( fileMap::const_reference f ) {
return f.second->fd() ==
fd; } );
772 if ( j !=
std::end( m_oldFiles ) ) {
786 [&]( fileMap::const_reference f ) {
return f.second->fptr() == vp; } );
794 if ( j !=
std::end( m_oldFiles ) ) {
837 if ( tech ==
UNKNOWN )
return getFiles( files, op );
841 [&]( fileMap::const_reference f ) {
842 return f.second->tech() == tech &&
844 [&](
const std::string& j ) {
return j == f.first; } );
862 if ( tech ==
UNKNOWN )
return getFiles( files, op );
864 auto matches_tech = [&](
const FileAttr* f ) {
return f->tech() == tech; };
885 auto matches_tech_and_flags = [&](
const FileAttr* f ) {
886 return ( f->tech() == tech || tech ==
UNKNOWN ) && f->flags() == flags;
891 [&]( fileMap::const_reference f ) {
return matches_tech_and_flags( f.second ) && not_in_files( f.first ); } );
894 [&](
const FileAttr* f ) {
return matches_tech_and_flags( f ) && not_in_files( f->
name() ); } );
906 auto matches_tech_and_flags = [&](
const FileAttr* f ) {
907 return ( f->tech() == tech || tech ==
UNKNOWN ) && f->
flags() == flags;
911 matches_tech_and_flags );
914 matches_tech_and_flags );
929 return m_descriptors.size();
940 if ( tech ==
UNKNOWN )
return getFd( fd );
957 transform_if( m_descriptors.begin(), m_descriptors.end(),
std::back_inserter( fd ), select1st,
959 return ( d.second->tech() == tech || tech ==
UNKNOWN ) && ( d.second->flags() == flags );
970 [&]( fileMap::const_reference f ) {
return f.second->fd() ==
fd; } );
971 return ( itr !=
std::end( m_files ) ) ? itr->second->name() : s_empty;
979 auto itr =
std::find_if( m_files.begin(), m_files.end(),
980 [&]( fileMap::const_reference f ) {
return f.second->fptr() == vp; } );
981 return itr != m_files.end() ? itr->second->name() : s_empty;
989 auto fitr = m_files.equal_range( fname );
990 auto itr =
std::find_if( fitr.first, fitr.second, []( fileMap::const_reference f ) { return f.second->fd() != -1; } );
991 return itr != fitr.second ? itr->second->fd() : -1;
999 auto itr =
std::find_if( m_files.begin(), m_files.end(),
1000 [&]( fileMap::const_reference f ) {
return f.second->fptr() == fptr; } );
1001 return itr != m_files.end() ? itr->second->fd() : -1;
1008 auto fitr = m_files.equal_range( fname );
1010 std::find_if( fitr.first, fitr.second, []( fileMap::const_reference f ) ->
bool { return f.second->fptr(); } );
1011 return itr != fitr.second ? itr->second->fptr() :
nullptr;
1019 auto itr =
std::find_if( m_files.begin(), m_files.end(),
1020 [&]( fileMap::const_reference f ) {
return f.second->fd() ==
fd; } );
1021 return itr != m_files.end() ? itr->second->fptr() :
nullptr;
1029 info() <<
"listing registered files [" << ( m_files.size() + m_oldFiles.size() ) <<
"]:" <<
endl;
1031 for (
auto& itr : m_files ) info() << itr.second <<
endl;
1032 for (
auto& it2 : m_oldFiles ) info() << *it2 <<
endl;
1051 auto itr = m_handlers.find( tech );
1052 if ( itr == m_handlers.end() ) {
1053 error() <<
"no handler for tech " << tech <<
" registered" <<
endmsg;
1065 auto fitr = m_files.equal_range( fname );
1066 if ( fitr.first == fitr.second ) {
1067 error() <<
"no file \"" << fname <<
"\" registered. Cannot determine tech" <<
endmsg;
1071 auto itr = fitr.first;
1072 IoTech tech = itr->second->tech();
1075 while ( itr != fitr.second ) {
1076 if ( itr->second->tech() != tech ) {
1077 error() <<
"multiple technologies registered for file \"" << fname <<
"\". Cannot determine handler" <<
endmsg;
1083 return getHandler( tech, hdlr );
1091 info() <<
"Listing registered handlers:" <<
endl;
1093 for (
const auto& itr : m_handlers ) info() <<
" " << itr.first <<
endl;
1123 info() <<
"listing registered actions" <<
endl;
1125 for (
const auto& iit : m_actions ) {
1130 info() <<
" --- Tech: ";
1132 info() <<
"ALL ---" <<
endl;
1134 info() << t <<
" ---" <<
endl;
1136 for (
const auto& iia : m ) {
1137 for (
const auto& it2 : iia.second ) {
1138 info() <<
" " << iia.first <<
" " << it2.second <<
endl;
1157 if ( itr != m_actions.end() && !itr->second.empty() ) {
1158 s1 = execActs( fa, caller, a, itr->second );
1161 itr = m_actions.find( tech );
1162 if ( itr != m_actions.end() && !itr->second.empty() ) {
1163 s2 = execActs( fa, caller, a, itr->second );
1175 auto mitr = m.
find( a );
1177 if ( mitr == m.
end() || mitr->second.empty() ) {
1182 debug() <<
"executing " << mitr->second.size() <<
" " << a <<
" actions on " << *fa <<
" from " << caller <<
endmsg;
1186 auto it2 = m_supMap.find( fa->
name() );
1187 if ( it2 != m_supMap.end() ) {
1190 debug() <<
" --> suppressing callback action for " << a <<
endmsg;
1195 for (
const auto& itr : mitr->second ) {
1198 debug() <<
"executing " << itr.second <<
endmsg;
1200 if ( ( ( ( itr.first ) )( fa, caller ) ).isFailure() ) {
1201 warning() <<
"execution of " << itr.second <<
" on " << *fa <<
" failed during " << a <<
" action" <<
endmsg;
1215 verbose() <<
"accessMatch old: " << fold <<
" new: " << fnew <<
endmsg;
1218 ( ( fold &
Io::WRITE ) != 0 && ( fnew & Io::WRITE ) != 0 ) ||
1219 ( ( fold &
Io::RDWR ) != 0 && ( fnew & Io::RDWR ) != 0 ) );
1230 auto set_bit = [](
int f,
unsigned int b ) {
return f | ( 1 << b ); };
1232 auto i = m_supMap.find( f );
1233 if ( i == m_supMap.end() ) {
1234 m_supMap.emplace( f, set_bit( 0, a ) );
1236 i->second = set_bit( i->second, a );
1245 if ( m_supMap.empty() )
return;
1247 info() <<
"listing suppressed file actions" <<
endl;
1249 for (
auto it2 = m_supMap.begin(); it2 != m_supMap.end(); ++it2 ) {
1250 info() <<
" " << it2->first;
1252 info() <<
" ALL" <<
endl;
1255 if ( get_bit( it2->second, i ) ) {
StatusCode regHandler(FileHdlr) override
void listHandlers() const override
StatusCode initialize() override
int getFileAttr(const std::string &, std::vector< const FileAttr * > &) const override
void listFiles() const override
StatusCode finalize() override
StatusCode hasHandler(const IoTech &) const override
GAUDI_API const std::string typeinfoName(const std::type_info &)
Get platform independent information about the class type.
Io::open_t open(const Io::IoTech &, const std::string &caller, const std::string &fname, const Io::IoFlags &, Io::Fd &fd, void *&ptr, const std::string &desc="", const bool shared=false) override
bfcn_reopen_t b_reopen_fcn
void suppressAction(const std::string &) override
bool isSuccess() const
Test for a status code of SUCCESS.
int getFiles(std::vector< std::string > &, bool onlyOpen=true) const override
StatusCode deregHandler(const IoTech &) override
StatusCode execAction(Io::FileAttr *, const std::string &, const Io::Action &) const
bool isFailure() const
Test for a status code of FAILURE.
bool accessMatch(const Io::IoFlags &, const Io::IoFlags &, bool strict=false) const
virtual void listActions() const
Io::Fd fd(const std::string &) const override
const std::string & name() const
void handle(const Incident &) override
StatusCode getHandler(const IoTech &, FileHdlr &) const override
This class is used for returning status codes from appropriate routines.
Io::reopen_t reopen(const Fd, const IoFlags &, const std::string &caller) override
StatusCode execActs(Io::FileAttr *, const std::string &, const Io::Action &, const actionMap &m) const
bfcn_closeP_t b_closeP_fcn
Io::close_t close(const Fd, const std::string &caller) override
bfcn_reopenP_t b_reopenP_fcn
#define DECLARE_SERVICE_FACTORY(x)
StatusCode regAction(Io::bfcn_action_t, const Io::Action &, const std::string &desc="") override
virtual Out operator()(const vector_of_const_< In > &inputs) const =0
virtual void listSuppression() const
bool match(const IoFlags &fa, bool strict=true) const
T back_inserter(T...args)
Base class for all Incidents (computing events).
const std::string & fname(const Io::Fd &) const override
int getFd(std::vector< Fd > &) const override
StatusCode finalize() override
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
StatusCode initialize() override
int getLastError(std::string &) const override
void * fptr(const std::string &) const override