bool check_discovered_participants(DomainParticipant_var& dp,
                                   InstanceHandle_t& handle)
{
  InstanceHandle_t my_handle    = dp->get_instance_handle();

  DDS::InstanceHandleSeq part_handles;
  DDS::ReturnCode_t stat = dp->get_discovered_participants(part_handles);
  while (stat == RETCODE_NO_DATA || part_handles.length() == 0) {
    ACE_OS::sleep(1);
    stat = dp->get_discovered_participants(part_handles);
  }

  if (stat == RETCODE_OK) {
    CORBA::ULong len = part_handles.length();
    if (len != 1) {
      ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT("ERROR: %P expected to discover")
                                  ACE_TEXT("one other participant handle but ")
                                  ACE_TEXT("found %d\n"), len), false);
    } else if (part_handles[0] == my_handle) {
      ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT("ERROR: %P discovered own ")
                                  ACE_TEXT("participant handle\n")), false);
    } else {
      DDS::ParticipantBuiltinTopicData data;
      dp->get_discovered_participant_data(data, part_handles[0]);
      OpenDDS::DCPS::Discovery_rch disc =
          TheServiceParticipant->get_discovery(dp->get_domain_id());
      OpenDDS::DCPS::DomainParticipantImpl* dp_impl =
          dynamic_cast<OpenDDS::DCPS::DomainParticipantImpl*>(dp.in());

      OpenDDS::DCPS::RepoId repo_id = disc->bit_key_to_repo_id(
          dp_impl,
          OpenDDS::DCPS::BUILT_IN_PARTICIPANT_TOPIC,
          data.key);
      if (dp_impl->get_handle(repo_id) != part_handles[0]) {
        ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT("ERROR: %P discovered participant ")
                                    ACE_TEXT("BIT key could not be converted ")
                                    ACE_TEXT("to repo id, then handle\n")),
                         false);
      }
      handle = part_handles[0];
      {
        OpenDDS::DCPS::GuidConverter converter1(dp_impl->get_id ());
        OpenDDS::DCPS::GuidConverter converter2(repo_id);
        ACE_DEBUG ((LM_DEBUG,
                    ACE_TEXT("%P ")
                    ACE_TEXT("%C discovered %C\n"),
                    std::string(converter1).c_str(),
                    std::string(converter2).c_str()));
      }
    }
  }
  return (stat == RETCODE_OK);
}
Beispiel #2
0
int
main (
    int ,
    char *[])
{
    /* Generic DDS entities */
    DomainParticipant_var           participant;
    Topic_var                       chatMessageTopic;
    Topic_var                       nameServiceTopic;
    Subscriber_var                  chatSubscriber;
    DataReader_ptr                  parentReader;
    QueryCondition_var              singleUser;
    ReadCondition_var               newUser;
    StatusCondition_var             leftUser;
    WaitSet_var                     userLoadWS;
    LivelinessChangedStatus         livChangStatus;

    /* QosPolicy holders */
    TopicQos                        setting_topic_qos;
    TopicQos                        reliable_topic_qos;
    SubscriberQos                   sub_qos;
    DataReaderQos                   message_qos;

    /* DDS Identifiers */
    DomainId_t                      domain = NULL;
    ReturnCode_t                    status;
    ConditionSeq                    guardList;

    /* Type-specific DDS entities */
    ChatMessageTypeSupport_var      chatMessageTS;
    NameServiceTypeSupport_var      nameServiceTS;
    NameServiceDataReader_var       nameServer;
    ChatMessageDataReader_var       loadAdmin;
    ChatMessageSeq                  msgList;
    NameServiceSeq                  nsList;
    SampleInfoSeq                   infoSeq;
    SampleInfoSeq                   infoSeq2;

    /* Others */
    StringSeq                       args;
    char *                          chatMessageTypeName = NULL;
    char *                          nameServiceTypeName = NULL;

    bool                            closed = false;
    CORBA::Long                     prevCount = 0;
    DWORD                           tid;
    HANDLE                          tHandle = INVALID_HANDLE_VALUE;

    /* Create a DomainParticipant (using the 'TheParticipantFactory' convenience macro). */
    participant = TheParticipantFactory->create_participant (
        domain,
        PARTICIPANT_QOS_DEFAULT,
        NULL,
        STATUS_MASK_NONE);
    checkHandle(participant.in(), "DDS::DomainParticipantFactory::create_participant");

    /* Register the required datatype for ChatMessage. */
    chatMessageTS = new ChatMessageTypeSupport();
    checkHandle(chatMessageTS.in(), "new ChatMessageTypeSupport");
    chatMessageTypeName = chatMessageTS->get_type_name();
    status = chatMessageTS->register_type(participant.in(), chatMessageTypeName);
    checkStatus(status, "Chat::ChatMessageTypeSupport::register_type");

    /* Register the required datatype for NameService. */
    nameServiceTS = new NameServiceTypeSupport();
    checkHandle(nameServiceTS.in(), "new NameServiceTypeSupport");
    nameServiceTypeName =  nameServiceTS->get_type_name();
    status = nameServiceTS->register_type(participant.in(), nameServiceTypeName);
    checkStatus(status, "Chat::NameServiceTypeSupport::register_type");

    /* Set the ReliabilityQosPolicy to RELIABLE. */
    status = participant->get_default_topic_qos(reliable_topic_qos);
    checkStatus(status, "DDS::DomainParticipant::get_default_topic_qos");
    reliable_topic_qos.reliability.kind = RELIABLE_RELIABILITY_QOS;

    /* Make the tailored QoS the new default. */
    status = participant->set_default_topic_qos(reliable_topic_qos);
    checkStatus(status, "DDS::DomainParticipant::set_default_topic_qos");

    /* Use the changed policy when defining the ChatMessage topic */
    chatMessageTopic = participant->create_topic(
        "Chat_ChatMessage",
        chatMessageTypeName,
        reliable_topic_qos,
        NULL,
        STATUS_MASK_NONE);
    checkHandle(chatMessageTopic.in(), "DDS::DomainParticipant::create_topic (ChatMessage)");

    /* Set the DurabilityQosPolicy to TRANSIENT. */
    status = participant->get_default_topic_qos(setting_topic_qos);
    checkStatus(status, "DDS::DomainParticipant::get_default_topic_qos");
    setting_topic_qos.durability.kind = TRANSIENT_DURABILITY_QOS;

    /* Create the NameService Topic. */
    nameServiceTopic = participant->create_topic(
        "Chat_NameService",
        nameServiceTypeName,
        setting_topic_qos,
        NULL,
        STATUS_MASK_NONE);
    checkHandle(nameServiceTopic.in(), "DDS::DomainParticipant::create_topic");

    /* Adapt the default SubscriberQos to read from the "ChatRoom" Partition. */
    status = participant->get_default_subscriber_qos (sub_qos);
    checkStatus(status, "DDS::DomainParticipant::get_default_subscriber_qos");
    sub_qos.partition.name.length(1);
    sub_qos.partition.name[0UL] = "ChatRoom";

    /* Create a Subscriber for the UserLoad application. */
    chatSubscriber = participant->create_subscriber(sub_qos, NULL, STATUS_MASK_NONE);
    checkHandle(chatSubscriber.in(), "DDS::DomainParticipant::create_subscriber");

    /* Create a DataReader for the NameService Topic (using the appropriate QoS). */
    parentReader = chatSubscriber->create_datareader(
        nameServiceTopic.in(),
        DATAREADER_QOS_USE_TOPIC_QOS,
        NULL,
        STATUS_MASK_NONE);
    checkHandle(parentReader, "DDS::Subscriber::create_datareader (NameService)");

    /* Narrow the abstract parent into its typed representative. */
    nameServer = NameServiceDataReader::_narrow(parentReader);
    checkHandle(nameServer.in(), "Chat::NameServiceDataReader::_narrow");

    /* Adapt the DataReaderQos for the ChatMessageDataReader to keep track of all messages. */
    status = chatSubscriber->get_default_datareader_qos(message_qos);
    checkStatus(status, "DDS::Subscriber::get_default_datareader_qos");
    status = chatSubscriber->copy_from_topic_qos(message_qos, reliable_topic_qos);
    checkStatus(status, "DDS::Subscriber::copy_from_topic_qos");
    message_qos.history.kind = KEEP_ALL_HISTORY_QOS;

    /* Create a DataReader for the ChatMessage Topic (using the appropriate QoS). */
    parentReader = chatSubscriber->create_datareader(
        chatMessageTopic.in(),
        message_qos,
        NULL,
        STATUS_MASK_NONE);
    checkHandle(parentReader, "DDS::Subscriber::create_datareader (ChatMessage)");

    /* Narrow the abstract parent into its typed representative. */
    loadAdmin = ChatMessageDataReader::_narrow(parentReader);
    checkHandle(loadAdmin.in(), "Chat::ChatMessageDataReader::_narrow");

    /* Initialize the Query Arguments. */
    args.length(1);
    args[0UL] = "0";

    /* Create a QueryCondition that will contain all messages with userID=ownID */
    singleUser = loadAdmin->create_querycondition(
        ANY_SAMPLE_STATE,
        ANY_VIEW_STATE,
        ANY_INSTANCE_STATE,
        "userID=%0",
        args);
    checkHandle(singleUser.in(), "DDS::DataReader::create_querycondition");

    /* Create a ReadCondition that will contain new users only */
    newUser = nameServer->create_readcondition(
        NOT_READ_SAMPLE_STATE,
        NEW_VIEW_STATE,
        ALIVE_INSTANCE_STATE);
    checkHandle(newUser.in(), "DDS::DataReader::create_readcondition");

    /* Obtain a StatusCondition that triggers only when a Writer changes Liveliness */
    leftUser = loadAdmin->get_statuscondition();
    checkHandle(leftUser.in(), "DDS::DataReader::get_statuscondition");
    status = leftUser->set_enabled_statuses(LIVELINESS_CHANGED_STATUS);
    checkStatus(status, "DDS::StatusCondition::set_enabled_statuses");

    /* Create a bare guard which will be used to close the room */
    escape = new GuardCondition();

    /* Create a waitset and add the ReadConditions */
    userLoadWS = new WaitSet();
    status = userLoadWS->attach_condition(newUser.in());
    checkStatus(status, "DDS::WaitSet::attach_condition (newUser)");
    status = userLoadWS->attach_condition(leftUser.in());
    checkStatus(status, "DDS::WaitSet::attach_condition (leftUser)");
    status = userLoadWS->attach_condition(escape.in());
    checkStatus(status, "DDS::WaitSet::attach_condition (escape)");

    /* Initialize and pre-allocate the GuardList used to obtain the triggered Conditions. */
    guardList.length(3);

    /* Remove all known Users that are not currently active. */
    status = nameServer->take(
        nsList,
        infoSeq,
        LENGTH_UNLIMITED,
        ANY_SAMPLE_STATE,
        ANY_VIEW_STATE,
        NOT_ALIVE_INSTANCE_STATE);
    checkStatus(status, "Chat::NameServiceDataReader::take");
    status = nameServer->return_loan(nsList, infoSeq);
    checkStatus(status, "Chat::NameServiceDataReader::return_loan");

    /* Start the sleeper thread. */
    tHandle = CreateThread(NULL, 0, delayedEscape, NULL, 0, &tid);

    while (!closed) {
        /* Wait until at least one of the Conditions in the waitset triggers. */
        status = userLoadWS->wait(guardList, DURATION_INFINITE);
        checkStatus(status, "DDS::WaitSet::wait");

        /* Walk over all guards to display information */
        for (CORBA::ULong i = 0; i < guardList.length(); i++) {
            if ( guardList[i].in() == newUser.in() ) {
                /* The newUser ReadCondition contains data */
                status = nameServer->read_w_condition(
                    nsList,
                    infoSeq,
                    LENGTH_UNLIMITED,
                    newUser.in() );
                checkStatus(status, "Chat::NameServiceDataReader::read_w_condition");

                for (CORBA::ULong j = 0; j < nsList.length(); j++) {
                    cout << "New user: "******"Chat::NameServiceDataReader::return_loan");

            } else if ( guardList[i].in() == leftUser.in() ) {
                /* Some liveliness has changed (either a DataWriter joined or a DataWriter left) */
                status = loadAdmin->get_liveliness_changed_status(livChangStatus);
                checkStatus(status, "DDS::DataReader::get_liveliness_changed_status");
                if (livChangStatus.alive_count < prevCount) {
                    /* A user has left the ChatRoom, since a DataWriter lost its liveliness */
                    /* Take the effected users so tey will not appear in the list later on. */
                    status = nameServer->take(
                        nsList,
                        infoSeq,
                        LENGTH_UNLIMITED,
                        ANY_SAMPLE_STATE,
                        ANY_VIEW_STATE,
                        NOT_ALIVE_NO_WRITERS_INSTANCE_STATE);
                    checkStatus(status, "Chat::NameServiceDataReader::take");

                    for (CORBA::ULong j = 0; j < nsList.length(); j++) {
                        /* re-apply query arguments */
                        ostringstream numberString;
                        numberString << nsList[j].userID;
                        args[0UL] = numberString.str().c_str();
                        status = singleUser->set_query_parameters(args);
                        checkStatus(status, "DDS::QueryCondition::set_query_parameters");

                        /* Read this users history */
                        status = loadAdmin->take_w_condition(
                            msgList,
                            infoSeq2,
                            LENGTH_UNLIMITED,
                            singleUser.in() );
                        checkStatus(status, "Chat::ChatMessageDataReader::take_w_condition");

                        /* Display the user and his history */
                        cout << "Departed user " << nsList[j].name << " has sent " <<
                            msgList.length() << " messages." << endl;
                        status = loadAdmin->return_loan(msgList, infoSeq2);
                        checkStatus(status, "Chat::ChatMessageDataReader::return_loan");
                    }
                    status = nameServer->return_loan(nsList, infoSeq);
                    checkStatus(status, "Chat::NameServiceDataReader::return_loan");
                }
                prevCount = livChangStatus.alive_count;

            } else if ( guardList[i].in() == escape.in() ) {
                cout << "UserLoad has terminated." << endl;
                closed = true;
            }
            else
            {
                assert(0);
            };
        } /* for */
    } /* while (!closed) */

    /* Remove all Conditions from the WaitSet. */
    status = userLoadWS->detach_condition( escape.in() );
    checkStatus(status, "DDS::WaitSet::detach_condition (escape)");
    status = userLoadWS->detach_condition( leftUser.in() );
    checkStatus(status, "DDS::WaitSet::detach_condition (leftUser)");
    status = userLoadWS->detach_condition( newUser.in() );
    checkStatus(status, "DDS::WaitSet::detach_condition (newUser)");

    /* Remove the type-names. */
    CORBA::string_free(chatMessageTypeName);
    CORBA::string_free(nameServiceTypeName);

    /* Free all resources */
    status = participant->delete_contained_entities();
    checkStatus(status, "DDS::DomainParticipant::delete_contained_entities");
    status = TheParticipantFactory->delete_participant( participant.in() );
    checkStatus(status, "DDS::DomainParticipantFactory::delete_participant");

    CloseHandle(tHandle);

    return 0;
}
Beispiel #3
0
int
OSPL_MAIN (
    int argc,
    char *argv[])
{
    /* Generic DDS entities */
    DomainParticipantFactory_var    dpf;
    DomainParticipant_var           parentDP;
    ExtDomainParticipant_var        participant;
    Topic_var                       chatMessageTopic;
    Topic_var                       nameServiceTopic;
    TopicDescription_var            namedMessageTopic;
    Subscriber_var                  chatSubscriber;
    DataReader_var                  parentReader;

    /* Type-specific DDS entities */
    ChatMessageTypeSupport_var      chatMessageTS;
    NameServiceTypeSupport_var      nameServiceTS;
    NamedMessageTypeSupport_var     namedMessageTS;
    NamedMessageDataReader_var      chatAdmin;
    NamedMessageSeq_var             msgSeq = new NamedMessageSeq();
    SampleInfoSeq_var               infoSeq = new SampleInfoSeq();

    /* QosPolicy holders */
    TopicQos                        reliable_topic_qos;
    TopicQos                        setting_topic_qos;
    SubscriberQos                   sub_qos;
    DDS::StringSeq                  parameterList;

    /* DDS Identifiers */
    DomainId_t                      domain = DOMAIN_ID_DEFAULT;
    ReturnCode_t                    status;

    /* Others */
    bool                            terminated = false;
    const char *                    partitionName = "ChatRoom";
    char  *                         chatMessageTypeName = NULL;
    char  *                         nameServiceTypeName = NULL;
    char  *                         namedMessageTypeName = NULL;

#ifdef USE_NANOSLEEP
    struct timespec                 sleeptime;
    struct timespec                 remtime;
#endif

    /* Options: MessageBoard [ownID] */
    /* Messages having owner ownID will be ignored */
    parameterList.length(1);

    if (argc > 1) {
        parameterList[0] = DDS::string_dup(argv[1]);
    }
    else
    {
        parameterList[0] = "0";
    }

    /* Create a DomainParticipantFactory and a DomainParticipant (using Default QoS settings. */
    dpf = DomainParticipantFactory::get_instance();
    checkHandle(dpf.in(), "DDS::DomainParticipantFactory::get_instance");
    parentDP = dpf->create_participant (
        domain,
        PARTICIPANT_QOS_DEFAULT,
        NULL,
        STATUS_MASK_NONE);
    checkHandle(parentDP.in(), "DDS::DomainParticipantFactory::create_participant");

    /* Narrow the normal participant to its extended representative */
    participant = ExtDomainParticipantImpl::_narrow(parentDP.in());
    checkHandle(participant.in(), "DDS::ExtDomainParticipant::_narrow");

    /* Register the required datatype for ChatMessage. */
    chatMessageTS = new ChatMessageTypeSupport();
    checkHandle(chatMessageTS.in(), "new ChatMessageTypeSupport");
    chatMessageTypeName = chatMessageTS->get_type_name();
    status = chatMessageTS->register_type(
        participant.in(),
        chatMessageTypeName);
    checkStatus(status, "Chat::ChatMessageTypeSupport::register_type");

    /* Register the required datatype for NameService. */
    nameServiceTS = new NameServiceTypeSupport();
    checkHandle(nameServiceTS.in(), "new NameServiceTypeSupport");
    nameServiceTypeName =  nameServiceTS->get_type_name();
    status = nameServiceTS->register_type(
        participant.in(),
        nameServiceTypeName);
    checkStatus(status, "Chat::NameServiceTypeSupport::register_type");

    /* Register the required datatype for NamedMessage. */
    namedMessageTS = new NamedMessageTypeSupport();
    checkHandle(namedMessageTS.in(), "new NamedMessageTypeSupport");
    namedMessageTypeName = namedMessageTS->get_type_name();
    status = namedMessageTS->register_type(
        participant.in(),
        namedMessageTypeName);
    checkStatus(status, "Chat::NamedMessageTypeSupport::register_type");

    /* Set the ReliabilityQosPolicy to RELIABLE. */
    status = participant->get_default_topic_qos(reliable_topic_qos);
    checkStatus(status, "DDS::DomainParticipant::get_default_topic_qos");
    reliable_topic_qos.reliability.kind = DDS::RELIABLE_RELIABILITY_QOS;

    /* Make the tailored QoS the new default. */
    status = participant->set_default_topic_qos(reliable_topic_qos);
    checkStatus(status, "DDS::DomainParticipant::set_default_topic_qos");

    /* Use the changed policy when defining the ChatMessage topic */
    chatMessageTopic = participant->create_topic(
        "Chat_ChatMessage",
        chatMessageTypeName,
        reliable_topic_qos,
        NULL,
        STATUS_MASK_NONE);
    checkHandle(chatMessageTopic.in(), "DDS::DomainParticipant::create_topic (ChatMessage)");

    /* Set the DurabilityQosPolicy to TRANSIENT. */
    status = participant->get_default_topic_qos(setting_topic_qos);
    checkStatus(status, "DDS::DomainParticipant::get_default_topic_qos");
    setting_topic_qos.durability.kind = DDS::TRANSIENT_DURABILITY_QOS;

    /* Create the NameService Topic. */
    nameServiceTopic = participant->create_topic(
        "Chat_NameService",
        nameServiceTypeName,
        setting_topic_qos,
        NULL,
        STATUS_MASK_NONE);
    checkHandle(nameServiceTopic.in(), "DDS::DomainParticipant::create_topic");

    /* Create a multitopic that substitutes the userID with its corresponding userName. */
    namedMessageTopic = participant->create_simulated_multitopic(
        "Chat_NamedMessage",
        namedMessageTypeName,
        "SELECT userID, name AS userName, index, content "
            "FROM Chat_NameService NATURAL JOIN Chat_ChatMessage WHERE userID <> %0",
        parameterList);
    checkHandle(namedMessageTopic.in(), "DDS::ExtDomainParticipant::create_simulated_multitopic");

    /* Adapt the default SubscriberQos to read from the "ChatRoom" Partition. */
    status = participant->get_default_subscriber_qos (sub_qos);
    checkStatus(status, "DDS::DomainParticipant::get_default_subscriber_qos");
    sub_qos.partition.name.length(1);
    sub_qos.partition.name[0] = partitionName;

    /* Create a Subscriber for the MessageBoard application. */
    chatSubscriber = participant->create_subscriber(sub_qos, NULL, STATUS_MASK_NONE);
    checkHandle(chatSubscriber.in(), "DDS::DomainParticipant::create_subscriber");

    /* Create a DataReader for the NamedMessage Topic (using the appropriate QoS). */
    parentReader = chatSubscriber->create_datareader(
        namedMessageTopic.in(),
        DATAREADER_QOS_USE_TOPIC_QOS,
        NULL,
        STATUS_MASK_NONE);
    checkHandle(parentReader.in(), "DDS::Subscriber::create_datareader");

    /* Narrow the abstract parent into its typed representative. */
    chatAdmin = Chat::NamedMessageDataReader::_narrow(parentReader.in());
    checkHandle(chatAdmin.in(), "Chat::NamedMessageDataReader::_narrow");

    /* Print a message that the MessageBoard has opened. */
    cout << "MessageBoard has opened: send a ChatMessage with userID = -1 to close it...." << endl << endl;

    while (!terminated) {
        /* Note: using read does not remove the samples from
           unregistered instances from the DataReader. This means
           that the DataRase would use more and more resources.
           That's why we use take here instead. */

        status = chatAdmin->take(
            msgSeq,
            infoSeq,
            LENGTH_UNLIMITED,
            ANY_SAMPLE_STATE,
            ANY_VIEW_STATE,
            ALIVE_INSTANCE_STATE );
        checkStatus(status, "Chat::NamedMessageDataReader::take");

        for (DDS::ULong i = 0; i < msgSeq->length(); i++) {
            NamedMessage *msg = &(msgSeq[i]);
            if (msg->userID == TERMINATION_MESSAGE) {
                cout << "Termination message received: exiting..." << endl;
                terminated = true;
            } else {
                cout << msg->userName << ": " << msg->content << endl;
            }
            fflush(stdout);
        }

        status = chatAdmin->return_loan(msgSeq, infoSeq);
        checkStatus(status, "Chat::ChatMessageDataReader::return_loan");

        /* Sleep for some amount of time, as not to consume too much CPU cycles. */
#ifdef USE_NANOSLEEP
        sleeptime.tv_sec = 0;
        sleeptime.tv_nsec = 100000000;
        nanosleep(&sleeptime, &remtime);
#elif defined _WIN32
        Sleep(100);
#else
        usleep(100000);
#endif
    }

    /* Remove the DataReader */
    status = chatSubscriber->delete_datareader(chatAdmin.in());
    checkStatus(status, "DDS::Subscriber::delete_datareader");

    /* Remove the Subscriber. */
    status = participant->delete_subscriber(chatSubscriber.in());
    checkStatus(status, "DDS::DomainParticipant::delete_subscriber");

    /* Remove the Topics. */
    status = participant->delete_simulated_multitopic(namedMessageTopic.in());
    checkStatus(status, "DDS::ExtDomainParticipant::delete_simulated_multitopic");

    status = participant->delete_topic(nameServiceTopic.in());
    checkStatus(status, "DDS::DomainParticipant::delete_topic (nameServiceTopic)");

    status = participant->delete_topic(chatMessageTopic.in());
    checkStatus(status, "DDS::DomainParticipant::delete_topic (chatMessageTopic)");

    /* De-allocate the type-names. */
    DDS::string_free(namedMessageTypeName);
    DDS::string_free(nameServiceTypeName);
    DDS::string_free(chatMessageTypeName);

    /* Remove the DomainParticipant. */
    status = dpf->delete_participant(participant.in());
    checkStatus(status, "DDS::DomainParticipantFactory::delete_participant");

    return 0;
}
bool run_test(DomainParticipant_var& dp_sub,
              DomainParticipant_var& dp_pub)
{
  OpenDDS::DCPS::RepoId sub_repo_id, pub_repo_id;

  {
    OpenDDS::DCPS::DomainParticipantImpl* dp_impl =
      dynamic_cast<OpenDDS::DCPS::DomainParticipantImpl*>(dp_sub.in());
    sub_repo_id = dp_impl->get_id ();
    OpenDDS::DCPS::GuidConverter converter(sub_repo_id);
    ACE_DEBUG ((LM_DEBUG,
                ACE_TEXT("%P ")
                ACE_TEXT("Sub Domain Participant GUID=%C\n"),
                std::string(converter).c_str()));
  }

  {
    OpenDDS::DCPS::DomainParticipantImpl* dp_impl =
      dynamic_cast<OpenDDS::DCPS::DomainParticipantImpl*>(dp_pub.in());
    pub_repo_id = dp_impl->get_id ();
    OpenDDS::DCPS::GuidConverter converter(pub_repo_id);
    ACE_DEBUG ((LM_DEBUG,
                ACE_TEXT("%P ")
                ACE_TEXT("Pub Domain Participant GUID=%C\n"),
                std::string(converter).c_str()));
  }

  // If we are running with an rtps_udp transport, it can't be shared between
  // participants.
  TransportConfig_rch cfg = TheTransportRegistry->get_config("dp1");
  if (!cfg.is_nil()) {
    TheTransportRegistry->bind_config(cfg, dp_sub);
  }
  cfg = TheTransportRegistry->get_config("dp2");
  if (!cfg.is_nil()) {
    TheTransportRegistry->bind_config(cfg, dp_pub);
  }

  Subscriber_var bit_sub = dp_sub->get_builtin_subscriber();

  if (!read_participant_bit(bit_sub, dp_sub, pub_repo_id, TestConfig::PARTICIPANT_USER_DATA())) {
    return false;
  }

  // Each domain participant's handle to the other
  InstanceHandle_t dp_sub_ih, dp_pub_ih;
  InstanceHandle_t pub_ih, sub_ih, ig_ih;

  if (!(check_discovered_participants(dp_sub, dp_pub_ih) &&
        check_discovered_participants(dp_pub, dp_sub_ih)))
  {
    return false;
  }

  DataWriter_var dw = create_data_writer(dp_pub);
  if (!dw) {
    ACE_DEBUG((LM_ERROR, "ERROR: %P could not create Data Writer (participant 2)\n"));
    return false;
  }

  if (!read_publication_bit(bit_sub, dp_sub, pub_repo_id, pub_ih, TestConfig::DATA_WRITER_USER_DATA(), TestConfig::TOPIC_DATA(), 1, 1)) {
    return false;
  }

  DataReader_var dr = create_data_reader(dp_sub);
  if (!dr) {
    ACE_DEBUG((LM_ERROR, "ERROR: %P could not create Data Reader (participant 1)\n"));
    return false;
  }
  if (!read_subscription_bit(dp_pub->get_builtin_subscriber(), dp_pub, sub_repo_id, sub_ih, TestConfig::DATA_READER_USER_DATA(), TestConfig::TOPIC_DATA())) {
    return false;
  }

  // Wait for the reader to associate with the writer.
  WriterSync::wait_match(dw);

  // Remove the writer and its topic, then re-create them.  The writer's
  // participant should still have discovery info about the reader so that
  // the association between the new writer and old reader can be established.
  recreate_data_writer_and_topic(dw, dr);

  // Wait for the reader to associate with the writer.
  WriterSync::wait_match(dw);

  // The new writer is associated with the reader, but the reader may still
  // also be associated with the old writer.
  wait_match(dr, 1);

  // Get the new instance handle as pub_ih
  if (!read_publication_bit(bit_sub, dp_sub, pub_repo_id, pub_ih, TestConfig::DATA_WRITER_USER_DATA(), TestConfig::TOPIC_DATA(), 1, 2)) {
    return false;
  }

  TestMsgDataWriter_var tmdw = TestMsgDataWriter::_narrow(dw);
  const TestMsg msg = {42};
  tmdw->write(msg, HANDLE_NIL);

  ReadCondition_var rc = dr->create_readcondition(ANY_SAMPLE_STATE,
                                                  ANY_VIEW_STATE,
                                                  ALIVE_INSTANCE_STATE);
  WaitSet_var waiter = new WaitSet;
  waiter->attach_condition(rc);
  ConditionSeq activeConditions;
  const Duration_t timeout = { 90, 0 };
  ReturnCode_t result = waiter->wait(activeConditions, timeout);
  waiter->detach_condition(rc);
  if (result != RETCODE_OK) {
    ACE_DEBUG((LM_ERROR,
      "ERROR: %P TestMsg reader could not wait for condition: %d\n", result));
    return false;
  }

  TestMsgDataReader_var tmdr = TestMsgDataReader::_narrow(dr);

  TestMsgSeq data;
  SampleInfoSeq infos;
  ReturnCode_t ret = tmdr->read_w_condition(data, infos, LENGTH_UNLIMITED, rc);
  if (ret != RETCODE_OK) {
    ACE_DEBUG((LM_ERROR, "ERROR: %P could not read TestMsg: %d\n", ret));
    return false;
  }

  bool ok = false;
  for (CORBA::ULong i = 0; i < data.length(); ++i) {
    if (infos[i].valid_data) {
      ok = true;
      ACE_DEBUG((LM_DEBUG, "%P Read data sample: %d\n", data[i].value));
    }
  }

  if (!ok) {
    ACE_DEBUG((LM_ERROR, "ERROR: %P no valid data from TestMsg data reader\n"));
  }

  // Change dp qos
  {
    DomainParticipantQos dp_qos;
    dp_pub->get_qos(dp_qos);
    set_qos(dp_qos.user_data.value, TestConfig::PARTICIPANT_USER_DATA2());
    dp_pub->set_qos(dp_qos);
  }
  // Change dw qos
  {
    DataWriterQos dw_qos;
    dw->get_qos(dw_qos);
    set_qos(dw_qos.user_data.value, TestConfig::DATA_WRITER_USER_DATA2());
    dw->set_qos(dw_qos);
  }
  // Change dr qos
  {
    DataReaderQos dr_qos;
    dr->get_qos(dr_qos);
    set_qos(dr_qos.user_data.value, TestConfig::DATA_READER_USER_DATA2());
    dr->set_qos(dr_qos);
  }
  // Wait for propagation
  ACE_OS::sleep(3);
  if (!read_participant_bit(bit_sub, dp_sub, pub_repo_id, TestConfig::PARTICIPANT_USER_DATA2())) {
    return false;
  }
  if (!read_publication_bit(bit_sub, dp_sub, pub_repo_id, ig_ih, TestConfig::DATA_WRITER_USER_DATA2(), TestConfig::TOPIC_DATA(), 1, 1)) {
    return false;
  }
  if (!read_subscription_bit(dp_pub->get_builtin_subscriber(), dp_pub, sub_repo_id, ig_ih, TestConfig::DATA_READER_USER_DATA2(), TestConfig::TOPIC_DATA())) {
    return false;
  }

  // Set dw topic qos
  Topic_var topic = dw->get_topic();
  TopicQos topic_qos;
  topic->get_qos(topic_qos);
  set_qos(topic_qos.topic_data.value, TestConfig::TOPIC_DATA2());
  topic->set_qos(topic_qos);

  // Set dr topic qos
  TopicDescription_var topic_desc = dr->get_topicdescription();
  topic = Topic::_narrow(topic_desc);
  topic->get_qos(topic_qos);
  set_qos(topic_qos.topic_data.value, TestConfig::TOPIC_DATA2());
  topic->set_qos(topic_qos);

  // Wait for propagation
  ACE_OS::sleep(3);
  if (!read_publication_bit(bit_sub, dp_sub, pub_repo_id, ig_ih, TestConfig::DATA_WRITER_USER_DATA2(), TestConfig::TOPIC_DATA2(), 1, 1)) {
    return false;
  }
  if (!read_subscription_bit(dp_pub->get_builtin_subscriber(), dp_pub, sub_repo_id, ig_ih, TestConfig::DATA_READER_USER_DATA2(), TestConfig::TOPIC_DATA2())) {
    return false;
  }

  // Test ignore
  dp_sub->ignore_publication(pub_ih);
  if (!read_publication_bit(bit_sub, dp_sub, pub_repo_id, pub_ih, TestConfig::DATA_WRITER_USER_DATA2(), TestConfig::TOPIC_DATA2(), 0, 0)) {
    ACE_ERROR_RETURN((LM_ERROR,
                     ACE_TEXT("ERROR: %P Could not ignore publication\n")), false);
  }

  dp_pub->ignore_subscription(sub_ih);
  if (!read_subscription_bit(dp_pub->get_builtin_subscriber(), dp_pub, sub_repo_id, sub_ih, TestConfig::DATA_READER_USER_DATA2(), TestConfig::TOPIC_DATA2(), true)) {
    ACE_ERROR_RETURN((LM_ERROR,
                     ACE_TEXT("ERROR: %P Could not ignore subscription\n")), false);
  }

  dp_sub->ignore_participant(dp_pub_ih);
  InstanceHandleSeq handles;
  dp_sub->get_discovered_participants(handles);
  // Check that the handle is no longer in the sequence.
  for (CORBA::ULong i = 0; i < handles.length (); ++i) {
    if (handles[i] == dp_pub_ih) {
      ACE_ERROR_RETURN((LM_ERROR,
                        ACE_TEXT("ERROR: %P Could not ignore participant\n")), false);

    }
  }

  return ok;
}
bool read_subscription_bit(const Subscriber_var& bit_sub,
                           const DomainParticipant_var& publisher,
                           const OpenDDS::DCPS::RepoId& subscriber_repo_id,
                           InstanceHandle_t& handle,
                           int user_data,
                           int topic_data,
                           bool ignored_subscription = false)
{
  OpenDDS::DCPS::Discovery_rch disc =
    TheServiceParticipant->get_discovery(publisher->get_domain_id());
  OpenDDS::DCPS::DomainParticipantImpl* publisher_impl =
    dynamic_cast<OpenDDS::DCPS::DomainParticipantImpl*>(publisher.in());

  DataReader_var dr = bit_sub->lookup_datareader(BUILT_IN_SUBSCRIPTION_TOPIC);
  if (!ignored_subscription) {
    ReadCondition_var rc = dr->create_readcondition(ANY_SAMPLE_STATE,
                                                    ANY_VIEW_STATE,
                                                    ALIVE_INSTANCE_STATE);
    WaitSet_var waiter = new WaitSet;
    waiter->attach_condition(rc);
    ConditionSeq activeConditions;
    Duration_t forever = { DURATION_INFINITE_SEC,
                           DURATION_INFINITE_NSEC };
    ReturnCode_t result = waiter->wait(activeConditions, forever);
    waiter->detach_condition(rc);
    if (result != RETCODE_OK) {
      ACE_DEBUG((LM_ERROR,
        "ERROR: %P (subscription BIT) could not wait for condition: %d\n", result));
      return false;
    }
  } else {
    ACE_OS::sleep(1);
  }
  SubscriptionBuiltinTopicDataDataReader_var pub_bit =
    SubscriptionBuiltinTopicDataDataReader::_narrow(dr);

  SubscriptionBuiltinTopicDataSeq data;
  SampleInfoSeq infos;
  ReturnCode_t ret =
    pub_bit->read(data, infos, LENGTH_UNLIMITED,
                  ANY_SAMPLE_STATE, ANY_VIEW_STATE, ALIVE_INSTANCE_STATE);
  if (ignored_subscription && (ret != RETCODE_NO_DATA)) {
    ACE_DEBUG((LM_ERROR, "ERROR: %P could not read ignored subscription BIT: %d\n",
               ret));
    return false;
  } else if (ret != RETCODE_OK && ret != RETCODE_NO_DATA) {
    ACE_DEBUG((LM_ERROR, "ERROR: %P could not read subscription BIT: %d\n", ret));
    return false;
  }

  int num_valid = 0;
  bool found_subscriber = false;
  for (CORBA::ULong i = 0; i < data.length(); ++i) {
    if (infos[i].valid_data) {
      ++num_valid;

      OpenDDS::DCPS::RepoId repo_id =
        disc->bit_key_to_repo_id(publisher_impl,
                                 OpenDDS::DCPS::BUILT_IN_PARTICIPANT_TOPIC,
                                 data[i].participant_key);

      OpenDDS::DCPS::GuidConverter converter(repo_id);

      ACE_DEBUG((LM_DEBUG,
                 "%P Read Subscription BIT with key: %x %x %x and handle %d\n"
                 "\tParticipant's GUID=%C\n\tTopic: %C\tType: %C\n",
                 data[i].key.value[0], data[i].key.value[1],
                 data[i].key.value[2], infos[i].instance_handle,
                 std::string(converter).c_str (), data[i].topic_name.in(),
                 data[i].type_name.in()));
      if (repo_id == subscriber_repo_id) {
        found_subscriber = true;
        if (data[i].user_data.value.length() != 1) {
          ACE_ERROR_RETURN((LM_ERROR,
                            "ERROR: %P subscription [%d] user data length %d "
                            "not expected length of 1\n",
                            i,
                            data[i].user_data.value.length()),
                           false);
        }
        if (data[i].topic_data.value.length() != 1) {
          ACE_ERROR_RETURN((LM_ERROR,
                            "ERROR: %P subscription [%d] topic data length %d "
                            "not expected length of 1\n",
                            i,
                            data[i].topic_data.value.length()),
                           false);
        }
        if (data[i].user_data.value[0] != user_data) {
          ACE_ERROR_RETURN((LM_ERROR,
                            "ERROR: %P subscription [%d] user data value %d "
                            "not expected value %d\n",
                            i,
                            data[i].user_data.value[0],
                            user_data),
                           false);
        }
        if (data[i].topic_data.value[0] != topic_data) {
          ACE_ERROR_RETURN((LM_ERROR,
                            "ERROR: %P subscription [%d] topic data value %d "
                            "not expected value %d\n",
                            i,
                            data[i].topic_data.value[0],
                            topic_data),
                           false);
        }
      }
      handle = infos[i].instance_handle;
    }
  }
  if (ignored_subscription) {
    if (num_valid != 0) {
      ACE_ERROR_RETURN((LM_ERROR, "ERROR: %P expected 0 discovered "
                        "subscriptions, found %d\n",
                        num_valid), false);
    }
  }
  else {
    if (num_valid != 1) {
      ACE_ERROR_RETURN((LM_ERROR, "ERROR: %P expected 1 discovered "
                        "subscriptions, found %d\n",
                        num_valid), false);
    }
    if (!found_subscriber) {
      ACE_ERROR_RETURN((LM_ERROR, "ERROR: %P did not find expected subscription\n"), false);
    }
  }

  return true;
}
bool read_participant_bit(const Subscriber_var& bit_sub,
                          const DomainParticipant_var& dp,
                          const OpenDDS::DCPS::RepoId& other_dp_repo_id,
                          int user_data)
{
  OpenDDS::DCPS::Discovery_rch disc =
    TheServiceParticipant->get_discovery(dp->get_domain_id());
  OpenDDS::DCPS::DomainParticipantImpl* dp_impl =
    dynamic_cast<OpenDDS::DCPS::DomainParticipantImpl*>(dp.in());

  DataReader_var dr = bit_sub->lookup_datareader(BUILT_IN_PARTICIPANT_TOPIC);
  ReadCondition_var rc = dr->create_readcondition(ANY_SAMPLE_STATE,
                                                  ANY_VIEW_STATE,
                                                  ALIVE_INSTANCE_STATE);
  WaitSet_var waiter = new WaitSet;
  waiter->attach_condition(rc);
  ConditionSeq activeConditions;
  Duration_t forever = { DURATION_INFINITE_SEC,
                         DURATION_INFINITE_NSEC };
  ReturnCode_t result = waiter->wait(activeConditions, forever);
  waiter->detach_condition(rc);
  if (result != RETCODE_OK) {
    ACE_ERROR_RETURN((LM_ERROR, "ERROR: %P could not wait for condition: %d\n", result), false);
  }

  ParticipantBuiltinTopicDataDataReader_var part_bit =
    ParticipantBuiltinTopicDataDataReader::_narrow(dr);

  ParticipantBuiltinTopicDataSeq data;
  SampleInfoSeq infos;
  ReturnCode_t ret =
    part_bit->read_w_condition(data, infos, LENGTH_UNLIMITED, rc);
  if (ret != RETCODE_OK) {
    ACE_DEBUG((LM_ERROR, "ERROR: %P could not read participant BIT: %d\n", ret));
    return false;
  }

  bool found_other_dp = false;
  int num_valid = 0;

  for (CORBA::ULong i = 0; i < data.length(); ++i) {
    if (infos[i].valid_data) {
      ++num_valid;
      OpenDDS::DCPS::RepoId repo_id =
        disc->bit_key_to_repo_id(dp_impl,
                                 OpenDDS::DCPS::BUILT_IN_PARTICIPANT_TOPIC,
                                 data[i].key);

      OpenDDS::DCPS::GuidConverter converter(repo_id);
      ACE_DEBUG((LM_DEBUG,
                 ACE_TEXT("%P ")
                 ACE_TEXT("Read Participant BIT GUID=%C handle=%d\n"),
                 std::string(converter).c_str(), infos[i].instance_handle));

      if (repo_id == other_dp_repo_id) {
        if (data[i].user_data.value.length() != 1) {
          ACE_ERROR_RETURN((LM_ERROR,
                            "ERROR: %P participant[%d] user data length %d "
                            "not expected length of 1\n",
                            i,
                            data[i].user_data.value.length()),
                           false);
        }

        if (data[i].user_data.value[0] != user_data) {
          ACE_ERROR_RETURN((LM_ERROR,
                            "ERROR: %P participant[%d] user data value %d "
                            "not expected value %d\n",
                            i,
                            data[i].user_data.value[0],
                            user_data),
                           false);
        }

        found_other_dp = true;
      }
    }
  }

  if (num_valid != 1) {
    ACE_DEBUG((LM_ERROR, "ERROR: %P expected to discover 1 other participant, found %d\n", data.length ()));
  }

  part_bit->return_loan(data, infos);

  if (!found_other_dp) {
    ACE_ERROR_RETURN((LM_ERROR, "ERROR: %P did not find expected participant\n"), false);
  }

  return true;
}
Beispiel #7
0
int
OSPL_MAIN (
    int argc,
    char *argv[])
{
    /* Generic DDS entities */
    DomainParticipantFactory_var    dpf;
    DomainParticipant_var           participant;
    Topic_var                       chatMessageTopic;
    Subscriber_var                  chatSubscriber;
    DataReader_ptr                  parentReader;

    /* Type-specific DDS entities */
    ChatMessageTypeSupport_var      chatMessageTS;
    ChatMessageDataReader_var       chatAdmin;
    ChatMessageSeq_var              msgSeq = new ChatMessageSeq();
    SampleInfoSeq_var               infoSeq = new SampleInfoSeq();

    /* QosPolicy holders */
    TopicQos                        reliable_topic_qos;
    SubscriberQos                   sub_qos;
    DDS::StringSeq                  parameterList;

    /* DDS Identifiers */
    DomainId_t                      domain = 0;
    ReturnCode_t                    status;

    /* Others */
    bool                            terminated = false;
    const char *                    partitionName = "ChatRoom1";
    char  *                         chatMessageTypeName = NULL;

    /* Options: MessageBoard [ownID] */
    /* Messages having owner ownID will be ignored */
    parameterList.length(1);

    if (argc > 1) {
        parameterList[0] = string_dup(argv[1]);
    }
    else
    {
        parameterList[0] = "0";
    }

    /* Create a DomainParticipantFactory and a DomainParticipant (using Default QoS settings. */
    dpf = DomainParticipantFactory::get_instance();
    checkHandle(dpf.in(), "DDS::DomainParticipantFactory::get_instance");
    participant = dpf->create_participant (
        domain,
        PARTICIPANT_QOS_DEFAULT,
        NULL,
        STATUS_MASK_NONE);
    checkHandle(participant, "DDS::DomainParticipantFactory::create_participant");

    /* Register the required datatype for ChatMessage. */
    chatMessageTS = new ChatMessageTypeSupport();
    checkHandle(chatMessageTS.in(), "new ChatMessageTypeSupport");
    chatMessageTypeName = chatMessageTS->get_type_name();
    status = chatMessageTS->register_type(
        participant.in(),
        chatMessageTypeName);
    checkStatus(status, "NetworkPartitionsData::ChatMessageTypeSupport::register_type");

    /* Set the ReliabilityQosPolicy to RELIABLE. */
    status = participant->get_default_topic_qos(reliable_topic_qos);
    checkStatus(status, "DDS::DomainParticipant::get_default_topic_qos");
    reliable_topic_qos.reliability.kind = DDS::RELIABLE_RELIABILITY_QOS;

    /* Make the tailored QoS the new default. */
    status = participant->set_default_topic_qos(reliable_topic_qos);
    checkStatus(status, "DDS::DomainParticipant::set_default_topic_qos");

    /* Use the changed policy when defining the ChatMessage topic */
    chatMessageTopic = participant->create_topic(
        "Chat_ChatMessage",
        chatMessageTypeName,
        reliable_topic_qos,
        NULL,
        STATUS_MASK_NONE);
    checkHandle(chatMessageTopic.in(), "DDS::DomainParticipant::create_topic (ChatMessage)");

    /* Adapt the default SubscriberQos to read from the "ChatRoom1" Partition. */
    status = participant->get_default_subscriber_qos (sub_qos);
    checkStatus(status, "DDS::DomainParticipant::get_default_subscriber_qos");
    sub_qos.partition.name.length(1);
    sub_qos.partition.name[0] = partitionName;

    /* Create a Subscriber for the MessageBoard application. */
    chatSubscriber = participant->create_subscriber(sub_qos, NULL, STATUS_MASK_NONE);
    checkHandle(chatSubscriber.in(), "DDS::DomainParticipant::create_subscriber");

    /* Create a DataReader for the NamedMessage Topic (using the appropriate QoS). */
    parentReader = chatSubscriber->create_datareader(
        chatMessageTopic.in(),
        DATAREADER_QOS_USE_TOPIC_QOS,
        NULL,
        STATUS_MASK_NONE);
    checkHandle(parentReader, "DDS::Subscriber::create_datareader");

    /* Narrow the abstract parent into its typed representative. */
    chatAdmin = ChatMessageDataReader::_narrow(parentReader);
    checkHandle(chatAdmin.in(), "NetworkPartitionsData::ChatMessageDataReader::_narrow");

    /* Print a message that the MessageBoard has opened. */
    cout << "MessageBoard has opened: send a ChatMessage with userID = -1 to close it...." << endl << endl;

    while (!terminated) {
        /* Note: using read does not remove the samples from
           unregistered instances from the DataReader. This means
           that the DataRase would use more and more resources.
           That's why we use take here instead. */

        status = chatAdmin->take(
            msgSeq,
            infoSeq,
            LENGTH_UNLIMITED,
            ANY_SAMPLE_STATE,
            ANY_VIEW_STATE,
            ALIVE_INSTANCE_STATE );
        checkStatus(status, "NetworkPartitionsData::ChatMessageDataReader::take");

        for (ULong i = 0; i < msgSeq->length(); i++) {
            ChatMessage *msg = &(msgSeq[i]);
            if (msg->userID == TERMINATION_MESSAGE) {
                cout << "Termination message received: exiting..." << endl;
                terminated = true;
            } else {
                cout << msg->userID << ": " << msg->content << endl;
            }
        }

        status = chatAdmin->return_loan(msgSeq, infoSeq);
        checkStatus(status, "NetworkPartitionsData::ChatMessageDataReader::return_loan");

        /* Sleep for some amount of time, so as not to consume too many CPU cycles. */
        sleep(1);
    }

    /* Remove the DataReader */
    status = chatSubscriber->delete_datareader(chatAdmin.in());
    checkStatus(status, "DDS::Subscriber::delete_datareader");

    /* Remove the Subscriber. */
    status = participant->delete_subscriber(chatSubscriber.in());
    checkStatus(status, "DDS::DomainParticipant::delete_subscriber");

    /* Remove the Topic. */
    status = participant->delete_topic(chatMessageTopic.in());
    checkStatus(status, "DDS::DomainParticipant::delete_topic (chatMessageTopic)");

    /* De-allocate the type-names. */
    string_free(chatMessageTypeName);

    /* Remove the DomainParticipant. */
    status = dpf->delete_participant(participant.in());
    checkStatus(status, "DDS::DomainParticipantFactory::delete_participant");

    return 0;
}
Beispiel #8
0
int
OSPL_MAIN (
    int argc,
    char *argv[])
{
    /* Generic DDS entities */
    DomainParticipantFactory_var    dpf;
    DomainParticipant_var           participant;
    Topic_var                       chatMessageTopic;
    Publisher_var                   chatPublisher;
    DataWriter_ptr                  parentWriter;

    /* QosPolicy holders */
    TopicQos                        reliable_topic_qos;
    PublisherQos                    pub_qos;
    DataWriterQos                   dw_qos;

    /* DDS Identifiers */
    DomainId_t                      domain = 0;
    InstanceHandle_t                userHandle;
    ReturnCode_t                    status;

    /* Type-specific DDS entities */
    ChatMessageTypeSupport_var      chatMessageTS;
    ChatMessageDataWriter_var       talker;

    /* Sample definitions */
    ChatMessage                     *msg;   /* Example on Heap */

    /* Others */
    int                             ownID = 1;
    int                             i;
    const char                      *partitionName = "ChatRoom1";
    char                            *chatMessageTypeName = NULL;
    char                            buf[MAX_MSG_LEN];

#ifdef INTEGRITY
#ifdef CHATTER_QUIT
    ownID = -1;
#else
    ownID = 1;
#endif
#else
    /* Options: Chatter [ownID] */
    if (argc > 1) {
        ownID = atoi(argv[1]);
    }
#endif

    /* Create a DomainParticipantFactory and a DomainParticipant (using Default QoS settings. */
    dpf = DomainParticipantFactory::get_instance ();
    checkHandle(dpf.in(), "DDS::DomainParticipantFactory::get_instance");
    participant = dpf->create_participant(domain, PARTICIPANT_QOS_DEFAULT, NULL, STATUS_MASK_NONE);
    checkHandle(participant.in(), "DDS::DomainParticipantFactory::create_participant");

    /* Register the required datatype for ChatMessage. */
    chatMessageTS = new ChatMessageTypeSupport();
    checkHandle(chatMessageTS.in(), "new ChatMessageTypeSupport");
    chatMessageTypeName = chatMessageTS->get_type_name();
    status = chatMessageTS->register_type(
        participant.in(),
        chatMessageTypeName);
    checkStatus(status, "NetworkPartitionsData::ChatMessageTypeSupport::register_type");

    /* Set the ReliabilityQosPolicy to RELIABLE. */
    status = participant->get_default_topic_qos(reliable_topic_qos);
    checkStatus(status, "DDS::DomainParticipant::get_default_topic_qos");
    reliable_topic_qos.reliability.kind = RELIABLE_RELIABILITY_QOS;

    /* Make the tailored QoS the new default. */
    status = participant->set_default_topic_qos(reliable_topic_qos);
    checkStatus(status, "DDS::DomainParticipant::set_default_topic_qos");

    /* Use the changed policy when defining the ChatMessage topic */
    chatMessageTopic = participant->create_topic(
        "Chat_ChatMessage",
        chatMessageTypeName,
        reliable_topic_qos,
        NULL,
        STATUS_MASK_NONE);
    checkHandle(chatMessageTopic.in(), "DDS::DomainParticipant::create_topic (ChatMessage)");

    /* Adapt the default PublisherQos to write into the "ChatRoom1" Partition. */
    status = participant->get_default_publisher_qos (pub_qos);
    checkStatus(status, "DDS::DomainParticipant::get_default_publisher_qos");
    pub_qos.partition.name.length(1);
    pub_qos.partition.name[0] = partitionName;

    /* Create a Publisher for the chatter application. */
    chatPublisher = participant->create_publisher(pub_qos, NULL, STATUS_MASK_NONE);
    checkHandle(chatPublisher.in(), "DDS::DomainParticipant::create_publisher");

    /* Create a DataWriter for the ChatMessage Topic (using the appropriate QoS). */
    parentWriter = chatPublisher->create_datawriter(
        chatMessageTopic.in(),
        DATAWRITER_QOS_USE_TOPIC_QOS,
        NULL,
        STATUS_MASK_NONE);
    checkHandle(parentWriter, "DDS::Publisher::create_datawriter (chatMessage)");

    /* Narrow the abstract parent into its typed representative. */
    talker = ChatMessageDataWriter::_narrow(parentWriter);
    checkHandle(talker.in(), "NetworkPartitionsData::ChatMessageDataWriter::_narrow");

    /* Initialize the chat messages on Heap. */
    msg = new ChatMessage();
    checkHandle(msg, "new ChatMessage");
    msg->userID = ownID;
    msg->index = 0;
    if (ownID == TERMINATION_MESSAGE) {
        snprintf(buf, MAX_MSG_LEN, "Termination message.");
    } else {
        snprintf(buf, MAX_MSG_LEN, "Hi there, I will send you %d more messages.", NUM_MSG);
    }
    msg->content = string_dup(buf);
    cout << "Writing message: \"" << msg->content  << "\"" << endl;

    /* Register a chat message for this user (pre-allocating resources for it!!) */
    userHandle = talker->register_instance(*msg);

    /* Write a message using the pre-generated instance handle. */
    status = talker->write(*msg, userHandle);
    checkStatus(status, "NetworkPartitionsData::ChatMessageDataWriter::write");

    sleep (1); /* do not run so fast! */

    /* Write any number of messages, re-using the existing string-buffer: no leak!!. */
    for (i = 1; i <= NUM_MSG && ownID != TERMINATION_MESSAGE; i++) {
        msg->index = i;
        snprintf(buf, MAX_MSG_LEN, "Message no. %d", i);
        msg->content = string_dup(buf);
        cout << "Writing message: \"" << msg->content << "\"" << endl;
        status = talker->write(*msg, userHandle);
        checkStatus(status, "NetworkPartitionsData::ChatMessageDataWriter::write");
        sleep (1); /* do not run so fast! */
    }

    /* Leave the room by disposing and unregistering the message instance. */
    status = talker->dispose(*msg, userHandle);
    checkStatus(status, "NetworkPartitionsData::ChatMessageDataWriter::dispose");
    status = talker->unregister_instance(*msg, userHandle);
    checkStatus(status, "NetworkPartitionsData::ChatMessageDataWriter::unregister_instance");

    /* Release the data-samples. */
    delete msg;     // msg allocated on heap: explicit de-allocation required!!

    /* Remove the DataWriters */
    status = chatPublisher->delete_datawriter( talker.in() );
    checkStatus(status, "DDS::Publisher::delete_datawriter (talker)");

    /* Remove the Publisher. */
    status = participant->delete_publisher( chatPublisher.in() );
    checkStatus(status, "DDS::DomainParticipant::delete_publisher");

    status = participant->delete_topic( chatMessageTopic.in() );
    checkStatus(status, "DDS::DomainParticipant::delete_topic (chatMessageTopic)");

    /* Remove the type-names. */
    string_free(chatMessageTypeName);

    /* Remove the DomainParticipant. */
    status = dpf->delete_participant( participant.in() );
    checkStatus(status, "DDS::DomainParticipantFactory::delete_participant");

    cout << "Completed Chatter example" << endl;
    return 0;
}