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