// -*- C++ -*-
// $Id: Keyed_Test_Receiver_exec.cpp 92902 2010-12-17 15:09:42Z mcorino $

/**
 * Code generated by the The ACE ORB (TAO) IDL Compiler v1.8.3
 * TAO and the TAO IDL Compiler have been developed by:
 *       Center for Distributed Object Computing
 *       Washington University
 *       St. Louis, MO
 *       USA
 *       http://www.cs.wustl.edu/~schmidt/doc-center.html
 * and
 *       Distributed Object Computing Laboratory
 *       University of California at Irvine
 *       Irvine, CA
 *       USA
 * and
 *       Institute for Software Integrated Systems
 *       Vanderbilt University
 *       Nashville, TN
 *       USA
 *       http://www.isis.vanderbilt.edu/
 *
 * Information about TAO is available at:
 *     http://www.cs.wustl.edu/~schmidt/TAO.html
 **/

#include "Keyed_Test_Receiver_exec.h"
#include "tao/ORB_Core.h"
#include "ace/Reactor.h"
#include "ace/OS_NS_time.h"
#include "dds4ccm/impl/TimeUtilities.h"
#include "dds4ccm/impl/Utils.h"

namespace CIAO_Keyed_Test_Receiver_Impl
{
  /**
   * Read action generator
   */

  read_action_Generator::read_action_Generator (Receiver_exec_i &callback)
    : pulse_callback_ (callback)
  {
  }

  read_action_Generator::~read_action_Generator ()
  {
  }

  int
  read_action_Generator::handle_timeout (const ACE_Time_Value &, const void *)
  {
    this->pulse_callback_.read ();
    return 0;
  }

  /**
   * Facet Executor Implementation Class: info_out_status_exec_i
   */

  info_out_status_exec_i::info_out_status_exec_i (
        ::Keyed_Test::CCM_Receiver_Context_ptr ctx)
    : ciao_context_ (
        ::Keyed_Test::CCM_Receiver_Context::_duplicate (ctx))
  {
  }

  info_out_status_exec_i::~info_out_status_exec_i (void)
  {
  }

  // Operations from ::CCM_DDS::PortStatusListener

  void
  info_out_status_exec_i::on_requested_deadline_missed (::DDS::DataReader_ptr /* the_reader */,
  const ::DDS::RequestedDeadlineMissedStatus & /* status */)
  {
    /* Your code here. */
  }

  void
  info_out_status_exec_i::on_sample_lost (::DDS::DataReader_ptr /* the_reader */,
  const ::DDS::SampleLostStatus & /* status */)
  {
    /* Your code here. */
  }

  /**
   * Component Executor Implementation Class: Receiver_exec_i
   */

  Receiver_exec_i::Receiver_exec_i (void)
    : rate_ (1)
      , iterations_ (10)
      , keys_ (5)
      , expected_ (50)
  {
    ACE_NEW_THROW_EX (this->ticker_,
                      read_action_Generator (*this),
                      ::CORBA::NO_MEMORY ());
  }

  Receiver_exec_i::~Receiver_exec_i (void)
  {
    delete this->ticker_;
  }

  // Supported operations and attributes.
  ACE_Reactor*
  Receiver_exec_i::reactor (void)
  {
    ACE_Reactor* reactor = 0;
    ::CORBA::Object_var ccm_object =
      this->ciao_context_->get_CCM_object();
    if (! ::CORBA::is_nil (ccm_object.in ()))
      {
        ::CORBA::ORB_var orb = ccm_object->_get_orb ();
        if (! ::CORBA::is_nil (orb.in ()))
          {
            reactor = orb->orb_core ()->reactor ();
          }
      }
    if (reactor == 0)
      {
        throw ::CORBA::INTERNAL ();
      }
    return reactor;
  }

