Index: .cvsignore
===================================================================
RCS file: /cvsroot/omniNotify/.cvsignore,v
retrieving revision 1.4
retrieving revision 1.4.2.1
diff -u -u -r1.4 -r1.4.2.1
--- .cvsignore	2001/06/27 15:08:38	1.4
+++ .cvsignore	2002/02/28 23:43:55	1.4.2.1
@@ -1,4 +1,5 @@
 *.foo *.mine *.diff *.prev
 tmp_tests
 python_tests
+core_unit_tests
 NOTES
Index: daemon/ReadyChannel_d.cc
===================================================================
RCS file: /cvsroot/omniNotify/daemon/ReadyChannel_d.cc,v
retrieving revision 1.63.2.1
retrieving revision 1.63.2.2
diff -u -u -r1.63.2.1 -r1.63.2.2
--- daemon/ReadyChannel_d.cc	2001/10/09 06:38:04	1.63.2.1
+++ daemon/ReadyChannel_d.cc	2002/02/28 23:43:56	1.63.2.2
@@ -30,6 +30,18 @@
  
 /*
 $Log: ReadyChannel_d.cc,v $
+Revision 1.63.2.2  2002/02/28 23:43:56  alcfp
+merge alpha branch back into dev for latest fixes
+
+Revision 1.63.4.3  2002/02/26 22:26:37  alcfp
+changed notifd to use RDI_Interactive_Mode helper, wait_for_destroy
+
+Revision 1.63.4.2  2002/02/20 21:17:14  alcfp
+steps towards correct oref refcounts
+
+Revision 1.63.4.1  2002/02/07 18:10:54  alcfp
+merged recent dev fixes into alpha
+
 Revision 1.63.2.1  2001/10/09 06:38:04  alcfp
 11 release
 
@@ -103,19 +115,15 @@
 #include "RDIOSWrappers.h"
 #include "RDIStringDefs.h"
 #include "RDIstrstream.h"
+#include "RDIInteractiveMode.h"
 
-#define OMNINOTIFY_VERSION "1.1"
- 
-// ----------------------------------------------------------//
-
-void processUserInput(const char* prompt, AttN::Server_ptr server);
-
 // ----------------------------------------------------------//
 
 int main(int argc, char** argv)
 {
-  AttN::Server_var server = AttN::Server::_nil();
-  int indx=0, interactive=0;
+  CORBA::Boolean interactive = 0;
+  AttN::Server_ptr server = AttN::Server::_nil();
+  int indx=0;
   char* pn = argv[0];
   while (RDI_STRCHR(pn, '/')) { pn = RDI_STRCHR(pn, '/'); pn++; }
   while (RDI_STRCHR(pn, '\\')) { pn = RDI_STRCHR(pn, '\\'); pn++; }
@@ -126,20 +134,22 @@
   RDI_OS_MAX_OPEN_FILE_DESCRIPTORS;
 
   while ( indx < argc ) {
-    if (RDI_STR_EQ(argv[indx], "-i")) {
-      RDI_rm_arg(argc, argv, indx);
-      interactive = 1;
-    } else if (RDI_STR_EQ(argv[indx], "-h")) {
-      fprintf(stdout, "Usage: %s [-i] [-h] [-n] [-c <f>]\n", pname);
-      fprintf(stdout, "   -i       : interactive mode\n");
-      fprintf(stdout, "   -h       : usage information\n");
+    if (RDI_STR_EQ(argv[indx], "-h")) {
+      fprintf(stdout, "Usage: %s [-h] [-v] [-i] [-n] [-c <f>]\n", pname);
+      fprintf(stdout, "   -h       : print usage information and exit\n");
+      fprintf(stdout, "   -v       : print software version and exit\n");
+      fprintf(stdout, "   -i       : enter interactive mode\n");
       fprintf(stdout, "   -n       : do NOT register with the NameService\n");
-      fprintf(stdout, "   -c <f>   : read config file <f>\n");
-      fprintf(stdout, "   -v       : print software version\n");
+      fprintf(stdout, "   -c <f>   : read config file <f>\n\n");
       return 0;
-    } else if (RDI_STR_EQ(argv[indx], "-v")) {
+    }
+    if (RDI_STR_EQ(argv[indx], "-v")) {
       fprintf(stdout, "notifd:  -- omniNotify server version %s\n", OMNINOTIFY_VERSION);
       return 0;
+    }
+    if (RDI_STR_EQ(argv[indx], "-i")) {
+      RDI_rm_arg(argc, argv, indx);
+      interactive = 1;
     } else {
       indx += 1;
     }
@@ -158,218 +168,16 @@
   server = omniNotify::init_server(argc, argv);
   if (CORBA::is_nil(server)) {
     fprintf(stdout, "\nnotifd: failed to create a new omniNotify server\n");
-    exit(-1);
+    return -1;
   }
   WRAPPED_ORB_OA::activate_oas();
-  if ( interactive ) {
-    processUserInput(pname, server);
-  } else {
-    WRAPPED_ORB_OA::run();
+  if (interactive) {
+    RDI_Interactive_Mode(server, 1); // 1 means spawn a thread
   }
-  // destroy server
-  try {
-    server->destroy();
-  } catch (...) {
-    // server already destroyed?
-  }
-  CORBA_STRING_FREE(pname);
+  // wait for server to be destroyed
+  omniNotify::wait_for_destroy();
   WRAPPED_ORB_OA::cleanup();
+  CORBA_STRING_FREE(pname);
   return 0;
 }
 
-// ----------------------------------------------------------//
-
-void processUserInput(const char* prompt, AttN::Server_ptr server)
-{
-  char cmnd[1024], tname[1024];
-  CORBA::Boolean success, target_changed, res_to_file;
-  CORBA::String_var cmdres;
-  AttN::NameSeq* target_nm = 0;
-  const char* final_nm = "server";
-  do {
-    RDIstrstream str;
-    str << "\n\t\t-------------------------------";
-    str << "\n\t\tomniNotify Server Version " << OMNINOTIFY_VERSION;
-    str << "\n\t\t AT&T Laboratories -- Research ";
-    str << "\n\t\t-------------------------------\n\n";
-    fprintf(stdout, "%s", str.buf());
-  } while (0);
-
-  AttN::Interactive_var target      = AttN::Interactive::_nil();
-  AttN::Interactive_var next_target = AttN::Interactive::_narrow(server);
-  target_changed = 1;
-  success = 1;
-
-  res_to_file = server->results_to_file(); // XXX can this change
-  while ( 1 ) {
-    if (target_changed) {
-      target = next_target;
-      if (CORBA::is_nil(target)) {
-	goto server_problem;
-      }
-      if (target_nm) {
-	delete target_nm; target_nm = 0;
-      }
-      CORBA::Boolean name_problem = 0;
-      try {
-	target_nm = target->my_name();
-      } 
-      catch ( CORBA::INV_OBJREF& e ) { name_problem = 1; } \
-      catch ( CORBA::OBJECT_NOT_EXIST& e ) { name_problem = 1; } \
-      catch ( CORBA::COMM_FAILURE& e ) { name_problem = 1; }
-      if (name_problem || (target_nm->length() == 0)) {
-	// target may have become invalid
-	fprintf(stdout, "\nomniNotify: target %s not available, reverting to top-level server target\n", final_nm);
-	target = AttN::Interactive::_narrow(server);
-	fprintf(stdout, "\nomniNotify: new target ==> server\n");
-	name_problem = 0;
-	try {
-	  target_nm = target->my_name();
-	} 
-	catch ( CORBA::INV_OBJREF& e ) { name_problem = 1; } \
-	catch ( CORBA::OBJECT_NOT_EXIST& e ) { name_problem = 1; } \
-	catch ( CORBA::COMM_FAILURE& e ) { name_problem = 1; }
-	if (name_problem || (target_nm->length() == 0)) {
-	  // something is very wrong
-	  goto server_problem;
-	}
-      }
-      final_nm = (*target_nm)[target_nm->length()-1];
-    }
-    success = 1;
-    do {
-      RDIstrstream str;
-      str << "\n" << prompt << " [";
-      for (unsigned int i = 0; i < target_nm->length(); i++) {
-	if (i > 0) str << '.';
-	str << (*target_nm)[i];
-      }
-      str << "]: ";
-      fprintf(stdout, "%s", str.buf());
-    } while (0);
-    omni_thread::yield();
-    if ( fgets(cmnd, 1024, stdin) ) {
-      cmnd[ RDI_STRLEN(cmnd) - 1 ] = '\0';    // Remove new line
-      RDIParseCmd p(cmnd);
-      fprintf(stdout, "\n");
-      if (p.argc == 0) {
-	continue;
-      }
-      // first see if daemon can handle request 
-      if ((p.argc == 1) && (RDI_STR_EQ_I(p.argv[0], "exit") || RDI_STR_EQ_I(p.argv[0], "quit"))) {
-	fprintf(stdout, "omniNotify:  exiting....\n\n");
-	break;
-      }
-      if ((p.argc == 1) && RDI_STR_EQ_I(p.argv[0], "children")) {
-	AttN::NameSeq* child_names = 0;
-	CORBA::Boolean cnames_problem = 0;
-	try {
-	  child_names = target->child_names();
-	} 
-	catch ( CORBA::INV_OBJREF& e ) { cnames_problem = 1; } \
-	catch ( CORBA::OBJECT_NOT_EXIST& e ) { cnames_problem = 1; } \
-	catch ( CORBA::COMM_FAILURE& e ) { cnames_problem = 1; }
-	if (cnames_problem) {
-	  fprintf(stdout, "\nomniNotify: target %s not available, reverting to top-level server target\n", final_nm);
-	  next_target = AttN::Interactive::_narrow(server);
-	  target_changed = 1;
-	  fprintf(stdout, "\nomniNotify: new target ==> server\n");
-	  continue;
-	}
-	if (child_names) {
-	  RDIstrstream str;
-	  if (child_names->length()) {
-	    str << "Children of " << final_nm << ": ";
-	    for (unsigned int i = 0; i < child_names->length(); i++) {
-	      if (i > 0) str << ", ";
-	      str << (*child_names)[i];
-	    }
-	    str << "\n  (Use 'go <name>' to go to one of the children)\n";
-	  } else {
-	    str << "No children\n";
-	  }
-	  delete child_names;
-	  fprintf(stdout, "%s", str.buf());
-	} else {
-	  fprintf(stdout, "**Error getting children**\n");
-	}
-	continue;
-      }
-      if ((p.argc == 2) && RDI_STR_EQ_I(p.argv[0], "go") && RDI_STR_EQ_I(p.argv[1], "server")) {
-	next_target = AttN::Interactive::_narrow(server);
-	target_changed = 1;
-	fprintf(stdout, "\nomniNotify: new target ==> server\n");
-	continue;
-      }
-      // now see if server or target can handle cmnd
-      // direct some commands to server regardless of currrent target
-      CORBA::Boolean docmd_problem = 0;
-      if ( ( (p.argc == 2) && RDI_STR_EQ_I(p.argv[0], "go") && 
-	     ( RDI_STR_EQ_I(p.argv[1], "chanfact") ||
-	       RDI_STR_EQ_I(p.argv[1], "filtfact") ||
-	       RDI_STRN_EQ_I(p.argv[1], "chanfact.", 9) ||
-	       RDI_STRN_EQ_I(p.argv[1], "filtfact.", 9) ) ) ||
-	   ( (p.argc == 1) && 
-	     ( RDI_STR_EQ_I(p.argv[0], "flags") ||
-	       ((RDI_STRLEN(p.argv[0]) > 1) && ((p.argv[0][0] == '+') || (p.argv[0][0] == '-'))))) ) {
-	try {
-	  cmdres = server->do_command(cmnd, success, target_changed, next_target);
-	}
-	catch ( CORBA::INV_OBJREF& e ) { docmd_problem = 1; } \
-	catch ( CORBA::OBJECT_NOT_EXIST& e ) { docmd_problem = 1; } \
-	catch ( CORBA::COMM_FAILURE& e ) { docmd_problem = 1; }
-	if (docmd_problem) {
-	  // something is very wrong
-	  goto server_problem;
-	}
-      } else {
-	try {
-	  cmdres = target->do_command(cmnd, success, target_changed, next_target);
-	}
-	catch ( CORBA::INV_OBJREF& e ) { docmd_problem = 1; } \
-	catch ( CORBA::OBJECT_NOT_EXIST& e ) { docmd_problem = 1; } \
-	catch ( CORBA::COMM_FAILURE& e ) { docmd_problem = 1; }
-      }
-      if (docmd_problem) {
-	fprintf(stdout, "\nomniNotify: target %s not available, reverting to top-level server target\n", final_nm);
-	next_target = AttN::Interactive::_narrow(server);
-	target_changed = 1;
-	fprintf(stdout, "\nomniNotify: new target ==> server\n");
-	continue;
-      }
-      if (res_to_file) {
-	fprintf(stdout, "%s\n", cmdres.in());
-      }
-      if (! success) {
-	fprintf(stdout, "\nUse 'help' for a list of valid commands\n");
-      }
-      if ((p.argc == 1) && RDI_STR_EQ_I(p.argv[0], "help")) {
-	RDIstrstream str;
-	str << "The following commands work regardless of the current target:\n"
-	    << "  exit              : terminate omniNotify daemon\n"
-	    << "  go server         : change target to server\n"
-	    << "  go chanfact       : change target to channel factory\n"
-	    << "  go filtfact       : change target to filter factory\n"
-	    << "  children          : list children of current target\n"
-	    << "  flags             : show debug/report flag settings\n"
-	    << "  +<flag-name>      : enable a debug/report flag\n"
-	    << "  -<flag-name>      : disable a debug/report flag\n"
-	    << "  +alldebug         : enable all debug flags\n"
-	    << "  -alldebug         : disable all debug flags\n"
-	    << "  +allreport        : enable all report flags\n"
-	    << "  -allreport        : disable all report flags\n";
-	fprintf(stdout, "%s", str.buf());
-      }
-    }
-  }
-  if (target_nm) {
-    delete target_nm;
-  }
-  return;
- server_problem:
-  if (target_nm) {
-    delete target_nm;
-  }
-  fprintf(stdout, "\nomniNotify: server target unavailable; exiting interactive mode\n");
-  WRAPPED_ORB_OA::run();
-}
Index: examples/all_cosnotify_clients.cc
===================================================================
RCS file: /cvsroot/omniNotify/examples/all_cosnotify_clients.cc,v
retrieving revision 1.6
retrieving revision 1.6.2.1
diff -u -u -r1.6 -r1.6.2.1
--- examples/all_cosnotify_clients.cc	2001/08/03 17:54:12	1.6
+++ examples/all_cosnotify_clients.cc	2002/02/28 23:43:56	1.6.2.1
@@ -20,7 +20,7 @@
   char* ior_file = 0; 
   char* proxy_ior_file = 0; 
   char* admin_ior_file = 0;
-  CORBA::ULong num_events = 0, num_con_events = 0, batch_size = 0, millisecs = 0;
+  CORBA::ULong num_events = 0, num_con_events = 0, batch_size = 0, millisecs = 0, delay_millisecs = 0;
   CORBA::Boolean verbose = 0;
   
   omniORB::maxTcpConnectionPerServer = 50;
@@ -31,7 +31,7 @@
 
     // (1) parse the command line arguments
     if (parse_cmd_line(argc, argv, pname, SUPPORTS_FILTERS,
-		       num_events, batch_size, millisecs, verbose,
+		       num_events, batch_size, millisecs, delay_millisecs, verbose,
 		       channel_name, ior_file, proxy_ior_file, admin_ior_file, evs, constraint_expr)) {
       goto error_return; // command line parsing failed
     }
@@ -55,7 +55,7 @@
     PushConsumer_i* a_push_c =
       PushConsumer_i::create(orb, channel, num_con_events, batch_size, "any_push_consumer",
 			     "", "", sample_consume_any_fn, sample_offer_change_fn,
-			     &evs, constraint_expr, millisecs, verbose);
+			     &evs, constraint_expr, millisecs, delay_millisecs, verbose);
     if (! a_push_c) {
       cerr << "Constructing any_push_consumer failed" << endl;
       goto error_return; // failed to create a client
@@ -67,7 +67,7 @@
     StructuredPushConsumer_i* s_push_c =
       StructuredPushConsumer_i::create(orb, channel, num_con_events, batch_size, "struct_push_consumer",
 				       "", "", sample_consume_structured_fn, sample_offer_change_fn,
-				       &evs, constraint_expr, millisecs, verbose);
+				       &evs, constraint_expr, millisecs, delay_millisecs, verbose);
     if (! s_push_c) {
       cerr << "Constructing struct_push_consumer failed" << endl;
       goto error_return; // failed to create a client
@@ -79,7 +79,7 @@
     SequencePushConsumer_i* b_push_c =
       SequencePushConsumer_i::create(orb, channel, num_con_events, batch_size, "batch_push_consumer",
 				     "", "", sample_consume_batch_fn, sample_offer_change_fn,
-				     &evs, constraint_expr, millisecs, verbose);
+				     &evs, constraint_expr, millisecs, delay_millisecs, verbose);
     if (! b_push_c) {
       cerr << "Constructing batch_push_consumer failed" << endl;
       goto error_return; // failed to create a client
@@ -91,7 +91,7 @@
     PullConsumer_i* a_pull_c =
       PullConsumer_i::create(orb, channel, num_con_events, batch_size, "any_pull_consumer",
 			     "", "", sample_consume_any_fn, sample_offer_change_fn,
-			     &evs, constraint_expr, millisecs, verbose);
+			     &evs, constraint_expr, millisecs, delay_millisecs, verbose);
     if (! a_pull_c) {
       cerr << "Constructing any_pull_consumer failed" << endl;
       goto error_return; // failed to create a client
@@ -103,7 +103,7 @@
     StructuredPullConsumer_i* s_pull_c =
       StructuredPullConsumer_i::create(orb, channel, num_con_events, batch_size, "struct_pull_consumer",
 				       "", "", sample_consume_structured_fn, sample_offer_change_fn,
-				       &evs, constraint_expr, millisecs, verbose);
+				       &evs, constraint_expr, millisecs, delay_millisecs, verbose);
     if (! s_pull_c) {
       cerr << "Constructing struct_pull_consumer failed" << endl;
       goto error_return; // failed to create a client
@@ -115,7 +115,7 @@
     SequencePullConsumer_i* b_pull_c =
       SequencePullConsumer_i::create(orb, channel, num_con_events, batch_size, "batch_pull_consumer",
 				     "", "", sample_consume_batch_fn, sample_offer_change_fn,
-				     &evs, constraint_expr, millisecs, verbose);
+				     &evs, constraint_expr, millisecs, delay_millisecs, verbose);
     if (! b_pull_c) {
       cerr << "Constructing batch_pull_consumer failed" << endl;
       goto error_return; // failed to create a client
@@ -127,7 +127,7 @@
     PushSupplier_i* a_push_s =
       PushSupplier_i::create(orb, channel, num_events, batch_size, "any_push_supplier",
 			     "", "", sample_supply_any_fn, sample_subscription_change_fn,
-			     &evs, constraint_expr, millisecs, verbose);
+			     &evs, constraint_expr, millisecs, delay_millisecs, verbose);
     if (! a_push_s) {
       cerr << "Constructing any_push_supplier failed" << endl;
       goto error_return; // failed to create a client
@@ -139,7 +139,7 @@
     StructuredPushSupplier_i* s_push_s =
       StructuredPushSupplier_i::create(orb, channel, num_events, batch_size, "struct_push_supplier",
 				       "", "", sample_supply_structured_fn, sample_subscription_change_fn,
-				       &evs, constraint_expr, millisecs, verbose);
+				       &evs, constraint_expr, millisecs, delay_millisecs, verbose);
     if (! s_push_s) {
       cerr << "Constructing struct_push_supplier failed" << endl;
       goto error_return; // failed to create a client
@@ -151,7 +151,7 @@
     SequencePushSupplier_i* b_push_s =
       SequencePushSupplier_i::create(orb, channel, num_events, batch_size, "batch_push_supplier",
 				     "", "", sample_supply_batch_fn, sample_subscription_change_fn,
-				     &evs, constraint_expr, millisecs, verbose);
+				     &evs, constraint_expr, millisecs, delay_millisecs, verbose);
     if (! b_push_s) {
       cerr << "Constructing batch_push_supplier failed" << endl;
       goto error_return; // failed to create a client
@@ -163,7 +163,7 @@
     PullSupplier_i* a_pull_s =
       PullSupplier_i::create(orb, channel, num_events, batch_size, "any_pull_supplier",
 			     "", "", sample_supply_any_fn, sample_subscription_change_fn,
-			     &evs, constraint_expr, millisecs, verbose);
+			     &evs, constraint_expr, millisecs, delay_millisecs, verbose);
     if (! a_pull_s) {
       cerr << "Constructing any_pull_supplier failed" << endl;
       goto error_return; // failed to create a client
@@ -175,7 +175,7 @@
     StructuredPullSupplier_i* s_pull_s =
       StructuredPullSupplier_i::create(orb, channel, num_events, batch_size, "struct_pull_supplier",
 				       "", "", sample_supply_structured_fn, sample_subscription_change_fn,
-				       &evs, constraint_expr, millisecs, verbose);
+				       &evs, constraint_expr, millisecs, delay_millisecs, verbose);
     if (! s_pull_s) {
       cerr << "Constructing struct_pull_supplier failed" << endl;
       goto error_return; // failed to create a client
@@ -187,7 +187,7 @@
     SequencePullSupplier_i* b_pull_s =
       SequencePullSupplier_i::create(orb, channel, num_events, batch_size, "batch_pull_supplier",
 				     "", "", sample_supply_batch_fn, sample_subscription_change_fn,
-				     &evs, constraint_expr, millisecs, verbose);
+				     &evs, constraint_expr, millisecs, delay_millisecs, verbose);
     if (! b_pull_s) {
       cerr << "Constructing batch_pull_supplier failed" << endl;
       goto error_return; // failed to create a client
Index: examples/dir.mk
===================================================================
RCS file: /cvsroot/omniNotify/examples/dir.mk,v
retrieving revision 1.17
retrieving revision 1.17.2.2
diff -u -u -r1.17 -r1.17.2.2
--- examples/dir.mk	2001/05/29 20:38:19	1.17
+++ examples/dir.mk	2002/02/28 23:43:56	1.17.2.2
@@ -5,7 +5,7 @@
 undef CosUsesBoa
 endif
 
-include $(BASE_OMNI_TREE)/mk/cos.mk
+include ../trilib.mk
 
 ifdef HPUX
 # XXX Why is HPUX linker choking on COSDynamic ?
@@ -23,6 +23,7 @@
 IMPORT_CPPFLAGS += $(patsubst %,-I%/src/services/include/omniNotify,$(IMPORT_TREES))
 
 CXXSRCS = \
+  ndadmin.cc \
   sample_functions.cc \
   sample_clients.cc \
   legacy_clients.cc \
@@ -46,11 +47,15 @@
   struct_push_consumer.cc \
   struct_push_supplier.cc \
   ten_any_pull_consumers.cc \
+  some_notify_clients.cc \
   all_cosnotify_clients.cc
 
 CXXOBJS = $(CXXSRCS:.cc=.o)
 
+ndadmin = $(patsubst %,$(BinPattern),ndadmin)
+
 ten_any_pull_consumers = $(patsubst %,$(BinPattern),ten_any_pull_consumers)
+some_notify_clients = $(patsubst %,$(BinPattern),some_notify_clients)
 all_cosnotify_clients = $(patsubst %,$(BinPattern),all_cosnotify_clients)
 
 demo_add_filter = $(patsubst %,$(BinPattern),demo_add_filter)
@@ -75,7 +80,9 @@
 struct_push_supplier = $(patsubst %,$(BinPattern),struct_push_supplier)
 
 ALL_TARGETS = \
+  $(ndadmin)  \
   $(ten_any_pull_consumers)  \
+  $(some_notify_clients)  \
   $(all_cosnotify_clients)  \
   $(demo_add_filter)  \
   $(demo_offer_change)  \
@@ -107,9 +114,15 @@
 clean::
 	$(RM) $(TARGETS) *.d
 
+$(ndadmin) : ndadmin.o sample_functions.o $(BOTH_LIB_DEPEND)
+	@(libs="$(BOTH_LIB)"; $(CXXExecutable))
+
 $(ten_any_pull_consumers) : ten_any_pull_consumers.o sample_clients.o sample_functions.o $(EXAMPLE_LIB_DEPEND)
 	@(libs="$(EXAMPLE_LIB)"; $(CXXExecutable))
 
+$(some_notify_clients) : some_notify_clients.o sample_clients.o legacy_clients.o sample_functions.o $(EXAMPLE_LIB_DEPEND)
+	@(libs="$(EXAMPLE_LIB)"; $(CXXExecutable))
+
 $(all_cosnotify_clients) : all_cosnotify_clients.o sample_clients.o sample_functions.o $(EXAMPLE_LIB_DEPEND)
 	@(libs="$(EXAMPLE_LIB)"; $(CXXExecutable))
 
@@ -169,4 +182,3 @@
 
 $(legacy_push_supplier) : legacy_push_supplier.o legacy_clients.o sample_functions.o $(EXAMPLE_LIB_DEPEND)
 	@(libs="$(EXAMPLE_LIB)"; $(CXXExecutable))
-
Index: examples/legacy_clients.cc
===================================================================
RCS file: /cvsroot/omniNotify/examples/legacy_clients.cc,v
retrieving revision 1.8
retrieving revision 1.8.2.1
diff -u -u -r1.8 -r1.8.2.1
--- examples/legacy_clients.cc	2001/08/03 17:54:12	1.8
+++ examples/legacy_clients.cc	2002/02/28 23:43:56	1.8.2.1
@@ -16,10 +16,10 @@
 LegacyPushConsumer_i::
 LegacyPushConsumer_i(CosEA::ProxyPushSupplier_ptr proxy, CORBA::ULong max_events,
 		     const char* objnm, consume_any_fn* consume_fn,
-		     CORBA::ULong millisecs, CORBA::Boolean verbose) :
+		     CORBA::ULong millisecs, CORBA::ULong delay_millisecs, CORBA::Boolean verbose) :
   _my_proxy(proxy), _obj_name(objnm), _consume_fn(consume_fn),
   _num_events(0), _max_events(max_events),
-  _millisecs(millisecs), _verbose(verbose), _done(0), _com_err(0),
+  _millisecs(millisecs), _delay_millisecs(delay_millisecs), _verbose(verbose), _done(0), _com_err(0),
   _oplock(), _finish(&_oplock), _worker(0)
 {
   // nothing else to do
@@ -31,6 +31,7 @@
 			     const char* objnm,
 			     consume_any_fn* consume_fn,
 			     CORBA::ULong millisecs,
+			     CORBA::ULong delay_millisecs,
 			     CORBA::Boolean verbose)
 {
   // Obtain appropriate proxy object
@@ -58,7 +59,7 @@
 
     // Construct a client
   LegacyPushConsumer_i* client =
-    new LegacyPushConsumer_i(proxy, max_events, objnm, consume_fn, millisecs, verbose);
+    new LegacyPushConsumer_i(proxy, max_events, objnm, consume_fn, millisecs, delay_millisecs, verbose);
   return client;
 }
 
@@ -158,6 +159,14 @@
     _done = 1;
     _finish.broadcast();
   }
+  if (!_done && _delay_millisecs) {
+    unsigned long d_secs     =  _delay_millisecs / 1000;
+    unsigned long d_nanosecs = (_delay_millisecs % 1000) * 1000000;
+    if (_verbose) cout << _obj_name << ": delaying push response for " << _delay_millisecs << " millisecs" << endl;
+    unsigned long t_secs, t_nanosecs;
+    omni_thread::get_time(&t_secs, &t_nanosecs, d_secs, d_nanosecs);
+    _finish.timedwait(t_secs, t_nanosecs);
+  }
 }
 
 void LegacyPushConsumer_i::disconnect_push_consumer()
@@ -191,10 +200,10 @@
 LegacyPullConsumer_i::
 LegacyPullConsumer_i(CosEA::ProxyPullSupplier_ptr proxy, CORBA::ULong max_events, 
 		     const char* objnm, consume_any_fn* consume_fn,
-		     CORBA::ULong millisecs, CORBA::Boolean verbose) :
+		     CORBA::ULong millisecs, CORBA::ULong delay_millisecs, CORBA::Boolean verbose) :
   _my_proxy(proxy), _obj_name(objnm), _consume_fn(consume_fn),
   _num_events(0), _max_events(max_events),
-  _millisecs(millisecs), _verbose(verbose), _done(0), _com_err(0),
+  _millisecs(millisecs), _delay_millisecs(delay_millisecs), _verbose(verbose), _done(0), _com_err(0),
   _oplock(), _finish(&_oplock), _worker(0)
 {
   // nothing else to do
@@ -206,6 +215,7 @@
 			     const char* objnm,
 			     consume_any_fn* consume_fn,
 			     CORBA::ULong millisecs,
+			     CORBA::ULong delay_millisecs,
 			     CORBA::Boolean verbose)
 {
   // Obtain appropriate proxy object
@@ -233,7 +243,7 @@
 
     // Construct a client
   LegacyPullConsumer_i* client =
-    new LegacyPullConsumer_i(proxy, max_events, objnm, consume_fn, millisecs, verbose);
+    new LegacyPullConsumer_i(proxy, max_events, objnm, consume_fn, millisecs, delay_millisecs, verbose);
   return client;
 }
 
@@ -374,10 +384,10 @@
 LegacyPushSupplier_i::
 LegacyPushSupplier_i(CosEA::ProxyPushConsumer_ptr proxy, CORBA::ULong max_events,
 		     const char* objnm, supply_any_fn* supply_fn,
-		     CORBA::ULong millisecs, CORBA::Boolean verbose) :
+		     CORBA::ULong millisecs, CORBA::ULong delay_millisecs, CORBA::Boolean verbose) :
   _my_proxy(proxy), _obj_name(objnm), _supply_fn(supply_fn),
   _num_events(0), _max_events(max_events),
-  _millisecs(millisecs), _verbose(verbose), _done(0), _com_err(0),
+  _millisecs(millisecs), _delay_millisecs(delay_millisecs), _verbose(verbose), _done(0), _com_err(0),
   _oplock(), _finish(&_oplock), _worker(0)
 {
   // providing explict NULL for supply_fn is not OK -- must have a valid function
@@ -390,6 +400,7 @@
 			     const char* objnm,
 			     supply_any_fn* supply_fn,
 			     CORBA::ULong millisecs,
+			     CORBA::ULong delay_millisecs,
 			     CORBA::Boolean verbose)
 {
   // Obtain appropriate proxy object
@@ -417,7 +428,7 @@
 
     // Construct a client
   LegacyPushSupplier_i* client =
-    new LegacyPushSupplier_i(proxy, max_events, objnm, supply_fn, millisecs, verbose);
+    new LegacyPushSupplier_i(proxy, max_events, objnm, supply_fn, millisecs, delay_millisecs, verbose);
   return client;
 }
 
@@ -551,10 +562,10 @@
 LegacyPullSupplier_i::
 LegacyPullSupplier_i(CosEA::ProxyPullConsumer_ptr proxy, CORBA::ULong max_events,
 		     const char* objnm, supply_any_fn* supply_fn,
-		     CORBA::ULong millisecs, CORBA::Boolean verbose) :
+		     CORBA::ULong millisecs, CORBA::ULong delay_millisecs, CORBA::Boolean verbose) :
   _my_proxy(proxy), _obj_name(objnm), _supply_fn(supply_fn),
   _num_events(0), _max_events(max_events),
-  _millisecs(millisecs), _verbose(verbose), _done(0), _com_err(0),
+  _millisecs(millisecs), _delay_millisecs(delay_millisecs), _verbose(verbose), _done(0), _com_err(0),
   _oplock(), _finish(&_oplock), _worker(0)
 {
   // providing explict NULL for supply_fn is not OK -- must have a valid function
@@ -567,6 +578,7 @@
 			     const char* objnm,
 			     supply_any_fn* supply_fn,
 			     CORBA::ULong millisecs,
+			     CORBA::ULong delay_millisecs,
 			     CORBA::Boolean verbose)
 {
   // Obtain appropriate proxy object
@@ -594,7 +606,7 @@
 
     // Construct a client
   LegacyPullSupplier_i* client =
-    new LegacyPullSupplier_i(proxy, max_events, objnm, supply_fn, millisecs, verbose);
+    new LegacyPullSupplier_i(proxy, max_events, objnm, supply_fn, millisecs, delay_millisecs, verbose);
   return client;
 }
 
@@ -710,6 +722,14 @@
   } else {
     if (_verbose) cout << _obj_name << ": NOT returning an event" << endl;
   }
+  if (!_done && _delay_millisecs) {
+    unsigned long d_secs     =  _delay_millisecs / 1000;
+    unsigned long d_nanosecs = (_delay_millisecs % 1000) * 1000000;
+    if (_verbose) cout << _obj_name << ": delaying try_pull response for " << _delay_millisecs << " millisecs" << endl;
+    unsigned long t_secs, t_nanosecs;
+    omni_thread::get_time(&t_secs, &t_nanosecs, d_secs, d_nanosecs);
+    _finish.timedwait(t_secs, t_nanosecs);
+  }
   return data;
 }
 
@@ -751,6 +771,14 @@
       omni_thread::yield();
       _oplock.lock();
     }
+  }
+  if (!_done && _delay_millisecs) {
+    unsigned long d_secs     =  _delay_millisecs / 1000;
+    unsigned long d_nanosecs = (_delay_millisecs % 1000) * 1000000;
+    if (_verbose) cout << _obj_name << ": delaying pull response for " << _delay_millisecs << " millisecs" << endl;
+    unsigned long t_secs, t_nanosecs;
+    omni_thread::get_time(&t_secs, &t_nanosecs, d_secs, d_nanosecs);
+    _finish.timedwait(t_secs, t_nanosecs);
   }
   _oplock.unlock();
   return data;
Index: examples/legacy_clients.h
===================================================================
RCS file: /cvsroot/omniNotify/examples/legacy_clients.h,v
retrieving revision 1.5
retrieving revision 1.5.2.2
diff -u -u -r1.5 -r1.5.2.2
--- examples/legacy_clients.h	2001/08/03 17:54:12	1.5
+++ examples/legacy_clients.h	2002/02/28 23:43:56	1.5.2.2
@@ -28,6 +28,8 @@
 // Helper Classes                                                //
 ///////////////////////////////////////////////////////////////////
 
+#ifndef __GenericWorker__
+#define __GenericWorker__
 class GenericWorker {
 public:
   GenericWorker() {;}
@@ -44,6 +46,7 @@
   GenericWorker* _worker;
   GenericBoundWorkerThread()  {;}
 }; 
+#endif /*  __GenericWorker__  */
 
 // ----------------- CosEvC::PushConsumer ---------------- //
 
