Получать сообщения только от определенного экземпляра темы 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