Exemple #1
0
int UdpTransport::setup_read_socket(void)
{
  if(BasicASIOTransport::setup_read_socket() < 0)
  {
    return -1;
  }

  try
  {
    socket_.non_blocking(true);

    socket_.bind(udp::endpoint(ip::address_v4::any(), addresses_[0].port()));

    madara_logger_log(context_.get_logger(), logger::LOG_MAJOR,
        "UdpTransport::setup_read_socket:"
        " Bound to port: %d\n",
        (int)addresses_[0].port());
  }
  catch (const boost::system::system_error& e)
  {
    madara_logger_log(context_.get_logger(), logger::LOG_MAJOR,
        "UdpTransport::setup:"
        " Error setting up read socket: %s\n",
        e.what());

    this->invalidate_transport();
    return -1;
  }

  return 0;
}
Exemple #2
0
long UdpTransport::receive_buffer(
    char* buf, size_t & bytes_read, udp::endpoint& remote)
{
  boost::system::error_code err;
  bytes_read = socket_.receive_from(
      asio::buffer((void*)buf, settings_.queue_length), remote,
      udp::socket::message_flags{}, err);

  if (err == asio::error::would_block || bytes_read == 0)
  {
    madara_logger_log(context_.get_logger(), logger::LOG_MINOR,
        "UdpTransport::receive_buffer: "
        " no bytes to read. Proceeding to next wait\n");

    return 1;
  }
  else if (err)
  {
    madara_logger_log(context_.get_logger(), logger::LOG_MINOR,
        "UdpTransport::receive_buffer: unexpected error: %s. "
        "Proceeding to next wait\n",
        err.message().c_str());

    return 2;
  }

  return 0;
}
int BasicASIOTransport::setup_read_threads()
{
  if (!settings_.no_receiving)
  {
    double hertz = settings_.read_thread_hertz;
    if (hertz < 0.0)
    {
      // we need to maintain backwards compatibility
      // people should be capable of bursting reads especially
      hertz = 0.0;
    }

    madara_logger_log(context_.get_logger(), logger::LOG_MAJOR,
        "BasicASIOTransport::setup:"
        " starting %d threads at %f hertz\n",
        settings_.read_threads, hertz);

    for (uint32_t i = 0; i < settings_.read_threads; ++i)
    {
      std::stringstream thread_name;
      thread_name << "read";
      thread_name << i;

      madara_logger_log(context_.get_logger(), logger::LOG_MAJOR,
          "BasicASIOTransport::setup:"
          " starting thread %s at %f hertz\n",
          thread_name.str().c_str(), hertz);
      setup_read_thread(hertz, thread_name.str());
    }
  }

  return 0;
}
Exemple #4
0
void
madara::transport::UdpRegistryClientReadThread::init (
  knowledge::KnowledgeBase & knowledge)
{
  context_ = &(knowledge.get_context ());

  // setup the receive buffer
  if (settings_.queue_length > 0)
    buffer_ = new char [settings_.queue_length];

  if (context_)
  {
    // check for an on_data_received ruleset
    if (settings_.on_data_received_logic.length () != 0)
    {
      
#ifndef _MADARA_NO_KARL_
      madara_logger_log (context_->get_logger (), logger::LOG_MAJOR,
        "UdpRegistryClientReadThread::init:" \
        " setting rules to %s\n",
        settings_.on_data_received_logic.c_str ());

      madara::expression::Interpreter interpreter;
      on_data_received_ = context_->compile (settings_.on_data_received_logic);
#endif // _MADARA_NO_KARL_
    }
    else
    {
      madara_logger_log (context_->get_logger (), logger::LOG_MINOR,
        "UdpRegistryClientReadThread::init:" \
        " no permanent rules were set\n");
    }
  }
}
Exemple #5
0
bool
madara::knowledge::containers::IntegerVector::is_true (void) const
{
  bool result (false);

  madara_logger_log (context_->get_logger (), logger::LOG_MAJOR,
    "IntegerVector::is_true: Checking for truth\n");

  if (context_)
  {
    ContextGuard context_guard (*context_);
    MADARA_GUARD_TYPE guard (mutex_);

    result = true;

    madara_logger_log (context_->get_logger (), logger::LOG_MINOR,
      "IntegerVector::is_true: context was not null. Result changed to %d\n",
      (int)result);

    for (size_t index = 0; index < vector_.size (); ++index)
    {

      madara_logger_log (context_->get_logger (), logger::LOG_DETAILED,
        "IntegerVector::is_true: checking index %d, is_false of %d. \n",
        (int)result, (int)context_->get (vector_[index]).is_false ());

      if (context_->get (vector_[index]).is_false ())
      {
        madara_logger_log (context_->get_logger (), logger::LOG_MAJOR,
          "IntegerVector::is_true: result is false, breaking\n");

        result = false;
        break;
      }
    }

    if (vector_.size () == 0)
      result = false;
  }

  madara_logger_log (context_->get_logger (), logger::LOG_MAJOR,
    "IntegerVector::is_true: final result is %d\n", (int)result);

  return result;
}
Exemple #6
0
int UdpTransport::setup_read_thread(double hertz, const std::string& name)
{
  madara_logger_log(context_.get_logger(), logger::LOG_MAJOR,
      "UdpTransport::setup_read_thread:"
      " Starting UdpTransport read thread: %s\n",
      name.c_str());
  read_threads_.run(hertz, name, new UdpTransportReadThread(*this));

  return 0;
}
Exemple #7
0
/**
 * Checks if the value in the record is not false (0)
 * @return  true if value is not false
 **/
