Libbarrett  1.2.4
examples/ex11_master_master.h
00001 /*
00002  * ex11_master_master.h
00003  *
00004  *  Created on: Feb 22, 2010
00005  *      Author: Christopher Dellin
00006  *      Author: Dan Cody
00007  */
00008 
00009 #ifndef MASTER_MASTER_H_
00010 #define MASTER_MASTER_H_
00011 
00012 
00013 #include <stdexcept>
00014 
00015 #include <syslog.h>
00016 #include <unistd.h> /* for close() */
00017 #include <sys/socket.h> /* For sockets */
00018 #include <fcntl.h>      /* To change socket to nonblocking mode */
00019 #include <arpa/inet.h>  /* For inet_pton() */
00020 
00021 #include <barrett/detail/ca_macro.h>
00022 #include <barrett/thread/abstract/mutex.h>
00023 #include <barrett/thread/disable_secondary_mode_warning.h>
00024 #include <barrett/units.h>
00025 #include <barrett/systems/abstract/single_io.h>
00026 
00027 
00028 template <size_t DOF>
00029 class MasterMaster : public barrett::systems::SingleIO<typename barrett::units::JointPositions<DOF>::type, typename barrett::units::JointPositions<DOF>::type> {
00030         BARRETT_UNITS_TEMPLATE_TYPEDEFS(DOF);
00031 
00032 public:
00033         explicit MasterMaster(barrett::systems::ExecutionManager* em, char* remoteHost, int port = 5555, const std::string& sysName = "MasterMaster") :
00034                 barrett::systems::SingleIO<jp_type,jp_type>(sysName), sock(-1), linked(false), numMissed(NUM_MISSED_LIMIT), theirJp(0.0)
00035         {
00036                 int err;
00037                 long flags;
00038                 int buflen;
00039                 unsigned int buflenlen;
00040                 struct sockaddr_in bind_addr;
00041                 struct sockaddr_in their_addr;
00042 
00043                 /* Create socket */
00044                 sock = socket(PF_INET, SOCK_DGRAM, 0);
00045                 if (sock == -1)
00046                 {
00047                         syslog(LOG_ERR,"%s: Could not create socket.",__func__);
00048                         throw std::runtime_error("(MasterMaster::MasterMaster): Ctor failed. Check /var/log/syslog.");
00049                 }
00050 
00051                 /* Set socket to non-blocking, set flag associated with open file */
00052                 flags = fcntl(sock, F_GETFL, 0);
00053                 if (flags < 0)
00054                 {
00055                         syslog(LOG_ERR,"%s: Could not get socket flags.",__func__);
00056                         throw std::runtime_error("(MasterMaster::MasterMaster): Ctor failed. Check /var/log/syslog.");
00057                 }
00058                 flags |= O_NONBLOCK;
00059                 err = fcntl(sock, F_SETFL, flags);
00060                 if (err < 0)
00061                 {
00062                         syslog(LOG_ERR,"%s: Could not set socket flags.",__func__);
00063                         throw std::runtime_error("(MasterMaster::MasterMaster): Ctor failed. Check /var/log/syslog.");
00064                 }
00065 
00066                 /* Maybe set UDP buffer size? */
00067                 buflenlen = sizeof(buflen);
00068                 err = getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *)&buflen, &buflenlen);
00069                 if (err)
00070                 {
00071                         syslog(LOG_ERR,"%s: Could not get output buffer size.",__func__);
00072                         throw std::runtime_error("(MasterMaster::MasterMaster): Ctor failed. Check /var/log/syslog.");
00073                 }
00074                 syslog(LOG_ERR,"%s: Note, output buffer is %d bytes.",__func__,buflen);
00075 
00076                 buflenlen = sizeof(buflen);
00077                 buflen = 5 * SIZE_OF_MSG;
00078                 err = setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *)&buflen, buflenlen);
00079                 if (err)
00080                 {
00081                         syslog(LOG_ERR,"%s: Could not set output buffer size.",__func__);
00082                         throw std::runtime_error("(MasterMaster::MasterMaster): Ctor failed. Check /var/log/syslog.");
00083                 }
00084 
00085                 buflenlen = sizeof(buflen);
00086                 err = getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *)&buflen, &buflenlen);
00087                 if (err)
00088                 {
00089                         syslog(LOG_ERR,"%s: Could not get output buffer size.",__func__);
00090                         throw std::runtime_error("(MasterMaster::MasterMaster): Ctor failed. Check /var/log/syslog.");
00091                 }
00092                 syslog(LOG_ERR,"%s: Note, output buffer is %d bytes.",__func__,buflen);
00093 
00094                 /* Set up the bind address */
00095                 bind_addr.sin_family = AF_INET;
00096                 bind_addr.sin_port = htons(port);
00097                 bind_addr.sin_addr.s_addr = htonl(INADDR_ANY);
00098                 err = bind(sock, (struct sockaddr *)&bind_addr, sizeof(bind_addr));
00099                 if (err == -1)
00100                 {
00101                         syslog(LOG_ERR,"%s: Could not bind to socket on port %d.",__func__,port);
00102                         throw std::runtime_error("(MasterMaster::MasterMaster): Ctor failed. Check /var/log/syslog.");
00103                 }
00104 
00105                 /* Set up the other guy's address */
00106                 their_addr.sin_family = AF_INET;
00107                 their_addr.sin_port = htons(port);
00108                 err = ! inet_pton(AF_INET, remoteHost, &their_addr.sin_addr);
00109                 if (err)
00110                 {
00111                         syslog(LOG_ERR,"%s: Bad IP argument '%s'.",__func__,remoteHost);
00112                         throw std::runtime_error("(MasterMaster::MasterMaster): Ctor failed. Check /var/log/syslog.");
00113                 }
00114 
00115                 /* Call "connect" to set datagram destination */
00116                 err = connect(sock, (struct sockaddr *)&their_addr, sizeof(struct sockaddr));
00117                 if (err)
00118                 {
00119                         syslog(LOG_ERR,"%s: Could not set datagram destination.",__func__);
00120                         throw std::runtime_error("(MasterMaster::MasterMaster): Ctor failed. Check /var/log/syslog.");
00121                 }
00122 
00123 
00124                 if (em != NULL) {
00125                         em->startManaging(*this);
00126                 }
00127         }
00128 
00129         virtual ~MasterMaster() {
00130                 this->mandatoryCleanUp();
00131 
00132                 close(sock);
00133         }
00134 
00135         bool isLinked() const { return linked; }
00136         void tryLink() {
00137                 BARRETT_SCOPED_LOCK(this->getEmMutex());
00138 
00139                 if (numMissed < NUM_MISSED_LIMIT) {
00140                         linked = true;
00141                 }
00142         }
00143         void unlink() { linked = false; }
00144 
00145 protected:
00146         static const int SIZE_OF_MSG = DOF*sizeof(double);
00147         static const int NUM_MISSED_LIMIT = 10;
00148 
00149         virtual void operate() {
00150 
00151                 {
00152                         // send() and recv() cause switches to secondary mode. The socket is
00153                         // non-blocking, so this *probably* won't impact the control-loop
00154                         // timing that much...
00155                         barrett::thread::DisableSecondaryModeWarning dsmw;
00156 
00157 
00158                         send(sock, this->input.getValue().data(), SIZE_OF_MSG, 0);
00159 
00160                         if (numMissed < NUM_MISSED_LIMIT) {  // prevent numMissed from wrapping
00161                                 ++numMissed;
00162                         }
00163                         while (recv(sock, theirJp.data(), SIZE_OF_MSG, 0) == SIZE_OF_MSG) {
00164                                 numMissed = 0;
00165                         }
00166                 }
00167 
00168                 if ( !linked  ||  numMissed >= NUM_MISSED_LIMIT) {
00169                         linked = false;
00170                         theirJp = this->input.getValue();
00171                 }
00172 
00173                 this->outputValue->setData(&theirJp);
00174         }
00175 
00176         int sock;
00177         bool linked;
00178         int numMissed;
00179         jp_type theirJp;
00180 
00181 private:
00182         DISALLOW_COPY_AND_ASSIGN(MasterMaster);
00183 };
00184 
00185 
00186 #endif /* MASTER_MASTER_H_ */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Defines