XRootD
XrdSysPlugin Class Reference

#include <XrdSysPlugin.hh>

+ Collaboration diagram for XrdSysPlugin:

Public Member Functions

 XrdSysPlugin (char *ebuff, int eblen, const char *path, const char *lname, XrdVersionInfo *vinf=0, int msgNum=-1)
 
 XrdSysPlugin (XrdSysError *erp, const char *path)
 
 XrdSysPlugin (XrdSysError *erp, const char *path, const char *lname, XrdVersionInfo *vinf=0, int msgNum=-1)
 
 ~XrdSysPlugin ()
 Destructor. More...
 
void * getLibrary (bool allMsgs=true, bool global=false)
 
void * getPlugin (const char *pname, int optional, bool global)
 
void * getPlugin (const char *pname, int optional=0)
 
void * Persist ()
 

Static Public Member Functions

static bool Preload (const char *path, char *ebuff=0, int eblen=0)
 
static bool VerCmp (XrdVersionInfo &vInf1, XrdVersionInfo &vInf2, bool noMsg=false)
 

Detailed Description

Handy class to load run-time plugins and optionally check if the version is compatible with the caller's version number. Version numbers are defined as "aaa.bb.cc" where aaa is a decimnal major version, bb is a decimal minor version, and cc is the decimal patch version number. Only the major and, optionally, minor version numbers are checked. The checking rules are defined in XrdVersion.hh and are rather liberal in nature. In order to check versions, the plugin versioning rule must be defined in XrdVersion.hh and constructor #2 or #3 must be used. The symbolic name of the plugin's version information is the plugin symbol being looked up appended with "Version" and must be defined as an XrdVersionInfo structure.

Definition at line 52 of file XrdSysPlugin.hh.

Constructor & Destructor Documentation

◆ XrdSysPlugin() [1/3]

XrdSysPlugin::XrdSysPlugin ( XrdSysError erp,
const char *  path 
)
inline

Constructor #1 (version number checking is not to be performed)

Parameters
erp-> error message object to display error messages.
path-> path to the shared library containing a plug-in. If NULL the the executable image is searched for the plug-in. Storage must persist while this object is alive.

Definition at line 165 of file XrdSysPlugin.hh.

166  : eDest(erp), libName(0), libPath(path ? strdup(path) : 0),
167  libHandle(0), myInfo(0), eBuff(0), eBLen(0), msgCnt(-1) {}

◆ XrdSysPlugin() [2/3]

XrdSysPlugin::XrdSysPlugin ( XrdSysError erp,
const char *  path,
const char *  lname,
XrdVersionInfo *  vinf = 0,
int  msgNum = -1 
)
inline

Constructor #2 (version number checking may be performed)

Parameters
erp-> error message object to display error messages.
path-> path to the shared library containing a plug-in. If NULL the the executable image is searched for the plug-in. Storage must persist while this object is alive.
lname-> logical name of the plugin library (e.g. osslib) to be used in any error messages. Storage must persist while this object is alive.
vinf-> permanent version information of the plug-in loader. If zero, then no version checking is performed.
msgNum-> Number of times getPlugin() is to produce a version message for a loaded plugin. The default is always.

Definition at line 185 of file XrdSysPlugin.hh.

187  : eDest(erp), libName(lname),
188  libPath(path ? strdup(path) : 0), libHandle(0),
189  myInfo(vinf), eBuff(0), eBLen(0), msgCnt(msgNum) {}

◆ XrdSysPlugin() [3/3]

XrdSysPlugin::XrdSysPlugin ( char *  ebuff,
int  eblen,
const char *  path,
const char *  lname,
XrdVersionInfo *  vinf = 0,
int  msgNum = -1 
)
inline

Constructor #3 (version number checking may be performed and any error is returned in a supplied buffer)

Parameters
ebuff-> buffer where eror message is to be placed. The message will always end with a null byte.
eblen-> length of the supplied buffer, eBuff.
path-> path to the shared library containing a plug-in. If NULL the the executable image is searched for the plug-in. Storage must persist while this object is alive.
lname-> logical name of the plugin library (e.g. osslib) to be used in any error messages. Storage must persist while this object is alive.
vinf-> permanent version information of the plug-in loader. If Zero, then no version checking is performed.
msgNum-> Number of times getPlugin() is to produce a version message for a loaded plugin. The default is always.

Definition at line 210 of file XrdSysPlugin.hh.

212  : eDest(0), libName(lname),
213  libPath(path ? strdup(path) : 0), libHandle(0),
214  myInfo(vinf), eBuff(ebuff), eBLen(eblen), msgCnt(msgNum) {}

◆ ~XrdSysPlugin()

XrdSysPlugin::~XrdSysPlugin ( )

Destructor.

Definition at line 72 of file XrdSysPlugin.cc.

73 {
74  if (libHandle) dlclose(libHandle);
75  if (libPath) free(libPath);
76 }

Member Function Documentation

◆ getLibrary()

