#include "TEnv.h"
#include "TFileStager.h"
#include "TObjString.h"
#include "TROOT.h"
#include "TSocket.h"
#include "TString.h"
#include "TUrl.h"
#include "TVirtualMutex.h"
#include "TXNetFile.h"
#include "TXNetSystem.h"
#include "XrdClient/XrdClientAdmin.hh"
#include "XrdClient/XrdClientConn.hh"
#include "XrdClient/XrdClientEnv.hh"
#include "XProtocol/XProtocol.hh"
ClassImp(TXNetSystem);
Bool_t TXNetSystem::fgInitDone = kFALSE;
Bool_t TXNetSystem::fgRootdBC = kTRUE;
#ifndef OLDXRDLOCATE
THashList TXNetSystem::fgAddrFQDN;
THashList TXNetSystem::fgAdminHash;
#endif
TXNetSystem::TXNetSystem(Bool_t owner) : TNetSystem(owner)
{
   
   SetTitle("(x)rootd system administration");
   fIsXRootd = kFALSE;
   fDir = "";
   fDirp = 0;
   fDirListValid = kFALSE;
   fUrl = "";
}
TXNetSystem::TXNetSystem(const char *url, Bool_t owner) : TNetSystem(owner)
{
   
   SetTitle("(x)rootd system administration");
   fIsRootd = kFALSE;
   fIsXRootd = kFALSE;
   fDir = "";
   fDirp = 0;
   fDirListValid = kFALSE;
   fUrl = url;
#ifndef OLDXRDLOCATE
   fgAddrFQDN.SetOwner();
   fgAdminHash.SetOwner();
#endif
   
   EnvPutInt(NAME_DEBUG, gEnv->GetValue("XNet.Debug", -1));
   
   if (!fgInitDone)
      InitXrdClient();
   
   TNetSystem::InitRemoteEntity(url);
   TXNetSystemConnectGuard cguard(this, url);
   if (!cguard.IsValid() && !fIsRootd)
      Error("TXNetSystem","fatal error: connection creation failed.");
   return;
}
XrdClientAdmin *TXNetSystem::Connect(const char *url)
{
   
   
   
   
   TString dummy = url;
   dummy += "/dummy";
#ifndef OLDXRDLOCATE
   XrdClientAdmin *cadm = TXNetSystem::GetClientAdmin(dummy);
#else
   XrdClientAdmin *cadm = XrdClientAdmin::GetClientAdmin(dummy);
#endif
   if (!cadm) {
      Error("Connect","fatal error: new object creation failed.");
      return cadm;
   }
   
   if (cadm->Connect()) {
      fIsXRootd = kTRUE;
   } else {
      if (fgRootdBC) {
         Bool_t isRootd =
            (cadm->GetClientConn()->GetServerType() == kSTRootd);
         Int_t sd = cadm->GetClientConn()->GetOpenSockFD();
         if (isRootd && sd > -1) {
            
            
            TSocket *s = new TSocket(sd);
            
            R__LOCKGUARD2(gROOTMutex);
            gROOT->GetListOfSockets()->Remove(s);
            s->SetOption(kNoBlock, 0);
            
            Int_t rproto = TXNetFile::GetRootdProtocol(s);
            if (rproto < 0) {
               Error("TXNetSystem", "getting protocol of the rootd server");
               cadm = 0;
               return 0;
            }
            
            s->SetRemoteProtocol(rproto);
            TUrl uut((cadm->GetClientConn()
                             ->GetCurrentUrl()).GetUrl().c_str());
            TString uu;
            TXNetFile::FormUrl(uut,uu);
            if (gDebug > 2)
               Info("Connect"," url: %s",uu.Data());
            s->SetUrl(uu.Data());
            s->SetService("rootd");
            s->SetServType(TSocket::kROOTD);
            
            
            
            if (rproto > 13) {
               
               
               TNetSystem::Create(uu, s);
            } else {
               
               
               
               TNetSystem::Create(uu);
            }
            
            fIsRootd = kTRUE;
            cadm = 0;
         } else {
            Error("Connect", "some severe error occurred while opening"
                  " the connection at %s - exit", url);
            cadm = 0;
            return cadm;
         }
      } else {
         Error("Connect",
               "while opening the connection at %s - exit", url);
         cadm = 0;
         return cadm;
      }
   }
   return cadm;
}
void TXNetSystem::InitXrdClient()
{
   
   
   TXNetFile::SetEnv();
#if defined(OLDXRDLOCATE) && !defined(OLDXRDOUC)
   
   XrdClientAdmin::SetAdminConn();
#endif
   
   fgInitDone = kTRUE;
   
   if (gEnv->GetValue("XNet.PrintTAG",0) == 1)
     Info("TXNetFile","(C) 2005 SLAC TXNetSystem (eXtended TNetSystem) %s",
         gROOT->GetVersion());
}
void* TXNetSystem::OpenDirectory(const char* dir)
{
   
   
   if (fIsXRootd) {
      
      TXNetSystemConnectGuard cg(this, dir);
      if (cg.IsValid()) {
         fUrl = dir;
         
         fDir = TUrl(dir).GetFile();
         fDirp = (void*)&fDir;     
         vecString dirs;
         vecBool existDirs;
         XrdOucString s(fDir.Data());
         dirs.Push_back(s);
         cg.ClientAdmin()->ExistDirs(dirs, existDirs);
         if (existDirs.GetSize()>0 && existDirs[0])
            return fDirp;
         else
            cg.NotifyLastError();
      }
      return 0;
   }
   if (gDebug > 1)
      Info("OpenDirectory", "calling TNetSystem::OpenDirectory");
   return TNetSystem::OpenDirectory(dir);       
}
void TXNetSystem::FreeDirectory(void *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);     
}
Int_t TXNetSystem::MakeDirectory(const char* dir)
{
   
   if (fIsXRootd) {
      TXNetSystemConnectGuard cg(this, dir);
      if (cg.IsValid()) {
         
         Bool_t ok = cg.ClientAdmin()->Mkdir(TUrl(dir).GetFile(),7,5,5);
         if (ok) {
            return 0;
         } else {
            cg.NotifyLastError();
            return -1;
         }
      }
   }
   if (gDebug > 1)
      Info("MakeDirectory","Calling TNetSystem::MakeDirectory");
   return TNetSystem::MakeDirectory(dir);     
}
const char* TXNetSystem::GetDirEntry(void *dirp)
{
   
   
   if (fIsXRootd) {
      if (dirp != fDirp) {
         Error("GetDirEntry","invalid directory pointer");
         return 0;
      }
      
      if (!fDirListValid) {
         TXNetSystemConnectGuard cg(this, fUrl);
         if (cg.IsValid()) {
            Bool_t ok = cg.ClientAdmin()->DirList(fDir, fDirList);
            if (ok) {
               fDirListValid = kTRUE;
            } else {
               cg.NotifyLastError();
               return 0;
            }
         }
      }
      
      if (fDirList.GetSize() > 0)
         return fDirList.Pop_back().c_str();
      return 0;   
   }
   if (gDebug > 1) Info("GetDirEntry","Calling TNetSystem::GetDirEntry");
   return TNetSystem::GetDirEntry(dirp);      
}
Int_t TXNetSystem::GetPathInfo(const char* path, FileStat_t &buf)
{
   
   
   
   
   
   if (fIsXRootd) {
      TXNetSystemConnectGuard cg(this, path);
      if (cg.IsValid()) {
         Long_t id;
         Long64_t size;
         Long_t flags;
         Long_t modtime;
         
         TString edir = TUrl(path).GetFile();
         Bool_t ok = cg.ClientAdmin()->Stat(edir.Data(),id,size,flags,modtime);
         
         if (flags & kXR_offline) {
            buf.fMode = kS_IFOFF;
         } else if (ok) {
            buf.fDev = (id >> 24);
            buf.fIno = (id && 0x00FFFFFF);
            buf.fUid = -1;       
            buf.fGid = -1;       
            buf.fSize = size;
            buf.fMtime = modtime;
            if (flags == 0) buf.fMode = kS_IFREG;
            if (flags & kXR_xset) buf.fMode = (kS_IFREG|kS_IXUSR|kS_IXGRP|kS_IXOTH);
            if (flags & kXR_isDir) buf.fMode = kS_IFDIR;
            if (flags & kXR_other) buf.fMode = kS_IFSOCK;
            if (flags & kXR_readable) buf.fMode |= kS_IRUSR;
            if (flags & kXR_writable) buf.fMode |= kS_IWUSR;
            buf.fIsLink = 0;     
            return 0;
         } else {
            if (gDebug > 0)
               cg.NotifyLastError();
         }
      }
      return 1;
   }
   if (gDebug > 1)
      Info("GetPathInfo","Calling TNetSystem::GetPathInfo");
   return TNetSystem::GetPathInfo(path,buf);       
}
Bool_t TXNetSystem::ConsistentWith(const char *path, void *dirptr)
{
   
   
   if (gDebug > 1)
      Info("ConsistenWith",
           "Calling TNetSystem::ConsistenWith for path: %s, dir: %p", path, dirptr);
   return TNetSystem::ConsistentWith(path,dirptr);    
}
Bool_t TXNetSystem::AccessPathName(const char *path, EAccessMode mode)
{
   
   
   
   
   
   if (fIsXRootd) {
      
      FileStat_t buf;
      if (GetPathInfo(path, buf) == 0)
         if (buf.fMode != kS_IFSOCK)
            return kFALSE;
      
      return kTRUE;
   }
   if (gDebug > 1)
      Info("AccessPathName", "calling TNetSystem::AccessPathName");
   return TNetSystem::AccessPathName(path,mode);    
}
int TXNetSystem::Unlink(const char *path)
{
   
   
   if (fIsXRootd) {
      TXNetSystemConnectGuard cg(this, path);
      if (cg.IsValid()) {
         Long_t id;
         Long64_t size;
         Long_t flags;
         Long_t modtime;
         
         TString edir = TUrl(path).GetFile();
         Bool_t ok = cg.ClientAdmin()->Stat(edir.Data(), id, size, flags, modtime);
         
         if (ok && !(flags & kXR_offline)) {
            if (flags & kXR_isDir)
               ok = cg.ClientAdmin()->Rmdir(edir.Data());
            else
               ok = cg.ClientAdmin()->Rm(edir.Data());
            
            return ((ok) ? 0 : -1);
         } else if (!ok) {
            cg.NotifyLastError();
         }
      }
   }
   if (gDebug > 1)
      Info("Unlink", "calling TNetSystem::Unlink");
   return -1;    
}
Bool_t TXNetSystem::IsOnline(const char *path)
{
   
   TXNetSystemConnectGuard cg(this, path);
   if (cg.IsValid()) {
      vecBool vb;
      vecString vs;
      XrdOucString pathname = TUrl(path).GetFileAndOptions();
      pathname.replace("\n","\r");
      vs.Push_back(pathname);
      if (gDebug > 1 )
         Info("IsOnline", "Checking %s\n",path);
      cg.ClientAdmin()->IsFileOnline(vs,vb);
      if (!cg.ClientAdmin()->LastServerResp()) {
         return kFALSE;
      }
      switch (cg.ClientAdmin()->LastServerResp()->status) {
         case kXR_ok:
            if (vb[0]) {
               return kTRUE;
            } else {
               return kFALSE;
         }
         case kXR_error:
            Error("IsOnline","Error %d : %s", cg.ClientAdmin()->LastServerError()->errnum,
                             cg.ClientAdmin()->LastServerError()->errmsg);
            return kFALSE;
         default:
            return kTRUE;
      }
   }
   return kFALSE;
}
Bool_t TXNetSystem::Prepare(const char *path, UChar_t option, UChar_t priority)
{
   
   TXNetSystemConnectGuard cg(this, path);
   if (cg.IsValid()) {
      XrdOucString pathname = TUrl(path).GetFileAndOptions();
      vecString vs;
      vs.Push_back(pathname);
      cg.ClientAdmin()->Prepare(vs, (kXR_char)option, (kXR_char)priority);
      if (gDebug >0)
         Info("Prepare", "Got Status %d for %s",
              cg.ClientAdmin()->LastServerResp()->status, pathname.c_str());
      if (!(cg.ClientAdmin()->LastServerResp()->status)){
         return kTRUE;
      }
      cg.NotifyLastError();
   }
   
   return kFALSE;
}
Int_t TXNetSystem::Prepare(TCollection *paths,
                           UChar_t opt, UChar_t prio, TString *bufout)
{
   
   
   
   
   
   if (!paths) {
      Warning("Prepare", "input list is empty!");
      return -1;
   }
   Int_t npaths = 0;
   TXNetSystemConnectGuard cg(this, "");
   if (cg.IsValid()) {
      TString *buf = (bufout) ? bufout : new TString();
      
      TObject *o = 0;
      TUrl u;
      TString path;
      TIter nxt(paths);
      while ((o = nxt()))  {
         
         TString pn = TFileStager::GetPathName(o);
         if (pn == "") {
            Warning("Prepare", "object is of unexpected type %s - ignoring", o->ClassName());
            continue;
         }
         u.SetUrl(pn);
         
         path = u.GetFileAndOptions();
         path.ReplaceAll("\n","\r");
         npaths++;
         *buf += Form("%s\n", path.Data());
      }
      Info("Prepare","buffer ready: issuing prepare ...");
      cg.ClientAdmin()->Prepare(buf->Data(), (kXR_char)opt, (kXR_char)prio);
      if (!bufout)
         delete buf;
      if (gDebug >0)
         Info("Prepare", "Got Status %d",
              cg.ClientAdmin()->LastServerResp()->status);
      if (!(cg.ClientAdmin()->LastServerResp()->status)){
         return npaths;
      }
      cg.NotifyLastError();
   }
   
   return -1;
}
Bool_t TXNetSystem::GetPathsInfo(const char *paths, UChar_t *info)
{
   
   
   
   if (!paths) {
      Warning("GetPathsInfo", "input list is empty!");
      return kFALSE;
   }
   TXNetSystemConnectGuard cg(this, "");
   if (cg.IsValid()) {
      cg.ClientAdmin()->SysStatX(paths, info);
      if (gDebug >0)
         Info("GetPathsInfo", "Got Status %d",
              cg.ClientAdmin()->LastServerResp()->status);
      if (!(cg.ClientAdmin()->LastServerResp()->status)){
         return kTRUE;
      }
      cg.NotifyLastError();
   }
   
   return kFALSE;
}
Int_t TXNetSystem::Locate(const char *path, TString &eurl)
{
   
   
   
   if (fIsXRootd) {
      TXNetSystemConnectGuard cg(this, path);
      if (cg.IsValid()) {
#ifndef OLDXRDLOCATE
         
         XrdClientLocate_Info li;
         TString edir = TUrl(path).GetFile();
         if (cg.ClientAdmin()->Locate((kXR_char *)edir.Data(), li)) {
            TUrl u(path);
            XrdClientUrlInfo ui((const char *)&li.Location[0]);
            
            
            TNamed *hn = 0;
            if (fgAddrFQDN.GetSize() <= 0 ||
               !(hn = dynamic_cast<TNamed *>(fgAddrFQDN.FindObject(ui.Host.c_str())))) {
               TInetAddress a(gSystem->GetHostByName(ui.Host.c_str()));
               if (strlen(a.GetHostName()) > 0)
                  hn = new TNamed(ui.Host.c_str(), a.GetHostName());
               else
                  hn = new TNamed(ui.Host.c_str(), ui.Host.c_str());
               fgAddrFQDN.Add(hn);
               if (gDebug > 0)
                  Info("Locate","caching host name: %s", hn->GetTitle());
            }
            if (hn)
               u.SetHost(hn->GetTitle());
            else
               u.SetHost(ui.Host.c_str());
            u.SetPort(ui.Port);
            eurl = u.GetUrl();
            return 0;
         }
#else
         
         XrdClientUrlInfo ui;
         TString edir = TUrl(path).GetFile();
         if (cg.ClientAdmin()->Locate((kXR_char *)edir.Data(), ui, kTRUE)) {
            TUrl u(path);
            u.SetHost(ui.Host.c_str());
            u.SetPort(ui.Port);
            eurl = u.GetUrl();
            return 0;
         }
#endif
         cg.NotifyLastError();
      }
      return 1;
   }
   
   Warning("Locate", "method not implemented!");
   return -1;
}
#ifndef OLDXRDLOCATE
XrdClientAdmin *TXNetSystem::GetClientAdmin(const char *url)
{
   
   
   XrdClientAdmin *ca = 0;
   
   TString key = TXNetSystem::GetKey(url);
   
   TXrdClientAdminWrapper *caw = 0;
   if (fgAdminHash.GetSize() > 0 &&
      (caw = dynamic_cast<TXrdClientAdminWrapper *>(fgAdminHash.FindObject(key.Data()))))
      return caw->fXCA;
   
   ca = new XrdClientAdmin(url);
   fgAdminHash.Add(new TXrdClientAdminWrapper(key, ca));
   
   return ca;
}
TString TXNetSystem::GetKey(const char *url)
{
   
   TUrl u(url);
   TString key(u.GetUser());
   if (!key.IsNull())
      key += "@";
   key += u.GetHost();
   if (u.GetPort() > 0) {
      key += ":";
      key += u.GetPort();
   }
   
   return key;
}
TXrdClientAdminWrapper::~TXrdClientAdminWrapper()
{
   
   SafeDelete(fXCA);
}
#endif
TXNetSystemConnectGuard::TXNetSystemConnectGuard(TXNetSystem *xn, const char *url)
                        : fClientAdmin(0)
{
   
    if (xn)
       
       fClientAdmin = (url && strlen(url) > 0) ? xn->Connect(url)
                                               : xn->Connect(xn->fUrl);
}
TXNetSystemConnectGuard::~TXNetSystemConnectGuard()
{
   
   fClientAdmin = 0;
}
void TXNetSystemConnectGuard::NotifyLastError()
{
   
   if (fClientAdmin)
      if (fClientAdmin->GetClientConn())
         Printf("Srv err: %s", fClientAdmin->GetClientConn()->LastServerError.errmsg);
}
Last update: Thu Jan 17 09:05:32 2008
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.