  void
  Receiver_exec_i::check_received_samples ()
  {
    bool all_received = true;
    for (Last_Iteration_Table::iterator iter = this->last_iters_.begin ();
         iter != this->last_iters_.end () && all_received;
         ++iter)
      {
        all_received = iter->second == this->iterations_;
        if (iter->second > this->iterations_)
          {
            all_received = true;
            ACE_ERROR ((LM_ERROR, "Receiver_exec_i::check_received_samples - "
                       "ERROR: Unexpected iteration received-> Bailing out\n"));
          }
      }
    if (all_received)
      {
        ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("All samples received. Stop the timer\n")));
        this->reactor ()->cancel_timer (this->ticker_);
      }
  }

  void
  Receiver_exec_i::read (void)
  {
    ::KeyedTestConnector::Reader_var reader =
      this->ciao_context_->get_connection_info_out_data();

    if (::CORBA::is_nil (reader.in ()))
      {
        return;
      }
    try
      {
        for (CORBA::UShort i = 1; i < this->keys_ + 1; ++i)
          {
            KeyedTest keyedtest_info;
            char key[10];
            ACE_OS::sprintf (key, "KEY_%d", i);
            keyedtest_info.key = CORBA::string_dup (key);
            ::CCM_DDS::ReadInfo readinfo;
            reader->read_one_last (keyedtest_info, readinfo, ::DDS::HANDLE_NIL);

            ACE_Time_Value tv;
            tv <<= readinfo.source_timestamp;
            ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("READ_ONE Read_Info ")
                                  ACE_TEXT (" -> date =%#T\n"),
                                  &tv));

            ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("READ ONE keyed test info : ")
                ACE_TEXT ("received keyedtest_info for <%C> at %u\n"),
                keyedtest_info.key.in (),
                keyedtest_info.iteration));
            this->last_iters_[key] = keyedtest_info.iteration;
            check_received_samples ();
          }
      }
    catch(const CCM_DDS::InternalError& ex)
      {
        ACE_ERROR ((LM_ERROR, ACE_TEXT ("ERROR: KeyedTest_Read: ")
                  ACE_TEXT ("Unexpected InternalError exception received <%C>\n"),
                  ::CIAO::DDS4CCM::translate_retcode (ex.error_code)));
      }
    catch(const CCM_DDS::NonExistent& )
      {
        ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("KeyedTest_Read: ")
                  ACE_TEXT ("Expected NonExistent received\n")));
      }
  }

  // Component attributes and port operations.

  ::CCM_DDS::CCM_PortStatusListener_ptr
  Receiver_exec_i::get_info_out_status (void)
  {
    if ( ::CORBA::is_nil (this->ciao_info_out_status_.in ()))
      {
        info_out_status_exec_i *tmp = 0;
        ACE_NEW_RETURN (
          tmp,
          info_out_status_exec_i (
            this->ciao_context_.in ()),
            ::CCM_DDS::CCM_PortStatusListener::_nil ());

          this->ciao_info_out_status_ = tmp;
      }

    return
      ::CCM_DDS::CCM_PortStatusListener::_duplicate (
        this->ciao_info_out_status_.in ());
  }

  ::CORBA::ULong
  Receiver_exec_i::rate (void)
  {
    return this->rate_;
  }

  void
  Receiver_exec_i::rate (
    const ::CORBA::ULong rate)
  {
    this->rate_ = rate;
  }

  ::CORBA::UShort
  Receiver_exec_i::iterations (void)
  {
    return this->iterations_;
  }

  void
  Receiver_exec_i::iterations (
    const ::CORBA::UShort iterations)
  {
    this->iterations_ = iterations;
    this->expected_ = this->iterations_ * this->keys_;
  }

  ::CORBA::UShort
  Receiver_exec_i::keys (void)
  {
    return this->keys_;
  }

  void
  Receiver_exec_i::keys (
    const ::CORBA::UShort keys)
  {
    this->keys_ = keys;
    this->expected_ = this->iterations_ * this->keys_;
  }

  // Operations from Components::SessionComponent.

  void
  Receiver_exec_i::set_session_context (
    ::Components::SessionContext_ptr ctx)
  {
    this->ciao_context_ =
      ::Keyed_Test::CCM_Receiver_Context::_narrow (ctx);

    if ( ::CORBA::is_nil (this->ciao_context_.in ()))
      {
        throw ::CORBA::INTERNAL ();
      }
  }

  void
  Receiver_exec_i::configuration_complete (void)
  {
    /* Your code here. */
  }

  void
  Receiver_exec_i::ccm_activate (void)
  {
    long const usec = 1000000 / this->rate_;
    if (this->reactor ()->schedule_timer (this->ticker_,
                                          0,
                                          ACE_Time_Value(0, usec),
                                          ACE_Time_Value(0, usec)) == -1)
      {
        ACE_ERROR ((LM_ERROR, "Unable to schedule Timer\n"));
      }
  }

  void
  Receiver_exec_i::ccm_passivate (void)
  {
    this->reactor ()->cancel_timer (this->ticker_);
  }

  void
  Receiver_exec_i::ccm_remove (void)
  {
    CORBA::UShort received_ = 0;
    for (Last_Iteration_Table::iterator iter = this->last_iters_.begin ();
         iter != this->last_iters_.end ();
         ++iter)
      {
        ACE_DEBUG ((LM_INFO, "Receiver_exec_i summary for <%C>: last sample <%u> - expected <%u>\n",
                      iter->first.c_str(),
                      iter->second,
                      this->iterations_));
        received_ += iter->second;
      }

    if (received_ < this->expected_)
      {
        ACE_ERROR ((LM_ERROR, "ERROR : Expected to receive %u samples, actually got %u\n",
            this->expected_, received_));
      }
  }

  extern "C" RECEIVER_EXEC_Export ::Components::EnterpriseComponent_ptr
  create_Keyed_Test_Receiver_Impl (void)
  {
    ::Components::EnterpriseComponent_ptr retval =
      ::Components::EnterpriseComponent::_nil ();

    ACE_NEW_NORETURN (
      retval,
      Receiver_exec_i);

    return retval;
  }
}
