ROOT  6.07/01
Reference Guide
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
XrdProofdProofServMgr.cxx
Go to the documentation of this file.
1 // @(#)root/proofd:$Id$
2 // Author: G. Ganis Jan 2008
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2005, 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 //////////////////////////////////////////////////////////////////////////
13 // //
14 // XrdProofdProofServMgr //
15 // //
16 // Author: G. Ganis, CERN, 2008 //
17 // //
18 // Class managing proofserv sessions manager. //
19 // //
20 //////////////////////////////////////////////////////////////////////////
21 #include "XrdProofdPlatform.h"
22 
23 #include "XpdSysDNS.h"
24 #include "XpdSysError.h"
25 #include "XpdSysLogger.h"
26 
27 #include "Xrd/XrdBuffer.hh"
28 #include "Xrd/XrdPoll.hh"
29 #include "Xrd/XrdScheduler.hh"
30 #include "XrdNet/XrdNet.hh"
31 #include "XrdOuc/XrdOucRash.hh"
32 #include "XrdOuc/XrdOucStream.hh"
33 #include "XrdSys/XrdSysPriv.hh"
34 #include "XrdSys/XrdSysPlugin.hh"
35 #include "XrdProofdClient.h"
36 #include "XrdProofdClientMgr.h"
37 #include "XrdProofdManager.h"
38 #include "XrdProofdNetMgr.h"
39 #include "XrdProofdPriorityMgr.h"
40 #include "XrdProofdProofServMgr.h"
41 #include "XrdProofdProtocol.h"
42 #include "XrdProofGroup.h"
43 #include "XrdProofSched.h"
44 #include "XrdROOT.h"
45 
46 #include <map>
47 
48 // Aux structures for scan through operations
49 typedef struct {
50  XrdProofGroupMgr *fGroupMgr;
51  int *fNBroadcast;
52 } XpdBroadcastPriority_t;
53 typedef struct {
54  XrdProofdManager *fMgr;
55  XrdProofdClient *fClient;
56  FILE *fEnv;
57  bool fExport;
58 } XpdWriteEnv_t;
59 
60 #ifndef PutEnv
61 #define PutEnv(x,e) { if (e) { putenv(x); } else { delete[] x; } }
62 #endif
63 
64 // Tracing utilities
65 #include "XrdProofdTrace.h"
66 
68 
69 //--------------------------------------------------------------------------
70 //
71 // XrdProofdProofServCron
72 //
73 // Function run in separate thread watching changes in session status
74 // frequency
75 //
76 ////////////////////////////////////////////////////////////////////////////////
77 /// This is an endless loop to check the system periodically or when
78 /// triggered via a message in a dedicated pipe
79 
80 void *XrdProofdProofServCron(void *p)
81 {
82  XPDLOC(SMGR, "ProofServCron")
83 
86  XrdProofSched *sched = mc->fProofSched;
87  if (!(mgr)) {
88  TRACE(XERR, "undefined session manager: cannot start");
89  return (void *)0;
90  }
91 
92  // Quicj checks for client disconnections: frequency (5 secs) and
93  // flag for disconnections effectively occuring
94  int quickcheckfreq = 5;
95  int clnlostscale = 0;
96 
97  // Time of last full sessions check
98  int lastrun = time(0);
99  int lastcheck = lastrun, ckfreq = mgr->CheckFrequency(), waitt = 0;
100  int deltat = ((int)(0.1*ckfreq) >= 1) ? (int)(0.1*ckfreq) : 1;
101  int maxdelay = 5*ckfreq; // Force check after 5 times the check frequency
102  mgr->SetNextSessionsCheck(lastcheck + ckfreq);
103  TRACE(ALL, "next full sessions check in "<<ckfreq<<" secs");
104  while(1) {
105  // We check for client disconnections every 'quickcheckfreq' secs; we do
106  // a full check every mgr->CheckFrequency() secs; we make sure that we
107  // do not pass a negative value (meaning no timeout)
108  waitt = ckfreq - (time(0) - lastcheck);
109  if (waitt > quickcheckfreq || waitt <= 0)
110  waitt = quickcheckfreq;
111  int pollRet = mgr->Pipe()->Poll(waitt);
112 
113  if (pollRet > 0) {
114  // Read message
115  XpdMsg msg;
116  int rc = 0;
117  if ((rc = mgr->Pipe()->Recv(msg)) != 0) {
118  TRACE(XERR, "problems receiving message; errno: "<<-rc);
119  continue;
120  }
121  // Parse type
123  // A session has just gone: read process id
124  XrdOucString fpid;
125  if ((rc = msg.Get(fpid)) != 0) {
126  TRACE(XERR, "kSessionRemoval: problems receiving process ID (buf: '"<<
127  msg.Buf()<<"'); errno: "<<-rc);
128  continue;
129  }
130  XrdSysMutexHelper mhp(mgr->Mutex());
131  // Remove it from the hash list
132  mgr->DeleteFromSessions(fpid.c_str());
133  // Move the entry to the terminated sessions area
134  mgr->MvSession(fpid.c_str());
135  // Notify the scheduler too
136  if (sched) {
137  if (sched->Pipe()->Post(XrdProofSched::kReschedule, 0) != 0) {
138  TRACE(XERR, "kSessionRemoval: problem posting the scheduler pipe");
139  }
140  }
141  // Notify action
142  TRACE(REQ, "kSessionRemoval: session: "<<fpid<<
143  " has been removed from the active list");
144  } else if (msg.Type() == XrdProofdProofServMgr::kClientDisconnect) {
145  // Obsolete
146  TRACE(XERR, "obsolete type: XrdProofdProofServMgr::kClientDisconnect");
147  } else if (msg.Type() == XrdProofdProofServMgr::kCleanSessions) {
148  // Request for cleanup all sessions of a client (or all clients)
150  XrdOucString usr;
151  rc = msg.Get(usr);
152  int svrtype = kXPD_AnyServer;
153  rc = (rc == 0) ? msg.Get(svrtype) : rc;
154  if (rc != 0) {
155  TRACE(XERR, "kCleanSessions: problems parsing message (buf: '"<<
156  msg.Buf()<<"'); errno: "<<-rc);
157  continue;
158  }
159  // Notify action
160  TRACE(REQ, "kCleanSessions: request for user: '"<<usr<<"', server type: "<<svrtype);
161  // Clean sessions
162  mgr->CleanClientSessions(usr.c_str(), svrtype);
163  // Check if there is any orphalin sessions and clean them up
164  mgr->CleanupLostProofServ();
165  } else if (msg.Type() == XrdProofdProofServMgr::kProcessReq) {
166  // Process request from some client: if we are here it means they can go ahead
167  mgr->ProcessSem()->Post();
168  } else if (msg.Type() == XrdProofdProofServMgr::kChgSessionSt) {
169  // Propagate cluster information to active sessions after one session changed its state
170  mgr->BroadcastClusterInfo();
171  } else {
172  TRACE(XERR, "unknown type: "<<msg.Type());
173  continue;
174  }
175  } else {
176 
177  // The current time
178  int now = time(0);
179 
180  // If there is any activity in mgr->Process() we postpone the checks in 5 secs
182  if (cnt > 0) {
183  if ((now - lastrun) < maxdelay) {
184  // The current time
185  lastcheck = now + 5 - ckfreq;
186  mgr->SetNextSessionsCheck(now + 5);
187  // Notify
188  TRACE(ALL, "postponing sessions check (will retry in 5 secs)");
189  continue;
190  } else {
191  // Max time without checks reached: force a check
192  TRACE(ALL, "Max time without checks reached ("<<maxdelay<<"): force a session check");
193  // Reset the counter
195  }
196  }
197 
198  bool full = (now > mgr->NextSessionsCheck() - deltat) ? 1 : 0;
199  if (full) {
200  // Run periodical full checks
201  mgr->CheckActiveSessions();
203  if (clnlostscale <= 0) {
204  mgr->CleanupLostProofServ();
205  clnlostscale = 10;
206  } else {
207  clnlostscale--;
208  }
209  // How many active sessions do we have
210  int cursess = mgr->CurrentSessions(1);
211  TRACE(ALL, cursess << " sessions are currently active");
212  // Remember when ...
213  lastrun = now;
214  lastcheck = now;
215  mgr->SetNextSessionsCheck(lastcheck + mgr->CheckFrequency());
216  // Notify
217  TRACE(ALL, "next sessions check in "<<mgr->CheckFrequency()<<" secs");
218  } else {
219  TRACE(HDBG, "nothing to do; "<<mgr->NextSessionsCheck()-now<<" secs to full check");
220  }
221  }
222  }
223 
224  // Should never come here
225  return (void *)0;
226 }
227 
228 //--------------------------------------------------------------------------
229 //
230 // XrdProofdProofServRecover
231 //
232 // Function run in a separate thread waiting for session to recover after
233 // an abrupt shutdown
234 //
235 ////////////////////////////////////////////////////////////////////////////////
236 /// Waiting for session to recover after an abrupt shutdown
237 
239 {
240  XPDLOC(SMGR, "ProofServRecover")
241 
244  if (!(mgr)) {
245  TRACE(XERR, "undefined session manager: cannot start");
246  return (void *)0;
247  }
248 
249  // Recover active sessions
250  int rc = mgr->RecoverActiveSessions();
251 
252  // Notify end of recovering
253  if (rc > 0) {
254  TRACE(ALL, "timeout recovering sessions: "<<rc<<" sessions not recovered");
255  } else if (rc < 0) {
256  TRACE(XERR, "some problem occured while recovering sessions");
257  } else {
258  TRACE(ALL, "recovering successfully terminated");
259  }
260 
261  // Should never come here
262  return (void *)0;
263 }
264 
265 ////////////////////////////////////////////////////////////////////////////////
266 /// Constructor
267 
269  XrdProtocol_Config *pi, XrdSysError *e)
270  : XrdProofdConfig(pi->ConfigFN, e), fProcessSem(0)
271 {
272  XPDLOC(SMGR, "XrdProofdProofServMgr")
273 
274  fMgr = mgr;
275  fLogger = pi->eDest->logger();
276  fInternalWait = 10;
277  fActiveSessions.clear();
278  fShutdownOpt = 1;
279  fShutdownDelay = 0;
280  fReconnectTime = -1;
281  fReconnectTimeOut = 300;
282  fNextSessionsCheck = -1;
283  // Init internal counters
284  for (int i = 0; i < PSMMAXCNTS; i++) {
285  fCounters[i] = 0;
286  }
287  fCurrentSessions = 0;
288 
289  fSeqSessionN = 0;
290 
291  fCredsSaver = 0;
292 
293  // Defaults can be changed via 'proofservmgr'
294  fCheckFrequency = 30;
297  fRecoverTimeOut = 10;
298  fCheckLost = 1;
299  fUseFork = 1;
300  fParentExecs = "xproofd,xrootd";
301 
302  // Recover-related quantities
303  fRecoverClients = 0;
304  fRecoverDeadline = -1;
305 
306  // Init pipe for the poller
307  if (!fPipe.IsValid()) {
308  TRACE(XERR, "unable to generate pipe for the session poller");
309  return;
310  }
311 
312  // Configuration directives
314 }
315 
316 ////////////////////////////////////////////////////////////////////////////////
317 /// Run configuration and parse the entered config directives.
318 /// Return 0 on success, -1 on error
319 
321 {
322  XPDLOC(SMGR, "ProofServMgr::Config")
323 
325 
326  bool notify = (rcf) ? 0 : 1;
327  if (rcf && ReadFile(0)) {
328  // Cleanup lists of envs and RCs
329  fProofServRCs.clear();
330  fProofServEnvs.clear();
331  // Notify possible new settings
332  notify = 1;
333  }
334 
335  // Run first the configurator
336  if (XrdProofdConfig::Config(rcf) != 0) {
337  TRACE(XERR, "problems parsing file ");
338  return -1;
339  }
340 
341  XrdOucString msg;
342  msg = (rcf) ? "re-configuring" : "configuring";
343  if (notify) XPDPRT(msg);
344 
345  // Notify timeout on internal communications
346  XPDFORM(msg, "setting internal timeout to %d secs", fInternalWait);
347  if (notify) XPDPRT(msg);
348 
349  // Shutdown options
350  msg = "client sessions shutdown after disconnection";
351  if (fShutdownOpt > 0) {
352  XPDFORM(msg, "client sessions kept %sfor %d secs after disconnection",
353  (fShutdownOpt == 1) ? "idle " : "", fShutdownDelay);
354  }
355  if (notify) XPDPRT(msg);
356 
357  if (!rcf) {
358  // Admin paths
360  fActiAdminPath += "/activesessions";
362  fTermAdminPath += "/terminatedsessions";
363 
364  // Make sure they exist
365  XrdProofUI ui;
367  if (XrdProofdAux::AssertDir(fActiAdminPath.c_str(), ui, 1) != 0) {
368  TRACE(XERR, "unable to assert the admin path: "<<fActiAdminPath);
369  fActiAdminPath = "";
370  return -1;
371  }
372  XPDPRT("active sessions admin path set to: "<<fActiAdminPath);
373 
374  if (XrdProofdAux::AssertDir(fTermAdminPath.c_str(), ui, 1) != 0) {
375  TRACE(XERR, "unable to assert the admin path "<<fTermAdminPath);
376  fTermAdminPath = "";
377  return -1;
378  }
379  XPDPRT("terminated sessions admin path set to "<<fTermAdminPath);
380  }
381 
382  if (notify) {
383  XPDPRT("RC settings: "<< fProofServRCs.size());
384  if (fProofServRCs.size() > 0) {
385  std::list<XpdEnv>::iterator ircs = fProofServRCs.begin();
386  for ( ; ircs != fProofServRCs.end(); ircs++) { (*ircs).Print("rc"); }
387  }
388  XPDPRT("ENV settings: "<< fProofServEnvs.size());
389  if (fProofServEnvs.size() > 0) {
390  std::list<XpdEnv>::iterator ienvs = fProofServEnvs.begin();
391  for ( ; ienvs != fProofServEnvs.end(); ienvs++) { (*ienvs).Print("env"); }
392  }
393  }
394 
395  // Notify sessions startup technology
396  XPDFORM(msg, "using %s to start proofserv sessions", fUseFork ? "fork()" : "system()");
397  if (notify) XPDPRT(msg);
398 
399  if (!rcf) {
400  // Try to recover active session previously started
401  int nr = -1;
402  if ((nr = PrepareSessionRecovering()) < 0) {
403  TRACE(XERR, "problems trying to recover active sessions");
404  } else if (nr > 0) {
405  XPDFORM(msg, "%d active sessions have been recovered", nr);
406  XPDPRT(msg);
407  }
408 
409  // Start cron thread
410  pthread_t tid;
411  // Fill manager pointers structure
412  fManagerCron.fClientMgr = fMgr->ClientMgr();
413  fManagerCron.fSessionMgr = this;
414  if (XrdSysThread::Run(&tid, XrdProofdProofServCron,
415  (void *)&fManagerCron, 0, "ProofServMgr cron thread") != 0) {
416  TRACE(XERR, "could not start cron thread");
417  return 0;
418  }
419  XPDPRT("cron thread started");
420  }
421 
422  // Done
423  return 0;
424 }
425 
426 ////////////////////////////////////////////////////////////////////////////////
427 /// Add new active session
428 
430 {
431  XPDLOC(SMGR, "ProofServMgr::AddSession")
432 
433  TRACE(REQ, "adding new active session ...");
434 
435  // Check inputs
436  if (!s || !p->Client()) {
437  TRACE(XERR,"invalid inputs: "<<(s ? "" : "s, ") <<", "<< (p->Client() ? "" : "p->Client()"));
438  return -1;
439  }
440  XrdProofdClient *c = p->Client();
441 
442  // Path
443  XrdOucString path;
444  XPDFORM(path, "%s/%s.%s.%d", fActiAdminPath.c_str(), c->User(), c->Group(), s->SrvPID());
445 
446  // Save session info to file
447  XrdProofSessionInfo info(c, s);
448  int rc = info.SaveToFile(path.c_str());
449 
450  return rc;
451 }
452 
453 ////////////////////////////////////////////////////////////////////////////////
454 /// Checks is fpid is the path of a session UNIX socket
455 /// Returns TRUE is yes; cleans the socket if the session is gone.
456 
458 {
459  XPDLOC(SMGR, "ProofServMgr::IsSessionSocket")
460 
461  TRACE(REQ, "checking "<<fpid<<" ...");
462 
463  // Check inputs
464  if (!fpid || strlen(fpid) <= 0) {
465  TRACE(XERR, "invalid input: "<<(fpid ? fpid : "<nul>"));
466  return 0;
467  }
468 
469  // Paths
470  XrdOucString spath(fpid);
471  if (!spath.endswith(".sock")) return 0;
472  if (!spath.beginswith(fActiAdminPath.c_str())) {
473  // We are given a partial path: create full paths
474  XPDFORM(spath, "%s/%s", fActiAdminPath.c_str(), fpid);
475  }
476  XrdOucString apath = spath;
477  apath.replace(".sock", "");
478 
479  // Check the admin path
480  struct stat st;
481  if (stat(apath.c_str(), &st) != 0 && (errno == ENOENT)) {
482  // Remove the socket path if not during creation
483  if (CheckCounter(kCreateCnt) <= 0) {
484  unlink(spath.c_str());
485  TRACE(REQ, "missing admin path: removing "<<spath<<" ...");
486  }
487  }
488 
489  // Done
490  return 1;
491 }
492 
493 ////////////////////////////////////////////////////////////////////////////////
494 /// Move session file from the active to the terminated areas
495 
496 int XrdProofdProofServMgr::MvSession(const char *fpid)
497 {
498  XPDLOC(SMGR, "ProofServMgr::MvSession")
499 
500  TRACE(REQ, "moving "<<fpid<<" ...");
501 
502  // Check inputs
503  if (!fpid || strlen(fpid) <= 0) {
504  TRACE(XERR, "invalid input: "<<(fpid ? fpid : "<nul>"));
505  return -1;
506  }
507 
508  // Paths
509  XrdOucString opath(fpid), npath;
510  if (!opath.beginswith(fActiAdminPath.c_str())) {
511  // We are given a partial path: create full paths
512  XPDFORM(opath, "%s/%s", fActiAdminPath.c_str(), fpid);
513  opath.replace(".status", "");
514  } else {
515  // Full path: just create the new path
516  opath.replace(".status", "");
517  }
518  // The target path
519  npath = opath;
520  npath.replace(fActiAdminPath.c_str(), fTermAdminPath.c_str());
521 
522  // Remove the socket path
523  XrdOucString spath = opath;
524  spath += ".sock";
525  if (unlink(spath.c_str()) != 0 && errno != ENOENT)
526  TRACE(XERR, "problems removing the UNIX socket path: "<<spath<<"; errno: "<<errno);
527  spath.replace(".sock", ".status");
528  if (unlink(spath.c_str()) != 0 && errno != ENOENT)
529  TRACE(XERR, "problems removing the status file: "<<spath<<"; errno: "<<errno);
530 
531  // Move the file
532  errno = 0;
533  int rc = 0;
534  if ((rc = rename(opath.c_str(), npath.c_str())) == 0 || (errno == ENOENT)) {
535  if (!rc)
536  // Record the time when we did this
537  TouchSession(fpid, npath.c_str());
538  return 0;
539  }
540 
541  TRACE(XERR, "session pid file cannot be moved: "<<opath<<
542  "; target file: "<<npath<<"; errno: "<<errno);
543  return -1;
544 }
545 
546 ////////////////////////////////////////////////////////////////////////////////
547 /// Remove session file from the terminated sessions area
548 
549 int XrdProofdProofServMgr::RmSession(const char *fpid)
550 {
551  XPDLOC(SMGR, "ProofServMgr::RmSession")
552 
553  TRACE(REQ, "removing "<<fpid<<" ...");
554 
555  // Check inputs
556  if (!fpid || strlen(fpid) <= 0) {
557  TRACE(XERR, "invalid input: "<< (fpid ? fpid : "<nul>"));
558  return -1;
559  }
560 
561  // Path
562  XrdOucString path;
563  XPDFORM(path, "%s/%s", fTermAdminPath.c_str(), fpid);
564 
565  // remove the file
566  if (unlink(path.c_str()) == 0)
567  return 0;
568 
569  TRACE(XERR, "session pid file cannot be unlinked: "<<
570  path<<"; error: "<<errno);
571  return -1;
572 }
573 
574 ////////////////////////////////////////////////////////////////////////////////
575 /// Update the access time for the session pid file to the current time
576 
577 int XrdProofdProofServMgr::TouchSession(const char *fpid, const char *fpath)
578 {
579  XPDLOC(SMGR, "ProofServMgr::TouchSession")
580 
581  TRACE(REQ, "touching "<<(fpid ? fpid : "<nul>")<<", "<<(fpath ? fpath : "<nul>")<<" ...");
582 
583  // Check inputs
584  if (!fpid || strlen(fpid) <= 0) {
585  TRACE(XERR, "invalid input: "<<(fpid ? fpid : "<nul>"));
586  return -1;
587  }
588 
589  // Path
590  XrdOucString path(fpath);
591  if (!fpath || !fpath[0])
592  XPDFORM(path, "%s/%s.status", fActiAdminPath.c_str(), fpid);
593 
594  // Update file time stamps
595  if (utime(path.c_str(), 0) == 0)
596  return 0;
597 
598  TRACE(XERR, "time stamps for session pid file cannot be updated: "<<
599  path<<"; error: "<<errno);
600  return -1;
601 }
602 
603 ////////////////////////////////////////////////////////////////////////////////
604 /// Check if the session is alive, i.e. if it has recently touched its admin file.
605 /// Return 0 if alive, 1 if not-responding, -1 in case of error.
606 /// The timeout for verification is 'to' if positive, else fVerifyTimeOut;
607 /// the admin file is looked under 'fpath' if defined, else fActiAdminPath.
608 
610  int to, const char *fpath)
611 {
612  XPDLOC(SMGR, "ProofServMgr::VerifySession")
613 
614  // Check inputs
615  if (!fpid || strlen(fpid) <= 0) {
616  TRACE(XERR, "invalid input: "<<(fpid ? fpid : "<nul>"));
617  return -1;
618  }
619 
620  // Path
621  XrdOucString path;
622  if (fpath && strlen(fpath) > 0)
623  XPDFORM(path, "%s/%s", fpath, fpid);
624  else
625  XPDFORM(path, "%s/%s", fActiAdminPath.c_str(), fpid);
626 
627  // Check first the new file but also the old one, for backward compatibility
628  int deltat = -1;
629  bool checkmore = 1;
630  while (checkmore) {
631  // Current settings
632  struct stat st;
633  if (stat(path.c_str(), &st)) {
634  TRACE(XERR, "session status file cannot be stat'ed: "<<
635  path<<"; error: "<<errno);
636  return -1;
637  }
638  // Check times
639  int xto = (to > 0) ? to : fVerifyTimeOut;
640  deltat = time(0) - st.st_mtime;
641  if (deltat > xto) {
642  if (path.endswith(".status")) {
643  // Check the old one too
644  path.erase(path.rfind(".status"));
645  } else {
646  // Dead
647  TRACE(DBG, "admin path for session "<<fpid<<" hase not been touched"
648  " since at least "<< xto <<" secs");
649  return 1;
650  }
651  } else {
652  // We are done
653  checkmore = 0;
654  }
655  }
656 
657  // Alive
658  TRACE(DBG, "admin path for session "<<fpid<<" was touched " <<
659  deltat <<" secs ago");
660  return 0;
661 }
662 
663 ////////////////////////////////////////////////////////////////////////////////
664 /// Delete from the hash list the session with ID pid.
665 /// Return -ENOENT if not found, or 0.
666 
668 {
669  XPDLOC(SMGR, "ProofServMgr::DeleteFromSessions")
670 
671  TRACE(REQ, "session: "<<fpid);
672 
673  // Check inputs
674  if (!fpid || strlen(fpid) <= 0) {
675  TRACE(XERR, "invalid input: "<<(fpid ? fpid : "<nul>"));
676  return -1;
677  }
678 
679  XrdOucString key = fpid;
680  key.replace(".status", "");
681  key.erase(0, key.rfind('.') + 1);
682  XrdProofdProofServ *xps = 0;
683  { XrdSysMutexHelper mhp(fMutex); xps = fSessions.Find(key.c_str()); }
684  if (xps) {
685  // Tell other attached clients, if any, that this session is gone
686  XrdOucString msg;
687  XPDFORM(msg, "session: %s terminated by peer", fpid);
688  TRACE(DBG, msg);
689  // Reset this instance
690  int tp = xps->Reset(msg.c_str(), kXPD_wrkmortem);
691  // Update counters and lists
693  if (tp == 1) fCurrentSessions--;
694  // remove from the list of active sessions
695  fActiveSessions.remove(xps);
696  }
697  int rc = -1;
698  { XrdSysMutexHelper mhp(fMutex); rc = fSessions.Del(key.c_str()); }
699  return rc;
700 }
701 
702 ////////////////////////////////////////////////////////////////////////////////
703 /// Go through the active sessions admin path and prepare reconnection of those
704 /// still alive.
705 /// Called at start-up.
706 
708 {
709  XPDLOC(SMGR, "ProofServMgr::PrepareSessionRecovering")
710 
711  // Open dir
712  DIR *dir = opendir(fActiAdminPath.c_str());
713  if (!dir) {
714  TRACE(XERR, "cannot open dir "<<fActiAdminPath<<" ; error: "<<errno);
715  return -1;
716  }
717  TRACE(REQ, "preparing recovering of active sessions ...");
718 
719  // Scan the active sessions admin path
720  fRecoverClients = new std::list<XpdClientSessions *>;
721  struct dirent *ent = 0;
722  while ((ent = (struct dirent *)readdir(dir))) {
723  if (!strncmp(ent->d_name, ".", 1) || !strncmp(ent->d_name, "..", 2)) continue;
724  // Get the session instance (skip non-digital entries)
725  XrdOucString rest, a;
726  int pid = XrdProofdAux::ParsePidPath(ent->d_name, rest, a);
727  if (!XPD_LONGOK(pid) || pid <= 0) continue;
728  if (a.length() > 0) continue;
729  bool rmsession = 1;
730  // Check if the process is still alive
731  if (XrdProofdAux::VerifyProcessByID(pid) != 0) {
732  if (ResolveSession(ent->d_name) == 0) {
733  TRACE(DBG, "found active session: "<<pid);
734  rmsession = 0;
735  }
736  }
737  // Remove the session, if needed
738  if (rmsession)
739  MvSession(ent->d_name);
740  }
741  // Close the directory
742  closedir(dir);
743 
744  // Start the recovering thread, if needed
745  int nrc = 0;
746  { XrdSysMutexHelper mhp(fRecoverMutex); nrc = fRecoverClients->size(); }
747  if (nrc > 0) {
748  // Start recovering thread
749  pthread_t tid;
750  // Fill manager pointers structure
751  fManagerCron.fClientMgr = fMgr->ClientMgr();
752  fManagerCron.fSessionMgr = this;
753  fManagerCron.fProofSched = fMgr->ProofSched();
754  if (XrdSysThread::Run(&tid, XrdProofdProofServRecover, (void *)&fManagerCron,
755  0, "ProofServMgr session recover thread") != 0) {
756  TRACE(XERR, "could not start session recover thread");
757  return 0;
758  }
759  XPDPRT("session recover thread started");
760  } else {
761  // End reconnect state if there is nothing to reconnect
762  if (fMgr->ClientMgr() && fMgr->ClientMgr()->GetNClients() <= 0)
763  SetReconnectTime(0);
764  }
765 
766  // Done
767  return 0;
768 }
769 
770 
771 ////////////////////////////////////////////////////////////////////////////////
772 /// Accept connections from sessions still alive. This is run in a dedicated
773 /// thread.
774 /// Returns -1 in case of failure, 0 if all alive sessions reconnected or the
775 /// numer of sessions not reconnected if the timeout (fRecoverTimeOut per client)
776 /// expired.
777 
779 {
780  XPDLOC(SMGR, "ProofServMgr::RecoverActiveSessions")
781 
782  int rc = 0;
783 
784  if (!fRecoverClients) {
785  // Invalid input
786  TRACE(XERR, "recovering clients list undefined");
787  return -1;
788  }
789 
790  int nrc = 0;
791  { XrdSysMutexHelper mhp(fRecoverMutex); nrc = fRecoverClients->size(); }
792  TRACE(REQ, "start recovering of "<<nrc<<" clients");
793 
794  // Recovering deadline
796  fRecoverDeadline = time(0) + fRecoverTimeOut * nrc; }
797 
798  // Respect the deadline
799  int nr = 0;
800  XpdClientSessions *cls = 0;
801  bool go = true;
802  while (go) {
803 
804  // Pickup the first one in the list
805  { XrdSysMutexHelper mhp(fRecoverMutex); cls = fRecoverClients->front(); }
806  if (cls) {
808  nr += Recover(cls);
809 
810  // If all client sessions reconnected remove the client from the list
811  { XrdSysMutexHelper mhp(cls->fMutex);
812  if (cls->fProofServs.size() <= 0) {
814  fRecoverClients->remove(cls);
815  // We may be over
816  if ((nrc = fRecoverClients->size()) <= 0)
817  break;
818  }
819  }
820  }
821  TRACE(REQ, nrc<<" clients still to recover");
822 
823  // Check the deadline
825  go = (time(0) < fRecoverDeadline) ? true : false; }
826  }
827  // End reconnect state
828  SetReconnectTime(0);
829 
830  // If we reached the deadline, calculate the number of sessions not reconnected
831  rc = 0;
833  if (fRecoverClients->size() > 0) {
834  std::list<XpdClientSessions* >::iterator ii = fRecoverClients->begin();
835  for (; ii != fRecoverClients->end(); ii++) {
836  rc += (*ii)->fProofServs.size();
837  }
838  }
839  }
840 
841  // Delete the recovering clients list
843  fRecoverClients->clear();
844  delete fRecoverClients;
845  fRecoverClients = 0;
846  fRecoverDeadline = -1;
847  }
848 
849  // Done
850  return rc;
851 }
852 
853 ////////////////////////////////////////////////////////////////////////////////
854 /// Returns true (an the recovering deadline) if the client has sessions in
855 /// recovering state; returns false otherwise.
856 /// Called during for attach requests.
857 
858 bool XrdProofdProofServMgr::IsClientRecovering(const char *usr, const char *grp,
859  int &deadline)
860 {
861  XPDLOC(SMGR, "ProofServMgr::IsClientRecovering")
862 
863  if (!usr || !grp) {
864  TRACE(XERR, "invalid inputs: usr: "<<(usr ? usr : "")<<", grp:"<<(grp ? grp : "")<<" ...");
865  return false;
866  }
867 
868  deadline = -1;
869  int rc = false;
871  if (fRecoverClients && fRecoverClients->size() > 0) {
872  std::list<XpdClientSessions *>::iterator ii = fRecoverClients->begin();
873  for (; ii != fRecoverClients->end(); ii++) {
874  if ((*ii)->fClient && (*ii)->fClient->Match(usr, grp)) {
875  rc = true;
876  deadline = fRecoverDeadline;
877  break;
878  }
879  }
880  }
881  }
882  TRACE(DBG, "checking usr: "<<usr<<", grp:"<<grp<<" ... recovering? "<<
883  rc<<", until: "<<deadline);
884 
885  // Done
886  return rc;
887 }
888 
889 ////////////////////////////////////////////////////////////////////////////////
890 /// Go through the active sessions admin path and make sure sessions are alive.
891 /// If 'verify' is true also ask the session to proof that they are alive
892 /// via asynchronous ping (the result will be done at next check).
893 /// Move those not responding in the terminated sessions admin path.
894 
896 {
897  XPDLOC(SMGR, "ProofServMgr::CheckActiveSessions")
898 
899  TRACE(REQ, "checking active sessions ...");
900 
901  // Open dir
902  DIR *dir = opendir(fActiAdminPath.c_str());
903  if (!dir) {
904  TRACE(XERR, "cannot open dir "<<fActiAdminPath<<" ; error: "<<errno);
905  return -1;
906  }
907 
908  // Scan the active sessions admin path
909  struct dirent *ent = 0;
910  while ((ent = (struct dirent *)readdir(dir))) {
911  if (!strncmp(ent->d_name, ".", 1) || !strncmp(ent->d_name, "..", 2)) continue;
912  // If a socket path, make sure that the associated session still exists
913  // and go to the next
914  if (strstr(ent->d_name, ".sock") && IsSessionSocket(ent->d_name)) continue;
915  // Get the session instance (skip non-digital entries)
916  XrdOucString rest, key, after;
917  int pid = XrdProofdAux::ParsePidPath(ent->d_name, rest, after);
918  // If not a status path, go to the next
919  if (after != "status") continue;
920  // If not a good pid
921  if (!XPD_LONGOK(pid) || pid <= 0) continue;
922  key += pid;
923  //
924  XrdProofdProofServ *xps = 0;
925  { XrdSysMutexHelper mhp(fMutex);
926  xps = fSessions.Find(key.c_str());
927  }
928 
929  bool sessionalive = (VerifySession(ent->d_name) == 0) ? 1 : 0;
930  bool rmsession = 0;
931  if (xps) {
932  if (!xps->IsValid() || !sessionalive) rmsession = 1;
933  } else {
934  // Session not yet registered, possibly starting
935  // Skips checks the admin file verification was OK
936  if (sessionalive) continue;
937  rmsession = 1;
938  }
939 
940  // For backward compatibility we need to check the session version
941  bool oldvers = (xps && xps->ROOT() && xps->ROOT()->SrvProtVers() >= 18) ? 0 : 1;
942 
943  // If somebody is interested in this session, we give them some
944  // more time by skipping the connected clients check this time
945  int nc = -1;
946  if (!rmsession)
947  rmsession = xps->CheckSession(oldvers, IsReconnecting(),
949 
950  // Verify the session: this just sends a request to the session
951  // to touch the session file; all this will be done asynchronously;
952  // the result will be checked next time.
953  // We do not want further propagation at this stage.
954  if (!rmsession && verify && !oldvers) {
955  if (xps->VerifyProofServ(0) != 0) {
956  // This means that the connection is already gone
957  rmsession = 1;
958  }
959  }
960  TRACE(REQ, "session: "<<ent->d_name<<"; nc: "<<nc<<"; rm: "<<rmsession);
961  // Remove the session, if needed
962  if (rmsession)
963  MvSession(ent->d_name);
964  }
965  // Close the directory
966  closedir(dir);
967 
968  // Done
969  return 0;
970 }
971 
972 ////////////////////////////////////////////////////////////////////////////////
973 /// Go through the terminated sessions admin path and make sure sessions they
974 /// are gone.
975 /// Hard-kill those still alive.
976 
978 {
979  XPDLOC(SMGR, "ProofServMgr::CheckTerminatedSessions")
980 
981  TRACE(REQ, "checking terminated sessions ...");
982 
983  // Open dir
984  DIR *dir = opendir(fTermAdminPath.c_str());
985  if (!dir) {
986  TRACE(XERR, "cannot open dir "<<fTermAdminPath<<" ; error: "<<errno);
987  return -1;
988  }
989 
990  // Scan the terminated sessions admin path
991  int now = -1;
992  struct dirent *ent = 0;
993  while ((ent = (struct dirent *)readdir(dir))) {
994  if (!strncmp(ent->d_name, ".", 1) || !strncmp(ent->d_name, "..", 2)) continue;
995  // Get the session instance (skip non-digital entries)
996  XrdOucString rest, a;
997  int pid = XrdProofdAux::ParsePidPath(ent->d_name, rest, a);
998  if (!XPD_LONGOK(pid) || pid <= 0) continue;
999 
1000  // Current time
1001  now = (now > 0) ? now : time(0);
1002 
1003  // Full path
1004  XrdOucString path;
1005  XPDFORM(path, "%s/%s", fTermAdminPath.c_str(), ent->d_name);
1006 
1007  // Check termination time
1008  struct stat st;
1009  int rcst = stat(path.c_str(), &st);
1010  TRACE(DBG, pid<<": rcst: "<<rcst<<", now - mtime: "<<now - st.st_mtime<<" secs")
1011  if ((now - st.st_mtime) > fTerminationTimeOut || rcst != 0) {
1012  // Check if the process is still alive
1013  if (XrdProofdAux::VerifyProcessByID(pid) != 0) {
1014  // Send again an hard-kill signal
1015  XrdProofSessionInfo info(path.c_str());
1016  XrdProofUI ui;
1017  XrdProofdAux::GetUserInfo(info.fUser.c_str(), ui);
1018  XrdProofdAux::KillProcess(pid, 1, ui, fMgr->ChangeOwn());
1019  } else {
1020  // Delete the entry
1021  RmSession(ent->d_name);
1022  }
1023  }
1024  }
1025  // Close the directory
1026  closedir(dir);
1027 
1028  // Done
1029  return 0;
1030 }
1031 
1032 ////////////////////////////////////////////////////////////////////////////////
1033 /// Go through the sessions admin path and clean all sessions belonging to 'usr'.
1034 /// Move those not responding in the terminated sessions admin path.
1035 
1036 int XrdProofdProofServMgr::CleanClientSessions(const char *usr, int srvtype)
1037 {
1038  XPDLOC(SMGR, "ProofServMgr::CleanClientSessions")
1039 
1040  TRACE(REQ, "cleaning "<<usr<<" ...");
1041 
1042  // Check which client
1043  bool all = (!usr || strlen(usr) <= 0 || !strcmp(usr, "all")) ? 1 : 0;
1044 
1045  // Get user info
1046  XrdProofUI ui;
1047  if (!all)
1048  XrdProofdAux::GetUserInfo(usr, ui);
1049  XrdOucString path, rest, key, a;
1050 
1051  // We need lock to avoid session actions request while we are doing this
1052  XrdSysRecMutex *mtx = 0;
1053  if (all) {
1054  // Lock us all
1055  mtx = &fMutex;
1056  } else {
1057  // Lock the client
1059  if (c) mtx = c->Mutex();
1060  }
1061 
1062  std::list<int> tobedel;
1063  { XrdSysMutexHelper mtxh(mtx);
1064 
1065  // Check the terminated session dir first
1066  DIR *dir = opendir(fTermAdminPath.c_str());
1067  if (!dir) {
1068  TRACE(XERR, "cannot open dir "<<fTermAdminPath<<" ; error: "<<errno);
1069  } else {
1070  // Go trough
1071  struct dirent *ent = 0;
1072  while ((ent = (struct dirent *)readdir(dir))) {
1073  // Skip basic entries
1074  if (!strncmp(ent->d_name, ".", 1) || !strncmp(ent->d_name, "..", 2)) continue;
1075  // Get the session instance
1076  int pid = XrdProofdAux::ParsePidPath(ent->d_name, rest, a);
1077  if (!XPD_LONGOK(pid) || pid <= 0) continue;
1078  // Read info from file and check that we are interested in this session
1079  XPDFORM(path, "%s/%s", fTermAdminPath.c_str(), ent->d_name);
1080  XrdProofSessionInfo info(path.c_str());
1081  // Check user
1082  if (!all && info.fUser != usr) continue;
1083  // Check server type
1084  if (srvtype != kXPD_AnyServer && info.fSrvType != srvtype) continue;
1085  // Refresh user info, if needed
1086  if (all)
1087  XrdProofdAux::GetUserInfo(info.fUser.c_str(), ui);
1088  // Check if the process is still alive
1089  if (XrdProofdAux::VerifyProcessByID(pid) != 0) {
1090  // Send a hard-kill signal
1091  XrdProofdAux::KillProcess(pid, 1, ui, fMgr->ChangeOwn());
1092  } else {
1093  // Delete the entry
1094  RmSession(ent->d_name);
1095  }
1096  }
1097  // Close the directory
1098  closedir(dir);
1099  }
1100 
1101  // Check the active session dir now
1102  dir = opendir(fActiAdminPath.c_str());
1103  if (!dir) {
1104  TRACE(XERR, "cannot open dir "<<fActiAdminPath<<" ; error: "<<errno);
1105  return -1;
1106  }
1107 
1108  // Scan the active sessions admin path
1109  struct dirent *ent = 0;
1110  while ((ent = (struct dirent *)readdir(dir))) {
1111  // Skip basic entries
1112  if (!strncmp(ent->d_name, ".", 1) || !strncmp(ent->d_name, "..", 2)) continue;
1113  // Get the session instance
1114  int pid = XrdProofdAux::ParsePidPath(ent->d_name, rest, a);
1115  if (a == "status") continue;
1116  if (!XPD_LONGOK(pid) || pid <= 0) continue;
1117  // Read info from file and check that we are interested in this session
1118  XPDFORM(path, "%s/%s", fActiAdminPath.c_str(), ent->d_name);
1119  XrdProofSessionInfo info(path.c_str());
1120  if (!all && info.fUser != usr) continue;
1121  // Check server type
1122  if (srvtype != kXPD_AnyServer && info.fSrvType != srvtype) continue;
1123  // Refresh user info, if needed
1124  if (all)
1125  XrdProofdAux::GetUserInfo(info.fUser.c_str(), ui);
1126  // Check if the process is still alive
1127  if (XrdProofdAux::VerifyProcessByID(pid) != 0) {
1128  // We will remove this later
1129  tobedel.push_back(pid);
1130  // Send a termination signal
1131  XrdProofdAux::KillProcess(pid, 0, ui, fMgr->ChangeOwn());
1132  }
1133  // Flag as terminated
1134  MvSession(ent->d_name);
1135  }
1136  // Close the directory
1137  closedir(dir);
1138  }
1139 
1140  // Cleanup fSessions
1141  std::list<int>::iterator ii = tobedel.begin();
1142  while (ii != tobedel.end()) {
1143  XPDFORM(key, "%d", *ii);
1145  XrdProofdProofServ *xps = fSessions.Find(key.c_str());
1146  bool active = 0;
1147  std::list<XrdProofdProofServ *>::iterator ixps = fActiveSessions.begin();
1148  while (ixps != fActiveSessions.end()) {
1149  if (*ixps == xps) {
1150  active = 1;
1151  break;
1152  }
1153  ixps++;
1154  }
1155  if (!active) fSessions.Del(key.c_str());
1156  ii++;
1157  }
1158 
1159  // Done
1160  return 0;
1161 }
1162 
1163 ////////////////////////////////////////////////////////////////////////////////
1164 /// Register directives for configuration
1165 
1167 {
1168  // Register special config directives
1169  Register("proofservmgr", new XrdProofdDirective("proofservmgr", this, &DoDirectiveClass));
1170  Register("putenv", new XrdProofdDirective("putenv", this, &DoDirectiveClass));
1171  Register("putrc", new XrdProofdDirective("putrc", this, &DoDirectiveClass));
1172  Register("shutdown", new XrdProofdDirective("shutdown", this, &DoDirectiveClass));
1173  // Register config directives for ints
1174  Register("intwait",
1175  new XrdProofdDirective("intwait", (void *)&fInternalWait, &DoDirectiveInt));
1176  Register("reconnto",
1177  new XrdProofdDirective("reconnto", (void *)&fReconnectTimeOut, &DoDirectiveInt));
1178  // Register config directives for strings
1179  Register("proofplugin",
1180  new XrdProofdDirective("proofplugin", (void *)&fProofPlugin, &DoDirectiveString));
1181  Register("proofservparents",
1182  new XrdProofdDirective("proofservparents", (void *)&fParentExecs, &DoDirectiveString));
1183 }
1184 
1185 ////////////////////////////////////////////////////////////////////////////////
1186 /// Update the priorities of the active sessions.
1187 
1189  char *val, XrdOucStream *cfg, bool rcf)
1190 {
1191  XPDLOC(SMGR, "ProofServMgr::DoDirective")
1192 
1193  if (!d)
1194  // undefined inputs
1195  return -1;
1196 
1197  if (d->fName == "proofservmgr") {
1198  return DoDirectiveProofServMgr(val, cfg, rcf);
1199  } else if (d->fName == "putenv") {
1200  return DoDirectivePutEnv(val, cfg, rcf);
1201  } else if (d->fName == "putrc") {
1202  return DoDirectivePutRc(val, cfg, rcf);
1203  } else if (d->fName == "shutdown") {
1204  return DoDirectiveShutdown(val, cfg, rcf);
1205  }
1206  TRACE(XERR,"unknown directive: "<<d->fName);
1207  return -1;
1208 }
1209 
1210 ////////////////////////////////////////////////////////////////////////////////
1211 /// Process 'proofswrvmgr' directive
1212 /// eg: xpd.proofswrvmgr checkfq:120 termto:100 verifyto:5 recoverto:20
1213 
1214 int XrdProofdProofServMgr::DoDirectiveProofServMgr(char *val, XrdOucStream *cfg, bool rcf)
1215 {
1216  XPDLOC(SMGR, "ProofServMgr::DoDirectiveProofServMgr")
1217 
1218  if (!val || !cfg)
1219  // undefined inputs
1220  return -1;
1221 
1222  if (rcf)
1223  // Do not reconfigure this (need to check what happens with the cron thread ...
1224  return 0;
1225 
1226  int checkfq = -1;
1227  int termto = -1;
1228  int verifyto = -1;
1229  int recoverto = -1;
1230  int checklost = 0;
1231  int usefork = 0;
1232 
1233  while (val) {
1234  XrdOucString tok(val);
1235  if (tok.beginswith("checkfq:")) {
1236  tok.replace("checkfq:", "");
1237  checkfq = strtol(tok.c_str(), 0, 10);
1238  } else if (tok.beginswith("termto:")) {
1239  tok.replace("termto:", "");
1240  termto = strtol(tok.c_str(), 0, 10);
1241  } else if (tok.beginswith("verifyto:")) {
1242  tok.replace("verifyto:", "");
1243  verifyto = strtol(tok.c_str(), 0, 10);
1244  } else if (tok.beginswith("recoverto:")) {
1245  tok.replace("recoverto:", "");
1246  recoverto = strtol(tok.c_str(), 0, 10);
1247  } else if (tok.beginswith("checklost:")) {
1248  tok.replace("checklost:", "");
1249  checklost = strtol(tok.c_str(), 0, 10);
1250  } else if (tok.beginswith("usefork:")) {
1251  tok.replace("usefork:", "");
1252  usefork = strtol(tok.c_str(), 0, 10);
1253  }
1254  // Get next
1255  val = cfg->GetWord();
1256  }
1257 
1258  // Check deprecated 'if' directive
1259  if (fMgr->Host() && cfg)
1260  if (XrdProofdAux::CheckIf(cfg, fMgr->Host()) == 0)
1261  return 0;
1262 
1263  // Set the values
1264  fCheckFrequency = (XPD_LONGOK(checkfq) && checkfq > 0) ? checkfq : fCheckFrequency;
1265  fTerminationTimeOut = (XPD_LONGOK(termto) && termto > 0) ? termto : fTerminationTimeOut;
1266  fVerifyTimeOut = (XPD_LONGOK(verifyto) && (verifyto > fCheckFrequency + 1))
1267  ? verifyto : fVerifyTimeOut;
1268  fRecoverTimeOut = (XPD_LONGOK(recoverto) && recoverto > 0) ? recoverto : fRecoverTimeOut;
1269  if (XPD_LONGOK(checklost)) fCheckLost = (checklost != 0) ? 1 : 0;
1270  if (XPD_LONGOK(usefork)) fUseFork = (usefork != 0) ? 1 : 0;
1271 
1272  XrdOucString msg;
1273  XPDFORM(msg, "checkfq: %d s, termto: %d s, verifyto: %d s, recoverto: %d s, checklost: %d, usefork: %d",
1275  TRACE(ALL, msg);
1276 
1277  return 0;
1278 }
1279 
1280 ////////////////////////////////////////////////////////////////////////////////
1281 /// Process 'putenv' directives
1282 
1283 int XrdProofdProofServMgr::DoDirectivePutEnv(char *val, XrdOucStream *cfg, bool)
1284 {
1285  if (!val)
1286  // undefined inputs
1287  return -1;
1288 
1289  // Parse env variables to be passed to 'proofserv':
1290  XrdOucString users, groups, rcval, rcnam;
1291  int smi = -1, smx = -1, vmi = -1, vmx = -1;
1292  bool hex = 0;
1293  ExtractEnv(val, cfg, users, groups, rcval, rcnam, smi, smx, vmi, vmx, hex);
1294 
1295  // Adjust name of the variable
1296  int iequ = rcnam.find('=');
1297  if (iequ == STR_NPOS) return -1;
1298  rcnam.erase(iequ);
1299 
1300  // Fill entries
1301  FillEnvList(&fProofServEnvs, rcnam.c_str(), rcval.c_str(),
1302  users.c_str(), groups.c_str(), smi, smx, vmi, vmx, hex);
1303 
1304  return 0;
1305 }
1306 
1307 ////////////////////////////////////////////////////////////////////////////////
1308 /// Process 'putrc' directives.
1309 /// Syntax:
1310 /// xpd.putrc [u:<usr1>,<usr2>,...] [g:<grp1>,<grp2>,...]
1311 /// [s:[svnmin][-][svnmax]] [v:[vermin][-][vermax]] RcVarName RcVarValue
1312 /// NB: <usr1>,... and <grp1>,... may contain the wild card '*'
1313 
1314 int XrdProofdProofServMgr::DoDirectivePutRc(char *val, XrdOucStream *cfg, bool)
1315 {
1316  if (!val || !cfg)
1317  // undefined inputs
1318  return -1;
1319 
1320  // Parse rootrc variables to be passed to 'proofserv':
1321  XrdOucString users, groups, rcval, rcnam;
1322  int smi = -1, smx = -1, vmi = -1, vmx = -1;
1323  bool hex = 0;
1324  ExtractEnv(val, cfg, users, groups, rcval, rcnam, smi, smx, vmi, vmx, hex);
1325 
1326  // Fill entries
1327  FillEnvList(&fProofServRCs, rcnam.c_str(), rcval.c_str(),
1328  users.c_str(), groups.c_str(), smi, smx, vmi, vmx, hex);
1329 
1330  return 0;
1331 }
1332 
1333 ////////////////////////////////////////////////////////////////////////////////
1334 /// Extract env information from the stream 'cfg'
1335 
1336 void XrdProofdProofServMgr::ExtractEnv(char *val, XrdOucStream *cfg,
1337  XrdOucString &users, XrdOucString &groups,
1338  XrdOucString &rcval, XrdOucString &rcnam,
1339  int &smi, int &smx, int &vmi, int &vmx, bool &hex)
1340 {
1341  XrdOucString ssvn, sver;
1342  int idash = -1;
1343  while (val && val[0]) {
1344  if (!strncmp(val, "u:", 2)) {
1345  users = val;
1346  users.erase(0,2);
1347  } else if (!strncmp(val, "g:", 2)) {
1348  groups = val;
1349  groups.erase(0,2);
1350  } else if (!strncmp(val, "s:", 2)) {
1351  ssvn = val;
1352  ssvn.erase(0,2);
1353  idash = ssvn.find('-');
1354  if (idash != STR_NPOS) {
1355  if (ssvn.isdigit(0, idash-1)) smi = ssvn.atoi(0, idash-1);
1356  if (ssvn.isdigit(idash+1)) smx = ssvn.atoi(idash+1);
1357  } else {
1358  if (ssvn.isdigit()) smi = ssvn.atoi();
1359  }
1360  } else if (!strncmp(val, "v:", 2)) {
1361  sver = val;
1362  sver.erase(0,2);
1363  hex = 0;
1364  if (sver.beginswith('x')) {
1365  hex = 1;
1366  sver.erase(0,1);
1367  }
1368  idash = sver.find('-');
1369  if (idash != STR_NPOS) {
1370  if (sver.isdigit(0, idash-1)) vmi = sver.atoi(0, idash-1);
1371  if (sver.isdigit(idash+1)) vmx = sver.atoi(idash+1);
1372  } else {
1373  if (sver.isdigit()) vmi = sver.atoi();
1374  }
1375  } else {
1376  if (rcval.length() > 0) {
1377  rcval += ' ';
1378  } else {
1379  rcnam = val;
1380  }
1381  rcval += val;
1382  }
1383  val = cfg->GetWord();
1384  }
1385  // Done
1386  return;
1387 }
1388 
1389 ////////////////////////////////////////////////////////////////////////////////
1390 /// Fill env entry(ies) in the relevant list
1391 
1392 void XrdProofdProofServMgr::FillEnvList(std::list<XpdEnv> *el, const char *nam, const char *val,
1393  const char *usrs, const char *grps,
1394  int smi, int smx, int vmi, int vmx, bool hex)
1395 {
1396  XPDLOC(SMGR, "ProofServMgr::FillEnvList")
1397 
1398  if (!el) {
1399  TRACE(ALL, "env list undefined!");
1400  return;
1401  }
1402 
1403  XrdOucString users(usrs), groups(grps);
1404  // Transform version numbers in the human unreadable format used internally (version code)
1405  if (vmi > 0) vmi = XpdEnv::ToVersCode(vmi, hex);
1406  if (vmx > 0) vmx = XpdEnv::ToVersCode(vmx, hex);
1407  // Create the entry
1408  XpdEnv xpe(nam, val, users.c_str(), groups.c_str(), smi, smx, vmi, vmx);
1409  if (users.length() > 0) {
1410  XrdOucString usr;
1411  int from = 0;
1412  while ((from = users.tokenize(usr, from, ',')) != -1) {
1413  if (usr.length() > 0) {
1414  if (groups.length() > 0) {
1415  XrdOucString grp;
1416  int fromg = 0;
1417  while ((fromg = groups.tokenize(grp, from, ',')) != -1) {
1418  if (grp.length() > 0) {
1419  xpe.Reset(nam, val, usr.c_str(), grp.c_str(), smi, smx, vmi, vmx);
1420  el->push_back(xpe);
1421  }
1422  }
1423  } else {
1424  xpe.Reset(nam, val, usr.c_str(), 0, smi, smx, vmi, vmx);
1425  el->push_back(xpe);
1426  }
1427  }
1428  }
1429  } else {
1430  if (groups.length() > 0) {
1431  XrdOucString grp;
1432  int fromg = 0;
1433  while ((fromg = groups.tokenize(grp, fromg, ',')) != -1) {
1434  if (grp.length() > 0) {
1435  xpe.Reset(nam, val, 0, grp.c_str(), smi, smx, vmi, vmx);
1436  el->push_back(xpe);
1437  }
1438  }
1439  } else {
1440  el->push_back(xpe);
1441  }
1442  }
1443  // Done
1444  return;
1445 }
1446 
1447 ////////////////////////////////////////////////////////////////////////////////
1448 /// Process 'shutdown' directive
1449 
1450 int XrdProofdProofServMgr::DoDirectiveShutdown(char *val, XrdOucStream *cfg, bool)
1451 {
1452  if (!val || !cfg)
1453  // undefined inputs
1454  return -1;
1455 
1456  int opt = -1;
1457  int delay = -1;
1458 
1459  // Shutdown option
1460  int dp = strtol(val,0,10);
1461  if (dp >= 0 && dp <= 2)
1462  opt = dp;
1463  // Shutdown delay
1464  if ((val = cfg->GetWord())) {
1465  int l = strlen(val);
1466  int f = 1;
1467  XrdOucString tval = val;
1468  // Parse
1469  if (val[l-1] == 's') {
1470  val[l-1] = 0;
1471  } else if (val[l-1] == 'm') {
1472  f = 60;
1473  val[l-1] = 0;
1474  } else if (val[l-1] == 'h') {
1475  f = 3600;
1476  val[l-1] = 0;
1477  } else if (val[l-1] < 48 || val[l-1] > 57) {
1478  f = -1;
1479  }
1480  if (f > 0) {
1481  int de = strtol(val,0,10);
1482  if (de > 0)
1483  delay = de * f;
1484  }
1485  }
1486 
1487  // Check deprecated 'if' directive
1488  if (fMgr->Host() && cfg)
1489  if (XrdProofdAux::CheckIf(cfg, fMgr->Host()) == 0)
1490  return 0;
1491 
1492  // Set the values
1493  fShutdownOpt = (opt > -1) ? opt : fShutdownOpt;
1494  fShutdownDelay = (delay > -1) ? delay : fShutdownDelay;
1495 
1496  return 0;
1497 }
1498 
1499 ////////////////////////////////////////////////////////////////////////////////
1500 /// Process manager request
1501 
1503 {
1504  XPDLOC(SMGR, "ProofServMgr::Process")
1505 
1506  int rc = 1;
1507  XPD_SETRESP(p, "Process");
1508 
1509  TRACEP(p, REQ, "enter: req id: " << p->Request()->header.requestid << " (" <<
1510  XrdProofdAux::ProofRequestTypes(p->Request()->header.requestid) << ")");
1511 
1512  XrdSysMutexHelper mtxh(p->Client()->Mutex());
1513 
1514  // Once logged-in, the user can request the real actions
1515  XrdOucString emsg("Invalid request code: ");
1516 
1517  int twait = 20;
1518 
1519  if (Pipe()->Post(XrdProofdProofServMgr::kProcessReq, 0) != 0) {
1520  response->Send(kXR_ServerError,
1521  "ProofServMgr::Process: error posting internal pipe for authorization to proceed");
1522  return 0;
1523  }
1524  if (fProcessSem.Wait(twait) != 0) {
1525  response->Send(kXR_ServerError,
1526  "ProofServMgr::Process: timed-out waiting for authorization to proceed - retry later");
1527  return 0;
1528  }
1529 
1530  // This is needed to block the session checks
1532 
1533  switch(p->Request()->header.requestid) {
1534  case kXP_create:
1535  return Create(p);
1536  case kXP_destroy:
1537  return Destroy(p);
1538  case kXP_attach:
1539  return Attach(p);
1540  case kXP_detach:
1541  return Detach(p);
1542  default:
1543  emsg += p->Request()->header.requestid;
1544  break;
1545  }
1546 
1547  // Whatever we have, it's not valid
1548  response->Send(kXR_InvalidRequest, emsg.c_str());
1549  return 0;
1550 }
1551 
1552 ////////////////////////////////////////////////////////////////////////////////
1553 /// Handle a request to attach to an existing session
1554 
1556 {
1557  XPDLOC(SMGR, "ProofServMgr::Attach")
1558 
1559  int psid = -1, rc = 0;
1560  XPD_SETRESP(p, "Attach");
1561 
1562  // Unmarshall the data
1563  psid = ntohl(p->Request()->proof.sid);
1564  TRACEP(p, REQ, "psid: "<<psid<<", CID = "<<p->CID());
1565 
1566  // The client instance must be defined
1567  XrdProofdClient *c = p->Client();
1568  if (!c) {
1569  TRACEP(p, XERR, "client instance undefined");
1570  response->Send(kXR_ServerError,"client instance undefined");
1571  return 0;
1572  }
1573 
1574  // Find server session; sessions maybe recovering, so we need to take
1575  // that into account
1576  XrdProofdProofServ *xps = 0;
1577  int now = time(0);
1578  int deadline = -1, defdeadline = now + fRecoverTimeOut;
1579  while ((deadline < 0) || (now < deadline)) {
1580  if (!(xps = c->GetServer(psid)) || !xps->IsValid()) {
1581  // If the client is recovering start regular checks
1582  if (!IsClientRecovering(c->User(), c->Group(), deadline)) {
1583  // Failure
1584  TRACEP(p, XERR, "session ID not found: "<<psid);
1585  response->Send(kXR_InvalidRequest,"session ID not found");
1586  return 0;
1587  } else {
1588  // Make dure we do not enter an infinite loop
1589  deadline = (deadline > 0) ? deadline : defdeadline;
1590  // Wait until deadline in 1 sec steps
1591  sleep(1);
1592  now++;
1593  }
1594  } else {
1595  // Found
1596  break;
1597  }
1598  }
1599  // If we deadline we should fail now
1600  if (!xps || !xps->IsValid()) {
1601  TRACEP(p, XERR, "session ID not found: "<<psid);
1602  response->Send(kXR_InvalidRequest,"session ID not found");
1603  return 0;
1604  }
1605  TRACEP(p, DBG, "xps: "<<xps<<", status: "<< xps->Status());
1606 
1607  // Stream ID
1608  unsigned short sid;
1609  memcpy((void *)&sid, (const void *)&(p->Request()->header.streamid[0]), 2);
1610 
1611  // We associate this instance to the corresponding slot in the
1612  // session vector of attached clients
1613  XrdClientID *csid = xps->GetClientID(p->CID());
1614  csid->SetP(p);
1615  csid->SetSid(sid);
1616 
1617  // Take parentship, if orphalin
1618  if (!(xps->Parent()))
1619  xps->SetParent(csid);
1620 
1621  // Notify to user
1622  int protvers = (xps && xps->ROOT()) ? xps->ROOT()->SrvProtVers() : -1;
1623  if (p->ConnType() == kXPD_ClientMaster) {
1624  // Send also back the data pool url
1625  XrdOucString dpu = fMgr->PoolURL();
1626  if (!dpu.endswith('/'))
1627  dpu += '/';
1628  dpu += fMgr->NameSpace();
1629  response->SendI(psid, protvers, (kXR_int16)XPROOFD_VERSBIN,
1630  (void *) dpu.c_str(), dpu.length());
1631  } else
1632  response->SendI(psid, protvers, (kXR_int16)XPROOFD_VERSBIN);
1633 
1634  // Send saved start processing message, if not idle
1635  if (xps->Status() == kXPD_running && xps->StartMsg()) {
1636  TRACEP(p, XERR, "sending start process message ("<<xps->StartMsg()->fSize<<" bytes)");
1637  response->Send(kXR_attn, kXPD_msg,
1638  xps->StartMsg()->fBuff, xps->StartMsg()->fSize);
1639  }
1640 
1641  // Over
1642  return 0;
1643 }
1644 
1645 ////////////////////////////////////////////////////////////////////////////////
1646 /// Allocate and prepare the XrdProofdProofServ object describing this session
1647 
1650  unsigned short &sid)
1651 {
1652  XPDLOC(SMGR, "ProofServMgr::PrepareProofServ")
1653 
1654  // Allocate next free server ID and fill in the basic stuff
1655  XrdProofdProofServ *xps = p->Client()->GetFreeServObj();
1656  xps->SetClient(p->Client()->User());
1657  xps->SetSrvType(p->ConnType());
1658 
1659  // Prepare the stream identifier
1660  memcpy((void *)&sid, (const void *)&(p->Request()->header.streamid[0]), 2);
1661  // We associate this instance to the corresponding slot in the
1662  // session vector of attached clients
1663  XrdClientID *csid = xps->GetClientID(p->CID());
1664  csid->SetSid(sid);
1665  csid->SetP(p);
1666  // Take parentship, if orphalin
1667  xps->SetParent(csid);
1668 
1669  // The ROOT version to be used
1670  xps->SetROOT(p->Client()->ROOT());
1671  XrdOucString msg;
1672  XPDFORM(msg, "using ROOT version: %s", xps->ROOT()->Export());
1673  TRACEP(p, REQ, msg);
1674  if (p->ConnType() == kXPD_ClientMaster) {
1675  // Notify the client if using a version different from the default one
1676  if (fMgr && p->Client()->ROOT() != fMgr->ROOTMgr()->DefaultVersion()) {
1677  XPDFORM(msg, "++++ Using NON-default ROOT version: %s ++++\n", xps->ROOT()->Export());
1678  r->Send(kXR_attn, kXPD_srvmsg, (char *) msg.c_str(), msg.length());
1679  }
1680  }
1681 
1682  // Done
1683  return xps;
1684 }
1685 
1686 ////////////////////////////////////////////////////////////////////////////////
1687 /// Extract relevant quantities from the buffer received during a create request
1688 
1690  XrdProofdProofServ *xps,
1691  XrdOucString &tag, XrdOucString &ord,
1692  XrdOucString &cffile,
1693  XrdOucString &uenvs, int &intwait)
1694 {
1695  XPDLOC(SMGR, "ProofServMgr::ParseCreateBuffer")
1696 
1697  // Parse buffer
1698  char *buf = p->Argp()->buff;
1699  int len = p->Request()->proof.dlen;
1700 
1701  // Extract session tag
1702  tag.assign(buf,0,len-1);
1703 
1704  TRACEP(p, DBG, "received buf: "<<tag);
1705 
1706  tag.erase(tag.find('|'));
1707  xps->SetTag(tag.c_str());
1708  TRACEP(p, DBG, "tag: "<<tag);
1709 
1710  // Extract ordinal number
1711  ord = "0";
1712  if ((p->ConnType() == kXPD_MasterWorker) || (p->ConnType() == kXPD_MasterMaster)) {
1713  ord.assign(buf,0,len-1);
1714  int iord = ord.find("|ord:");
1715  if (iord != STR_NPOS) {
1716  ord.erase(0,iord+5);
1717  ord.erase(ord.find("|"));
1718  } else
1719  ord = "0";
1720  }
1721  xps->SetOrdinal(ord.c_str());
1722 
1723  // Extract config file, if any (for backward compatibility)
1724  cffile.assign(buf,0,len-1);
1725  int icf = cffile.find("|cf:");
1726  if (icf != STR_NPOS) {
1727  cffile.erase(0,icf+4);
1728  cffile.erase(cffile.find("|"));
1729  } else
1730  cffile = "";
1731 
1732  // Extract # number of workers, if plite master
1733  XrdOucString plitenwk;
1734  plitenwk.assign(buf,0,len-1);
1735  int inwk = plitenwk.find("|plite:");
1736  if (inwk != STR_NPOS) {
1737  plitenwk.erase(0,inwk+7);
1738  plitenwk.erase(plitenwk.find("|"));
1739  int nwk = plitenwk.atoi();
1740  if (nwk > -1) {
1741  xps->SetPLiteNWrks(nwk);
1742  TRACEP(p, DBG, "P-Lite master with "<<nwk<<" workers (0 means # or cores)");
1743  }
1744  }
1745 
1746  // Extract user envs, if any
1747  uenvs.assign(buf,0,len-1);
1748  int ienv = uenvs.find("|envs:");
1749  if (ienv != STR_NPOS) {
1750  uenvs.erase(0,ienv+6);
1751  uenvs.erase(uenvs.find("|"));
1752  xps->SetUserEnvs(uenvs.c_str());
1753  } else
1754  uenvs = "";
1755 
1756  // Check if the user wants to wait more for the session startup
1757  intwait = fInternalWait;
1758  if (uenvs.length() > 0) {
1759  TRACEP(p, DBG, "user envs: "<<uenvs);
1760  int iiw = STR_NPOS;
1761  if ((iiw = uenvs.find("PROOF_INTWAIT=")) != STR_NPOS) {
1762  XrdOucString s(uenvs, iiw + strlen("PROOF_INTWAIT="));
1763  s.erase(s.find(','));
1764  if (s.isdigit()) {
1765  intwait = s.atoi();
1766  TRACEP(p, ALL, "startup internal wait set by user to "<<intwait);
1767  }
1768  }
1769  }
1770 }
1771 
1772 ////////////////////////////////////////////////////////////////////////////////
1773 /// Handle a request to create a new session
1774 
1776 {
1777  XPDLOC(SMGR, "ProofServMgr::Create")
1778 
1779  int psid = -1, rc = 0;
1780  XPD_SETRESP(p, "Create");
1781 
1782  TRACEP(p, DBG, "enter");
1783  XrdOucString msg;
1784 
1785  XpdSrvMgrCreateGuard mcGuard;
1786 
1787  // Check if we are allowed to start a new session
1788  int mxsess = fMgr->ProofSched() ? fMgr->ProofSched()->MaxSessions() : -1;
1789  if (p->ConnType() == kXPD_ClientMaster && mxsess > 0) {
1791  int cursess = CurrentSessions();
1792  TRACEP(p,ALL," cursess: "<<cursess);
1793  if (mxsess <= cursess) {
1794  XPDFORM(msg, " ++++ Max number of sessions reached (%d) - please retry later ++++ \n", cursess);
1795  response->Send(kXR_attn, kXPD_srvmsg, (char *) msg.c_str(), msg.length());
1796  response->Send(kXP_TooManySess, "cannot start a new session");
1797  return 0;
1798  }
1799  // If we fail this guarantees that the counters are decreased, if needed
1800  mcGuard.Set(&fCurrentSessions);
1801  }
1802 
1803  // Update counter to control checks during creation
1805  if (TRACING(DBG)) {
1806  int nc = CheckCounter(kCreateCnt);
1807  TRACEP(p, DBG, nc << " threads are creating a new session");
1808  }
1809 
1810  // Allocate and prepare the XrdProofdProofServ object describing this session
1811  unsigned short sid;
1812  XrdProofdProofServ *xps = PrepareProofServ(p, response, sid);
1813  psid = xps->ID();
1814 
1815  // Unmarshall log level
1816  int loglevel = ntohl(p->Request()->proof.int1);
1817 
1818  // Parse buffer
1819  int intwait;
1820  XrdOucString tag, ord, cffile, uenvs;
1821  ParseCreateBuffer(p, xps, tag, ord, cffile, uenvs, intwait);
1822 
1823  // Notify
1824  TRACEP(p, DBG, "{ord,cfg,psid,cid,log}: {"<<ord<<","<<cffile<<","<<psid
1825  <<","<<p->CID()<<","<<loglevel<<"}");
1826 
1827  // Here we fork: for some weird problem on SMP machines there is a
1828  // non-zero probability for a deadlock situation in system mutexes.
1829  // The semaphore seems to have solved the problem.
1830  if (fForkSem.Wait(10) != 0) {
1831  xps->Reset();
1832  // Timeout acquire fork semaphore
1833  response->Send(kXP_ServerError, "timed-out acquiring fork semaphore");
1834  return 0;
1835  }
1836 
1837  // Pipe for child-to-parent communications during setup
1838  XrdProofdPipe fpc, fcp;
1839  if (!(fpc.IsValid()) || !(fcp.IsValid())) {
1840  xps->Reset();
1841  // Failure creating pipe
1842  response->Send(kXP_ServerError,
1843  "unable to create pipes for communication during setup");
1844  return 0;
1845  }
1846 
1847  // Start setting up the unique tag and relevant dirs for this session
1848  ProofServEnv_t in = {xps, loglevel, cffile.c_str(), "", "", tag.c_str(), "", "", 1};
1849  GetTagDirs(0, p, xps, in.fSessionTag, in.fTopSessionTag, in.fSessionDir, in.fWrkDir);
1850 
1851  // Fork an agent process to handle this session
1852  int pid = -1;
1853  TRACEP(p, FORK,"Forking external proofsrv");
1854  if (!(pid = fMgr->Sched()->Fork("proofsrv"))) {
1855 
1856  // Finalize unique tag and relevant dirs for this session
1857  GetTagDirs((int)getpid(),
1858  p, xps, in.fSessionTag, in.fTopSessionTag, in.fSessionDir, in.fWrkDir);
1859 
1860  // Create log file path
1861  FormFileNameInSessionDir(p, xps, in.fSessionDir.c_str(), "log", in.fLogFile);
1862 
1863  // Log to the session log file from now on
1864  if (fLogger) fLogger->Bind(in.fLogFile.c_str());
1865  TRACE(FORK, "log file: "<<in.fLogFile);
1866 
1867  XrdOucString pmsg = "*** spawned child process ";
1868  pmsg += (int) getpid();
1869  pmsg += " ***";
1870  TRACE(ALL, pmsg);
1871 
1872  // These files belongs to the client
1873  if (chown(in.fLogFile.c_str(), p->Client()->UI().fUid, p->Client()->UI().fGid) != 0)
1874  TRACE(XERR, "chown on '"<<in.fLogFile.c_str()<<"'; errno: "<<errno);
1875 
1876  XpdMsg xmsg;
1877  XrdOucString path, sockpath, emsg;
1878 
1879  // Receive the admin path from the parent
1880  if (fpc.Poll() < 0) {
1881  TRACE(XERR, "error while polling to receive the admin path from parent - EXIT" );
1882  exit(1);
1883  }
1884  if (fpc.Recv(xmsg) != 0) {
1885  TRACE(XERR, "error reading message while waiting for the admin path from parent - EXIT" );
1886  exit(1);
1887  }
1888  if (xmsg.Type() < 0) {
1889  TRACE(XERR, "the parent failed to setup the admin path - EXIT" );
1890  exit(1);
1891  }
1892  // Set the path w/o asserting the related files
1893  path = xmsg.Buf();
1894  xps->SetAdminPath(path.c_str(), 0, fMgr->ChangeOwn());
1895  TRACE(FORK, "admin path: "<<path);
1896 
1897  xmsg.Reset();
1898  // Receive the sock path from the parent
1899  if (fpc.Poll() < 0) {
1900  TRACE(XERR, "error while polling to receive the sock path from parent - EXIT" );
1901  exit(1);
1902  }
1903  if (fpc.Recv(xmsg) != 0) {
1904  TRACE(XERR, "error reading message while waiting for the sock path from parent - EXIT" );
1905  exit(1);
1906  }
1907  if (xmsg.Type() < 0) {
1908  TRACE(XERR, "the parent failed to setup the sock path - EXIT" );
1909  exit(1);
1910  }
1911  // Set the UNIX sock path
1912  sockpath = xmsg.Buf();
1913  xps->SetUNIXSockPath(sockpath.c_str());
1914  TRACE(FORK, "UNIX sock path: "<<sockpath);
1915 
1916  // We set to the user ownerships and create relevant dirs
1917  bool asserdatadir = 1;
1918  int srvtype = xps->SrvType();
1919  TRACE(ALL,"srvtype = "<< srvtype);
1920  if (xps->SrvType() != kXPD_Worker && !strchr(fMgr->DataDirOpts(), 'M')) {
1921  asserdatadir = 0;
1922  } else if (xps->SrvType() == kXPD_Worker && !strchr(fMgr->DataDirOpts(), 'W')) {
1923  asserdatadir = 0;
1924  }
1925  const char *pord = asserdatadir ? ord.c_str() : 0;
1926  const char *ptag = asserdatadir ? in.fSessionTag.c_str() : 0;
1927  if (SetUserOwnerships(p, pord, ptag) != 0) {
1928  emsg = "SetUserOwnerships did not return OK - EXIT";
1929  TRACE(XERR, emsg);
1930  if (fcp.Post(0, emsg.c_str()) != 0)
1931  TRACE(XERR, "cannot write to internal pipe; errno: "<<errno);
1932  exit(1);
1933  }
1934 
1935  // We set to the user environment
1936  if (SetUserEnvironment(p) != 0) {
1937  emsg = "SetUserEnvironment did not return OK - EXIT";
1938  TRACE(XERR, emsg);
1939  if (fcp.Post(0, emsg.c_str()) != 0)
1940  TRACE(XERR, "cannot write to internal pipe; errno: "<<errno);
1941  exit(1);
1942  }
1943 
1944  char *argvv[7] = {0};
1945 
1946  // We set to the user environment
1947  if (!fMgr) {
1948  emsg = "XrdProofdManager instance undefined!";
1949  TRACE(XERR, emsg);
1950  if (fcp.Post(0, emsg.c_str()) != 0)
1951  TRACE(XERR, "cannot write to internal pipe; errno: "<<errno);
1952  exit(1);
1953  }
1954  char *sxpd = 0;
1955  if (fMgr->AdminPath()) {
1956  // We add our admin path to be able to identify processes coming from us
1957  size_t len = strlen(fMgr->AdminPath()) + strlen("xpdpath:") + 1;
1958  sxpd = new char[len];
1959  snprintf(sxpd, len, "xpdpath:%s", fMgr->AdminPath());
1960  } else {
1961  // We add our PID to be able to identify processes coming from us
1962  sxpd = new char[10];
1963  snprintf(sxpd, 10, "%d", getppid());
1964  }
1965 
1966  // Log level
1967  char slog[10] = {0};
1968  snprintf(slog, 10, "%d", loglevel);
1969 
1970  // Server type
1971  char ssrv[10] = {0};
1972  snprintf(ssrv, 10, "%d", xps->SrvType());
1973 
1974  // start server
1975  argvv[0] = (char *) xps->ROOT()->PrgmSrv();
1976  argvv[1] = (char *)((p->ConnType() == kXPD_MasterWorker) ? "proofslave"
1977  : "proofserv");
1978  argvv[2] = (char *)"xpd";
1979  argvv[3] = (char *)sxpd;
1980  argvv[4] = (char *)slog;
1981  argvv[5] = (char *)ssrv;
1982  argvv[6] = 0;
1983 
1984  // Set environment for proofserv
1985  if (SetProofServEnv(p, (void *)&in) != 0) {
1986  emsg = "SetProofServEnv did not return OK - EXIT";
1987  TRACE(XERR, emsg);
1988  if (fcp.Post(0, emsg.c_str()) != 0)
1989  TRACE(XERR, "cannot write to internal pipe; errno: "<<errno);
1990  exit(1);
1991  }
1992  TRACE(FORK, (int)getpid() << ": proofserv env set up");
1993 
1994  // Setup OK: now we go
1995  // Communicate the logfile path
1996  if (fcp.Post(1, xps->Fileout()) != 0) {
1997  TRACE(XERR, "cannot write log file path to internal pipe; errno: "<<errno);
1998  exit(1);
1999  }
2000  TRACE(FORK, (int)getpid()<< ": log file path communicated");
2001 
2002  // Unblock SIGUSR1 and SIGUSR2
2003  sigset_t myset;
2004  sigemptyset(&myset);
2005  sigaddset(&myset, SIGUSR1);
2006  sigaddset(&myset, SIGUSR2);
2007  pthread_sigmask(SIG_UNBLOCK, &myset, 0);
2008 
2009  // Close pipes
2010  fpc.Close();
2011  fcp.Close();
2012 
2013  TRACE(FORK, (int)getpid()<<": user: "<<p->Client()->User()<<
2014  ", uid: "<<getuid()<<", euid:"<<geteuid()<<
2015  ", psrv: "<<xps->ROOT()->PrgmSrv()<<", argvv[1]: "<<argvv[1]);
2016  // Run the program
2017  execv(xps->ROOT()->PrgmSrv(), argvv);
2018 
2019  // We should not be here!!!
2020  TRACE(XERR, "returned from execv: bad, bad sign !!! errno:" << (int)errno);
2021  exit(1);
2022  }
2023 
2024  // Wakeup colleagues
2025  fForkSem.Post();
2026 
2027  // parent process
2028  if (pid < 0) {
2029  xps->Reset();
2030  // Failure in forking
2031  response->Send(kXP_ServerError, "could not fork agent");
2032  return 0;
2033  }
2034 
2035  TRACEP(p, FORK,"Parent process: child is "<<pid);
2036  XrdOucString emsg;
2037 
2038  // Finalize unique tag and relevant dirs for this session
2039  GetTagDirs((int)pid, p, xps, in.fSessionTag, in.fTopSessionTag, in.fSessionDir, in.fWrkDir);
2040 
2041  // Create log file path
2042  FormFileNameInSessionDir(p, xps, in.fSessionDir.c_str(), "log", in.fLogFile);
2043 
2044  TRACEP(p, FORK, "log file: "<<in.fLogFile);
2045 
2046  // Log prefix
2047  XrdOucString npfx;
2048  XPDFORM(npfx, "%s-%s:", (p->ConnType() == kXPD_MasterWorker) ? "wrk" : "mst", xps->Ordinal());
2049 
2050  // Cleanup current socket, if any
2051  if (xps->UNIXSock()) {
2052  TRACEP(p, FORK,"current UNIX sock: "<<xps->UNIXSock() <<", path: "<<xps->UNIXSockPath());
2053  xps->DeleteUNIXSock();
2054  }
2055 
2056  // Admin and UNIX Socket Path (set path and create the socket); we need to
2057  // set and create them in here, otherwise the cleaning may remove the socket
2058  XrdOucString path, sockpath;
2059  XPDFORM(path, "%s/%s.%s.%d", fActiAdminPath.c_str(),
2060  p->Client()->User(), p->Client()->Group(), pid);
2061  // Sock path under dedicated directory to avoid problems related to its length
2062  XPDFORM(sockpath, "%s/xpd.%d.%d", fMgr->SockPathDir(), fMgr->Port(), pid);
2063  struct sockaddr_un unserver;
2064  if (sockpath.length() > (int)(sizeof(unserver.sun_path) - 1)) {
2065  emsg = "socket path very long (";
2066  emsg += sockpath.length();
2067  emsg += "): this may lead to stack corruption!";
2068  emsg += " Use xpd.sockpathdir to change it";
2069  TRACEP(p, XERR, emsg.c_str());
2070  }
2071  int pathrc = 0;
2072  if (!pathrc && !(pathrc = xps->SetAdminPath(path.c_str(), 1, fMgr->ChangeOwn()))) {
2073  // Communicate the path to child
2074  if ((pathrc = fpc.Post(0, path.c_str())) != 0) {
2075  emsg = "failed to communicating path to child";
2076  XrdProofdAux::LogEmsgToFile(in.fLogFile.c_str(), emsg.c_str(), npfx.c_str());
2077  TRACEP(p, XERR, emsg.c_str());
2078  }
2079  } else {
2080  emsg = "failed to setup child admin path";
2081  // Communicate failure to child
2082  if ((pathrc = fpc.Post(-1, path.c_str())) != 0) {
2083  emsg += ": failed communicating failure to child";
2084  XrdProofdAux::LogEmsgToFile(in.fLogFile.c_str(), emsg.c_str(), npfx.c_str());
2085  TRACEP(p, XERR, emsg.c_str());
2086  }
2087  }
2088  // Now create the UNIX sock path
2089  if (!pathrc) {
2090  xps->SetUNIXSockPath(sockpath.c_str());
2091  if ((pathrc = xps->CreateUNIXSock(fEDest)) != 0) {
2092  // Failure
2093  emsg = "failure creating UNIX socket on " ;
2094  emsg += sockpath;
2095  XrdProofdAux::LogEmsgToFile(in.fLogFile.c_str(), emsg.c_str(), npfx.c_str());
2096  TRACEP(p, XERR, emsg.c_str());
2097  }
2098  }
2099  if (!pathrc) {
2100  TRACEP(p, FORK,"UNIX sock: "<<xps->UNIXSockPath());
2101  if ((pathrc = chown(sockpath.c_str(), p->Client()->UI().fUid, p->Client()->UI().fGid)) != 0) {
2102  emsg = "failure changing ownership of the UNIX socket on " ;
2103  emsg += sockpath;
2104  emsg += "; errno: " ;
2105  emsg += errno;
2106  XrdProofdAux::LogEmsgToFile(in.fLogFile.c_str(), emsg.c_str(), npfx.c_str());
2107  TRACEP(p, XERR, emsg.c_str());
2108  }
2109  }
2110  // Communicate sockpath or failure, if any
2111  if (!pathrc) {
2112  // Communicate the path to child
2113  if ((pathrc = fpc.Post(0, sockpath.c_str())) != 0) {
2114  emsg = "failed to communicating path to child";
2115  XrdProofdAux::LogEmsgToFile(in.fLogFile.c_str(), emsg.c_str(), npfx.c_str());
2116  TRACEP(p, XERR, emsg.c_str());
2117  }
2118  } else {
2119  emsg = "failed to setup child admin path";
2120  // Communicate failure to child
2121  if ((pathrc = fpc.Post(-1, sockpath.c_str())) != 0) {
2122  emsg += ": failed communicating failure to child";
2123  XrdProofdAux::LogEmsgToFile(in.fLogFile.c_str(), emsg.c_str(), npfx.c_str());
2124  TRACEP(p, XERR, emsg.c_str());
2125  }
2126  }
2127 
2128  if (pathrc != 0) {
2129  // Failure
2130  xps->Reset();
2131  XrdProofdAux::KillProcess(pid, 1, p->Client()->UI(), fMgr->ChangeOwn());
2132  // Make sure that the log file path reaches the caller
2133  emsg += "|log:";
2134  emsg += in.fLogFile;
2135  emsg.insert(npfx, 0);
2136  response->Send(kXP_ServerError, emsg.c_str());
2137  return 0;
2138  }
2139 
2140  TRACEP(p, FORK, "waiting for client setup status ...");
2141 
2142  emsg = "proofserv setup";
2143  // Wait for the setup process on the pipe, 20 secs max (10 x 2000 millisecs): this
2144  // is enough to cover possible delays due to heavy load; the client will anyhow
2145  // retry a few times
2146  int ntry = 10, prc = 0, rst = -1;
2147  while (prc == 0 && ntry--) {
2148  // Poll for 2 secs
2149  if ((prc = fcp.Poll(2)) > 0) {
2150  // Got something: read the message out
2151  XpdMsg xmsg;
2152  if (fcp.Recv(xmsg) != 0) {
2153  emsg = "error receiving message from pipe";
2154  XrdProofdAux::LogEmsgToFile(in.fLogFile.c_str(), emsg.c_str(), npfx.c_str());
2155  TRACEP(p, XERR, emsg.c_str());
2156  prc = -1;
2157  break;
2158  }
2159  // Status is the message type
2160  rst = xmsg.Type();
2161  // Read string, if any
2162  XrdOucString xbuf = xmsg.Buf();
2163  if (xbuf.length() <= 0) {
2164  emsg = "error reading buffer {logfile, error message} from message received on the pipe";
2165  XrdProofdAux::LogEmsgToFile(in.fLogFile.c_str(), emsg.c_str(), npfx.c_str());
2166  TRACEP(p, XERR, emsg.c_str());
2167  prc = -1;
2168  break;
2169  }
2170  if (rst > 0) {
2171  // Set the log file
2172  xps->SetFileout(xbuf.c_str());
2173  // Set also the session tag
2174  XrdOucString stag(xbuf);
2175  stag.erase(stag.rfind('/'));
2176  stag.erase(0, stag.find("session-") + strlen("session-"));
2177  xps->SetTag(stag.c_str());
2178 
2179  } else {
2180  // Setup failed: save the error
2181  prc = -1;
2182  emsg = "failed: ";
2183  emsg += xbuf;
2184  XrdProofdAux::LogEmsgToFile(in.fLogFile.c_str(), emsg.c_str(), npfx.c_str());
2185  TRACEP(p, XERR, emsg.c_str());
2186  break;
2187  }
2188 
2189  } else if (prc < 0) {
2190  emsg = "error receive status-of-setup from pipe";
2191  XrdProofdAux::LogEmsgToFile(in.fLogFile.c_str(), emsg.c_str(), npfx.c_str());
2192  TRACEP(p, XERR, emsg.c_str());
2193  break;
2194  } else {
2195  TRACEP(p, FORK, "receiving status-of-setup from pipe: waiting 2 s ..."<<pid);
2196  }
2197  }
2198 
2199  // Close pipes
2200  fpc.Close();
2201  fcp.Close();
2202 
2203  TRACEP(p, FORK, "tags: tag:"<<in.fSessionTag<<" top:"<<in.fTopSessionTag<<" xps:"<<xps->Tag());
2204 
2205  // Notify the user
2206  if (prc <= 0) {
2207  // Timed-out or failed: we are done; if timed-out finalize the notification message
2208  emsg = "failure setting up proofserv" ;
2209  if (prc == 0) emsg += ": timed-out receiving status-of-setup from pipe";
2210  // Dump to the log file
2211  XrdProofdAux::LogEmsgToFile(in.fLogFile.c_str(), emsg.c_str(), npfx.c_str());
2212  // Recycle the session object
2213  xps->Reset();
2214  XrdProofdAux::KillProcess(pid, 1, p->Client()->UI(), fMgr->ChangeOwn());
2215  // Make sure that the log file path reaches the caller
2216  emsg += "|log:";
2217  emsg += in.fLogFile;
2218  TRACEP(p, XERR, emsg.c_str());
2219  emsg.insert(npfx, 0);
2220  response->Send(kXP_ServerError, emsg.c_str());
2221  return 0;
2222 
2223  } else {
2224  // Setup was successful
2225  XrdOucString info;
2226  // The log file path (so we do it independently of a successful session startup)
2227  info += "|log:";
2228  info += xps->Fileout();
2229  // Send it back
2230  response->SendI(psid, xps->ROOT()->SrvProtVers(), (kXR_int16)XPROOFD_VERSBIN,
2231  (void *) info.c_str(), info.length());
2232  }
2233 
2234  // now we wait for the callback to be (successfully) established
2235  TRACEP(p, FORK, "server launched: wait for callback ");
2236 
2237  // Set ID
2238  xps->SetSrvPID(pid);
2239 
2240  // Wait for the call back
2241  if (AcceptPeer(xps, intwait, emsg) != 0) {
2242  emsg = "problems accepting callback: ";
2243  // Failure: kill the child process
2244  if (XrdProofdAux::KillProcess(pid, 0, p->Client()->UI(), fMgr->ChangeOwn()) != 0)
2245  emsg += "process could not be killed - pid: ";
2246  else
2247  emsg += "process killed - pid: ";
2248  emsg += (int)pid;
2249  // Dump to the log file
2250  XrdProofdAux::LogEmsgToFile(in.fLogFile.c_str(), emsg.c_str(), npfx.c_str());
2251  // Reset the instance
2252  xps->Reset();
2253  // Notify
2254  TRACEP(p, XERR, emsg.c_str());
2255  emsg.insert(npfx, 0);
2256  response->Send(kXR_attn, kXPD_errmsg, (char *) emsg.c_str(), emsg.length());
2257  return 0;
2258  }
2259  // Set the group, if any
2260  xps->SetGroup(p->Client()->Group());
2261 
2262  // Change child process priority, if required
2263  int dp = 0;
2264  if (fMgr->PriorityMgr()->SetProcessPriority(xps->SrvPID(),
2265  p->Client()->User(), dp) != 0) {
2266  TRACEP(p, XERR, "problems changing child process priority");
2267  } else if (dp > 0) {
2268  TRACEP(p, DBG, "priority of the child process changed by " << dp << " units");
2269  }
2270 
2271  XrdClientID *cid = xps->Parent();
2272  TRACEP(p, FORK, "xps: "<<xps<<", ClientID: "<<(int *)cid<<" (sid: "<<sid<<")"<<" NClients: "<<xps->GetNClients(1));
2273 
2274  // Record this session in the client sandbox
2275  if (p->Client()->Sandbox()->AddSession(xps->Tag()) == -1)
2276  TRACEP(p, REQ, "problems recording session in sandbox");
2277 
2278  // Success; avoid that the global counter is decreased
2279  mcGuard.Set(0);
2280 
2281  // Update the global session handlers
2282  XrdOucString key; key += pid;
2283  { XrdSysMutexHelper mh(fMutex);
2284  fSessions.Add(key.c_str(), xps, 0, Hash_keepdata);
2285  fActiveSessions.push_back(xps);
2286  }
2287  AddSession(p, xps);
2288 
2289  // Check session validity
2290  if (!xps->IsValid()) {
2291  // Notify
2292  TRACEP(p, XERR, "PROOF session is invalid: protocol error? " <<emsg);
2293  }
2294 
2295  // Over
2296  return 0;
2297 }
2298 ////////////////////////////////////////////////////////////////////////////////
2299 /// Create the admin path for the starting session
2300 /// Return 0 on success, -1 on error (error message in 'emsg')
2301 
2303  XrdProofdProtocol *p, int pid,
2304  XrdOucString &emsg)
2305 {
2306  XrdOucString path;
2307  bool assert = (pid > 0) ? 1 : 0;
2308  XPDFORM(path, "%s/%s.%s.", fActiAdminPath.c_str(),
2309  p->Client()->User(), p->Client()->Group());
2310  if (pid > 0) path += pid;
2311  if (xps->SetAdminPath(path.c_str(), assert, fMgr->ChangeOwn()) != 0) {
2312  XPDFORM(emsg, "failure setting admin path '%s'", path.c_str());
2313  return -1;
2314  }
2315  // Done
2316  return 0;
2317 }
2318 
2319 ////////////////////////////////////////////////////////////////////////////////
2320 /// Create the socket path for the starting session
2321 /// Return 0 on success, -1 on error (error message in 'emsg')
2322 
2324  XrdProofdProtocol *p,
2325  unsigned int seq, XrdOucString &emsg)
2326 {
2327  XPDLOC(SMGR, "ProofServMgr::CreateSockPath")
2328 
2329  XrdOucString sockpath;
2330  // Sock path under dedicated directory to avoid problems related to its length
2331  XPDFORM(sockpath, "%s/xpd.%d.%d.%u", fMgr->SockPathDir(), fMgr->Port(), getpid(), seq);
2332  TRACEP(p, ALL, "socket path: " << sockpath);
2333  struct sockaddr_un unserver;
2334  if (sockpath.length() > (int)(sizeof(unserver.sun_path) - 1)) {
2335  XPDFORM(emsg, "socket path very long (%d): this may lead to stack corruption! ", sockpath.length());
2336  return -1;
2337  }
2338  // Now create the UNIX sock path and set its permissions
2339  xps->SetUNIXSockPath(sockpath.c_str());
2340  if (xps->CreateUNIXSock(fEDest) != 0) {
2341  // Failure
2342  XPDFORM(emsg, "failure creating UNIX socket on '%s'", sockpath.c_str());
2343  return -1;
2344  }
2345  if (chmod(sockpath.c_str(), 0755) != 0) {
2346  XPDFORM(emsg, "failure changing permissions of the UNIX socket on '%s'; errno: %d",
2347  sockpath.c_str(), (int)errno);
2348  return -1;
2349  }
2350 
2351  // Done
2352  return 0;
2353 }
2354 
2355 ////////////////////////////////////////////////////////////////////////////////
2356 /// Send content of errlog upstream asynchronously
2357 
2359 {
2360  XPDLOC(SMGR, "ProofServMgr::SendErrLog")
2361 
2362  XrdOucString emsg("An error occured: the content of errlog follows:");
2363  r->Send(kXR_attn, kXPD_srvmsg, (char *) emsg.c_str(), emsg.length());
2364  emsg = "------------------------------------------------\n";
2365  r->Send(kXR_attn, kXPD_srvmsg, 2, (char *) emsg.c_str(), emsg.length());
2366 
2367  int ierr = open(errlog, O_RDONLY);
2368  if (ierr < 0) {
2369  XPDFORM(emsg, "cannot open '%s' (errno: %d)", errlog, errno);
2370  r->Send(kXR_attn, kXPD_srvmsg, 2, (char *) emsg.c_str(), emsg.length());
2371  return;
2372  }
2373  struct stat st;
2374  if (fstat(ierr, &st) != 0) {
2375  XPDFORM(emsg, "cannot stat '%s' (errno: %d)", errlog, errno);
2376  r->Send(kXR_attn, kXPD_srvmsg, 2, (char *) emsg.c_str(), emsg.length());
2377  close (ierr);
2378  return;
2379  }
2380  off_t len = st.st_size;
2381  TRACE(ALL, " reading "<<len<<" bytes from "<<errlog);
2382  ssize_t chunk = 2048, nb, nr;
2383  char buf[2048];
2384  ssize_t left = len;
2385  while (left > 0) {
2386  nb = (left > chunk) ? chunk : left;
2387  if ((nr = read(ierr, buf, nb)) < 0) {
2388  XPDFORM(emsg, "problems reading from '%s' (errno: %d)", errlog, errno);
2389  r->Send(kXR_attn, kXPD_srvmsg, 2, (char *) emsg.c_str(), emsg.length());
2390  close(ierr);
2391  return;
2392  }
2393  TRACE(ALL, buf);
2394  r->Send(kXR_attn, kXPD_srvmsg, 2, buf, nr);
2395  left -= nr;
2396  }
2397  close(ierr);
2398  emsg = "------------------------------------------------";
2399  r->Send(kXR_attn, kXPD_srvmsg, 2, (char *) emsg.c_str(), emsg.length());
2400 
2401  // Done
2402  return;
2403 }
2404 
2405 ////////////////////////////////////////////////////////////////////////////////
2406 /// Handle a request to recover a session after stop&restart
2407 
2409 {
2410  XPDLOC(SMGR, "ProofServMgr::ResolveSession")
2411 
2412  TRACE(REQ, "resolving "<< (fpid ? fpid : "<nul>")<<" ...");
2413 
2414  // Check inputs
2415  if (!fpid || strlen(fpid)<= 0 || !(fMgr->ClientMgr()) || !fRecoverClients) {
2416  TRACE(XERR, "invalid inputs: "<<(fpid ? fpid : "<nul>")<<", "<<fMgr->ClientMgr()<<
2417  ", "<<fRecoverClients);
2418  return -1;
2419  }
2420 
2421  // Path to the session file
2422  XrdOucString path;
2423  XPDFORM(path, "%s/%s", fActiAdminPath.c_str(), fpid);
2424 
2425  // Read info
2426  XrdProofSessionInfo si(path.c_str());
2427 
2428  // Check if recovering is supported
2429  if (si.fSrvProtVers < 18) {
2430  TRACE(DBG, "session does not support recovering: protocol "
2431  <<si.fSrvProtVers<<" < 18");
2432  return -1;
2433  }
2434 
2435  // Create client instance
2436  XrdProofdClient *c = fMgr->ClientMgr()->GetClient(si.fUser.c_str(), si.fGroup.c_str(),
2437  si.fUnixPath.c_str());
2438  if (!c) {
2439  TRACE(DBG, "client instance not initialized");
2440  return -1;
2441  }
2442 
2443  // Allocate the server object
2444  int psid = si.fID;
2445  XrdProofdProofServ *xps = c->GetServObj(psid);
2446  if (!xps) {
2447  TRACE(DBG, "server object not initialized");
2448  return -1;
2449  }
2450 
2451  // Fill info for this session
2452  si.FillProofServ(*xps, fMgr->ROOTMgr());
2453  if (xps->CreateUNIXSock(fEDest) != 0) {
2454  // Failure
2455  TRACE(XERR,"failure creating UNIX socket on " << xps->UNIXSockPath());
2456  xps->Reset();
2457  return -1;
2458  }
2459 
2460  // Set invalid as we are not yet connected
2461  xps->SetValid(0);
2462 
2463  // Add to the lists
2465  std::list<XpdClientSessions *>::iterator ii = fRecoverClients->begin();
2466  while (ii != fRecoverClients->end()) {
2467  if ((*ii)->fClient == c)
2468  break;
2469  ii++;
2470  }
2471  if (ii != fRecoverClients->end()) {
2472  (*ii)->fProofServs.push_back(xps);
2473  } else {
2474  XpdClientSessions *cl = new XpdClientSessions(c);
2475  cl->fProofServs.push_back(xps);
2476  fRecoverClients->push_back(cl);
2477  }
2478 
2479  // Done
2480  return 0;
2481 }
2482 
2483 ////////////////////////////////////////////////////////////////////////////////
2484 /// Handle a request to recover a session after stop&restart for a specific client
2485 
2487 {
2488  XPDLOC(SMGR, "ProofServMgr::Recover")
2489 
2490  if (!cl) {
2491  TRACE(XERR, "invalid input!");
2492  return 0;
2493  }
2494 
2495  TRACE(DBG, "client: "<< cl->fClient->User());
2496 
2497  int nr = 0;
2498  XrdOucString emsg;
2499  XrdProofdProofServ *xps = 0;
2500  int nps = 0;
2501  { XrdSysMutexHelper mhp(cl->fMutex); nps = cl->fProofServs.size(); }
2502  while (nps--) {
2503 
2504  { XrdSysMutexHelper mhp(cl->fMutex); xps = cl->fProofServs.front();
2505  cl->fProofServs.remove(xps); cl->fProofServs.push_back(xps); }
2506 
2507  // Short steps of 1 sec
2508  if (AcceptPeer(xps, 1, emsg) != 0) {
2509  if (emsg == "timeout") {
2510  TRACE(DBG, "timeout while accepting callback");
2511  } else {
2512  TRACE(XERR, "problems accepting callback: "<<emsg);
2513  }
2514  } else {
2515  // Update the global session handlers
2516  XrdOucString key; key += xps->SrvPID();
2517  fSessions.Add(key.c_str(), xps, 0, Hash_keepdata);
2518  fActiveSessions.push_back(xps);
2519  xps->Protocol()->SetAdminPath(xps->AdminPath());
2520  // Remove from the temp list
2521  { XrdSysMutexHelper mhp(cl->fMutex); cl->fProofServs.remove(xps); }
2522  // Count
2523  nr++;
2524  // Notify
2525  if (TRACING(REQ)) {
2526  int pid = xps->SrvPID();
2527  int left = -1;
2528  { XrdSysMutexHelper mhp(cl->fMutex); left = cl->fProofServs.size(); }
2529  XPDPRT("session for "<<cl->fClient->User()<<"."<<cl->fClient->Group()<<
2530  " successfully recovered ("<<left<<" left); pid: "<<pid);
2531  }
2532  }
2533  }
2534 
2535  // Over
2536  return nr;
2537 }
2538 
2539 #ifndef ROOT_XrdFour
2540 ////////////////////////////////////////////////////////////////////////////////
2541 /// Accept a callback from a starting-up server and setup the related protocol
2542 /// object. Used for old servers.
2543 /// Return 0 if successful or -1 in case of failure.
2544 
2546  int to, XrdOucString &msg)
2547 {
2548  XPDLOC(SMGR, "ProofServMgr::AcceptPeer")
2549 
2550  // We will get back a peer to initialize a link
2551  XrdNetPeer peerpsrv;
2552 
2553  // Check inputs
2554  if (!xps || !xps->UNIXSock()) {
2555  XPDFORM(msg, "session pointer undefined or socket invalid: %p", xps);
2556  return -1;
2557  }
2558  TRACE(REQ, "waiting for server callback for "<<to<<" secs ... on "<<xps->UNIXSockPath());
2559 
2560  // Perform regular accept
2561  if (!(xps->UNIXSock()->Accept(peerpsrv, XRDNET_NODNTRIM, to))) {
2562  msg = "timeout";
2563  return -1;
2564  }
2565 
2566  // Setup the protocol serving this peer
2567  if (SetupProtocol(peerpsrv, xps, msg) != 0) {
2568  msg = "could not assert connected peer: ";
2569  return -1;
2570  }
2571 
2572  // Done
2573  return 0;
2574 }
2575 
2576 ////////////////////////////////////////////////////////////////////////////////
2577 /// Setup the protocol object serving the peer described by 'peerpsrv'
2578 
2579 int XrdProofdProofServMgr::SetupProtocol(XrdNetPeer &peerpsrv,
2580  XrdProofdProofServ *xps, XrdOucString &msg)
2581 {
2582  XPDLOC(SMGR, "ProofServMgr::SetupProtocol")
2583 
2584  // We will get back a peer to initialize a link
2585  XrdLink *linkpsrv = 0;
2586  XrdProtocol *xp = 0;
2587  int lnkopts = 0;
2588  bool go = 1;
2589 
2590  // Make sure we have the full host name
2591  if (peerpsrv.InetName) free(peerpsrv.InetName);
2592  peerpsrv.InetName = XrdSysDNS::getHostName("localhost");
2593 
2594  // Allocate a new network object
2595  if (!(linkpsrv = XrdLink::Alloc(peerpsrv, lnkopts))) {
2596  msg = "could not allocate network object: ";
2597  go = 0;
2598  }
2599 
2600  if (go) {
2601  // Keep buffer after object goes away
2602  peerpsrv.InetBuff = 0;
2603  TRACE(DBG, "connection accepted: matching protocol ... ");
2604  // Get a protocol object off the stack (if none, allocate a new one)
2606  if (!(xp = p->Match(linkpsrv))) {
2607  msg = "match failed: protocol error: ";
2608  go = 0;
2609  }
2610  delete p;
2611  }
2612 
2613  if (go) {
2614  // Save path into the protocol instance: it may be needed during Process
2615  XrdOucString apath(xps->AdminPath());
2616  apath += ".status";
2617  ((XrdProofdProtocol *)xp)->SetAdminPath(apath.c_str());
2618  // Take a short-cut and process the initial request as a sticky request
2619  if (xp->Process(linkpsrv) != 0) {
2620  msg = "handshake with internal link failed: ";
2621  go = 0;
2622  }
2623  }
2624 
2625  // Attach this link to the appropriate poller and enable it.
2626  if (go && !XrdPoll::Attach(linkpsrv)) {
2627  msg = "could not attach new internal link to poller: ";
2628  go = 0;
2629  }
2630 
2631  if (!go) {
2632  // Close the link
2633  if (linkpsrv)
2634  linkpsrv->Close();
2635  return -1;
2636  }
2637 
2638  // Tight this protocol instance to the link
2639  linkpsrv->setProtocol(xp);
2640 
2641  TRACE(REQ, "Protocol "<<xp<<" attached to link "<<linkpsrv<<" ("<< peerpsrv.InetName <<")");
2642 
2643  // Schedule it
2644  fMgr->Sched()->Schedule((XrdJob *)linkpsrv);
2645 
2646  // Save the protocol in the session instance
2647  xps->SetProtocol((XrdProofdProtocol *)xp);
2648 
2649  // Done
2650  return 0;
2651 }
2652 
2653 #else
2654 
2655 ////////////////////////////////////////////////////////////////////////////////
2656 /// Accept a callback from a starting-up server and setup the related protocol
2657 /// object. Used for old servers.
2658 /// Return 0 if successful or -1 in case of failure.
2659 
2661  int to, XrdOucString &msg)
2662 {
2663  XPDLOC(SMGR, "ProofServMgr::AcceptPeer")
2664 
2665  // We will get back a peer to initialize a link
2666  XrdNetAddr netaddr;
2667 
2668  // Check inputs
2669  if (!xps || !xps->UNIXSock()) {
2670  XPDFORM(msg, "session pointer undefined or socket invalid: %p", xps);
2671  return -1;
2672  }
2673  TRACE(REQ, "waiting for server callback for "<<to<<" secs ... on "<<xps->UNIXSockPath());
2674 
2675  // Perform regular accept
2676  if (!(xps->UNIXSock()->Accept(netaddr, 0, to))) {
2677  msg = "timeout";
2678  return -1;
2679  }
2680 
2681  // Setup the protocol serving this peer
2682  if (SetupProtocol(netaddr, xps, msg) != 0) {
2683  msg = "could not assert connected peer: ";
2684  return -1;
2685  }
2686 
2687  // Done
2688  return 0;
2689 }
2690 
2691 ////////////////////////////////////////////////////////////////////////////////
2692 /// Setup the protocol object serving the peer described by 'peerpsrv'
2693 
2694 int XrdProofdProofServMgr::SetupProtocol(XrdNetAddr &netaddr,
2695  XrdProofdProofServ *xps, XrdOucString &msg)
2696 {
2697  XPDLOC(SMGR, "ProofServMgr::SetupProtocol")
2698 
2699  // We will get back a peer to initialize a link
2700  XrdLink *linkpsrv = 0;
2701  XrdProtocol *xp = 0;
2702  int lnkopts = 0;
2703  bool go = 1;
2704 
2705  // Allocate a new network object
2706  if (!(linkpsrv = XrdLink::Alloc(netaddr, lnkopts))) {
2707  msg = "could not allocate network object: ";
2708  go = 0;
2709  }
2710 
2711  if (go) {
2712  TRACE(DBG, "connection accepted: matching protocol ... ");
2713  // Get a protocol object off the stack (if none, allocate a new one)
2715  if (!(xp = p->Match(linkpsrv))) {
2716  msg = "match failed: protocol error: ";
2717  go = 0;
2718  }
2719  delete p;
2720  }
2721 
2722  if (go) {
2723  // Save path into the protocol instance: it may be needed during Process
2724  XrdOucString apath(xps->AdminPath());
2725  apath += ".status";
2726  ((XrdProofdProtocol *)xp)->SetAdminPath(apath.c_str());
2727  // Take a short-cut and process the initial request as a sticky request
2728  if (xp->Process(linkpsrv) != 0) {
2729  msg = "handshake with internal link failed: ";
2730  go = 0;
2731  }
2732  }
2733 
2734  // Attach this link to the appropriate poller and enable it.
2735  if (go && !XrdPoll::Attach(linkpsrv)) {
2736  msg = "could not attach new internal link to poller: ";
2737  go = 0;
2738  }
2739 
2740  if (!go) {
2741  // Close the link
2742  if (linkpsrv)
2743  linkpsrv->Close();
2744  return -1;
2745  }
2746 
2747  // Tight this protocol instance to the link
2748  linkpsrv->setProtocol(xp);
2749 
2750  TRACE(REQ, "Protocol "<<xp<<" attached to link "<<linkpsrv<<" ("<< netaddr.Name() <<")");
2751 
2752  // Schedule it
2753  fMgr->Sched()->Schedule((XrdJob *)linkpsrv);
2754 
2755  // Save the protocol in the session instance
2756  xps->SetProtocol((XrdProofdProtocol *)xp);
2757 
2758  // Done
2759  return 0;
2760 }
2761 
2762 #endif
2763 
2764 ////////////////////////////////////////////////////////////////////////////////
2765 /// Handle a request to detach from an existing session
2766 
2768 {
2769  XPDLOC(SMGR, "ProofServMgr::Detach")
2770 
2771  int psid = -1, rc = 0;
2772  XPD_SETRESP(p, "Detach");
2773 
2774  // Unmarshall the data
2775  psid = ntohl(p->Request()->proof.sid);
2776  TRACEP(p, REQ, "psid: "<<psid);
2777 
2778  // Find server session
2779  XrdProofdProofServ *xps = 0;
2780  if (!p->Client() || !(xps = p->Client()->GetServer(psid))) {
2781  TRACEP(p, XERR, "session ID not found: "<<psid);
2782  response->Send(kXR_InvalidRequest,"session ID not found");
2783  return 0;
2784  }
2785  xps->FreeClientID(p->Pid());
2786 
2787  // Notify to user
2788  response->Send();
2789 
2790  return 0;
2791 }
2792 
2793 ////////////////////////////////////////////////////////////////////////////////
2794 /// Handle a request to shutdown an existing session
2795 
2797 {
2798  XPDLOC(SMGR, "ProofServMgr::Destroy")
2799 
2800  int psid = -1, rc = 0;
2801  XPD_SETRESP(p, "Destroy");
2802 
2803  // Unmarshall the data
2804  psid = ntohl(p->Request()->proof.sid);
2805  TRACEP(p, REQ, "psid: "<<psid);
2806 
2807  XrdOucString msg;
2808 
2809  // Find server session
2810  XrdProofdProofServ *xpsref = 0;
2811  if (psid > -1) {
2812  // Request for a specific session
2813  if (!p->Client() || !(xpsref = p->Client()->GetServer(psid))) {
2814  TRACEP(p, XERR, "reference session ID not found");
2815  response->Send(kXR_InvalidRequest,"reference session ID not found");
2816  return 0;
2817  }
2818  XPDFORM(msg, "session %d destroyed by %s", xpsref->SrvPID(), p->Link()->ID);
2819  } else {
2820  XPDFORM(msg, "all sessions destroyed by %s", p->Link()->ID);
2821  }
2822 
2823  // Terminate the servers
2824  p->Client()->TerminateSessions(kXPD_AnyServer, xpsref,
2825  msg.c_str(), Pipe(), fMgr->ChangeOwn());
2826 
2827  // Add to destroyed list
2828  fDestroyTimes[p] = time(0);
2829 
2830  // Notify to user
2831  response->Send();
2832 
2833  // Over
2834  return 0;
2835 }
2836 
2837 ////////////////////////////////////////////////////////////////////////////////
2838 /// Run thorugh entries to broadcast the relevant priority
2839 
2840 static int WriteSessEnvs(const char *, XpdEnv *env, void *s)
2841 {
2842  XPDLOC(SMGR, "WriteSessEnvs")
2843 
2844  XrdOucString emsg;
2845 
2846  XpdWriteEnv_t *xwe = (XpdWriteEnv_t *)s;
2847 
2848  if (env && xwe && xwe->fMgr && xwe->fClient && xwe->fEnv) {
2849  if (env->fEnv.length() > 0) {
2850  // Resolve keywords
2851  xwe->fMgr->ResolveKeywords(env->fEnv, xwe->fClient);
2852  // Set the env now
2853  char *ev = new char[env->fEnv.length()+1];
2854  strncpy(ev, env->fEnv.c_str(), env->fEnv.length());
2855  ev[env->fEnv.length()] = 0;
2856  fprintf(xwe->fEnv, "%s\n", ev);
2857  TRACE(DBG, ev);
2858  PutEnv(ev, xwe->fExport);
2859  }
2860  // Go to next
2861  return 0;
2862  } else {
2863  emsg = "some input undefined";
2864  }
2865 
2866  // Some problem
2867  TRACE(XERR,"protocol error: "<<emsg);
2868  return 1;
2869 }
2870 
2871 ////////////////////////////////////////////////////////////////////////////////
2872 /// Set environment for proofserv; old version preparing the environment for
2873 /// proofserv protocol version <= 13. Needed for backward compatibility.
2874 
2876 {
2877  XPDLOC(SMGR, "ProofServMgr::SetProofServEnvOld")
2878 
2879  char *ev = 0;
2880 
2881  // Check inputs
2882  if (!p || !p->Client() || !input) {
2883  TRACE(XERR, "at leat one input is invalid - cannot continue");
2884  return -1;
2885  }
2886 
2887  // Set basic environment for proofserv
2888  if (SetProofServEnv(fMgr, p->Client()->ROOT()) != 0) {
2889  TRACE(XERR, "problems setting basic environment - exit");
2890  return -1;
2891  }
2892 
2893  ProofServEnv_t *in = (ProofServEnv_t *)input;
2894 
2895  // Session proxy
2896  XrdProofdProofServ *xps = in->fPS;
2897  if (!xps) {
2898  TRACE(XERR, "unable to get instance of proofserv proxy");
2899  return -1;
2900  }
2901  int psid = xps->ID();
2902  TRACE(REQ, "psid: "<<psid<<", log: "<<in->fLogLevel);
2903 
2904  // Work directory
2905  XrdOucString udir = p->Client()->Sandbox()->Dir();
2906  TRACE(DBG, "working dir for "<<p->Client()->User()<<" is: "<<udir);
2907 
2908  size_t len = strlen("ROOTPROOFSESSDIR=") + in->fWrkDir.length() + 2;
2909  ev = new char[len];
2910  snprintf(ev, len, "ROOTPROOFSESSDIR=%s", in->fWrkDir.c_str());
2911  putenv(ev);
2912  TRACE(DBG, ev);
2913 
2914  // Log level
2915  len = strlen("ROOTPROOFLOGLEVEL=") + 5;
2916  ev = new char[len];
2917  snprintf(ev, len, "ROOTPROOFLOGLEVEL=%d", in->fLogLevel);
2918  putenv(ev);
2919  TRACE(DBG, ev);
2920 
2921  // Ordinal number
2922  len = strlen("ROOTPROOFORDINAL=")+strlen(xps->Ordinal()) + 2;
2923  ev = new char[len];
2924  snprintf(ev, len, "ROOTPROOFORDINAL=%s", xps->Ordinal());
2925  putenv(ev);
2926  TRACE(DBG, ev);
2927 
2928  // ROOT Version tag if not the default one
2929  len = strlen("ROOTVERSIONTAG=")+strlen(p->Client()->ROOT()->Tag())+2;
2930  ev = new char[len];
2931  snprintf(ev, len, "ROOTVERSIONTAG=%s", p->Client()->ROOT()->Tag());
2932  putenv(ev);
2933  TRACE(DBG, ev);
2934 
2935  // Create the env file
2936  TRACE(DBG, "creating env file");
2937  XrdOucString envfile = in->fWrkDir;
2938  envfile += ".env";
2939  FILE *fenv = fopen(envfile.c_str(), "w");
2940  if (!fenv) {
2941  TRACE(XERR,
2942  "unable to open env file: "<<envfile);
2943  return -1;
2944  }
2945  TRACE(DBG, "environment file: "<< envfile);
2946 
2947  // Forwarded sec credentials, if any
2948  if (p->AuthProt()) {
2949 
2950  // Additional envs possibly set by the protocol for next application
2951  XrdOucString secenvs(getenv("XrdSecENVS"));
2952  if (secenvs.length() > 0) {
2953  // Go through the list
2954  XrdOucString env;
2955  int from = 0;
2956  while ((from = secenvs.tokenize(env, from, ',')) != -1) {
2957  if (env.length() > 0) {
2958  // Set the env now
2959  ev = new char[env.length()+1];
2960  strncpy(ev, env.c_str(), env.length());
2961  ev[env.length()] = 0;
2962  putenv(ev);
2963  fprintf(fenv, "%s\n", ev);
2964  TRACE(DBG, ev);
2965  }
2966  }
2967  }
2968 
2969  // The credential buffer, if any
2970  XrdSecCredentials *creds = p->AuthProt()->getCredentials();
2971  if (creds) {
2972  len = strlen("XrdSecCREDS=")+creds->size;
2973  ev = new char[len + 1];
2974  strcpy(ev, "XrdSecCREDS=");
2975  memcpy(ev + strlen("XrdSecCREDS="), creds->buffer, creds->size);
2976  ev[len] = 0;
2977  putenv(ev);
2978  TRACE(DBG, "XrdSecCREDS set");
2979  if (fCredsSaver) {
2980  XrdOucString credsdir = udir;
2981  credsdir += "/.creds";
2982  // Make sure the directory exists
2983  if (!XrdProofdAux::AssertDir(credsdir.c_str(), p->Client()->UI(), fMgr->ChangeOwn())) {
2984  if ((*fCredsSaver)(creds, credsdir.c_str(), p->Client()->UI()) != 0) {
2985  TRACE(DBG, "problems in saving authentication creds under "<<credsdir);
2986  }
2987  } else {
2988  TRACE(XERR, "unable to create creds dir: "<<credsdir);
2989  fclose(fenv);
2990  return -1;
2991  }
2992  }
2993  }
2994  }
2995 
2996  // Set ROOTSYS
2997  fprintf(fenv, "ROOTSYS=%s\n", xps->ROOT()->Dir());
2998 
2999  // Set conf dir
3000  fprintf(fenv, "ROOTCONFDIR=%s\n", xps->ROOT()->Dir());
3001 
3002  // Set TMPDIR
3003  fprintf(fenv, "ROOTTMPDIR=%s\n", fMgr->TMPdir());
3004 
3005  // Port (really needed?)
3006  fprintf(fenv, "ROOTXPDPORT=%d\n", fMgr->Port());
3007 
3008  // Work dir
3009  fprintf(fenv, "ROOTPROOFWORKDIR=%s\n", udir.c_str());
3010 
3011  // Session tag
3012  fprintf(fenv, "ROOTPROOFSESSIONTAG=%s\n", in->fSessionTag.c_str());
3013 
3014  // Whether user specific config files are enabled
3015  if (fMgr->NetMgr()->WorkerUsrCfg())
3016  fprintf(fenv, "ROOTUSEUSERCFG=1\n");
3017 
3018  // Set Open socket
3019  fprintf(fenv, "ROOTOPENSOCK=%s\n", xps->UNIXSockPath());
3020 
3021  // Entity
3022  fprintf(fenv, "ROOTENTITY=%s@%s\n", p->Client()->User(), p->Link()->Host());
3023 
3024  // Session ID
3025  fprintf(fenv, "ROOTSESSIONID=%d\n", psid);
3026 
3027  // Client ID
3028  fprintf(fenv, "ROOTCLIENTID=%d\n", p->CID());
3029 
3030  // Client Protocol
3031  fprintf(fenv, "ROOTPROOFCLNTVERS=%d\n", p->ProofProtocol());
3032 
3033  // Ordinal number
3034  fprintf(fenv, "ROOTPROOFORDINAL=%s\n", xps->Ordinal());
3035 
3036  // ROOT version tag if different from the default one
3037  if (getenv("ROOTVERSIONTAG"))
3038  fprintf(fenv, "ROOTVERSIONTAG=%s\n", getenv("ROOTVERSIONTAG"));
3039 
3040  // Config file
3041  if (in->fCfg.length() > 0)
3042  fprintf(fenv, "ROOTPROOFCFGFILE=%s\n", in->fCfg.c_str());
3043 
3044  // Log file in the log dir
3045  fprintf(fenv, "ROOTPROOFLOGFILE=%s\n", in->fLogFile.c_str());
3046  xps->SetFileout(in->fLogFile.c_str());
3047 
3048  // Additional envs (xpd.putenv directive)
3050  if (fProofServEnvs.size() > 0) {
3051  // Hash list of the directives applying to this {user, group, svn, version}
3052  XrdOucHash<XpdEnv> sessenvs;
3053  std::list<XpdEnv>::iterator ienvs = fProofServEnvs.begin();
3054  for ( ; ienvs != fProofServEnvs.end(); ienvs++) {
3055  int envmatch = (*ienvs).Matches(p->Client()->User(), p->Client()->Group(),
3056  p->Client()->ROOT()->VersionCode());
3057  if (envmatch >= 0) {
3058  XpdEnv *env = sessenvs.Find((*ienvs).fName.c_str());
3059  if (env) {
3060  int envmtcex = env->Matches(p->Client()->User(), p->Client()->Group(),
3061  p->Client()->ROOT()->VersionCode());
3062  if (envmatch > envmtcex) {
3063  // Replace the entry
3064  env = &(*ienvs);
3065  sessenvs.Rep(env->fName.c_str(), env, 0, Hash_keepdata);
3066  }
3067  } else {
3068  // Add an entry
3069  env = &(*ienvs);
3070  sessenvs.Add(env->fName.c_str(), env, 0, Hash_keepdata);
3071  }
3072  TRACE(HDBG, "Adding: "<<(*ienvs).fEnv);
3073  }
3074  }
3075  XpdWriteEnv_t xpwe = {fMgr, p->Client(), fenv, in->fOld};
3076  sessenvs.Apply(WriteSessEnvs, (void *)&xpwe);
3077  }
3078  }
3079 
3080  // Set the user envs
3081  if (xps->UserEnvs() &&
3082  strlen(xps->UserEnvs()) && strstr(xps->UserEnvs(),"=")) {
3083  // The single components
3084  XrdOucString ue = xps->UserEnvs();
3085  XrdOucString env, namelist;
3086  int from = 0, ieq = -1;
3087  while ((from = ue.tokenize(env, from, ',')) != -1) {
3088  if (env.length() > 0 && (ieq = env.find('=')) != -1) {
3089  // Resolve keywords
3090  ResolveKeywords(env, in);
3091  ev = new char[env.length()+1];
3092  strncpy(ev, env.c_str(), env.length());
3093  ev[env.length()] = 0;
3094  putenv(ev);
3095  fprintf(fenv, "%s\n", ev);
3096  TRACE(DBG, ev);
3097  env.erase(ieq);
3098  if (namelist.length() > 0)
3099  namelist += ',';
3100  namelist += env;
3101  }
3102  }
3103  // The list of names, ','-separated
3104  len = strlen("PROOF_ALLVARS=") + namelist.length() + 2;
3105  ev = new char[len];
3106  snprintf(ev, len, "PROOF_ALLVARS=%s", namelist.c_str());
3107  putenv(ev);
3108  fprintf(fenv, "%s\n", ev);
3109  TRACE(DBG, ev);
3110  }
3111 
3112  // Close file
3113  fclose(fenv);
3114 
3115  // Create or Update symlink to last session
3116  TRACE(DBG, "creating symlink");
3117  XrdOucString syml = udir;
3118  if (p->ConnType() == kXPD_MasterWorker)
3119  syml += "/last-worker-session";
3120  else
3121  syml += "/last-master-session";
3122  if (XrdProofdAux::SymLink(in->fSessionDir.c_str(), syml.c_str()) != 0) {
3123  TRACE(XERR, "problems creating symlink to last session (errno: "<<errno<<")");
3124  }
3125 
3126  // We are done
3127  TRACE(DBG, "done");
3128  return 0;
3129 }
3130 
3131 ////////////////////////////////////////////////////////////////////////////////
3132 /// Set basic environment accordingly to 'r'
3133 
3135 {
3136  XPDLOC(SMGR, "ProofServMgr::SetProofServEnv")
3137 
3138  char *ev = 0;
3139  size_t len = 0;
3140 
3141  TRACE(REQ, "ROOT dir: "<< (r ? r->Dir() : "*** undef ***"));
3142 
3143  if (r) {
3144  char *libdir = (char *) r->LibDir();
3145  char *ldpath = 0;
3146  if (mgr->BareLibPath() && strlen(mgr->BareLibPath()) > 0) {
3147  len = 32 + strlen(libdir) + strlen(mgr->BareLibPath());
3148  ldpath = new char[len];
3149  snprintf(ldpath, len, "%s=%s:%s", XPD_LIBPATH, libdir, mgr->BareLibPath());
3150  } else {
3151  len = 32 + strlen(libdir);
3152  ldpath = new char[len];
3153  snprintf(ldpath, len, "%s=%s", XPD_LIBPATH, libdir);
3154  }
3155  putenv(ldpath);
3156  // Set ROOTSYS
3157  char *rootsys = (char *) r->Dir();
3158  len = 15 + strlen(rootsys);
3159  ev = new char[len];
3160  snprintf(ev, len, "ROOTSYS=%s", rootsys);
3161  putenv(ev);
3162 
3163  // Set bin directory
3164  char *bindir = (char *) r->BinDir();
3165  len = 15 + strlen(bindir);
3166  ev = new char[len];
3167  snprintf(ev, len, "ROOTBINDIR=%s", bindir);
3168  putenv(ev);
3169 
3170  // Set conf dir
3171  char *confdir = (char *) r->DataDir();
3172  len = 20 + strlen(confdir);
3173  ev = new char[len];
3174  snprintf(ev, len, "ROOTCONFDIR=%s", confdir);
3175  putenv(ev);
3176 
3177  // Set TMPDIR
3178  len = 20 + strlen(mgr->TMPdir());
3179  ev = new char[len];
3180  snprintf(ev, len, "TMPDIR=%s", mgr->TMPdir());
3181  putenv(ev);
3182 
3183  // Done
3184  return 0;
3185  }
3186 
3187  // Bad input
3188  TRACE(XERR, "XrdROOT instance undefined!");
3189  return -1;
3190 }
3191 
3192 ////////////////////////////////////////////////////////////////////////////////
3193 
3195  XrdProofdProofServ *xps,
3196  const char *sessiondir,
3197  const char *extension,
3198  XrdOucString &outfn)
3199 {
3200  XrdOucString host = fMgr->Host();
3201  XrdOucString ord = xps->Ordinal();
3202  XrdOucString role;
3203 
3204  // Shorten host name
3205  if (host.find(".") != STR_NPOS)
3206  host.erase(host.find("."));
3207 
3208  if (p->ConnType() == kXPD_MasterWorker) role = "worker";
3209  else role = "master";
3210 
3211  // File name format:
3212  // <sessiondir>/[master|worker]-<ordinal>-<host>.<ext>
3213  // No PID is contained
3214  XPDFORM(outfn, "%s/%s-%s-%s.%s",
3215  sessiondir,
3216  role.c_str(),
3217  ord.c_str(),
3218  host.c_str(),
3219  extension
3220  );
3221 }
3222 
3223 ////////////////////////////////////////////////////////////////////////////////
3224 /// Determine the unique tag and relevant dirs for this session
3225 
3228  XrdOucString &sesstag, XrdOucString &topsesstag,
3229  XrdOucString &sessiondir, XrdOucString &sesswrkdir)
3230 {
3231  XPDLOC(SMGR, "GetTagDirs")
3232 
3233  // Client sandbox
3234  XrdOucString udir = p->Client()->Sandbox()->Dir();
3235 
3236  if (pid == 0) {
3237 
3238  // Create the unique tag identify this session
3239  XrdOucString host = fMgr->Host();
3240  if (host.find(".") != STR_NPOS)
3241  host.erase(host.find("."));
3242  XPDFORM(sesstag, "%s-%d-", host.c_str(), (int)time(0));
3243 
3244  // Session dir
3245  sessiondir = udir;
3246  if (p->ConnType() == kXPD_ClientMaster) {
3247  sessiondir += "/session-";
3248  sessiondir += sesstag;
3249  topsesstag = sesstag;
3250  } else {
3251  sessiondir += "/";
3252  sessiondir += xps->Tag();
3253  topsesstag = xps->Tag();
3254  topsesstag.replace("session-","");
3255  // If the child, make sure the directory exists ...
3256  if (XrdProofdAux::AssertDir(sessiondir.c_str(), p->Client()->UI(),
3257  fMgr->ChangeOwn()) == -1) {
3258  TRACE(XERR, "problems asserting dir '"<<sessiondir<<"' - errno: "<<errno);
3259  return;
3260  }
3261  }
3262 
3263  } else if (pid > 0) {
3264 
3265  // Finalize unique tag identifying this session
3266  sesstag += pid;
3267 
3268  // Session dir
3269  if (p->ConnType() == kXPD_ClientMaster) {
3270  topsesstag = sesstag;
3271  sessiondir += pid;
3272  xps->SetTag(sesstag.c_str());
3273  }
3274 
3275  // If the child, make sure the directory exists ...
3276  if (pid == (int) getpid()) {
3277  if (XrdProofdAux::AssertDir(sessiondir.c_str(), p->Client()->UI(),
3278  fMgr->ChangeOwn()) == -1) {
3279  return;
3280  }
3281  }
3282 
3283  // The session working dir depends on the role
3284  sesswrkdir = sessiondir;
3285  if (p->ConnType() == kXPD_MasterWorker) {
3286  XPDFORM(sesswrkdir, "%s/worker-%s-%s", sessiondir.c_str(), xps->Ordinal(), sesstag.c_str());
3287  } else {
3288  XPDFORM(sesswrkdir, "%s/master-%s-%s", sessiondir.c_str(), xps->Ordinal(), sesstag.c_str());
3289  }
3290  } else {
3291  TRACE(XERR, "negative pid ("<<pid<<"): should not have got here!");
3292  }
3293 
3294  // Done
3295  return;
3296 }
3297 
3298 ////////////////////////////////////////////////////////////////////////////////
3299 /// Run thorugh entries to broadcast the relevant priority
3300 
3301 static int WriteSessRCs(const char *, XpdEnv *erc, void *f)
3302 {
3303  XPDLOC(SMGR, "WriteSessRCs")
3304 
3305  XrdOucString emsg;
3306  FILE *frc = (FILE *)f;
3307  if (frc && erc) {
3308  XrdOucString rc = erc->fEnv;
3309  if (rc.length() > 0) {
3310  if (rc.find("Proof.DataSetManager") != STR_NPOS) {
3311  TRACE(ALL,"Proof.DataSetManager ignored: use xpd.datasetsrc to define dataset managers");
3312  } else {
3313  fprintf(frc, "%s\n", rc.c_str());
3314  }
3315  }
3316  // Go to next
3317  return 0;
3318  } else {
3319  emsg = "file or input entry undefined";
3320  }
3321 
3322  // Some problem
3323  TRACE(XERR,"protocol error: "<<emsg);
3324  return 1;
3325 }
3326 
3327 ////////////////////////////////////////////////////////////////////////////////
3328 /// Set environment for proofserv
3329 
3331 {
3332  XPDLOC(SMGR, "ProofServMgr::SetProofServEnv")
3333 
3334  // Check inputs
3335  if (!p || !p->Client() || !input) {
3336  TRACE(XERR, "at leat one input is invalid - cannot continue");
3337  return -1;
3338  }
3339 
3340  // Old proofservs expect different settings
3341  int rootvers = p->Client()->ROOT() ? p->Client()->ROOT()->SrvProtVers() : -1;
3342  TRACE(DBG, "rootvers: "<< rootvers);
3343  if (rootvers < 14 && rootvers > -1)
3344  return SetProofServEnvOld(p, input);
3345 
3346  ProofServEnv_t *in = (ProofServEnv_t *)input;
3347 
3348  // Session proxy
3349  XrdProofdProofServ *xps = in->fPS;
3350  if (!xps) {
3351  TRACE(XERR, "unable to get instance of proofserv proxy");
3352  return -1;
3353  }
3354  int psid = xps->ID();
3355  TRACE(REQ, "psid: "<<psid<<", log: "<<in->fLogLevel);
3356 
3357  // Client sandbox
3358  XrdOucString udir = p->Client()->Sandbox()->Dir();
3359  TRACE(DBG, "sandbox for "<<p->Client()->User()<<" is: "<<udir);
3360  TRACE(DBG, "session unique tag "<<in->fSessionTag);
3361  TRACE(DBG, "session dir " << in->fSessionDir);
3362  TRACE(DBG, "session working dir:" << in->fWrkDir);
3363 
3364  // Log into the session it
3365  if (XrdProofdAux::ChangeToDir(in->fSessionDir.c_str(), p->Client()->UI(),
3366  fMgr->ChangeOwn()) != 0) {
3367  TRACE(XERR, "couldn't change directory to " << in->fSessionDir);
3368  return -1;
3369  }
3370 
3371  // Set basic environment for proofserv
3372  if (SetProofServEnv(fMgr, p->Client()->ROOT()) != 0) {
3373  TRACE(XERR, "problems setting basic environment - exit");
3374  return -1;
3375  }
3376 
3377  // Create .rootrc and .env files
3378  TRACE(DBG, "creating rc and env files");
3379  XrdOucString rcfile, envfile;
3380  FormFileNameInSessionDir(p, xps, in->fSessionDir.c_str(), "rootrc", rcfile);
3381  if (CreateProofServRootRc(p, in, rcfile.c_str()) != 0) {
3382  TRACE(XERR, "problems creating RC file "<<rcfile.c_str());
3383  return -1;
3384  }
3385 
3386  FormFileNameInSessionDir(p, xps, in->fSessionDir.c_str(), "env", envfile);
3387  if (CreateProofServEnvFile(p, in, envfile.c_str(), rcfile.c_str()) != 0) {
3388  TRACE(XERR, "problems creating environment file "<<envfile.c_str());
3389  return -1;
3390  }
3391 
3392  // Create or Update symlink to last session
3393  if (in->fOld) {
3394  TRACE(REQ, "creating symlink");
3395  XrdOucString syml = udir;
3396  if (p->ConnType() == kXPD_MasterWorker)
3397  syml += "/last-worker-session";
3398  else
3399  syml += "/last-master-session";
3400  if (XrdProofdAux::SymLink(in->fSessionDir.c_str(), syml.c_str()) != 0) {
3401  TRACE(XERR, "problems creating symlink to "
3402  " last session (errno: "<<errno<<")");
3403  }
3404  }
3405 
3406  // We are done
3407  TRACE(REQ, "done");
3408  return 0;
3409 }
3410 
3411 ////////////////////////////////////////////////////////////////////////////////
3412 /// Create in 'rcfn' the rootrc file for the proofserv being created
3413 /// return 0 on success, -1 on error
3414 
3416  const char *envfn, const char *rcfn)
3417 {
3418  XPDLOC(SMGR, "ProofServMgr::CreateProofServEnvFile")
3419 
3420  // Check inputs
3421  if (!p || !input || (!envfn ||
3422  (envfn && strlen(envfn) <= 0)) || (!rcfn || (rcfn && strlen(rcfn) <= 0))) {
3423  TRACE(XERR, "invalid inputs!");
3424  return -1;
3425  }
3426 
3427  // Attach the structure
3428  ProofServEnv_t *in = (ProofServEnv_t *)input;
3429 
3430  // Session proxy
3431  XrdProofdProofServ *xps = in->fPS;
3432  if (!xps) {
3433  TRACE(XERR, "unable to get instance of proofserv proxy");
3434  return -1;
3435  }
3436 
3437  FILE *fenv = fopen(envfn, "w");
3438  if (!fenv) {
3439  TRACE(XERR, "unable to open env file: "<<envfn);
3440  return -1;
3441  }
3442  TRACE(REQ, "environment file: "<< envfn);
3443 
3444  char *ev = 0;
3445  size_t len = 0;
3446  // Forwarded sec credentials, if any
3447  if (p->AuthProt()) {
3448 
3449  // Additional envs possibly set by the protocol for next application
3450  XrdOucString secenvs(getenv("XrdSecENVS"));
3451  if (secenvs.length() > 0) {
3452  // Go through the list
3453  XrdOucString env;
3454  int from = 0;
3455  while ((from = secenvs.tokenize(env, from, ',')) != -1) {
3456  if (env.length() > 0) {
3457  // Set the env now
3458  ev = new char[env.length()+1];
3459  strncpy(ev, env.c_str(), env.length());
3460  ev[env.length()] = 0;
3461  fprintf(fenv, "%s\n", ev);
3462  TRACE(DBG, ev);
3463  PutEnv(ev, in->fOld);
3464  }
3465  }
3466  }
3467 
3468  // The credential buffer, if any
3469  XrdSecCredentials *creds = p->AuthProt()->getCredentials();
3470  if (creds) {
3471  int lev = strlen("XrdSecCREDS=") + creds->size;
3472  ev = new char[lev+1];
3473  strncpy(ev, "XrdSecCREDS=", lev);
3474  memcpy(ev+strlen("XrdSecCREDS="), creds->buffer, creds->size);
3475  ev[lev] = 0;
3476  PutEnv(ev, in->fOld);
3477  TRACE(DBG, "XrdSecCREDS set");
3478 
3479  if (fCredsSaver) {
3480  XrdOucString credsdir = p->Client()->Sandbox()->Dir();
3481  credsdir += "/.creds";
3482  // Make sure the directory exists
3483  if (!XrdProofdAux::AssertDir(credsdir.c_str(), p->Client()->UI(), fMgr->ChangeOwn())) {
3484  if ((*fCredsSaver)(creds, credsdir.c_str(), p->Client()->UI()) != 0) {
3485  TRACE(DBG, "problems in saving authentication creds under "<<credsdir);
3486  }
3487  } else {
3488  TRACE(XERR, "unable to create creds dir: "<<credsdir);
3489  fclose(fenv);
3490  return -1;
3491  }
3492  }
3493  }
3494  }
3495 
3496  // Library path
3497  fprintf(fenv, "%s=%s\n", XPD_LIBPATH, getenv(XPD_LIBPATH));
3498 
3499  // ROOTSYS
3500  fprintf(fenv, "ROOTSYS=%s\n", xps->ROOT()->Dir());
3501 
3502  // Conf dir
3503  fprintf(fenv, "ROOTCONFDIR=%s\n", xps->ROOT()->Dir());
3504 
3505  // TMPDIR
3506  fprintf(fenv, "TMPDIR=%s\n", fMgr->TMPdir());
3507 
3508  // RC file
3509  if (in->fOld) {
3510  len = strlen("ROOTRCFILE=") + strlen(rcfn) + 2;
3511  ev = new char[len];
3512  snprintf(ev, len, "ROOTRCFILE=%s", rcfn);
3513  fprintf(fenv, "%s\n", ev);
3514  TRACE(DBG, ev);
3515  PutEnv(ev, in->fOld);
3516  }
3517 
3518  // ROOT version tag (needed in building packages)
3519  len = strlen("ROOTVERSIONTAG=") + strlen(p->Client()->ROOT()->Tag()) + 2;
3520  ev = new char[len];
3521  snprintf(ev, len, "ROOTVERSIONTAG=%s", p->Client()->ROOT()->Tag());
3522  fprintf(fenv, "%s\n", ev);
3523  TRACE(DBG, ev);
3524  PutEnv(ev, in->fOld);
3525 
3526  // Log file in the log dir
3527  if (in->fOld) {
3528  len = strlen("ROOTPROOFLOGFILE=") + in->fLogFile.length() + 2;
3529  ev = new char[len];
3530  snprintf(ev, len, "ROOTPROOFLOGFILE=%s", in->fLogFile.c_str());
3531  fprintf(fenv, "%s\n", ev);
3532  xps->SetFileout(in->fLogFile.c_str());
3533  TRACE(DBG, ev);
3534  PutEnv(ev, in->fOld);
3535  }
3536 
3537  // Local data server
3538  XrdOucString locdatasrv;
3539  if (strlen(fMgr->RootdExe()) <= 0) {
3540  XPDFORM(locdatasrv, "root://%s", fMgr->Host());
3541  } else {
3542  XrdOucString uh(fMgr->Host());
3543  if (fMgr->MultiUser()) {
3544  XPDFORM(uh, "%s@%s", fMgr->EffectiveUser(), fMgr->Host());
3545  } else {
3546  XPDFORM(uh, "<effuser>@%s", fMgr->Host());
3547  }
3548  XPDFORM(locdatasrv, "rootd://%s:%d", uh.c_str(), fMgr->Port());
3549  }
3550  int nrk = fMgr->ResolveKeywords(locdatasrv, p->Client());
3551  TRACE(HDBG, nrk << " placeholders resolved for LOCALDATASERVER");
3552  len = strlen("LOCALDATASERVER=") + locdatasrv.length() + 2;
3553  ev = new char[len];
3554  snprintf(ev, len, "LOCALDATASERVER=%s", locdatasrv.c_str());
3555  fprintf(fenv, "%s\n", ev);
3556  TRACE(DBG, ev);
3557  PutEnv(ev, in->fOld);
3558 
3559  // Xrootd config file
3560  if (CfgFile()) {
3561  len = strlen("XRDCF=") + strlen(CfgFile()) + 2;
3562  ev = new char[len];
3563  snprintf(ev, len, "XRDCF=%s", CfgFile());
3564  fprintf(fenv, "%s\n", ev);
3565  TRACE(DBG, ev);
3566  PutEnv(ev, in->fOld);
3567  }
3568 
3569  // Additional envs (xpd.putenv directive)
3571  if (fProofServEnvs.size() > 0) {
3572  // Hash list of the directives applying to this {user, group, svn, version}
3573  XrdOucHash<XpdEnv> sessenvs;
3574  std::list<XpdEnv>::iterator ienvs = fProofServEnvs.begin();
3575  for ( ; ienvs != fProofServEnvs.end(); ienvs++) {
3576  int envmatch = (*ienvs).Matches(p->Client()->User(), p->Client()->Group(),
3577  p->Client()->ROOT()->VersionCode());
3578  if (envmatch >= 0) {
3579  XpdEnv *env = sessenvs.Find((*ienvs).fName.c_str());
3580  if (env) {
3581  int envmtcex = env->Matches(p->Client()->User(), p->Client()->Group(),
3582  p->Client()->ROOT()->VersionCode());
3583  if (envmatch > envmtcex) {
3584  // Replace the entry
3585  env = &(*ienvs);
3586  sessenvs.Rep(env->fName.c_str(), env, 0, Hash_keepdata);
3587  }
3588  } else {
3589  // Add an entry
3590  env = &(*ienvs);
3591  sessenvs.Add(env->fName.c_str(), env, 0, Hash_keepdata);
3592  }
3593  TRACE(HDBG, "Adding: "<<(*ienvs).fEnv);
3594  }
3595  }
3596  XpdWriteEnv_t xpwe = {fMgr, p->Client(), fenv, in->fOld};
3597  sessenvs.Apply(WriteSessEnvs, (void *)&xpwe);
3598  }
3599  }
3600  // Set the user envs
3601  if (xps->UserEnvs() &&
3602  strlen(xps->UserEnvs()) && strstr(xps->UserEnvs(),"=")) {
3603  // The single components
3604  XrdOucString ue = xps->UserEnvs();
3605  XrdOucString env, namelist;
3606  int from = 0, ieq = -1;
3607  while ((from = ue.tokenize(env, from, ',')) != -1) {
3608  if (env.length() > 0 && (ieq = env.find('=')) != -1) {
3609  // Resolve keywords
3610  ResolveKeywords(env, in);
3611  ev = new char[env.length()+1];
3612  strncpy(ev, env.c_str(), env.length());
3613  ev[env.length()] = 0;
3614  if (env.find("WRAPPERCMD") == STR_NPOS || !xps->IsPLite())
3615  fprintf(fenv, "%s\n", ev);
3616  TRACE(DBG, ev);
3617  PutEnv(ev, in->fOld);
3618  if (env.find("WRAPPERCMD") == STR_NPOS || !xps->IsPLite()) {
3619  env.erase(ieq);
3620  if (namelist.length() > 0)
3621  namelist += ',';
3622  namelist += env;
3623  }
3624  }
3625  }
3626  // The list of names, ','-separated
3627  len = strlen("PROOF_ALLVARS=") + namelist.length() + 2;
3628  ev = new char[len];
3629  snprintf(ev, len, "PROOF_ALLVARS=%s", namelist.c_str());
3630  fprintf(fenv, "%s\n", ev);
3631  TRACE(DBG, ev);
3632  PutEnv(ev, in->fOld);
3633  }
3634 
3635  // Close file
3636  fclose(fenv);
3637 
3638  // We are done
3639  return 0;
3640 }
3641 
3642 ////////////////////////////////////////////////////////////////////////////////
3643 /// Create in 'rcfn' the rootrc file for the proofserv being created
3644 /// return 0 on success, -1 on error
3645 
3647  void *input, const char *rcfn)
3648 {
3649  XPDLOC(SMGR, "ProofServMgr::CreateProofServRootRc")
3650 
3651  // Check inputs
3652  if (!p || !input || (!rcfn || (rcfn && strlen(rcfn) <= 0))) {
3653  TRACE(XERR, "invalid inputs!");
3654  return -1;
3655  }
3656 
3657  // Attach the structure
3658  ProofServEnv_t *in = (ProofServEnv_t *)input;
3659 
3660  // Session proxy
3661  XrdProofdProofServ *xps = in->fPS;
3662  if (!xps) {
3663  TRACE(XERR, "unable to get instance of proofserv proxy");
3664  return -1;
3665  }
3666  int psid = xps->ID();
3667 
3668  FILE *frc = fopen(rcfn, "w");
3669  if (!frc) {
3670  TRACE(XERR, "unable to open rootrc file: "<<rcfn);
3671  return -1;
3672  }
3673  // Symlink to session.rootrc
3674  if (in->fOld) {
3675  if (XrdProofdAux::SymLink(rcfn, "session.rootrc") != 0) {
3676  TRACE(XERR, "problems creating symlink to 'session.rootrc' (errno: "<<errno<<")");
3677  }
3678  }
3679  TRACE(REQ, "session rootrc file: "<< rcfn);
3680 
3681  // Port
3682  fprintf(frc, "# XrdProofdProtocol listening port\n");
3683  fprintf(frc, "ProofServ.XpdPort: %d\n", fMgr->Port());
3684 
3685  // Local root prefix
3686  if (fMgr->LocalROOT() && strlen(fMgr->LocalROOT()) > 0) {
3687  fprintf(frc, "# Prefix to be prepended to local paths\n");
3688  fprintf(frc, "Path.Localroot: %s\n", fMgr->LocalROOT());
3689  }
3690 
3691  // Data pool entry-point URL
3692  if (fMgr->PoolURL() && strlen(fMgr->PoolURL()) > 0) {
3693  XrdOucString purl(fMgr->PoolURL());
3694  if (!purl.endswith("/"))
3695  purl += "/";
3696  fprintf(frc, "# URL for the data pool entry-point\n");
3697  fprintf(frc, "ProofServ.PoolUrl: %s\n", purl.c_str());
3698  }
3699 
3700  // The session working dir depends on the role
3701  if (in->fOld) {
3702  fprintf(frc, "# The session working dir\n");
3703  fprintf(frc, "ProofServ.SessionDir: %s\n", in->fWrkDir.c_str());
3704  }
3705 
3706  // Log / Debug level
3707  fprintf(frc, "# Proof Log/Debug level\n");
3708  fprintf(frc, "Proof.DebugLevel: %d\n", in->fLogLevel);
3709 
3710  // Ordinal number
3711  fprintf(frc, "# Ordinal number\n");
3712  fprintf(frc, "ProofServ.Ordinal: %s\n", xps->Ordinal());
3713 
3714  // ROOT Version tag
3715  if (p->Client()->ROOT()) {
3716  fprintf(frc, "# ROOT Version tag\n");
3717  fprintf(frc, "ProofServ.RootVersionTag: %s\n", p->Client()->ROOT()->Tag());
3718  }
3719  // Proof group
3720  if (p->Client()->Group()) {
3721  fprintf(frc, "# Proof group\n");
3722  fprintf(frc, "ProofServ.ProofGroup: %s\n", p->Client()->Group());
3723  }
3724 
3725  // Path to file with group information
3726  if (fMgr->GroupsMgr() && fMgr->GroupsMgr()->GetCfgFile()) {
3727  fprintf(frc, "# File with group information\n");
3728  fprintf(frc, "Proof.GroupFile: %s\n", fMgr->GroupsMgr()->GetCfgFile());
3729  }
3730 
3731  // Work dir
3732  XrdOucString udir = p->Client()->Sandbox()->Dir();
3733  fprintf(frc, "# Users sandbox\n");
3734  fprintf(frc, "ProofServ.Sandbox: %s\n", udir.c_str());
3735 
3736  // Image
3737  if (fMgr->Image() && strlen(fMgr->Image()) > 0) {
3738  fprintf(frc, "# Server image\n");
3739  fprintf(frc, "ProofServ.Image: %s\n", fMgr->Image());
3740  }
3741 
3742  // Session tags
3743  if (in->fOld) {
3744  fprintf(frc, "# Session tag\n");
3745  fprintf(frc, "ProofServ.SessionTag: %s\n", in->fSessionTag.c_str());
3746  fprintf(frc, "# Top Session tag\n");
3747  fprintf(frc, "ProofServ.TopSessionTag: %s\n", in->fTopSessionTag.c_str());
3748  }
3749 
3750  // Session admin path
3751  fprintf(frc, "# Session admin path\n");
3752  int proofvrs = (p->Client()->ROOT()) ? p->Client()->ROOT()->SrvProtVers() : -1;
3753  if (proofvrs < 0 || proofvrs < 27) {
3754  // Use the first version of the session status file
3755  fprintf(frc, "ProofServ.AdminPath: %s\n", xps->AdminPath());
3756  } else {
3757  if (in->fOld) {
3758  // New version with updated status
3759  fprintf(frc, "ProofServ.AdminPath: %s.status\n", xps->AdminPath());
3760  }
3761  }
3762 
3763  // Whether user specific config files are enabled
3764  if (fMgr->NetMgr()->WorkerUsrCfg()) {
3765  fprintf(frc, "# Whether user specific config files are enabled\n");
3766  fprintf(frc, "ProofServ.UseUserCfg: 1\n");
3767  }
3768  // Set Open socket
3769  fprintf(frc, "# Open socket\n");
3770  fprintf(frc, "ProofServ.OpenSock: %s\n", xps->UNIXSockPath());
3771  // Entity
3772  fprintf(frc, "# Entity\n");
3773  if (p->Client()->UI().fGroup.length() > 0)
3774  fprintf(frc, "ProofServ.Entity: %s:%s@%s\n",
3775  p->Client()->User(), p->Client()->UI().fGroup.c_str(), p->Link()->Host());
3776  else
3777  fprintf(frc, "ProofServ.Entity: %s@%s\n", p->Client()->User(), p->Link()->Host());
3778 
3779 
3780  // Session ID
3781  fprintf(frc, "# Session ID\n");
3782  fprintf(frc, "ProofServ.SessionID: %d\n", psid);
3783 
3784  // Client ID
3785  fprintf(frc, "# Client ID\n");
3786  fprintf(frc, "ProofServ.ClientID: %d\n", p->CID());
3787 
3788  // Client Protocol
3789  fprintf(frc, "# Client Protocol\n");
3790  fprintf(frc, "ProofServ.ClientVersion: %d\n", p->ProofProtocol());
3791 
3792  // Config file
3793  if (in->fCfg.length() > 0) {
3794  if (in->fCfg == "masteronly") {
3795  fprintf(frc, "# MasterOnly option\n");
3796  // Master Only setup
3797  fprintf(frc, "Proof.MasterOnly: 1\n");
3798  } else {
3799  fprintf(frc, "# Config file\n");
3800  // User defined
3801  fprintf(frc, "ProofServ.ProofConfFile: %s\n", in->fCfg.c_str());
3802  }
3803  } else {
3804  fprintf(frc, "# Config file\n");
3805  if (fMgr->IsSuperMst()) {
3806  fprintf(frc, "ProofServ.ProofConfFile: sm:\n");
3807  } else if (xps->IsPLite()) {
3808  fprintf(frc, "ProofServ.ProofConfFile: lite:\n");
3809  fprintf(frc, "# Number of ProofLite workers\n");
3810  fprintf(frc, "ProofLite.Workers: %d\n", xps->PLiteNWrks());
3811  fprintf(frc, "# Users sandbox\n");
3812  fprintf(frc, "ProofLite.Sandbox: %s\n", udir.c_str());
3813  fprintf(frc, "# No subpaths\n");
3814  fprintf(frc, "ProofLite.SubPath: 0\n");
3815  } else if (fProofPlugin.length() > 0) {
3816  fprintf(frc, "ProofServ.ProofConfFile: %s\n", fProofPlugin.c_str());
3817  }
3818  }
3819 
3820  // We set this to avoid blocking to much on xrdclient actions; they can be
3821  // oevrwritten with explicit putrc directives
3822  fprintf(frc, "# Default settings for XrdClient\n");
3823  fprintf(frc, "XNet.FirstConnectMaxCnt 3\n");
3824  fprintf(frc, "XNet.ConnectTimeout 5\n");
3825 
3826  // This is a workaround for a problem fixed in 5.24/00
3827  int vrscode = (p->Client()->ROOT()) ? p->Client()->ROOT()->VersionCode() : -1;
3828  if (vrscode > 0 && vrscode < XrdROOT::GetVersionCode(5,24,0)) {
3829  fprintf(frc, "# Force remote reading also for local files to avoid a wrong TTreeCache initialization\n");
3830  fprintf(frc, "Path.ForceRemote 1\n");
3831  }
3832 
3833  // Additional rootrcs (xpd.putrc directive)
3835  if (fProofServRCs.size() > 0) {
3836  fprintf(frc, "# Additional rootrcs (xpd.putrc directives)\n");
3837  // Hash list of the directives applying to this {user, group, svn, version}
3838  XrdOucHash<XpdEnv> sessrcs;
3839  std::list<XpdEnv>::iterator ircs = fProofServRCs.begin();
3840  for ( ; ircs != fProofServRCs.end(); ircs++) {
3841  int rcmatch = (*ircs).Matches(p->Client()->User(), p->Client()->Group(),
3842  p->Client()->ROOT()->VersionCode());
3843  if (rcmatch >= 0) {
3844  XpdEnv *rcenv = sessrcs.Find((*ircs).fName.c_str());
3845  if (rcenv) {
3846  int rcmtcex = rcenv->Matches(p->Client()->User(), p->Client()->Group(),
3847  p->Client()->ROOT()->VersionCode());
3848  if (rcmatch > rcmtcex) {
3849  // Replace the entry
3850  rcenv = &(*ircs);
3851  sessrcs.Rep(rcenv->fName.c_str(), rcenv, 0, Hash_keepdata);
3852  }
3853  } else {
3854  // Add an entry
3855  rcenv = &(*ircs);
3856  sessrcs.Add(rcenv->fName.c_str(), rcenv, 0, Hash_keepdata);
3857  }
3858  TRACE(HDBG, "Adding: "<<(*ircs).fEnv);
3859  }
3860  }
3861  sessrcs.Apply(WriteSessRCs, (void *)frc);
3862  }
3863  }
3864  // If applicable, add dataset managers initiators
3865  if (fMgr->DataSetSrcs()->size() > 0) {
3866  fprintf(frc, "# Dataset sources\n");
3867  XrdOucString rc("Proof.DataSetManager: ");
3868  std::list<XrdProofdDSInfo *>::iterator ii;
3869  for (ii = fMgr->DataSetSrcs()->begin(); ii != fMgr->DataSetSrcs()->end(); ii++) {
3870  if (ii != fMgr->DataSetSrcs()->begin()) rc += ", ";
3871  rc += (*ii)->fType;
3872  rc += " dir:";
3873  rc += (*ii)->fUrl;
3874  rc += " opt:";
3875  rc += (*ii)->fOpts;
3876  rc += " ";
3877  rc += (*ii)->fObscure;
3878  }
3879  fprintf(frc, "%s\n", rc.c_str());
3880  }
3881 
3882  // If applicable, add staging requests repository directive initiator
3883  if (strlen(fMgr->StageReqRepo()) > 0) {
3884  fprintf(frc, "# Dataset staging requests repository\n");
3885  fprintf(frc, "Proof.DataSetStagingRequests: %s\n", fMgr->StageReqRepo());
3886  }
3887 
3888  // If applicable, add datadir location
3889  if (fMgr->DataDir() && strlen(fMgr->DataDir()) > 0) {
3890  fprintf(frc, "# Data directory\n");
3891  XrdOucString rc;
3892  XPDFORM(rc, "ProofServ.DataDir: %s/%s/%s/%s/%s", fMgr->DataDir(),
3893  p->Client()->Group(), p->Client()->User(), xps->Ordinal(),
3894  in->fSessionTag.c_str());
3895  if (fMgr->DataDirUrlOpts() && strlen(fMgr->DataDirUrlOpts()) > 0) {
3896  fprintf(frc, "%s %s\n", rc.c_str(), fMgr->DataDirUrlOpts());
3897  } else {
3898  fprintf(frc, "%s\n", rc.c_str());
3899  }
3900  }
3901 
3902  // Done with this
3903  fclose(frc);
3904 
3905  // Done
3906  return 0;
3907 }
3908 
3909 ////////////////////////////////////////////////////////////////////////////////
3910 /// Cleanup (kill) all 'proofserv' processes which lost control from their
3911 /// creator or controller daemon. We rely here on the information in the admin
3912 /// path(s) (<xrd_admin>/.xproof.<port>).
3913 /// This is called regurarly by the cron job to avoid having proofservs around.
3914 /// Return number of process killed or -1 in case of any error.
3915 
3917 {
3918  XPDLOC(SMGR, "ProofServMgr::CleanupLostProofServ")
3919 
3920  if (!fCheckLost) {
3921  TRACE(REQ, "disabled ...");
3922  return 0;
3923  }
3924 
3925  TRACE(REQ, "checking for orphalin proofserv processes ...");
3926  int nk = 0;
3927 
3928  // Get the list of existing proofserv processes from the process table
3929  std::map<int,XrdOucString> procs;
3930  if (XrdProofdAux::GetProcesses("proofserv", &procs) <= 0) {
3931  TRACE(DBG, " no proofservs around: nothing to do");
3932  return 0;
3933  }
3934 
3935  XrdProofUI ui;
3936  if (XrdProofdAux::GetUserInfo(fMgr->EffectiveUser(), ui) != 0) {
3937  TRACE(DBG, "problems getting info for user " << fMgr->EffectiveUser());
3938  return -1;
3939  }
3940 
3941  // Hash list of controlled and xrootd process
3942  XrdOucRash<int, int> controlled, xrdproc;
3943 
3944  // Hash list of sessions files loaded
3945  XrdOucHash<XrdOucString> sessionspaths;
3946 
3947  // For each process extract the information about the daemon supposed to be in control
3948  int pid, ia, a;
3949  XrdOucString cmd, apath, pidpath, sessiondir, emsg, rest, after;
3950  std::map<int,XrdOucString>::iterator ip;
3951  for (ip = procs.begin(); ip != procs.end(); ip++) {
3952  pid = ip->first;
3953  cmd = ip->second;
3954  if ((ia = cmd.find("xpdpath:")) != STR_NPOS) {
3955  cmd.tokenize(apath, ia, ' ');
3956  apath.replace("xpdpath:", "");
3957  if (apath.length() <= 0) {
3958  TRACE(ALL, "admin path not found; initial cmd line: "<<cmd);
3959  continue;
3960  }
3961  // Extract daemon PID and check that it is alive
3962  XPDFORM(pidpath, "%s/xrootd.pid", apath.c_str());
3963  TRACE(ALL, "pidpath: "<<pidpath);
3964  int xpid = XrdProofdAux::GetIDFromPath(pidpath.c_str(), emsg);
3965  int *alive = xrdproc.Find(xpid);
3966  if (!alive) {
3967  a = (XrdProofdAux::VerifyProcessByID(xpid, fParentExecs.c_str())) ? 1 : 0;
3968  xrdproc.Add(xpid, a);
3969  } else {
3970  a = *alive;
3971  }
3972  // If the daemon is still there check that the process has its entry in the
3973  // session path(s);
3974  bool ok = 0;
3975  if (a == 1) {
3976  const char *subdir[2] = {"activesessions", "terminatedsessions"};
3977  for (int i = 0; i < 2; i++) {
3978  XPDFORM(sessiondir, "%s/%s", apath.c_str(), subdir[i]);
3979  if (!sessionspaths.Find(sessiondir.c_str())) {
3980  DIR *sdir = opendir(sessiondir.c_str());
3981  if (!sdir) {
3982  XPDFORM(emsg, "cannot open '%s' - errno: %d", apath.c_str(), errno);
3983  TRACE(XERR, emsg.c_str());
3984  continue;
3985  }
3986  struct dirent *sent = 0;
3987  while ((sent = readdir(sdir))) {
3988  if (!strncmp(sent->d_name, ".", 1) || !strncmp(sent->d_name, "..", 2))
3989  continue;
3990  // Get the pid
3991  int ppid = XrdProofdAux::ParsePidPath(sent->d_name, rest, after);
3992  // Add to the list
3993  controlled.Add(ppid, ppid);
3994  }
3995  closedir(sdir);
3996  sessionspaths.Add(sessiondir.c_str(), 0, 0, Hash_data_is_key);
3997  }
3998  ok = (controlled.Find(pid)) ? 1 : ok;
3999  // We are done, if the process is controlled
4000  if (ok) break;
4001  }
4002  }
4003  // If the process is not controlled we have to kill it
4004  if (!ok) {
4005  TRACE(ALL,"process: "<<pid<<" lost its controller: killing");
4006  if (XrdProofdAux::KillProcess(pid, 1, ui, fMgr->ChangeOwn()) == 0)
4007  nk++;
4008  }
4009  }
4010 
4011  }
4012 
4013  // Done
4014  return nk;
4015 }
4016 
4017 ////////////////////////////////////////////////////////////////////////////////
4018 /// Cleanup (kill) all 'proofserv' processes from the process table.
4019 /// Only the processes associated with 'usr' are killed,
4020 /// unless 'all' is TRUE, in which case all 'proofserv' instances are
4021 /// terminated (this requires superuser privileges).
4022 /// Super users can also terminated all processes fo another user (specified
4023 /// via usr).
4024 /// Return number of process notified for termination on success, -1 otherwise
4025 
4027 {
4028  XPDLOC(SMGR, "ProofServMgr::CleanupProofServ")
4029 
4030  TRACE(REQ, "all: "<<all<<", usr: " << (usr ? usr : "undef"));
4031  int nk = 0;
4032 
4033  // Name
4034  const char *pn = "proofserv";
4035 
4036  // Uid
4037  XrdProofUI ui;
4038  int refuid = -1;
4039  if (!all) {
4040  if (!usr) {
4041  TRACE(DBG, "usr must be defined for all = FALSE");
4042  return -1;
4043  }
4044  if (XrdProofdAux::GetUserInfo(usr, ui) != 0) {
4045  TRACE(DBG, "problems getting info for user " << usr);
4046  return -1;
4047  }
4048  refuid = ui.fUid;
4049  }
4050 
4051 #if defined(linux)
4052  // Loop over the "/proc" dir
4053  DIR *dir = opendir("/proc");
4054  if (!dir) {
4055  XrdOucString emsg("cannot open /proc - errno: ");
4056  emsg += errno;
4057  TRACE(DBG, emsg.c_str());
4058  return -1;
4059  }
4060 
4061  struct dirent *ent = 0;
4062  while ((ent = readdir(dir))) {
4063  if (!strncmp(ent->d_name, ".", 1) || !strncmp(ent->d_name, "..", 2)) continue;
4064  if (DIGIT(ent->d_name[0])) {
4065  XrdOucString fn("/proc/", 256);
4066  fn += ent->d_name;
4067  fn += "/status";
4068  // Open file
4069  FILE *ffn = fopen(fn.c_str(), "r");
4070  if (!ffn) {
4071  XrdOucString emsg("cannot open file ");
4072  emsg += fn; emsg += " - errno: "; emsg += errno;
4073  TRACE(HDBG, emsg);
4074  continue;
4075  }
4076  // Read info
4077  bool xname = 1, xpid = 1, xppid = 1;
4078  bool xuid = (all) ? 0 : 1;
4079  int pid = -1;
4080  int ppid = -1;
4081  char line[2048] = { 0 };
4082  while (fgets(line, sizeof(line), ffn) &&
4083  (xname || xpid || xppid || xuid)) {
4084  // Check name
4085  if (xname && strstr(line, "Name:")) {
4086  if (!strstr(line, pn))
4087  break;
4088  xname = 0;
4089  }
4090  if (xpid && strstr(line, "Pid:")) {
4091  pid = (int) XrdProofdAux::GetLong(&line[strlen("Pid:")]);
4092  xpid = 0;
4093  }
4094  if (xppid && strstr(line, "PPid:")) {
4095  ppid = (int) XrdProofdAux::GetLong(&line[strlen("PPid:")]);
4096  // Parent process must be us or be dead
4097  if (ppid != getpid() && XrdProofdAux::VerifyProcessByID(ppid, fParentExecs.c_str()))
4098  // Process created by another running xrootd
4099  break;
4100  xppid = 0;
4101  }
4102  if (xuid && strstr(line, "Uid:")) {
4103  int uid = (int) XrdProofdAux::GetLong(&line[strlen("Uid:")]);
4104  if (refuid == uid)
4105  xuid = 0;
4106  }
4107  }
4108  // Close the file
4109  fclose(ffn);
4110  // If this is a good candidate, kill it
4111  if (!xname && !xpid && !xppid && !xuid) {
4112 
4113  bool muok = 1;
4114  if (fMgr->MultiUser() && !all) {
4115  // We need to check the user name: we may be the owner of somebody
4116  // else process; if not session is attached, we kill it
4117  muok = 0;
4119  if (!srv || (srv && !strcmp(usr, srv->Client())))
4120  muok = 1;
4121  }
4122  if (muok)
4123  if (XrdProofdAux::KillProcess(pid, 1, ui, fMgr->ChangeOwn()) == 0)
4124  nk++;
4125  }
4126  }
4127  }
4128  // Close the directory
4129  closedir(dir);
4130 
4131 #elif defined(__sun)
4132 
4133  // Loop over the "/proc" dir
4134  DIR *dir = opendir("/proc");
4135  if (!dir) {
4136  XrdOucString emsg("cannot open /proc - errno: ");
4137  emsg += errno;
4138  TRACE(DBG, emsg);
4139  return -1;
4140  }
4141 
4142  struct dirent *ent = 0;
4143  while ((ent = readdir(dir))) {
4144  if (!strncmp(ent->d_name, ".", 1) || !strncmp(ent->d_name, "..", 2)) continue;
4145  if (DIGIT(ent->d_name[0])) {
4146  XrdOucString fn("/proc/", 256);
4147  fn += ent->d_name;
4148  fn += "/psinfo";
4149  // Open file
4150  int ffd = open(fn.c_str(), O_RDONLY);
4151  if (ffd <= 0) {
4152  XrdOucString emsg("cannot open file ");
4153  emsg += fn; emsg += " - errno: "; emsg += errno;
4154  TRACE(HDBG, emsg);
4155  continue;
4156  }
4157  // Read info
4158  bool xname = 1;
4159  bool xuid = (all) ? 0 : 1;
4160  bool xppid = 1;
4161  // Get the information
4162  psinfo_t psi;
4163  if (read(ffd, &psi, sizeof(psinfo_t)) != sizeof(psinfo_t)) {
4164  XrdOucString emsg("cannot read ");
4165  emsg += fn; emsg += ": errno: "; emsg += errno;
4166  TRACE(XERR, emsg);
4167  close(ffd);
4168  continue;
4169  }
4170  // Close the file
4171  close(ffd);
4172 
4173  // Check name
4174  if (xname) {
4175  if (!strstr(psi.pr_fname, pn))
4176  continue;
4177  xname = 0;
4178  }
4179  // Check uid, if required
4180  if (xuid) {
4181  if (refuid == psi.pr_uid)
4182  xuid = 0;
4183  }
4184  // Parent process must be us or be dead
4185  int ppid = psi.pr_ppid;
4186  if (ppid != getpid() && XrdProofdAux::VerifyProcessByID(ppid, fParentExecs.c_str())) {
4187  // Process created by another running xrootd
4188  continue;
4189  xppid = 0;
4190  }
4191 
4192  // If this is a good candidate, kill it
4193  if (!xname && !xppid && !xuid) {
4194  bool muok = 1;
4195  if (fMgr->MultiUser() && !all) {
4196  // We need to check the user name: we may be the owner of somebody
4197  // else process; if no session is attached , we kill it
4198  muok = 0;
4199  XrdProofdProofServ *srv = GetActiveSession(psi.pr_pid);
4200  if (!srv || (srv && !strcmp(usr, srv->Client())))
4201  muok = 1;
4202  }
4203  if (muok)
4204  if (XrdProofdAux::KillProcess(psi.pr_pid, 1, ui, fMgr->ChangeOwn()) == 0)
4205  nk++;
4206  }
4207  }
4208  }
4209  // Close the directory
4210  closedir(dir);
4211 
4212 #elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
4213 
4214  // Get the proclist
4215  kinfo_proc *pl = 0;
4216  int np;
4217  int ern = 0;
4218  if ((ern = XrdProofdAux::GetMacProcList(&pl, np)) != 0) {
4219  XrdOucString emsg("cannot get the process list: errno: ");
4220  emsg += ern;
4221  TRACE(XERR, emsg);
4222  return -1;
4223  }
4224 
4225  // Loop over the list
4226  int ii = np;
4227  while (ii--) {
4228  if (strstr(pl[ii].kp_proc.p_comm, pn)) {
4229  if (all || (int)(pl[ii].kp_eproc.e_ucred.cr_uid) == refuid) {
4230  // Parent process must be us or be dead
4231  int ppid = pl[ii].kp_eproc.e_ppid;
4232  bool xppid = 0;
4233  if (ppid != getpid()) {
4234  int jj = np;
4235  while (jj--) {
4236  if (strstr(pl[jj].kp_proc.p_comm, "xrootd") &&
4237  pl[jj].kp_proc.p_pid == ppid) {
4238  xppid = 1;
4239  break;
4240  }
4241  }
4242  }
4243  if (!xppid) {
4244  bool muok = 1;
4245  if (fMgr->MultiUser() && !all) {
4246  // We need to check the user name: we may be the owner of somebody
4247  // else process; if no session is attached, we kill it
4248  muok = 0;
4249  XrdProofdProofServ *srv = GetActiveSession(pl[np].kp_proc.p_pid);
4250  if (!srv || (srv && !strcmp(usr, srv->Client())))
4251  muok = 1;
4252  }
4253  if (muok)
4254  // Good candidate to be shot
4255  if (XrdProofdAux::KillProcess(pl[np].kp_proc.p_pid, 1, ui, fMgr->ChangeOwn()))
4256  nk++;
4257  }
4258  }
4259  }
4260  }
4261  // Cleanup
4262  free(pl);
4263 #else
4264  // For the remaining cases we use 'ps' via popen to localize the processes
4265 
4266  // Build command
4267  XrdOucString cmd = "ps ";
4268  bool busr = 0;
4269  const char *cusr = (usr && strlen(usr) && fSuperUser) ? usr : fPClient->ID();
4270  if (all) {
4271  cmd += "ax";
4272  } else {
4273  cmd += "-U ";
4274  cmd += cusr;
4275  cmd += " -u ";
4276  cmd += cusr;
4277  cmd += " -f";
4278  busr = 1;
4279  }
4280  cmd += " | grep proofserv 2>/dev/null";
4281 
4282  // Our parent ID as a string
4283  char cpid[10];
4284  snprintf(cpid, 10, "%d", getpid());
4285 
4286  // Run it ...
4287  XrdOucString pids = ":";
4288  FILE *fp = popen(cmd.c_str(), "r");
4289  if (fp != 0) {
4290  char line[2048] = { 0 };
4291  while (fgets(line, sizeof(line), fp)) {
4292  // Parse line: make sure that we are the parent
4293  char *px = strstr(line, "xpd");
4294  if (!px)
4295  // Not xpd: old proofd ?
4296  continue;
4297  char *pi = strstr(px+3, cpid);
4298  if (!pi) {
4299  // Not started by us: check if the parent is still running
4300  pi = px + 3;
4301  int ppid = (int) XrdProofdAux::GetLong(pi);
4302  TRACE(HDBG, "found alternative parent ID: "<< ppid);
4303  // If still running then skip
4304  if (XrdProofdAux::VerifyProcessByID(ppid, fParentExecs.c_str()))
4305  continue;
4306  }
4307  // Get pid now
4308  int from = 0;
4309  if (busr)
4310  from += strlen(cusr);
4311  int pid = (int) XrdProofdAux::GetLong(&line[from]);
4312  bool muok = 1;
4313  if (fMgr->MultiUser() && !all) {
4314  // We need to check the user name: we may be the owner of somebody
4315  // else process; if no session is attached, we kill it
4316  muok = 0;
4318  if (!srv || (srv && !strcmp(usr, srv->Client())))
4319  muok = 1;
4320  }
4321  if (muok)
4322  // Kill it
4323  if (XrdProofdAux::KillProcess(pid, 1, ui, fMgr->ChangeOwn()) == 0)
4324  nk++;
4325  }
4326  pclose(fp);
4327  } else {
4328  // Error executing the command
4329  return -1;
4330  }
4331 #endif
4332 
4333  // Done
4334  return nk;
4335 }
4336 
4337 ////////////////////////////////////////////////////////////////////////////////
4338 /// Set user ownerships on some critical files or directories.
4339 /// Return 0 on success, -1 if enything goes wrong.
4340 
4342  const char *ord, const char *stag)
4343 {
4344  XPDLOC(SMGR, "ProofServMgr::SetUserOwnerships")
4345 
4346  TRACE(REQ, "enter");
4347 
4348  // If applicable, make sure that the private dataset dir for this user exists
4349  // and has the right permissions
4350  if (fMgr->DataSetSrcs()->size() > 0) {
4351  XrdProofUI ui;
4353  std::list<XrdProofdDSInfo *>::iterator ii;
4354  for (ii = fMgr->DataSetSrcs()->begin(); ii != fMgr->DataSetSrcs()->end(); ii++) {
4355  TRACE(ALL, "Checking dataset source: url:"<<(*ii)->fUrl<<", local:"
4356  <<(*ii)->fLocal<<", rw:"<<(*ii)->fRW);
4357  if ((*ii)->fLocal && (*ii)->fRW) {
4358  XrdOucString d;
4359  XPDFORM(d, "%s/%s", ((*ii)->fUrl).c_str(), p->Client()->UI().fGroup.c_str());
4360  if (XrdProofdAux::AssertDir(d.c_str(), ui, fMgr->ChangeOwn()) == 0) {
4361  if (XrdProofdAux::ChangeMod(d.c_str(), 0777) == 0) {
4362  XPDFORM(d, "%s/%s/%s", ((*ii)->fUrl).c_str(), p->Client()->UI().fGroup.c_str(),
4363  p->Client()->UI().fUser.c_str());
4364  if (XrdProofdAux::AssertDir(d.c_str(), p->Client()->UI(), fMgr->ChangeOwn()) == 0) {
4365  if (XrdProofdAux::ChangeMod(d.c_str(), 0755) != 0) {
4366  TRACE(XERR, "problems setting permissions 0755 on: "<<d);
4367  }
4368  } else {
4369  TRACE(XERR, "problems asserting: "<<d);
4370  }
4371  } else {
4372  TRACE(XERR, "problems setting permissions 0777 on: "<<d);
4373  }
4374  } else {
4375  TRACE(XERR, "problems asserting: "<<d);
4376  }
4377  }
4378  }
4379  }
4380 
4381  // If applicable, make sure that the private data dir for this user exists
4382  // and has the right permissions
4383  if (fMgr->DataDir() && strlen(fMgr->DataDir()) > 0 &&
4384  fMgr->DataDirOpts() && strlen(fMgr->DataDirOpts()) > 0 && ord && stag) {
4385  XrdProofUI ui;
4387  XrdOucString dgr, dus[3];
4388  XPDFORM(dgr, "%s/%s", fMgr->DataDir(), p->Client()->UI().fGroup.c_str());
4389  if (XrdProofdAux::AssertDir(dgr.c_str(), ui, fMgr->ChangeOwn()) == 0) {
4390  if (XrdProofdAux::ChangeMod(dgr.c_str(), 0777) == 0) {
4391  unsigned int mode = 0755;
4392  if (strchr(fMgr->DataDirOpts(), 'g')) mode = 0775;
4393  if (strchr(fMgr->DataDirOpts(), 'a') || strchr(fMgr->DataDirOpts(), 'o')) mode = 0777;
4394  XPDFORM(dus[0], "%s/%s", dgr.c_str(), p->Client()->UI().fUser.c_str());
4395  XPDFORM(dus[1], "%s/%s", dus[0].c_str(), ord);
4396  XPDFORM(dus[2], "%s/%s", dus[1].c_str(), stag);
4397  for (int i = 0; i < 3; i++) {
4398  if (XrdProofdAux::AssertDir(dus[i].c_str(), p->Client()->UI(), fMgr->ChangeOwn()) == 0) {
4399  if (XrdProofdAux::ChangeMod(dus[i].c_str(), mode) != 0) {
4400  std::ios_base::fmtflags oflags = std::cerr.flags();
4401  TRACE(XERR, "problems setting permissions "<< oct << mode<<" on: "<<dus[i]);
4402  std::cerr.flags(oflags);
4403  }
4404  } else {
4405  TRACE(XERR, "problems asserting: "<<dus[i]);
4406  break;
4407  }
4408  }
4409  } else {
4410  TRACE(XERR, "problems setting permissions 0777 on: "<<dgr);
4411  }
4412  } else {
4413  TRACE(XERR, "problems asserting: "<<dgr);
4414  }
4415  }
4416 
4417  if (fMgr->ChangeOwn()) {
4418  // Change ownership of '.creds'
4419  XrdOucString creds(p->Client()->Sandbox()->Dir());
4420  creds += "/.creds";
4421  if (XrdProofdAux::ChangeOwn(creds.c_str(), p->Client()->UI()) != 0) {
4422  TRACE(XERR, "can't change ownership of "<<creds);
4423  return -1;
4424  }
4425  }
4426 
4427  // We are done
4428  TRACE(REQ, "done");
4429  return 0;
4430 }
4431 
4432 ////////////////////////////////////////////////////////////////////////////////
4433 /// Set user environment: set effective user and group ID of the process
4434 /// to the ones of the owner of this protocol instnace and change working
4435 /// dir to the sandbox.
4436 /// Return 0 on success, -1 if enything goes wrong.
4437 
4439 {
4440  XPDLOC(SMGR, "ProofServMgr::SetUserEnvironment")
4441 
4442  TRACE(REQ, "enter");
4443 
4445  p->Client()->UI(), fMgr->ChangeOwn()) != 0) {
4446  TRACE(XERR, "couldn't change directory to "<< p->Client()->Sandbox()->Dir());
4447  return -1;
4448  }
4449 
4450  size_t len = 0;
4451  // set HOME env
4452  len = 8 + strlen(p->Client()->Sandbox()->Dir());
4453  char *h = new char[len];
4454  snprintf(h, len, "HOME=%s", p->Client()->Sandbox()->Dir());
4455  putenv(h);
4456  TRACE(DBG, "set "<<h);
4457 
4458  // set USER env
4459  len = 8 + strlen(p->Client()->User());
4460  char *u = new char[len];
4461  snprintf(u, len, "USER=%s", p->Client()->User());
4462  putenv(u);
4463  TRACE(DBG, "set "<<u);
4464 
4465  // Set access control list from /etc/initgroup
4466  // (super-user privileges required)
4467  TRACE(DBG, "setting ACLs");
4468  if (fMgr->ChangeOwn() && (int) geteuid() != p->Client()->UI().fUid) {
4469 
4470  XrdSysPrivGuard pGuard((uid_t)0, (gid_t)0);
4471  if (XpdBadPGuard(pGuard, p->Client()->UI().fUid)) {
4472  TRACE(XERR, "could not get privileges");
4473  return -1;
4474  }
4475 
4476  initgroups(p->Client()->UI().fUser.c_str(), p->Client()->UI().fGid);
4477  }
4478 
4479  if (fMgr->ChangeOwn()) {
4480  // acquire permanently target user privileges
4481  TRACE(DBG, "acquiring target user identity: "<<(uid_t)p->Client()->UI().fUid<<
4482  ", "<<(gid_t)p->Client()->UI().fGid);
4483  if (XrdSysPriv::ChangePerm((uid_t)p->Client()->UI().fUid,
4484  (gid_t)p->Client()->UI().fGid) != 0) {
4485  TRACE(XERR, "can't acquire "<< p->Client()->UI().fUser <<" identity");
4486  return -1;
4487  }
4488  }
4489 
4490  // We are done
4491  TRACE(REQ, "done");
4492  return 0;
4493 }
4494 
4495 ////////////////////////////////////////////////////////////////////////////////
4496 /// Return active session with process ID pid, if any.
4497 
4499 {
4500  XrdOucString key; key += pid;
4501  return fSessions.Find(key.c_str());
4502 }
4503 
4504 ////////////////////////////////////////////////////////////////////////////////
4505 /// Run thorugh entries to broadcast the relevant priority
4506 
4507 static int BroadcastPriority(const char *, XrdProofdProofServ *ps, void *s)
4508 {
4509  XPDLOC(SMGR, "BroadcastPriority")
4510 
4511  XpdBroadcastPriority_t *bp = (XpdBroadcastPriority_t *)s;
4512 
4513  int nb = *(bp->fNBroadcast);
4514 
4515  XrdOucString emsg;
4516  if (ps) {
4517  if (ps->IsValid() && (ps->Status() == kXPD_running) &&
4518  !(ps->SrvType() == kXPD_Master)) {
4519  XrdProofGroup *g = (ps->Group() && bp->fGroupMgr)
4520  ? bp->fGroupMgr->GetGroup(ps->Group()) : 0;
4521  TRACE(DBG, "group: "<< g<<", client: "<<ps->Client());
4522  if (g && g->Active() > 0) {
4523  TRACE(DBG, "priority: "<< g->Priority()<<" active: "<<g->Active());
4524  int prio = (int) (g->Priority() * 100);
4525  ps->BroadcastPriority(prio);
4526  nb++;
4527  }
4528  }
4529  // Go to next
4530  return 0;
4531  } else {
4532  emsg = "input entry undefined";
4533  }
4534 
4535  // Some problem
4536  TRACE(XERR,"protocol error: "<<emsg);
4537  return 1;
4538 }
4539 
4540 ////////////////////////////////////////////////////////////////////////////////
4541 /// Broadcast cluster info to the active sessions
4542 
4544 {
4545  XPDLOC(SMGR, "ProofServMgr::BroadcastClusterInfo")
4546 
4547  TRACE(REQ, "enter");
4548 
4549  int tot = 0, act = 0;
4550  std::list<XrdProofdProofServ *>::iterator si = fActiveSessions.begin();
4551  while (si != fActiveSessions.end()) {
4552  if ((*si)->SrvType() != kXPD_Worker) {
4553  tot++;
4554  if ((*si)->Status() == kXPD_running) act++;
4555  }
4556  si++;
4557  }
4558  if (tot > 0) {
4559  XPDPRT("tot: "<<tot<<", act: "<<act);
4560  // Now propagate to master or sub-masters
4561  si = fActiveSessions.begin();
4562  while (si != fActiveSessions.end()) {
4563  if ((*si)->Status() == kXPD_running &&
4564  (*si)->SrvType() != kXPD_Worker) (*si)->SendClusterInfo(tot, act);
4565  si++;
4566  }
4567  } else {
4568  TRACE(DBG, "No master or submaster controlled by this manager");
4569  }
4570 }
4571 
4572 ////////////////////////////////////////////////////////////////////////////////
4573 /// Broadcast priorities to the active sessions.
4574 /// Returns the number of sessions contacted.
4575 
4577 {
4578  XPDLOC(SMGR, "ProofServMgr::BroadcastPriorities")
4579 
4580  TRACE(REQ, "enter");
4581 
4582  int nb = 0;
4583  XpdBroadcastPriority_t bp = { (fMgr ? fMgr->GroupsMgr() : 0), &nb };
4584  fSessions.Apply(BroadcastPriority, (void *)&bp);
4585  // Done
4586  return nb;
4587 }
4588 
4589 ////////////////////////////////////////////////////////////////////////////////
4590 /// Return true if in reconnection state, i.e. during
4591 /// that period during which clients are expected to reconnect.
4592 /// Return false if the session is fully effective
4593 
4595 {
4596  int rect = -1;
4597  if (fReconnectTime >= 0) {
4598  rect = time(0) - fReconnectTime;
4599  if (rect < fReconnectTimeOut)
4600  return true;
4601  }
4602  // Not reconnecting
4603  return false;
4604 }
4605 
4606 ////////////////////////////////////////////////////////////////////////////////
4607 /// Change reconnecting status
4608 ///
4609 
4611 {
4613 
4614  if (on) {
4615  fReconnectTime = time(0);
4616  } else {
4617  fReconnectTime = -1;
4618  }
4619 }
4620 
4621 ////////////////////////////////////////////////////////////////////////////////
4622 /// Check destroyed status
4623 ///
4624 
4626 {
4628 
4629  bool alive = true;
4630  int now = time(0);
4631  std::map<XrdProofdProtocol*,int>::iterator iter = fDestroyTimes.begin();
4632  while (iter != fDestroyTimes.end()) {
4633  int rect = now - iter->second;
4634  if (rect < fReconnectTimeOut) {
4635  if (p == iter->first) alive = false;
4636  } else {
4637  fDestroyTimes.erase(iter);
4638  }
4639  iter++;
4640  }
4641 
4642  return alive;
4643 }
4644 
4645 ////////////////////////////////////////////////////////////////////////////////
4646 /// Run through entries to reset the disconnecting client slots
4647 
4648 static int FreeClientID(const char *, XrdProofdProofServ *ps, void *s)
4649 {
4650  XPDLOC(SMGR, "FreeClientID")
4651 
4652  int pid = *((int *)s);
4653 
4654  if (ps) {
4655  ps->FreeClientID(pid);
4656  // Go to next
4657  return 0;
4658  }
4659 
4660  // Some problem
4661  TRACE(XERR, "protocol error: undefined session!");
4662  return 1;
4663 }
4664 
4665 ////////////////////////////////////////////////////////////////////////////////
4666 /// Change reconnecting status
4667 ///
4668 
4670 {
4672 
4673  fSessions.Apply(FreeClientID, (void *)&pid);
4674 }
4675 
4676 ////////////////////////////////////////////////////////////////////////////////
4677 /// Run thorugh entries to count top-masters
4678 
4679 static int CountTopMasters(const char *, XrdProofdProofServ *ps, void *s)
4680 {
4681  XPDLOC(SMGR, "CountTopMasters")
4682 
4683  int *ntm = (int *)s;
4684 
4685  XrdOucString emsg;
4686  if (ps) {
4687  if (ps->SrvType() == kXPD_TopMaster) (*ntm)++;
4688  // Go to next
4689  return 0;
4690  } else {
4691  emsg = "input entry undefined";
4692  }
4693 
4694  // Some problem
4695  TRACE(XERR,"protocol error: "<<emsg);
4696  return 1;
4697 }
4698 
4699 ////////////////////////////////////////////////////////////////////////////////
4700 /// Return the number of current sessions (top masters)
4701 
4703 {
4704  XPDLOC(SMGR, "ProofServMgr::CurrentSessions")
4705 
4706  TRACE(REQ, "enter");
4707 
4709  if (recalculate) {
4710  fCurrentSessions = 0;
4711  fSessions.Apply(CountTopMasters, (void *)&fCurrentSessions);
4712  }
4713 
4714  // Done
4715  return fCurrentSessions;
4716 }
4717 
4718 ////////////////////////////////////////////////////////////////////////////////
4719 /// Resolve some keywords in 's'
4720 /// <logfileroot>, <user>, <rootsys>
4721 
4723 {
4724  if (!in) return;
4725 
4726  bool isWorker = 0;
4727  if (in->fPS->SrvType() == kXPD_Worker) isWorker = 1;
4728 
4729  // Log file
4730  if (!isWorker && s.find("<logfilemst>") != STR_NPOS) {
4731  XrdOucString lfr(in->fLogFile);
4732  if (lfr.endswith(".log")) lfr.erase(lfr.rfind(".log"));
4733  s.replace("<logfilemst>", lfr);
4734  } else if (isWorker && s.find("<logfilewrk>") != STR_NPOS) {
4735  XrdOucString lfr(in->fLogFile);
4736  if (lfr.endswith(".log")) lfr.erase(lfr.rfind(".log"));
4737  s.replace("<logfilewrk>", lfr);
4738  }
4739 
4740  // user
4741  if (getenv("USER") && s.find("<user>") != STR_NPOS) {
4742  XrdOucString usr(getenv("USER"));
4743  s.replace("<user>", usr);
4744  }
4745 
4746  // rootsys
4747  if (getenv("ROOTSYS") && s.find("<rootsys>") != STR_NPOS) {
4748  XrdOucString rootsys(getenv("ROOTSYS"));
4749  s.replace("<rootsys>", rootsys);
4750  }
4751 }
4752 
4753 //
4754 // Auxilliary class to handle session pid files
4755 //
4756 
4757 ////////////////////////////////////////////////////////////////////////////////
4758 /// Construct from 'c' and 's'
4759 
4761 {
4762  fLastAccess = 0;
4763 
4764  // Fill from the client instance
4765  fUser = c ? c->User() : "";
4766  fGroup = c ? c->Group() : "";
4767 
4768  // Fill from the server instance
4769  fPid = s ? s->SrvPID() : -1;
4770  fID = s ? s->ID() : -1;
4771  fSrvType = s ? s->SrvType() : -1;
4772  fPLiteNWrks = s ? s->PLiteNWrks() : -1;
4773  fStatus = s ? s->Status() : kXPD_unknown;
4774  fOrdinal = s ? s->Ordinal() : "";
4775  fTag = s ? s->Tag() : "";
4776  fAlias = s ? s->Alias() : "";
4777  fLogFile = s ? s->Fileout() : "";
4778  fROOTTag = (s && s->ROOT())? s->ROOT()->Tag() : "";
4779  fSrvProtVers = (s && s->ROOT()) ? s->ROOT()->SrvProtVers() : -1;
4780  fUserEnvs = s ? s->UserEnvs() : "";
4781  fAdminPath = s ? s->AdminPath() : "";
4782  fUnixPath = s ? s->UNIXSockPath() : "";
4783 }
4784 
4785 ////////////////////////////////////////////////////////////////////////////////
4786 /// Fill 's' fields using the stored info
4787 
4789 {
4790  XPDLOC(SMGR, "SessionInfo::FillProofServ")
4791 
4792  s.SetClient(fUser.c_str());
4793  s.SetGroup(fGroup.c_str());
4794  if (fPid > 0)
4795  s.SetSrvPID(fPid);
4796  if (fID >= 0)
4797  s.SetID(fID);
4798  s.SetSrvType(fSrvType);
4799  s.SetPLiteNWrks(fPLiteNWrks);
4800  s.SetStatus(fStatus);
4801  s.SetOrdinal(fOrdinal.c_str());
4802  s.SetTag(fTag.c_str());
4803  s.SetAlias(fAlias.c_str());
4804  s.SetFileout(fLogFile.c_str());
4805  if (rmgr) {
4806  if (rmgr->GetVersion(fROOTTag.c_str())) {
4807  s.SetROOT(rmgr->GetVersion(fROOTTag.c_str()));
4808  } else {
4809  TRACE(ALL, "ROOT version '"<< fROOTTag <<
4810  "' not availabe anymore: setting the default");
4811  s.SetROOT(rmgr->DefaultVersion());
4812  }
4813  }
4814  s.SetUserEnvs(fUserEnvs.c_str());
4815  s.SetAdminPath(fAdminPath.c_str(), 0, 0);
4816  s.SetUNIXSockPath(fUnixPath.c_str());
4817 }
4818 
4819 ////////////////////////////////////////////////////////////////////////////////
4820 /// Save content to 'file'
4821 
4823 {
4824  XPDLOC(SMGR, "SessionInfo::SaveToFile")
4825 
4826  // Check inputs
4827  if (!file || strlen(file) <= 0) {
4828  TRACE(XERR,"invalid input: "<< (file ? file : "<nul>"));
4829  return -1;
4830  }
4831  TRACE(HDBG,"session saved to file: "<<file);
4832 
4833  // Create the file
4834  FILE *fpid = fopen(file, "w");
4835  if (fpid) {
4836  fprintf(fpid, "%s %s\n", fUser.c_str(), fGroup.c_str());
4837  fprintf(fpid, "%s\n", fUnixPath.c_str());
4838  fprintf(fpid, "%d %d %d %d\n", fPid, fID, fSrvType, fPLiteNWrks);
4839  fprintf(fpid, "%s %s %s\n", fOrdinal.c_str(), fTag.c_str(), fAlias.c_str());
4840  fprintf(fpid, "%s\n", fLogFile.c_str());
4841  fprintf(fpid, "%d %s\n", fSrvProtVers, fROOTTag.c_str());
4842  if (fUserEnvs.length() > 0)
4843  fprintf(fpid, "\n%s", fUserEnvs.c_str());
4844  fclose(fpid);
4845 
4846  // Make it writable by anyone (to allow the corresponding proofserv
4847  // to touch it for the asynchronous ping request)
4848  if (chmod(file, 0666) != 0) {
4849  TRACE(XERR, "could not change mode to 0666 on file "<<
4850  file<<"; error: "<<errno);
4851  }
4852 
4853  return 0;
4854  }
4855 
4856  TRACE(XERR,"session pid file cannot be (re-)created: "<<
4857  file<<"; error: "<<errno);
4858  return -1;
4859 }
4860 
4861 ////////////////////////////////////////////////////////////////////////////////
4862 /// Reset the content
4863 
4865 {
4866  fLastAccess = 0;
4867  fUser = "";
4868  fGroup = "";
4869  fAdminPath = "";
4870  fUnixPath = "";
4871  fPid = -1;
4872  fStatus = kXPD_unknown;
4873  fID = -1;
4874  fSrvType = -1;
4875  fPLiteNWrks = -1;
4876  fOrdinal = "";
4877  fTag = "";
4878  fAlias = "";
4879  fLogFile = "";
4880  fROOTTag = "";
4881  fSrvProtVers = -1;
4882  fUserEnvs = "";
4883 }
4884 
4885 ////////////////////////////////////////////////////////////////////////////////
4886 /// Read content from 'file'
4887 
4889 {
4890  XPDLOC(SMGR, "SessionInfo::ReadFromFile")
4891 
4892  Reset();
4893 
4894  // Check inputs
4895  if (!file || strlen(file) <= 0) {
4896  TRACE(XERR,"invalid input: "<<(file ? file : "<nul>"));
4897  return -1;
4898  }
4899 
4900  // Open the session file
4901  FILE *fpid = fopen(file,"r");
4902  if (fpid) {
4903  char line[4096];
4904  XrdOucString sline, t;
4905  int from = 0;
4906  if (fgets(line, sizeof(line), fpid)) {
4907  if (line[strlen(line)-1] == '\n') line[strlen(line)-1] = '\0';
4908  sline = line;
4909  if ((from = sline.tokenize(fUser, from, ' ')) == -1)
4910  TRACE(XERR,"warning: fUser: corrupted line? "<<line<<" (file: "<<file<<")");
4911  if ((from = sline.tokenize(fGroup, from, ' ')) == -1)
4912  TRACE(XERR,"warning: fGroup: corrupted line? "<<line<<" (file: "<<file<<")");
4913  }
4914  if (fgets(line, sizeof(line), fpid)) {
4915  if (line[strlen(line)-1] == '\n') line[strlen(line)-1] = '\0';
4916  fUnixPath = line;
4917  }
4918  if (fgets(line, sizeof(line), fpid)) {
4919  if (line[strlen(line)-1] == '\n') line[strlen(line)-1] = '\0';
4920  sline = line;
4921  from = 0;
4922  if ((from = sline.tokenize(t, from, ' ')) == -1)
4923  TRACE(XERR,"warning: fPid: corrupted line? "<<line<<" (file: "<<file<<")");
4924  fPid = t.atoi();
4925  if ((from = sline.tokenize(t, from, ' ')) == -1)
4926  TRACE(XERR,"warning: fID: corrupted line? "<<line<<" (file: "<<file<<")");
4927  fID = t.atoi();
4928  if ((from = sline.tokenize(t, from, ' ')) == -1)
4929  TRACE(XERR,"warning: fSrvType: corrupted line? "<<line<<" (file: "<<file<<")");
4930  fSrvType = t.atoi();
4931  }
4932  if (fgets(line, sizeof(line), fpid)) {
4933  if (line[strlen(line)-1] == '\n') line[strlen(line)-1] = '\0';
4934  sline = line;
4935  from = 0;
4936  if ((from = sline.tokenize(fOrdinal, from, ' ')) == -1)
4937  TRACE(XERR,"warning: fOrdinal: corrupted line? "<<line<<" (file: "<<file<<")");
4938  if ((from = sline.tokenize(fTag, from, ' ')) == -1)
4939  TRACE(XERR,"warning: fTag: corrupted line? "<<line<<" (file: "<<file<<")");
4940  if ((from = sline.tokenize(fAlias, from, ' ')) == -1)
4941  TRACE(HDBG,"fAlias undefined "<<line);
4942  }
4943  if (fgets(line, sizeof(line), fpid)) {
4944  if (line[strlen(line)-1] == '\n') line[strlen(line)-1] = '\0';
4945  fLogFile = line;
4946  }
4947  if (fgets(line, sizeof(line), fpid)) {
4948  if (line[strlen(line)-1] == '\n') line[strlen(line)-1] = '\0';
4949  sline = line;
4950  from = 0;
4951  if ((from = sline.tokenize(t, from, ' ')) == -1)
4952  TRACE(XERR,"warning: fSrvProtVers: corrupted line? "<<line<<" (file: "<<file<<")");
4953  fSrvProtVers = t.atoi();
4954  if ((from = sline.tokenize(fROOTTag, from, ' ')) == -1)
4955  TRACE(XERR,"warning: fROOTTag: corrupted line? "<<line<<" (file: "<<file<<")");
4956  }
4957  // All the remaining into fUserEnvs
4958  fUserEnvs = "";
4959  off_t lnow = lseek(fileno(fpid), (off_t) 0, SEEK_CUR);
4960  off_t ltot = lseek(fileno(fpid), (off_t) 0, SEEK_END);
4961  int left = (int)(ltot - lnow);
4962  int len = -1;
4963  do {
4964  int wanted = (left > 4095) ? 4095 : left;
4965  while ((len = read(fileno(fpid), line, wanted)) < 0 &&
4966  errno == EINTR)
4967  errno = 0;
4968  if (len < 0 || len < wanted) {
4969  break;
4970  } else {
4971  line[len] = '\0';
4972  fUserEnvs += line;
4973  }
4974  // Update counters
4975  left -= len;
4976  } while (len > 0 && left > 0);
4977  // Done
4978  fclose(fpid);
4979  // The file name is the admin path
4980  fAdminPath = file;
4981  // Fill access time
4982  struct stat st;
4983  if (!stat(file, &st))
4984  fLastAccess = st.st_atime;
4985  } else {
4986  TRACE(XERR,"session file cannot be open: "<< file<<"; error: "<<errno);
4987  return -1;
4988  }
4989 
4990  // Read the last status now if the session is active
4991  XrdOucString fs(file);
4992  fs += ".status";
4993  fpid = fopen(fs.c_str(),"r");
4994  if (fpid) {
4995  char line[64];
4996  if (fgets(line, sizeof(line), fpid)) {
4997  if (line[strlen(line)-1] == '\n') line[strlen(line)-1] = 0;
4998  fStatus = atoi(line);
4999  }
5000  // Done
5001  fclose(fpid);
5002  } else {
5003  TRACE(DBG,"no session status file for: "<< fs<<"; session was probably terminated");
5004  }
5005 
5006  // Done
5007  return 0;
5008 }
5009 
5010 ////////////////////////////////////////////////////////////////////////////////
5011 /// Check if this env applies to 'usr', 'grp, 'ver'.
5012 /// Returns -1 if it does not match, >=0 if it matches. The value is a linear
5013 /// combination of matching lengths for user and group, with a weight of 1000 for
5014 /// the users one, so that an exact user match will always win.
5015 
5016 int XpdEnv::Matches(const char *usr, const char *grp, int ver)
5017 {
5018  XPDLOC(SMGR, "XpdEnv::Matches")
5019 
5020  int nmtc = -1;
5021  // Check the user
5022  if (fUsers.length() > 0) {
5023  XrdOucString u(usr);
5024  if ((nmtc = u.matches(fUsers.c_str())) == 0) return -1;
5025  } else {
5026  nmtc = strlen(usr);
5027  }
5028  nmtc += 1000; // Weigth of user name match
5029  // Check the group
5030  int nmtcg = -1;
5031  if (fGroups.length() > 0) {
5032  XrdOucString g(grp);
5033  if ((nmtcg = g.matches(fGroups.c_str())) == 0) return -1;
5034  } else {
5035  nmtcg = strlen(grp);
5036  }
5037  nmtc += nmtcg;
5038 
5039  TRACE(HDBG, fEnv <<", u:"<<usr<<", g:"<<grp<<" --> nmtc: "<<nmtc);
5040 
5041  // Check the version code
5042  TRACE(HDBG, fEnv <<", ver:"<<ver);
5043  if (fVerMin > 0 && ver < fVerMin) return -1;
5044  if (fVerMax > 0 && ver > fVerMax) return -1;
5045 
5046  // If we are here then it matches
5047  return nmtc;
5048 }
5049 
5050 ////////////////////////////////////////////////////////////////////////////////
5051 /// Transform version number ver (format patch + 100*minor + 10000*maj, e.g. 52706)
5052 /// If 'hex' is true, the components are decoded as hex numbers
5053 
5054 int XpdEnv::ToVersCode(int ver, bool hex)
5055 {
5056  int maj = -1, min = -1, ptc = -1, xv = ver;
5057  if (hex) {
5058  maj = xv / 65536;
5059  xv -= maj * 65536;
5060  min = xv / 256;
5061  ptc = xv - min * 256;
5062  } else {
5063  maj = xv / 10000;
5064  xv -= maj * 10000;
5065  min = xv / 100;
5066  ptc = xv - min * 100;
5067  }
5068  // Get the version code now
5069  int vc = (maj << 16) + (min << 8) + ptc;
5070  return vc;
5071 }
5072 
5073 ////////////////////////////////////////////////////////////////////////////////
5074 /// Print the content of this env
5075 
5076 void XpdEnv::Print(const char *what)
5077 {
5078  XPDLOC(SMGR, what)
5079 
5080  XrdOucString vmi("-1"), vmx("-1");
5081  if (fVerMin > 0) {
5082  int maj = (fVerMin >> 16);
5083  int min = ((fVerMin - maj * 65536) >> 8);
5084  int ptc = fVerMin - maj * 65536 - min * 256;
5085  XPDFORM(vmi, "%d%d%d", maj, min, ptc);
5086  }
5087  if (fVerMax > 0) {
5088  int maj = (fVerMax >> 16);
5089  int min = ((fVerMax - maj * 65536) >> 8);
5090  int ptc = fVerMax - maj * 65536 - min * 256;
5091  XPDFORM(vmx, "%d%d%d", maj, min, ptc);
5092  }
5093  XrdOucString u("allusers"), g("allgroups");
5094  if (fUsers.length() > 0) u = fUsers;
5095  if (fGroups.length() > 0) u = fGroups;
5096 
5097  TRACE(ALL, "'"<<fEnv<<"' {"<<u<<"|"<<g<<
5098  "} svn:["<<fSvnMin<<","<<fSvnMax<<"] vers:["<<vmi<<","<<vmx<<"]");
5099 }
int CreateSockPath(XrdProofdProofServ *xps, XrdProofdProtocol *p, unsigned int seq, XrdOucString &emsg)
Create the socket path for the starting session Return 0 on success, -1 on error (error message in 'e...
int FreeClientID(int pid)
Free instance corresponding to protocol connecting process 'pid'.
bool ChangeOwn() const
double read(const std::string &file_name)
reading
void SetParent(XrdClientID *cid)
int SetupProtocol(XrdNetPeer &peerpsrv, XrdProofdProofServ *xps, XrdOucString &e)
Setup the protocol object serving the peer described by 'peerpsrv'.
static int BroadcastPriority(const char *, XrdProofdProofServ *ps, void *s)
Run thorugh entries to broadcast the relevant priority.
void Reset(const char *n, const char *env, const char *usr=0, const char *grp=0, int smi=-1, int smx=-1, int vmi=-1, int vmx=-1)
int BroadcastPriorities()
Broadcast priorities to the active sessions.
XrdOucHash< XrdProofdProofServ > fSessions
static Vc_ALWAYS_INLINE int_v min(const int_v &x, const int_v &y)
Definition: vector.h:433
void SetReconnectTime(bool on=1)
Change reconnecting status.
XrdProofdClientMgr * ClientMgr() const
int Poll(int to=-1)
Poll over the read pipe for to secs; return whatever poll returns.
int CurrentSessions(bool recalculate=0)
Return the number of current sessions (top masters)
#define XPD_LIBPATH
static int ToVersCode(int ver, bool hex=0)
Transform version number ver (format patch + 100*minor + 10000*maj, e.g.
XrdROOT * ROOT() const
const char * DataDirUrlOpts() const
#define kXPD_TopMaster
int VersionCode() const
Definition: XrdROOT.h:84
unsigned int hex
Definition: math.cpp:442
#define TRACING(x)
int Process(XrdProofdProtocol *p)
Process manager request.
#define XPROOFD_VERSBIN
const char * Dir() const
const char * PoolURL() const
void Print(const char *what)
Print the content of this env.
TLine * line
const double pi
static int GetUserInfo(const char *usr, XrdProofUI &ui)
Get information about user 'usr' in a thread safe way.
XrdProtocol * Match(XrdLink *lp)
Check whether the request matches this protocol.
int CleanupProofServ(bool all=0, const char *usr=0)
Cleanup (kill) all 'proofserv' processes from the process table.
return c
bool IsClientRecovering(const char *usr, const char *grp, int &deadline)
Returns true (an the recovering deadline) if the client has sessions in recovering state; returns fal...
void ParseCreateBuffer(XrdProofdProtocol *p, XrdProofdProofServ *xps, XrdOucString &tag, XrdOucString &ord, XrdOucString &cffile, XrdOucString &uenvs, int &intwait)
Extract relevant quantities from the buffer received during a create request.
void SetAlias(const char *a)
#define assert(cond)
Definition: unittest.h:542
short int ID() const
int SetUserOwnerships(XrdProofdProtocol *p, const char *ord, const char *stag)
Set user ownerships on some critical files or directories.
int SetProofServEnv(XrdProofdProtocol *p, void *in)
Set environment for proofserv.
#define PutEnv(x, e)
std::map< XrdProofdProtocol *, int > fDestroyTimes
int DoDirectiveClass(XrdProofdDirective *, char *val, XrdOucStream *cfg, bool rcf)
Generic class directive processor.
TH1 * h
Definition: legend2.C:5
const char * SockPathDir() const
#define XrdSysRecMutex
Definition: XrdSysToOuc.h:18
bool IsSessionSocket(const char *fpid)
Checks is fpid is the path of a session UNIX socket Returns TRUE is yes; cleans the socket if the ses...
int CheckSession(bool oldvers, bool isrec, int shutopt, int shutdel, bool changeown, int &nc)
Calculate the effective number of users on this session nodes and communicate it to the master togeth...
int CreateProofServRootRc(XrdProofdProtocol *p, void *input, const char *rcfn)
Create in 'rcfn' the rootrc file for the proofserv being created return 0 on success, -1 on error.
const char * DataDir() const
kXR_int16 SrvProtVers() const
Definition: XrdROOT.h:82
#define TRACE(Flag, Args)
Definition: TGHtml.h:124
XrdProofGroupMgr * GroupsMgr() const
void UpdateCounter(int t, int n)
void SetSid(unsigned short sid)
kXR_int32 CID() const
int RmSession(const char *fpid)
Remove session file from the terminated sessions area.
XrdProofdProofServ * GetServObj(int id)
Get server at 'id'. If needed, increase the vector size.
int DeleteFromSessions(const char *pid)
Delete from the hash list the session with ID pid.
void Reset()
Reset this instance.
static int FreeClientID(const char *, XrdProofdProofServ *ps, void *s)
Run through entries to reset the disconnecting client slots.
const char * Tag() const
Definition: XrdROOT.h:83
const char * RootdExe() const
int DoDirectiveInt(XrdProofdDirective *, char *val, XrdOucStream *cfg, bool rcf)
Process directive for an integer.
TArc * a
Definition: textangle.C:12
int Port() const
const char * BareLibPath() const
int GetNClients() const
XrdProofUI UI() const
float Priority() const
Definition: XrdProofGroup.h:80
#define kXPD_MasterMaster
XrdClientID * Parent() const
#define XPD_LONGOK(x)
bool MultiUser() const
void ResolveKeywords(XrdOucString &s, ProofServEnv_t *in)
Resolve some keywords in 's' <logfileroot>, <user>, <rootsys>
void SetOrdinal(const char *o)
void SetAdminPath(const char *p)
bool Alive(XrdProofdProtocol *p)
Check destroyed status.
int AddSession(XrdProofdProtocol *p, XrdProofdProofServ *s)
Add new active session.
#define kXPD_ClientMaster
TFile * f
static int ChangePerm(uid_t uid, gid_t gid)
XrdClientID * GetClientID(int cid)
Get instance corresponding to cid.
int Type() const
Definition: XrdProofdAux.h:194
XrdSysRecMutex * Mutex() const
#define XPDPRT(x)
struct ClientRequestHdr header
XrdSysSemWait * ProcessSem()
int CreateUNIXSock(XrdSysError *edest)
Create UNIX socket for internal connections.
int Recv(XpdMsg &msg)
Recv message from the pipe.
const char * UNIXSockPath() const
static int CountTopMasters(const char *, XrdProofdProofServ *ps, void *s)
Run thorugh entries to count top-masters.
XrdROOT * DefaultVersion() const
Definition: XrdROOT.h:118
void * XrdProofdProofServRecover(void *p)
Waiting for session to recover after an abrupt shutdown.
XrdSecCredsSaver_t fCredsSaver
int CreateProofServEnvFile(XrdProofdProtocol *p, void *input, const char *envfn, const char *rcfn)
Create in 'rcfn' the rootrc file for the proofserv being created return 0 on success, -1 on error.
static int GetVersionCode(const char *release)
Translate 'release' into a version code integer following the rules in $ROOTSYS/include/RVersion.h.
Definition: XrdROOT.cxx:275
const char * BinDir() const
Definition: XrdROOT.h:66
void ExtractEnv(char *, XrdOucStream *, XrdOucString &users, XrdOucString &groups, XrdOucString &rcval, XrdOucString &rcnam, int &smi, int &smx, int &vmi, int &vmx, bool &hex)
Extract env information from the stream 'cfg'.
const char * ord
Definition: TXSlave.cxx:46
static int ParsePidPath(const char *path, XrdOucString &before, XrdOucString &after)
Parse a path in the form of "<before>[.<pid>][.<after>]", filling 'rest' and returning 'pid'...
int Destroy(XrdProofdProtocol *p)
Handle a request to shutdown an existing session.
static int SymLink(const char *path, const char *link)
Create a symlink 'link' to 'path' Return 0 in case of success, -1 in case of error.
void SetProtocol(XrdProofdProtocol *p)
void FormFileNameInSessionDir(XrdProofdProtocol *p, XrdProofdProofServ *xps, const char *sessiondir, const char *extension, XrdOucString &outfn)
short int ProofProtocol() const
int CreateAdminPath(XrdProofdProofServ *xps, XrdProofdProtocol *p, int pid, XrdOucString &emsg)
Create the admin path for the starting session Return 0 on success, -1 on error (error message in 'em...
int d
Definition: tornado.py:11
XrdProofSessionInfo(XrdProofdClient *c, XrdProofdProofServ *s)
Construct from 'c' and 's'.
int SetProcessPriority(int pid, const char *usr, int &dp)
Change priority of process pid belonging to user, if needed.
XrdOucString fName
std::map< std::string, std::string >::const_iterator iter
Definition: TAlienJob.cxx:54
std::list< XpdEnv > fProofServEnvs
bool IsReconnecting()
Return true if in reconnection state, i.e.
if(pyself &&pyself!=Py_None)
const char * DataDir() const
Definition: XrdROOT.h:67
tuple np
Definition: multifit.py:30
const char * Client() const
void Close()
If open, close and invalidated the pipe descriptors.
void DeleteUNIXSock()
Delete the current UNIX socket.
XrdProofdClientMgr * fClientMgr
int CheckActiveSessions(bool verify=1)
Go through the active sessions admin path and make sure sessions are alive.
static int Attach(XrdLink *lp)
void SetUNIXSockPath(const char *s)
int TouchSession(const char *fpid, const char *path=0)
Update the access time for the session pid file to the current time.
std::list< XrdProofdProofServ * > fActiveSessions
static int EUidAtStartup()
XrdOucString fUser
Definition: XrdProofdAux.h:40
XrdSysError * fEDest
void DisconnectFromProofServ(int pid)
Change reconnecting status.
void SetGroup(const char *g)
int Matches(const char *usr, const char *grp, int ver=-1)
Check if this env applies to 'usr', 'grp, 'ver'.
XrdProofdProtocol * Protocol() const
const char * Buf() const
Definition: XrdProofdAux.h:185
#define XPDLOC(d, x)
XrdProofSched * ProofSched() const
static const char * what
Definition: stlLoader.cc:6
XrdProofdPipe * Pipe()
std::list< XpdClientSessions * > * fRecoverClients
void SetROOT(XrdROOT *r)
void FillProofServ(XrdProofdProofServ &s, XrdROOTMgr *rmgr)
Fill 's' fields using the stored info.
void RegisterDirectives()
Register directives for configuration.
XrdProofSched * fProofSched
std::list< XrdProofdProofServ * > fProofServs
int Config(bool rcf=0)
Run configuration and parse the entered config directives.
int ConnType() const
const char * NameSpace() const
void SetFileout(const char *f)
TThread * t[5]
Definition: threadsh1.C:13
XrdSrvBuffer * StartMsg() const
int Attach(XrdProofdProtocol *p)
Handle a request to attach to an existing session.
const char * Ordinal() const
XPClientRequest * Request() const
int GetNClients(bool check)
Get the number of connected clients.
std::list< XpdEnv > fProofServRCs
#define kXPD_MasterWorker
static XpdManagerCron_t fManagerCron
ROOT::R::TRInterface & r
Definition: Object.C:4
static const char * ProofRequestTypes(int type)
Translates the proof request type in a human readable string.
static int GetIDFromPath(const char *path, XrdOucString &emsg)
Extract an integer from a file.
const char * Image() const
int ResolveSession(const char *fpid)
Handle a request to recover a session after stop&restart.
XrdOucString fGroup
Definition: XrdProofdAux.h:41
void SetP(XrdProofdProtocol *p)
XrdROOT * GetVersion(const char *tag)
Return pointer to the ROOT version corresponding to 'tag' or 0 if not found.
Definition: XrdROOT.cxx:730
#define XrdSysMutexHelper
Definition: XrdSysToOuc.h:17
static int WriteSessEnvs(const char *, XpdEnv *env, void *s)
Run thorugh entries to broadcast the relevant priority.
struct XPClientProofRequest proof
XrdScheduler * Sched() const
#define XrdSysError
Definition: XpdSysError.h:8
virtual int MaxSessions() const
Definition: XrdProofSched.h:89
void Reset()
Reset the content.
int Recover(XpdClientSessions *cl)
Handle a request to recover a session after stop&restart for a specific client.
const char * AdminPath() const
#define TRACEP(p, act, x)
int CleanClientSessions(const char *usr, int srvtype)
Go through the sessions admin path and clean all sessions belonging to 'usr'.
int MvSession(const char *fpid)
Move session file from the active to the terminated areas.
#define XpdBadPGuard(g, u)
Definition: XrdProofdAux.h:368
bool IsSuperMst() const
XrdSecProtocol * AuthProt() const
const char * Dir() const
Definition: XrdROOT.h:65
TLine * l
Definition: textangle.C:4
int PrepareSessionRecovering()
Go through the active sessions admin path and prepare reconnection of those still alive...
int VerifySession(const char *fpid, int to=-1, const char *path=0)
Check if the session is alive, i.e.
tuple pl
Definition: first.py:10
XrdProofdNetMgr * NetMgr() const
std::list< XrdProofdDSInfo * > * DataSetSrcs()
void Reset(Detail::TBranchProxy *x)
int Active(const char *usr=0)
Return the number of active groups (usr = 0) or the number of active sessions for user 'usr'...
int Detach(XrdProofdProtocol *p)
Handle a request to detach from an existing session.
const char * StageReqRepo() const
void SetID(short int id)
static long int GetLong(char *str)
Extract first integer from string at 'str', if any.
const char * AdminPath() const
void GetTagDirs(int opt, XrdProofdProtocol *p, XrdProofdProofServ *xps, XrdOucString &sesstag, XrdOucString &topsesstag, XrdOucString &sessiondir, XrdOucString &sesswrkdir)
Determine the unique tag and relevant dirs for this session.
#define kXPD_AnyServer
tuple free
Definition: fildir.py:30
void SetTag(const char *t)
int AddSession(const char *tag)
Record entry for new proofserv session tagged 'tag' in the active sessions file (<SandBox>/.sessions).
XrdProofdProofServ * fPS
int BroadcastPriority(int priority)
Broadcast a new group priority value to the worker servers.
const char * UserEnvs() const
const char * extension
Definition: civetweb.c:2467
const char * GetCfgFile() const
int SetAdminPath(const char *a, bool assert, bool setown)
Set the admin path and make sure the file exists.
static int AssertDir(const char *path, XrdProofUI ui, bool changeown)
Make sure that 'path' exists and is owned by the entity described by 'ui'.
XrdProofdSandbox * Sandbox() const
XrdNet * UNIXSock() const
void TerminateSessions(int srvtype, XrdProofdProofServ *ref, const char *msg, XrdProofdPipe *pipe, bool changeown)
Terminate client sessions; IDs of signalled processes are added to sigpid.
#define XPDFORM
Definition: XrdProofdAux.h:381
#define kXPD_Worker
XrdROOT * ROOT() const
XrdProofdProofServMgr * fSessionMgr
static int CheckIf(XrdOucStream *s, const char *h)
Check existence and match condition of an 'if' directive If none (valid) is found, return -1.
int CheckTerminatedSessions()
Go through the terminated sessions admin path and make sure sessions they are gone.
tuple file
Definition: fildir.py:20
int ResolveKeywords(XrdOucString &s, XrdProofdClient *pcl)
Resolve special keywords in 's' for client 'pcl'.
#define DIGIT(x)
Definition: XrdProofdAux.h:349
int DoDirectiveString(XrdProofdDirective *, char *val, XrdOucStream *cfg, bool rcf)
Process directive for a string.
void SendErrLog(const char *errlog, XrdProofdResponse *r)
Send content of errlog upstream asynchronously.
XrdBuffer * Argp() const
int CleanupLostProofServ()
Cleanup (kill) all 'proofserv' processes which lost control from their creator or controller daemon...
XrdOucString fSessionDir
XrdOucString fSessionTag
int SetProofServEnvOld(XrdProofdProtocol *p, void *in)
Set environment for proofserv; old version preparing the environment for proofserv protocol version <...
void dir(char *path=0)
Definition: rootalias.C:30
const char * Alias() const
const char * Host() const
void SetValid(bool valid=1)
void SetUserEnvs(const char *t)
XrdProofdProofServ * PrepareProofServ(XrdProofdProtocol *p, XrdProofdResponse *r, unsigned short &sid)
Allocate and prepare the XrdProofdProofServ object describing this session.
static int ChangeMod(const char *path, unsigned int mode)
Change the permission mode of 'path' to 'mode'.
const char * Group() const
int DoDirectiveShutdown(char *, XrdOucStream *, bool)
Process 'shutdown' directive.
bool IsValid() const
Definition: XrdProofdAux.h:209
#define XPD_SETRESP(p, x)
const char * LocalROOT() const
R__EXTERN C unsigned int sleep(unsigned int seconds)
static int WriteSessRCs(const char *, XpdEnv *erc, void *f)
Run thorugh entries to broadcast the relevant priority.
bool WorkerUsrCfg() const
void FillEnvList(std::list< XpdEnv > *el, const char *nam, const char *val, const char *usrs=0, const char *grps=0, int smi=-1, int smx=-1, int vmi=-1, int vmx=-1, bool hex=0)
Fill env entry(ies) in the relevant list.
const char * Tag() const
XrdProofdPriorityMgr * PriorityMgr() const
Float_t px
Definition: hprod.C:33
const char * Fileout() const
XrdOucString fName
Definition: XrdProofdAux.h:111
int Get(int &i)
Get next token and interpret it as an int.
const char * Export() const
Definition: XrdROOT.h:70
XrdProofdProofServMgr(XrdProofdManager *mgr, XrdProtocol_Config *pi, XrdSysError *e)
Constructor.
int Create(XrdProofdProtocol *p)
Handle a request to create a new session.
const char * EffectiveUser() const
const char * User() const
const char * PrgmSrv() const
Definition: XrdROOT.h:79
static int ChangeToDir(const char *dir, XrdProofUI ui, bool changeown)
Change current directory to 'dir'.
XrdROOTMgr * ROOTMgr() const
void * XrdProofdProofServCron(void *p)
This is an endless loop to check the system periodically or when triggered via a message in a dedicat...
const char * DataDirOpts() const
XrdOucString fTopSessionTag
int DoDirective(XrdProofdDirective *d, char *val, XrdOucStream *cfg, bool rcf)
Update the priorities of the active sessions.
int DoDirectivePutRc(char *, XrdOucStream *, bool)
Process 'putrc' directives.
ClassImp(TSlaveInfo) Int_t TSlaveInfo const TSlaveInfo * si
Used to sort slaveinfos by ordinal.
Definition: TProof.cxx:183
XrdProofdProofServ * GetActiveSession(int pid)
Return active session with process ID pid, if any.
#define kXPD_Master
int ReadFromFile(const char *file)
Read content from 'file'.
XrdProofdClient * GetClient(const char *usr, const char *grp=0, bool create=1)
Handle request for localizing a client instance for {usr, grp} from the list.
static int ChangeOwn(const char *path, XrdProofUI ui)
Change the ownership of 'path' to the entity described by 'ui'.
int Post(int type, const char *msg)
Post message on the pipe.
static int VerifyProcessByID(int pid, const char *pname="proofserv")
Check if a process named 'pname' and process 'pid' is still in the process table. ...
int AcceptPeer(XrdProofdProofServ *xps, int to, XrdOucString &e)
Accept a callback from a starting-up server and setup the related protocol object.
int RecoverActiveSessions()
Accept connections from sessions still alive.
int DoDirectivePutEnv(char *, XrdOucStream *, bool)
Process 'putenv' directives.
XrdOucString fEnv
#define PSMMAXCNTS
const char * CfgFile() const
XrdProofdProofServ * GetServer(int psid)
Get from the vector server instance with ID psid.
static int GetProcesses(const char *pn, std::map< int, XrdOucString > *plist)
Get from the process table list of PIDs for processes named "proofserv' For {linux, sun, macosx} it uses the system info; for other systems it invokes the command shell 'ps ax' via popen.
static void LogEmsgToFile(const char *flog, const char *emsg, const char *pfx=0)
Logs error message 'emsg' to file 'flog' using standard technology.
XrdLink * Link() const
int VerifyProofServ(bool fw)
Check if the associated proofserv process is alive.
XrdProofdProofServ * GetFreeServObj()
Get next free server ID.
virtual int Config(bool rcf=0)
tuple all
Definition: na49view.py:13
bool ReadFile(bool update=true)
Return true if the file has never been read or did change since last reading, false otherwise...
int Send(void)
Auxilliary Send method.
XrdProofdClient * fClient
void SetClient(const char *c)
const char * TMPdir() const
static int KillProcess(int pid, bool forcekill, XrdProofUI ui, bool changeown)
Kill the process 'pid'.
const char * cnt
Definition: TXMLSetup.cxx:75
void Register(const char *dname, XrdProofdDirective *d)
XrdProofdClient * Client() const
int SaveToFile(const char *file)
Save content to 'file'.
const char * LibDir() const
Definition: XrdROOT.h:69
int DoDirectiveProofServMgr(char *, XrdOucStream *, bool)
Process 'proofswrvmgr' directive eg: xpd.proofswrvmgr checkfq:120 termto:100 verifyto:5 recoverto:20...
void BroadcastClusterInfo()
Broadcast cluster info to the active sessions.
int SetUserEnvironment(XrdProofdProtocol *p)
Set user environment: set effective user and group ID of the process to the ones of the owner of this...
const char * Group() const
int ii
Definition: hprod.C:34