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