bool madara::knowledge::containers::FlexMap::is_true(void) const
{
  ContextGuard context_guard(*context_);
  bool result(false);

  KnowledgeUpdateSettings keep_local(true);

  madara_logger_log(context_->get_logger(), logger::LOG_MAJOR,
      "Vector::is_true: checking for non-zero value\n");

  if (variable_.is_valid())
  {
    result = context_->get(variable_, keep_local).is_true();
  }

  madara_logger_log(context_->get_logger(), logger::LOG_MAJOR,
      "FlexMap::is_true: final result is %d\n", (int)result);

  return result;
}
int madara::transport::SpliceDDSTransport::check_status(
    DDS::ReturnCode_t status, const char* info)
{
  // if the status is okay, then return without issue
  if ((status == DDS::RETCODE_OK) || (status == DDS::RETCODE_NO_DATA))
    return 0;

  madara_logger_log(context_.get_logger(), logger::LOG_ERROR,
      "SpliceDDSTransport::check_status:"
      " error in %s: Creation failed: %s\n",
      info, get_error_name(status));

  return -2;
}
Exemple #9
0
bool
madara::knowledge::containers::NativeDoubleVector::is_true (void) const
{
  bool result (false);

  madara_logger_log (context_->get_logger (), logger::LOG_MAJOR,
    "NativeDoubleVector::is_true: %s: Checking for non-zero value\n",
    this->name_.c_str ());

  if (context_)
  {
    ContextGuard context_guard (*context_);
    MADARA_GUARD_TYPE guard (mutex_);
    result = context_->get (vector_, settings_).is_true ();
  }

  madara_logger_log (context_->get_logger (), logger::LOG_MAJOR,
    "NativeDoubleVector::is_true: %s: final result is %d\n",
    this->name_.c_str (),
    (int)result);

  return result;
}
int madara::transport::SpliceDDSTransport::check_handle(
    void* handle, const char* info)
{
  if (!handle)
  {
    madara_logger_log(context_.get_logger(), logger::LOG_ERROR,
        "SpliceDDSTransport::check_handle:"
        " error in %s: Creation failed: invalid handle\n",
        info);

    return -2;
  }

  return 0;
}
long madara::transport::SpliceDDSTransport::send_data(
    const knowledge::KnowledgeMap& updates)
{
  long result = 0;

  if (!settings_.no_sending)
  {
    result = prep_send(updates, "SpliceDDSTransport::send_data:");

    // get the maximum quality from the updates
    uint32_t quality = knowledge::max_quality(updates);

    /// get current lamport clock.
    unsigned long long cur_clock = context_.get_clock();

    DDS::ReturnCode_t dds_result;
    DDS::InstanceHandle_t handle;

    Knowledge::Update data;

    data.buffer =
        Knowledge::seq_oct(result, result, (unsigned char*)buffer_.get_ptr());
    data.clock = cur_clock;
    data.quality = quality;
    data.updates = DDS::ULong(updates.size());
    data.originator = DDS::string_dup(id_.c_str());
    data.type = madara::transport::MULTIASSIGN;
    data.ttl = settings_.get_rebroadcast_ttl();
    data.timestamp = utility::get_time();
    data.madara_id = DDS::string_dup(MADARA_IDENTIFIER);

    madara_logger_log(context_.get_logger(), logger::LOG_MAJOR,
        "SpliceDDSTransport::send:"
        " sending multiassignment: %d updates, time=llu, quality=%d\n",
        data.updates, cur_clock, quality);

    handle = update_writer_->register_instance(data);
    dds_result = update_writer_->write(data, handle);
    result = (long)dds_result;
    // update_writer_->unregister_instance (data, handle);
  }

  return result;
}
Exemple #12
0
void madara::filters::EndpointClear::filter(knowledge::KnowledgeMap& records,
    const transport::TransportContext& transport_context,
    knowledge::Variables& vars)
{
  if (!initialized_)
  {
    knowledge::KnowledgeUpdateSettings settings(true);
    endpoints_.set_settings(settings);
    endpoints_.set_name(prefix_, vars);
    initialized_ = true;
  }

  endpoints_.sync_keys();

  madara_logger_log(vars.get_context()->get_logger(), logger::LOG_MAJOR,
      "EndpointClear::filter:"
      " Processing a new update from %s with %d records\n",
      transport_context.get_originator().c_str(), (int)records.size());

  // if a trusted originator has been added, and this is the originator
  if (trusted_originators_.size() != 0 &&
      (trusted_originators_.find(transport_context.get_originator()) !=
          trusted_originators_.end()))
  {
    madara_logger_log(vars.get_context()->get_logger(), logger::LOG_MAJOR,
        "EndpointClear::filter:"
        " Sender is trusted. Clearing endpoints.\n");

    // then clear the endpoints
    endpoints_.clear();

    if (vars.get_context()->get_logger().get_level() >= logger::LOG_DETAILED)
    {
      vars.print();
    }
  }
  else
  {
    bool found = false;
    const std::string prefix(endpoints_.get_name());

    if (prefix != "")
    {
      // iterate through all records looking for the common prefix
      for (knowledge::KnowledgeMap::const_iterator i = records.begin();
           i != records.end() && !found; ++i)
      {
        // if we've found the prefix, then clear the endpoints
        if (utility::begins_with(i->first, prefix))
        {
          madara_logger_log(vars.get_context()->get_logger(), logger::LOG_MAJOR,
              "EndpointClear::filter:"
              " Prefix is match. Clearing endpoints.\n");

          endpoints_.clear();
          found = true;

          if (vars.get_context()->get_logger().get_level() >=
              logger::LOG_DETAILED)
          {
            vars.print();
          }
        }
        // if we're past where the prefix would be, quit
        else if (prefix[0] < i->first[0])
        {
          madara_logger_log(vars.get_context()->get_logger(), logger::LOG_MAJOR,
              "EndpointClear::filter:"
              " Prefix is not a match. Not clearing endpoints.\n");

          found = true;
        }
      }
    }
  }
}
int BasicASIOTransport::setup(void)
{
  // call base setup method to initialize certain common variables
  if (Base::setup() < 0)
  {
    return -1;
  }

  // resize addresses to be the size of the list of hosts
  addresses_.clear();
  addresses_.reserve(this->settings_.hosts.size());

  if (settings_.hosts.size() == 0)
  {
    madara_logger_log(context_.get_logger(), logger::LOG_MINOR,
        "BasicASIOTransport::setup:"
        " No host addresses. Aborting setup.\n");
    this->invalidate_transport();
    return -1;
  }

  // convert the string host:port into an asio address
  for (unsigned int i = 0; i < settings_.hosts.size(); ++i)
  {
    try
    {
      auto addr_parts = utility::parse_address(settings_.hosts[i]);

      auto addr = ip::address::from_string(addr_parts.first);
      addresses_.emplace_back(addr, addr_parts.second);

      madara_logger_log(context_.get_logger(), logger::LOG_MAJOR,
          "BasicASIOTransport::setup:"
          " settings address[%d] to %s:%d\n",
          i, addresses_.back().address().to_string().c_str(),
          addresses_.back().port());
    }
    catch (const boost::system::system_error& e)
    {
      madara_logger_log(context_.get_logger(), logger::LOG_MAJOR,
          "BasicASIOTransport::setup:"
          " Error parsing address %s: %s\n",
          settings_.hosts[i].c_str(), e.what());
    }
  }

  if (addresses_.size() == 0)
  {
    madara_logger_log(context_.get_logger(), logger::LOG_MAJOR,
        "BasicASIOTransport::setup:"
        " No valid addresses. Aborting setup.\n");
    this->invalidate_transport();
    return -1;
  }

  try
  {
    socket_.open(addresses_[0].protocol());
  }
  catch (const boost::system::system_error& e)
  {
    madara_logger_log(context_.get_logger(), logger::LOG_MAJOR,
        "BasicASIOTransport::setup:"
        " Error opening sockets: %s\n",
        e.what());

    this->invalidate_transport();
    return -1;
  }

  int ret = setup_sockets();
  if (ret < 0)
  {
    return ret;
  }

  ret = setup_read_threads();
  if (ret < 0)
  {
    return ret;
  }

  return this->validate_transport();
}
int madara::transport::SpliceDDSTransport::setup(void)
{
  Base::setup();
  DDS::ReturnCode_t status;

  this->is_valid_ = false;

  // reset the valid setup flag
  // valid_setup_ = false;

  madara_logger_log(context_.get_logger(), logger::LOG_DETAILED,
      "SpliceDDSTransport::setup:"
      " Creating a participant for topic (%s)\n",
      madara::utility::dds_topicify(settings_.write_domain).c_str());

  madara_logger_log(context_.get_logger(), logger::LOG_DETAILED,
      "SpliceDDSTransport::setup:"
      " Participant settings are being read from the OSPL_URI environment"
      " variable\n",
      madara::utility::dds_topicify(settings_.write_domain).c_str());

  // get the domain participant factory
  domain_factory_ = DDS::DomainParticipantFactory::get_instance();
  domain_factory_->get_default_participant_qos(part_qos_);
  domain_participant_ = domain_factory_->create_participant(
      domain_, part_qos_, NULL, DDS::STATUS_MASK_NONE);

  // if dp == NULL, we've got an error
  if (domain_participant_ == NULL)
  {
    madara_logger_log(context_.get_logger(), logger::LOG_ERROR,
        "\nSpliceDDSTransport::setup:"
        " splice daemon not running. Try 'ospl start'...\n");

    return -2;
  }

  domain_participant_->get_default_topic_qos(topic_qos_);

  if (madara::transport::RELIABLE == this->settings_.reliability)
  {
    topic_qos_.reliability.kind = DDS::RELIABLE_RELIABILITY_QOS;
    topic_qos_.history.depth = this->settings_.queue_length;
    topic_qos_.resource_limits.max_samples_per_instance =
        this->settings_.queue_length;
    topic_qos_.resource_limits.max_samples = this->settings_.queue_length;
    topic_qos_.destination_order.kind =
        DDS::BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS;
    // topic_qos_.
  }
  // topic_qos_.resource_limits.max_samples_per_instance= 10;
  domain_participant_->set_default_topic_qos(topic_qos_);

  madara_logger_log(context_.get_logger(), logger::LOG_DETAILED,
      "SpliceDDSTransport::setup:"
      " Registering type support\n");

  //  Register Update type
  status = this->update_type_support_.register_type(
      domain_participant_, "Knowledge::Update");
  if (int ret = check_status(
                    status, "Knowledge::UpdateTypeSupport::register_type") < 0)
    return ret;

  //  Register Mutex type
  // status = this->mutex_type_support_.register_type (
  //  domain_participant_, "Knowledge::Mutex");
  // check_status(status, "Knowledge::MutexTypeSupport::register_type");

  madara_logger_log(context_.get_logger(), logger::LOG_DETAILED,
      "SpliceDDSTransport::setup:"
      " Setting up knowledge domain via topic (%s)\n",
      madara::utility::dds_topicify(settings_.write_domain).c_str());

  // Create Update topic
  update_topic_ = domain_participant_->create_topic(
      madara::utility::dds_topicify(settings_.write_domain).c_str(),
      "Knowledge::Update", topic_qos_, NULL, DDS::STATUS_MASK_NONE);

  if (int ret =
          check_handle(update_topic_,
              "DDS::DomainParticipant::create_topic (KnowledgeUpdate)") < 0)
    return ret;

  // Get default qos for publisher
  status = domain_participant_->get_default_publisher_qos(pub_qos_);
  if (int ret = check_status(status,
                    "DDS::DomainParticipant::get_default_publisher_qos") < 0)
    return ret;

  if (madara::transport::RELIABLE == this->settings_.reliability)
  {
    pub_qos_.presentation.access_scope = DDS::TOPIC_PRESENTATION_QOS;
    pub_qos_.presentation.coherent_access = true;
    pub_qos_.presentation.ordered_access = false;
    // topic_qos_.
  }

  madara_logger_log(context_.get_logger(), logger::LOG_DETAILED,
      "SpliceDDSTransport::setup:"
      " Creating publisher for topic (%s)\n",
      madara::utility::dds_topicify(settings_.write_domain).c_str());

  // Create publisher
  pub_qos_.partition.name.length(1);
  pub_qos_.partition.name[0] = DDS::string_dup(partition_);
  publisher_ = domain_participant_->create_publisher(
      pub_qos_, NULL, DDS::STATUS_MASK_NONE);
  if (int ret = check_handle(
                    publisher_, "DDS::DomainParticipant::create_publisher") < 0)
    return ret;

  // Create subscriber
  status = domain_participant_->get_default_subscriber_qos(sub_qos_);
  if (int ret = check_status(status,
                    "DDS::DomainParticipant::get_default_subscriber_qos") < 0)
    return ret;

  if (madara::transport::RELIABLE == this->settings_.reliability)
  {
    sub_qos_.presentation.access_scope = DDS::TOPIC_PRESENTATION_QOS;
    sub_qos_.presentation.coherent_access = true;
    sub_qos_.presentation.ordered_access = false;
  }

  madara_logger_log(context_.get_logger(), logger::LOG_DETAILED,
      "SpliceDDSTransport::setup:"
      " Creating subscriber for topic (%s)\n",
      madara::utility::dds_topicify(settings_.write_domain).c_str());

  sub_qos_.partition.name.length(1);
  sub_qos_.partition.name[0] = DDS::string_dup(partition_);
  subscriber_ = domain_participant_->create_subscriber(
      //    sub_qos_, &sub_listener_, DDS::DATA_AVAILABLE_STATUS |
      //    DDS::DATA_ON_READERS_STATUS);
      sub_qos_, NULL, DDS::STATUS_MASK_NONE);
  if (int ret = check_handle(subscriber_,
                    "DDS::DomainParticipant::create_subscriber") < 0)
    return ret;

  if (!subscriber_ || !publisher_)
  {
    madara_logger_log(context_.get_logger(), logger::LOG_ERROR,
        "SpliceDDSTransport::setup:"
        " pub or sub could not be created. Try 'ospl stop; ospl start'...\n");

    return -2;
  }

  // Create datawriter
  publisher_->get_default_datawriter_qos(datawriter_qos_);
  publisher_->copy_from_topic_qos(datawriter_qos_, topic_qos_);

  if (madara::transport::RELIABLE == this->settings_.reliability)
  {
    madara_logger_log(context_.get_logger(), logger::LOG_DETAILED,
        "SpliceDDSTransport::setup:"
        " Enabling reliable transport for (%s) datawriters\n",
        madara::utility::dds_topicify(settings_.write_domain).c_str());

    datawriter_qos_.reliability.kind = DDS::RELIABLE_RELIABILITY_QOS;
    datawriter_qos_.history.depth = this->settings_.queue_length;
    datawriter_qos_.resource_limits.max_samples = this->settings_.queue_length;
    datawriter_qos_.resource_limits.max_samples_per_instance =
        this->settings_.queue_length;
    datawriter_qos_.destination_order.kind =
        DDS::BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS;
  }
  else
  {
    madara_logger_log(context_.get_logger(), logger::LOG_DETAILED,
        "SpliceDDSTransport::setup:"
        " Enabling unreliable transport for (%s) datawriters\n",
        madara::utility::dds_topicify(settings_.write_domain).c_str());
  }

  madara_logger_log(context_.get_logger(), logger::LOG_DETAILED,
      "SpliceDDSTransport::setup:"
      " Creating datawriter for topic (%s)\n",
      madara::utility::dds_topicify(settings_.write_domain).c_str());

  // Create Update writer
  datawriter_ = publisher_->create_datawriter(
      update_topic_, datawriter_qos_, NULL, DDS::STATUS_MASK_NONE);
  if (int ret = check_handle(datawriter_,
                    "DDS::Publisher::create_datawriter (Update)") < 0)
    return ret;
  update_writer_ =
      dynamic_cast<Knowledge::UpdateDataWriter_ptr>(datawriter_.in());
  if (int ret = check_handle(update_writer_,
                    "Knowledge::UpdateDataWriter_ptr::narrow") < 0)
    return ret;

  // Create Latency Update writer for Read Thread
  latencywriter_ = publisher_->create_datawriter(
      update_topic_, datawriter_qos_, NULL, DDS::STATUS_MASK_NONE);
  if (int ret = check_handle(latencywriter_,
                    "DDS::Publisher::create_datawriter (Update)") < 0)
    return ret;
  latency_update_writer_ =
      dynamic_cast<Knowledge::UpdateDataWriter_ptr>(latencywriter_.in());
  if (int ret = check_handle(latency_update_writer_,
                    "Knowledge::UpdateDataWriter_ptr::narrow") < 0)
    return ret;

  // Create datareader
  status = subscriber_->get_default_datareader_qos(datareader_qos_);
  subscriber_->copy_from_topic_qos(datareader_qos_, topic_qos_);
  // publisher_->copy_from_topic_qos(datawriter_qos_, topic_qos_);
  if (int ret = check_status(
                    status, "DDS::Subscriber::get_default_datareader_qos") < 0)
    return ret;

  datareader_qos_.reader_data_lifecycle.enable_invalid_samples = FALSE;

  if (madara::transport::RELIABLE == this->settings_.reliability)
  {
    madara_logger_log(context_.get_logger(), logger::LOG_DETAILED,
        "SpliceDDSTransport::setup:"
        " Enabling reliable transport for (%s) datareaders\n",
        madara::utility::dds_topicify(settings_.write_domain).c_str());

    datareader_qos_.reliability.kind = DDS::RELIABLE_RELIABILITY_QOS;
    datareader_qos_.history.depth = this->settings_.queue_length;
    datareader_qos_.resource_limits.max_samples = this->settings_.queue_length;
    datareader_qos_.destination_order.kind =
        DDS::BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS;

    // unlike the other qos, we do not set max_samples_per_instance here.
    // that shouldn't be as necessary, since we are using take on the reader
  }
  else
  {
    madara_logger_log(context_.get_logger(), logger::LOG_DETAILED,
        "SpliceDDSTransport::setup:"
        " Enabling unreliable transport for (%s) datareaders\n",
        madara::utility::dds_topicify(settings_.write_domain).c_str());
  }

  madara_logger_log(context_.get_logger(), logger::LOG_DETAILED,
      "SpliceDDSTransport::setup:"
      " Creating datareader for topic (%s)\n",
      madara::utility::dds_topicify(settings_.write_domain).c_str());

  // Create Update datareader
  datareader_ = subscriber_->create_datareader(update_topic_,
      // datareader_qos_, &dr_listener_, DDS::STATUS_MASK_NONE);
      datareader_qos_, NULL, DDS::STATUS_MASK_NONE);

  // notes: we set the mask to none because the listener will be called
  // by the subscriber listener with notify_datareaders. This is the Splice
  // way of doing this, since we require subscription information and they
  // have so far not implemented on_subscription_matched.

  if (int ret = check_handle(datareader_,
                    "DDS::Subscriber::create_datareader (Update)") < 0)
    return ret;
  update_reader_ =
      dynamic_cast<Knowledge::UpdateDataReader_ptr>(datareader_.in());
  if (int ret = check_handle(update_reader_,
                    "Knowledge::UpdateDataReader_ptr::narrow") < 0)
    return ret;

  if (!settings_.no_receiving)
  {
    double hertz = settings_.read_thread_hertz;
    if (hertz < 0.0)
    {
      hertz = 0.0;
    }

    madara_logger_log(context_.get_logger(), logger::LOG_MAJOR,
        "UdpTransportReadThread::setup:"
        " starting %d threads at %f hertz\n",
        settings_.read_threads, hertz);

    for (uint32_t i = 0; i < settings_.read_threads; ++i)
    {
      std::stringstream thread_name;
      thread_name << "read";
      thread_name << i;

      read_threads_.run(hertz, thread_name.str(),
          new madara::transport::SpliceReadThread(id_, this->settings_,
              context_, update_reader_, latency_update_writer_, send_monitor_,
              receive_monitor_, packet_scheduler_));
    }
  }

  return this->validate_transport();
}
Exemple #15
0
long UdpTransport::send_message(const char* buf, size_t packet_size,
  uint64_t clock)
{
  static const char print_prefix[] = "UdpTransport::send_message";

  uint64_t bytes_sent = 0;

  if(packet_size > settings_.max_fragment_size)
  {
    FragmentMap map;

    madara_logger_log(context_.get_logger(), logger::LOG_MAJOR,
        "%s:"
        " fragmenting %" PRIu64 " byte packet (%" PRIu32
        " bytes is max fragment size)\n",
        print_prefix, packet_size, settings_.max_fragment_size);

    // fragment the message
    frag(buf, packet_size, id_.c_str (), settings_.write_domain.c_str(),
      clock, utility::get_time(), 0, 0,
      settings_.max_fragment_size, map);

    int j(0);
    for(FragmentMap::iterator i = map.begin(); i != map.end(); ++i, ++j)
    {
      madara_logger_log(context_.get_logger(), logger::LOG_MAJOR,
          "%s:"
          " Sending fragment %d\n",
          print_prefix, j);

      for(const auto& address : addresses_)
      {
        if(pre_send_buffer(&address - &*addresses_.begin()))
        {
          bytes_sent += send_buffer(
              address, i->second.get(),
              (size_t)MessageHeader::get_size(i->second.get()));
        }
      }

      // sleep between fragments, if such a slack time is specified
      if(settings_.slack_time > 0)
        utility::sleep(settings_.slack_time);
    }

    madara_logger_log(context_.get_logger(), logger::LOG_MAJOR,
        "%s:"
        " Sent fragments totalling %" PRIu64 " bytes\n",
        print_prefix, bytes_sent);

    delete_fragments(map);
  }
  else
  {
    madara_logger_log(context_.get_logger(), logger::LOG_MAJOR,
        "%s:"
        " Sending packet of size %ld\n",
        print_prefix, packet_size);

    for(const auto& address : addresses_)
    {
      size_t addr_index = &address - &*addresses_.begin();
      bool should_send = pre_send_buffer(addr_index);

      madara_logger_log(context_.get_logger(), logger::LOG_MINOR,
          "%s:"
          " Deciding to send to %s:%d (index %d): %d\n",
          print_prefix, address.address().to_string().c_str(),
          (int)address.port(), addr_index, should_send);

      if(should_send)
      {
        bytes_sent += send_buffer(address, buf, (size_t)packet_size);
      }
    }
  }

  if(bytes_sent > 0)
  {
    send_monitor_.add((uint32_t)bytes_sent);
  }

  madara_logger_log(context_.get_logger(), logger::LOG_MAJOR,
      "%s:"
      " Send bandwidth = %" PRIu64 " B/s\n",
      print_prefix, send_monitor_.get_bytes_per_second());

  return (long)bytes_sent;
}
Exemple #16
0
long UdpTransport::send_buffer(
    const udp::endpoint& target, const char* buf, size_t size)
{
  uint64_t bytes_sent = 0;

  int send_attempts = -1;
  ssize_t actual_sent = -1;

  while (actual_sent < 0 && (settings_.resend_attempts < 0 ||
                                send_attempts < settings_.resend_attempts))
  {
    if(settings_.max_send_hertz > 0)
    {
      enforcer_.sleep_until_next();
    }

    // send the fragment
    try
    {
      actual_sent = socket_.send_to(asio::buffer(buf, size), target);
    }
    catch (const boost::system::system_error& e)
    {
      madara_logger_log(context_.get_logger(), logger::LOG_MAJOR,
          "UdpTransport::send_buffer:"
          " Error sending packet to %s:%d: %s\n",
          target.address().to_string().c_str(), (int)target.port(), e.what());

      // ensure erroneous data is not being used
      actual_sent = -1;
    }

    ++send_attempts;
    if(settings_.debug_to_kb_prefix != "")
    {
      ++sent_packets;
    }

    if(actual_sent > 0)
    {
      madara_logger_log(context_.get_logger(), logger::LOG_MAJOR,
          "UdpTransport::send_buffer: Sent %d byte packet to %s:%d\n",
          (int)actual_sent, target.address().to_string().c_str(),
          (int)target.port());

      bytes_sent += actual_sent;

      if(settings_.debug_to_kb_prefix != "")
      {
        sent_data += actual_sent;
        if(sent_data_max < actual_sent)
        {
          sent_data_max = actual_sent;
        }
        if(sent_data_min > actual_sent || sent_data_min == 0)
        {
          sent_data_min = actual_sent;
        }
      }
    }
    else
    {
      if(settings_.debug_to_kb_prefix != "")
      {
        ++failed_sends;
      }
    }
  }

  return (long)bytes_sent;
}
Exemple #17
0
void
madara::transport::UdpRegistryClientReadThread::run (void)
{
  if (!settings_.no_receiving)
  {
    ACE_Time_Value wait_time (1);
    ACE_INET_Addr  remote;
  
    // allocate a buffer to send
    char * buffer = buffer_.get_ptr ();
    const char * print_prefix = "UdpRegistryClientReadThread::run";
    int64_t buffer_remaining = settings_.queue_length;

    madara_logger_log (context_->get_logger (), logger::LOG_MAJOR,
      "%s:" \
      " entering main service loop.\n",
      print_prefix);
    
    knowledge::KnowledgeMap rebroadcast_records;

    if (buffer == 0)
    {
      madara_logger_log (context_->get_logger (), logger::LOG_MINOR,
        "%s:" \
        " Unable to allocate buffer of size " PRIu32 ". Exiting thread.\n",
        print_prefix,
        settings_.queue_length);
    
      return;
    }
    
    madara_logger_log (context_->get_logger (), logger::LOG_MINOR,
      "%s:" \
      " entering a recv on the socket.\n",
      print_prefix);
    
    // read the message
    ssize_t bytes_read = socket_.recv ((void *)buffer, 
      (size_t)settings_.queue_length, remote, 0, &wait_time);
 
    if (bytes_read > 0)
    {
      if (remote.get_host_addr () != 0)
      {
        madara_logger_ptr_log (logger::global_logger.get (),
          logger::LOG_MAJOR,
          "%s:" \
          " received a message header of %lld bytes from %s:%d\n",
          print_prefix,
          (long long)bytes_read,
          remote.get_host_addr (), (int)remote.get_port_number ());
      }
      else
      {
        madara_logger_ptr_log (logger::global_logger.get (),
          logger::LOG_WARNING,
          "%s:" \
          " received %lld bytes from unknown host\n",
          print_prefix,
          (long long)bytes_read);
      }
      MessageHeader * header = 0;

      std::stringstream remote_host;
      remote_host << remote.get_host_addr ();
      remote_host << ":";
      remote_host << remote.get_port_number ();

      process_received_update (buffer, bytes_read, id_, *context_,
        settings_, send_monitor_, receive_monitor_, rebroadcast_records,
  #ifndef _MADARA_NO_KARL_
        on_data_received_,
  #endif // _MADARA_NO_KARL_
        print_prefix,
        remote_host.str ().c_str (), header);
      
      if (header)
      {
        if (header->ttl > 0 && rebroadcast_records.size () > 0 &&
            settings_.get_participant_ttl () > 0)
        {
          --header->ttl;
          header->ttl = std::min (
            settings_.get_participant_ttl (), header->ttl);

          rebroadcast (print_prefix, header, rebroadcast_records);
        }

        // delete header
        delete header;
      }
    }
    else
    {
      madara_logger_log (context_->get_logger (), logger::LOG_MAJOR,
        "%s:" \
        " wait timeout on new messages. Proceeding to next wait\n",
        print_prefix);
    }
  }
}
Exemple #18
0
void
madara::transport::UdpRegistryClientReadThread::rebroadcast (
  const char * print_prefix,
  MessageHeader * header,
  const knowledge::KnowledgeMap & records)
{
  int64_t buffer_remaining = (int64_t) settings_.queue_length;
  char * buffer = buffer_.get_ptr ();
  int result (0);

  if (!settings_.no_sending)
  {
    result = prep_rebroadcast (*context_, buffer, buffer_remaining,
                                   settings_, print_prefix,
                                   header, records,
                                   packet_scheduler_);

    if (result > 0)
    {
      uint64_t bytes_sent = 0;
      uint64_t packet_size = (uint64_t)result;

      if (packet_size > settings_.max_fragment_size)
      {
        FragmentMap map;

        madara_logger_log (context_->get_logger (), logger::LOG_MAJOR,
          "%s:" \
          " fragmenting %" PRIu64 " byte packet (%" PRIu32 " bytes is max fragment size)\n",
          print_prefix, packet_size, settings_.max_fragment_size);

        // fragment the message
        frag (buffer_.get_ptr (), settings_.max_fragment_size, map);

        int j (0);
        for (FragmentMap::iterator i = map.begin (); i != map.end ();
          ++i, ++j)
        {
          size_t frag_size =
            (size_t)MessageHeader::get_size (i->second);

          for (std::map <std::string, ACE_INET_Addr>::const_iterator addr =
            addresses_.begin (); addr != addresses_.end (); ++addr)
          {
            if (addr->first != settings_.hosts[0])
            {
              madara_logger_log (this->context_->get_logger (), logger::LOG_MAJOR,
                "%s:" \
                " Sending fragment %d\n",
                print_prefix, j);

              int send_attempts = -1;
              ssize_t actual_sent = -1;

              while (actual_sent < 0 &&
                (settings_.resend_attempts < 0 ||
                send_attempts < settings_.resend_attempts))
              {

                // send the fragment
                actual_sent = socket_.send (
                  i->second, frag_size, addr->second);

                ++send_attempts;

                if (actual_sent > 0)
                {
                  bytes_sent = (uint64_t)actual_sent;

                  madara_logger_log (context_->get_logger (), logger::LOG_MAJOR,
                    "%s:" \
                    " Sent packet of size %" PRIu64 "\n",
                    print_prefix, bytes_sent);

                  send_monitor_.add ((uint32_t)actual_sent);
                }
                else if (actual_sent == ECONNRESET)
                {
                  madara_logger_log (context_->get_logger (), logger::LOG_WARNING,
                    "%s:" \
                    " WARNING: Remote socket disappeared during send (ECONNRESET)\n",
                    print_prefix);
                }
                else if (actual_sent == EINTR)
                {
                  madara_logger_log (context_->get_logger (), logger::LOG_WARNING,
                    "%s:" \
                    " Local socket was interrupted during send (EINTR)\n",
                    print_prefix);
                }
                else if (actual_sent == EWOULDBLOCK)
                {
                  madara_logger_log (context_->get_logger (), logger::LOG_WARNING,
                    "%s:" \
                    " Send would have blocked (EWOULDBLOCK)\n",
                    print_prefix);
                }
                else if (actual_sent == ENOTCONN)
                {
                  madara_logger_log (context_->get_logger (), logger::LOG_WARNING,
                    "%s:" \
                    " Send reports socket is not connected (ENOTCONN)\n",
                    print_prefix);
                }
                else if (actual_sent == EADDRINUSE)
                {
                  madara_logger_log (context_->get_logger (), logger::LOG_WARNING,
                    "%s:" \
                    " Send reports the interface is busy (EADDRINUSE)\n",
                    print_prefix);
                }
                else if (actual_sent == EBADF)
                {
                  madara_logger_log (context_->get_logger (), logger::LOG_WARNING,
                    "%s:" \
                    " Send socket is invalid (EBADF)\n",
                    print_prefix);
                }
                else
                {
                  madara_logger_log (context_->get_logger (), logger::LOG_WARNING,
                    "%s:" \
                    " Packet was not sent due to unknown error (%d)\n",
                    print_prefix, (int)actual_sent);
                }
              }

              // sleep between fragments, if such a slack time is specified
              if (settings_.slack_time > 0)
                madara::utility::sleep (settings_.slack_time);

            }
          }
        }

        madara_logger_log (context_->get_logger (), logger::LOG_MAJOR,
          "%s:" \
          " Sent fragments totalling %" PRIu64 " bytes\n",
          print_prefix, bytes_sent);

        delete_fragments (map);
      }
      else
      {
        for (std::map <std::string, ACE_INET_Addr>::const_iterator i =
                addresses_.begin (); i != addresses_.end (); ++i)
        {
          if (i->first != settings_.hosts[0])
          {
            madara_logger_log (this->context_->get_logger (),
              logger::LOG_MAJOR,
              "%s:" \
              " Sending packet of size %ld\n",
              print_prefix, result);

            int send_attempts = -1;
            ssize_t actual_sent = -1;

            while (actual_sent < 0 &&
              (settings_.resend_attempts < 0 ||
              send_attempts < settings_.resend_attempts))
            {

              // send the fragment
              actual_sent = socket_.send (buffer_.get_ptr (),
                (ssize_t)result, i->second);

              ++send_attempts;

              if (actual_sent > 0)
              {
                bytes_sent += actual_sent;

                madara_logger_log (this->context_->get_logger (),
                  logger::LOG_MAJOR,
                  "%s:" \
                  " Sent packet of size %" PRIu64 "\n",
                  print_prefix, (int)actual_sent);

                send_monitor_.add ((uint32_t)actual_sent);
              }
              else if (actual_sent == ECONNRESET)
              {
                madara_logger_log (this->context_->get_logger (),
                  logger::LOG_WARNING,
                  "%s:" \
                  " WARNING: Remote socket disappeared during send (ECONNRESET)\n",
                  print_prefix);
              }
              else if (actual_sent == EINTR)
              {
                madara_logger_log (this->context_->get_logger (),
                  logger::LOG_WARNING,
                  "%s:" \
                  " Local socket was interrupted during send (EINTR)\n",
                  print_prefix);
              }
              else if (actual_sent == EWOULDBLOCK)
              {
                madara_logger_log (this->context_->get_logger (),
                  logger::LOG_WARNING,
                  "%s:" \
                  " Send would have blocked (EWOULDBLOCK)\n",
                  print_prefix);
              }
              else if (actual_sent == ENOTCONN)
              {
                madara_logger_log (this->context_->get_logger (),
                  logger::LOG_WARNING,
                  "%s:" \
                  " Send reports socket is not connected (ENOTCONN)\n",
                  print_prefix);
              }
              else if (actual_sent == EADDRINUSE)
              {
                madara_logger_log (this->context_->get_logger (),
                  logger::LOG_WARNING,
                  "%s:" \
                  " Send reports the interface is busy (EADDRINUSE)\n",
                  print_prefix);
              }
              else if (actual_sent == EBADF)
              {
                madara_logger_log (this->context_->get_logger (),
                  logger::LOG_WARNING,
                  "%s:" \
                  " Send socket is invalid (EBADF)\n",
                  print_prefix);
              }
              else
              {
                madara_logger_log (this->context_->get_logger (),
                  logger::LOG_WARNING,
                  "%s:" \
                  " Packet was not sent due to unknown error (%d)\n",
                  print_prefix, (int)actual_sent);
              }
            }
          }
        }

        madara_logger_log (context_->get_logger (), logger::LOG_MAJOR,
          "%s:" \
          " Sent %d total bytes via rebroadcast\n",
          print_prefix, bytes_sent);
      }

      madara_logger_log (context_->get_logger (), logger::LOG_MAJOR,
        "%s:" \
        " Send bandwidth = %" PRIu64 " B/s\n",
        print_prefix,
        send_monitor_.get_bytes_per_second ());
    }
  }
}
int BasicASIOTransport::setup_socket(udp::socket& socket)
{
  int tar_buff_size(settings_.queue_length);

  asio::socket_base::send_buffer_size send_buffer_option;
  asio::socket_base::receive_buffer_size receive_buffer_option;

  try
  {
    socket.get_option(send_buffer_option);
    int send_buff_size = send_buffer_option.value();

    socket.get_option(receive_buffer_option);
    int rcv_buff_size = receive_buffer_option.value();

    madara_logger_log(context_.get_logger(), logger::LOG_MAJOR,
        "BasicASIOTransport::setup:"
        " default socket buff size is send=%d, rcv=%d\n",
        send_buff_size, rcv_buff_size);

    if (send_buff_size < tar_buff_size)
    {
      madara_logger_log(context_.get_logger(), logger::LOG_MAJOR,
          "BasicASIOTransport::setup:"
          " setting send buff size to settings.queue_length (%d)\n",
          tar_buff_size);

      send_buffer_option = tar_buff_size;
      socket.set_option(send_buffer_option);

      socket.get_option(send_buffer_option);
      send_buff_size = send_buffer_option.value();

      madara_logger_log(context_.get_logger(), logger::LOG_MAJOR,
          "BasicASIOTransport::setup:"
          " current socket buff size is send=%d, rcv=%d\n",
          send_buff_size, rcv_buff_size);
    }

    if (rcv_buff_size < tar_buff_size)
    {
      madara_logger_log(context_.get_logger(), logger::LOG_MAJOR,
          "BasicASIOTransport::setup:"
          " setting rcv buff size to settings.queue_length (%d)\n",
          tar_buff_size);

      receive_buffer_option = tar_buff_size;
      socket.set_option(receive_buffer_option);

      socket.get_option(receive_buffer_option);
      rcv_buff_size = receive_buffer_option.value();

      madara_logger_log(context_.get_logger(), logger::LOG_MAJOR,
          "BasicASIOTransport::setup:"
          " current socket buff size is send=%d, rcv=%d\n",
          send_buff_size, rcv_buff_size);
    }
  }
  catch (const boost::system::system_error& e)
  {
    madara_logger_log(context_.get_logger(), logger::LOG_MAJOR,
        "BasicASIOTransport::setup:"
        " Error setting up sockets: %s\n",
        e.what());

    this->invalidate_transport();
    return -1;
  }

  return 0;
}