// -*- Mode: C++; -*-
//                              File      : CosEventChannelAdmin_i.h
//                              Package   : omniNotify-Library
//                              Created on: 1-Jan-1998
//                              Authors   : gruber&panagos
//
//    Copyright (C) 1998-2001 AT&T Laboratories -- Research
//
//    This file is part of the omniNotify library
//    and is distributed with the omniNotify release.
//
//    The omniNotify library is free software; you can redistribute it and/or
//    modify it under the terms of the GNU Library General Public
//    License as published by the Free Software Foundation; either
//    version 2 of the License, or (at your option) any later version.
//
//    This library is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//    Library General Public License for more details.
//
//    You should have received a copy of the GNU Library General Public
//    License along with this library; if not, write to the Free
//    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
//    02111-1307, USA
//
//
// Description:
//     set of C++ definitions for the CosEventChanneAdmin module
//
 
/*
$Log: CosEventChannelAdmin_i.h,v $
Revision 1.25  2001/09/19 21:10:01  alcfp
Added cleanup support to interactive api

Revision 1.24  2001/08/03 17:54:13  alcfp
added support for AttNotification

Revision 1.23  2001/06/26 20:01:03  alcfp
updated copyright notices, added support for omniORB4, switched default to POA

Revision 1.22  2001/06/22 07:00:21  alcfp
moved to new logging scheme

Revision 1.21  2001/06/12 17:33:34  alcfp
minor cleanup

Revision 1.20  2001/05/07 16:11:36  alcfp
A few changes:
+ Added support for OrderPolicy and DiscardPolicy
+ Took some initial steps towards new time value handling approach
+ Took some initial steps towards a new logging approach

Revision 1.19  2000/11/15 21:18:17  alcfp
large number of changes to switch to use of RDIOplocks for safe object disposal support.  also reduced code duplication a little, and tried hard to make all the proxy code consistent

Revision 1.18  2000/11/05 04:48:07  alcfp
changed in defaults, env variable overrride, try_pull variants

Revision 1.17  2000/10/30 04:39:02  alcfp
extensive changes in preparation for 1.1 release.  will add notes about changes to update.log

Revision 1.16  2000/10/01 13:29:09  alcfp
Removed sleep() calls used for synchronization with unbound threads. Counters and flags are used instead

Revision 1.15.2.1  2000/09/30 15:39:50  alcfp
Removed sleep() calls used for synchronization with unbound threads. Counters and flags are used instead

Revision 1.15  2000/08/22 18:23:47  alcfp
added description to each file

Revision 1.14  2000/08/16 20:18:54  alcfp
Added licensing notice to each .h and .cc file where library files get GLPL notice and daemon file gets GPL notice -- examples do not claim any license but point out that the library and daemon code does have a license notice

*/
 
#ifndef _COS_EVENT_CHANNEL_ADMIN_I_H_
#define _COS_EVENT_CHANNEL_ADMIN_I_H_

#include "corba_wrappers.h"
#include "RDIstrstream.h"
#include "RDIOplocks.h"
#include "RDIEvent.h"
#include "RDIChannelUtil.h"
#include "CosNotifyShorthands.h"

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= //
// While the Notification Service can be used to offer the functionality //
// of the Event Service,  we need to implement the Proxy objects for the //
// Event Service in order to have full backward compatibility.           //
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= //

class EventProxyPushConsumer_i : 
	WRAPPED_SKELETON_SUPER(AttNotification, CosEvProxyPushConsumer) {
  friend class SupplierAdmin_i;
public:
  EventProxyPushConsumer_i(SupplierAdmin_i* admin, EventChannel_i* channel,
			   const CosNA::ProxyID& prxID);

  // Methods from AttNotification::Interactive Interface
  char* do_command(const char* cmd, CORBA::Boolean& success, CORBA::Boolean& target_changed,
		   AttN_Interactive_outarg next_target  WRAPPED_DECLARG);
  AttN::NameSeq* child_names( WRAPPED_DECLARG_VOID );
  AttN::NameSeq* my_name( WRAPPED_DECLARG_VOID );
  AttN::IactSeq* children(CORBA::Boolean only_cleanup_candidates);
  CORBA::Boolean safe_cleanup();

  // Methods from CosEvC::PushConsumer Interface
  void push(const CORBA::Any& data  WRAPPED_DECLARG );
  void disconnect_push_consumer( WRAPPED_DECLARG_VOID );

  // Methods from CosEvCA::ProxyPushConsumer Interface
  void connect_push_supplier(CosEvC::PushSupplier_ptr supplier  
			     WRAPPED_DECLARG );

  // (Local only -- not available via RPC)
  void disconnect_client_and_dispose(CORBA::Boolean remove_proxy_from_admin = 0);

  RDIstrstream& log_output(RDIstrstream& str) const;

  // Local-only static functions
  static void out_commands(RDIstrstream& str);

  const AttN::NameSeq& L_my_name() { return _my_name; }

private:
  RDIOplockEntry*                _oplockptr;
  AttN::NameSeq                  _my_name;
  EventChannel_i*                _channel;
  SupplierAdmin_i*               _myadmin;
  CORBA::ULong                   _nevents;
  RDI_ProxyState                 _pxstate;
  CosNA::ProxyID                 _pserial;
  CosEvC::PushSupplier_var       _supplier;

  // The real implementation (called after acquiring oplock):
  void _disconnect_client_and_dispose(CORBA::Boolean remove_proxy_from_admin = 0);

  virtual ~EventProxyPushConsumer_i();
};

