Да получавате съобщения само от конкретен екземпляр на DDS тема?

Използвам OpenDDS v3.6 и се опитвам да изпратя съобщение до определен DDS партньор, един от многото. В IDL структурата на съобщението изглежда по следния начин:

module Test
{
#pragma DCPS_DATA_TYPE "Test::MyMessage"
#pragma DCPS_DATA_KEY "Test::MyMessage dest_id"
    struct MyMessage {
        short dest_id;
        string txt;
    };
};

Разбирам, че тъй като ключът за данни е уникален, това е нов екземпляр на темата, в който се пише, и всички допълнителни съобщения, написани със същия ключ за данни, се изпращат до този конкретен екземпляр на темата. Моят код за изпращане е както следва:

DDS::ReturnCode_t ret;
Test::MyMessage msg;

// populate msg
msg.dest_id = n;

DDS::InstanceHandle_t handle;

handle = msg_writer->register_instance(msg);

ret = msg_writer->write(msg, handle);

Така че сега трябва да разбера как да накарам получаващия партньор да чете само от този екземпляр на тема и да не получава всички останали съобщения, изпратени до други партньори. Започнах със следното, но не съм сигурен как правилно да избера конкретен екземпляр на тема.

DDS::InstanceHandle_t instance;

status = msg_dr->take_next_instance(spec, si, 1, DDS::ANY_SAMPLE_STATE, 
    DDS::ANY_VIEW_STATE, DDS::ANY_INSTANCE_STATE);

Всяка помощ е много ценена.


person Ender    schedule 19.04.2015    source източник


Отговори (1)


Най-лесният начин да постигнете това, което търсите, е като използвате ContentFilteredTopic. Този клас е специализация на класа TopicDescription и ви позволява да укажете израз (като SQL WHERE-клауза) на примерите, които ви интересуват.

Да предположим, че искате вашето DataReader да получава само проби с dest_id, равно на 42, тогава съответният код за създаване на ContentFilteredTopic ще изглежда нещо като

DDS::ContentFilteredTopic_var cft =
              participant->create_contentfilteredtopic("MyTopic-Filtered",
                                                       topic,
                                                       "dest_id = 42",
                                                       StringSeq());

Оттам нататък създавате своя DataReader, като използвате cft като параметър за TopicDescription. Полученият четец ще изглежда като обикновен DataReader, с изключение на това, че получава само желаните проби и нищо друго. Тъй като полето dest_id се оказва полето, което идентифицира екземпляра, крайният резултат е, че ще имате само един екземпляр във вашия DataReader.

Можете да разгледате DDS спецификацията (раздел 7.1.2.3.3) или Ръководство за разработчици на OpenDDS (раздел 5.2) за повече подробности.

person Reinier Torenbeek    schedule 20.04.2015
comment
Благодаря, тогава ще променя това на ContentFiltered. Дали обаче моето разбиране за екземплярите на теми е грешно? Каква е целта на нов екземпляр, базиран на ключа, ако партньорът ще получи всички проби от всички екземпляри от този тип? Може ли връстниците да не четат нито един екземпляр? - person Ender; 20.04.2015
comment
И ако разбирам правилно специализацията на класа, това е TopicDecscription, а не Topic, както имате. Така че предполагам, че това е просто правописна грешка или, моля, поправете ме. - person Ender; 21.04.2015
comment
Вашето разбиране за екземплярите на теми може наистина да е погрешно... Целта на нов екземпляр, базиран на ключа, е всеки екземпляр на темата да има свой собствен жизнен цикъл на CRUD. В тази светлина можете да сравните тема с таблица на база данни и екземплярите с редовете в тази таблица. В някои случаи партньорът може да се интересува от всички редове (например всички камиони във флота), но в други случаи партньорът може да се интересува от един ред (например ако се използва за заявка/отговор). - person Reinier Torenbeek; 21.04.2015
comment
Вие също попитахте Могат ли партньорите да не четат нито един екземпляр? -- да, могат, за това е ContentFilteredTopic. Обърнете внимание, че read_instance() (и свързаните функции за екземпляри) могат да се използват за четене на единичен екземпляр извън пула от екземпляри в DataReader. Това обаче няма да избегне доставката на други копия на DataReader. За това се нуждаете от ContentFilteredTopic. - person Reinier Torenbeek; 21.04.2015
comment
Прав си за базовия клас TopicDescription, благодаря. коригирах го. - person Reinier Torenbeek; 21.04.2015
comment
Работи чудесно. Благодаря и за разяснението. - person Ender; 21.04.2015