00001
00002
00003
00004
00005
00006
00008
00009 #include "Rotorooter/RotoClient.h"
00010
00011 #include "MessageService/MsgService.h"
00012
00013 #include "TSocket.h"
00014 #include "TSystem.h"
00015
00016
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
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;
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;
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
00311 fSocket->SetOption(kRecvBuffer,1024);
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
00365
00366
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
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
00394
00395 fSocket->SendRaw(&cmd.fEncoded,sizeof(Int_t));
00396 if (nSendBytes && sendBuffer) {
00397
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
00416
00417
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
00437
00438
00439
00440 RotoRcCmd expect_ack = cmd;
00441 expect_ack.SwapToFrom();
00442 expect_ack.SetType(MINOS_ROOTER_ACKNOWLEDGE);
00443 expect_ack.SetDataToFollow(false);
00444
00445 fSocket->RecvRaw(&fLastCommandAck.fEncoded,sizeof(Int_t));
00446
00447 Int_t nNackBytes = 0;
00448 Char_t* nackBuffer = 0;
00449 if (fLastCommandAck.HasDataToFollow()) {
00450
00451 fSocket->RecvRaw(&nNackBytes,sizeof(Int_t));
00452
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
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
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
00534
00535 fLastCommandState = report;
00536 break;
00537 case MINOS_ROOTER_REQ_STATUS_REPORT:
00538 if (report.HasDataToFollow()) {
00539
00540 fSocket->RecvRaw(&nStatusBytes,sizeof(Int_t));
00541
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