// @(#)root/netx:$Name: $:$Id: TXNetSystem.cxx,v 1.4 2006/02/26 16:13:38 rdm Exp $
// Author: Frank Winklmeier, Fabrizio Furano
/*************************************************************************
* Copyright (C) 1995-2005, Rene Brun and Fons Rademakers. *
* All rights reserved. *
* *
* For the licensing terms see $ROOTSYS/LICENSE. *
* For the list of contributors see $ROOTSYS/README/CREDITS. *
*************************************************************************/
//////////////////////////////////////////////////////////////////////////
// //
// TXNetSystem //
// //
// Authors: Frank Winklmeier, Fabrizio Furano //
// INFN Padova, 2005 //
// //
// TXNetSystem is an extension of TNetSystem able to deal with new //
// xrootd servers. The class detects the nature of the server and //
// redirects the calls to TNetSystem in case of a rootd server. //
// //
//////////////////////////////////////////////////////////////////////////
#include "TString.h"
#include "TEnv.h"
#include "TSocket.h"
#include "TUrl.h"
#include "TVirtualMutex.h"
#include "TXNetFile.h"
#include "TXNetSystem.h"
#include "XrdClient/XrdClientAdmin.hh"
#include "XrdClient/XrdClientEnv.hh"
ClassImp(TXNetSystem);
Bool_t TXNetSystem::fgInitDone = kFALSE;
Bool_t TXNetSystem::fgRootdBC = kTRUE;
//_____________________________________________________________________________
TXNetSystem::TXNetSystem(Bool_t owner) : TNetSystem(owner)
{
// Create system management class without connecting to server.
SetTitle("(x)rootd system administration");
fClientAdmin = 0;
fIsXRootd = kFALSE;
fDir = "";
fDirp = 0;
fDirListValid = kFALSE;
}
//_____________________________________________________________________________
TXNetSystem::TXNetSystem(const char *url, Bool_t owner) : TNetSystem(owner)
{
// Create system management class and connect to server specified by url.
SetTitle("(x)rootd system administration");
fIsRootd = kFALSE;
fIsXRootd = kFALSE;
fDir = "";
fDirp = 0;
fDirListValid = kFALSE;
// The first time do some global initialization
if (!fgInitDone)
InitXrdClient();
// Fill in user, host, port
TNetSystem::InitRemoteEntity(url);
// We need a dummy filename after the server url to connect
TString dummy = url;
dummy += "/dummy";
fClientAdmin = new XrdClientAdmin(dummy);
if (!fClientAdmin) {
Error("TXNetSystem","fatal error: new object creation failed.");
gSystem->Abort();
}
// Try to connect to the server
if (fClientAdmin->Connect()) {
fIsXRootd = kTRUE;
} else {
if (fgRootdBC) {
Bool_t isRootd =
(fClientAdmin->GetClientConn()->GetServerType() == XrdClientConn::kSTRootd);
Int_t sd = fClientAdmin->GetClientConn()->GetOpenSockFD();
if (isRootd && sd > -1) {
//
// Create a TSocket on the open connection
TSocket *s = new TSocket(sd);
// We will clean it by ourselves
R__LOCKGUARD2(gROOTMutex);
gROOT->GetListOfSockets()->Remove(s);
s->SetOption(kNoBlock, 0);
// Find out the remote protocol (send the client protocol first)
Int_t rproto = TXNetFile::GetRootdProtocol(s);
if (rproto < 0) {
Error("TXNetSystem", "getting protocol of the rootd server");
return;
}
// Finalize TSocket initialization
s->SetRemoteProtocol(rproto);
TUrl uut((fClientAdmin->GetClientConn()
->GetCurrentUrl()).GetUrl().c_str());
TString uu;
TXNetFile::FormUrl(uut,uu);
if (gDebug > 2)
Info("TXNetSystem"," url: %s",uu.Data());
s->SetUrl(uu.Data());
s->SetService("rootd");
s->SetServType(TSocket::kROOTD);
//
// Now we can check if we can create a TNetFile on the
// open connection
if (rproto > 13) {
//
// Remote support for reuse of open connection
TNetSystem::Create(uu, s);
} else {
//
// Open connection has been closed because could
// not be reused; TNetSystem will open a new connection
TNetSystem::Create(uu);
}
// Type of server
fIsRootd = kTRUE;
} else {
Error("TXNetSystem", "some severe error occurred while opening"
" the connection at %s - exit", url);
return;
}
} else {
Error("TXNetSystem",
"while opening the connection at %s - exit", url);
return;
}
}
return;
}
//_____________________________________________________________________________
TXNetSystem::~TXNetSystem()
{
// Destructor
if (fIsXRootd && fClientAdmin)
delete fClientAdmin;
}
//_____________________________________________________________________________
void TXNetSystem::InitXrdClient()
{
// One-time initialization of some communication variables for xrootd protocol
// Set debug level
EnvPutInt(NAME_DEBUG, gEnv->GetValue("XNet.Debug", 0));
// List of domains where redirection is allowed
TString allowRE = gEnv->GetValue("XNet.RedirDomainAllowRE", "");
if (allowRE.Length() > 0)
EnvPutString(NAME_REDIRDOMAINALLOW_RE, allowRE.Data());
// List of domains where redirection is denied
TString denyRE = gEnv->GetValue("XNet.RedirDomainDenyRE", "");
if (denyRE.Length() > 0)
EnvPutString(NAME_REDIRDOMAINDENY_RE, denyRE.Data());
// List of domains where connection is allowed
TString allowCO = gEnv->GetValue("XNet.ConnectDomainAllowRE", "");
if (allowCO.Length() > 0)
EnvPutString(NAME_CONNECTDOMAINALLOW_RE, allowCO.Data());
// List of domains where connection is denied
TString denyCO = gEnv->GetValue("XNet.ConnectDomainDenyRE", "");
if (denyCO.Length() > 0)
EnvPutString(NAME_CONNECTDOMAINDENY_RE, denyCO.Data());
// Connect Timeout
Int_t connTO = gEnv->GetValue("XNet.ConnectTimeout",
DFLT_CONNECTTIMEOUT);
EnvPutInt(NAME_CONNECTTIMEOUT, connTO);
// Reconnect Timeout
Int_t recoTO = gEnv->GetValue("XNet.ReconnectTimeout",
DFLT_RECONNECTTIMEOUT);
EnvPutInt(NAME_RECONNECTTIMEOUT, recoTO);
// Request Timeout
Int_t requTO = gEnv->GetValue("XNet.RequestTimeout",
DFLT_REQUESTTIMEOUT);
EnvPutInt(NAME_REQUESTTIMEOUT, requTO);
// Max number of redirections
Int_t maxRedir = gEnv->GetValue("XNet.MaxRedirectCount",
DFLT_MAXREDIRECTCOUNT);
EnvPutInt(NAME_MAXREDIRECTCOUNT, maxRedir);
// Whether to use a separate thread for garbage collection
Int_t garbCollTh = gEnv->GetValue("XNet.StartGarbageCollectorThread",
DFLT_STARTGARBAGECOLLECTORTHREAD);
EnvPutInt(NAME_STARTGARBAGECOLLECTORTHREAD, garbCollTh);
// Whether to use a separate thread for reading
Int_t goAsync = gEnv->GetValue("XNet.GoAsynchronous", DFLT_GOASYNC);
EnvPutInt(NAME_GOASYNC, goAsync);
// Read ahead size
Int_t rAheadsiz = gEnv->GetValue("XNet.ReadAheadSize",
DFLT_READAHEADSIZE);
EnvPutInt(NAME_READAHEADSIZE, rAheadsiz);
// Cache size (<= 0 disables cache)
Int_t rCachesiz = gEnv->GetValue("XNet.ReadCacheSize",
DFLT_READCACHESIZE);
EnvPutInt(NAME_READCACHESIZE, rCachesiz);
// Max number of retries on first connect
Int_t maxRetries = gEnv->GetValue("XNet.TryConnect",
DFLT_FIRSTCONNECTMAXCNT);
EnvPutInt(NAME_FIRSTCONNECTMAXCNT, maxRetries);
// Whether to activate automatic rootd backward-compatibility
// (We override XrdClient default)
fgRootdBC = gEnv->GetValue("XNet.RootdFallback", 1);
EnvPutInt(NAME_KEEPSOCKOPENIFNOTXRD, fgRootdBC);
// For password-based authentication
TString autolog = gEnv->GetValue("XSec.Pwd.AutoLogin","1");
if (autolog.Length() > 0)
gSystem->Setenv("XrdSecPWDAUTOLOG",autolog.Data());
// Old style netrc file
TString netrc;
netrc.Form("%s/.rootnetrc",gSystem->HomeDirectory());
gSystem->Setenv("XrdSecNETRC", netrc.Data());
TString alogfile = gEnv->GetValue("XSec.Pwd.ALogFile","");
if (alogfile.Length() > 0)
gSystem->Setenv("XrdSecPWDALOGFILE",alogfile.Data());
TString verisrv = gEnv->GetValue("XSec.Pwd.VerifySrv","1");
if (verisrv.Length() > 0)
gSystem->Setenv("XrdSecPWDVERIFYSRV",verisrv.Data());
TString srvpuk = gEnv->GetValue("XSec.Pwd.ServerPuk","");
if (srvpuk.Length() > 0)
gSystem->Setenv("XrdSecPWDSRVPUK",srvpuk.Data());
// For GSI authentication
TString cadir = gEnv->GetValue("XSec.GSI.CAdir","");
if (cadir.Length() > 0)
gSystem->Setenv("XrdSecGSICADIR",cadir.Data());
TString crldir = gEnv->GetValue("XSec.GSI.CRLdir","");
if (crldir.Length() > 0)
gSystem->Setenv("XrdSecGSICRLDIR",crldir.Data());
TString crlext = gEnv->GetValue("XSec.GSI.CRLextension","");
if (crlext.Length() > 0)
gSystem->Setenv("XrdSecGSICRLEXT",crlext.Data());
TString ucert = gEnv->GetValue("XSec.GSI.UserCert","");
if (ucert.Length() > 0)
gSystem->Setenv("XrdSecGSIUSERCERT",ucert.Data());
TString ukey = gEnv->GetValue("XSec.GSI.UserKey","");
if (ukey.Length() > 0)
gSystem->Setenv("XrdSecGSIUSERKEY",ukey.Data());
TString upxy = gEnv->GetValue("XSec.GSI.UserProxy","");
if (upxy.Length() > 0)
gSystem->Setenv("XrdSecGSIUSERPROXY",upxy.Data());
TString valid = gEnv->GetValue("XSec.GSI.ProxyValid","");
if (valid.Length() > 0)
gSystem->Setenv("XrdSecGSIPROXYVALID",valid.Data());
TString deplen = gEnv->GetValue("XSec.GSI.ProxyForward","0");
if (deplen.Length() > 0)
gSystem->Setenv("XrdSecGSIPROXYDEPLEN",deplen.Data());
TString pxybits = gEnv->GetValue("XSec.GSI.ProxyKeyBits","");
if (pxybits.Length() > 0)
gSystem->Setenv("XrdSecGSIPROXYKEYBITS",pxybits.Data());
TString crlcheck = gEnv->GetValue("XSec.GSI.CheckCRL","2");
if (crlcheck.Length() > 0)
gSystem->Setenv("XrdSecGSICRLCHECK",crlcheck.Data());
// Using ROOT mechanism to IGNORE SIGPIPE signal
gSystem->IgnoreSignal(kSigPipe);
// Only once
fgInitDone = kTRUE;
// Print the tag, if required (only once)
if (gEnv->GetValue("XNet.PrintTAG",0) == 1)
Info("TXNetFile","(C) 2005 SLAC TXNetSystem (eXtended TNetSystem) %s",
gROOT->GetVersion());
}
//_____________________________________________________________________________
void* TXNetSystem::OpenDirectory(const char* dir)
{
// Open a directory. Returns a non-zero pointer (with no special
// purpose) in case of success, 0 in case of error.
if (fIsXRootd) {
// Extract the directory name
fDir = TUrl(dir).GetFile();
fDirp = (void*)&fDir; // serves as directory pointer
vecString dirs;
vecBool existDirs;
XrdClientString s(fDir.Data());
dirs.Push_back(s);
// Check if the directory exists
fClientAdmin->ExistDirs(dirs,existDirs);
if (existDirs.GetSize()>0 && existDirs[0])
return fDirp;
else
return 0;
}
if (gDebug > 1)
Info("OpenDirectory", "calling TNetSystem::OpenDirectory");
return TNetSystem::OpenDirectory(dir); // for a rootd
}
//_____________________________________________________________________________
void TXNetSystem::FreeDirectory(void *dirp)
{
// Free(Close) the directory referenced by dirp
if (fIsXRootd) {
if (dirp != fDirp) {
Error("FreeDirectory","invalid directory pointer (%p, %p)", dirp, fDirp);
return;
}
fDir = "";
fDirp = 0;
fDirListValid = kFALSE;
return;
}
if (gDebug > 1)
Info("FreeDirectory","calling TNetSystem::FreeDirectory");
return TNetSystem::FreeDirectory(dirp); // for a rootd
}
//_____________________________________________________________________________
Int_t TXNetSystem::MakeDirectory(const char* dir)
{
// Create a directory. Return 0 on success, -1 otherwise.
if (fIsXRootd) {
// use default permissions 755 to create directory
Bool_t ok = fClientAdmin->Mkdir(TUrl(dir).GetFile(),7,5,5);
return (ok ? 0 : -1);
}
if (gDebug > 1) Info("MakeDirectory","Calling TNetSystem::MakeDirectory");
return TNetSystem::MakeDirectory(dir); // for a rootd
}
//_____________________________________________________________________________
const char* TXNetSystem::GetDirEntry(void *dirp)
{
// Get directory entry for directory referenced by dirp.
// Returns 0 in case there are no more entries.
if (fIsXRootd) {
if (dirp != fDirp) {
Error("GetDirEntry","invalid directory pointer");
return 0;
}
// Only request new directory listing the first time called
if (!fDirListValid) {
Bool_t ok = fClientAdmin->DirList(fDir,fDirList);
if (ok)
fDirListValid = kTRUE;
else
return 0;
}
// Return entries one by one with each call of method
if (fDirList.GetSize()>0) return fDirList.Pop_back().c_str();
else return 0; // until all of them have been returned
}
if (gDebug > 1) Info("GetDirEntry","Calling TNetSystem::GetDirEntry");
return TNetSystem::GetDirEntry(dirp); // for a rootd
}
//_____________________________________________________________________________
Int_t TXNetSystem::GetPathInfo(const char* path, FileStat_t &buf)
{
// Get info about a file. Info is returned in the form of a FileStat_t
// structure (see TSystem.h).
// The function returns 0 in case of success and 1 if the file could
// not be stat'ed.
// NOTICE: Not all information is available with an xrootd server.
if (fIsXRootd) {
Long_t id;
Long64_t size;
Long_t flags;
Long_t modtime;
// Extract the directory name
TString edir = TUrl(path).GetFile();
Bool_t ok = fClientAdmin->Stat(edir,id,size,flags,modtime);
if (ok) {
buf.fDev = (id >> 24);
buf.fIno = (id && 0x00FFFFFF);
buf.fUid = -1; // not all information available in xrootd
buf.fGid = -1; // not available
buf.fSize = size;
buf.fMtime = modtime;
if (flags == 0) buf.fMode = kS_IFREG;
if (flags & 1) buf.fMode = (kS_IFREG|kS_IXUSR|kS_IXGRP|kS_IXOTH);
if (flags & 2) buf.fMode = kS_IFDIR;
if (flags & 4) buf.fMode = kS_IFSOCK;
buf.fIsLink = 0; // not available
return 0;
}
else return 1;
}
if (gDebug > 1)
Info("GetPathInfo","Calling TNetSystem::GetPathInfo");
return TNetSystem::GetPathInfo(path,buf); // for a rootd
}
//_____________________________________________________________________________
Bool_t TXNetSystem::ConsistentWith(const char *path, void *dirptr)
{
// Check consistency of this helper with the one required
// by 'path' or 'dirptr'.
if (gDebug > 1)
Info("ConsistenWith","Calling TNetSystem::ConsistenWith");
return TNetSystem::ConsistentWith(path,dirptr); // for a rootd
}
//_____________________________________________________________________________
Bool_t TXNetSystem::AccessPathName(const char *path, EAccessMode mode)
{
// Returns FALSE if one can access a file using the specified access mode.
// NB: for the time being mode is ignored for XROOTD (just checks existence
// of the file or directory).
// Mode is the same as for the Unix access(2) function.
// Attention, bizarre convention of return value!!
if (fIsXRootd) {
// Check only if the file or directory exists and
FileStat_t buf;
if (GetPathInfo(path, buf) == 0)
if (buf.fMode != kS_IFSOCK)
return kFALSE;
// The file could not be stated
return kTRUE;
}
if (gDebug > 1)
Info("AccessPathName", "calling TNetSystem::AccessPathName");
return TNetSystem::AccessPathName(path,mode); // for a rootd
}
ROOT page - Class index - Class Hierarchy - Top of the page
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.