@@ -56,7 +59,7 @@
 public:
   LegacyPushConsumer_i(CosEA::ProxyPushSupplier_ptr proxy, CORBA::ULong max_events,
 		       const char* objnm, consume_any_fn* consume_fn,
-		       CORBA::ULong millisecs, CORBA::Boolean verbose);
+		       CORBA::ULong millisecs, CORBA::ULong delay_millisecs, CORBA::Boolean verbose);
 
   static LegacyPushConsumer_i*
   create(CosEA::EventChannel_ptr channel,
@@ -64,6 +67,7 @@
 	 const char* objnm = "LegacyPushConsumer_i",
 	 consume_any_fn* consume_fn = sample_consume_any_fn,
 	 CORBA::ULong millisecs = 0,
+	 CORBA::ULong delay_millisecs = 0,
 	 CORBA::Boolean verbose = 0);
 
   // IDL methods 
@@ -83,6 +87,7 @@
   CORBA::ULong                 _num_events;
   CORBA::ULong                 _max_events;
   CORBA::ULong                 _millisecs;
+  CORBA::ULong                 _delay_millisecs;
   CORBA::Boolean               _verbose;
   CORBA::Boolean               _done;
   CORBA::Boolean               _com_err;
@@ -101,7 +106,7 @@
 public:
   LegacyPullConsumer_i(CosEA::ProxyPullSupplier_ptr proxy, CORBA::ULong max_events, 
 		       const char* objnm, consume_any_fn* consume_fn,
-		       CORBA::ULong millisecs, CORBA::Boolean verbose);
+		       CORBA::ULong millisecs, CORBA::ULong delay_millisecs, CORBA::Boolean verbose);
 
   static LegacyPullConsumer_i*
   create(CosEA::EventChannel_ptr channel,
@@ -109,6 +114,7 @@
 	 const char* objnm = "LegacyPullConsumer_i",
 	 consume_any_fn* consume_fn = sample_consume_any_fn,
 	 CORBA::ULong millisecs = 0,
+	 CORBA::ULong delay_millisecs = 0,
 	 CORBA::Boolean verbose = 0);
 
   // IDL methods
@@ -127,6 +133,7 @@
   CORBA::ULong                 _num_events;
   CORBA::ULong                 _max_events;
   CORBA::ULong                 _millisecs;
+  CORBA::ULong                 _delay_millisecs;
   CORBA::Boolean               _verbose;
   CORBA::Boolean               _done;
   CORBA::Boolean               _com_err;
@@ -145,7 +152,7 @@
 public:
   LegacyPushSupplier_i(CosEA::ProxyPushConsumer_ptr proxy, CORBA::ULong max_events,
 		       const char* objnm, supply_any_fn* supply_fn,
-		       CORBA::ULong millisecs, CORBA::Boolean verbose);
+		       CORBA::ULong millisecs, CORBA::ULong delay_millisecs, CORBA::Boolean verbose);
 
   static LegacyPushSupplier_i*
   create(CosEA::EventChannel_ptr channel,
@@ -153,6 +160,7 @@
 	 const char* objnm = "LegacyPushSupplier_i",
 	 supply_any_fn* supply_fn = sample_supply_any_fn,
 	 CORBA::ULong millisecs = 0,
+	 CORBA::ULong delay_millisecs = 0,
 	 CORBA::Boolean verbose = 0);
 
   // IDL methods
@@ -171,6 +179,7 @@
   CORBA::ULong                 _num_events;
   CORBA::ULong                 _max_events;
   CORBA::ULong                 _millisecs;
+  CORBA::ULong                 _delay_millisecs;
   CORBA::Boolean               _verbose;
   CORBA::Boolean               _done;
   CORBA::Boolean               _com_err;
@@ -189,7 +198,7 @@
 public:
   LegacyPullSupplier_i(CosEA::ProxyPullConsumer_ptr proxy, CORBA::ULong max_events,
 		       const char* objnm, supply_any_fn* supply_fn,
-		       CORBA::ULong millisecs, CORBA::Boolean verbose);
+		       CORBA::ULong millisecs, CORBA::ULong delay_millisecs, CORBA::Boolean verbose);
 
   static LegacyPullSupplier_i*
   create(CosEA::EventChannel_ptr channel,
@@ -197,6 +206,7 @@
 	 const char* objnm = "LegacyPullSupplier_i",
 	 supply_any_fn* supply_fn = sample_supply_any_fn,
 	 CORBA::ULong millisecs = 0,
+	 CORBA::ULong delay_millisecs = 0,
 	 CORBA::Boolean verbose = 0);
 
   // IDL methods
@@ -217,6 +227,7 @@
   CORBA::ULong                 _num_events;
   CORBA::ULong                 _max_events;
   CORBA::ULong                 _millisecs;
+  CORBA::ULong                 _delay_millisecs;
   CORBA::Boolean               _verbose;
   CORBA::Boolean               _done;
   CORBA::Boolean               _com_err;
Index: examples/main_program.h
===================================================================
RCS file: /cvsroot/omniNotify/examples/main_program.h,v
retrieving revision 1.9
retrieving revision 1.9.2.1
diff -u -u -r1.9 -r1.9.2.1
--- examples/main_program.h	2001/08/03 17:54:13	1.9
+++ examples/main_program.h	2002/02/28 23:43:56	1.9.2.1
@@ -33,7 +33,7 @@
   char* ior_file = 0; 
   char* proxy_ior_file = 0; 
   char* admin_ior_file = 0; 
-  CORBA::ULong num_events = 0, batch_size = 0, millisecs = 0;
+  CORBA::ULong num_events = 0, batch_size = 0, millisecs = 0, delay_millisecs = 0;
   CORBA::Boolean verbose = 0;
   
   CORBA::ORB_ptr orb = CORBA::ORB_init(argc, argv, ORB_INIT_NAME);
@@ -43,7 +43,7 @@
 
     // (1) parse the command line arguments
     if (parse_cmd_line(argc, argv, pname, SUPPORTS_FILTERS,
-		       num_events, batch_size, millisecs, verbose,
+		       num_events, batch_size, millisecs, delay_millisecs, verbose,
 		       channel_name, ior_file, proxy_ior_file, admin_ior_file, evs, constraint_expr)) {
       goto error_return; // command line parsing failed
     }
@@ -65,11 +65,11 @@
     CLIENT_IMPL_CLASS* client =
       CLIENT_IMPL_CLASS::create(orb, channel, num_events, batch_size, CLIENT_NAME, proxy_ior_file, admin_ior_file,
 				SUPPLY_OR_CONSUME_FN, CHANGE_FN,
-				&evs, constraint_expr, millisecs, verbose);
+				&evs, constraint_expr, millisecs, delay_millisecs, verbose);
 #else
     CLIENT_IMPL_CLASS* client =
       CLIENT_IMPL_CLASS::create(channel, num_events, CLIENT_NAME,
-				SUPPLY_OR_CONSUME_FN, millisecs, verbose);
+				SUPPLY_OR_CONSUME_FN, millisecs, delay_millisecs, verbose);
 #endif
     if (! client) {
       goto error_return; // failed to create client
Index: examples/parse_cmd_line.h
===================================================================
RCS file: /cvsroot/omniNotify/examples/parse_cmd_line.h,v
retrieving revision 1.9
retrieving revision 1.9.2.2
diff -u -u -r1.9 -r1.9.2.2
--- examples/parse_cmd_line.h	2001/08/03 17:54:13	1.9
+++ examples/parse_cmd_line.h	2002/02/28 23:43:57	1.9.2.2
@@ -9,13 +9,20 @@
 
 #include "CosNotifyShorthands.h"
 
-static void usage(const char* pname)
+static void usage(const char* pname, CORBA::Boolean supports_filters)
 {
-  cout << "Usage: " << pname << " [-d #] [-m #] [-n name] [-f file] [-v]" << endl;
+  cout << "Usage: " << pname << " [-d #] [-b #] [-m #] [-M #] [-n name] [-f file] [-p file] [-a file] [-v]";
+  if (supports_filters) {
+    cout << " [-t types] [-e expr]" << endl;
+  } else {
+    cout << endl;
+  }
   cout << "  -d #     : disconnect after # events [default 0 means never disconnect]" << endl;
   cout << "  -b #     : batch size (only relevant for batch supplier programs) [default 5]" << endl;
   cout << "               => must be >= 1" << endl;
   cout << "  -m #     : # of milliseconds to pause between each push/pull [default 0]" << endl;
+  cout << "  -M #     : # of milliseconds to pause during incoming push, pull, try_pull [default 0]" << endl;
+  cout << "             (-M only applies to push consumers and pull suppliers)" << endl;
   cout << "  -n name  : channel name" << endl;
   cout << "               => use event service to lookup this name" << endl;
   cout << "  -f file  : file containing channel IOR" << endl;
@@ -26,6 +33,16 @@
   cout << "                (used by demo_add_filter, demo_offer_change, or demo_subscription_chang)" << endl;
   cout << "  -v       : verbose output" << endl;
   cout << endl;
+  if (supports_filters) {
+    cout << "Options for adding a filter:" << endl;
+    cout << "  -t types : add a filter for the specified types, which should be a" << endl;
+    cout << "               comma-separated list of types of the form D::T" << endl;
+    cout << "  -e expr  : add a filter with the specified boolean expression" << endl;
+    cout << endl;
+    cout << "If only -t specified, the expression \"true\" is used for the filter" << endl;
+    cout << "If only -e specified, the event type \"*::*\" is used for the filter" << endl;
+    cout << endl;
+  }
   cout << "If both -n and -f are specified, the -n option is tried first" << endl;
   cout << endl;
   cout << "If neither -n or -f is specified, program first tries name service" << endl;
@@ -33,17 +50,6 @@
   cout << endl;
 }
 
-static void filter_usage() {
-  cout << "Options for adding a filter:" << endl;
-  cout << "  -t types : add a filter for the specified types, which should be a" << endl;
-  cout << "               comma-separated list of types of the form D::T" << endl;
-  cout << "  -e expr  : add a filter with the specified boolean expression" << endl;
-  cout << endl;
-  cout << "If only -t specified, the expression \"true\" is used for the filter" << endl;
-  cout << "If only -e specified, the event type \"*::*\" is used for the filter" << endl;
-  cout << endl;
-}
-
 // return 0 if etype_list is a valid comma-separated event type list
 // (and fill in evs with the event types); else return 1 (1 means error)
 CORBA::Boolean parse_etype_list(const char* etype_list, CosN::EventTypeSeq& evs)
@@ -94,6 +100,7 @@
 			      CORBA::ULong& num_events,
 			      CORBA::ULong& batch_size,
 			      CORBA::ULong& millisecs,
+			      CORBA::ULong& delay_millisecs,
 			      CORBA::Boolean& verbose,
 			      char*& channel_name,
 			      char*& ior_file,
@@ -115,23 +122,29 @@
   long tmp_long = 0;
 
   // Process command line arguments
-  while ( (c = getopt(argc, argv,"d:b:m:n:f:a:p:t:e:v")) != EOF ) {
+  const char* opts = "d:b:m:M:n:f:a:p:t:e:v";
+  while ( (c = getopt(argc, argv, opts)) != EOF ) {
     switch (c) {
     case 'd' :
       tmp_long = atol(optarg);
-      if (tmp_long < 0) { usage(pname); if (supports_filters) filter_usage(); return 1; }
+      if (tmp_long < 0) { usage(pname, supports_filters); return 1; }
       num_events = (CORBA::ULong)tmp_long;
       continue;
     case 'b' :
       tmp_long = atol(optarg);
-      if (tmp_long < 1) { usage(pname); if (supports_filters) filter_usage(); return 1; }
+      if (tmp_long < 1) { usage(pname, supports_filters); return 1; }
       batch_size = (CORBA::ULong)tmp_long;
       continue;
     case 'm' :
       tmp_long = atol(optarg);
-      if (tmp_long < 0) { usage(pname); if (supports_filters) filter_usage(); return 1; }
+      if (tmp_long < 0) { usage(pname, supports_filters); return 1; }
       millisecs = (CORBA::ULong)tmp_long;
       continue;
+    case 'M' :
+      tmp_long = atol(optarg);
+      if (tmp_long < 0) { usage(pname, supports_filters); return 1; }
+      delay_millisecs = (CORBA::ULong)tmp_long;
+      continue;
     case 'n' :
       channel_name = optarg;
       continue;
@@ -154,7 +167,7 @@
       verbose = 1;
       continue;
     default :
-      usage(pname); if (supports_filters) filter_usage();
+      usage(pname, supports_filters);
       return 1;
     }
   }
@@ -164,12 +177,12 @@
   }
   if ( (!supports_filters) && ( strlen(etype_list) || strlen(constraint_expr) ) ) {
     cout << "Filter options not supported for this client" << endl;
-    usage(pname);
+    usage(pname, supports_filters);
     return 1; // error
   }
   if (strlen(etype_list) && parse_etype_list(etype_list, evs)) {
     cout << "Event type list for -t option must be comma-separated list of D::T" << endl << endl; 
-    usage(pname); filter_usage();
+    usage(pname, supports_filters);
     return 1;
   }
   if ( evs.length() && (! strlen(constraint_expr))) {
Index: examples/sample_clients.cc
===================================================================
RCS file: /cvsroot/omniNotify/examples/sample_clients.cc,v
retrieving revision 1.13
retrieving revision 1.13.2.1
diff -u -u -r1.13 -r1.13.2.1
--- examples/sample_clients.cc	2001/09/28 02:09:47	1.13
+++ examples/sample_clients.cc	2002/02/28 23:43:57	1.13.2.1
@@ -301,11 +301,11 @@
 	       CosNF::Filter_ptr filter,
 	       CORBA::ULong max_events,const char* objnm,
 	       consume_any_fn* consume_fn, type_change_fn* change_fn,
-	       CORBA::ULong millisecs, CORBA::Boolean verbose) :
+	       CORBA::ULong millisecs, CORBA::ULong delay_millisecs, CORBA::Boolean verbose) :
   _my_proxy(proxy), _my_admin(admin), _my_filters(0),
   _obj_name(objnm), _consume_fn(consume_fn), _change_fn(change_fn),
   _num_changes(0), _num_events(0), _max_events(max_events),
-  _millisecs(millisecs), _verbose(verbose), _done(0), _com_err(0),
+  _millisecs(millisecs), _delay_millisecs(delay_millisecs), _verbose(verbose), _done(0), _com_err(0),
   _oplock(), _finish(&_oplock), _worker(0)
 {
   if (! CORBA::is_nil(filter)) {
@@ -327,6 +327,7 @@
 		       CosN::EventTypeSeq* evs_ptr,
 		       const char* constraint_expr,
 		       CORBA::ULong millisecs,
+		       CORBA::ULong delay_millisecs,
 		       CORBA::Boolean verbose)
 {
   // Obtain appropriate proxy object
@@ -352,7 +353,7 @@
   write_ior_to_file(orb, proxy, proxy_ior_file, verbose);
   // Construct a client
   PushConsumer_i* client =
-    new PushConsumer_i(proxy, admin, filter, max_events, objnm, consume_fn, change_fn, millisecs, verbose);
+    new PushConsumer_i(proxy, admin, filter, max_events, objnm, consume_fn, change_fn, millisecs, delay_millisecs, verbose);
   return client;
 }
 
@@ -465,6 +466,14 @@
     _done = 1;
     _finish.broadcast();
   }
+  if (!_done && _delay_millisecs) {
+    unsigned long d_secs     =  _delay_millisecs / 1000;
+    unsigned long d_nanosecs = (_delay_millisecs % 1000) * 1000000;
+    if (_verbose) cout << _obj_name << ": delaying push response for " << _delay_millisecs << " millisecs" << endl;
+    unsigned long t_secs, t_nanosecs;
+    omni_thread::get_time(&t_secs, &t_nanosecs, d_secs, d_nanosecs);
+    _finish.timedwait(t_secs, t_nanosecs);
+  }
 }
 
 void PushConsumer_i::disconnect_push_consumer()
@@ -502,6 +511,14 @@
   _num_changes++;
   if (_change_fn) (*_change_fn)(added, deled, _obj_name, _num_changes, _verbose);
   else if (_verbose) cout << _obj_name << ": offer_change received [# " << _num_changes << "]" << endl;
+  if (!_done && _delay_millisecs) {
+    unsigned long d_secs     =  _delay_millisecs / 1000;
+    unsigned long d_nanosecs = (_delay_millisecs % 1000) * 1000000;
+    if (_verbose) cout << _obj_name << ": delaying offer_change response for " << _delay_millisecs << " millisecs" << endl;
+    unsigned long t_secs, t_nanosecs;
+    omni_thread::get_time(&t_secs, &t_nanosecs, d_secs, d_nanosecs);
+    _finish.timedwait(t_secs, t_nanosecs);
+  }
 }
 
 // -------------- CosNotifyComm::StructuredPushConsumer -------------- //
@@ -512,11 +529,11 @@
 			 CosNF::Filter_ptr filter,
 			 CORBA::ULong max_events, const char* objnm,
 			 consume_structured_fn* consume_fn, type_change_fn* change_fn,
-			 CORBA::ULong millisecs, CORBA::Boolean verbose) :
+			 CORBA::ULong millisecs, CORBA::ULong delay_millisecs, CORBA::Boolean verbose) :
   _my_proxy(proxy), _my_admin(admin), _my_filters(0),
   _obj_name(objnm), _consume_fn(consume_fn), _change_fn(change_fn),
   _num_changes(0), _num_events(0), _max_events(max_events),
-  _millisecs(millisecs), _verbose(verbose),
+  _millisecs(millisecs), _delay_millisecs(delay_millisecs), _verbose(verbose),
   _done(0), _com_err(0), _oplock(), _finish(&_oplock), _worker(0)
 {
   if (! CORBA::is_nil(filter)) {
@@ -538,6 +555,7 @@
 				 CosN::EventTypeSeq* evs_ptr,
 				 const char* constraint_expr,
 				 CORBA::ULong millisecs,
+				 CORBA::ULong delay_millisecs,
 				 CORBA::Boolean verbose)
 {
   // Obtain appropriate proxy object
@@ -563,7 +581,7 @@
   write_ior_to_file(orb, proxy, proxy_ior_file, verbose);
   // Construct a client
   StructuredPushConsumer_i* client =
-    new StructuredPushConsumer_i(proxy, admin, filter, max_events, objnm, consume_fn, change_fn, millisecs, verbose);
+    new StructuredPushConsumer_i(proxy, admin, filter, max_events, objnm, consume_fn, change_fn, millisecs, delay_millisecs, verbose);
   return client;
 }
 
@@ -677,6 +695,14 @@
     _done = 1;
     _finish.broadcast();
   }
+  if (!_done && _delay_millisecs) {
+    unsigned long d_secs     =  _delay_millisecs / 1000;
+    unsigned long d_nanosecs = (_delay_millisecs % 1000) * 1000000;
+    if (_verbose) cout << _obj_name << ": delaying push_structured_event response for " << _delay_millisecs << " millisecs" << endl;
+    unsigned long t_secs, t_nanosecs;
+    omni_thread::get_time(&t_secs, &t_nanosecs, d_secs, d_nanosecs);
+    _finish.timedwait(t_secs, t_nanosecs);
+  }
 }
 
 void StructuredPushConsumer_i::disconnect_structured_push_consumer()
@@ -714,6 +740,14 @@
   _num_changes++;
   if (_change_fn) (*_change_fn)(added, deled, _obj_name, _num_changes, _verbose);
   else if (_verbose) cout << _obj_name << ": offer_change received [# " << _num_changes << "]" << endl;
+  if (!_done && _delay_millisecs) {
+    unsigned long d_secs     =  _delay_millisecs / 1000;
+    unsigned long d_nanosecs = (_delay_millisecs % 1000) * 1000000;
+    if (_verbose) cout << _obj_name << ": delaying offer_change response for " << _delay_millisecs << " millisecs" << endl;
+    unsigned long t_secs, t_nanosecs;
+    omni_thread::get_time(&t_secs, &t_nanosecs, d_secs, d_nanosecs);
+    _finish.timedwait(t_secs, t_nanosecs);
+  }
 }
 
 // ------------- CosNotifyComm::SequencePushConsumer ------------- //
@@ -724,11 +758,11 @@
 		       CosNF::Filter_ptr filter,
 		       CORBA::ULong max_events, const char* objnm,
 		       consume_batch_fn* consume_fn, type_change_fn* change_fn,
-		       CORBA::ULong millisecs, CORBA::Boolean verbose) :
+		       CORBA::ULong millisecs, CORBA::ULong delay_millisecs, CORBA::Boolean verbose) :
   _my_proxy(proxy), _my_admin(admin), _my_filters(0),
   _obj_name(objnm), _consume_fn(consume_fn), _change_fn(change_fn),
   _num_changes(0), _num_events(0), _num_batches(0), _max_events(max_events),
-  _millisecs(millisecs), _verbose(verbose), _done(0), _com_err(0),
+  _millisecs(millisecs), _delay_millisecs(delay_millisecs), _verbose(verbose), _done(0), _com_err(0),
   _oplock(), _finish(&_oplock), _worker(0)
 {
   if (! CORBA::is_nil(filter)) {
@@ -750,6 +784,7 @@
 			       CosN::EventTypeSeq* evs_ptr,
 			       const char* constraint_expr,
 			       CORBA::ULong millisecs,
+			       CORBA::ULong delay_millisecs,
 			       CORBA::Boolean verbose)
 {
   // Obtain appropriate proxy object
@@ -775,7 +810,7 @@
   write_ior_to_file(orb, proxy, proxy_ior_file, verbose);
   // Construct a client
   SequencePushConsumer_i* client =
-    new SequencePushConsumer_i(proxy, admin, filter, max_events, objnm, consume_fn, change_fn, millisecs, verbose);
+    new SequencePushConsumer_i(proxy, admin, filter, max_events, objnm, consume_fn, change_fn, millisecs, delay_millisecs, verbose);
   return client;
 }
 
@@ -889,6 +924,14 @@
     _done = 1;
     _finish.broadcast();
   }
+  if (!_done && _delay_millisecs) {
+    unsigned long d_secs     =  _delay_millisecs / 1000;
+    unsigned long d_nanosecs = (_delay_millisecs % 1000) * 1000000;
+    if (_verbose) cout << _obj_name << ": delaying push_structured_events response for " << _delay_millisecs << " millisecs" << endl;
+    unsigned long t_secs, t_nanosecs;
+    omni_thread::get_time(&t_secs, &t_nanosecs, d_secs, d_nanosecs);
+    _finish.timedwait(t_secs, t_nanosecs);
+  }
 }
 
 void SequencePushConsumer_i::disconnect_sequence_push_consumer()
@@ -926,6 +969,14 @@
   _num_changes++;
   if (_change_fn) (*_change_fn)(added, deled, _obj_name, _num_changes, _verbose);
   else if (_verbose) cout << _obj_name << ": offer_change received [# " << _num_changes << "]" << endl;
+  if (!_done && _delay_millisecs) {
+    unsigned long d_secs     =  _delay_millisecs / 1000;
+    unsigned long d_nanosecs = (_delay_millisecs % 1000) * 1000000;
+    if (_verbose) cout << _obj_name << ": delaying offer_change response for " << _delay_millisecs << " millisecs" << endl;
+    unsigned long t_secs, t_nanosecs;
+    omni_thread::get_time(&t_secs, &t_nanosecs, d_secs, d_nanosecs);
+    _finish.timedwait(t_secs, t_nanosecs);
+  }
 }
 
 ///////////////////////////////////////////////////////////////////
@@ -940,11 +991,11 @@
 	       CosNF::Filter_ptr filter,
 	       CORBA::ULong max_events, const char* objnm,
 	       consume_any_fn* consume_fn, type_change_fn* change_fn,
-	       CORBA::ULong millisecs, CORBA::Boolean verbose) :
+	       CORBA::ULong millisecs, CORBA::ULong delay_millisecs, CORBA::Boolean verbose) :
   _my_proxy(proxy), _my_admin(admin), _my_filters(0),
   _obj_name(objnm), _consume_fn(consume_fn), _change_fn(change_fn),
   _num_changes(0), _num_events(0), _max_events(max_events),
-  _millisecs(millisecs), _verbose(verbose), _done(0), _com_err(0),
+  _millisecs(millisecs), _delay_millisecs(delay_millisecs), _verbose(verbose), _done(0), _com_err(0),
   _oplock(), _finish(&_oplock), _worker(0)
 {
   if (! CORBA::is_nil(filter)) {
@@ -966,6 +1017,7 @@
 		       CosN::EventTypeSeq* evs_ptr,
 		       const char* constraint_expr,
 		       CORBA::ULong millisecs,
+		       CORBA::ULong delay_millisecs,
 		       CORBA::Boolean verbose)
 {
   // Obtain appropriate proxy object
@@ -991,7 +1043,7 @@
   write_ior_to_file(orb, proxy, proxy_ior_file, verbose);
   // Construct a client
   PullConsumer_i* client =
-    new PullConsumer_i(proxy, admin, filter, max_events, objnm, consume_fn, change_fn, millisecs, verbose);
+    new PullConsumer_i(proxy, admin, filter, max_events, objnm, consume_fn, change_fn, millisecs, delay_millisecs, verbose);
   return client;
 }
 
@@ -1151,6 +1203,14 @@
   _num_changes++;
   if (_change_fn) (*_change_fn)(added, deled, _obj_name, _num_changes, _verbose);
   else if (_verbose) cout << _obj_name << ": offer_change received [# " << _num_changes << "]" << endl;
+  if (!_done && _delay_millisecs) {
+    unsigned long d_secs     =  _delay_millisecs / 1000;
+    unsigned long d_nanosecs = (_delay_millisecs % 1000) * 1000000;
+    if (_verbose) cout << _obj_name << ": delaying offer_change response for " << _delay_millisecs << " millisecs" << endl;
+    unsigned long t_secs, t_nanosecs;
+    omni_thread::get_time(&t_secs, &t_nanosecs, d_secs, d_nanosecs);
+    _finish.timedwait(t_secs, t_nanosecs);
+  }
 }
 
 // ---------------- CosNotifyComm::StructuredPullConsumer ---------------- //
@@ -1161,11 +1221,11 @@
 			 CosNF::Filter_ptr filter,
 			 CORBA::ULong max_events, const char* objnm,
 			 consume_structured_fn* consume_fn, type_change_fn* change_fn,
-			 CORBA::ULong millisecs, CORBA::Boolean verbose) :
+			 CORBA::ULong millisecs, CORBA::ULong delay_millisecs, CORBA::Boolean verbose) :
   _my_proxy(proxy), _my_admin(admin), _my_filters(0),
   _obj_name(objnm), _consume_fn(consume_fn), _change_fn(change_fn),
   _num_changes(0), _num_events(0), _max_events(max_events),
-  _millisecs(millisecs), _verbose(verbose),
+  _millisecs(millisecs), _delay_millisecs(delay_millisecs), _verbose(verbose),
   _done(0), _com_err(0), _oplock(), _finish(&_oplock), _worker(0)
 {
   if (! CORBA::is_nil(filter)) {
@@ -1187,6 +1247,7 @@
 				 CosN::EventTypeSeq* evs_ptr,
 				 const char* constraint_expr,
 				 CORBA::ULong millisecs,
+				 CORBA::ULong delay_millisecs,
 				 CORBA::Boolean verbose)
 {
   // Obtain appropriate proxy object
@@ -1213,7 +1274,7 @@
   write_ior_to_file(orb, proxy, proxy_ior_file, verbose);
   // Construct a client
   StructuredPullConsumer_i* client =
-    new StructuredPullConsumer_i(proxy, admin, filter, max_events, objnm, consume_fn, change_fn, millisecs, verbose);
+    new StructuredPullConsumer_i(proxy, admin, filter, max_events, objnm, consume_fn, change_fn, millisecs, delay_millisecs, verbose);
   return client;
 }
 
@@ -1374,6 +1435,14 @@
   _num_changes++;
   if (_change_fn) (*_change_fn)(added, deled, _obj_name, _num_changes, _verbose);
   else if (_verbose) cout << _obj_name << ": offer_change received [# " << _num_changes << "]" << endl;
+  if (!_done && _delay_millisecs) {
+    unsigned long d_secs     =  _delay_millisecs / 1000;
+    unsigned long d_nanosecs = (_delay_millisecs % 1000) * 1000000;
+    if (_verbose) cout << _obj_name << ": delaying offer_change response for " << _delay_millisecs << " millisecs" << endl;
+    unsigned long t_secs, t_nanosecs;
+    omni_thread::get_time(&t_secs, &t_nanosecs, d_secs, d_nanosecs);
+    _finish.timedwait(t_secs, t_nanosecs);
+  }
 }
 
 // ---------------- CosNotifyComm::SequencePullConsumer ---------------- //
@@ -1384,11 +1453,11 @@
 		       CosNF::Filter_ptr filter,
 		       CORBA::ULong max_events, const char* objnm,
 		       consume_batch_fn* consume_fn, type_change_fn* change_fn,
-		       CORBA::ULong millisecs, CORBA::Boolean verbose) :
+		       CORBA::ULong millisecs, CORBA::ULong delay_millisecs, CORBA::Boolean verbose) :
   _my_proxy(proxy), _my_admin(admin), _my_filters(0),
   _obj_name(objnm), _consume_fn(consume_fn), _change_fn(change_fn),
   _num_changes(0), _num_events(0), _num_batches(0), _max_events(max_events),
-  _millisecs(millisecs), _verbose(verbose), _done(0), _com_err(0),
+  _millisecs(millisecs), _delay_millisecs(delay_millisecs), _verbose(verbose), _done(0), _com_err(0),
   _oplock(), _finish(&_oplock), _worker(0)
 {
   if (! CORBA::is_nil(filter)) {
@@ -1410,6 +1479,7 @@
 			       CosN::EventTypeSeq* evs_ptr,
 			       const char* constraint_expr,
 			       CORBA::ULong millisecs,
+			       CORBA::ULong delay_millisecs,
 			       CORBA::Boolean verbose)
 {
   // Obtain appropriate proxy object
@@ -1435,7 +1505,7 @@
   write_ior_to_file(orb, proxy, proxy_ior_file, verbose);
   // Construct a client
   SequencePullConsumer_i* client =
-    new SequencePullConsumer_i(proxy, admin, filter, max_events, objnm, consume_fn, change_fn, millisecs, verbose);
+    new SequencePullConsumer_i(proxy, admin, filter, max_events, objnm, consume_fn, change_fn, millisecs, delay_millisecs, verbose);
   return client;
 }
 
@@ -1597,6 +1667,14 @@
   _num_changes++;
   if (_change_fn) (*_change_fn)(added, deled, _obj_name, _num_changes, _verbose);
   else if (_verbose) cout << _obj_name << ": offer_change received [# " << _num_changes << "]" << endl;
+  if (!_done && _delay_millisecs) {
+    unsigned long d_secs     =  _delay_millisecs / 1000;
+    unsigned long d_nanosecs = (_delay_millisecs % 1000) * 1000000;
+    if (_verbose) cout << _obj_name << ": delaying offer_change response for " << _delay_millisecs << " millisecs" << endl;
+    unsigned long t_secs, t_nanosecs;
+    omni_thread::get_time(&t_secs, &t_nanosecs, d_secs, d_nanosecs);
+    _finish.timedwait(t_secs, t_nanosecs);
+  }
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1620,11 +1698,11 @@
 	       CosNF::Filter_ptr filter,
 	       CORBA::ULong max_events, const char* objnm,
 	       supply_any_fn* supply_fn, type_change_fn* change_fn,
-	       CORBA::ULong millisecs, CORBA::Boolean verbose) :
+	       CORBA::ULong millisecs, CORBA::ULong delay_millisecs, CORBA::Boolean verbose) :
   _my_proxy(proxy), _my_admin(admin), _my_filters(0),
   _obj_name(objnm), _supply_fn(supply_fn), _change_fn(change_fn),
   _num_changes(0), _num_events(0), _max_events(max_events),
