Create Domain with specific Qos File

5 posts / 0 new
Last post
Offline
Last seen: 4 years 2 weeks ago
Joined: 02/27/2014
Posts: 6
Create Domain with specific Qos File

I want to create two domain participant with two qos file. One for one participant.

 

I try but I don't succes very well...

 

First Step, I create the two domain like this :



    DomainParticipantManager::createParticipant(1, _T("PLOP_QOS_FILE.xml"));
    DomainParticipantManager::createParticipant(2, _T("PLIP_QOS_FILE.xml"));

 

DomainParticipantManager is like this :


void DomainParticipantManager::createParticipant(int domainId, const CString & qosFile)
{

    DDSDomainParticipant * domainParticipant = NULL;

    for (int index = 0; index < m_CountDDSDomainParticipant; index++)
    {
        DDSDomainParticipant * tmpDDSParticipant = m_TabDDSDomainParticipant[index];

        if (tmpDDSParticipant->get_domain_id() == domainId)
        {
            domainParticipant = tmpDDSParticipant;
        }
    }

    if (domainParticipant == NULL)
    {
        /* To load my_custom_qos_profiles.xml, as explained above, we need to modify
         * the  DDSTheParticipantFactory Profile QoSPolicy */
        DDS_DomainParticipantFactoryQos factory_qos;
        DDSTheParticipantFactory->get_qos(factory_qos);

        /* We are only going to add one XML file to the url_profile sequence, so we
         * ensure a length of 1,1. */
        factory_qos.profile.url_profile.ensure_length(1, 1);

        /* The XML file will be loaded from the working directory. That means, you
         * need to run the example like this:
         * ./objs/<architecture>/profiles_publisher
         * (see README.txt for more information on how to run the example).
         *
         * Note that you can specify the absolute path of the XML QoS file to avoid
         * this problem.
         */
        factory_qos.profile.url_profile[0] =
                DDS_String_dup(qosFile); //"TEST_QOS_FILE.xml");

        DDSTheParticipantFactory->set_qos(factory_qos);


        /* Our default Qos profile, volatile_profile, sets the participant name.
         * This is the only participant_qos policy that we change in our
         * example. As this is done in the default QoS profile, we don't need
         * to specify its name, so we can create the participant using the
         * create_participant() method rather than using
         * create_participant_with_profile().  */
        /*participant = DDSTheParticipantFactory->create_participant(
                domainId, DDS_PARTICIPANT_QOS_DEFAULT,
                NULL, DDS_STATUS_MASK_NONE);
        if (participant == NULL) {
            printf("create_participant error\n");
            publisher_shutdown(participant);
            return -1;
        }*/

        domainParticipant = DDSTheParticipantFactory->create_participant(
                domainId,
                DDS_PARTICIPANT_QOS_DEFAULT,
                NULL /* listener */,
                DDS_STATUS_MASK_NONE);

        DDSDomainParticipant ** newTableau = new DDSDomainParticipant*[m_CountDDSDomainParticipant + 1];
        
        for (int index = 0; index < m_CountDDSDomainParticipant; index++)
        {
            newTableau[index] = m_TabDDSDomainParticipant[index];
        }
        newTableau[m_CountDDSDomainParticipant] = domainParticipant;
        m_CountDDSDomainParticipant++;
        delete[] m_TabDDSDomainParticipant;
        m_TabDDSDomainParticipant = newTableau;
    }
    else
    {
        printf("warning : domain %d already initialized !\n", domainId);
    }

    //return domainParticipant;
}

 

The second step is simple :

    //Creation des publishers
    m_pTopicPP = new TopicPPPublisher(
            1,
            _T("EXT"),
            _T("P_P_Library"),
            _T("P_P_Publisher_Profile"),
            _T("P_P_Writer_Qos"));

 

    //Creation des publishers
    m_pTopicTX = new TopicTXPublisher(
            2,
            _T("INT"),
            _T("T_X_Library"),
            _T("T_X_Publisher_Profile"),
            _T("T_X_Writer_Qos"));

 

The result is like the second call of DomainParticipantManager::createParticipant erase the first call. So My Qos Factory don't containt the first file.

 

Maybe it is because I execute "factory_qos.profile.url_profile[0] =
                DDS_String_dup(qosFile); //"TEST_QOS_FILE.xml");" and I should do something like this :

 

factory_qos.profile.url_profile[m_CountDDSDomainParticipant] =
                DDS_String_dup(qosFile); //"TEST_QOS_FILE.xml"); but int this case, how can I says at DDSTheParticipantFactory to select the first url and not the second in this line of code :  domainParticipant = DDSTheParticipantFactory->create_participant(
                domainId,
                DDS_PARTICIPANT_QOS_DEFAULT,
                NULL /* listener */,
                DDS_STATUS_MASK_NONE); 

What sould I wrote to replace "DDS_PARTICIPANT_QOS_DEFAULT" ?

 

 

Thank you very much !

 

Maxime

 

Organization:
Fernando Garcia's picture
Offline
Last seen: 1 week 4 days ago
Joined: 05/18/2011
Posts: 198

Hello Potoman,

The DomainParticipantFactory is a singleton class, so every time you set and get its QoS you are operating over the same object. As a result, when you call factory->set_qos(factory_qos) you are actually overwriting the value of the different url_profile sequence with your new QoS file. To add a new file instead of overwriting the value of whatever was in there, you will need to add new elements to the sequence every time you want to add a new XML file with new QoS definitions.

This is more or less what I would in your createParticipant() function to be able to load more than one QoS file:

