ROOT logo
// @(#)root/proof:$Id: TSlave.cxx 25918 2008-10-22 15:00:04Z ganis $
// Author: Fons Rademakers   14/02/97

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TSlave                                                               //
//                                                                      //
// This class describes a PROOF slave server.                           //
// It contains information like the slaves host name, ordinal number,   //
// performance index, socket, etc. Objects of this class can only be    //
// created via TProof member functions.                                 //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include <stdlib.h>

#include "RConfigure.h"
#include "TApplication.h"
#include "TSlave.h"
#include "TSlaveLite.h"
#include "TProof.h"
#include "TSystem.h"
#include "TEnv.h"
#include "TROOT.h"
#include "TUrl.h"
#include "TMessage.h"
#include "TError.h"
#include "TVirtualMutex.h"
#include "TThread.h"
#include "TSocket.h"
#include "TObjString.h"

ClassImp(TSlave)

// Hook for the TXSlave constructor
TSlave_t TSlave::fgTXSlaveHook = 0;

//______________________________________________________________________________
TSlave::TSlave(const char *url, const char *ord, Int_t perf,
               const char *image, TProof *proof, Int_t stype,
               const char *workdir, const char *msd)
  : fImage(image), fProofWorkDir(workdir),
    fWorkDir(workdir), fPort(-1),
    fOrdinal(ord), fPerfIdx(perf),
    fProtocol(0), fSocket(0), fProof(proof),
    fInput(0), fBytesRead(0), fRealTime(0),
    fCpuTime(0), fSlaveType((ESlaveType)stype), fStatus(TSlave::kInvalid),
    fParallel(0), fMsd(msd)
{
   // Create a PROOF slave object. Called via the TProof ctor.
   fName = TUrl(url).GetHostFQDN();
   fPort = TUrl(url).GetPort();

   Init(url, -1, stype);
}

//______________________________________________________________________________
TSlave::TSlave()
{
   // Default constructor used by derived classes

   fPort      = -1;
   fOrdinal   = "-1";
   fPerfIdx   = -1;
   fProof     = 0;
   fSlaveType = kMaster;
   fProtocol  = 0;
   fSocket    = 0;
   fInput     = 0;
   fBytesRead = 0;
   fRealTime  = 0;
   fCpuTime   = 0;
   fStatus    = kInvalid;
   fParallel  = 0;
}

//______________________________________________________________________________
void TSlave::Init(const char *host, Int_t port, Int_t stype)
{
   // Init a PROOF slave object. Called via the TSlave ctor.
   // The Init method is technology specific and is overwritten by derived
   // classes.

   // The url contains information about the server type: make sure
   // it is 'proofd' or alike
   TString proto = fProof->fUrl.GetProtocol();
   proto.Insert(5, 'd');

   TUrl hurl(host);
   hurl.SetProtocol(proto);
   if (port > 0)
      hurl.SetPort(port);

   // Add information about our status (Client or Master)
   TString iam;
   if (fProof->IsMaster() && stype == kSlave) {
      iam = "Master";
      hurl.SetOptions("SM");
   } else if (fProof->IsMaster() && stype == kMaster) {
      iam = "Master";
      hurl.SetOptions("MM");
   } else if (!fProof->IsMaster() && stype == kMaster) {
      iam = "Local Client";
      hurl.SetOptions("MC");
   } else {
      Error("Init","Impossible PROOF <-> SlaveType Configuration Requested");
      R__ASSERT(0);
   }

   // Open authenticated connection to remote PROOF slave server.
   // If a connection was already open (fSocket != 0), re-use it
   // to perform authentication (optimization needed to avoid a double
   // opening in case this is called by TXSlave).
   Int_t wsize = 65536;
   fSocket = TSocket::CreateAuthSocket(hurl.GetUrl(), 0, wsize, fSocket);

   if (!fSocket || !fSocket->IsAuthenticated()) {
      SafeDelete(fSocket);
      return;
   }

   // Remove socket from global TROOT socket list. Only the TProof object,
   // representing all slave sockets, will be added to this list. This will
   // ensure the correct termination of all proof servers in case the
   // root session terminates.
   {
      R__LOCKGUARD2(gROOTMutex);
      gROOT->GetListOfSockets()->Remove(fSocket);
   }

   R__LOCKGUARD2(gProofMutex);

   // Fill some useful info
   fUser              = fSocket->GetSecContext()->GetUser();
   PDB(kGlobal,3) {
      Info("Init","%s: fUser is .... %s", iam.Data(), fUser.Data());
   }

   if (fSocket->GetRemoteProtocol() >= 14 ) {
      TMessage m(kPROOF_SETENV);

      const TList *envs = TProof::GetEnvVars();
      if (envs != 0 ) {
         TIter next(envs);
         for (TObject *o = next(); o != 0; o = next()) {
            TNamed *env = dynamic_cast<TNamed*>(o);
            if (env != 0) {
               TString def = Form("%s=%s", env->GetName(), env->GetTitle());
               const char *p = def.Data();
               m << p;
            }
         }
      }
      fSocket->Send(m);
   } else {
      Info("Init","** NOT ** Sending kPROOF_SETENV RemoteProtocol : %d",
         fSocket->GetRemoteProtocol());
   }

   char buf[512];
   fSocket->Recv(buf, sizeof(buf));
   if (strcmp(buf, "Okay")) {
      Printf("%s", buf);
      SafeDelete(fSocket);
      return;
   }

}

