Subscriber::Subscriber( const Options& options) : options_( options), listener_( 0), waiter_( new DDS::WaitSet) { // Create the DomainParticipant this->participant_ = TheParticipantFactory->create_participant( this->options_.domain(), PARTICIPANT_QOS_DEFAULT, DDS::DomainParticipantListener::_nil(), ::OpenDDS::DCPS::DEFAULT_STATUS_MASK ); if( CORBA::is_nil( this->participant_.in())) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: Subscriber::Subscriber() - ") ACE_TEXT("failed to create a participant.\n") )); throw BadParticipantException(); } else if( this->options_.verbose()) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) Subscriber::Subscriber() - ") ACE_TEXT("created participant in domain %d.\n"), this->options_.domain() )); } // Create the transport. this->transport_ = TheTransportFactory->create_transport_impl( this->options_.transportKey(), OpenDDS::DCPS::AUTO_CONFIG ); if( this->transport_.is_nil()) { std::stringstream buffer; buffer << this->options_.transportType(); ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: Subscriber::Subscriber() - ") ACE_TEXT("failed to create %C transport.\n"), buffer.str().c_str() )); throw BadTransportException(); } else if( this->options_.verbose()) { std::stringstream buffer; buffer << this->options_.transportType(); ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) Subscriber::Subscriber() - ") ACE_TEXT("created %C transport.\n"), buffer.str().c_str() )); } // Create the listener. this->listener_ = new DataReaderListener( this->options_.verbose()); this->safe_listener_ = this->listener_; if( this->options_.verbose()) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) Subscriber::Subscriber() - ") ACE_TEXT("created reader listener.\n") )); } // Create and register the type support. DataTypeSupportImpl* testData = new DataTypeSupportImpl(); if( ::DDS::RETCODE_OK != testData->register_type( this->participant_.in(), 0)) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: Subscriber::Subscriber() - ") ACE_TEXT("unable to install type %C support.\n"), testData->get_type_name() )); throw BadTypeSupportException (); } else if( this->options_.verbose()) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) Subscriber::Subscriber() - ") ACE_TEXT("created type %C support.\n"), testData->get_type_name() )); } // Create the topic. this->topic_ = this->participant_->create_topic( this->options_.topicName().c_str(), testData->get_type_name(), TOPIC_QOS_DEFAULT, ::DDS::TopicListener::_nil(), ::OpenDDS::DCPS::DEFAULT_STATUS_MASK ); if( CORBA::is_nil( this->topic_.in())) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: Subscriber::Subscriber() - ") ACE_TEXT("failed to create topic %C.\n"), this->options_.topicName().c_str() )); throw BadTopicException(); } else if( this->options_.verbose()) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) Subscriber::Subscriber() - ") ACE_TEXT("created topic %C.\n"), this->options_.topicName().c_str() )); } // Create the subscriber. this->subscriber_ = this->participant_->create_subscriber( SUBSCRIBER_QOS_DEFAULT, ::DDS::SubscriberListener::_nil(), ::OpenDDS::DCPS::DEFAULT_STATUS_MASK ); if( CORBA::is_nil( this->subscriber_.in())) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: Subscriber::Subscriber() - ") ACE_TEXT("failed to create subscriber.\n") )); throw BadSubscriberException(); } else if( this->options_.verbose()) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) Subscriber::Subscriber() - ") ACE_TEXT("created subscriber.\n") )); } // Attach the transport to the subscriber. ::OpenDDS::DCPS::SubscriberImpl* servant = dynamic_cast< ::OpenDDS::DCPS::SubscriberImpl*>( this->subscriber_.in()); if( 0 == servant) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: Subscriber::Subscriber() - ") ACE_TEXT("failed to narrow subscriber servant.\n") )); throw BadServantException(); } if( ::OpenDDS::DCPS::ATTACH_OK != servant->attach_transport( this->transport_.in())) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: Subscriber::Subscriber() - ") ACE_TEXT("failed to attach transport to subscriber.\n") )); throw BadAttachException(); } else if( this->options_.verbose()) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) Subscriber::Subscriber() - ") ACE_TEXT("attached transport to subscriber.\n") )); } // Reader Qos policy values. ::DDS::DataReaderQos readerQos; this->subscriber_->get_default_datareader_qos( readerQos); readerQos.durability.kind = ::DDS::TRANSIENT_LOCAL_DURABILITY_QOS; readerQos.history.kind = ::DDS::KEEP_ALL_HISTORY_QOS; readerQos.resource_limits.max_samples_per_instance = ::DDS::LENGTH_UNLIMITED; // Reliability varies with the transport implementation. switch( this->options_.transportType()) { case Options::TCP: case Options::MC: readerQos.reliability.kind = ::DDS::RELIABLE_RELIABILITY_QOS; break; case Options::UDP: readerQos.reliability.kind = ::DDS::BEST_EFFORT_RELIABILITY_QOS; break; case Options::TRANSPORT_NONE: default: ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: Subscriber::Subscriber() - ") ACE_TEXT("unrecognized transport when setting up Qos policies.\n") )); throw BadQosException(); } // Create the reader. this->reader_ = this->subscriber_->create_datareader( this->topic_.in(), readerQos, DDS::DataReaderListener::_nil(), ::OpenDDS::DCPS::DEFAULT_STATUS_MASK ); if( CORBA::is_nil( this->reader_.in())) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: Subscriber::Subscriber() - ") ACE_TEXT("failed to create reader.\n") )); throw BadReaderException(); } else if( this->options_.verbose()) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) Subscriber::Subscriber() - ") ACE_TEXT("created reader.\n") )); } // Set the listener mask here so that we don't conflict with the // StatusCondition(s) that we want to wait on in the main thread. this->reader_->set_listener( this->listener_, DDS::DATA_AVAILABLE_STATUS); // Grab, enable and attach the status condition for test synchronization. this->status_ = this->reader_->get_statuscondition(); this->status_->set_enabled_statuses( DDS::SUBSCRIPTION_MATCHED_STATUS); this->waiter_->attach_condition( this->status_.in()); if( this->options_.verbose()) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) Subscriber::Subscriber() - ") ACE_TEXT("created StatusCondition and WaitSet for test synchronization.\n") )); } }
/** * @brief Construct a test system from the command line. */ TestMonitor::TestMonitor( int argc, ACE_TCHAR** argv, char** envp) : config_( argc, argv, envp) { /// DDS_RUN_DEBUG_LEVEL = 5; /// OpenDDS::DCPS::DCPS_debug_level = 5; // Grab a local reference to the factory to ensure that we perform the // operations - they should not get optimized away! Note that this // passes the arguments to the ORB initialization first, then strips // the DCPS arguments. ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) %T INFO: initializing the monitor.\n"))); ::DDS::DomainParticipantFactory_var factory = TheParticipantFactoryWithArgs( argc, argv); this->subscriberParticipant_.resize( this->config_.subscriberDomainSize(), ::DDS::DomainParticipant::_nil() ); this->publisherParticipant_.resize( this->config_.publisherDomainSize(), ::DDS::DomainParticipant::_nil() ); this->subscriber_.resize( this->config_.subscriberDomainSize(), ::DDS::Subscriber::_nil()); this->publisher_.resize( this->config_.publisherDomainSize(), ::DDS::Publisher::_nil()); this->readerTopic_.resize( this->config_.subscriberDomainSize(), ::DDS::Topic::_nil()); this->writerTopic_.resize( this->config_.publisherDomainSize(), ::DDS::Topic::_nil()); this->dataReader_.resize( this->config_.subscriberDomainSize(), ::DDS::DataReader::_nil()); this->dataWriter_.resize( this->config_.publisherDomainSize(), ::DDS::DataWriter::_nil()); this->listener_.resize( this->config_.subscriberDomainSize(), ::DDS::DataReaderListener::_nil()); this->forwarder_.resize( this->config_.subscriberDomainSize(), 0); if( signed(OpenDDS::DCPS::DCPS_debug_level) >= 0) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) %T COMMANDLINE: Verbose == %C\n") ACE_TEXT("(%P|%t) %T COMMANDLINE: Samples == %d\n") ACE_TEXT("(%P|%t) %T COMMANDLINE: Type == %C\n") ACE_TEXT("(%P|%t) %T COMMANDLINE: Transport Address == %s\n"), (this->config_.verbose()? "true": "false"), this->config_.samples(), this->config_.typeName().c_str(), this->config_.transportAddressName().c_str() )); for( int index = 0; index < this->config_.infoRepoIorSize(); ++index) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) %T COMMANDLINE: InforRepoIOR[ %d] == %C\n"), index, this->config_.infoRepoIor( index).c_str() )); } for( int index = 0; index < this->config_.readerTopicNameSize(); ++index) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) %T COMMANDLINE: readerTopicName[ %d] == %C\n"), index, this->config_.readerTopicName( index).c_str() )); } for( int index = 0; index < this->config_.writerTopicNameSize(); ++index) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) %T COMMANDLINE: writerTopicName[ %d] == %C\n"), index, this->config_.writerTopicName( index).c_str() )); } for( int index = 0; index < this->config_.subscriberDomainSize(); ++index) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) %T COMMANDLINE: subscriberDomain[ %d] == %d\n") ACE_TEXT("(%P|%t) %T COMMANDLINE: using repository key %d\n"), index, this->config_.subscriberDomain( index), this->config_.domainToRepo( this->config_.subscriberDomain( index)) )); } for( int index = 0; index < this->config_.publisherDomainSize(); ++index) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) %T COMMANDLINE: publisherDomain[ %d] == %d\n") ACE_TEXT("(%P|%t) %T COMMANDLINE: using repository key %d\n"), index, this->config_.publisherDomain( index), this->config_.domainToRepo( this->config_.publisherDomain( index)) )); } } for( int index = 0; index < this->config_.infoRepoIorSize(); ++index) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) %T INFO: loading repository %d.\n"), index )); TheServiceParticipant->set_repo_ior( this->config_.infoRepoIor( index).c_str(), index ); } // We only need to do binding if we receive InfoRepo IOR values on the // command line - otherwise this is done during configuration file // processing. if( this->config_.infoRepoIorSize() > 0) { for( int index = 0; index < this->config_.subscriberDomainSize(); ++index) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) %T INFO: binding subscriber domain %d to repository %d.\n"), this->config_.subscriberDomain( index), this->config_.domainToRepo( this->config_.subscriberDomain( index)) )); TheServiceParticipant->set_repo_domain( this->config_.subscriberDomain( index), this->config_.domainToRepo( this->config_.subscriberDomain( index)) ); } for( int index = 0; index < this->config_.publisherDomainSize(); ++index) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) %T INFO: binding publisher domain %d to repository %d.\n"), this->config_.publisherDomain( index), this->config_.domainToRepo( this->config_.publisherDomain( index)) )); TheServiceParticipant->set_repo_domain( this->config_.publisherDomain( index), this->config_.domainToRepo( this->config_.publisherDomain( index)) ); } } // // Establish DomainParticipants for the subscription domains. // for( int index = 0; index < this->config_.subscriberDomainSize(); ++index) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) %T INFO: creating subscriber participant in domain %d.\n"), this->config_.subscriberDomain( index) )); ParticipantMap::iterator where = this->participants_.find( this->config_.subscriberDomain( index)); if( where == this->participants_.end()) { this->participants_[ this->config_.subscriberDomain( index)] = factory->create_participant( this->config_.subscriberDomain( index), PARTICIPANT_QOS_DEFAULT, ::DDS::DomainParticipantListener::_nil(), ::OpenDDS::DCPS::DEFAULT_STATUS_MASK ); if (CORBA::is_nil (this->participants_[ this->config_.subscriberDomain( index)].in ())) { ACE_ERROR ((LM_ERROR, ACE_TEXT("(%P|%t) %T ERROR: create_participant failed for ") ACE_TEXT("subscriber[ %d] in domain %d.\n"), index, this->config_.subscriberDomain( index) )); throw BadParticipantException (); } } this->subscriberParticipant_[ index] = ::DDS::DomainParticipant::_duplicate (this->participants_[ this->config_.subscriberDomain( index)].in()); } // // Establish DomainParticipants for the publication domains. // for( int index = 0; index < this->config_.publisherDomainSize(); ++index) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) %T INFO: creating publisher participant in domain %d.\n"), this->config_.publisherDomain( index) )); ParticipantMap::iterator where = this->participants_.find( this->config_.publisherDomain( index)); if( where == this->participants_.end()) { this->participants_[ this->config_.publisherDomain( index)] = factory->create_participant( this->config_.publisherDomain( index), PARTICIPANT_QOS_DEFAULT, ::DDS::DomainParticipantListener::_nil(), ::OpenDDS::DCPS::DEFAULT_STATUS_MASK ); if (CORBA::is_nil (this->participants_[ this->config_.publisherDomain( index)].in ())) { ACE_ERROR ((LM_ERROR, ACE_TEXT("(%P|%t) %T ERROR: create_participant failed for ") ACE_TEXT("publisher[ %d] in domain %d.\n"), index, this->config_.publisherDomain( index) )); throw BadParticipantException (); } } this->publisherParticipant_[ index] = ::DDS::DomainParticipant::_duplicate (this->participants_[ this->config_.publisherDomain( index)].in()); } // // Grab and install the transport implementations. // // We need to have a separate transport implementation for each // repository since the RepoId space will collide between them without // modification of the current implementation. // // Establish debug level. if( this->config_.verbose()) { TURN_ON_VERBOSE_DEBUG; } // // We have to extract the repository keys here since if we configured // the repositories and domains from a file, we do not have that // information available to us. Drat. // std::set< OpenDDS::DCPS::Service_Participant::RepoKey> keylist; for( int index = 0; index < this->config_.subscriberDomainSize(); ++index) { keylist.insert( TheServiceParticipant->domain_to_repo( this->config_.subscriberDomain( index))); } for( int index = 0; index < this->config_.publisherDomainSize(); ++index) { keylist.insert( TheServiceParticipant->domain_to_repo( this->config_.publisherDomain( index))); } ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) %T INFO: creating transports for repositories.\n"))); ACE_UINT32 transportKey = 0; for( std::set< OpenDDS::DCPS::Service_Participant::RepoKey>::const_iterator current = keylist.begin(); current != keylist.end(); ++current, ++transportKey) { // Only create transports that need to be. if( false == TheTransportFactory->obtain( transportKey).is_nil()) { continue; } ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) %T INFO: creating a SimpleTCP transport for repository: %d.\n"), *current )); this->transport_[ *current] = TheTransportFactory->create_transport_impl( transportKey, ACE_TEXT("SimpleTcp"), OpenDDS::DCPS::DONT_AUTO_CONFIG ); OpenDDS::DCPS::TransportConfiguration_rch reader_config = TheTransportFactory->create_configuration( transportKey, ACE_TEXT("SimpleTcp") ); // OpenDDS::DCPS::SimpleTcpConfiguration* reader_tcp_config // = static_cast <OpenDDS::DCPS::SimpleTcpConfiguration*>( reader_config.in() ); // // if( this->config_.transportAddressName().length() > 0) // { // ACE_INET_Addr reader_address( this->config_.transportAddressName().c_str()); // reader_tcp_config->local_address_ = reader_address; // reader_tcp_config->local_address_str_ = this->config_.transportAddressName(); // } // else use default address - OS assigned. if( this->transport_[ *current]->configure( reader_config.in()) != 0) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) %T ERROR: TCP ") ACE_TEXT("failed to configure the transport.\n"))); throw BadTransportException (); } } // // Establish the listeners. // for( int index = 0; index < this->config_.subscriberDomainSize(); ++index) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) %T INFO: creating data reader listener for domain %d.\n"), this->config_.subscriberDomain( index) )); this->listener_[ index] = new ForwardingListenerImpl( TheServiceParticipant->domain_to_repo( this->config_.subscriberDomain( index) )); this->forwarder_[ index] = dynamic_cast<ForwardingListenerImpl*>(this->listener_[ index].in()); if (CORBA::is_nil (this->listener_[ index].in ())) { ACE_ERROR((LM_ERROR, ACE_TEXT ("(%P|%t) %T ERROR: failed to obtain listener for domain %d.\n"), this->config_.subscriberDomain( index) )); throw BadReaderListenerException (); } } // // Establish the Type Support for the data in each participant. (??) // for( ParticipantMap::const_iterator current = this->participants_.begin(); current != this->participants_.end(); ++current) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) %T INFO: Installing type %C support into domain %d.\n"), this->config_.typeName().c_str(), current->first )); if( 0 == CORBA::is_nil( current->second.in())) { ::Xyz::FooNoKeyTypeSupportImpl* subscriber_data = new ::Xyz::FooNoKeyTypeSupportImpl(); if(::DDS::RETCODE_OK != subscriber_data->register_type( current->second.in (), this->config_.typeName().c_str() ) ) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) %T ERROR: Unable to install type %C support for domain %d.\n"), this->config_.typeName().c_str(), current->first )); throw TestException (); } } } // // Establish the Subscriber Topics. // for( int index = 0; index < this->config_.readerTopicNameSize(); ++index) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) %T INFO: creating subscription[ %d] topic: %C.\n"), index, this->config_.readerTopicName( index).c_str() )); this->readerTopic_[ index] = this->participants_[ this->config_.subscriberDomain( index)]->create_topic( this->config_.readerTopicName( index).c_str(), this->config_.typeName().c_str(), TOPIC_QOS_DEFAULT, ::DDS::TopicListener::_nil(), ::OpenDDS::DCPS::DEFAULT_STATUS_MASK ); if( CORBA::is_nil( this->readerTopic_[ index].in()) ) { ACE_ERROR ((LM_ERROR, ACE_TEXT ("(%P|%t) %T ERROR: Failed to create topic %C for subscriber[ %d].\n"), this->config_.readerTopicName( index).c_str(), index )); throw BadTopicException (); } } // // Establish the Publisher Topics. // for( int index = 0; index < this->config_.writerTopicNameSize(); ++index) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) %T INFO: creating publication[ %d] topic: %C.\n"), index, this->config_.writerTopicName( index).c_str() )); this->writerTopic_[ index] = this->participants_[ this->config_.publisherDomain( index)]->create_topic( this->config_.writerTopicName( index).c_str(), this->config_.typeName().c_str(), TOPIC_QOS_DEFAULT, ::DDS::TopicListener::_nil(), ::OpenDDS::DCPS::DEFAULT_STATUS_MASK ); if( CORBA::is_nil( this->writerTopic_[ index].in()) ) { ACE_ERROR ((LM_ERROR, ACE_TEXT ("(%P|%t) %T ERROR: Failed to create topic %C for publisher[ %d].\n"), this->config_.writerTopicName( index).c_str(), index )); throw BadTopicException (); } } // // Establish the Subscribers. // for( int index = 0; index < this->config_.subscriberDomainSize(); ++index) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) %T INFO: creating subscriber[ %d].\n"), index )); this->subscriber_[ index] = this->participants_[ this->config_.subscriberDomain( index)]->create_subscriber( SUBSCRIBER_QOS_DEFAULT, ::DDS::SubscriberListener::_nil(), ::OpenDDS::DCPS::DEFAULT_STATUS_MASK); if (CORBA::is_nil (this->subscriber_[ index].in ())) { ACE_ERROR ((LM_ERROR, ACE_TEXT ("(%P|%t) %T ERROR: Failed to create_subscriber[ %d].\n"), index )); throw BadSubscriberException (); } // Attach the subscriber to the transport. OpenDDS::DCPS::SubscriberImpl* sub_impl = dynamic_cast<OpenDDS::DCPS::SubscriberImpl*>( this->subscriber_[ index].in () ); if (0 == sub_impl) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) %T ERROR: Failed to obtain subscriber servant[ %d]\n"), index )); throw BadSubscriberException (); } OpenDDS::DCPS::AttachStatus attach_status; ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) %T INFO: attaching subscriber[ %d] to transport \n"), index )); attach_status = sub_impl->attach_transport( this->transport_[ TheServiceParticipant->domain_to_repo( this->config_.subscriberDomain( index)) ].in() ); if (attach_status != OpenDDS::DCPS::ATTACH_OK) { // We failed to attach to the transport for some reason. ACE_TString status_str; switch (attach_status) { case OpenDDS::DCPS::ATTACH_BAD_TRANSPORT: status_str = ACE_TEXT("ATTACH_BAD_TRANSPORT"); break; case OpenDDS::DCPS::ATTACH_ERROR: status_str = ACE_TEXT("ATTACH_ERROR"); break; case OpenDDS::DCPS::ATTACH_INCOMPATIBLE_QOS: status_str = ACE_TEXT("ATTACH_INCOMPATIBLE_QOS"); break; default: status_str = ACE_TEXT("Unknown Status"); break; } ACE_ERROR ((LM_ERROR, ACE_TEXT("(%P|%t) %T ERROR: Failed to attach to the transport. ") ACE_TEXT("AttachStatus == %s\n"), status_str.c_str())); throw BadTransportException (); } } // // Establish the Publishers. // for( int index = 0; index < this->config_.publisherDomainSize(); ++index) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) %T INFO: creating publisher[ %d].\n"), index )); this->publisher_[ index] = this->participants_[ this->config_.publisherDomain( index)]->create_publisher( PUBLISHER_QOS_DEFAULT, ::DDS::PublisherListener::_nil(), ::OpenDDS::DCPS::DEFAULT_STATUS_MASK); if (CORBA::is_nil (this->publisher_[ index].in ())) { ACE_ERROR ((LM_ERROR, ACE_TEXT ("(%P|%t) %T ERROR: Failed to create_publisher[ %d].\n"), index )); throw BadSubscriberException (); } // Attach the publisher to the transport. OpenDDS::DCPS::PublisherImpl* pub_impl = dynamic_cast<OpenDDS::DCPS::PublisherImpl*>( this->publisher_[ index].in () ); if (0 == pub_impl) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) %T ERROR: Failed to obtain publisher servant[ %d]\n"), index )); throw BadSubscriberException (); } OpenDDS::DCPS::AttachStatus attach_status; ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) %T INFO: attaching publisher[ %d] to transport \n"), index )); attach_status = pub_impl->attach_transport( this->transport_[ TheServiceParticipant->domain_to_repo( this->config_.publisherDomain( index)) ].in() ); if (attach_status != OpenDDS::DCPS::ATTACH_OK) { // We failed to attach to the transport for some reason. ACE_TString status_str; switch (attach_status) { case OpenDDS::DCPS::ATTACH_BAD_TRANSPORT: status_str = ACE_TEXT("ATTACH_BAD_TRANSPORT"); break; case OpenDDS::DCPS::ATTACH_ERROR: status_str = ACE_TEXT("ATTACH_ERROR"); break; case OpenDDS::DCPS::ATTACH_INCOMPATIBLE_QOS: status_str = ACE_TEXT("ATTACH_INCOMPATIBLE_QOS"); break; default: status_str = ACE_TEXT("Unknown Status"); break; } ACE_ERROR ((LM_ERROR, ACE_TEXT("(%P|%t) %T ERROR: Failed to attach to the transport. ") ACE_TEXT("AttachStatus == %s\n"), status_str.c_str())); throw BadTransportException (); } } // // Establish and install the DataWriter. // for( int index = 0; index < this->config_.publisherDomainSize(); ++index) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) %T INFO: creating datawriter[ %d].\n"), index )); ::DDS::DataWriterListener_var listener ( new DataWriterListenerImpl( TheServiceParticipant->domain_to_repo( this->config_.publisherDomain( index) ))); // // Keep all data samples to allow us to establish connections in an // arbitrary order, with samples being buffered at the first writer // that has not yet had a subscription match. // ::DDS::DataWriterQos writerQos; this->publisher_[ index]->get_default_datawriter_qos( writerQos); writerQos.durability.kind = ::DDS::TRANSIENT_LOCAL_DURABILITY_QOS; writerQos.history.kind = ::DDS::KEEP_ALL_HISTORY_QOS; writerQos.resource_limits.max_samples_per_instance = ::DDS::LENGTH_UNLIMITED; writerQos.reliability.kind = ::DDS::RELIABLE_RELIABILITY_QOS; writerQos.reliability.max_blocking_time.sec = 0; writerQos.reliability.max_blocking_time.nanosec = 0; this->dataWriter_[ index] = this->publisher_[ index]->create_datawriter(this->writerTopic_[ index].in(), writerQos, listener.in(), ::OpenDDS::DCPS::DEFAULT_STATUS_MASK); if( CORBA::is_nil( this->dataWriter_[ index].in()) ) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) %T ERROR: create datawriter[ %d] failed.\n"), index )); throw BadWriterException (); } } for( unsigned int index = 1; index < this->forwarder_.size(); ++index) { // Pass the writer into the (previous) forwarder. this->forwarder_[ index - 1]->dataWriter( this->dataWriter_[ index].in()); } // The last forwarder does not. this->forwarder_[ this->forwarder_.size() - 1]->dataWriter( ::DDS::DataWriter::_nil() ); // // Establish and install the DataReader. This needs to be done after // the writer has been created and attached since it is possible (I // know, I've seen it happen!) that messages can be received and // forwarded between the time the reader is created and the writer is // created and attached to the forwarder if we do it the other way // round. // for( int index = 0; index < this->config_.subscriberDomainSize(); ++index) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) %T INFO: creating data reader[ %d].\n"), index )); ::DDS::TopicDescription_var description = this->participants_[ this->config_.subscriberDomain( index)]->lookup_topicdescription( this->config_.readerTopicName( index).c_str() ); this->dataReader_[ index] = this->subscriber_[ index]->create_datareader( description.in(), DATAREADER_QOS_DEFAULT, this->listener_[ index].in (), ::OpenDDS::DCPS::DEFAULT_STATUS_MASK ); if( CORBA::is_nil( this->dataReader_[ index].in()) ) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) %T ERROR: create datareader[ %d] failed.\n"), index )); throw BadReaderException (); } } }
void Publication::enable( ::DDS::DomainParticipant_ptr participant, ::DDS::Topic_ptr topic ) { if( this->enabled_) { if( this->verbose_) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) Publication::enable() - publication %C: ") ACE_TEXT("already enabled, declining to process.\n"), this->name_.c_str() )); } return; } // Create the publisher. publisher_ = participant->create_publisher( this->profile_->publisherQos, ::DDS::PublisherListener::_nil(), ::OpenDDS::DCPS::DEFAULT_STATUS_MASK ); if( CORBA::is_nil( publisher_.in())) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) Publication::enable() - publication %C: ") ACE_TEXT("failed to create publisher.\n"), this->name_.c_str() )); throw BadPublisherException(); } OpenDDS::DCPS::TransportConfig_rch transport = TheTransportRegistry->get_config(this->profile_->transportConfig); if (transport.is_nil() || transport->instances_.empty()) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) Publication::enable() - publication %C: ") ACE_TEXT("failed to get_config() OR got empty config with name %C.\n"), this->name_.c_str(), this->profile_->transportConfig.c_str() )); throw BadTransportException(); } if (this->verbose_) { OpenDDS::DCPS::MulticastInst* mcconfig = dynamic_cast<OpenDDS::DCPS::MulticastInst*>( transport->instances_[0].in() ); bool isMcast = false; bool isReliable = false; if (mcconfig != 0) { isMcast = true; isReliable = mcconfig->reliable_; } ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) Publication::enable() - publication %C: ") ACE_TEXT("%C %C transport with config %C.\n"), this->name_.c_str(), (!isMcast? "obtained": (isReliable? "obtained reliable": "obtained best effort" )), transport->instances_[0]->transport_type_.c_str(), this->profile_->transportConfig.c_str() )); } // Attach the transport TheTransportRegistry->bind_config(transport, publisher_); if (this->verbose_) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) Publication::enable() - publication %C: ") ACE_TEXT("attached transport with config %C to publisher.\n"), this->name_.c_str(), this->profile_->transportConfig.c_str() )); } // Derive the writer Qos values. ::DDS::TopicQos topicQos; topic->get_qos( topicQos); ::DDS::DataWriterQos writerQos; publisher_->get_default_datawriter_qos( writerQos); publisher_->copy_from_topic_qos( writerQos, topicQos); this->profile_->copyToWriterQos( writerQos); // Create the writer. DDS::DataWriter_var writer = publisher_->create_datawriter( topic, writerQos, ::DDS::DataWriterListener::_nil(), ::OpenDDS::DCPS::DEFAULT_STATUS_MASK ); if( CORBA::is_nil( writer.in())) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) Publication::enable() - publication %C: ") ACE_TEXT("failed to create writer.\n"), this->name_.c_str() )); throw BadWriterException(); } else if( this->verbose_) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) Publication::enable() - publication %C: ") ACE_TEXT("created writer.\n"), this->name_.c_str() )); } this->writer_ = Test::DataDataWriter::_narrow( writer.in()); if( CORBA::is_nil( this->writer_.in())) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) Publication::enable() - publication %C: ") ACE_TEXT("failed to narrow writer for Test::Data type.\n"), this->name_.c_str() )); throw BadWriterException(); } else if( this->verbose_) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) Publication::enable() - publication %C: ") ACE_TEXT("narrowed writer for Test::Data type.\n"), this->name_.c_str() )); } // We can finally indicate successful completion. this->enabled_ = true; }
/** * @brief Construct a test system from the command line. */ Publisher::Publisher( int argc, char** argv, char** envp) : config_( argc, argv, envp) { // Grab a local reference to the factory ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) INFO: initializing the publisher.\n"))); ::DDS::DomainParticipantFactory_var factory = TheParticipantFactoryWithArgs( argc, argv); if( OpenDDS::DCPS::DCPS_debug_level > 0) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) COMMANDLINE: Verbose == %s\n") ACE_TEXT("(%P|%t) COMMANDLINE: Samples == %d\n"), (this->config_.verbose()? "true": "false"), this->config_.samples() )); } // // Establish DomainParticipant // if( OpenDDS::DCPS::DCPS_debug_level > 0) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) INFO: creating publisher participant in domain %d.\n"), this->config_.domain() )); } this->participant_ = factory->create_participant( this->config_.domain(), PARTICIPANT_QOS_DEFAULT, ::DDS::DomainParticipantListener::_nil() ); if( CORBA::is_nil( this->participant_.in())) { ACE_ERROR ((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: create_participant failed for ") ACE_TEXT("publisher in domain %d.\n"), this->config_.domain() )); throw BadParticipantException (); } // // Grab and install the transport implementation. // // Establish debug level. if( this->config_.verbose()) { TURN_ON_VERBOSE_DEBUG; } if( OpenDDS::DCPS::DCPS_debug_level > 0) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) INFO: creating a SimpleTCP transport.\n"))); } this->transport_ = TheTransportFactory->create_transport_impl( 0, "SimpleTcp", OpenDDS::DCPS::DONT_AUTO_CONFIG ); OpenDDS::DCPS::TransportConfiguration_rch transport_config = TheTransportFactory->create_configuration( 0, ACE_TString("SimpleTcp") ); #if 0 OpenDDS::DCPS::SimpleTcpConfiguration* tcp_config = static_cast <OpenDDS::DCPS::SimpleTcpConfiguration*>( transport_config.in() ); std::string address; if( address.length() > 0) { ACE_INET_Addr reader_address( address.c_str()); tcp_config->local_address_ = reader_address; } #endif if( this->transport_->configure( transport_config.in()) != 0) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: TCP ") ACE_TEXT("failed to configure the transport.\n") )); throw BadTransportException (); } // // Establish the Type Support for the data // if( OpenDDS::DCPS::DCPS_debug_level > 0) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) INFO: Installing type %s support into domain %d.\n"), this->config_.typeName().c_str(), this->config_.domain() )); } ::Xyz::FooNoKeyTypeSupportImpl* publisher_data = new ::Xyz::FooNoKeyTypeSupportImpl(); if(::DDS::RETCODE_OK != publisher_data->register_type( this->participant_.in(), this->config_.typeName().c_str() ) ) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: Unable to install type %s support for domain %d.\n"), this->config_.typeName().c_str(), this->config_.domain() )); throw TestException (); } // // Establish the Topic // this->topic_ = this->participant_->create_topic( this->config_.topicName().c_str(), this->config_.typeName().c_str(), TOPIC_QOS_DEFAULT, ::DDS::TopicListener::_nil() ); if( CORBA::is_nil( this->topic_.in()) ) { ACE_ERROR ((LM_ERROR, ACE_TEXT ("(%P|%t) ERROR: Failed to create topic %s for publisher.\n"), this->config_.topicName().c_str() )); throw BadTopicException (); } // // Establish the Publisher // this->publisher_ = this->participant_->create_publisher( PUBLISHER_QOS_DEFAULT, ::DDS::PublisherListener::_nil() ); if( CORBA::is_nil (this->publisher_.in ())) { ACE_ERROR ((LM_ERROR, ACE_TEXT ("(%P|%t) ERROR: Failed to create_publisher.\n"))); throw BadPublisherException (); } // Attach the publisher to the transport. OpenDDS::DCPS::PublisherImpl* pub_impl = dynamic_cast<OpenDDS::DCPS::PublisherImpl*>( this->publisher_.in() ); if (0 == pub_impl) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: Failed to obtain publisher servant\n"))); throw BadPublisherException (); } OpenDDS::DCPS::AttachStatus attach_status; if( OpenDDS::DCPS::DCPS_debug_level > 0) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) INFO: attaching publisher to transport \n"))); } attach_status = pub_impl->attach_transport( this->transport_.in()); if (attach_status != OpenDDS::DCPS::ATTACH_OK) { // We failed to attach to the transport for some reason. ACE_TString status_str; switch (attach_status) { case OpenDDS::DCPS::ATTACH_BAD_TRANSPORT: status_str = "ATTACH_BAD_TRANSPORT"; break; case OpenDDS::DCPS::ATTACH_ERROR: status_str = "ATTACH_ERROR"; break; case OpenDDS::DCPS::ATTACH_INCOMPATIBLE_QOS: status_str = "ATTACH_INCOMPATIBLE_QOS"; break; default: status_str = "Unknown Status"; break; } ACE_ERROR ((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: Failed to attach to the transport. ") ACE_TEXT("AttachStatus == %s\n"), status_str.c_str())); throw BadTransportException (); } // // Establish and install the DataWriter. // if( OpenDDS::DCPS::DCPS_debug_level > 0) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) INFO: creating datawriter.\n"))); } // // Keep all data samples to allow us to establish connections in an // arbitrary order, with samples being buffered at the first writer // that has not yet had a subscription match. // ::DDS::DataWriterQos writerQos; this->publisher_->get_default_datawriter_qos( writerQos); writerQos.durability.kind = ::DDS::TRANSIENT_LOCAL_DURABILITY_QOS; writerQos.history.kind = ::DDS::KEEP_ALL_HISTORY_QOS; writerQos.resource_limits.max_samples_per_instance = ::DDS::LENGTH_UNLIMITED; writerQos.reliability.kind = ::DDS::RELIABLE_RELIABILITY_QOS; writerQos.reliability.max_blocking_time.sec = 0; writerQos.reliability.max_blocking_time.nanosec = 0; this->dataWriter_ = this->publisher_->create_datawriter( this->topic_.in(), writerQos, ::DDS::DataWriterListener::_nil() ); if( CORBA::is_nil( this->dataWriter_.in()) ) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: create datawriter failed.\n"))); throw BadWriterException (); } }
Publisher::Publisher( const Options& options) : options_( options), waiter_( new DDS::WaitSet) { DDS::DomainParticipantFactory_var dpf = TheParticipantFactory; // Create the DomainParticipant this->participant_ = dpf->create_participant( this->options_.domain(), PARTICIPANT_QOS_DEFAULT, DDS::DomainParticipantListener::_nil(), ::OpenDDS::DCPS::DEFAULT_STATUS_MASK ); if( CORBA::is_nil( this->participant_.in())) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: Publisher::Publisher() - ") ACE_TEXT("failed to create a participant.\n") )); throw BadParticipantException(); } else if( this->options_.verbose()) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) Publisher::Publisher() - ") ACE_TEXT("created participant in domain %d.\n"), this->options_.domain() )); } // Create the transport. OpenDDS::DCPS::TransportConfig_rch transport = TheTransportRegistry->get_config(this->options_.transportKey()); if (transport.is_nil()) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: Subscriber::Subscriber() - ") ACE_TEXT("failed to get %C transport.\n"), this->options_.transportKey().c_str() )); throw BadTransportException(); } else if( this->options_.verbose()) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) Subscriber::Subscriber() - ") ACE_TEXT("created %C transport.\n"), this->options_.transportKey().c_str() )); } // Create and register the type support. DataTypeSupportImpl* testData = new DataTypeSupportImpl(); if( ::DDS::RETCODE_OK != testData->register_type( this->participant_.in(), 0)) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: Publisher::Publisher() - ") ACE_TEXT("unable to install type %C support.\n"), testData->get_type_name() )); throw BadTypeSupportException (); } else if( this->options_.verbose()) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) Publisher::Publisher() - ") ACE_TEXT("created type %C support.\n"), testData->get_type_name() )); } // Create the topic. this->topic_ = this->participant_->create_topic( this->options_.topicName().c_str(), testData->get_type_name(), TOPIC_QOS_DEFAULT, ::DDS::TopicListener::_nil(), ::OpenDDS::DCPS::DEFAULT_STATUS_MASK ); if( CORBA::is_nil( this->topic_.in())) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: Publisher::Publisher() - ") ACE_TEXT("failed to create topic %C.\n"), this->options_.topicName().c_str() )); throw BadTopicException(); } else if( this->options_.verbose()) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) Publisher::Publisher() - ") ACE_TEXT("created topic %C.\n"), this->options_.topicName().c_str() )); } // Create the publisher. this->publisher_ = this->participant_->create_publisher( PUBLISHER_QOS_DEFAULT, ::DDS::PublisherListener::_nil(), ::OpenDDS::DCPS::DEFAULT_STATUS_MASK ); if( CORBA::is_nil( this->publisher_.in())) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: Publisher::Publisher() - ") ACE_TEXT("failed to create publisher.\n") )); throw BadPublisherException(); } else if( this->options_.verbose()) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) Publisher::Publisher() - ") ACE_TEXT("created publisher.\n") )); } TheTransportRegistry->bind_config(transport, this->publisher_); if( this->options_.verbose()) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) Publisher::Publisher() - ") ACE_TEXT("attached transport to publisher.\n") )); } // Writer Qos policy values. ::DDS::DataWriterQos writerQos; this->publisher_->get_default_datawriter_qos( writerQos); writerQos.durability.kind = ::DDS::TRANSIENT_LOCAL_DURABILITY_QOS; writerQos.history.kind = ::DDS::KEEP_ALL_HISTORY_QOS; writerQos.resource_limits.max_samples_per_instance = ::DDS::LENGTH_UNLIMITED; // Reliability varies with the transport implementation. switch( this->options_.transportType()) { case Options::TCP: case Options::MC: writerQos.reliability.kind = ::DDS::RELIABLE_RELIABILITY_QOS; break; case Options::UDP: writerQos.reliability.kind = ::DDS::BEST_EFFORT_RELIABILITY_QOS; break; case Options::TRANSPORT_NONE: default: ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: Publisher::Publisher() - ") ACE_TEXT("unrecognized transport when setting up Qos policies.\n") )); throw BadQosException(); } if( this->options_.verbose()) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) Publisher::Publisher() - ") ACE_TEXT("starting to create %d publications.\n"), this->options_.profiles().size() )); } // Build as many publications as are specified. for( unsigned int index = 0; index < this->options_.profiles().size(); ++index) { // This publications priority is needed when creating the writer. writerQos.transport_priority.value = this->options_.profiles()[ index]->priority(); // Create the writer. DDS::DataWriter_var writer = this->publisher_->create_datawriter( this->topic_.in(), writerQos, DDS::DataWriterListener::_nil(), ::OpenDDS::DCPS::DEFAULT_STATUS_MASK ); if( CORBA::is_nil( writer.in())) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: Publisher::Publisher() - ") ACE_TEXT("failed to create writer.\n") )); throw BadWriterException(); } else if( this->options_.verbose()) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) Publisher::Publisher() - ") ACE_TEXT("created writer for publication %C ") ACE_TEXT("with priority %d.\n"), this->options_.profiles()[ index]->name().c_str(), writerQos.transport_priority.value )); } // Create a publication and store it. this->publications_[ this->options_.profiles()[ index]->name()] = new Writer( writer.in(), *this->options_.profiles()[ index], this->options_.verbose() ); // // Grab, enable and attach the status condition for test // synchronization of the current publication. // DDS::StatusCondition_var status = writer->get_statuscondition(); status->set_enabled_statuses( DDS::PUBLICATION_MATCHED_STATUS); this->waiter_->attach_condition( status.in()); if( this->options_.verbose()) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) Publisher::Publisher() - ") ACE_TEXT("created StatusCondition for publication %C.\n"), this->options_.profiles()[ index]->name().c_str() )); } } }
Subscriber::Subscriber( const Options& options) : options_( options), waiter_( new DDS::WaitSet) { // Create the DomainParticipant this->participant_ = TheParticipantFactory->create_participant( this->options_.domain(), PARTICIPANT_QOS_DEFAULT, DDS::DomainParticipantListener::_nil(), ::OpenDDS::DCPS::DEFAULT_STATUS_MASK ); if( CORBA::is_nil( this->participant_.in())) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: Subscriber::Subscriber() - ") ACE_TEXT("failed to create a participant.\n") )); throw BadParticipantException(); } else if( this->options_.verbose()) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) Subscriber::Subscriber() - ") ACE_TEXT("created participant in domain %d.\n"), this->options_.domain() )); } // Create and register the type support. DataTypeSupportImpl* testData = new DataTypeSupportImpl(); if( ::DDS::RETCODE_OK != testData->register_type( this->participant_.in(), 0)) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: Subscriber::Subscriber() - ") ACE_TEXT("unable to install type %C support.\n"), testData->get_type_name() )); throw BadTypeSupportException (); } else if( this->options_.verbose()) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) Subscriber::Subscriber() - ") ACE_TEXT("created type %C support.\n"), testData->get_type_name() )); } // Create the topic. DDS::Topic_var topic = this->participant_->create_topic( this->options_.topicName().c_str(), testData->get_type_name(), TOPIC_QOS_DEFAULT, ::DDS::TopicListener::_nil(), ::OpenDDS::DCPS::DEFAULT_STATUS_MASK ); if( CORBA::is_nil( topic.in())) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: Subscriber::Subscriber() - ") ACE_TEXT("failed to create topic %C.\n"), this->options_.topicName().c_str() )); throw BadTopicException(); } else if( this->options_.verbose()) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) Subscriber::Subscriber() - ") ACE_TEXT("created topic %C.\n"), this->options_.topicName().c_str() )); } // Create the subscriber. DDS::Subscriber_var subscriber = this->participant_->create_subscriber( SUBSCRIBER_QOS_DEFAULT, ::DDS::SubscriberListener::_nil(), ::OpenDDS::DCPS::DEFAULT_STATUS_MASK ); if( CORBA::is_nil( subscriber.in())) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: Subscriber::Subscriber() - ") ACE_TEXT("failed to create subscriber.\n") )); throw BadSubscriberException(); } else if( this->options_.verbose()) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) Subscriber::Subscriber() - ") ACE_TEXT("created subscriber.\n") )); } // Create the transport. OpenDDS::DCPS::TransportImpl_rch transport = TheTransportFactory->create_transport_impl( this->options_.transportKey(), OpenDDS::DCPS::AUTO_CONFIG ); if( transport.is_nil()) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: Subscriber::Subscriber() - ") ACE_TEXT("failed to create transport.\n") )); throw BadTransportException(); } else if( this->options_.verbose()) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) Subscriber::Subscriber() - ") ACE_TEXT("created transport.\n") )); } // Attach the transport. if( ::OpenDDS::DCPS::ATTACH_OK != transport->attach( subscriber.in())) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: Subscriber::Subscriber() - ") ACE_TEXT("failed to attach subscriber to transport.\n") )); throw BadAttachException(); } else if( this->options_.verbose()) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) Subscriber::Subscriber() - ") ACE_TEXT("attached subscriber to transport.\n") )); } // Reader Qos policy values. ::DDS::DataReaderQos readerQos; subscriber->get_default_datareader_qos( readerQos); readerQos.reliability.kind = ::DDS::RELIABLE_RELIABILITY_QOS; // Create the readers. for( int index = 0; index < 2; ++index) { ::DDS::DataReader_var reader = subscriber->create_datareader( topic.in(), readerQos, DDS::DataReaderListener::_nil(), ::OpenDDS::DCPS::DEFAULT_STATUS_MASK ); if( CORBA::is_nil( reader.in())) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: Subscriber::Subscriber() - ") ACE_TEXT("failed to create reader.\n") )); throw BadReaderException(); } else if( this->options_.verbose()) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) Subscriber::Subscriber() - ") ACE_TEXT("created reader.\n") )); } this->reader_[ index] = ::OpenDDS::DCPS::DataReaderEx::_narrow( reader.in()); if( CORBA::is_nil( this->reader_[ index].in())) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: Subscriber::Subscriber() - ") ACE_TEXT("failed to narrow reader to extract statistics.\n") )); throw BadReaderException(); } // Grab, enable and attach the status condition for test synchronization. this->status_ = this->reader_[ index]->get_statuscondition(); this->status_->set_enabled_statuses( DDS::SUBSCRIPTION_MATCHED_STATUS); this->waiter_->attach_condition( this->status_.in()); if( this->options_.verbose()) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) Subscriber::Subscriber() - ") ACE_TEXT("created StatusCondition and WaitSet for test synchronization.\n") )); } } }
Subscriber::Subscriber( const Options& options) : options_( options), listener_( 0), waiter_( new DDS::WaitSet) { DDS::DomainParticipantFactory_var dpf = TheParticipantFactory; // Create the DomainParticipant this->participant_ = dpf->create_participant( this->options_.domain(), PARTICIPANT_QOS_DEFAULT, DDS::DomainParticipantListener::_nil(), ::OpenDDS::DCPS::DEFAULT_STATUS_MASK ); if( CORBA::is_nil( this->participant_.in())) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: Subscriber::Subscriber() - ") ACE_TEXT("failed to create a participant.\n") )); throw BadParticipantException(); } else if( this->options_.verbose()) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) Subscriber::Subscriber() - ") ACE_TEXT("created participant in domain %d.\n"), this->options_.domain() )); } // Create the transport. OpenDDS::DCPS::TransportConfig_rch transport = TheTransportRegistry->get_config(this->options_.transportKey()); if (transport.is_nil()) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: Subscriber::Subscriber() - ") ACE_TEXT("failed to get %C transport.\n"), this->options_.transportKey().c_str() )); throw BadTransportException(); } else if( this->options_.verbose()) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) Subscriber::Subscriber() - ") ACE_TEXT("created %C transport.\n"), this->options_.transportKey().c_str() )); } // Create the listener. this->listener_ = new DataReaderListener( this->options_.verbose()); this->safe_listener_ = this->listener_; if( this->options_.verbose()) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) Subscriber::Subscriber() - ") ACE_TEXT("created reader listener.\n") )); } // Create and register the type support. DataTypeSupportImpl* testData = new DataTypeSupportImpl(); if( ::DDS::RETCODE_OK != testData->register_type( this->participant_.in(), 0)) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: Subscriber::Subscriber() - ") ACE_TEXT("unable to install type %C support.\n"), testData->get_type_name() )); throw BadTypeSupportException (); } else if( this->options_.verbose()) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) Subscriber::Subscriber() - ") ACE_TEXT("created type %C support.\n"), testData->get_type_name() )); } // Create the topic. this->topic_ = this->participant_->create_topic( this->options_.topicName().c_str(), testData->get_type_name(), TOPIC_QOS_DEFAULT, ::DDS::TopicListener::_nil(), ::OpenDDS::DCPS::DEFAULT_STATUS_MASK ); if( CORBA::is_nil( this->topic_.in())) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: Subscriber::Subscriber() - ") ACE_TEXT("failed to create topic %C.\n"), this->options_.topicName().c_str() )); throw BadTopicException(); } else if( this->options_.verbose()) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) Subscriber::Subscriber() - ") ACE_TEXT("created topic %C.\n"), this->options_.topicName().c_str() )); } // Create the subscriber. this->subscriber_ = this->participant_->create_subscriber( SUBSCRIBER_QOS_DEFAULT, ::DDS::SubscriberListener::_nil(), ::OpenDDS::DCPS::DEFAULT_STATUS_MASK ); if( CORBA::is_nil( this->subscriber_.in())) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: Subscriber::Subscriber() - ") ACE_TEXT("failed to create subscriber.\n") )); throw BadSubscriberException(); } else if( this->options_.verbose()) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) Subscriber::Subscriber() - ") ACE_TEXT("created subscriber.\n") )); } // Attach the transport to the subscriber. ::OpenDDS::DCPS::SubscriberImpl* servant = dynamic_cast< ::OpenDDS::DCPS::SubscriberImpl*>( this->subscriber_.in()); if( 0 == servant) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: Subscriber::Subscriber() - ") ACE_TEXT("failed to narrow subscriber servant.\n") )); throw BadServantException(); } // Configure the raw data gathering. servant->raw_latency_buffer_size() = this->options_.raw_buffer_size(); servant->raw_latency_buffer_type() = this->options_.raw_buffer_type(); if( this->options_.verbose()) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) Subscriber::Subscriber() - ") ACE_TEXT("configured to capture %d latency measurements of type %d ") ACE_TEXT("per writer to file %C.\n"), this->options_.raw_buffer_size(), this->options_.raw_buffer_type(), this->options_.rawOutputFilename().c_str() )); } TheTransportRegistry->bind_config(transport, servant); if( this->options_.verbose()) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) Subscriber::Subscriber() - ") ACE_TEXT("attached transport to subscriber.\n") )); } // Reader Qos policy values. ::DDS::DataReaderQos readerQos; this->subscriber_->get_default_datareader_qos( readerQos); readerQos.durability.kind = ::DDS::TRANSIENT_LOCAL_DURABILITY_QOS; readerQos.history.kind = ::DDS::KEEP_ALL_HISTORY_QOS; readerQos.resource_limits.max_samples_per_instance = ::DDS::LENGTH_UNLIMITED; // Reliability varies with the transport implementation. switch( this->options_.transportType()) { case Options::TCP: case Options::MC: readerQos.reliability.kind = ::DDS::RELIABLE_RELIABILITY_QOS; break; case Options::UDP: readerQos.reliability.kind = ::DDS::BEST_EFFORT_RELIABILITY_QOS; break; case Options::TRANSPORT_NONE: default: ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: Subscriber::Subscriber() - ") ACE_TEXT("unrecognized transport when setting up Qos policies.\n") )); throw BadQosException(); } // Create the reader. ::DDS::DataReader_var reader = this->subscriber_->create_datareader( this->topic_.in(), readerQos, DDS::DataReaderListener::_nil(), ::OpenDDS::DCPS::DEFAULT_STATUS_MASK ); if( CORBA::is_nil( reader.in())) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: Subscriber::Subscriber() - ") ACE_TEXT("failed to create reader.\n") )); throw BadReaderException(); } else if( this->options_.verbose()) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) Subscriber::Subscriber() - ") ACE_TEXT("created reader.\n") )); } this->reader_ = ::OpenDDS::DCPS::DataReaderEx::_narrow( reader.in()); if( CORBA::is_nil( this->reader_.in())) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: Subscriber::Subscriber() - ") ACE_TEXT("failed to narrow reader to extract statistics.\n") )); throw BadReaderException(); } // Clear and start statistics gathering. Ideally we would want to // configurably delay the start here to avoid edge effects. this->reader_->reset_latency_stats(); this->reader_->statistics_enabled( true); // Set the listener mask here so that we don't conflict with the // StatusCondition(s) that we want to wait on in the main thread. this->reader_->set_listener( this->listener_, DDS::DATA_AVAILABLE_STATUS); // Grab, enable and attach the status condition for test synchronization. this->status_ = this->reader_->get_statuscondition(); this->status_->set_enabled_statuses( DDS::SUBSCRIPTION_MATCHED_STATUS); this->waiter_->attach_condition( this->status_.in()); if( this->options_.verbose()) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) Subscriber::Subscriber() - ") ACE_TEXT("created StatusCondition and WaitSet for test synchronization.\n") )); } }