Changes between Version 33 and Version 34 of Documentation/Tutorial/PingPong


Ignore:
Timestamp:
Feb 4, 2010, 6:00:49 PM (15 years ago)
Author:
Christoph Mayer
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Documentation/Tutorial/PingPong

    v33 v34  
    5353
    5454{{{
    55 01 #include "PingPong.h"
    56 02 #include "ariba/utility/configuration/Configuration.h"
    57 03
    58 04 using ariba::utility::Configuration;
    59 05 using namespace ariba;
    60 06
    61 07 namespace ariba {
    62 08 namespace application {
    63 09 namespace pingpong {
    64 10
    65 11 // logging
    66 12 use_logging_cpp( PingPong );
    67 13
    68 14 // the service that the pingpong wants to use
    69 15 ServiceID PingPong::PINGPONG_SERVICEID = ServiceID( 111 );
    70 16
    71 17 // construction
    72 18 PingPong::PingPong() : pingId( 0 ) {
    73 19      Timer::setInterval( 5000 );
    74 20 }
    75 21
    76 22 // destruction
    77 23 PingPong::~PingPong() {
    78 24 }
    79 25
    80 26 // implementation of the startup interface
    81 27 void PingPong::startup() {
    82 28
    83 29      logging_info( "starting up PingPong service ... " );
    84 30
    85 31      // create ariba module
    86 32      logging_debug( "creating ariba underlay module ... " );
    87 33      ariba = new AribaModule();
    88 34
    89 35      // get the configuration object
    90 36      Configuration& config = Configuration::instance();
    91 37
    92 38      // generate spovnet name
    93 39      Name spovnetName("pingpong");
    94 40
    95 41     
    96 42     
    97 43
    98 44      // get node name
    99 45      Name nodeName = Name::UNSPECIFIED;
    100 46      if (config.exists("node.name")) nodeName = config.read<string> ("node.name");
    101 47
    102 48      // configure ariba module
    103 49      if (config.exists("ariba.ip.addr")) ariba->setProperty("ip.addr",
    104 50                      config.read<string>("ariba.ip.addr"));
    105 51      if (config.exists("ariba.tcp.port")) ariba->setProperty("tcp.port",
    106 52                      config.read<string>("ariba.tcp.port"));
    107 53      if (config.exists("ariba.udp.port")) ariba->setProperty("udp.port",
    108 54                      config.read<string>("ariba.udp.port"));
    109 55      if (config.exists("ariba.bootstrap.hints")) ariba->setProperty("bootstrap.hints",
    110 56                      config.read<string>("ariba.bootstrap.hints"));
    111 57
    112 58      // start ariba module
    113 59      ariba->start();
    114 60
    115 61      // create node and join
    116 62      node = new Node( *ariba, nodeName );
    117 63
    118 64      // bind communication and node listener
    119 65      node->bind( this );                              /*NodeListener*/
    120 66      node->bind( this, PingPong::PINGPONG_SERVICEID); /*CommunicationListener*/
    121 67
    122 68      // start node module
    123 69      node->start();
    124 70
    125 71      // initiate or join the spovnet
    126 72      if (!isInitiator) node->join(spovnetName);
    127 73      else node->initiate(spovnetName);
    128 74
    129 75      // ping pong started up...
    130 76      logging_info( "pingpong starting up with"
    131 77                      << " [spovnetid " << node->getSpoVNetId().toString() << "]"
    132 78                      << " and [nodeid " << node->getNodeId().toString() << "]" );
    133 79 }
     55     1  #include "PingPong.h"
     56     2  #include "ariba/utility/configuration/Configuration.h"
     57     3  #include "ariba/utility/visual/DddVis.h"
     58     4 
     59     5  using ariba::utility::Configuration;
     60     6  using namespace ariba;
     61     7 
     62     8  namespace ariba {
     63     9  namespace application {
     64    10  namespace pingpong {
     65    11 
     66    12  // logging
     67    13  use_logging_cpp( PingPong );
     68    14 
     69    15  // the service that the pingpong wants to use
     70    16  ServiceID PingPong::PINGPONG_SERVICEID = ServiceID( 111 );
     71    17 
     72    18  // construction
     73    19  PingPong::PingPong() : pingId( 0 ) {
     74    20          Timer::setInterval( 1000 );
     75    21  }
     76    22 
     77    23  // destruction
     78    24  PingPong::~PingPong() {
     79    25  }
     80    26 
     81    27  // implementation of the startup interface
     82    28  void PingPong::startup() {
     83    29 
     84    30          logging_info( "starting up PingPong service ... " );
     85    31 
     86    32          // create ariba module
     87    33          logging_debug( "creating ariba underlay module ... " );
     88    34          ariba = new AribaModule();
     89    35 
     90    36          Name spovnetName("pingpong");
     91    37          Name nodeName = Name::UNSPECIFIED;
     92    38          this->name = string("<ping>");
     93    39 
     94    40          // get settings from configuration object
     95    41          if( Configuration::haveConfig() ){
     96    42                  Configuration& config = Configuration::instance();
     97    43 
     98    44                  // get node name
     99    45                  if (config.exists("node.name"))
     100    46                          nodeName = config.read<string> ("node.name");
     101    47 
     102    48                  // configure ariba module
     103    49                  if (config.exists("ariba.endpoints"))
     104    50                          ariba->setProperty("endpoints", config.read<string>("ariba.endpoints"));
     105    51                  if (config.exists("ariba.bootstrap.hints"))
     106    52                          ariba->setProperty("bootstrap.hints", config.read<string>("ariba.bootstrap.hints"));
     107    53                  if (config.exists("pingpong.name"))
     108    54                          name = config.read<string>("pingpong.name");
     109    55 
     110    56                  // get visualization
     111    57                  if( config.exists("ariba.visual3d.ip") && config.exists("ariba.visual3d.port")){
     112    58                          string ip = config.read<string>("ariba.visual3d.ip");
     113    59                          unsigned int port = config.read<unsigned int>("ariba.visual3d.port");
     114    60                          unsigned int color = config.exists("node.color") ?
     115    61                                          config.read<unsigned int>("node.color") : 0;
     116    62                          ariba::utility::DddVis::instance().configure(ip, port, color);
     117    63                  }
     118    64 
     119    65          } // if( Configuration::haveConfig() )
     120    66 
     121    67          // start ariba module
     122    68          ariba->start();
     123    69 
     124    70          // create node and join
     125    71          node = new Node( *ariba, nodeName );
     126    72 
     127    73          // bind communication and node listener
     128    74          node->bind( this );                              /*NodeListener*/
     129    75          node->bind( this, PingPong::PINGPONG_SERVICEID); /*CommunicationListener*/
     130    76 
     131    77          // start node module
     132    78          node->start();
     133    79 
     134    80          // when initiating, you can define the overlay type, default is Chord [CHORD_OVERLAY]
     135    81          SpoVNetProperties params;
     136    82          //params.setBaseOverlayType( SpoVNetProperties::ONE_HOP_OVERLAY ); // alternative: OneHop
     137    83 
     138    84          // initiate the spovnet
     139    85          logging_info("initiating spovnet");
     140    86          node->initiate(spovnetName, params);
     141    87 
     142    88          // join the spovnet
     143    89          logging_info("joining spovnet");
     144    90          node->join(spovnetName);
     145    91 
     146    92          // ping pong started up...
     147    93          logging_info( "pingpong starting up with"
     148    94                          << " [spovnetid " << node->getSpoVNetId().toString() << "]"
     149    95                          << " and [nodeid " << node->getNodeId().toString() << "]" );
     150    96  }
    134151}}}
    135152
     
    142159
    143160{{{
    144 01 void PingPong::shutdown() {
    145 02
    146 03      logging_info( "pingpong service starting shutdown sequence ..." );
    147 04
    148 05      // stop timer
    149 06      Timer::stop();
    150 07
    151 08      // leave spovnet
    152 09      node->leave();
    153 10
    154 11      // unbind communication and node listener
    155 12      node->unbind( this );                               /*NodeListener*/
    156 13      node->unbind( this, PingPong::PINGPONG_SERVICEID ); /*CommunicationListener*/
    157 14
    158 15      // stop the ariba module
    159 16      ariba->stop();
    160 17
    161 18      // delete node and ariba module
    162 19      delete node;
    163 20      delete ariba;
    164 21
    165 22      // now we are completely shut down
    166 23      logging_info( "pingpong service shut down" );
    167 24}
     161    99  void PingPong::shutdown() {
     162   100 
     163   101          logging_info( "pingpong service starting shutdown sequence ..." );
     164   102 
     165   103          // stop timer
     166   104          Timer::stop();
     167   105 
     168   106          // leave spovnet
     169   107          node->leave();
     170   108 
     171   109          // unbind communication and node listener
     172   110          node->unbind( this );                               /*NodeListener*/
     173   111          node->unbind( this, PingPong::PINGPONG_SERVICEID ); /*CommunicationListener*/
     174   112 
     175   113          // stop the ariba module
     176   114          ariba->stop();
     177   115 
     178   116          // delete node and ariba module
     179   117          delete node;
     180   118          delete ariba;
     181   119 
     182   120          // now we are completely shut down
     183   121          logging_info( "pingpong service shut down" );
     184   122  }
    168185}}}
    169186
     
    173190
    174191{{{
    175 01 void PingPong::eventFunction() {
    176 02
    177 03      // we ping all nodes that are known in the overlay structure
    178 04      // this can be all nodes (OneHop) overlay or just some neighbors
    179 05      // in case of a Chord or Kademlia structure
    180 06
    181 07      // in this sample we use auto-links: we just send out our message
    182 08      // to the node and the link is established automatically. for more
    183 09      // control we would use the node->establishLink function to create
    184 10      // a link and start using the link in the CommunicationListener::onLinkUp
    185 11      // function that is implemented further down in PingPong::onLinkUp
    186 12
    187 13      logging_info( "pinging overlay neighbors with ping id " << ++pingId );
    188 14
    189 15      PingPongMessage pingmsg( pingId );
    190 16
    191 17      //-----------------------------------------------------------------------
    192 18      // Option 1: get all neighboring nodes and send the message to each
    193 19      //-----------------------------------------------------------------------
    194 20      vector<NodeID> nodes = node->getNeighborNodes();
    195 21      BOOST_FOREACH( NodeID nid, nodes ){
    196 22              node->sendMessage( pingmsg, nid, PingPong::PINGPONG_SERVICEID );
    197 23      }
    198 24
    199 25      //-----------------------------------------------------------------------
    200 26      // Option 2: send a "broadcast message" that actually does the same thing
    201 27      //           internally, gets all neighboring nodes and sends the message
    202 28      //-----------------------------------------------------------------------
    203 29      // node->sendBroadcastMessage( pingmsg, PingPong::PINGPONG_SERVICEID );
    204 30 }
     192   125  void PingPong::eventFunction() {
     193   126 
     194   127          // we ping all nodes that are known in the overlay structure
     195   128          // this can be all nodes (OneHop) overlay or just some neighbors
     196   129          // in case of a Chord or Kademlia structure
     197   130 
     198   131          // in this sample we use auto-links: we just send out our message
     199   132          // to the node and the link is established automatically. for more
     200   133          // control we would use the node->establishLink function to create
     201   134          // a link and start using the link in the CommunicationListener::onLinkUp
     202   135          // function that is implemented further down in PingPong::onLinkUp
     203   136 
     204   137          logging_info( "pinging overlay neighbors with ping id " << ++pingId );
     205   138          PingPongMessage pingmsg( pingId, name );
     206   139 
     207   140          //-----------------------------------------------------------------------
     208   141          // Option 1: get all neighboring nodes and send the message to each
     209   142          //-----------------------------------------------------------------------
     210   143          counter++;
     211   144          if (counter<0 || counter>4) {
     212   145                  counter = 0;
     213   146                  string s;
     214   147                  for (int i=0; i<names.size();i++) {
     215   148                          if (i!=0) s+= ", ";
     216   149                          s = s+names[i];
     217   150                  }
     218   151                  logging_info("----> I am " << name << " and I know " << s);
     219   152                  names.clear();
     220   153          }
     221   154 
     222   155          vector<NodeID> nodes = node->getNeighborNodes();
     223   156          BOOST_FOREACH( NodeID nid, nodes ){
     224   157                  logging_info( "sending ping message to " << nid.toString() );
     225   158                  node->sendMessage( pingmsg, nid, PingPong::PINGPONG_SERVICEID );
     226   159          }
     227   160 
     228   161          //-----------------------------------------------------------------------
     229   162          // Option 2: send a "broadcast message" that actually does the same thing
     230   163          //           internally, gets all neighboring nodes and sends the message
     231   164          //-----------------------------------------------------------------------
     232   165          // node->sendBroadcastMessage( pingmsg, PingPong::PINGPONG_SERVICEID );
     233   166  }
    205234}}}
    206235
     
    208237
    209238{{{
    210 01 #include "PingPongMessage.h"
    211 02
    212 03 namespace ariba {
    213 04 namespace application {
    214 05 namespace pingpong {
    215 06
    216 07 vsznDefault(PingPongMessage);
    217 08
    218 09 PingPongMessage::PingPongMessage() : id(0) {
    219 10 }
    220 11
    221 12 PingPongMessage::PingPongMessage(uint8_t _id) : id(_id) {
    222 13 }
    223 14
    224 15 PingPongMessage::~PingPongMessage(){
    225 16 }
    226 17
    227 18 string PingPongMessage::info(){
    228 19      return "ping pong message id " + ariba::utility::Helper::ultos(id);
    229 20 }
    230 21
    231 22 uint8_t PingPongMessage::getid(){
    232 23      return id;
    233 24 }
    234 25
    235 26 }}} // namespace ariba, appplication, pingpong
     239    01 #include "PingPongMessage.h"
     240    02
     241    03 namespace ariba {
     242    04 namespace application {
     243    05 namespace pingpong {
     244    06
     245    07 vsznDefault(PingPongMessage);
     246    08
     247    09 PingPongMessage::PingPongMessage() : id(0) {
     248    10 }
     249    11
     250    12 PingPongMessage::PingPongMessage(uint8_t _id) : id(_id) {
     251    13 }
     252    14
     253    15 PingPongMessage::~PingPongMessage(){
     254    16 }
     255    17
     256    18 string PingPongMessage::info(){
     257    19  return "ping pong message id " + ariba::utility::Helper::ultos(id);
     258    20 }
     259    21
     260    22 uint8_t PingPongMessage::getid(){
     261    23  return id;
     262    24 }
     263    25
     264    26 }}} // namespace ariba, appplication, pingpong
    236265}}}
    237266
     
    239268
    240269{{{
    241 130 bool PingPong::receiveMessage(const Message* message, const LinkID& link, const NodeID& node){
    242 131     
    243 132     PingPongMessage* incoming = ((Message*)message)->decapsulate<PingPongMessage>();
    244 133     
    245 134     logging_info( "received ping message on link " << link.toString() <<
    246 135                              " from node with id " << (int)incoming->getid());
    247 136
    248 137 }
     270   187  void PingPong::onMessage(const DataMessage& msg, const NodeID& remote, const LinkID& lnk) {
     271   188          PingPongMessage* pingmsg = msg.getMessage()->convert<PingPongMessage> ();
     272   189          bool found=false;
     273   190          for (int i=0;i<names.size(); i++) if (names[i]==pingmsg->getName()) found=true;
     274   191          if (!found) names.push_back(pingmsg->getName());
     275   192          logging_info( "received ping message on link " << lnk.toString()
     276   193                          << " from node " << remote.toString()
     277   194                          << ": " << pingmsg->info() );
     278   195  }
    249279}}}
    250280
    251281Getting back to ''!PingPong.cpp'': After the initiator has send a message to a joiner, it will arrive and has to be handled. This is accomplished in ''receiveMessage'' (the name says it). Every received message has to be decapsulated by a service, casting the data back to the service's message format (line 132).
    252282
    253 ''Ariba'' provides several callback functions that may used by services to catch all kinds of events that could be of interest. In this exampe we limit ourselves to the event cases of node joins and node leaves. When a node successfull joines to the SpoVNet instance, ''onNodeJoin'' is triggered nn the initiator's service side. He may then react to this event, exemplary shown in line 80-93, implementing ''onNodeJoin''. In this case, the initiator starts establishing a link to the joined node (line 85), essentially for all kinds of communications via ''Ariba''. We then store the link for further usage (line 88) and prepare a timer which intention is to trigger periodic events. In our case we initialize the timer to be triggered every 2 seconds (line 90), before starting it (line 91).
    254 
    255 {{{
    256 100 void PingPong::onNodeLeave( const NodeID& id, const SpoVNetID& spovnetid ){
    257 101     RemoteNodes::iterator i = remoteNodes.find( id );
    258 102     if( i != remoteNodes.end() ) remoteNodes.erase( i );
    259 103 }
    260 }}}
    261 
    262 Node leaves in our case only lead to deletion of links we had stored before, for we don't need them anymore (line 102).
    263 
    264 {{{
    265 80 void PingPong::onNodeJoin( const NodeID& nodeid, const SpoVNetID& spovnetid ){
    266 81
    267 82      if( !startping ){
    268 83             
    269 84              logging_info( "establishing link to node " << nodeid.toString() );
    270 85              const LinkID link = overlay->establishLink( nodeid, PingPong::PINGPONG_ID );
    271 86
    272 87              logging_info( "adding node to registered nodes in pingpong: " << nodeid.toString() );
    273 88              remoteNodes.insert( make_pair(nodeid,link) );
    274 89             
    275 90              Timer::setInterval( 2000 );
    276 91              Timer::start();
    277 92      }
    278 93 }
    279 }}}