// @(#)root/proof:$Name: $:$Id: TSlave.cxx,v 1.37 2005/02/18 14:27:33 rdm Exp $
// 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 "TSlave.h"
#include "TProof.h"
#include "TSystem.h"
#include "TEnv.h"
#include "TROOT.h"
#include "TUrl.h"
#include "TMessage.h"
#include "TError.h"
ClassImp(TSlave)
//______________________________________________________________________________
TSlave::TSlave(const char *host, Int_t port, const char *ord, Int_t perf,
const char *image, TProof *proof, ESlaveType stype,
const char *workdir, const char *conffile, const char *msd)
{
// Create a PROOF slave object. Called via the TProof ctor.
fName = host;
fPort = port;
fImage = image;
fWorkDir = workdir;
fProofWorkDir = workdir;
fOrdinal = ord;
fPerfIdx = perf;
fSecContext = 0;
fProof = proof;
fSocket = 0;
fInput = 0;
fBytesRead = 0;
fRealTime = 0.;
fCpuTime = 0.;
fSlaveType = stype;
fStatus = 0;
fParallel = 0;
fMsd = msd;
// The url contains information about the server type: make sure
// it is 'proofd' or alike
TString hurl(proof->GetUrlProtocol());
hurl.Insert(5, 'd');
// Add host, port (and user) information
if (proof->GetUser() && strlen(proof->GetUser())) {
hurl += TString(Form("://%s@%s:%d", proof->GetUser(), host, port));
} else {
hurl += TString(Form("://%s:%d", host, port));
}
// Add information about our status (Client or Master)
TString iam;
if (proof->IsMaster() && stype == kSlave) {
iam = "Master";
hurl += TString("/?SM");
} else if (proof->IsMaster() && stype == kMaster) {
iam = "Master";
hurl += TString("/?MM");
} else if (!proof->IsMaster() && stype == kMaster) {
iam = "Local Client";
hurl += TString("/?MC");
} else {
Error("TSlave","Impossible PROOF <-> SlaveType Configuration Requested");
Assert(0);
}
// Open authenticated connection to remote PROOF slave server.
Int_t wsize = 65536;
fSocket = TSocket::CreateAuthSocket(hurl, 0, wsize);
if (fSocket && fSocket->IsAuthenticated()) {
// 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.
gROOT->GetListOfSockets()->Remove(fSocket);
// Fill some useful info
fSecContext = fSocket->GetSecContext();
fUser = fSecContext->GetUser();
proof->fSecContext = fSecContext;
proof->fUser = fUser;
Int_t ProofdProto = fSocket->GetRemoteProtocol();
PDB(kGlobal,3) {
fSocket->GetSecContext()->Print("e");
Info("TSlave",
"%s: fUser is .... %s", iam.Data(), proof->fUser.Data());
}
TString Details = fSocket->GetSecContext()->GetDetails();
Int_t RemoteOffSet = fSocket->GetSecContext()->GetOffSet();
char buf[512];
fSocket->Recv(buf, sizeof(buf));
if (strcmp(buf, "Okay")) {
Printf("%s", buf);
SafeDelete(fSocket);
} else {
// 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;
if (fSocket->Recv(buf, sizeof(buf), what) <= 0) {
Error("TSlave", "failed to receive slave startup message");
SafeDelete(fSocket);
return;
}
if (what == kMESS_NOTOK) {
SafeDelete(fSocket);
return;
}
// exchange protocol level between client and master and between
// master and slave
if (fSocket->Send(kPROOF_Protocol, kROOTD_PROTOCOL) != 2*sizeof(Int_t)) {
Error("TSlave", "failed to send local PROOF protocol");
SafeDelete(fSocket);
return;
}
if (fSocket->Recv(fProtocol, what) != 2*sizeof(Int_t)) {
Error("TSlave", "failed to receive remote PROOF protocol");
SafeDelete(fSocket);
return;
}
// protocols less than 4 are incompatible
if (fProtocol < 4) {
Error("TSlave", "incompatible PROOF versions (remote version must be >= 4, is %d)", fProtocol);
SafeDelete(fSocket);
return;
}
fProof->fProtocol = fProtocol; // on master this is the protocol
// of the last slave
// send user name to remote host
// for UsrPwd and SRP methods send also passwd, rsa encoded
TMessage pubkey;
TString passwd = "";
Bool_t pwhash = kFALSE;
Bool_t srppwd = kFALSE;
Bool_t sndsrp = kFALSE;
TPwdCtx *pwdctx = 0;
if (RemoteOffSet > -1 &&
(fSecContext->IsA("UsrPwd") || fSecContext->IsA("SRP")))
pwdctx = (TPwdCtx *)(fSecContext->GetContext());
if (!fProof->IsMaster()) {
if (gEnv->GetValue("Proofd.SendSRPPwd",0))
if (RemoteOffSet > -1)
sndsrp = kTRUE;
} else {
if (fSecContext->IsA("SRP") && pwdctx) {
if (pwdctx->GetPasswd() != "" && RemoteOffSet > -1)
sndsrp = kTRUE;
}
}
if ((fSecContext->IsA("UsrPwd") && pwdctx) ||
(fSecContext->IsA("SRP") && sndsrp)) {
// Send offset to identify remotely the public part of RSA key
if (fSocket->Send(RemoteOffSet,kROOTD_RSAKEY) != 2*sizeof(Int_t)) {
Error("TSlave", "failed to send offset in RSA key");
SafeDelete(fSocket);
return;
}
if (pwdctx) {
passwd = pwdctx->GetPasswd();
pwhash = pwdctx->IsPwHash();
}
srppwd = fSecContext->IsA("SRP");
if (fSocket->SecureSend(passwd,1,fSecContext->GetRSAKey()) == -1) {
if (RemoteOffSet > -1)
Warning("TSlave","problems secure-sending pass hash %s",
"- may result in failures");
// If non RSA encoding available try passwd inversion
if (fSecContext->IsA("UsrPwd")) {
for (int i = 0; i < passwd.Length(); i++) {
char inv = ~passwd(i);
passwd.Replace(i, 1, inv);
}
TMessage mess;
mess << passwd;
if (fSocket->Send(mess) < 0) {
Error("TSlave", "failed to send inverted password");
SafeDelete(fSocket);
return;
}
}
}
} else {
// Send notification of no offset to be sent ...
if (fSocket->Send(-2, kROOTD_RSAKEY) != 2*sizeof(Int_t)) {
Error("TSlave", "failed to send no offset notification in RSA key");
SafeDelete(fSocket);
return;
}
}
// Send ordinal (and config) info to slave (or master)
TMessage mess;
if (stype == kMaster)
mess << fUser << pwhash << srppwd << fOrdinal << TString(conffile);
else
mess << fUser << pwhash << srppwd << fOrdinal << fProofWorkDir;
if (fSocket->Send(mess) < 0) {
Error("TSlave", "failed to send ordinal and config info");
SafeDelete(fSocket);
return;
}
if (ProofdProto > 6) {
// Now we send authentication details to access, e.g., data servers
// not in the proof cluster and to be propagated to slaves.
// This is triggered by the 'proofserv <dserv1> <dserv2> ...'
// line in .rootauthrc
if (fSocket->SendHostAuth() < 0) {
Error("TSlave", "failed to send HostAuth info");
SafeDelete(fSocket);
return;
}
}
// set some socket options
fSocket->SetOption(kNoDelay, 1);
}
} else
SafeDelete(fSocket);
}
//______________________________________________________________________________
TSlave::~TSlave()
{
// Destroy slave.
Close();
}
//______________________________________________________________________________
void TSlave::Close(Option_t *)
{
// Close slave socket.
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.
Printf("*** Slave %s (%s)", fOrdinal.Data(), fSocket ? "valid" : "invalid");
Printf(" Host name: %s", GetName());
Printf(" Port number: %d", GetPort());
if (fSocket) {
Printf(" User: %s", GetUser());
Printf(" Security context: %s", fSecContext->AsString());
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();
}
ROOT page - Class index - Class Hierarchy - Top of the page
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.