00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "RConfigure.h"
00022 #include "RConfig.h"
00023 #include "Riostream.h"
00024
00025 #ifdef WIN32
00026 #include <io.h>
00027 typedef long off_t;
00028 #endif
00029 #include <stdlib.h>
00030 #include <errno.h>
00031 #include <time.h>
00032 #include <fcntl.h>
00033 #include <sys/types.h>
00034 #include <sys/stat.h>
00035
00036 #if (defined(__FreeBSD__) && (__FreeBSD__ < 4)) || \
00037 (defined(__APPLE__) && (!defined(MAC_OS_X_VERSION_10_3) || \
00038 (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_3)))
00039 #include <sys/file.h>
00040 #define lockf(fd, op, sz) flock((fd), (op))
00041 #ifndef F_LOCK
00042 #define F_LOCK (LOCK_EX | LOCK_NB)
00043 #endif
00044 #ifndef F_ULOCK
00045 #define F_ULOCK LOCK_UN
00046 #endif
00047 #endif
00048
00049 #include "RRemoteProtocol.h"
00050
00051 #include "TApplicationServer.h"
00052 #include "TBenchmark.h"
00053 #include "TEnv.h"
00054 #include "TError.h"
00055 #include "TException.h"
00056 #include "TInterpreter.h"
00057 #include "TMD5.h"
00058 #include "TMessage.h"
00059 #include "TROOT.h"
00060 #include "TSocket.h"
00061 #include "TSystem.h"
00062 #include "TRemoteObject.h"
00063 #include "TUrl.h"
00064 #include "TObjString.h"
00065 #include "compiledata.h"
00066 #include "TClass.h"
00067
00068
00069
00070
00071 class TASInterruptHandler : public TSignalHandler {
00072 TApplicationServer *fServ;
00073 public:
00074 TASInterruptHandler(TApplicationServer *s)
00075 : TSignalHandler(kSigUrgent, kFALSE) { fServ = s; }
00076 Bool_t Notify();
00077 };
00078
00079
00080 Bool_t TASInterruptHandler::Notify()
00081 {
00082
00083
00084 fServ->HandleUrgentData();
00085 if (TROOT::Initialized()) {
00086 Throw(GetSignal());
00087 }
00088 return kTRUE;
00089 }
00090
00091
00092
00093 class TASSigPipeHandler : public TSignalHandler {
00094 TApplicationServer *fServ;
00095 public:
00096 TASSigPipeHandler(TApplicationServer *s) : TSignalHandler(kSigPipe, kFALSE)
00097 { fServ = s; }
00098 Bool_t Notify();
00099 };
00100
00101
00102 Bool_t TASSigPipeHandler::Notify()
00103 {
00104
00105
00106 fServ->HandleSigPipe();
00107 return kTRUE;
00108 }
00109
00110
00111
00112 class TASInputHandler : public TFileHandler {
00113 TApplicationServer *fServ;
00114 public:
00115 TASInputHandler(TApplicationServer *s, Int_t fd) : TFileHandler(fd, 1)
00116 { fServ = s; }
00117 Bool_t Notify();
00118 Bool_t ReadNotify() { return Notify(); }
00119 };
00120
00121
00122 Bool_t TASInputHandler::Notify()
00123 {
00124
00125
00126 fServ->HandleSocketInput();
00127 return kTRUE;
00128 }
00129
00130 TString TASLogHandler::fgPfx = "";
00131
00132 TASLogHandler::TASLogHandler(const char *cmd, TSocket *s, const char *pfx)
00133 : TFileHandler(-1, 1), fSocket(s), fPfx(pfx)
00134 {
00135
00136
00137 ResetBit(kFileIsPipe);
00138 fFile = 0;
00139 if (s && cmd) {
00140 fFile = gSystem->OpenPipe(cmd, "r");
00141 if (fFile) {
00142 SetFd(fileno(fFile));
00143
00144 Notify();
00145
00146 SetBit(kFileIsPipe);
00147 } else {
00148 fSocket = 0;
00149 Error("TASLogHandler", "executing command in pipe");
00150 }
00151 } else {
00152 Error("TASLogHandler",
00153 "undefined command (%p) or socket (%p)", (int *)cmd, s);
00154 }
00155 }
00156
00157 TASLogHandler::TASLogHandler(FILE *f, TSocket *s, const char *pfx)
00158 : TFileHandler(-1, 1), fSocket(s), fPfx(pfx)
00159 {
00160
00161
00162 ResetBit(kFileIsPipe);
00163 fFile = 0;
00164 if (s && f) {
00165 fFile = f;
00166 SetFd(fileno(fFile));
00167
00168 Notify();
00169 } else {
00170 Error("TASLogHandler", "undefined file (%p) or socket (%p)", f, s);
00171 }
00172 }
00173
00174 TASLogHandler::~TASLogHandler()
00175 {
00176
00177
00178 if (TestBit(kFileIsPipe) && fFile)
00179 gSystem->ClosePipe(fFile);
00180 fFile = 0;
00181 fSocket = 0;
00182 ResetBit(kFileIsPipe);
00183 }
00184
00185 Bool_t TASLogHandler::Notify()
00186 {
00187
00188
00189 if (IsValid()) {
00190 TMessage m(kMESS_ANY);
00191
00192 char line[4096];
00193 char *plf = 0;
00194 while (fgets(line, sizeof(line), fFile)) {
00195 if ((plf = strchr(line, '\n')))
00196 *plf = 0;
00197
00198 m.Reset(kMESS_ANY);
00199 m << (Int_t)kRRT_Message;
00200 if (fPfx.Length() > 0) {
00201
00202 m << TString(Form("%s: %s", fPfx.Data(), line));
00203 } else if (fgPfx.Length() > 0) {
00204
00205 m << TString(Form("%s: %s", fgPfx.Data(), line));
00206 } else {
00207
00208 m << TString(line);
00209 }
00210 fSocket->Send(m);
00211 }
00212 }
00213 return kTRUE;
00214 }
00215
00216 void TASLogHandler::SetDefaultPrefix(const char *pfx)
00217 {
00218
00219
00220 fgPfx = pfx;
00221 }
00222
00223
00224 TASLogHandlerGuard::TASLogHandlerGuard(const char *cmd, TSocket *s,
00225 const char *pfx, Bool_t on)
00226 {
00227
00228
00229 fExecHandler = 0;
00230 if (cmd && on) {
00231 fExecHandler = new TASLogHandler(cmd, s, pfx);
00232 if (fExecHandler->IsValid()) {
00233 gSystem->AddFileHandler(fExecHandler);
00234 } else {
00235 Error("TASLogHandlerGuard","invalid handler");
00236 }
00237 } else {
00238 if (on)
00239 Error("TASLogHandlerGuard","undefined command");
00240 }
00241 }
00242
00243
00244 TASLogHandlerGuard::TASLogHandlerGuard(FILE *f, TSocket *s,
00245 const char *pfx, Bool_t on)
00246 {
00247
00248
00249 fExecHandler = 0;
00250 if (f && on) {
00251 fExecHandler = new TASLogHandler(f, s, pfx);
00252 if (fExecHandler->IsValid()) {
00253 gSystem->AddFileHandler(fExecHandler);
00254 } else {
00255 Error("TASLogHandlerGuard","invalid handler");
00256 }
00257 } else {
00258 if (on)
00259 Error("TASLogHandlerGuard","undefined file");
00260 }
00261 }
00262
00263
00264 TASLogHandlerGuard::~TASLogHandlerGuard()
00265 {
00266
00267
00268 if (fExecHandler && fExecHandler->IsValid()) {
00269 gSystem->RemoveFileHandler(fExecHandler);
00270 SafeDelete(fExecHandler);
00271 }
00272 }
00273
00274 ClassImp(TApplicationServer)
00275
00276
00277 TApplicationServer::TApplicationServer(Int_t *argc, char **argv,
00278 FILE *flog, const char *logfile)
00279 : TApplication("server", argc, argv, 0, -1)
00280 {
00281
00282
00283
00284
00285 GetOptions(argc, argv);
00286
00287
00288 gErrorAbortLevel = kSysError + 1;
00289 SetErrorHandler(ErrorHandler);
00290
00291 fInterrupt = kFALSE;
00292 fSocket = 0;
00293 fWorkingDir = 0;
00294
00295 fLogFilePath = logfile;
00296 fLogFile = flog;
00297 fLogFileDes = -1;
00298 if (!fLogFile || (fLogFileDes = fileno(fLogFile)) < 0)
00299
00300 Terminate(0);
00301 fRealTimeLog = kFALSE;
00302 fSentCanvases = 0;
00303
00304
00305 TASLogHandler::SetDefaultPrefix(Form("roots:%s", gSystem->HostName()));
00306
00307
00308
00309 fIsValid = kFALSE;
00310
00311 if (!(fSocket = new TSocket(GetHost(), GetPort()))) {
00312 Terminate(0);
00313 return;
00314 }
00315 Int_t sock = fSocket->GetDescriptor();
00316
00317 if (Setup() != 0) {
00318 Error("TApplicationServer", "failed to setup - quitting");
00319 SendLogFile(-98);
00320 Terminate(0);
00321 }
00322
00323
00324 ProcessLine("#include <iostream>", kTRUE);
00325 ProcessLine("#include <string>",kTRUE);
00326
00327
00328 const char *logon;
00329 logon = gEnv->GetValue("Rint.Load", (char *)0);
00330 if (logon) {
00331 char *mac = gSystem->Which(TROOT::GetMacroPath(), logon, kReadPermission);
00332 if (mac)
00333 ProcessLine(Form(".L %s", logon), kTRUE);
00334 delete [] mac;
00335 }
00336
00337
00338 ExecLogon();
00339
00340
00341 gBenchmark = new TBenchmark();
00342
00343
00344 gInterpreter->SaveContext();
00345 gInterpreter->SaveGlobalsContext();
00346
00347
00348 gSystem->AddSignalHandler(new TASInterruptHandler(this));
00349 gSystem->AddFileHandler(new TASInputHandler(this, sock));
00350
00351
00352 fIsValid = kTRUE;
00353
00354
00355 BrowseDirectory(0);
00356 SendLogFile();
00357 }
00358
00359
00360 Int_t TApplicationServer::Setup()
00361 {
00362
00363
00364
00365 char str[512];
00366 snprintf(str, 512, "**** Remote session @ %s started ****", gSystem->HostName());
00367 if (fSocket->Send(str) != 1+static_cast<Int_t>(strlen(str))) {
00368 Error("Setup", "failed to send startup message");
00369 return -1;
00370 }
00371
00372
00373 if (fSocket->Send(kRRemote_Protocol, kROOTD_PROTOCOL) != 2*sizeof(Int_t)) {
00374 Error("Setup", "failed to send local protocol");
00375 return -1;
00376 }
00377
00378
00379 TMessage msg(kMESS_ANY);
00380 msg << TString(gSystem->HostName()) << fLogFilePath;
00381 fSocket->Send(msg);
00382
00383
00384 fWorkDir = gSystem->WorkingDirectory();
00385 if (strlen(fUrl.GetFile()) > 0) {
00386 fWorkDir = fUrl.GetFile();
00387 char *workdir = gSystem->ExpandPathName(fWorkDir.Data());
00388 fWorkDir = workdir;
00389 delete [] workdir;
00390 }
00391
00392
00393 if (gSystem->AccessPathName(fWorkDir)) {
00394 gSystem->mkdir(fWorkDir, kTRUE);
00395 if (!gSystem->ChangeDirectory(fWorkDir)) {
00396 SysError("Setup", "can not change to directory %s",
00397 fWorkDir.Data());
00398 }
00399 } else {
00400 if (!gSystem->ChangeDirectory(fWorkDir)) {
00401 gSystem->Unlink(fWorkDir);
00402 gSystem->mkdir(fWorkDir, kTRUE);
00403 if (!gSystem->ChangeDirectory(fWorkDir)) {
00404 SysError("Setup", "can not change to directory %s",
00405 fWorkDir.Data());
00406 }
00407 }
00408 }
00409
00410 #if 0 // G.Ganis May 11, 2007
00411
00412
00413 if (fSocket->SetOption(kProcessGroup, (-1)*gSystem->GetPid()) != 0)
00414 SysWarning("Setup", "failed to enable SIGURG generation on incoming OOB");
00415 #endif
00416
00417
00418 if (fSocket->SetOption(kNoDelay, 1) != 0) {}
00419
00420
00421
00422 if (fSocket->SetOption(kKeepAlive, 1) != 0) {}
00423
00424
00425
00426 gSystem->AddSignalHandler(new TASSigPipeHandler(this));
00427
00428
00429 return 0;
00430 }
00431
00432
00433 TApplicationServer::~TApplicationServer()
00434 {
00435
00436
00437
00438 fSentCanvases->SetOwner(kFALSE);
00439 SafeDelete(fSentCanvases);
00440 SafeDelete(fSocket);
00441 close(fLogFileDes);
00442 }
00443
00444
00445 void TApplicationServer::GetOptions(Int_t *argc, char **argv)
00446 {
00447
00448
00449
00450 if (*argc < 4) {
00451 Fatal("GetOptions", "must be started with 4 arguments");
00452 gSystem->Exit(1);
00453 }
00454
00455
00456 fProtocol = TString(argv[1]).Atoi();
00457
00458
00459 fUrl.SetUrl(argv[2]);
00460
00461
00462 gDebug = 0;
00463 TString argdbg(argv[3]);
00464 if (argdbg.BeginsWith("-d=")) {
00465 argdbg.ReplaceAll("-d=","");
00466 gDebug = argdbg.Atoi();
00467 }
00468 }
00469
00470
00471 void TApplicationServer::Run(Bool_t retrn)
00472 {
00473
00474
00475
00476 if (fIsValid) {
00477
00478 TApplication::Run(retrn);
00479 } else {
00480 Error("Run", "invalid instance: cannot Run()");
00481 gSystem->Exit(1);
00482 }
00483 }
00484
00485
00486 void TApplicationServer::HandleSocketInput()
00487 {
00488
00489
00490 TMessage *mess;
00491 char str[2048];
00492 Int_t what;
00493
00494 if (fSocket->Recv(mess) <= 0) {
00495
00496
00497 Error("HandleSocketInput", "retrieving message from input socket");
00498 Terminate(0);
00499 return;
00500 }
00501
00502 what = mess->What();
00503 if (gDebug > 0)
00504 Info("HandleSocketInput", "got message of type %d", what);
00505
00506 switch (what) {
00507
00508 case kMESS_CINT:
00509 { TASLogHandlerGuard hg(fLogFile, fSocket, "", fRealTimeLog);
00510 mess->ReadString(str, sizeof(str));
00511 if (gDebug > 1)
00512 Info("HandleSocketInput:kMESS_CINT", "processing: %s...", str);
00513 ProcessLine(str);
00514 }
00515 SendCanvases();
00516 SendLogFile();
00517 break;
00518
00519 case kMESS_STRING:
00520 mess->ReadString(str, sizeof(str));
00521 break;
00522
00523 case kMESS_OBJECT:
00524 mess->ReadObject(mess->GetClass());
00525 break;
00526
00527 case kMESS_ANY:
00528 {
00529 Int_t type;
00530 (*mess) >> type;
00531 switch (type) {
00532 case kRRT_Reset:
00533 mess->ReadString(str, sizeof(str));
00534 Reset(str);
00535 break;
00536
00537 case kRRT_CheckFile:
00538
00539 HandleCheckFile(mess);
00540 break;
00541
00542 case kRRT_File:
00543
00544 mess->ReadString(str, sizeof(str));
00545 { char name[2048], i1[20], i2[40];
00546 sscanf(str, "%2047s %19s %39s", name, i1, i2);
00547 Int_t bin = atoi(i1);
00548 Long_t size = atol(i2);
00549 ReceiveFile(name, bin ? kTRUE : kFALSE, size);
00550 }
00551 break;
00552
00553 case kRRT_Terminate:
00554
00555 Int_t status;
00556 (*mess) >> status;
00557 Terminate(status);
00558 break;
00559
00560 default:
00561 break;
00562 }
00563 }
00564 SendLogFile();
00565 break;
00566 default:
00567 Warning("HandleSocketInput","message type unknown (%d)", what);
00568 SendLogFile();
00569 break;
00570 }
00571
00572 delete mess;
00573 }
00574
00575
00576 void TApplicationServer::HandleUrgentData()
00577 {
00578
00579
00580 char oob_byte;
00581 Int_t n, nch, wasted = 0;
00582
00583 const Int_t kBufSize = 1024;
00584 char waste[kBufSize];
00585
00586
00587 TASLogHandlerGuard hg(fLogFile, fSocket, "", fRealTimeLog);
00588
00589 Info("HandleUrgentData", "handling oob...");
00590
00591
00592 while ((n = fSocket->RecvRaw(&oob_byte, 1, kOob)) < 0) {
00593 if (n == -2) {
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604 fSocket->GetOption(kBytesToRead, nch);
00605 if (nch == 0) {
00606 gSystem->Sleep(1000);
00607 continue;
00608 }
00609
00610 if (nch > kBufSize) nch = kBufSize;
00611 n = fSocket->RecvRaw(waste, nch);
00612 if (n <= 0) {
00613 Error("HandleUrgentData", "error receiving waste");
00614 break;
00615 }
00616 wasted = 1;
00617 } else {
00618 Error("HandleUrgentData", "error receiving OOB (n = %d)",n);
00619 return;
00620 }
00621 }
00622
00623 Info("HandleUrgentData", "got OOB byte: %d\n", oob_byte);
00624
00625 switch (oob_byte) {
00626
00627 case kRRI_Hard:
00628 Info("HandleUrgentData", "*** Hard Interrupt");
00629
00630
00631 while (1) {
00632 Int_t atmark;
00633
00634 fSocket->GetOption(kAtMark, atmark);
00635
00636 if (atmark) {
00637
00638
00639 n = fSocket->SendRaw(&oob_byte, 1, kOob);
00640 if (n <= 0)
00641 Error("HandleUrgentData", "error sending OOB");
00642 break;
00643 }
00644
00645
00646 fSocket->GetOption(kBytesToRead, nch);
00647 if (nch == 0) {
00648 gSystem->Sleep(1000);
00649 continue;
00650 }
00651
00652 if (nch > kBufSize) nch = kBufSize;
00653 n = fSocket->RecvRaw(waste, nch);
00654 if (n <= 0) {
00655 Error("HandleUrgentData", "error receiving waste (2)");
00656 break;
00657 }
00658 }
00659
00660 SendLogFile();
00661
00662 break;
00663
00664 case kRRI_Soft:
00665 Info("HandleUrgentData", "Soft Interrupt");
00666
00667 if (wasted) {
00668 Error("HandleUrgentData", "soft interrupt flushed stream");
00669 break;
00670 }
00671
00672 Interrupt();
00673
00674 SendLogFile();
00675
00676 break;
00677
00678 case kRRI_Shutdown:
00679 Info("HandleUrgentData", "Shutdown Interrupt");
00680
00681 Terminate(0);
00682
00683 break;
00684
00685 default:
00686 Error("HandleUrgentData", "unexpected OOB byte");
00687 break;
00688 }
00689 }
00690
00691
00692 void TApplicationServer::HandleSigPipe()
00693 {
00694
00695
00696
00697
00698 TASLogHandlerGuard hg(fLogFile, fSocket, "", fRealTimeLog);
00699
00700 Info("HandleSigPipe", "client died");
00701 Terminate(0);
00702 }
00703
00704
00705 void TApplicationServer::Reset(const char *dir)
00706 {
00707
00708
00709
00710 gDirectory->cd(dir);
00711
00712
00713 gROOT->Reset();
00714
00715
00716
00717 if (gDirectory != gROOT) {
00718 gDirectory->Delete();
00719 }
00720 }
00721
00722
00723 Int_t TApplicationServer::ReceiveFile(const char *file, Bool_t bin, Long64_t size)
00724 {
00725
00726
00727
00728
00729
00730 if (size <= 0) return 0;
00731
00732
00733 Int_t fd = open(file, O_CREAT | O_TRUNC | O_WRONLY, 0600);
00734 if (fd < 0) {
00735 SysError("ReceiveFile", "error opening file %s", file);
00736 return -1;
00737 }
00738
00739 const Int_t kMAXBUF = 16384;
00740 char buf[kMAXBUF], cpy[kMAXBUF];
00741
00742 Int_t left, r;
00743 Long64_t filesize = 0;
00744
00745 while (filesize < size) {
00746 left = Int_t(size - filesize);
00747 if (left > kMAXBUF)
00748 left = kMAXBUF;
00749 r = fSocket->RecvRaw(&buf, left);
00750 if (r > 0) {
00751 char *p = buf;
00752
00753 filesize += r;
00754 while (r) {
00755 Int_t w;
00756
00757 if (!bin) {
00758 Int_t k = 0, i = 0, j = 0;
00759 char *q;
00760 while (i < r) {
00761 if (p[i] == '\r') {
00762 i++;
00763 k++;
00764 }
00765 cpy[j++] = buf[i++];
00766 }
00767 q = cpy;
00768 r -= k;
00769 w = write(fd, q, r);
00770 } else {
00771 w = write(fd, p, r);
00772 }
00773
00774 if (w < 0) {
00775 SysError("ReceiveFile", "error writing to file %s", file);
00776 close(fd);
00777 return -1;
00778 }
00779 r -= w;
00780 p += w;
00781 }
00782 } else if (r < 0) {
00783 Error("ReceiveFile", "error during receiving file %s", file);
00784 close(fd);
00785 return -1;
00786 }
00787 }
00788
00789 close(fd);
00790
00791 chmod(file, 0644);
00792
00793 return 0;
00794 }
00795
00796
00797 void TApplicationServer::SendLogFile(Int_t status, Int_t start, Int_t end)
00798 {
00799
00800
00801
00802
00803
00804 fflush(stdout);
00805
00806 off_t ltot=0, lnow=0;
00807 Int_t left = -1;
00808 Bool_t adhoc = kFALSE;
00809
00810 if (fLogFileDes > -1) {
00811 ltot = lseek(fileno(stdout), (off_t) 0, SEEK_END);
00812 lnow = lseek(fLogFileDes, (off_t) 0, SEEK_CUR);
00813 if (lnow == -1) {
00814 SysError("SendLogFile", "lseek failed");
00815 lnow = 0;
00816 }
00817
00818 if (start > -1) {
00819 lseek(fLogFileDes, (off_t) start, SEEK_SET);
00820 if (end <= start || end > ltot)
00821 end = ltot;
00822 left = (Int_t)(end - start);
00823 if (end < ltot)
00824 left++;
00825 adhoc = kTRUE;
00826 } else {
00827 left = (Int_t)(ltot - lnow);
00828 }
00829 }
00830
00831 TMessage m(kMESS_ANY);
00832
00833 if (left > 0) {
00834
00835 m << (Int_t)kRRT_LogFile << left;
00836 fSocket->Send(m);
00837
00838 const Int_t kMAXBUF = 32768;
00839 char buf[kMAXBUF];
00840 Int_t wanted = (left > kMAXBUF) ? kMAXBUF : left;
00841 Int_t len;
00842 do {
00843 while ((len = read(fLogFileDes, buf, wanted)) < 0 &&
00844 TSystem::GetErrno() == EINTR)
00845 TSystem::ResetErrno();
00846
00847 if (len < 0) {
00848 SysError("SendLogFile", "error reading log file");
00849 break;
00850 }
00851
00852 if (end == ltot && len == wanted)
00853 buf[len-1] = '\n';
00854
00855 if (fSocket->SendRaw(buf, len) < 0) {
00856 SysError("SendLogFile", "error sending log file");
00857 break;
00858 }
00859
00860
00861 left -= len;
00862 wanted = (left > kMAXBUF) ? kMAXBUF : left;
00863
00864 } while (len > 0 && left > 0);
00865 }
00866
00867
00868 if (adhoc)
00869 lseek(fLogFileDes, lnow, SEEK_SET);
00870
00871 m.Reset();
00872 m << (Int_t)kRRT_LogDone << status;
00873
00874 fSocket->Send(m);
00875 }
00876
00877
00878 Int_t TApplicationServer::SendCanvases()
00879 {
00880
00881
00882 Int_t nc = 0;
00883
00884
00885 TMessage mess(kMESS_OBJECT);
00886 TIter next(gROOT->GetListOfCanvases());
00887 TObject *o = 0;
00888 while ((o = next())) {
00889 if (!fSentCanvases)
00890 fSentCanvases = new TList;
00891 Bool_t sentalready = kFALSE;
00892
00893
00894 TObjLink *lnk = fSentCanvases->FirstLink();
00895 while (lnk) {
00896 TObject *sc = lnk->GetObject();
00897 lnk = lnk->Next();
00898 if ((sc->TestBit(kNotDeleted)) && sc == o)
00899 sentalready = kTRUE;
00900 }
00901 if (!sentalready) {
00902 if (gDebug > 0)
00903 Info("SendCanvases","new canvas found: %p", o);
00904 mess.Reset(kMESS_OBJECT);
00905 mess.WriteObject(o);
00906 fSocket->Send(mess);
00907 nc++;
00908 fSentCanvases->Add(o);
00909 }
00910 }
00911 return nc;
00912 }
00913
00914
00915 Int_t TApplicationServer::BrowseDirectory(const char *dirname)
00916 {
00917
00918
00919 Int_t nc = 0;
00920
00921 TMessage mess(kMESS_OBJECT);
00922 if (!fWorkingDir || !dirname || !*dirname) {
00923 if (!fWorkingDir)
00924 fWorkingDir = new TRemoteObject(fWorkDir, fWorkDir, "TSystemDirectory");
00925 fWorkingDir->Browse();
00926 mess.Reset(kMESS_OBJECT);
00927 mess.WriteObject(fWorkingDir);
00928 fSocket->Send(mess);
00929 nc++;
00930 }
00931 else if (fWorkingDir) {
00932 TRemoteObject dir(dirname, dirname, "TSystemDirectory");
00933 TList *list = dir.Browse();
00934 mess.Reset(kMESS_OBJECT);
00935 mess.WriteObject(list);
00936 fSocket->Send(mess);
00937 nc++;
00938 }
00939 return nc;
00940 }
00941
00942
00943 Int_t TApplicationServer::BrowseFile(const char *fname)
00944 {
00945
00946
00947
00948 Int_t nc = 0;
00949
00950 TList *list = new TList;
00951 TMessage mess(kMESS_OBJECT);
00952 if (!fname || !*fname) {
00953
00954 TIter next(gROOT->GetListOfFiles());
00955 TNamed *fh = 0;
00956 TRemoteObject *robj;
00957 while ((fh = (TNamed *)next())) {
00958 robj = new TRemoteObject(fh->GetName(), fh->GetTitle(), "TFile");
00959 list->Add(robj);
00960 }
00961 if (list->GetEntries() > 0) {
00962 mess.Reset(kMESS_OBJECT);
00963 mess.WriteObject(list);
00964 fSocket->Send(mess);
00965 nc++;
00966 }
00967 }
00968 else {
00969
00970 TDirectory *fh = (TDirectory *)gROOT->GetListOfFiles()->FindObject(fname);
00971 if (fh) {
00972 fh->cd();
00973 TRemoteObject dir(fh->GetName(), fh->GetTitle(), "TFile");
00974 TList *keylist = (TList *)gROOT->ProcessLine(Form("((TFile *)0x%lx)->GetListOfKeys();", (ULong_t)fh));
00975 TIter nextk(keylist);
00976 TNamed *key = 0;
00977 TRemoteObject *robj;
00978 while ((key = (TNamed *)nextk())) {
00979 robj = new TRemoteObject(key->GetName(), key->GetTitle(), "TKey");
00980 const char *classname = (const char *)gROOT->ProcessLine(Form("((TKey *)0x%lx)->GetClassName();", (ULong_t)key));
00981 robj->SetKeyClassName(classname);
00982 Bool_t isFolder = (Bool_t)gROOT->ProcessLine(Form("((TKey *)0x%lx)->IsFolder();", (ULong_t)key));
00983 robj->SetFolder(isFolder);
00984 robj->SetRemoteAddress((Long_t) key);
00985 list->Add(robj);
00986 }
00987 if (list->GetEntries() > 0) {
00988 mess.Reset(kMESS_OBJECT);
00989 mess.WriteObject(list);
00990 fSocket->Send(mess);
00991 nc++;
00992 }
00993 }
00994 }
00995 return nc;
00996 }
00997
00998
00999 Int_t TApplicationServer::BrowseKey(const char *keyname)
01000 {
01001
01002
01003 Int_t nc = 0;
01004
01005 TMessage mess(kMESS_OBJECT);
01006 TNamed *obj = (TNamed *)gROOT->ProcessLine(Form("gFile->GetKey(\"%s\")->ReadObj();", keyname));
01007 if (obj) {
01008 mess.Reset(kMESS_OBJECT);
01009 mess.WriteObject(obj);
01010 fSocket->Send(mess);
01011 nc++;
01012 }
01013 return nc;
01014 }
01015
01016
01017 void TApplicationServer::Terminate(Int_t status)
01018 {
01019
01020
01021
01022 if (fLogFile) {
01023 fclose(fLogFile);
01024
01025 if (gDebug <= 0)
01026 gSystem->Unlink(fLogFilePath);
01027 TString cleanup = fLogFilePath;
01028 cleanup.ReplaceAll(".log", ".cleanup");
01029 gSystem->Unlink(cleanup);
01030 }
01031
01032
01033
01034 TIter next(gSystem->GetListOfFileHandlers());
01035 TObject *fh = 0;
01036 while ((fh = next())) {
01037 TASInputHandler *ih = dynamic_cast<TASInputHandler *>(fh);
01038 if (ih)
01039 gSystem->RemoveFileHandler(ih);
01040 }
01041
01042
01043 gSystem->Exit(status);
01044 }
01045
01046
01047 void TApplicationServer::HandleCheckFile(TMessage *mess)
01048 {
01049
01050
01051 TString filenam;
01052 TMD5 md5;
01053 TMessage m(kMESS_ANY);
01054
01055
01056 (*mess) >> filenam >> md5;
01057
01058
01059 TMD5 *md5local = TMD5::FileChecksum(filenam);
01060 if (md5local && md5 == (*md5local)) {
01061
01062 m << (Int_t) kRRT_CheckFile << (Bool_t) kTRUE;
01063 fSocket->Send(m);
01064 if (gDebug > 0)
01065 Info("HandleCheckFile", "up-to-date version of %s available", filenam.Data());
01066 } else {
01067 m << (Int_t) kRRT_CheckFile << (Bool_t) kFALSE;
01068 fSocket->Send(m);
01069 if (gDebug > 0)
01070 Info("HandleCheckFile", "file %s needs to be uploaded", filenam.Data());
01071 }
01072 delete md5local;
01073 }
01074
01075
01076 void TApplicationServer::ErrorHandler(Int_t level, Bool_t abort, const char *location,
01077 const char *msg)
01078 {
01079
01080
01081
01082 if (gErrorIgnoreLevel == kUnset) {
01083 gErrorIgnoreLevel = 0;
01084 if (gEnv) {
01085 TString slevel = gEnv->GetValue("Root.ErrorIgnoreLevel", "Print");
01086 if (!slevel.CompareTo("Print", TString::kIgnoreCase))
01087 gErrorIgnoreLevel = kPrint;
01088 else if (!slevel.CompareTo("Info", TString::kIgnoreCase))
01089 gErrorIgnoreLevel = kInfo;
01090 else if (!slevel.CompareTo("Warning", TString::kIgnoreCase))
01091 gErrorIgnoreLevel = kWarning;
01092 else if (!slevel.CompareTo("Error", TString::kIgnoreCase))
01093 gErrorIgnoreLevel = kError;
01094 else if (!slevel.CompareTo("Break", TString::kIgnoreCase))
01095 gErrorIgnoreLevel = kBreak;
01096 else if (!slevel.CompareTo("SysError", TString::kIgnoreCase))
01097 gErrorIgnoreLevel = kSysError;
01098 else if (!slevel.CompareTo("Fatal", TString::kIgnoreCase))
01099 gErrorIgnoreLevel = kFatal;
01100 }
01101 }
01102
01103 if (level < gErrorIgnoreLevel)
01104 return;
01105
01106 static TString syslogService;
01107
01108 if (syslogService.IsNull()) {
01109 syslogService = "server";
01110 gSystem->Openlog(syslogService, kLogPid | kLogCons, kLogLocal5);
01111 }
01112
01113 const char *type = 0;
01114 ELogLevel loglevel = kLogInfo;
01115
01116 if (level >= kPrint) {
01117 loglevel = kLogInfo;
01118 type = "Print";
01119 }
01120 if (level >= kInfo) {
01121 loglevel = kLogInfo;
01122 type = "Info";
01123 }
01124 if (level >= kWarning) {
01125 loglevel = kLogWarning;
01126 type = "Warning";
01127 }
01128 if (level >= kError) {
01129 loglevel = kLogErr;
01130 type = "Error";
01131 }
01132 if (level >= kBreak) {
01133 loglevel = kLogErr;
01134 type = "*** Break ***";
01135 }
01136 if (level >= kSysError) {
01137 loglevel = kLogErr;
01138 type = "SysError";
01139 }
01140 if (level >= kFatal) {
01141 loglevel = kLogErr;
01142 type = "Fatal";
01143 }
01144
01145 TString node = "server";
01146 TString buf;
01147
01148 if (!location || strlen(location) == 0 ||
01149 (level >= kPrint && level < kInfo) ||
01150 (level >= kBreak && level < kSysError)) {
01151 fprintf(stderr, "%s on %s: %s\n", type, node.Data(), msg);
01152 buf.Form("%s:%s:%s", node.Data(), type, msg);
01153 } else {
01154 fprintf(stderr, "%s in <%s> on %s: %s\n", type, location, node.Data(), msg);
01155 buf.Form("%s:%s:<%s>:%s", node.Data(), type, location, msg);
01156 }
01157 fflush(stderr);
01158
01159 gSystem->Syslog(loglevel, buf);
01160
01161 if (abort) {
01162 fprintf(stderr, "aborting\n");
01163 fflush(stderr);
01164 gSystem->StackTrace();
01165 gSystem->Abort();
01166 }
01167 }
01168
01169
01170 Long_t TApplicationServer::ProcessLine(const char *line, Bool_t, Int_t *)
01171 {
01172
01173
01174
01175
01176
01177 if (!line || !*line) return 0;
01178
01179
01180
01181 if (!strncmp(line, ".L", 2) || !strncmp(line, ".U", 2) ||
01182 !strncmp(line, ".X", 2) || !strncmp(line, ".x", 2)) {
01183 TString aclicMode;
01184 TString arguments;
01185 TString io;
01186 TString fname = gSystem->SplitAclicMode(line+3, aclicMode, arguments, io);
01187
01188 char *imp = gSystem->Which(TROOT::GetMacroPath(), fname, kReadPermission);
01189 if (!imp) {
01190
01191
01192 if (gSystem->AccessPathName(gSystem->WorkingDirectory(), kWritePermission)) {
01193 Error("ProcessLine","no write permission in %s", gSystem->WorkingDirectory());
01194 return 0;
01195 }
01196
01197 if (gDebug > 0)
01198 Info("ProcessLine", "macro %s not found in path %s: asking the client",
01199 fname.Data(), TROOT::GetMacroPath());
01200 TMessage m(kMESS_ANY);
01201 m << (Int_t) kRRT_SendFile << TString(gSystem->BaseName(fname));
01202 fSocket->Send(m);
01203
01204
01205 Int_t type;
01206 Bool_t filefollows = kTRUE;
01207
01208 while (filefollows) {
01209
01210
01211 TMessage *rm = 0;
01212 if (fSocket->Recv(rm) <= 0) {
01213 Error("ProcessLine","ask-file: received empty message from client");
01214 return 0;
01215 }
01216 if (rm->What() != kMESS_ANY) {
01217 Error("ProcessLine","ask-file: wrong message received (what: %d)", rm->What());
01218 return 0;
01219 }
01220 (*rm) >> type;
01221 if (type != kRRT_SendFile) {
01222 Error("ProcessLine","ask-file: wrong sub-type received (type: %d)", type);
01223 return 0;
01224 }
01225 (*rm) >> filefollows;
01226 if (filefollows) {
01227
01228 if (fSocket->Recv(rm) <= 0) {
01229 Error("ProcessLine","file: received empty message from client");
01230 return 0;
01231 }
01232 if (rm->What() != kMESS_ANY) {
01233 Error("ProcessLine","file: wrong message received (what: %d)", rm->What());
01234 return 0;
01235 }
01236 (*rm) >> type;
01237 if (type != kRRT_File) {
01238 Error("ProcessLine","file: wrong sub-type received (type: %d)", type);
01239 return 0;
01240 }
01241
01242 char str[2048];
01243 rm->ReadString(str, sizeof(str));
01244 char name[2048], i1[20], i2[40];
01245 sscanf(str, "%2047s %19s %39s", name, i1, i2);
01246 Int_t bin = atoi(i1);
01247 Long_t size = atol(i2);
01248 ReceiveFile(name, bin ? kTRUE : kFALSE, size);
01249 }
01250 }
01251 }
01252 delete [] imp;
01253 }
01254
01255
01256 return TApplication::ProcessLine(line);
01257 }
01258
01259
01260 void TApplicationServer::ExecLogon()
01261 {
01262
01263
01264
01265
01266
01267
01268
01269
01270 if (NoLogOpt()) return;
01271
01272 TString name = ".rootlogon.C";
01273 TString sname = "system";
01274 sname += name;
01275 #ifdef ROOTETCDIR
01276 char *s = gSystem->ConcatFileName(ROOTETCDIR, sname);
01277 #else
01278 TString etc = gRootDir;
01279 #ifdef WIN32
01280 etc += "\\etc";
01281 #else
01282 etc += "/etc";
01283 #endif
01284 char *s = gSystem->ConcatFileName(etc, sname);
01285 #endif
01286 if (!gSystem->AccessPathName(s, kReadPermission)) {
01287 ProcessFile(s);
01288 }
01289 delete [] s;
01290 s = gSystem->ConcatFileName(gSystem->HomeDirectory(), name);
01291 if (!gSystem->AccessPathName(s, kReadPermission)) {
01292 ProcessFile(s);
01293 }
01294 delete [] s;
01295
01296 if (strcmp(gSystem->HomeDirectory(), gSystem->WorkingDirectory())) {
01297 if (!gSystem->AccessPathName(name, kReadPermission))
01298 ProcessFile(name);
01299 }
01300
01301
01302 const char *logon = gEnv->GetValue("Rint.Logon", (char*)0);
01303 if (logon) {
01304 char *mac = gSystem->Which(TROOT::GetMacroPath(), logon, kReadPermission);
01305 if (mac)
01306 ProcessFile(logon);
01307 delete [] mac;
01308 }
01309 }