//______________________________________________________________________________
Int_t TSlave::SetupServ(Int_t stype, const char *conffile)
{
   // Init a PROOF slave object. Called via the TSlave ctor.
   // The Init method is technology specific and is overwritten by derived
   // classes.

   // get back startup message of proofserv (we are now talking with
   // the real proofserver and not anymore with the proofd front-end)
   Int_t what;
   char buf[512];
   if (fSocket->Recv(buf, sizeof(buf), what) <= 0) {
      Error("SetupServ", "failed to receive slave startup message");
      SafeDelete(fSocket);
      return -1;
   }

   if (what == kMESS_NOTOK) {
      SafeDelete(fSocket);
      return -1;
   }

   // exchange protocol level between client and master and between
   // master and slave
   if (fSocket->Send(kPROOF_Protocol, kROOTD_PROTOCOL) != 2*sizeof(Int_t)) {
      Error("SetupServ", "failed to send local PROOF protocol");
      SafeDelete(fSocket);
      return -1;
   }

   if (fSocket->Recv(fProtocol, what) != 2*sizeof(Int_t)) {
      Error("SetupServ", "failed to receive remote PROOF protocol");
      SafeDelete(fSocket);
      return -1;
   }

   // protocols less than 4 are incompatible
   if (fProtocol < 4) {
      Error("SetupServ", "incompatible PROOF versions (remote version"
                      " must be >= 4, is %d)", fProtocol);
      SafeDelete(fSocket);
      return -1;
   }

   fProof->fProtocol   = fProtocol;   // protocol of last slave on master

   if (fProtocol < 5) {
      //
      // Setup authentication related stuff for ald versions
      Bool_t isMaster = (stype == kMaster);
      TString wconf = isMaster ? TString(conffile) : fProofWorkDir;
      if (OldAuthSetup(isMaster, wconf) != 0) {
         Error("SetupServ", "OldAuthSetup: failed to setup authentication");
         SafeDelete(fSocket);
         return -1;
      }
   } else {
      //
      // Send ordinal (and config) info to slave (or master)
      TMessage mess;
      if (stype == kMaster)
         mess << fUser << fOrdinal << TString(conffile);
      else
         mess << fUser << fOrdinal << fProofWorkDir;

      if (fSocket->Send(mess) < 0) {
         Error("SetupServ", "failed to send ordinal and config info");
         SafeDelete(fSocket);
         return -1;
      }
   }

   // set some socket options
   fSocket->SetOption(kNoDelay, 1);

   // Set active state
   fStatus = kActive;

   // We are done
   return 0;
}

//______________________________________________________________________________
void TSlave::Init(TSocket *s, Int_t stype)
{
   // Init a PROOF slave object using the connection opened via s. Used to
   // avoid double opening when an attempt via TXSlave found a remote proofd.

   fSocket = s;
   TSlave::Init(s->GetInetAddress().GetHostName(), s->GetPort(), stype);
}

//______________________________________________________________________________
TSlave::~TSlave()
{
   // Destroy slave.

   Close();
}

//______________________________________________________________________________
void TSlave::Close(Option_t *opt)
{
   // Close slave socket.

   if (fSocket) {

      // If local client ...
      if (!(fProof->IsMaster()) && !strncasecmp(opt,"S",1)) {
         // ... tell master and slaves to stop
         Interrupt(TProof::kShutdownInterrupt);
      }

      // deactivate used sec context if talking to proofd daemon running
      // an old protocol (sec context disactivated remotely)
      TSecContext *sc = fSocket->GetSecContext();
      if (sc && sc->IsActive()) {
         TIter last(sc->GetSecContextCleanup(), kIterBackward);
         TSecContextCleanup *nscc = 0;
         while ((nscc = (TSecContextCleanup *)last())) {
            if (nscc->GetType() == TSocket::kPROOFD &&
                nscc->GetProtocol() < 9) {
               sc->DeActivate("");
               break;
            }
         }
      }
   }

   SafeDelete(fInput);
   SafeDelete(fSocket);
}

//______________________________________________________________________________
Int_t TSlave::Compare(const TObject *obj) const
{
   // Used to sort slaves by performance index.

   const TSlave *sl = dynamic_cast<const TSlave*>(obj);

   if (fPerfIdx > sl->GetPerfIdx()) return 1;
   if (fPerfIdx < sl->GetPerfIdx()) return -1;
   const char *myord = GetOrdinal();
   const char *otherord = sl->GetOrdinal();
   while (myord && otherord) {
      Int_t myval = atoi(myord);
      Int_t otherval = atoi(otherord);
      if (myval < otherval) return 1;
      if (myval > otherval) return -1;
      myord = strchr(myord, '.');
      if (myord) myord++;
      otherord = strchr(otherord, '.');
      if (otherord) otherord++;
   }
   if (myord) return -1;
   if (otherord) return 1;
   return 0;
}

