17 #define ON_DEBUG if ( msgLevel( MSG::DEBUG ) )
18 #define ON_VERBOSE if ( msgLevel( MSG::VERBOSE ) )
31 constexpr
struct to_name_t {
36 const auto select1st = [](
auto&& x ) -> decltype(
auto ) {
return std::get<0>(
std::forward<decltype( x )>( x ) ); };
38 const auto select2nd = [](
auto&& x ) -> decltype(
auto ) {
return std::get<1>(
std::forward<decltype( x )>( x ) ); };
40 template <
typename InputIterator,
typename OutputIterator,
typename UnaryOperation,
typename UnaryPredicate>
41 OutputIterator transform_if( InputIterator first, InputIterator last, OutputIterator result, UnaryOperation op,
42 UnaryPredicate pred ) {
43 while ( first != last ) {
44 if ( pred( *first ) ) *result++ = op( *first );
50 template <
typename InputIterator,
typename OutputIterator,
typename UnaryOperation,
typename UnaryPredicate>
51 OutputIterator transform_copy_if( InputIterator first, InputIterator last, OutputIterator result, UnaryOperation op,
52 UnaryPredicate pred ) {
53 while ( first != last ) {
54 auto t = op( *first );
77 debug() <<
"Failed to initialize the base class (Service)" <<
endmsg;
84 if ( m_loadRootHandler.value() ) {
88 msgSvc()->setOutputLevel(
"RootFileHandler", m_outputLevel.value() );
89 m_rfh.emplace(
msgSvc(), m_ssl_proxy, m_ssl_cert );
91 auto& rfh = m_rfh.value();
95 void*& ptr ) ->
Io::open_t {
return rfh.openRootFile(
n, f, desc,
fd, ptr ); },
96 [&rfh](
void* ptr ) ->
Io::close_t {
return rfh.closeRootFile( ptr ); },
99 if ( regHandler( hdlr ).isFailure() ) { 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();
113 void*& ptr ) ->
Io::open_t {
return pfh.openPOSIXFile(
n, f, desc,
fd, ptr ); },
117 if ( regHandler( hdlp ).isFailure() ) { error() <<
"unable to register ROOT file handler with FileMgr" <<
endmsg; }
129 if ( m_printSummary || msgLevel(
MSG::DEBUG ) ) {
136 if ( !m_files.empty() ) {
137 auto&
log = warning();
138 log <<
"At finalize, the following files remained open:\n";
139 for (
const auto& itr : m_files )
log << *( itr.second ) <<
'\n';
143 if ( m_logfile.value() !=
"" ) {
145 ofs.
open( m_logfile.value().c_str() );
147 error() <<
"Unable to open output file \"" << m_logfile.value() <<
"\" for writing" <<
endmsg;
150 debug() <<
"Saving log to \"" << m_logfile.value() <<
"\"" <<
endmsg;
151 for (
const auto& itr : m_files ) {
152 ofs << itr.second->name() <<
" " << itr.second->tech() <<
" " << itr.second->desc() <<
" "
153 << itr.second->iflags() <<
'\n';
157 for (
const auto& it2 : m_oldFiles ) fs.
insert( *it2 );
158 for (
const auto& it3 : fs ) {
159 ofs << it3.name() <<
" " << it3.tech() <<
" " << it3.desc() <<
" " << it3.iflags()
160 << ( it3.isShared() ?
" SHARED" :
"" ) <<
'\n';
175 if ( status.
isSuccess() ) debug() <<
"Service finalised successfully" <<
endmsg;
190 if ( m_handlers.find( tech ) != m_handlers.end() ) {
191 warning() <<
"Handler for IoTech " << tech <<
" already registered. Ignoring." <<
endmsg;
196 error() <<
"open handler for tech " << tech <<
" is NULL" <<
endmsg;
201 error() <<
"no close handler for tech " << tech <<
" registered" <<
endmsg;
206 error() <<
"no reopen handler for tech " << tech <<
" registered" <<
endmsg;
211 debug() <<
"Successfully registered handler for tech \"" << tech <<
"\"" <<
endmsg;
213 m_handlers[tech] = fh;
223 auto itr = m_handlers.find( tech );
224 if ( itr == m_handlers.end() ) {
225 error() <<
"Can't de-register tech " << tech <<
" as it hasn't been registered!" <<
endmsg;
229 m_handlers.erase( itr );
236 auto itr = m_handlers.find( tech );
245 return open( tech, caller, fname, desc, flags,
fd, ptr, sh );
253 return open( tech, caller, fname, desc, flags,
fd, dummy, sh );
261 return open( tech, caller, fname, desc, flags, dummy, ptr, sh );
267 const IoFlags& flags,
Fd&
fd,
void*& ptr,
bool shared ) {
285 verbose() <<
"open(" << tech <<
"," << caller <<
",\"" << fname <<
"\",\"" << desc <<
"\"," << flags
286 << ( shared ?
",shared" :
",unshared" ) <<
")" <<
endmsg;
290 if ( getHandler( tech, fh ).isFailure() )
return r;
292 auto fitr = m_files.equal_range( fname );
297 std::find_if( fitr.first, fitr.second, [&]( fileMap::const_reference i ) { return i.second->tech() != tech; } );
298 if ( itr != fitr.second ) {
299 error() <<
"when calling open on " << fname <<
" with tech " << tech <<
", file already opened with different tech "
300 << itr->second->tech() <<
endmsg;
309 bool shareable(
true );
311 for (
auto itr = fitr.first; itr != fitr.second; ++itr ) {
314 if ( !fa->
isShared() ) shareable =
false;
317 if ( shareable && fa->
flags().
match( flags,
false ) ) {
320 debug() <<
" found shared file: " << *fa <<
endmsg;
341 error() <<
"when calling open handler for " << tech <<
" on file " << fname <<
" caught " << err.
what() <<
endmsg;
344 error() <<
"when calling open handler for " << tech <<
" on file " << fname <<
" caught an unknown exception."
350 warning() <<
"open of file \"" << fname <<
"\", tech: \"" << tech <<
"\", flags: \"" << flags
351 <<
"\" requested by " << caller <<
" failed. return code: " << r <<
endmsg;
353 FileAttr xfa( -1, fname, desc, tech, flags, 0,
false );
366 debug() <<
"opened file " << *fa <<
endmsg;
368 if (
fd == -1 && ptr == 0 ) {
369 warning() <<
"when opening " << *fa <<
" both File Descriptor"
370 <<
" and File Ptr are invalid" <<
endmsg;
374 for (
auto itr = fitr.first; itr != fitr.second; ++itr ) {
377 }
else if ( *fa == *( itr->second ) ) {
378 warning() <<
"open call for file \"" << fname <<
"\" returned a pre-existing file with identical"
379 <<
" FileAttributes: " << *fa <<
endmsg;
382 warning() <<
"open call for file \"" << fname <<
"\" returned a pre-existing file with different"
383 <<
" FileAttributes -\n"
384 <<
"old: " << *( itr->second ) <<
'\n'
385 <<
"new: " << *fa <<
endmsg;
390 m_files.emplace( fname, fa );
393 if ( execAction( fa, caller,
Io::OPEN ).isFailure() ) {
394 warning() <<
"at least one open callback action failed" <<
endmsg;
416 [&]( fileMap::const_reference i ) {
return i.second->fd() ==
fd; } );
419 error() <<
"unknown file descriptor \"" <<
fd <<
"\" when calling close()" <<
endmsg;
423 IoTech tech = itr->second->tech();
427 if ( getHandler( tech, fh ).isFailure() ) {
return r; }
430 error() <<
"no close(" << tech <<
",Fd) function registered" <<
endmsg;
437 auto fitr = m_files.equal_range( fa->
name() );
438 int i =
std::count_if( fitr.first, fitr.second, [&]( fileMap::const_reference f ) { return f.second->fd() == fd; } );
446 debug() <<
"closing file " << fa->
name() <<
" opened " << i <<
" times with Fd " <<
fd <<
endmsg;
447 m_files.erase( itr );
451 }
else if ( i == 1 || ( i > 1 && !fa->
isShared() ) ) {
453 debug() <<
"closing " << *fa <<
endmsg;
458 error() <<
"when calling close handler for " << tech <<
" on file descriptor " <<
fd <<
" caught " << err.
what()
463 error() <<
"when calling close handler for " << tech <<
" on file descriptor " <<
fd
464 <<
" caught an unknown exception." <<
endmsg;
470 warning() <<
"close of file with FD \"" <<
fd <<
"\", name: \"" << fa->
name() <<
"\", tech: \"" << tech
478 m_files.erase( itr );
480 }
else if ( i <= 0 ) {
482 error() <<
"ref count < 0 when closing " << fa <<
". This should never happen" <<
endmsg;
490 m_oldFiles.push_back( fa );
493 if ( execAction( fa, caller,
Io::CLOSE ).isFailure() ) {
494 warning() <<
"at least one close callback action failed" <<
endmsg;
515 [&]( fileMap::const_reference i ) {
return i.second->fptr() == vp; } );
517 if ( itr == m_files.end() ) {
518 error() <<
"unknown file ptr \"" << vp <<
"\" when calling close()" <<
endmsg;
522 IoTech tech = itr->second->tech();
526 if ( getHandler( tech, fh ).isFailure() ) {
return r; }
528 error() <<
"no close(" << tech <<
",void*) function registered" <<
endmsg;
538 std::count_if( fitr.first, fitr.second, [&]( fileMap::const_reference f ) { return f.second->fptr() == vp; } );
546 debug() <<
"closing file " << fa->
name() <<
" opened " << i <<
" times with fptr " << vp <<
endmsg;
547 m_files.erase( itr );
551 }
else if ( i == 1 || ( i > 1 && !fa->
isShared() ) ) {
553 debug() <<
"closing: " << *fa <<
endmsg;
558 error() <<
"when calling close handler for " << tech <<
" on file " << fa->
name() <<
" caught " << err.
what()
560 execAction( fa, caller,
CLOSE_ERR ).ignore();
563 error() <<
"when calling close handler for " << tech <<
" on file " << fa->
name()
564 <<
" caught an unknown exception." <<
endmsg;
565 execAction( fa, caller,
CLOSE_ERR ).ignore();
570 warning() <<
"close of file with ptr \"" << vp <<
"\", name: \"" << fa->
name() <<
"\", tech: \"" << tech
576 m_files.erase( itr );
580 error() <<
"ref count: " << i <<
" < 0 when closing " << fa <<
". This should never happen" <<
endmsg;
588 m_oldFiles.push_back( fa );
591 if ( execAction( fa, caller,
CLOSE ).isFailure() ) {
592 warning() <<
"at least one close callback action failed" <<
endmsg;
603 verbose() <<
"reopen(" <<
fd <<
"," << flags <<
"," << caller <<
")" <<
endmsg;
608 [&]( fileMap::const_reference f ) {
return f.second->fd() ==
fd; } );
610 if ( itr == m_files.end() ) {
611 error() <<
"unregistered FD \"" <<
fd <<
"\" when calling reopen()" <<
endmsg;
620 if ( getHandler( tech, fh ).isFailure() ) {
return r; }
625 error() <<
"no reopen(" << tech <<
",Fd) function registered" <<
endmsg;
634 error() <<
"when calling reopen handler for " << tech <<
" on file descriptor " <<
fd <<
" with flags " << flags
638 error() <<
"when calling reopen handler for " << tech <<
" on file descriptor " <<
fd <<
" with flags " << flags
639 <<
" caught an unknown exception." <<
endmsg;
644 warning() <<
"reopen of file with FD \"" <<
fd <<
"\", name: \"" << fa->
name() <<
"\", tech: \"" << tech
645 <<
"\", flags: \"" << flags <<
"\" failed" <<
endmsg;
656 if ( execAction( fa, caller,
Io::REOPEN ).isFailure() ) {
657 warning() <<
"at least one reopen callback action failed" <<
endmsg;
667 verbose() <<
"reopen(" << vp <<
"," << flags <<
"," << caller <<
")" <<
endmsg;
672 [&]( fileMap::const_reference f ) {
return f.second->fptr() == vp; } );
673 if ( itr == m_files.end() ) {
674 error() <<
"unregistered file ptr \"" << vp <<
"\" when calling reopen()" <<
endmsg;
682 if ( getHandler( tech, fh ).isFailure() ) {
return r; }
685 error() <<
"no reopen(" << tech <<
",void*) function registered" <<
endmsg;
692 error() <<
"when calling reopen handler for " << tech <<
" on file " << fa->
name() <<
" with flags " << flags
696 error() <<
"when calling reopen handler for " << tech <<
" on file " << fa->
name() <<
" with flags " << flags
697 <<
" caught an unknown exception." <<
endmsg;
702 warning() <<
"reopen of file with ptr \"" << vp <<
"\", name: \"" << fa->
name() <<
"\", tech: \"" << tech
703 <<
"\", flags: \"" << flags <<
"\" failed" <<
endmsg;
714 if ( execAction( fa, caller,
Io::REOPEN ).isFailure() ) {
715 warning() <<
"at least one reopen callback action failed" <<
endmsg;
727 auto fitr = m_files.equal_range( fname );
731 [&](
const FileAttr* f ) {
return f->
name() == fname; } );
741 [&]( fileMap::const_reference f ) {
return f.second->fd() ==
fd; } );
762 [&]( fileMap::const_reference f ) {
return f.second->fptr() == vp; } );
808 if ( tech ==
UNKNOWN )
return getFiles( files, op );
812 [&]( fileMap::const_reference f ) {
813 return f.second->tech() == tech &&
832 if ( tech ==
UNKNOWN )
return getFiles( files, op );
834 auto matches_tech = [&](
const FileAttr* f ) {
return f->
tech() == tech; };
854 auto matches_tech_and_flags = [&](
const FileAttr* f ) {
860 [&]( fileMap::const_reference f ) {
return matches_tech_and_flags( f.second ) && not_in_files( f.first ); } );
863 [&](
const FileAttr* f ) {
return matches_tech_and_flags( f ) && not_in_files( f->
name() ); } );
874 auto matches_tech_and_flags = [&](
const FileAttr* f ) {
879 matches_tech_and_flags );
882 matches_tech_and_flags );
896 return m_descriptors.size();
906 if ( tech ==
UNKNOWN )
return getFd(
fd );
924 return ( d.second->tech() == tech || tech == UNKNOWN ) && ( d.second->flags() == flags );
934 [&]( fileMap::const_reference f ) {
return f.second->fd() ==
fd; } );
935 return ( itr !=
std::end( m_files ) ) ? itr->second->name() : s_empty;
942 auto itr =
std::find_if( m_files.begin(), m_files.end(),
943 [&]( fileMap::const_reference f ) { return f.second->fptr() == vp; } );
944 return itr != m_files.end() ? itr->second->name() : s_empty;
951 auto fitr = m_files.equal_range( fname );
952 auto itr =
std::find_if( fitr.first, fitr.second, []( fileMap::const_reference f ) { return f.second->fd() != -1; } );
953 return itr != fitr.second ? itr->second->fd() : -1;
960 auto itr =
std::find_if( m_files.begin(), m_files.end(),
961 [&]( fileMap::const_reference f ) { return f.second->fptr() == fptr; } );
962 return itr != m_files.end() ? itr->second->fd() : -1;
968 auto fitr = m_files.equal_range( fname );
970 std::find_if( fitr.first, fitr.second, []( fileMap::const_reference f ) ->
bool { return f.second->fptr(); } );
971 return itr != fitr.second ? itr->second->fptr() :
nullptr;
978 auto itr =
std::find_if( m_files.begin(), m_files.end(),
979 [&]( fileMap::const_reference f ) { return f.second->fd() == fd; } );
980 return itr != m_files.end() ? itr->second->fptr() :
nullptr;
987 info() <<
"listing registered files [" << ( m_files.size() + m_oldFiles.size() ) <<
"]:\n";
989 for (
auto& itr : m_files ) info() << itr.second <<
'\n';
990 for (
auto& it2 : m_oldFiles ) info() << *it2 <<
'\n';
1007 auto itr = m_handlers.find( tech );
1008 if ( itr == m_handlers.end() ) {
1009 error() <<
"no handler for tech " << tech <<
" registered" <<
endmsg;
1020 auto fitr = m_files.equal_range( fname );
1021 if ( fitr.first == fitr.second ) {
1022 error() <<
"no file \"" << fname <<
"\" registered. Cannot determine tech" <<
endmsg;
1026 auto itr = fitr.first;
1027 IoTech tech = itr->second->tech();
1030 while ( itr != fitr.second ) {
1031 if ( itr->second->tech() != tech ) {
1032 error() <<
"multiple technologies registered for file \"" << fname <<
"\". Cannot determine handler" <<
endmsg;
1038 return getHandler( tech, hdlr );
1045 info() <<
"Listing registered handlers:\n";
1047 for (
const auto& itr : m_handlers ) info() <<
" " << itr.first <<
'\n';
1074 info() <<
"listing registered actions\n";
1076 for (
const auto& iit : m_actions ) {
1081 info() <<
" --- Tech: ";
1083 info() <<
"ALL ---\n";
1085 info() <<
t <<
" ---\n";
1087 for (
const auto& iia :
m ) {
1088 for (
const auto& it2 : iia.second ) { info() <<
" " << iia.first <<
" " << it2.second <<
'\n'; }
1105 if ( itr != m_actions.end() && !itr->second.empty() ) {
s1 = execActs( fa, caller, a, itr->second ); }
1107 itr = m_actions.find( tech );
1108 if ( itr != m_actions.end() && !itr->second.empty() ) {
s2 = execActs( fa, caller, a, itr->second ); }
1118 auto mitr =
m.find( a );
1122 debug() <<
"executing " << mitr->second.size() <<
" " << a <<
" actions on " << *fa <<
" from " << caller <<
endmsg;
1126 auto it2 = m_supMap.find( fa->
name() );
1127 if ( it2 != m_supMap.end() ) {
1130 debug() <<
" --> suppressing callback action for " << a <<
endmsg;
1135 for (
const auto& itr : mitr->second ) {
1138 debug() <<
"executing " << itr.second <<
endmsg;
1140 if ( ( ( ( itr.first ) )( fa, caller ) ).isFailure() ) {
1141 warning() <<
"execution of " << itr.second <<
" on " << *fa <<
" failed during " << a <<
" action" <<
endmsg;
1153 verbose() <<
"accessMatch old: " << fold <<
" new: " << fnew <<
endmsg;
1171 if ( m_supMap.empty() )
return;
1173 info() <<
"listing suppressed file actions\n";
1175 for (
const auto& sup : m_supMap ) {
1176 info() <<
" " << sup.first;
1180 for (
unsigned i = 0; i != sup.second.size(); ++i ) {
1181 if ( sup.second[i] ) info() <<
" " << (
Io::Action)i;