-  _millisecs(millisecs), _verbose(verbose), _done(0), _com_err(0),
+  _millisecs(millisecs), _delay_millisecs(delay_millisecs), _verbose(verbose), _done(0), _com_err(0),
   _oplock(), _finish(&_oplock), _worker(0)
 {
   // providing explict NULL for supply_fn is not OK -- must have a valid function
@@ -1648,6 +1726,7 @@
 		       CosN::EventTypeSeq* evs_ptr,
 		       const char* constraint_expr,
 		       CORBA::ULong millisecs,
+		       CORBA::ULong delay_millisecs,
 		       CORBA::Boolean verbose)
 {
   // Obtain appropriate proxy object
@@ -1673,7 +1752,7 @@
   write_ior_to_file(orb, proxy, proxy_ior_file, verbose);
   // Construct a client
   PushSupplier_i* client =
-    new PushSupplier_i(proxy, admin, filter, max_events, objnm, supply_fn, change_fn, millisecs, verbose);
+    new PushSupplier_i(proxy, admin, filter, max_events, objnm, supply_fn, change_fn, millisecs, delay_millisecs, verbose);
   return client;
 }
 
@@ -1826,6 +1905,14 @@
   _num_changes++;
   if (_change_fn) (*_change_fn)(added, deled, _obj_name, _num_changes, _verbose);
   else if (_verbose) cout << _obj_name << ": subscription_change received [# " << _num_changes << "]" << endl;
+  if (!_done && _delay_millisecs) {
+    unsigned long d_secs     =  _delay_millisecs / 1000;
+    unsigned long d_nanosecs = (_delay_millisecs % 1000) * 1000000;
+    if (_verbose) cout << _obj_name << ": delaying subscription_change response for " << _delay_millisecs << " millisecs" << endl;
+    unsigned long t_secs, t_nanosecs;
+    omni_thread::get_time(&t_secs, &t_nanosecs, d_secs, d_nanosecs);
+    _finish.timedwait(t_secs, t_nanosecs);
+  }
 }
 
 // ---------------- CosNotifyComm::StructuredPushSupplier ---------------- //
@@ -1836,11 +1923,11 @@
 			 CosNF::Filter_ptr filter,
 			 CORBA::ULong max_events, const char* objnm,
 			 supply_structured_fn* supply_fn, type_change_fn* change_fn,
-			 CORBA::ULong millisecs, CORBA::Boolean verbose) :
+			 CORBA::ULong millisecs, CORBA::ULong delay_millisecs, CORBA::Boolean verbose) :
   _my_proxy(proxy), _my_admin(admin), _my_filters(0),
   _obj_name(objnm), _supply_fn(supply_fn), _change_fn(change_fn),
   _num_changes(0), _num_events(0), _max_events(max_events),
-  _millisecs(millisecs), _verbose(verbose), _done(0), _com_err(0),
+  _millisecs(millisecs), _delay_millisecs(delay_millisecs), _verbose(verbose), _done(0), _com_err(0),
   _oplock(), _finish(&_oplock), _worker(0)
 {
   // providing explict NULL for supply_fn is not OK -- must have a valid function
@@ -1864,6 +1951,7 @@
 				 CosN::EventTypeSeq* evs_ptr,
 				 const char* constraint_expr,
 				 CORBA::ULong millisecs,
+				 CORBA::ULong delay_millisecs,
 				 CORBA::Boolean verbose)
 {
   // Obtain appropriate proxy object
@@ -1889,7 +1977,7 @@
   write_ior_to_file(orb, proxy, proxy_ior_file, verbose);
   // Construct a client
   StructuredPushSupplier_i* client =
-    new StructuredPushSupplier_i(proxy, admin, filter, max_events, objnm, supply_fn, change_fn, millisecs, verbose);
+    new StructuredPushSupplier_i(proxy, admin, filter, max_events, objnm, supply_fn, change_fn, millisecs, delay_millisecs, verbose);
   return client;
 }
 
@@ -2042,6 +2130,14 @@
   _num_changes++;
   if (_change_fn) (*_change_fn)(added, deled, _obj_name, _num_changes, _verbose);
   else if (_verbose) cout << _obj_name << ": subscription_change received [# " << _num_changes << "]" << endl;
+  if (!_done && _delay_millisecs) {
+    unsigned long d_secs     =  _delay_millisecs / 1000;
+    unsigned long d_nanosecs = (_delay_millisecs % 1000) * 1000000;
+    if (_verbose) cout << _obj_name << ": delaying subscription_change response for " << _delay_millisecs << " millisecs" << endl;
+    unsigned long t_secs, t_nanosecs;
+    omni_thread::get_time(&t_secs, &t_nanosecs, d_secs, d_nanosecs);
+    _finish.timedwait(t_secs, t_nanosecs);
+  }
 }
 
 // ---------------- CosNotifyComm::SequencePushSupplier ---------------- //
@@ -2056,11 +2152,12 @@
 		       supply_batch_fn* supply_fn,
 		       type_change_fn* change_fn,
 		       CORBA::ULong millisecs,
+		       CORBA::ULong delay_millisecs,
 		       CORBA::Boolean verbose) :
   _my_proxy(proxy), _my_admin(admin), _my_filters(0),
   _obj_name(objnm), _supply_fn(supply_fn), _change_fn(change_fn),
   _num_changes(0), _num_events(0), _batch_size(batch_size), _num_batches(0), _max_events(max_events),
-  _millisecs(millisecs), _verbose(verbose), _done(0), _com_err(0),
+  _millisecs(millisecs), _delay_millisecs(delay_millisecs), _verbose(verbose), _done(0), _com_err(0),
   _oplock(), _finish(&_oplock), _worker(0)
 {
   // providing explict NULL for supply_fn is not OK -- must have a valid function
@@ -2084,6 +2181,7 @@
 			       CosN::EventTypeSeq* evs_ptr,
 			       const char* constraint_expr,
 			       CORBA::ULong millisecs,
+			       CORBA::ULong delay_millisecs,
 			       CORBA::Boolean verbose)
 {
   // Obtain appropriate proxy object
@@ -2109,7 +2207,7 @@
   write_ior_to_file(orb, proxy, proxy_ior_file, verbose);
   // Construct a client
   SequencePushSupplier_i* client =
-    new SequencePushSupplier_i(proxy, admin, filter, max_events, batch_size, objnm, supply_fn, change_fn, millisecs, verbose);
+    new SequencePushSupplier_i(proxy, admin, filter, max_events, batch_size, objnm, supply_fn, change_fn, millisecs, delay_millisecs, verbose);
   return client;
 }
 
@@ -2265,6 +2363,14 @@
   _num_changes++;
   if (_change_fn) (*_change_fn)(added, deled, _obj_name, _num_changes, _verbose);
   else if (_verbose) cout << _obj_name << ": subscription_change received [# " << _num_changes << "]" << endl;
+  if (!_done && _delay_millisecs) {
+    unsigned long d_secs     =  _delay_millisecs / 1000;
+    unsigned long d_nanosecs = (_delay_millisecs % 1000) * 1000000;
+    if (_verbose) cout << _obj_name << ": delaying subscription_change response for " << _delay_millisecs << " millisecs" << endl;
+    unsigned long t_secs, t_nanosecs;
+    omni_thread::get_time(&t_secs, &t_nanosecs, d_secs, d_nanosecs);
+    _finish.timedwait(t_secs, t_nanosecs);
+  }
 }
 
 
@@ -2288,11 +2394,11 @@
 	       CosNF::Filter_ptr filter,
 	       CORBA::ULong max_events, const char* objnm,
 	       supply_any_fn* supply_fn, type_change_fn* change_fn,
-	       CORBA::ULong millisecs, CORBA::Boolean verbose) :
+	       CORBA::ULong millisecs, CORBA::ULong delay_millisecs, CORBA::Boolean verbose) :
   _my_proxy(proxy), _my_admin(admin), _my_filters(0),
   _obj_name(objnm), _supply_fn(supply_fn), _change_fn(change_fn),
   _num_changes(0), _num_events(0), _max_events(max_events),
-  _millisecs(millisecs), _verbose(verbose), _done(0), _com_err(0),
+  _millisecs(millisecs), _delay_millisecs(delay_millisecs), _verbose(verbose), _done(0), _com_err(0),
   _oplock(), _finish(&_oplock), _worker(0)
 {
   // providing explict NULL for supply_fn is not OK -- must have a valid function
@@ -2316,6 +2422,7 @@
 		       CosN::EventTypeSeq* evs_ptr,
 		       const char* constraint_expr,
 		       CORBA::ULong millisecs,
+		       CORBA::ULong delay_millisecs,
 		       CORBA::Boolean verbose)
 {
   // Obtain appropriate proxy object
@@ -2341,7 +2448,7 @@
   write_ior_to_file(orb, proxy, proxy_ior_file, verbose);
   // Construct a client
   PullSupplier_i* client =
-    new PullSupplier_i(proxy, admin, filter, max_events, objnm, supply_fn, change_fn, millisecs, verbose);
+    new PullSupplier_i(proxy, admin, filter, max_events, objnm, supply_fn, change_fn, millisecs, delay_millisecs, verbose);
   return client;
 }
 
@@ -2470,6 +2577,14 @@
   } else {
     if (_verbose) cout << _obj_name << ": NOT returning an event" << endl;
   }
+  if (!_done && _delay_millisecs) {
+    unsigned long d_secs     =  _delay_millisecs / 1000;
+    unsigned long d_nanosecs = (_delay_millisecs % 1000) * 1000000;
+    if (_verbose) cout << _obj_name << ": delaying try_pull response for " << _delay_millisecs << " millisecs" << endl;
+    unsigned long t_secs, t_nanosecs;
+    omni_thread::get_time(&t_secs, &t_nanosecs, d_secs, d_nanosecs);
+    _finish.timedwait(t_secs, t_nanosecs);
+  }
   return data;
 }
 
@@ -2514,6 +2629,14 @@
       _oplock.lock();
     }
   }
+  if (!_done && _delay_millisecs) {
+    unsigned long d_secs     =  _delay_millisecs / 1000;
+    unsigned long d_nanosecs = (_delay_millisecs % 1000) * 1000000;
+    if (_verbose) cout << _obj_name << ": delaying pull response for " << _delay_millisecs << " millisecs" << endl;
+    unsigned long t_secs, t_nanosecs;
+    omni_thread::get_time(&t_secs, &t_nanosecs, d_secs, d_nanosecs);
+    _finish.timedwait(t_secs, t_nanosecs);
+  }
   _oplock.unlock();
   return data;
 }
@@ -2553,6 +2676,14 @@
   _num_changes++;
   if (_change_fn) (*_change_fn)(added, deled, _obj_name, _num_changes, _verbose);
   else if (_verbose) cout << _obj_name << ": subscription_change received [# " << _num_changes << "]" << endl;
+  if (!_done && _delay_millisecs) {
+    unsigned long d_secs     =  _delay_millisecs / 1000;
+    unsigned long d_nanosecs = (_delay_millisecs % 1000) * 1000000;
+    if (_verbose) cout << _obj_name << ": delaying subscription_change response for " << _delay_millisecs << " millisecs" << endl;
+    unsigned long t_secs, t_nanosecs;
+    omni_thread::get_time(&t_secs, &t_nanosecs, d_secs, d_nanosecs);
+    _finish.timedwait(t_secs, t_nanosecs);
+  }
 }
 
 // ------------ CosNotifyComm::StructuredPullSupplier ------------ //
@@ -2563,11 +2694,11 @@
 			 CosNF::Filter_ptr filter,
 			 CORBA::ULong max_events, const char* objnm,
 			 supply_structured_fn* supply_fn, type_change_fn* change_fn,
-			 CORBA::ULong millisecs, CORBA::Boolean verbose) :
+			 CORBA::ULong millisecs, CORBA::ULong delay_millisecs, CORBA::Boolean verbose) :
   _my_proxy(proxy), _my_admin(admin), _my_filters(0),
   _obj_name(objnm), _supply_fn(supply_fn), _change_fn(change_fn),
   _num_changes(0), _num_events(0), _max_events(max_events),
-  _millisecs(millisecs), _verbose(verbose), _done(0), _com_err(0),
+  _millisecs(millisecs), _delay_millisecs(delay_millisecs), _verbose(verbose), _done(0), _com_err(0),
   _oplock(), _finish(&_oplock), _worker(0)
 {
   // providing explict NULL for supply_fn is not OK -- must have a valid function
@@ -2591,6 +2722,7 @@
 				 CosN::EventTypeSeq* evs_ptr,
 				 const char* constraint_expr,
 				 CORBA::ULong millisecs,
+				 CORBA::ULong delay_millisecs,
 				 CORBA::Boolean verbose)
 {
   // Obtain appropriate proxy object
@@ -2616,7 +2748,7 @@
   write_ior_to_file(orb, proxy, proxy_ior_file, verbose);
   // Construct a client
   StructuredPullSupplier_i* client =
-    new StructuredPullSupplier_i(proxy, admin, filter, max_events, objnm, supply_fn, change_fn, millisecs, verbose);
+    new StructuredPullSupplier_i(proxy, admin, filter, max_events, objnm, supply_fn, change_fn, millisecs, delay_millisecs, verbose);
   return client;
 }
 
@@ -2746,6 +2878,14 @@
   } else {
     if (_verbose) cout << _obj_name << ": NOT returning an event" << endl;
   }
+  if (!_done && _delay_millisecs) {
+    unsigned long d_secs     =  _delay_millisecs / 1000;
+    unsigned long d_nanosecs = (_delay_millisecs % 1000) * 1000000;
+    if (_verbose) cout << _obj_name << ": delaying try_pull_structured_event response for " << _delay_millisecs << " millisecs" << endl;
+    unsigned long t_secs, t_nanosecs;
+    omni_thread::get_time(&t_secs, &t_nanosecs, d_secs, d_nanosecs);
+    _finish.timedwait(t_secs, t_nanosecs);
+  }
   return data;
 }
 
@@ -2790,6 +2930,14 @@
       _oplock.lock();
     }
   }
+  if (!_done && _delay_millisecs) {
+    unsigned long d_secs     =  _delay_millisecs / 1000;
+    unsigned long d_nanosecs = (_delay_millisecs % 1000) * 1000000;
+    if (_verbose) cout << _obj_name << ": delaying pull_structured_event response for " << _delay_millisecs << " millisecs" << endl;
+    unsigned long t_secs, t_nanosecs;
+    omni_thread::get_time(&t_secs, &t_nanosecs, d_secs, d_nanosecs);
+    _finish.timedwait(t_secs, t_nanosecs);
+  }
   _oplock.unlock();
   return data;
 }
@@ -2829,6 +2977,14 @@
   _num_changes++;
   if (_change_fn) (*_change_fn)(added, deled, _obj_name, _num_changes, _verbose);
   else if (_verbose) cout << _obj_name << ": subscription_change received [# " << _num_changes << "]" << endl;
+  if (!_done && _delay_millisecs) {
+    unsigned long d_secs     =  _delay_millisecs / 1000;
+    unsigned long d_nanosecs = (_delay_millisecs % 1000) * 1000000;
+    if (_verbose) cout << _obj_name << ": delaying subscription_change response for " << _delay_millisecs << " millisecs" << endl;
+    unsigned long t_secs, t_nanosecs;
+    omni_thread::get_time(&t_secs, &t_nanosecs, d_secs, d_nanosecs);
+    _finish.timedwait(t_secs, t_nanosecs);
+  }
 }
 
 // ------------ CosNotifyComm::SequencePullSupplier ------------ //
@@ -2843,11 +2999,12 @@
 		       supply_batch_fn* supply_fn,
 		       type_change_fn* change_fn,
 		       CORBA::ULong millisecs,
+		       CORBA::ULong delay_millisecs,
 		       CORBA::Boolean verbose) :
   _my_proxy(proxy), _my_admin(admin), _my_filters(0),
   _obj_name(objnm), _supply_fn(supply_fn), _change_fn(change_fn),
   _num_changes(0), _num_events(0), _batch_size(batch_size), _num_batches(0), _max_events(max_events),
-  _millisecs(millisecs), _verbose(verbose), _done(0), _com_err(0),
+  _millisecs(millisecs), _delay_millisecs(delay_millisecs), _verbose(verbose), _done(0), _com_err(0),
   _oplock(), _finish(&_oplock), _worker(0)
 {
   // providing explict NULL for supply_fn is not OK -- must have a valid function
@@ -2871,6 +3028,7 @@
 			       CosN::EventTypeSeq* evs_ptr,
 			       const char* constraint_expr,
 			       CORBA::ULong millisecs,
+			       CORBA::ULong delay_millisecs,
 			       CORBA::Boolean verbose)
 {
   // Obtain appropriate proxy object
@@ -2896,7 +3054,7 @@
   write_ior_to_file(orb, proxy, proxy_ior_file, verbose);
   // Construct a client
   SequencePullSupplier_i* client =
-    new SequencePullSupplier_i(proxy, admin, filter, max_events, batch_size, objnm, supply_fn, change_fn, millisecs, verbose);
+    new SequencePullSupplier_i(proxy, admin, filter, max_events, batch_size, objnm, supply_fn, change_fn, millisecs, delay_millisecs, verbose);
   return client;
 }
 
@@ -3028,6 +3186,14 @@
   } else {
     if (_verbose) cout << _obj_name << ": NOT returning a batch" << endl;
   }
+  if (!_done && _delay_millisecs) {
+    unsigned long d_secs     =  _delay_millisecs / 1000;
+    unsigned long d_nanosecs = (_delay_millisecs % 1000) * 1000000;
+    if (_verbose) cout << _obj_name << ": delaying try_pull_structured_events response for " << _delay_millisecs << " millisecs" << endl;
+    unsigned long t_secs, t_nanosecs;
+    omni_thread::get_time(&t_secs, &t_nanosecs, d_secs, d_nanosecs);
+    _finish.timedwait(t_secs, t_nanosecs);
+  }
   return data;
 }
 
@@ -3075,6 +3241,14 @@
       _oplock.lock();
     }
   }
+  if (!_done && _delay_millisecs) {
+    unsigned long d_secs     =  _delay_millisecs / 1000;
+    unsigned long d_nanosecs = (_delay_millisecs % 1000) * 1000000;
+    if (_verbose) cout << _obj_name << ": delaying pull_structured_events response for " << _delay_millisecs << " millisecs" << endl;
+    unsigned long t_secs, t_nanosecs;
+    omni_thread::get_time(&t_secs, &t_nanosecs, d_secs, d_nanosecs);
+    _finish.timedwait(t_secs, t_nanosecs);
+  }
   _oplock.unlock();
   return data;
 }
@@ -3114,4 +3288,12 @@
   _num_changes++;
   if (_change_fn) (*_change_fn)(added, deled, _obj_name, _num_changes, _verbose);
   else if (_verbose) cout << _obj_name << ": subscription_change received [# " << _num_changes << "]" << endl;
+  if (!_done && _delay_millisecs) {
+    unsigned long d_secs     =  _delay_millisecs / 1000;
+    unsigned long d_nanosecs = (_delay_millisecs % 1000) * 1000000;
+    if (_verbose) cout << _obj_name << ": delaying subscription_change response for " << _delay_millisecs << " millisecs" << endl;
+    unsigned long t_secs, t_nanosecs;
+    omni_thread::get_time(&t_secs, &t_nanosecs, d_secs, d_nanosecs);
+    _finish.timedwait(t_secs, t_nanosecs);
+  }
 }
Index: examples/sample_clients.h
===================================================================
RCS file: /cvsroot/omniNotify/examples/sample_clients.h,v
retrieving revision 1.8
retrieving revision 1.8.2.2
diff -u -u -r1.8 -r1.8.2.2
--- examples/sample_clients.h	2001/08/03 17:54:13	1.8
+++ examples/sample_clients.h	2002/02/28 23:43:57	1.8.2.2
@@ -107,6 +107,8 @@
 // Helper Classes                                                //
 ///////////////////////////////////////////////////////////////////
 
+#ifndef __GenericWorker__
+#define __GenericWorker__
 class GenericWorker {
 public:
   GenericWorker() {;}
@@ -123,6 +125,7 @@
   GenericWorker* _worker;
   GenericBoundWorkerThread()  {;}
 };
+#endif /*  __GenericWorker__  */
 
 ///////////////////////////////////////////////////////////////////
 //                   PUSH  CONSUMER  EXAMPLES                    //
@@ -139,7 +142,7 @@
   PushConsumer_i(CosNA::ProxyPushSupplier_ptr proxy, CosNA::ConsumerAdmin_ptr admin, CosNF::Filter_ptr filter,
 		 CORBA::ULong max_events,
 		 const char* objnm, consume_any_fn* consume_fn, type_change_fn* change_fn,
-		 CORBA::ULong millisecs, CORBA::Boolean verbose);
+		 CORBA::ULong millisecs, CORBA::ULong delay_millisecs, CORBA::Boolean verbose);
 
   static PushConsumer_i* 
   create(CORBA::ORB_ptr orb,
@@ -154,6 +157,7 @@
 	 CosN::EventTypeSeq* evs_ptr = 0,
 	 const char* constraint_expr = "",
 	 CORBA::ULong millisecs = 0,
+	 CORBA::ULong delay_millisecs = 0,
 	 CORBA::Boolean verbose = 0);
 
   // IDL methods
@@ -179,6 +183,7 @@
   CORBA::ULong                _num_events;
   CORBA::ULong                _max_events;
   CORBA::ULong                _millisecs;
+  CORBA::ULong                _delay_millisecs;
   CORBA::Boolean              _verbose;
   CORBA::Boolean              _done;
   CORBA::Boolean              _com_err;
@@ -198,7 +203,7 @@
   StructuredPushConsumer_i(CosNA::StructuredProxyPushSupplier_ptr proxy, CosNA::ConsumerAdmin_ptr admin, CosNF::Filter_ptr filter,
 			   CORBA::ULong max_events,
 			   const char* objnm, consume_structured_fn* consume_fn, type_change_fn* change_fn,
-			   CORBA::ULong millisecs, CORBA::Boolean verbose);
+			   CORBA::ULong millisecs, CORBA::ULong delay_millisecs, CORBA::Boolean verbose);
 
   static StructuredPushConsumer_i*
   create(CORBA::ORB_ptr orb,
@@ -213,6 +218,7 @@
 	 CosN::EventTypeSeq* evs_ptr = 0,
 	 const char* constraint_expr = "",
 	 CORBA::ULong millisecs = 0,
+	 CORBA::ULong delay_millisecs = 0,
 	 CORBA::Boolean verbose = 0);
 
   // IDL methods
@@ -238,6 +244,7 @@
   CORBA::ULong                          _num_events;
   CORBA::ULong                          _max_events;
   CORBA::ULong                          _millisecs;
+  CORBA::ULong                          _delay_millisecs;
   CORBA::Boolean                        _verbose;
   CORBA::Boolean                        _done;
   CORBA::Boolean                        _com_err;
@@ -257,7 +264,7 @@
   SequencePushConsumer_i(CosNA::SequenceProxyPushSupplier_ptr proxy, CosNA::ConsumerAdmin_ptr admin, CosNF::Filter_ptr filter,
 			 CORBA::ULong max_events,
 			 const char* objnm, consume_batch_fn* consume_fn, type_change_fn* change_fn,
-			 CORBA::ULong millisecs, CORBA::Boolean verbose);
+			 CORBA::ULong millisecs, CORBA::ULong delay_millisecs, CORBA::Boolean verbose);
 
   static SequencePushConsumer_i*
   create(CORBA::ORB_ptr orb,
@@ -272,6 +279,7 @@
 	 CosN::EventTypeSeq* evs_ptr = 0,
 	 const char* constraint_expr = "",
 	 CORBA::ULong millisecs = 0,
+	 CORBA::ULong delay_millisecs = 0,
 	 CORBA::Boolean verbose = 0);
 
   // IDL methods
@@ -298,6 +306,7 @@
   CORBA::ULong                        _num_batches;
   CORBA::ULong                        _max_events;
   CORBA::ULong                        _millisecs;
+  CORBA::ULong                        _delay_millisecs;
   CORBA::Boolean                      _verbose;
   CORBA::Boolean                      _done;
   CORBA::Boolean                      _com_err;
@@ -321,7 +330,7 @@
   PullConsumer_i(CosNA::ProxyPullSupplier_ptr proxy, CosNA::ConsumerAdmin_ptr admin, CosNF::Filter_ptr filter,
 		 CORBA::ULong max_events,
 		 const char* objnm, consume_any_fn* consume_fn, type_change_fn* change_fn,
-		 CORBA::ULong millisecs, CORBA::Boolean verbose);
+		 CORBA::ULong millisecs, CORBA::ULong delay_millisecs, CORBA::Boolean verbose);
 
   static PullConsumer_i*
   create(CORBA::ORB_ptr orb,
@@ -336,6 +345,7 @@
 	 CosN::EventTypeSeq* evs_ptr = 0,
 	 const char* constraint_expr = "",
 	 CORBA::ULong millisecs = 0,
+	 CORBA::ULong delay_millisecs = 0,
 	 CORBA::Boolean verbose = 0);
 
   // IDL methods
@@ -360,6 +370,7 @@
   CORBA::ULong                _num_events;
   CORBA::ULong                _max_events;
   CORBA::ULong                _millisecs;
+  CORBA::ULong                _delay_millisecs;
   CORBA::Boolean              _verbose;
   CORBA::Boolean              _done;
   CORBA::Boolean              _com_err;
@@ -379,7 +390,7 @@
   StructuredPullConsumer_i(CosNA::StructuredProxyPullSupplier_ptr proxy, CosNA::ConsumerAdmin_ptr admin, CosNF::Filter_ptr filter,
 			   CORBA::ULong max_events,
 			   const char* objnm, consume_structured_fn* consume_fn, type_change_fn* change_fn,
-			   CORBA::ULong millisecs, CORBA::Boolean verbose);
+			   CORBA::ULong millisecs, CORBA::ULong delay_millisecs, CORBA::Boolean verbose);
 
   static StructuredPullConsumer_i*
   create(CORBA::ORB_ptr orb,
@@ -394,6 +405,7 @@
 	 CosN::EventTypeSeq* evs_ptr = 0,
 	 const char* constraint_expr = "",
 	 CORBA::ULong millisecs = 0,
+	 CORBA::ULong delay_millisecs = 0,
 	 CORBA::Boolean verbose = 0);
 
   // IDL methods
@@ -418,6 +430,7 @@
   CORBA::ULong                          _num_events;
   CORBA::ULong                          _max_events;
   CORBA::ULong                          _millisecs;
+  CORBA::ULong                          _delay_millisecs;
   CORBA::Boolean                        _verbose;
   CORBA::Boolean                        _done;
   CORBA::Boolean                        _com_err;
@@ -437,7 +450,7 @@
   SequencePullConsumer_i(CosNA::SequenceProxyPullSupplier_ptr proxy, CosNA::ConsumerAdmin_ptr admin, CosNF::Filter_ptr filter,
 			 CORBA::ULong max_events,
 			 const char* objnm, consume_batch_fn* consume_fn, type_change_fn* change_fn,
-			 CORBA::ULong millisecs, CORBA::Boolean verbose);
+			 CORBA::ULong millisecs, CORBA::ULong delay_millisecs, CORBA::Boolean verbose);
 
   static SequencePullConsumer_i*
   create(CORBA::ORB_ptr orb,
@@ -452,6 +465,7 @@
 	 CosN::EventTypeSeq* evs_ptr = 0,
 	 const char* constraint_expr = "",
 	 CORBA::ULong millisecs = 0,
+	 CORBA::ULong delay_millisecs = 0,
 	 CORBA::Boolean verbose = 0);
 
   // IDL methods
@@ -477,6 +491,7 @@
   CORBA::ULong                        _num_batches;
   CORBA::ULong                        _max_events;
   CORBA::ULong                        _millisecs;
+  CORBA::ULong                        _delay_millisecs;
   CORBA::Boolean                      _verbose;
   CORBA::Boolean                      _done;
   CORBA::Boolean                      _com_err;
@@ -510,7 +525,7 @@
   PushSupplier_i(CosNA::ProxyPushConsumer_ptr proxy, CosNA::SupplierAdmin_ptr admin, CosNF::Filter_ptr filter,
 		 CORBA::ULong max_events,
 		 const char* objnm, supply_any_fn* supply_fn, type_change_fn* change_fn,
-		 CORBA::ULong millisecs, CORBA::Boolean verbose);
+		 CORBA::ULong millisecs, CORBA::ULong delay_millisecs, CORBA::Boolean verbose);
 
   static PushSupplier_i*
   create(CORBA::ORB_ptr orb,
@@ -525,6 +540,7 @@
 	 CosN::EventTypeSeq* evs_ptr = 0,
 	 const char* constraint_expr = "",
 	 CORBA::ULong millisecs = 0,
+	 CORBA::ULong delay_millisecs = 0,
 	 CORBA::Boolean verbose = 0);
 
   // IDL methods
@@ -548,6 +564,7 @@
   CORBA::ULong                _num_events;
   CORBA::ULong                _max_events;
   CORBA::ULong                _millisecs;
+  CORBA::ULong                _delay_millisecs;
   CORBA::Boolean              _verbose;
   CORBA::Boolean              _done;
   CORBA::Boolean              _com_err;
@@ -567,7 +584,7 @@
   StructuredPushSupplier_i(CosNA::StructuredProxyPushConsumer_ptr proxy, CosNA::SupplierAdmin_ptr admin, CosNF::Filter_ptr filter,
 			   CORBA::ULong max_events,
 			   const char* objnm, supply_structured_fn* supply_fn, type_change_fn* change_fn,
-			   CORBA::ULong millisecs, CORBA::Boolean verbose);
+			   CORBA::ULong millisecs, CORBA::ULong delay_millisecs, CORBA::Boolean verbose);
 
   static StructuredPushSupplier_i*
   create(CORBA::ORB_ptr orb,
@@ -582,6 +599,7 @@
 	 CosN::EventTypeSeq* evs_ptr = 0,
 	 const char* constraint_expr = "",
 	 CORBA::ULong millisecs = 0,
+	 CORBA::ULong delay_millisecs = 0,
 	 CORBA::Boolean verbose = 0);
 
   // IDL methods
@@ -605,6 +623,7 @@
   CORBA::ULong                          _num_events;
   CORBA::ULong                          _max_events;
   CORBA::ULong                          _millisecs;
+  CORBA::ULong                          _delay_millisecs;
   CORBA::Boolean                        _verbose;
   CORBA::Boolean                        _done;
   CORBA::Boolean                        _com_err;
@@ -624,7 +643,7 @@
   SequencePushSupplier_i(CosNA::SequenceProxyPushConsumer_ptr proxy, CosNA::SupplierAdmin_ptr admin, CosNF::Filter_ptr filter,
 			 CORBA::ULong max_events, CORBA::ULong batch_size,
 			 const char* objnm, supply_batch_fn* supply_fn, type_change_fn* change_fn,
-			 CORBA::ULong millisecs, CORBA::Boolean verbose);
+			 CORBA::ULong millisecs, CORBA::ULong delay_millisecs, CORBA::Boolean verbose);
 
   static SequencePushSupplier_i*
   create(CORBA::ORB_ptr orb,
@@ -639,6 +658,7 @@
 	 CosN::EventTypeSeq* evs_ptr = 0,
 	 const char* constraint_expr = "",
 	 CORBA::ULong millisecs = 0,
+	 CORBA::ULong delay_millisecs = 0,
 	 CORBA::Boolean verbose = 0);
 
   // IDL methods
@@ -664,6 +684,7 @@
   CORBA::ULong                        _num_batches;
   CORBA::ULong                        _max_events;
   CORBA::ULong                        _millisecs;
+  CORBA::ULong                        _delay_millisecs;
   CORBA::Boolean                      _verbose;
   CORBA::Boolean                      _done;
   CORBA::Boolean                      _com_err;
@@ -695,7 +716,7 @@
   PullSupplier_i(CosNA::ProxyPullConsumer_ptr proxy, CosNA::SupplierAdmin_ptr admin, CosNF::Filter_ptr filter,
 		 CORBA::ULong max_events,
 		 const char* objnm, supply_any_fn* supply_fn, type_change_fn* change_fn,
-		 CORBA::ULong millisecs, CORBA::Boolean verbose);
+		 CORBA::ULong millisecs, CORBA::ULong delay_millisecs, CORBA::Boolean verbose);
 
   static PullSupplier_i*
   create(CORBA::ORB_ptr orb,
@@ -710,6 +731,7 @@
 	 CosN::EventTypeSeq* evs_ptr = 0,
 	 const char* constraint_expr = "",
 	 CORBA::ULong millisecs = 0,
+	 CORBA::ULong delay_millisecs = 0,
 	 CORBA::Boolean verbose = 0);
 
   // IDL methods
@@ -735,6 +757,7 @@
   CORBA::ULong                _num_events;
   CORBA::ULong                _max_events;
   CORBA::ULong                _millisecs;
+  CORBA::ULong                _delay_millisecs;
   CORBA::Boolean              _verbose;
   CORBA::Boolean              _done;
   CORBA::Boolean              _com_err;
@@ -754,7 +777,7 @@
   StructuredPullSupplier_i(CosNA::StructuredProxyPullConsumer_ptr proxy, CosNA::SupplierAdmin_ptr admin, CosNF::Filter_ptr filter,
 			   CORBA::ULong max_events,
 			   const char* objnm, supply_structured_fn* supply_fn, type_change_fn* change_fn,
-			   CORBA::ULong millisecs, CORBA::Boolean verbose);
+			   CORBA::ULong millisecs, CORBA::ULong delay_millisecs, CORBA::Boolean verbose);
 
   static StructuredPullSupplier_i*
   create(CORBA::ORB_ptr orb,
@@ -769,6 +792,7 @@
 	 CosN::EventTypeSeq* evs_ptr = 0,
 	 const char* constraint_expr = "",
 	 CORBA::ULong millisecs = 0,
+	 CORBA::ULong delay_millisecs = 0,
 	 CORBA::Boolean verbose = 0);
 
   // IDL methods
