32#include "XrdVersion.hh"
62 std::map<std::string, FactoryHelper*>::iterator it;
63 for( it = pFactoryMap.begin(); it != pFactoryMap.end(); ++it )
65 it->second->counter--;
66 if( it->second->counter == 0 )
70 delete pDefaultFactory;
82 std::string normUrl = NormalizeURL( url );
86 std::map<std::string, FactoryHelper*>::iterator it;
87 it = pFactoryMap.find( normUrl );
88 if( it != pFactoryMap.end() )
90 if( it->second->isEnv )
103 pFactoryMap.erase( it );
110 FactoryHelper *h =
new FactoryHelper();
111 h->factory = factory;
113 pFactoryMap[normUrl] = h;
125 if( pDefaultFactory && pDefaultFactory->isEnv )
128 delete pDefaultFactory;
134 pDefaultFactory =
new FactoryHelper;
135 pDefaultFactory->factory = factory;
150 if( pDefaultFactory && pDefaultFactory->isEnv )
151 return pDefaultFactory->factory;
153 std::string normUrl = NormalizeURL( url );
154 if( normUrl.empty() )
156 if( pDefaultFactory )
157 return pDefaultFactory->factory;
161 std::map<std::string, FactoryHelper*>::iterator it;
162 it = pFactoryMap.find( normUrl );
163 if( it != pFactoryMap.end() && it->second->isEnv )
164 return it->second->factory;
166 std::string protocol =
URL( url ).GetProtocol();
167 std::map<std::string, FactoryHelper*>::iterator itProt;
168 itProt = pFactoryMap.find( protocol );
169 if( itProt != pFactoryMap.end() && itProt->second->isEnv )
170 return itProt->second->factory;
172 if( pDefaultFactory )
173 return pDefaultFactory->factory;
175 if( it != pFactoryMap.end() )
176 return it->second->factory;
178 if( itProt != pFactoryMap.end() )
179 return itProt->second->factory;
198 bool loadConfigs =
true;
200 env->
GetString(
"PlugIn", defaultPlugIn );
201 if( !defaultPlugIn.empty() )
205 defaultPlugIn.c_str());
207 std::pair<XrdOucPinLoader*, PlugInFactory *> pg = LoadFactory(
208 defaultPlugIn, std::map<std::string, std::string>() );
213 defaultPlugIn.c_str());
217 pDefaultFactory =
new FactoryHelper();
218 pDefaultFactory->factory = pg.second;
219 pDefaultFactory->plugin = pg.first;
220 pDefaultFactory->isEnv =
true;
230 "No default plug-in, loading plug-in configs..." );
232 std::vector<std::string> dirs;
235 env->
GetString(
"PlugInConfDir", customPlugIns );
236 if( !customPlugIns.empty() )
237 dirs.push_back( customPlugIns );
240 passwd *pwd = pwdHandler.
Get( getuid() );
242 dirs.push_back( std::string( pwd->pw_dir ) +
"/.xrootd/client.plugins.d" );
244 dirs.push_back(
"/etc/xrootd/client.plugins.d" );
246 ProcessConfigDirs( dirs );
253 void PlugInManager::ProcessConfigDirs(
const std::vector<std::string> &dirs )
255 std::set<std::string> settled;
256 for(
const auto &dir : dirs )
257 ProcessConfigDir( dir, settled );
263 void PlugInManager::ProcessConfigDir(
const std::string &dir )
265 std::set<std::string> settled;
266 ProcessConfigDir( dir, settled );
272 void PlugInManager::ProcessConfigDir(
const std::string &dir,
273 std::set<std::string> &settled )
276 log->Debug(
PlugInMgrMsg,
"Processing plug-in definitions in %s...",
279 std::vector<std::string> entries;
280 std::vector<std::string>::iterator it;
284 log->Debug(
PlugInMgrMsg,
"Unable to process directory %s: %s",
285 dir.c_str(), st.ToString().c_str() );
288 std::sort( entries.begin(), entries.end() );
290 std::set<std::string> decided;
291 for( it = entries.begin(); it != entries.end(); ++it )
293 std::string confFile = dir +
"/" + *it;
294 std::string suffix =
".conf";
295 if( confFile.length() <= suffix.length() )
297 if( !std::equal( suffix.rbegin(), suffix.rend(), confFile.rbegin() ) )
300 ProcessPlugInConfig( confFile, settled, decided );
303 settled.insert( decided.begin(), decided.end() );
309 void PlugInManager::ProcessPlugInConfig(
const std::string &confFile )
311 std::set<std::string> settled, decided;
312 ProcessPlugInConfig( confFile, settled, decided );
318 void PlugInManager::ProcessPlugInConfig(
const std::string &confFile,
319 const std::set<std::string> &settled,
320 std::set<std::string> &decided )
323 log->Dump(
PlugInMgrMsg,
"Processing: %s", confFile.c_str() );
328 std::map<std::string, std::string> config;
332 log->Debug(
PlugInMgrMsg,
"Unable process config %s: %s",
333 confFile.c_str(), st.ToString().c_str() );
337 const char *keys[] = {
"url",
"lib",
"enable", 0 };
338 for(
int i = 0; keys[i]; ++i )
340 if( config.find( keys[i] ) == config.end() )
342 log->Debug(
PlugInMgrMsg,
"Unable to find '%s' key in the config file "
343 "%s, ignoring this config", keys[i], confFile.c_str() );
351 std::string url = config[
"url"];
352 std::string lib = config[
"lib"];
353 std::string enable = config[
"enable"];
355 log->Dump(
PlugInMgrMsg,
"Settings from '%s': url='%s', lib='%s', "
356 "enable='%s'", confFile.c_str(), url.c_str(), lib.c_str(),
362 std::vector<std::string> tokens;
364 tokens.push_back( url );
368 std::vector<std::string> normURLs;
370 for(
const auto &token : tokens )
372 std::string key = token ==
"*" ? token : NormalizeURL( token );
373 if( settled.count( key ) )
375 log->Debug(
PlugInMgrMsg,
"Skipping %s for '%s', set by a directory "
376 "with higher priority", lib.c_str(), token.c_str() );
379 normURLs.push_back( key );
388 std::pair<XrdOucPinLoader*, PlugInFactory *> pg;
389 pg.first = 0; pg.second = 0;
390 if( enable ==
"true" )
392 log->Debug(
PlugInMgrMsg,
"Trying to load a plug-in for '%s' from '%s'",
393 urls.c_str(), lib.c_str() );
395 pg = LoadFactory( lib, config );
401 log->Debug(
PlugInMgrMsg,
"Trying to disable plug-in for '%s'",
404 decided.insert( normURLs.begin(), normURLs.end() );
416 std::pair<XrdOucPinLoader*,PlugInFactory*> PlugInManager::LoadFactory(
417 const std::string &lib,
const std::map<std::string, std::string> &config )
422 if( lib ==
"XrdEcDefault" )
424 auto itr = config.find(
"nbdta" );
425 if( itr == config.end() )
426 return std::make_pair<XrdOucPinLoader*, PlugInFactory*>(
nullptr,
nullptr );
427 uint8_t nbdta = std::stoul( itr->second );
428 itr = config.find(
"nbprt" );
429 if( itr == config.end() )
430 return std::make_pair<XrdOucPinLoader*, PlugInFactory*>(
nullptr,
nullptr );
431 uint8_t nbprt = std::stoul( itr->second );
432 itr = config.find(
"chsz" );
433 if( itr == config.end() )
434 return std::make_pair<XrdOucPinLoader*, PlugInFactory*>(
nullptr,
nullptr );
435 uint64_t chsz = std::stoul( itr->second );
436 std::vector<std::string> plgr;
437 itr = config.find(
"plgr" );
438 if( itr != config.end() )
441 std::string xrdclECenv = std::to_string(nbdta) +
"," +
442 std::to_string(nbprt) +
"," +
443 std::to_string(chsz);
444 setenv(
"XRDCL_EC", xrdclECenv.c_str(), 1);
446 EcPlugInFactory *ecHandler =
new EcPlugInFactory( nbdta, nbprt, chsz, std::move( plgr ) );
447 return std::make_pair<XrdOucPinLoader*, PlugInFactory*>(
nullptr, ecHandler );
451 char errorBuff[1024];
453 &XrdVERSIONINFOVAR( XrdCl ),
454 "client", lib.c_str() );
456 PlugInFunc_t pgFunc = (PlugInFunc_t)pgHandler->
Resolve(
"XrdClGetPlugIn", -1);
460 log->Debug(
PlugInMgrMsg,
"Error while loading %s: %s", lib.c_str(),
464 return std::make_pair<XrdOucPinLoader*, PlugInFactory*>( 0, 0 );
467 PlugInFactory *f = (PlugInFactory*)pgFunc( &config );
472 return std::make_pair<XrdOucPinLoader*, PlugInFactory*>( 0, 0 );
475 return std::make_pair( pgHandler, f );
482 const std::string &lib,
484 XrdOucPinLoader *plugin )
490 std::vector<std::string> urls;
491 std::vector<std::string> normalizedURLs;
492 std::vector<std::string>::iterator it;
494 if (urlString ==
"*") {
495 if (pDefaultFactory) {
496 if (pDefaultFactory->isEnv) {
497 log->Debug(
PlugInMgrMsg,
"There is already an env default plugin "
498 "loaded, skipping %s", lib.c_str());
501 log->Debug(
PlugInMgrMsg,
"There can be only one default plugin "
502 "loaded, skipping %s", lib.c_str());
505 }
else if (!factory) {
509 log->Debug(
PlugInMgrMsg,
"No default plugin loaded, nothing to "
510 "disable for %s", lib.c_str());
513 pDefaultFactory =
new FactoryHelper();
514 pDefaultFactory->factory = factory;
515 pDefaultFactory->plugin = plugin;
516 pDefaultFactory->isEnv =
false;
523 for( it = urls.begin(); it != urls.end(); ++it )
525 std::string normURL = NormalizeURL( *it );
528 log->Debug(
PlugInMgrMsg,
"Url cannot be normalized: '%s', ignoring",
532 normalizedURLs.push_back( normURL );
535 std::sort( normalizedURLs.begin(), normalizedURLs.end() );
537 auto last = std::unique( normalizedURLs.begin(), normalizedURLs.end() );
538 normalizedURLs.erase( last, normalizedURLs.end() );
540 if( normalizedURLs.empty() )
546 FactoryHelper *h = 0;
550 h =
new FactoryHelper();
552 h->counter = normalizedURLs.size();
554 h->factory = factory;
557 std::map<std::string, FactoryHelper*>::iterator mapIt;
558 for( it = normalizedURLs.begin(); it != normalizedURLs.end(); ++it )
560 mapIt = pFactoryMap.find( *it );
561 if( mapIt != pFactoryMap.end() )
563 mapIt->second->counter--;
564 if( mapIt->second->counter == 0 )
565 delete mapIt->second;
570 log->Debug(
PlugInMgrMsg,
"Registering a factory for %s from %s",
571 it->c_str(), lib.c_str() );
572 pFactoryMap[*it] = h;
576 if( mapIt != pFactoryMap.end() )
578 log->Debug(
PlugInMgrMsg,
"Removing the factory for %s",
580 pFactoryMap.erase( mapIt );
591 std::string PlugInManager::NormalizeURL(
const std::string url )
594 if( !urlObj.IsValid() )
597 std::string protocol = urlObj.GetProtocol();
598 std::string hostname = urlObj.GetHostName();
600 if( hostname ==
"*" )
603 std::ostringstream o;
604 o << protocol <<
"://" << hostname <<
":";
605 o << urlObj.GetPort();
static Log * GetLog()
Get default log.
static Env * GetEnv()
Get default client environment.
EcPlugInFactory(uint8_t nbdta, uint8_t nbprt, uint64_t chsz, std::vector< std::string > &&plgr)
Constructor.
bool GetString(const std::string &key, std::string &value)
void Debug(uint64_t topic, const char *format,...)
Print a debug message.
void ProcessEnvironmentSettings()
bool RegisterFactory(const std::string &url, PlugInFactory *factory)
PlugInManager()
Constructor.
bool RegisterDefaultFactory(PlugInFactory *factory)
Register a plug-in factory applying to all URLs.
~PlugInManager()
Destructor.
PlugInFactory * GetFactory(const std::string url)
URL()
Default constructor.
static Status ProcessConfig(std::map< std::string, std::string > &config, const std::string &file)
Process a config file and return key-value pairs.
static void splitString(Container &result, const std::string &input, const std::string &delimiter)
Split a string.
static Status GetDirectoryEntries(std::vector< std::string > &entries, const std::string &path)
Get directory entries.
XrdOucPinLoader(XrdSysError *errP, XrdVersionInfo *vInfo, const char *drctv, const char *plib)
void * Resolve(const char *symbl, int mcnt=1)
void Unload(bool dodel=false)
struct passwd * Get(const char *Usr)
const char *const DefaultPlugIn
const char *const DefaultPlugInConfDir
const uint64_t PlugInMgrMsg