class EventProxyPullConsumer_i : 
	public virtual RDIProxyPullConsumer, 
	WRAPPED_SKELETON_SUPER(AttNotification, CosEvProxyPullConsumer) {
  friend class SupplierAdmin_i;
public:
  EventProxyPullConsumer_i(SupplierAdmin_i* admin, EventChannel_i* channel,
			   const CosNA::ProxyID& prxID);

  // Methods from AttNotification::Interactive Interface
  char* do_command(const char* cmd, CORBA::Boolean& success, CORBA::Boolean& target_changed,
		   AttN_Interactive_outarg next_target  WRAPPED_DECLARG);
  AttN::NameSeq* child_names( WRAPPED_DECLARG_VOID );
  AttN::NameSeq* my_name( WRAPPED_DECLARG_VOID );
  AttN::IactSeq* children(CORBA::Boolean only_cleanup_candidates);
  CORBA::Boolean safe_cleanup();

  // Methods from CosEvC::PullConsumer Interface
  void disconnect_pull_consumer( WRAPPED_DECLARG_VOID );

  // Methods from CosEvCA::ProxyPullConsumer Interface
  void connect_pull_supplier(CosEvC::PullSupplier_ptr supplier
			     WRAPPED_DECLARG );

  // (Local only -- not available via RPC)
  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);

  RDIstrstream& log_output(RDIstrstream& str) const;

  // Local-only static functions
  static void out_commands(RDIstrstream& str);

  const AttN::NameSeq& L_my_name() { return _my_name; }

private:
  RDIOplockEntry*                 _oplockptr;
  AttN::NameSeq                   _my_name;
  EventChannel_i*                 _channel;
  SupplierAdmin_i*                _myadmin;
  omni_thread*                    _pworker;
  CORBA::Boolean                  _thrdone; // true when worker thread exits
  CORBA::ULong                    _nevents;
  RDI_ProxyState                  _pxstate;
  CosNA::ProxyID                  _pserial;
  CosEvC::PullSupplier_var        _supplier;

  // absolute time of next timeout
  unsigned long                   _timeout_s;
  unsigned long                   _timeout_n;

  void _pull();

  // The real implementation (called after acquiring oplock):
  void _disconnect_client_and_dispose(CORBA::Boolean remove_proxy_from_admin = 0);

  virtual ~EventProxyPullConsumer_i();
};

class EventProxyPushSupplier_i : 
	public virtual RDIProxyPushSupplier, 
	WRAPPED_SKELETON_SUPER(AttNotification, CosEvProxyPushSupplier) {
  friend class ConsumerAdmin_i;
public:
  EventProxyPushSupplier_i(ConsumerAdmin_i* admin, EventChannel_i* channel,
			   const CosNA::ProxyID& prxID);

  // Methods from AttNotification::Interactive Interface
  char* do_command(const char* cmd, CORBA::Boolean& success, CORBA::Boolean& target_changed,
		   AttN_Interactive_outarg next_target  WRAPPED_DECLARG);
  AttN::NameSeq* child_names( WRAPPED_DECLARG_VOID );
  AttN::NameSeq* my_name( WRAPPED_DECLARG_VOID );
  AttN::IactSeq* children(CORBA::Boolean only_cleanup_candidates);
  CORBA::Boolean safe_cleanup();

  // Methods from CosEvCA::ProxyPushSupplier Interface
  void connect_push_consumer(CosEvC::PushConsumer_ptr consumer
			     WRAPPED_DECLARG );

  // Methods from CosEvC::PushSupplier Interface
  void disconnect_push_supplier( WRAPPED_DECLARG_VOID );

  // (Local only -- not available via RPC)
  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);
  virtual CORBA::Boolean has_events(unsigned long*, unsigned long*) { return _cnfqueue.length() ? 1 : 0; }

  RDIstrstream& log_output(RDIstrstream& str) const;

  // Local-only static functions
  static void out_commands(RDIstrstream& str);

  const AttN::NameSeq& L_my_name() { return _my_name; }