@@ -794,6 +818,7 @@
   CORBA::ULong                          _num_events;
   CORBA::ULong                          _max_events;
   CORBA::ULong                          _millisecs;
+  CORBA::ULong                          _delay_millisecs;
   CORBA::Boolean                        _verbose;
   CORBA::Boolean                        _done;
   CORBA::Boolean                        _com_err;
@@ -813,7 +838,7 @@
   SequencePullSupplier_i(CosNA::SequenceProxyPullConsumer_ptr proxy, CosNA::SupplierAdmin_ptr admin, CosNF::Filter_ptr filter,
 			 CORBA::ULong max_events, CORBA::ULong batch_size,
 			 const char* objnm, supply_batch_fn* supply_fn, type_change_fn* change_fn,
-			 CORBA::ULong millisecs, CORBA::Boolean verbose);
+			 CORBA::ULong millisecs, CORBA::ULong delay_millisecs, CORBA::Boolean verbose);
 
   static SequencePullSupplier_i*
   create(CORBA::ORB_ptr orb,
@@ -828,6 +853,7 @@
 	 CosN::EventTypeSeq* evs_ptr = 0,
 	 const char* constraint_expr = "",
 	 CORBA::ULong millisecs = 0,
+	 CORBA::ULong delay_millisecs = 0,
 	 CORBA::Boolean verbose = 0);
 
   // IDL methods
@@ -856,6 +882,7 @@
   CORBA::ULong                        _num_batches;
   CORBA::ULong                        _max_events;
   CORBA::ULong                        _millisecs;
+  CORBA::ULong                        _delay_millisecs;
   CORBA::Boolean                      _verbose;
   CORBA::Boolean                      _done;
   CORBA::Boolean                      _com_err;
Index: examples/ten_any_pull_consumers.cc
===================================================================
RCS file: /cvsroot/omniNotify/examples/ten_any_pull_consumers.cc,v
retrieving revision 1.3
retrieving revision 1.3.2.1
diff -u -u -r1.3 -r1.3.2.1
--- examples/ten_any_pull_consumers.cc	2001/08/03 17:54:13	1.3
+++ examples/ten_any_pull_consumers.cc	2002/02/28 23:43:57	1.3.2.1
@@ -21,7 +21,7 @@
   char* ior_file = 0; 
   char* proxy_ior_file = 0; 
   char* admin_ior_file = 0;
-  CORBA::ULong num_events = 0, num_con_events = 0, batch_size = 0, millisecs = 0;
+  CORBA::ULong num_events = 0, num_con_events = 0, batch_size = 0, millisecs = 0, delay_millisecs = 0;
   CORBA::Boolean verbose = 0;
   
   omniORB::maxTcpConnectionPerServer = 50;
@@ -37,7 +37,7 @@
 
     // (2) parse the command line arguments
     if (parse_cmd_line(argc, argv, pname, SUPPORTS_FILTERS,
-		       num_events, batch_size, millisecs, verbose,
+		       num_events, batch_size, millisecs, delay_millisecs, verbose,
 		       channel_name, ior_file, proxy_ior_file, admin_ior_file, evs, constraint_expr)) {
       goto error_return; // command line parsing failed
     }
@@ -65,7 +65,7 @@
       a_pull_c[i] =
 	PullConsumer_i::create(orb, channel, num_con_events, batch_size, CORBA::string_dup(buf),
 			       "", "", sample_consume_any_fn, sample_offer_change_fn,
-			       &evs, constraint_expr, millisecs, verbose);
+			       &evs, constraint_expr, millisecs, delay_millisecs, verbose);
       if (! a_pull_c[i]) {
 	goto error_return; // failed to create a client
       }
Index: include/CosEventChannelAdmin_i.h
===================================================================
RCS file: /cvsroot/omniNotify/include/CosEventChannelAdmin_i.h,v
retrieving revision 1.25
retrieving revision 1.25.2.1
diff -u -u -r1.25 -r1.25.2.1
--- include/CosEventChannelAdmin_i.h	2001/09/19 21:10:01	1.25
+++ include/CosEventChannelAdmin_i.h	2002/02/28 23:43:58	1.25.2.1
@@ -31,6 +31,12 @@
  
 /*
 $Log: CosEventChannelAdmin_i.h,v $
+Revision 1.25.2.1  2002/02/28 23:43:58  alcfp
+merge alpha branch back into dev for latest fixes
+
+Revision 1.25.4.1  2002/02/20 21:18:04  alcfp
+steps towards correct oref refcounts
+
 Revision 1.25  2001/09/19 21:10:01  alcfp
 Added cleanup support to interactive api
 
@@ -115,6 +121,7 @@
 			     WRAPPED_DECLARG );
 
   // (Local only -- not available via RPC)
+  CORBA::Boolean is_connected() const { return _pxstate == RDI_Connected; }
   void disconnect_client_and_dispose(CORBA::Boolean remove_proxy_from_admin = 0);
 
   RDIstrstream& log_output(RDIstrstream& str) const;
@@ -164,6 +171,7 @@
 			     WRAPPED_DECLARG );
 
   // (Local only -- not available via RPC)
+  CORBA::Boolean is_connected() const { return _pxstate == RDI_Connected; }
   virtual CORBA::Boolean is_available(unsigned long* wait_s, unsigned long* wait_t);
   virtual void pull_event(CORBA::Boolean& invalid);
   void disconnect_client_and_dispose(CORBA::Boolean remove_proxy_from_admin = 0);
@@ -223,6 +231,7 @@
   void disconnect_push_supplier( WRAPPED_DECLARG_VOID );
 
   // (Local only -- not available via RPC)
+  CORBA::Boolean is_connected() const { return _pxstate == RDI_Connected; }
   void add_event(RDI_StructuredEvent* event);
   virtual void push_event(CORBA::Boolean& invalid);
   void disconnect_client_and_dispose(CORBA::Boolean remove_proxy_from_admin = 0);
@@ -281,6 +290,7 @@
   void        disconnect_pull_supplier( WRAPPED_DECLARG_VOID );
 
   // (Local only -- not available via RPC)
+  CORBA::Boolean is_connected() const { return _pxstate == RDI_Connected; }
   void add_event(RDI_StructuredEvent* event);
   void disconnect_client_and_dispose(CORBA::Boolean remove_proxy_from_admin = 0);
 
Index: include/CosNotifyChannelAdmin_i.h
===================================================================
RCS file: /cvsroot/omniNotify/include/CosNotifyChannelAdmin_i.h,v
retrieving revision 1.102
retrieving revision 1.102.2.2
diff -u -u -r1.102 -r1.102.2.2
--- include/CosNotifyChannelAdmin_i.h	2001/10/06 00:44:10	1.102
+++ include/CosNotifyChannelAdmin_i.h	2002/03/13 08:57:16	1.102.2.2
@@ -31,6 +31,18 @@
  
 /*
 $Log: CosNotifyChannelAdmin_i.h,v $
+Revision 1.102.2.2  2002/03/13 08:57:16  alcfp
+fixed oref counting bug in get_filter implementations
+
+Revision 1.102.2.1  2002/02/28 23:43:58  alcfp
+merge alpha branch back into dev for latest fixes
+
+Revision 1.102.4.2  2002/02/20 21:18:04  alcfp
+steps towards correct oref refcounts
+
+Revision 1.102.4.1  2002/02/08 10:40:16  alcfp
+fixed oplock cleanup bug for deferred disposal case, also suppressed event rejection report when channel is shutting down
+
 Revision 1.102  2001/10/06 00:44:10  alcfp
 moved some EventChannel_i state to private
 
@@ -205,8 +217,8 @@
 
   // Methods from CosNF::FilterAdmin Interface
   CosNF::FilterID     add_filter(CosNF::Filter_ptr filter);
-  void               remove_filter(CosNF::FilterID fltrID);
-  void               remove_all_filters();
+  void                remove_filter(CosNF::FilterID fltrID);
+  void                remove_all_filters();
   CosNF::Filter_ptr   get_filter(CosNF::FilterID fltrID);
   CosNF::FilterIDSeq* get_all_filters();
 
@@ -714,8 +726,8 @@
 
   // Methods from CosNF::FilterAdmin Interface
   CosNF::FilterID     add_filter(CosNF::Filter_ptr filter);
-  void               remove_filter(CosNF::FilterID fltrID);
-  void               remove_all_filters();
+  void                remove_filter(CosNF::FilterID fltrID);
+  void                remove_all_filters();
   CosNF::Filter_ptr   get_filter(CosNF::FilterID fltrID);
   CosNF::FilterIDSeq* get_all_filters();
 
@@ -1274,6 +1286,7 @@
 
 private:
   RDIOplockEntry*                 _oplockptr;
+  AttN::ConsumerAdmin_var         _my_oref;
   AttN::NameSeq                   _my_name;
   // _disposed is true once _disconnect_clients_and_dispose has been called
   CORBA::Boolean                  _disposed;
@@ -1382,10 +1395,10 @@
 
   // Methods from CosNF::FilterAdmin Interface
   CosNF::FilterID     add_filter(CosNF::Filter_ptr filter WRAPPED_DECLARG );
-  void               remove_filter(CosNF::FilterID fltrID WRAPPED_DECLARG );
+  void                remove_filter(CosNF::FilterID fltrID WRAPPED_DECLARG );
   CosNF::Filter_ptr   get_filter(CosNF::FilterID fltrID WRAPPED_DECLARG );
   CosNF::FilterIDSeq* get_all_filters( WRAPPED_DECLARG_VOID );
-  void               remove_all_filters( WRAPPED_DECLARG_VOID );
+  void                remove_all_filters( WRAPPED_DECLARG_VOID );
 
   // Methods from CosNC::NotifyPublish Interface
   // Called externally -- not clear that suppliers should be doing this!
@@ -1445,6 +1458,7 @@
 
 private:
   RDIOplockEntry*                 _oplockptr;
+  AttN::SupplierAdmin_var         _my_oref;
   AttN::NameSeq                   _my_name;
   // _disposed is true once _disconnect_clients_and_dispose has been called
   CORBA::Boolean                  _disposed;
@@ -1684,8 +1698,11 @@
   RDI_ChangePool*        ochange_pool()  { if (_shutmedown) return 0; return _ochange_pool; }
   RDI_ChangePool*        schange_pool()  { if (_shutmedown) return 0; return _schange_pool; }
 
+  CORBA::Boolean shutting_down() { return _shutmedown; }
+
 private:
   RDIOplockEntry*        _oplockptr;
+  AttN::EventChannel_var _my_oref;
   AttN::NameSeq          _my_name;
   EventChannelFactory_i* _my_channel_factory;
   ConsumerAdmin_i*       _def_consumer_admin;
@@ -1935,6 +1952,7 @@
 
 private:
   RDIOplockEntry*                              _oplockptr;
+  AttN::EventChannelFactory_var                _my_oref;
   FilterFactory_i*                             _ffactory;
   AttN::NameSeq                                _my_name;
   // _disposed is true once cleanup_and_dispose has been called
Index: include/CosNotifyFilter_i.h
===================================================================
RCS file: /cvsroot/omniNotify/include/CosNotifyFilter_i.h,v
retrieving revision 1.52
retrieving revision 1.52.2.2
diff -u -u -r1.52 -r1.52.2.2
--- include/CosNotifyFilter_i.h	2001/10/06 00:43:34	1.52
+++ include/CosNotifyFilter_i.h	2002/03/13 08:57:16	1.52.2.2
@@ -31,6 +31,15 @@
  
 /*
 $Log: CosNotifyFilter_i.h,v $
+Revision 1.52.2.2  2002/03/13 08:57:16  alcfp
+fixed oref counting bug in get_filter implementations
+
+Revision 1.52.2.1  2002/02/28 23:43:58  alcfp
+merge alpha branch back into dev for latest fixes
+
+Revision 1.52.4.1  2002/02/08 10:40:16  alcfp
+fixed oplock cleanup bug for deferred disposal case, also suppressed event rejection report when channel is shutting down
+
 Revision 1.52  2001/10/06 00:43:34  alcfp
 small compiler warning fix
 
@@ -357,9 +366,19 @@
   CORBA::Boolean match_typed(const CosN::PropertySeq & event,
 			     WRAPPED_OUTARG_TYPE(CORBA::Any) result_to_set
 			     WRAPPED_DECLARG );
+
+  // class state
+  static omni_mutex          _classlock;
+  static CORBA::Long         _classctr;
+
+  // The following methods are not available to Notification clients
+
+  const AttN::NameSeq& L_my_name() { return _my_name; }
+
  private:
   RDIOplockEntry*            _oplockptr;
   CORBA::Boolean             _disposed;        // true once cleanup_and_dispose called
+  AttN::NameSeq              _my_name;
   char*                      _constraint_grammar;
   CORBA::Any                 _def_value;
 
@@ -440,12 +459,12 @@
   FAdminHelper();
   ~FAdminHelper();
 
-  // Methods from CosNF::FilterAdmin Interface
+  // Methods to help implement CosNF::FilterAdmin Interface
 
-  CosNF::Filter_ptr    get_filter(CosNF::FilterID fltrID WRAPPED_DECLARG );
-  CosNF::FilterIDSeq*  get_all_filters( WRAPPED_DECLARG_VOID );
-  void                 remove_filter(CosNF::FilterID fltrID WRAPPED_DECLARG );
-  void                 remove_all_filters( WRAPPED_DECLARG_VOID );
+  CosNF::Filter_ptr    get_filter(CosNF::FilterID fltrID);
+  CosNF::FilterIDSeq*  get_all_filters();
+  void                 remove_filter(CosNF::FilterID fltrID);
+  void                 remove_all_filters();
 
   // omniNotify-specific methods
 
Index: include/RDI.h
===================================================================
RCS file: /cvsroot/omniNotify/include/RDI.h,v
retrieving revision 1.18
retrieving revision 1.18.2.1
diff -u -u -r1.18 -r1.18.2.1
--- include/RDI.h	2001/10/04 06:48:31	1.18
+++ include/RDI.h	2002/02/28 23:43:58	1.18.2.1
@@ -35,6 +35,15 @@
  
 /*
 $Log: RDI.h,v $
+Revision 1.18.2.1  2002/02/28 23:43:58  alcfp
+merge alpha branch back into dev for latest fixes
+
+Revision 1.18.4.2  2002/02/27 02:31:44  alcfp
+small fix
+
+Revision 1.18.4.1  2002/02/26 22:27:50  alcfp
+added ReportInteractive flag - controls whether results of interactive cmds are output to report log, also added wait_for_destroy support
+
 Revision 1.18  2001/10/04 06:48:31  alcfp
 Added report thread, changed ReportingInterval param to have units = seconds
 
@@ -88,7 +97,8 @@
   static AttN::Server_ptr get_server() { return AttN::Server::_duplicate(_Server); }
   static RDI_ServerQoS*   get_server_qos();
 
-  static RDINotifServer* get_server_i() { return _Server_i; }
+  static RDINotifServer* get_server_i();
+  static void wait_for_destroy();
 
   static void CleanupAll();
   // shutting down daemon; cleanup all global state
@@ -207,6 +217,7 @@
 #define RDIRptNotifQoSF      (1 <<  9)
 #define RDIRptAdminQoSF      (1 << 10)
 #define RDIRptServerQoSF     (1 << 11)
+#define RDIRptInteractiveF   (1 << 12)
 // ...
 
 
@@ -242,6 +253,7 @@
 #define RDIRptNotifQoS      (RDI::RptFlags() & RDIRptNotifQoSF     )
 #define RDIRptAdminQoS      (RDI::RptFlags() & RDIRptAdminQoSF     )
 #define RDIRptServerQoS     (RDI::RptFlags() & RDIRptServerQoSF    )
+#define RDIRptInteractive   (RDI::RptFlags() & RDIRptInteractiveF  )
 
 // config file names for the flags
 #define RDIDbgDaemon_nm        "DebugDaemon"
@@ -273,6 +285,7 @@
 #define RDIRptNotifQoS_nm      "ReportNotifQoS"
 #define RDIRptAdminQoS_nm      "ReportAdminQoS"
 #define RDIRptServerQoS_nm     "ReportServerQoS"
+#define RDIRptInteractive_nm   "ReportInteractive"
 
 #define MacroArg2String(s) #s
 
@@ -343,6 +356,7 @@
 #define RDIRptNotifQoSLog(stuff) RDIRptLog(RDIRptNotifQoS, RDIRptNotifQoS_nm, stuff)
 #define RDIRptAdminQoSLog(stuff) RDIRptLog(RDIRptAdminQoS, RDIRptAdminQoS_nm, stuff)
 #define RDIRptServerQoSLog(stuff) RDIRptLog(RDIRptServerQoS, RDIRptServerQoS_nm, stuff)
+#define RDIRptInteractiveLog(stuff) RDIRptLog(RDIRptInteractive, RDIRptInteractive_nm, stuff)
 
 /////////////////////////////////////////////////////////////////////////////////
 // Additional macros
Index: include/RDIEvent.h
===================================================================
RCS file: /cvsroot/omniNotify/include/RDIEvent.h,v
retrieving revision 1.38
retrieving revision 1.38.2.2
diff -u -u -r1.38 -r1.38.2.2
--- include/RDIEvent.h	2001/08/03 17:54:14	1.38
+++ include/RDIEvent.h	2002/02/28 23:43:58	1.38.2.2
@@ -31,6 +31,15 @@
  
 /*
   $Log: RDIEvent.h,v $
+  Revision 1.38.2.2  2002/02/28 23:43:58  alcfp
+  merge alpha branch back into dev for latest fixes
+
+  Revision 1.38.4.1  2002/02/07 18:10:55  alcfp
+  merged recent dev fixes into alpha
+
+  Revision 1.38.2.1  2001/10/31 16:39:04  alcfp
+  fixed typo that caused a memory leak
+
   Revision 1.38  2001/08/03 17:54:14  alcfp
   added support for AttNotification
 
@@ -602,7 +611,7 @@
   if (_fdata_rtval) { delete [] _fdata_rtval; _fdata_rtval = 0; }
   RDI_DELNULL(_cached_ename_rtval);
   RDI_DELNULL(_cached_dname_rtval);
-  RDI_DELNULL(_cached_ename_rtval);
+  RDI_DELNULL(_cached_tname_rtval);
   RDI_DELNULL(_cached_top_rtval);
   RDI_DELNULL(_cached_hdr_rtval);
   RDI_DELNULL(_cached_vahdr_rtval);
Index: include/RDINotifServer.h
===================================================================
RCS file: /cvsroot/omniNotify/include/RDINotifServer.h,v
retrieving revision 1.6
retrieving revision 1.6.2.1
diff -u -u -r1.6 -r1.6.2.1
--- include/RDINotifServer.h	2001/10/04 02:23:24	1.6
+++ include/RDINotifServer.h	2002/02/28 23:43:59	1.6.2.1
@@ -31,6 +31,12 @@
  
 /*
 $Log: RDINotifServer.h,v $
+Revision 1.6.2.1  2002/02/28 23:43:59  alcfp
+merge alpha branch back into dev for latest fixes
+
+Revision 1.6.4.1  2002/02/26 22:27:50  alcfp
+added ReportInteractive flag - controls whether results of interactive cmds are output to report log, also added wait_for_destroy support
+
 Revision 1.6  2001/10/04 02:23:24  alcfp
 moved local clock params into ServerQoS
 
@@ -122,10 +128,18 @@
 
   const AttN::NameSeq& L_my_name() { return _my_name; }
 
+  // This method normally called by main program thread.
+  // It waits for destroy to be invoked, then invokes _destroy.
+  void L_wait_for_destroy(); 
+
+  CORBA::Boolean destroyed() { return _destroyed; }
+
 private:
   RDIOplockEntry*                _oplockptr;
   AttN::NameSeq                  _my_name;
+  omni_condition*                _destroy_wait;
   CORBA::Boolean                 _destroyed;
+  CORBA::Boolean                 _destroy_called;
   RDI_Config*                    _configp; 
   FilterFactory_i*               _ffactory_i;
   AttN::FilterFactory_var        _ffactory; 
@@ -134,6 +148,8 @@
   EventChannel_i*                _channel_i;
   AttN::EventChannel_var         _channel;
   RDI_ServerQoS*                 _server_qos;
+
+  void _destroy(); // do the real destroy work
 
   virtual ~RDINotifServer();
 };
Index: include/RDIOplocks.h
===================================================================
RCS file: /cvsroot/omniNotify/include/RDIOplocks.h,v
retrieving revision 1.3
retrieving revision 1.3.2.1
diff -u -u -r1.3 -r1.3.2.1
--- include/RDIOplocks.h	2001/09/06 15:28:45	1.3
+++ include/RDIOplocks.h	2002/02/28 23:43:59	1.3.2.1
@@ -31,6 +31,15 @@
  
 /*
 $Log: RDIOplocks.h,v $
+Revision 1.3.2.1  2002/02/28 23:43:59  alcfp
+merge alpha branch back into dev for latest fixes
+
+Revision 1.3.4.2  2002/02/08 23:02:55  alcfp
+oplock cleanup update
+
+Revision 1.3.4.1  2002/02/08 10:40:16  alcfp
+fixed oplock cleanup bug for deferred disposal case, also suppressed event rejection report when channel is shutting down
+
 Revision 1.3  2001/09/06 15:28:45  alcfp
 changed event channel to use oplockptr
 
@@ -76,7 +85,7 @@
 class RDIOplockEntry {
 public:
   RDIOplockEntry() : _oplock(), _waitvar(&_oplock), _inusezero(&_oplock),
-		     _inuse(0), _ptr(0), _disposed(0)
+		     _inuse(0), _ptr(0), _disposed(0), _owner_name(0)
   {
     _prev = this;
     _next = this;
@@ -119,6 +128,7 @@
   RDIOplockEntry**         _ptr;
   CORBA::Boolean           _disposed;
   WRAPPED_DISPOSEINFO_VAR  _dispose_info;
+  AttN::NameSeq*           _owner_name;
 
   // for chaining entry on a doubly-linked list
   RDIOplockEntry*          _prev;
@@ -139,7 +149,7 @@
 
 class RDIOplocks {
 public:
-  static RDIOplockEntry* alloc_entry(RDIOplockEntry** optr);
+  static RDIOplockEntry* alloc_entry(RDIOplockEntry** optr, AttN::NameSeq* oname);
   static void            free_entry(RDIOplockEntry* e, RDIOplockEntry** optr, WRAPPED_DISPOSEINFO_PTR dinfo);
 
   // * alloc_entry returns an entry whose ptr is
@@ -153,6 +163,9 @@
   //   Another side-effect: if a non-nil dinfo is passed to free_entry,
   //   then RDIOplocks is in charge of disposal.  If inuse is zero disposal
   //   happens immediately, otherwise it is deferred; disposed is set to 1.
+  //   N.B.: If disposal happens immediately, *optr is set to zero
+  //   (i.e., _oplockptr is set to zero).  If it is deferred, _oplockptr
+  //   remains set until the deferred disposal takes place.
   //
   //   Once disposal has occurred, ptr is changed either
   //   to zero or to some other value, thus an entry's user can compare
@@ -160,10 +173,10 @@
   //   The RDI_OPLOCK_PREAMBLE macro above performs this check and
   //   obtains a lock on oplock.
 
-  static CORBA::Boolean cleanup();
+  static CORBA::ULong cleanup();
   static void shutdown();
 
-  // * cleanup returns 1 if there are entries in use that could not be discarded, else 0
+  // * cleanup returns the # of entries that could not be discarded (inuse > 0)
 
   // * shutdown disables further allocations and calls cleanup until
   //   there are no more entries, then it deletes the dummy entry.
Index: include/RDIOplocksMacros.h
===================================================================
RCS file: /cvsroot/omniNotify/include/RDIOplocksMacros.h,v
retrieving revision 1.4
retrieving revision 1.4.2.1
diff -u -u -r1.4 -r1.4.2.1
--- include/RDIOplocksMacros.h	2001/06/26 20:01:09	1.4
+++ include/RDIOplocksMacros.h	2002/02/28 23:43:59	1.4.2.1
@@ -31,6 +31,12 @@
  
 /*
 $Log: RDIOplocksMacros.h,v $
+Revision 1.4.2.1  2002/02/28 23:43:59  alcfp
+merge alpha branch back into dev for latest fixes
+
+Revision 1.4.4.1  2002/02/08 10:40:16  alcfp
+fixed oplock cleanup bug for deferred disposal case, also suppressed event rejection report when channel is shutting down
+
 Revision 1.4  2001/06/26 20:01:09  alcfp
 updated copyright notices, added support for omniORB4, switched default to POA
 
@@ -209,15 +215,13 @@
 //    ** For dispose macros, _oplockptr->oplock MUST be held
 
 #define RDI_OPLOCK_INIT \
-  do {_oplockptr = RDIOplocks::alloc_entry(&_oplockptr); \
+  do {_oplockptr = RDIOplocks::alloc_entry(&_oplockptr, &_my_name); \
            RDI_AssertAllocThrowNo(_oplockptr, "Failed to allocate RDIOplockEntry"); } while (0)
 
 // Effect: triggers immediate or deferred disposal (depending on inuse)
-//         and releases oplock; also sets _oplockptr to NULL which
-//         speeds up (rejection of) future ACQUIRE/REACQUIRE calls
+//         and releases oplock
 #define RDI_OPLOCK_DISPOSE_IMPL_AND_RELEASE \
   do { RDIOplockEntry* tmp_entry = _oplockptr; \
-           _oplockptr = 0; \
            RDIOplocks::free_entry(tmp_entry, (&_oplockptr), WRAPPED_IMPL2DISPOSEINFO(this)); \
          } while (0)
 
Index: include/RDIRVMPool.h
===================================================================
RCS file: /cvsroot/omniNotify/include/RDIRVMPool.h,v
retrieving revision 1.3
retrieving revision 1.3.2.1
diff -u -u -r1.3 -r1.3.2.1
--- include/RDIRVMPool.h	2001/08/03 17:54:15	1.3
+++ include/RDIRVMPool.h	2002/02/28 23:43:59	1.3.2.1
@@ -30,6 +30,12 @@
  
 /*
 $Log: RDIRVMPool.h,v $
+Revision 1.3.2.1  2002/02/28 23:43:59  alcfp
+merge alpha branch back into dev for latest fixes
+
+Revision 1.3.4.1  2002/02/10 03:55:30  alcfp
+removed RVMPool
+
 Revision 1.3  2001/08/03 17:54:15  alcfp
 added support for AttNotification
 
@@ -40,27 +46,10 @@
 new RVM pool
 
 */
-
-#ifndef __RDI_RVM_POOL__
-#define __RDI_RVM_POOL__
-
-#include "RDIDynamicEvalDefs.h"
-#include "RDIHash.h"
-#include "omnithread.h"
-
-////////////////////////////////////////////////////////////////////////////////
-
-class RDI_RVMPool {
-public:
-  // Return a reference to an 'RDI_RVM' that is thread-safe;
-  // the current implementation allocates an RDI_RVM per thread
-  // that does filtering
-  static RDI_RVM* get_rvm();
-  
-private:
-  static RDI_Hash<int, RDI_RVM*> _rvms;
-};
 
-////////////////////////////////////////////////////////////////////////////////
+////////////////////////////
+//                        //
+// ** NO LONGER NEEDED ** //
+//                        //
+////////////////////////////
 
-#endif /* __RDI_RVM_POOL__ */
Index: include/corba_wrappers.h
===================================================================
RCS file: /cvsroot/omniNotify/include/corba_wrappers.h,v
retrieving revision 1.5
retrieving revision 1.5.2.1
diff -u -u -r1.5 -r1.5.2.1
--- include/corba_wrappers.h	2001/10/02 14:07:51	1.5
+++ include/corba_wrappers.h	2002/02/28 23:43:59	1.5.2.1
@@ -76,6 +76,7 @@
 //   This call cleans up the orb and boa or poa that were
 //   initialized via WRAPPED_ORB_OA::init.  None of the
 //   calls below should be used after invoking cleanup.
+//   Should only be called by main thread.
 //
 // Constructing and registering objects
 // ------------------------------------