void * XrdSysPlugin::getLibrary ( bool  allMsgs = true,
bool  global = false 
)

Prepare shared library for use (optional call).

Parameters
allMsgsWhen true messages all messages are handled as directed by the constructor. Otherwise, only messages regarding ENOENT (file not found ) are suppressed.
globalwhen true then the symbols defined in the plug-in shared library are made available for symbol resolution of subsequently loaded libraries.
Returns
!0 Library successfully prepared. =0 Library cannot be prepared; if mBuff is supplied, it contains the error message. If the file was not found, errno is set to ENOENT; otherwise to ENOEXEC.
Note
This method is implicitly called when calling getPlugin().

Definition at line 255 of file XrdSysPlugin.cc.

256 {
257  void *myHandle;
258  int flags;
259 
260 // Check if we should use the preload list
261 //
262  if (!(myHandle = libHandle) && plList) myHandle = Find(libPath);
263 
264 // If already open, return the handle
265 //
266  if (myHandle) return myHandle;
267 
268 // If no path is given then we want to just search the executable. This is easy
269 // for some platforms and more difficult for others. So, we do the best we can.
270 //
271  if (libPath) flags = DLflags();
272  else { flags = RTLD_NOW;
273 #ifndef WIN32
274  flags|= global ? RTLD_GLOBAL : RTLD_LOCAL;
275 #else
276  if (global && eDest) eDest->Emsg("getPlugin",
277  "request for global symbols unsupported under Windows - ignored");
278 #endif
279  }
280 
281 // Try to open this library or the executable image
282 //
283  if ((myHandle = dlopen(libPath, flags))) libHandle = myHandle;
284  else {const char *eTxt = dlerror();
285  if (strcasestr(eTxt, "no such file")) errno = ENOENT;
286  else errno = ENOEXEC;
287  if (allMsgs || errno != ENOENT) libMsg(eTxt, " loading ");
288  }
289 
290 // All done
291 //
292  return myHandle;
293 }
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
Definition: XrdSysError.cc:95

References eDest, and XrdSysError::Emsg().

Referenced by getPlugin().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ getPlugin() [1/2]

void * XrdSysPlugin::getPlugin ( const char *  pname,
int  optional,
bool  global 
)

Get the address of a plugin from a shared library, opening the plug-in shared library if not already open and optionally make the symbols global.

Parameters
pnamethe plug-in extern "C" symbolic name
optionalwhen 0 then issue error message when symbol isn't found. Otherwise, the mising symbol is treated as an error. When optional is greater than 1, the load message is suppressed.
globalwhen true then the symbols defined in the plug-in shared library are made available for symbol resolution of subsequently loaded libraries.
Returns
Success: the address of the symbol in the shared library/executable. The address becomes invalid when this object is deleted unless Persist() is called prior to deletion. Failure: Null

Definition at line 304 of file XrdSysPlugin.cc.

305 {
306  XrdVERSIONINFODEF(urInfo, unknown, XrdVNUMUNK, "");
307  void *ep, *myHandle;
308  cvResult cvRC;
309 
310 // Open whatever it is we need to open
311 //
312  if (!(myHandle = getLibrary(optional < 2, global))) return 0;
313 
314 // Get the symbol. In the environment we have defined, null values are not
315 // allowed and we will issue an error.
316 //
317  if (!(ep = dlsym(myHandle, pname)))
318  {if (optional < 2) libMsg(dlerror(), " symbol %s in ", pname);
319  return 0;
320  }
321 
322 // Check if we need to verify version compatibility
323 //
324  if ((cvRC = chkVersion(urInfo, pname, myHandle)) == cvBad) return 0;
325 
326 // Print the loaded version unless message is suppressed or not needed
327 //
328  if (libPath && optional < 2 && msgCnt
329  && (cvRC == cvClean || cvRC == cvMissing))
330  {char buff[128];
331  msgSuffix(" from ", buff, sizeof(buff));
332  msgCnt--;
333  if (cvRC == cvClean)
334  {const char *wTxt=(urInfo.vNum == XrdVNUMUNK ? "unreleased ":"");
335  Inform("loaded ", wTxt, urInfo.vStr, buff, libPath);
336  }
337  else if (cvRC == cvMissing)
338  {Inform("loaded unversioned ", pname, buff, libPath);}
339  }
340 
341 // All done
342 //
343  return ep;
344 }
void * getLibrary(bool allMsgs=true, bool global=false)
XrdVERSIONINFODEF(myVersion, cmsclient, XrdVNUMBER, XrdVERSION)

References getLibrary(), and XrdCms::XrdVERSIONINFODEF().

+ Here is the call graph for this function:

◆ getPlugin() [2/2]

void * XrdSysPlugin::getPlugin ( const char *  pname,
int  optional = 0 
)

Get the address of a plugin from a shared library, opening the plug-in shared library if not already open. Symbols in the library are local.

