  
#include "ace/Acceptor.h"
#include "ace/SOCK_Acceptor.h"
#include "ace/Reactor.h"
#include "ace/Thread.h"


ACE_Reactor * g_reactor;

static sig_atomic_t finished = 0;
	
class Logging_Handler;

extern "C" void handler (int) { finished = 1; }



class Reactor_Derived : public ACE_Reactor
{	

public :
	Reactor_Derived() : ()
	{
		counter = 0;
	}
	
	virtual ~Reactor_Derived()
	{
		cout << "*****Calling the reactor destructor*****" << endl;
	}

private :
	friend class Logging_Handler;
	
	// counter is used to keep track of the number of service handlers
	// registered with this reactor (Surely theres a better way ;-)
	int counter;
};

class Logging_Handler : public ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH>
{

public:

  Logging_Handler (void) { };

   virtual void destroy (void)
	{ 
          if (this->thread_reactorP->remove_handler(this,
		ACE_Event_Handler::READ_MASK | ACE_Event_Handler::DONT_CALL) == -1
	  )
  	        ACE_ERROR_RETURN ((LM_ERROR, "can'(%P|%t) t remove service from reactor\n"), -1);

	  // Decrement the handler tracking variable in the reactor to
	  // indicate this service handler has terminated
	  --thread_reactorP->counter;

	  this->peer ().close ();
	  delete this;
	}

  static void *run_thread(Logging_Handler *this_)
  	{
	  Reactor_Derived thread_reactor;     

	  this_->thread_reactorP = &thread_reactor;
	  
	  // Increment our handler counter to account for this service handler
	  ++thread_reactor.counter;

	  if (thread_reactor.register_handler(this_, ACE_Event_Handler::READ_MASK) == -1)
		  ACE_ERROR_RETURN ((LM_ERROR,"can'(%P|%t) t register with reactor\n"), -1);
	
	  while( thread_reactor.counter > 0 )
	  {
	        // If thread_reactor.counter = 0 then we have no more service
		// handlers connected to the reactor. We set a timeout value
		// of 1 second so that the handle_events loop break out every
		// second to check on the count ( because of it blocking 
		// even when there are no connections we need to do this)
		thread_reactor.handle_events(ACE_Time_Value(1,0));
	  }
	} 

 virtual int open (void *)
	{
          ACE_Thread::spawn(&Logging_Handler::run_thread,this);
	  return 0;
	}

  virtual int close (u_long)
	{
	  this->destroy ();
	  return 0;
	}

protected:

  virtual int handle_input (ACE_HANDLE)
        {
          char buf[128];
          memset(buf,0,sizeof(buf));

          switch( this->peer().recv(buf,sizeof buf) )
          {
          case -1:
            ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) %p bad read\n", "client logger"), -1);
          case 0:
            ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) closing log daemon (fd = %d)\n", this->get_handle ()), -1);
          default:
	    ACE_DEBUG ((LM_DEBUG, "(%p|%t) from client : %s",buf));
        }
          
          return 0;
        }


private:
  Reactor_Derived *thread_reactorP; 
};


typedef ACE_Acceptor <Logging_Handler, ACE_SOCK_ACCEPTOR> Logging_Acceptor;


static const u_short PORT = ACE_DEFAULT_SERVER_PORT;

int main (int argc, char *argv[])
{
  g_reactor = new ACE_Reactor;

  // Acceptor factory.
  Logging_Acceptor peer_acceptor;

  if (peer_acceptor.open (ACE_INET_Addr (PORT)) == -1)
    ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "open"), -1);

  else if (g_reactor->register_handler (&peer_acceptor, ACE_Event_Handler::READ_MASK) == -1)
    ACE_ERROR_RETURN ((LM_ERROR, "registering service with ACE_Reactor\n"), -1);

  ACE_Sig_Action sa ((ACE_SignalHandler) handler, SIGINT);

  // Run forever, performing logging service.

  ACE_DEBUG ((LM_DEBUG, "(%P|%t) starting up server logging daemon\n"));

  // Perform logging service until QUIT_HANDLER receives SIGINT.
  while ( !finished )
    g_reactor->handle_events ();

  ACE_DEBUG ((LM_DEBUG, "(%P|%t) shutting down server logging daemon\n"));

  return 0;
}