//______________________________________________________________________________
void TSlave::Print(Option_t *) const
{
   // Printf info about slave.

   TString sc;

   const char *sst[] = { "invalid" , "valid", "inactive" };
   Int_t st = fSocket ? ((fStatus == kInactive) ? 2 : 1) : 0;

   Printf("*** Worker %s  (%s)", fOrdinal.Data(), sst[st]);
   Printf("    Host name:               %s", GetName());
   Printf("    Port number:             %d", GetPort());
   Printf("    ROOT version|rev|tag:    %s", GetROOTVersion());
   Printf("    Architecture-Compiler:   %s", GetArchCompiler());
   if (fSocket) {
      if (strlen(GetGroup()) > 0) {
         Printf("    User/Group:              %s/%s", GetUser(), GetGroup());
      } else {
         Printf("    User:                    %s", GetUser());
      }
      if (fSocket->GetSecContext())
         Printf("    Security context:        %s", fSocket->GetSecContext()->AsString(sc));
      Printf("    Proofd protocol version: %d", fSocket->GetRemoteProtocol());
      Printf("    Image name:              %s", GetImage());
      Printf("    Working directory:       %s", GetWorkDir());
      Printf("    Performance index:       %d", GetPerfIdx());
      Printf("    MB's processed:          %.2f", float(GetBytesRead())/(1024*1024));
      Printf("    MB's sent:               %.2f", float(fSocket->GetBytesRecv())/(1024*1024));
      Printf("    MB's received:           %.2f", float(fSocket->GetBytesSent())/(1024*1024));
      Printf("    Real time used (s):      %.3f", GetRealTime());
      Printf("    CPU time used (s):       %.3f", GetCpuTime());
   }
}

//______________________________________________________________________________
void TSlave::SetInputHandler(TFileHandler *ih)
{
   // Adopt and register input handler for this slave. Handler will be deleted
   // by the slave.

   fInput = ih;
   fInput->Add();
}

//______________________________________________________________________________
Int_t TSlave::OldAuthSetup(Bool_t master, TString wconf)
{
   // Setup authentication related stuff for old versions.
   // Provided for backward compatibility.
   static OldSlaveAuthSetup_t oldAuthSetupHook = 0;

   if (!oldAuthSetupHook) {
      // Load libraries needed for (server) authentication ...
      TString authlib = "libRootAuth";
      char *p = 0;
      // The generic one
      if ((p = gSystem->DynamicPathName(authlib, kTRUE))) {
         delete[] p;
         if (gSystem->Load(authlib) == -1) {
            Error("OldAuthSetup", "can't load %s",authlib.Data());
            return kFALSE;
         }
      } else {
         Error("OldAuthSetup", "can't locate %s",authlib.Data());
         return -1;
      }
      //
      // Locate OldSlaveAuthSetup
      Func_t f = gSystem->DynFindSymbol(authlib,"OldSlaveAuthSetup");
      if (f)
         oldAuthSetupHook = (OldSlaveAuthSetup_t)(f);
      else {
         Error("OldAuthSetup", "can't find OldSlaveAuthSetup");
         return -1;
      }
   }
   //
   // Setup
   if (oldAuthSetupHook) {
      return (*oldAuthSetupHook)(fSocket, master, fOrdinal, wconf);
   } else {
      Error("OldAuthSetup", "hook to method OldSlaveAuthSetup is undefined");
      return -1;
   }
}

//______________________________________________________________________________
TSlave *TSlave::Create(const char *url, const char *ord, Int_t perf,
                       const char *image, TProof *proof, Int_t stype,
                       const char *workdir, const char *msd)
{
   // Static method returning the appropriate TSlave object for the remote
   // server.

   TSlave *s = 0;

   // Check if we are setting up a lite version
   if (!strcmp(url, "lite")) {
      return new TSlaveLite(ord, perf, image, proof, stype, workdir, msd);
   }

   // No need to try a XPD connection in some well defined cases
   Bool_t tryxpd = kTRUE;
   if (!(proof->IsMaster())) {
      if (proof->IsProofd())
         tryxpd = kFALSE;
   } else {
      if (gApplication &&
         (gApplication->Argc() < 3 || strncmp(gApplication->Argv(2),"xpd",3)))
         tryxpd = kFALSE;
   }

   // We do this without the plugin manager because it blocks the CINT mutex
   // breaking the parallel startup
   if (!fgTXSlaveHook) {

      // Load the library containing TXSlave ...
      TString proofxlib = "libProofx";
      char *p = 0;
      if ((p = gSystem->DynamicPathName(proofxlib, kTRUE))) {
         delete[] p;
         if (gSystem->Load(proofxlib) == -1)
            ::Error("TSlave::Create", "can't load %s", proofxlib.Data());
      } else
         ::Error("TSlave::Create", "can't locate %s", proofxlib.Data());
   }

   // Load the right class
   if (fgTXSlaveHook && tryxpd) {
      s = (*fgTXSlaveHook)(url, ord, perf, image, proof, stype, workdir, msd);
   } else {
      s = new TSlave(url, ord, perf, image, proof, stype, workdir, msd);
   }

   return s;
}

//______________________________________________________________________________
Int_t TSlave::Ping()
{
   // Ping the remote master or slave servers.
   // Returns 0 if ok, -1 in case of error

   if (!IsValid()) return -1;

   TMessage mess(kPROOF_PING | kMESS_ACK);
   fSocket->Send(mess);
   if (fSocket->Send(mess) == -1) {
      Warning("Ping","%s: acknowledgement not received", GetOrdinal());
      return -1;
   }
   return 0;
}

//______________________________________________________________________________
void TSlave::Interrupt(Int_t type)
{
   // Send interrupt OOB byte to master or slave servers.
   // Returns 0 if ok, -1 in case of error

   if (!IsValid()) return;

   char oobc = (char) type;
   const int kBufSize = 1024;
   char waste[kBufSize];

   // Send one byte out-of-band message to server
   if (fSocket->SendRaw(&oobc, 1, kOob) <= 0) {
      Error("Interrupt", "error sending oobc to slave %s", GetOrdinal());
      return;
   }

   if (type == TProof::kHardInterrupt) {
      char  oob_byte;
      int   n, nch, nbytes = 0, nloop = 0;

      // Receive the OOB byte
      while ((n = fSocket->RecvRaw(&oob_byte, 1, kOob)) < 0) {
         if (n == -2) {   // EWOULDBLOCK
            //
            // The OOB data has not yet arrived: flush the input stream
            //
            // In some systems (Solaris) regular recv() does not return upon
            // receipt of the oob byte, which makes the below call to recv()
            // block indefinitely if there are no other data in the queue.
            // FIONREAD ioctl can be used to check if there are actually any
            // data to be flushed.  If not, wait for a while for the oob byte
            // to arrive and try to read it again.
            //
            fSocket->GetOption(kBytesToRead, nch);
            if (nch == 0) {
               gSystem->Sleep(1000);
               continue;
            }

            if (nch > kBufSize) nch = kBufSize;
            n = fSocket->RecvRaw(waste, nch);
            if (n <= 0) {
               Error("Interrupt", "error receiving waste from slave %s",
                     GetOrdinal());
               break;
            }
            nbytes += n;
         } else if (n == -3) {   // EINVAL
            //
            // The OOB data has not arrived yet
            //
            gSystem->Sleep(100);
            if (++nloop > 100) {  // 10 seconds time-out
               Error("Interrupt", "server %s does not respond", GetOrdinal());
               break;
            }
         } else {
            Error("Interrupt", "error receiving OOB from server %s",
                  GetOrdinal());
            break;
         }
      }

      //
      // Continue flushing the input socket stream until the OOB
      // mark is reached
      //
      while (1) {
         int atmark;

         fSocket->GetOption(kAtMark, atmark);

         if (atmark)
            break;

         // find out number of bytes to read before atmark
         fSocket->GetOption(kBytesToRead, nch);
         if (nch == 0) {
            gSystem->Sleep(1000);
            continue;
         }

         if (nch > kBufSize) nch = kBufSize;
         n = fSocket->RecvRaw(waste, nch);
         if (n <= 0) {
            Error("Interrupt", "error receiving waste (2) from slave %s",
                  GetOrdinal());
            break;
         }
         nbytes += n;
      }
      if (nbytes > 0) {
         if (fProof->IsMaster())
            Info("Interrupt", "slave %s:%s synchronized: %d bytes discarded",
                 GetName(), GetOrdinal(), nbytes);
         else
            Info("Interrupt", "PROOF synchronized: %d bytes discarded", nbytes);
      }

      // Get log file from master or slave after a hard interrupt
      fProof->Collect(this);

   } else if (type == TProof::kSoftInterrupt) {

      // Get log file from master or slave after a soft interrupt
      fProof->Collect(this);

   } else if (type == TProof::kShutdownInterrupt) {

      ; // nothing expected to be returned

   } else {

      // Unexpected message, just receive log file
      fProof->Collect(this);
   }
}

//______________________________________________________________________________
void TSlave::StopProcess(Bool_t abort, Int_t timeout)
{
   // Sent stop/abort request to PROOF server.

   // Notify the remote counterpart
   TMessage msg(kPROOF_STOPPROCESS);
   msg << abort;
   if (fProof->fProtocol > 9)
      msg << timeout;
   fSocket->Send(msg);
}

//______________________________________________________________________________
TObjString *TSlave::SendCoordinator(Int_t, const char *, Int_t)
{
   // Send message to intermediate coordinator. Only meaningful when there is one,
   // i.e. in XPD framework

   if (gDebug > 0)
      Info("SendCoordinator","method not implemented for this communication layer");
   return 0;
}

//______________________________________________________________________________
void TSlave::SetAlias(const char *)
{
   // Set an alias for this session. If reconnection is supported, the alias
   // will be communicated to the remote coordinator so that it can be recovered
   // when reconnecting

   if (gDebug > 0)
      Info("SetAlias","method not implemented for this communication layer");
   return;
}

//_____________________________________________________________________________
void TSlave::SetTXSlaveHook(TSlave_t xslavehook)
{
   // Set hook to TXSlave ctor
   fgTXSlaveHook = xslavehook;
}
 TSlave.cxx:1
 TSlave.cxx:2
 TSlave.cxx:3
 TSlave.cxx:4
 TSlave.cxx:5
 TSlave.cxx:6
 TSlave.cxx:7
 TSlave.cxx:8
 TSlave.cxx:9
 TSlave.cxx:10
 TSlave.cxx:11
 TSlave.cxx:12
 TSlave.cxx:13
 TSlave.cxx:14
 TSlave.cxx:15
 TSlave.cxx:16
 TSlave.cxx:17
 TSlave.cxx:18
 TSlave.cxx:19
 TSlave.cxx:20
 TSlave.cxx:21
 TSlave.cxx:22
 TSlave.cxx:23
 TSlave.cxx:24
 TSlave.cxx:25
 TSlave.cxx:26
 TSlave.cxx:27
 TSlave.cxx:28
 TSlave.cxx:29
 TSlave.cxx:30
 TSlave.cxx:31
 TSlave.cxx:32
 TSlave.cxx:33
 TSlave.cxx:34
 TSlave.cxx:35
 TSlave.cxx:36
 TSlave.cxx:37
 TSlave.cxx:38
 TSlave.cxx:39
 TSlave.cxx:40
 TSlave.cxx:41
 TSlave.cxx:42
 TSlave.cxx:43
 TSlave.cxx:44
 TSlave.cxx:45
 TSlave.cxx:46
 TSlave.cxx:47
 TSlave.cxx:48
 TSlave.cxx:49
 TSlave.cxx:50
 TSlave.cxx:51
 TSlave.cxx:52
 TSlave.cxx:53
 TSlave.cxx:54
 TSlave.cxx:55
 TSlave.cxx:56
 TSlave.cxx:57
 TSlave.cxx:58
 TSlave.cxx:59
 TSlave.cxx:60
 TSlave.cxx:61
 TSlave.cxx:62
 TSlave.cxx:63
 TSlave.cxx:64
 TSlave.cxx:65
 TSlave.cxx:66
 TSlave.cxx:67
 TSlave.cxx:68
 TSlave.cxx:69
 TSlave.cxx:70
 TSlave.cxx:71
 TSlave.cxx:72
 TSlave.cxx:73
 TSlave.cxx:74
 TSlave.cxx:75
 TSlave.cxx:76
 TSlave.cxx:77
 TSlave.cxx:78
 TSlave.cxx:79
 TSlave.cxx:80
 TSlave.cxx:81
 TSlave.cxx:82
 TSlave.cxx:83
 TSlave.cxx:84
 TSlave.cxx:85
 TSlave.cxx:86
 TSlave.cxx:87
 TSlave.cxx:88
 TSlave.cxx:89
 TSlave.cxx:90
 TSlave.cxx:91
 TSlave.cxx:92
 TSlave.cxx:93
 TSlave.cxx:94
 TSlave.cxx:95
 TSlave.cxx:96
 TSlave.cxx:97
 TSlave.cxx:98
 TSlave.cxx:99
 TSlave.cxx:100
 TSlave.cxx:101
 TSlave.cxx:102
 TSlave.cxx:103
 TSlave.cxx:104
 TSlave.cxx:105
 TSlave.cxx:106
 TSlave.cxx:107
 TSlave.cxx:108
 TSlave.cxx:109
 TSlave.cxx:110
 TSlave.cxx:111
 TSlave.cxx:112
 TSlave.cxx:113
 TSlave.cxx:114
 TSlave.cxx:115
 TSlave.cxx:116
 TSlave.cxx:117
 TSlave.cxx:118
 TSlave.cxx:119
 TSlave.cxx:120
 TSlave.cxx:121
 TSlave.cxx:122
 TSlave.cxx:123
 TSlave.cxx:124
 TSlave.cxx:125
 TSlave.cxx:126
 TSlave.cxx:127
 TSlave.cxx:128
 TSlave.cxx:129
 TSlave.cxx:130
 TSlave.cxx:131
 TSlave.cxx:132
 TSlave.cxx:133
 TSlave.cxx:134
 TSlave.cxx:135
 TSlave.cxx:136
 TSlave.cxx:137
 TSlave.cxx:138
 TSlave.cxx:139
 TSlave.cxx:140
 TSlave.cxx:141
 TSlave.cxx:142
 TSlave.cxx:143
 TSlave.cxx:144
 TSlave.cxx:145
 TSlave.cxx:146
 TSlave.cxx:147
 TSlave.cxx:148
 TSlave.cxx:149
 TSlave.cxx:150
 TSlave.cxx:151
 TSlave.cxx:152
 TSlave.cxx:153
 TSlave.cxx:154
 TSlave.cxx:155
 TSlave.cxx:156
 TSlave.cxx:157
 TSlave.cxx:158
 TSlave.cxx:159
 TSlave.cxx:160
 TSlave.cxx:161
 TSlave.cxx:162
 TSlave.cxx:163
 TSlave.cxx:164
 TSlave.cxx:165
 TSlave.cxx:166
 TSlave.cxx:167
 TSlave.cxx:168
 TSlave.cxx:169
 TSlave.cxx:170
 TSlave.cxx:171
 TSlave.cxx:172
 TSlave.cxx:173
 TSlave.cxx:174
 TSlave.cxx:175
 TSlave.cxx:176
 TSlave.cxx:177
 TSlave.cxx:178
 TSlave.cxx:179
 TSlave.cxx:180
 TSlave.cxx:181
 TSlave.cxx:182
 TSlave.cxx:183
 TSlave.cxx:184
 TSlave.cxx:185
 TSlave.cxx:186
 TSlave.cxx:187
 TSlave.cxx:188
 TSlave.cxx:189
 TSlave.cxx:190
 TSlave.cxx:191
 TSlave.cxx:192
 TSlave.cxx:193
 TSlave.cxx:194
 TSlave.cxx:195
 TSlave.cxx:196
 TSlave.cxx:197
 TSlave.cxx:198
 TSlave.cxx:199
 TSlave.cxx:200
 TSlave.cxx:201
 TSlave.cxx:202
 TSlave.cxx:203
 TSlave.cxx:204
 TSlave.cxx:205
 TSlave.cxx:206
 TSlave.cxx:207
 TSlave.cxx:208
 TSlave.cxx:209
 TSlave.cxx:210
 TSlave.cxx:211
 TSlave.cxx:212
 TSlave.cxx:213
 TSlave.cxx:214
 TSlave.cxx:215
 TSlave.cxx:216
 TSlave.cxx:217
 TSlave.cxx:218
 TSlave.cxx:219
 TSlave.cxx:220
 TSlave.cxx:221
 TSlave.cxx:222
 TSlave.cxx:223
 TSlave.cxx:224
 TSlave.cxx:225
 TSlave.cxx:226
 TSlave.cxx:227
 TSlave.cxx:228
 TSlave.cxx:229
 TSlave.cxx:230
 TSlave.cxx:231
 TSlave.cxx:232
 TSlave.cxx:233
 TSlave.cxx:234
 TSlave.cxx:235
 TSlave.cxx:236
 TSlave.cxx:237
 TSlave.cxx:238
 TSlave.cxx:239
 TSlave.cxx:240
 TSlave.cxx:241
 TSlave.cxx:242
 TSlave.cxx:243
 TSlave.cxx:244
 TSlave.cxx:245
 TSlave.cxx:246
 TSlave.cxx:247
 TSlave.cxx:248
 TSlave.cxx:249
 TSlave.cxx:250
 TSlave.cxx:251
 TSlave.cxx:252
 TSlave.cxx:253
 TSlave.cxx:254
 TSlave.cxx:255
 TSlave.cxx:256
 TSlave.cxx:257
 TSlave.cxx:258
 TSlave.cxx:259
 TSlave.cxx:260
 TSlave.cxx:261
 TSlave.cxx:262
 TSlave.cxx:263
 TSlave.cxx:264
 TSlave.cxx:265
 TSlave.cxx:266
 TSlave.cxx:267
 TSlave.cxx:268
 TSlave.cxx:269
 TSlave.cxx:270
 TSlave.cxx:271
 TSlave.cxx:272
 TSlave.cxx:273
 TSlave.cxx:274
 TSlave.cxx:275
 TSlave.cxx:276
 TSlave.cxx:277
 TSlave.cxx:278
 TSlave.cxx:279
 TSlave.cxx:280
 TSlave.cxx:281
 TSlave.cxx:282
 TSlave.cxx:283
 TSlave.cxx:284
 TSlave.cxx:285
 TSlave.cxx:286
 TSlave.cxx:287
 TSlave.cxx:288
 TSlave.cxx:289
 TSlave.cxx:290
 TSlave.cxx:291
 TSlave.cxx:292
 TSlave.cxx:293
 TSlave.cxx:294
 TSlave.cxx:295
 TSlave.cxx:296
 TSlave.cxx:297
 TSlave.cxx:298
 TSlave.cxx:299
 TSlave.cxx:300
 TSlave.cxx:301
 TSlave.cxx:302
 TSlave.cxx:303
 TSlave.cxx:304
 TSlave.cxx:305
 TSlave.cxx:306
 TSlave.cxx:307
 TSlave.cxx:308
 TSlave.cxx:309
 TSlave.cxx:310
 TSlave.cxx:311
 TSlave.cxx:312
 TSlave.cxx:313
 TSlave.cxx:314
 TSlave.cxx:315
 TSlave.cxx:316
 TSlave.cxx:317
 TSlave.cxx:318
 TSlave.cxx:319
 TSlave.cxx:320
 TSlave.cxx:321
 TSlave.cxx:322
 TSlave.cxx:323
 TSlave.cxx:324
 TSlave.cxx:325
 TSlave.cxx:326
 TSlave.cxx:327
 TSlave.cxx:328
 TSlave.cxx:329
 TSlave.cxx:330
 TSlave.cxx:331
 TSlave.cxx:332
 TSlave.cxx:333
 TSlave.cxx:334
 TSlave.cxx:335
 TSlave.cxx:336
 TSlave.cxx:337
 TSlave.cxx:338
 TSlave.cxx:339
 TSlave.cxx:340
 TSlave.cxx:341
 TSlave.cxx:342
 TSlave.cxx:343
 TSlave.cxx:344
 TSlave.cxx:345
 TSlave.cxx:346
 TSlave.cxx:347
 TSlave.cxx:348
 TSlave.cxx:349
 TSlave.cxx:350
 TSlave.cxx:351
 TSlave.cxx:352
 TSlave.cxx:353
 TSlave.cxx:354
 TSlave.cxx:355
 TSlave.cxx:356
 TSlave.cxx:357
 TSlave.cxx:358
 TSlave.cxx:359
 TSlave.cxx:360
 TSlave.cxx:361
 TSlave.cxx:362
 TSlave.cxx:363
 TSlave.cxx:364
 TSlave.cxx:365
 TSlave.cxx:366
 TSlave.cxx:367
 TSlave.cxx:368
 TSlave.cxx:369
 TSlave.cxx:370
 TSlave.cxx:371
 TSlave.cxx:372
 TSlave.cxx:373
 TSlave.cxx:374
 TSlave.cxx:375
 TSlave.cxx:376
 TSlave.cxx:377
 TSlave.cxx:378
 TSlave.cxx:379
 TSlave.cxx:380
 TSlave.cxx:381
 TSlave.cxx:382
 TSlave.cxx:383
 TSlave.cxx:384
 TSlave.cxx:385
 TSlave.cxx:386
 TSlave.cxx:387
 TSlave.cxx:388
 TSlave.cxx:389
 TSlave.cxx:390
 TSlave.cxx:391
 TSlave.cxx:392
 TSlave.cxx:393
 TSlave.cxx:394
 TSlave.cxx:395
 TSlave.cxx:396
 TSlave.cxx:397
 TSlave.cxx:398
 TSlave.cxx:399
 TSlave.cxx:400
 TSlave.cxx:401
 TSlave.cxx:402
 TSlave.cxx:403
 TSlave.cxx:404
 TSlave.cxx:405
 TSlave.cxx:406
 TSlave.cxx:407
 TSlave.cxx:408
 TSlave.cxx:409
 TSlave.cxx:410
 TSlave.cxx:411
 TSlave.cxx:412
 TSlave.cxx:413
 TSlave.cxx:414
 TSlave.cxx:415
 TSlave.cxx:416
 TSlave.cxx:417
 TSlave.cxx:418
 TSlave.cxx:419
 TSlave.cxx:420
 TSlave.cxx:421
 TSlave.cxx:422
 TSlave.cxx:423
 TSlave.cxx:424
 TSlave.cxx:425
 TSlave.cxx:426
 TSlave.cxx:427
 TSlave.cxx:428
 TSlave.cxx:429
 TSlave.cxx:430
 TSlave.cxx:431
 TSlave.cxx:432
 TSlave.cxx:433
 TSlave.cxx:434
 TSlave.cxx:435
 TSlave.cxx:436
 TSlave.cxx:437
 TSlave.cxx:438
 TSlave.cxx:439
 TSlave.cxx:440
 TSlave.cxx:441
 TSlave.cxx:442
 TSlave.cxx:443
 TSlave.cxx:444
 TSlave.cxx:445
 TSlave.cxx:446
 TSlave.cxx:447
 TSlave.cxx:448
 TSlave.cxx:449
 TSlave.cxx:450
 TSlave.cxx:451
 TSlave.cxx:452
 TSlave.cxx:453
 TSlave.cxx:454
 TSlave.cxx:455
 TSlave.cxx:456
 TSlave.cxx:457
 TSlave.cxx:458
 TSlave.cxx:459
 TSlave.cxx:460
 TSlave.cxx:461
 TSlave.cxx:462
 TSlave.cxx:463
 TSlave.cxx:464
 TSlave.cxx:465
 TSlave.cxx:466
 TSlave.cxx:467
 TSlave.cxx:468
 TSlave.cxx:469
 TSlave.cxx:470
 TSlave.cxx:471
 TSlave.cxx:472
 TSlave.cxx:473
 TSlave.cxx:474
 TSlave.cxx:475
 TSlave.cxx:476
 TSlave.cxx:477
 TSlave.cxx:478
 TSlave.cxx:479
 TSlave.cxx:480
 TSlave.cxx:481
 TSlave.cxx:482
 TSlave.cxx:483
 TSlave.cxx:484
 TSlave.cxx:485
 TSlave.cxx:486
 TSlave.cxx:487
 TSlave.cxx:488
 TSlave.cxx:489
 TSlave.cxx:490
 TSlave.cxx:491
 TSlave.cxx:492
 TSlave.cxx:493
 TSlave.cxx:494
 TSlave.cxx:495
 TSlave.cxx:496
 TSlave.cxx:497
 TSlave.cxx:498
 TSlave.cxx:499
 TSlave.cxx:500
 TSlave.cxx:501
 TSlave.cxx:502
 TSlave.cxx:503
 TSlave.cxx:504
 TSlave.cxx:505
 TSlave.cxx:506
 TSlave.cxx:507
 TSlave.cxx:508
 TSlave.cxx:509
 TSlave.cxx:510
 TSlave.cxx:511
 TSlave.cxx:512
 TSlave.cxx:513
 TSlave.cxx:514
 TSlave.cxx:515
 TSlave.cxx:516
 TSlave.cxx:517
 TSlave.cxx:518
 TSlave.cxx:519
 TSlave.cxx:520
 TSlave.cxx:521
 TSlave.cxx:522
 TSlave.cxx:523
 TSlave.cxx:524
 TSlave.cxx:525
 TSlave.cxx:526
 TSlave.cxx:527
 TSlave.cxx:528
 TSlave.cxx:529
 TSlave.cxx:530
 TSlave.cxx:531
 TSlave.cxx:532
 TSlave.cxx:533
 TSlave.cxx:534
 TSlave.cxx:535
 TSlave.cxx:536
 TSlave.cxx:537
 TSlave.cxx:538
 TSlave.cxx:539
 TSlave.cxx:540
 TSlave.cxx:541
 TSlave.cxx:542
 TSlave.cxx:543
 TSlave.cxx:544
 TSlave.cxx:545
 TSlave.cxx:546
 TSlave.cxx:547
 TSlave.cxx:548
 TSlave.cxx:549
 TSlave.cxx:550
 TSlave.cxx:551
 TSlave.cxx:552
 TSlave.cxx:553
 TSlave.cxx:554
 TSlave.cxx:555
 TSlave.cxx:556
 TSlave.cxx:557
 TSlave.cxx:558
 TSlave.cxx:559
 TSlave.cxx:560
 TSlave.cxx:561
 TSlave.cxx:562
 TSlave.cxx:563
 TSlave.cxx:564
 TSlave.cxx:565
 TSlave.cxx:566
 TSlave.cxx:567
 TSlave.cxx:568
 TSlave.cxx:569
 TSlave.cxx:570
 TSlave.cxx:571
 TSlave.cxx:572
 TSlave.cxx:573
 TSlave.cxx:574
 TSlave.cxx:575
 TSlave.cxx:576
 TSlave.cxx:577
 TSlave.cxx:578
 TSlave.cxx:579
 TSlave.cxx:580
 TSlave.cxx:581
 TSlave.cxx:582
 TSlave.cxx:583
 TSlave.cxx:584
 TSlave.cxx:585
 TSlave.cxx:586
 TSlave.cxx:587
 TSlave.cxx:588
 TSlave.cxx:589
 TSlave.cxx:590
 TSlave.cxx:591
 TSlave.cxx:592
 TSlave.cxx:593
 TSlave.cxx:594
 TSlave.cxx:595
 TSlave.cxx:596
 TSlave.cxx:597
 TSlave.cxx:598
 TSlave.cxx:599
 TSlave.cxx:600
 TSlave.cxx:601
 TSlave.cxx:602
 TSlave.cxx:603
 TSlave.cxx:604
 TSlave.cxx:605
 TSlave.cxx:606
 TSlave.cxx:607
 TSlave.cxx:608
 TSlave.cxx:609
 TSlave.cxx:610
 TSlave.cxx:611
 TSlave.cxx:612
 TSlave.cxx:613
 TSlave.cxx:614
 TSlave.cxx:615
 TSlave.cxx:616
 TSlave.cxx:617
 TSlave.cxx:618
 TSlave.cxx:619
 TSlave.cxx:620
 TSlave.cxx:621
 TSlave.cxx:622
 TSlave.cxx:623
 TSlave.cxx:624
 TSlave.cxx:625
 TSlave.cxx:626
 TSlave.cxx:627
 TSlave.cxx:628
 TSlave.cxx:629
 TSlave.cxx:630
 TSlave.cxx:631
 TSlave.cxx:632
 TSlave.cxx:633
 TSlave.cxx:634
 TSlave.cxx:635
 TSlave.cxx:636
 TSlave.cxx:637
 TSlave.cxx:638
 TSlave.cxx:639
 TSlave.cxx:640
 TSlave.cxx:641
 TSlave.cxx:642
 TSlave.cxx:643
 TSlave.cxx:644
 TSlave.cxx:645
 TSlave.cxx:646
 TSlave.cxx:647
 TSlave.cxx:648
 TSlave.cxx:649
 TSlave.cxx:650
 TSlave.cxx:651
 TSlave.cxx:652
 TSlave.cxx:653