Logo ROOT   6.08/07
Reference Guide
TProofServ.cxx
Go to the documentation of this file.
1 // @(#)root/proof:$Id$
2 // Author: Fons Rademakers 16/02/97
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 /** \class TProofServ
13 \ingroup proofkernel
14 
15 Class providing the PROOF server. It can act either as the master
16 server or as a slave server, depending on its startup arguments. It
17 receives and handles message coming from the client or from the
18 master server.
19 
20 */
21 
22 #include "RConfigure.h"
23 #include "RConfig.h"
24 #include "Riostream.h"
25 
26 #ifdef WIN32
27  #include <process.h>
28  #include <io.h>
29  #include "snprintf.h"
30  typedef long off_t;
31 #endif
32 #include <errno.h>
33 #include <time.h>
34 #include <fcntl.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #ifndef WIN32
38 #include <sys/wait.h>
39 #endif
40 #include <cstdlib>
41 
42 // To handle exceptions
43 #include <exception>
44 #include <new>
45 
46 using namespace std;
47 
48 #if (defined(__FreeBSD__) && (__FreeBSD__ < 4)) || \
49  (defined(__APPLE__) && (!defined(MAC_OS_X_VERSION_10_3) || \
50  (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_3)))
51 #include <sys/file.h>
52 #define lockf(fd, op, sz) flock((fd), (op))
53 #ifndef F_LOCK
54 #define F_LOCK (LOCK_EX | LOCK_NB)
55 #endif
56 #ifndef F_ULOCK
57 #define F_ULOCK LOCK_UN
58 #endif
59 #endif
60 
61 #include "TProofServ.h"
62 #include "TDSetProxy.h"
63 #include "TEnv.h"
64 #include "TError.h"
65 #include "TEventList.h"
66 #include "TEntryList.h"
67 #include "TException.h"
68 #include "TFile.h"
69 #include "THashList.h"
70 #include "TInterpreter.h"
71 #include "TKey.h"
72 #include "TMessage.h"
73 #include "TVirtualPerfStats.h"
74 #include "TProofDebug.h"
75 #include "TProof.h"
76 #include "TVirtualProofPlayer.h"
77 #include "TProofQueryResult.h"
78 #include "TQueryResultManager.h"
79 #include "TRegexp.h"
80 #include "TROOT.h"
81 #include "TSocket.h"
82 #include "TStopwatch.h"
83 #include "TSystem.h"
84 #include "TTimeStamp.h"
85 #include "TUrl.h"
86 #include "TPluginManager.h"
87 #include "TObjString.h"
88 #include "compiledata.h"
89 #include "TProofResourcesStatic.h"
90 #include "TProofNodeInfo.h"
91 #include "TFileInfo.h"
92 #include "TClass.h"
93 #include "TSQLServer.h"
94 #include "TSQLResult.h"
95 #include "TSQLRow.h"
96 #include "TPRegexp.h"
97 #include "TParameter.h"
98 #include "TMap.h"
99 #include "TSortedList.h"
100 #include "TParameter.h"
101 #include "TFileCollection.h"
102 #include "TLockFile.h"
103 #include "TDataSetManagerFile.h"
104 #include "TProofProgressStatus.h"
105 #include "TServerSocket.h"
106 #include "TMonitor.h"
107 #include "TFunction.h"
108 #include "TMethodArg.h"
109 #include "TMethodCall.h"
110 #include "TProofOutputFile.h"
111 #include "TSelector.h"
112 #include "TPackMgr.h"
113 
114 // global proofserv handle
116 
117 // debug hook
118 static volatile Int_t gProofServDebug = 1;
119 
120 // Syslog control
122 TString TProofServ::fgSysLogService("proof");
123 TString TProofServ::fgSysLogEntity("undef:default");
124 
125 // File where to log: default stderr
127 
128 // Integrate with crash reporter.
129 #ifdef __APPLE__
130 extern "C" {
131 static const char *__crashreporter_info__ = 0;
132 asm(".desc ___crashreporter_info__, 0x10");
133 }
134 #endif
135 
136 // To control allowed actions while processing
138 
139 // Last message and entry before exceptions
140 TString TProofServ::fgLastMsg("<undef>");
142 
143 // Memory controllers
148 
149 // Async Logger
150 static void SendAsynMsg(const char *msg) {
151  if (gProofServ) gProofServ->SendAsynMessage(msg, kTRUE);
152 }
153 
154 //----- Termination signal handler ---------------------------------------------
155 ////////////////////////////////////////////////////////////////////////////////
156 
157 class TProofServTerminationHandler : public TSignalHandler {
158  TProofServ *fServ;
159 public:
160  TProofServTerminationHandler(TProofServ *s)
161  : TSignalHandler(kSigTermination, kFALSE) { fServ = s; }
162  Bool_t Notify();
163 };
164 
165 ////////////////////////////////////////////////////////////////////////////////
166 /// Handle this interrupt
167 
168 Bool_t TProofServTerminationHandler::Notify()
169 {
170  Printf("Received SIGTERM: terminating");
171  fServ->HandleTermination();
172  return kTRUE;
173 }
174 
175 //----- Interrupt signal handler -----------------------------------------------
176 ////////////////////////////////////////////////////////////////////////////////
177 
178 class TProofServInterruptHandler : public TSignalHandler {
179  TProofServ *fServ;
180 public:
181  TProofServInterruptHandler(TProofServ *s)
182  : TSignalHandler(kSigUrgent, kFALSE) { fServ = s; }
183  Bool_t Notify();
184 };
185 
186 ////////////////////////////////////////////////////////////////////////////////
187 /// Handle this interrupt
188 
189 Bool_t TProofServInterruptHandler::Notify()
190 {
191  fServ->HandleUrgentData();
192  if (TROOT::Initialized()) {
193  Throw(GetSignal());
194  }
195  return kTRUE;
196 }
197 
198 //----- SigPipe signal handler -------------------------------------------------
199 ////////////////////////////////////////////////////////////////////////////////
200 
201 class TProofServSigPipeHandler : public TSignalHandler {
202  TProofServ *fServ;
203 public:
204  TProofServSigPipeHandler(TProofServ *s) : TSignalHandler(kSigPipe, kFALSE)
205  { fServ = s; }
206  Bool_t Notify();
207 };
208 
209 ////////////////////////////////////////////////////////////////////////////////
210 /// Handle this signal
211 
212 Bool_t TProofServSigPipeHandler::Notify()
213 {
214  fServ->HandleSigPipe();
215  return kTRUE;
216 }
217 
218 //----- Input handler for messages from parent or master -----------------------
219 ////////////////////////////////////////////////////////////////////////////////
220 
221 class TProofServInputHandler : public TFileHandler {
222  TProofServ *fServ;
223 public:
224  TProofServInputHandler(TProofServ *s, Int_t fd) : TFileHandler(fd, 1)
225  { fServ = s; }
226  Bool_t Notify();
227  Bool_t ReadNotify() { return Notify(); }
228 };
229 
230 ////////////////////////////////////////////////////////////////////////////////
231 /// Handle this input
232 
233 Bool_t TProofServInputHandler::Notify()
234 {
235  fServ->HandleSocketInput();
236  return kTRUE;
237 }
238 
239 TString TProofServLogHandler::fgPfx = ""; // Default prefix to be prepended to messages
240 Int_t TProofServLogHandler::fgCmdRtn = 0; // Return code of the command execution (available only
241  // after closing the pipe)
242 ////////////////////////////////////////////////////////////////////////////////
243 /// Execute 'cmd' in a pipe and handle output messages from the related file
244 
246  TSocket *s, const char *pfx)
247  : TFileHandler(-1, 1), fSocket(s), fPfx(pfx)
248 {
250  fgCmdRtn = 0;
251  fFile = 0;
252  if (s && cmd) {
253  fFile = gSystem->OpenPipe(cmd, "r");
254  if (fFile) {
255  SetFd(fileno(fFile));
256  // Notify what already in the file
257  Notify();
258  // Used in the destructor
260  } else {
261  fSocket = 0;
262  Error("TProofServLogHandler", "executing command in pipe");
263  fgCmdRtn = -1;
264  }
265  } else {
266  Error("TProofServLogHandler",
267  "undefined command (%p) or socket (%p)", (int *)cmd, s);
268  }
269 }
270 ////////////////////////////////////////////////////////////////////////////////
271 /// Handle available message from the open file 'f'
272 
274  : TFileHandler(-1, 1), fSocket(s), fPfx(pfx)
275 {
277  fgCmdRtn = 0;
278  fFile = 0;
279  if (s && f) {
280  fFile = f;
281  SetFd(fileno(fFile));
282  // Notify what already in the file
283  Notify();
284  } else {
285  Error("TProofServLogHandler", "undefined file (%p) or socket (%p)", f, s);
286  }
287 }
288 ////////////////////////////////////////////////////////////////////////////////
289 /// Handle available message in the open file
290 
292 {
293  if (TestBit(kFileIsPipe) && fFile) {
294  Int_t rc = gSystem->ClosePipe(fFile);
295 #ifdef WIN32
296  fgCmdRtn = rc;
297 #else
298  fgCmdRtn = WIFEXITED(rc) ? WEXITSTATUS(rc) : -1;
299 #endif
300  }
301  fFile = 0;
302  fSocket = 0;
304 }
305 ////////////////////////////////////////////////////////////////////////////////
306 /// Handle available message in the open file
307 
309 {
310  if (IsValid()) {
312  // Read buffer
313  char line[4096];
314  char *plf = 0;
315  while (fgets(line, sizeof(line), fFile)) {
316  if ((plf = strchr(line, '\n')))
317  *plf = 0;
318  // Create log string
319  TString log;
320  if (fPfx.Length() > 0) {
321  // Prepend prefix specific to this instance
322  log.Form("%s: %s", fPfx.Data(), line);
323  } else if (fgPfx.Length() > 0) {
324  // Prepend default prefix
325  log.Form("%s: %s", fgPfx.Data(), line);
326  } else {
327  // Nothing to prepend
328  log = line;
329  }
330  // Send the message one level up
332  m << log;
333  fSocket->Send(m);
334  }
335  }
336  return kTRUE;
337 }
338 ////////////////////////////////////////////////////////////////////////////////
339 /// Static method to set the default prefix
340 
342 {
343  fgPfx = pfx;
344 }
345 ////////////////////////////////////////////////////////////////////////////////
346 /// Static method to get the return code from the execution of a command via
347 /// the pipe. This is always 0 when the log handler is not used with a pipe
348 
350 {
351  return fgCmdRtn;
352 }
353 
354 ////////////////////////////////////////////////////////////////////////////////
355 /// Init a guard for executing a command in a pipe
356 
358  const char *pfx, Bool_t on)
359 {
360  fExecHandler = 0;
361  if (cmd && on) {
362  fExecHandler = new TProofServLogHandler(cmd, s, pfx);
363  if (fExecHandler->IsValid()) {
364  gSystem->AddFileHandler(fExecHandler);
365  } else {
366  Error("TProofServLogHandlerGuard","invalid handler");
367  }
368  } else {
369  if (on)
370  Error("TProofServLogHandlerGuard","undefined command");
371  }
372 }
373 
374 ////////////////////////////////////////////////////////////////////////////////
375 /// Init a guard for executing a command in a pipe
376 
378  const char *pfx, Bool_t on)
379 {
380  fExecHandler = 0;
381  if (f && on) {
382  fExecHandler = new TProofServLogHandler(f, s, pfx);
383  if (fExecHandler->IsValid()) {
384  gSystem->AddFileHandler(fExecHandler);
385  } else {
386  Error("TProofServLogHandlerGuard","invalid handler");
387  }
388  } else {
389  if (on)
390  Error("TProofServLogHandlerGuard","undefined file");
391  }
392 }
393 
394 ////////////////////////////////////////////////////////////////////////////////
395 /// Close a guard for executing a command in a pipe
396 
398 {
399  if (fExecHandler && fExecHandler->IsValid()) {
400  gSystem->RemoveFileHandler(fExecHandler);
401  SafeDelete(fExecHandler);
402  }
403 }
404 
405 //--- Special timer to control delayed shutdowns ----------------------------//
406 ////////////////////////////////////////////////////////////////////////////////
407 /// Construtor
408 
410  : TTimer(delay, kFALSE), fProofServ(p)
411 {
412  fTimeout = gEnv->GetValue("ProofServ.ShutdownTimeout", 20);
413  // Backward compaitibility: until 5.32 the variable was called ProofServ.ShutdonwTimeout
414  fTimeout = gEnv->GetValue("ProofServ.ShutdonwTimeout", fTimeout);
415 }
416 
417 ////////////////////////////////////////////////////////////////////////////////
418 /// Handle expiration of the shutdown timer. In the case of low activity the
419 /// process will be aborted.
420 
422 {
423  if (gDebug > 0)
424  printf("TShutdownTimer::Notify: checking activity on the input socket\n");
425 
426  // Check activity on the socket
427  TSocket *xs = 0;
428  if (fProofServ && (xs = fProofServ->GetSocket())) {
429  TTimeStamp now;
430  TTimeStamp ts = xs->GetLastUsage();
431  Long_t dt = (Long_t)(now.GetSec() - ts.GetSec()) * 1000 +
432  (Long_t)(now.GetNanoSec() - ts.GetNanoSec()) / 1000000 ;
433  if (dt > fTimeout * 60000) {
434  printf("TShutdownTimer::Notify: input socket: %p: did not show any activity"
435  " during the last %d mins: aborting\n", xs, fTimeout);
436  // At this point we lost our controller: we need to abort to avoid
437  // hidden timeouts or loops
438  gSystem->Abort();
439  } else {
440  if (gDebug > 0)
441  printf("TShutdownTimer::Notify: input socket: %p: show activity"
442  " %ld secs ago\n", xs, dt / 60000);
443  }
444  }
445  // Needed for the next shot
446  Reset();
447  return kTRUE;
448 }
449 
450 //--- Synchronous timer used to reap children processes change of state ------//
451 ////////////////////////////////////////////////////////////////////////////////
452 /// Destructor
453 
455 {
456  if (fChildren) {
457  fChildren->SetOwner(kTRUE);
458  delete fChildren;
459  fChildren = 0;
460  }
461 }
462 
463 ////////////////////////////////////////////////////////////////////////////////
464 /// Add an entry for 'pid' in the internal list
465 
467 {
468  if (pid > 0) {
469  if (!fChildren)
470  fChildren = new TList;
471  TString spid;
472  spid.Form("%d", pid);
473  fChildren->Add(new TParameter<Int_t>(spid.Data(), pid));
474  TurnOn();
475  }
476 }
477 
478 ////////////////////////////////////////////////////////////////////////////////
479 /// Check if any of the registered children has changed its state.
480 /// Unregister those that are gone.
481 
483 {
484  if (fChildren) {
485  TIter nxp(fChildren);
486  TParameter<Int_t> *p = 0;
487  while ((p = (TParameter<Int_t> *)nxp())) {
488  int status;
489 #ifndef WIN32
490  pid_t pid;
491  do {
492  pid = waitpid(p->GetVal(), &status, WNOHANG);
493  } while (pid < 0 && errno == EINTR);
494 #else
495  intptr_t pid;
496  pid = _cwait(&status, (intptr_t)p->GetVal(), 0);
497 #endif
498  if (pid > 0 && pid == p->GetVal()) {
499  // Remove from the list
500  fChildren->Remove(p);
501  delete p;
502  }
503  }
504  }
505 
506  // Stop the timer if no children
507  if (!fChildren || fChildren->GetSize() <= 0) {
508  Stop();
509  } else {
510  // Needed for the next shot
511  Reset();
512  }
513  return kTRUE;
514 }
515 
516 //--- Special timer to terminate idle sessions ----------------------------//
517 ////////////////////////////////////////////////////////////////////////////////
518 /// Handle expiration of the idle timer. The session will just be terminated.
519 
521 {
522  Info ("Notify", "session idle for more then %lld secs: terminating", Long64_t(fTime)/1000);
523 
524  if (fProofServ) {
525  // Set the status to timed-out
526  Int_t uss_rc = -1;
527  if ((uss_rc = fProofServ->UpdateSessionStatus(4)) != 0)
528  Warning("Notify", "problems updating session status (errno: %d)", -uss_rc);
529  // Send a terminate request
530  TString msg;
531  if (fProofServ->GetProtocol() < 29) {
532  msg.Form("\n//\n// PROOF session at %s (%s) terminated because idle for more than %lld secs\n"
533  "// Please IGNORE any error message possibly displayed below\n//",
535  } else {
536  msg.Form("\n//\n// PROOF session at %s (%s) terminated because idle for more than %lld secs\n//",
538  }
539  fProofServ->SendAsynMessage(msg.Data());
540  fProofServ->Terminate(0);
541  Reset();
542  Stop();
543  } else {
544  Warning("Notify", "fProofServ undefined!");
545  Start(-1, kTRUE);
546  }
547  return kTRUE;
548 }
549 
551 
552 // Hook to the constructor. This is needed to avoid using the plugin manager
553 // which may create problems in multi-threaded environments.
554 extern "C" {
555  TApplication *GetTProofServ(Int_t *argc, char **argv, FILE *flog)
556  { return new TProofServ(argc, argv, flog); }
557 }
558 
559 ////////////////////////////////////////////////////////////////////////////////
560 /// Main constructor. Create an application environment. The TProofServ
561 /// environment provides an eventloop via inheritance of TApplication.
562 /// Actual server creation work is done in CreateServer() to allow
563 /// overloading.
564 
565 TProofServ::TProofServ(Int_t *argc, char **argv, FILE *flog)
566  : TApplication("proofserv", argc, argv, 0, -1)
567 {
568  // If test and tty, we are done
569  Bool_t xtest = (argc && *argc == 1) ? kTRUE : kFALSE;
570  if (xtest) {
571  Printf("proofserv: command line testing: OK");
572  exit(0);
573  }
574 
575  // Read session specific rootrc file
576  TString rcfile = gSystem->Getenv("ROOTRCFILE") ? gSystem->Getenv("ROOTRCFILE")
577  : "session.rootrc";
578  if (!gSystem->AccessPathName(rcfile, kReadPermission))
579  gEnv->ReadFile(rcfile, kEnvChange);
580 
581  // Upper limit on Virtual Memory (in kB)
582  fgVirtMemMax = gEnv->GetValue("Proof.VirtMemMax",-1);
583  if (fgVirtMemMax < 0 && gSystem->Getenv("PROOF_VIRTMEMMAX")) {
584  Long_t mmx = strtol(gSystem->Getenv("PROOF_VIRTMEMMAX"), 0, 10);
585  if (mmx < kMaxLong && mmx > 0)
586  fgVirtMemMax = mmx * 1024;
587  }
588  // Old variable for backward compatibility
589  if (fgVirtMemMax < 0 && gSystem->Getenv("ROOTPROOFASHARD")) {
590  Long_t mmx = strtol(gSystem->Getenv("ROOTPROOFASHARD"), 0, 10);
591  if (mmx < kMaxLong && mmx > 0)
592  fgVirtMemMax = mmx * 1024;
593  }
594  // Upper limit on Resident Memory (in kB)
595  fgResMemMax = gEnv->GetValue("Proof.ResMemMax",-1);
596  if (fgResMemMax < 0 && gSystem->Getenv("PROOF_RESMEMMAX")) {
597  Long_t mmx = strtol(gSystem->Getenv("PROOF_RESMEMMAX"), 0, 10);
598  if (mmx < kMaxLong && mmx > 0)
599  fgResMemMax = mmx * 1024;
600  }
601  // Thresholds for warnings and stop processing
602  fgMemStop = gEnv->GetValue("Proof.MemStop", 0.95);
603  fgMemHWM = gEnv->GetValue("Proof.MemHWM", 0.80);
604  if (fgVirtMemMax > 0 || fgResMemMax > 0) {
605  if ((fgMemStop < 0.) || (fgMemStop > 1.)) {
606  Warning("TProofServ", "requested memory fraction threshold to stop processing"
607  " (MemStop) out of range [0,1] - ignoring");
608  fgMemStop = 0.95;
609  }
610  if ((fgMemHWM < 0.) || (fgMemHWM > fgMemStop)) {
611  Warning("TProofServ", "requested memory fraction threshold for warning and finer monitoring"
612  " (MemHWM) out of range [0,MemStop] - ignoring");
613  fgMemHWM = 0.80;
614  }
615  }
616 
617  // Wait (loop) to allow debugger to connect
618  Bool_t test = (argc && *argc >= 4 && !strcmp(argv[3], "test")) ? kTRUE : kFALSE;
619  if ((gEnv->GetValue("Proof.GdbHook",0) == 3 && !test) ||
620  (gEnv->GetValue("Proof.GdbHook",0) == 4 && test)) {
621  while (gProofServDebug)
622  ;
623  }
624 
625  // Test instance
626  if (argc && *argc >= 4)
627  if (!strcmp(argv[3], "test"))
628  fService = "prooftest";
629 
630  // crude check on number of arguments
631  if (argc && *argc < 2) {
632  Error("TProofServ", "Must have at least 1 arguments (see proofd).");
633  exit(1);
634  }
635 
636  // Set global to this instance
637  gProofServ = this;
638 
639  // Log control flags
641 
642  // Abort on higher than kSysError's and set error handler
644  SetErrorHandlerFile(stderr);
646 
647  fNcmd = 0;
648  fGroupPriority = 100;
649  fInterrupt = kFALSE;
650  fProtocol = 0;
651  fOrdinal = gEnv->GetValue("ProofServ.Ordinal", "-1");
652  fGroupId = -1;
653  fGroupSize = 0;
654  fRealTime = 0.0;
655  fCpuTime = 0.0;
656  fProof = 0;
657  fPlayer = 0;
658  fSocket = 0;
659 
660  fTotSessions = -1;
661  fActSessions = -1;
662  fEffSessions = -1.;
663  fPackMgr = 0;
664 
665  fLogFile = flog;
666  fLogFileDes = -1;
667 
668  fArchivePath = "";
669  // Init lockers
670  fCacheLock = 0;
671  fQueryLock = 0;
672 
673  fQMgr = 0;
674  fWaitingQueries = new TList;
675  fIdle = kTRUE;
676  fQuerySeqNum = -1;
677 
678  fQueuedMsg = new TList;
679 
681 
682  fShutdownTimer = 0;
683  fReaperTimer = 0;
684  fIdleTOTimer = 0;
685 
686  fDataSetManager = 0; // Initialized in Setup()
687  fDataSetStgRepo = 0; // Initialized in Setup()
688 
689  fInputHandler = 0;
690 
691  // Quotas disabled by default
692  fMaxQueries = -1;
693  fMaxBoxSize = -1;
694  fHWMBoxSize = -1;
695 
696  // Submerger quantities
697  fMergingSocket = 0;
698  fMergingMonitor = 0;
699  fMergedWorkers = 0;
700 
701  // Bit to flg high-memory footprint
703 
704  // Max message size
705  fMsgSizeHWM = gEnv->GetValue("ProofServ.MsgSizeHWM", 1000000);
706 
707  // Message compression
708  fCompressMsg = gEnv->GetValue("ProofServ.CompressMessage", 0);
709 
710  gProofDebugLevel = gEnv->GetValue("Proof.DebugLevel",0);
712 
713  gProofDebugMask = (TProofDebug::EProofDebugMask) gEnv->GetValue("Proof.DebugMask",~0);
714  if (gProofDebugLevel > 0)
715  Info("TProofServ", "DebugLevel %d Mask 0x%x", gProofDebugLevel, gProofDebugMask);
716 
717  // Max log file size
718  fLogFileMaxSize = -1;
719  TString logmx = gEnv->GetValue("ProofServ.LogFileMaxSize", "");
720  if (!logmx.IsNull()) {
721  Long64_t xf = 1;
722  if (!logmx.IsDigit()) {
723  if (logmx.EndsWith("K")) {
724  xf = 1024;
725  logmx.Remove(TString::kTrailing, 'K');
726  } else if (logmx.EndsWith("M")) {
727  xf = 1024*1024;
728  logmx.Remove(TString::kTrailing, 'M');
729  } if (logmx.EndsWith("G")) {
730  xf = 1024*1024*1024;
731  logmx.Remove(TString::kTrailing, 'G');
732  }
733  }
734  if (logmx.IsDigit()) {
735  fLogFileMaxSize = logmx.Atoi() * xf;
736  if (fLogFileMaxSize > 0)
737  Info("TProofServ", "keeping the log file size within %lld bytes", fLogFileMaxSize);
738  } else {
739  logmx = gEnv->GetValue("ProofServ.LogFileMaxSize", "");
740  Warning("TProofServ", "bad formatted log file size limit ignored: '%s'", logmx.Data());
741  }
742  }
743 
744  // Parse options
745  GetOptions(argc, argv);
746 
747  // Default prefix in the form '<role>-<ordinal>'
748  fPrefix = (IsMaster() ? "Mst-" : "Wrk-");
749  if (test) fPrefix = "Test";
750  if (fOrdinal != "-1")
751  fPrefix += fOrdinal;
753 
754  // Syslog control
755  TString slog = gEnv->GetValue("ProofServ.LogToSysLog", "");
756  if (!(slog.IsNull())) {
757  if (slog.IsDigit()) {
758  fgLogToSysLog = slog.Atoi();
759  } else {
760  char c = (slog[0] == 'M' || slog[0] == 'm') ? 'm' : 'a';
761  c = (slog[0] == 'W' || slog[0] == 'w') ? 'w' : c;
762  Bool_t dosyslog = ((c == 'm' && IsMaster()) ||
763  (c == 'w' && !IsMaster()) || c == 'a') ? kTRUE : kFALSE;
764  if (dosyslog) {
765  slog.Remove(0,1);
766  if (slog.IsDigit()) fgLogToSysLog = slog.Atoi();
767  if (fgLogToSysLog <= 0)
768  Warning("TProofServ", "request for syslog logging ineffective!");
769  }
770  }
771  }
772  // Initialize proper service if required
773  if (fgLogToSysLog > 0) {
774  fgSysLogService = (IsMaster()) ? "proofm" : "proofw";
775  if (fOrdinal != "-1") fgSysLogService += TString::Format("-%s", fOrdinal.Data());
777  }
778 
779  // Enable optimized sending of streamer infos to use embedded backward/forward
780  // compatibility support between different ROOT versions and different versions of
781  // users classes
782  Bool_t enableSchemaEvolution = gEnv->GetValue("Proof.SchemaEvolution",1);
783  if (enableSchemaEvolution) {
785  } else {
786  Info("TProofServ", "automatic schema evolution in TMessage explicitly disabled");
787  }
788 }
789 
790 ////////////////////////////////////////////////////////////////////////////////
791 /// Finalize the server setup. If master, create the TProof instance to talk
792 /// to the worker or submaster nodes.
793 /// Return 0 on success, -1 on error
794 
796 {
797  // Get socket to be used (setup in proofd)
798  TString opensock = gSystem->Getenv("ROOTOPENSOCK");
799  if (opensock.Length() <= 0)
800  opensock = gEnv->GetValue("ProofServ.OpenSock", "-1");
801  Int_t sock = opensock.Atoi();
802  if (sock <= 0) {
803  Fatal("CreateServer", "Invalid socket descriptor number (%d)", sock);
804  return -1;
805  }
806  fSocket = new TSocket(sock);
807 
808  // Set compression level, if any
810 
811  // debug hooks
812  if (IsMaster()) {
813  // wait (loop) in master to allow debugger to connect
814  if (gEnv->GetValue("Proof.GdbHook",0) == 1) {
815  while (gProofServDebug)
816  ;
817  }
818  } else {
819  // wait (loop) in slave to allow debugger to connect
820  if (gEnv->GetValue("Proof.GdbHook",0) == 2) {
821  while (gProofServDebug)
822  ;
823  }
824  }
825 
826  if (gProofDebugLevel > 0)
827  Info("CreateServer", "Service %s ConfDir %s IsMaster %d\n",
829 
830  if (Setup() != 0) {
831  // Setup failure
832  LogToMaster();
833  SendLogFile();
834  Terminate(0);
835  return -1;
836  }
837 
838  // Set the default prefix in the form '<role>-<ordinal>' (it was already done
839  // in the constructor, but for standard PROOF the ordinal number is only set in
840  // Setup(), so we need to do it again here)
841  TString pfx = (IsMaster() ? "Mst-" : "Wrk-");
842  pfx += GetOrdinal();
844 
845  if (!fLogFile) {
846  RedirectOutput();
847  // If for some reason we failed setting a redirection file for the logs
848  // we cannot continue
849  if (!fLogFile || (fLogFileDes = fileno(fLogFile)) < 0) {
850  LogToMaster();
851  SendLogFile(-98);
852  Terminate(0);
853  return -1;
854  }
855  } else {
856  // Use the file already open by pmain
857  if ((fLogFileDes = fileno(fLogFile)) < 0) {
858  LogToMaster();
859  SendLogFile(-98);
860  Terminate(0);
861  return -1;
862  }
863  }
864 
865  // Send message of the day to the client
866  if (IsMaster()) {
867  if (CatMotd() == -1) {
868  LogToMaster();
869  SendLogFile(-99);
870  Terminate(0);
871  return -1;
872  }
873  }
874 
875  // Everybody expects std::iostream to be available, so load it...
876  ProcessLine("#include <iostream>", kTRUE);
877  ProcessLine("#include <string>",kTRUE); // for std::string std::iostream.
878 
879  // The following libs are also useful to have, make sure they are loaded...
880  //gROOT->LoadClass("TMinuit", "Minuit");
881  //gROOT->LoadClass("TPostScript", "Postscript");
882 
883  // Load user functions
884  const char *logon;
885  logon = gEnv->GetValue("Proof.Load", (char *)0);
886  if (logon) {
887  char *mac = gSystem->Which(TROOT::GetMacroPath(), logon, kReadPermission);
888  if (mac)
889  ProcessLine(TString::Format(".L %s", logon), kTRUE);
890  delete [] mac;
891  }
892 
893  // Execute logon macro
894  logon = gEnv->GetValue("Proof.Logon", (char *)0);
895  if (logon && !NoLogOpt()) {
896  char *mac = gSystem->Which(TROOT::GetMacroPath(), logon, kReadPermission);
897  if (mac)
898  ProcessFile(logon);
899  delete [] mac;
900  }
901 
902  // Save current interpreter context
903  gInterpreter->SaveContext();
904  gInterpreter->SaveGlobalsContext();
905 
906  // Install interrupt and message input handlers
907  gSystem->AddSignalHandler(new TProofServTerminationHandler(this));
908  gSystem->AddSignalHandler(new TProofServInterruptHandler(this));
909  fInputHandler = new TProofServInputHandler(this, sock);
911 
912  // if master, start slave servers
913  if (IsMaster()) {
914  TString master = "proof://__master__";
916  if (a.IsValid()) {
917  master += ":";
918  master += a.GetPort();
919  }
920 
921  // Get plugin manager to load appropriate TProof from
922  TPluginManager *pm = gROOT->GetPluginManager();
923  if (!pm) {
924  Error("CreateServer", "no plugin manager found");
925  SendLogFile(-99);
926  Terminate(0);
927  return -1;
928  }
929 
930  // Find the appropriate handler
931  TPluginHandler *h = pm->FindHandler("TProof", fConfFile);
932  if (!h) {
933  Error("CreateServer", "no plugin found for TProof with a"
934  " config file of '%s'", fConfFile.Data());
935  SendLogFile(-99);
936  Terminate(0);
937  return -1;
938  }
939 
940  // load the plugin
941  if (h->LoadPlugin() == -1) {
942  Error("CreateServer", "plugin for TProof could not be loaded");
943  SendLogFile(-99);
944  Terminate(0);
945  return -1;
946  }
947 
948  // make instance of TProof
949  fProof = reinterpret_cast<TProof*>(h->ExecPlugin(5, master.Data(),
950  fConfFile.Data(),
951  GetConfDir(),
952  fLogLevel, 0));
953  if (!fProof || !fProof->IsValid()) {
954  Error("CreateServer", "plugin for TProof could not be executed");
956  SendLogFile(-99);
957  Terminate(0);
958  return -1;
959  }
960  // Find out if we are a master in direct contact only with workers
962 
963  SendLogFile();
964  }
965 
966  // Setup the shutdown timer
967  if (!fShutdownTimer) {
968  // Check activity on socket every 5 mins
969  fShutdownTimer = new TShutdownTimer(this, 300000);
971  }
972 
973  // Check if schema evolution is effective: clients running versions <=17 do not
974  // support that: send a warning message
975  if (fProtocol <= 17) {
976  TString msg;
977  msg.Form("Warning: client version is too old: automatic schema evolution is ineffective.\n"
978  " This may generate compatibility problems between streamed objects.\n"
979  " The advise is to move to ROOT >= 5.21/02 .");
980  SendAsynMessage(msg.Data());
981  }
982 
983  // Setup the idle timer
984  if (IsMaster() && !fIdleTOTimer) {
985  // Check activity on socket every 5 mins
986  Int_t idle_to = gEnv->GetValue("ProofServ.IdleTimeout", -1);
987  if (idle_to > 0) {
988  fIdleTOTimer = new TIdleTOTimer(this, idle_to * 1000);
989  fIdleTOTimer->Start(-1, kTRUE);
990  if (gProofDebugLevel > 0)
991  Info("CreateServer", " idle timer started (%d secs)", idle_to);
992  } else if (gProofDebugLevel > 0) {
993  Info("CreateServer", " idle timer not started (no idle timeout requested)");
994  }
995  }
996 
997  // Done
998  return 0;
999 }
1000 
1001 ////////////////////////////////////////////////////////////////////////////////
1002 /// Cleanup. Not really necessary since after this dtor there is no
1003 /// live anyway.
1004 
1006 {
1014  close(fLogFileDes);
1015 }
1016 
1017 ////////////////////////////////////////////////////////////////////////////////
1018 /// Print message of the day (in the file pointed by the env PROOFMOTD
1019 /// or from fConfDir/etc/proof/motd). The motd is not shown more than
1020 /// once a day. If the file pointed by env PROOFNOPROOF exists (or the
1021 /// file fConfDir/etc/proof/noproof exists), show its contents and close
1022 /// the connection.
1023 
1025 {
1026  TString lastname;
1027  FILE *motd;
1028  Bool_t show = kFALSE;
1029 
1030  // If we are disabled just print the message and close the connection
1031  TString motdname(GetConfDir());
1032  // The env variable PROOFNOPROOF allows to put the file in an alternative
1033  // location not overwritten by a new installation
1034  if (gSystem->Getenv("PROOFNOPROOF")) {
1035  motdname = gSystem->Getenv("PROOFNOPROOF");
1036  } else {
1037  motdname += "/etc/proof/noproof";
1038  }
1039  if ((motd = fopen(motdname, "r"))) {
1040  Int_t c;
1041  printf("\n");
1042  while ((c = getc(motd)) != EOF)
1043  putchar(c);
1044  fclose(motd);
1045  printf("\n");
1046 
1047  return -1;
1048  }
1049 
1050  // get last modification time of the file ~/proof/.prooflast
1051  lastname = TString(GetWorkDir()) + "/.prooflast";
1052  char *last = gSystem->ExpandPathName(lastname.Data());
1053  Long64_t size;
1054  Long_t id, flags, modtime, lasttime = 0;
1055  if (gSystem->GetPathInfo(last, &id, &size, &flags, &lasttime) == 1)
1056  lasttime = 0;
1057 
1058  // show motd at least once per day
1059  if (time(0) - lasttime > (time_t)86400)
1060  show = kTRUE;
1061 
1062  // The env variable PROOFMOTD allows to put the file in an alternative
1063  // location not overwritten by a new installation
1064  if (gSystem->Getenv("PROOFMOTD")) {
1065  motdname = gSystem->Getenv("PROOFMOTD");
1066  } else {
1067  motdname = GetConfDir();
1068  motdname += "/etc/proof/motd";
1069  }
1070  if (gSystem->GetPathInfo(motdname, &id, &size, &flags, &modtime) == 0) {
1071  if (modtime > lasttime || show) {
1072  if ((motd = fopen(motdname, "r"))) {
1073  Int_t c;
1074  printf("\n");
1075  while ((c = getc(motd)) != EOF)
1076  putchar(c);
1077  fclose(motd);
1078  printf("\n");
1079  }
1080  }
1081  }
1082 
1083  if (lasttime)
1084  gSystem->Unlink(last);
1085  Int_t fd = creat(last, 0600);
1086  if (fd >= 0) close(fd);
1087  delete [] last;
1088 
1089  return 0;
1090 }
1091 
1092 ////////////////////////////////////////////////////////////////////////////////
1093 /// Get object with name "name;cycle" (e.g. "aap;2") from master or client.
1094 /// This method is called by TDirectory::Get() in case the object can not
1095 /// be found locally.
1096 
1097 TObject *TProofServ::Get(const char *namecycle)
1098 {
1099  if (fSocket->Send(namecycle, kPROOF_GETOBJECT) < 0) {
1100  Error("Get", "problems sending request");
1101  return (TObject *)0;
1102  }
1103 
1104  TObject *idcur = 0;
1105 
1106  Bool_t notdone = kTRUE;
1107  while (notdone) {
1108  TMessage *mess = 0;
1109  if (fSocket->Recv(mess) < 0)
1110  return 0;
1111  Int_t what = mess->What();
1112  if (what == kMESS_OBJECT) {
1113  idcur = mess->ReadObject(mess->GetClass());
1114  notdone = kFALSE;
1115  } else {
1116  Int_t xrc = HandleSocketInput(mess, kFALSE);
1117  if (xrc == -1) {
1118  Error("Get", "command %d cannot be executed while processing", what);
1119  } else if (xrc == -2) {
1120  Error("Get", "unknown command %d ! Protocol error?", what);
1121  }
1122  }
1123  delete mess;
1124  }
1125 
1126  return idcur;
1127 }
1128 
1129 ////////////////////////////////////////////////////////////////////////////////
1130 /// Reset the compute time
1131 
1133 {
1134  fCompute.Stop();
1135  if (fPlayer) {
1137  if (status) status->SetLearnTime(fCompute.RealTime());
1138  Info("RestartComputeTime", "compute time restarted after %f secs (%d entries)",
1140  }
1142 }
1143 
1144 ////////////////////////////////////////////////////////////////////////////////
1145 /// Get next range of entries to be processed on this server.
1146 
1148 {
1149  Long64_t bytesRead = 0;
1150 
1151  if (gPerfStats) bytesRead = gPerfStats->GetBytesRead();
1152 
1153  if (fCompute.Counter() > 0)
1154  fCompute.Stop();
1155 
1157  Double_t cputime = fCompute.CpuTime();
1158  Double_t realtime = fCompute.RealTime();
1159 
1160  if (fProtocol > 18) {
1161  req << fLatency.RealTime();
1162  TProofProgressStatus *status = 0;
1163  if (fPlayer) {
1165  status = fPlayer->GetProgressStatus();
1166  } else {
1167  Error("GetNextPacket", "no progress status object");
1168  return 0;
1169  }
1170  // the CPU and wallclock proc times are kept in the TProofServ and here
1171  // added to the status object in the fPlayer.
1172  if (status->GetEntries() > 0) {
1173  PDB(kLoop, 2) status->Print(GetOrdinal());
1174  status->IncProcTime(realtime);
1175  status->IncCPUTime(cputime);
1176  }
1177  // Flag cases with problems in opening files
1178  if (totalEntries < 0) status->SetBit(TProofProgressStatus::kFileNotOpen);
1179  // Add to the message
1180  req << status;
1181  // Send tree cache information
1182  Long64_t cacheSize = (fPlayer) ? fPlayer->GetCacheSize() : -1;
1183  Int_t learnent = (fPlayer) ? fPlayer->GetLearnEntries() : -1;
1184  req << cacheSize << learnent;
1185 
1186  // Sent over the number of entries in the file, used by packetizer do not relying
1187  // on initial validation. Also, -1 means that the file could not be open, which is
1188  // used to flag files as missing
1189  req << totalEntries;
1190 
1191  // Send the time spent in saving the partial result to file
1192  if (fProtocol > 34) req << fSaveOutput.RealTime();
1193 
1194  PDB(kLoop, 1) {
1195  PDB(kLoop, 2) status->Print();
1196  Info("GetNextPacket","cacheSize: %lld, learnent: %d", cacheSize, learnent);
1197  }
1198  // Reset the status bits
1199  status->ResetBit(TProofProgressStatus::kFileNotOpen);
1200  status->ResetBit(TProofProgressStatus::kFileCorrupted);
1201  status = 0; // status is owned by the player.
1202  } else {
1203  req << fLatency.RealTime() << realtime << cputime
1204  << bytesRead << totalEntries;
1205  if (fPlayer)
1206  req << fPlayer->GetEventsProcessed();
1207  }
1208 
1209  fLatency.Start();
1210  Int_t rc = fSocket->Send(req);
1211  if (rc <= 0) {
1212  Error("GetNextPacket","Send() failed, returned %d", rc);
1213  return 0;
1214  }
1215 
1216  // Save the current output
1217  if (fPlayer) {
1218  fSaveOutput.Start();
1219  if (fPlayer->SavePartialResults(kFALSE) < 0)
1220  Warning("GetNextPacket", "problems saving partial results");
1221  fSaveOutput.Stop();
1222  }
1223 
1224  TDSetElement *e = 0;
1225  Bool_t notdone = kTRUE;
1226  while (notdone) {
1227 
1228  TMessage *mess;
1229  if ((rc = fSocket->Recv(mess)) <= 0) {
1230  fLatency.Stop();
1231  Error("GetNextPacket","Recv() failed, returned %d", rc);
1232  return 0;
1233  }
1234 
1235  Int_t xrc = 0;
1236  TString file, dir, obj;
1237 
1238  Int_t what = mess->What();
1239 
1240  switch (what) {
1241  case kPROOF_GETPACKET:
1242 
1243  fLatency.Stop();
1244  (*mess) >> e;
1245  if (e != 0) {
1246  fCompute.Start();
1247  PDB(kLoop, 2) Info("GetNextPacket", "'%s' '%s' '%s' %lld %lld",
1248  e->GetFileName(), e->GetDirectory(),
1249  e->GetObjName(), e->GetFirst(),e->GetNum());
1250  } else {
1251  PDB(kLoop, 2) Info("GetNextPacket", "Done");
1252  }
1253  notdone = kFALSE;
1254  break;
1255 
1256  case kPROOF_STOPPROCESS:
1257  // if a kPROOF_STOPPROCESS message is returned to kPROOF_GETPACKET
1258  // GetNextPacket() will return 0 and the TPacketizer and hence
1259  // TEventIter will be stopped
1260  fLatency.Stop();
1261  PDB(kLoop, 2) Info("GetNextPacket:kPROOF_STOPPROCESS","received");
1262  break;
1263 
1264  default:
1265  xrc = HandleSocketInput(mess, kFALSE);
1266  if (xrc == -1) {
1267  Error("GetNextPacket", "command %d cannot be executed while processing", what);
1268  } else if (xrc == -2) {
1269  Error("GetNextPacket", "unknown command %d ! Protocol error?", what);
1270  }
1271  break;
1272  }
1273 
1274  delete mess;
1275 
1276  }
1277 
1278  // Done
1279  return e;
1280 }
1281 
1282 ////////////////////////////////////////////////////////////////////////////////
1283 /// Get and handle command line options. Fixed format:
1284 /// "proofserv"|"proofslave" <confdir>
1285 
1286 void TProofServ::GetOptions(Int_t *argc, char **argv)
1287 {
1288  Bool_t xtest = (argc && *argc > 3 && !strcmp(argv[3], "test")) ? kTRUE : kFALSE;
1289 
1290  // If test and tty
1291  if (xtest && !(isatty(0) == 0 || isatty(1) == 0)) {
1292  Printf("proofserv: command line testing: OK");
1293  exit(0);
1294  }
1295 
1296  if (!argc || (argc && *argc <= 1)) {
1297  Fatal("GetOptions", "Must be started from proofd with arguments");
1298  exit(1);
1299  }
1300 
1301  if (!strcmp(argv[1], "proofserv")) {
1302  fMasterServ = kTRUE;
1303  fEndMaster = kTRUE;
1304  } else if (!strcmp(argv[1], "proofslave")) {
1305  fMasterServ = kFALSE;
1306  fEndMaster = kFALSE;
1307  } else {
1308  Fatal("GetOptions", "Must be started as 'proofserv' or 'proofslave'");
1309  exit(1);
1310  }
1311 
1312  fService = argv[1];
1313 
1314  // Confdir
1315  if (!(gSystem->Getenv("ROOTCONFDIR"))) {
1316  Fatal("GetOptions", "ROOTCONFDIR shell variable not set");
1317  exit(1);
1318  }
1319  fConfDir = gSystem->Getenv("ROOTCONFDIR");
1320 }
1321 
1322 ////////////////////////////////////////////////////////////////////////////////
1323 /// Handle input coming from the client or from the master server.
1324 
1326 {
1327  // The idle timeout guard: stops the timer and restarts when we return from here
1329 
1330  Bool_t all = (fgRecursive > 0) ? kFALSE : kTRUE;
1331  fgRecursive++;
1332 
1333  TMessage *mess;
1334  Int_t rc = 0;
1335  TString exmsg;
1336 
1337  // Check log file length (before the action, so we have the chance to keep the
1338  // latest logs)
1339  TruncateLogFile();
1340 
1341  try {
1342 
1343  // Get message
1344  if (fSocket->Recv(mess) <= 0 || !mess) {
1345  // Pending: do something more intelligent here
1346  // but at least get a message in the log file
1347  Error("HandleSocketInput", "retrieving message from input socket");
1348  Terminate(0);
1349  return;
1350  }
1351  Int_t what = mess->What();
1352  PDB(kCollect, 1)
1353  Info("HandleSocketInput", "got type %d from '%s'", what, fSocket->GetTitle());
1354 
1355  fNcmd++;
1356 
1357  if (fProof) fProof->SetActive();
1358 
1359  Bool_t doit = kTRUE;
1360 
1361  while (doit) {
1362 
1363  // Process the message
1364  rc = HandleSocketInput(mess, all);
1365  if (rc < 0) {
1366  TString emsg;
1367  if (rc == -1) {
1368  emsg.Form("HandleSocketInput: command %d cannot be executed while processing", what);
1369  } else if (rc == -3) {
1370  emsg.Form("HandleSocketInput: message %d undefined! Protocol error?", what);
1371  } else {
1372  emsg.Form("HandleSocketInput: unknown command %d! Protocol error?", what);
1373  }
1374  SendAsynMessage(emsg.Data());
1375  } else if (rc == 2) {
1376  // Add to the queue
1377  fQueuedMsg->Add(mess);
1378  PDB(kGlobal, 1)
1379  Info("HandleSocketInput", "message of type %d enqueued; sz: %d",
1380  what, fQueuedMsg->GetSize());
1381  mess = 0;
1382  }
1383 
1384  // Still something to do?
1385  doit = 0;
1386  if (fgRecursive == 1 && fQueuedMsg->GetSize() > 0) {
1387  // Add to the queue
1388  PDB(kCollect, 1)
1389  Info("HandleSocketInput", "processing enqueued message of type %d; left: %d",
1390  what, fQueuedMsg->GetSize());
1391  all = 1;
1392  SafeDelete(mess);
1393  mess = (TMessage *) fQueuedMsg->First();
1394  if (mess) fQueuedMsg->Remove(mess);
1395  doit = 1;
1396  }
1397  }
1398 
1399  } catch (std::bad_alloc &) {
1400  // Memory allocation problem:
1401  exmsg.Form("caught exception 'bad_alloc' (memory leak?) %s %lld",
1402  fgLastMsg.Data(), fgLastEntry);
1403  } catch (std::exception &exc) {
1404  // Standard exception caught
1405  exmsg.Form("caught standard exception '%s' %s %lld",
1406  exc.what(), fgLastMsg.Data(), fgLastEntry);
1407  } catch (int i) {
1408  // Other exception caught
1409  exmsg.Form("caught exception throwing %d %s %lld",
1410  i, fgLastMsg.Data(), fgLastEntry);
1411  } catch (const char *str) {
1412  // Other exception caught
1413  exmsg.Form("caught exception throwing '%s' %s %lld",
1414  str, fgLastMsg.Data(), fgLastEntry);
1415  } catch (...) {
1416  // Caught other exception
1417  exmsg.Form("caught exception <unknown> %s %lld",
1418  fgLastMsg.Data(), fgLastEntry);
1419  }
1420 
1421  // Terminate on exception
1422  if (!exmsg.IsNull()) {
1423  // Save info in the log file too
1424  Error("HandleSocketInput", "%s", exmsg.Data());
1425  // Try to warn the user
1426  SendAsynMessage(TString::Format("%s: %s", GetOrdinal(), exmsg.Data()));
1427  // Terminate
1428  Terminate(0);
1429  }
1430 
1431  // Terminate also if a high memory footprint was detected before the related
1432  // exception was thrwon
1434  // Save info in the log file too
1435  exmsg.Form("high-memory footprint detected during Process(...) - terminating");
1436  Error("HandleSocketInput", "%s", exmsg.Data());
1437  // Try to warn the user
1438  SendAsynMessage(TString::Format("%s: %s", GetOrdinal(), exmsg.Data()));
1439  // Terminate
1440  Terminate(0);
1441  }
1442 
1443  fgRecursive--;
1444 
1445  if (fProof) {
1446  // If something wrong went on during processing and we do not have
1447  // any worker anymore, we shutdown this session
1448  Bool_t masterOnly = gEnv->GetValue("Proof.MasterOnly", kFALSE);
1449  Bool_t dynamicStartup = gEnv->GetValue("Proof.DynamicStartup", kFALSE);
1451  if (rc == 0 && ngwrks == 0 && !masterOnly && !dynamicStartup) {
1452  SendAsynMessage(" *** No workers left: cannot continue! Terminating ... *** ");
1453  Terminate(0);
1454  }
1456  // Reset PROOF to running state
1458  }
1459 
1460  // Cleanup
1461  SafeDelete(mess);
1462 }
1463 
1464 ////////////////////////////////////////////////////////////////////////////////
1465 /// Process input coming from the client or from the master server.
1466 /// If 'all' is kFALSE, process only those messages that can be handled
1467 /// during query processing.
1468 /// Returns -1 if the message could not be processed, <-1 if something went
1469 /// wrong. Returns 1 if the action may have changed the parallel state.
1470 /// Returns 2 if the message has to be enqueued.
1471 /// Returns 0 otherwise
1472 
1474 {
1475  static TStopwatch timer;
1476  char str[2048];
1477  Bool_t aborted = kFALSE;
1478 
1479  if (!mess) return -3;
1480 
1481  Int_t what = mess->What();
1482  PDB(kCollect, 1)
1483  Info("HandleSocketInput", "processing message type %d from '%s'",
1484  what, fSocket->GetTitle());
1485 
1486  timer.Start();
1487 
1488  Int_t rc = 0, lirc = 0;
1489  TString slb;
1490  TString *pslb = (fgLogToSysLog > 0) ? &slb : (TString *)0;
1491 
1492  switch (what) {
1493 
1494  case kMESS_CINT:
1495  if (all) {
1496  mess->ReadString(str, sizeof(str));
1497  // Make sure that the relevant files are available
1498  TString fn;
1499 
1500  Bool_t hasfn = TProof::GetFileInCmd(str, fn);
1501 
1502  if (IsParallel() && fProof && !fProof->UseDynamicStartup()) {
1503  fProof->SendCommand(str);
1504  } else {
1505  PDB(kGlobal, 1)
1506  Info("HandleSocketInput:kMESS_CINT", "processing: %s...", str);
1507  TString ocwd;
1508  if (hasfn) {
1509  fCacheLock->Lock();
1510  ocwd = gSystem->WorkingDirectory();
1512  }
1513  ProcessLine(str);
1514  if (hasfn) {
1515  gSystem->ChangeDirectory(ocwd);
1516  fCacheLock->Unlock();
1517  }
1518  }
1519 
1520  LogToMaster();
1521  } else {
1522  rc = -1;
1523  }
1524  SendLogFile();
1525  if (pslb) slb = str;
1526  break;
1527 
1528  case kMESS_STRING:
1529  if (all) {
1530  mess->ReadString(str, sizeof(str));
1531  } else {
1532  rc = -1;
1533  }
1534  break;
1535 
1536  case kMESS_OBJECT:
1537  if (all) {
1538  mess->ReadObject(mess->GetClass());
1539  } else {
1540  rc = -1;
1541  }
1542  break;
1543 
1544  case kPROOF_GROUPVIEW:
1545  if (all) {
1546  mess->ReadString(str, sizeof(str));
1547  // coverity[secure_coding]
1548  sscanf(str, "%d %d", &fGroupId, &fGroupSize);
1549  } else {
1550  rc = -1;
1551  }
1552  break;
1553 
1554  case kPROOF_LOGLEVEL:
1555  { UInt_t mask;
1556  mess->ReadString(str, sizeof(str));
1557  sscanf(str, "%d %u", &fLogLevel, &mask);
1558  Bool_t levelchanged = (fLogLevel != gProofDebugLevel) ? kTRUE : kFALSE;
1561  if (levelchanged)
1562  Info("HandleSocketInput:kPROOF_LOGLEVEL", "debug level set to %d (mask: 0x%x)",
1564  if (IsMaster())
1565  fProof->SetLogLevel(fLogLevel, mask);
1566  }
1567  break;
1568 
1569  case kPROOF_PING:
1570  { if (IsMaster())
1571  fProof->Ping();
1572  // do nothing (ping is already acknowledged)
1573  }
1574  break;
1575 
1576  case kPROOF_PRINT:
1577  mess->ReadString(str, sizeof(str));
1578  Print(str);
1579  LogToMaster();
1580  SendLogFile();
1581  break;
1582 
1583  case kPROOF_RESET:
1584  if (all) {
1585  mess->ReadString(str, sizeof(str));
1586  Reset(str);
1587  } else {
1588  rc = -1;
1589  }
1590  break;
1591 
1592  case kPROOF_STATUS:
1593  Warning("HandleSocketInput:kPROOF_STATUS",
1594  "kPROOF_STATUS message is obsolete");
1596  Warning("HandleSocketInput:kPROOF_STATUS", "problem sending of request");
1597  break;
1598 
1599  case kPROOF_GETSTATS:
1600  SendStatistics();
1601  break;
1602 
1603  case kPROOF_GETPARALLEL:
1604  SendParallel();
1605  break;
1606 
1607  case kPROOF_STOP:
1608  if (all) {
1609  if (IsMaster()) {
1610  TString ord;
1611  *mess >> ord;
1612  PDB(kGlobal, 1)
1613  Info("HandleSocketInput:kPROOF_STOP", "request for worker %s", ord.Data());
1614  if (fProof) fProof->TerminateWorker(ord);
1615  } else {
1616  PDB(kGlobal, 1)
1617  Info("HandleSocketInput:kPROOF_STOP", "got request to terminate");
1618  Terminate(0);
1619  }
1620  } else {
1621  rc = -1;
1622  }
1623  break;
1624 
1625  case kPROOF_STOPPROCESS:
1626  if (all) {
1627  // this message makes only sense when the query is being processed,
1628  // however the message can also be received if the user pressed
1629  // ctrl-c, so ignore it!
1630  PDB(kGlobal, 1) Info("HandleSocketInput:kPROOF_STOPPROCESS","enter");
1631  } else {
1632  Long_t timeout = -1;
1633  (*mess) >> aborted;
1634  if (fProtocol > 9)
1635  (*mess) >> timeout;
1636  PDB(kGlobal, 1)
1637  Info("HandleSocketInput:kPROOF_STOPPROCESS",
1638  "recursive mode: enter %d, %ld", aborted, timeout);
1639  if (fProof)
1640  // On the master: propagate further
1641  fProof->StopProcess(aborted, timeout);
1642  else
1643  // Worker: actually stop processing
1644  if (fPlayer)
1645  fPlayer->StopProcess(aborted, timeout);
1646  }
1647  break;
1648 
1649  case kPROOF_PROCESS:
1650  {
1652  PDB(kGlobal, 1) Info("HandleSocketInput:kPROOF_PROCESS","enter");
1653  HandleProcess(mess, pslb);
1654  // The log file is send either in HandleProcess or HandleSubmergers.
1655  // The reason is that the order of various messages depend on the
1656  // processing mode (sync/async) and/or merging mode
1657  }
1658  break;
1659 
1660  case kPROOF_SENDOUTPUT:
1661  {
1662  PDB(kGlobal, 1) Info("HandleSocketInput:kPROOF_SENDOUTPUT",
1663  "worker was asked to send output to master");
1664  Int_t sorc = 0;
1665  if (SendResults(fSocket, fPlayer->GetOutputList()) != 0) {
1666  Error("HandleSocketInput:kPROOF_SENDOUTPUT", "problems sending output list");
1667  sorc = 1;
1668  }
1669  // Signal the master that we are idle
1671  SetIdle(kTRUE);
1672  DeletePlayer();
1673  SendLogFile(sorc);
1674  }
1675  break;
1676 
1677  case kPROOF_QUERYLIST:
1678  {
1679  HandleQueryList(mess);
1680  // Notify
1681  SendLogFile();
1682  }
1683  break;
1684 
1685  case kPROOF_REMOVE:
1686  {
1687  HandleRemove(mess, pslb);
1688  // Notify
1689  SendLogFile();
1690  }
1691  break;
1692 
1693  case kPROOF_RETRIEVE:
1694  {
1695  HandleRetrieve(mess, pslb);
1696  // Notify
1697  SendLogFile();
1698  }
1699  break;
1700 
1701  case kPROOF_ARCHIVE:
1702  {
1703  HandleArchive(mess, pslb);
1704  // Notify
1705  SendLogFile();
1706  }
1707  break;
1708 
1709  case kPROOF_MAXQUERIES:
1710  { PDB(kGlobal, 1)
1711  Info("HandleSocketInput:kPROOF_MAXQUERIES", "Enter");
1713  m << fMaxQueries;
1714  fSocket->Send(m);
1715  // Notify
1716  SendLogFile();
1717  }
1718  break;
1719 
1720  case kPROOF_CLEANUPSESSION:
1721  if (all) {
1722  PDB(kGlobal, 1)
1723  Info("HandleSocketInput:kPROOF_CLEANUPSESSION", "Enter");
1724  TString stag;
1725  (*mess) >> stag;
1726  if (fQMgr && fQMgr->CleanupSession(stag) == 0) {
1727  Printf("Session %s cleaned up", stag.Data());
1728  } else {
1729  Printf("Could not cleanup session %s", stag.Data());
1730  }
1731  } else {
1732  rc = -1;
1733  }
1734  // Notify
1735  SendLogFile();
1736  break;
1737 
1738  case kPROOF_GETENTRIES:
1739  { PDB(kGlobal, 1) Info("HandleSocketInput:kPROOF_GETENTRIES", "Enter");
1740  Bool_t isTree;
1741  TString filename;
1742  TString dir;
1743  TString objname("undef");
1744  Long64_t entries = -1;
1745 
1746  if (all) {
1747  (*mess) >> isTree >> filename >> dir >> objname;
1748  PDB(kGlobal, 2) Info("HandleSocketInput:kPROOF_GETENTRIES",
1749  "Report size of object %s (%s) in dir %s in file %s",
1750  objname.Data(), isTree ? "T" : "O",
1751  dir.Data(), filename.Data());
1752  entries = TDSet::GetEntries(isTree, filename, dir, objname);
1753  PDB(kGlobal, 2) Info("HandleSocketInput:kPROOF_GETENTRIES",
1754  "Found %lld %s", entries, isTree ? "entries" : "objects");
1755  } else {
1756  rc = -1;
1757  }
1759  answ << entries << objname;
1760  SendLogFile(); // in case of error messages
1761  fSocket->Send(answ);
1762  PDB(kGlobal, 1) Info("HandleSocketInput:kPROOF_GETENTRIES", "Done");
1763  }
1764  break;
1765 
1766  case kPROOF_CHECKFILE:
1767  if (!all && fProtocol <= 19) {
1768  // Come back later
1769  rc = 2;
1770  } else {
1771  // Handle file checking request
1772  HandleCheckFile(mess, pslb);
1773  FlushLogFile(); // Avoid sending (error) messages at next action
1774  }
1775  break;
1776 
1777  case kPROOF_SENDFILE:
1778  if (!all && fProtocol <= 19) {
1779  // Come back later
1780  rc = 2;
1781  } else {
1782  mess->ReadString(str, sizeof(str));
1783  Long_t size;
1784  Int_t bin, fw = 1;
1785  char name[1024];
1786  if (fProtocol > 5) {
1787  sscanf(str, "%1023s %d %ld %d", name, &bin, &size, &fw);
1788  } else {
1789  sscanf(str, "%1023s %d %ld", name, &bin, &size);
1790  }
1791  TString fnam(name);
1792  Bool_t copytocache = kTRUE;
1793  if (fnam.BeginsWith("cache:")) {
1794  fnam.ReplaceAll("cache:", TString::Format("%s/", fCacheDir.Data()));
1795  copytocache = kFALSE;
1796  }
1797 
1798  Int_t rfrc = 0;
1799  if (size > 0) {
1800  rfrc = ReceiveFile(fnam, bin ? kTRUE : kFALSE, size);
1801  } else {
1802  // Take it from the cache
1803  if (!fnam.BeginsWith(fCacheDir.Data())) {
1804  fnam.Insert(0, TString::Format("%s/", fCacheDir.Data()));
1805  }
1806  }
1807  if (rfrc == 0) {
1808  // copy file to cache if not a PAR file
1809  if (copytocache && size > 0 && !fPackMgr->IsInDir(name))
1810  gSystem->Exec(TString::Format("%s %s %s", kCP, fnam.Data(), fCacheDir.Data()));
1811  if (IsMaster() && fw == 1) {
1813  if (bin)
1814  opt |= TProof::kBinary;
1815  PDB(kGlobal, 1)
1816  Info("HandleSocketInput","forwarding file: %s", fnam.Data());
1817  if (fProof->SendFile(fnam, opt, (copytocache ? "cache" : "")) < 0) {
1818  Error("HandleSocketInput", "forwarding file: %s", fnam.Data());
1819  }
1820  }
1821  if (fProtocol > 19) fSocket->Send(kPROOF_SENDFILE);
1822  } else {
1823  // There was an error
1824  SendLogFile(1);
1825  }
1826  }
1827  break;
1828 
1829  case kPROOF_LOGFILE:
1830  {
1831  Int_t start, end;
1832  (*mess) >> start >> end;
1833  PDB(kGlobal, 1)
1834  Info("HandleSocketInput:kPROOF_LOGFILE",
1835  "Logfile request - byte range: %d - %d", start, end);
1836 
1837  LogToMaster();
1838  SendLogFile(0, start, end);
1839  }
1840  break;
1841 
1842  case kPROOF_PARALLEL:
1843  if (all) {
1844  if (IsMaster()) {
1845  Int_t nodes;
1846  Bool_t random = kFALSE;
1847  (*mess) >> nodes;
1848  if ((mess->BufferSize() > mess->Length()))
1849  (*mess) >> random;
1850  if (fProof) fProof->SetParallel(nodes, random);
1851  rc = 1;
1852  }
1853  } else {
1854  rc = -1;
1855  }
1856  // Notify
1857  SendLogFile();
1858  break;
1859 
1860  case kPROOF_CACHE:
1861  if (!all && fProtocol <= 19) {
1862  // Come back later
1863  rc = 2;
1864  } else {
1866  PDB(kGlobal, 1) Info("HandleSocketInput:kPROOF_CACHE","enter");
1867  Int_t hcrc = HandleCache(mess, pslb);
1868  // Notify
1869  SendLogFile(hcrc);
1870  }
1871  break;
1872 
1873  case kPROOF_WORKERLISTS:
1874  { Int_t wlrc = -1;
1875  if (all) {
1876  if (IsMaster())
1877  wlrc = HandleWorkerLists(mess);
1878  else
1879  Warning("HandleSocketInput:kPROOF_WORKERLISTS",
1880  "Action meaning-less on worker nodes: protocol error?");
1881  } else {
1882  rc = -1;
1883  }
1884  // Notify
1885  SendLogFile(wlrc);
1886  }
1887  break;
1888 
1889  case kPROOF_GETSLAVEINFO:
1890  if (all) {
1891  PDB(kGlobal, 1) Info("HandleSocketInput:kPROOF_GETSLAVEINFO", "Enter");
1892  if (IsMaster()) {
1893 
1894  Bool_t ok = kTRUE;
1895  // if the session does not have workers and is in the dynamic mode
1896  if (fProof->UseDynamicStartup()) {
1897  ok = kFALSE;
1898  // get the a list of workers and start them
1899  Int_t pc = 0;
1900  TList* workerList = new TList();
1901  EQueryAction retVal = GetWorkers(workerList, pc);
1902  if (retVal != TProofServ::kQueryStop && retVal != TProofServ::kQueryEnqueued) {
1903  if (Int_t ret = fProof->AddWorkers(workerList) < 0) {
1904  Error("HandleSocketInput:kPROOF_GETSLAVEINFO",
1905  "adding a list of worker nodes returned: %d", ret);
1906  }
1907  } else {
1908  Error("HandleSocketInput:kPROOF_GETSLAVEINFO",
1909  "getting list of worker nodes returned: %d", retVal);
1910  }
1911  ok = kTRUE;
1912  }
1913  if (ok) {
1914  TList *info = fProof->GetListOfSlaveInfos();
1916  answ << info;
1917  fSocket->Send(answ);
1918  // stop the workers
1920  }
1921  } else {
1923  TList *info = new TList;
1924  TSlaveInfo *wi = new TSlaveInfo(GetOrdinal(), TUrl(gSystem->HostName()).GetHostFQDN(), 0, "", GetDataDir());
1925  SysInfo_t si;
1926  gSystem->GetSysInfo(&si);
1927  wi->SetSysInfo(si);
1928  info->Add(wi);
1929  answ << (TList *)info;
1930  fSocket->Send(answ);
1931  info->SetOwner(kTRUE);
1932  delete info;
1933  }
1934 
1935  PDB(kGlobal, 1) Info("HandleSocketInput:kPROOF_GETSLAVEINFO", "Done");
1936  } else {
1938  answ << (TList *)0;
1939  fSocket->Send(answ);
1940  rc = -1;
1941  }
1942  break;
1943 
1944  case kPROOF_GETTREEHEADER:
1945  if (all) {
1946  PDB(kGlobal, 1) Info("HandleSocketInput:kPROOF_GETTREEHEADER", "Enter");
1947 
1949  if (p) {
1950  p->HandleGetTreeHeader(mess);
1951  delete p;
1952  } else {
1953  Error("HandleSocketInput:kPROOF_GETTREEHEADER", "could not create TProofPlayer instance!");
1954  }
1955 
1956  PDB(kGlobal, 1) Info("HandleSocketInput:kPROOF_GETTREEHEADER", "Done");
1957  } else {
1959  answ << TString("Failed") << (TObject *)0;
1960  fSocket->Send(answ);
1961  rc = -1;
1962  }
1963  break;
1964 
1965  case kPROOF_GETOUTPUTLIST:
1966  { PDB(kGlobal, 1) Info("HandleSocketInput:kPROOF_GETOUTPUTLIST", "Enter");
1967  TList* outputList = 0;
1968  if (IsMaster()) {
1969  outputList = fProof->GetOutputList();
1970  if (!outputList)
1971  outputList = new TList();
1972  } else {
1973  outputList = new TList();
1974  if (fProof->GetPlayer()) {
1975  TList *olist = fProof->GetPlayer()->GetOutputList();
1976  TIter next(olist);
1977  TObject *o;
1978  while ( (o = next()) ) {
1979  outputList->Add(new TNamed(o->GetName(), ""));
1980  }
1981  }
1982  }
1983  outputList->SetOwner();
1985  answ << outputList;
1986  fSocket->Send(answ);
1987  delete outputList;
1988  PDB(kGlobal, 1) Info("HandleSocketInput:kPROOF_GETOUTPUTLIST", "Done");
1989  }
1990  break;
1991 
1992  case kPROOF_VALIDATE_DSET:
1993  if (all) {
1994  PDB(kGlobal, 1)
1995  Info("HandleSocketInput:kPROOF_VALIDATE_DSET", "Enter");
1996 
1997  TDSet* dset = 0;
1998  (*mess) >> dset;
1999 
2000  if (IsMaster()) fProof->ValidateDSet(dset);
2001  else dset->Validate();
2002 
2004  answ << dset;
2005  fSocket->Send(answ);
2006  delete dset;
2007  PDB(kGlobal, 1)
2008  Info("HandleSocketInput:kPROOF_VALIDATE_DSET", "Done");
2009  } else {
2010  rc = -1;
2011  }
2012  // Notify
2013  SendLogFile();
2014  break;
2015 
2016  case kPROOF_DATA_READY:
2017  if (all) {
2018  PDB(kGlobal, 1) Info("HandleSocketInput:kPROOF_DATA_READY", "Enter");
2020  if (IsMaster()) {
2021  Long64_t totalbytes = 0, bytesready = 0;
2022  Bool_t dataready = fProof->IsDataReady(totalbytes, bytesready);
2023  answ << dataready << totalbytes << bytesready;
2024  } else {
2025  Error("HandleSocketInput:kPROOF_DATA_READY",
2026  "This message should not be sent to slaves");
2027  answ << kFALSE << Long64_t(0) << Long64_t(0);
2028  }
2029  fSocket->Send(answ);
2030  PDB(kGlobal, 1) Info("HandleSocketInput:kPROOF_DATA_READY", "Done");
2031  } else {
2033  answ << kFALSE << Long64_t(0) << Long64_t(0);
2034  fSocket->Send(answ);
2035  rc = -1;
2036  }
2037  // Notify
2038  SendLogFile();
2039  break;
2040 
2041  case kPROOF_DATASETS:
2042  { Int_t dsrc = -1;
2043  if (fProtocol > 16) {
2044  dsrc = HandleDataSets(mess, pslb);
2045  } else {
2046  Error("HandleSocketInput", "old client: no or incompatible dataset support");
2047  }
2048  SendLogFile(dsrc);
2049  }
2050  break;
2051 
2052  case kPROOF_SUBMERGER:
2053  { HandleSubmerger(mess);
2054  }
2055  break;
2056 
2057  case kPROOF_LIB_INC_PATH:
2058  if (all) {
2059  lirc = HandleLibIncPath(mess);
2060  } else {
2061  rc = -1;
2062  }
2063  // Notify the client
2064  if (lirc > 0) SendLogFile();
2065  break;
2066 
2067  case kPROOF_REALTIMELOG:
2068  { Bool_t on;
2069  (*mess) >> on;
2070  PDB(kGlobal, 1)
2071  Info("HandleSocketInput:kPROOF_REALTIMELOG",
2072  "setting real-time logging %s", (on ? "ON" : "OFF"));
2073  fRealTimeLog = on;
2074  // Forward the request to lower levels
2075  if (IsMaster())
2076  fProof->SetRealTimeLog(on);
2077  }
2078  break;
2079 
2080  case kPROOF_FORK:
2081  if (all) {
2082  HandleFork(mess);
2083  LogToMaster();
2084  } else {
2085  rc = -1;
2086  }
2087  SendLogFile();
2088  break;
2089 
2090  case kPROOF_STARTPROCESS:
2091  if (all) {
2092  // This message resumes the session; should not come during processing.
2093 
2094  if (WaitingQueries() == 0) {
2095  Error("HandleSocketInput", "no queries enqueued");
2096  break;
2097  }
2098 
2099  // Similar to handle process
2100  // get the list of workers and start them
2101  TList *workerList = (fProof->UseDynamicStartup()) ? new TList : (TList *)0;
2102  Int_t pc = 0;
2103  EQueryAction retVal = GetWorkers(workerList, pc, kTRUE);
2104 
2105  if (retVal == TProofServ::kQueryOK) {
2106  Int_t ret = 0;
2107  if (workerList && (ret = fProof->AddWorkers(workerList)) < 0) {
2108  Error("HandleSocketInput", "adding a list of worker nodes returned: %d", ret);
2109  } else {
2110  ProcessNext(pslb);
2111  // Set idle
2112  SetIdle(kTRUE);
2113  // Signal the client that we are idle
2115  Bool_t waiting = (WaitingQueries() > 0) ? kTRUE : kFALSE;
2116  m << waiting;
2117  fSocket->Send(m);
2118  }
2119  } else {
2120  if (retVal == TProofServ::kQueryStop) {
2121  Error("HandleSocketInput", "error getting list of worker nodes");
2122  } else if (retVal != TProofServ::kQueryEnqueued) {
2123  Warning("HandleSocketInput", "query was re-queued!");
2124  } else {
2125  Error("HandleSocketInput", "unexpected answer: %d", retVal);
2126  break;
2127  }
2128  }
2129 
2130  }
2131  break;
2132 
2133  case kPROOF_GOASYNC:
2134  { // The client requested to switch to asynchronous mode:
2135  // communicate the sequential number of the running query for later
2136  // identification, if any
2137  if (!IsIdle() && fPlayer) {
2138  // Get query currently being processed
2141  m << pq->GetSeqNum() << kFALSE;
2142  fSocket->Send(m);
2143  } else {
2144  // Idle or undefined: nothing to do; ignore
2145  SendAsynMessage("Processing request to go asynchronous:"
2146  " idle or undefined player - ignoring");
2147  }
2148  }
2149  break;
2150 
2151  case kPROOF_ECHO:
2152  { // Echo request: an object has been sent along. If the object is a
2153  // string, it is simply echoed back to the client from the master
2154  // and each worker. Elsewhere, the output of TObject::Print() is
2155  // sent. Received object is disposed after usage.
2156 
2157  TObject *obj = mess->ReadObject(0x0); // class type ignored
2158 
2159  if (IsMaster()) {
2160  // We are on master
2161  // dbTODO: forward on dynamic startup when wrks are up
2162  if (IsParallel() && fProof && !fProof->UseDynamicStartup()) {
2163  fProof->Echo(obj); // forward to lower layer
2164  }
2165  }
2166 
2167  TMessage rmsg(kPROOF_MESSAGE);
2168  TString smsg;
2169 
2170  if (obj->InheritsFrom(TObjString::Class())) {
2171  // It's a string: echo it
2172  smsg.Form("Echo response from %s:%s: %s",
2173  gSystem->HostName(), GetOrdinal(),
2174  ((TObjString *)obj)->String().Data());
2175  }
2176  else {
2177  // Not a string: collect Print() output and send it
2178 
2179  // Output to tempfile
2180  TString tmpfn = "echo-out-";
2181  FILE *tf = gSystem->TempFileName(tmpfn, fDataDir);
2182  if (!tf || (gSystem->RedirectOutput(tmpfn.Data()) == -1)) {
2183  Error("HandleSocketInput", "Can't redirect output");
2184  if (tf) {
2185  fclose(tf);
2186  gSystem->Unlink(tmpfn);
2187  }
2188  rc = -1;
2189  delete obj;
2190  break;
2191  }
2192  //cout << obj->ClassName() << endl;
2193  obj->Print();
2194  gSystem->RedirectOutput(0x0); // restore
2195  fclose(tf);
2196 
2197  // Read file back and send it via message
2198  smsg.Form("*** Echo response from %s:%s ***\n",
2199  gSystem->HostName(), GetOrdinal());
2200  TMacro *fr = new TMacro();
2201  fr->ReadFile(tmpfn);
2202  TIter nextLine(fr->GetListOfLines());
2203  TObjString *line;
2204  while (( line = (TObjString *)nextLine() )) {
2205  smsg.Append( line->String() );
2206  }
2207 
2208  // Close the reader (TMacro) and remove file
2209  delete fr;
2210  gSystem->Unlink(tmpfn);
2211  }
2212 
2213  // Send message and dispose object
2214  rmsg << smsg;
2215  GetSocket()->Send(rmsg);
2216  delete obj;
2217  }
2218  break;
2219 
2220  default:
2221  Error("HandleSocketInput", "unknown command %d", what);
2222  rc = -2;
2223  break;
2224  }
2225 
2226  fRealTime += (Float_t)timer.RealTime();
2227  fCpuTime += (Float_t)timer.CpuTime();
2228 
2229  if (!(slb.IsNull()) || fgLogToSysLog > 1) {
2230  TString s;
2231  s.Form("%s %d %.3f %.3f %s", fgSysLogEntity.Data(),
2232  what, timer.RealTime(), timer.CpuTime(), slb.Data());
2233  gSystem->Syslog(kLogNotice, s.Data());
2234  }
2235 
2236  // Done
2237  return rc;
2238 }
2239 
2240 ////////////////////////////////////////////////////////////////////////////////
2241 /// Accept and merge results from a set of workers
2242 
2244 {
2245  TMessage *mess = new TMessage();
2246  Int_t mergedWorkers = 0;
2247 
2248  PDB(kSubmerger, 1) Info("AcceptResults", "enter");
2249 
2250  // Overall result of this procedure
2251  Bool_t result = kTRUE;
2252 
2253  fMergingMonitor = new TMonitor();
2255 
2256  Int_t numworkers = 0;
2257  while (fMergingMonitor->GetActive() > 0 && mergedWorkers < connections) {
2258 
2259  TSocket *s = fMergingMonitor->Select();
2260  if (!s) {
2261  Info("AcceptResults", "interrupt!");
2262  result = kFALSE;
2263  break;
2264  }
2265 
2266  if (s == fMergingSocket) {
2267  // New incoming connection
2268  TSocket *sw = fMergingSocket->Accept();
2269  if (sw && sw != (TSocket *)(-1)) {
2270  fMergingMonitor->Add(sw);
2271 
2272  PDB(kSubmerger, 2)
2273  Info("AcceptResults", "connection from a worker accepted on merger %s ",
2274  fOrdinal.Data());
2275  // All assigned workers are connected
2276  if (++numworkers >= connections)
2278  } else {
2279  PDB(kSubmerger, 1)
2280  Info("AcceptResults", "spurious signal found of merging socket");
2281  }
2282  } else {
2283  if (s->Recv(mess) < 0) {
2284  Error("AcceptResults", "problems receiving message");
2285  continue;
2286  }
2287  PDB(kSubmerger, 2)
2288  Info("AcceptResults", "message received: %d ", (mess ? mess->What() : 0));
2289  if (!mess) {
2290  Error("AcceptResults", "message received: %p ", mess);
2291  continue;
2292  }
2293  Int_t type = 0;
2294 
2295  // Read output objec(s) from the received message
2296  while ((mess->BufferSize() > mess->Length())) {
2297  (*mess) >> type;
2298 
2299  PDB(kSubmerger, 2) Info("AcceptResults", " type %d ", type);
2300  if (type == 2) {
2301  mergedWorkers++;
2302  PDB(kSubmerger, 2)
2303  Info("AcceptResults",
2304  "a new worker has been mergerd. Total merged workers: %d",
2305  mergedWorkers);
2306  }
2307  TObject *o = mess->ReadObject(TObject::Class());
2308  if (mergerPlayer->AddOutputObject(o) == 1) {
2309  // Remove the object if it has been merged
2310  PDB(kSubmerger, 2) Info("AcceptResults", "removing %p (has been merged)", o);
2311  SafeDelete(o);
2312  } else
2313  PDB(kSubmerger, 2) Info("AcceptResults", "%p not merged yet", o);
2314  }
2315  }
2316  }
2318 
2320  Int_t size = sockets->GetSize();
2321  for (Int_t i =0; i< size; ++i){
2322  ((TSocket*)(sockets->At(i)))->Close();
2323  PDB(kSubmerger, 2) Info("AcceptResults", "closing socket");
2324  delete ((TSocket*)(sockets->At(i)));
2325  }
2326 
2329 
2330  PDB(kSubmerger, 2) Info("AcceptResults", "exit: %d", result);
2331  return result;
2332 }
2333 
2334 ////////////////////////////////////////////////////////////////////////////////
2335 /// Handle Out-Of-Band data sent by the master or client.
2336 
2338 {
2339  char oob_byte;
2340  Int_t n, nch, wasted = 0;
2341 
2342  const Int_t kBufSize = 1024;
2343  char waste[kBufSize];
2344 
2345  // Real-time notification of messages
2347 
2348  PDB(kGlobal, 5)
2349  Info("HandleUrgentData", "handling oob...");
2350 
2351  // Receive the OOB byte
2352  while ((n = fSocket->RecvRaw(&oob_byte, 1, kOob)) < 0) {
2353  if (n == -2) { // EWOULDBLOCK
2354  //
2355  // The OOB data has not yet arrived: flush the input stream
2356  //
2357  // In some systems (Solaris) regular recv() does not return upon
2358  // receipt of the oob byte, which makes the below call to recv()
2359  // block indefinitely if there are no other data in the queue.
2360  // FIONREAD ioctl can be used to check if there are actually any
2361  // data to be flushed. If not, wait for a while for the oob byte
2362  // to arrive and try to read it again.
2363  //
2365  if (nch == 0) {
2366  gSystem->Sleep(1000);
2367  continue;
2368  }
2369 
2370  if (nch > kBufSize) nch = kBufSize;
2371  n = fSocket->RecvRaw(waste, nch);
2372  if (n <= 0) {
2373  Error("HandleUrgentData", "error receiving waste");
2374  break;
2375  }
2376  wasted = 1;
2377  } else {
2378  Error("HandleUrgentData", "error receiving OOB");
2379  return;
2380  }
2381  }
2382 
2383  PDB(kGlobal, 5)
2384  Info("HandleUrgentData", "got OOB byte: %d\n", oob_byte);
2385 
2386  if (fProof) fProof->SetActive();
2387 
2388  switch (oob_byte) {
2389 
2391  Info("HandleUrgentData", "*** Hard Interrupt");
2392 
2393  // If master server, propagate interrupt to slaves
2394  if (IsMaster())
2396 
2397  // Flush input socket
2398  while (1) {
2399  Int_t atmark;
2400 
2401  fSocket->GetOption(kAtMark, atmark);
2402 
2403  if (atmark) {
2404  // Send the OOB byte back so that the client knows where
2405  // to stop flushing its input stream of obsolete messages
2406  n = fSocket->SendRaw(&oob_byte, 1, kOob);
2407  if (n <= 0)
2408  Error("HandleUrgentData", "error sending OOB");
2409  break;
2410  }
2411 
2412  // find out number of bytes to read before atmark
2414  if (nch == 0) {
2415  gSystem->Sleep(1000);
2416  continue;
2417  }
2418 
2419  if (nch > kBufSize) nch = kBufSize;
2420  n = fSocket->RecvRaw(waste, nch);
2421  if (n <= 0) {
2422  Error("HandleUrgentData", "error receiving waste (2)");
2423  break;
2424  }
2425  }
2426 
2427  SendLogFile();
2428 
2429  break;
2430 
2432  Info("HandleUrgentData", "Soft Interrupt");
2433 
2434  // If master server, propagate interrupt to slaves
2435  if (IsMaster())
2437 
2438  if (wasted) {
2439  Error("HandleUrgentData", "soft interrupt flushed stream");
2440  break;
2441  }
2442 
2443  Interrupt();
2444 
2445  SendLogFile();
2446 
2447  break;
2448 
2450  Info("HandleUrgentData", "Shutdown Interrupt");
2451 
2452  // If master server, propagate interrupt to slaves
2453  if (IsMaster())
2455 
2456  Terminate(0);
2457 
2458  break;
2459 
2460  default:
2461  Error("HandleUrgentData", "unexpected OOB byte");
2462  break;
2463  }
2464 
2465  if (fProof) fProof->SetActive(kFALSE);
2466 }
2467 
2468 ////////////////////////////////////////////////////////////////////////////////
2469 /// Called when the client is not alive anymore (i.e. when kKeepAlive
2470 /// has failed).
2471 
2473 {
2474  // Real-time notification of messages
2476 
2477  if (IsMaster()) {
2478  // Check if we are here because client is closed. Try to ping client,
2479  // if that works it we are here because some slave died
2480  if (fSocket->Send(kPROOF_PING | kMESS_ACK) < 0) {
2481  Info("HandleSigPipe", "keepAlive probe failed");
2482  // Tell slaves we are going to close since there is no client anymore
2483 
2484  fProof->SetActive();
2487  Terminate(0);
2488  }
2489  } else {
2490  Info("HandleSigPipe", "keepAlive probe failed");
2491  Terminate(0); // will not return from here....
2492  }
2493 }
2494 
2495 ////////////////////////////////////////////////////////////////////////////////
2496 /// True if in parallel mode.
2497 
2499 {
2500  if (IsMaster() && fProof)
2501  return fProof->IsParallel() || fProof->UseDynamicStartup() ;
2502 
2503  // false in case we are a slave
2504  return kFALSE;
2505 }
2506 
2507 ////////////////////////////////////////////////////////////////////////////////
2508 /// Print status of slave server.
2509 
2510 void TProofServ::Print(Option_t *option) const
2511 {
2512  if (IsMaster() && fProof)
2513  fProof->Print(option);
2514  else
2515  Printf("This is worker %s", gSystem->HostName());
2516 }
2517 
2518 ////////////////////////////////////////////////////////////////////////////////
2519 /// Redirect stdout to a log file. This log file will be flushed to the
2520 /// client or master after each command.
2521 
2522 void TProofServ::RedirectOutput(const char *dir, const char *mode)
2523 {
2524  char logfile[512];
2525 
2526  TString sdir = (dir && strlen(dir) > 0) ? dir : fSessionDir.Data();
2527  if (IsMaster()) {
2528  snprintf(logfile, 512, "%s/master-%s.log", sdir.Data(), fOrdinal.Data());
2529  } else {
2530  snprintf(logfile, 512, "%s/worker-%s.log", sdir.Data(), fOrdinal.Data());
2531  }
2532 
2533  if ((freopen(logfile, mode, stdout)) == 0)
2534  SysError("RedirectOutput", "could not freopen stdout (%s)", logfile);
2535 
2536  if ((dup2(fileno(stdout), fileno(stderr))) < 0)
2537  SysError("RedirectOutput", "could not redirect stderr");
2538 
2539  if ((fLogFile = fopen(logfile, "r")) == 0)
2540  SysError("RedirectOutput", "could not open logfile '%s'", logfile);
2541 
2542  // from this point on stdout and stderr are properly redirected
2543  if (fProtocol < 4 && fWorkDir != TString::Format("~/%s", kPROOF_WorkDir)) {
2544  Warning("RedirectOutput", "no way to tell master (or client) where"
2545  " to upload packages");
2546  }
2547 }
2548 
2549 ////////////////////////////////////////////////////////////////////////////////
2550 /// Reset PROOF environment to be ready for execution of next command.
2551 
2552 void TProofServ::Reset(const char *dir)
2553 {
2554  // First go to new directory. Check first that we got a reasonable path;
2555  // in PROOF-Lite it may not be the case
2556  TString dd(dir);
2557  if (!dd.BeginsWith("proofserv")) {
2558  Int_t ic = dd.Index(":");
2559  if (ic != kNPOS)
2560  dd.Replace(0, ic, "proofserv");
2561  }
2562  gDirectory->cd(dd.Data());
2563 
2564  // Clear interpreter environment.
2565  gROOT->Reset();
2566 
2567  // Make sure current directory is empty (don't delete anything when
2568  // we happen to be in the ROOT memory only directory!?)
2569  if (gDirectory != gROOT) {
2570  gDirectory->Delete();
2571  }
2572 
2573  if (IsMaster()) fProof->SendCurrentState();
2574 }
2575 
2576 ////////////////////////////////////////////////////////////////////////////////
2577 /// Receive a file, either sent by a client or a master server.
2578 /// If bin is true it is a binary file, other wise it is an ASCII
2579 /// file and we need to check for Windows \r tokens. Returns -1 in
2580 /// case of error, 0 otherwise.
2581 
2583 {
2584  if (size <= 0) return 0;
2585 
2586  // open file, overwrite already existing file
2587  Int_t fd = open(file, O_CREAT | O_TRUNC | O_WRONLY, 0600);
2588  if (fd < 0) {
2589  SysError("ReceiveFile", "error opening file %s", file);
2590  return -1;
2591  }
2592 
2593  const Int_t kMAXBUF = 16384; //32768 //16384 //65536;
2594  char buf[kMAXBUF], cpy[kMAXBUF];
2595 
2596  Int_t left, r;
2597  Long64_t filesize = 0;
2598 
2599  while (filesize < size) {
2600  left = Int_t(size - filesize);
2601  if (left > kMAXBUF)
2602  left = kMAXBUF;
2603  r = fSocket->RecvRaw(&buf, left);
2604  if (r > 0) {
2605  char *p = buf;
2606 
2607  filesize += r;
2608  while (r) {
2609  Int_t w;
2610 
2611  if (!bin) {
2612  Int_t k = 0, i = 0, j = 0;
2613  char *q;
2614  while (i < r) {
2615  if (p[i] == '\r') {
2616  i++;
2617  k++;
2618  }
2619  cpy[j++] = buf[i++];
2620  }
2621  q = cpy;
2622  r -= k;
2623  w = write(fd, q, r);
2624  } else {
2625  w = write(fd, p, r);
2626  }
2627 
2628  if (w < 0) {
2629  SysError("ReceiveFile", "error writing to file %s", file);
2630  close(fd);
2631  return -1;
2632  }
2633  r -= w;
2634  p += w;
2635  }
2636  } else if (r < 0) {
2637  Error("ReceiveFile", "error during receiving file %s", file);
2638  close(fd);
2639  return -1;
2640  }
2641  }
2642 
2643  close(fd);
2644 
2645  if (chmod(file, 0644) != 0)
2646  Warning("ReceiveFile", "error setting mode 0644 on file %s", file);
2647 
2648  return 0;
2649 }
2650 
2651 ////////////////////////////////////////////////////////////////////////////////
2652 /// Main server eventloop.
2653 
2655 {
2656  // Setup the server
2657  if (CreateServer() == 0) {
2658 
2659  // Run the main event loop
2660  TApplication::Run(retrn);
2661  }
2662 }
2663 
2664 ////////////////////////////////////////////////////////////////////////////////
2665 /// Send log file to master.
2666 /// If start > -1 send only bytes in the range from start to end,
2667 /// if end <= start send everything from start.
2668 
2669 void TProofServ::SendLogFile(Int_t status, Int_t start, Int_t end)
2670 {
2671  // Determine the number of bytes left to be read from the log file.
2672  fflush(stdout);
2673 
2674  // On workers we do not send the logs to masters (to avoid duplication of
2675  // text) unless asked explicitly, e.g. after an Exec(...) request.
2676  if (!IsMaster()) {
2677  if (!fSendLogToMaster) {
2678  FlushLogFile();
2679  } else {
2680  // Decide case by case
2682  }
2683  }
2684 
2685  off_t ltot=0, lnow=0;
2686  Int_t left = -1;
2687  Bool_t adhoc = kFALSE;
2688 
2689  if (fLogFileDes > -1) {
2690  ltot = lseek(fileno(stdout), (off_t) 0, SEEK_END);
2691  lnow = lseek(fLogFileDes, (off_t) 0, SEEK_CUR);
2692 
2693  if (ltot >= 0 && lnow >= 0) {
2694  if (start > -1) {
2695  lseek(fLogFileDes, (off_t) start, SEEK_SET);
2696  if (end <= start || end > ltot)
2697  end = ltot;
2698  left = (Int_t)(end - start);
2699  if (end < ltot)
2700  left++;
2701  adhoc = kTRUE;
2702  } else {
2703  left = (Int_t)(ltot - lnow);
2704  }
2705  }
2706  }
2707 
2708  if (left > 0) {
2709  if (fSocket->Send(left, kPROOF_LOGFILE) < 0) {
2710  SysError("SendLogFile", "error sending kPROOF_LOGFILE");
2711  return;
2712  }
2713 
2714  const Int_t kMAXBUF = 32768; //16384 //65536;
2715  char buf[kMAXBUF];
2716  Int_t wanted = (left > kMAXBUF) ? kMAXBUF : left;
2717  Int_t len;
2718  do {
2719  while ((len = read(fLogFileDes, buf, wanted)) < 0 &&
2720  TSystem::GetErrno() == EINTR)
2722 
2723  if (len < 0) {
2724  SysError("SendLogFile", "error reading log file");
2725  break;
2726  }
2727 
2728  if (end == ltot && len == wanted)
2729  buf[len-1] = '\n';
2730 
2731  if (fSocket->SendRaw(buf, len) < 0) {
2732  SysError("SendLogFile", "error sending log file");
2733  break;
2734  }
2735 
2736  // Update counters
2737  left -= len;
2738  wanted = (left > kMAXBUF) ? kMAXBUF : left;
2739 
2740  } while (len > 0 && left > 0);
2741  }
2742 
2743  // Restore initial position if partial send
2744  if (adhoc && lnow >=0 )
2745  lseek(fLogFileDes, lnow, SEEK_SET);
2746 
2747  TMessage mess(kPROOF_LOGDONE);
2748  if (IsMaster())
2749  mess << status << (fProof ? fProof->GetParallel() : 0);
2750  else
2751  mess << status << (Int_t) 1;
2752 
2753  if (fSocket->Send(mess) < 0) {
2754  SysError("SendLogFile", "error sending kPROOF_LOGDONE");
2755  return;
2756  }
2757 
2758  PDB(kGlobal, 1) Info("SendLogFile", "kPROOF_LOGDONE sent");
2759 }
2760 
2761 ////////////////////////////////////////////////////////////////////////////////
2762 /// Send statistics of slave server to master or client.
2763 
2765 {
2766  Long64_t bytesread = TFile::GetFileBytesRead();
2767  Float_t cputime = fCpuTime, realtime = fRealTime;
2768  if (IsMaster()) {
2769  bytesread = fProof->GetBytesRead();
2770  cputime = fProof->GetCpuTime();
2771  }
2772 
2773  TMessage mess(kPROOF_GETSTATS);
2774  TString workdir = gSystem->WorkingDirectory(); // expect TString on other side
2775  mess << bytesread << realtime << cputime << workdir;
2776  if (fProtocol >= 4) mess << TString(gProofServ->GetWorkDir());
2777  mess << TString(gProofServ->GetImage());
2778  fSocket->Send(mess);
2779 }
2780 
2781 ////////////////////////////////////////////////////////////////////////////////
2782 /// Send number of parallel nodes to master or client.
2783 
2785 {
2786  Int_t nparallel = 0;
2787  if (IsMaster()) {
2788  PDB(kGlobal, 2)
2789  Info("SendParallel", "Will invoke AskParallel()");
2790  fProof->AskParallel();
2791  PDB(kGlobal, 2)
2792  Info("SendParallel", "Will invoke GetParallel()");
2793  nparallel = fProof->GetParallel();
2794  } else {
2795  nparallel = 1;
2796  }
2797 
2799  mess << nparallel << async;
2800  fSocket->Send(mess);
2801 }
2802 
2803 ////////////////////////////////////////////////////////////////////////////////
2804 /// Print the ProofServ logo on standard output.
2805 /// Return 0 on success, -1 on failure
2806 
2808 {
2809  char str[512];
2810 
2811  if (IsMaster()) {
2812  snprintf(str, 512, "**** Welcome to the PROOF server @ %s ****", gSystem->HostName());
2813  } else {
2814  snprintf(str, 512, "**** PROOF slave server @ %s started ****", gSystem->HostName());
2815  }
2816 
2817  if (fSocket->Send(str) != 1+static_cast<Int_t>(strlen(str))) {
2818  Error("Setup", "failed to send proof server startup message");
2819  return -1;
2820  }
2821 
2822  // exchange protocol level between client and master and between
2823  // master and slave
2824  Int_t what;
2825  if (fSocket->Recv(fProtocol, what) != 2*sizeof(Int_t)) {
2826  Error("Setup", "failed to receive remote proof protocol");
2827  return -1;
2828  }
2829  if (fSocket->Send(kPROOF_Protocol, kROOTD_PROTOCOL) != 2*sizeof(Int_t)) {
2830  Error("Setup", "failed to send local proof protocol");
2831  return -1;
2832  }
2833 
2834  // If old version, setup authentication related stuff
2835  if (fProtocol < 5) {
2836  TString wconf;
2837  if (OldAuthSetup(wconf) != 0) {
2838  Error("Setup", "OldAuthSetup: failed to setup authentication");
2839  return -1;
2840  }
2841  if (IsMaster()) {
2842  fConfFile = wconf;
2843  fWorkDir.Form("~/%s", kPROOF_WorkDir);
2844  } else {
2845  if (fProtocol < 4) {
2846  fWorkDir.Form("~/%s", kPROOF_WorkDir);
2847  } else {
2848  fWorkDir = wconf;
2849  if (fWorkDir.IsNull()) fWorkDir.Form("~/%s", kPROOF_WorkDir);
2850  }
2851  }
2852  } else {
2853 
2854  // Receive some useful information
2855  TMessage *mess;
2856  if ((fSocket->Recv(mess) <= 0) || !mess) {
2857  Error("Setup", "failed to receive ordinal and config info");
2858  return -1;
2859  }
2860  if (IsMaster()) {
2861  (*mess) >> fUser >> fOrdinal >> fConfFile;
2862  fWorkDir = gEnv->GetValue("ProofServ.Sandbox", TString::Format("~/%s", kPROOF_WorkDir));
2863  } else {
2864  (*mess) >> fUser >> fOrdinal >> fWorkDir;
2865  if (fWorkDir.IsNull())
2866  fWorkDir = gEnv->GetValue("ProofServ.Sandbox", TString::Format("~/%s", kPROOF_WorkDir));
2867  }
2868  // Set the correct prefix
2869  if (fOrdinal != "-1")
2870  fPrefix += fOrdinal;
2872  delete mess;
2873  }
2874 
2875  if (IsMaster()) {
2876 
2877  // strip off any prooftype directives
2878  TString conffile = fConfFile;
2879  conffile.Remove(0, 1 + conffile.Index(":"));
2880 
2881  // parse config file to find working directory
2882  TProofResourcesStatic resources(fConfDir, conffile);
2883  if (resources.IsValid()) {
2884  if (resources.GetMaster()) {
2885  TString tmpWorkDir = resources.GetMaster()->GetWorkDir();
2886  if (tmpWorkDir != "")
2887  fWorkDir = tmpWorkDir;
2888  }
2889  } else {
2890  Info("Setup", "invalid config file %s (missing or unreadable",
2891  resources.GetFileName().Data());
2892  }
2893  }
2894 
2895  // Set $HOME and $PATH. The HOME directory was already set to the
2896  // user's home directory by proofd.
2897  gSystem->Setenv("HOME", gSystem->HomeDirectory());
2898 
2899  // Add user name in case of non default workdir
2900  if (fWorkDir.BeginsWith("/") &&
2901  !fWorkDir.BeginsWith(gSystem->HomeDirectory())) {
2902  if (!fWorkDir.EndsWith("/"))
2903  fWorkDir += "/";
2905  if (u) {
2906  fWorkDir += u->fUser;
2907  delete u;
2908  }
2909  }
2910 
2911  // Goto to the main PROOF working directory
2912  char *workdir = gSystem->ExpandPathName(fWorkDir.Data());
2913  fWorkDir = workdir;
2914  delete [] workdir;
2915  if (gProofDebugLevel > 0)
2916  Info("Setup", "working directory set to %s", fWorkDir.Data());
2917 
2918  // host first name
2919  TString host = gSystem->HostName();
2920  if (host.Index(".") != kNPOS)
2921  host.Remove(host.Index("."));
2922 
2923  // Session tag
2924  fSessionTag.Form("%s-%s-%ld-%d", fOrdinal.Data(), host.Data(),
2927 
2928  // create session directory and make it the working directory
2930  if (IsMaster())
2931  fSessionDir += "/master-";
2932  else
2933  fSessionDir += "/slave-";
2935 
2936  // Common setup
2937  if (SetupCommon() != 0) {
2938  Error("Setup", "common setup failed");
2939  return -1;
2940  }
2941 
2942  // Incoming OOB should generate a SIGURG
2944 
2945  // Send packets off immediately to reduce latency
2946  fSocket->SetOption(kNoDelay, 1);
2947 
2948  // Check every two hours if client is still alive
2950 
2951  // Done
2952  return 0;
2953 }
2954 
2955 ////////////////////////////////////////////////////////////////////////////////
2956 /// Common part (between TProofServ and TXProofServ) of the setup phase.
2957 /// Return 0 on success, -1 on error
2958 
2960 {
2961  // deny write access for group and world
2962  gSystem->Umask(022);
2963 
2964 #ifdef R__UNIX
2965  // Add bindir to PATH
2966  TString path(gSystem->Getenv("PATH"));
2967  TString bindir;
2968 # ifdef ROOTBINDIR
2969  bindir = ROOTBINDIR;
2970 # else
2971  bindir = gSystem->Getenv("ROOTSYS");
2972  if (!bindir.IsNull()) bindir += "/bin";
2973 # endif
2974  // Augment PATH, if required
2975  // ^<compiler>, <compiler>, ^<sysbin>, <sysbin>
2976  TString paths = gEnv->GetValue("ProofServ.BinPaths", "");
2977  if (paths.Length() > 0) {
2978  Int_t icomp = 0;
2979  if (paths.Contains("^<compiler>"))
2980  icomp = 1;
2981  else if (paths.Contains("<compiler>"))
2982  icomp = -1;
2983  if (icomp != 0) {
2984 # ifdef COMPILER
2985  TString compiler = COMPILER;
2986  if (compiler.Index("is ") != kNPOS)
2987  compiler.Remove(0, compiler.Index("is ") + 3);
2988  compiler = gSystem->DirName(compiler);
2989  if (icomp == 1) {
2990  if (!bindir.IsNull()) bindir += ":";
2991  bindir += compiler;
2992  } else if (icomp == -1) {
2993  if (!path.IsNull()) path += ":";
2994  path += compiler;
2995  }
2996 #endif
2997  }
2998  Int_t isysb = 0;
2999  if (paths.Contains("^<sysbin>"))
3000  isysb = 1;
3001  else if (paths.Contains("<sysbin>"))
3002  isysb = -1;
3003  if (isysb != 0) {
3004  if (isysb == 1) {
3005  if (!bindir.IsNull()) bindir += ":";
3006  bindir += "/bin:/usr/bin:/usr/local/bin";
3007  } else if (isysb == -1) {
3008  if (!path.IsNull()) path += ":";
3009  path += "/bin:/usr/bin:/usr/local/bin";
3010  }
3011  }
3012  }
3013  // Final insert
3014  if (!bindir.IsNull()) bindir += ":";
3015  path.Insert(0, bindir);
3016  gSystem->Setenv("PATH", path);
3017 #endif
3018 
3021  if (!gSystem->ChangeDirectory(fWorkDir)) {
3022  Error("SetupCommon", "can not change to PROOF directory %s",
3023  fWorkDir.Data());
3024  return -1;
3025  }
3026  } else {
3027  if (!gSystem->ChangeDirectory(fWorkDir)) {
3030  if (!gSystem->ChangeDirectory(fWorkDir)) {
3031  Error("SetupCommon", "can not change to PROOF directory %s",
3032  fWorkDir.Data());
3033  return -1;
3034  }
3035  }
3036  }
3037 
3038  // Set group
3039  fGroup = gEnv->GetValue("ProofServ.ProofGroup", "default");
3040 
3041  // Check and make sure "cache" directory exists
3042  fCacheDir = gEnv->GetValue("ProofServ.CacheDir",
3043  TString::Format("%s/%s", fWorkDir.Data(), kPROOF_CacheDir));
3047  if (gProofDebugLevel > 0)
3048  Info("SetupCommon", "cache directory set to %s", fCacheDir.Data());
3049  fCacheLock =
3050  new TProofLockPath(TString::Format("%s/%s%s",
3052  TString(fCacheDir).ReplaceAll("/","%").Data()));
3053  // Make also sure the cache path is in the macro path
3055 
3056  // Check and make sure "packages" directory exists
3057  TString packdir = gEnv->GetValue("ProofServ.PackageDir",
3058  TString::Format("%s/%s", fWorkDir.Data(), kPROOF_PackDir));
3059  ResolveKeywords(packdir);
3060  if (gSystem->AccessPathName(packdir))
3061  gSystem->mkdir(packdir, kTRUE);
3062  fPackMgr = new TPackMgr(packdir);
3064  // Notification message
3065  TString noth;
3066  const char *k = (IsMaster()) ? "Mst" : "Wrk";
3067  noth.Form("%s-%s", k, fOrdinal.Data());
3068  fPackMgr->SetPrefix(noth.Data());
3069  if (gProofDebugLevel > 0)
3070  Info("SetupCommon", "package directory set to %s", packdir.Data());
3071 
3072  // Check and make sure "data" directory exists
3073  fDataDir = gEnv->GetValue("ProofServ.DataDir","");
3074  Ssiz_t isep = kNPOS;
3075  if (fDataDir.IsNull()) {
3076  // Use default
3077  fDataDir.Form("%s/%s/<ord>/<stag>", fWorkDir.Data(), kPROOF_DataDir);
3078  } else if ((isep = fDataDir.Last(' ')) != kNPOS) {
3079  fDataDirOpts = fDataDir(isep + 1, fDataDir.Length());
3080  fDataDir.Remove(isep);
3081  }
3082  ResolveKeywords(fDataDir);
3083  if (gSystem->AccessPathName(fDataDir))
3084  if (gSystem->mkdir(fDataDir, kTRUE) != 0) {
3085  Warning("SetupCommon", "problems creating path '%s' (errno: %d)",
3086  fDataDir.Data(), TSystem::GetErrno());
3087  }
3088  if (gProofDebugLevel > 0)
3089  Info("SetupCommon", "data directory set to %s", fDataDir.Data());
3090 
3091  // Check and apply possible options
3092  // (see http://root.cern.ch/drupal/content/configuration-reference-guide#datadir)
3093  TString dataDirOpts = gEnv->GetValue("ProofServ.DataDirOpts","");
3094  if (!dataDirOpts.IsNull()) {
3095  // Do they apply to this server type
3096  Bool_t doit = kTRUE;
3097  if ((IsMaster() && !dataDirOpts.Contains("M")) ||
3098  (!IsMaster() && !dataDirOpts.Contains("W"))) doit = kFALSE;
3099  if (doit) {
3100  // Get the wanted mode
3101  UInt_t m = 0755;
3102  if (dataDirOpts.Contains("g")) m = 0775;
3103  if (dataDirOpts.Contains("a") || dataDirOpts.Contains("o")) m = 0777;
3104  if (gProofDebugLevel > 0)
3105  Info("SetupCommon", "requested mode for data directories is '%o'", m);
3106  // Loop over paths
3107  FileStat_t st;
3108  TString p, subp;
3109  Int_t from = 0;
3110  if (fDataDir.BeginsWith("/")) p = "/";
3111  while (fDataDir.Tokenize(subp, from, "/")) {
3112  if (subp.IsNull()) continue;
3113  p += subp;
3114  if (gSystem->GetPathInfo(p, st) == 0) {
3115  if (st.fUid == (Int_t) gSystem->GetUid() && st.fGid == (Int_t) gSystem->GetGid()) {
3116  if (gSystem->Chmod(p.Data(), m) != 0) {
3117  Warning("SetupCommon", "problems setting mode '%o' on path '%s' (errno: %d)",
3118  m, p.Data(), TSystem::GetErrno());
3119  break;
3120  }
3121  }
3122  p += "/";
3123  } else {
3124  Warning("SetupCommon", "problems stat-ing path '%s' (errno: %d; datadir: %s)",
3125  p.Data(), TSystem::GetErrno(), fDataDir.Data());
3126  break;
3127  }
3128  }
3129  }
3130  }
3131 
3132  // List of directories where to look for global packages
3133  TString globpack = gEnv->GetValue("Proof.GlobalPackageDirs","");
3134 
3135  ResolveKeywords(globpack);
3136  Int_t nglb = TPackMgr::RegisterGlobalPath(globpack);
3137  Info("SetupCommon", " %d global package directories registered", nglb);
3138  FlushLogFile();
3139 
3140  // Check the session dir
3141  if (fSessionDir != gSystem->WorkingDirectory()) {
3146  Error("SetupCommon", "can not change to working directory '%s'",
3147  fSessionDir.Data());
3148  return -1;
3149  }
3150  }
3151  gSystem->Setenv("PROOF_SANDBOX", fSessionDir);
3152  if (gProofDebugLevel > 0)
3153  Info("SetupCommon", "session dir is '%s'", fSessionDir.Data());
3154 
3155  // On masters, check and make sure that "queries" and "datasets"
3156  // directories exist
3157  if (IsMaster()) {
3158 
3159  // Make sure that the 'queries' dir exist
3160  fQueryDir = fWorkDir;
3161  fQueryDir += TString("/") + kPROOF_QueryDir;
3165  fQueryDir += TString("/session-") + fTopSessionTag;
3168  if (gProofDebugLevel > 0)
3169  Info("SetupCommon", "queries dir is %s", fQueryDir.Data());
3170 
3171  // Create 'queries' locker instance and lock it
3172  fQueryLock = new TProofLockPath(TString::Format("%s/%s%s-%s",
3175  TString(fQueryDir).ReplaceAll("/","%").Data()));
3176  fQueryLock->Lock();
3177  // Create the query manager
3179  fQueryLock, 0);
3180  }
3181 
3182  // Server image
3183  fImage = gEnv->GetValue("ProofServ.Image", "");
3184 
3185  // Get the group priority
3186  if (IsMaster()) {
3187  // Send session tag to client
3189  m << fTopSessionTag << fGroup << fUser;
3190  fSocket->Send(m);
3191  // Group priority
3193  // Dataset manager instance via plug-in
3194  TPluginHandler *h = 0;
3195  TString dsms = gEnv->GetValue("Proof.DataSetManager", "");
3196  if (!dsms.IsNull()) {
3197  TString dsm;
3198  Int_t from = 0;
3199  while (dsms.Tokenize(dsm, from, ",")) {
3201  Warning("SetupCommon", "a valid dataset manager already initialized");
3202  Warning("SetupCommon", "support for multiple managers not yet available");
3203  break;
3204  }
3205  // Get plugin manager to load the appropriate TDataSetManager
3206  if (gROOT->GetPluginManager()) {
3207  // Find the appropriate handler
3208  h = gROOT->GetPluginManager()->FindHandler("TDataSetManager", dsm);
3209  if (h && h->LoadPlugin() != -1) {
3210  // make instance of the dataset manager
3211  fDataSetManager =
3212  reinterpret_cast<TDataSetManager*>(h->ExecPlugin(3, fGroup.Data(),
3213  fUser.Data(), dsm.Data()));
3214  }
3215  }
3216  }
3217  // Check the result of the dataset manager initialization
3219  Warning("SetupCommon", "dataset manager plug-in initialization failed");
3220  SendAsynMessage("TXProofServ::SetupCommon: dataset manager plug-in initialization failed");
3222  }
3223  } else {
3224  // Initialize the default dataset manager
3225  TString opts("Av:");
3226  TString dsetdir = gEnv->GetValue("ProofServ.DataSetDir", "");
3227  if (dsetdir.IsNull()) {
3228  // Use the default in the sandbox
3229  dsetdir.Form("%s/%s", fWorkDir.Data(), kPROOF_DataSetDir);
3232  opts += "Sb:";
3233  }
3234  // Find the appropriate handler
3235  if (!h) {
3236  h = gROOT->GetPluginManager()->FindHandler("TDataSetManager", "file");
3237  if (h && h->LoadPlugin() == -1) h = 0;
3238  }
3239  if (h) {
3240  // make instance of the dataset manager
3241  TString oo = TString::Format("dir:%s opt:%s", dsetdir.Data(), opts.Data());
3242  fDataSetManager = reinterpret_cast<TDataSetManager*>(h->ExecPlugin(3,
3243  fGroup.Data(), fUser.Data(), oo.Data()));
3244  }
3246  Warning("SetupCommon", "default dataset manager plug-in initialization failed");
3248  }
3249  }
3250  // Dataset manager for staging requests
3251  TString dsReqCfg = gEnv->GetValue("Proof.DataSetStagingRequests", "");
3252  if (!dsReqCfg.IsNull()) {
3253  TPMERegexp reReqDir("(^| )(dir:)?([^ ]+)( |$)");
3254 
3255  if (reReqDir.Match(dsReqCfg) == 5) {
3256  TString dsDirFmt;
3257  dsDirFmt.Form("dir:%s perms:open", reReqDir[3].Data());
3258  fDataSetStgRepo = new TDataSetManagerFile("_stage_", "_stage_",
3259  dsDirFmt);
3260  if (fDataSetStgRepo &&
3262  Warning("SetupCommon",
3263  "failed init of dataset staging requests repository");
3265  }
3266  } else {
3267  Warning("SetupCommon",
3268  "specify, with [dir:]<path>, a valid path for staging requests");
3269  }
3270  } else if (gProofDebugLevel > 0) {
3271  Warning("SetupCommon", "no repository for staging requests available");
3272  }
3273  }
3274 
3275  // Quotas
3276  TString quotas = gEnv->GetValue(TString::Format("ProofServ.UserQuotas.%s", fUser.Data()),"");
3277  if (quotas.IsNull())
3278  quotas = gEnv->GetValue(TString::Format("ProofServ.UserQuotasByGroup.%s", fGroup.Data()),"");
3279  if (quotas.IsNull())
3280  quotas = gEnv->GetValue("ProofServ.UserQuotas", "");
3281  if (!quotas.IsNull()) {
3282  // Parse it; format ("maxquerykept=10 hwmsz=800m maxsz=1g")
3283  TString tok;
3284  Ssiz_t from = 0;
3285  while (quotas.Tokenize(tok, from, " ")) {
3286  // Set max number of query results to keep
3287  if (tok.BeginsWith("maxquerykept=")) {
3288  tok.ReplaceAll("maxquerykept=","");
3289  if (tok.IsDigit())
3290  fMaxQueries = tok.Atoi();
3291  else
3292  Info("SetupCommon",
3293  "parsing 'maxquerykept' :ignoring token %s : not a digit", tok.Data());
3294  }
3295  // Set High-Water-Mark or max on the sandbox size
3296  const char *ksz[2] = {"hwmsz=", "maxsz="};
3297  for (Int_t j = 0; j < 2; j++) {
3298  if (tok.BeginsWith(ksz[j])) {
3299  tok.ReplaceAll(ksz[j],"");
3300  Long64_t fact = -1;
3301  if (!tok.IsDigit()) {
3302  // Parse (k, m, g)
3303  tok.ToLower();
3304  const char *s[3] = {"k", "m", "g"};
3305  Int_t i = 0, ki = 1024;
3306  while (fact < 0) {
3307  if (tok.EndsWith(s[i++]))
3308  fact = ki;
3309  else
3310  ki *= 1024;
3311  }
3312  tok.Remove(tok.Length()-1);
3313  }
3314  if (tok.IsDigit()) {
3315  if (j == 0)
3316  fHWMBoxSize = (fact > 0) ? tok.Atoi() * fact : tok.Atoi();
3317  else
3318  fMaxBoxSize = (fact > 0) ? tok.Atoi() * fact : tok.Atoi();
3319  } else {
3320  TString ssz(ksz[j], strlen(ksz[j])-1);
3321  Info("SetupCommon", "parsing '%s' : ignoring token %s", ssz.Data(), tok.Data());
3322  }
3323  }
3324  }
3325  }
3326  }
3327 
3328  // Apply quotas, if any
3329  if (IsMaster() && fQMgr)
3330  if (fQMgr->ApplyMaxQueries(fMaxQueries) != 0)
3331  Warning("SetupCommon", "problems applying fMaxQueries");
3332 
3333  // Send "ROOTversion|ArchCompiler" flag
3334  if (fProtocol > 12) {
3335  TString vac = gROOT->GetVersion();
3336  vac += TString::Format(":%s", gROOT->GetGitCommit());
3337  TString rtag = gEnv->GetValue("ProofServ.RootVersionTag", "");
3338  if (rtag.Length() > 0)
3339  vac += TString::Format(":%s", rtag.Data());
3342  m << vac;
3343  fSocket->Send(m);
3344  }
3345 
3346  // Set user vars in TProof
3347  TString all_vars(gSystem->Getenv("PROOF_ALLVARS"));
3348  TString name;
3349  Int_t from = 0;
3350  while (all_vars.Tokenize(name, from, ",")) {
3351  if (!name.IsNull()) {
3352  TString value = gSystem->Getenv(name);
3353  TProof::AddEnvVar(name, value);
3354  }
3355  }
3356 
3357  if (fgLogToSysLog > 0) {
3358  // Set the syslog entity (all the information is available now)
3359  if (!(fUser.IsNull()) && !(fGroup.IsNull())) {
3360  fgSysLogEntity.Form("%s:%s", fUser.Data(), fGroup.Data());
3361  } else if (!(fUser.IsNull()) && fGroup.IsNull()) {
3362  fgSysLogEntity.Form("%s:default", fUser.Data());
3363  } else if (fUser.IsNull() && !(fGroup.IsNull())) {
3364  fgSysLogEntity.Form("undef:%s", fGroup.Data());
3365  }
3366  // Log the beginning of this session
3367  TString s;
3368  s.Form("%s 0 %.3f %.3f", fgSysLogEntity.Data(), fRealTime, fCpuTime);
3369  gSystem->Syslog(kLogNotice, s.Data());
3370  }
3371 
3372  if (gProofDebugLevel > 0)
3373  Info("SetupCommon", "successfully completed");
3374 
3375  // Done
3376  return 0;
3377 }
3378 
3379 ////////////////////////////////////////////////////////////////////////////////
3380 /// Terminate the proof server.
3381 
3383 {
3384  if (fgLogToSysLog > 0) {
3385  TString s;
3386  s.Form("%s -1 %.3f %.3f %d", fgSysLogEntity.Data(), fRealTime, fCpuTime, status);
3387  gSystem->Syslog(kLogNotice, s.Data());
3388  }
3389 
3390  // Notify the memory footprint
3391  ProcInfo_t pi;
3392  if (!gSystem->GetProcInfo(&pi)){
3393  Info("Terminate", "process memory footprint: %ld/%ld kB virtual, %ld/%ld kB resident ",
3395  }
3396 
3397  // Cleanup session directory
3398  if (status == 0) {
3399  // make sure we remain in a "connected" directory
3400  gSystem->ChangeDirectory("/");
3401  // needed in case fSessionDir is on NFS ?!
3402  gSystem->MakeDirectory(fSessionDir+"/.delete");
3403  gSystem->Exec(TString::Format("%s %s", kRM, fSessionDir.Data()));
3404  }
3405 
3406  // Cleanup queries directory if empty
3407  if (IsMaster()) {
3408  if (!(fQMgr && fQMgr->Queries() && fQMgr->Queries()->GetSize())) {
3409  // make sure we remain in a "connected" directory
3410  gSystem->ChangeDirectory("/");
3411  // needed in case fQueryDir is on NFS ?!
3412  gSystem->MakeDirectory(fQueryDir+"/.delete");
3413  gSystem->Exec(TString::Format("%s %s", kRM, fQueryDir.Data()));
3414  // Remove lock file
3415  if (fQueryLock)
3417  }
3418 
3419  // Unlock the query dir owned by this session
3420  if (fQueryLock)
3421  fQueryLock->Unlock();
3422  }
3423 
3424  // Cleanup data directory if empty
3425  if (!fDataDir.IsNull() && !gSystem->AccessPathName(fDataDir, kWritePermission)) {
3426  if (UnlinkDataDir(fDataDir))
3427  Info("Terminate", "data directory '%s' has been removed", fDataDir.Data());
3428  }
3429 
3430  // Remove input handler to avoid spurious signals in socket
3431  // selection for closing activities executed upon exit()
3433  TObject *fh = 0;
3434  while ((fh = next())) {
3435  TProofServInputHandler *ih = dynamic_cast<TProofServInputHandler *>(fh);
3436  if (ih)
3438  }
3439 
3440  // Stop processing events
3441  gSystem->ExitLoop();
3442 
3443  // Exit() is called in pmain
3444 }
3445 
3446 ////////////////////////////////////////////////////////////////////////////////
3447 /// Scan recursively the datadir and unlink it if empty
3448 /// Return kTRUE if it can be unlinked, kFALSE otherwise
3449 
3451 {
3452  if (!path || strlen(path) <= 0) return kFALSE;
3453 
3454  Bool_t dorm = kTRUE;
3455  void *dirp = gSystem->OpenDirectory(path);
3456  if (dirp) {
3457  TString fpath;
3458  const char *ent = 0;
3459  while (dorm && (ent = gSystem->GetDirEntry(dirp))) {
3460  if (!strcmp(ent, ".") || !strcmp(ent, "..")) continue;
3461  fpath.Form("%s/%s", path, ent);
3462  FileStat_t st;
3463  if (gSystem->GetPathInfo(fpath, st) == 0 && R_ISDIR(st.fMode)) {
3464  dorm = UnlinkDataDir(fpath);
3465  } else {
3466  dorm = kFALSE;
3467  }
3468  }
3469  // Close the directory
3470  gSystem->FreeDirectory(dirp);
3471  } else {
3472  // Cannot open the directory
3473  dorm = kFALSE;
3474  }
3475 
3476  // Do remove, if required
3477  if (dorm && gSystem->Unlink(path) != 0)
3478  Warning("UnlinkDataDir", "data directory '%s' is empty but could not be removed", path);
3479  // done
3480  return dorm;
3481 }
3482 
3483 ////////////////////////////////////////////////////////////////////////////////
3484 /// Static function that returns kTRUE in case we are a PROOF server.
3485 
3487 {
3488  return gProofServ ? kTRUE : kFALSE;
3489 }
3490 
3491 ////////////////////////////////////////////////////////////////////////////////
3492 /// Static function returning pointer to global object gProofServ.
3493 /// Mainly for use via CINT, where the gProofServ symbol might be
3494 /// deleted from the symbol table.
3495 
3497 {
3498  return gProofServ;
3499 }
3500 
3501 ////////////////////////////////////////////////////////////////////////////////
3502 /// Setup authentication related stuff for old versions.
3503 /// Provided for backward compatibility.
3504 
3506 {
3507  OldProofServAuthSetup_t oldAuthSetupHook = 0;
3508 
3509  if (!oldAuthSetupHook) {
3510  // Load libraries needed for (server) authentication ...
3511  TString authlib = "libRootAuth";
3512  char *p = 0;
3513  // The generic one
3514  if ((p = gSystem->DynamicPathName(authlib, kTRUE))) {
3515  delete[] p;
3516  if (gSystem->Load(authlib) == -1) {
3517  Error("OldAuthSetup", "can't load %s",authlib.Data());
3518  return kFALSE;
3519  }
3520  } else {
3521  Error("OldAuthSetup", "can't locate %s",authlib.Data());
3522  return -1;
3523  }
3524  //
3525  // Locate OldProofServAuthSetup
3526  Func_t f = gSystem->DynFindSymbol(authlib,"OldProofServAuthSetup");
3527  if (f)
3528  oldAuthSetupHook = (OldProofServAuthSetup_t)(f);
3529  else {
3530  Error("OldAuthSetup", "can't find OldProofServAuthSetup");
3531  return -1;
3532  }
3533  }
3534  //
3535  // Setup
3536  return (*oldAuthSetupHook)(fSocket, IsMaster(), fProtocol,
3537  fUser, fOrdinal, conf);
3538 }
3539 
3540 ////////////////////////////////////////////////////////////////////////////////
3541 /// Create a TProofQueryResult instance for this query.
3542 
3544  const char *opt,
3545  TList *inlist, Long64_t fst,
3546  TDSet *dset, const char *selec,
3547  TObject *elist)
3548 {
3549  // Increment sequential number
3550  Int_t seqnum = -1;
3551  if (fQMgr) {
3553  seqnum = fQMgr->SeqNum();
3554  }
3555 
3556  // Locally we always use the current streamer
3557  Bool_t olds = (dset && dset->TestBit(TDSet::kWriteV3)) ? kTRUE : kFALSE;
3558  if (olds)
3559  dset->SetWriteV3(kFALSE);
3560 
3561  // Create the instance and add it to the list
3562  TProofQueryResult *pqr = new TProofQueryResult(seqnum, opt, inlist, nent,
3563  fst, dset, selec, elist);
3564  // Title is the session identifier
3566 
3567  // Restore old streamer info
3568  if (olds)
3569  dset->SetWriteV3(kTRUE);
3570 
3571  return pqr;
3572 }
3573 
3574 ////////////////////////////////////////////////////////////////////////////////
3575 /// Set query in running state.
3576 
3578 {
3579  // Record current position in the log file at start
3580  fflush(stdout);
3581  Int_t startlog = lseek(fileno(stdout), (off_t) 0, SEEK_END);
3582 
3583  // Add some header to logs
3584  Printf(" ");
3585  Info("SetQueryRunning", "starting query: %d", pq->GetSeqNum());
3586 
3587  // Build the list of loaded PAR packages
3588  TString parlist = "";
3589  fPackMgr->GetEnabledPackages(parlist);
3590 
3591  if (fProof) {
3592  // Set in running state
3593  pq->SetRunning(startlog, parlist, fProof->GetParallel());
3594 
3595  // Bytes and CPU at start (we will calculate the differential at end)
3596  pq->SetProcessInfo(pq->GetEntries(),
3598  } else {
3599  // Set in running state
3600  pq->SetRunning(startlog, parlist, -1);
3601 
3602  // Bytes and CPU at start (we will calculate the differential at end)
3603  pq->SetProcessInfo(pq->GetEntries(), float(0.), 0);
3604  }
3605 }
3606 
3607 ////////////////////////////////////////////////////////////////////////////////
3608 /// Handle archive request.
3609 
3610 void TProofServ::HandleArchive(TMessage *mess, TString *slb)
3611 {
3612  PDB(kGlobal, 1)
3613  Info("HandleArchive", "Enter");
3614 
3615  TString queryref;
3616  TString path;
3617  (*mess) >> queryref >> path;
3618 
3619  if (slb) slb->Form("%s %s", queryref.Data(), path.Data());
3620 
3621  // If this is a set default action just save the default
3622  if (queryref == "Default") {
3623  fArchivePath = path;
3624  Info("HandleArchive",
3625  "default path set to %s", fArchivePath.Data());
3626  return;
3627  }
3628 
3629  Int_t qry = -1;
3630  TString qdir;
3631  TProofQueryResult *pqr = fQMgr ? fQMgr->LocateQuery(queryref, qry, qdir) : 0;
3632  TProofQueryResult *pqm = pqr;
3633 
3634  if (path.Length() <= 0) {
3635  if (fArchivePath.Length() <= 0) {
3636  Info("HandleArchive",
3637  "archive paths are not defined - do nothing");
3638  return;
3639  }
3640  if (qry > 0) {
3641  path.Form("%s/session-%s-%d.root",
3642  fArchivePath.Data(), fTopSessionTag.Data(), qry);
3643  } else {
3644  path = queryref;
3645  path.ReplaceAll(":q","-");
3646  path.Insert(0, TString::Format("%s/",fArchivePath.Data()));
3647  path += ".root";
3648  }
3649  }
3650 
3651  // Build file name for specific query
3652  if (!pqr || qry < 0) {
3653  TString fout = qdir;
3654  fout += "/query-result.root";
3655 
3656  TFile *f = TFile::Open(fout,"READ");
3657  pqr = 0;
3658  if (f) {
3659  f->ReadKeys();
3660  TIter nxk(f->GetListOfKeys());
3661  TKey *k = 0;
3662  while ((k = (TKey *)nxk())) {
3663  if (!strcmp(k->GetClassName(), "TProofQueryResult")) {
3664  pqr = (TProofQueryResult *) f->Get(k->GetName());
3665  if (pqr)
3666  break;
3667  }
3668  }
3669  f->Close();
3670  delete f;
3671  } else {
3672  Info("HandleArchive",
3673  "file cannot be open (%s)",fout.Data());
3674  return;
3675  }
3676  }
3677 
3678  if (pqr) {
3679 
3680  PDB(kGlobal, 1) Info("HandleArchive",
3681  "archive path for query #%d: %s",
3682  qry, path.Data());
3683  TFile *farc = 0;
3684  if (gSystem->AccessPathName(path))
3685  farc = TFile::Open(path,"NEW");
3686  else
3687  farc = TFile::Open(path,"UPDATE");
3688  if (!farc || !(farc->IsOpen())) {
3689  Info("HandleArchive",
3690  "archive file cannot be open (%s)",path.Data());
3691  return;
3692  }
3693  farc->cd();
3694 
3695  // Update query status
3696  pqr->SetArchived(path);
3697  if (pqm)
3698  pqm->SetArchived(path);
3699 
3700  // Write to file
3701  pqr->Write();
3702 
3703  // Update temporary files too
3704  if (qry > -1 && fQMgr)
3705  fQMgr->SaveQuery(pqr);
3706 
3707  // Notify
3708  Info("HandleArchive",
3709  "results of query %s archived to file %s",
3710  queryref.Data(), path.Data());
3711  }
3712 
3713  // Done
3714  return;
3715 }
3716 
3717 ////////////////////////////////////////////////////////////////////////////////
3718 /// Get a map {server-name, list-of-files} for collection 'fc' to be used in
3719 /// TPacketizerFile. Returns a pointer to the map (ownership of the caller).
3720 /// Or (TMap *)0 and an error message in emsg.
3721 
3723 {
3724  TMap *fcmap = 0;
3725  emsg = "";
3726 
3727  // Sanity checks
3728  if (!fc) {
3729  emsg.Form("file collection undefined!");
3730  return fcmap;
3731  }
3732 
3733  // Prepare data set map
3734  fcmap = new TMap();
3735 
3736  TIter nxf(fc->GetList());
3737  TFileInfo *fiind = 0;
3738  TString key;
3739  while ((fiind = (TFileInfo *)nxf())) {
3740  TUrl *xurl = fiind->GetCurrentUrl();
3741  // Find the key for this server
3742  key.Form("%s://%s", xurl->GetProtocol(), xurl->GetHostFQDN());
3743  if (xurl->GetPort() > 0)
3744  key += TString::Format(":%d", xurl->GetPort());
3745  // Get the map entry for this key
3746  TPair *ent = 0;
3747  THashList* l = 0;
3748  if ((ent = (TPair *) fcmap->FindObject(key.Data()))) {
3749  // Attach to the list
3750  l = (THashList *) ent->Value();
3751  } else {
3752  // Create list
3753  l = new THashList;
3754  l->SetOwner(kTRUE);
3755  // Add it to the map
3756  fcmap->Add(new TObjString(key.Data()), l);
3757  }
3758  // Add fileinfo with index to list
3759  l->Add(fiind);
3760  }
3761 
3762  // Done
3763  return fcmap;
3764 }
3765 
3766 ////////////////////////////////////////////////////////////////////////////////
3767 /// Handle processing request.
3768 
3769 void TProofServ::HandleProcess(TMessage *mess, TString *slb)
3770 {
3771  PDB(kGlobal, 1)
3772  Info("HandleProcess", "Enter");
3773 
3774  // Nothing to do for slaves if we are not idle
3775  if (!IsTopMaster() && !IsIdle())
3776  return;
3777 
3778  TDSet *dset;
3779  TString filename, opt;
3780  TList *input;
3782  TEventList *evl = 0;
3783  TEntryList *enl = 0;
3784  Bool_t sync;
3785 
3786  (*mess) >> dset >> filename >> input >> opt >> nentries >> first >> evl >> sync;
3787  // Get entry list information, if any (support started with fProtocol == 15)
3788  if ((mess->BufferSize() > mess->Length()) && fProtocol > 14)
3789  (*mess) >> enl;
3790  Bool_t hasNoData = (!dset || dset->TestBit(TDSet::kEmpty)) ? kTRUE : kFALSE;
3791 
3792  // Priority to the entry list
3793  TObject *elist = (enl) ? (TObject *)enl : (TObject *)evl;
3794  if (enl && evl)
3795  // Cannot specify both at the same time
3796  SafeDelete(evl);
3797  if ((!hasNoData) && elist)
3798  dset->SetEntryList(elist);
3799 
3800  if (IsTopMaster()) {
3801 
3802  TString emsg;
3803  // Make sure the dataset contains the information needed
3804  if ((!hasNoData) && dset->GetListOfElements()->GetSize() == 0) {
3805  if (TProof::AssertDataSet(dset, input, fDataSetManager, emsg) != 0) {
3806  SendAsynMessage(TString::Format("AssertDataSet on %s: %s",
3807  fPrefix.Data(), emsg.Data()));
3808  Error("HandleProcess", "AssertDataSet: %s", emsg.Data());
3809  // To terminate collection
3810  if (sync) SendLogFile();
3811  return;
3812  }
3813  } else if (hasNoData) {
3814  // Check if we are required to process with TPacketizerFile a registered dataset
3815  TNamed *ftp = dynamic_cast<TNamed *>(input->FindObject("PROOF_FilesToProcess"));
3816  if (ftp) {
3817  TString dsn(ftp->GetTitle());
3818  if (!dsn.Contains(":") || dsn.BeginsWith("dataset:")) {
3819  dsn.ReplaceAll("dataset:", "");
3820  // Get the map for TPacketizerFile
3821  // Make sure we have something in input and a dataset manager
3822  if (!fDataSetManager) {
3823  emsg.Form("dataset manager not initialized!");
3824  } else {
3825  TFileCollection *fc = 0;
3826  // Get the dataset
3827  if (!(fc = fDataSetManager->GetDataSet(dsn))) {
3828  emsg.Form("requested dataset '%s' does not exists", dsn.Data());
3829  } else {
3830  TMap *fcmap = GetDataSetNodeMap(fc, emsg);
3831  if (fcmap) {
3832  input->Remove(ftp);
3833  delete ftp;
3834  fcmap->SetOwner(kTRUE);
3835  fcmap->SetName("PROOF_FilesToProcess");
3836  input->Add(fcmap);
3837  }
3838  }
3839  }
3840  if (!emsg.IsNull()) {
3841  SendAsynMessage(TString::Format("HandleProcess on %s: %s",
3842  fPrefix.Data(), emsg.Data()));
3843  Error("HandleProcess", "%s", emsg.Data());
3844  // To terminate collection
3845  if (sync) SendLogFile();
3846  return;
3847  }
3848  }
3849  }
3850  }
3851 
3852  TProofQueryResult *pq = 0;
3853 
3854  // Create instance of query results; we set ownership of the input list
3855  // to the TQueryResult object, to avoid too many instantiations
3856  pq = MakeQueryResult(nentries, opt, 0, first, 0, filename, 0);
3857 
3858  // Prepare the input list and transfer it into the TQueryResult object
3859  if (dset) input->Add(dset);
3860  if (elist) input->Add(elist);
3861  pq->SetInputList(input, kTRUE);
3862 
3863  // Clear the list
3864  input->Clear("nodelete");
3865  SafeDelete(input);
3866 
3867  // Save input data, if any
3868  if (TProof::SaveInputData(pq, fCacheDir.Data(), emsg) != 0)
3869  Warning("HandleProcess", "could not save input data: %s", emsg.Data());
3870 
3871  // If not a draw action add the query to the main list
3872  if (!(pq->IsDraw())) {
3873  if (fQMgr) {
3874  if (fQMgr->Queries()) fQMgr->Queries()->Add(pq);
3875  // Also save it to queries dir
3876  fQMgr->SaveQuery(pq);
3877  }
3878  }
3879 
3880  // Add anyhow to the waiting lists
3881  QueueQuery(pq);
3882 
3883  // Call get Workers
3884  // if we are not idle the scheduler will just enqueue the query and
3885  // send a resume message later.
3886 
3887  Bool_t enqueued = kFALSE;
3888  Int_t pc = 0;
3889  // if the session does not have workers and is in the dynamic mode
3890  if (fProof->UseDynamicStartup()) {
3891  // get the a list of workers and start them
3892  TList* workerList = new TList();
3893  EQueryAction retVal = GetWorkers(workerList, pc);
3894  if (retVal == TProofServ::kQueryStop) {
3895  Error("HandleProcess", "error getting list of worker nodes");
3896  // To terminate collection
3897  if (sync) SendLogFile();
3898  return;
3899  } else if (retVal == TProofServ::kQueryEnqueued) {
3900  // change to an asynchronous query
3901  enqueued = kTRUE;
3902  Info("HandleProcess", "query %d enqueued", pq->GetSeqNum());
3903  } else if (Int_t ret = fProof->AddWorkers(workerList) < 0) {
3904  Error("HandleProcess", "Adding a list of worker nodes returned: %d",
3905  ret);
3906  // To terminate collection
3907  if (sync) SendLogFile();
3908  return;
3909  }
3910  } else {
3911  EQueryAction retVal = GetWorkers(0, pc);
3912  if (retVal == TProofServ::kQueryStop) {
3913  Error("HandleProcess", "error getting list of worker nodes");
3914  // To terminate collection
3915  if (sync) SendLogFile();
3916  return;
3917  } else if (retVal == TProofServ::kQueryEnqueued) {
3918  // change to an asynchronous query
3919  enqueued = kTRUE;
3920  Info("HandleProcess", "query %d enqueued", pq->GetSeqNum());
3921  } else if (retVal != TProofServ::kQueryOK) {
3922  Error("HandleProcess", "unknown return value: %d", retVal);
3923  // To terminate collection
3924  if (sync) SendLogFile();
3925  return;
3926  }
3927  }
3928 
3929  // If the client submission was asynchronous, signal the submission of
3930  // the query and communicate the assigned sequential number for later
3931  // identification
3933  if (!sync || enqueued) {
3934  m << pq->GetSeqNum() << kFALSE;
3935  fSocket->Send(m);
3936  }
3937 
3938  // Nothing more to do if we are not idle
3939  if (!IsIdle()) {
3940  // Notify submission
3941  Info("HandleProcess",
3942  "query \"%s:%s\" submitted", pq->GetTitle(), pq->GetName());
3943  return;
3944  }
3945 
3946  // Process
3947  // in the static mode, if a session is enqueued it will be processed after current query
3948  // (there is no way to enqueue if idle).
3949  // in the dynamic mode we will process here only if the session was idle and got workers!
3950  Bool_t doprocess = kFALSE;
3951  while (WaitingQueries() > 0 && !enqueued) {
3952  doprocess = kTRUE;
3953  //
3954  ProcessNext(slb);
3955  // avoid processing async queries sent during processing in dyn mode
3956  if (fProof->UseDynamicStartup())
3957  enqueued = kTRUE;
3958 
3959  } // Loop on submitted queries
3960 
3961  // Set idle
3962  SetIdle(kTRUE);
3963 
3964  // Reset mergers
3965  fProof->ResetMergers();
3966 
3967  // kPROOF_SETIDLE sets the client to idle; in asynchronous mode clients monitor
3968  // TProof::IsIdle for to check the readiness of a query, so we need to send this
3969  // before to be sure thatn everything about a query is received by the client
3970  if (!sync) SendLogFile();
3971 
3972  // Signal the client that we are idle
3973  if (doprocess) {
3974  m.Reset(kPROOF_SETIDLE);
3975  Bool_t waiting = (WaitingQueries() > 0) ? kTRUE : kFALSE;
3976  m << waiting;
3977  fSocket->Send(m);
3978  }
3979 
3980  // In synchronous mode TProof::Collect is terminated by the reception of the
3981  // log file and subsequent submissions are controlled by TProof::IsIdle(), so
3982  // this must be last one to be sent
3983  if (sync) SendLogFile();
3984 
3985  // Set idle
3986  SetIdle(kTRUE);
3987 
3988  } else {
3989 
3990  // Reset compute stopwatch: we include all what done from now on
3991  fCompute.Reset();
3992  fCompute.Start();
3993 
3994  // Set not idle
3995  SetIdle(kFALSE);
3996 
3997  // Cleanup the player
3998  Bool_t deleteplayer = kTRUE;
3999  MakePlayer();
4000 
4001  // Setup data set
4002  if (dset && (dset->IsA() == TDSetProxy::Class()))
4003  ((TDSetProxy*)dset)->SetProofServ(this);
4004 
4005  // Get input data, if any
4006  TString emsg;
4007  if (TProof::GetInputData(input, fCacheDir.Data(), emsg) != 0)
4008  Warning("HandleProcess", "could not get input data: %s", emsg.Data());
4009 
4010  // Get query sequential number
4011  if (TProof::GetParameter(input, "PROOF_QuerySeqNum", fQuerySeqNum) != 0)
4012  Warning("HandleProcess", "could not get query sequential number!");
4013 
4014  // Make the ordinal number available in the selector
4015  TObject *nord = 0;
4016  while ((nord = input->FindObject("PROOF_Ordinal")))
4017  input->Remove(nord);
4018  input->Add(new TNamed("PROOF_Ordinal", GetOrdinal()));
4019 
4020  // Set input
4021  TIter next(input);
4022  TObject *o = 0;
4023  while ((o = next())) {
4024  PDB(kGlobal, 2) Info("HandleProcess", "adding: %s", o->GetName());
4025  fPlayer->AddInput(o);
4026  }
4027 
4028  // Check if a TSelector object is passed via input list
4029  TObject *obj = 0;
4030  TSelector *selector_obj = 0;
4031  TIter nxt(input);
4032  while ((obj = nxt())){
4033  if (obj->InheritsFrom("TSelector")) {
4034  selector_obj = (TSelector *) obj;
4035  filename = selector_obj->ClassName();
4036  Info("HandleProcess", "selector obj for '%s' found", selector_obj->ClassName());
4037  break;
4038  }
4039  }
4040 
4041  // Signal the master that we are starting processing
4043 
4044  // Reset latency stopwatch
4045  fLatency.Reset();
4046  fSaveOutput.Reset();
4047 
4048  // Process
4049  PDB(kGlobal, 1) Info("HandleProcess", "calling %s::Process()", fPlayer->IsA()->GetName());
4050 
4051  if (selector_obj){
4052  Info("HandleProcess", "calling fPlayer->Process() with selector object: %s", selector_obj->ClassName());
4053  fPlayer->Process(dset, selector_obj, opt, nentries, first);
4054  }
4055  else {
4056  Info("HandleProcess", "calling fPlayer->Process() with selector name: %s", filename.Data());
4057  fPlayer->Process(dset, filename, opt, nentries, first);
4058  }
4059 
4060  // Return number of events processed
4063  if (fProtocol > 18) {
4064  TProofProgressStatus* status =
4066  gPerfStats?gPerfStats->GetBytesRead():0);
4067  if (status)
4068  m << status << abort;
4069  if (slb)
4070  slb->Form("%d %lld %lld", fPlayer->GetExitStatus(),
4071  status->GetEntries(), status->GetBytesRead());
4072  SafeDelete(status);
4073  } else {
4074  m << fPlayer->GetEventsProcessed() << abort;
4075  if (slb)
4076  slb->Form("%d %lld -1", fPlayer->GetExitStatus(), fPlayer->GetEventsProcessed());
4077  }
4078 
4079  fSocket->Send(m);
4080  PDB(kGlobal, 2)
4081  Info("TProofServ::Handleprocess",
4082  "worker %s has finished processing with %d objects in output list",
4084 
4085  // Cleanup the input data set info
4086  SafeDelete(dset);
4087  SafeDelete(enl);
4088  SafeDelete(evl);
4089 
4092  if (outok) {
4093  // Check if in controlled output sending mode or submerging
4094  Int_t cso = 0;
4095  Bool_t isSubMerging = kFALSE;
4096 
4097  // Check if we are in merging mode (i.e. parameter PROOF_UseMergers exists)
4098  Int_t nm = 0;
4099  if (TProof::GetParameter(input, "PROOF_UseMergers", nm) == 0) {
4100  isSubMerging = (nm >= 0) ? kTRUE : kFALSE;
4101  }
4102  if (!isSubMerging) {
4103  cso = gEnv->GetValue("Proof.ControlSendOutput", 1);
4104  if (TProof::GetParameter(input, "PROOF_ControlSendOutput", cso) != 0)
4105  cso = gEnv->GetValue("Proof.ControlSendOutput", 1);
4106  }
4107 
4108  if (cso > 0) {
4109 
4110  // Control output sending mode: wait for the master to ask for the objects.
4111  // Allows controls of memory usage on the master.
4113  fSocket->Send(msg);
4114 
4115  // Set idle
4116  SetIdle(kTRUE);
4117 
4118  // Do not cleanup the player yet: it will be used in sending output activities
4119  deleteplayer = kFALSE;
4120 
4121  PDB(kGlobal, 1)
4122  Info("HandleProcess", "controlled mode: worker %s has finished,"
4123  " sizes sent to master", fOrdinal.Data());
4124  } else {
4125 
4126  // Check if we are in merging mode (i.e. parameter PROOF_UseMergers exists)
4128  if (isSubMerging)
4129  Info("HandleProcess", "submerging disabled because of high-memory case");
4130  isSubMerging = kFALSE;
4131  } else {
4132  PDB(kGlobal, 2) Info("HandleProcess", "merging mode check: %d", isSubMerging);
4133  }
4134 
4135  if (!IsMaster() && isSubMerging) {
4136  // Worker in merging mode.
4137  //----------------------------
4138  // First, it reports only the size of its output to the master
4139  // + port on which it can possibly accept outputs from other workers if it becomes a merger
4140  // Master will later tell it where it should send the output (either to the master or to some merger)
4141  // or if it should become a merger
4142 
4143  TMessage msg_osize(kPROOF_SUBMERGER);
4144  msg_osize << Int_t(TProof::kOutputSize);
4145  msg_osize << fPlayer->GetOutputList()->GetEntries();
4146 
4147  fMergingSocket = new TServerSocket(0);
4148  Int_t merge_port = 0;
4149  if (fMergingSocket) {
4150  PDB(kGlobal, 2)
4151  Info("HandleProcess", "possible port for merging connections: %d",
4153  merge_port = fMergingSocket->GetLocalPort();
4154  }
4155  msg_osize << merge_port;
4156  fSocket->Send(msg_osize);
4157 
4158  // Set idle
4159  SetIdle(kTRUE);
4160 
4161  // Do not cleanup the player yet: it will be used in sub-merging activities
4162  deleteplayer = kFALSE;
4163 
4164  PDB(kSubmerger, 2) Info("HandleProcess", "worker %s has finished", fOrdinal.Data());
4165 
4166  } else {
4167  // Sub-master OR worker not in merging mode
4168  // ---------------------------------------------
4169  PDB(kGlobal, 2) Info("HandleProcess", "sending result directly to master");
4170  if (SendResults(fSocket, fPlayer->GetOutputList()) != 0)
4171  Warning("HandleProcess","problems sending output list");
4172 
4173  // Masters reset the mergers, if any
4174  if (IsMaster()) fProof->ResetMergers();
4175 
4176  // Signal the master that we are idle
4178 
4179  // Set idle
4180  SetIdle(kTRUE);
4181 
4182  // Notify the user
4183  SendLogFile();
4184  }
4185 
4186 
4187 
4188  }
4189 
4190  } else {
4191  // No output list
4193  Warning("HandleProcess","the output list is empty!");
4194  if (SendResults(fSocket) != 0)
4195  Warning("HandleProcess", "problems sending output list");
4196 
4197  // Masters reset the mergers, if any
4198  if (IsMaster()) fProof->ResetMergers();
4199 
4200  // Signal the master that we are idle
4202 
4203  // Set idle
4204  SetIdle(kTRUE);
4205 
4206  // Notify the user
4207  SendLogFile();
4208  }
4209 
4210  // Prevent from double-deleting in input
4211  TIter nex(input);
4212  while ((obj = nex())) {
4213  if (obj->InheritsFrom("TSelector")) input->Remove(obj);
4214  }
4215 
4216  // Make also sure the input list objects are deleted
4217  fPlayer->GetInputList()->SetOwner(0);
4218 
4219  // Remove possible inputs from a file and the file, if any
4220  TList *added = dynamic_cast<TList *>(input->FindObject("PROOF_InputObjsFromFile"));
4221  if (added) {
4222  if (added->GetSize() > 0) {
4223  // The file must be the last one
4224  TFile *f = dynamic_cast<TFile *>(added->Last());
4225  if (f) {
4226  added->Remove(f);
4227  TIter nxo(added);
4228  while ((o = nxo())) { input->Remove(o); }
4229  input->Remove(added);
4230  added->SetOwner(kFALSE);
4231  added->Clear();
4232  f->Close();
4233  delete f;
4234  }
4235  }
4236  SafeDelete(added);
4237  }
4238  input->SetOwner();
4239  SafeDelete(input);
4240 
4241  // Cleanup if required
4242  if (deleteplayer) DeletePlayer();
4243  }
4244 
4245  PDB(kGlobal, 1) Info("HandleProcess", "done");
4246 
4247  // Done
4248  return;
4249 }
4250 
4251 ////////////////////////////////////////////////////////////////////////////////
4252 /// Sends all objects from the given list to the specified socket
4253 
4255 {
4256  PDB(kOutput, 2) Info("SendResults", "enter");
4257 
4258  TString msg;
4259  if (fProtocol > 23 && outlist) {
4260  // Send objects in bunches of max fMsgSizeHWM bytes to optimize transfer
4261  // Objects are merged one-by-one by the client
4262  // Messages for objects
4264  // Objects in the output list
4265  Int_t olsz = outlist->GetSize();
4266  if (IsTopMaster() && pq) {
4267  msg.Form("%s: merging output objects ... done ",
4268  fPrefix.Data());
4269  SendAsynMessage(msg.Data());
4270  // Message for the client
4271  msg.Form("%s: objects merged; sending output: %d objs", fPrefix.Data(), olsz);
4272  SendAsynMessage(msg.Data(), kFALSE);
4273  // Send light query info
4274  mbuf << (Int_t) 0;
4275  mbuf.WriteObject(pq);
4276  if (sock->Send(mbuf) < 0) return -1;
4277  }
4278  // Objects in the output list
4279  Int_t ns = 0, np = 0;
4280  TIter nxo(outlist);
4281  TObject *o = 0;
4282  Int_t totsz = 0, objsz = 0;
4283  mbuf.Reset();
4284  while ((o = nxo())) {
4285  if (mbuf.Length() > fMsgSizeHWM) {
4286  PDB(kOutput, 1)
4287  Info("SendResults",
4288  "message has %d bytes: limit of %lld bytes reached - sending ...",
4289  mbuf.Length(), fMsgSizeHWM);
4290  // Compress the message, if required; for these messages we do it already
4291  // here so we get the size; TXSocket does not do it twice.
4292  if (GetCompressionLevel() > 0) {
4294  mbuf.Compress();
4295  objsz = mbuf.CompLength();
4296  } else {
4297  objsz = mbuf.Length();
4298  }
4299  totsz += objsz;
4300  if (IsTopMaster()) {
4301  msg.Form("%s: objects merged; sending obj %d/%d (%d bytes) ",
4302  fPrefix.Data(), ns, olsz, objsz);
4303  SendAsynMessage(msg.Data(), kFALSE);
4304  }
4305  if (sock->Send(mbuf) < 0) return -1;
4306  // Reset the message
4307  mbuf.Reset();
4308  np = 0;
4309  }
4310  ns++;
4311  np++;
4312  mbuf << (Int_t) ((ns >= olsz) ? 2 : 1);
4313  mbuf << o;
4314  }
4315  if (np > 0) {
4316  // Compress the message, if required; for these messages we do it already
4317  // here so we get the size; TXSocket does not do it twice.
4318  if (GetCompressionLevel() > 0) {
4320  mbuf.Compress();
4321  objsz = mbuf.CompLength();
4322  } else {
4323  objsz = mbuf.Length();
4324  }
4325  totsz += objsz;
4326  if (IsTopMaster()) {
4327  msg.Form("%s: objects merged; sending obj %d/%d (%d bytes) ",
4328  fPrefix.Data(), ns, olsz, objsz);
4329  SendAsynMessage(msg.Data(), kFALSE);
4330  }
4331  if (sock->Send(mbuf) < 0) return -1;
4332  }
4333  if (IsTopMaster()) {
4334  // Send total size
4335  msg.Form("%s: grand total: sent %d objects, size: %d bytes ",
4336  fPrefix.Data(), olsz, totsz);
4337  SendAsynMessage(msg.Data());
4338  }
4339  } else if (fProtocol > 10 && outlist) {
4340 
4341  // Send objects one-by-one to optimize transfer and merging
4342  // Messages for objects
4344  // Objects in the output list
4345  Int_t olsz = outlist->GetSize();
4346  if (IsTopMaster() && pq) {
4347  msg.Form("%s: merging output objects ... done ",
4348  fPrefix.Data());
4349  SendAsynMessage(msg.Data());
4350  // Message for the client
4351  msg.Form("%s: objects merged; sending output: %d objs", fPrefix.Data(), olsz);
4352  SendAsynMessage(msg.Data(), kFALSE);
4353  // Send light query info
4354  mbuf << (Int_t) 0;
4355  mbuf.WriteObject(pq);
4356  if (sock->Send(mbuf) < 0) return -1;
4357  }
4358 
4359  Int_t ns = 0;
4360  Int_t totsz = 0, objsz = 0;
4361  TIter nxo(fPlayer->GetOutputList());
4362  TObject *o = 0;
4363  while ((o = nxo())) {
4364  ns++;
4365  mbuf.Reset();
4366  Int_t type = (Int_t) ((ns >= olsz) ? 2 : 1);
4367  mbuf << type;
4368  mbuf.WriteObject(o);
4369  // Compress the message, if required; for these messages we do it already
4370  // here so we get the size; TXSocket does not do it twice.
4371  if (GetCompressionLevel() > 0) {
4373  mbuf.Compress();
4374  objsz = mbuf.CompLength();
4375  } else {
4376  objsz = mbuf.Length();
4377  }
4378  totsz += objsz;
4379  if (IsTopMaster()) {
4380  msg.Form("%s: objects merged; sending obj %d/%d (%d bytes) ",
4381  fPrefix.Data(), ns, olsz, objsz);
4382  SendAsynMessage(msg.Data(), kFALSE);
4383  }
4384  if (sock->Send(mbuf) < 0) return -1;
4385  }
4386  // Total size
4387  if (IsTopMaster()) {
4388  // Send total size
4389  msg.Form("%s: grand total: sent %d objects, size: %d bytes ",
4390  fPrefix.Data(), olsz, totsz);
4391  SendAsynMessage(msg.Data());
4392  }
4393 
4394  } else if (IsTopMaster() && fProtocol > 6 && outlist) {
4395 
4396  // Buffer to be sent
4398  mbuf.WriteObject(pq);
4399  // Sizes
4400  Int_t blen = mbuf.CompLength();
4401  Int_t olsz = outlist->GetSize();
4402  // Message for the client
4403  msg.Form("%s: sending output: %d objs, %d bytes", fPrefix.Data(), olsz, blen);
4404  SendAsynMessage(msg.Data(), kFALSE);
4405  if (sock->Send(mbuf) < 0) return -1;
4406 
4407  } else {
4408  if (outlist) {
4409  PDB(kGlobal, 2) Info("SendResults", "sending output list");
4410  } else {
4411  PDB(kGlobal, 2) Info("SendResults", "notifying failure or abort");
4412  }
4413  if (sock->SendObject(outlist, kPROOF_OUTPUTLIST) < 0) return -1;
4414  }
4415 
4416  PDB(kOutput,2) Info("SendResults", "done");
4417 
4418  // Done
4419  return 0;
4420 }
4421 
4422 ////////////////////////////////////////////////////////////////////////////////
4423 /// process the next query from the queue of submitted jobs.
4424 /// to be called on the top master only.
4425 
4426 void TProofServ::ProcessNext(TString *slb)
4427 {
4428  TDSet *dset = 0;
4429  TString filename, opt;
4430  TList *input = 0;
4431  Long64_t nentries = -1, first = 0;
4432 
4433  // TObject *elist = 0;
4434  TProofQueryResult *pq = 0;
4435 
4436  TObject* obj = 0;
4437  TSelector* selector_obj = 0;
4438 
4439  // Process
4440 
4441  // Reset compute stopwatch: we include all what done from now on
4442  fCompute.Reset();
4443  fCompute.Start();
4444 
4445  // Get next query info (also removes query from the list)
4446  pq = NextQuery();
4447  if (pq) {
4448 
4449  // Set not idle
4450  SetIdle(kFALSE);
4451  opt = pq->GetOptions();
4452  input = pq->GetInputList();
4453  nentries = pq->GetEntries();
4454  first = pq->GetFirst();
4455  filename = pq->GetSelecImp()->GetName();
4456  Ssiz_t id = opt.Last('#');
4457  if (id != kNPOS && id < opt.Length() - 1) {
4458  filename += opt(id + 1, opt.Length());
4459  // Remove it from 'opt' so user found on the workers what they specified
4460  opt.Remove(id);
4461  }
4462  // Attach to data set and entry- (or event-) list (if any)
4463  TObject *o = 0;
4464  if ((o = pq->GetInputObject("TDSet"))) {
4465  dset = (TDSet *) o;
4466  } else {
4467  // Should never get here
4468  Error("ProcessNext", "no TDset object: cannot continue");
4469  return;
4470  }
4471  // elist = 0;
4472  // if ((o = pq->GetInputObject("TEntryList")))
4473  // elist = o;
4474  // else if ((o = pq->GetInputObject("TEventList")))
4475  // elist = o;
4476 
4477  // Expand selector files
4478  if (pq->GetSelecImp()) {
4479  gSystem->Exec(TString::Format("%s %s", kRM, pq->GetSelecImp()->GetName()));
4480  pq->GetSelecImp()->SaveSource(pq->GetSelecImp()->GetName());
4481  }
4482  if (pq->GetSelecHdr() &&
4483  !strstr(pq->GetSelecHdr()->GetName(), "TProofDrawHist")) {
4484  gSystem->Exec(TString::Format("%s %s", kRM, pq->GetSelecHdr()->GetName()));
4485  pq->GetSelecHdr()->SaveSource(pq->GetSelecHdr()->GetName());
4486  }
4487 
4488  // Taking out a TSelector object from input list
4489  TIter nxt(input);
4490  while ((obj = nxt())){
4491  if (obj->InheritsFrom("TSelector") &&
4492  !strcmp(pq->GetSelecImp()->GetName(), obj->ClassName())) {
4493  selector_obj = (TSelector *) obj;
4494  Info("ProcessNext", "found object for selector '%s'", obj->ClassName());
4495  break;
4496  }
4497  }
4498 
4499  } else {
4500  // Should never get here
4501  Error("ProcessNext", "empty waiting queries list!");
4502  return;
4503  }
4504 
4505  // Set in running state
4506  SetQueryRunning(pq);
4507 
4508  // Save to queries dir, if not standard draw
4509  if (fQMgr) {
4510  if (!(pq->IsDraw()))
4511  fQMgr->SaveQuery(pq);
4512  else
4514  fQMgr->ResetTime();
4515  }
4516 
4517  // Signal the client that we are starting a new query
4519  m << TString(pq->GetSelecImp()->GetName())
4520  << dset->GetNumOfFiles()
4521  << pq->GetFirst() << pq->GetEntries();
4522  fSocket->Send(m);
4523 
4524  // Create player
4525  MakePlayer();
4526 
4527  // Add query results to the player lists
4528  fPlayer->AddQueryResult(pq);
4529 
4530  // Set query currently processed
4531  fPlayer->SetCurrentQuery(pq);
4532 
4533  // Setup data set
4534  if (dset->IsA() == TDSetProxy::Class())
4535  ((TDSetProxy*)dset)->SetProofServ(this);
4536 
4537  // Add the unique query tag as TNamed object to the input list
4538  // so that it is available in TSelectors for monitoring
4539  TString qid = TString::Format("%s:%s",pq->GetTitle(),pq->GetName());
4540  input->Add(new TNamed("PROOF_QueryTag", qid.Data()));
4541  // ... and the sequential number
4542  fQuerySeqNum = pq->GetSeqNum();
4543  input->Add(new TParameter<Int_t>("PROOF_QuerySeqNum", fQuerySeqNum));
4544 
4545  // Check whether we have to enforce the use of submergers, but only if the user did
4546  // not express itself on the subject
4547  if (gEnv->Lookup("Proof.UseMergers") && !input->FindObject("PROOF_UseMergers")) {
4548  Int_t smg = gEnv->GetValue("Proof.UseMergers",-1);
4549  if (smg >= 0) {
4550  input->Add(new TParameter<Int_t>("PROOF_UseMergers", smg));
4551  PDB(kSubmerger, 2) Info("ProcessNext", "PROOF_UseMergers set to %d", smg);
4552  if (gEnv->Lookup("Proof.MergersByHost")) {
4553  Int_t mbh = gEnv->GetValue("Proof.MergersByHost", 0);
4554  if (mbh != 0) {
4555  // Administrator settings have the priority
4556  TObject *o = 0;
4557  if ((o = input->FindObject("PROOF_MergersByHost"))) { input->Remove(o); delete o; }
4558  input->Add(new TParameter<Int_t>("PROOF_MergersByHost", mbh));
4559  PDB(kSubmerger, 2) Info("ProcessNext", "submergers setup by host/node");
4560  }
4561  }
4562  }
4563  }
4564 
4565  // Set input
4566  TIter next(input);
4567  TObject *o = 0;
4568  while ((o = next())) {
4569  PDB(kGlobal, 2) Info("ProcessNext", "adding: %s", o->GetName());
4570  fPlayer->AddInput(o);
4571  }
4572 
4573  // Remove the list of the missing files from the original list, if any
4574  if ((o = input->FindObject("MissingFiles"))) input->Remove(o);
4575 
4576  // Process
4577  PDB(kGlobal, 1) Info("ProcessNext", "calling %s::Process()", fPlayer->IsA()->GetName());
4578  if (selector_obj){
4579  Info("ProcessNext", "calling fPlayer->Process() with selector object: %s", selector_obj->ClassName());
4580  fPlayer->Process(dset, selector_obj, opt, nentries, first);
4581  }
4582  else {
4583  Info("ProcessNext", "calling fPlayer->Process() with selector name: %s", filename.Data());
4584  fPlayer->Process(dset, filename, opt, nentries, first);
4585  }
4586 
4587  // This is the end of merging
4589 
4590  // Return number of events processed
4591  Bool_t abort =
4595  // message sent from worker to the master
4596  if (fProtocol > 18) {
4598  m << status << abort;
4599  status = 0; // the status belongs to the player.
4600  } else if (fProtocol > 8) {
4601  m << fPlayer->GetEventsProcessed() << abort;
4602  } else {
4603  m << fPlayer->GetEventsProcessed();
4604  }
4605  fSocket->Send(m);
4606  }
4607 
4608  // Register any dataset produced during this processing, if required
4610  TNamed *psr = (TNamed *) fPlayer->GetOutputList()->FindObject("PROOFSERV_RegisterDataSet");
4611  if (psr) {
4612  TString emsg;
4613  if (RegisterDataSets(input, fPlayer->GetOutputList(), fDataSetManager, emsg) != 0)
4614  Warning("ProcessNext", "problems registering produced datasets: %s", emsg.Data());
4615  do {
4616  fPlayer->GetOutputList()->Remove(psr);
4617  delete psr;
4618  } while ((psr = (TNamed *) fPlayer->GetOutputList()->FindObject("PROOFSERV_RegisterDataSet")));
4619  }
4620  }
4621 
4622  // Complete filling of the TQueryResult instance
4623  if (fQMgr && !pq->IsDraw()) {
4624  if (!abort) fProof->AskStatistics();
4625  if (fQMgr->FinalizeQuery(pq, fProof, fPlayer))
4626  fQMgr->SaveQuery(pq, fMaxQueries);
4627  }
4628 
4629  // If we were requested to save results on the master and we are not in save-to-file mode
4630  // then we save the results
4631  if (IsTopMaster() && fPlayer->GetOutputList()) {
4632  Bool_t save = kTRUE;
4633  TIter nxo(fPlayer->GetOutputList());
4634  TObject *xo = 0;
4635  while ((xo = nxo())) {
4636  if (xo->InheritsFrom("TProofOutputFile") && xo->TestBit(TProofOutputFile::kSwapFile)) {
4637  save = kFALSE;
4638  break;
4639  }
4640  }
4641  if (save) {
4642  TNamed *nof = (TNamed *) input->FindObject("PROOF_DefaultOutputOption");
4643  if (nof) {
4644  TString oopt(nof->GetTitle());
4645  if (oopt.BeginsWith("of:")) {
4646  oopt.Replace(0, 3, "");
4647  if (!oopt.IsNull()) fPlayer->SetOutputFilePath(oopt);
4649  }
4650  }
4651  }
4652  }
4653 
4654  // Send back the results
4655  TQueryResult *pqr = pq->CloneInfo();
4656  // At least the TDSet name in the light object
4657  Info("ProcessNext", "adding info about dataset '%s' in the light query result", dset->GetName());
4658  TList rin;
4659  TDSet *ds = new TDSet(dset->GetName(), dset->GetObjName());
4660  rin.Add(ds);
4661  if (pqr) pqr->SetInputList(&rin, kTRUE);
4663  PDB(kGlobal, 2)
4664  Info("ProcessNext", "sending results");
4665  TQueryResult *xpq = (pqr && fProtocol > 10) ? pqr : pq;
4666  if (SendResults(fSocket, fPlayer->GetOutputList(), xpq) != 0)
4667  Warning("ProcessNext", "problems sending output list");
4668  if (slb) slb->Form("%d %lld %lld %.3f", fPlayer->GetExitStatus(), pq->GetEntries(),
4669  pq->GetBytes(), pq->GetUsedCPU());
4670  } else {
4672  Warning("ProcessNext","the output list is empty!");
4673  if (SendResults(fSocket, fPlayer->GetOutputList()) != 0)
4674  Warning("ProcessNext", "problems sending output list");
4675  if (slb) slb->Form("%d -1 -1 %.3f", fPlayer->GetExitStatus(), pq->GetUsedCPU());
4676  }
4677 
4678  // Remove aborted queries from the list
4680  SafeDelete(pqr);
4681  if (fQMgr) fQMgr->RemoveQuery(pq);
4682  } else {
4683  // Keep in memory only light infor about a query
4684  if (!(pq->IsDraw()) && pqr) {
4685  if (fQMgr && fQMgr->Queries()) {
4686  fQMgr->Queries()->Add(pqr);
4687  // Remove from the fQueries list
4688  fQMgr->Queries()->Remove(pq);
4689  }
4690  // These removes 'pq' from the internal player list and
4691  // deletes it; in this way we do not attempt a double delete
4692  // when destroying the player
4694  pq->GetTitle(), pq->GetName()));
4695  }
4696  }
4697 
4698  DeletePlayer();
4699  if (IsMaster() && fProof->UseDynamicStartup())
4700  // stop the workers
4701  fProof->RemoveWorkers(0);
4702 }
4703 
4704 ////////////////////////////////////////////////////////////////////////////////
4705 /// Register TFileCollections in 'out' as datasets according to the rules in 'in'
4706 
4708  TDataSetManager *dsm, TString &msg)
4709 {
4710  PDB(kDataset, 1)
4711  ::Info("TProofServ::RegisterDataSets",
4712  "enter: %d objs in the output list", (out ? out->GetSize() : -1));
4713 
4714  if (!in || !out || !dsm) {
4715  ::Error("TProofServ::RegisterDataSets", "invalid inputs: %p, %p, %p", in, out, dsm);
4716  return 0;
4717  }
4718  msg = "";
4719  THashList tags;
4720  TList torm;
4721  TIter nxo(out);
4722  TObject *o = 0;
4723  while ((o = nxo())) {
4724  // Only file collections TFileCollection
4725  TFileCollection *ds = dynamic_cast<TFileCollection*> (o);
4726  if (ds) {
4727  // Origin of this dataset
4728  ds->SetTitle(gSystem->HostName());
4729  // The tag and register option
4730  TNamed *fcn = 0;
4731  TString tag = TString::Format("DATASET_%s", ds->GetName());
4732  if (!(fcn = (TNamed *) out->FindObject(tag))) continue;
4733  // If this tag is in the list of processed tags, flag it for removal
4734  if (tags.FindObject(tag)) {
4735  torm.Add(o);
4736  continue;
4737  }
4738  // Register option
4739  TString regopt(fcn->GetTitle());
4740  // Sort according to the internal index, if required
4741  if (regopt.Contains(":sortidx:")) {
4742  ds->Sort(kTRUE);
4743  regopt.ReplaceAll(":sortidx:", "");
4744  }
4745  // Register this dataset
4747  // Extract the list
4748  if (ds->GetList()->GetSize() > 0) {
4749  // Register the dataset (quota checks are done inside here)
4750  const char *vfmsg = regopt.Contains("V") ? " and verifying" : "";
4751  msg.Form("Registering%s dataset '%s' ... ", vfmsg, ds->GetName());
4752  // Always allow verification for this action
4753  Bool_t allowVerify = dsm->TestBit(TDataSetManager::kAllowVerify) ? kTRUE : kFALSE;
4754  if (regopt.Contains("V") && !allowVerify) dsm->SetBit(TDataSetManager::kAllowVerify);
4755  // Main action
4756  Int_t rc = dsm->RegisterDataSet(ds->GetName(), ds, regopt);
4757  // Reset to the previous state if needed
4758  if (regopt.Contains("V") && !allowVerify) dsm->ResetBit(TDataSetManager::kAllowVerify);
4759  if (rc != 0) {
4760  ::Warning("TProofServ::RegisterDataSets",
4761  "failure registering or verifying dataset '%s'", ds->GetName());
4762  msg.Form("Registering%s dataset '%s' ... failed! See log for more details", vfmsg, ds->GetName());
4763  } else {
4764  ::Info("TProofServ::RegisterDataSets", "dataset '%s' successfully registered%s",
4765  ds->GetName(), (strlen(vfmsg) > 0) ? " and verified" : "");
4766  msg.Form("Registering%s dataset '%s' ... OK", vfmsg, ds->GetName());
4767  // Add tag to the list of processed tags to avoid double processing
4768  // (there may be more objects with the same name, created by each worker)
4769  tags.Add(new TObjString(tag));
4770  }
4771  // Notify
4772  PDB(kDataset, 2) {
4773  ::Info("TProofServ::RegisterDataSets", "printing collection");
4774  ds->Print("F");
4775  }
4776  } else {
4777  ::Warning("TProofServ::RegisterDataSets", "collection '%s' is empty", o->GetName());
4778  }
4779  } else {
4780  ::Info("TProofServ::RegisterDataSets", "dataset registration not allowed");
4781  return -1;
4782  }
4783  }
4784  }
4785  // Cleanup all temporary stuff possibly created by each worker
4786  TIter nxrm(&torm);
4787  while ((o = nxrm())) out->Remove(o);
4788  torm.SetOwner(kTRUE);
4789  // Remove tags
4790  TIter nxtg(&tags);
4791  while((o = nxtg())) {
4792  TObject *oo = 0;
4793  while ((oo = out->FindObject(o->GetName()))) { out->Remove(oo); }
4794  }
4795  tags.SetOwner(kTRUE);
4796 
4797  PDB(kDataset, 1) ::Info("TProofServ::RegisterDataSets", "exit");
4798  // Done
4799  return 0;
4800 }
4801 
4802 ////////////////////////////////////////////////////////////////////////////////
4803 /// Handle request for list of queries.
4804 
4806 {
4807  PDB(kGlobal, 1)
4808  Info("HandleQueryList", "Enter");
4809 
4810  Bool_t all;
4811  (*mess) >> all;
4812 
4813  TList *ql = new TList;
4814  Int_t ntot = 0, npre = 0, ndraw= 0;
4815  if (fQMgr) {
4816  if (all) {
4817  // Rescan
4818  TString qdir = fQueryDir;
4819  Int_t idx = qdir.Index("session-");
4820  if (idx != kNPOS)
4821  qdir.Remove(idx);
4822  fQMgr->ScanPreviousQueries(qdir);
4823  // Send also information about previous queries, if any
4824  if (fQMgr->PreviousQueries()) {
4825  TIter nxq(fQMgr->PreviousQueries());
4826  TProofQueryResult *pqr = 0;
4827  while ((pqr = (TProofQueryResult *)nxq())) {
4828  ntot++;
4829  pqr->fSeqNum = ntot;
4830  ql->Add(pqr);
4831  }
4832  }
4833  }
4834 
4835  npre = ntot;
4836  if (fQMgr->Queries()) {
4837  // Add info about queries in this session
4838  TIter nxq(fQMgr->Queries());
4839  TProofQueryResult *pqr = 0;
4840  TQueryResult *pqm = 0;
4841  while ((pqr = (TProofQueryResult *)nxq())) {
4842  ntot++;
4843  if ((pqm = pqr->CloneInfo())) {
4844  pqm->fSeqNum = ntot;
4845  ql->Add(pqm);
4846  } else {
4847  Warning("HandleQueryList", "unable to clone TProofQueryResult '%s:%s'",
4848  pqr->GetName(), pqr->GetTitle());
4849  }
4850  }
4851  }
4852  // Number of draw queries
4853  ndraw = fQMgr->DrawQueries();
4854  }
4855 
4857  m << npre << ndraw << ql;
4858  fSocket->Send(m);
4859  delete ql;
4860 
4861  // Done
4862  return;
4863 }
4864 
4865 ////////////////////////////////////////////////////////////////////////////////
4866 /// Handle remove request.
4867 
4868 void TProofServ::HandleRemove(TMessage *mess, TString *slb)
4869 {
4870  PDB(kGlobal, 1)
4871  Info("HandleRemove", "Enter");
4872 
4873  TString queryref;
4874  (*mess) >> queryref;
4875 
4876  if (slb) *slb = queryref;
4877 
4878  if (queryref == "cleanupqueue") {
4879  // Remove pending requests
4880  Int_t pend = CleanupWaitingQueries();
4881  // Notify
4882  Info("HandleRemove", "%d queries removed from the waiting list", pend);
4883  // We are done
4884  return;
4885  }
4886 
4887  if (queryref == "cleanupdir") {
4888 
4889  // Cleanup previous sessions results
4890  Int_t nd = (fQMgr) ? fQMgr->CleanupQueriesDir() : -1;
4891 
4892  // Notify
4893  Info("HandleRemove", "%d directories removed", nd);
4894  // We are done
4895  return;
4896  }
4897 
4898 
4899  if (fQMgr) {
4900  TProofLockPath *lck = 0;
4901  if (fQMgr->LockSession(queryref, &lck) == 0) {
4902 
4903  // Remove query
4904  TList qtorm;
4905  fQMgr->RemoveQuery(queryref, &qtorm);
4906  CleanupWaitingQueries(kFALSE, &qtorm);
4907 
4908  // Unlock and remove the lock file
4909  if (lck) {
4910  gSystem->Unlink(lck->GetName());
4911  SafeDelete(lck);
4912  }
4913 
4914  // We are done
4915  return;
4916  }
4917  } else {
4918  Warning("HandleRemove", "query result manager undefined!");
4919  }
4920 
4921  // Notify failure
4922  Info("HandleRemove",
4923  "query %s could not be removed (unable to lock session)", queryref.Data());
4924 
4925  // Done
4926  return;
4927 }
4928 
4929 ////////////////////////////////////////////////////////////////////////////////
4930 /// Handle retrieve request.
4931 
4932 void TProofServ::HandleRetrieve(TMessage *mess, TString *slb)
4933 {
4934  PDB(kGlobal, 1)
4935  Info("HandleRetrieve", "Enter");
4936 
4937  TString queryref;
4938  (*mess) >> queryref;
4939 
4940  if (slb) *slb = queryref;
4941 
4942  // Parse reference string
4943  Int_t qry = -1;
4944  TString qdir;
4945  if (fQMgr) fQMgr->LocateQuery(queryref, qry, qdir);
4946 
4947  TString fout = qdir;
4948  fout += "/query-result.root";
4949 
4950  TFile *f = TFile::Open(fout,"READ");
4951  TProofQueryResult *pqr = 0;
4952  if (f) {
4953  f->ReadKeys();
4954  TIter nxk(f->GetListOfKeys());
4955  TKey *k = 0;
4956  while ((k = (TKey *)nxk())) {
4957  if (!strcmp(k->GetClassName(), "TProofQueryResult")) {
4958  pqr = (TProofQueryResult *) f->Get(k->GetName());
4959  // For backward compatibility
4960  if (pqr && fProtocol < 13) {
4961  TDSet *d = 0;
4962  TObject *o = 0;
4963  TIter nxi(pqr->GetInputList());
4964  while ((o = nxi()))
4965  if ((d = dynamic_cast<TDSet *>(o)))
4966  break;
4967  d->SetWriteV3(kTRUE);
4968  }
4969  if (pqr) {
4970 
4971  // Message for the client
4972  Float_t qsz = (Float_t) f->GetSize();
4973  Int_t ilb = 0;
4974  static const char *clb[4] = { "bytes", "KB", "MB", "GB" };
4975  while (qsz > 1000. && ilb < 3) {
4976  qsz /= 1000.;
4977  ilb++;
4978  }
4979  SendAsynMessage(TString::Format("%s: sending result of %s:%s (%.1f %s)",
4980  fPrefix.Data(), pqr->GetTitle(), pqr->GetName(),
4981  qsz, clb[ilb]));
4983  } else {
4984  Info("HandleRetrieve",
4985  "query not found in file %s",fout.Data());
4986  // Notify not found
4988  }
4989  break;
4990  }
4991  }
4992  f->Close();
4993  delete f;
4994  } else {
4995  Info("HandleRetrieve",
4996  "file cannot be open (%s)",fout.Data());
4997  // Notify not found
4999  return;
5000  }
5001 
5002  // Done
5003  return;
5004 }
5005 
5006 ////////////////////////////////////////////////////////////////////////////////
5007 /// Handle lib, inc search paths modification request
5008 
5010 {
5011  TString type;
5012  Bool_t add;
5013  TString path;
5014  Int_t rc = 1;
5015  (*mess) >> type >> add >> path;
5016  if (mess->BufferSize() > mess->Length()) (*mess) >> rc;
5017 
5018  // Check type of action
5019  if ((type != "lib") && (type != "inc")) {
5020  Error("HandleLibIncPath","unknown action type: %s", type.Data());
5021  return rc;
5022  }
5023 
5024  // Separators can be either commas or blanks
5025  path.ReplaceAll(","," ");
5026 
5027  // Decompose lists
5028  TObjArray *op = 0;
5029  if (path.Length() > 0 && path != "-") {
5030  if (!(op = path.Tokenize(" "))) {
5031  Error("HandleLibIncPath","decomposing path %s", path.Data());
5032  return rc;
5033  }
5034  }
5035 
5036  if (add) {
5037 
5038  if (type == "lib") {
5039 
5040  // Add libs
5041  TIter nxl(op, kIterBackward);
5042  TObjString *lib = 0;
5043  while ((lib = (TObjString *) nxl())) {
5044  // Expand path
5045  TString xlib = lib->GetName();
5046  gSystem->ExpandPathName(xlib);
5047  // Add to the dynamic lib search path if it exists and can be read
5048  if (!gSystem->AccessPathName(xlib, kReadPermission)) {
5049  TString newlibpath = gSystem->GetDynamicPath();
5050  // In the first position after the working dir
5051  Int_t pos = 0;
5052  if (newlibpath.BeginsWith(".:"))
5053  pos = 2;
5054  if (newlibpath.Index(xlib) == kNPOS) {
5055  newlibpath.Insert(pos,TString::Format("%s:", xlib.Data()));
5056  gSystem->SetDynamicPath(newlibpath);
5057  }
5058  } else {
5059  Info("HandleLibIncPath",
5060  "libpath %s does not exist or cannot be read - not added", xlib.Data());
5061  }
5062  }
5063 
5064  // Forward the request, if required
5065  if (IsMaster())
5066  fProof->AddDynamicPath(path);
5067 
5068  } else {
5069 
5070  // Add incs
5071  TIter nxi(op);
5072  TObjString *inc = 0;
5073  while ((inc = (TObjString *) nxi())) {
5074  // Expand path
5075  TString xinc = inc->GetName();
5076  gSystem->ExpandPathName(xinc);
5077  // Add to the dynamic lib search path if it exists and can be read
5078  if (!gSystem->AccessPathName(xinc, kReadPermission)) {
5079  TString curincpath = gSystem->GetIncludePath();
5080  if (curincpath.Index(xinc) == kNPOS)
5081  gSystem->AddIncludePath(TString::Format("-I%s", xinc.Data()));
5082  } else
5083  Info("HandleLibIncPath",
5084  "incpath %s does not exist or cannot be read - not added", xinc.Data());
5085  }
5086 
5087  // Forward the request, if required
5088  if (IsMaster())
5089  fProof->AddIncludePath(path);
5090  }
5091 
5092 
5093  } else {
5094 
5095  if (type == "lib") {
5096 
5097  // Remove libs
5098  TIter nxl(op);
5099  TObjString *lib = 0;
5100  while ((lib = (TObjString *) nxl())) {
5101  // Expand path
5102  TString xlib = lib->GetName();
5103  gSystem->ExpandPathName(xlib);
5104  // Remove from the dynamic lib search path
5105  TString newlibpath = gSystem->GetDynamicPath();
5106  newlibpath.ReplaceAll(TString::Format("%s:", xlib.Data()),"");
5107  gSystem->SetDynamicPath(newlibpath);
5108  }
5109 
5110  // Forward the request, if required
5111  if (IsMaster())
5112  fProof->RemoveDynamicPath(path);
5113 
5114  } else {
5115 
5116  // Remove incs
5117  TIter nxi(op);
5118  TObjString *inc = 0;
5119  while ((inc = (TObjString *) nxi())) {
5120  TString newincpath = gSystem->GetIncludePath();
5121  newincpath.ReplaceAll(TString::Format("-I%s", inc->GetName()),"");
5122  // Remove the interpreter path (added anyhow internally)
5123  newincpath.ReplaceAll(gInterpreter->GetIncludePath(),"");
5124  gSystem->SetIncludePath(newincpath);
5125  }
5126 
5127  // Forward the request, if required
5128  if (IsMaster())
5129  fProof->RemoveIncludePath(path);
5130  }
5131  }
5132  // Done
5133  return rc;
5134 }
5135 
5136 ////////////////////////////////////////////////////////////////////////////////
5137 /// Handle file checking request.
5138 
5139 void TProofServ::HandleCheckFile(TMessage *mess, TString *slb)
5140 {
5141  TString filenam;
5142  TMD5 md5;
5143  UInt_t opt = TProof::kUntar;
5144 
5145  TMessage reply(kPROOF_CHECKFILE);
5146 
5147  // Parse message
5148  (*mess) >> filenam >> md5;
5149  if ((mess->BufferSize() > mess->Length()) && (fProtocol > 8))
5150  (*mess) >> opt;
5151 
5152  if (slb) *slb = filenam;
5153 
5154  if (filenam.BeginsWith("-")) {
5155  // install package:
5156  // compare md5's, untar, store md5 in PROOF-INF, remove par file
5157  Int_t st = 0;
5158  Bool_t err = kFALSE;
5159  filenam = filenam.Strip(TString::kLeading, '-');
5160  TString packnam = filenam;
5161  packnam.Remove(packnam.Length() - 4); // strip off ".par"
5162  // compare md5's to check if transmission was ok
5163  TMD5 *md5local = fPackMgr->GetMD5(packnam);
5164  if (md5local && md5 == (*md5local)) {
5165  if ((opt & TProof::kRemoveOld)) {
5166  if ((st = fPackMgr->Clean(packnam)))
5167  Error("HandleCheckFile", "failure cleaning %s", packnam.Data());
5168  }
5169  // Unpack
5170  st = fPackMgr->Unpack(packnam, md5local);
5171  if (st == 0) {
5172  // Notify the client
5173  reply << (Int_t)1;
5174  PDB(kPackage, 1)
5175  Info("HandleCheckFile",
5176  "package %s installed on node", filenam.Data());
5177  } else {
5178  if (st == -2) {
5179  Error("HandleCheckFile", "gunzip not found");
5180  } else {
5181  Error("HandleCheckFile", "package %s did not unpack into %s",
5182  filenam.Data(), packnam.Data());
5183  }
5184  reply << (Int_t)0;
5185  if (fProtocol <= 19) reply.Reset(kPROOF_FATAL);
5186  err = kTRUE;
5187  }
5188  } else {
5189  reply << (Int_t)0;
5190  if (fProtocol <= 19) reply.Reset(kPROOF_FATAL);
5191  err = kTRUE;
5192  PDB(kPackage, 1)
5193  Error("HandleCheckFile",
5194  "package %s not yet on node", filenam.Data());
5195  }
5196 
5197  // Note: Originally an fPackageLock->Unlock() call was made
5198  // after the if-else statement below. With multilevel masters,
5199  // submasters still check to make sure the package exists with
5200  // the correct md5 checksum and need to do a read lock there.
5201  // As yet locking is not that sophisicated so the lock must
5202  // be released below before the call to fProof->UploadPackage().
5203  if (err) {
5204  // delete par file in case of error
5205  fPackMgr->Remove(filenam);
5206  } else if (IsMaster()) {
5207  // forward to workers
5208  TString parpath;
5209  fPackMgr->GetParPath(filenam, parpath);
5210  if (fProof->UploadPackage(parpath,
5211  (TProof::EUploadPackageOpt)opt) != 0)
5212  Info("HandleCheckFile",
5213  "problems uploading package %s", parpath.Data());
5214  }
5215  delete md5local;
5216  fSocket->Send(reply);
5217 
5218  } else if (filenam.BeginsWith("+") || filenam.BeginsWith("=")) {
5219  filenam.Remove(0,1);
5220 
5221  TString parname = filenam;
5222  // If remote install it from there
5223  TFile::EFileType ft = TFile::GetType(filenam);
5224  if (ft == TFile::kWeb || ft == TFile::kNet) {
5225  parname = gSystem->BaseName(filenam);
5226  if (fPackMgr->Install(filenam) < 0) {
5227  Warning("HandleCheckFile",
5228  "problems installing package %s", filenam.Data());
5229 
5230  }
5231  }
5232 
5233  // check file in package directory
5234  TMD5 *md5local = fPackMgr->ReadMD5(parname);
5235 
5236  if (md5local && md5 == (*md5local)) {
5237  // package already on server, unlock directory
5238  reply << (Int_t)1;
5239  PDB(kPackage, 1)
5240  Info("HandleCheckFile",
5241  "package %s already on node", parname.Data());
5242  if (IsMaster()) {
5243  Int_t xrc = 0;
5244  TString par = filenam;
5245  if (ft != TFile::kWeb && ft != TFile::kNet) {
5246  xrc = fPackMgr->GetParPath(filenam, par);
5247  }
5248  if (xrc == 0) {
5249  if (fProof->UploadPackage(par) != 0)
5250  Warning("HandleCheckFile",
5251  "problems uploading package %s", par.Data());
5252  }
5253  }
5254 
5255  } else {
5256  reply << (Int_t)0;
5257  if (fProtocol <= 19) reply.Reset(kPROOF_FATAL);
5258  PDB(kPackage, 1)
5259  Info("HandleCheckFile",
5260  "package %s not yet on node", filenam.Data());
5261  }
5262  delete md5local;
5263  fSocket->Send(reply);
5264 
5265  } else {
5266  // check file in cache directory
5267  TString cachef = fCacheDir + "/" + filenam;
5268  fCacheLock->Lock();
5269  TMD5 *md5local = TMD5::FileChecksum(cachef);
5270 
5271  if (md5local && md5 == (*md5local)) {
5272  reply << (Int_t)1;
5273  PDB(kCache, 1)
5274  Info("HandleCheckFile", "file %s already on node", filenam.Data());
5275  } else {
5276  reply << (Int_t)0;
5277  if (fProtocol <= 19) reply.Reset(kPROOF_FATAL);
5278  PDB(kCache, 1)
5279  Info("HandleCheckFile", "file %s not yet on node", filenam.Data());
5280  }
5281  delete md5local;
5282  fSocket->Send(reply);
5283  fCacheLock->Unlock();
5284  }
5285 }
5286 
5287 ////////////////////////////////////////////////////////////////////////////////
5288 /// Handle here all cache and package requests.
5289 
5291 {
5292  PDB(kGlobal, 1)
5293  Info("HandleCache", "Enter");
5294 
5295  Int_t status = 0;
5296  Int_t type = 0;
5297  Bool_t all = kFALSE;
5298  TMessage msg;
5299  Bool_t fromglobal = kFALSE;
5300  Int_t chkveropt = TPackMgr::kCheckROOT; // Default: check ROOT version
5301  TPackMgr *packmgr = 0;
5302 
5303  // Notification message
5304  TString noth;
5305  const char *k = (IsMaster()) ? "Mst" : "Wrk";
5306  noth.Form("%s-%s", k, fOrdinal.Data());
5307 
5308  TList *optls = 0;
5309  TString packagedir, package, pdir, ocwd, file;
5310  (*mess) >> type;
5311  switch (type) {
5312  case TProof::kShowCache:
5313  (*mess) >> all;
5314  printf("*** File cache %s:%s ***\n", gSystem->HostName(),
5315  fCacheDir.Data());
5316  fflush(stdout);
5317  PDB(kCache, 1) {
5318  gSystem->Exec(TString::Format("%s -a %s", kLS, fCacheDir.Data()));
5319  } else {
5320  gSystem->Exec(TString::Format("%s %s", kLS, fCacheDir.Data()));
5321  }
5322  if (IsMaster() && all)
5323  fProof->ShowCache(all);
5324  LogToMaster();
5325  if (slb) slb->Form("%d %d", type, all);
5326  break;
5327  case TProof::kClearCache:
5328  file = "";
5329  if ((mess->BufferSize() > mess->Length())) (*mess) >> file;
5330  fCacheLock->Lock();
5331  if (file.IsNull() || file == "*") {
5332  gSystem->Exec(TString::Format("%s %s/* %s/.*.binversion", kRM, fCacheDir.Data(), fCacheDir.Data()));
5333  } else {
5334  gSystem->Exec(TString::Format("%s %s/%s", kRM, fCacheDir.Data(), file.Data()));
5335  }
5336  fCacheLock->Unlock();
5337  if (IsMaster())
5338  fProof->ClearCache(file);
5339  if (slb) slb->Form("%d %s", type, file.Data());
5340  break;
5341  case TProof::kShowPackages:
5342  (*mess) >> all;
5343  fPackMgr->Show();
5344  if (IsMaster() && all)
5345  fProof->ShowPackages(all);
5346  LogToMaster();
5347  if (slb) slb->Form("%d %d", type, all);
5348  break;
5350  if ((status = fPackMgr->Unload(0)) == 0) {
5351  fPackMgr->Remove();
5352  if (IsMaster())
5353  status = fProof->ClearPackages();
5354  }
5355  if (slb) slb->Form("%d %d", type, status);
5356  break;
5357  case TProof::kClearPackage:
5358  (*mess) >> package;
5359  if ((status = fPackMgr->Unload(package)) == 0) {
5360  fPackMgr->Remove(package);
5361  if (IsMaster())
5362  status = fProof->ClearPackage(package);
5363  }
5364  if (slb) slb->Form("%d %s %d", type, package.Data(), status);
5365  break;
5366  case TProof::kBuildPackage:
5367  (*mess) >> package;
5368  if ((mess->BufferSize() > mess->Length())) (*mess) >> chkveropt;
5369 
5370  if (!(packmgr = TPackMgr::GetPackMgr(package.Data(), fPackMgr))) {
5371  // Package not found
5372  SendAsynMessage(TString::Format("%s: kBuildPackage: failure locating %s ...",
5373  noth.Data(), package.Data()));
5374  status = -1;
5375  break;
5376  }
5377  fromglobal = (packmgr == fPackMgr) ? kFALSE : kTRUE;
5378  packagedir = packmgr->GetTitle();
5379 
5380  if (IsMaster() && !fromglobal) {
5381  // Make sure package is available on all slaves, even new ones
5382  TString par;
5383  Int_t xrc = packmgr->GetParPath(package, par);
5384  if (xrc != 0 || fProof->UploadPackage(par) != 0) {
5385  Warning("HandleCache",
5386  "kBuildPackage: problems forwarding package %s to workers", package.Data());
5387  SendAsynMessage(TString::Format("%s: kBuildPackage: problems forwarding package %s to workers ...",
5388  noth.Data(), package.Data()));
5389  }
5390  }
5391 
5392  if (!status) {
5393 
5394  PDB(kPackage, 1)
5395  Info("HandleCache",
5396  "kBuildPackage: package %s exists and has PROOF-INF directory", package.Data());
5397 
5398  // Forward build command to slaves, but don't wait for results
5399  if (IsMaster())
5401 
5402  // Build here
5403  status = packmgr->Build(package.Data(), chkveropt);
5404  }
5405 
5406  if (status) {
5407  // Notify the upper level
5408  SendAsynMessage(TString::Format("%s: failure building %s ... (status: %d)", noth.Data(), package.Data(), status));
5409  } else {
5410  // collect built results from slaves
5411  if (IsMaster())
5412  status = fProof->BuildPackage(package, TProof::kCollectBuildResults);
5413  PDB(kPackage, 1)
5414  Info("HandleCache", "package %s successfully built", package.Data());
5415  }
5416  if (slb) slb->Form("%d %s %d %d", type, package.Data(), status, chkveropt);
5417  break;
5418 
5419  case TProof::kLoadPackage:
5420  (*mess) >> package;
5421 
5422  // Get argument, if any
5423  if ((mess->BufferSize() > mess->Length())) (*mess) >> optls;
5424  // Load the package
5425  if ((status = fPackMgr->Load(package.Data(), optls)) < 0) {
5426 
5427  // Notify the upper level
5428  SendAsynMessage(TString::Format("%s: failure loading %s, args: %p (%d) ...",
5429  noth.Data(), package.Data(), optls,
5430  (optls && optls->GetSize() > 0) ? optls->GetSize() : 0));
5431 
5432  } else {
5433 
5434  if (IsMaster()) {
5435  if (optls && optls->GetSize() > 0) {
5436  // List argument
5437  status = fProof->LoadPackage(package, kFALSE, optls);
5438  } else {
5439  // No argument
5440  status = fProof->LoadPackage(package);
5441  }
5442  }
5443 
5444  PDB(kPackage, 1)
5445  Info("HandleCache", "package %s successfully loaded", package.Data());
5446  }
5447 
5448  if (slb) slb->Form("%d %s %d", type, package.Data(), status);
5449  break;
5450 
5452  (*mess) >> all;
5453  { TString title("*** Enabled packages ***");
5454  if (!IsMaster() || all) {
5455  title.Form("*** Enabled packages on %s %s on %s",
5456  (IsMaster()) ? "master" : "worker",
5457  fOrdinal.Data(), gSystem->HostName());
5458  }
5459  fPackMgr->ShowEnabled(title);
5460  }
5461  if (IsMaster() && all)
5463  LogToMaster();
5464  if (slb) slb->Form("%d %d", type, all);
5465  break;
5466  case TProof::kShowSubCache:
5467  (*mess) >> all;
5468  if (IsMaster() && all)
5469  fProof->ShowCache(all);
5470  LogToMaster();
5471  if (slb) slb->Form("%d %d", type, all);
5472  break;
5474  file = "";
5475  if ((mess->BufferSize() > mess->Length())) (*mess) >> file;
5476  if (IsMaster())
5477  fProof->ClearCache(file);
5478  if (slb) slb->Form("%d %s", type, file.Data());
5479  break;
5481  (*mess) >> all;
5482  if (IsMaster() && all)
5483  fProof->ShowPackages(all);
5484  LogToMaster();
5485  if (slb) slb->Form("%d %d", type, all);
5486  break;
5488  if (IsMaster())
5490  if (slb) slb->Form("%d", type);
5491  break;
5493  (*mess) >> package;
5494  if (IsMaster())
5495  fProof->DisablePackage(package);
5496  if (slb) slb->Form("%d %s", type, package.Data());
5497  break;
5499  (*mess) >> package;
5500  if ((mess->BufferSize() > mess->Length())) (*mess) >> chkveropt;
5501  if (IsMaster())
5502  fProof->BuildPackage(package, TProof::kBuildAll, chkveropt);
5503  if (slb) slb->Form("%d %s %d", type, package.Data(), chkveropt);
5504  break;
5506  (*mess) >> package;
5507  status = fPackMgr->Unload(package);
5508  if (IsMaster() && status == 0)
5509  status = fProof->UnloadPackage(package);
5510  if (slb) slb->Form("%d %s %d", type, package.Data(), status);
5511  break;
5513  (*mess) >> package;
5514  fPackMgr->Remove(package);
5515  if (IsMaster())
5516  fProof->DisablePackage(package);
5517  if (slb) slb->Form("%d %s", type, package.Data());
5518  break;
5520  status = fPackMgr->Unload(0);
5521  if (IsMaster() && status == 0)
5522  status = fProof->UnloadPackages();
5523  if (slb) slb->Form("%d %s %d", type, package.Data(), status);
5524  break;
5526  fPackMgr->Remove();
5527  if (IsMaster())
5529  if (slb) slb->Form("%d %s", type, package.Data());
5530  break;
5533  { TList *epl = fPackMgr->GetListOfEnabled();
5534  msg << type << epl;
5535  fSocket->Send(msg);
5536  epl->SetOwner();
5537  delete epl;
5538  }
5539  if (slb) slb->Form("%d", type);
5540  break;
5541  case TProof::kListPackages:
5542  {
5543  TList *pack = fPackMgr->GetList();
5545  msg << type << pack;
5546  fSocket->Send(msg);
5547  pack->SetOwner(kTRUE);
5548  delete pack;
5549  }
5550  if (slb) slb->Form("%d", type);
5551  break;
5552  case TProof::kLoadMacro:
5553  {
5554  (*mess) >> package;
5555 
5556  // By first forwarding the load command to the unique workers
5557  // and only then loading locally we load/build in parallel
5558  if (IsMaster())
5559  fProof->Load(package, kFALSE, kTRUE);
5560 
5561  // Atomic action
5562  fCacheLock->Lock();
5563 
5564  TString originalCwd = gSystem->WorkingDirectory();
5566 
5567  // Load the macro
5568  TString pack(package);
5569  Ssiz_t from = 0;
5570  if ((from = pack.Index(",")) != kNPOS) pack.Remove(from);
5571  Info("HandleCache", "loading macro %s ...", pack.Data());
5572  gROOT->ProcessLine(TString::Format(".L %s", pack.Data()));
5573 
5574  // Release atomicity
5575  gSystem->ChangeDirectory(originalCwd.Data());
5576  fCacheLock->Unlock();
5577 
5578  // Now we collect the result from the unique workers and send the load request
5579  // to the other workers (no compilation)
5580  if (IsMaster())
5581  fProof->Load(package, kFALSE, kFALSE);
5582 
5583  // Notify the upper level
5584  LogToMaster();
5585 
5586  if (slb) slb->Form("%d %s", type, package.Data());
5587  }
5588  break;
5589  default:
5590  Error("HandleCache", "unknown type %d", type);
5591  break;
5592  }
5593 
5594  // We are done
5595  return status;
5596 }
5597 
5598 ////////////////////////////////////////////////////////////////////////////////
5599 /// Handle here all requests to modify worker lists
5600 
5602 {
5603  PDB(kGlobal, 1)
5604  Info("HandleWorkerLists", "Enter");
5605 
5606  Int_t type = 0, rc = 0;
5607  TString ord;
5608 
5609  (*mess) >> type;
5610 
5611  switch (type) {
5613  (*mess) >> ord;
5614  if (ord != "*" && !ord.BeginsWith(GetOrdinal()) && ord != "restore") break;
5615  if (fProof) {
5617  Int_t nactmax = fProof->GetListOfSlaves()->GetSize() -
5619  if (nact < nactmax || !IsEndMaster()) {
5620  Int_t nwc = fProof->ActivateWorker(ord);
5621  Int_t nactnew = fProof->GetListOfActiveSlaves()->GetSize();
5622  if (ord == "*") {
5623  if (nactnew == nactmax) {
5624  PDB(kGlobal, 1) Info("HandleWorkerList", "all workers (re-)activated");
5625  } else {
5626  if (IsEndMaster())
5627  PDB(kGlobal, 1) Info("HandleWorkerList", "%d workers could not be (re-)activated", nactmax - nactnew);
5628  }
5629  } else if (ord == "restore") {
5630  if (nwc > 0) {
5631  PDB(kGlobal, 1) Info("HandleWorkerList","active worker(s) restored");
5632  } else {
5633  Error("HandleWorkerList", "some active worker(s) could not be restored; check logs");
5634  }
5635  } else {
5636  if (nactnew == (nact + nwc)) {
5637  if (nwc > 0)
5638  PDB(kGlobal, 1) Info("HandleWorkerList","worker(s) %s (re-)activated", ord.Data());
5639  } else {
5640  if (nwc != -2 && IsEndMaster()) {
5641  Error("HandleWorkerList", "some worker(s) could not be (re-)activated;"
5642  " # of actives: %d --> %d (nwc: %d)",
5643  nact, nactnew, nwc);
5644  }
5645  rc = (nwc < 0) ? nwc : -1;
5646  }
5647  }
5648  } else {
5649  PDB(kGlobal, 1) Info("HandleWorkerList","all workers are already active");
5650  }
5651  } else {
5652  Warning("HandleWorkerList","undefined PROOF session: protocol error?");
5653  }
5654  break;
5656  (*mess) >> ord;
5657  if (ord != "*" && !ord.BeginsWith(GetOrdinal()) && ord != "restore") break;
5658  if (fProof) {
5660  if (nact > 0) {
5661  Int_t nwc = fProof->DeactivateWorker(ord);
5662  Int_t nactnew = fProof->GetListOfActiveSlaves()->GetSize();
5663  if (ord == "*") {
5664  if (nactnew == 0) {
5665  PDB(kGlobal, 1) Info("HandleWorkerList","all workers deactivated");
5666  } else {
5667  if (IsEndMaster())
5668  PDB(kGlobal, 1) Info("HandleWorkerList","%d workers could not be deactivated", nactnew);
5669  }
5670  } else {
5671  if (nactnew == (nact - nwc)) {
5672  if (nwc > 0)
5673  PDB(kGlobal, 1) Info("HandleWorkerList","worker(s) %s deactivated", ord.Data());
5674  } else {
5675  if (nwc != -2 && IsEndMaster()) {
5676  Error("HandleWorkerList", "some worker(s) could not be deactivated:"
5677  " # of actives: %d --> %d (nwc: %d)",
5678  nact, nactnew, nwc);
5679  }
5680  rc = (nwc < 0) ? nwc : -1;
5681  }
5682  }
5683  } else {
5684  PDB(kGlobal, 1) Info("HandleWorkerList","all workers are already inactive");
5685  }
5686  } else {
5687  Warning("HandleWorkerList","undefined PROOF session: protocol error?");
5688  }
5689  break;
5690  default:
5691  Warning("HandleWorkerList","unknown action type (%d)", type);
5692  rc = -1;
5693  }
5694  // Done
5695  return rc;
5696 }
5697 
5698 ////////////////////////////////////////////////////////////////////////////////
5699 /// Get list of workers to be used from now on.
5700 /// The list must be provided by the caller.
5701 
5703  Int_t & /* prioritychange */,
5704  Bool_t /* resume */)
5705 {
5706  // Parse the config file
5707  TProofResourcesStatic *resources =
5709  fConfFile = resources->GetFileName(); // Update the global file name (with path)
5710  PDB(kGlobal,1)
5711  Info("GetWorkers", "using PROOF config file: %s", fConfFile.Data());
5712 
5713  // Get the master
5714  TProofNodeInfo *master = resources->GetMaster();
5715  if (!master) {
5716  PDB(kAll,1)
5717  Info("GetWorkers",
5718  "no appropriate master line found in %s", fConfFile.Data());
5719  return kQueryStop;
5720  } else {
5721  // Set image if not yet done and available
5722  if (fImage.IsNull() && strlen(master->GetImage()) > 0)
5723  fImage = master->GetImage();
5724  }
5725 
5726  // Fill submaster or worker list
5727  if (workers) {
5728  if (resources->GetSubmasters() && resources->GetSubmasters()->GetSize() > 0) {
5729  PDB(kAll,1)
5730  resources->GetSubmasters()->Print();
5731  TProofNodeInfo *ni = 0;
5732  TIter nw(resources->GetSubmasters());
5733  while ((ni = (TProofNodeInfo *) nw()))
5734  workers->Add(new TProofNodeInfo(*ni));
5735  } else if (resources->GetWorkers() && resources->GetWorkers()->GetSize() > 0) {
5736  PDB(kAll,1)
5737  resources->GetWorkers()->Print();
5738  TProofNodeInfo *ni = 0;
5739  TIter nw(resources->GetWorkers());
5740  while ((ni = (TProofNodeInfo *) nw()))
5741  workers->Add(new TProofNodeInfo(*ni));
5742  }
5743  }
5744 
5745  // We are done
5746  return kQueryOK;
5747 }
5748 
5749 ////////////////////////////////////////////////////////////////////////////////
5750 /// Set the file stream where to log (default stderr).
5751 /// If ferr == 0 the default is restored.
5752 /// Returns current setting.
5753 
5755 {
5756  FILE *oldferr = fgErrorHandlerFile;
5757  fgErrorHandlerFile = (ferr) ? ferr : stderr;
5758  return oldferr;
5759 }
5760 
5761 ////////////////////////////////////////////////////////////////////////////////
5762 /// The PROOF error handler function. It prints the message on fgErrorHandlerFile and
5763 /// if abort is set it aborts the application.
5764 
5765 void TProofServ::ErrorHandler(Int_t level, Bool_t abort, const char *location,
5766  const char *msg)
5767 {
5768  if (gErrorIgnoreLevel == kUnset) {
5769  gErrorIgnoreLevel = 0;
5770  if (gEnv) {
5771  TString lvl = gEnv->GetValue("Root.ErrorIgnoreLevel", "Print");
5772  if (!lvl.CompareTo("Print", TString::kIgnoreCase))
5774  else if (!lvl.CompareTo("Info", TString::kIgnoreCase))
5776  else if (!lvl.CompareTo("Warning", TString::kIgnoreCase))
5778  else if (!lvl.CompareTo("Error", TString::kIgnoreCase))
5780  else if (!lvl.CompareTo("Break", TString::kIgnoreCase))
5782  else if (!lvl.CompareTo("SysError", TString::kIgnoreCase))
5784  else if (!lvl.CompareTo("Fatal", TString::kIgnoreCase))
5786  }
5787  }
5788 
5789  if (level < gErrorIgnoreLevel)
5790  return;
5791 
5792  // Always communicate errors via SendLogFile
5793  if (level >= kError && gProofServ)
5794  gProofServ->LogToMaster();
5795 
5796  Bool_t tosyslog = (fgLogToSysLog > 2) ? kTRUE : kFALSE;
5797 
5798  const char *type = 0;
5799  ELogLevel loglevel = kLogInfo;
5800 
5801  Int_t ipos = (location) ? strlen(location) : 0;
5802 
5803  if (level >= kPrint) {
5804  loglevel = kLogInfo;
5805  type = "Print";
5806  }
5807  if (level >= kInfo) {
5808  loglevel = kLogInfo;
5809  char *ps = location ? (char *) strrchr(location, '|') : (char *)0;
5810  if (ps) {
5811  ipos = (int)(ps - (char *)location);
5812  type = "SvcMsg";
5813  } else {
5814  type = "Info";
5815  }
5816  }
5817  if (level >= kWarning) {
5818  loglevel = kLogWarning;
5819  type = "Warning";
5820  }
5821  if (level >= kError) {
5822  loglevel = kLogErr;
5823  type = "Error";
5824  }
5825  if (level >= kBreak) {
5826  loglevel = kLogErr;
5827  type = "*** Break ***";
5828  }
5829  if (level >= kSysError) {
5830  loglevel = kLogErr;
5831  type = "SysError";
5832  }
5833  if (level >= kFatal) {
5834  loglevel = kLogErr;
5835  type = "Fatal";
5836  }
5837 
5838 
5839  TString buf;
5840 
5841  // Time stamp
5842  TTimeStamp ts;
5843  TString st(ts.AsString("lc"),19);
5844 
5845  if (!location || ipos == 0 ||
5846  (level >= kPrint && level < kInfo) ||
5847  (level >= kBreak && level < kSysError)) {
5848  fprintf(fgErrorHandlerFile, "%s %5d %s | %s: %s\n", st(11,8).Data(),
5849  gSystem->GetPid(),
5850  (gProofServ ? gProofServ->GetPrefix() : "proof"),
5851  type, msg);
5852  if (tosyslog)
5853  buf.Form("%s: %s:%s", fgSysLogEntity.Data(), type, msg);
5854  } else {
5855  fprintf(fgErrorHandlerFile, "%s %5d %s | %s in <%.*s>: %s\n", st(11,8).Data(),
5856  gSystem->GetPid(),
5857  (gProofServ ? gProofServ->GetPrefix() : "proof"),
5858  type, ipos, location, msg);
5859  if (tosyslog)
5860  buf.Form("%s: %s:<%.*s>: %s", fgSysLogEntity.Data(), type, ipos, location, msg);
5861  }
5862  fflush(fgErrorHandlerFile);
5863 
5864  if (tosyslog)
5865  gSystem->Syslog(loglevel, buf);
5866 
5867 #ifdef __APPLE__
5868  if (__crashreporter_info__)
5869  delete [] __crashreporter_info__;
5870  __crashreporter_info__ = StrDup(buf);
5871 #endif
5872 
5873  if (abort) {
5874 
5875  static Bool_t recursive = kFALSE;
5876 
5877  if (gProofServ != 0 && !recursive) {
5878  recursive = kTRUE;
5879  if (gProofServ->GetSocket()) gProofServ->GetSocket()->Send(kPROOF_FATAL);
5880  recursive = kFALSE;
5881  }
5882 
5883  fprintf(fgErrorHandlerFile, "aborting\n");
5884  fflush(fgErrorHandlerFile);
5885  gSystem->StackTrace();
5886  gSystem->Abort();
5887  }
5888 }
5889 
5890 ////////////////////////////////////////////////////////////////////////////////
5891 /// Make player instance.
5892 
5894 {
5895  TVirtualProofPlayer *p = 0;
5896 
5897  // Cleanup first
5898  DeletePlayer();
5899 
5900  if (IsParallel()) {
5901  // remote mode
5902  p = fProof->MakePlayer();
5903  } else {
5904  // slave or sequential mode
5905  p = TVirtualProofPlayer::Create("slave", 0, fSocket);
5906  if (IsMaster())
5907  fProof->SetPlayer(p);
5908  }
5909 
5910  // set player
5911  fPlayer = p;
5912 }
5913 
5914 ////////////////////////////////////////////////////////////////////////////////
5915 /// Delete player instance.
5916 
5918 {
5919  if (IsMaster()) {
5920  PDB(kGlobal, 1) {
5921  fCompute.Stop();
5922  Printf(" +++ Latest processing times: %f s (CPU: %f s)",
5924  }
5925  if (fProof) fProof->SetPlayer(0);
5926  } else {
5928  }
5929  fPlayer = 0;
5930 }
5931 
5932 ////////////////////////////////////////////////////////////////////////////////
5933 /// Get the processing priority for the group the user belongs too. This
5934 /// priority is a number (0 - 100) determined by a scheduler (third
5935 /// party process) based on some basic priority the group has, e.g.
5936 /// we might want to give users in a specific group (e.g. promptana)
5937 /// a higher priority than users in other groups, and on the analysis
5938 /// of historical logging data (i.e. usage of CPU by the group in a
5939 /// previous time slot, as recorded in TPerfStats::WriteQueryLog()).
5940 ///
5941 /// Currently the group priority is obtained by a query in a SQL DB
5942 /// table proofpriority, which has the format:
5943 /// CREATE TABLE proofpriority (
5944 /// id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
5945 /// group VARCHAR(32) NOT NULL,
5946 /// priority INT
5947 ///)
5948 
5950 {
5951  TString sqlserv = gEnv->GetValue("ProofServ.QueryLogDB","");
5952  TString sqluser = gEnv->GetValue("ProofServ.QueryLogUser","");
5953  TString sqlpass = gEnv->GetValue("ProofServ.QueryLogPasswd","");
5954 
5955  Int_t priority = 100;
5956 
5957  if (sqlserv == "")
5958  return priority;
5959 
5960  TString sql;
5961  sql.Form("SELECT priority WHERE group='%s' FROM proofpriority", fGroup.Data());
5962 
5963  // open connection to SQL server
5964  TSQLServer *db = TSQLServer::Connect(sqlserv, sqluser, sqlpass);
5965 
5966  if (!db || db->IsZombie()) {
5967  Error("GetPriority", "failed to connect to SQL server %s as %s %s",
5968  sqlserv.Data(), sqluser.Data(), sqlpass.Data());
5969  printf("%s\n", sql.Data());
5970  } else {
5971  TSQLResult *res = db->Query(sql);
5972 
5973  if (!res) {
5974  Error("GetPriority", "query into proofpriority failed");
5975  Printf("%s", sql.Data());
5976  } else {
5977  TSQLRow *row = res->Next(); // first row is header
5978  if (row) {
5979  priority = atoi(row->GetField(0));
5980  delete row;
5981  } else {
5982  Error("GetPriority", "first row is header is NULL");
5983  }
5984  }
5985  delete res;
5986  }
5987  delete db;
5988 
5989  return priority;
5990 }
5991 
5992 ////////////////////////////////////////////////////////////////////////////////
5993 /// Send an asychronous message to the master / client .
5994 /// Masters will forward up the message to the client.
5995 /// The client prints 'msg' of stderr and adds a '\n'/'\r' depending on
5996 /// 'lf' being kTRUE (default) or kFALSE.
5997 /// Returns the return value from TSocket::Send(TMessage &) .
5998 
5999 void TProofServ::SendAsynMessage(const char *msg, Bool_t lf)
6000 {
6001  static TMessage m(kPROOF_MESSAGE);
6002 
6003  // To leave a track in the output file ... if requested
6004  // (clients will be notified twice)
6005  PDB(kAsyn,1)
6006  Info("SendAsynMessage","%s", (msg ? msg : "(null)"));
6007 
6008  if (fSocket && msg) {
6009  m.Reset(kPROOF_MESSAGE);
6010  m << TString(msg) << lf;
6011  if (fSocket->Send(m) <= 0)
6012  Warning("SendAsynMessage",
6013  "could not send message '%s'", (msg ? msg : "(null)"));
6014  }
6015 
6016  return;
6017 }
6018 
6019 ////////////////////////////////////////////////////////////////////////////////
6020 /// Reposition the read pointer in the log file to the very end.
6021 /// This allows to "hide" useful debug messages during normal operations
6022 /// while preserving the possibility to have them in case of problems.
6023 
6025 {
6026  off_t lend = lseek(fileno(stdout), (off_t)0, SEEK_END);
6027  if (lend >= 0) lseek(fLogFileDes, lend, SEEK_SET);
6028 }
6029 
6030 ////////////////////////////////////////////////////////////////////////////////
6031 /// Truncate the log file to the 80% of the required max size if this
6032 /// is set.
6033 
6035 {
6036 #ifndef WIN32
6037  TString emsg;
6038  if (fLogFileMaxSize > 0 && fLogFileDes > 0) {
6039  fflush(stdout);
6040  struct stat st;
6041  if (fstat(fLogFileDes, &st) == 0) {
6042  if (st.st_size >= fLogFileMaxSize) {
6043  off_t truncsz = (off_t) (( fLogFileMaxSize * 80 ) / 100 );
6044  if (truncsz < 100) {
6045  emsg.Form("+++ WARNING +++: %s: requested truncate size too small"
6046  " (%lld,%lld) - ignore ", fPrefix.Data(), (Long64_t) truncsz, fLogFileMaxSize);
6047  SendAsynMessage(emsg.Data());
6048  return;
6049  }
6051  while (ftruncate(fileno(stdout), truncsz) != 0 &&
6052  (TSystem::GetErrno() == EINTR)) {
6054  }
6055  if (TSystem::GetErrno() > 0) {
6056  Error("TruncateLogFile", "truncating to %lld bytes; file size is %lld bytes (errno: %d)",
6057  (Long64_t)truncsz, (Long64_t)st.st_size, TSystem::GetErrno());
6058  emsg.Form("+++ WARNING +++: %s: problems truncating log file to %lld bytes; file size is %lld bytes"
6059  " (errno: %d)", fPrefix.Data(), (Long64_t)truncsz, (Long64_t)st.st_size, TSystem::GetErrno());
6060  SendAsynMessage(emsg.Data());
6061  } else {
6062  Info("TruncateLogFile", "file truncated to %lld bytes (80%% of %lld); file size was %lld bytes ",
6063  (Long64_t)truncsz, fLogFileMaxSize, (Long64_t)st.st_size);
6064  emsg.Form("+++ WARNING +++: %s: log file truncated to %lld bytes (80%% of %lld)",
6065  fPrefix.Data(), (Long64_t)truncsz, fLogFileMaxSize);
6066  SendAsynMessage(emsg.Data());
6067  }
6068  }
6069  } else {
6070  emsg.Form("+++ WARNING +++: %s: could not stat log file descriptor"
6071  " for truncation (errno: %d)", fPrefix.Data(), TSystem::GetErrno());
6072  SendAsynMessage(emsg.Data());
6073  }
6074  }
6075 #endif
6076 }
6077 
6078 ////////////////////////////////////////////////////////////////////////////////
6079 /// Exception handler: we do not try to recover here, just exit.
6080 
6082 {
6083  Error("HandleException", "caugth exception triggered by signal '%d' %s %lld",
6084  sig, fgLastMsg.Data(), fgLastEntry);
6085  // Description
6086  TString emsg;
6087  emsg.Form("%s: caught exception triggered by signal '%d' %s %lld",
6088  GetOrdinal(), sig, fgLastMsg.Data(), fgLastEntry);
6089  // Try to warn the user
6090  SendAsynMessage(emsg.Data());
6091 
6092  gSystem->Exit(sig);
6093 }
6094 
6095 ////////////////////////////////////////////////////////////////////////////////
6096 /// Handle here requests about datasets.
6097 
6099 {
6100  if (gDebug > 0)
6101  Info("HandleDataSets", "enter");
6102 
6103  // We need a dataset manager
6104  if (!fDataSetManager) {
6105  Warning("HandleDataSets", "no data manager is available to fullfil the request");
6106  return -1;
6107  }
6108 
6109  // Used in most cases
6110  TString dsUser, dsGroup, dsName, dsTree, uri, opt;
6111  Int_t rc = 0;
6112 
6113  // Invalid characters in dataset URI
6114  TPMERegexp reInvalid("[^A-Za-z0-9._-]"); // from ParseUri
6115 
6116  // Message type
6117  Int_t type = 0;
6118  (*mess) >> type;
6119 
6120  switch (type) {
6122  //
6123  // Check whether this dataset exist
6124  {
6125  (*mess) >> uri;
6126  if (slb) slb->Form("%d %s", type, uri.Data());
6127  if (fDataSetManager->ExistsDataSet(uri))
6128  // Dataset name does exist
6129  return -1;
6130  }
6131  break;
6133  // list size must be above 0
6134  {
6136  (*mess) >> uri;
6137  (*mess) >> opt;
6138  if (slb) slb->Form("%d %s %s", type, uri.Data(), opt.Data());
6139  // Extract the list
6140  TFileCollection *dataSet =
6141  dynamic_cast<TFileCollection*> ((mess->ReadObject(TFileCollection::Class())));
6142  if (!dataSet || dataSet->GetList()->GetSize() == 0) {
6143  Error("HandleDataSets", "can not save an empty list.");
6144  return -1;
6145  }
6146  // Register the dataset (quota checks are done inside here)
6147  rc = fDataSetManager->RegisterDataSet(uri, dataSet, opt);
6148  delete dataSet;
6149  return rc;
6150  } else {
6151  Info("HandleDataSets", "dataset registration not allowed");
6152  if (slb) slb->Form("%d notallowed", type);
6153  return -1;
6154  }
6155  }
6156  break;
6157 
6159  {
6160  (*mess) >> uri; // TString
6161 
6162  if (!fDataSetStgRepo) {
6163  Error("HandleDataSets",
6164  "no dataset staging request repository available");
6165  return -1;
6166  }
6167 
6168  // Transform input URI in a valid dataset name
6169  TString validUri = uri;
6170  while (reInvalid.Substitute(validUri, "_")) {}
6171 
6172  // Check if dataset exists beforehand: if it does, staging has
6173  // already been requested
6174  if (fDataSetStgRepo->ExistsDataSet(validUri.Data())) {
6175  Warning("HandleDataSets", "staging of %s already requested",
6176  uri.Data());
6177  return -1;
6178  }
6179 
6180  // Try to get dataset from current manager
6181  TFileCollection *fc = fDataSetManager->GetDataSet(uri.Data());
6182  if (!fc || (fc->GetNFiles() == 0)) {
6183  Error("HandleDataSets", "empty dataset or no dataset returned");
6184  if (fc) delete fc;
6185  return -1;
6186  }
6187 
6188  // Reset all staged bits and remove unnecessary URLs (all but last)
6189  TIter it(fc->GetList());
6190  TFileInfo *fi;
6191  while ((fi = dynamic_cast<TFileInfo *>(it.Next()))) {
6193  Int_t nToErase = fi->GetNUrls() - 1;
6194  for (Int_t i=0; i<nToErase; i++)
6195  fi->RemoveUrlAt(0);
6196  }
6197 
6198  fc->Update(); // absolutely necessary
6199 
6200  // Save request
6201  fDataSetStgRepo->ParseUri(validUri, &dsGroup, &dsUser, &dsName);
6202  if (fDataSetStgRepo->WriteDataSet(dsGroup, dsUser,
6203  dsName, fc) == 0) {
6204  // Error, can't save dataset
6205  Error("HandleDataSets",
6206  "can't register staging request for %s", uri.Data());
6207  delete fc;
6208  return -1;
6209  }
6210 
6211  Info("HandleDataSets",
6212  "Staging request registered for %s", uri.Data());
6213 
6214  delete fc;
6215  return 0; // success (-1 == failure)
6216  }
6217  break;
6218 
6220  {
6221  if (!fDataSetStgRepo) {
6222  Error("HandleDataSets",
6223  "no dataset staging request repository available");
6224  return -1;
6225  }
6226 
6227  (*mess) >> uri; // TString
6228 
6229  // Transform URI in a valid dataset name
6230  while (reInvalid.Substitute(uri, "_")) {}
6231 
6232  // Get the list
6233  TFileCollection *fc = fDataSetStgRepo->GetDataSet(uri.Data());
6234  if (fc) {
6235  fSocket->SendObject(fc, kMESS_OK);
6236  delete fc;
6237  return 0;
6238  }
6239  else {
6240  // No such dataset: not an error, but don't send message
6241  Info("HandleDataSets", "no pending staging request for %s",
6242  uri.Data());
6243  return 0;
6244  }
6245  }
6246  break;
6247 
6249  {
6250  if (!fDataSetStgRepo) {
6251  Error("HandleDataSets",
6252  "no dataset staging request repository available");
6253  return -1;
6254  }
6255 
6256  (*mess) >> uri;
6257 
6258  // Transform URI in a valid dataset name
6259  while (reInvalid.Substitute(uri, "_")) {}
6260 
6261  if (!fDataSetStgRepo->RemoveDataSet(uri.Data()))
6262  return -1; // failure
6263 
6264  return 0; // success
6265  }
6266  break;
6267 
6268  case TProof::kShowDataSets:
6269  {
6270  (*mess) >> uri >> opt;
6271  if (slb) slb->Form("%d %s %s", type, uri.Data(), opt.Data());
6272  // Show content
6273  fDataSetManager->ShowDataSets(uri, opt);
6274  }
6275  break;
6276 
6277  case TProof::kGetDataSets:
6278  {
6279  (*mess) >> uri >> opt;
6280  if (slb) slb->Form("%d %s %s", type, uri.Data(), opt.Data());
6281  // Get the datasets and fill a map
6283  Ssiz_t kLite = opt.Index(":lite:", 0, TString::kIgnoreCase);
6284  if (kLite != kNPOS) {
6286  opt.Remove(kLite, strlen(":lite:"));
6287  }
6288  TMap *returnMap = fDataSetManager->GetDataSets(uri, omsk);
6289  // If defines, option gives the name of a server for which to extract the information
6290  if (returnMap && !opt.IsNull()) {
6291  // The return map will be in the form </group/user/datasetname> --> <dataset>
6292  TMap *rmap = new TMap;
6293  TObject *k = 0;
6294  TFileCollection *fc = 0, *xfc = 0;
6295  TIter nxd(returnMap);
6296  while ((k = nxd()) && (fc = (TFileCollection *) returnMap->GetValue(k))) {
6297  // Get subset on specified server, if any
6298  if ((xfc = fc->GetFilesOnServer(opt.Data()))) {
6299  rmap->Add(new TObjString(k->GetName()), xfc);
6300  }
6301  }
6302  returnMap->DeleteAll();
6303  if (rmap->GetSize() > 0) {
6304  returnMap = rmap;
6305  } else {
6306  Info("HandleDataSets", "no dataset found on server '%s'", opt.Data());
6307  delete rmap;
6308  returnMap = 0;
6309  }
6310  }
6311  if (returnMap) {
6312  // Send them back
6313  fSocket->SendObject(returnMap, kMESS_OK);
6314  returnMap->DeleteAll();
6315  } else {
6316  // Failure
6317  return -1;
6318  }
6319  }
6320  break;
6321  case TProof::kGetDataSet:
6322  {
6323  (*mess) >> uri >> opt;
6324  if (slb) slb->Form("%d %s %s", type, uri.Data(), opt.Data());
6325  // Get the list
6326  TFileCollection *fileList = fDataSetManager->GetDataSet(uri,opt);
6327  if (fileList) {
6328  fSocket->SendObject(fileList, kMESS_OK);
6329  delete fileList;
6330  } else {
6331  // Failure
6332  return -1;
6333  }
6334  }
6335  break;
6337  {
6339  (*mess) >> uri;
6340  if (slb) slb->Form("%d %s", type, uri.Data());
6341  if (!fDataSetManager->RemoveDataSet(uri)) {
6342  // Failure
6343  return -1;
6344  }
6345  } else {
6346  Info("HandleDataSets", "dataset creation / removal not allowed");
6347  if (slb) slb->Form("%d notallowed", type);
6348  return -1;
6349  }
6350  }
6351  break;
6353  {
6355  (*mess) >> uri >> opt;
6356  if (slb) slb->Form("%d %s %s", type, uri.Data(), opt.Data());
6358  rc = fDataSetManager->ScanDataSet(uri, opt);
6359  // TODO: verify in parallel:
6360  // - dataset = GetDataSet(uri)
6361  // - TList flist; TDataSetManager::ScanDataSet(dataset, ..., &flist)
6362  // - fPlayer->Process( ... flist ...) // needs to be developed
6363  // - dataset->Integrate(flist) (perhaps automatic; flist object owned by dataset)
6364  // - RegisterDataSet(uri, dataset, "OT")
6365  } else {
6366  Info("HandleDataSets", "dataset verification not allowed");
6367  return -1;
6368  }
6369  }
6370  break;
6371  case TProof::kGetQuota:
6372  {
6374  if (slb) slb->Form("%d", type);
6375  TMap *groupQuotaMap = fDataSetManager->GetGroupQuotaMap();
6376  if (groupQuotaMap) {
6377  // Send result
6378  fSocket->SendObject(groupQuotaMap, kMESS_OK);
6379  } else {
6380  return -1;
6381  }
6382  } else {
6383  Info("HandleDataSets", "quota control disabled");
6384  if (slb) slb->Form("%d disabled", type);
6385  return -1;
6386  }
6387  }
6388  break;
6389  case TProof::kShowQuota:
6390  {
6392  if (slb) slb->Form("%d", type);
6393  (*mess) >> opt;
6394  // Display quota information
6395  fDataSetManager->ShowQuota(opt);
6396  } else {
6397  Info("HandleDataSets", "quota control disabled");
6398  if (slb) slb->Form("%d disabled", type);
6399  }
6400  }
6401  break;
6403  {
6405  (*mess) >> uri;
6406  if (slb) slb->Form("%d %s", type, uri.Data());
6408  } else {
6409  Info("HandleDataSets", "kSetDefaultTreeName: modification of dataset info not allowed");
6410  if (slb) slb->Form("%d notallowed", type);
6411  return -1;
6412  }
6413  }
6414  break;
6415  case TProof::kCache:
6416  {
6417  (*mess) >> uri >> opt;
6418  if (slb) slb->Form("%d %s %s", type, uri.Data(), opt.Data());
6419  if (opt == "show") {
6420  // Show cache content
6421  fDataSetManager->ShowCache(uri);
6422  } else if (opt == "clear") {
6423  // Clear cache content
6425  } else {
6426  Error("HandleDataSets", "kCache: unknown action: %s", opt.Data());
6427  }
6428  }
6429  break;
6430  default:
6431  rc = -1;
6432  Error("HandleDataSets", "unknown type %d", type);
6433  break;
6434  }
6435 
6436  // We are done
6437  return rc;
6438 }
6439 
6440 ////////////////////////////////////////////////////////////////////////////////
6441 /// Handle a message of type kPROOF_SUBMERGER
6442 
6444 {
6445  // Message type
6446  Int_t type = 0;
6447  (*mess) >> type;
6448 
6449  TString msg;
6450  switch (type) {
6451  case TProof::kOutputSize:
6452  break;
6453 
6454  case TProof::kSendOutput:
6455  {
6456  Bool_t deleteplayer = kTRUE;
6457  if (!IsMaster()) {
6458  if (fMergingMonitor) {
6459  Info("HandleSubmerger", "kSendOutput: interrupting ...");
6461  }
6462  if (fMergingSocket) {
6464  fMergingSocket->Close();
6466  }
6467 
6468  TString name;
6469  Int_t port = 0;
6470  Int_t merger_id = -1;
6471  (*mess) >> merger_id >> name >> port;
6472  PDB(kSubmerger, 1)
6473  Info("HandleSubmerger","worker %s redirected to merger #%d %s:%d", fOrdinal.Data(), merger_id, name.Data(), port);
6474 
6475  TSocket *t = 0;
6476  if (name.Length() > 0 && port > 0 && (t = new TSocket(name, port)) && t->IsValid()) {
6477 
6478  PDB(kSubmerger, 2) Info("HandleSubmerger",
6479  "kSendOutput: worker asked for sending output to merger #%d %s:%d",
6480  merger_id, name.Data(), port);
6481 
6482  if (SendResults(t, fPlayer->GetOutputList()) != 0) {
6483  msg.Form("worker %s cannot send results to merger #%d at %s:%d", GetPrefix(), merger_id, name.Data(), port);
6484  PDB(kSubmerger, 2) Info("HandleSubmerger",
6485  "kSendOutput: %s - inform the master", msg.Data());
6486  SendAsynMessage(msg);
6487  // Results not send
6488  TMessage answ(kPROOF_SUBMERGER);
6489  answ << Int_t(TProof::kMergerDown);
6490  answ << merger_id;
6491  fSocket->Send(answ);
6492  } else {
6493  // Worker informs master that it had sent its output to the merger
6494  TMessage answ(kPROOF_SUBMERGER);
6495  answ << Int_t(TProof::kOutputSent);
6496  answ << merger_id;
6497  fSocket->Send(answ);
6498 
6499  PDB(kSubmerger, 2) Info("HandleSubmerger", "kSendOutput: worker sent its output");
6501  SetIdle(kTRUE);
6502  SendLogFile();
6503  }
6504  } else {
6505 
6506  if (name == "master") {
6507  PDB(kSubmerger, 2) Info("HandleSubmerger",
6508  "kSendOutput: worker was asked for sending output to master");
6509  if (SendResults(fSocket, fPlayer->GetOutputList()) != 0)
6510  Warning("HandleSubmerger", "problems sending output list");
6511  // Signal the master that we are idle
6513  SetIdle(kTRUE);
6514  SendLogFile();
6515 
6516  } else if (!t || !(t->IsValid())) {
6517  msg.Form("worker %s could not open a valid socket to merger #%d at %s:%d",
6518  GetPrefix(), merger_id, name.Data(), port);
6519  PDB(kSubmerger, 2) Info("HandleSubmerger",
6520  "kSendOutput: %s - inform the master", msg.Data());
6521  SendAsynMessage(msg);
6522  // Results not send
6523  TMessage answ(kPROOF_SUBMERGER);
6524  answ << Int_t(TProof::kMergerDown);
6525  answ << merger_id;
6526  fSocket->Send(answ);
6527  deleteplayer = kFALSE;
6528  }
6529 
6530  SafeDelete(t);
6531 
6532  }
6533 
6534  } else {
6535  Error("HandleSubmerger", "kSendOutput: received not on worker");
6536  }
6537 
6538  // Cleanup
6539  if (deleteplayer) DeletePlayer();
6540  }
6541  break;
6542  case TProof::kBeMerger:
6543  {
6544  Bool_t deleteplayer = kTRUE;
6545  if (!IsMaster()) {
6546  Int_t merger_id = -1;
6547  //Int_t merger_port = 0;
6548  Int_t connections = 0;
6549  (*mess) >> merger_id >> connections;
6550  PDB(kSubmerger, 2)
6551  Info("HandleSubmerger", "worker %s established as merger", fOrdinal.Data());
6552 
6553  PDB(kSubmerger, 2)
6554  Info("HandleSubmerger",
6555  "kBeMerger: worker asked for being merger #%d for %d connections",
6556  merger_id, connections);
6557 
6558  TVirtualProofPlayer *mergerPlayer = TVirtualProofPlayer::Create("remote",fProof,0);
6559 
6560  if (mergerPlayer) {
6561  PDB(kSubmerger, 2) Info("HandleSubmerger",
6562  "kBeMerger: mergerPlayer created (%p) ", mergerPlayer);
6563 
6564  // This may be used internally
6566 
6567  // Accept results from assigned workers
6568  if (AcceptResults(connections, mergerPlayer)) {
6569  PDB(kSubmerger, 2)
6570  Info("HandleSubmerger", "kBeMerger: all outputs from workers accepted");
6571 
6572  PDB(kSubmerger, 2)
6573  Info("","adding own output to the list on %s", fOrdinal.Data());
6574 
6575  // Add own results to the output list.
6576  // On workers the player does not own the output list, which is owned
6577  // by the selector and deleted in there
6578  // On workers the player does not own the output list, which is owned
6579  // by the selector and deleted in there
6580  TIter nxo(fPlayer->GetOutputList());
6581  TObject * o = 0;
6582  while ((o = nxo())) {
6583  if ((mergerPlayer->AddOutputObject(o) != 1)) {
6584  // Remove the object if it has not been merged: it is owned
6585  // now by the merger player (in its output list)
6586  if (fPlayer->GetOutputList()) {
6587  PDB(kSubmerger, 2)
6588  Info("HandleSocketInput", "removing merged object (%p)", o);
6589  fPlayer->GetOutputList()->Remove(o);
6590  }
6591  }
6592  }
6593  PDB(kSubmerger, 2) Info("HandleSubmerger","kBeMerger: own outputs added");
6594  PDB(kSubmerger, 2) Info("HandleSubmerger","starting delayed merging on %s", fOrdinal.Data());
6595 
6596  // Delayed merging if neccessary
6597  mergerPlayer->MergeOutput(kTRUE);
6598 
6599  PDB(kSubmerger, 2) mergerPlayer->GetOutputList()->Print("all");
6600 
6601  PDB(kSubmerger, 2) Info("HandleSubmerger", "delayed merging on %s finished ", fOrdinal.Data());
6602  PDB(kSubmerger, 2) Info("HandleSubmerger", "%s sending results to master ", fOrdinal.Data());
6603  // Send merged results to master
6604  if (SendResults(fSocket, mergerPlayer->GetOutputList()) != 0)
6605  Warning("HandleSubmerger","kBeMerger: problems sending output list");
6606  if (mergerPlayer->GetOutputList())
6607  mergerPlayer->GetOutputList()->SetOwner(kTRUE);
6608 
6609  PDB(kSubmerger, 2) Info("HandleSubmerger","kBeMerger: results sent to master");
6610  // Signal the master that we are idle
6612  SetIdle(kTRUE);
6613  SendLogFile();
6614  } else {
6615  // Results from all assigned workers not accepted
6616  TMessage answ(kPROOF_SUBMERGER);
6617  answ << Int_t(TProof::kMergerDown);
6618  answ << merger_id;
6619  fSocket->Send(answ);
6620  deleteplayer = kFALSE;
6621  }
6622  // Reset
6623  SafeDelete(mergerPlayer);
6624 
6625  } else {
6626  Warning("HandleSubmerger","kBeMerger: problems craeting the merger player!");
6627  // Results from all assigned workers not accepted
6628  TMessage answ(kPROOF_SUBMERGER);
6629  answ << Int_t(TProof::kMergerDown);
6630  answ << merger_id;
6631  fSocket->Send(answ);
6632  deleteplayer = kFALSE;
6633  }
6634  } else {
6635  Error("HandleSubmerger","kSendOutput: received not on worker");
6636  }
6637 
6638  // Cleanup
6639  if (deleteplayer) DeletePlayer();
6640  }
6641  break;
6642 
6643  case TProof::kMergerDown:
6644  break;
6645 
6646  case TProof::kStopMerging:
6647  {
6648  // Received only in case of forced termination of merger by master
6649  PDB(kSubmerger, 2) Info("HandleSubmerger", "kStopMerging");
6650  if (fMergingMonitor) {
6651  Info("HandleSubmerger", "kStopMerging: interrupting ...");
6653  }
6654  }
6655  break;
6656 
6657  case TProof::kOutputSent:
6658  break;
6659  }
6660 }
6661 
6662 ////////////////////////////////////////////////////////////////////////////////
6663 /// Cloning itself via fork. Not implemented
6664 
6666 {
6667  Info("HandleFork", "fork cloning not implemented");
6668 }
6669 
6670 ////////////////////////////////////////////////////////////////////////////////
6671 /// Fork a child.
6672 /// If successful, return 0 in the child process and the child pid in the parent
6673 /// process. The child pid is registered for reaping.
6674 /// Return <0 in the parent process in case of failure.
6675 
6677 {
6678 #ifndef WIN32
6679  // Fork
6680  pid_t pid;
6681  if ((pid = fork()) < 0) {
6682  Error("Fork", "failed to fork");
6683  return pid;
6684  }
6685 
6686  // Nothing else to do in the child
6687  if (!pid) return pid;
6688 
6689  // Make sure that the reaper timer is started
6690  if (!fReaperTimer) {
6691  fReaperTimer = new TReaperTimer(1000);
6692  fReaperTimer->Start(-1);
6693  }
6694 
6695  // Register the new child
6696  fReaperTimer->AddPid(pid);
6697 
6698  // Done
6699  return pid;
6700 #else
6701  Warning("Fork", "Functionality not provided under windows");
6702  return -1;
6703 #endif
6704 }
6705 
6706 ////////////////////////////////////////////////////////////////////////////////
6707 /// Replace <ord>, <user>, <u>, <group>, <stag>, <qnum>, <file>, <rver> and
6708 /// <build> placeholders in fname.
6709 /// Here, <rver> is the root version in integer form, e.g. 53403, and <build> a
6710 /// string includign version, architecture and compiler version, e.g.
6711 /// '53403_linuxx8664gcc_gcc46' .
6712 
6713 void TProofServ::ResolveKeywords(TString &fname, const char *path)
6714 {
6715  // Replace <user>, if any
6716  if (fname.Contains("<user>")) {
6717  if (gProofServ && gProofServ->GetUser() && strlen(gProofServ->GetUser())) {
6718  fname.ReplaceAll("<user>", gProofServ->GetUser());
6719  } else if (gProof && gProof->GetUser() && strlen(gProof->GetUser())) {
6720  fname.ReplaceAll("<user>", gProof->GetUser());
6721  } else {
6722  fname.ReplaceAll("<user>", "nouser");
6723  }
6724  }
6725  // Replace <us>, if any
6726  if (fname.Contains("<u>")) {
6727  if (gProofServ && gProofServ->GetUser() && strlen(gProofServ->GetUser())) {
6728  TString u(gProofServ->GetUser()[0]);
6729  fname.ReplaceAll("<u>", u);
6730  } else if (gProof && gProof->GetUser() && strlen(gProof->GetUser())) {
6731  TString u(gProof->GetUser()[0]);
6732  fname.ReplaceAll("<u>", u);
6733  } else {
6734  fname.ReplaceAll("<u>", "n");
6735  }
6736  }
6737  // Replace <group>, if any
6738  if (fname.Contains("<group>")) {
6739  if (gProofServ && gProofServ->GetGroup() && strlen(gProofServ->GetGroup())) {
6740  fname.ReplaceAll("<group>", gProofServ->GetGroup());
6741  } else if (gProof && gProof->GetGroup() && strlen(gProof->GetGroup())) {
6742  fname.ReplaceAll("<group>", gProof->GetGroup());
6743  } else {
6744  fname.ReplaceAll("<group>", "default");
6745  }
6746  }
6747  // Replace <stag>, if any
6748  if (fname.Contains("<stag>")) {
6749  if (gProofServ && gProofServ->GetSessionTag() && strlen(gProofServ->GetSessionTag())) {
6750  fname.ReplaceAll("<stag>", gProofServ->GetSessionTag());
6751  } else if (gProof && gProof->GetSessionTag() && strlen(gProof->GetSessionTag())) {
6752  fname.ReplaceAll("<stag>", gProof->GetSessionTag());
6753  } else {
6754  ::Warning("TProofServ::ResolveKeywords", "session tag undefined: ignoring");
6755  }
6756  }
6757  // Replace <ord>, if any
6758  if (fname.Contains("<ord>")) {
6759  if (gProofServ && gProofServ->GetOrdinal() && strlen(gProofServ->GetOrdinal()))
6760  fname.ReplaceAll("<ord>", gProofServ->GetOrdinal());
6761  else
6762  ::Warning("TProofServ::ResolveKeywords", "ordinal number undefined: ignoring");
6763  }
6764  // Replace <qnum>, if any
6765  if (fname.Contains("<qnum>")) {
6766  if (gProofServ && gProofServ->GetQuerySeqNum() && gProofServ->GetQuerySeqNum() > 0)
6767  fname.ReplaceAll("<qnum>", TString::Format("%d", gProofServ->GetQuerySeqNum()).Data());
6768  else
6769  ::Warning("TProofServ::ResolveKeywords", "query seqeuntial number undefined: ignoring");
6770  }
6771  // Replace <file>, if any
6772  if (fname.Contains("<file>") && path && strlen(path) > 0) {
6773  fname.ReplaceAll("<file>", path);
6774  }
6775  // Replace <rver>, if any
6776  if (fname.Contains("<rver>")) {
6777  TString v = TString::Format("%d", gROOT->GetVersionInt());
6778  fname.ReplaceAll("<rver>", v);
6779  }
6780  // Replace <build>, if any
6781  if (fname.Contains("<build>")) {
6782  TString b = TString::Format("%d_%s_%s", gROOT->GetVersionInt(), gSystem->GetBuildArch(),
6784  fname.ReplaceAll("<build>", b);
6785  }
6786 }
6787 
6788 ////////////////////////////////////////////////////////////////////////////////
6789 /// Return the status of this session:
6790 /// 0 idle
6791 /// 1 running
6792 /// 2 being terminated (currently unused)
6793 /// 3 queued
6794 /// 4 idle timed-out (not set in here but in TIdleTOTimer::Notify)
6795 /// This is typically run in the reader thread, so access needs to be protected
6796 
6798 {
6799  std::lock_guard<std::recursive_mutex> lock(fQMtx);
6800  Int_t st = (fIdle) ? 0 : 1;
6801  if (fIdle && fWaitingQueries->GetSize() > 0) st = 3;
6802  return st;
6803 }
6804 
6805 ////////////////////////////////////////////////////////////////////////////////
6806 /// Update the session status in the relevant file. The status is taken from
6807 /// GetSessionStatus() unless xst >= 0, in which case xst is used.
6808 /// Return 0 on success, -errno if the file could not be opened.
6809 
6811 {
6812  FILE *fs = fopen(fAdminPath.Data(), "w");
6813  if (fs) {
6814  Int_t st = (xst < 0) ? GetSessionStatus() : xst;
6815  fprintf(fs, "%d", st);
6816  fclose(fs);
6817  PDB(kGlobal, 2)
6818  Info("UpdateSessionStatus", "status (=%d) update in path: %s", st, fAdminPath.Data());
6819  } else {
6820  return -errno;
6821  }
6822  // Done
6823  return 0;
6824 }
6825 
6826 ////////////////////////////////////////////////////////////////////////////////
6827 /// Return the idle status
6828 
6830 {
6831  std::lock_guard<std::recursive_mutex> lock(fQMtx);
6832  return fIdle;
6833 }
6834 
6835 ////////////////////////////////////////////////////////////////////////////////
6836 /// Change the idle status
6837 
6839 {
6840  std::lock_guard<std::recursive_mutex> lock(fQMtx);
6841  fIdle = st;
6842 }
6843 
6844 ////////////////////////////////////////////////////////////////////////////////
6845 /// Return kTRUE if the session is waiting for the OK to start processing
6846 
6848 {
6849  std::lock_guard<std::recursive_mutex> lock(fQMtx);
6850  if (fIdle && fWaitingQueries->GetSize() > 0) return kTRUE;
6851  return kFALSE;
6852 }
6853 
6854 ////////////////////////////////////////////////////////////////////////////////
6855 /// Return the number of waiting queries
6856 
6858 {
6859  std::lock_guard<std::recursive_mutex> lock(fQMtx);
6860  return fWaitingQueries->GetSize();
6861 }
6862 
6863 ////////////////////////////////////////////////////////////////////////////////
6864 /// Add a query to the waiting list
6865 /// Returns the number of queries in the list
6866 
6868 {
6869  std::lock_guard<std::recursive_mutex> lock(fQMtx);
6870  fWaitingQueries->Add(pq);
6871  return fWaitingQueries->GetSize();
6872 }
6873 
6874 ////////////////////////////////////////////////////////////////////////////////
6875 /// Get the next query from the waiting list.
6876 /// The query is removed from the list.
6877 
6879 {
6880  std::lock_guard<std::recursive_mutex> lock(fQMtx);
6882  fWaitingQueries->Remove(pq);
6883  return pq;
6884 }
6885 
6886 ////////////////////////////////////////////////////////////////////////////////
6887 /// Cleanup the waiting queries list. The objects are deleted if 'del' is true.
6888 /// If 'qls' is non null, only objects in 'qls' are removed.
6889 /// Returns the number of cleanup queries
6890 
6892 {
6893  std::lock_guard<std::recursive_mutex> lock(fQMtx);
6894  Int_t ncq = 0;
6895  if (qls) {
6896  TIter nxq(qls);
6897  TObject *o = 0;
6898  while ((o = nxq())) {
6899  if (fWaitingQueries->FindObject(o)) ncq++;
6900  fWaitingQueries->Remove(o);
6901  if (del) delete o;
6902  }
6903  } else {
6904  ncq = fWaitingQueries->GetSize();
6905  fWaitingQueries->SetOwner(del);
6907  }
6908  // Done
6909  return ncq;
6910 }
6911 
6912 ////////////////////////////////////////////////////////////////////////////////
6913 /// Set the message to be sent back in case of exceptions
6914 
6915 void TProofServ::SetLastMsg(const char *lastmsg)
6916 {
6917  fgLastMsg = lastmsg;
6918 }
6919 
6920 ////////////////////////////////////////////////////////////////////////////////
6921 /// Set the last entry before exception
6922 
6924 {
6925  fgLastEntry = entry;
6926 }
6927 
6928 ////////////////////////////////////////////////////////////////////////////////
6929 /// VirtMemMax getter
6930 
6932 {
6933  return fgVirtMemMax;
6934 }
6935 ////////////////////////////////////////////////////////////////////////////////
6936 /// ResMemMax getter
6937 
6939 {
6940  return fgResMemMax;
6941 }
6942 ////////////////////////////////////////////////////////////////////////////////
6943 /// MemHWM getter
6944 
6946 {
6947  return fgMemHWM;
6948 }
6949 ////////////////////////////////////////////////////////////////////////////////
6950 /// MemStop getter
6951 
6953 {
6954  return fgMemStop;
6955 }
6956 
6957 ////////////////////////////////////////////////////////////////////////////////
6958 /// Extract LOCALDATASERVER info in 'dsrv'
6959 
6960 void TProofServ::GetLocalServer(TString &dsrv)
6961 {
6962  // Check if a local data server has been specified
6963  if (gSystem->Getenv("LOCALDATASERVER")) {
6964  dsrv = gSystem->Getenv("LOCALDATASERVER");
6965  if (!dsrv.EndsWith("/")) dsrv += "/";
6966  }
6967 
6968  // Done
6969  return;
6970 }
6971 
6972 ////////////////////////////////////////////////////////////////////////////////
6973 /// If 'path' is local and 'dsrv' is Xrootd, apply 'path.Localroot' settings,
6974 /// if any.
6975 /// The final path via the server is dsrv+path.
6976 
6977 void TProofServ::FilterLocalroot(TString &path, const char *dsrv)
6978 {
6979  TUrl u(path, kTRUE);
6980  if (!strcmp(u.GetProtocol(), "file")) {
6981  // Remove prefix, if any, if included and if Xrootd
6982  TString pfx = gEnv->GetValue("Path.Localroot","");
6983  if (!pfx.IsNull() && !strncmp(u.GetFile(), pfx.Data(), pfx.Length())) {
6984  TString srvp = TUrl(dsrv).GetProtocol();
6985  if (srvp == "root" || srvp == "xrd") path.Remove(0, pfx.Length());
6986  }
6987  }
6988 
6989  // Done
6990  return;
6991 }
6992 
6993 ////////////////////////////////////////////////////////////////////////////////
6994 /// Locks the directory. Waits if lock is hold by an other process.
6995 /// Returns 0 on success, -1 in case of error.
6996 
6998 {
6999  const char *pname = GetName();
7000 
7001  if (gSystem->AccessPathName(pname))
7002  fLockId = open(pname, O_CREAT|O_RDWR, 0644);
7003  else
7004  fLockId = open(pname, O_RDWR);
7005 
7006  if (fLockId == -1) {
7007  SysError("Lock", "cannot open lock file %s", pname);
7008  return -1;
7009  }
7010 
7011  PDB(kPackage, 2)
7012  Info("Lock", "%d: locking file %s ...", gSystem->GetPid(), pname);
7013  // lock the file
7014 #if !defined(R__WIN32) && !defined(R__WINGCC)
7015  if (lockf(fLockId, F_LOCK, (off_t) 1) == -1) {
7016  SysError("Lock", "error locking %s", pname);
7017  close(fLockId);
7018  fLockId = -1;
7019  return -1;
7020  }
7021 #endif
7022 
7023  PDB(kPackage, 2)
7024  Info("Lock", "%d: file %s locked", gSystem->GetPid(), pname);
7025 
7026  return 0;
7027 }
7028 
7029 ////////////////////////////////////////////////////////////////////////////////
7030 /// Unlock the directory. Returns 0 in case of success,
7031 /// -1 in case of error.
7032 
7034 {
7035  if (!IsLocked())
7036  return 0;
7037 
7038  PDB(kPackage, 2)
7039  Info("Lock", "%d: unlocking file %s ...", gSystem->GetPid(), GetName());
7040  // unlock the file
7041  lseek(fLockId, 0, SEEK_SET);
7042 #if !defined(R__WIN32) && !defined(R__WINGCC)
7043  if (lockf(fLockId, F_ULOCK, (off_t)1) == -1) {
7044  SysError("Unlock", "error unlocking %s", GetName());
7045  close(fLockId);
7046  fLockId = -1;
7047  return -1;
7048  }
7049 #endif
7050 
7051  PDB(kPackage, 2)
7052  Info("Unlock", "%d: file %s unlocked", gSystem->GetPid(), GetName());
7053 
7054  close(fLockId);
7055  fLockId = -1;
7056 
7057  return 0;
7058 }
virtual void HandleException(Int_t sig)
Exception handler: we do not try to recover here, just exit.
void SetCompressionSettings(Int_t settings=1)
Definition: TMessage.cxx:268
Bool_t fMasterServ
Definition: TProofServ.h:125
Int_t fNcmd
Definition: TProofServ.h:122
Float_t fEffSessions
Definition: TProofServ.h:136
FILE * fLogFile
Definition: TProofServ.h:114
TClass * GetClass() const
Definition: TMessage.h:76
Bool_t fRealTimeLog
Definition: TProofServ.h:150
virtual const char * BaseName(const char *pathname)
Base name of a file name. Base name of /user/root is root.
Definition: TSystem.cxx:929
static void AssertMacroPath(const char *macro)
Make sure that the directory path contained by macro is in the macro path.
Definition: TProof.cxx:8571
Bool_t AcceptResults(Int_t connections, TVirtualProofPlayer *mergerPlayer)
Accept and merge results from a set of workers.
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:51
virtual void SysError(const char *method, const char *msgfmt,...) const
Issue system error message.
Definition: TObject.cxx:939
virtual Int_t Write(const char *name=0, Int_t option=0, Int_t bufsize=0)
Write this object to the current directory.
Definition: TObject.cxx:830
Long64_t GetEntries() const
Definition: TQueryResult.h:130
virtual Bool_t AccessPathName(const char *path, EAccessMode mode=kFileExists)
Returns FALSE if one can access a file using the specified access mode.
Definition: TSystem.cxx:1266
static Int_t GetCmdRtn()
Static method to get the return code from the execution of a command via the pipe.
Definition: TProofServ.cxx:349
TList * GetListOfLines() const
Definition: TMacro.h:53
static FILE * SetErrorHandlerFile(FILE *ferr)
Set the file stream where to log (default stderr).
double par[1]
Definition: unuranDistr.cxx:38
void Interrupt(EUrgent type, ESlaves list=kActive)
Send interrupt to master or slave servers.
Definition: TProof.cxx:2254
Int_t Compress()
Compress the message.
Definition: TMessage.cxx:286
double read(const std::string &file_name)
reading
ErrorHandlerFunc_t SetErrorHandler(ErrorHandlerFunc_t newhandler)
Set an errorhandler function. Returns the old handler.
Definition: TError.cxx:106
TList * GetListOfBadSlaves() const
Definition: TProof.h:687
TMD5 * ReadMD5(const char *pack)
Read MD5 checksum of the PAR file from the PROOF-INF/md5.txt file.
Definition: TPackMgr.cxx:722
static FILE * fgErrorHandlerFile
Definition: TProofServ.h:182
Int_t CatMotd()
Print message of the day (in the file pointed by the env PROOFMOTD or from fConfDir/etc/proof/motd).
Bool_t IsIdle()
Return the idle status.
virtual Long_t ProcessLine(const char *line, Bool_t sync=kFALSE, Int_t *error=0)
Process a single command line, either a C++ statement or an interpreter command starting with a "...
virtual TList * GetInputList() const =0
void IncCPUTime(Double_t procTime)
The PROOF package manager contains tools to manage packages.
Definition: TPackMgr.h:47
void GetEnabledPackages(TString &packlist)
Method to get a semi-colon separated list with the names of the enabled packages. ...
Definition: TPackMgr.cxx:515
virtual void HandleRemove(TMessage *mess, TString *slb=0)
Handle remove request.
virtual int GetPid()
Get process id.
Definition: TSystem.cxx:712
An array of TObjects.
Definition: TObjArray.h:39
Int_t fActSessions
Definition: TProofServ.h:135
virtual Int_t GetLearnEntries()=0
Int_t UnloadPackages()
Unload all packages.
Definition: TProof.cxx:8119
void GetOptions(Int_t *argc, char **argv)
Get and handle command line options.
TList * GetSubmasters()
Get the list of submaster nodes.
TString fConfFile
Definition: TProofServ.h:94
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
Definition: TList.cxx:405
virtual void Syslog(ELogLevel level, const char *mess)
Send mess to syslog daemon.
Definition: TSystem.cxx:1649
static Long64_t GetEntries(Bool_t isTree, const char *filename, const char *path, TString &objname)
Returns number of entries in tree or objects in file.
Definition: TDSet.cxx:1363
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:899
void AskParallel()
Ask the for the number of parallel slaves.
Definition: TProof.cxx:2055
TStopwatch fCompute
Definition: TProofServ.h:130
void LogToMaster(Bool_t on=kTRUE)
Definition: TProofServ.h:336
Long64_t GetBytesRead() const
Definition: TProof.h:959
static Bool_t GetFileInCmd(const char *cmd, TString &fn)
Static method to extract the filename (if any) form a CINT command.
Definition: TProof.cxx:6467
Double_t RealTime()
Stop the stopwatch (if it is running) and return the realtime (in seconds) passed between the start a...
Definition: TStopwatch.cxx:110
Int_t ClearPackages()
Remove all packages.
Definition: TProof.cxx:7812
TFileCollection * GetFilesOnServer(const char *server)
Return the subset of files served by &#39;server&#39;.
virtual const char * GetBuildCompilerVersion() const
Return the build compiler version.
Definition: TSystem.cxx:3769
virtual void Remove(TSocket *sock)
Remove a socket from the monitor.
Definition: TMonitor.cxx:214
virtual Int_t ClearCache(const char *uri)
Clear cached information matching uri.
Int_t GetActive(Long_t timeout=-1) const
Return number of sockets in the active list.
Definition: TMonitor.cxx:438
virtual void AddInput(TObject *inp)=0
long long Long64_t
Definition: RtypesCore.h:69
Int_t fGroupSize
Definition: TProofServ.h:120
void Start(Bool_t reset=kTRUE)
Start the stopwatch.
Definition: TStopwatch.cxx:58
R__EXTERN Int_t gErrorIgnoreLevel
Definition: TError.h:107
Bool_t IsWaiting()
Return kTRUE if the session is waiting for the OK to start processing.
R__EXTERN TProofDebug::EProofDebugMask gProofDebugMask
Definition: TProofDebug.h:55
virtual const char * WorkingDirectory()
Return working directory.
Definition: TSystem.cxx:866
virtual void StackTrace()
Print a stack trace.
Definition: TSystem.cxx:737
static TSQLServer * Connect(const char *db, const char *uid, const char *pw)
The db should be of the form: <dbms>://<host>[:<port>][/<database>], e.g.
Definition: TSQLServer.cxx:61
static TMD5 * FileChecksum(const char *file)
Returns checksum of specified file.
Definition: TMD5.cxx:474
void SetRealTimeLog(Bool_t on=kTRUE)
Switch ON/OFF the real-time logging facility.
Definition: TProof.cxx:7068
void Reset()
Reset the timer.
Definition: TTimer.cxx:157
virtual EQueryAction GetWorkers(TList *workers, Int_t &prioritychange, Bool_t resume=kFALSE)
Get list of workers to be used from now on.
double write(int n, const std::string &file_name, const std::string &vector_type, int compress=0)
writing
static Long_t fgResMemMax
Definition: TProofServ.h:174
void SetCompressionSettings(Int_t settings=1)
Used to specify the compression level and algorithm: settings = 100 * algorithm + level...
Definition: TSocket.cxx:1103
const char *const kCP
Definition: TProof.h:171
Int_t SetupCommon()
Common part (between TProofServ and TXProofServ) of the setup phase.
const char *const kLS
Definition: TProof.h:173
TLine * line
const double pi
virtual TSeqCollection * GetListOfFileHandlers() const
Definition: TSystem.h:374
Collectable string class.
Definition: TObjString.h:32
float Float_t
Definition: RtypesCore.h:53
virtual TVirtualProofPlayer * MakePlayer(const char *player=0, TSocket *s=0)
Construct a TProofPlayer object.
Definition: TProof.cxx:10183
return c
const char Option_t
Definition: RtypesCore.h:62
virtual TSQLResult * Query(const char *sql)=0
Long64_t fHWMBoxSize
Definition: TProofServ.h:170
virtual Int_t Send(const TMessage &mess)
Send a TMessage object.
Definition: TSocket.cxx:520
virtual Int_t SetOption(ESockOptions opt, Int_t val)
Set socket options.
Definition: TSocket.cxx:1017
This class represents a WWW compatible URL.
Definition: TUrl.h:41
Int_t fUid
Definition: TSystem.h:139
void SetWriteV3(Bool_t on=kTRUE)
Set/Reset the &#39;OldStreamer&#39; bit in this instance and its elements.
Definition: TDSet.cxx:1856
static void FilterLocalroot(TString &path, const char *url="root://dum/")
If &#39;path&#39; is local and &#39;dsrv&#39; is Xrootd, apply &#39;path.Localroot&#39; settings, if any. ...
int GetPathInfo(const char *path, Long_t *id, Long_t *size, Long_t *flags, Long_t *modtime)
Get info about a file: id, size, flags, modification time.
Definition: TSystem.cxx:1364
TString fSessionTag
Definition: TProofServ.h:97
void SetPlayer(TVirtualProofPlayer *player)
Set a new PROOF player.
Definition: TProof.cxx:10171
TObject * GetParameter(const char *par) const
Get specified parameter.
Definition: TProof.cxx:9890
Bool_t TestBit(UInt_t f) const
Definition: TObject.h:157
virtual Int_t Recv(TMessage *&mess)
Receive a TMessage object.
Definition: TSocket.cxx:818
const char * GetProtocol() const
Definition: TUrl.h:73
This class implements a data set to be used for PROOF processing.
Definition: TDSet.h:153
TStopwatch fLatency
Definition: TProofServ.h:129
const char * GetGroup() const
Definition: TProofServ.h:256
void TerminateWorker(TSlave *wrk)
Ask an active worker &#39;wrk&#39; to terminate, i.e. to shutdown.
Definition: TProof.cxx:4668
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
virtual Int_t HandleDataSets(TMessage *mess, TString *slb=0)
Handle here requests about datasets.
Int_t Unload(const char *pack)
Method to unload a package.
Definition: TPackMgr.cxx:425
virtual void MakePlayer()
Make player instance.
TH1 * h
Definition: legend2.C:5
virtual void HandleProcess(TMessage *mess, TString *slb=0)
Handle processing request.
TVirtualProofPlayer * fPlayer
Definition: TProofServ.h:113
void Interrupt()
Definition: TMonitor.h:75
Bool_t UnlinkDataDir(const char *path)
Scan recursively the datadir and unlink it if empty Return kTRUE if it can be unlinked, kFALSE otherwise.
static void SendAsynMsg(const char *msg)
Definition: TProofServ.cxx:150
Int_t GetParPath(const char *pack, TString &path)
Method to get the path of the PAR file for package &#39;pack&#39;.
Definition: TPackMgr.cxx:535
virtual Bool_t RemoveDataSet(const char *uri)
Removes the indicated dataset.
Int_t GetNumOfFiles()
Return the number of files in the dataset.
Definition: TDSet.cxx:1992
TSocket * GetSocket() const
Definition: TProofServ.h:271
const char *const kPROOF_WorkDir
Definition: TProof.h:154
Bool_t NoLogOpt() const
Definition: TApplication.h:144
Int_t LockSession(const char *sessiontag, TProofLockPath **lck)
Try locking query area of session tagged sessiontag.
virtual EExitStatus GetExitStatus() const =0
virtual Int_t GetEntries() const
Definition: TCollection.h:92
virtual TObject * Last() const
Return the last object in the list. Returns 0 when list is empty.
Definition: TList.cxx:581
TString fGroup
Definition: TProofServ.h:92
TList * GetOutputList()
Get list with all object created during processing (see Process()).
Definition: TProof.cxx:9780
static Long_t GetVirtMemMax()
VirtMemMax getter.
TDataSetManager * fDataSetManager
Definition: TProofServ.h:158
TObject * GetInputObject(const char *classname) const
Return first instance of class &#39;classname&#39; in the input list.
virtual Int_t GetLocalPort()
Get port # to which server socket is bound. In case of error returns -1.
This class represents an Internet Protocol (IP) address.
Definition: TInetAddress.h:40
virtual int MakeDirectory(const char *name)
Make a directory.
Definition: TSystem.cxx:822
virtual void AddSignalHandler(TSignalHandler *sh)
Add a signal handler to list of system signal handlers.
Definition: TSystem.cxx:537
Int_t DisablePackage(const char *package)
Remove a specific package.
Definition: TProof.cxx:7857
virtual const char * HomeDirectory(const char *userName=0)
Return the user&#39;s home directory.
Definition: TSystem.cxx:882
virtual TFileCollection * GetDataSet(const char *uri, const char *server=0)
Utility function used in various methods for user dataset upload.
Int_t WaitingQueries()
Return the number of waiting queries.
Int_t UpdateSessionStatus(Int_t xst=-1)
Update the session status in the relevant file.
virtual Bool_t ChangeDirectory(const char *path)
Change directory.
Definition: TSystem.cxx:857
static TPackMgr * GetPackMgr(const char *pack, TPackMgr *packmgr=nullptr)
Get the package manager having &#39;pack&#39;; priority is given to packmgr, if defined.
Definition: TPackMgr.cxx:922
TPluginHandler * FindHandler(const char *base, const char *uri=0)
Returns the handler if there exists a handler for the specified URI.
void IncProcTime(Double_t procTime)
void Add(TObject *obj)
This function may not be used (but we need to provide it since it is a pure virtual in TCollection)...
Definition: TMap.cxx:53
TString ferr
Definition: pq2main.cxx:38
#define gROOT
Definition: TROOT.h:364
R__EXTERN Int_t gErrorAbortLevel
Definition: TError.h:108
Definition: test.py:1
virtual void Add(TSocket *sock, Int_t interest=kRead)
Add socket to the monitor&#39;s active list.
Definition: TMonitor.cxx:168
virtual Int_t HandleLibIncPath(TMessage *mess)
Handle lib, inc search paths modification request.
Class supporting a collection of lines with C++ code.
Definition: TMacro.h:33
TList * GetListOfInactiveSlaves() const
Definition: TProof.h:685
Int_t LoadPlugin()
Load the plugin library for this handler.
TList * GetListOfSlaves() const
Definition: TProof.h:684
TList * fQueuedMsg
Definition: TProofServ.h:146
virtual int Load(const char *module, const char *entry="", Bool_t system=kFALSE)
Load a shared library.
Definition: TSystem.cxx:1819
virtual void SetCurrentQuery(TQueryResult *q)=0
TList * Queries() const
TDataSetManagerFile * fDataSetStgRepo
Definition: TProofServ.h:159
Int_t Clean(const char *pack)
Clean dir for package &#39;pack&#39; Return -1 in case of error, 0 otherwise.
Definition: TPackMgr.cxx:590
Double_t CpuTime()
Stop the stopwatch (if it is running) and return the cputime (in seconds) passed between the start an...
Definition: TStopwatch.cxx:125
void SetQueryRunning(TProofQueryResult *pq)
Set query in running state.
int Int_t
Definition: RtypesCore.h:41
Int_t Load(const char *pack, TList *optls=0)
Method to load a package taking an option list Return -1 on error, 0 otherwise.
Definition: TPackMgr.cxx:234
virtual const char * DirName(const char *pathname)
Return the directory name in pathname.
Definition: TSystem.cxx:997
bool Bool_t
Definition: RtypesCore.h:59
time_t GetSec() const
Definition: TTimeStamp.h:140
TArc * a
Definition: textangle.C:12
TQueryResult * CloneInfo()
Return an instance of TQueryResult containing only the local info fields, i.e.
const Bool_t kFALSE
Definition: Rtypes.h:92
virtual Int_t SendObject(const TObject *obj, Int_t kind=kMESS_OBJECT)
Send an object.
Definition: TSocket.cxx:600
const char *const kRM
Definition: TProof.h:172
#define gInterpreter
Definition: TInterpreter.h:517
TReaperTimer * fReaperTimer
Definition: TProofServ.h:153
virtual char * Which(const char *search, const char *file, EAccessMode mode=kFileExists)
Find location of file in a search path.
Definition: TSystem.cxx:1512
TString fImage
Definition: TProofServ.h:96
Int_t GetProtocol() const
Definition: TProofServ.h:266
virtual void RemoveAll()
Remove all sockets from the monitor.
Definition: TMonitor.cxx:241
virtual void ShowDataSets(const char *uri="*", const char *opt="")
Prints formatted information about the dataset &#39;uri&#39;.
Option_t * GetOption() const
Definition: TSocket.h:128
TString fService
Definition: TProofServ.h:90
TProofQueryResult * LocateQuery(TString queryref, Int_t &qry, TString &qdir)
Locate query referenced by queryref.
virtual TMap * GetGroupQuotaMap()
virtual FILE * OpenPipe(const char *command, const char *mode)
Open a pipe.
Definition: TSystem.cxx:667
TProofServ * gProofServ
Definition: TProofServ.cxx:115
STL namespace.
virtual void Print(Option_t *option="") const
This method must be overridden when a class wants to print itself.
Definition: TObject.cxx:595
Int_t GetSeqNum() const
Definition: TQueryResult.h:123
void ResetMergers()
Definition: TProof.h:721
Long64_t fMaxBoxSize
Definition: TProofServ.h:169
TProofServLogHandlerGuard(const char *cmd, TSocket *s, const char *pfx="", Bool_t on=kTRUE)
Init a guard for executing a command in a pipe.
Definition: TProofServ.cxx:357
void Show(const char *title=0)
Show available packages.
Definition: TPackMgr.cxx:562
virtual void DeActivateAll()
De-activate all activated sockets.
Definition: TMonitor.cxx:302
const char * Class
Definition: TXMLSetup.cxx:64
Bool_t IsTopMaster() const
Definition: TProofServ.h:309
Bool_t UseDynamicStartup() const
Definition: TProof.h:951
static volatile Int_t gProofServDebug
Definition: TProofServ.cxx:118
TObject * FindObject(const char *name) const
Find object using its name.
Definition: THashList.cxx:213
TMonitor * fMergingMonitor
Definition: TProofServ.h:164
Long64_t GetEntries() const
void ScanPreviousQueries(const char *dir)
Scan the queries directory for the results of previous queries.
Int_t Unpack(const char *pack, TMD5 *sum=0)
Read MD5 checksum of the PAR file from the PROOF-INF/md5.txt file.
Definition: TPackMgr.cxx:737
Int_t AddIncludePath(const char *incpath, Bool_t onClient=kFALSE, TList *wrks=0, Bool_t doCollect=kTRUE)
Add &#39;incpath&#39; to the inc path search.
Definition: TProof.cxx:8860
static void ResolveKeywords(TString &fname, const char *path=0)
Replace <ord>, <user>, <u>, <group>, <stag>, <qnum>, <file>, <rver> and <build> placeholders in fname...
virtual void ClearCache(const char *file=0)
Remove file from all file caches.
Definition: TProof.cxx:7686
void Print(Option_t *option="") const
Dump the content.
const char * GetOptions() const
Definition: TQueryResult.h:127
static Float_t GetMemHWM()
MemHWM getter.
TString fPrefix
Definition: TProofServ.h:148
Int_t SendCurrentState(ESlaves list=kActive)
Transfer the current state of the master to the active slave servers.
Definition: TProof.cxx:6730
static Int_t fgRecursive
Definition: TProofServ.h:183
virtual TFileHandler * RemoveFileHandler(TFileHandler *fh)
Remove a file handler from the list of file handlers.
Definition: TSystem.cxx:569
TList * GetListOfElements() const
Definition: TDSet.h:231
const char * GetHostFQDN() const
Return fully qualified domain name of url host.
Definition: TUrl.cxx:469
const Int_t kBreak
Definition: TError.h:42
TProofNodeInfo * GetMaster()
Get the master node.
virtual int mkdir(const char *name, Bool_t recursive=kFALSE)
Make a file system directory.
Definition: TSystem.cxx:901
static Long_t fgVirtMemMax
Definition: TProofServ.h:173
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:739
virtual void HandleCheckFile(TMessage *mess, TString *slb=0)
Handle file checking request.
void SendParallel(Bool_t async=kFALSE)
Send number of parallel nodes to master or client.
Int_t fMaxQueries
Definition: TProofServ.h:168
virtual TObject * FindObject(const char *name) const
Find an object in this list using its name.
Definition: TList.cxx:497
static TString fgPfx
Definition: TProofServ.h:395
virtual void HandleSocketInput()
Handle input coming from the client or from the master server.
std::recursive_mutex fQMtx
Definition: TProofServ.h:144
static const char * GetMacroPath()
Get macro search path. Static utility function.
Definition: TROOT.cxx:2563
static Int_t GetErrno()
Static function returning system error number.
Definition: TSystem.cxx:265
EUploadPackageOpt
Definition: TProof.h:396
virtual void HandleArchive(TMessage *mess, TString *slb=0)
Handle archive request.
static TFile * Open(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=1, Int_t netopt=0)
Create / open a file.
Definition: TFile.cxx:3907
Int_t Length() const
Definition: TBuffer.h:96
virtual void UpdateProgressInfo()=0
Int_t fMode
Definition: TSystem.h:138
TString fArchivePath
Definition: TProofServ.h:110
Int_t RemoveIncludePath(const char *incpath, Bool_t onClient=kFALSE)
Remove &#39;incpath&#39; from the inc path search.
Definition: TProof.cxx:8939
virtual Long64_t Process(TDSet *set, const char *selector, Option_t *option="", Long64_t nentries=-1, Long64_t firstentry=0)=0
TTimeStamp GetLastUsage()
Definition: TSocket.h:159
const char * GetFile() const
Definition: TUrl.h:78
Int_t Install(const char *par, Bool_t rmold=kFALSE)
Install package from par (unpack the file in the directory); par can be an URL for remote retrieval...
Definition: TPackMgr.cxx:780
Manages an element of a TDSet.
Definition: TDSet.h:68
virtual TObject * ReadObject(const TClass *cl)
Read object from I/O buffer.
Int_t fGroupId
Definition: TProofServ.h:119
virtual Int_t SendRaw(const void *buffer, Int_t length, ESendRecvOptions opt=kDefault)
Send a raw buffer of specified length.
Definition: TSocket.cxx:620
static void SetLastEntry(Long64_t lastentry)
Set the last entry before exception.
TList * GetListOfEnabled() const
Get list of enabled packages Returns a pointer to a TList object, transferring ownership to the calle...
Definition: TPackMgr.cxx:658
static struct mg_connection * fc(struct mg_context *ctx)
Definition: civetweb.c:1956
Int_t Update(Long64_t avgsize=-1)
Update accumulated information about the elements of the collection (e.g.
virtual const char * GetDirEntry(void *dirp)
Get a directory entry. Returns 0 if no more entries.
Definition: TSystem.cxx:848
#define SafeDelete(p)
Definition: RConfig.h:507
virtual TList * GetOutputList() const =0
virtual int Unlink(const char *name)
Unlink, i.e. remove, a file.
Definition: TSystem.cxx:1347
Int_t GetQuerySeqNum() const
Definition: TProofServ.h:274
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition: TObject.cxx:188
TSocket * fSocket
Definition: TProofServ.h:111
TStopwatch timer
Definition: pirndm.C:37
void Stop()
Stop the stopwatch.
Definition: TStopwatch.cxx:77
TList * GetWorkers()
Get the list of worker nodes.
Int_t GetCompressionLevel() const
Definition: TProofServ.h:478
virtual void Print(Option_t *option="") const
Print status of PROOF cluster.
Definition: TProof.cxx:4775
void StopProcess(Bool_t abort, Int_t timeout=-1)
Send STOPPROCESS message to master and workers.
Definition: TProof.cxx:6196
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString...
Definition: TString.cxx:2335
virtual int GetSysInfo(SysInfo_t *info) const
Returns static system info, like OS type, CPU type, number of CPUs RAM size, etc into the SysInfo_t s...
Definition: TSystem.cxx:2440
virtual FILE * TempFileName(TString &base, const char *dir=0)
Create a secure temporary file by appending a unique 6 letter string to base.
Definition: TSystem.cxx:1463
#define PDB(mask, level)
Definition: TProofDebug.h:58
const Int_t kSysError
Definition: TError.h:43
virtual void HandleFork(TMessage *mess)
Cloning itself via fork. Not implemented.
THashList implements a hybrid collection class consisting of a hash table and a list to store TObject...
Definition: THashList.h:36
virtual void Sleep(UInt_t milliSec)
Sleep milliSec milli seconds.
Definition: TSystem.cxx:442
virtual void MergeOutput(Bool_t=kFALSE)=0
This code implements the MD5 message-digest algorithm.
Definition: TMD5.h:46
The TNamed class is the base class for all named ROOT classes.
Definition: TNamed.h:33
virtual void ShowQuota(const char *opt)
Display quota information.
void SetLogLevel(Int_t level, UInt_t mask=TProofDebug::kAll)
Set server logging level.
Definition: TProof.cxx:7051
virtual void Run(Bool_t retrn=kFALSE)
Main application eventloop. Calls system dependent eventloop via gSystem.
virtual char * ReadString(char *s, Int_t max)
Read string from I/O buffer.
TList * PreviousQueries() const
const char *const kPROOF_QueryDir
Definition: TProof.h:158
TMacro * GetSelecHdr() const
Definition: TQueryResult.h:135
static Bool_t Initialized()
Return kTRUE if the TROOT object has been initialized.
Definition: TROOT.cxx:2626
static Long64_t GetFileBytesRead()
Static function returning the total number of bytes read from all files.
Definition: TFile.cxx:4375
const Int_t kFatal
Definition: TError.h:44
virtual Int_t RegisterDataSet(const char *uri, TFileCollection *dataSet, const char *opt)
Register a dataset, perfoming quota checkings, if needed.
virtual void ShowCache(Bool_t all=kFALSE)
List contents of file cache.
Definition: TProof.cxx:7663
TDSetElement * GetNextPacket(Long64_t totalEntries=-1)
Get next range of entries to be processed on this server.
static EFileType GetType(const char *name, Option_t *option="", TString *prefix=0)
Resolve the file type as a function of the protocol field in &#39;name&#39;.
Definition: TFile.cxx:4622
Long64_t GetBytes() const
Definition: TQueryResult.h:132
virtual void Start(Long_t milliSec=-1, Bool_t singleShot=kFALSE)
Starts the timer with a milliSec timeout.
Definition: TTimer.cxx:211
Bool_t IsEndMaster() const
Definition: TProof.h:694
void ShowEnabled(const char *title=0)
Show enabled packages.
Definition: TPackMgr.cxx:676
void DeleteAll()
Remove all (key,value) pairs from the map AND delete the keys AND values when they are allocated on t...
Definition: TMap.cxx:167
virtual const char * GetDynamicPath()
Return the dynamic path (used to find shared libraries).
Definition: TSystem.cxx:1758
const char * GetGroup() const
Definition: TProof.h:937
Long64_t fLogFileMaxSize
Definition: TProofServ.h:116
virtual void HandleUrgentData()
Handle Out-Of-Band data sent by the master or client.
TFileHandler * fInputHandler
Definition: TProofServ.h:138
Int_t CleanupSession(const char *sessiontag)
Cleanup query dir qdir.
Int_t CompLength() const
Definition: TMessage.h:95
const char * AsString(const Option_t *option="") const
Return the date & time as a string.
Definition: TTimeStamp.cxx:271
virtual const char * Getenv(const char *env)
Get environment variable.
Definition: TSystem.cxx:1628
static Int_t RegisterDataSets(TList *in, TList *out, TDataSetManager *dsm, TString &e)
Register TFileCollections in &#39;out&#39; as datasets according to the rules in &#39;in&#39;.
Int_t ApplyMaxQueries(Int_t mxq)
Scan the queries directory and remove the oldest ones (and relative dirs, if empty) in such a way onl...
std::vector< std::vector< double > > Data
virtual void ExitLoop()
Exit from event loop.
Definition: TSystem.cxx:397
virtual Bool_t IsValid() const
const char * GetSessionTag() const
Definition: TProof.h:939
virtual UserGroup_t * GetUserInfo(Int_t uid)
Returns all user info in the UserGroup_t structure.
Definition: TSystem.cxx:1564
TProofQueryResult * NextQuery()
Get the next query from the waiting list.
TString fDataDir
Definition: TProofServ.h:104
void FlushLogFile()
Reposition the read pointer in the log file to the very end.
virtual ~TProofServ()
Cleanup.
Int_t GetPort() const
Definition: TInetAddress.h:77
TProof * fProof
Definition: TProofServ.h:112
static Long_t GetResMemMax()
ResMemMax getter.
virtual TSocket * Accept(UChar_t Opt=0)
Accept a connection on a server socket.
virtual const char * TempDirectory() const
Return a user configured or systemwide directory to create temporary files in.
Definition: TSystem.cxx:1448
Book space in a file, create I/O buffers, to fill them, (un)compress them.
Definition: TKey.h:30
TString fConfDir
Definition: TProofServ.h:93
XFontStruct * id
Definition: TGX11.cxx:108
TString flog
Definition: pq2main.cxx:37
virtual Int_t HandleCache(TMessage *mess, TString *slb=0)
Handle here all cache and package requests.
TProofServ * fProofServ
Definition: TProofServ.h:432
virtual void HandleQueryList(TMessage *mess)
Handle request for list of queries.
Bool_t fInterrupt
Definition: TProofServ.h:126
A container class for query results.
Definition: TQueryResult.h:44
Int_t ActivateWorker(const char *ord, Bool_t save=kTRUE)
Make sure that the worker identified by the ordinal number &#39;ord&#39; is in the active list...
Definition: TProof.cxx:11325
const char * GetTitle() const
Returns title of object.
Definition: TPackMgr.h:73
TString fOrdinal
Definition: TProofServ.h:118
TList * GetListOfSlaveInfos()
Returns list of TSlaveInfo&#39;s. In case of error return 0.
Definition: TProof.cxx:2299
TObject * Value() const
Definition: TMap.h:125
const char *const kPROOF_DataDir
Definition: TProof.h:160
Int_t fGid
Definition: TSystem.h:140
TSocket * Select()
Return pointer to socket for which an event is waiting.
Definition: TMonitor.cxx:322
virtual void SetProcessInfo(Long64_t ent, Float_t cpu=0., Long64_t siz=-1, Float_t inittime=0., Float_t proctime=0.)
Set processing info.
ELogLevel
Definition: TSystem.h:66
static TVirtualProofPlayer * Create(const char *player, TProof *p, TSocket *s=0)
Create a PROOF player.
TString fAdminPath
Definition: TProofServ.h:106
virtual ~TProofServLogHandler()
Handle available message in the open file.
Definition: TProofServ.cxx:291
A doubly linked list.
Definition: TList.h:47
static const char * what
Definition: stlLoader.cc:6
Int_t fGroupPriority
Definition: TProofServ.h:123
virtual ~TReaperTimer()
Destructor.
Definition: TProofServ.cxx:454
const char * GetSessionTag() const
Definition: TProofServ.h:259
Float_t fCpuTime
Definition: TProofServ.h:128
virtual Int_t Fork()
Fork a child.
TList * GetList() const
Get list of available packages Returns a pointer to a TList object, transferring ownership to the cal...
Definition: TPackMgr.cxx:635
Bool_t Notify()
Check if any of the registered children has changed its state.
Definition: TProofServ.cxx:482
TShutdownTimer(TProofServ *p, Int_t delay)
Construtor.
Definition: TProofServ.cxx:409
static TProofServ * This()
Static function returning pointer to global object gProofServ.
Bool_t RemoveDataSet(const char *group, const char *user, const char *dsName)
Removes the indicated dataset.
const char * GetName() const
Returns name of object.
Definition: TObjString.h:42
virtual Int_t ReadFile(const char *fname, EEnvLevel level)
Read and parse the resource file for a certain level.
Definition: TEnv.cxx:597
const char *const kPROOF_QueryLockFile
Definition: TProof.h:163
static Float_t GetMemStop()
MemStop getter.
void Sort(Bool_t useindex=kFALSE)
Sort the collection.
void Reset()
Reset the message buffer so we can use (i.e. fill) it again.
Definition: TMessage.cxx:171
Int_t UploadPackage(const char *par, EUploadPackageOpt opt=kUntar, TList *workers=0)
Upload a PROOF archive (PAR file).
Definition: TProof.cxx:8413
virtual void AddQueryResult(TQueryResult *q)=0
void SendAsynMessage(const char *msg, Bool_t lf=kTRUE)
Send an asychronous message to the master / client .
Named parameter, streamable and storable.
Definition: TParameter.h:49
const Int_t kUnset
Definition: TError.h:37
Int_t GetPriority()
Get the processing priority for the group the user belongs too.
Bool_t IsEndMaster() const
Definition: TProofServ.h:306
EFileType
File type.
Definition: TFile.h:172
Int_t fProtocol
Definition: TProofServ.h:117
Int_t Build(const char *pack, Int_t opt=TPackMgr::kCheckROOT)
Method to build a package.
Definition: TPackMgr.cxx:101
Bool_t IsInDir(const char *path)
Method to check if &#39;path&#39; is in the managed directory Return kTRUE or kFALSE.
Definition: TPackMgr.cxx:492
TString fUser
Definition: TSystem.h:152
virtual const char * GetBuildArch() const
Return the build architecture.
Definition: TSystem.cxx:3753
virtual void Close(Option_t *opt="")
Close the socket.
Definition: TSocket.cxx:388
static Int_t fgLogToSysLog
Definition: TProofServ.h:186
const Int_t kPrint
Definition: TError.h:38
Int_t ReceiveFile(const char *file, Bool_t bin, Long64_t size)
Receive a file, either sent by a client or a master server.
virtual void Setenv(const char *name, const char *value)
Set environment variable.
Definition: TSystem.cxx:1612
The purpose of this class is to provide a complete node description for masters, submasters and worke...
virtual TObject * First() const
Return the first object in the list. Returns 0 when list is empty.
Definition: TList.cxx:557
Int_t DisablePackages()
Remove all packages.
Definition: TProof.cxx:7914
TRandom2 r(17)
const Int_t kInfo
Definition: TError.h:39
Class managing the query-result area.
R__EXTERN TSystem * gSystem
Definition: TSystem.h:549
Class providing the PROOF server.
Definition: TProofServ.h:80
SVector< double, 2 > v
Definition: Dict.h:5
if object ctor succeeded but object should not be used
Definition: TObject.h:63
Int_t fCompressMsg
Definition: TProofServ.h:156
TString fSessionDir
Definition: TProofServ.h:99
static void GetLocalServer(TString &dsrv)
Extract LOCALDATASERVER info in &#39;dsrv&#39;.
const char *const kPROOF_DataSetDir
Definition: TProof.h:159
THashList * GetList()
TApplication * GetTProofServ(Int_t *argc, char **argv, FILE *flog)
Definition: TProofServ.cxx:555
void SetLearnTime(Double_t learnTime)
Long_t ExecPlugin(int nargs, const T &... params)
Long64_t GetNFiles() const
virtual Int_t GetValue(const char *name, Int_t dflt)
Returns the integer value for a resource.
Definition: TEnv.cxx:496
void Print(Option_t *option="") const
Prints the contents of the TFileCollection.
virtual TObject * Remove(TObject *obj)
Remove object from the list.
Definition: TList.cxx:675
void ShowPackages(Bool_t all=kFALSE, Bool_t redirlog=kFALSE)
List contents of package directory.
Definition: TProof.cxx:7742
void SetPrefix(const char *pfx)
Definition: TPackMgr.h:78
virtual Bool_t ExistsDataSet(const char *uri)
Checks if the indicated dataset exits.
Bool_t IsDraw() const
Definition: TQueryResult.h:152
Long_t fMemVirtual
Definition: TSystem.h:207
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:488
Bool_t ParseUri(const char *uri, TString *dsGroup=0, TString *dsUser=0, TString *dsName=0, TString *dsTree=0, Bool_t onlyCurrent=kFALSE, Bool_t wildcards=kFALSE)
Parses a (relative) URI that describes a DataSet on the cluster.
Bool_t Notify()
Handle expiration of the idle timer. The session will just be terminated.
Definition: TProofServ.cxx:520
virtual TEnvRec * Lookup(const char *n)
Loop over all resource records and return the one with name.
Definition: TEnv.cxx:552
virtual void SetDynamicPath(const char *pathname)
Set the dynamic path to a new value.
Definition: TSystem.cxx:1769
virtual Int_t ShowCache(const char *uri)
Show cached information matching uri.
void SetActive(Bool_t=kTRUE)
Definition: TProof.h:1018
Int_t BuildPackage(const char *package, EBuildPackageOpt opt=kBuildAll, Int_t chkveropt=TPackMgr::kCheckROOT, TList *workers=0)
Build specified package.
Definition: TProof.cxx:7962
Int_t WriteDataSet(const char *group, const char *user, const char *dsName, TFileCollection *dataset, UInt_t option=0, TMD5 *checksum=0)
Writes indicated dataset.
Int_t QueueQuery(TProofQueryResult *pq)
Add a query to the waiting list Returns the number of queries in the list.
static Float_t fgMemHWM
Definition: TProofServ.h:176
unsigned int UInt_t
Definition: RtypesCore.h:42
TList * GetInputList()
Definition: TQueryResult.h:128
TMarker * m
Definition: textangle.C:8
const char *const kPROOF_CacheLockFile
Definition: TProof.h:161
TIdleTOTimer * fIdleTOTimer
Definition: TProofServ.h:154
Int_t ScanDataSet(const char *uri, const char *opt)
Scans the dataset indicated by &#39;uri&#39; following the &#39;opts&#39; directives.
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:925
virtual int Umask(Int_t mask)
Set the process file creation mode mask.
Definition: TSystem.cxx:1481
void SetRunning(Int_t startlog, const char *par, Int_t nwrks)
Call when running starts.
TString fDataDirOpts
Definition: TProofServ.h:105
const char * GetConfDir() const
Definition: TProofServ.h:253
Bool_t IsDataReady(Long64_t &totalbytes, Long64_t &bytesready)
See if the data is ready to be analyzed.
Definition: TProof.cxx:2218
This class implements a plugin library manager.
virtual void SetMerging(Bool_t on=kTRUE)=0
void SaveSource(FILE *fp)
Save macro source in file pointer fp.
Definition: TMacro.cxx:380
virtual Int_t Echo(const TObject *obj)
Sends an object to master and workers and expect them to send back a message with the output of its T...
Definition: TProof.cxx:7000
virtual Int_t ReadFile(const char *filename)
Read lines in filename in this macro.
Definition: TMacro.cxx:335
TPackMgr * fPackMgr
Definition: TProofServ.h:100
A TEventList object is a list of selected events (entries) in a TTree.
Definition: TEventList.h:33
Int_t fSeqNum
query unique sequential number
Definition: TQueryResult.h:60
TLine * l
Definition: textangle.C:4
virtual void HandleSigPipe()
Called when the client is not alive anymore (i.e.
Handles synchronous and a-synchronous timer events.
Definition: TTimer.h:57
virtual const char * GetField(Int_t field)=0
static void AddEnvVar(const char *name, const char *value)
Add an variable to the list of environment variables passed to proofserv on the master and slaves...
Definition: TProof.cxx:11732
TServerSocket * fMergingSocket
Definition: TProofServ.h:163
Int_t Ping(ESlaves list)
Ping PROOF slaves. Returns the number of slaves that responded.
Definition: TProof.cxx:4724
const Int_t kPROOF_Protocol
Definition: TProof.h:150
virtual Int_t Exec(const char *shellcmd)
Execute a command.
Definition: TSystem.cxx:658
const Int_t kWarning
Definition: TError.h:40
static Bool_t IsActive()
Static function that returns kTRUE in case we are a PROOF server.
virtual TObject * At(Int_t idx) const
Returns the object at position idx. Returns 0 if idx is out of range.
Definition: TList.cxx:311
virtual void Abort(int code=0)
Abort the application.
Definition: TSystem.cxx:729
void Interrupt()
Definition: TProofServ.h:305
TString fUser
Definition: TProofServ.h:91
Bool_t FinalizeQuery(TProofQueryResult *pq, TProof *proof, TVirtualProofPlayer *player)
Final steps after Process() to complete the TQueryResult instance.
Bool_t fIdle
Definition: TProofServ.h:143
virtual void ProcessNext(TString *slb=0)
process the next query from the queue of submitted jobs.
Int_t RemoveWorkers(TList *wrks)
Used for shuting down the workres after a query is finished.
Definition: TProof.cxx:1575
void SetName(const char *name)
Definition: TCollection.h:116
Int_t SendFile(const char *file, Int_t opt=(kBinary|kForward|kCp|kCpBin), const char *rfile=0, TSlave *sl=0)
Send a file to master or slave servers.
Definition: TProof.cxx:6866
static void EnableSchemaEvolutionForAll(Bool_t enable=kTRUE)
Static function enabling or disabling the automatic schema evolution.
Definition: TMessage.cxx:116
void Warning(const char *location, const char *msgfmt,...)
TString fDataSetDir
Definition: TProofServ.h:103
TShutdownTimer * fShutdownTimer
Definition: TProofServ.h:152
Float_t GetUsedCPU() const
Definition: TQueryResult.h:133
virtual void FreeDirectory(void *dirp)
Free a directory.
Definition: TSystem.cxx:840
Int_t SendResults(TSocket *sock, TList *outlist=0, TQueryResult *pq=0)
Sends all objects from the given list to the specified socket.
virtual int ClosePipe(FILE *pipe)
Close the pipe.
Definition: TSystem.cxx:676
virtual void ValidateDSet(TDSet *dset)
Validate a TDSet.
Definition: TProof.cxx:9352
#define Printf
Definition: TGeoToOCC.h:18
Long64_t GetFirst() const
Definition: TQueryResult.h:131
void AddPid(Int_t pid)
Add an entry for &#39;pid&#39; in the internal list.
Definition: TProofServ.cxx:466
virtual void HandleSubmerger(TMessage *mess)
Handle a message of type kPROOF_SUBMERGER.
#define gPerfStats
char * StrDup(const char *str)
Duplicate the string str.
Definition: TString.cxx:2514
Int_t RemoveDynamicPath(const char *libpath, Bool_t onClient=kFALSE)
Remove &#39;libpath&#39; from the lib path search.
Definition: TProof.cxx:8905
virtual void RemoveQueryResult(const char *ref)=0
virtual void HandleRetrieve(TMessage *mess, TString *slb=0)
Handle retrieve request.
UInt_t What() const
Definition: TMessage.h:80
Int_t SendCommand(const char *cmd, ESlaves list=kActive)
Send command to be executed on the PROOF master and/or slaves.
Definition: TProof.cxx:6603
virtual Int_t HandleWorkerLists(TMessage *mess)
Handle here all requests to modify worker lists.
virtual Int_t RedirectOutput(const char *name, const char *mode="a", RedirectHandle_t *h=0)
Redirect standard output (stdout, stderr) to the specified file.
Definition: TSystem.cxx:1678
Int_t LoadPackage(const char *package, Bool_t notOnClient=kFALSE, TList *loadopts=0, TList *workers=0)
Load specified package.
Definition: TProof.cxx:8041
long Long_t
Definition: RtypesCore.h:50
TObject * Get(const char *namecycle)
Get object with name "name;cycle" (e.g.
int Ssiz_t
Definition: RtypesCore.h:63
TMacro * GetSelecImp() const
Definition: TQueryResult.h:136
virtual int Chmod(const char *file, UInt_t mode)
Set the file permission bits. Returns -1 in case or error, 0 otherwise.
Definition: TSystem.cxx:1472
R__EXTERN TProof * gProof
Definition: TProof.h:1107
Class used by TMap to store (key,value) pairs.
Definition: TMap.h:106
Int_t OldAuthSetup(TString &wconf)
Setup authentication related stuff for old versions.
virtual const char * GetIncludePath()
Get the list of include path.
Definition: TSystem.cxx:3843
Bool_t Notify()
Handle available message in the open file.
Definition: TProofServ.cxx:308
virtual void SendLogFile(Int_t status=0, Int_t start=-1, Int_t end=-1)
Send log file to master.
#define ClassImp(name)
Definition: Rtypes.h:279
double f(double x)
static Int_t fgCmdRtn
Definition: TProofServ.h:396
Bool_t IsZombie() const
Definition: TObject.h:120
virtual Long64_t GetEventsProcessed() const =0
TString fTopSessionTag
Definition: TProofServ.h:98
const char * GetService() const
Definition: TProofServ.h:252
void SetSysInfo(SysInfo_t si)
Setter for fSysInfo.
Definition: TProof.cxx:265
TVirtualProofPlayer * GetPlayer() const
Definition: TProof.h:746
virtual Func_t DynFindSymbol(const char *module, const char *entry)
Find specific entry point in specified library.
Definition: TSystem.cxx:1983
Int_t Counter() const
Definition: TStopwatch.h:52
double Double_t
Definition: RtypesCore.h:55
virtual const char * HostName()
Return the system&#39;s host name.
Definition: TSystem.cxx:308
void Reset(const char *dir)
Reset PROOF environment to be ready for execution of next command.
char * DynamicPathName(const char *lib, Bool_t quiet=kFALSE)
Find a dynamic library called lib using the system search paths.
Definition: TSystem.cxx:1959
TList * GetListOfDeActives() const
Returns a list with all de-active sockets.
Definition: TMonitor.cxx:515
static Float_t fgMemStop
Definition: TProofServ.h:177
Int_t(* OldProofServAuthSetup_t)(TSocket *, Bool_t, Int_t, TString &, TString &, TString &)
Definition: TProofServ.h:76
Int_t Lock()
Locks the directory.
static Int_t GetInputData(TList *input, const char *cachedir, TString &emsg)
Get the input data from the file defined in the input list.
Definition: TProof.cxx:12386
void Run(Bool_t retrn=kFALSE)
Main server eventloop.
void SetFd(int fd)
virtual void SetEntryList(TObject *aList)
Set entry (or event) list for this data set.
Definition: TDSet.cxx:1875
Int_t fLogLevel
Definition: TProofServ.h:121
Int_t GetParallel() const
Returns number of slaves active in parallel mode.
Definition: TProof.cxx:2282
TMap implements an associative array of (key,value) pairs using a THashTable for efficient retrieval ...
Definition: TMap.h:44
int type
Definition: TGX11.cxx:120
R__EXTERN TEnv * gEnv
Definition: TEnv.h:174
Int_t fMergedWorkers
Definition: TProofServ.h:165
The TTimeStamp encapsulates seconds and ns since EPOCH.
Definition: TTimeStamp.h:76
This class controls a Parallel ROOT Facility, PROOF, cluster.
Definition: TProof.h:346
int nentries
Definition: THbookFile.cxx:89
virtual void SetInputList(TList *in, Bool_t adopt=kTRUE)
Set / change the input list.
you should not use this method at all Int_t Int_t Double_t Double_t Double_t e
Definition: TRolke.cxx:630
virtual Int_t GetGid(const char *group=0)
Returns the group&#39;s id. If group = 0, returns current user&#39;s group.
Definition: TSystem.cxx:1544
virtual TQueryResult * GetCurrentQuery() const =0
void SetRunStatus(ERunStatus rst)
Definition: TProof.h:702
Float_t fRealTime
Definition: TProofServ.h:127
static Int_t RegisterGlobalPath(const char *paths)
Parse one or more paths as possible sources of packages Returns number of paths added; or -1 in case ...
Definition: TPackMgr.cxx:882
Int_t BufferSize() const
Definition: TBuffer.h:94
TStopwatch fSaveOutput
Definition: TProofServ.h:131
void RemoveQuery(TQueryResult *qr, Bool_t soft=kFALSE)
Remove everything about query qr.
virtual TInetAddress GetSockName(int sock)
Get Internet Protocol (IP) address of host and port #.
Definition: TSystem.cxx:2291
Int_t Unlock()
Unlock the directory.
virtual void StopProcess(Bool_t abort, Int_t timeout=-1)=0
virtual void Clear(Option_t *option="")
Remove all objects from the list.
Definition: TList.cxx:349
virtual Int_t GetUid(const char *user=0)
Returns the user&#39;s id. If user = 0, returns current user&#39;s id.
Definition: TSystem.cxx:1525
void SetIdle(Bool_t st=kTRUE)
Change the idle status.
Definition: TSocket.h:67
Int_t AddWorkers(TList *wrks)
Works on the master node only.
Definition: TProof.cxx:1304
void SetArchived(const char *archfile)
Set (or update) query in archived state.
Bool_t Notify()
Handle expiration of the shutdown timer.
Definition: TProofServ.cxx:421
Bool_t fEndMaster
Definition: TProofServ.h:124
TQueryResult version adapted to PROOF neeeds.
Int_t GetPort() const
Definition: TUrl.h:87
static TMap * GetDataSetNodeMap(TFileCollection *fc, TString &emsg)
Get a map {server-name, list-of-files} for collection &#39;fc&#39; to be used in TPacketizerFile.
void SetLogger(TPackMgrLog_t logger)
Definition: TPackMgr.h:77
void SaveQuery(TProofQueryResult *qr, const char *fout=0)
Save current status of query &#39;qr&#39; to file name fout.
Int_t Match(const TString &s, UInt_t start=0)
Runs a match on s against the regex &#39;this&#39; was created with.
Definition: TPRegexp.cxx:705
static TString fgSysLogEntity
Definition: TProofServ.h:188
Int_t UnloadPackage(const char *package)
Unload specified package.
Definition: TProof.cxx:8086
void Throw(int code)
If an exception context has been set (using the TRY and RETRY macros) jump back to where it was set...
Definition: TException.cxx:27
Mother of all ROOT objects.
Definition: TObject.h:37
The purpose of this class is to provide a standard interface to static config files.
void TruncateLogFile()
Truncate the log file to the 80% of the required max size if this is set.
Bool_t IsValid() const
Definition: TInetAddress.h:80
const char * GetImage() const
Definition: TProofServ.h:258
virtual Bool_t Add(const char *file, const char *objname=0, const char *dir=0, Long64_t first=0, Long64_t num=-1, const char *msd=0)
Add file to list of files to be analyzed.
Definition: TDSet.cxx:1033
Bool_t ExistsDataSet(const char *group, const char *user, const char *dsName)
Checks if the indicated dataset exits.
TObject * FindObject(const char *keyname) const
Check if a (key,value) pair exists with keyname as name of the key.
Definition: TMap.cxx:214
TTime fTime
Definition: TTimer.h:60
Float_t GetCpuTime() const
Definition: TProof.h:961
Long64_t GetBytesRead() const
virtual void HandleGetTreeHeader(TMessage *mess)=0
virtual void Openlog(const char *name, Int_t options, ELogFacility facility)
Open connection to system log daemon.
Definition: TSystem.cxx:1640
void ShowEnabledPackages(Bool_t all=kFALSE)
List which packages are enabled.
Definition: TProof.cxx:7790
Bool_t R_ISDIR(Int_t mode)
Definition: TSystem.h:126
const TString & GetWorkDir() const
virtual Int_t CreateServer()
Finalize the server setup.
Definition: TProofServ.cxx:795
virtual Long64_t GetCacheSize()=0
virtual void Add(TObject *obj)
Definition: TList.h:81
const Ssiz_t kNPOS
Definition: Rtypes.h:115
Wrapper for PCRE library (Perl Compatible Regular Expressions).
Definition: TPRegexp.h:103
Int_t GetSessionStatus()
Return the status of this session: 0 idle 1 running 2 being terminated (currently unused) 3 queued 4 ...
Class that contains a list of TFileInfo&#39;s and accumulated meta data information about its entries...
Definition: file.py:1
const char * GetWorkDir() const
Definition: TProofServ.h:257
virtual void SetOutputFilePath(const char *fp)=0
TFileCollection * GetDataSet(const char *uri, const char *srv=0)
Utility function used in various methods for user dataset upload.
TProofQueryResult * MakeQueryResult(Long64_t nentries, const char *opt, TList *inl, Long64_t first, TDSet *dset, const char *selec, TObject *elist)
Create a TProofQueryResult instance for this query.
virtual void Exit(int code, Bool_t mode=kTRUE)
Exit the application.
Definition: TSystem.cxx:721
Int_t CleanupQueriesDir()
Remove all queries results referring to previous sessions.
R__EXTERN Int_t gProofDebugLevel
Definition: TProofDebug.h:56
static TString fgLastMsg
Definition: TProofServ.h:242
void WriteObject(const TObject *obj)
Write object to message buffer.
Definition: TMessage.cxx:418
virtual Int_t Setup()
Print the ProofServ logo on standard output.
TProofServLogHandler(const char *cmd, TSocket *s, const char *pfx="")
Execute &#39;cmd&#39; in a pipe and handle output messages from the related file.
Definition: TProofServ.cxx:245
void AskStatistics()
Ask the for the statistics of the slaves.
Definition: TProof.cxx:2000
const Int_t kError
Definition: TError.h:41
virtual int GetProcInfo(ProcInfo_t *info) const
Returns cpu and memory used by this process into the ProcInfo_t structure.
Definition: TSystem.cxx:2471
you should not use this method at all Int_t Int_t Double_t Double_t Double_t Int_t Double_t Double_t Double_t Double_t b
Definition: TRolke.cxx:630
TString fWorkDir
Definition: TProofServ.h:95
static Int_t SaveInputData(TQueryResult *qr, const char *cachedir, TString &emsg)
Save input data file from &#39;cachedir&#39; into the sandbox or create a the file with input data objects...
Definition: TProof.cxx:12284
#define snprintf
Definition: civetweb.c:822
Int_t SetParallel(Int_t nodes=-1, Bool_t random=kFALSE)
Tell PROOF how many slaves to use in parallel.
Definition: TProof.cxx:7112
virtual void * OpenDirectory(const char *name)
Open a directory. Returns 0 if directory does not exist.
Definition: TSystem.cxx:831
R__EXTERN Int_t gDebug
Definition: Rtypes.h:128
TObject * GetValue(const char *keyname) const
Returns a pointer to the value associated with keyname as name of the key.
Definition: TMap.cxx:235
Int_t Remove(const char *pack=0, Bool_t dolock=kTRUE)
Remove package &#39;pack&#39; If &#39;pack&#39; is null or empty all packages are cleared.
Definition: TPackMgr.cxx:607
virtual void DeletePlayer()
Delete player instance.
Int_t AddDynamicPath(const char *libpath, Bool_t onClient=kFALSE, TList *wrks=0, Bool_t doCollect=kTRUE)
Add &#39;libpath&#39; to the lib path search.
Definition: TProof.cxx:8815
virtual TProofProgressStatus * GetProgressStatus() const =0
void Reset()
Definition: TStopwatch.h:54
Bool_t IsParallel() const
Definition: TProof.h:969
void RedirectOutput(const char *dir=0, const char *mode="w")
Redirect stdout to a log file.
virtual void AddIncludePath(const char *includePath)
Add includePath to the already set include path.
Definition: TSystem.cxx:4010
const char * GetUser() const
Definition: TProof.h:936
virtual Int_t AddOutputObject(TObject *obj)=0
virtual void Stop()
Definition: TTimer.h:99
const AParamType & GetVal() const
Definition: TParameter.h:77
virtual void AddFileHandler(TFileHandler *fh)
Add a file handler to the list of system file handlers.
Definition: TSystem.cxx:559
TMD5 * GetMD5(const char *pack)
Get MD5 checksum of the PAR file corresponding to given package Returns a pointer to a TMD5 object...
Definition: TPackMgr.cxx:706
static void ResetErrno()
Static function resetting system error number.
Definition: TSystem.cxx:281
#define gDirectory
Definition: TDirectory.h:221
static void SetLastMsg(const char *lastmsg)
Set the message to be sent back in case of exceptions.
double result[121]
Class describing a generic file including meta information.
Definition: TFileInfo.h:50
static void SetDefaultPrefix(const char *pfx)
Static method to set the default prefix.
Definition: TProofServ.cxx:341
void ResetBit(UInt_t f)
Definition: TObject.h:156
This class creates the ROOT Application Environment that interfaces to the windowing system eventloop...
Definition: TApplication.h:45
Bool_t IsValid() const
Definition: TProof.h:967
void RestartComputeTime()
Reset the compute time.
virtual Bool_t ExpandPathName(TString &path)
Expand a pathname getting rid of special shell characters like ~.
Definition: TSystem.cxx:1244
Abstract interface for the PROOF player.
Long64_t fMsgSizeHWM
Definition: TProofServ.h:180
Definition: first.py:1
virtual void Terminate(Int_t status)
Terminate the proof server.
TList * fWaitingQueries
Definition: TProofServ.h:142
TString fCacheDir
Definition: TProofServ.h:101
TString fQueryDir
Definition: TProofServ.h:102
Int_t fTotSessions
Definition: TProofServ.h:134
virtual ~TProofServLogHandlerGuard()
Close a guard for executing a command in a pipe.
Definition: TProofServ.cxx:397
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition: TObject.cxx:953
const Bool_t kIterBackward
Definition: TCollection.h:44
virtual Int_t SavePartialResults(Bool_t queryend=kFALSE, Bool_t force=kFALSE)=0
virtual void Print(Option_t *option="") const
Default print for collections, calls Print(option, 1).
void Print(Option_t *option="") const
Print status of slave server.
void SendStatistics()
Send statistics of slave server to master or client.
virtual Int_t Load(const char *macro, Bool_t notOnClient=kFALSE, Bool_t uniqueOnly=kTRUE, TList *wrks=0)
Load the specified macro on master, workers and, if notOnClient is kFALSE, on the client...
Definition: TProof.cxx:8600
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:416
virtual Int_t GetSize() const
Definition: TCollection.h:95
Int_t Substitute(TString &s, const TString &r, Bool_t doDollarSubst=kTRUE)
Substitute matching part of s with r, dollar back-ref substitution is performed if doDollarSubst is t...
Definition: TPRegexp.cxx:871
const char * GetDataDir() const
Definition: TProofServ.h:264
const char * GetUser() const
Definition: TProofServ.h:255
Container class for processing statistics.
A TSelector object is used by the TTree::Draw, TTree::Scan, TTree::Process to navigate in a TTree and...
Definition: TSelector.h:39
static void ErrorHandler(Int_t level, Bool_t abort, const char *location, const char *msg)
The PROOF error handler function.
const char * GetObjName() const
Definition: TDSet.h:229
virtual Int_t RecvRaw(void *buffer, Int_t length, ESendRecvOptions opt=kDefault)
Receive a raw buffer of specified length bytes.
Definition: TSocket.cxx:901
const Bool_t kTRUE
Definition: Rtypes.h:91
float * q
Definition: THbookFile.cxx:87
Int_t ClearPackage(const char *package)
Remove a specific package.
Definition: TProof.cxx:7829
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition: TNamed.cxx:155
Bool_t IsParallel() const
True if in parallel mode.
Int_t CleanupWaitingQueries(Bool_t del=kTRUE, TList *qls=0)
Cleanup the waiting queries list.
virtual void TurnOn()
Add the timer to the system timer list.
Definition: TTimer.cxx:241
A List of entry numbers in a TTree or TChain.
Definition: TEntryList.h:27
Int_t DeactivateWorker(const char *ord, Bool_t save=kTRUE)
Remove the worker identified by the ordinal number &#39;ord&#39; from the the active list.
Definition: TProof.cxx:11342
TList * GetListOfActiveSlaves() const
Definition: TProof.h:753
virtual TMap * GetDataSets(const char *uri, UInt_t=TDataSetManager::kExport)
Returns all datasets for the <group> and <user> specified by <uri>.
Int_t fQuerySeqNum
Definition: TProofServ.h:132
static TString fgSysLogService
Definition: TProofServ.h:187
const char * GetOrdinal() const
Definition: TProofServ.h:267
const Int_t n
Definition: legend1.C:16
Int_t fLogFileDes
Definition: TProofServ.h:115
Bool_t IsMaster() const
Definition: TProofServ.h:307
TProofServ(Int_t *argc, char **argv, FILE *flog=0)
Main constructor.
Definition: TProofServ.cxx:565
Int_t GetNanoSec() const
Definition: TTimeStamp.h:141
char name[80]
Definition: TGX11.cxx:109
TProofLockPath * fCacheLock
Definition: TProofServ.h:108
double log(double)
Long_t fMemResident
Definition: TSystem.h:206
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:911
virtual void SetIncludePath(const char *includePath)
IncludePath should contain the list of compiler flags to indicate where to find user defined header f...
Definition: TSystem.cxx:4045
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:52
TQueryResultManager * fQMgr
Definition: TProofServ.h:140
const char * GetPrefix() const
Definition: TProofServ.h:290
virtual Long_t ProcessFile(const char *file, Int_t *error=0, Bool_t keep=kFALSE)
Process a file containing a C++ macro.
Bool_t fSendLogToMaster
Definition: TProofServ.h:161
TProofLockPath * fQueryLock
Definition: TProofServ.h:109
static Long64_t fgLastEntry
Definition: TProofServ.h:243
const char *const kPROOF_CacheDir
Definition: TProof.h:155
virtual TSQLRow * Next()=0
const char *const kPROOF_PackDir
Definition: TProof.h:156
Stopwatch class.
Definition: TStopwatch.h:30
static Int_t AssertDataSet(TDSet *dset, TList *input, TDataSetManager *mgr, TString &emsg)
Make sure that dataset is in the form to be processed.
Definition: TProof.cxx:11987