00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "TEnv.h"
00026 #include "TFileStager.h"
00027 #include "TObjString.h"
00028 #include "TROOT.h"
00029 #include "TSocket.h"
00030 #include "TString.h"
00031 #include "TUrl.h"
00032 #include "TVirtualMutex.h"
00033 #include "TXNetFile.h"
00034 #include "TXNetSystem.h"
00035
00036 #include "XrdClient/XrdClientAdmin.hh"
00037 #include "XrdClient/XrdClientConn.hh"
00038 #include <XrdClient/XrdClientConst.hh>
00039 #include "XrdClient/XrdClientEnv.hh"
00040 #include "XProtocol/XProtocol.hh"
00041
00042
00043 ClassImp(TXNetSystem);
00044
00045 Bool_t TXNetSystem::fgInitDone = kFALSE;
00046 Bool_t TXNetSystem::fgRootdBC = kTRUE;
00047 #ifndef OLDXRDLOCATE
00048 THashList TXNetSystem::fgAddrFQDN;
00049 THashList TXNetSystem::fgAdminHash;
00050 #endif
00051
00052
00053 TXNetSystem::TXNetSystem(Bool_t owner) : TNetSystem(owner)
00054 {
00055
00056
00057 SetTitle("(x)rootd system administration");
00058 fIsXRootd = kFALSE;
00059 fDir = "";
00060 fDirp = 0;
00061 fDirListValid = kFALSE;
00062 fUrl = "";
00063 }
00064
00065
00066 TXNetSystem::TXNetSystem(const char *url, Bool_t owner) : TNetSystem(owner)
00067 {
00068
00069
00070 SetTitle("(x)rootd system administration");
00071 fIsRootd = kFALSE;
00072 fIsXRootd = kFALSE;
00073 fDir = "";
00074 fDirp = 0;
00075 fDirListValid = kFALSE;
00076 fUrl = url;
00077
00078 #ifndef OLDXRDLOCATE
00079 fgAddrFQDN.SetOwner();
00080 fgAdminHash.SetOwner();
00081 #endif
00082
00083
00084 EnvPutInt(NAME_DEBUG, gEnv->GetValue("XNet.Debug", -1));
00085
00086
00087 if (!fgInitDone)
00088 InitXrdClient();
00089
00090
00091 TNetSystem::InitRemoteEntity(url);
00092
00093 TXNetSystemConnectGuard cguard(this, url);
00094 if (!cguard.IsValid() && !fIsRootd)
00095 Error("TXNetSystem","fatal error: connection creation failed.");
00096
00097 return;
00098 }
00099
00100
00101 XrdClientAdmin *TXNetSystem::Connect(const char *url)
00102 {
00103
00104
00105
00106
00107
00108 TString dummy = url;
00109 dummy += "/dummy";
00110
00111 #ifndef OLDXRDLOCATE
00112 XrdClientAdmin *cadm = TXNetSystem::GetClientAdmin(dummy);
00113 #else
00114 XrdClientAdmin *cadm = XrdClientAdmin::GetClientAdmin(dummy);
00115 #endif
00116
00117 if (!cadm) {
00118 Error("Connect","fatal error: new object creation failed.");
00119 return cadm;
00120 }
00121
00122
00123 Int_t maxOld = EnvGetLong(NAME_FIRSTCONNECTMAXCNT);
00124
00125
00126 gEnv->SetValue("XNet.FirstConnectMaxCnt", 1);
00127 EnvPutInt(NAME_FIRSTCONNECTMAXCNT, 1);
00128 if (cadm->Connect()) {
00129 fIsXRootd = kTRUE;
00130 EnvPutInt(NAME_FIRSTCONNECTMAXCNT, maxOld);
00131 } else {
00132 EnvPutInt(NAME_FIRSTCONNECTMAXCNT, maxOld);
00133 if (fgRootdBC) {
00134 Bool_t isRootd =
00135 (cadm->GetClientConn()->GetServerType() == kSTRootd);
00136 Int_t sd = cadm->GetClientConn()->GetOpenSockFD();
00137 if (isRootd && sd > -1) {
00138
00139
00140 TSocket *s = new TSocket(sd);
00141
00142
00143 R__LOCKGUARD2(gROOTMutex);
00144 gROOT->GetListOfSockets()->Remove(s);
00145
00146 s->SetOption(kNoBlock, 0);
00147
00148
00149 Int_t rproto = TXNetFile::GetRootdProtocol(s);
00150 if (rproto < 0) {
00151 Error("TXNetSystem", "getting protocol of the rootd server");
00152 cadm = 0;
00153 return 0;
00154 }
00155
00156 s->SetRemoteProtocol(rproto);
00157 TUrl uut((cadm->GetClientConn()
00158 ->GetCurrentUrl()).GetUrl().c_str());
00159 TString uu;
00160 TXNetFile::FormUrl(uut,uu);
00161 if (gDebug > 2)
00162 Info("Connect"," url: %s",uu.Data());
00163
00164 s->SetUrl(uu.Data());
00165 s->SetService("rootd");
00166 s->SetServType(TSocket::kROOTD);
00167
00168
00169
00170 if (rproto > 13) {
00171
00172
00173 TNetSystem::Create(uu, s);
00174 } else {
00175
00176
00177
00178 TNetSystem::Create(uu);
00179 }
00180
00181
00182 fIsRootd = kTRUE;
00183 cadm = 0;
00184
00185 } else {
00186 Error("Connect", "some severe error occurred while opening"
00187 " the connection at %s - exit", url);
00188 cadm = 0;
00189 return cadm;
00190 }
00191 } else {
00192 Error("Connect",
00193 "while opening the connection at %s - exit", url);
00194 cadm = 0;
00195 return cadm;
00196 }
00197 }
00198
00199 return cadm;
00200 }
00201
00202
00203 void TXNetSystem::InitXrdClient()
00204 {
00205
00206
00207
00208 TXNetFile::SetEnv();
00209
00210 #if defined(OLDXRDLOCATE) && !defined(OLDXRDOUC)
00211
00212 XrdClientAdmin::SetAdminConn();
00213 #endif
00214
00215
00216 fgInitDone = kTRUE;
00217
00218
00219 if (gEnv->GetValue("XNet.PrintTAG",0) == 1)
00220 Info("TXNetFile","(C) 2005 SLAC TXNetSystem (eXtended TNetSystem) %s",
00221 gROOT->GetVersion());
00222 }
00223
00224
00225 void* TXNetSystem::OpenDirectory(const char* dir)
00226 {
00227
00228
00229
00230 if (fIsXRootd) {
00231
00232 TXNetSystemConnectGuard cg(this, dir);
00233 if (cg.IsValid()) {
00234 fUrl = dir;
00235
00236 fDir = TUrl(dir).GetFile();
00237 fDirp = (void*)&fDir;
00238
00239 vecString dirs;
00240 vecBool existDirs;
00241 XrdOucString s(fDir.Data());
00242 dirs.Push_back(s);
00243 cg.ClientAdmin()->ExistDirs(dirs, existDirs);
00244 cg.ClientAdmin()->GoBackToRedirector();
00245 if (existDirs.GetSize()>0 && existDirs[0])
00246 return fDirp;
00247 else
00248 cg.NotifyLastError();
00249 }
00250 return 0;
00251 }
00252
00253 if (gDebug > 1)
00254 Info("OpenDirectory", "calling TNetSystem::OpenDirectory");
00255 return TNetSystem::OpenDirectory(dir);
00256 }
00257
00258
00259 void TXNetSystem::FreeDirectory(void *dirp)
00260 {
00261
00262
00263 if (fIsXRootd) {
00264 if (dirp != fDirp) {
00265 Error("FreeDirectory","invalid directory pointer (%p, %p)", dirp, fDirp);
00266 return;
00267 }
00268 fDir = "";
00269 fDirp = 0;
00270 fDirListValid = kFALSE;
00271 fDirEntry = "";
00272 fDirList.Clear();
00273 return;
00274 }
00275
00276 if (gDebug > 1)
00277 Info("FreeDirectory","calling TNetSystem::FreeDirectory");
00278 return TNetSystem::FreeDirectory(dirp);
00279 }
00280
00281
00282 Int_t TXNetSystem::MakeDirectory(const char* dir)
00283 {
00284
00285
00286 if (fIsXRootd) {
00287 TXNetSystemConnectGuard cg(this, dir);
00288 if (cg.IsValid()) {
00289
00290 Bool_t ok = cg.ClientAdmin()->Mkdir(TUrl(dir).GetFile(),7,5,5);
00291 cg.ClientAdmin()->GoBackToRedirector();
00292 if (ok) {
00293 return 0;
00294 } else {
00295 cg.NotifyLastError();
00296 return -1;
00297 }
00298 }
00299 }
00300
00301 if (gDebug > 1)
00302 Info("MakeDirectory","Calling TNetSystem::MakeDirectory");
00303 return TNetSystem::MakeDirectory(dir);
00304 }
00305
00306
00307 const char* TXNetSystem::GetDirEntry(void *dirp)
00308 {
00309
00310
00311
00312 if (fIsXRootd) {
00313 if (dirp != fDirp) {
00314 Error("GetDirEntry","invalid directory pointer");
00315 return 0;
00316 }
00317
00318
00319 if (!fDirListValid) {
00320 TXNetSystemConnectGuard cg(this, fUrl);
00321 if (cg.IsValid()) {
00322 Bool_t ok = cg.ClientAdmin()->DirList(fDir, fDirList);
00323 cg.ClientAdmin()->GoBackToRedirector();
00324 if (ok) {
00325 fDirListValid = kTRUE;
00326 } else {
00327 cg.NotifyLastError();
00328 return 0;
00329 }
00330 }
00331 }
00332
00333
00334 if (fDirList.GetSize() > 0) {
00335 fDirEntry = fDirList.Pop_front().c_str();
00336 return fDirEntry.Data();
00337 }
00338 return 0;
00339 }
00340
00341 if (gDebug > 1) Info("GetDirEntry","Calling TNetSystem::GetDirEntry");
00342 return TNetSystem::GetDirEntry(dirp);
00343 }
00344
00345
00346 Int_t TXNetSystem::GetPathInfo(const char* path, FileStat_t &buf)
00347 {
00348
00349
00350
00351
00352
00353
00354 if (fIsXRootd) {
00355 TXNetSystemConnectGuard cg(this, path);
00356 if (cg.IsValid()) {
00357
00358 Long_t id;
00359 Long64_t size;
00360 Long_t flags;
00361 Long_t modtime;
00362
00363
00364 TUrl urlpath(path);
00365 Bool_t ok = cg.ClientAdmin()->Stat(urlpath.GetFile(),id,size,flags,modtime);
00366 if (ok) {
00367
00368 urlpath.SetProtocol(cg.ClientAdmin()->GetCurrentUrl().Proto.c_str());
00369 urlpath.SetHost(cg.ClientAdmin()->GetCurrentUrl().Host.c_str());
00370 urlpath.SetPort(cg.ClientAdmin()->GetCurrentUrl().Port);
00371 buf.fUrl = urlpath.GetUrl();
00372 }
00373 cg.ClientAdmin()->GoBackToRedirector();
00374
00375
00376 if (flags & kXR_offline) {
00377 buf.fMode = kS_IFOFF;
00378 } else if (ok) {
00379 buf.fDev = (id >> 24);
00380 buf.fIno = (id & 0x00FFFFFF);
00381 buf.fUid = -1;
00382 buf.fGid = -1;
00383 buf.fSize = size;
00384 buf.fMtime = modtime;
00385
00386 if (flags == 0) buf.fMode = kS_IFREG;
00387 if (flags & kXR_xset) buf.fMode = (kS_IFREG|kS_IXUSR|kS_IXGRP|kS_IXOTH);
00388 if (flags & kXR_isDir) buf.fMode = kS_IFDIR;
00389 if (flags & kXR_other) buf.fMode = kS_IFSOCK;
00390 if (flags & kXR_readable) buf.fMode |= kS_IRUSR;
00391 if (flags & kXR_writable) buf.fMode |= kS_IWUSR;
00392
00393 buf.fIsLink = 0;
00394 return 0;
00395 } else {
00396 if (gDebug > 0)
00397 cg.NotifyLastError();
00398 }
00399 }
00400 return 1;
00401 }
00402
00403 if (gDebug > 1)
00404 Info("GetPathInfo","Calling TNetSystem::GetPathInfo");
00405 return TNetSystem::GetPathInfo(path,buf);
00406 }
00407
00408
00409 Bool_t TXNetSystem::ConsistentWith(const char *path, void *dirptr)
00410 {
00411
00412
00413
00414 if (gDebug > 1)
00415 Info("ConsistentWith",
00416 "calling for path: %s, dir: %p", path, dirptr);
00417
00418 return TNetSystem::ConsistentWith(path,dirptr);
00419 }
00420
00421
00422 Bool_t TXNetSystem::AccessPathName(const char *path, EAccessMode mode)
00423 {
00424
00425
00426
00427
00428
00429
00430 if (fIsXRootd) {
00431
00432 FileStat_t buf;
00433 if (GetPathInfo(path, buf) == 0)
00434 if (buf.fMode != kS_IFSOCK)
00435 return kFALSE;
00436
00437 return kTRUE;
00438 }
00439
00440 if (gDebug > 1)
00441 Info("AccessPathName", "calling TNetSystem::AccessPathName");
00442 return TNetSystem::AccessPathName(path,mode);
00443 }
00444
00445
00446 int TXNetSystem::Unlink(const char *path)
00447 {
00448
00449
00450
00451 if (fIsXRootd) {
00452
00453 TXNetSystemConnectGuard cg(this, path);
00454 if (cg.IsValid()) {
00455
00456 Long_t id;
00457 Long64_t size;
00458 Long_t flags;
00459 Long_t modtime;
00460
00461
00462 TString edir = TUrl(path).GetFile();
00463 Bool_t ok = cg.ClientAdmin()->Stat(edir.Data(), id, size, flags, modtime);
00464
00465
00466 if (ok && !(flags & kXR_offline)) {
00467 if (flags & kXR_isDir)
00468 ok = cg.ClientAdmin()->Rmdir(edir.Data());
00469 else
00470 ok = cg.ClientAdmin()->Rm(edir.Data());
00471 cg.ClientAdmin()->GoBackToRedirector();
00472
00473
00474 return ((ok) ? 0 : -1);
00475 } else if (!ok) {
00476 cg.ClientAdmin()->GoBackToRedirector();
00477 cg.NotifyLastError();
00478 }
00479 }
00480 }
00481
00482 if (gDebug > 1)
00483 Info("Unlink", "calling TNetSystem::Unlink");
00484 return -1;
00485 }
00486
00487
00488 Bool_t TXNetSystem::IsOnline(const char *path)
00489 {
00490
00491
00492
00493 FileStat_t st;
00494 if (GetPathInfo(path, st) != 0) {
00495 if (gDebug > 0)
00496 Info("IsOnline", "path '%s' cannot be stat'ed", path);
00497 return kFALSE;
00498 }
00499 if (R_ISOFF(st.fMode)) {
00500 if (gDebug > 0)
00501 Info("IsOnline", "path '%s' is offline", path);
00502 return kFALSE;
00503 }
00504
00505 return kTRUE;
00506 }
00507
00508
00509 Bool_t TXNetSystem::Prepare(const char *path, UChar_t option, UChar_t priority)
00510 {
00511
00512
00513 TXNetSystemConnectGuard cg(this, path);
00514 if (cg.IsValid()) {
00515 XrdOucString pathname = TUrl(path).GetFileAndOptions();
00516 vecString vs;
00517 vs.Push_back(pathname);
00518 cg.ClientAdmin()->Prepare(vs, (kXR_char)option, (kXR_char)priority);
00519 cg.ClientAdmin()->GoBackToRedirector();
00520 if (gDebug >0)
00521 Info("Prepare", "Got Status %d for %s",
00522 cg.ClientAdmin()->LastServerResp()->status, pathname.c_str());
00523 if (!(cg.ClientAdmin()->LastServerResp()->status)){
00524 return kTRUE;
00525 }
00526 cg.NotifyLastError();
00527 }
00528
00529
00530 return kFALSE;
00531 }
00532
00533
00534 Int_t TXNetSystem::Prepare(TCollection *paths,
00535 UChar_t opt, UChar_t prio, TString *bufout)
00536 {
00537
00538
00539
00540
00541
00542
00543 if (!paths) {
00544 Warning("Prepare", "input list is empty!");
00545 return -1;
00546 }
00547
00548 Int_t npaths = 0;
00549
00550 TXNetSystemConnectGuard cg(this, "");
00551 if (cg.IsValid()) {
00552
00553 TString *buf = (bufout) ? bufout : new TString();
00554
00555
00556 TObject *o = 0;
00557 TUrl u;
00558 TString path;
00559 TIter nxt(paths);
00560 while ((o = nxt())) {
00561
00562 TString pn = TFileStager::GetPathName(o);
00563 if (pn == "") {
00564 Warning("Prepare", "object is of unexpected type %s - ignoring", o->ClassName());
00565 continue;
00566 }
00567 u.SetUrl(pn);
00568
00569 path = u.GetFileAndOptions();
00570 path.ReplaceAll("\n","\r");
00571 npaths++;
00572 *buf += Form("%s\n", path.Data());
00573 }
00574
00575 Info("Prepare","buffer ready: issuing prepare ...");
00576 cg.ClientAdmin()->Prepare(buf->Data(), (kXR_char)opt, (kXR_char)prio);
00577 cg.ClientAdmin()->GoBackToRedirector();
00578 if (!bufout)
00579 delete buf;
00580 if (gDebug >0)
00581 Info("Prepare", "Got Status %d",
00582 cg.ClientAdmin()->LastServerResp()->status);
00583 if (!(cg.ClientAdmin()->LastServerResp()->status)){
00584 return npaths;
00585 }
00586 cg.NotifyLastError();
00587 }
00588
00589
00590 return -1;
00591 }
00592
00593
00594 Bool_t TXNetSystem::GetPathsInfo(const char *paths, UChar_t *info)
00595 {
00596
00597
00598
00599
00600 if (!paths) {
00601 Warning("GetPathsInfo", "input list is empty!");
00602 return kFALSE;
00603 }
00604
00605 TXNetSystemConnectGuard cg(this, "");
00606 if (cg.IsValid()) {
00607 cg.ClientAdmin()->SysStatX(paths, info);
00608 cg.ClientAdmin()->GoBackToRedirector();
00609 if (gDebug >0)
00610 Info("GetPathsInfo", "Got Status %d",
00611 cg.ClientAdmin()->LastServerResp()->status);
00612 if (!(cg.ClientAdmin()->LastServerResp()->status)){
00613 return kTRUE;
00614 }
00615 cg.NotifyLastError();
00616 }
00617
00618
00619 return kFALSE;
00620 }
00621
00622
00623 Bool_t TXNetSystem::IsPathLocal(const char *path)
00624 {
00625
00626
00627
00628 if (fIsXRootd) {
00629 TXNetSystemConnectGuard cg(this, path);
00630 if (cg.IsValid()) {
00631 if (cg.ClientAdmin()->GetClientConn()->GetServerType() != kSTDataXrootd) {
00632
00633 return kFALSE;
00634 }
00635 }
00636 }
00637
00638 return TSystem::IsPathLocal(path);
00639 }
00640
00641
00642 Int_t TXNetSystem::Locate(const char *path, TString &eurl)
00643 {
00644
00645
00646
00647
00648 if (fIsXRootd) {
00649 TXNetSystemConnectGuard cg(this, path);
00650 if (cg.IsValid()) {
00651
00652 #ifndef OLDXRDLOCATE
00653
00654 XrdClientLocate_Info li;
00655 TString edir = TUrl(path).GetFile();
00656
00657 if (cg.ClientAdmin()->Locate((kXR_char *)edir.Data(), li)) {
00658 TUrl u(path);
00659 XrdClientUrlInfo ui((const char *)&li.Location[0]);
00660
00661
00662 TNamed *hn = 0;
00663 if (fgAddrFQDN.GetSize() <= 0 ||
00664 !(hn = dynamic_cast<TNamed *>(fgAddrFQDN.FindObject(ui.Host.c_str())))) {
00665 TInetAddress a(gSystem->GetHostByName(ui.Host.c_str()));
00666 if (strlen(a.GetHostName()) > 0)
00667 hn = new TNamed(ui.Host.c_str(), a.GetHostName());
00668 else
00669 hn = new TNamed(ui.Host.c_str(), ui.Host.c_str());
00670 fgAddrFQDN.Add(hn);
00671 if (gDebug > 0)
00672 Info("Locate","caching host name: %s", hn->GetTitle());
00673 }
00674 if (hn)
00675 u.SetHost(hn->GetTitle());
00676 else
00677 u.SetHost(ui.Host.c_str());
00678 u.SetPort(ui.Port);
00679 eurl = u.GetUrl();
00680 return 0;
00681 }
00682 #else
00683
00684 XrdClientUrlInfo ui;
00685 TString edir = TUrl(path).GetFile();
00686
00687 if (cg.ClientAdmin()->Locate((kXR_char *)edir.Data(), ui, kTRUE)) {
00688 TUrl u(path);
00689 u.SetHost(ui.Host.c_str());
00690 u.SetPort(ui.Port);
00691 eurl = u.GetUrl();
00692 return 0;
00693 }
00694 #endif
00695 cg.NotifyLastError();
00696 }
00697 return 1;
00698 }
00699
00700
00701 if (gDebug > 0) Info("Locate", "server not Xrootd: method not implemented!");
00702 return -1;
00703 }
00704
00705 #ifndef OLDXRDLOCATE
00706
00707 XrdClientAdmin *TXNetSystem::GetClientAdmin(const char *url)
00708 {
00709
00710
00711 XrdClientAdmin *ca = 0;
00712
00713
00714 TString key = TXNetSystem::GetKey(url);
00715
00716
00717 TXrdClientAdminWrapper *caw = 0;
00718 if (fgAdminHash.GetSize() > 0 &&
00719 (caw = dynamic_cast<TXrdClientAdminWrapper *>(fgAdminHash.FindObject(key.Data()))))
00720 return caw->fXCA;
00721
00722
00723 ca = new XrdClientAdmin(url);
00724 fgAdminHash.Add(new TXrdClientAdminWrapper(key, ca));
00725
00726
00727 return ca;
00728 }
00729
00730
00731 TString TXNetSystem::GetKey(const char *url)
00732 {
00733
00734
00735 TUrl u(url);
00736 TString key(u.GetUser());
00737 if (!key.IsNull())
00738 key += "@";
00739 key += u.GetHost();
00740 if (u.GetPort() > 0) {
00741 key += ":";
00742 key += u.GetPort();
00743 }
00744
00745
00746 return key;
00747 }
00748
00749
00750
00751
00752
00753 TXrdClientAdminWrapper::~TXrdClientAdminWrapper()
00754 {
00755
00756
00757 SafeDelete(fXCA);
00758 }
00759 #endif
00760
00761
00762
00763
00764
00765 TXNetSystemConnectGuard::TXNetSystemConnectGuard(TXNetSystem *xn, const char *url)
00766 : fClientAdmin(0)
00767 {
00768
00769
00770 if (xn)
00771
00772 fClientAdmin = (url && strlen(url) > 0) ? xn->Connect(url)
00773 : xn->Connect(xn->fUrl);
00774 }
00775
00776
00777 TXNetSystemConnectGuard::~TXNetSystemConnectGuard()
00778 {
00779
00780
00781 fClientAdmin = 0;
00782 }
00783
00784
00785 void TXNetSystemConnectGuard::NotifyLastError()
00786 {
00787
00788
00789 if (fClientAdmin)
00790 if (fClientAdmin->GetClientConn())
00791 Printf("Srv err: %s", fClientAdmin->GetClientConn()->LastServerError.errmsg);
00792 }