Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

pullcons.cc

Go to the documentation of this file.
00001 // -*- Mode: C++; -*-
00002 //                            Package   : omniEvents
00003 // pullcons.cc                Created on: 1/4/98
00004 //                            Author    : Paul Nader (pwn)
00005 //
00006 //    Copyright (C) 1998 Paul Nader, 2003-2004 Alex Tingle
00007 //
00008 //    This file is part of the omniEvents application.
00009 //
00010 //    omniEvents is free software; you can redistribute it and/or
00011 //    modify it under the terms of the GNU Lesser General Public
00012 //    License as published by the Free Software Foundation; either
00013 //    version 2.1 of the License, or (at your option) any later version.
00014 //
00015 //    omniEvents is distributed in the hope that it will be useful,
00016 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 //    Lesser General Public License for more details.
00019 //
00020 //    You should have received a copy of the GNU Lesser General Public
00021 //    License along with this library; if not, write to the Free Software
00022 //    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00023 //
00024 // Description:
00025 //    Pull Model consumer implementation.
00026 //      
00027 
00028 /*
00029   $Log: pullcons.cc,v $
00030   Revision 1.12  2004/10/08 09:06:08  alextingle
00031   More robust exception minor code handling.
00032 
00033   Revision 1.11  2004/08/18 17:49:45  alextingle
00034   Added check for SIGPIPE before trying to use it.
00035 
00036   Revision 1.10  2004/08/06 16:19:23  alextingle
00037   -k & -K options removed.
00038   Naming service names may now be as complex as you like.
00039 
00040   Revision 1.9  2004/04/20 16:52:02  alextingle
00041   All examples updated for latest version on omniEvents. Server may now be
00042   specified as a 'corbaloc' string or IOR, instead of as naming service id/kind.
00043 
00044   Revision 1.8  2004/03/08 18:00:13  alextingle
00045   One too many newlines.
00046 
00047   Revision 1.7  2004/03/08 17:48:25  alextingle
00048   Added newlines to cirrectly format output when exceptions occur.
00049 
00050   Revision 1.6  2004/02/21 19:07:45  alextingle
00051   Corrected servants to use POA instead of BOA.
00052 
00053   Revision 1.5  2004/02/04 22:29:55  alextingle
00054   Reworked all C++ examples.
00055   Removed catch(...) as it tends to make it harder to see what's going on.
00056   Now uses POA instead of BOA.
00057   Uses omniORB4's Exception name probing.
00058   No longer uses 'naming.h/cc' utility code.
00059 
00060   Revision 1.4  2004/01/11 16:59:28  alextingle
00061   Added more helpful exception handling error messages to pullcons.cc.
00062 
00063   Revision 1.3  2003/11/03 22:20:54  alextingle
00064   Removed all platform specific switches. Now uses autoconf, config.h.
00065   Removed stub header in order to allow makefile dependency checking to work
00066   correctly.
00067   Changed int to bool where appropriate.
00068 
00069   Revision 1.1.1.1.2.1  2002/09/28 22:20:51  shamus13
00070   Added ifdefs to enable omniEvents to compile
00071   with both omniORB3 and omniORB4. If __OMNIORB4__
00072   is defined during compilation, omniORB4 headers
00073   and command line option syntax is used, otherwise
00074   fall back to omniORB3 style.
00075 
00076   Revision 1.1.1.1  2002/09/25 19:00:25  shamus13
00077   Import of OmniEvents source tree from release 2.1.1
00078 
00079   Revision 0.11  2000/10/11 01:16:21  naderp
00080   *** empty log message ***
00081 
00082   Revision 0.10  2000/08/30 04:39:48  naderp
00083   Port to omniORB 3.0.1.
00084 
00085   Revision 0.9  2000/03/16 05:37:27  naderp
00086   Added stdlib.h for getopt.
00087 
00088   Revision 0.8  2000/03/06 13:25:44  naderp
00089   Using util getRootNamingContext function.
00090   Using stub headers.
00091   Fixed error messages.
00092 
00093   Revision 0.7  2000/03/02 02:11:27  naderp
00094   Added -r option to connect using nil reference.
00095   Added retry resiliency for handling COMM_FAUILURE exceptions.
00096 
00097   Revision 0.6  1999/11/02 13:38:57  naderp
00098   Added <signal.h>
00099 
00100   Revision 0.5  1999/11/01 15:55:11  naderp
00101   omniEvents 2.0 Release.
00102   Ignoring SIGPIPE for UNIX platforms.
00103 
00104 Revision 0.4  99/04/23  16:05:38  16:05:38  naderp (Paul Nader)
00105 gcc port.
00106 
00107 Revision 0.3  99/04/23  09:33:40  09:33:40  naderp (Paul Nader)
00108 Windows Port.
00109 
00110 Revision 0.2  99/04/21  18:06:25  18:06:25  naderp (Paul Nader)
00111 *** empty log message ***
00112 
00113 Revision 0.1.1.1  98/11/27  16:59:07  16:59:07  naderp (Paul Nader)
00114 Added -s option to sleep after disconnecting.
00115 
00116 Revision 0.1  98/11/25  14:08:04  14:08:04  naderp (Paul Nader)
00117 Initial Revision
00118 
00119 */
00120 
00121 #ifdef HAVE_CONFIG_H
00122 #  include "config.h"
00123 #endif
00124 
00125 #ifdef HAVE_GETOPT
00126 #  include <unistd.h>
00127 extern char* optarg;
00128 extern int optind;
00129 #else
00130 #  include "getopt.h"
00131 #endif
00132 
00133 #ifdef HAVE_IOSTREAM
00134 #  include <iostream>
00135 #else
00136 #  include <iostream.h>
00137 #endif
00138 
00139 #ifdef HAVE_STD_IOSTREAM
00140 using namespace std;
00141 #endif
00142 
00143 #ifdef HAVE_STDLIB_H
00144 #  include <stdlib.h>
00145 #endif
00146 
00147 #ifdef HAVE_SIGNAL_H
00148 #  include <signal.h>
00149 #endif
00150 
00151 #include "CosEventComm.hh"
00152 #include "CosEventChannelAdmin.hh"
00153 #include "naming.h"
00154 
00155 static void usage(int argc, char **argv);
00156 
00157 class Consumer_i : virtual public POA_CosEventComm::PullConsumer {
00158 public:
00159   Consumer_i () {};
00160   void disconnect_pull_consumer ();
00161 };
00162 
00163 void Consumer_i::disconnect_pull_consumer () {
00164   cout << "Pull Consumer: disconnected." << endl;
00165 }
00166 
00167 int
00168 main(int argc, char **argv)
00169 {
00170   //
00171   // Start orb.
00172   CORBA::ORB_ptr orb = CORBA::ORB_init(argc,argv);
00173 
00174   // Process Options
00175   bool        trymode       =false;
00176   int         discnum       =0;
00177   bool        refnil        =false;
00178   int         sleepInterval =0;
00179   const char* channelName   ="EventChannel";
00180 
00181   int c;
00182   while ((c = getopt(argc,argv,"td:rs:n:h")) != EOF)
00183   {
00184      switch (c)
00185      {
00186         case 't': trymode = true;
00187                   break;
00188 
00189         case 'd': discnum = atoi(optarg);
00190                   break;
00191 
00192         case 'r': refnil = true;
00193                   break;
00194 
00195         case 's': sleepInterval = atoi(optarg);
00196                   break;
00197 
00198         case 'n': channelName = optarg;
00199                   break;
00200 
00201         case 'h':
00202         default : usage(argc,argv);
00203                   exit(-1);
00204                   break;
00205      }
00206   }
00207 
00208 #if defined(HAVE_SIGNAL_H) && defined(SIGPIPE)
00209   // Ignore broken pipes
00210   signal(SIGPIPE, SIG_IGN);
00211 #endif
00212 
00213   Consumer_i* consumer =NULL;
00214   CosEventChannelAdmin::EventChannel_var channel;
00215 
00216   const char* action=""; // Use this variable to help report errors.
00217   try {
00218     CORBA::Object_var obj;
00219 
00220     // A Pull Consumer can be implemented as a pure client or as a mixed
00221     // client-server process, depending on whether it requires and is
00222     // prepared to service disconnect requests from the channel.
00223     // If it is, then create the servant object and activate the POA.
00224     if (! refnil)
00225     {
00226        consumer=new Consumer_i();
00227 
00228        action="resolve initial reference 'RootPOA'";
00229        obj=orb->resolve_initial_references("RootPOA");
00230        PortableServer::POA_var rootPoa =PortableServer::POA::_narrow(obj);
00231        if(CORBA::is_nil(rootPoa))
00232            throw CORBA::OBJECT_NOT_EXIST();
00233 
00234        action="activate the RootPOA's POAManager";
00235        PortableServer::POAManager_var pman =rootPoa->the_POAManager();
00236        pman->activate();
00237     }
00238    
00239     //
00240     // Obtain object reference to EventChannel
00241     // (from command-line argument or from the Naming Service).
00242     if(optind<argc)
00243     {
00244       action="convert URI from command line into object reference";
00245       obj=orb->string_to_object(argv[optind]);
00246     }
00247     else
00248     {
00249       action="resolve initial reference 'NameService'";
00250       obj=orb->resolve_initial_references("NameService");
00251       CosNaming::NamingContext_var rootContext=
00252         CosNaming::NamingContext::_narrow(obj);
00253       if(CORBA::is_nil(rootContext))
00254           throw CORBA::OBJECT_NOT_EXIST();
00255 
00256       action="find EventChannel in NameService";
00257       cout << action << endl;
00258       obj=rootContext->resolve(str2name(channelName));
00259     }
00260 
00261     action="narrow object reference to event channel";
00262     channel=CosEventChannelAdmin::EventChannel::_narrow(obj);
00263     if(CORBA::is_nil(channel))
00264     {
00265        cerr << "Failed to narrow Event Channel reference." << endl;
00266        exit(1);
00267     }
00268 
00269   }
00270   catch(CORBA::ORB::InvalidName& ex) { // resolve_initial_references
00271      cerr<<"Failed to "<<action<<". ORB::InvalidName"<<endl;
00272      exit(1);
00273   }
00274   catch(CosNaming::NamingContext::InvalidName& ex) { // resolve
00275      cerr<<"Failed to "<<action<<". NamingContext::InvalidName"<<endl;
00276      exit(1);
00277   }
00278   catch(CosNaming::NamingContext::NotFound& ex) { // resolve
00279      cerr<<"Failed to "<<action<<". NamingContext::NotFound"<<endl;
00280      exit(1);
00281   }
00282   catch(CosNaming::NamingContext::CannotProceed& ex) { // resolve
00283      cerr<<"Failed to "<<action<<". NamingContext::CannotProceed"<<endl;
00284      exit(1);
00285   }
00286   catch(CORBA::TRANSIENT& ex) { // _narrow()
00287      cerr<<"Failed to "<<action<<". TRANSIENT"<<endl;
00288      exit(1);
00289   }
00290   catch(CORBA::OBJECT_NOT_EXIST& ex) { // _narrow()
00291      cerr<<"Failed to "<<action<<". OBJECT_NOT_EXIST"<<endl;
00292      exit(1);
00293   }
00294   catch(CORBA::SystemException& ex) {
00295      cerr<<"Failed to "<<action<<".";
00296 #if defined(HAVE_OMNIORB4)
00297      cerr<<" "<<ex._name();
00298      if(ex.NP_minorString())
00299          cerr<<" ("<<ex.NP_minorString()<<")";
00300 #endif
00301      cerr<<endl;
00302      exit(1);
00303   }
00304   catch(CORBA::Exception& ex) {
00305      cerr<<"Failed to "<<action<<"."
00306 #if defined(HAVE_OMNIORB4)
00307        " "<<ex._name()
00308 #endif
00309        <<endl;
00310      exit(1);
00311   }
00312 
00313   //
00314   // Get Consumer admin interface - retrying on Comms Failure.
00315   CosEventChannelAdmin::ConsumerAdmin_var consumer_admin;
00316   while (1)
00317   {
00318      try {
00319         consumer_admin = channel->for_consumers ();
00320         if (CORBA::is_nil (consumer_admin))
00321         {
00322            cerr << "Event Channel returned nil Consumer Admin!" << endl;
00323            exit (1);
00324         }
00325         break;
00326      }
00327      catch (CORBA::COMM_FAILURE& ex) {
00328         cerr << "Caught COMM_FAILURE exception "
00329              << "obtaining Consumer Admin! Retrying..."
00330              << endl;
00331         continue;
00332      }
00333   }
00334   cout << "Obtained Consumer Admin." << endl;
00335 
00336   while (1)
00337   {
00338      //
00339      // Get proxy supplier - retrying on Comms Failure.
00340      CosEventChannelAdmin::ProxyPullSupplier_var proxy_supplier;
00341      while (1)
00342      {
00343         try {
00344            proxy_supplier = consumer_admin->obtain_pull_supplier ();
00345            if (CORBA::is_nil (proxy_supplier))
00346            {
00347               cerr << "Consumer Admin returned nil Proxy Supplier!" << endl;
00348               exit (1);
00349            }
00350            break;
00351         }
00352         catch (CORBA::COMM_FAILURE& ex) {
00353            cerr << "Caught COMM_FAILURE Exception "
00354                 << "obtaining Pull Supplier! Retrying..."
00355                 << endl;
00356            continue;
00357         }
00358      }
00359      cout << "Obtained ProxyPullSupplier." << endl;
00360    
00361      //
00362      // Connect Pull Consumer - retrying on Comms Failure.
00363      CosEventComm::PullConsumer_ptr cptr =CosEventComm::PullConsumer::_nil();
00364      if (! refnil) {
00365         cptr=consumer->_this();
00366      }
00367 
00368      while (1)
00369      {
00370         try {
00371            proxy_supplier->connect_pull_consumer(cptr);
00372            break;
00373         }
00374         catch (CORBA::BAD_PARAM& ex) {
00375            cerr << "Caught BAD_PARAM exception connecting Pull Consumer!"<<endl;
00376            exit (1);
00377         }
00378         catch (CosEventChannelAdmin::AlreadyConnected& ex) {
00379            cerr << "Proxy Pull Supplier already connected!" 
00380                 << endl;
00381            break;
00382         }
00383         catch (CORBA::COMM_FAILURE& ex) {
00384            cerr << "Caught COMM_FAILURE Exception "
00385                 << "connecting Pull Consumer! Retrying..." 
00386                 << endl;
00387            continue;
00388         }
00389      }
00390      cout << "Connected Pull Consumer." << endl;
00391 
00392      // Pull data.
00393      CORBA::Any *data;
00394      CORBA::ULong l = 0;
00395      for (int i=0; (discnum == 0) || (i < discnum); i++)
00396      {
00397         if(trymode)
00398         {
00399            try {
00400                CORBA::Boolean has_event;
00401                data = proxy_supplier->try_pull(has_event);
00402                cout << "Consumer: try_pull() called. Data : " << flush;
00403                if (has_event)
00404                {
00405                   l = 0;
00406                   *data >>= l;
00407                   cout << l << endl;
00408                   delete data;
00409                }
00410                else
00411                {
00412                   cout << "None" << endl;
00413                }
00414            }
00415            catch (CosEventComm::Disconnected& ex) {
00416               cout << endl;
00417               cerr << "Failed. Caught Disconnected Exception !" << endl;
00418            }
00419            catch (CORBA::COMM_FAILURE& ex) {
00420               cout << endl;
00421               cerr << "Failed. Caught COMM_FAILURE Exception !" << endl;
00422            }
00423            catch (CORBA::Exception& ex) {
00424               cout << endl;
00425               cerr<<"CORBA exception, unable to try_pull()"
00426 #ifdef HAVE_OMNIORB4
00427                   <<": "<<ex._name()
00428 #endif
00429                   << endl;
00430            }
00431         }
00432         else
00433         {
00434            try {
00435                cout << "Pull Consumer: pull() called. ";
00436                cout.flush();
00437                data = proxy_supplier->pull();
00438                l = 0;
00439                *data >>= l;
00440                cout << "Data : " << l << endl;
00441                delete data;
00442            }
00443            catch(CORBA::TRANSIENT&) {
00444               cout << "caught TRANSIENT." << endl;
00445               omni_thread::sleep(1);
00446            }
00447            catch (CosEventComm::Disconnected& ex) {
00448               cout << endl;
00449               cerr << "Failed. Caught Disconnected exception!" << endl;
00450               exit(1);
00451            }
00452            catch (CORBA::COMM_FAILURE& ex) {
00453               cout << endl;
00454               cerr << "Failed. Caught COMM_FAILURE exception!" << endl;
00455               exit(1);
00456            }
00457            catch (CORBA::SystemException& ex) {
00458               cout << endl;
00459               cerr<<"System exception, unable to pull()";
00460 #ifdef HAVE_OMNIORB4
00461               cerr<<": "<<ex._name();
00462               if(ex.NP_minorString())
00463                   cerr<<" ("<<ex.NP_minorString()<<")";
00464 #endif
00465               cerr<< endl;
00466               exit(1);
00467            }
00468            catch (CORBA::Exception& ex) {
00469               cout << endl;
00470               cerr<<"CORBA exception, unable to pull()"
00471 #ifdef HAVE_OMNIORB4
00472                   <<": "<<ex._name()
00473 #endif
00474                   << endl;
00475               exit(1);
00476            }
00477         }
00478      }
00479 
00480      // Disconnect - retrying on Comms Failure.
00481      while (1)
00482      {
00483         try {
00484            proxy_supplier->disconnect_pull_supplier();
00485            break;
00486         }
00487         catch (CORBA::COMM_FAILURE& ex) {
00488            cerr << "Caught COMM_FAILURE exception "
00489                 << "disconnecting Pull Consumer! Retrying..." 
00490                 << endl;
00491            continue;
00492         }
00493      }
00494      cout << "Disconnected Pull Consumer." << endl;
00495 
00496      // Yawn
00497      cout << "Sleeping " << sleepInterval << " seconds." << endl;
00498      omni_thread::sleep(sleepInterval);
00499   }
00500 
00501   // Not Reached
00502   return 0;
00503 }
00504 
00505 static void
00506 usage(int argc, char **argv)
00507 {
00508   cerr<<
00509 "\nCreate a PullConsumer to receive events from a channel.\n"
00510 "syntax: "<<(argc?argv[0]:"pullcons")<<" OPTIONS [CHANNEL_URI]\n"
00511 "\n"
00512 "CHANNEL_URI: The event channel may be specified as a URI.\n"
00513 " This may be an IOR, or a corbaloc::: or corbaname::: URI.\n"
00514 "\n"
00515 "OPTIONS:                                         DEFAULT:\n"
00516 " -t       enable try_pull mode\n"
00517 " -r       connect using a nil reference\n"
00518 " -d NUM   disconnect after receiving NUM events   [0 - never disconnect]\n"
00519 " -s SECS  sleep SECS seconds after disconnecting  [0]\n"
00520 " -n NAME  channel name (if URI is not specified)  [\"EventChannel\"]\n"
00521 " -h       display this help text\n" << endl;
00522 }

Generated on Fri Aug 26 20:56:14 2005 for OmniEvents by  doxygen 1.4.3-20050530