OmniEvents
pushsupp.cc
Go to the documentation of this file.
1 // -*- Mode: C++; -*-
2 // Package : omniEvents
3 // pushsupp.cc Created on: 1/4/98
4 // Author : Paul Nader (pwn)
5 //
6 // Copyright (C) 1998 Paul Nader, 2003-2004 Alex Tingle
7 //
8 // This file is part of the omnievents application.
9 //
10 // omniEvents is free software; you can redistribute it and/or
11 // modify it under the terms of the GNU Lesser General Public
12 // License as published by the Free Software Foundation; either
13 // version 2.1 of the License, or (at your option) any later version.
14 //
15 // omniEvents is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 // Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public
21 // License along with this library; if not, write to the Free Software
22 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 //
24 // Description:
25 // Push Model supplier implementation.
26 //
27 
28 /*
29  $Log: pushsupp.cc,v $
30  Revision 1.10 2004/10/08 09:06:08 alextingle
31  More robust exception minor code handling.
32 
33  Revision 1.9 2004/08/18 17:49:45 alextingle
34  Added check for SIGPIPE before trying to use it.
35 
36  Revision 1.8 2004/08/06 16:19:23 alextingle
37  -k & -K options removed.
38  Naming service names may now be as complex as you like.
39 
40  Revision 1.7 2004/04/20 16:52:17 alextingle
41  All examples updated for latest version on omniEvents. Server may now be
42  specified as a 'corbaloc' string or IOR, instead of as naming service id/kind.
43 
44  Revision 1.6 2004/03/23 19:09:26 alextingle
45  Fixed typos.
46 
47  Revision 1.5 2004/02/21 19:07:45 alextingle
48  Corrected servants to use POA instead of BOA.
49 
50  Revision 1.4 2004/02/04 22:29:55 alextingle
51  Reworked all C++ examples.
52  Removed catch(...) as it tends to make it harder to see what's going on.
53  Now uses POA instead of BOA.
54  Uses omniORB4's Exception name probing.
55  No longer uses 'naming.h/cc' utility code.
56 
57  Revision 1.3 2003/11/03 22:19:25 alextingle
58  Removed all platform specific switches. Now uses autoconf, config.h.
59  Removed stub header in order to allow makefile dependency checking to work
60  correctly.
61  Changed int to bool where appropriate.
62 
63  Revision 1.1.1.1.2.1 2002/09/28 22:20:51 shamus13
64  Added ifdefs to enable omniEvents to compile
65  with both omniORB3 and omniORB4. If __OMNIORB4__
66  is defined during compilation, omniORB4 headers
67  and command line option syntax is used, otherwise
68  fall back to omniORB3 style.
69 
70  Revision 1.1.1.1 2002/09/25 19:00:26 shamus13
71  Import of OmniEvents source tree from release 2.1.1
72 
73  Revision 0.14 2000/10/11 01:16:21 naderp
74  *** empty log message ***
75 
76  Revision 0.13 2000/08/30 04:39:48 naderp
77  Port to omniORB 3.0.1.
78 
79  Revision 0.12 2000/03/16 05:37:27 naderp
80  Added stdlib.h for getopt.
81 
82  Revision 0.11 2000/03/06 13:27:10 naderp
83  Using util getRootNamingContext function.
84  Using stub headers.
85  Fixed error messages.
86 
87  Revision 0.10 2000/03/02 03:21:20 naderp
88  Added -r option to connect using nil reference.
89  Added retry resiliency for handling COMM_FAUILURE exceptions.
90 
91 Revision 0.9 99/11/02 13:39:17 13:39:17 naderp (Paul Nader)
92 Added <signal.h>
93 
94  Revision 0.8 1999/11/02 07:57:18 naderp
95  Updated usage.
96 
97 Revision 0.7 99/11/01 19:22:43 19:22:43 naderp (Paul Nader)
98 Added catch for COMM_FAILURE exception in obtain_push_consumer
99 and disconnect_push_consumer calls.
100 
101 Revision 0.6 99/11/01 16:12:03 16:12:03 naderp (Paul Nader)
102 omniEvents 2.0 Release.
103 
104 Revision 0.5 99/10/27 19:42:31 19:42:31 naderp (Paul Nader)
105 Ignoring Unix SIGPIPE signal.
106 Reporting sleep beforhand.
107 
108 Revision 0.4 99/04/23 16:05:47 16:05:47 naderp (Paul Nader)
109 gcc port.
110 
111 Revision 0.3 99/04/23 09:34:04 09:34:04 naderp (Paul Nader)
112 Windows Port.
113 
114 Revision 0.2 99/04/21 18:06:26 18:06:26 naderp (Paul Nader)
115 *** empty log message ***
116 
117 Revision 0.1.1.1 98/11/27 16:59:40 16:59:40 naderp (Paul Nader)
118 Added -s option to sleep after disconnecting.
119 
120 Revision 0.1 98/11/25 14:08:25 14:08:25 naderp (Paul Nader)
121 Initial Revision
122 
123 */
124 
125 #ifdef HAVE_CONFIG_H
126 # include "config.h"
127 #endif
128 
129 #ifdef HAVE_GETOPT
130 # include <unistd.h>
131 extern char* optarg;
132 extern int optind;
133 #else
134 # include "getopt.h"
135 #endif
136 
137 #ifdef HAVE_IOSTREAM
138 # include <iostream>
139 #else
140 # include <iostream.h>
141 #endif
142 
143 #ifdef HAVE_STD_IOSTREAM
144 using namespace std;
145 #endif
146 
147 #ifdef HAVE_STDLIB_H
148 # include <stdlib.h>
149 #endif
150 
151 #ifdef HAVE_SIGNAL_H
152 # include <signal.h>
153 #endif
154 
155 #include <cstdio>
156 
157 #include "CosEventComm.hh"
158 #include "CosEventChannelAdmin.hh"
159 #include "naming.h"
160 
161 static void usage(int argc, char **argv);
162 
163 class Supplier_i : virtual public POA_CosEventComm::PushSupplier {
164 public:
165  Supplier_i () {};
167 };
168 
169 void
171  cout << "Push Supplier: disconnected." << endl;
172 }
173 
174 int main (int argc, char** argv)
175 {
176  long l = 0;
177  CORBA::ORB_ptr orb = CORBA::ORB_init(argc,argv);
178 
179  // Process Options
180  int discnum =0;
181  bool refnil =false;
182  int sleepInterval =0;
183  const char* channelName ="EventChannel";
184 
185  int c;
186  while ((c = getopt(argc,argv,"d:rs:n:h")) != EOF)
187  {
188  switch (c)
189  {
190  case 'd': discnum = atoi(optarg);
191  break;
192 
193  case 'r': refnil = true;
194  break;
195 
196  case 's': sleepInterval = atoi(optarg);
197  break;
198 
199  case 'n': channelName = optarg;
200  break;
201 
202  case 'h':
203  default : usage(argc,argv);
204  exit(-1);
205  break;
206  }
207  }
208 
209 #if defined(HAVE_SIGNAL_H) && defined(SIGPIPE)
210  // Ignore broken pipes
211  signal(SIGPIPE, SIG_IGN);
212 #endif
213 
214  Supplier_i* supplier = NULL;
215  CosEventChannelAdmin::EventChannel_var channel;
216 
217  const char* action=""; // Use this variable to help report errors.
218  try {
219  CORBA::Object_var obj;
220 
221  // A Push Supplier can be implemented as a pure client or as a mixed
222  // client-server process, depending on whether it requires and is
223  // prepared to service disconnect requests from the channel.
224  // If it is then create the servant object and activate the POA.
225  if(!refnil)
226  {
227  supplier=new Supplier_i();
228 
229  action="resolve initial reference 'RootPOA'";
230  obj=orb->resolve_initial_references("RootPOA");
231  PortableServer::POA_var rootPoa =PortableServer::POA::_narrow(obj);
232  if(CORBA::is_nil(rootPoa))
233  throw CORBA::OBJECT_NOT_EXIST();
234 
235  action="activate the RootPOA's POAManager";
236  PortableServer::POAManager_var pman =rootPoa->the_POAManager();
237  pman->activate();
238  }
239 
240  //
241  // Obtain object reference to EventChannel
242  // (from command-line argument or from the Naming Service).
243  if(optind<argc)
244  {
245  action="convert URI from command line into object reference";
246  obj=orb->string_to_object(argv[optind]);
247  }
248  else
249  {
250  action="resolve initial reference 'NameService'";
251  obj=orb->resolve_initial_references("NameService");
252  CosNaming::NamingContext_var rootContext=
253  CosNaming::NamingContext::_narrow(obj);
254  if(CORBA::is_nil(rootContext))
255  throw CORBA::OBJECT_NOT_EXIST();
256 
257  action="find EventChannel in NameService";
258  cout << action << endl;
259  obj=rootContext->resolve(str2name(channelName));
260  }
261 
262  action="narrow object reference to event channel";
263  channel=CosEventChannelAdmin::EventChannel::_narrow(obj);
264  if(CORBA::is_nil(channel))
265  {
266  cerr << "Failed to narrow Event Channel reference." << endl;
267  exit(1);
268  }
269 
270  }
271  catch(CORBA::ORB::InvalidName& ex) { // resolve_initial_references
272  cerr<<"Failed to "<<action<<". ORB::InvalidName"<<endl;
273  exit(1);
274  }
275  catch(CosNaming::NamingContext::InvalidName& ex) { // resolve
276  cerr<<"Failed to "<<action<<". NamingContext::InvalidName"<<endl;
277  exit(1);
278  }
279  catch(CosNaming::NamingContext::NotFound& ex) { // resolve
280  cerr<<"Failed to "<<action<<". NamingContext::NotFound"<<endl;
281  exit(1);
282  }
283  catch(CosNaming::NamingContext::CannotProceed& ex) { // resolve
284  cerr<<"Failed to "<<action<<". NamingContext::CannotProceed"<<endl;
285  exit(1);
286  }
287  catch(CORBA::TRANSIENT& ex) { // _narrow()
288  cerr<<"Failed to "<<action<<". TRANSIENT"<<endl;
289  exit(1);
290  }
291  catch(CORBA::OBJECT_NOT_EXIST& ex) { // _narrow()
292  cerr<<"Failed to "<<action<<". OBJECT_NOT_EXIST"<<endl;
293  exit(1);
294  }
295  catch(CORBA::SystemException& ex) {
296  cerr<<"Failed to "<<action<<".";
297 #if defined(HAVE_OMNIORB4)
298  cerr<<" "<<ex._name();
299  if(ex.NP_minorString())
300  cerr<<" ("<<ex.NP_minorString()<<")";
301 #endif
302  cerr<<endl;
303  exit(1);
304  }
305  catch(CORBA::Exception& ex) {
306  cerr<<"Failed to "<<action<<"."
307 #if defined(HAVE_OMNIORB4)
308  " "<<ex._name()
309 #endif
310  <<endl;
311  exit(1);
312  }
313 
314  //
315  // Get Supplier Admin interface - retrying on Comms Failure.
316  CosEventChannelAdmin::SupplierAdmin_var supplier_admin;
317  while (1)
318  {
319  try {
320  supplier_admin = channel->for_suppliers ();
321  if (CORBA::is_nil(supplier_admin))
322  {
323  cerr << "Event Channel returned nil Supplier Admin!"
324  << endl;
325  exit(1);
326  }
327  break;
328  }
329  catch (CORBA::COMM_FAILURE& ex) {
330  cerr << "Caught COMM_FAILURE Exception "
331  << "obtaining Supplier Admin! Retrying..."
332  << endl;
333  continue;
334  }
335  }
336  cout << "Obtained SupplierAdmin." << endl;
337 
338  while (1)
339  {
340  //
341  // Get proxy consumer - retrying on Comms Failure.
342  CosEventChannelAdmin::ProxyPushConsumer_var proxy_consumer;
343  while (1)
344  {
345  try {
346  proxy_consumer = supplier_admin->obtain_push_consumer ();
347  if (CORBA::is_nil(proxy_consumer))
348  {
349  cerr << "Supplier Admin returned nil proxy_consumer!"<< endl;
350  exit(1);
351  }
352  break;
353  }
354  catch (CORBA::COMM_FAILURE& ex) {
355  cerr << "Caught COMM_FAILURE Exception "
356  << "obtaining Proxy Push Consumer! Retrying..."
357  << endl;
358  continue;
359  }
360  }
361  cout << "Obtained ProxyPushConsumer." << endl;
362 
363  //
364  // Connect Push Supplier - retrying on Comms Failure.
365  CosEventComm::PushSupplier_var sptr =CosEventComm::PushSupplier::_nil();
366  if (! refnil) {
367  sptr = supplier->_this();
368  }
369 
370  while (1)
371  {
372  try {
373  proxy_consumer->connect_push_supplier(sptr.in());
374  break;
375  }
376  catch (CORBA::BAD_PARAM& ex) {
377  cerr << "Caught BAD_PARAM Exception connecting Push Supplier!"
378  << endl;
379  exit (1);
380  }
381  catch (CosEventChannelAdmin::AlreadyConnected& ex) {
382  cerr << "Proxy Push Consumer already connected!"
383  << endl;
384  break;
385  }
386  catch (CORBA::COMM_FAILURE& ex) {
387  cerr << "Caught COMM_FAILURE Exception "
388  << "connecting Push Supplier! Retrying..."
389  << endl;
390  continue;
391  }
392  }
393  cout << "Connected Push Supplier." << endl;
394 
395  // Push data.
396  for (int i=0; (discnum == 0) || (i < discnum); i++)
397  {
398  CORBA::Any any;
399  any <<= (CORBA::ULong) l++;
400  try {
401  cout << "Push Supplier: push() called. " << flush;
402  proxy_consumer->push(any);
403  cout << "Data : " << l-1 << endl;
404  }
405  catch(CosEventComm::Disconnected&) {
406  cout << "Failed. Caught Disconnected Exception!" << endl;
407  }
408  catch(CORBA::COMM_FAILURE&) {
409  cout << "Failed. Caught COMM_FAILURE Exception!" << endl;
410  }
411  }
412 
413  // Disconnect - retrying on Comms Failure.
414  while (1)
415  {
416  try {
417  proxy_consumer->disconnect_push_consumer();
418  break;
419  }
420  catch (CORBA::COMM_FAILURE& ex) {
421  cerr << "Caught COMM_FAILURE Exception "
422  << "disconnecting Push Supplier! Retrying..."
423  << endl;
424  continue;
425  }
426  }
427  cout << "ProxyPushConsumer disconnected." << endl;
428 
429  // Yawn.
430  cout << "Sleeping " << sleepInterval << " seconds." << endl;
431  omni_thread::sleep(sleepInterval);
432  }
433 
434  // Not Reached
435  return 0;
436 }
437 
438 static void
439 usage(int argc, char **argv)
440 {
441  cerr<<
442 "\nCreate a PushSupplier to send events to a channel.\n"
443 "syntax: "<<(argc?argv[0]:"pushsupp")<<" OPTIONS [CHANNEL_URI]\n"
444 "\n"
445 "CHANNEL_URI: The event channel may be specified as a URI.\n"
446 " This may be an IOR, or a corbaloc::: or corbaname::: URI.\n"
447 "\n"
448 "OPTIONS: DEFAULT:\n"
449 " -d NUM disconnect after sending NUM events [0 - never disconnect]\n"
450 " -r connect using a nil reference\n"
451 " -s SECS sleep SECS seconds after disconnecting [0]\n"
452 " -n NAME channel name (if URI is not specified) [\"EventChannel\"]\n"
453 " -h display this help text\n" << endl;
454 }
int optind
Definition: getopt.cc:82
char * optarg
Definition: getopt.cc:83
int getopt(int argc, char *argv[], const char *optionS)
Definition: getopt.cc:88
CosNaming::Name str2name(const char *namestr)
Converts stringified name to naming service name.
Definition: naming.cc:117
CORBA::ORB_ptr orb
Definition: eventf.cc:60
int main(int argc, char **argv)
The main process entry point.
Definition: pushsupp.cc:174
static void usage(int argc, char **argv)
Definition: pushsupp.cc:439
void disconnect_push_supplier()