Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

RotoClient.cxx

Go to the documentation of this file.
00001 
00002 // $Id: RotoClient.cxx,v 1.7 2007/07/09 00:50:06 rhatcher Exp $
00003 //
00004 // A JobControl  for sending raw blocks to the Roto-Rooter
00005 //
00006 // rhatcher@fnal.gov
00008 
00009 #include "Rotorooter/RotoClient.h"
00010 
00011 #include "MessageService/MsgService.h"
00012 
00013 #include "TSocket.h"
00014 #include "TSystem.h"
00015 
00016 // for function: char* Form(const char *fmt, ...)
00017 #include "TString.h"
00018 
00019 const UInt_t dbg_ReportCmd    = 0x0001;
00020 const UInt_t dbg_ReportReply  = 0x0002;
00021 const UInt_t dbg_ReportHex    = 0x0004;
00022 const UInt_t dbg_ReportConn   = 0x0008;
00023 
00024 #define ALLOW_ROTOTALK
00025 #ifdef  ALLOW_ROTOTALK
00026 #include "OnlineUtil/rototalk.h"
00027 #endif
00028 
00029 UInt_t RotoClient::fgDebugFlags = 0;
00030 //   dbg_ReportCmd | dbg_ReportReply | dbg_ReportConn ; //| dbg_ReportHex;
00031 
00032 static string reportOpt = 
00033   (RotoClient::GetDebugFlags() & dbg_ReportHex) ? "b" : " ";
00034 
00035 ClassImp(RotoClient)
00036 CVSID("$Id: RotoClient.cxx,v 1.7 2007/07/09 00:50:06 rhatcher Exp $");
00037 
00038 //_____________________________________________________________________________
00039 RotoClient::RotoClient(const Char_t* ipaddress, Int_t port, 
00040                        MinosRooterEntity whom, Bool_t useRototalk) 
00041    : fRcWhoAmI(whom), fSocket(0), fIPAddress(ipaddress), fLastCommandAck(), 
00042      fLastCommandState(RUN_STATE_UNKNOWN), fUseRototalk(useRototalk)
00043 {
00044 
00045    Bool_t ok = SetupConnection(ipaddress,port);
00046 
00047    MSG("Roto", Msg::kVerbose) << "RotoClient::ctor okay = " << (int)ok << endl;
00048 }
00049 
00050 //_____________________________________________________________________________
00051 RotoClient::~RotoClient() 
00052 {
00053 
00054    Bool_t ok = CloseConnection();
00055 
00056    MSG("Roto", Msg::kVerbose) << "RotoClient::dtor okay = " << (int)ok << endl;
00057 
00058 }
00059 
00060 //_____________________________________________________________________________
00061 Bool_t RotoClient::Connected()
00062 {
00063 
00064 #ifdef ALLOW_ROTOTALK
00065   if (fUseRototalk) return true;
00066 #endif
00067    if (!fSocket) return false;
00068    return fSocket->IsValid();
00069 
00070 
00071 }
00072 
00073 
00074 //_____________________________________________________________________________
00075 Bool_t RotoClient::OpenDAQFile(Int_t detector, Int_t run, Int_t subrun)
00076 {
00077 
00078 #ifdef ALLOW_ROTOTALK
00079    if (fUseRototalk) return roto_open_daqfile(detector,run,subrun);
00080 #endif
00081    Int_t minibuff[4];
00082    minibuff[0] = MINOS_ROOTER_DCP;
00083    minibuff[1] = detector;
00084    minibuff[2] = run;
00085    minibuff[3] = subrun;
00086    RotoRcCmd cmd(fRcWhoAmI,
00087                  MINOS_ROOTER_ROOTER,
00088                  MINOS_ROOTER_COMMAND,
00089                  MINOS_ROOTER_OPENFILE,
00090                  true);
00091    return SendCommand(cmd,4*sizeof(Int_t),minibuff);
00092 
00093 }
00094 
00095 //_____________________________________________________________________________
00096 Bool_t RotoClient::OpenDCSFile(Int_t detector, Int_t sec, Int_t nanosec)
00097 {
00098 
00099 #ifdef ALLOW_ROTOTALK
00100   if (fUseRototalk) return roto_open_dcsfile(detector,sec,nanosec);
00101 #endif
00102    Int_t minibuff[4];
00103    minibuff[0] = MINOS_ROOTER_DCS;
00104    minibuff[1] = detector;
00105    minibuff[2] = sec;
00106    minibuff[3] = nanosec;
00107    RotoRcCmd cmd(fRcWhoAmI,
00108                  MINOS_ROOTER_ROOTER,
00109                  MINOS_ROOTER_COMMAND,
00110                  MINOS_ROOTER_OPENFILE,
00111                  true);
00112    return SendCommand(cmd,4*sizeof(Int_t),minibuff);
00113 
00114 }
00115 
00116 //_____________________________________________________________________________
00117 Bool_t RotoClient::OpenBeamMonFile(Int_t detector, Int_t sec, Int_t nanosec)
00118 {
00119 
00120 #ifdef ALLOW_ROTOTALK
00121   if (fUseRototalk) return roto_open_beammonfile(sec,nanosec);
00122 #endif
00123    Int_t minibuff[4];
00124    minibuff[0] = MINOS_ROOTER_BEAMMON;
00125    minibuff[1] = detector;
00126    minibuff[2] = sec;
00127    minibuff[3] = nanosec;
00128    RotoRcCmd cmd(fRcWhoAmI,
00129                  MINOS_ROOTER_ROOTER,
00130                  MINOS_ROOTER_COMMAND,
00131                  MINOS_ROOTER_OPENFILE,
00132                  true);
00133    return SendCommand(cmd,4*sizeof(Int_t),minibuff);
00134 
00135 }
00136 
00137 //_____________________________________________________________________________
00138 Bool_t RotoClient::CloseDAQFile(Int_t detector, Int_t run, Int_t subrun)
00139 {
00140 
00141 #ifdef ALLOW_ROTOTALK
00142   if (fUseRototalk) return roto_close_daqfile(detector,run,subrun);
00143 #endif
00144    Int_t minibuff[4];
00145    minibuff[0] = MINOS_ROOTER_DCP;
00146    minibuff[1] = detector;
00147    minibuff[2] = run;
00148    minibuff[3] = subrun;
00149    RotoRcCmd cmd(fRcWhoAmI,
00150                  MINOS_ROOTER_ROOTER,
00151                  MINOS_ROOTER_COMMAND,
00152                  MINOS_ROOTER_CLOSEFILE,
00153                  true);
00154    return SendCommand(cmd,4*sizeof(Int_t),minibuff);
00155 
00156 }
00157 
00158 //_____________________________________________________________________________
00159 Bool_t RotoClient::CloseDCSFile(Int_t detector, Int_t sec, Int_t nanosec)
00160 {
00161 #ifdef ALLOW_ROTOTALK
00162   if (fUseRototalk) return roto_close_dcsfile();
00163 #endif
00164    Int_t minibuff[4];
00165    minibuff[0] = MINOS_ROOTER_DCS;
00166    minibuff[1] = detector;
00167    minibuff[2] = sec;
00168    minibuff[3] = nanosec;
00169    RotoRcCmd cmd(fRcWhoAmI,
00170                  MINOS_ROOTER_ROOTER,
00171                  MINOS_ROOTER_COMMAND,
00172                  MINOS_ROOTER_CLOSEFILE,
00173                  true);
00174    return SendCommand(cmd,4*sizeof(Int_t),minibuff);
00175 
00176 }
00177 
00178 //_____________________________________________________________________________
00179 Bool_t RotoClient::CloseBeamMonFile(Int_t detector, Int_t sec, Int_t nanosec)
00180 {
00181 
00182 #ifdef ALLOW_ROTOTALK
00183   if (fUseRototalk) return roto_close_beammonfile();
00184 #endif
00185    Int_t minibuff[4];
00186    minibuff[0] = MINOS_ROOTER_BEAMMON;
00187    minibuff[1] = detector;
00188    minibuff[2] = sec;
00189    minibuff[3] = nanosec;
00190    RotoRcCmd cmd(fRcWhoAmI,
00191                  MINOS_ROOTER_ROOTER,
00192                  MINOS_ROOTER_COMMAND,
00193                  MINOS_ROOTER_CLOSEFILE,
00194                  true);
00195    return SendCommand(cmd,4*sizeof(Int_t),minibuff);
00196 
00197 }
00198 
00199 //_____________________________________________________________________________
00200 Bool_t RotoClient::OpenFile(const string& fname)
00201 {
00202 
00203 #ifdef ALLOW_ROTOTALK
00204   if (fUseRototalk) return roto_open_named_file(fname.c_str());
00205 #endif
00206    RotoRcCmd cmd(fRcWhoAmI,
00207                  MINOS_ROOTER_ROOTER,
00208                  MINOS_ROOTER_COMMAND,
00209                  MINOS_ROOTER_OPENFILE,
00210                  true);
00211    int nbytes = fname.length()+1; // don't forget the trailing \0
00212    return SendCommand(cmd,nbytes,fname.c_str());
00213 
00214 }
00215 
00216 //_____________________________________________________________________________
00217 Bool_t RotoClient::CloseFile(const string& fname)
00218 {
00219 
00220 #ifdef ALLOW_ROTOTALK
00221   if (fUseRototalk) return roto_close_named_file(fname.c_str());
00222 #endif
00223    RotoRcCmd cmd(fRcWhoAmI,
00224                  MINOS_ROOTER_ROOTER,
00225                  MINOS_ROOTER_COMMAND,
00226                  MINOS_ROOTER_CLOSEFILE,
00227                  true);
00228    int nbytes = fname.length()+1; // don't forget the trailing \0
00229    return SendCommand(cmd,nbytes,fname.c_str());
00230 
00231 }
00232 
00233 //_____________________________________________________________________________
00234 Bool_t RotoClient::GetRotoStatus(Char_t* statusBuffer, Int_t maxBytes)
00235 {
00236 
00237 #ifdef ALLOW_ROTOTALK
00238   if (fUseRototalk) {
00239     MSG("Roto",Msg::kWarning) 
00240       << " ********** GetRotoStatus() called, no rototalk equiv. " << endl;
00241     return 1;
00242   }
00243 #endif
00244    RotoRcCmd cmd(fRcWhoAmI,
00245                  MINOS_ROOTER_ROOTER,
00246                  MINOS_ROOTER_REQUEST,
00247                  MINOS_ROOTER_REQ_CURRENT_STATE,
00248                  false);
00249    Bool_t status = SendCommand(cmd,0,0);
00250 
00251    fStatusReport.copy(statusBuffer,maxBytes-1);
00252    statusBuffer[maxBytes] = 0;
00253 
00254    return status;
00255 
00256 }
00257 
00258 //_____________________________________________________________________________
00259 Bool_t RotoClient::SendRecordBuffer(const void* buffer, Int_t nbytes)
00260 {
00261 
00262 #ifdef ALLOW_ROTOTALK
00263   if (fUseRototalk) return roto_send_record(buffer,nbytes);
00264 #endif
00265    RotoRcCmd cmd(fRcWhoAmI,
00266                  MINOS_ROOTER_ROOTER,
00267                  MINOS_ROOTER_COMMAND,
00268                  MINOS_ROOTER_RECBUFFER,
00269                  true);
00270    Bool_t status = SendCommand(cmd,nbytes,buffer);
00271 
00272    return status;
00273 
00274 }
00275 
00276 //_____________________________________________________________________________
00277 Bool_t RotoClient::SendShutdownMessage()
00278 {
00279 
00280 #ifdef ALLOW_ROTOTALK
00281   if (fUseRototalk) return roto_request_shutdown(1);
00282 #endif
00283    RotoRcCmd cmd(fRcWhoAmI,
00284                  MINOS_ROOTER_ROOTER,
00285                  MINOS_ROOTER_COMMAND,
00286                  MINOS_ROOTER_SHUTDOWN,
00287                  false);
00288    return SendCommand(cmd,0,0);
00289 
00290 }
00291 
00292 //_____________________________________________________________________________
00293 Bool_t RotoClient::SetupConnection(const Char_t* ipaddress, Int_t port)
00294 {
00295 
00296 #ifdef ALLOW_ROTOTALK
00297   if (fUseRototalk) return roto_open_connection(ipaddress,port,fRcWhoAmI);
00298 #endif
00299    if ( !ipaddress || port<=0 ) return false;
00300 
00301    fSocket = new TSocket(ipaddress,port);
00302 
00303    if (fgDebugFlags & dbg_ReportConn) 
00304       MSG("Roto",Msg::kInfo) 
00305          << Form("Open TSocket connection at %s:%d -- %svalid\n",
00306                  ipaddress,port,((fSocket->IsValid()) ? "" : "in"))
00307          << endl;
00308 
00309    if (!fSocket->IsValid()) { delete fSocket; fSocket=0; return false; }
00310    // fSocket->SetOption(kKeepAlive,1);
00311    fSocket->SetOption(kRecvBuffer,1024); // small packets back
00312 
00313    RotoRcCmd cmd(fRcWhoAmI,
00314                  MINOS_ROOTER_ROOTER,
00315                  MINOS_ROOTER_COMMAND,
00316                  MINOS_ROOTER_OPENSOCKET,
00317                  false);
00318    return SendCommand(cmd,0,0);
00319 
00320 }
00321 
00322 //_____________________________________________________________________________
00323 Bool_t RotoClient::CloseConnection()
00324 {
00325 
00326 #ifdef ALLOW_ROTOTALK
00327   if (fUseRototalk) return roto_close_connection();
00328 #endif
00329    if (fgDebugFlags & dbg_ReportConn) 
00330       MSG("Roto", Msg::kInfo) 
00331          << "RotoClient::CloseConnection" 
00332          << " Connected = " << (int)Connected() << endl;
00333 
00334    if (!Connected()) return false;
00335 
00336    RotoRcCmd cmd(fRcWhoAmI,
00337                  MINOS_ROOTER_ROOTER,
00338                  MINOS_ROOTER_COMMAND,
00339                  MINOS_ROOTER_CLOSESOCKET,
00340                  false);
00341    Bool_t status = SendCommand(cmd,0,0);
00342 
00343    CloseAndDeleteSocket(fSocket);
00344 
00345    return status;
00346 
00347 }
00348 
00349 //_____________________________________________________________________________
00350 void RotoClient::CloseAndDeleteSocket(TSocket*& socket)
00351 {
00352    if (socket) {
00353       if (socket->IsValid()) socket->Close();
00354       delete socket;
00355       socket = 0;
00356    }
00357 }
00358 
00359 //_____________________________________________________________________________
00360 Bool_t RotoClient::SendCommand(RotoRcCmd& cmd,
00361                                Int_t  nSendBytes,
00362                                const void*  sendBuffer)
00363 {
00364    // send a command to the Rotorooter, along with possible
00365    // additional information
00366    // receive ACK/NACK and results from any request
00367 
00368    if (!Connected()) {
00369       fLastCommandAck  = MINOS_ROOTER_UNABLE_TO;
00370       fLastCommandState = MINOS_ROOTER_STATE_UNCONNECTED;
00371       return false;
00372    }
00373 
00374    static Int_t nmsg = 0;
00375    nmsg++;
00376 
00377 #ifdef VERBOSE_MSG
00378 //rwh: very verbose
00379    MSG("Roto",Msg::kInfo) << " Send "
00380                           << cmd.AsStlString() << endl;
00381 #endif
00382 
00383    if ( (nSendBytes && sendBuffer) != cmd.HasDataToFollow() ) {
00384       MSG("Roto",Msg::kInfo)
00385          << "RotoClient::SendCommand HasDataToFollow mismatch "
00386          << nSendBytes << " bytes vs. flag "
00387          << (int)cmd.HasDataToFollow()
00388          << endl;
00389       cmd.SetDataToFollow(nSendBytes);
00390    }
00391 
00392    //
00393    // send the command and optional extra data
00394    //
00395    fSocket->SendRaw(&cmd.fEncoded,sizeof(Int_t));
00396    if (nSendBytes && sendBuffer) {
00397       // byte count includes its own 4 bytes
00398       Int_t nbytes = nSendBytes + 4;
00399       fSocket->SendRaw(&nbytes,sizeof(Int_t));
00400       fSocket->SendRaw(sendBuffer,nSendBytes);
00401    }
00402 
00403    if (fgDebugFlags & dbg_ReportCmd) {
00404       string extra(" ");
00405       if (nSendBytes) 
00406          extra += Form("\n with %d (0x%x) extra bytes",nSendBytes,nSendBytes);
00407       MSG("Roto", Msg::kInfo) 
00408          << "RotoClient::SendCommand msg#" 
00409          << nmsg 
00410          << " " << cmd.AsStlString(reportOpt)
00411          << extra 
00412          << endl;
00413    }
00414 
00415    // should do something here in
00416    // case Roto doesn't respond ... ie. correctly handle
00417    // timeout situation --- currently just blocks forever
00418 
00419    switch (cmd.GetType()) {
00420    case MINOS_ROOTER_COMMAND:
00421       return ReceiveCommandReply(cmd,nmsg);
00422       break;
00423    case MINOS_ROOTER_REQUEST:
00424       return ReceiveRequestReply(cmd,nmsg);
00425       break;
00426    default:
00427       return false;
00428    }
00429 
00430 }
00431 
00432 //_____________________________________________________________________________
00433 Bool_t RotoClient::ReceiveCommandReply(RotoRcCmd& cmd, Int_t nmsg)
00434 {
00435    // 
00436    // commands require an acknowledgement and state_report
00437    // allow for extended information in case of NACK
00438    //
00439 
00440    RotoRcCmd expect_ack = cmd;
00441    expect_ack.SwapToFrom();
00442    expect_ack.SetType(MINOS_ROOTER_ACKNOWLEDGE);
00443    expect_ack.SetDataToFollow(false);
00444    // RWH 2007-06-29  All the time is spend in next line!
00445    fSocket->RecvRaw(&fLastCommandAck.fEncoded,sizeof(Int_t));
00446 
00447    Int_t   nNackBytes = 0;
00448    Char_t* nackBuffer = 0;
00449    if (fLastCommandAck.HasDataToFollow()) {
00450       // get the followup data
00451       fSocket->RecvRaw(&nNackBytes,sizeof(Int_t));
00452       // byte count includes its own 4 bytes
00453       nNackBytes -= 4;
00454       if (nNackBytes>0) {
00455          nackBuffer = new Char_t[nNackBytes+1];
00456          nackBuffer[nNackBytes] = 0;
00457          fSocket->RecvRaw(nackBuffer,nNackBytes);
00458          fNackReport = nackBuffer;
00459          delete [] nackBuffer;
00460       }
00461    }
00462 
00463    //
00464    // protocol says COMMAND also gets a STATE_REPORT reply
00465    //
00466    fSocket->RecvRaw(&fLastCommandState.fEncoded,sizeof(Int_t));
00467  
00468   if (fgDebugFlags & dbg_ReportReply) {
00469       string match;
00470       string nackmsg = "";
00471       if (fLastCommandAck == expect_ack) {
00472          match = " ok ";
00473       } else {
00474          match = "\n          should be ";
00475          match += expect_ack.AsStlString(reportOpt);
00476          if (fNackReport != "") {
00477             nackmsg = "\n       NACK message: \"";
00478             nackmsg += fNackReport;
00479             nackmsg += "\"";
00480          }
00481       }
00482       MSG("Roto", Msg::kInfo)
00483          << "RotoClient::SendCommand reply#" 
00484          << nmsg 
00485          << " " << fLastCommandAck.AsStlString(reportOpt)
00486          << match
00487          << nackmsg
00488          << " state report " << fLastCommandState.AsStlString(reportOpt)
00489          << endl;
00490    }
00491 
00492   return fLastCommandAck.TestAckAsBool();
00493 }
00494 
00495 //_____________________________________________________________________________
00496 Bool_t RotoClient::ReceiveRequestReply(RotoRcCmd& cmd, Int_t nmsg)
00497 {
00498    //
00499    // if sent message was a REQUEST the handle the reply
00500    //
00501 
00502    RotoRcCmd report;
00503    RotoRcCmd expect_report = cmd;
00504    expect_report.SwapToFrom();
00505    expect_report.SetType(MINOS_ROOTER_REPORT);
00506    bool expectfollowup = false;
00507    if (cmd.GetInstr() == MINOS_ROOTER_REQ_STATUS_REPORT) expectfollowup = true;
00508    expect_report.SetDataToFollow(expectfollowup);
00509    
00510    fSocket->RecvRaw(&report.fEncoded,sizeof(Int_t));
00511 
00512    if (fgDebugFlags & dbg_ReportReply) {
00513       string match;
00514       if (report == expect_report) {
00515          match = " as expected ";
00516       } else {
00517          match = "\n          should be ";
00518          match += expect_report.AsStlString(reportOpt);
00519       }
00520       MSG("Roto", Msg::kInfo)
00521          << "RotoClient::SendCommand reply#" 
00522          << nmsg 
00523          << " " << report.AsStlString(reportOpt)
00524          << match
00525          << endl;
00526    }
00527 
00528    Int_t   nStatusBytes = 0;
00529    Char_t* statusBuffer = 0;
00530 
00531    switch (cmd.GetInstr()) {
00532    case MINOS_ROOTER_REQ_CURRENT_STATE:
00533       // if instruction was CURRENT_STATE then one expects 
00534       // REPORT CURRENT_STATE and this is like a COMMAND reply
00535       fLastCommandState = report;
00536       break;
00537    case MINOS_ROOTER_REQ_STATUS_REPORT:
00538       if (report.HasDataToFollow()) {
00539          // get the followup data
00540          fSocket->RecvRaw(&nStatusBytes,sizeof(Int_t));
00541          // byte count includes its own 4 bytes
00542          nStatusBytes -= 4;
00543          if (nStatusBytes>0) {
00544             statusBuffer = new Char_t[nStatusBytes+1];
00545             statusBuffer[nStatusBytes] = 0;
00546             fSocket->RecvRaw(statusBuffer,nStatusBytes);
00547             fStatusReport = statusBuffer;
00548             delete [] statusBuffer;
00549         }
00550       }
00551       break;
00552    default:
00553       return false;
00554    }
00555 
00556    return true;
00557 }
00558 
00559 //_____________________________________________________________________________
00560 

Generated on Mon Feb 15 11:07:32 2010 for loon by  doxygen 1.3.9.1