private:
  RDIOplockEntry*                 _oplockptr;
  AttN::NameSeq                   _my_name;
  EventChannel_i*                 _channel;
  ConsumerAdmin_i*                _myadmin;
  omni_thread*                    _pworker;
  CORBA::Boolean                  _thrdone;	// true when worker thread exits
  CORBA::ULong                    _nevents;
  RDI_ProxyState                  _pxstate;
  CosNA::ProxyID                  _pserial;
  CosEvC::PushConsumer_var        _consumer;
  RDI_List<RDI_StructuredEvent *> _cnfqueue;

  void _push();

  // The real implementation (called after acquiring oplock):
  void _disconnect_client_and_dispose(CORBA::Boolean remove_proxy_from_admin = 0);

  virtual ~EventProxyPushSupplier_i();
};

class EventProxyPullSupplier_i : 
	WRAPPED_SKELETON_SUPER(AttNotification, CosEvProxyPullSupplier) {
  friend class ConsumerAdmin_i;
public:
  EventProxyPullSupplier_i(ConsumerAdmin_i* admin, EventChannel_i* channel,
			   const CosNA::ProxyID& prxID);

  // Methods from AttNotification::Interactive Interface
  char* do_command(const char* cmd, CORBA::Boolean& success, CORBA::Boolean& target_changed,
		   AttN_Interactive_outarg next_target  WRAPPED_DECLARG);
  AttN::NameSeq* child_names( WRAPPED_DECLARG_VOID );
  AttN::NameSeq* my_name( WRAPPED_DECLARG_VOID );
  AttN::IactSeq* children(CORBA::Boolean only_cleanup_candidates);
  CORBA::Boolean safe_cleanup();

  // Methods from CosEvCA::ProxyPullSupplier
  void  connect_pull_consumer(CosEvC::PullConsumer_ptr consumer
			      WRAPPED_DECLARG );

  // Methods from CosEvC::PullSupplier
  CORBA::Any* pull( WRAPPED_DECLARG_VOID );
  CORBA::Any* try_pull(CORBA::Boolean& has_event WRAPPED_DECLARG );
  void        disconnect_pull_supplier( WRAPPED_DECLARG_VOID );

  // (Local only -- not available via RPC)
  void add_event(RDI_StructuredEvent* event);
  void disconnect_client_and_dispose(CORBA::Boolean remove_proxy_from_admin = 0);

  RDIstrstream& log_output(RDIstrstream& str) const;

  // Local-only static functions
  static void out_commands(RDIstrstream& str);

  const AttN::NameSeq& L_my_name() { return _my_name; }

private:
  RDIOplockEntry*                 _oplockptr;
  AttN::NameSeq                   _my_name;
  EventChannel_i*                 _channel;
  ConsumerAdmin_i*                _myadmin;
  CORBA::ULong                    _nevents;
  RDI_ProxyState                  _pxstate;
  CosNA::ProxyID                  _pserial;
  CosEvC::PullConsumer_var        _consumer;
  RDI_List<RDI_StructuredEvent *> _cnfqueue;

  // The real implementation (called after acquiring oplock):
  void _disconnect_client_and_dispose(CORBA::Boolean remove_proxy_from_admin = 0);

  virtual ~EventProxyPullSupplier_i();
};

////////////////////////////////////////
// Logging

inline RDIstrstream& operator<< (RDIstrstream& str, const EventProxyPushConsumer_i& prx) { return prx.log_output(str); }
inline RDIstrstream& operator<< (RDIstrstream& str, const EventProxyPullConsumer_i& prx) { return prx.log_output(str); }
inline RDIstrstream& operator<< (RDIstrstream& str, const EventProxyPushSupplier_i& prx) { return prx.log_output(str); }
inline RDIstrstream& operator<< (RDIstrstream& str, const EventProxyPullSupplier_i& prx) { return prx.log_output(str); }

#endif
