/// This method is called when the (remote) subscriber is being /// released. This method will return a 0 if the subscriber_id is /// successfully disassociated with the publisher_id *and* there /// are still other subscribers associated with the publisher_id. /// This method will return 1 if, after the disassociation, the /// publisher_id is no longer associated with any subscribers (which /// also means it's element was removed from our map_). int OpenDDS::DCPS::ReceiveListenerSetMap::release_subscriber(RepoId publisher_id, RepoId subscriber_id) { DBG_ENTRY_LVL("ReceiveListenerSetMap","release_subscriber",6); ReceiveListenerSet_rch listener_set; if (OpenDDS::DCPS::find(map_, publisher_id, listener_set) != 0) { GuidConverter converter(publisher_id); ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: ReciveListenerSetMap::release_subscriber: ") ACE_TEXT("publisher %C not found in map_.\n"), std::string(converter).c_str())); // Return 1 to indicate that the publisher_id is no longer associated // with any subscribers at all. return 1; } int result = listener_set->remove(subscriber_id); // Ignore the result ACE_UNUSED_ARG(result); if (listener_set->size() == 0) { if (unbind(map_, publisher_id) != 0) { GuidConverter converter(publisher_id); ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: ReceiveListenerSetMap::release_subscriber: ") ACE_TEXT("failed to remove empty ReceiveListenerSet for ") ACE_TEXT("publisher %C.\n"), std::string(converter).c_str())); } // We always return 1 if we know the publisher_id is no longer // associated with any ReceiveListeners. return 1; } // There are still ReceiveListeners associated with the publisher_id. // We return a 0 in this case. return 0; }
void DataLink::transport_shutdown() { DBG_ENTRY_LVL("DataLink", "transport_shutdown", 6); if (!this->send_strategy_.is_nil()) { this->send_strategy_->transport_shutdown(); } //this->cancel_release(); this->set_scheduling_release(false); this->scheduled_to_stop_at_ = ACE_Time_Value::zero; ACE_Reactor_Timer_Interface* reactor = this->impl_->timer(); reactor->cancel_timer(this); this->stop(); // Drop our reference to the TransportImpl object this->impl_ = 0; }
void OpenDDS::DCPS::ThreadPerConnectionSendTask::execute(SendRequest& req) { DBG_ENTRY_LVL("ThreadPerConnectionSendTask","execute",6); switch (req.op_) { case SEND_START: this->link_->send_start_i(); break; case SEND: this->link_->send_i(req.element_); break; case SEND_STOP: this->link_->send_stop_i(); break; default: ACE_ERROR((LM_ERROR, "(%P|%t) ERROR: ThreadPerConnectionSendTask::execute unknown command %d\n", req.op_)); break; } }
// This version removes an entire RepoIdSet from the map_. OpenDDS::DCPS::RepoIdSet* OpenDDS::DCPS::RepoIdSetMap::remove_set(RepoId key) { DBG_ENTRY_LVL("RepoIdSetMap","remove_set",6); RepoIdSet_rch value; if (unbind(map_, key, value) != 0) { if (DCPS_debug_level > 4) { RepoIdConverter converter(key); ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) RepeIdSetMap::remove_set: ") ACE_TEXT("RepoId %C not found in map.\n"), std::string(converter).c_str())); } return 0; } return value._retn(); }
void OpenDDS::DCPS::RepoIdSetMap::dump() { DBG_ENTRY_LVL("RepoIdSetMap","dump",6); for (MapType::iterator itr = map_.begin(); itr != map_.end(); ++itr) { RepoIdSet_rch set = itr->second; for (RepoIdSet::MapType::iterator it = set->map().begin(); it != set->map().end(); ++it) { std::stringstream buffer; buffer << "key " << itr->first << " - value " << it->first; ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) %C \n"), buffer.str().c_str())); } } }
SendControlStatus DataLink::send_control(const DataSampleHeader& header, ACE_Message_Block* message) { DBG_ENTRY_LVL("DataLink", "send_control", 6); TransportSendControlElement* const elem = TransportSendControlElement::alloc(1, // initial_count GUID_UNKNOWN, &send_response_listener_, header, message, send_control_allocator_); if (!elem) return SEND_CONTROL_ERROR; send_response_listener_.track_message(); RepoId senderId(header.publication_id_); send_start(); send(elem); send_stop(senderId); return SEND_CONTROL_OK; }
OpenDDS::DCPS::DataLink* OpenDDS::DCPS::TransportImpl::reserve_datalink( RepoId local_id, const AssociationData* remote_association, CORBA::Long priority, TransportSendListener* send_listener) { DBG_ENTRY_LVL("TransportImpl","reserve_datalink",6); // Ask our concrete subclass to find or create a (concrete) DataLink // that matches the supplied criterea. // Note that we pass-in true as the third argument. This means that // if a new DataLink needs to be created (ie, the find operation fails), // then the connection establishment logic will treat the local endpoint // as the publisher. This knowledge dictates whether a passive or active // connection establishment procedure should be followed. DataLink_rch link = this->find_or_create_datalink(local_id, remote_association, priority, true); if (link.is_nil()) { OpenDDS::DCPS::RepoIdConverter pub_converter(local_id); OpenDDS::DCPS::RepoIdConverter sub_converter(remote_association->remote_id_); ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: TransportImpl::reserve_datalink: ") ACE_TEXT("subclass was unable to find ") ACE_TEXT("or create a DataLink for local publisher_id %C ") ACE_TEXT("to remote subscriber_id %C.\n"), std::string(pub_converter).c_str(), std::string(sub_converter).c_str()),0); } link->make_reservation(remote_association->remote_id_, // subscription_id local_id, // publication_id send_listener); return link._retn(); }
/// The TcpTransport calls this method when it has an established /// connection object for us. This call puts this TcpDataLink into /// the "connected" state. int OpenDDS::DCPS::TcpDataLink::connect( const TcpConnection_rch& connection, const TransportSendStrategy_rch& send_strategy, const TransportStrategy_rch& receive_strategy) { DBG_ENTRY_LVL("TcpDataLink","connect",6); // Sanity check - cannot connect() if we are already connected. if (!this->connection_.is_nil()) { ACE_ERROR_RETURN((LM_ERROR, "(%P|%t) ERROR: TcpDataLink already connected.\n"), -1); } this->connection_ = connection; if (this->connection_->peer().enable(ACE_NONBLOCK) == -1) { ACE_ERROR_RETURN((LM_ERROR, "(%P|%t) ERROR: TcpDataLink::connect failed to set " "ACE_NONBLOCK %p\n", ACE_TEXT("enable")), -1); } // Let connection know the datalink for callbacks upon reconnect failure. this->connection_->set_datalink(this); // And lastly, inform our base class (DataLink) that we are now "connected", // and it should start the strategy objects. if (this->start(send_strategy, receive_strategy) != 0) { // Our base (DataLink) class failed to start the strategy objects. // We need to "undo" some things here before we return -1 to indicate // that an error has taken place. // Drop our reference to the connection object. this->connection_ = 0; return -1; } return 0; }
// This method is called on acceptor side when the lost connection is detected. // A timer is scheduled to check if a new connection is created within the // passive_reconnect_duration_ period. int OpenDDS::DCPS::TcpConnection::passive_reconnect_i() { DBG_ENTRY_LVL("TcpConnection","passive_reconnect_i",6); GuardType guard(this->reconnect_lock_); // The passive_reconnect_timer_id_ is used as flag to allow the timer scheduled just once. if (this->reconnect_state_ == INIT_STATE) { // Mark the connection lost since the recv/send just failed. this->connected_ = false; if (this->tcp_config_->passive_reconnect_duration_ == 0) return -1; ACE_Time_Value timeout(this->tcp_config_->passive_reconnect_duration_/1000, this->tcp_config_->passive_reconnect_duration_%1000 * 1000); this->reconnect_state_ = PASSIVE_WAITING_STATE; this->link_->notify(DataLink::DISCONNECTED); // It is possible that the passive reconnect is called after the new connection // is accepted and the receive_strategy of this old connection is reset to nil. if (!this->receive_strategy_.is_nil()) { TcpReceiveStrategy* rs = dynamic_cast <TcpReceiveStrategy*>(this->receive_strategy_.in()); // Give a copy to reactor. this->_add_ref(); this->passive_reconnect_timer_id_ = rs->get_reactor()->schedule_timer(this, 0, timeout); if (this->passive_reconnect_timer_id_ == -1) { this->_remove_ref(); ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: TcpConnection::passive_reconnect_i") ACE_TEXT(", %p.\n"), ACE_TEXT("schedule_timer")), -1); } } } return 0; }
void OpenDDS::DCPS::TcpReceiveStrategy::deliver_sample (ReceivedDataSample& sample, const ACE_INET_Addr&) { DBG_ENTRY_LVL("TcpReceiveStrategy","deliver_sample",6); if (sample.header_.message_id_ == GRACEFUL_DISCONNECT) { VDBG((LM_DEBUG, "(%P|%t) DBG: received GRACEFUL_DISCONNECT \n")); this->gracefully_disconnected_ = true; } else if (sample.header_.message_id_ == REQUEST_ACK) { VDBG((LM_DEBUG, "(%P|%t) DBG: received REQUEST_ACK \n")); this->link_->request_ack_received(sample); } else if (sample.header_.message_id_ == SAMPLE_ACK) { VDBG((LM_DEBUG, "(%P|%t) DBG: received SAMPLE_ACK \n")); this->link_->ack_received(sample); } else { this->link_->data_received(sample); } }
bool TcpTransport::connection_info_i(TransportLocator& local_info) const { DBG_ENTRY_LVL("TcpTransport", "connection_info_i", 6); VDBG_LVL((LM_DEBUG, "(%P|%t) TcpTransport public address str %C\n", this->tcp_config_->get_public_address().c_str()), 2); // Get the public address string from the inst (usually the local address) NetworkAddress network_order_address(this->tcp_config_->get_public_address()); ACE_OutputCDR cdr; cdr << network_order_address; const CORBA::ULong len = static_cast<CORBA::ULong>(cdr.total_length()); char* buffer = const_cast<char*>(cdr.buffer()); // safe local_info.transport_type = "tcp"; local_info.data = TransportBLOB(len, len, reinterpret_cast<CORBA::Octet*>(buffer)); return true; }
bool DataLink::cancel_release() { DBG_ENTRY_LVL("DataLink", "cancel_release", 6); if (stopped_) { if (DCPS_debug_level > 0) { ACE_DEBUG((LM_DEBUG, "(%P|%t) DataLink::cancel_release - link[%@] already stopped_ cannot cancel release\n", this)); } return false; } if (scheduling_release_) { if (DCPS_debug_level > 0) { ACE_DEBUG((LM_DEBUG, "(%P|%t) DataLink::cancel_release - link[%@] currently scheduling release, notify reactor of cancel\n", this)); } this->set_scheduling_release(false); this->scheduled_to_stop_at_ = ACE_Time_Value::zero; TransportReactorTask_rch reactor(this->impl_->reactor_task()); reactor->get_reactor()->notify(this); } return true; }
OpenDDS::DCPS::TcpSendStrategy::TcpSendStrategy( std::size_t id, const TcpDataLink_rch& link, const TcpInst_rch& config, const TcpConnection_rch& connection, TcpSynchResource* synch_resource, const TransportReactorTask_rch& task, Priority priority) : TransportSendStrategy(id, static_rchandle_cast<TransportInst>(config), synch_resource, priority, new ReactorSynchStrategy( this, task->get_reactor())) , connection_(connection) , link_(link) , reactor_task_(task) { DBG_ENTRY_LVL("TcpSendStrategy","TcpSendStrategy",6); connection->set_send_strategy(this); }
int OpenDDS::DCPS::ThreadPerConnectionSendTask::svc() { DBG_ENTRY_LVL("ThreadPerConnectionSendTask","svc",6); this->thr_id_ = ACE_OS::thr_self (); // Start the "GetWork-And-PerformWork" loop for the current worker thread. while (! this->shutdown_initiated_) { SendRequest* req; { GuardType guard(this->lock_); if (this->queue_.size() == 0) { this->work_available_.wait (); } if (this->shutdown_initiated_) break; req = queue_.get (); if(req == 0) { //I'm not sure why this thread got more signals than actual signals //when using thread_per_connection and the user application thread //send requests without interval. We just need ignore the dequeue //failure. //ACE_ERROR ((LM_ERROR, "(%P|%t)ERROR: ThreadPerConnectionSendTask::svc %p\n", // "dequeue_head")); continue; } } this->execute(*req); delete req; } // This will never get executed. return 0; }
bool OpenDDS::DCPS::TransportImpl::check_fully_association(const RepoId pub_id, AssociationInfo& associations) { DBG_ENTRY_LVL("TransportImpl","check_fully_association",6); int num_acked = 0; PublicationObjectMap::iterator pubiter = dw_map_.find(pub_id); for (ssize_t i=0; i < associations.num_associations_; ++i) { RepoId sub_id = associations.association_data_[i].remote_id_; if (this->acked(pub_id, sub_id) && pubiter != dw_map_.end()) { ++ num_acked; } } bool ret = (num_acked == associations.num_associations_); if (ret && pubiter != dw_map_.end()) { for (ssize_t i=0; i < associations.num_associations_; ++i) { RepoId sub_id = associations.association_data_[i].remote_id_; this->remove_ack(pub_id, sub_id); } pubiter->second->fully_associated(pub_id, associations.num_associations_, associations.association_data_); return true; } else if (ret && OpenDDS::DCPS::Transport_debug_level > 8) { std::stringstream buffer; buffer << " pub " << pub_id << " - sub " << associations.association_data_->remote_id_; ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) acked but DW is not registered: %C \n"), buffer.str().c_str())); } return false; }
int OpenDDS::DCPS::TcpReceiveStrategy::start_i() { DBG_ENTRY_LVL("TcpReceiveStrategy","start_i",6); // Tell the TcpConnection that we are the object that it should // call when it receives a handle_input() "event", and we will carry // it out. The TcpConnection object will make a "copy" of the // reference (to this object) that we pass-in here. this->connection_->set_receive_strategy(rchandle_from(this)); if (connection_->is_connector()) { // Give the reactor its own reference to the connection object. // If ACE_Acceptor was used, the reactor already has this reference } if (DCPS_debug_level > 9) { std::stringstream buffer; buffer << *this->link_.in(); ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) TcpReceiveStrategy::start_i() - ") ACE_TEXT("link:\n%C connected to %C:%d ") ACE_TEXT("registering with reactor to receive.\n"), buffer.str().c_str(), this->connection_->get_remote_address().get_host_name(), this->connection_->get_remote_address().get_port_number())); } if (this->reactor_task_->get_reactor()->register_handler (this->connection_.in(), ACE_Event_Handler::READ_MASK) == -1) { // Take back the "copy" we made. ACE_ERROR_RETURN((LM_ERROR, "(%P|%t) ERROR: TcpReceiveStrategy::start_i TcpConnection can't register with " "reactor %@ %p\n", this->connection_.in(), ACE_TEXT("register_handler")), -1); } return 0; }
int OpenDDS::DCPS::TransportImpl::add_pending_association( RepoId local_id, const AssociationInfo& info) { DBG_ENTRY_LVL("TransportImpl","add_pending_association",6); GuardType guard(this->lock_); // Cache the Association data so it can be used for the callback // to notify datawriter on_publication_matched. PendingAssociationsMap::iterator iter = pending_association_sub_map_.find(local_id); if (iter != pending_association_sub_map_.end()) iter->second->push_back(info); else { AssociationInfoList* infos = new AssociationInfoList; infos->push_back(info); if (OpenDDS::DCPS::bind(pending_association_sub_map_, local_id, infos) == -1) { OpenDDS::DCPS::RepoIdConverter converter(local_id); ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: TransportImpl::add_pending_association: ") ACE_TEXT("failed to add pending associations for pub %C\n"), std::string(converter).c_str()),-1); } } // Acks for this new pending association may arrive at this time. // If check for individual association, it needs remove the association // from pending_association_sub_map_ so the fully_associated won't be // called multiple times. To simplify, check by pub id since the // check_fully_association overloaded function clean the pending list // after calling fully_associated. check_fully_association(local_id); return 0; }
void OpenDDS::DCPS::TcpSendStrategy::schedule_output() { DBG_ENTRY_LVL("TcpSendStrategy","schedule_output",6); // Notify the reactor to adjust its processing policy according to mode_. synch()->work_available(); if (DCPS_debug_level > 4) { const char* action = ""; if( mode() == MODE_DIRECT) { action = "canceling"; } else if( (mode() == MODE_QUEUE) || (mode() == MODE_SUSPEND)) { action = "starting"; } ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) TcpSendStrategy::schedule_output() [%d] - ") ACE_TEXT("%C data queueing for handle %d.\n"), id(),action,get_handle())); } }
OpenDDS::DCPS::TcpConnection::TcpConnection() : connected_(false) , is_connector_(false) , passive_reconnect_timer_id_(-1) , reconnect_task_(this) , reconnect_state_(INIT_STATE) , last_reconnect_attempted_(ACE_Time_Value::zero) , transport_priority_(0) // TRANSPORT_PRIORITY.value default value - 0. , shutdown_(false) , passive_setup_(false) , passive_setup_buffer_(sizeof(ACE_UINT32)) , id_(0) { DBG_ENTRY_LVL("TcpConnection","TcpConnection",6); if (this->reconnect_task_.open()) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: Reconnect task failed to open : %p\n"), ACE_TEXT("open"))); } }
/// A timer is scheduled on acceptor side to check if a new connection /// is accepted after the connection is lost. int OpenDDS::DCPS::SimpleTcpConnection::handle_timeout (const ACE_Time_Value &, const void *) { DBG_ENTRY_LVL("SimpleTcpConnection","handle_timeout",6); this->reconnect_state_ = PASSIVE_TIMEOUT_CALLED_STATE; GuardType guard (this->reconnect_lock_); switch (this->reconnect_state_) { case PASSIVE_TIMEOUT_CALLED_STATE: { // We stay in PASSIVE_TIMEOUT_CALLED_STATE indicates there is no new connection. // Now we need declare the connection is lost. this->link_->notify (DataLink::LOST); // The handle_timeout may be called after the connection is re-established // and the send strategy of this old connection is reset to nil. if (! this->send_strategy_.is_nil ()) this->send_strategy_->terminate_send (); this->reconnect_state_ = LOST_STATE; } break; case RECONNECTED_STATE: // reconnected successfully. break; default : ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: SimpleTcpConnection::handle_timeout, ") ACE_TEXT(" unknown state or it should not be in state=%d \n"), this->reconnect_state_)); break; } // Take back the "copy" we gave to reactor when we schedule the timer. this->_remove_ref (); return 0; }
/// The client application calls this to attach this TransportInterface /// object to the supplied TransportImpl object. OpenDDS::DCPS::AttachStatus OpenDDS::DCPS::TransportInterface::attach_transport(TransportImpl* impl) { DBG_ENTRY_LVL("TransportInterface","attach_transport",6); { // guard scope GuardType guard(this->lock_); if (!this->impl_.is_nil()) { // This TransportInterface object is currently attached to // a TransportImpl. return ATTACH_BAD_TRANSPORT; } // Ask the impl for the swap_bytes() value, and cache the answer in // a data member (this->swap_bytes_) so that we don't have to ask // the impl for it anymore. this->swap_bytes_ = impl->swap_bytes(); // Ask the impl for the connection_info() value, and cache the answer in // a data member (this->connection_info_) so that we don't have to ask // the impl for it anymore. impl->connection_info(this->connection_info_); // Attempt to attach ourselves to the TransportImpl object now. if (impl->attach_interface(this) == ATTACH_BAD_TRANSPORT) { // The TransportImpl didn't accept our attachment for some reason. return ATTACH_BAD_TRANSPORT; } // Now the TransportImpl object knows about us. Let's remember the // TransportImpl object by saving a "copy" of the reference to our // impl_ data member. impl->_add_ref(); this->impl_ = impl; } return ATTACH_OK; }
/// This function is called when the backpressure occurs and timed out after /// "max_output_pause_period". The lost connection notification should be sent /// and the connection needs be closed since we declared it as a "lost" /// connection. void OpenDDS::DCPS::TcpConnection::notify_lost_on_backpressure_timeout() { DBG_ENTRY_LVL("TcpConnection","notify_lost_on_backpressure_timeout",6); bool notify_lost = false; { GuardType guard(this->reconnect_lock_); if (this->reconnect_state_ == INIT_STATE) { this->reconnect_state_ = LOST_STATE; notify_lost = true; this->disconnect(); } } if (notify_lost) { this->link_->notify(DataLink::LOST); this->send_strategy_->terminate_send(); } }
OpenDDS::DCPS::DataLinkSet* OpenDDS::DCPS::DataLinkSet::select_links(const RepoId* remoteIds, const CORBA::ULong num_targets) { DBG_ENTRY_LVL("DataLinkSet","select_links",6); DataLinkSet_rch selected_links = new DataLinkSet(); GuardType guard(this->lock_); for (MapType::iterator itr = map_.begin(); itr != map_.end(); ++itr) { for (CORBA::ULong i = 0; i < num_targets; ++i) { if (itr->second->is_target(remoteIds[i])) { OpenDDS::DCPS::bind(selected_links->map_, itr->second->id(), itr->second); break; } } } return selected_links._retn(); }
int OpenDDS::DCPS::TransportReactorTask::open(void*) { DBG_ENTRY_LVL("TransportReactorTask","open",6); GuardType guard(this->lock_); // Reset our state. this->state_ = STATE_NOT_RUNNING; // For now, we only support one thread to run the reactor event loop. // Parts of the logic in this class would need to change to support // more than one thread running the reactor. // Attempt to activate ourselves. If successful, a new thread will be // started and it will invoke our svc() method. Note that we still have // a hold on our lock while we do this. if (this->activate(THR_NEW_LWP | THR_JOINABLE,1) != 0) { ACE_ERROR_RETURN((LM_ERROR, "(%P|%t) ERROR: TransportReactorTask Failed to activate " "itself.\n"), -1); } this->wait_for_startup(); // Here we need to wait until a condition is triggered by the new thread(s) // that we created. Note that this will cause us to release the lock and // wait until the condition_ is signal()'ed. When it is signaled, the // condition will attempt to obtain the lock again, and then return to us // here. We can then go on. if (this->state_ == STATE_NOT_RUNNING) { this->state_ = STATE_OPENING; this->condition_.wait(); } return 0; }
void OpenDDS::DCPS::RepoIdSetMap::dump() { DBG_ENTRY_LVL("RepoIdSetMap","dump",6); for (MapType::iterator itr = map_.begin(); itr != map_.end(); ++itr) { RepoIdSet_rch set = itr->second; for (RepoIdSet::MapType::iterator it = set->map().begin(); it != set->map().end(); ++it) { OPENDDS_STRING buffer; buffer + "key "; buffer += to_string(itr->first); buffer + " - value "; buffer += to_string(it->first); ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) %C \n"), buffer.c_str())); } } }
void OpenDDS::DCPS::TransportImpl::check_fully_association() { DBG_ENTRY_LVL("TransportImpl","check_fully_association",6); GuardType guard(this->lock_); if (OpenDDS::DCPS::Transport_debug_level > 8) { ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) ack dump: \n"))); acked_sub_map_.dump(); } PendingAssociationsMap::iterator penditer = pending_association_sub_map_.begin(); while (penditer != pending_association_sub_map_.end()) { PendingAssociationsMap::iterator cur = penditer; ++ penditer; check_fully_association(cur->first); } }
/// The SimpleTcpTransport calls this method when it has an established /// connection object for us. This call puts this SimpleTcpDataLink into /// the "connected" state. int OpenDDS::DCPS::SimpleTcpDataLink::connect (SimpleTcpConnection* connection, TransportSendStrategy* send_strategy, TransportReceiveStrategy* receive_strategy) { DBG_ENTRY_LVL("SimpleTcpDataLink","connect",6); // Sanity check - cannot connect() if we are already connected. if (!this->connection_.is_nil()) { ACE_ERROR_RETURN((LM_ERROR, "(%P|%t) ERROR: SimpleTcpDataLink already connected.\n"), -1); } // Keep a "copy" of the reference to the connection object for ourselves. connection->_add_ref(); this->connection_ = connection; // Let connection know the datalink for callbacks upon reconnect failure. this->connection_->set_datalink(this); // And lastly, inform our base class (DataLink) that we are now "connected", // and it should start the strategy objects. if (this->start(send_strategy,receive_strategy) != 0) { // Our base (DataLink) class failed to start the strategy objects. // We need to "undo" some things here before we return -1 to indicate // that an error has taken place. // Drop our reference to the connection object. this->connection_ = 0; return -1; } return 0; }
int DataLink::make_reservation(const RepoId& remote_publication_id, const RepoId& local_subscription_id, TransportReceiveListener* receive_listener) { DBG_ENTRY_LVL("DataLink", "make_reservation", 6); if (DCPS_debug_level > 9) { GuidConverter local(local_subscription_id), remote(remote_publication_id); ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) DataLink::make_reservation() - ") ACE_TEXT("creating association local subscription %C ") ACE_TEXT("<--> with remote publication %C.\n"), OPENDDS_STRING(local).c_str(), OPENDDS_STRING(remote).c_str())); } { GuardType guard(strategy_lock_); if (!send_strategy_.is_nil()) { send_strategy_->link_released(false); } } { GuardType guard(pub_sub_maps_lock_); assoc_by_local_[local_subscription_id].insert(remote_publication_id); ReceiveListenerSet_rch& rls = assoc_by_remote_[remote_publication_id]; if (rls.is_nil()) rls = new ReceiveListenerSet; rls->insert(local_subscription_id, receive_listener); recv_listeners_[local_subscription_id] = receive_listener; } return 0; }
void RecorderImpl::remove_all_associations() { DBG_ENTRY_LVL("RecorderImpl","remove_all_associations",6); OpenDDS::DCPS::WriterIdSeq writers; int size; ACE_GUARD(ACE_Recursive_Thread_Mutex, guard, this->publication_handle_lock_); { ACE_READ_GUARD(ACE_RW_Thread_Mutex, read_guard, this->writers_lock_); size = static_cast<int>(writers_.size()); writers.length(size); WriterMapType::iterator curr_writer = writers_.begin(); WriterMapType::iterator end_writer = writers_.end(); int i = 0; while (curr_writer != end_writer) { writers[i++] = curr_writer->first; ++curr_writer; } } try { CORBA::Boolean dont_notify_lost = 0; if (0 < size) { remove_associations(writers, dont_notify_lost); } } catch (const CORBA::Exception&) { } }
int OpenDDS::DCPS::TcpSendStrategy::reset(TcpConnection* connection) { DBG_ENTRY_LVL("TcpSendStrategy","reset",6); // Sanity check - this connection is passed in from the constructor and // it should not be nil. if (this->connection_.is_nil()) { ACE_ERROR_RETURN((LM_ERROR, "(%P|%t) ERROR: TcpSendStrategy::reset previous connection " "should not be nil.\n"), -1); } if (this->connection_.in() == connection) { ACE_ERROR_RETURN((LM_ERROR, "(%P|%t) ERROR: TcpSendStrategy::reset should not be called" " to replace the same connection.\n"), -1); } // This will cause the connection_ object to drop its reference to this // TransportSendStrategy object. this->connection_->remove_send_strategy(); // Replace with a new connection. connection->_add_ref(); this->connection_ = connection; // Tell the TcpConnection that we are the object that it should // call when it receives a handle_input() "event", and we will carry // it out. The TcpConnection object will make a "copy" of the // reference (to this object) that we pass-in here. this->connection_->set_send_strategy(this); return 0; }