Index: include/omniNotify.h
===================================================================
RCS file: /cvsroot/omniNotify/include/omniNotify.h,v
retrieving revision 1.12
retrieving revision 1.12.2.1
diff -u -u -r1.12 -r1.12.2.1
--- include/omniNotify.h	2001/10/02 14:07:51	1.12
+++ include/omniNotify.h	2002/02/28 23:43:59	1.12.2.1
@@ -31,6 +31,12 @@
  
 /*
 $Log: omniNotify.h,v $
+Revision 1.12.2.1  2002/02/28 23:43:59  alcfp
+merge alpha branch back into dev for latest fixes
+
+Revision 1.12.4.1  2002/02/26 22:26:57  alcfp
+added omniNotify::wait_for_destroy
+
 Revision 1.12  2001/10/02 14:07:51  alcfp
 improved error messages for command line errors
 
@@ -77,6 +83,8 @@
 // omniNotify library, i.e., creation of an AttNotification::Server //
 // ---------------------------------------------------------------- //
 
+#define OMNINOTIFY_VERSION "1.1"
+
 class omniNotify {
 public:
   // The first time omniNotify::init_server is called with valid arguments,
@@ -119,6 +127,9 @@
   // (or a nil reference if init_server has not yet been used to
   // initialize the server).
   static AttNotification::Server_ptr get_server();
+
+  // wait for the server to be destroyed (via a destroy call)
+  static void wait_for_destroy();
 };
 
 #endif
Index: include/omniorb_poa_wrappers.h
===================================================================
RCS file: /cvsroot/omniNotify/include/omniorb_poa_wrappers.h,v
retrieving revision 1.4
retrieving revision 1.4.2.2
diff -u -u -r1.4 -r1.4.2.2
--- include/omniorb_poa_wrappers.h	2001/10/02 14:07:52	1.4
+++ include/omniorb_poa_wrappers.h	2002/02/28 23:43:59	1.4.2.2
@@ -60,24 +60,27 @@
 
 // With refcounting POA, using _remove_ref enables POA cleanup of servant
 #define WRAPPED_REGISTER_IMPL(implref) \
-  do { WRAPPED_ORB_OA::_poa->activate_object(implref); implref->_remove_ref(); } while (0)
+  do { PortableServer::ObjectId_var obv = WRAPPED_ORB_OA::_poa->activate_object(implref); implref->_remove_ref(); } while (0)
 
 #ifdef DBG_POA_REFCOUNT
 #define WRAPPED_REGISTER_IMPL2(implref, nm) \
   do { \
        implref->_setServantName(nm); \
-       WRAPPED_ORB_OA::_poa->activate_object(implref); implref->_remove_ref(); \
+       PortableServer::ObjectId_var obv = WRAPPED_ORB_OA::_poa->activate_object(implref); implref->_remove_ref(); \
        implref->_describeRefCount((const char*)"after active_object and _remove_ref"); \
      } while (0)
 #else
 #define WRAPPED_REGISTER_IMPL2(implref, nm) \
-  do { WRAPPED_ORB_OA::_poa->activate_object(implref); implref->_remove_ref(); } while (0)
+  do { PortableServer::ObjectId_var obv = WRAPPED_ORB_OA::_poa->activate_object(implref); implref->_remove_ref(); } while (0)
 #endif
+
 #define WRAPPED_IMPL2OREF(interfaceClass, implref) \
-  interfaceClass::_duplicate(implref->_this())
+  implref->_this()
 
-#define WRAPPED_RELEASE_IMPL(implref)\
-  CORBA::release(implref->_this())
+// Since _this() does a duplicate, we must do 2 releases.
+// One is explicit, one is the result of using Object_var.
+#define WRAPPED_RELEASE_IMPL(implref) \
+  do { CORBA::Object_var oref = implref->_this(); CORBA::release(oref); } while (0)
 
 // ** NB: note that either WRAPPED_DISPOSE_INFO
 //    is in charge of freeing any storage that was allocated
Index: lib/ChannelAdmin_i.cc
===================================================================
RCS file: /cvsroot/omniNotify/lib/ChannelAdmin_i.cc,v
retrieving revision 1.79
retrieving revision 1.79.2.2
diff -u -u -r1.79 -r1.79.2.2
--- lib/ChannelAdmin_i.cc	2001/10/06 00:44:22	1.79
+++ lib/ChannelAdmin_i.cc	2002/03/13 08:57:17	1.79.2.2
@@ -31,6 +31,21 @@
  
 /*
 $Log: ChannelAdmin_i.cc,v $
+Revision 1.79.2.2  2002/03/13 08:57:17  alcfp
+fixed oref counting bug in get_filter implementations
+
+Revision 1.79.2.1  2002/02/28 23:43:59  alcfp
+merge alpha branch back into dev for latest fixes
+
+Revision 1.79.4.3  2002/02/26 22:28:42  alcfp
+added ReportInteractive flag - controls whether results of interactive cmds are output to report log, also added wait_for_destroy support, fixed server destroy so it causes main notifd thread to terminate
+
+Revision 1.79.4.2  2002/02/20 21:22:55  alcfp
+steps towards correct oref refcounts
+
+Revision 1.79.4.1  2002/02/08 17:08:52  alcfp
+improved use of REACQUIRE oplock macro
+
 Revision 1.79  2001/10/06 00:44:22  alcfp
 moved some EventChannel_i state to private
 
@@ -161,6 +176,7 @@
   _my_name.length(_my_name.length()+1);
   _my_name[_my_name.length()-1] = (const char*)buf;
   WRAPPED_REGISTER_IMPL2(this, &_my_name);
+  _my_oref = WRAPPED_IMPL2OREF(AttN::ConsumerAdmin, this);
 }
 
 ConsumerAdmin_i::~ConsumerAdmin_i() {
@@ -748,7 +764,7 @@
   if (_disposed) { RDI_OPLOCK_RELEASE; RDI_THROW_INV_OBJREF; } // in process of being disposed
   CosNF::Filter_ptr res = _fa_helper.get_filter(fltrID);
   RDI_OPLOCK_RELEASE;
-  return res;
+  return CosNF::Filter::_duplicate(res);
 }
 
 CosNF::FilterIDSeq*
@@ -1465,6 +1481,7 @@
   _my_name.length(_my_name.length()+1);
   _my_name[_my_name.length()-1] = (const char*)buf;
   WRAPPED_REGISTER_IMPL2(this, &_my_name);
+  _my_oref = WRAPPED_IMPL2OREF(AttN::SupplierAdmin, this);
 }
 
 SupplierAdmin_i::~SupplierAdmin_i() {
@@ -1943,7 +1960,7 @@
   if (_disposed) { RDI_OPLOCK_RELEASE; RDI_THROW_INV_OBJREF; } // in process of being disposed
   CosNF::Filter_ptr res = _fa_helper.get_filter(fltrID);
   RDI_OPLOCK_RELEASE;
-  return res;
+  return CosNF::Filter::_duplicate(res);
 }
 
 CosNF::FilterIDSeq*
@@ -2226,7 +2243,7 @@
       EventChannel_i* chan = _channel;
       RDI_OPLOCK_RELEASE; // debump after invoking channel ops
       chan->propagate_offer_change(added, deled);
-      RDI_OPLOCK_REACQUIRE(return);
+      RDI_OPLOCK_REACQUIRE(RDI_METHOD_RETURN_NULL(RDIDbgSAdm, RDIDbgSAdm_nm, "SupplierAdmin_i::_disconnect_clients_and_dispose [**unexpected REACQUIRE failure**]\n"));
     }
   }
   RDIDbgSAdmLog("Begin Destruction of SupplierAdmin @ " << (void*)this << " [" << _serial << "]\n");
@@ -2486,18 +2503,38 @@
     RDI_OPLOCK_RELEASE;
     throw CORBA::NO_MEMORY(0, CORBA::COMPLETED_NO);
   }
+  unsigned long num = 
+    _cosevent_push.length()  +
+    _cosevent_pull.length()  +
+    _prx_any_push.length()   +
+    _prx_struc_push.length() +
+    _prx_batch_push.length() +
+    _prx_any_pull.length()   +
+    _prx_struc_pull.length() +
+    _prx_batch_pull.length();
+  names->length(num);
+  num = 0;
+  // CosEvent clients
+  unsigned int i;
+  RDI_ListCursor<EventProxyPushSupplier_i *>                cpushcur;
+  RDI_ListCursor<EventProxyPullSupplier_i *>                cpullcur;
+  cpushcur = _cosevent_push.cursor();
+  for (i=0; i < _cosevent_push.length(); ++i, ++cpushcur) {
+    EventProxyPushSupplier_i* prx = *cpushcur;
+    (*names)[num++] = (const char*)(prx->_my_name[prx->_my_name.length()-1]);
+  }
+  cpullcur = _cosevent_pull.cursor();
+  for (i=0; i < _cosevent_pull.length(); ++i, ++cpullcur) {
+    EventProxyPullSupplier_i* prx = *cpullcur;
+    (*names)[num++] = (const char*)(prx->_my_name[prx->_my_name.length()-1]);
+  }
+  // CosNotify clients
   RDI_HashCursor<CosNA::ProxyID, ProxyPushSupplier_i *>           ac1;
   RDI_HashCursor<CosNA::ProxyID, StructuredProxyPushSupplier_i *> sc1;
   RDI_HashCursor<CosNA::ProxyID, SequenceProxyPushSupplier_i * >  bc1;
   RDI_HashCursor<CosNA::ProxyID, ProxyPullSupplier_i *>           ac2;
   RDI_HashCursor<CosNA::ProxyID, StructuredProxyPullSupplier_i *> sc2;
   RDI_HashCursor<CosNA::ProxyID, SequenceProxyPullSupplier_i * >  bc2;
-  unsigned long num = _prx_any_push.length() +
-    _prx_struc_push.length() + _prx_batch_push.length() +
-    _prx_any_pull.length() +
-    _prx_struc_pull.length() + _prx_batch_pull.length();
-  names->length(num);
-  num = 0;
   for ( ac1 = _prx_any_push.cursor(); ac1.is_valid(); ++ac1, ++num ) {
     sprintf(buf, "proxy%ld", ac1.key());
     (*names)[num] = (const char*)buf;
@@ -2571,12 +2608,33 @@
   // Unconnected proxies are cleanup candidates
   unsigned int idx = 0;
   // start with max length
-  ren.length(_prx_any_push.length() +
+  ren.length(_cosevent_push.length()  +
+	     _cosevent_pull.length()  +
+	     _prx_any_push.length()   +
 	     _prx_struc_push.length() +
 	     _prx_batch_push.length() +
-	     _prx_any_pull.length() +
+	     _prx_any_pull.length()   +
 	     _prx_struc_pull.length() +
 	     _prx_batch_pull.length());
+  // CosEvent clients
+  unsigned int i;
+  RDI_ListCursor<EventProxyPushSupplier_i *>                cpushcur;
+  RDI_ListCursor<EventProxyPullSupplier_i *>                cpullcur;
+  cpushcur = _cosevent_push.cursor();
+  for (i=0; i < _cosevent_push.length(); ++i, ++cpushcur) {
+    EventProxyPushSupplier_i* prx = *cpushcur;
+    if ((!only_cleanup_candidates) || (!prx->is_connected())) {
+      ren[idx++] = WRAPPED_IMPL2OREF(AttN::Interactive, prx);
+    }
+  }
+  cpullcur = _cosevent_pull.cursor();
+  for (i=0; i < _cosevent_pull.length(); ++i, ++cpullcur) {
+    EventProxyPullSupplier_i* prx = *cpullcur;
+    if ((!only_cleanup_candidates) || (!prx->is_connected())) {
+      ren[idx++] = WRAPPED_IMPL2OREF(AttN::Interactive, prx);
+    }
+  }
+  // CosNotify clients
   RDI_HashCursor<CosNA::ProxyID, ProxyPushSupplier_i *>           ac1;
   RDI_HashCursor<CosNA::ProxyID, StructuredProxyPushSupplier_i *> sc1;
   RDI_HashCursor<CosNA::ProxyID, SequenceProxyPushSupplier_i * >  bc1;
@@ -2633,7 +2691,7 @@
 
 void
 ConsumerAdmin_i::cleanup(RDIstrstream& str, CORBA::Boolean admin, CORBA::Boolean proxies) {
-  RDIInteractive::cleanup_admin(str, WRAPPED_IMPL2OREF(AttN::Interactive, this), admin, proxies);
+  RDIInteractive::cleanup_admin(str, _my_oref, admin, proxies);
 }
 
 CORBA::Boolean
@@ -2669,6 +2727,9 @@
 			       CORBA::Boolean& target_changed,
 			       AttN_Interactive_outarg next_target) {
   CORBA::Boolean success = 1;
+  AttN::Interactive_ptr targ1 = AttN::Interactive::_nil();
+  AttN::Interactive_ptr targ2 = AttN::Interactive::_nil();
+  CORBA::Boolean targ1_set = 0, targ2_set = 0;
   RDI_OPLOCK_ACQUIRE(RDI_THROW_INV_OBJREF);
   char* go_targ = CORBA_STRING_DUP(p.argv[1]);
   char* rest_go_targ = RDI_STRCHR(go_targ, '.');
@@ -2676,6 +2737,31 @@
     *rest_go_targ = '\0';
     rest_go_targ++;
   }
+  // CosEvent clients
+  unsigned int i;
+  RDI_ListCursor<EventProxyPushSupplier_i *>                cpushcur;
+  RDI_ListCursor<EventProxyPullSupplier_i *>                cpullcur;
+  cpushcur = _cosevent_push.cursor();
+  for (i=0; i < _cosevent_push.length(); ++i, ++cpushcur) {
+    EventProxyPushSupplier_i* prx = *cpushcur;
+    if (RDI_STR_EQ_I(go_targ, prx->_my_name[prx->_my_name.length()-1])) {
+      targ1 = WRAPPED_IMPL2OREF(AttN::CosEvProxyPushSupplier, prx);
+      targ1_set = 1;
+      break;
+    }
+  }
+  if (targ1_set == 0) {
+    cpullcur = _cosevent_pull.cursor();
+    for (i=0; i < _cosevent_pull.length(); ++i, ++cpullcur) {
+      EventProxyPullSupplier_i* prx = *cpullcur;
+      if (RDI_STR_EQ_I(go_targ, prx->_my_name[prx->_my_name.length()-1])) {
+	targ1 = WRAPPED_IMPL2OREF(AttN::CosEvProxyPullSupplier, prx);
+	targ1_set = 1;
+	break;
+      }
+    }
+  }
+  // CosNotify  clients
   char buf[20];
   RDI_HashCursor<CosNA::ProxyID, ProxyPushSupplier_i *>           ac1;
   RDI_HashCursor<CosNA::ProxyID, StructuredProxyPushSupplier_i *> sc1;
@@ -2683,93 +2769,98 @@
   RDI_HashCursor<CosNA::ProxyID, ProxyPullSupplier_i *>           ac2;
   RDI_HashCursor<CosNA::ProxyID, StructuredProxyPullSupplier_i *> sc2;
   RDI_HashCursor<CosNA::ProxyID, SequenceProxyPullSupplier_i * >  bc2;
-  for ( ac1 = _prx_any_push.cursor(); ac1.is_valid(); ++ac1 ) {
-    sprintf(buf, "proxy%ld", ac1.key());
-    if (RDI_STR_EQ_I(go_targ, buf)) {
-      target_changed = 1;
-      next_target = WRAPPED_IMPL2OREF(AttN::ProxyPushSupplier, ac1.val());
-      break;
+  if (targ1_set == 0) {
+    for ( ac1 = _prx_any_push.cursor(); ac1.is_valid(); ++ac1 ) {
+      sprintf(buf, "proxy%ld", ac1.key());
+      if (RDI_STR_EQ_I(go_targ, buf)) {
+	targ1 = WRAPPED_IMPL2OREF(AttN::ProxyPushSupplier, ac1.val());
+	targ1_set = 1;
+	break;
+      }
     }
   }
-  if (target_changed == 0) {
+  if (targ1_set == 0) {
     for ( sc1 = _prx_struc_push.cursor(); sc1.is_valid(); ++sc1 ) {
       sprintf(buf, "proxy%ld", sc1.key());
       if (RDI_STR_EQ_I(go_targ, buf)) {
-	target_changed = 1;
-	next_target = WRAPPED_IMPL2OREF(AttN::StructuredProxyPushSupplier, sc1.val());
+	targ1 = WRAPPED_IMPL2OREF(AttN::StructuredProxyPushSupplier, sc1.val());
+	targ1_set = 1;
 	break;
       }
     }
   }
-  if (target_changed == 0) {
+  if (targ1_set == 0) {
     for ( bc1 = _prx_batch_push.cursor(); bc1.is_valid(); ++bc1 ) {
       sprintf(buf, "proxy%ld", bc1.key());
       if (RDI_STR_EQ_I(go_targ, buf)) {
-	target_changed = 1;
-	next_target = WRAPPED_IMPL2OREF(AttN::SequenceProxyPushSupplier, bc1.val());
+	targ1 = WRAPPED_IMPL2OREF(AttN::SequenceProxyPushSupplier, bc1.val());
+	targ1_set = 1;
 	break;
       }
     }
   }
-  if (target_changed == 0) {
+  if (targ1_set == 0) {
     for ( ac2 = _prx_any_pull.cursor(); ac2.is_valid(); ++ac2 ) {
       sprintf(buf, "proxy%ld", ac2.key());
       if (RDI_STR_EQ_I(go_targ, buf)) {
-	target_changed = 1;
-	next_target = WRAPPED_IMPL2OREF(AttN::ProxyPullSupplier, ac2.val());
+	targ1 = WRAPPED_IMPL2OREF(AttN::ProxyPullSupplier, ac2.val());
+	targ1_set = 1;
 	break;
       }
     }
   }
-  if (target_changed == 0) {
+  if (targ1_set == 0) {
     for ( sc2 = _prx_struc_pull.cursor(); sc2.is_valid(); ++sc2 ) {
       sprintf(buf, "proxy%ld", sc2.key());
       if (RDI_STR_EQ_I(go_targ, buf)) {
-	target_changed = 1;
-	next_target = WRAPPED_IMPL2OREF(AttN::StructuredProxyPullSupplier, sc2.val());
+	targ1 = WRAPPED_IMPL2OREF(AttN::StructuredProxyPullSupplier, sc2.val());
+	targ1_set = 1;
 	break;
       }
     }
   }
-  if (target_changed == 0) {
+  if (targ1_set == 0) {
     for ( bc2 = _prx_batch_pull.cursor(); bc2.is_valid(); ++bc2 ) {
       sprintf(buf, "proxy%ld", bc2.key());
       if (RDI_STR_EQ_I(go_targ, buf)) {
-	target_changed = 1;
-	next_target = WRAPPED_IMPL2OREF(AttN::SequenceProxyPullSupplier, bc2.val());
+	targ1 = WRAPPED_IMPL2OREF(AttN::SequenceProxyPullSupplier, bc2.val());
+	targ1_set = 1;
 	break;
       }
     }
   }
   RDI_OPLOCK_RELEASE;
-  if (target_changed == 0) {
+  if (targ1_set == 0) {
     str << "Invalid target " << p.argv[1] << " : " << go_targ << " is not a proxy name\n";
     str << "  (Use 'children' for list of valid proxy names)\n";
     success = 0;
   } else {
     str << "\nomniNotify: new target ==> " << go_targ << '\n';
     if (rest_go_targ && (RDI_STRLEN(rest_go_targ) > 0)) {
-      CORBA::Boolean target_changed2 = 0;
-      AttN::Interactive_ptr next_target2 = AttN::Interactive::_nil();
       CORBA::String_var cmdres;
       char* newcmd = CORBA_STRING_ALLOC(4 + RDI_STRLEN(rest_go_targ));
       sprintf(newcmd, "go %s", rest_go_targ);
       CORBA::Boolean docmd_prob = 0;
       try {
-	cmdres = next_target->do_command(newcmd, success, target_changed2, next_target2);
+	cmdres = targ1->do_command(newcmd, success, targ2_set, targ2);
       } CATCH_INVOKE_PROBLEM(docmd_prob);
       CORBA_STRING_FREE(newcmd);
       if (docmd_prob) {
 	str << "The target " << rest_go_targ << " is not available\n";
       } else {
 	str << cmdres.in();
-	if (target_changed2) {
-	  next_target = next_target2; // XXX duplicate not needed ???
-	}
       }
     }
   }
   CORBA_STRING_FREE(go_targ);
+  if (targ2_set) {
+    CORBA::release(targ1);
+    next_target = targ2;
+    target_changed = 1;
+  } else if (targ1_set) {
+    next_target = targ1;
+    target_changed = 1;
+  }
   return success;
 }
 
@@ -2832,7 +2923,7 @@
     str << "Invalid command: " << cmnd << "\n";
     success = 0;
   }
-  RDIRptForceLog(_my_name << " received command: " << cmnd << "\nResult:\n" << str.buf());
+  RDIRptInteractiveLog(_my_name << " received command: " << cmnd << "\nResult:\n" << str.buf());
   // this is the only safe way to return a string?
   return CORBA_STRING_DUP(str.buf());
 }
@@ -2857,18 +2948,38 @@
     RDI_OPLOCK_RELEASE;
     throw CORBA::NO_MEMORY(0, CORBA::COMPLETED_NO);
   }
+  unsigned long num = 
+    _cosevent_push.length()  +
+    _cosevent_pull.length()  +
+    _prx_any_push.length()   +
+    _prx_struc_push.length() +
+    _prx_batch_push.length() +
+    _prx_any_pull.length()   +
+    _prx_struc_pull.length() +
+    _prx_batch_pull.length();
+  names->length(num);
+  num = 0;
+  // CosEvent clients
+  unsigned int i;
+  RDI_ListCursor<EventProxyPushConsumer_i *>                cpushcur;
+  RDI_ListCursor<EventProxyPullConsumer_i *>                cpullcur;
+  cpushcur = _cosevent_push.cursor();
+  for (i=0; i < _cosevent_push.length(); ++i, ++cpushcur) {
+    EventProxyPushConsumer_i* prx = *cpushcur;
+    (*names)[num++] = (const char*)(prx->_my_name[prx->_my_name.length()-1]);
+  }
+  cpullcur = _cosevent_pull.cursor();
+  for (i=0; i < _cosevent_pull.length(); ++i, ++cpullcur) {
+    EventProxyPullConsumer_i* prx = *cpullcur;
+    (*names)[num++] = (const char*)(prx->_my_name[prx->_my_name.length()-1]);
+  }
+  // CosNotify Clients
   RDI_HashCursor<CosNA::ProxyID, ProxyPushConsumer_i *>           ac1;
   RDI_HashCursor<CosNA::ProxyID, StructuredProxyPushConsumer_i *> sc1;
   RDI_HashCursor<CosNA::ProxyID, SequenceProxyPushConsumer_i *>   bc1;
   RDI_HashCursor<CosNA::ProxyID, ProxyPullConsumer_i *>           ac2;
   RDI_HashCursor<CosNA::ProxyID, StructuredProxyPullConsumer_i *> sc2;
   RDI_HashCursor<CosNA::ProxyID, SequenceProxyPullConsumer_i *>   bc2;
-  unsigned long num = _prx_any_push.length() +
-    _prx_struc_push.length() + _prx_batch_push.length() +
-    _prx_any_pull.length() +
-    _prx_struc_pull.length() + _prx_batch_pull.length();
-  names->length(num);
-  num = 0;
   for ( ac1 = _prx_any_push.cursor(); ac1.is_valid(); ++ac1, ++num ) {
     sprintf(buf, "proxy%ld", ac1.key());
     (*names)[num] = (const char*)buf;
@@ -2941,12 +3052,33 @@
   // Unconnected proxies are cleanup candidates
   unsigned int idx = 0;
   // start with max length
-  ren.length(_prx_any_push.length() +
+  ren.length(_cosevent_push.length()  +
+	     _cosevent_pull.length()  +
+	     _prx_any_push.length()   +
 	     _prx_struc_push.length() +
 	     _prx_batch_push.length() +
-	     _prx_any_pull.length() +
+	     _prx_any_pull.length()   +
 	     _prx_struc_pull.length() +
 	     _prx_batch_pull.length());
+  // CosEvent clients
+  unsigned int i;
+  RDI_ListCursor<EventProxyPushConsumer_i *>                cpushcur;
+  RDI_ListCursor<EventProxyPullConsumer_i *>                cpullcur;
+  cpushcur = _cosevent_push.cursor();
+  for (i=0; i < _cosevent_push.length(); ++i, ++cpushcur) {
+    EventProxyPushConsumer_i* prx = *cpushcur;
+    if ((!only_cleanup_candidates) || (!prx->is_connected())) {
+      ren[idx++] = WRAPPED_IMPL2OREF(AttN::Interactive, prx);
+    }
+  }
+  cpullcur = _cosevent_pull.cursor();
+  for (i=0; i < _cosevent_pull.length(); ++i, ++cpullcur) {
+    EventProxyPullConsumer_i* prx = *cpullcur;
+    if ((!only_cleanup_candidates) || (!prx->is_connected())) {
+      ren[idx++] = WRAPPED_IMPL2OREF(AttN::Interactive, prx);
+    }
+  }
+  // CosNotify clients
   RDI_HashCursor<CosNA::ProxyID, ProxyPushConsumer_i *>           ac1;
   RDI_HashCursor<CosNA::ProxyID, StructuredProxyPushConsumer_i *> sc1;
   RDI_HashCursor<CosNA::ProxyID, SequenceProxyPushConsumer_i * >  bc1;
@@ -3003,7 +3135,7 @@
 
 void
 SupplierAdmin_i::cleanup(RDIstrstream& str, CORBA::Boolean admin, CORBA::Boolean proxies) {
-  RDIInteractive::cleanup_admin(str, WRAPPED_IMPL2OREF(AttN::Interactive, this), admin, proxies);
+  RDIInteractive::cleanup_admin(str, _my_oref, admin, proxies);
 }
 
 CORBA::Boolean
@@ -3039,6 +3171,9 @@
 			       CORBA::Boolean& target_changed,
 			       AttN_Interactive_outarg next_target) {
   CORBA::Boolean success = 1;
+  AttN::Interactive_ptr targ1 = AttN::Interactive::_nil();
+  AttN::Interactive_ptr targ2 = AttN::Interactive::_nil();
+  CORBA::Boolean targ1_set = 0, targ2_set = 0;
   RDI_OPLOCK_ACQUIRE(RDI_THROW_INV_OBJREF);
   char* go_targ = CORBA_STRING_DUP(p.argv[1]);
   char* rest_go_targ = RDI_STRCHR(go_targ, '.');
@@ -3046,6 +3181,31 @@
     *rest_go_targ = '\0';
     rest_go_targ++;
   }
+  // CosEvent clients
+  unsigned int i;
+  RDI_ListCursor<EventProxyPushConsumer_i *>                cpushcur;
+  RDI_ListCursor<EventProxyPullConsumer_i *>                cpullcur;
+  cpushcur = _cosevent_push.cursor();
+  for (i=0; i < _cosevent_push.length(); ++i, ++cpushcur) {
+    EventProxyPushConsumer_i* prx = *cpushcur;
+    if (RDI_STR_EQ_I(go_targ, prx->_my_name[prx->_my_name.length()-1])) {
+      targ1 = WRAPPED_IMPL2OREF(AttN::CosEvProxyPushConsumer, prx);
+      targ1_set = 1;
+      break;
+    }
+  }
+  if (targ1_set == 0) {
+    cpullcur = _cosevent_pull.cursor();
+    for (i=0; i < _cosevent_pull.length(); ++i, ++cpullcur) {
+      EventProxyPullConsumer_i* prx = *cpullcur;
+      if (RDI_STR_EQ_I(go_targ, prx->_my_name[prx->_my_name.length()-1])) {
+	targ1 = WRAPPED_IMPL2OREF(AttN::CosEvProxyPullConsumer, prx);
+	targ1_set = 1;
+	break;
+      }
+    }
+  }
+  // CosNotify clients
   char buf[20];
   RDI_HashCursor<CosNA::ProxyID, ProxyPushConsumer_i *>           ac1;
   RDI_HashCursor<CosNA::ProxyID, StructuredProxyPushConsumer_i *> sc1;
@@ -3053,93 +3213,98 @@
   RDI_HashCursor<CosNA::ProxyID, ProxyPullConsumer_i *>           ac2;
   RDI_HashCursor<CosNA::ProxyID, StructuredProxyPullConsumer_i *> sc2;
   RDI_HashCursor<CosNA::ProxyID, SequenceProxyPullConsumer_i *>   bc2;
-  for ( ac1 = _prx_any_push.cursor(); ac1.is_valid(); ++ac1 ) {
-    sprintf(buf, "proxy%ld", ac1.key());
-    if (RDI_STR_EQ_I(go_targ, buf)) {
-      target_changed = 1;
-      next_target = WRAPPED_IMPL2OREF(AttN::ProxyPushConsumer, ac1.val());
-      break;
+  if (targ1_set == 0) {
+    for ( ac1 = _prx_any_push.cursor(); ac1.is_valid(); ++ac1 ) {
+      sprintf(buf, "proxy%ld", ac1.key());
+      if (RDI_STR_EQ_I(go_targ, buf)) {
+	targ1 = WRAPPED_IMPL2OREF(AttN::ProxyPushConsumer, ac1.val());
+	targ1_set = 1;
+	break;
+      }
     }
   }
-  if (target_changed == 0) {
+  if (targ1_set == 0) {
     for ( sc1 = _prx_struc_push.cursor(); sc1.is_valid(); ++sc1 ) {
       sprintf(buf, "proxy%ld", sc1.key());
       if (RDI_STR_EQ_I(go_targ, buf)) {
-	target_changed = 1;
-	next_target = WRAPPED_IMPL2OREF(AttN::StructuredProxyPushConsumer, sc1.val());
+	targ1 = WRAPPED_IMPL2OREF(AttN::StructuredProxyPushConsumer, sc1.val());
+	targ1_set = 1;
 	break;
       }
     }
   }
-  if (target_changed == 0) {
+  if (targ1_set == 0) {
     for ( bc1 = _prx_batch_push.cursor(); bc1.is_valid(); ++bc1 ) {
       sprintf(buf, "proxy%ld", bc1.key());
       if (RDI_STR_EQ_I(go_targ, buf)) {
-	target_changed = 1;
-	next_target = WRAPPED_IMPL2OREF(AttN::SequenceProxyPushConsumer, bc1.val());
+	targ1 = WRAPPED_IMPL2OREF(AttN::SequenceProxyPushConsumer, bc1.val());
+	targ1_set = 1;
 	break;
       }
     }
   }
-  if (target_changed == 0) {
+  if (targ1_set == 0) {
     for ( ac2 = _prx_any_pull.cursor(); ac2.is_valid(); ++ac2 ) {
       sprintf(buf, "proxy%ld", ac2.key());
       if (RDI_STR_EQ_I(go_targ, buf)) {
-	target_changed = 1;
-	next_target = WRAPPED_IMPL2OREF(AttN::ProxyPullConsumer, ac2.val());
+	targ1 = WRAPPED_IMPL2OREF(AttN::ProxyPullConsumer, ac2.val());
+	targ1_set = 1;
 	break;
       }
     }
   }
-  if (target_changed == 0) {
+  if (targ1_set == 0) {
     for ( sc2 = _prx_struc_pull.cursor(); sc2.is_valid(); ++sc2 ) {
       sprintf(buf, "proxy%ld", sc2.key());
       if (RDI_STR_EQ_I(go_targ, buf)) {
-	target_changed = 1;
-	next_target = WRAPPED_IMPL2OREF(AttN::StructuredProxyPullConsumer, sc2.val());
+	targ1 = WRAPPED_IMPL2OREF(AttN::StructuredProxyPullConsumer, sc2.val());
+	targ1_set = 1;
 	break;
       }
     }
   }
-  if (target_changed == 0) {
+  if (targ1_set == 0) {
     for ( bc2 = _prx_batch_pull.cursor(); bc2.is_valid(); ++bc2 ) {
       sprintf(buf, "proxy%ld", bc2.key());
       if (RDI_STR_EQ_I(go_targ, buf)) {
-	target_changed = 1;
-	next_target = WRAPPED_IMPL2OREF(AttN::SequenceProxyPullConsumer, bc2.val());
+	targ1 = WRAPPED_IMPL2OREF(AttN::SequenceProxyPullConsumer, bc2.val());
+	targ1_set = 1;
 	break;
       }
     }
   }
   RDI_OPLOCK_RELEASE;
-  if (target_changed == 0) {
+  if (targ1_set == 0) {
     str << "Invalid target " << p.argv[1] << " : " << go_targ << " is not a proxy name\n";
     str << "  (Use 'children' for list of valid proxy names)\n";
     success = 0;
   } else {
     str << "\nomniNotify: new target ==> " << p.argv[1] << '\n';
     if (rest_go_targ && (RDI_STRLEN(rest_go_targ) > 0)) {
-      CORBA::Boolean target_changed2 = 0;
-      AttN::Interactive_ptr next_target2 = AttN::Interactive::_nil();
       CORBA::String_var cmdres;
       char* newcmd = CORBA_STRING_ALLOC(4 + RDI_STRLEN(rest_go_targ));
       sprintf(newcmd, "go %s", rest_go_targ);
       CORBA::Boolean docmd_prob = 0;
       try {
-	cmdres = next_target->do_command(newcmd, success, target_changed2, next_target2);
+	cmdres = targ1->do_command(newcmd, success, targ2_set, targ2);
       } CATCH_INVOKE_PROBLEM(docmd_prob);
       CORBA_STRING_FREE(newcmd);
       if (docmd_prob) {
 	str << "The target " << rest_go_targ << " is not available\n";
       } else {
 	str << cmdres.in();
-	if (target_changed2) {
-	  next_target = next_target2; // XXX duplicate not needed ???
-	}
       }
     }
   }
   CORBA_STRING_FREE(go_targ);
+  if (targ2_set) {
+    CORBA::release(targ1);
+    next_target = targ2;
+    target_changed = 1;
+  } else if (targ1_set) {
+    next_target = targ1;
+    target_changed = 1;
+  }
   return success;
 }
 
@@ -3202,7 +3367,7 @@
     str << "Invalid command: " << cmnd << "\n";
     success = 0;
   }
-  RDIRptForceLog(_my_name << " received command: " << cmnd << "\nResult:\n" << str.buf());
+  RDIRptInteractiveLog(_my_name << " received command: " << cmnd << "\nResult:\n" << str.buf());
   // this is the only safe way to return a string?
   return CORBA_STRING_DUP(str.buf());
 }
Index: lib/CosEventProxy.cc
===================================================================
RCS file: /cvsroot/omniNotify/lib/CosEventProxy.cc,v
retrieving revision 1.27
retrieving revision 1.27.2.2
diff -u -u -r1.27 -r1.27.2.2
--- lib/CosEventProxy.cc	2001/10/06 00:44:35	1.27
+++ lib/CosEventProxy.cc	2002/02/28 23:44:00	1.27.2.2
@@ -31,6 +31,27 @@
  
 /*
 $Log: CosEventProxy.cc,v $
+Revision 1.27.2.2  2002/02/28 23:44:00  alcfp
+merge alpha branch back into dev for latest fixes
+
+Revision 1.27.4.5  2002/02/26 22:28:42  alcfp
+added ReportInteractive flag - controls whether results of interactive cmds are output to report log, also added wait_for_destroy support, fixed server destroy so it causes main notifd thread to terminate
+
+Revision 1.27.4.4  2002/02/26 05:54:34  alcfp
+fixed deadlock over oplock event locking order
+
+Revision 1.27.4.3  2002/02/25 15:11:09  alcfp
+fixes to oref ref counting and added proxy cmds
+
+Revision 1.27.4.2  2002/02/08 17:08:53  alcfp
+improved use of REACQUIRE oplock macro
+
+Revision 1.27.4.1  2002/02/07 18:10:55  alcfp
+merged recent dev fixes into alpha
+
+Revision 1.27.2.1  2001/11/28 15:53:05  alcfp
+connect_push_supplier and connect_pull_consumer now accept nil arg
+
 Revision 1.27  2001/10/06 00:44:35  alcfp
 moved some EventChannel_i state to private
 
@@ -120,16 +141,15 @@
 (CosEvC::PushSupplier_ptr supplier WRAPPED_IMPLARG)
 {
   RDI_OPLOCK_ACQUIRE(RDI_THROW_INV_OBJREF);
-  if ( CORBA::is_nil(supplier) ) {
-    RDI_OPLOCK_RELEASE;
-    throw CORBA::BAD_PARAM(0, CORBA::COMPLETED_NO);
-  }
   if ( _pxstate != RDI_NotConnected ) {
     RDI_OPLOCK_RELEASE;
     throw CosEvCA::AlreadyConnected();
   }
   _pxstate  = RDI_Connected;
-  _supplier = CosEvC::PushSupplier::_duplicate(supplier);
+  if ( ! CORBA::is_nil(supplier) ) {
+    _supplier = CosEvC::PushSupplier::_duplicate(supplier);
+  }
+  RDIDbgCosCPxyLog("CosEvent push supplier connected to " << (void*)this << '\n');
   RDI_OPLOCK_RELEASE;
 }
 
@@ -181,7 +201,6 @@
   }
   _supplier = CosEvC::PushSupplier::_nil();
   RDI_OPLOCK_DISPOSE_IMPL_AND_RELEASE;
-  _oplockptr = 0; // speeds up acquire check
 }
 
 // ------------------------------------------------------------ //
@@ -258,6 +277,7 @@
   if ( cps ) {
     cps->signal_pull_threads();
   }
+  RDIDbgCosCPxyLog("CosEvent pull supplier connected to " << (void*)this << '\n');
   RDI_OPLOCK_RELEASE;
 }
 
@@ -359,10 +379,10 @@
     RDIDbgCosCPxyLog("Pull pool calling pull_event for proxy " << (void*)this << " - Exception while pushing event to consumer\n");
   }
 
-  RDI_OPLOCK_REACQUIRE(return);
+  RDI_OPLOCK_REACQUIRE(RDI_METHOD_RETURN_NULL(RDIDbgCosCPxy, RDIDbgCosCPxy_nm, "EventProxyPullConsumer_i::pull_event [**unexpected REACQUIRE failure**]\n"));
 
-  // add new event to channel even if we have been disconnected in the meantime
-  if (outcall_worked && hasev && event ) {
+  // add new event to channel, but only if we are still connected
+  if ( (_pxstate == RDI_Connected) && outcall_worked && hasev && event ) {
     _nevents += 1;
     _channel->new_any_event(*event);
   }
@@ -460,8 +480,8 @@
 
     update_timeout = 1; // force update of timeout at top of loop
 
-    // add new event to channel even if we have been disconnected in the meantime
-    if (outcall_worked && hasev && event) {
+    // add new event to channel, but only if we are still connected
+    if ( (_pxstate == RDI_Connected) && outcall_worked && hasev && event ) {
       _nevents += 1;
       _channel->new_any_event(*event);
     }
@@ -518,7 +538,6 @@
   }
   _supplier = CosEvC::PullSupplier::_nil();
   RDI_OPLOCK_DISPOSE_IMPL_AND_RELEASE;
-  _oplockptr = 0; // speeds up acquire check
 }
 
 // ------------------------------------------------------------ //
@@ -595,6 +614,7 @@
   if ( cpc ) {
     cpc->signal_push_threads();
   }
+  RDIDbgCosSPxyLog("CosEvent push consumer connected to " << (void*)this << '\n');
   RDI_OPLOCK_RELEASE;
 }
 
@@ -656,20 +676,18 @@
   } catch (...) {
     RDIDbgCosSPxyLog("Push pool calling push_event for proxy " << (void*)this << " - Exception while pushing event to consumer\n");
   }
+  if (  RDI_LOCK_EVENT  ) event->mylock().unlock();
 
-  RDI_OPLOCK_REACQUIRE(return);
+  RDI_OPLOCK_REACQUIRE(RDI_METHOD_RETURN_NULL(RDIDbgCosSPxy, RDIDbgCosSPxy_nm, "EventProxyPushSupplier_i::push_event [**unexpected REACQUIRE failure**]\n"));
 
-  if (  RDI_LOCK_EVENT  ) event->mylock().unlock();
   event->decr_ref_counter( RDI_LOCK_EVENT );
 
-  if (outcall_worked) {
-    _channel->incr_num_notifications(qsize);
-  }
-
   if (_pxstate != RDI_Connected) {
     // disconnected/disposed during push -- do nothing else with my state
   } else {
-    if (!outcall_worked) { // exception
+    if (outcall_worked) {
+      _channel->incr_num_notifications(qsize);
+    } else { // exception
       _pxstate = RDI_Exception;
       invalid  = 1;
     }
@@ -732,20 +750,18 @@
     } catch (...) {
       RDIDbgCosSPxyLog("Push pool calling push_event for proxy " << (void*)this << " - Exception while pushing event to consumer\n");
     }
+    if (  RDI_LOCK_EVENT  ) event->mylock().unlock();
 
     RDI_OPLOCK_REACQUIRE(RDI_THREAD_EXIT(RDIDbgCosSPxy, RDIDbgCosSPxy_nm, "push thread [**unexpected REACQUIRE failure**]\n"));
 
-    if (  RDI_LOCK_EVENT  ) event->mylock().unlock();
     event->decr_ref_counter( RDI_LOCK_EVENT );
 
-    if (outcall_worked) {
-      _channel->incr_num_notifications(qsize);
-    }
-
     if (_pxstate != RDI_Connected) {
       // disconnected/disposed during push -- do nothing else with my state
     } else {
-      if (!outcall_worked) { // exception
+      if (outcall_worked) {
+	_channel->incr_num_notifications(qsize);
+      } else { // exception
 	_pxstate = RDI_Exception;
       }
     }
@@ -795,7 +811,6 @@
     event->decr_ref_counter( RDI_LOCK_EVENT );
   }
   RDI_OPLOCK_DISPOSE_IMPL_AND_RELEASE;
-  _oplockptr = 0; // speeds up acquire check
 }
 
 // ------------------------------------------------------------ //
@@ -826,18 +841,15 @@
 (CosEvC::PullConsumer_ptr consumer WRAPPED_IMPLARG)
 {
   RDI_OPLOCK_ACQUIRE(RDI_THROW_INV_OBJREF);
-  RDIDbgCosSPxyLog("CosEvent consumer to connect to " << (void*)this << '\n');
-  if ( CORBA::is_nil(consumer) ) {
-    RDI_OPLOCK_RELEASE;
-    throw CORBA::BAD_PARAM(0, CORBA::COMPLETED_NO);
-  }
   if ( _pxstate != RDI_NotConnected ) {
     RDI_OPLOCK_RELEASE;
     throw CosEvCA::AlreadyConnected();
   }
   _pxstate  = RDI_Connected;
-  _consumer = CosEvC::PullConsumer::_duplicate(consumer);
-  RDIDbgCosSPxyLog("CosEvent consumer connected to " << (void*)this << '\n');
+  if ( ! CORBA::is_nil(consumer) ) {
+    _consumer = CosEvC::PullConsumer::_duplicate(consumer);
+  }
+  RDIDbgCosSPxyLog("CosEvent pull consumer connected to " << (void*)this << '\n');
   RDI_OPLOCK_RELEASE;
 }
 
@@ -967,7 +979,6 @@
     event->decr_ref_counter( RDI_LOCK_EVENT );
   }
   RDI_OPLOCK_DISPOSE_IMPL_AND_RELEASE;
-  _oplockptr = 0; // speeds up acquire check
 }
 
 ////////////////////////////////////////
@@ -1046,7 +1057,9 @@
 }
 
 void EventProxyPushConsumer_i::out_commands(RDIstrstream& str) {
-  str << "CosEvent ProxyPushConsumer: No commands supported yet.\n";
+  str << "omniNotify CosEvent ProxyPushConsumer commands:\n"
+      << "  up                : change target to proxy's admin\n"
+      << "  debug             : show debugging information for this proxy\n";
 }
 
 char*
@@ -1061,16 +1074,26 @@
   RDIstrstream str;
   if ((p.argc == 1) && RDI_STR_EQ_I(p.argv[0], "help")) {
     out_commands(str);
+  } else if ((p.argc == 1) && RDI_STR_EQ_I(p.argv[0], "debug")) {
+    str << "----------------------------------------------------------------------\n";
+    str << "Debug info for " << _my_name << '\n';
+    str << "----------------------------------------------------------------------\n";
+    log_output(str);
+    str << '\n';
+  } else if ((p.argc == 1) && RDI_STR_EQ_I(p.argv[0], "up")) {
+    target_changed = 1;
+    next_target = WRAPPED_IMPL2OREF(AttN::SupplierAdmin, _myadmin);
+    str << "\nomniNotify: new target ==> " << _my_name[_my_name.length()-2] << '\n';
   } else {
     str << "Invalid command: " << cmnd << "\n";
     success = 0;
   }
-  RDIRptForceLog(_my_name << " received command: " << cmnd << "\nResult:\n" << str.buf());
+  RDIRptInteractiveLog(_my_name << " received command: " << cmnd << "\nResult:\n" << str.buf());
   // this is the only safe way to return a string?
   return CORBA_STRING_DUP(str.buf());
 }
 
-AttN::IactSeq* EventProxyPushSupplier_i::children(CORBA::Boolean only_cleanup_candidates) {
+AttN::IactSeq* EventProxyPullConsumer_i::children(CORBA::Boolean only_cleanup_candidates) {
   AttN::IactSeq* ren = new AttN::IactSeq;
   if ( ren == (AttN::IactSeq*) 0 ) {
     throw CORBA::NO_MEMORY(0, CORBA::COMPLETED_NO);
@@ -1079,7 +1102,7 @@
   return ren;
 }
 
-CORBA::Boolean EventProxyPushSupplier_i::safe_cleanup()
+CORBA::Boolean EventProxyPullConsumer_i::safe_cleanup()
 {
   RDI_OPLOCK_ACQUIRE(RDI_THROW_INV_OBJREF);
   if (_pxstate == RDI_Disconnected) { RDI_OPLOCK_RELEASE; RDI_THROW_INV_OBJREF; } // already in process of being disposed
@@ -1088,7 +1111,7 @@
   return 1;
 }
 
-AttN::NameSeq* EventProxyPushSupplier_i::my_name( WRAPPED_IMPLARG_VOID ) {
+AttN::NameSeq* EventProxyPullConsumer_i::my_name( WRAPPED_IMPLARG_VOID ) {
   RDI_OPLOCK_ACQUIRE(RDI_THROW_INV_OBJREF);
   AttN::NameSeq* res = new AttN::NameSeq(_my_name);
   if ( res == (AttN::NameSeq*) 0 ) {
@@ -1099,7 +1122,7 @@
   return res;
 }
 
-AttN::NameSeq* EventProxyPushSupplier_i::child_names( WRAPPED_IMPLARG_VOID ) {
+AttN::NameSeq* EventProxyPullConsumer_i::child_names( WRAPPED_IMPLARG_VOID ) {
   RDI_OPLOCK_ACQUIRE(RDI_THROW_INV_OBJREF);
   AttN::NameSeq* names = new AttN::NameSeq;
   if ( names == (AttN::NameSeq*) 0 ) {
@@ -1111,12 +1134,14 @@
   return names;
 }
 
-void EventProxyPushSupplier_i::out_commands(RDIstrstream& str) {
-  str << "CosEvent ProxyPushSupplier: No commands supported yet.\n";
+void EventProxyPullConsumer_i::out_commands(RDIstrstream& str) {
+  str << "omniNotify CosEvent ProxyPullConsumer commands:\n"
+      << "  up                : change target to proxy's admin\n"
+      << "  debug             : show debugging information for this proxy\n";
 }
 
 char*
-EventProxyPushSupplier_i::do_command(const char* cmnd, CORBA::Boolean& success,
+EventProxyPullConsumer_i::do_command(const char* cmnd, CORBA::Boolean& success,
 				     CORBA::Boolean& target_changed,
 				     AttN_Interactive_outarg next_target  WRAPPED_IMPLARG ) {
   RDIParseCmd p(cmnd);
@@ -1127,16 +1152,26 @@
   RDIstrstream str;
   if ((p.argc == 1) && RDI_STR_EQ_I(p.argv[0], "help")) {
     out_commands(str);
+  } else if ((p.argc == 1) && RDI_STR_EQ_I(p.argv[0], "debug")) {
+    str << "----------------------------------------------------------------------\n";
+    str << "Debug info for " << _my_name << '\n';
+    str << "----------------------------------------------------------------------\n";
+    log_output(str);
+    str << '\n';
+  } else if ((p.argc == 1) && RDI_STR_EQ_I(p.argv[0], "up")) {
+    target_changed = 1;
+    next_target = WRAPPED_IMPL2OREF(AttN::SupplierAdmin, _myadmin);
+    str << "\nomniNotify: new target ==> " << _my_name[_my_name.length()-2] << '\n';
   } else {
     str << "Invalid command: " << cmnd << "\n";
     success = 0;
   }
-  RDIRptForceLog(_my_name << " received command: " << cmnd << "\nResult:\n" << str.buf());
+  RDIRptInteractiveLog(_my_name << " received command: " << cmnd << "\nResult:\n" << str.buf());
   // this is the only safe way to return a string?
   return CORBA_STRING_DUP(str.buf());
 }
 
-AttN::IactSeq* EventProxyPullConsumer_i::children(CORBA::Boolean only_cleanup_candidates) {
+AttN::IactSeq* EventProxyPushSupplier_i::children(CORBA::Boolean only_cleanup_candidates) {
   AttN::IactSeq* ren = new AttN::IactSeq;
   if ( ren == (AttN::IactSeq*) 0 ) {
     throw CORBA::NO_MEMORY(0, CORBA::COMPLETED_NO);
@@ -1145,7 +1180,7 @@
   return ren;
 }
 
-CORBA::Boolean EventProxyPullConsumer_i::safe_cleanup()
+CORBA::Boolean EventProxyPushSupplier_i::safe_cleanup()
 {
   RDI_OPLOCK_ACQUIRE(RDI_THROW_INV_OBJREF);
   if (_pxstate == RDI_Disconnected) { RDI_OPLOCK_RELEASE; RDI_THROW_INV_OBJREF; } // already in process of being disposed
@@ -1154,7 +1189,7 @@
   return 1;
 }
 
-AttN::NameSeq* EventProxyPullConsumer_i::my_name( WRAPPED_IMPLARG_VOID ) {
+AttN::NameSeq* EventProxyPushSupplier_i::my_name( WRAPPED_IMPLARG_VOID ) {
   RDI_OPLOCK_ACQUIRE(RDI_THROW_INV_OBJREF);
   AttN::NameSeq* res = new AttN::NameSeq(_my_name);
   if ( res == (AttN::NameSeq*) 0 ) {
@@ -1165,7 +1200,7 @@
   return res;
 }
 
-AttN::NameSeq* EventProxyPullConsumer_i::child_names( WRAPPED_IMPLARG_VOID ) {
+AttN::NameSeq* EventProxyPushSupplier_i::child_names( WRAPPED_IMPLARG_VOID ) {
   RDI_OPLOCK_ACQUIRE(RDI_THROW_INV_OBJREF);
   AttN::NameSeq* names = new AttN::NameSeq;
   if ( names == (AttN::NameSeq*) 0 ) {
@@ -1177,12 +1212,14 @@
   return names;
 }
 
-void EventProxyPullConsumer_i::out_commands(RDIstrstream& str) {
-  str << "CosEvent ProxyPullConsumer: No commands supported yet.\n";
+void EventProxyPushSupplier_i::out_commands(RDIstrstream& str) {
+  str << "omniNotify CosEvent ProxyPushSupplier commands:\n"
+      << "  up                : change target to proxy's admin\n"
+      << "  debug             : show debugging information for this proxy\n";
 }
 
 char*
-EventProxyPullConsumer_i::do_command(const char* cmnd, CORBA::Boolean& success,
+EventProxyPushSupplier_i::do_command(const char* cmnd, CORBA::Boolean& success,
 				     CORBA::Boolean& target_changed,
 				     AttN_Interactive_outarg next_target  WRAPPED_IMPLARG ) {
   RDIParseCmd p(cmnd);
@@ -1193,11 +1230,21 @@
   RDIstrstream str;
   if ((p.argc == 1) && RDI_STR_EQ_I(p.argv[0], "help")) {
     out_commands(str);
+  } else if ((p.argc == 1) && RDI_STR_EQ_I(p.argv[0], "debug")) {
+    str << "----------------------------------------------------------------------\n";
+    str << "Debug info for " << _my_name << '\n';
+    str << "----------------------------------------------------------------------\n";
+    log_output(str);
+    str << '\n';
+  } else if ((p.argc == 1) && RDI_STR_EQ_I(p.argv[0], "up")) {
+    target_changed = 1;
+    next_target = WRAPPED_IMPL2OREF(AttN::ConsumerAdmin, _myadmin);
+    str << "\nomniNotify: new target ==> " << _my_name[_my_name.length()-2] << '\n';
   } else {
     str << "Invalid command: " << cmnd << "\n";
     success = 0;
   }
-  RDIRptForceLog(_my_name << " received command: " << cmnd << "\nResult:\n" << str.buf());
+  RDIRptInteractiveLog(_my_name << " received command: " << cmnd << "\nResult:\n" << str.buf());
   // this is the only safe way to return a string?
   return CORBA_STRING_DUP(str.buf());
 }
@@ -1244,7 +1291,9 @@
 }
 
 void EventProxyPullSupplier_i::out_commands(RDIstrstream& str) {
-  str << "CosEvent ProxyPullSupplier: No commands supported yet.\n";
+  str << "omniNotify CosEvent ProxyPullSupplier commands:\n"
+      << "  up                : change target to proxy's admin\n"
+      << "  debug             : show debugging information for this proxy\n";
 }
 
 char*
@@ -1259,11 +1308,21 @@
   RDIstrstream str;
   if ((p.argc == 1) && RDI_STR_EQ_I(p.argv[0], "help")) {
     out_commands(str);
+  } else if ((p.argc == 1) && RDI_STR_EQ_I(p.argv[0], "debug")) {
+    str << "----------------------------------------------------------------------\n";
+    str << "Debug info for " << _my_name << '\n';
+    str << "----------------------------------------------------------------------\n";
+    log_output(str);
+    str << '\n';
+  } else if ((p.argc == 1) && RDI_STR_EQ_I(p.argv[0], "up")) {
+    target_changed = 1;
+    next_target = WRAPPED_IMPL2OREF(AttN::ConsumerAdmin, _myadmin);
+    str << "\nomniNotify: new target ==> " << _my_name[_my_name.length()-2] << '\n';
   } else {
     str << "Invalid command: " << cmnd << "\n";
     success = 0;
   }
-  RDIRptForceLog(_my_name << " received command: " << cmnd << "\nResult:\n" << str.buf());
+  RDIRptInteractiveLog(_my_name << " received command: " << cmnd << "\nResult:\n" << str.buf());
   // this is the only safe way to return a string?
   return CORBA_STRING_DUP(str.buf());
 }
Index: lib/CosNotification.cc
===================================================================
RCS file: /cvsroot/omniNotify/lib/CosNotification.cc,v
retrieving revision 1.28
retrieving revision 1.28.2.1
diff -u -u -r1.28 -r1.28.2.1
--- lib/CosNotification.cc	2001/10/06 03:20:11	1.28
+++ lib/CosNotification.cc	2002/02/28 23:44:00	1.28.2.1
@@ -31,6 +31,12 @@
  
 /*
 $Log: CosNotification.cc,v $
+Revision 1.28.2.1  2002/02/28 23:44:00  alcfp
+merge alpha branch back into dev for latest fixes
+
+Revision 1.28.4.1  2002/02/26 22:28:43  alcfp
+added ReportInteractive flag - controls whether results of interactive cmds are output to report log, also added wait_for_destroy support, fixed server destroy so it causes main notifd thread to terminate
+
 Revision 1.28  2001/10/06 03:20:11  alcfp
 got rid of some compiler warnings
 
@@ -2084,6 +2090,7 @@
   config.set_value(RDIRptNotifQoS_nm      , "1");
   config.set_value(RDIRptAdminQoS_nm      , "1");
   config.set_value(RDIRptServerQoS_nm     , "1");
+  config.set_value(RDIRptInteractive_nm   , "1");
 }
 
 CORBA::Boolean RDI_AllQoS::validate_initial_config(RDIstrstream&  str, 
Index: lib/EventChannel_i.cc
===================================================================
RCS file: /cvsroot/omniNotify/lib/EventChannel_i.cc,v
retrieving revision 1.109
retrieving revision 1.109.2.1
diff -u -u -r1.109 -r1.109.2.1
--- lib/EventChannel_i.cc	2001/10/06 00:44:39	1.109
+++ lib/EventChannel_i.cc	2002/02/28 23:44:00	1.109.2.1
@@ -31,6 +31,15 @@
  
 /*
 $Log: EventChannel_i.cc,v $
+Revision 1.109.2.1  2002/02/28 23:44:00  alcfp
+merge alpha branch back into dev for latest fixes
+
+Revision 1.109.4.2  2002/02/26 22:28:43  alcfp
+added ReportInteractive flag - controls whether results of interactive cmds are output to report log, also added wait_for_destroy support, fixed server destroy so it causes main notifd thread to terminate
+
+Revision 1.109.4.1  2002/02/20 21:22:55  alcfp
+steps towards correct oref refcounts
+
 Revision 1.109  2001/10/06 00:44:39  alcfp
 moved some EventChannel_i state to private
 
@@ -264,9 +273,8 @@
   _gcisactive = 1;
   _reporter->start();
   _repisactive = 1;
-
-  // Register 'this' to start receiving requests
   WRAPPED_REGISTER_IMPL2(this, &_my_name);
+  _my_oref = WRAPPED_IMPL2OREF(AttN::EventChannel, this);
 }
 
 EventChannel_i::~EventChannel_i()
@@ -1429,6 +1437,7 @@
   _my_name[0] = (const char*)"server";
   _my_name[1] = (const char*)"chanfact";
   WRAPPED_REGISTER_IMPL2(this, &_my_name);
+  _my_oref = WRAPPED_IMPL2OREF(AttN::EventChannelFactory, this);
 }
 
 EventChannelFactory_i::~EventChannelFactory_i()
@@ -1758,7 +1767,7 @@
 void
 EventChannelFactory_i::cleanup_all(RDIstrstream& str, CORBA::Boolean admins, CORBA::Boolean proxies)
 {
-  RDIInteractive::cleanup_channels(str, WRAPPED_IMPL2OREF(AttN::Interactive, this), admins, proxies);
+  RDIInteractive::cleanup_channels(str, _my_oref, admins, proxies);
 }
 
 ////////////////////////////////////////
@@ -2145,6 +2154,9 @@
 			      AttN_Interactive_outarg next_target)
 {
   CORBA::Boolean success = 1;
+  AttN::Interactive_ptr targ1 = AttN::Interactive::_nil();
+  AttN::Interactive_ptr targ2 = AttN::Interactive::_nil();
+  CORBA::Boolean targ1_set = 0, targ2_set = 0;
   RDI_OPLOCK_ACQUIRE( return 0 );
   char* go_targ = CORBA_STRING_DUP(p.argv[1]);
   char* rest_go_targ = RDI_STRCHR(go_targ, '.');
@@ -2156,8 +2168,8 @@
   if (id >= 0) {
     SupplierAdmin_i* sadmin = 0;
     if ( _supl_admin.lookup((CosNA::AdminID)id, sadmin) ) {
-      target_changed = 1;
-      next_target = WRAPPED_IMPL2OREF(AttN::SupplierAdmin, sadmin);
+      targ1 = WRAPPED_IMPL2OREF(AttN::SupplierAdmin, sadmin);
+      targ1_set = 1;
       str << "\nomniNotify: new target ==> " << go_targ << '\n';
     }
   } else {
@@ -2165,45 +2177,48 @@
     if (id >= 0) {
       ConsumerAdmin_i* cadmin = 0;
       if ( _cons_admin.lookup((CosNA::AdminID)id, cadmin) ) {
-	target_changed = 1;
-	next_target = WRAPPED_IMPL2OREF(AttN::ConsumerAdmin, cadmin);
+	targ1 = WRAPPED_IMPL2OREF(AttN::ConsumerAdmin, cadmin);
+	targ1_set = 1;
 	str << "\nomniNotify: new target ==> " << go_targ << '\n';
       }
     }
   }
   RDI_OPLOCK_RELEASE;
-  if (target_changed == 0) {
+  if (targ1_set == 0) {
     str << "Invalid target " << p.argv[1] << " : " <<  go_targ << " is not an admin name\n";
     str << "  (Use 'children' for list of valid admin names)\n";
     success = 0;
   } else if (rest_go_targ && (RDI_STRLEN(rest_go_targ) > 0)) {
-    CORBA::Boolean target_changed2 = 0;
-    AttN::Interactive_ptr next_target2 = AttN::Interactive::_nil();
     CORBA::String_var cmdres;
     char* newcmd = CORBA_STRING_ALLOC(4 + RDI_STRLEN(rest_go_targ));
     sprintf(newcmd, "go %s", rest_go_targ);
     CORBA::Boolean docmd_prob = 0;
     try {
-      cmdres = next_target->do_command(newcmd, success, target_changed2, next_target2);
+      cmdres = targ1->do_command(newcmd, success, targ2_set, targ2);
     } CATCH_INVOKE_PROBLEM(docmd_prob);
     CORBA_STRING_FREE(newcmd);
     if (docmd_prob) {
       str << "The target " << rest_go_targ << " is not available\n";
     } else {
       str << cmdres.in();
-      if (target_changed2) {
-	next_target = next_target2; // XXX duplicate not needed ???
-      }
     }
   }
   CORBA_STRING_FREE(go_targ);
+  if (targ2_set) {
+    CORBA::release(targ1);
+    next_target = targ2;
+    target_changed = 1;
+  } else if (targ1_set) {
+    next_target = targ1;
+    target_changed = 1;
+  }
   return success;
 }
 
 void
 EventChannel_i::cleanup(RDIstrstream& str, CORBA::Boolean admins, CORBA::Boolean proxies)
 {
-  RDIInteractive::cleanup_channel(str, WRAPPED_IMPL2OREF(AttN::Interactive, this), admins, proxies);
+  RDIInteractive::cleanup_channel(str, _my_oref, admins, proxies);
 }
 
 CORBA::Boolean
@@ -2286,7 +2301,7 @@
     str << "Invalid command: " << cmnd << "\n";
     success = 0;
   }
-  RDIRptForceLog(_my_name << " received command: " << cmnd << "\nResult:\n" << str.buf());
+  RDIRptInteractiveLog(_my_name << " received command: " << cmnd << "\nResult:\n" << str.buf());
   // this is the only safe way to return a string?
   return CORBA_STRING_DUP(str.buf());
 }
@@ -2424,6 +2439,9 @@
 				     AttN_Interactive_outarg next_target)
 {
   CORBA::Boolean success = 1;
+  AttN::Interactive_ptr targ1 = AttN::Interactive::_nil();
+  AttN::Interactive_ptr targ2 = AttN::Interactive::_nil();
+  CORBA::Boolean targ1_set = 0, targ2_set = 0;
   RDI_OPLOCK_ACQUIRE( return 0 );
   char* go_targ = CORBA_STRING_DUP(p.argv[1]);
   char* rest_go_targ = RDI_STRCHR(go_targ, '.');
@@ -2435,37 +2453,40 @@
   if (id >= 0) {
     EventChannel_i* channel = 0;
     if ( _channel.lookup((CosNA::ChannelID)id, channel) ) {
-      target_changed = 1;
-      next_target = WRAPPED_IMPL2OREF(AttN::EventChannel, channel);
+      targ1 = WRAPPED_IMPL2OREF(AttN::EventChannel, channel);
+      targ1_set = 1;
       str << "\nomniNotify: new target ==> " << go_targ << '\n';
     }
   }
   RDI_OPLOCK_RELEASE;
-  if (target_changed == 0) {
+  if (targ1_set == 0) {
     str << "Invalid target " << p.argv[1] << " : " << go_targ << " is not a channel name\n";
     str << "  (Use 'children' for list of valid channel names)\n";
     success = 0;
   } else if (rest_go_targ && (RDI_STRLEN(rest_go_targ) > 0)) {
-    CORBA::Boolean target_changed2 = 0;
-    AttN::Interactive_ptr next_target2 = AttN::Interactive::_nil();
     CORBA::String_var cmdres;
     char* newcmd = CORBA_STRING_ALLOC(4 + RDI_STRLEN(rest_go_targ));
     sprintf(newcmd, "go %s", rest_go_targ);
     CORBA::Boolean docmd_prob = 0;
     try {
-      cmdres = next_target->do_command(newcmd, success, target_changed2, next_target2);
+      cmdres = targ1->do_command(newcmd, success, targ2_set, targ2);
     } CATCH_INVOKE_PROBLEM(docmd_prob);
     CORBA_STRING_FREE(newcmd);
     if (docmd_prob) {
       str << "The target " << rest_go_targ << " is not available\n";
     } else {
       str << cmdres.in();
-      if (target_changed2) {
-	next_target = next_target2; // XXX duplicate not needed ???
-      }
     }
   }
   CORBA_STRING_FREE(go_targ);
+  if (targ2_set) {
+    CORBA::release(targ1);
+    next_target = targ2;
+    target_changed = 1;
+  } else if (targ1_set) {
+    next_target = targ1;
+    target_changed = 1;
+  }
   return success;
 }
 
@@ -2530,7 +2551,7 @@
     str << "Invalid command: " << cmnd << "\n";
     success = 0;
   }
-  RDIRptForceLog(_my_name << " received command: " << cmnd << "\nResult:\n" << str.buf());
+  RDIRptInteractiveLog(_my_name << " received command: " << cmnd << "\nResult:\n" << str.buf());
   // this is the only safe way to return a string?
   return CORBA_STRING_DUP(str.buf());
 }
Index: lib/FilterAdmin_i.cc
===================================================================
RCS file: /cvsroot/omniNotify/lib/FilterAdmin_i.cc,v
retrieving revision 1.42
retrieving revision 1.42.2.2
diff -u -u -r1.42 -r1.42.2.2
--- lib/FilterAdmin_i.cc	2001/10/02 14:07:52	1.42
+++ lib/FilterAdmin_i.cc	2002/03/13 08:57:18	1.42.2.2
@@ -31,6 +31,18 @@
  
 /*
   $Log: FilterAdmin_i.cc,v $
+  Revision 1.42.2.2  2002/03/13 08:57:18  alcfp
+  fixed oref counting bug in get_filter implementations
+
+  Revision 1.42.2.1  2002/02/28 23:44:01  alcfp
+  merge alpha branch back into dev for latest fixes
+
+  Revision 1.42.4.2  2002/02/26 22:28:43  alcfp
+  added ReportInteractive flag - controls whether results of interactive cmds are output to report log, also added wait_for_destroy support, fixed server destroy so it causes main notifd thread to terminate
+
+  Revision 1.42.4.1  2002/02/25 15:10:16  alcfp
+  fix to oref ref counting
+
   Revision 1.42  2001/10/02 14:07:52  alcfp
   improved error messages for command line errors
 
@@ -341,7 +353,7 @@
     str << "Invalid command: " << cmnd << "\n";
     success = 0;
   }
-  RDIRptForceLog(_my_name << " received command: " << cmnd << "\nResult:\n" << str.buf());
+  RDIRptInteractiveLog(_my_name << " received command: " << cmnd << "\nResult:\n" << str.buf());
   // this is the only safe way to return a string?
   return CORBA_STRING_DUP(str.buf());
 }
@@ -422,19 +434,19 @@
   }
 }
 
-CosNF::Filter_ptr FAdminHelper::get_filter(CosNF::FilterID fltrID 
-					   WRAPPED_IMPLARG )
+CosNF::Filter_ptr FAdminHelper::get_filter(CosNF::FilterID fltrID)
 {
   Filter_i*       fltr=0;
   omni_mutex_lock lock(_oplock);
   if ( _filters.lookup(fltrID, fltr) ) {
     RDIDbgFAdminLog("Get Filter " << fltr << " [" << fltrID << "]\n");
-    return WRAPPED_IMPL2OREF(CosNF::Filter, fltr);
+    CosNF::Filter_var res = WRAPPED_IMPL2OREF(CosNF::Filter, fltr);
+    return res;
   }
   throw CosNF::FilterNotFound();
 }
 
-CosNF::FilterIDSeq* FAdminHelper::get_all_filters( WRAPPED_IMPLARG_VOID )
+CosNF::FilterIDSeq* FAdminHelper::get_all_filters()
 {
   RDI_HashCursor<CosNF::FilterID, Filter_i*> fcur;
   CORBA::ULong  indx=0;
@@ -448,8 +460,7 @@
   return fseq;
 }
 
-void FAdminHelper::remove_filter(CosNF::FilterID fltrID
-				 WRAPPED_IMPLARG )
+void FAdminHelper::remove_filter(CosNF::FilterID fltrID)
 {
   Filter_i* fltr=0;
   omni_mutex_lock lock(_oplock);
@@ -462,7 +473,7 @@
   WRAPPED_RELEASE_IMPL(fltr);
 }
 
-void FAdminHelper::remove_all_filters( WRAPPED_IMPLARG_VOID )
+void FAdminHelper::remove_all_filters()
 {
   RDI_HashCursor<CosNF::FilterID, Filter_i*> fcur;
   omni_mutex_lock lock(_oplock);
Index: lib/Filter_i.cc
===================================================================
RCS file: /cvsroot/omniNotify/lib/Filter_i.cc,v
retrieving revision 1.59
retrieving revision 1.59.2.1
diff -u -u -r1.59 -r1.59.2.1
--- lib/Filter_i.cc	2001/09/28 03:00:06	1.59
+++ lib/Filter_i.cc	2002/02/28 23:44:01	1.59.2.1
@@ -31,6 +31,21 @@
  
 /*
 $Log: Filter_i.cc,v $
+Revision 1.59.2.1  2002/02/28 23:44:01  alcfp
+merge alpha branch back into dev for latest fixes
+
+Revision 1.59.4.4  2002/02/26 22:28:43  alcfp
+added ReportInteractive flag - controls whether results of interactive cmds are output to report log, also added wait_for_destroy support, fixed server destroy so it causes main notifd thread to terminate
+
+Revision 1.59.4.3  2002/02/26 05:54:34  alcfp
+fixed deadlock over oplock event locking order
+
+Revision 1.59.4.2  2002/02/10 03:55:34  alcfp
+removed RVMPool
+
+Revision 1.59.4.1  2002/02/08 10:40:27  alcfp
+fixed oplock cleanup bug for deferred disposal case, also suppressed event rejection report when channel is shutting down
+
 Revision 1.59  2001/09/28 03:00:06  alcfp
 Filter_i uses oplockptr
 
@@ -680,19 +695,18 @@
 CORBA::Boolean
 Filter_i::rdi_match(RDI_StructuredEvent* se, EventChannel_i* channel) 
 {
-  unsigned int num=0;
-  RDI_RVM*     rvm=0;
-  CORBA::Boolean      delrvm=0;
+  RDI_RVM        rvm; // placing on stack more efficient than alloc
+  unsigned int   num     = 0;
 
   if ( channel ) channel->incr_num_rdi_match();
 
+  RDI_OPLOCK_ACQUIRE(RDI_THROW_INV_OBJREF);
+
   // Lock the event so that only one thread evaluates the event
   // at a time.  This may be too restrictive in some cases and,
   // hence,  we should either use different copies of the event
   // or synchronize the extraction from Any/DynAny only .......
-
   se->mylock().lock();   
-  RDI_OPLOCK_ACQUIRE(RDI_THROW_INV_OBJREF);
 
 #ifndef NDEBUG
   if (RDIDbgFilt) {
@@ -709,16 +723,12 @@
   // to it, we assume that the filter evaluates to TRUE ......
 
   if ( ! _constraint_impls || ! _constraint_impls->length() ) {
-    RDI_OPLOCK_RELEASE;
     se->mylock().unlock();
+    RDI_OPLOCK_RELEASE;
     RDIDbgFiltLog("No constraints -- filter eval returns TRUE\n");
     return 1;
   }
 
-  try {
-    rvm = RDI_RVMPool::get_rvm();
-  } catch (...) { throw; } // rethrows CORBA::NO_MEMORY
-
   for ( CORBA::ULong idx = 0; idx < _constraints->length(); idx++ ) {
     RDIDbgFiltLog("Eval constraint at idx " << idx << '\n');
     CORBA::Boolean isdominated = 0;
@@ -739,42 +749,40 @@
       continue;
 
     if ( (*_constraint_impls)[idx]->just_types ) {
-      RDI_OPLOCK_RELEASE;
       se->mylock().unlock();
-      if ( delrvm && rvm ) delete rvm;
+      RDI_OPLOCK_RELEASE;
       RDIDbgFiltLog("Dominating event type and no constraint -- filter eval returns TRUE\n");
       return 1;
     }
 
     while ( num <= 3 ) {
       try {
-	rvm->init((*_constraint_impls)[idx]->node->r_ops);
-	rvm->cexprs = 
+	rvm.init((*_constraint_impls)[idx]->node->r_ops);
+	rvm.cexprs = 
 	  (*_constraints)[idx].constraint_expression.constraint_expr;
-	rvm->eval(se);
+	rvm.eval(se);
 	if ( channel )
 	  channel->incr_num_rvm_eval();
 	break;
       } 
       catch (...) {
-	RDIDbgForceLog("XXX exception in rvm->init or rvm->eval: " << num << '\n');
+	RDIDbgForceLog("XXX exception in rvm.init or rvm.eval: " << num << '\n');
 	if ( num == 0 ) {
 	  CosNF::ConstraintExp& cxpr= (*_constraints)[idx].constraint_expression;
 	  RDIDbgForceLog("XXX constraint "<<(const char*)(cxpr.constraint_expr) << '\n');
 	}
 	if ( ++num == 3 ) {
-	  rvm->r_code = RDI_RTRet_OK;
-	  rvm->r_bool = 0;
+	  rvm.r_code = RDI_RTRet_OK;
+	  rvm.r_bool = 0;
 	  break;
 	}
       }
     }
 
-    if (rvm->r_code == RDI_RTRet_OK) {
-      if ( rvm->r_bool ) {
-	RDI_OPLOCK_RELEASE;
+    if (rvm.r_code == RDI_RTRet_OK) {
+      if ( rvm.r_bool ) {
 	se->mylock().unlock();
-	if ( delrvm && rvm ) delete rvm;
+	RDI_OPLOCK_RELEASE;
 	RDIDbgFiltLog("Constraint eval returned OK -- filter eval returns TRUE\n");
 	return 1;
       }
@@ -789,9 +797,8 @@
   }
   RDIDbgFiltLog("No more constraints -- filter eval returns FALSE\n");
 
-  RDI_OPLOCK_RELEASE;
   se->mylock().unlock();
-  if ( delrvm && rvm ) delete rvm;
+  RDI_OPLOCK_RELEASE;
   return 0;
 }
 
@@ -1067,14 +1074,24 @@
 
 ////////////////////////////////////////////////////////////////////
 
+omni_mutex       MappingFilter_i::_classlock;
+CORBA::Long      MappingFilter_i::_classctr = 0;
+
+// THIS CLASS NOT SUPPORTED YET
 MappingFilter_i::MappingFilter_i(const char* grammar, const CORBA::Any& value,
 				 FilterFactory_i* factory) :
-  _oplockptr(0), _disposed(0),
+  _oplockptr(0), _disposed(0), _my_name(factory->L_my_name()),
   _constraint_grammar(CORBA_STRING_DUP(grammar)), _def_value(value)
 { 
-  // NOT SUPPORTED YET
+  char buf[30];
+  _classlock.lock();
+  _classctr++;
+  sprintf(buf, "mapfilter%ld", _classctr);
+  _classlock.unlock();
+  _my_name.length(_my_name.length()+1);
+  _my_name[_my_name.length()-1] = (const char*)buf;
   RDI_OPLOCK_INIT;
-  WRAPPED_REGISTER_IMPL(this);
+  WRAPPED_REGISTER_IMPL2(this, &_my_name);
 }
 
 MappingFilter_i::~MappingFilter_i()
@@ -1428,7 +1445,7 @@
     str << "Invalid command: " << cmnd << "\n";
     success = 0;
   }
-  RDIRptForceLog(_my_name << " received command: " << cmnd << "\nResult:\n" << str.buf());
+  RDIRptInteractiveLog(_my_name << " received command: " << cmnd << "\nResult:\n" << str.buf());
   // this is the only safe way to return a string?
   return CORBA_STRING_DUP(str.buf());
 }
Index: lib/ProxyConsumer.cc
===================================================================
RCS file: /cvsroot/omniNotify/lib/ProxyConsumer.cc,v
retrieving revision 1.22
retrieving revision 1.22.2.3
diff -u -u -r1.22 -r1.22.2.3
--- lib/ProxyConsumer.cc	2001/10/06 00:44:52	1.22
+++ lib/ProxyConsumer.cc	2002/03/13 08:57:18	1.22.2.3
@@ -31,6 +31,27 @@
  
 /*
 $Log: ProxyConsumer.cc,v $
+Revision 1.22.2.3  2002/03/13 08:57:18  alcfp
+fixed oref counting bug in get_filter implementations
+
+Revision 1.22.2.2  2002/02/28 23:44:01  alcfp
+merge alpha branch back into dev for latest fixes
+
+Revision 1.22.4.4  2002/02/26 22:28:43  alcfp
+added ReportInteractive flag - controls whether results of interactive cmds are output to report log, also added wait_for_destroy support, fixed server destroy so it causes main notifd thread to terminate
+
+Revision 1.22.4.3  2002/02/08 17:08:53  alcfp
+improved use of REACQUIRE oplock macro
+
+Revision 1.22.4.2  2002/02/08 10:40:27  alcfp
+fixed oplock cleanup bug for deferred disposal case, also suppressed event rejection report when channel is shutting down
+
+Revision 1.22.4.1  2002/02/07 18:10:56  alcfp
+merged recent dev fixes into alpha
+
+Revision 1.22.2.1  2002/01/15 19:51:24  alcfp
+fixed case where BAD_PARAM was returned but AlreadyConnected should be returned and fixed _qosprop deletion
+
 Revision 1.22  2001/10/06 00:44:52  alcfp
 moved some EventChannel_i state to private
 
@@ -329,7 +350,7 @@
   if (_pxstate == RDI_Disconnected) { RDI_OPLOCK_RELEASE; RDI_THROW_INV_OBJREF; } // in process of being disposed
   CosNF::Filter_ptr res = _fa_helper.get_filter(fltrID);
   RDI_OPLOCK_RELEASE;
-  return res;
+  return CosNF::Filter::_duplicate(res);
 }
 
 CosNF::FilterIDSeq* RDIProxyConsumer::get_all_filters()
@@ -632,7 +653,7 @@
 	       "but for now, giving up immediately\n");
       res = 1;
     }
-    RDI_OPLOCK_REACQUIRE(return 1);
+    RDI_OPLOCK_REACQUIRE(RDI_METHOD_RETURN(RDIDbgCPxy, RDIDbgCPxy_nm, "RDIProxyConsumer::send_subscription_change [**unexpected REACQUIRE failure**]\n", 1));
   } else {
     RDIDbgCPxyLog("RDIProxyConsumer -- sc_subscriber not available => did not send subscription_change\n");
     res = 1;
@@ -643,16 +664,20 @@
 
 void RDIProxyConsumer::_report_reject_se(const char* cproxy_descr, CosNA::ProxyID consumer_id,
 					 const CosN::StructuredEvent& evnt) {
-  RDIRptRejectsLog("Rejecting structured event:\n" << evnt << 
-		   "\n\tfrom supplier connected to " << cproxy_descr << " proxy with id " << consumer_id <<
-		   "\n\tAnnounced-events queue hit limit MaxQueueLength\n");
+  if (!_channel->shutting_down()) {
+    RDIRptRejectsLog("Rejecting structured event:\n" << evnt << 
+		     "\n\tfrom supplier connected to " << cproxy_descr << " proxy with id " << consumer_id <<
+		     "\n\tAnnounced-events queue hit limit MaxQueueLength\n");
+  }
 }
 
 void RDIProxyConsumer::_report_reject_any(const char* cproxy_descr, CosNA::ProxyID consumer_id,
 					  const CORBA::Any& evnt) {
-  RDIRptRejectsLog("Rejecting event of type CORBA::Any:\n" << evnt <<
-		   "\n\tfrom supplier connected to " << cproxy_descr << " proxy with id " << consumer_id <<
-		   "\n\tAnnounced-events queue hit limit MaxQueueLength\n");
+  if (!_channel->shutting_down()) {
+    RDIRptRejectsLog("Rejecting event of type CORBA::Any:\n" << evnt <<
+		     "\n\tfrom supplier connected to " << cproxy_descr << " proxy with id " << consumer_id <<
+		     "\n\tAnnounced-events queue hit limit MaxQueueLength\n");
+  }
 }
 
 #ifndef NREPORT
@@ -696,7 +721,7 @@
 {
   RDI_OPLOCK_ACQUIRE(RDI_THROW_INV_OBJREF);
   CosEvC::PullSupplier_var evsupl;
-  if ( CORBA::is_nil(supplier) || (_pxstate != RDI_NotConnected) ) {
+  if ( CORBA::is_nil(supplier) ) {
     RDI_OPLOCK_RELEASE;
     throw CORBA::BAD_PARAM(0, CORBA::COMPLETED_NO);
   }
@@ -721,7 +746,6 @@
       cscp->insert_proxy(this);
     }
   }
-
   if ( _worker ) {    // Notify worker thread
     RDI_OPLOCK_SIGNAL;
   }
@@ -729,9 +753,6 @@
   if ( cps ) {
     cps->signal_pull_threads();
   }
-  if ( _qosprop ) {
-    delete _qosprop; _qosprop = 0;
-  }
   RDI_OPLOCK_RELEASE;
 }
 
@@ -813,7 +834,7 @@
   return 0;
 }
 
-// REQUIREMENT: A thread from push pool only calls this method
+// REQUIREMENT: A thread from pull pool only calls this method
 // if is_available() is true and it thinks state is connected and active.
 // (For safety we verify that these conditions actually hold.)
 void ProxyPullConsumer_i::pull_event(CORBA::Boolean& invalid)
@@ -877,10 +898,10 @@
     RDIDbgCPxyLog("Pull pool calling pull_event for proxy " << (void*)this << " - Exception while pulling event from supplier\n");
   }
 
-  RDI_OPLOCK_REACQUIRE(return);
+  RDI_OPLOCK_REACQUIRE(RDI_METHOD_RETURN_NULL(RDIDbgCPxy, RDIDbgCPxy_nm, "ProxyPullConsumer_i::pull_event [**unexpected REACQUIRE failure**]\n"));
 
-  // add new event to channel even if we have been disconnected in the meantime
-  if (outcall_worked && hasev && event) {
+  // add new event to channel, but only if we are still connected
+  if ( (_pxstate == RDI_Connected) && outcall_worked && hasev && event) {
     _nevents++; 
     if ( _match_event(*event) ) {
       if (_channel->new_any_event(*event)) {
@@ -985,8 +1006,8 @@
 
     update_timeout = 1; // force update of timeout at top of loop
 
-    // add new event to channel even if we have been disconnected in the meantime
-    if (outcall_worked && hasev && event) {
+    // add new event to channel, but only if we are still connected
+    if ( (_pxstate == RDI_Connected) && outcall_worked && hasev && event ) {
       _nevents += 1;
       if ( _match_event(*event) ) {
 	if (_channel->new_any_event(*event)) {
@@ -1055,6 +1076,9 @@
   _fa_helper.remove_all_filters();
   _supplier = CosEvC::PullSupplier::_nil();
   _nc_supplier = CosNC::PullSupplier::_nil();
+  if ( _qosprop ) {
+    delete _qosprop; _qosprop = 0;
+  }
   RDI_OPLOCK_DISPOSE_IMPL_AND_RELEASE;
 }
 
@@ -1090,7 +1114,7 @@
 (CosNC::StructuredPullSupplier_ptr supplier WRAPPED_IMPLARG )
 {
   RDI_OPLOCK_ACQUIRE(RDI_THROW_INV_OBJREF);
-  if ( CORBA::is_nil(supplier) || (_pxstate != RDI_NotConnected) ) {
+  if ( CORBA::is_nil(supplier)) {
     RDI_OPLOCK_RELEASE;
     throw CORBA::BAD_PARAM(0, CORBA::COMPLETED_NO);
   }
@@ -1111,7 +1135,6 @@
   if ( ! _sc_off && cscp ) {
     cscp->insert_proxy(this);
   }
-
   if ( _worker ) {    // Notify worker thread
     RDI_OPLOCK_SIGNAL;
   }
@@ -1119,9 +1142,6 @@
   if ( cps ) {
     cps->signal_pull_threads();
   }
-  if ( _qosprop ) {
-    delete _qosprop; _qosprop = 0;
-  }
   RDI_OPLOCK_RELEASE;
 }
 
@@ -1203,7 +1223,7 @@
   return 0;
 }
 
-// REQUIREMENT: A thread from push pool only calls this method
+// REQUIREMENT: A thread from pull pool only calls this method
 // if is_available() is true and it thinks state is connected and active.
 // (For safety we verify that these conditions actually hold.)
 void StructuredProxyPullConsumer_i::pull_event(CORBA::Boolean& invalid)
@@ -1270,11 +1290,11 @@
     RDIDbgCPxyLog("Pull pool calling pull_event for proxy " << (void*)this << " - Exception while pulling event from supplier\n");
   }
 
-  RDI_OPLOCK_REACQUIRE(return);
+  RDI_OPLOCK_REACQUIRE(RDI_METHOD_RETURN_NULL(RDIDbgCPxy, RDIDbgCPxy_nm, "StructuredProxyPullConsumer_i::pull_event [**unexpected REACQUIRE failure**]\n"));
 
-  // add new event to channel even if we have been disconnected in the meantime
+  // add new event to channel, but only if we are still connected
   out_of_space = 0;
-  if (outcall_worked && hasev && event) {
+  if ( (_pxstate == RDI_Connected) && outcall_worked && hasev && event ) {
     _nevents++; 
     sevnt = new RDI_StructuredEvent(*event);
     RDI_AssertAllocThrowNo(sevnt, "Memory allocation failure -- RDI_StructuredEvent\n");
@@ -1389,9 +1409,9 @@
 
     update_timeout = 1; // force update of timeout at top of loop
 
-    // add new event to channel even if we have been disconnected in the meantime
+    // add new event to channel, but only if we are still connected
     out_of_space = 0;
-    if (outcall_worked && hasev && event) {
+    if ( (_pxstate == RDI_Connected) && outcall_worked && hasev && event ) {
       _nevents++; 
       sevnt = new RDI_StructuredEvent(*event);
       RDI_AssertAllocThrowNo(sevnt, "Memory allocation failure -- RDI_StructuredEvent\n");
@@ -1468,6 +1488,9 @@
   _active  = 0;
   _fa_helper.remove_all_filters();
   _supplier = CosNC::StructuredPullSupplier::_nil();
+  if ( _qosprop ) {
+    delete _qosprop; _qosprop = 0;
+  }
   RDI_OPLOCK_DISPOSE_IMPL_AND_RELEASE;
 }
 
@@ -1503,7 +1526,7 @@
 (CosNC::SequencePullSupplier_ptr supplier WRAPPED_IMPLARG )
 {
   RDI_OPLOCK_ACQUIRE(RDI_THROW_INV_OBJREF);
-  if ( CORBA::is_nil(supplier) || (_pxstate != RDI_NotConnected) ) {
+  if ( CORBA::is_nil(supplier) ) {
     RDI_OPLOCK_RELEASE;
     throw CORBA::BAD_PARAM(0, CORBA::COMPLETED_NO);
   }
@@ -1524,7 +1547,6 @@
   if ( ! _sc_off && cscp ) {
     cscp->insert_proxy(this);
   }
-
   if ( _worker ) {	// Notify worker thread
     RDI_OPLOCK_SIGNAL;
   }
@@ -1532,7 +1554,6 @@
   if ( cps ) {
     cps->signal_pull_threads();
   }
-
   RDI_OPLOCK_RELEASE;
 }
 
@@ -1614,7 +1635,7 @@
   return 0;
 }
 
-// REQUIREMENT: A thread from push pool only calls this method
+// REQUIREMENT: A thread from pull pool only calls this method
 // if is_available() is true and it thinks state is connected and active.
 // (For safety we verify that these conditions actually hold.)
 void SequenceProxyPullConsumer_i::pull_event(CORBA::Boolean& invalid)
@@ -1687,11 +1708,11 @@
     RDIDbgCPxyLog("Pull pool calling pull_event for proxy " << (void*)this << " - Exception while pulling event from supplier\n");
   }
 
-  RDI_OPLOCK_REACQUIRE(return);
+  RDI_OPLOCK_REACQUIRE(RDI_METHOD_RETURN_NULL(RDIDbgCPxy, RDIDbgCPxy_nm, "SequenceProxyPullConsumer_i::pull_event [**unexpected REACQUIRE failure**]\n"));
 
-  // add new event to channel even if we have been disconnected in the meantime
+  // add new event to channel, but only if we are still connected
   out_of_space = 0;
-  if (outcall_worked && hasev && events) {
+  if ( (_pxstate == RDI_Connected) && outcall_worked && hasev && events ) {
     _nevents += events->length();
     for (ex = 0; (out_of_space == 0) && (ex < events->length()); ex++) {
       sevnt = new RDI_StructuredEvent((*events)[ex]);
@@ -1817,9 +1838,9 @@
 
     update_timeout = 1; // force update of timeout at top of loop
 
-    // add new event to channel even if we have been disconnected in the meantime
+    // add new event to channel, but only if we are still connected
     out_of_space = 0;
-    if (outcall_worked && hasev && events) {
+    if ( (_pxstate == RDI_Connected) && outcall_worked && hasev && events ) {
       _nevents += events->length();
       for (ex = 0; (out_of_space == 0) && (ex < events->length()); ex++) {
 	sevnt = new RDI_StructuredEvent((*events)[ex]);
@@ -1899,6 +1920,9 @@
   _active  = 0;
   _fa_helper.remove_all_filters();
   _supplier = CosNC::SequencePullSupplier::_nil();
+  if ( _qosprop ) {
+    delete _qosprop; _qosprop = 0;
+  }
   RDI_OPLOCK_DISPOSE_IMPL_AND_RELEASE;
 }
 
@@ -1968,7 +1992,6 @@
       cscp->insert_proxy(this);
     }
   }
-
   RDI_OPLOCK_RELEASE;
 }
 
@@ -2417,7 +2440,7 @@
     str << "Invalid command: " << cmnd << "\n";
     success = 0;
   }
-  RDIRptForceLog(_my_name << " received command: " << cmnd << "\nResult:\n" << str.buf());
+  RDIRptInteractiveLog(_my_name << " received command: " << cmnd << "\nResult:\n" << str.buf());
   // this is the only safe way to return a string?
   return CORBA_STRING_DUP(str.buf());
 }
Index: lib/ProxySupplier.cc
===================================================================
RCS file: /cvsroot/omniNotify/lib/ProxySupplier.cc,v
retrieving revision 1.22.2.2
retrieving revision 1.22.2.4
diff -u -u -r1.22.2.2 -r1.22.2.4
--- lib/ProxySupplier.cc	2001/10/09 06:38:05	1.22.2.2
+++ lib/ProxySupplier.cc	2002/03/13 08:57:18	1.22.2.4
@@ -31,6 +31,24 @@
  
 /*
 $Log: ProxySupplier.cc,v $
+Revision 1.22.2.4  2002/03/13 08:57:18  alcfp
+fixed oref counting bug in get_filter implementations
+
+Revision 1.22.2.3  2002/02/28 23:44:01  alcfp
+merge alpha branch back into dev for latest fixes
+
+Revision 1.22.4.5  2002/02/26 22:28:44  alcfp
+added ReportInteractive flag - controls whether results of interactive cmds are output to report log, also added wait_for_destroy support, fixed server destroy so it causes main notifd thread to terminate
+
+Revision 1.22.4.4  2002/02/26 05:54:35  alcfp
+fixed deadlock over oplock event locking order
+
+Revision 1.22.4.3  2002/02/08 17:08:53  alcfp
+improved use of REACQUIRE oplock macro
+
+Revision 1.22.4.2  2002/02/07 18:10:56  alcfp
+merged recent dev fixes into alpha
+
 Revision 1.22.2.2  2001/10/09 06:38:05  alcfp
 11 release
 
@@ -486,7 +504,7 @@
   if (_pxstate == RDI_Disconnected) { RDI_OPLOCK_RELEASE; RDI_THROW_INV_OBJREF; } // in process of being disposed
   CosNF::Filter_ptr res = _fa_helper.get_filter(fltrID);
   RDI_OPLOCK_RELEASE;
-  return res;
+  return CosNF::Filter::_duplicate(res);
 }
 
 CosNF::FilterIDSeq* RDIProxySupplier::get_all_filters()
@@ -655,7 +673,7 @@
 		    "but for now, giving up immediately\n");
       res = 1;
     }
-    RDI_OPLOCK_REACQUIRE(return 1);
+    RDI_OPLOCK_REACQUIRE(RDI_METHOD_RETURN(RDIDbgSPxy, RDIDbgSPxy_nm, "RDIProxySupplier::send_offer_change [**unexpected REACQUIRE failure**]\n", 1));
   } else {
     RDIDbgSPxyLog("RDIProxySupplier -- oc_subscriber not available => did not send offer_change\n");
     res = 1;
@@ -1416,20 +1434,18 @@
   } catch (...) {
     RDIDbgSPxyLog("Push pool calling push_event for proxy " << (void*)this << " - Exception while pushing event to consumer\n");
   }
+  if ( RDI_LOCK_EVENT ) event->mylock().unlock();
 
-  RDI_OPLOCK_REACQUIRE(return);
+  RDI_OPLOCK_REACQUIRE(RDI_METHOD_RETURN_NULL(RDIDbgSPxy, RDIDbgSPxy_nm, "ProxyPushSupplier_i::push_event [**unexpected REACQUIRE failure**]\n"));
 
-  if ( RDI_LOCK_EVENT ) event->mylock().unlock();
   event->decr_ref_counter(RDI_LOCK_EVENT);
 
-  if (outcall_worked) {
-    _channel->incr_num_notifications(qsize);
-  }
-
   if (_pxstate != RDI_Connected) {
     // disconnected/disposed during push -- do nothing else with my state
   } else {
-    if (!outcall_worked) { // exception
+    if (outcall_worked) {
+      _channel->incr_num_notifications(qsize);
+    } else { // exception
       // unregister this proxy -- no more subscription_change msgs
       RDI_ChangePool* cocp = _channel->ochange_pool();
       if ( ! _oc_off && ! CORBA::is_nil(_nc_consumer) && cocp ) {
@@ -1495,20 +1511,18 @@
     } catch (...) {
       RDIDbgSPxyLog("Push thread for proxy " << (void*)this << " - Exception while pushing event to consumer\n");
     }
+    if ( RDI_LOCK_EVENT ) event->mylock().unlock();
 
     RDI_OPLOCK_REACQUIRE(RDI_THREAD_EXIT(RDIDbgSPxy, RDIDbgSPxy_nm, "push thread [**unexpected REACQUIRE failure**]\n"));
 
-    if ( RDI_LOCK_EVENT ) event->mylock().unlock();
     event->decr_ref_counter(RDI_LOCK_EVENT);
 
-    if (outcall_worked) {
-      _channel->incr_num_notifications(qsize);
-    }
-
     if (_pxstate != RDI_Connected) {
       // disconnected/disposed during push -- do nothing else with my state
     } else {
-      if (!outcall_worked) { // exception
+      if (outcall_worked) {
+	_channel->incr_num_notifications(qsize);
+      } else { // exception
 	// unregister this proxy -- no more subscription_change msgs
 	RDI_ChangePool* cocp = _channel->ochange_pool();
 	if ( ! _oc_off && ! CORBA::is_nil(_nc_consumer) && cocp ) {
@@ -1733,20 +1747,18 @@
   } catch (...) {
     RDIDbgSPxyLog("Push pool calling push_event for proxy " << (void*)this << " - Exception while pushing event to consumer\n");
   }
+  if ( RDI_LOCK_EVENT ) event->mylock().unlock();
 
-  RDI_OPLOCK_REACQUIRE(return);
+  RDI_OPLOCK_REACQUIRE(RDI_METHOD_RETURN_NULL(RDIDbgSPxy, RDIDbgSPxy_nm, "StructuredProxyPushSupplier_i::push_event [**unexpected REACQUIRE failure**]\n"));
 
-  if ( RDI_LOCK_EVENT ) event->mylock().unlock();
   event->decr_ref_counter(RDI_LOCK_EVENT);
 
-  if (outcall_worked) {
-    _channel->incr_num_notifications(qsize);
-  }
-
   if (_pxstate != RDI_Connected) {
     // disconnected/disposed during push -- do nothing else with my state
   } else {
-    if (!outcall_worked) { // exception
+    if (outcall_worked) {
+      _channel->incr_num_notifications(qsize);
+    } else { // exception
       // unregister this proxy -- no more subscription_change msgs
       RDI_ChangePool* cocp = _channel->ochange_pool();
       if ( ! _oc_off && cocp ) {
@@ -1804,20 +1816,18 @@
     } catch (...) {
       RDIDbgSPxyLog("Push thread for proxy " << (void*)this << " - Exception while pushing event to consumer\n");
     }
+    if ( RDI_LOCK_EVENT ) event->mylock().unlock();
 
     RDI_OPLOCK_REACQUIRE(RDI_THREAD_EXIT(RDIDbgSPxy, RDIDbgSPxy_nm, "push thread [**unexpected REACQUIRE failure**]\n"));
 
-    if ( RDI_LOCK_EVENT ) event->mylock().unlock();
     event->decr_ref_counter(RDI_LOCK_EVENT);
 
-    if (outcall_worked) {
-      _channel->incr_num_notifications(qsize);
-    }
-
     if (_pxstate != RDI_Connected) {
       // disconnected/disposed during push -- do nothing else with my state
     } else {
-      if (!outcall_worked) { // exception
+      if (outcall_worked) {
+	_channel->incr_num_notifications(qsize);
+      } else { // exception
 	// unregister this proxy -- no more subscription_change msgs
 	RDI_ChangePool* cocp = _channel->ochange_pool();
 	if ( ! _oc_off && cocp ) {
@@ -2115,7 +2125,8 @@
   for ( i = 0; i < actsize; i++ ) {
     event[i] = _ntfqueue.remove_pri_head();
     if ( RDI_LOCK_EVENT ) event[i]->mylock().lock();
-    notif[i] = event[i]->get_cos_event();
+    notif[i] = event[i]->get_cos_event(); // unfortunate copying
+    if ( RDI_LOCK_EVENT ) event[i]->mylock().unlock();
   }
   _nevents += actsize;
   // update timeout before releasing OPLOCK -- this means we do the update
@@ -2143,24 +2154,22 @@
     RDIDbgSPxyLog("Push pool calling push_event for proxy " << (void*)this << " - Exception while pushing event to consumer\n");
   }
 
-  RDI_OPLOCK_REACQUIRE(return);
+  RDI_OPLOCK_REACQUIRE(RDI_METHOD_RETURN_NULL(RDIDbgSPxy, RDIDbgSPxy_nm, "SequenceProxyPushSupplier_i::push_event [**unexpected REACQUIRE failure**]\n"));
 
   for ( i = 0; i < actsize; i++ ) {
-    if ( RDI_LOCK_EVENT ) event[i]->mylock().unlock();
     event[i]->decr_ref_counter(RDI_LOCK_EVENT);
     event[i] = 0;
   }
   delete [] event;
-  if (outcall_worked) {
-    for ( i = 0; i < actsize; i++ ) {
-      _channel->incr_num_notifications(--qsize);
-    }
-  }
 
   if (_pxstate != RDI_Connected) {
     // disconnected/disposed during push -- do nothing else with my state
   } else {
-    if (!outcall_worked) { // exception
+    if (outcall_worked) {
+      for ( i = 0; i < actsize; i++ ) {
+	_channel->incr_num_notifications(--qsize);
+      }
+    } else { // exception
       // unregister this proxy -- no more subscription_change msgs
       RDI_ChangePool* cocp = _channel->ochange_pool();
       if ( ! _oc_off && cocp ) {
@@ -2250,7 +2259,8 @@
     for ( i = 0; i < actsize; i++ ) {
       event[i] = _ntfqueue.remove_pri_head();
       if ( RDI_LOCK_EVENT ) event[i]->mylock().lock();
-      notif[i] = event[i]->get_cos_event();
+      notif[i] = event[i]->get_cos_event(); // unfortunate copying
+      if ( RDI_LOCK_EVENT ) event[i]->mylock().unlock();
     }
     _nevents += actsize;
 
@@ -2281,21 +2291,18 @@
     update_timeout = 1; // force update of timeout at top of loop
 
     for ( i = 0; i < actsize; i++ ) {
-      if ( RDI_LOCK_EVENT ) event[i]->mylock().unlock();
       event[i]->decr_ref_counter(RDI_LOCK_EVENT);
       event[i] = 0;
     }
 
-    if (outcall_worked) {
-      for ( i = 0; i < actsize; i++ ) {
-	_channel->incr_num_notifications(--qsize);
-      }
-    }
-
     if (_pxstate != RDI_Connected) {
       // disconnected/disposed during push -- do nothing else with my state
     } else {
-      if (!outcall_worked) { // exception
+      if (outcall_worked) {
+	for ( i = 0; i < actsize; i++ ) {
+	  _channel->incr_num_notifications(--qsize);
+	}
+      } else { // exception
 	// unregister this proxy -- no more subscription_change msgs
 	RDI_ChangePool* cocp = _channel->ochange_pool();
 	if ( ! _oc_off && cocp ) {
@@ -2593,7 +2600,7 @@
     str << "Invalid command: " << cmnd << "\n";
     success = 0;
   }
-  RDIRptForceLog(_my_name << " received command: " << cmnd << "\nResult:\n" << str.buf());
+  RDIRptInteractiveLog(_my_name << " received command: " << cmnd << "\nResult:\n" << str.buf());
   // this is the only safe way to return a string?
   return CORBA_STRING_DUP(str.buf());
 }
Index: lib/RDI.cc
===================================================================
RCS file: /cvsroot/omniNotify/lib/RDI.cc,v
retrieving revision 1.14
retrieving revision 1.14.2.1
diff -u -u -r1.14 -r1.14.2.1
--- lib/RDI.cc	2001/10/04 02:23:26	1.14
+++ lib/RDI.cc	2002/02/28 23:44:02	1.14.2.1
@@ -30,6 +30,15 @@
  
 /*
 $Log: RDI.cc,v $
+Revision 1.14.2.1  2002/02/28 23:44:02  alcfp
+merge alpha branch back into dev for latest fixes
+
+Revision 1.14.4.3  2002/02/26 22:28:44  alcfp
+added ReportInteractive flag - controls whether results of interactive cmds are output to report log, also added wait_for_destroy support, fixed server destroy so it causes main notifd thread to terminate
+
+Revision 1.14.4.2  2002/02/25 15:10:24  alcfp
+fix to oref ref counting
+
 Revision 1.14  2001/10/04 02:23:26  alcfp
 moved local clock params into ServerQoS
 
@@ -51,17 +60,33 @@
 // --------------------------------------------------------------------------------
 // RDI static routines 
 
-AttN::Server_ptr RDI::init_server(int& argc, char** argv) {
+AttN::Server_ptr RDI::init_server(int& argc, char** argv)
+{
   if (! _Server_i) {
     _Server_i = RDINotifServer::create(argc, argv);
     if (_Server_i) {
       _Server = WRAPPED_IMPL2OREF(AttNotification::Server, _Server_i);
     }
+  }
+  return _Server;
+}
+
+void RDI::wait_for_destroy()
+{
+  _Server_i->L_wait_for_destroy(); 
+}
+
+RDINotifServer* RDI::get_server_i()
+{
+  if (!_Server_i || _Server_i->destroyed()) {
+    return 0;
   }
-  return AttN::Server::_duplicate(_Server);
+  return _Server_i;
 }
 
-void RDI::CleanupAll() {
+void RDI::CleanupAll()
+{
+  RDIOplocks::shutdown();
   RDI::CloseDbgFile();
   RDI::CloseRptFile();
   // XXX WHAT ELSE? XXX
@@ -105,7 +130,8 @@
 // --------------------------------------------------------------------------------
 // class RDI static functions
 
-int RDI::OpenDbgFile(const char* pathnm) {
+int RDI::OpenDbgFile(const char* pathnm)
+{
   if ( RDI_STR_EQ_I(pathnm, "stderr") ) {
     _DbgFile   = stderr;
   } else if ( RDI_STR_EQ_I(pathnm, "stderr") ) {
@@ -121,7 +147,8 @@
   return 0;
 }
 
-int RDI::OpenRptFile(const char* pathnm) {
+int RDI::OpenRptFile(const char* pathnm)
+{
   if ( RDI_STR_EQ_I(pathnm, "stdout") ) {
     _RptFile   = stdout;
   } else if ( RDI_STR_EQ_I(pathnm, "stderr") ) {
@@ -137,14 +164,16 @@
   return 0;
 }
 
-void RDI::CloseDbgFile() {
+void RDI::CloseDbgFile()
+{
   if ( _DbgFile && (_DbgFile != stdout) && (_DbgFile != stderr) ) {
     fclose(_DbgFile);
   }
   _DbgFile = 0;
 }
 
-void RDI::CloseRptFile() {
+void RDI::CloseRptFile()
+{
   if ( _RptFile && (_RptFile != stdout) && (_RptFile != stderr) ) {
     fclose(_RptFile);
   }
Index: lib/RDIEventQueue.cc
===================================================================
RCS file: /cvsroot/omniNotify/lib/RDIEventQueue.cc,v
retrieving revision 1.45
retrieving revision 1.45.2.1
diff -u -u -r1.45 -r1.45.2.1
--- lib/RDIEventQueue.cc	2001/10/04 06:48:33	1.45
+++ lib/RDIEventQueue.cc	2002/02/28 23:44:02	1.45.2.1
@@ -31,6 +31,12 @@
  
 /*
 $Log: RDIEventQueue.cc,v $
+Revision 1.45.2.1  2002/02/28 23:44:02  alcfp
+merge alpha branch back into dev for latest fixes
+
+Revision 1.45.4.1  2002/02/25 15:09:52  alcfp
+added missing unlock
+
 Revision 1.45  2001/10/04 06:48:33  alcfp
 Added report thread, changed ReportingInterval param to have units = seconds
 
@@ -392,6 +398,7 @@
     _gclock.lock();
     if ( _finish ) {
       RDIDbgEvQLog("\tGC thread "<<omni_thread::self()->id()<<" exits\n");
+      _gclock.unlock();
       omni_thread::exit();
       return;
     }
Index: lib/RDINotifServer.cc
===================================================================
RCS file: /cvsroot/omniNotify/lib/RDINotifServer.cc,v
retrieving revision 1.9
retrieving revision 1.9.2.2
diff -u -u -r1.9 -r1.9.2.2
--- lib/RDINotifServer.cc	2001/10/05 02:18:17	1.9
+++ lib/RDINotifServer.cc	2002/02/28 23:44:02	1.9.2.2
@@ -31,6 +31,21 @@
  
 /*
 $Log: RDINotifServer.cc,v $
+Revision 1.9.2.2  2002/02/28 23:44:02  alcfp
+merge alpha branch back into dev for latest fixes
+
+Revision 1.9.4.3  2002/02/26 22:28:44  alcfp
+added ReportInteractive flag - controls whether results of interactive cmds are output to report log, also added wait_for_destroy support, fixed server destroy so it causes main notifd thread to terminate
+
+Revision 1.9.4.2  2002/02/20 21:22:55  alcfp
+steps towards correct oref refcounts
+
+Revision 1.9.4.1  2002/02/07 18:10:56  alcfp
+merged recent dev fixes into alpha
+
+Revision 1.9.2.1  2001/10/29 19:27:53  alcfp
+small fix for "cleanup all" command
+
 Revision 1.9  2001/10/05 02:18:17  alcfp
 small fix
 
@@ -72,8 +87,6 @@
 #include "CosNfyUtils.h"
 #include "CosNotifyChannelAdmin_i.h"
 
-// #include "omniNotify.h" XXX needed?
-
 // ----------------------------------------------------------- //
 
 RDINotifServer::RDINotifServer(RDI_Config*                   config,
@@ -84,13 +97,18 @@
 			       EventChannel_i*               chan_i,
 			       AttN::EventChannel_ptr        chan,
 			       RDI_ServerQoS*                s_qos)
-  : _oplockptr(0), _destroyed(0), _configp(config),
-    _ffactory_i(ffact_i), _ffactory(ffact),
-    _cfactory_i(cfact_i), _cfactory(cfact), _channel_i(chan_i), _channel(chan), _server_qos(s_qos)
+  : _oplockptr(0), _destroy_wait(0), _destroyed(0), _destroy_called(0), _configp(config),
+    _ffactory_i(ffact_i), _cfactory_i(cfact_i), _channel_i(chan_i), _channel(chan), _server_qos(s_qos)
 {
   RDI_OPLOCK_INIT;
+  _destroy_wait = _oplockptr->add_condition();
   _my_name.length(1);
   _my_name[0] = (const char*)"server";
+  _ffactory = AttN::FilterFactory::_duplicate(ffact);
+  _cfactory = AttN::EventChannelFactory::_duplicate(cfact);
+
+  // Register 'this' to start receiving requests
+  WRAPPED_REGISTER_IMPL2(this, &_my_name);
 }
 
 RDINotifServer::~RDINotifServer()
@@ -145,6 +163,7 @@
   CORBA::Boolean RDIRptNotifQoS_set      = 0;  
   CORBA::Boolean RDIRptAdminQoS_set      = 0;  
   CORBA::Boolean RDIRptServerQoS_set     = 0;  
+  CORBA::Boolean RDIRptInteractive_set   = 0;  
 
   RDINotifServer*  server                = 0;
   EventChannel_i*  channel               = 0;
@@ -152,7 +171,7 @@
   EventChannelFactory_i* factory         = 0;
 
   CosNA::ChannelID        channID;
-  AttN::EventChannel_var chanref;
+  AttN::EventChannel_ptr  chanref;
   AttN::FilterFactory_var filtfactref;
   AttN::EventChannelFactory_var factref;
 
@@ -302,6 +321,9 @@
   if (config->get_value(error_str, RDIRptServerQoS_nm     , RDIRptServerQoS_set,    1) == -2) {
     goto cleanup_and_return_0;
   }
+  if (config->get_value(error_str, RDIRptInteractive_nm   , RDIRptInteractive_set,  1) == -2) {
+    goto cleanup_and_return_0;
+  }
 
   RDI::ClrDbgFlags();
   if (RDIDbgDaemon_set       ) RDI::AddDbgFlags(RDIDbgDaemonF        );
@@ -334,6 +356,7 @@
   if (RDIRptNotifQoS_set     ) RDI::AddRptFlags( RDIRptNotifQoSF     );
   if (RDIRptAdminQoS_set     ) RDI::AddRptFlags( RDIRptAdminQoSF     );
   if (RDIRptServerQoS_set    ) RDI::AddRptFlags( RDIRptServerQoSF    );
+  if (RDIRptInteractive_set  ) RDI::AddRptFlags( RDIRptInteractiveF  );
 
   RDI::OpenDbgFile(debugLogFile);
   RDI::OpenRptFile(reportLogFile);
@@ -460,9 +483,6 @@
   if (factory) {
     factory->cleanup_and_dispose();
   }
-  if (server) {
-    delete server;
-  } 
   RDI::CleanupAll(); // in case log/report files were opened
   return 0;
 }
@@ -471,11 +491,36 @@
 RDINotifServer::destroy( WRAPPED_IMPLARG_VOID )
 {
   RDI_OPLOCK_ACQUIRE(RDI_THROW_INV_OBJREF);
-  if (_destroyed) {
+  if (_destroy_called) {
     RDIDbgDaemonLog("** RDINotifServer::destroy called twice\n");
     RDI_OPLOCK_RELEASE;
     return;
   }
+  _destroy_called = 1; // acts as a guard -- only one thread executes the following
+  _destroy_wait->broadcast();
+  RDI_OPLOCK_RELEASE;
+}
+
+void
+RDINotifServer::L_wait_for_destroy()
+{
+  RDI_OPLOCK_ACQUIRE(return);
+  while (!_destroy_called) {
+    _destroy_wait->wait(); // does not hold lock during wait
+  }
+  RDI_OPLOCK_RELEASE;
+  _destroy();
+}
+
+void
+RDINotifServer::_destroy()
+{
+  RDI_OPLOCK_ACQUIRE(return);
+  if (_destroyed) {
+    RDIDbgDaemonLog("** RDINotifServer::_destroy called twice\n");
+    RDI_OPLOCK_RELEASE;
+    return;
+  }
   _destroyed = 1; // acts as guard -- only one thread executes the following
   if ( _configp ) {
     RDIstrstream error_str; // for type error msgs
@@ -493,7 +538,7 @@
   if ( ! CORBA::is_nil(_cfactory) ) {
     CosNA::ChannelIDSeq* cids = _cfactory->get_all_channels();
     for ( CORBA::ULong ix = 0; ix < cids->length(); ix++ ) {
-      CosNA::EventChannel_ptr chan_ptr;
+      CosNA::EventChannel_var chan_ptr;
       chan_ptr = _cfactory->get_event_channel( (*cids)[ix] );
       if ( ! CORBA::is_nil(chan_ptr) ) {
 	RDIDbgDaemonLog("Destroying Event Channel " << (*cids)[ix] << '\n');
@@ -503,13 +548,14 @@
     }
     delete cids;
   }
+  _cfactory = AttN::EventChannelFactory::_nil();
+  _ffactory = AttN::FilterFactory::_nil();
   if (_cfactory_i) {
     RDIDbgDaemonLog("Destroying Channel Factory\n");
     _cfactory_i->cleanup_and_dispose();
     RDIDbgDaemonLog("Done Destroying Channel Factory\n");
     _cfactory_i = 0;
   }
-  _cfactory = AttN::EventChannelFactory::_nil();
   if (_ffactory_i) {
     RDIDbgDaemonLog("Destroying Filter Factory\n");
     _ffactory_i->cleanup_and_dispose();
@@ -520,7 +566,6 @@
     delete _server_qos;
     _server_qos = 0;
   }
-  _ffactory = AttN::FilterFactory::_nil();
   RDI_OPLOCK_DISPOSE_IMPL_AND_RELEASE;
   RDI::CleanupAll();
 }
@@ -701,6 +746,9 @@
 			      AttN_Interactive_outarg next_target)
 {
   CORBA::Boolean success = 1;
+  AttN::Interactive_ptr targ1 = AttN::Interactive::_nil();
+  AttN::Interactive_ptr targ2 = AttN::Interactive::_nil();
+  CORBA::Boolean targ1_set = 0, targ2_set = 0;
   target_changed = 0;
   char* go_targ = CORBA_STRING_DUP(p.argv[1]);
   char* rest_go_targ = RDI_STRCHR(go_targ, '.');
@@ -709,38 +757,41 @@
     rest_go_targ++;
   }
   if (RDI_STR_EQ_I(go_targ, "chanfact")) {
-    target_changed = 1;
-    next_target = WRAPPED_IMPL2OREF(AttN::EventChannelFactory, _cfactory_i);
+    targ1 = WRAPPED_IMPL2OREF(AttN::EventChannelFactory, _cfactory_i);
+    targ1_set = 1;
     str << "\nomniNotify: new target ==> chanfact\n";
   } else if (RDI_STR_EQ_I(go_targ, "filtfact")) {
-    target_changed = 1;
-    next_target = WRAPPED_IMPL2OREF(AttN::FilterFactory, _ffactory_i);
+    targ1 = WRAPPED_IMPL2OREF(AttN::FilterFactory, _ffactory_i);
+    targ1_set = 1;
     str << "\nomniNotify: new target ==> filtfact\n";
   }
-  if (target_changed == 0) {
+  if (targ1_set == 0) {
     str << "Invalid target " << p.argv[1] << " : " <<  " must be chanfact or filtfact\n";
     success = 0;
   } else if (rest_go_targ && (RDI_STRLEN(rest_go_targ) > 0)) {
-    CORBA::Boolean target_changed2 = 0;
-    AttN::Interactive_ptr next_target2 = AttN::Interactive::_nil();
     CORBA::String_var cmdres;
     char* newcmd = CORBA_STRING_ALLOC(4 + RDI_STRLEN(rest_go_targ));
     sprintf(newcmd, "go %s", rest_go_targ);
     CORBA::Boolean docmd_prob = 0;
     try {
-      cmdres = next_target->do_command(newcmd, success, target_changed2, next_target2);
+      cmdres = targ1->do_command(newcmd, success, targ2_set, targ2);
     } CATCH_INVOKE_PROBLEM(docmd_prob);
     CORBA_STRING_FREE(newcmd);
     if (docmd_prob) {
       str << "The target " << rest_go_targ << " is not available\n";
     } else {
       str << cmdres.in();
-      if (target_changed2) {
-	next_target = next_target2; // XXX duplicate not needed ???
-      }
     }
   }
   CORBA_STRING_FREE(go_targ);
+  if (targ2_set) {
+    CORBA::release(targ1);
+    next_target = targ2;
+    target_changed = 1;
+  } else if (targ1_set) {
+    next_target = targ1;
+    target_changed = 1;
+  }
   return success;
 }
 
@@ -809,8 +860,9 @@
     _cfactory_i->cleanup_all(str, 1, 1);
   } else if ((p.argc == 2) &&
 	     RDI_STR_EQ_I(p.argv[0], "cleanup") && RDI_STR_EQ_I(p.argv[1], "all")) {
-    _ffactory_i->cleanup_all(str);
+    // cleanup channels first; may allow more filters to be destroyed
     _cfactory_i->cleanup_all(str, 1, 1);
+    _ffactory_i->cleanup_all(str);
   } else if ((p.argc == 1) && 
 	     ((RDI_STRLEN(p.argv[0]) > 1) && ((p.argv[0][0] == '+') || (p.argv[0][0] == '-'))) ) {
     success = flag_change(str, p.argv[0]);
@@ -818,7 +870,7 @@
     success = 0;
     str << "\nomniNotify: Invalid command: " << cmnd << "\n\n";
   }
-  RDIRptForceLog(_my_name << " received command: " << cmnd << "\nResult:\n" << str.buf());
+  RDIRptInteractiveLog(_my_name << " received command: " << cmnd << "\nResult:\n" << str.buf());
   // this is the only safe way to return a string?
   return CORBA_STRING_DUP(str.buf());
 }
@@ -897,6 +949,7 @@
   str.setw(25); str << RDIRptNotifQoS_nm; if (RDIRptNotifQoS) str << " true\n\t"; else str << " false\n\t";
   str.setw(25); str << RDIRptAdminQoS_nm; if (RDIRptAdminQoS) str << " true\n\t"; else str << " false\n\t";
   str.setw(25); str << RDIRptServerQoS_nm; if (RDIRptServerQoS) str << " true\n\t"; else str << " false\n\t";
+  str.setw(25); str << RDIRptInteractive_nm; if (RDIRptInteractive) str << " true\n\t"; else str << " false\n\t";
 
   str << "\nCurrent Debug Flag Values:\n\n\t";
   str.setw(25); str << RDIDbgDaemon_nm; if (RDIDbgDaemon) str << " true\n\t"; else str << " false\n\t";
@@ -1083,6 +1136,11 @@
     str << "  Report Flag " << RDIRptServerQoS_nm << " set to " << addflagstr << '\n';
     found_rpt_flag = 1;
   }
+  if (allrpt || RDI_STR_EQ(flag, RDIRptInteractive_nm)) {
+    if (addflag) RDI::AddRptFlags(RDIRptInteractiveF); else RDI::RemRptFlags(RDIRptInteractiveF);
+    str << "  Report Flag " << RDIRptInteractive_nm << " set to " << addflagstr << '\n';
+    found_rpt_flag = 1;
+  }
   // Not a legal flag?
   if ((found_dbg_flag == 0) && (found_rpt_flag == 0)) {
     str << "\nInvalid flag command: " << change << '\n';
@@ -1129,3 +1187,4 @@
 	  RDI_STR_EQ(p, "ReportAdminQoS") ||
 	  RDI_STR_EQ(p, "ReportServerQoS"));
 }
+
Index: lib/RDIOplocks.cc
===================================================================
RCS file: /cvsroot/omniNotify/lib/RDIOplocks.cc,v
retrieving revision 1.5
retrieving revision 1.5.2.1
diff -u -u -r1.5 -r1.5.2.1
--- lib/RDIOplocks.cc	2001/06/26 20:01:20	1.5
+++ lib/RDIOplocks.cc	2002/02/28 23:44:02	1.5.2.1
@@ -31,6 +31,15 @@
  
 /*
 $Log: RDIOplocks.cc,v $
+Revision 1.5.2.1  2002/02/28 23:44:02  alcfp
+merge alpha branch back into dev for latest fixes
+
+Revision 1.5.4.2  2002/02/08 22:59:12  alcfp
+oplock cleanup is now called on daemon exit
+
+Revision 1.5.4.1  2002/02/08 10:40:28  alcfp
+fixed oplock cleanup bug for deferred disposal case, also suppressed event rejection report when channel is shutting down
+
 Revision 1.5  2001/06/26 20:01:20  alcfp
 updated copyright notices, added support for omniORB4, switched default to POA
 
@@ -50,7 +59,20 @@
 
 #include "RDI.h"
 #include "RDIOplocks.h"
+#include "CosNfyUtils.h"
+
+#define RDI_100_MS_AS_NS 100000000
 
+#if 0
+#define DESCRIBE_INUSE_BUMP \
+  do { if (_owner_name) { RDIDbgForceLog("*** INUSE BUMP: " << *(_owner_name) << " inuse now " << _inuse << '\n'); } } while (0)
+#define DESCRIBE_INUSE_DEBUMP \
+  do { if (_owner_name) { RDIDbgForceLog("*** INUSE DEBUMP: " << *(_owner_name) << " inuse now " << _inuse << '\n'); } } while (0)
+#else
+#define DESCRIBE_INUSE_BUMP    do { } while(0)
+#define DESCRIBE_INUSE_DEBUMP  do { } while(0)
+#endif
+
 // ---------------------- RDIOplockEntry -------------------------------
 
 CORBA::Boolean RDIOplockEntry::acquire(RDIOplockEntry** ptr) {
@@ -82,9 +104,9 @@
     RDIDbgForceLog("** Internal error: RDIOplockEntry " << (void*)this <<
 		   " calling wait after disposed is true\n");
   }
-  if (do_bump_debump) { _inuse++; } 
+  if (do_bump_debump) { _inuse++; DESCRIBE_INUSE_BUMP; } 
   _waitvar.wait();
-  if (do_bump_debump) { _inuse--; } 
+  if (do_bump_debump) { _inuse--; DESCRIBE_INUSE_DEBUMP; } 
 }
 
 void RDIOplockEntry::timedwait(unsigned long s, unsigned long n) {
@@ -92,27 +114,27 @@
   if (_disposed) {
     do_bump_debump = 0;
     RDIDbgForceLog("** Internal error: RDIOplockEntry " << (void*)this <<
-		   " calling timedwait after disposed is true");
+		   " calling timedwait after disposed is true\n");
   }
-  if (do_bump_debump) { _inuse++; } 
+  if (do_bump_debump) { _inuse++; DESCRIBE_INUSE_BUMP; } 
   _waitvar.timedwait(s,n);
-  if (do_bump_debump) { _inuse--; } 
+  if (do_bump_debump) { _inuse--; DESCRIBE_INUSE_DEBUMP; } 
 }
 
 void RDIOplockEntry::bump() {
   if (_disposed) {
     RDIDbgForceLog("** Internal error: RDIOplockEntry " << (void*)this <<
-		   " bumping inuse after disposed is true");
+		   " bumping inuse after disposed is true\n");
   }
-  _inuse++;
+  _inuse++; DESCRIBE_INUSE_BUMP; 
 }
 
 void RDIOplockEntry::debump() {
   if (_inuse == 0) {
     RDIDbgForceLog("** Internal error: RDIOplockEntry " << (void*)this <<
-		   " debumping zero inuse -- ignored");
+		   " debumping zero inuse -- ignored\n");
   } else {
-    _inuse--;
+    _inuse--; DESCRIBE_INUSE_DEBUMP;
     if (_inuse == 0) {
       _inusezero.broadcast();
     }
@@ -154,27 +176,34 @@
 CORBA::Boolean   RDIOplocks::_shutdown = 0;
 
 // cleanup returns 1 if there are entries in use that could not be discarded, else 0
-CORBA::Boolean RDIOplocks::cleanup() {
+CORBA::ULong RDIOplocks::cleanup() {
+  CORBA::ULong res = 0;
   _oplock.lock();
   if (_freelist == 0) { 
     _oplock.unlock();
-    return 0;
+    return res;
   }
   // discard entries with ptr == 0 and inuse == 0
+  // or with disposed == 1 and inuse == 0
   RDIOplockEntry* nxt_nxt = _freelist;
   for (RDIOplockEntry* nxt = _freelist->_next; nxt != _freelist; nxt = nxt_nxt) {
     nxt_nxt = nxt->_next; 
-    if ((nxt->_ptr == 0) && (nxt->_inuse == 0)) {
+    if ((nxt->_inuse == 0) && ((nxt->_ptr == 0) || nxt->_disposed)) {
       nxt->_remove(); // removes from freelist
       delete nxt;
+    } else {
+      res++;
+      if (nxt->_disposed && nxt->_owner_name) {
+	RDIDbgForceLog("XXX_REMOVE_THIS: RDIOplocks::cleanup waiting for destroyed obj " <<
+		       *(nxt->_owner_name) << " to finish " << nxt->_inuse << " outstanding invocations\n");
+      } else if (nxt->_owner_name) {
+	RDIDbgForceLog("XXX_REMOVE_THIS: UNEXPECTED: free list has oplock of non-destroyed obj " <<
+		       *(nxt->_owner_name) << " with " << nxt->_inuse << " outstanding invocations\n");
+      }
     }
   }
-  if (_freelist->_next != _freelist) {
-    _oplock.unlock();
-    return 1;   // some entries are still in use
-  }
   _oplock.unlock();
-  return 0;
+  return res;
 }
 
 void RDIOplocks::shutdown() {
@@ -185,21 +214,22 @@
   }
   _shutdown = 1;
   _oplock.unlock();
-  while (cleanup()) {
-    // there are still entries to be cleaned up
-    omni_thread::yield(); // should put in microsec delay?
-  }
+  CORBA::ULong inuse = cleanup();
   _oplock.lock();
-  if (_freelist) {
-    delete _freelist;
+  if (inuse == 0) { // can discard freelist
+    if (_freelist) {
+      delete _freelist;
+    }
+    _freelist = 0;
+  } else { // fast shutdown requires leaving some allocated storage in freelist
+    RDIDbgForceLog("XXX_REMOVE_THIS: Leaving " << inuse << " inuse oplock entries in freelist\n");
   }
-  _freelist = 0;
   _oplock.unlock();
 }
 
-RDIOplockEntry* RDIOplocks::alloc_entry(RDIOplockEntry** optr) {
+RDIOplockEntry* RDIOplocks::alloc_entry(RDIOplockEntry** optr, AttN::NameSeq* oname) {
   if (optr == 0) {
-    RDIDbgForceLog("** Internal error: RDIOplocks::alloc_entry called with null ptr");
+    RDIDbgForceLog("** Internal error: RDIOplocks::alloc_entry called with null ptr\n");
     return 0;
   }
   _oplock.lock();
@@ -215,7 +245,7 @@
       if ((nxt->_ptr != 0) || (nxt->_inuse != 0) || (nxt->_disposed)) {
 	RDIDbgForceLog("** Internal error: RDIOplocks::alloc_entry : " <<
 		       "once ptr is zero, ptr, inuse, and disposed " <<
-		       "are supposed to remain zero until entry is reallocated");
+		       "are supposed to remain zero until entry is reallocated\n");
 	nxt->_oplock.unlock();
 	continue;
       }
@@ -224,6 +254,7 @@
       nxt->_inuse = 0;
       nxt->_disposed = 0;
       nxt->_ptr = optr;
+      nxt->_owner_name = oname;
       _oplock.unlock();
       nxt->_oplock.unlock();
       return nxt;
@@ -232,12 +263,20 @@
       nxt->_oplock.lock();
       if (!nxt->_disposed || (nxt->_inuse != 0)) {
 	RDIDbgForceLog("** Internal error: RDIOplocks::alloc_entry : " <<
-		       "once disposed is set, it is supposed to remain set " <<
-		       "and inuse is supposed to remain zero until dispose action occurs");
+		       "disposed changed from 1 to 0, or inuse from 0 to 1, unexpectedly!" <<
+		       "Once disposed is set, it is supposed to remain set " <<
+		       "and once inuse is zero, it is supposed to remain zero until dispose action occurs\n");
 	nxt->_oplock.unlock();
 	continue;
       }
       nxt->_remove(); // removes from freelist
+      if (!nxt->_ptr) {
+	RDIDbgForceLog("** Internal error: RDIOplocks::alloc_entry : " <<
+		       "ptr not set!  Once disposed is set, ptr is supposed to remain set " <<
+		       "until dispose action occurs\n");
+      } else {
+	*(nxt->_ptr) = 0; // _oplockptr of (about to be previous) owner set to zero
+      }
       if (!WRAPPED_DISPOSEINFO_IS_NIL(nxt->_dispose_info)) {
 	WRAPPED_DISPOSE_INFO(nxt->_dispose_info);
       }
@@ -245,6 +284,7 @@
       nxt->_inuse = 0;
       nxt->_disposed = 0;
       nxt->_ptr = optr;
+      nxt->_owner_name = oname;
       _oplock.unlock();
       nxt->_oplock.unlock();
       return nxt;
@@ -259,6 +299,7 @@
   nxt->_inuse = 0;
   nxt->_disposed = 0;
   nxt->_ptr = optr;
+  nxt->_owner_name = oname;
   _oplock.unlock();
   nxt->_oplock.unlock();
   return nxt;
@@ -266,27 +307,36 @@
 
 // ASSUMES: e->_oplock has been locked
 void RDIOplocks::free_entry(RDIOplockEntry* e, RDIOplockEntry** optr, WRAPPED_DISPOSEINFO_PTR dinfo) {
+  if (e->_inuse && e->_owner_name) {
+    //    RDIDbgForceLog("*** XXX_REMOVE_THIS: " << *(e->_owner_name) << " : RDIOplocks::free_entry called with e->_inuse = " << e->_inuse << '\n');
+  }
   if (e->_ptr != optr) {
-    RDIDbgForceLog("*** Internal error: RDIOplocks::free_entry called with optr != e->_ptr");
+    RDIDbgForceLog("*** Internal error: RDIOplocks::free_entry called with optr != e->_ptr\n");
+    return;
+  }
+  if (!e->_ptr) {
+    RDIDbgForceLog("*** Internal error: RDIOplocks::free_entry called with null e->_ptr\n");
     return;
   }
   if (e->_disposed) {  // it is OUR job to set e->_disposed
     RDIDbgForceLog("*** Internal error: RDIOplocks::free_entry should not be " <<
-		   "called with e->_disposed set");
+		   "called with e->_disposed set\n");
     e->_disposed = 0;
   }
   if ((e->_next != e) || (e->_prev != e)) {
     RDIDbgForceLog("*** Internal error: RDIOplocks::free_entry called with an entry " <<
-		   "that appears to already be on the free list");
+		   "that appears to already be on the free list\n");
     e->_remove();
   }
   // append e to free list (by prepending in front of dummy head elt)
   e->_prepend(_freelist);
   if (e->_inuse == 0) { // can dispose immediately
+    *(e->_ptr) = 0; // _oplockptr of owner set to zero
     if (!WRAPPED_DISPOSEINFO_IS_NIL(dinfo)) {
       WRAPPED_DISPOSE_INFO(dinfo);
     }
     e->_ptr = 0;
+    e->_owner_name = 0;
   } else { // defer disposal
     e->_disposed = 1;
     e->_dispose_info = dinfo;
Index: lib/RDIRVM.cc
===================================================================
RCS file: /cvsroot/omniNotify/lib/RDIRVM.cc,v
retrieving revision 1.30
retrieving revision 1.30.2.2
diff -u -u -r1.30 -r1.30.2.2
--- lib/RDIRVM.cc	2001/10/04 02:23:28	1.30
+++ lib/RDIRVM.cc	2002/02/28 23:44:02	1.30.2.2
@@ -31,6 +31,15 @@
  
 /*
 $Log: RDIRVM.cc,v $
+Revision 1.30.2.2  2002/02/28 23:44:02  alcfp
+merge alpha branch back into dev for latest fixes
+
+Revision 1.30.4.1  2002/02/07 18:10:56  alcfp
+merged recent dev fixes into alpha
+
+Revision 1.30.2.1  2001/10/29 19:35:50  alcfp
+fixed NDEBUG bug
+
 Revision 1.30  2001/10/04 02:23:28  alcfp
 moved local clock params into ServerQoS
 
@@ -1399,9 +1408,9 @@
   RDI_RVM_DbgLog_Op(_PC, _op[_PC], "=>BEGIN");
   RDI_RVM_Assert((_top >= 0) && (_stack[_top]._tckind == RDI_rtk_boolean), "");
   RDI_RVM_DbgLog_Top1(_stack[_top]);
-#ifndef NDEBUG
   if (_stack[_top]._v_boolean == 0) {
     long jumpto = _PC + _op[_PC]._arg._v_lbl._offset;
+#ifndef NDEBUG
     if ((jumpto < 0) || (jumpto > _ops->_opstail)) {
       if (RDIDbgTst(RDIDbgEval)) {
 	RDIDbgLogger(l, RDIDbgEval_nm);
Index: lib/RDIRVMPool.cc
===================================================================
RCS file: /cvsroot/omniNotify/lib/RDIRVMPool.cc,v
retrieving revision 1.3
retrieving revision 1.3.2.1
diff -u -u -r1.3 -r1.3.2.1
--- lib/RDIRVMPool.cc	2001/08/03 17:54:19	1.3
+++ lib/RDIRVMPool.cc	2002/02/28 23:44:03	1.3.2.1
@@ -30,6 +30,12 @@
  
 /*
 $Log: RDIRVMPool.cc,v $
+Revision 1.3.2.1  2002/02/28 23:44:03  alcfp
+merge alpha branch back into dev for latest fixes
+
+Revision 1.3.4.1  2002/02/10 03:55:34  alcfp
+removed RVMPool
+
 Revision 1.3  2001/08/03 17:54:19  alcfp
 added support for AttNotification
 
@@ -40,23 +46,9 @@
 added RDIRVMPool
 
 */