Parameters
pnamethe plug-in extern "C" symbolic name
optionalwhen 0 then issue error message when symbol isn't found. Otherwise, the mising symbol is treated as an error.
Returns
Success: the address of the symbol in the shared library/executable. The address becomes invalid when this object is deleted unless Persist() is called prior to deletion. Failure: Null

Definition at line 299 of file XrdSysPlugin.cc.

300 {
301  return getPlugin(pname, optional, false);
302 }
void * getPlugin(const char *pname, int optional=0)

Referenced by LoadFS(), and XrdOucPinLoader::Resolve().

+ Here is the caller graph for this function:

◆ Persist()

void* XrdSysPlugin::Persist ( )
inline

Make library persistent even when the plugin object is deleted. Note that if getPlugin() is called afterwards, the library will be re-opened!

Returns
pointer to the opened shared library.

Definition at line 118 of file XrdSysPlugin.hh.

118 {void *lHan = libHandle; libHandle = 0; return lHan;}

Referenced by XrdOucPinLoader::~XrdOucPinLoader(), and LoadFS().

+ Here is the caller graph for this function:

◆ Preload()

bool XrdSysPlugin::Preload ( const char *  path,
char *  ebuff = 0,
int  eblen = 0 
)
static

Preload a shared library. This method is meant for those threading models that require libraries to be opened in the main thread (e.g. MacOS). This method is meant to be called before therads start and is not thread-safe.

Parameters
path-> to the library path, typically this should just be the library filename so that LD_LIBRARY_PATH is used to discover the directory path. This allows getPlugin() to properly match preloaded libraries.
ebuff-> buffer where eror message is to be placed. The message will always end with a null byte. If no error buffer is supplied, any error messages are discarded.
eblen-> length of the supplied buffer, eBuff.
Returns
True The library was preloaded. False The library could not be preloaded, ebuff, if supplied, contains the error message text.

Definition at line 435 of file XrdSysPlugin.cc.

436 {
437  struct PLlist *plP;
438  void *myHandle;
439 
440 // First see if this is already in the preload list
441 //
442  if (Find(path)) return true;
443 
444 // Try to open the library
445 //
446  if (!(myHandle = dlopen(path, DLflags())))
447  {if (ebuff && eblen > 0)
448  {const char *dlMsg = dlerror();
449  snprintf(ebuff, eblen, "Plugin unable to load %s; %s", path,
450  (dlMsg ? dlMsg : "unknown system error"));
451  }
452  return false;
453  }
454 
455 // Add the library handle
456 //
457  plP = new PLlist;
458  plP->libHandle = myHandle;
459  plP->libPath = strdup(path);
460  plP->next = plList;
461  plList = plP;
462 
463 // All done
464 //
465  return true;
466 }

Referenced by XrdOucPreload().

+ Here is the caller graph for this function:

◆ VerCmp()

bool XrdSysPlugin::VerCmp ( XrdVersionInfo &  vInf1,
XrdVersionInfo &  vInf2,
bool  noMsg = false 
)
static

Compare two versions for compatibility, optionally printing a warning.

Parameters
vInf1-> Version information for source.
vInf2-> Version information for target.
noMsg-> If true, no error messages are written to stderr.
Returns
True if versions are compatible (i.e. major and minor versions are identical as required for locally linked code); false otherwise.

Definition at line 472 of file XrdSysPlugin.cc.

474 {
475  const char *mTxt;
476  char v1buff[128], v2buff[128];
477  int unRel;
478 
479 // Do a quick return if the version need not be checked or are equal
480 //
481  if (vInfo1.vNum <= 0 || vInfo1.vNum == vInfo2.vNum) return true;
482 
483 // As it works out, many times two modules wind up in different shared
484 // libraries. For consistency we require that both major.minor version be the
485 // same unless either is unreleased (i.e. test). Issue warning if need be.
486 //
487  mTxt = (vInfo1.vNum == XrdVNUMUNK ? "unreleased " : "");
488  sprintf(v1buff, " %sversion %s", mTxt, vInfo1.vStr);
489  unRel = *mTxt;
490 
491  mTxt = (vInfo2.vNum == XrdVNUMUNK ? "unreleased " : "");
492  sprintf(v2buff, " %sversion %s", mTxt, vInfo2.vStr);
493  unRel |= *mTxt;
494 
495  if (unRel || vInfo1.vNum/100 == vInfo2.vNum/100) mTxt = "";
496  else mTxt = " which is incompatible!";
497 
498  if (!noMsg)
499  std::cerr <<"Plugin: " <<v1buff <<" is using " <<v2buff <<mTxt <<std::endl;
500 
501  return (*mTxt == 0);
502 }

Referenced by XrdCksConfig::XrdCksConfig(), XrdCksLoader::XrdCksLoader(), XrdOucN2NLoader::Load(), XrdOfsConfigPI::New(), XrdCmsFinderRMT::VCheck(), XrdCmsFinderTRG::VCheck(), XrdAccDefaultAuthorizeObject(), and XrdOssGetSS().

+ Here is the caller graph for this function:

The documentation for this class was generated from the following files: