// @(#)root/proof:$Id$
// Author: Gerardo Ganis  March 2008

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

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TSlaveLite                                                           //
//                                                                      //
// This is the version of TSlave for local worker servers.              //
// See TSlave for details.                                              //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "RConfigure.h"
#include "TSlaveLite.h"
#include "TProof.h"
#include "TProofServ.h"
#include "TSystem.h"
#include "TEnv.h"
#include "TROOT.h"
#include "TUrl.h"
#include "TMessage.h"
#include "TMonitor.h"
#include "TError.h"
#include "TSocket.h"
#include "TSysEvtHandler.h"
#include "TVirtualMutex.h"
#include "TThread.h"

ClassImp(TSlaveLite)

//______________________________________________________________________________
//---- error handling ----------------------------------------------------------
//---- Needed to avoid blocking on the CINT mutex in printouts -----------------

//______________________________________________________________________________
void TSlaveLite::DoError(int level, const char *location,
                                    const char *fmt, va_list va) const
{
   // Interface to ErrorHandler (protected).

   ::ErrorHandler(level, Form("TSlaveLite::%s", location), fmt, va);
}

//______________________________________________________________________________
TSlaveLite::TSlaveLite(const char *ord, Int_t perf,
               const char *image, TProof *proof, Int_t stype,
               const char *workdir, const char *msd, Int_t) : TSlave()
{
   // Create a PROOF slave object. Called via the TProof ctor.
   fName = ord;  // Need this during the setup phase; see end of SetupServ
   fImage = image;
   fProofWorkDir = workdir;
   fWorkDir = workdir;
   fOrdinal = ord;
   fPerfIdx = perf;
   fProof = proof;
   fSlaveType = (ESlaveType)stype;
   fMsd = msd;
   fIntHandler = 0;
   fValid = kFALSE;
   fProtocol = kPROOF_Protocol;

   if (fPerfIdx > 0) Init();
}

