artdaq  v3_12_02
RTIDDS.cc
1 #define TRACE_NAME "RTIDDS"
2 
3 #include "artdaq/RTIDDS/RTIDDS.hh"
4 #include "artdaq/DAQdata/Globals.hh"
5 
6 #include <boost/lexical_cast.hpp>
7 #include <boost/tokenizer.hpp>
8 
9 #include <iostream>
10 
11 artdaq::RTIDDS::RTIDDS(std::string name, IOType iotype, std::string max_size)
12  : name_(name)
13  , iotype_(iotype)
14  , max_size_(max_size)
15 {
16  DDS_ReturnCode_t retcode = DDS_RETCODE_ERROR;
17  DDS_DomainParticipantQos participant_qos;
18 
19  retcode = DDSDomainParticipantFactory::get_instance()->get_default_participant_qos(participant_qos);
20 
21  if (retcode != DDS_RETCODE_OK)
22  {
23  TLOG(TLVL_WARNING) << name_ << ": Problem obtaining default participant QoS, retcode was " << retcode;
24  }
25 
26  retcode = DDSPropertyQosPolicyHelper::add_property(
27  participant_qos.property, "dds.builtin_type.octets.max_size",
28  max_size_.c_str(),
29  DDS_BOOLEAN_FALSE);
30 
31  if (retcode != DDS_RETCODE_OK)
32  {
33  TLOG(TLVL_WARNING) << name_ << ": Problem setting dds.builtin_type.octets.max_size, retcode was " << retcode;
34  }
35 
36  participant_.reset(DDSDomainParticipantFactory::get_instance()->create_participant(
37  0, // Domain ID
38  participant_qos,
39  nullptr, // Listener
40  DDS_STATUS_MASK_NONE));
41 
42  topic_octets_ = participant_->create_topic(
43  "artdaq fragments", // Topic name
44  DDSOctetsTypeSupport::get_type_name(), // Type name
45  DDS_TOPIC_QOS_DEFAULT, // Topic QoS
46  nullptr, // Listener
47  DDS_STATUS_MASK_NONE);
48 
49  if (participant_ == nullptr || topic_octets_ == nullptr)
50  {
51  TLOG(TLVL_WARNING) << name_ << ": Problem setting up the RTI-DDS participant and/or topic";
52  }
53 
54  // JCF, 9/16/15
55 
56  // Following effort to increase the max DDS buffer size from its
57  // default of 2048 bytes is cribbed from section 3.2.7 of the Core
58  // Utilities user manual, "Managing Memory for Built-in Types"
59 
60  DDS_DataWriterQos writer_qos;
61 
62  retcode = participant_->get_default_datawriter_qos(writer_qos);
63 
64  if (retcode != DDS_RETCODE_OK)
65  {
66  TLOG(TLVL_WARNING) << name_ << ": Problem obtaining default datawriter QoS, retcode was " << retcode;
67  }
68 
69  retcode = DDSPropertyQosPolicyHelper::add_property(
70  writer_qos.property, "dds.builtin_type.octets.alloc_size",
71  max_size_.c_str(),
72  DDS_BOOLEAN_FALSE);
73 
74  if (retcode != DDS_RETCODE_OK)
75  {
76  TLOG(TLVL_WARNING) << name_ << ": Problem setting dds.builtin_type.octets.alloc_size, retcode was " << retcode;
77  }
78 
79  if (iotype_ == IOType::writer)
80  {
81  octets_writer_ = DDSOctetsDataWriter::narrow(participant_->create_datawriter(
82  topic_octets_,
83  writer_qos,
84  nullptr, // Listener
85  DDS_STATUS_MASK_NONE));
86 
87  if (octets_writer_ == nullptr)
88  {
89  TLOG(TLVL_WARNING) << name_ << ": Problem setting up the RTI-DDS writer objects";
90  }
91  }
92  else
93  {
94  octets_reader_ = participant_->create_datareader(
95  topic_octets_,
96  DDS_DATAREADER_QOS_DEFAULT, // QoS
97  &octets_listener_, // Listener
98  DDS_DATA_AVAILABLE_STATUS);
99 
100  if (octets_reader_ == nullptr)
101  {
102  TLOG(TLVL_WARNING) << name_ << ": Problem setting up the RTI-DDS reader objects";
103  }
104  }
105 }
106 
107 void artdaq::RTIDDS::transfer_fragment_reliable_mode_via_DDS_(artdaq::Fragment&& fragment) { transfer_fragment_min_blocking_mode_via_DDS_(fragment); }
108 
110 {
111  // check if a fragment of this type has already been copied
112  size_t fragmentType = fragment.type();
113 
114  if (octets_writer_ == NULL) { return; }
115 
116  // JCF, 9/15/15
117 
118  // Perform the same checks Kurt implemented in the AggregatorCore's
119  // copyFragmentToSharedMemory_() function
120 
121  size_t max_fragment_size = boost::lexical_cast<size_t>(max_size_) -
122  detail::RawFragmentHeader::num_words() * sizeof(RawDataType);
123 
124  if (fragment.type() != artdaq::Fragment::InvalidFragmentType &&
125  fragment.sizeBytes() < max_fragment_size)
126  {
127  if (fragment.type() == artdaq::Fragment::InitFragmentType)
128  {
129  usleep(500000);
130  }
131 
132  DDS_ReturnCode_t retcode = octets_writer_->write(reinterpret_cast<unsigned char*>(fragment.headerBeginBytes()),
133  fragment.sizeBytes(),
134  DDS_HANDLE_NIL);
135 
136  if (retcode != DDS_RETCODE_OK)
137  {
138  TLOG(TLVL_WARNING) << name_ << ": Problem writing octets (bytes), retcode was " << retcode;
139 
140  TLOG(TLVL_WARNING) << name_ << ": Fragment failed for DDS! "
141  << "fragment address and size = "
142  << static_cast<void*>(fragment.headerBeginBytes()) << " " << static_cast<int>(fragment.sizeBytes()) << " "
143  << "sequence ID, fragment ID, and type = "
144  << fragment.sequenceID() << " "
145  << fragment.fragmentID() << " "
146  << ((int)fragment.type());
147  }
148  }
149  else
150  {
151  TLOG(TLVL_WARNING) << name_ << ": Fragment invalid for DDS! "
152  << "fragment address and size = "
153  << static_cast<void*>(fragment.headerBeginBytes()) << " " << static_cast<int>(fragment.sizeBytes()) << " "
154  << "sequence ID, fragment ID, and type = "
155  << fragment.sequenceID() << " "
156  << fragment.fragmentID() << " "
157  << ((int)fragment.type());
158  }
159 }
160 
162 {
163  DDSOctetsDataReader* octets_reader = NULL;
164  DDS_SampleInfo info;
165  DDS_ReturnCode_t retcode;
166 
167  TLOG(TLVL_DEBUG + 32) << name_ << ": In OctetsListener::on_data_available";
168 
169  octets_reader = DDSOctetsDataReader::narrow(reader);
170  if (octets_reader == nullptr)
171  {
172  TLOG(TLVL_ERROR) << name_ << ": Error: Very unexpected - DDSOctetsDataReader::narrow failed";
173  return;
174  }
175 
176  // Loop until there are messages available in the queue
177 
178  for (;;)
179  {
180  retcode = octets_reader->take_next_sample(
181  dds_octets_,
182  info);
183  if (retcode == DDS_RETCODE_NO_DATA)
184  {
185  // No more samples
186  break;
187  }
188  else if (retcode != DDS_RETCODE_OK)
189  {
190  TLOG(TLVL_WARNING) << "Unable to take data from data reader, error "
191  << retcode;
192  return;
193  }
194  if (info.valid_data)
195  {
196  // JCF, 9/17/15
197 
198  // We want to make sure the dds_octets_ doesn't get popped from
199  // by receiveFragmentFromDDS before we display its contents
200 
201  std::lock_guard<std::mutex> lock(queue_mutex_);
202 
203  dds_octets_queue_.push(dds_octets_);
204  }
205  }
206 }
207 
208 // receiveFragmentFromDDS returns true (and fills fragment passed to
209 // it) in there's no timeout; if there is, returns false
210 
212  const size_t receiveTimeout)
213 {
214  int loopCount = 0;
215  size_t sleepTime = 1000; // microseconds
216  size_t nloops = receiveTimeout / sleepTime;
217 
218  while (dds_octets_queue_.empty() && loopCount < nloops)
219  {
220  usleep(sleepTime);
221  ++loopCount;
222  }
223 
224  // JCF, 9/17/15
225 
226  // Make sure the on_data_available() callback function doesn't
227  // modify dds_octets_queue_ while this section is running
228 
229  std::lock_guard<std::mutex> lock(queue_mutex_);
230 
231  if (!dds_octets_queue_.empty())
232  {
233  fragment.resizeBytes(dds_octets_queue_.front().length);
234  memcpy(fragment.headerAddress(), dds_octets_queue_.front().value, dds_octets_queue_.front().length);
235 
236  dds_octets_queue_.pop();
237 
238  TLOG(TLVL_DEBUG + 32) << name_
239  << ": Received fragment from DDS, type ="
240  << ((int)fragment.type()) << ", sequenceID = "
241  << fragment.sequenceID() << ", size in bytes = "
242  << fragment.sizeBytes();
243 
244  return true;
245  }
246 
247  return false;
248 }
void transfer_fragment_min_blocking_mode_via_DDS_(artdaq::Fragment const &fragment)
Copy a Fragment to DDS.
Definition: RTIDDS.cc:109
OctetsListener octets_listener_
The receiver.
Definition: RTIDDS.hh:93
void on_data_available(DDSDataReader *reader)
Action to perform when data is available.
Definition: RTIDDS.cc:161
bool receiveFragmentFromDDS(artdaq::Fragment &fragment, const size_t receiveTimeout)
Receive a Fragment from DDS.
Definition: RTIDDS.cc:211
RTIDDS(std::string name, IOType iotype, std::string max_size="1000000")
Construct a RTIDDS transmitter.
Definition: RTIDDS.cc:11
void transfer_fragment_reliable_mode_via_DDS_(artdaq::Fragment &&fragment)
Move a Fragment to DDS.
Definition: RTIDDS.cc:107
IOType
Whether this DDS instance is a reader or a writer.
Definition: RTIDDS.hh:26