-
-#include "RDI.h"
-#include "RDIRVMPool.h"
-#include "RDIUtil.h"
-
-// static members
-RDI_Hash<int, RDI_RVM*> RDI_RVMPool::_rvms(RDI_SIntHash, RDI_SIntRank);
-
-RDI_RVM* RDI_RVMPool::get_rvm() {
-  RDI_RVM* res = 0;
-  int i = omni_thread::self()->id();
-  if (_rvms.lookup(i, res)) { // found it
-    return res;
-  }
-  res = new RDI_RVM();
-  RDI_AssertAllocThrowNo(res, "Memory allocation failed - RDI_RVM object");
-  _rvms.insert(i, res);
-  return res;
-}
 
+////////////////////////////
+//                        //
+// ** NO LONGER NEEDED ** //
+//                        //
+////////////////////////////
Index: lib/dir.mk
===================================================================
RCS file: /cvsroot/omniNotify/lib/dir.mk,v
retrieving revision 1.31
retrieving revision 1.31.2.1
diff -u -u -r1.31 -r1.31.2.1
--- lib/dir.mk	2001/10/05 20:57:33	1.31
+++ lib/dir.mk	2002/02/28 23:44:03	1.31.2.1
@@ -2,6 +2,8 @@
 include libdefs.mk
 include ../trilib.mk
 
