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