//______________________________________________________________________________
void TSlaveLite::Init()
{
   // Init a PROOF worker object. Called via the TSlaveLite ctor.

   // Command to be executed
   TString cmd;
#ifdef R__HAVE_CONFIG
   cmd.Form(". %s/worker-%s.env; export ROOTBINDIR=\"%s\"; %s/proofserv proofslave lite %d %d 0&",
            fWorkDir.Data(), fOrdinal.Data(), ROOTBINDIR, ROOTBINDIR,
#else
   cmd.Form(". %s/worker-%s.env; export ROOTBINDIR=\"%s/bin\"; %s/bin/proofserv proofslave lite %d %d 0&",
            fWorkDir.Data(), fOrdinal.Data(), gSystem->Getenv("ROOTSYS"), gSystem->Getenv("ROOTSYS"),
#endif
            gSystem->GetPid(), gDebug);
   // Execute
   if (gSystem->Exec(cmd) != 0) {
      Error("Init", "an error occured while executing 'proofserv'");
      SetBit(kInvalidObject);
      return;
   }
}

//______________________________________________________________________________
Int_t TSlaveLite::SetupServ(Int_t, const char *)
{
   // Init a PROOF slave object. Called via the TSlaveLite 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");
      Close("S");
      SafeDelete(fSocket);
      fValid = kFALSE;
      return -1;
   }

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

   // Receive the unique tag and save it as name of this object
   TMessage *msg = 0;
   if (fSocket->Recv(msg) <= 0 || !msg || msg->What() != kPROOF_SESSIONTAG) {
      Error("SetupServ", "failed to receive unique session tag");
      Close("S");
      SafeDelete(fSocket);
      fValid = kFALSE;
      return -1;
   }
   // Extract the unique tag
   (*msg) >> fSessionTag;
   
   // Set the real name (temporarly set to ordinal for the setup)
   fName = gSystem->HostName();
   
   // We are done
   return 0;
}

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

   Close();
}

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

   if (fSocket)
      // Closing socket ...
      fSocket->Close(opt);

   SafeDelete(fInput);
   SafeDelete(fSocket);
}

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

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

   Printf("*** Worker %s  (%s)", fOrdinal.Data(), sst[st]);
   Printf("    Worker session tag:      %s", GetSessionTag());
   Printf("    ROOT version|rev|tag:    %s", GetROOTVersion());
   Printf("    Architecture-Compiler:   %s", GetArchCompiler());
   if (fSocket) {
      Printf("    Working directory:       %s", GetWorkDir());
      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());
   }
}
 TSlaveLite.cxx:1
 TSlaveLite.cxx:2
 TSlaveLite.cxx:3
 TSlaveLite.cxx:4
 TSlaveLite.cxx:5
 TSlaveLite.cxx:6
 TSlaveLite.cxx:7
 TSlaveLite.cxx:8
 TSlaveLite.cxx:9
 TSlaveLite.cxx:10
 TSlaveLite.cxx:11
 TSlaveLite.cxx:12
 TSlaveLite.cxx:13
 TSlaveLite.cxx:14
 TSlaveLite.cxx:15
 TSlaveLite.cxx:16
 TSlaveLite.cxx:17
 TSlaveLite.cxx:18
 TSlaveLite.cxx:19
 TSlaveLite.cxx:20
 TSlaveLite.cxx:21
 TSlaveLite.cxx:22
 TSlaveLite.cxx:23
 TSlaveLite.cxx:24
 TSlaveLite.cxx:25
 TSlaveLite.cxx:26
 TSlaveLite.cxx:27
 TSlaveLite.cxx:28
 TSlaveLite.cxx:29
 TSlaveLite.cxx:30
 TSlaveLite.cxx:31
 TSlaveLite.cxx:32
 TSlaveLite.cxx:33
 TSlaveLite.cxx:34
 TSlaveLite.cxx:35
 TSlaveLite.cxx:36
 TSlaveLite.cxx:37
 TSlaveLite.cxx:38
 TSlaveLite.cxx:39
 TSlaveLite.cxx:40
 TSlaveLite.cxx:41
 TSlaveLite.cxx:42
 TSlaveLite.cxx:43
 TSlaveLite.cxx:44
 TSlaveLite.cxx:45
 TSlaveLite.cxx:46
 TSlaveLite.cxx:47
 TSlaveLite.cxx:48
 TSlaveLite.cxx:49
 TSlaveLite.cxx:50
 TSlaveLite.cxx:51
 TSlaveLite.cxx:52
 TSlaveLite.cxx:53
 TSlaveLite.cxx:54
 TSlaveLite.cxx:55
 TSlaveLite.cxx:56
 TSlaveLite.cxx:57
 TSlaveLite.cxx:58
 TSlaveLite.cxx:59
 TSlaveLite.cxx:60
 TSlaveLite.cxx:61
 TSlaveLite.cxx:62
 TSlaveLite.cxx:63
 TSlaveLite.cxx:64
 TSlaveLite.cxx:65
 TSlaveLite.cxx:66
 TSlaveLite.cxx:67
 TSlaveLite.cxx:68
 TSlaveLite.cxx:69
 TSlaveLite.cxx:70
 TSlaveLite.cxx:71
 TSlaveLite.cxx:72
 TSlaveLite.cxx:73
 TSlaveLite.cxx:74
 TSlaveLite.cxx:75
 TSlaveLite.cxx:76
 TSlaveLite.cxx:77
 TSlaveLite.cxx:78
 TSlaveLite.cxx:79
 TSlaveLite.cxx:80
 TSlaveLite.cxx:81
 TSlaveLite.cxx:82
 TSlaveLite.cxx:83
 TSlaveLite.cxx:84
 TSlaveLite.cxx:85
 TSlaveLite.cxx:86
 TSlaveLite.cxx:87
 TSlaveLite.cxx:88
 TSlaveLite.cxx:89
 TSlaveLite.cxx:90
 TSlaveLite.cxx:91
 TSlaveLite.cxx:92
 TSlaveLite.cxx:93
 TSlaveLite.cxx:94
 TSlaveLite.cxx:95
 TSlaveLite.cxx:96
 TSlaveLite.cxx:97
 TSlaveLite.cxx:98
 TSlaveLite.cxx:99
 TSlaveLite.cxx:100
 TSlaveLite.cxx:101
 TSlaveLite.cxx:102
 TSlaveLite.cxx:103
 TSlaveLite.cxx:104
 TSlaveLite.cxx:105
 TSlaveLite.cxx:106
 TSlaveLite.cxx:107
 TSlaveLite.cxx:108
 TSlaveLite.cxx:109
 TSlaveLite.cxx:110
 TSlaveLite.cxx:111
 TSlaveLite.cxx:112
 TSlaveLite.cxx:113
 TSlaveLite.cxx:114
 TSlaveLite.cxx:115
 TSlaveLite.cxx:116
 TSlaveLite.cxx:117
 TSlaveLite.cxx:118
 TSlaveLite.cxx:119
 TSlaveLite.cxx:120
 TSlaveLite.cxx:121
 TSlaveLite.cxx:122
 TSlaveLite.cxx:123
 TSlaveLite.cxx:124
 TSlaveLite.cxx:125
 TSlaveLite.cxx:126
 TSlaveLite.cxx:127
 TSlaveLite.cxx:128
 TSlaveLite.cxx:129
 TSlaveLite.cxx:130
 TSlaveLite.cxx:131
 TSlaveLite.cxx:132
 TSlaveLite.cxx:133
 TSlaveLite.cxx:134
 TSlaveLite.cxx:135
 TSlaveLite.cxx:136
 TSlaveLite.cxx:137
 TSlaveLite.cxx:138
 TSlaveLite.cxx:139
 TSlaveLite.cxx:140
 TSlaveLite.cxx:141
 TSlaveLite.cxx:142
 TSlaveLite.cxx:143
 TSlaveLite.cxx:144
 TSlaveLite.cxx:145
 TSlaveLite.cxx:146
 TSlaveLite.cxx:147
 TSlaveLite.cxx:148
 TSlaveLite.cxx:149
 TSlaveLite.cxx:150
 TSlaveLite.cxx:151
 TSlaveLite.cxx:152
 TSlaveLite.cxx:153
 TSlaveLite.cxx:154
 TSlaveLite.cxx:155
 TSlaveLite.cxx:156
 TSlaveLite.cxx:157
 TSlaveLite.cxx:158
 TSlaveLite.cxx:159
 TSlaveLite.cxx:160
 TSlaveLite.cxx:161
 TSlaveLite.cxx:162
 TSlaveLite.cxx:163
 TSlaveLite.cxx:164
 TSlaveLite.cxx:165
 TSlaveLite.cxx:166
 TSlaveLite.cxx:167
 TSlaveLite.cxx:168
 TSlaveLite.cxx:169
 TSlaveLite.cxx:170
 TSlaveLite.cxx:171
 TSlaveLite.cxx:172
 TSlaveLite.cxx:173
 TSlaveLite.cxx:174
 TSlaveLite.cxx:175
 TSlaveLite.cxx:176
 TSlaveLite.cxx:177
 TSlaveLite.cxx:178
 TSlaveLite.cxx:179
 TSlaveLite.cxx:180
 TSlaveLite.cxx:181
 TSlaveLite.cxx:182