+MDFLAGS += -p static/ -p shared/
+
 DIR_CPPFLAGS += $(COS_CPPFLAGS)
 
 ifeq ($(platform),sun4_sosV_5.5)
@@ -37,7 +39,7 @@
 
 # export .h files useful for writing omniNotify daemon / omniNotify client programs
 # to <omni_top>/src/services/include/omniNotify
-export_useful:: ../include/CosNotifyShorthands.h ../include/RDIStringDefs.h ../include/RDIstrstream.h ../include/RDIOSWrappers.h ../include/corba_wrappers.h ../include/corba_wrappers_impl.h ../include/omniorb_boa_wrappers.h ../include/omniorb_poa_wrappers.h ../include/omniorb_boa_wrappers_impl.h ../include/omniorb_poa_wrappers_impl.h
+export_useful:: ../include/CosNotifyShorthands.h ../include/RDIStringDefs.h ../include/RDIstrstream.h ../include/RDIOSWrappers.h ../include/RDIInteractiveMode.h ../include/corba_wrappers.h ../include/corba_wrappers_impl.h ../include/omniorb_boa_wrappers.h ../include/omniorb_poa_wrappers.h ../include/omniorb_boa_wrappers_impl.h ../include/omniorb_poa_wrappers_impl.h
 	@(for i in $^; do \
             file="$$i"; \
             dir="$(EXPORT_TREE)/src/services/include/omniNotify"; \
Index: lib/omniNotify.cc
===================================================================
RCS file: /cvsroot/omniNotify/lib/omniNotify.cc,v
retrieving revision 1.15
retrieving revision 1.15.2.1
diff -u -u -r1.15 -r1.15.2.1
--- lib/omniNotify.cc	2001/10/02 14:07:53	1.15
+++ lib/omniNotify.cc	2002/02/28 23:44:03	1.15.2.1
@@ -31,6 +31,12 @@
  
 /*
 $Log: omniNotify.cc,v $
+Revision 1.15.2.1  2002/02/28 23:44:03  alcfp
+merge alpha branch back into dev for latest fixes
+
+Revision 1.15.4.1  2002/02/26 22:28:44  alcfp
+added ReportInteractive flag - controls whether results of interactive cmds are output to report log, also added wait_for_destroy support, fixed server destroy so it causes main notifd thread to terminate
+
 Revision 1.15  2001/10/02 14:07:53  alcfp
 improved error messages for command line errors
 
@@ -94,3 +100,6 @@
   return RDI::get_server();
 };
 
+void omniNotify::wait_for_destroy() {
+  RDI::wait_for_destroy();
+};
