SCTDdcCommandSender.cxx

00001 
00002 // This file contains the class definition to issue 
00003 // a non-transition command (inspired from DDC code package)
00004 //                  
00005 //    Created 01.04.03
00006 //    by A. Abdesselam
00008 
00009 #include <string>
00010 
00011 //#include <is/isnamedinfo.h>
00012 #include <is/info.h>
00013 #include <is/infodictionary.h>
00014 #include <is/infoiterator.h>
00015 #include <is/inforeceiver.h>
00016 #include <is/infoT.h>
00017 #include "sctddc/SCTDdcCommandSender.hxx"
00018 #include <unistd.h> // for usleep
00019 
00020 using namespace std;
00021 
00022 
00023   //SCTDdcCommandSender(IPCPartition& p, string** ctrlList);
00024 SCTDdcCommandSender::SCTDdcCommandSender(IPCPartition& partition, string** ctrlList) 
00025   : m_partition(partition), m_commandAllowed(true), m_commandResponse(-99999), m_ctrlNum(0),
00026     m_controllers(ctrlList)
00027 {
00028   m_receiver = new ISInfoReceiver(partition);
00029 }
00030 
00031 // ~SCTDdcCommandSender();
00032 SCTDdcCommandSender::~SCTDdcCommandSender() 
00033 {
00034   delete m_receiver;
00035 }
00036 
00037 void callback(ISCallbackInfo* cbInfo)
00038 {
00039   SCTDdcCommandSender* sctDdcCommandSender = (SCTDdcCommandSender*)(cbInfo->parameter());
00040   
00041   DdcNtCommandResponse  result(sctDdcCommandSender->getPartition(),
00042                    (char*)cbInfo->name(), 0);
00043   string infoName(cbInfo->name());
00044 
00045   string ctrlName;
00046   
00047   //find the controller name. the received name has the format: command.controller.response
00048   ctrlName = infoName.substr(infoName.find('.')+1);
00049   ctrlName = ctrlName.substr(ctrlName.find('.')+1);
00050   ctrlName = ctrlName.substr(0, ctrlName.find("response")-1);
00051 
00052   if(cbInfo->reason() != is::Deleted) 
00053     {
00054       if(cbInfo->type() == result.type()) 
00055     {
00056       cbInfo->value(result);
00057       sctDdcCommandSender->setCommandResponse(result.getValue());
00058       if(result.getValue() <0) 
00059         {
00060           cerr << "SCTDdcCommandSender: Result of the "
00061            << sctDdcCommandSender->getCommand() << " command on " << ctrlName << " is ";
00062           // set the response command code
00063           
00064           switch(result.getValue()) 
00065         {
00066         case COMM_ERR_OK:
00067           cerr << "OK" << endl;
00068           break;
00069         case COMM_ERR_NAME:
00070           cerr << "INVALIDE COMMAND NAME" << endl;
00071           break;
00072         case COMM_ERR_DCSDP:
00073           cerr << "COMMAND NOT DEFINED PROPERLY IN DCS" << endl;
00074           break;
00075         case COMM_ERR_TIMEOUT:
00076           cerr << "TIMEOUT" << endl;
00077           break;
00078         case COMM_ERR_CONNECT:
00079           cerr << "PVSS IS UNAVAILABLE" << endl;
00080           break;
00081         case COMM_ERR_CONNBROKEN:
00082           cerr << "CONNECTION TO DCS LOST" << endl;
00083           break;
00084         case COMM_ERR_NTDESC:
00085           cerr << "INVALID COMMAND DEFINITION IN IS" << endl;
00086           break;
00087           
00088         default:
00089           cerr << "USER'S ERROR STATUS = " << result.getValue() 
00090                <<". THIS IS NOT DEFINED "<< endl;
00091         }
00092         } // end of if(result.getValue() <0) 
00093       sctDdcCommandSender->getReceiver()->unsubscribe(infoName.c_str());
00094       result.remove();
00095       if(sctDdcCommandSender->decreaseCtrlNum() == 0)
00096         {
00097           sctDdcCommandSender->ddcRemoveCommand(ctrlName);
00098           sctDdcCommandSender->ddcRemoveCommand();
00099           
00100           sctDdcCommandSender->setCommandAllowedTrue();
00101         }
00102     }
00103       else 
00104     cerr << "SCTDdcCommandSender: Incorrect response. Assume "
00105          << "an internal error" << endl;
00106     }
00107 }
00108 
00109 //this method  (which overload the method below) is jsut for the purpose to use a defalut 
00110 //controller (*m_controllers[0])
00111 int SCTDdcCommandSender::ddcSendCommand(string& commandName, 
00112                   string& commParameters, unsigned int timeout)
00113 {
00114   string ctrlName = *m_controllers[0];
00115   return ddcSendCommand(ctrlName, commandName, commParameters, timeout);
00116 }
00117 
00118 int SCTDdcCommandSender::ddcSendCommand(string ctrlName, string& commandName, 
00119                   string& commParameters, unsigned int timeout)
00120 {
00121   ISInfo::Status rc;
00122   string  respName;
00123   if(isValidCtrl(ctrlName)) 
00124     {
00125       m_ctrlNum = 0;
00126       if(ctrlName == "*") // send the command to all the contrllers
00127     {
00128       // First subscription for the command results
00129       for(unsigned int i=0; m_controllers[i] != 0; i++) 
00130         {
00131           respName = makeResponseName(*m_controllers[i], commandName);
00132           rc = m_receiver->subscribe(respName.c_str(), callback, (void*)this);
00133           if(rc == ISInfo::Success) 
00134         {
00135           m_ctrlNum += 1;
00136           cerr << "SCTDdcCommandSender_INFO: Subscribed for " << respName << endl;
00137         }
00138           else 
00139         {
00140           cerr << "DdcComander_WARNING: response of " << *m_controllers[i] 
00141                << " is not subscribed for: ERROR code = " << rc << endl;
00142         }
00143         }
00144       
00145       if(m_ctrlNum == 0) 
00146         {
00147           cerr << "SCTDdcCommandSender_ERROR: No response is subscribed" << endl;
00148           cerr << "        ======>    No IS server to send command" << endl;
00149         }
00150       else 
00151         {
00152           // And now sending the command
00153 
00154           
00155           string    commEntryName(COMMAND_SERVER);
00156           
00157           commEntryName = commEntryName + ".DdcNtCommand";
00158 
00159           m_timeout = (timeout == 0) ? DEFAULT_TIMEOUT : timeout;
00160           m_startTime = time(&m_startTime);
00161 
00162           __ddcSendCommand(commEntryName, commandName, 
00163                      commParameters, m_timeout); 
00164           m_commandName = commandName;
00165           m_commandAllowed = false;
00166         }
00167     }//end of if(ctrlName == "*")
00168       else 
00169     {
00170       // First subscription for the command result
00171       respName = makeResponseName(ctrlName, commandName);
00172       rc = m_receiver->subscribe(respName.c_str(), callback, (void*)this);
00173       if(rc != ISInfo::Success) 
00174         {
00175           cerr << "SCTDdcCommandSender_ERROR: " << respName
00176            << " DdcNtCommandResponse subscription fault " << rc << endl;
00177           cerr << "        ======>    No IS server to send command" << endl;;
00178         }
00179       else 
00180         {
00181           // And now sending the command
00182           m_startTime = time(&m_startTime);
00183           m_ctrlNum = 1;
00184           
00185           // send command for an individual DDC controller
00186           string    commEntryName(COMMAND_SERVER);
00187           commEntryName = commEntryName + ".DdcNtCommand" + '.' + ctrlName;
00188           m_timeout = (timeout == 0) ? DEFAULT_TIMEOUT : timeout;
00189 
00190           __ddcSendCommand(commEntryName, commandName, 
00191                      commParameters, m_timeout);
00192 
00193           m_commandName = commandName;
00194           m_commandAllowed = false;
00195         }
00196     }
00197     }
00198   else
00199     {
00200       cerr << "SCTDdcCommandSender_ERROR: Invalid controller name " << ctrlName << endl;
00201     }
00202 
00203   // wait until the command is finish the timeout sepnt
00204   time_t  now;
00205   while(!m_commandAllowed) 
00206     {
00207       usleep(10);
00208       now = time(&now);
00209 
00210       if(now - m_startTime > m_timeout) 
00211     {
00212       for(unsigned int i=0; m_controllers[i] != 0; i++) 
00213         {
00214           string respEntryName = COMMAND_SERVER;
00215           respEntryName = respEntryName + '.' + commandName + '.' 
00216         + *m_controllers[i] + ".response";
00217             m_receiver->unsubscribe(respEntryName.c_str());
00218             
00219             ddcRemoveCommand(*m_controllers[i]);
00220             ddcRemoveCommand();
00221             
00222             m_commandAllowed = true;
00223         }
00224       cerr << "SCTDdcCommandSender: Result of the "
00225            << getCommand() << " command is TIMEOUT" << endl;
00226       break;
00227     }
00228     } //end while(...)
00229   return m_commandResponse;
00230 }
00231 
00232 // Help method (send command)
00233 bool SCTDdcCommandSender::__ddcSendCommand(string& isEntryName, string& commandName, 
00234                                    string& commParameters, unsigned int timeout)
00235 {
00236   ISInfo::Status  rs;
00237   bool    ok = true;
00238 
00239   DdcNtCommand* command = new DdcNtCommand(m_partition, (char*)isEntryName.c_str());
00240 
00241   if(command->isExist()) 
00242     {
00243       cerr << "SCTDdcCommandSender_ERROR: Previous command for the same controller(s)" 
00244        << " seems to be still running" << endl;
00245       ok = false;
00246     }
00247   else 
00248     {
00249       command->setCommName(commandName);
00250       command->setParValue(commParameters);
00251       command->setTimeout(timeout);
00252 
00253       rs = command->checkin();
00254 
00255       if(rs != ISInfo::Success) {
00256     cerr << "SCTDdcCommandSender_ERROR: " << isEntryName
00257          << " command sending fault " << rs << endl;
00258     ok = false;
00259       }
00260     }
00261   delete command;
00262   return(ok);
00263 }
00264 
00265 
00266 bool SCTDdcCommandSender::ddcRemoveCommand(string& ctrlName)
00267 {
00268   ISInfo::Status rs;
00269   bool    ok = true;
00270   string  commEntryName(COMMAND_SERVER);
00271   
00272   commEntryName = commEntryName + ".DdcNtCommand" + '.' + ctrlName;
00273   DdcNtCommand* command = new DdcNtCommand(m_partition, (char*)commEntryName.c_str());
00274   rs = command->remove();
00275   if(rs == ISInfo::CommFailure) {
00276     cerr << "SCTDdcCommandSender_ERROR: " << COMMAND_SERVER
00277      << " is not running in " << m_partition.name() << endl;
00278     ok = false;
00279   }
00280   delete command;
00281   return(ok);
00282 }
00283 
00284 
00285 bool SCTDdcCommandSender::ddcRemoveCommand()
00286 {
00287   ISInfo::Status rs;
00288   bool ok = true;
00289   string commEntryName(COMMAND_SERVER);
00290   
00291   commEntryName = commEntryName + ".DdcNtCommand";
00292   DdcNtCommand* command = new DdcNtCommand(m_partition, (char*)commEntryName.c_str());
00293   rs = command->remove();
00294   if(rs == ISInfo::CommFailure) {
00295     cerr << "SCTDdcCommandSender_ERROR: " << COMMAND_SERVER
00296      << " is not running in " << m_partition.name() << endl;
00297     ok = false;
00298   }
00299   delete command;
00300   return(ok);
00301 }
00302 
00303 string  SCTDdcCommandSender::makeResponseName(string& ctrlName, string& commandName)
00304 {
00305     string  isEntry(COMMAND_SERVER);
00306     
00307     isEntry += '.' + commandName + '.' + ctrlName + ".response";
00308     return(isEntry);
00309 }
00310 
00311 
00312 bool SCTDdcCommandSender::isValidCtrl(string& name)
00313 {
00314   if(name == "*")
00315     {
00316       return(true);
00317     }
00318   else 
00319     {
00320       int i = 0;
00321       while(m_controllers[i] != 0) 
00322     {
00323       if(*m_controllers[i] == name) return(true);
00324       i++;
00325     }
00326       return(false);
00327     }
00328 }

Generated on Mon Feb 6 14:01:29 2006 for SCT DAQ/DCS Software - C++ by  doxygen 1.4.6