void DomainParticipantManager::createParticipant(int domainId, const CString & qosFile)
{
    DDSDomainParticipantFactory * factory = NULL;    
    DDS_DomainParticipantFactoryQos factory_qos;

    /* Get DDSDomainParticipantFactory instance */
    factory = DDSDomainParticipantFactory::get_instance();
    if (factory == NULL) {
        //report error accordingly
    }

    /* Get DDSParticipantFactory QoS */
    factory->get_qos(factory_qos);

    /* Get current length of url_profile sequence */
    DDS_Long url_profile_seq_len = factory_qos.profile.url_profile.length();

    /* Ensure new length of url_profile sequence, i.e., old length + 1 */
    if (!factory.qos.profile.url_profile.ensure_length(url_profile_seq_len + 1,
                                                       url_profile_seq_len + 1)) {
         DDS_DomainParticipantFactoryQos_finalize(&factory_qos);
         //report error accordingly
    }
    /* Add QoS file to the sequence. It will be the last element */
    factory_qos.profile.url_profile[url_profile_seq_length] = 
        DDS_String_dup(qosFile);
    ...
    
    DDS_DomainParticipantFactoryQos_finalize(&factory_qos);

}

Now if you want to create DomainParticipants with different QoS profiles you will need to create in your XML files different QoS profiles in different QoS libraries that you will need to specify when creating your participant. To specify an specific QoS profile when you create the participant you will need to call the DDSDomainParticipantFactory::create_participant_with_profile() method. I would change your function to pass the name of the library and QoS profile.

void DomainParticipantManager::createParticipant(int domainId, const CString & qosFile, 
    const char *library_name, *profile_name)
{
    /* before you would have logic we added in the previous snippet */ 
    
    /* Create participant with profile */
    DDSDomainParticipant *participant = NULL;
    participant = factory->create_participant_with_profile(domainId,
                                                           library_name,
                                                           profile_name,
                                                           NULL /*listener*/,
                                                           DDS_STATUS_MASK_NONE);
    if (participant == NULL) {
         // Report error accordingly
    }   
     
}  

Let me know if this works for you.

Best regards,
Fernando.

Offline
Last seen: 4 years 2 weeks ago
Joined: 02/27/2014
Posts: 6

Thank Fernando.

 

I already know what you say so let me tell you what I actually want to do...

 

 

Very sorry if I don't speak with a really good english by advance so I try to make short sentence with easy word :)

I want, when a user wish create a DomainParticipant, affect this domain with one (or more) specific Qos file. So when he want create participant with a specific profile, he only have the choice among the profil are in the Qos affected by the domain Id.

 

By example:

 

I have three Qos file :

Qos file A, B and C.


In Qos file A, I have profil a, b, c.

In Qos file B, I have profile d.


And finally, in Qos file C, I have profil e and f.

 

 

My question is : Can I instanciate a DomainParticipant with a DomainParticipantFactory init with Qos file A & B that allow this DomainParticipant to use the profil a, b, c and d.

And after, reset the Qos File in the DomainParticipantFactory by init it with Qos file C in front to create another DomainParticipant that allow the user to only use the profil e and f ?

 

The Qos File can be link with a DomainParticipant after the creating of the DomainParticipant And not only link with DomainParticipantFactory ?

 

Thanks.

 

 

 

 

Offline
Last seen: 4 years 2 weeks ago
Joined: 02/27/2014
Posts: 6

Because if we can't link different QOS file with different DomainParticipant... WHY !!! Yes WHY !!! Why we specific the value "DomainParticipantFactory.PARTICIPANT_QOS_DEFAULT" in the call to create a DomainParticipant.

Cf :

DomainParticipantFactory.TheParticipantFactory.create_participant(domainId,
                        DomainParticipantFactory.PARTICIPANT_QOS_DEFAULT,
                        null,
                        StatusKind.STATUS_MASK_NONE));

 

Me, I want to do :

DomainParticipantFactory.TheParticipantFactory.create_participant(1,
                        QosFileA,
                        null,
                        StatusKind.STATUS_MASK_NONE));

 

DomainParticipantFactory.TheParticipantFactory.create_participant(2,
                        QosFileB & QosFileC,
                        null,
                        StatusKind.STATUS_MASK_NONE));

 

Is it possible ?

 

Thanks.

 

Fernando Garcia's picture
Offline
Last seen: 1 week 4 days ago
Joined: 05/18/2011
Posts: 198

Hello Potoman,

When you create a DomainParticipant you are creating an entity that will interact with other DomainParticipants within the same domain. You can have many different DomainParticipants within the same domain with different QoS profiles. Each of these DomainParticipants needs to be created with an specific QoS profiles. If its profile is not specified (i.e., if you pass the PARTICIPANT_QOS_DEFAULT), the middleware will decide what is the default QoS profile in your case.

I have some doubts of what you intent to create when you pass an XML file to the DomainParticipantFactory to create a DomainParticipant. In DDS, you have to specify the QoS profile you want to create your participant with. XML files you may load are just containers where these QoS profiles are stored. In other words, all your profiles (i.e., a, b, c, d, and e) could be in the same XML file--it will not make a different in the end. 

Once you have written all the QoS profiles that you want your different participants to use, you need to load them. To load them you need to add them to a sequence of files to be loaded, which is contained in the DomainParticipantFactoryQoS (i.e., factory_qos.profile.url_profile). You will find how to do this in my previous answer. Once they are loaded and available, you need to explicitly specify the profile you want to create your participant with. DomainParticipants can only be created with one QoS profiles. If you want to use another QoS profile, you will need to create a different participant within the same domain. 

In summary, what you want to achieve is not possible. You can only create a DomainParticipant with a single QoS profile (regardless of whether is the default one or any of the other available ones). If you give us more detail about your use case, we will try to find a workaround to achieve what you want. 

Thanks,
Fernando.