00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <errno.h>
00024
00025 #include "TApplicationRemote.h"
00026
00027 #include "TBrowser.h"
00028 #include "TDirectory.h"
00029 #include "TError.h"
00030 #include "THashList.h"
00031 #include "TMonitor.h"
00032 #include "TRandom.h"
00033 #include "TROOT.h"
00034 #include "TServerSocket.h"
00035 #include "TSystem.h"
00036 #include "TRemoteObject.h"
00037 #ifdef WIN32
00038 #include <io.h>
00039 #include <sys/types.h>
00040 #endif
00041
00042
00043
00044
00045 Bool_t TARInterruptHandler::Notify()
00046 {
00047
00048
00049 Info("Notify","Processing interrupt signal ...");
00050
00051
00052 fApplicationRemote->Interrupt(kRRI_Hard);
00053
00054 return kTRUE;
00055 }
00056
00057
00058 ClassImp(TApplicationRemote)
00059
00060 static const char *gScript = "roots";
00061 static const char *gScriptCmd = "\\\"%s %d localhost:%d/%s -d=%d\\\"";
00062 #ifndef WIN32
00063 static const char *gSshCmd = "ssh %s -f4 %s -R %d:localhost:%d sh -c \
00064 \"'(sh=\\`basename \'\\\\\\$SHELL\'\\`; \
00065 if test xbash = x\'\\\\\\$sh\' -o xsh = x\'\\\\\\$sh\' -o xzsh = x\'\\\\\\$sh\' -o xdash = x\'\\\\\\$sh\'; then \
00066 \'\\\\\\$SHELL\' -l -c %s; \
00067 elif test xcsh = x\'\\\\\\$sh\' -o xtcsh = x\'\\\\\\$sh\' -o xksh = x\'\\\\\\$sh\'; then \
00068 \'\\\\\\$SHELL\' -c %s; \
00069 else \
00070 echo \\\"Unknown shell \'\\\\\\$SHELL\'\\\"; \
00071 fi)'\"";
00072 #else
00073 static const char *gSshCmd = "ssh %s -f4 %s -R %d:localhost:%d sh -c \
00074 \"'(sh=`basename $SHELL`; \
00075 if test xbash = x$sh -o xsh = x$sh -o xzsh = x$sh -o xdash = x$sh; then \
00076 $SHELL -l -c %s; \
00077 elif test xcsh = x$sh -o xtcsh = x$sh -o xksh = x$sh; then \
00078 $SHELL -c %s; \
00079 else \
00080 echo \"Unknown shell $SHELL\"; \
00081 fi)'\"";
00082 #endif
00083
00084 Int_t TApplicationRemote::fgPortAttempts = 100;
00085 Int_t TApplicationRemote::fgPortLower = 49152;
00086 Int_t TApplicationRemote::fgPortUpper = 65535;
00087
00088
00089 TApplicationRemote::TApplicationRemote(const char *url, Int_t debug,
00090 const char *script)
00091 : TApplication(), fUrl(url)
00092 {
00093
00094
00095
00096
00097
00098 fName = fUrl.GetHost();
00099 if (strlen(fUrl.GetOptions()) > 0)
00100 fName += Form("-%s", fUrl.GetOptions());
00101 UserGroup_t *pw = gSystem->GetUserInfo(gSystem->GetEffectiveUid());
00102 TString user = (pw) ? pw->fUser : "";
00103 SafeDelete(pw);
00104 if (strlen(fUrl.GetUser()) > 0 && user != fUrl.GetUser())
00105 fName.Insert(0,Form("%s@", fUrl.GetUser()));
00106
00107 fIntHandler = 0;
00108 fSocket = 0;
00109 fMonitor = 0;
00110 fFileList = 0;
00111 fWorkingDir = 0;
00112 fRootFiles = 0;
00113 fReceivedObject = 0;
00114 ResetBit(kCollecting);
00115
00116
00117 Int_t port = -1;
00118 Int_t na = fgPortAttempts;
00119 Long64_t now = gSystem->Now();
00120 gRandom->SetSeed((UInt_t)now);
00121 TServerSocket *ss = 0;
00122 while (na--) {
00123 port = (Int_t) (gRandom->Rndm() * (fgPortUpper - fgPortLower)) + fgPortLower;
00124 ss = new TServerSocket(port);
00125 if (ss->IsValid())
00126 break;
00127 }
00128 if (!ss || !ss->IsValid()) {
00129 Error("TApplicationRemote","unable to find a free port for connections");
00130 SetBit(kInvalidObject);
00131 return;
00132 }
00133
00134
00135 TMonitor *mon = new TMonitor;
00136 mon->Add(ss);
00137
00138
00139 Int_t rport = (port < fgPortUpper) ? port + 1 : port - 1;
00140 TString sc = gScript;
00141 if (script && *script) {
00142
00143 if (script[1] == '<') {
00144 if (script[2])
00145 sc.Form("source %s; %s", script+2, gScript);
00146 else
00147 Error("TApplicationRemote", "illegal script name <");
00148 } else
00149 sc = script;
00150 }
00151 sc.ReplaceAll("\"","");
00152 TString userhost = fUrl.GetHost();
00153 if (strlen(fUrl.GetUser()) > 0)
00154 userhost.Insert(0, Form("%s@", fUrl.GetUser()));
00155 const char *verb = "";
00156 if (debug > 0)
00157 verb = "-v";
00158 TString scriptCmd;
00159 scriptCmd.Form(gScriptCmd, sc.Data(), kRRemote_Protocol, rport, fUrl.GetFile(), debug);
00160 TString cmd;
00161 cmd.Form(gSshCmd, verb, userhost.Data(), rport, port, scriptCmd.Data(), scriptCmd.Data());
00162 #ifdef WIN32
00163
00164 TApplication::NeedGraphicsLibs();
00165 gApplication->InitializeGraphics();
00166 #endif
00167 if (gDebug > 0)
00168 Info("TApplicationRemote", "executing: %s", cmd.Data());
00169 if (gSystem->Exec(cmd) != 0) {
00170 Info("TApplicationRemote", "an error occured during SSH connection");
00171 mon->DeActivateAll();
00172 delete mon;
00173 delete ss;
00174 SafeDelete(fSocket);
00175 SetBit(kInvalidObject);
00176 return;
00177 }
00178
00179
00180 mon->Select();
00181
00182
00183 fSocket = ss->Accept();
00184
00185
00186 mon->DeActivateAll();
00187 delete mon;
00188 delete ss;
00189
00190
00191 Int_t what;
00192 char buf[512];
00193 if (fSocket->Recv(buf, sizeof(buf), what) <= 0) {
00194 Error("TApplicationRemote", "failed to receive startup message");
00195 SafeDelete(fSocket);
00196 SetBit(kInvalidObject);
00197 return;
00198 }
00199 Printf("%s", buf);
00200
00201
00202 if (fSocket->Recv(fProtocol, what) != 2*sizeof(Int_t)) {
00203 Error("TApplicationRemote", "failed to receive remote server protocol");
00204 SafeDelete(fSocket);
00205 SetBit(kInvalidObject);
00206 return;
00207 }
00208 if (fProtocol != kRRemote_Protocol)
00209 Info("TApplicationRemote","server runs a different protocol version: %d (vs %d)",
00210 fProtocol, kRRemote_Protocol);
00211
00212 TMessage *msg = 0;
00213
00214 if (fSocket->Recv(msg) < 0 || msg->What() != kMESS_ANY) {
00215 Error("TApplicationRemote", "failed to receive server info - protocol error");
00216 SafeDelete(fSocket);
00217 SetBit(kInvalidObject);
00218 return;
00219 }
00220
00221
00222 TString hostname;
00223 (*msg) >> hostname >> fLogFilePath;
00224 fUrl.SetHost(hostname);
00225
00226
00227 fMonitor = new TMonitor;
00228 fMonitor->Add(fSocket);
00229
00230
00231 fIntHandler = new TARInterruptHandler(this);
00232
00233
00234 gROOT->GetListOfSockets()->Remove(fSocket);
00235 gROOT->GetListOfSockets()->Add(this);
00236
00237 fRootFiles = new TList;
00238 fRootFiles->SetName("Files");
00239
00240
00241 Collect();
00242
00243
00244 return;
00245 }
00246
00247
00248 TApplicationRemote::~TApplicationRemote()
00249 {
00250
00251
00252 gROOT->GetListOfSockets()->Remove(this);
00253 Terminate(0);
00254 }
00255
00256
00257 Int_t TApplicationRemote::Broadcast(const TMessage &mess)
00258 {
00259
00260
00261
00262 if (!IsValid()) return -1;
00263
00264 if (fSocket->Send(mess) == -1) {
00265 Error("Broadcast", "could not send message");
00266 return -1;
00267 }
00268
00269 return 0;
00270 }
00271
00272
00273 Int_t TApplicationRemote::Broadcast(const char *str, Int_t kind, Int_t type)
00274 {
00275
00276
00277
00278
00279 TMessage mess(kind);
00280 if (kind == kMESS_ANY)
00281 mess << type;
00282 if (str) mess.WriteString(str);
00283 return Broadcast(mess);
00284 }
00285
00286
00287 Int_t TApplicationRemote::BroadcastObject(const TObject *obj, Int_t kind)
00288 {
00289
00290
00291
00292
00293 TMessage mess(kind);
00294 mess.WriteObject(obj);
00295 return Broadcast(mess);
00296 }
00297
00298
00299 Int_t TApplicationRemote::BroadcastRaw(const void *buffer, Int_t length)
00300 {
00301
00302
00303
00304 if (!IsValid()) return -1;
00305
00306 if (fSocket->SendRaw(buffer, length) == -1) {
00307 Error("Broadcast", "could not send raw buffer");
00308 return -1;
00309 }
00310
00311 return 0;
00312 }
00313
00314
00315 Int_t TApplicationRemote::Collect(Long_t timeout)
00316 {
00317
00318
00319
00320
00321
00322
00323 fMonitor->ActivateAll();
00324 if (!fMonitor->GetActive())
00325 return 0;
00326
00327
00328 Long_t nto = timeout;
00329 if (gDebug > 2)
00330 Info("Collect","active: %d", fMonitor->GetActive());
00331
00332
00333 if (fIntHandler)
00334 fIntHandler->Add();
00335
00336
00337 SetBit(kCollecting);
00338
00339 Int_t rc = 0, cnt = 0;
00340 while (fMonitor->GetActive() && (nto < 0 || nto > 0)) {
00341
00342
00343 TSocket *s = fMonitor->Select(1000);
00344
00345 if (s && s != (TSocket *)(-1)) {
00346
00347 if ((rc = CollectInput()) != 0) {
00348
00349 fMonitor->DeActivate(s);
00350 if (gDebug > 2)
00351 Info("Collect","deactivating %p", s);
00352 }
00353
00354
00355 if (rc >= 0)
00356 cnt++;
00357
00358 } else {
00359
00360
00361
00362 if (!s)
00363 fMonitor->DeActivateAll();
00364
00365 if (s == (TSocket *)(-1) && nto > 0)
00366 nto--;
00367 }
00368 }
00369
00370
00371 ResetBit(kCollecting);
00372
00373
00374 if (nto == 0)
00375 fMonitor->DeActivateAll();
00376
00377
00378 if (fIntHandler)
00379 fIntHandler->Remove();
00380
00381 return cnt;
00382 }
00383
00384
00385 Int_t TApplicationRemote::CollectInput()
00386 {
00387
00388
00389
00390 TMessage *mess;
00391 Int_t rc = 0;
00392
00393 char str[512];
00394 TObject *obj;
00395 Int_t what;
00396 Bool_t delete_mess = kTRUE;
00397
00398 if (fSocket->Recv(mess) < 0) {
00399 SetBit(kInvalidObject);
00400 SafeDelete(fSocket);
00401 return -1;
00402 }
00403 if (!mess) {
00404
00405 SetBit(kInvalidObject);
00406 SafeDelete(fSocket);
00407 return -1;
00408 }
00409
00410 what = mess->What();
00411
00412 if (gDebug > 2)
00413 Info("CollectInput","what %d", what);
00414
00415 switch (what) {
00416
00417 case kMESS_OBJECT:
00418 {
00419 TObject *o = mess->ReadObject(mess->GetClass());
00420
00421 if (TString(o->ClassName()) == "TCanvas")
00422 o->Draw();
00423 else if (TString(o->ClassName()) == "TRemoteObject") {
00424 TRemoteObject *robj = (TRemoteObject *)o;
00425 if (TString(robj->GetClassName()) == "TSystemDirectory") {
00426 if (fWorkingDir == 0) {
00427 fWorkingDir = (TRemoteObject *)o;
00428 }
00429 }
00430 }
00431 else if (TString(o->ClassName()) == "TList") {
00432 TList *list = (TList *)o;
00433 TRemoteObject *robj = (TRemoteObject *)list->First();
00434 if (robj && (TString(robj->GetClassName()) == "TFile")) {
00435 TIter next(list);
00436 while ((robj = (TRemoteObject *)next())) {
00437 if (!fRootFiles->FindObject(robj->GetName()))
00438 fRootFiles->Add(robj);
00439 }
00440 gROOT->RefreshBrowsers();
00441 }
00442 }
00443 fReceivedObject = o;
00444 }
00445 break;
00446
00447 case kMESS_ANY:
00448
00449 { Int_t type;
00450 (*mess) >> type;
00451
00452 if (gDebug > 2)
00453 Info("CollectInput","type %d", type);
00454
00455 switch (type) {
00456
00457 case kRRT_GetObject:
00458
00459 mess->ReadString(str, sizeof(str));
00460 obj = gDirectory->Get(str);
00461 if (obj) {
00462 fSocket->SendObject(obj);
00463 } else {
00464 Warning("CollectInput",
00465 "server requested an object that we do not have");
00466 fSocket->Send(kMESS_NOTOK);
00467 }
00468 break;
00469
00470 case kRRT_Fatal:
00471
00472 SafeDelete(fSocket);
00473 rc = -1;
00474 break;
00475
00476 case kRRT_LogFile:
00477 { Int_t size;
00478 (*mess) >> size;
00479 RecvLogFile(size);
00480 }
00481 break;
00482
00483 case kRRT_LogDone:
00484 { Int_t st;
00485 (*mess) >> st;
00486 if (st < 0) {
00487
00488 SetBit(kInvalidObject);
00489 }
00490 if (gDebug > 1)
00491 Info("CollectInput","kRTT_LogDone: status %d", st);
00492 rc = 1;
00493 }
00494 break;
00495
00496 case kRRT_Message:
00497 { TString msg;
00498 Bool_t lfeed;
00499 (*mess) >> msg >> lfeed;
00500 if (lfeed)
00501 fprintf(stderr,"%s\n", msg.Data());
00502 else
00503 fprintf(stderr,"%s\r", msg.Data());
00504 }
00505 break;
00506
00507 case kRRT_SendFile:
00508 { TString fname;
00509 (*mess) >> fname;
00510
00511 TMessage m(kMESS_ANY);
00512 m << (Int_t) kRRT_SendFile;
00513
00514
00515 char *imp = gSystem->Which(TROOT::GetMacroPath(), fname, kReadPermission);
00516 if (!imp) {
00517 Error("CollectInput", "file %s not found in path(s) %s",
00518 fname.Data(), TROOT::GetMacroPath());
00519 m << (Bool_t) kFALSE;
00520 Broadcast(m);
00521 } else {
00522 TString impfile = imp;
00523 delete [] imp;
00524 Int_t dot = impfile.Last('.');
00525
00526
00527 Bool_t hasHeader = kTRUE;
00528 TString headfile = impfile;
00529 if (dot != kNPOS)
00530 headfile.Remove(dot);
00531 headfile += ".h";
00532 if (gSystem->AccessPathName(headfile, kReadPermission)) {
00533 TString h = headfile;
00534 headfile.Remove(dot);
00535 headfile += ".hh";
00536 if (gSystem->AccessPathName(headfile, kReadPermission)) {
00537 hasHeader = kFALSE;
00538 if (gDebug > 0)
00539 Info("CollectInput", "no associated header file"
00540 " found: tried: %s %s",
00541 h.Data(), headfile.Data());
00542 }
00543 }
00544
00545
00546 m << (Bool_t) kTRUE;
00547 Broadcast(m);
00548 if (SendFile(impfile, kForce) == -1) {
00549 Info("CollectInput", "problems sending file %s", impfile.Data());
00550 return 0;
00551 }
00552 if (hasHeader) {
00553 Broadcast(m);
00554 if (SendFile(headfile, kForce) == -1) {
00555 Info("CollectInput", "problems sending file %s", headfile.Data());
00556 return 0;
00557 }
00558 }
00559 }
00560
00561 m.Reset(kMESS_ANY);
00562 m << (Int_t) kRRT_SendFile;
00563 m << (Bool_t) kFALSE;
00564 Broadcast(m);
00565 }
00566 break;
00567
00568 default:
00569 Warning("CollectInput","unknown type received from server: %d", type);
00570 break;
00571
00572 }
00573 }
00574 break;
00575
00576 default:
00577 Error("CollectInput", "unknown command received from server: %d", what);
00578 SetBit(kInvalidObject);
00579 SafeDelete(fSocket);
00580 rc = -1;
00581 break;
00582 }
00583
00584
00585 if (delete_mess)
00586 delete mess;
00587
00588
00589 return rc;
00590 }
00591
00592
00593
00594 void TApplicationRemote::RecvLogFile(Int_t size)
00595 {
00596
00597
00598 const Int_t kMAXBUF = 16384;
00599 char buf[kMAXBUF];
00600
00601
00602 Int_t fdout = fileno(stdout);
00603 if (fdout < 0) {
00604 Warning("RecvLogFile", "file descriptor for outputs undefined (%d):"
00605 " will not log msgs", fdout);
00606 return;
00607 }
00608 lseek(fdout, (off_t) 0, SEEK_END);
00609
00610 Int_t left, rec, r;
00611 Long_t filesize = 0;
00612
00613 while (filesize < size) {
00614 left = Int_t(size - filesize);
00615 if (left > kMAXBUF)
00616 left = kMAXBUF;
00617 rec = fSocket->RecvRaw(&buf, left);
00618 filesize = (rec > 0) ? (filesize + rec) : filesize;
00619 if (rec > 0) {
00620
00621 char *p = buf;
00622 r = rec;
00623 while (r) {
00624 Int_t w;
00625
00626 w = write(fdout, p, r);
00627
00628 if (w < 0) {
00629 SysError("RecvLogFile", "error writing to unit: %d", fdout);
00630 break;
00631 }
00632 r -= w;
00633 p += w;
00634 }
00635 } else if (rec < 0) {
00636 Error("RecvLogFile", "error during receiving log file");
00637 break;
00638 }
00639 }
00640 }
00641
00642
00643 Int_t TApplicationRemote::SendObject(const TObject *obj)
00644 {
00645
00646
00647
00648 if (!IsValid() || !obj) return -1;
00649
00650 TMessage mess(kMESS_OBJECT);
00651 mess.WriteObject(obj);
00652 return Broadcast(mess);
00653 }
00654
00655
00656 Bool_t TApplicationRemote::CheckFile(const char *file, Long_t modtime)
00657 {
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670 Bool_t sendto = kFALSE;
00671
00672 if (!IsValid()) return -1;
00673
00674
00675 TString fn = gSystem->BaseName(file);
00676
00677
00678 TARFileStat *fs = 0;
00679 if (fFileList && (fs = (TARFileStat *) fFileList->FindObject(fn))) {
00680
00681 if (fs->fModtime != modtime) {
00682 TMD5 *md5 = TMD5::FileChecksum(file);
00683 if (md5) {
00684 if ((*md5) != fs->fMD5) {
00685 sendto = kTRUE;
00686 fs->fMD5 = *md5;
00687 fs->fModtime = modtime;
00688 }
00689 delete md5;
00690 } else {
00691 Error("CheckFile", "could not calculate local MD5 check sum - dont send");
00692 return kFALSE;
00693 }
00694 }
00695 } else {
00696
00697 TMD5 *md5 = TMD5::FileChecksum(file);
00698 if (md5) {
00699 fs = new TARFileStat(fn, *md5, modtime);
00700 if (!fFileList)
00701 fFileList = new THashList;
00702 fFileList->Add(fs);
00703 delete md5;
00704 } else {
00705 Error("CheckFile", "could not calculate local MD5 check sum - dont send");
00706 return kFALSE;
00707 }
00708 TMessage mess(kMESS_ANY);
00709 mess << Int_t(kRRT_CheckFile) << TString(gSystem->BaseName(file)) << fs->fMD5;
00710 fSocket->Send(mess);
00711
00712 TMessage *reply;
00713 fSocket->Recv(reply);
00714 if (reply) {
00715 if (reply->What() == kMESS_ANY) {
00716
00717 Int_t type;
00718 Bool_t uptodate;
00719 (*reply) >> type >> uptodate;
00720 if (type != kRRT_CheckFile) {
00721
00722 Warning("CheckFile", "received wrong type:"
00723 " %d (expected %d): protocol error?",
00724 type, (Int_t)kRRT_CheckFile);
00725 }
00726 sendto = uptodate ? kFALSE : kTRUE;
00727 } else {
00728
00729 Error("CheckFile", "received wrong message: %d (expected %d)",
00730 reply->What(), kMESS_ANY);
00731 }
00732 } else {
00733 Error("CheckFile", "received empty message");
00734 }
00735
00736 Collect();
00737 }
00738
00739
00740 return sendto;
00741 }
00742
00743
00744 Int_t TApplicationRemote::SendFile(const char *file, Int_t opt, const char *rfile)
00745 {
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758 if (!IsValid()) return -1;
00759
00760 #ifndef R__WIN32
00761 Int_t fd = open(file, O_RDONLY);
00762 #else
00763 Int_t fd = open(file, O_RDONLY | O_BINARY);
00764 #endif
00765 if (fd < 0) {
00766 SysError("SendFile", "cannot open file %s", file);
00767 return -1;
00768 }
00769
00770
00771 Long64_t size;
00772 Long_t id, flags, modtime;
00773 if (gSystem->GetPathInfo(file, &id, &size, &flags, &modtime) == 1) {
00774 Error("SendFile", "cannot stat file %s", file);
00775 return -1;
00776 }
00777 if (size == 0) {
00778 Error("SendFile", "empty file %s", file);
00779 return -1;
00780 }
00781
00782
00783 Bool_t bin = (opt & kBinary) ? kTRUE : kFALSE;
00784 Bool_t force = (opt & kForce) ? kTRUE : kFALSE;
00785
00786 const Int_t kMAXBUF = 32768;
00787 char buf[kMAXBUF];
00788
00789 const char *fnam = (rfile) ? rfile : gSystem->BaseName(file);
00790
00791 Bool_t sendto = force ? kTRUE : CheckFile(file, modtime);
00792
00793
00794
00795 size = sendto ? size : 0;
00796
00797 if (gDebug > 1 && size > 0)
00798 Info("SendFile", "sending file %s", file);
00799
00800 snprintf(buf, kMAXBUF, "%s %d %lld", fnam, bin, size);
00801 if (Broadcast(buf, kMESS_ANY, kRRT_File) == -1) {
00802 SafeDelete(fSocket);
00803 return -1;
00804 }
00805
00806 if (sendto) {
00807
00808 lseek(fd, 0, SEEK_SET);
00809
00810 Int_t len;
00811 do {
00812 while ((len = read(fd, buf, kMAXBUF)) < 0 && TSystem::GetErrno() == EINTR)
00813 TSystem::ResetErrno();
00814
00815 if (len < 0) {
00816 SysError("SendFile", "error reading from file %s", file);
00817 Interrupt();
00818 close(fd);
00819 return -1;
00820 }
00821
00822 if (len > 0 && fSocket->SendRaw(buf, len) == -1) {
00823 SysError("SendFile", "error writing to server @ %s:%d (now offline)",
00824 fUrl.GetHost(), fUrl.GetPort());
00825 SafeDelete(fSocket);
00826 break;
00827 }
00828
00829 } while (len > 0);
00830 }
00831 close(fd);
00832
00833
00834 if (!TestBit(kCollecting))
00835 Collect();
00836
00837
00838 return IsValid() ? 0 : -1;
00839 }
00840
00841
00842 void TApplicationRemote::Terminate(Int_t status)
00843 {
00844
00845
00846 TMessage mess(kMESS_ANY);
00847 mess << (Int_t)kRRT_Terminate << status;
00848 Broadcast(mess);
00849
00850 SafeDelete(fRootFiles);
00851 SafeDelete(fMonitor);
00852 SafeDelete(fSocket);
00853 }
00854
00855
00856 void TApplicationRemote::SetPortParam(Int_t lower, Int_t upper, Int_t attempts)
00857 {
00858
00859
00860 if (lower > -1)
00861 fgPortLower = lower;
00862 if (upper > -1)
00863 fgPortUpper = upper;
00864 if (attempts > -1)
00865 fgPortAttempts = attempts;
00866
00867 ::Info("TApplicationRemote::SetPortParam","port scan: %d attempts in [%d,%d]",
00868 fgPortAttempts, fgPortLower, fgPortUpper);
00869 }
00870
00871
00872 Long_t TApplicationRemote::ProcessLine(const char *line, Bool_t, Int_t *)
00873 {
00874
00875
00876
00877
00878
00879 if (!line || !*line) return 0;
00880
00881 if (!strncasecmp(line, ".q", 2)) {
00882
00883 gApplication->ProcessLine(".R -close");
00884 return 0;
00885 }
00886
00887 if (!strncmp(line, "?", 1)) {
00888 Help(line);
00889 return 1;
00890 }
00891
00892 fReceivedObject = 0;
00893
00894
00895 InitializeGraphics();
00896
00897
00898 Broadcast(line, kMESS_CINT);
00899
00900
00901 Collect();
00902
00903
00904 return (Long_t)fReceivedObject;
00905 return 1;
00906 }
00907
00908
00909 void TApplicationRemote::Print(Option_t *opt) const
00910 {
00911
00912
00913 TString s(Form("OBJ: TApplicationRemote %s", fName.Data()));
00914 Printf("%s", s.Data());
00915 if (opt && opt[0] == 'F') {
00916 s = " url: ";
00917 if (strlen(fUrl.GetUser()) > 0)
00918 s += Form("%s@", fUrl.GetUser());
00919 s += fUrl.GetHostFQDN();
00920 s += Form(" logfile: %s", fLogFilePath.Data());
00921 Printf("%s", s.Data());
00922 }
00923 }
00924
00925 void TApplicationRemote::Interrupt(Int_t type)
00926 {
00927
00928
00929
00930 if (!IsValid()) return;
00931
00932 fInterrupt = kTRUE;
00933
00934 #if 1
00935 Info("Interrupt", "*** Ctrl-C not yet enabled *** (type= %d)", type);
00936 return;
00937 #else
00938
00939 char oobc = (char) type;
00940 const int kBufSize = 1024;
00941 char waste[kBufSize];
00942
00943
00944 if (fSocket->SendRaw(&oobc, 1, kOob) <= 0) {
00945 Error("Interrupt", "error sending oobc to server");
00946 return;
00947 }
00948
00949 if (type == kRRI_Hard) {
00950 char oob_byte;
00951 int n, nch, nbytes = 0, nloop = 0;
00952
00953
00954 while ((n = fSocket->RecvRaw(&oob_byte, 1, kOob)) < 0) {
00955 if (n == -2) {
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966 fSocket->GetOption(kBytesToRead, nch);
00967 if (nch == 0) {
00968 gSystem->Sleep(1000);
00969 continue;
00970 }
00971
00972 if (nch > kBufSize) nch = kBufSize;
00973 n = fSocket->RecvRaw(waste, nch);
00974 if (n <= 0) {
00975 Error("Interrupt", "error receiving waste from server");
00976 break;
00977 }
00978 nbytes += n;
00979 } else if (n == -3) {
00980
00981
00982
00983 gSystem->Sleep(100);
00984 if (++nloop > 100) {
00985 Error("Interrupt", "server does not respond");
00986 break;
00987 }
00988 } else {
00989 Error("Interrupt", "error receiving OOB from server");
00990 break;
00991 }
00992 }
00993
00994
00995
00996
00997
00998 while (1) {
00999 int atmark;
01000
01001 fSocket->GetOption(kAtMark, atmark);
01002
01003 if (atmark)
01004 break;
01005
01006
01007 fSocket->GetOption(kBytesToRead, nch);
01008 if (nch == 0) {
01009 gSystem->Sleep(1000);
01010 continue;
01011 }
01012
01013 if (nch > kBufSize) nch = kBufSize;
01014 n = fSocket->RecvRaw(waste, nch);
01015 if (n <= 0) {
01016 Error("Interrupt", "error receiving waste (2) from server");
01017 break;
01018 }
01019 nbytes += n;
01020 }
01021 if (nbytes > 0)
01022 Info("Interrupt", "server synchronized: %d bytes discarded", nbytes);
01023
01024
01025 Collect();
01026
01027 } else if (type == kRRI_Soft) {
01028
01029
01030 Collect();
01031
01032 } else if (type == kRRI_Shutdown) {
01033
01034 ;
01035
01036 } else {
01037
01038
01039 Collect();
01040 }
01041 #endif
01042 }
01043
01044
01045 void TApplicationRemote::Browse(TBrowser *b)
01046 {
01047
01048
01049 b->Add(fRootFiles, "ROOT Files");
01050 b->Add(fWorkingDir, fWorkingDir->GetTitle());
01051 gROOT->RefreshBrowsers();
01052 }