00001 #define TRACE_NAME "RTIDDS"
00002
00003 #include "artdaq/RTIDDS/RTIDDS.hh"
00004 #include "artdaq/DAQdata/Globals.hh"
00005
00006 #include <boost/tokenizer.hpp>
00007
00008 #include <iostream>
00009
00010
00011 artdaq::RTIDDS::RTIDDS(std::string name, IOType iotype, std::string max_size) :
00012 name_(name)
00013 , iotype_(iotype)
00014 , max_size_(max_size)
00015 {
00016 DDS_ReturnCode_t retcode = DDS_RETCODE_ERROR;
00017 DDS_DomainParticipantQos participant_qos;
00018
00019 retcode = DDSDomainParticipantFactory::get_instance()->get_default_participant_qos(participant_qos);
00020
00021 if (retcode != DDS_RETCODE_OK)
00022 {
00023 TLOG(TLVL_WARNING) << name_ << ": Problem obtaining default participant QoS, retcode was " << retcode ;
00024 }
00025
00026 retcode = DDSPropertyQosPolicyHelper::add_property(
00027 participant_qos.property, "dds.builtin_type.octets.max_size",
00028 max_size_.c_str(),
00029 DDS_BOOLEAN_FALSE);
00030
00031 if (retcode != DDS_RETCODE_OK)
00032 {
00033 TLOG(TLVL_WARNING) << name_ << ": Problem setting dds.builtin_type.octets.max_size, retcode was " << retcode ;
00034 }
00035
00036 participant_.reset(DDSDomainParticipantFactory::get_instance()->
00037 create_participant(
00038 0,
00039 participant_qos,
00040 nullptr,
00041 DDS_STATUS_MASK_NONE)
00042 );
00043
00044 topic_octets_ = participant_->create_topic(
00045 "artdaq fragments",
00046 DDSOctetsTypeSupport::get_type_name(),
00047 DDS_TOPIC_QOS_DEFAULT,
00048 nullptr,
00049 DDS_STATUS_MASK_NONE);
00050
00051 if (participant_ == nullptr || topic_octets_ == nullptr)
00052 {
00053 TLOG(TLVL_WARNING) << name_ << ": Problem setting up the RTI-DDS participant and/or topic" ;
00054 }
00055
00056
00057
00058
00059
00060
00061
00062
00063 DDS_DataWriterQos writer_qos;
00064
00065 retcode = participant_->get_default_datawriter_qos(writer_qos);
00066
00067 if (retcode != DDS_RETCODE_OK)
00068 {
00069 TLOG(TLVL_WARNING) << name_ << ": Problem obtaining default datawriter QoS, retcode was " << retcode ;
00070 }
00071
00072 retcode = DDSPropertyQosPolicyHelper::add_property(
00073 writer_qos.property, "dds.builtin_type.octets.alloc_size",
00074 max_size_.c_str(),
00075 DDS_BOOLEAN_FALSE);
00076
00077 if (retcode != DDS_RETCODE_OK)
00078 {
00079 TLOG(TLVL_WARNING) << name_ << ": Problem setting dds.builtin_type.octets.alloc_size, retcode was " << retcode ;
00080 }
00081
00082
00083 if (iotype_ == IOType::writer)
00084 {
00085 octets_writer_ = DDSOctetsDataWriter::narrow(participant_->create_datawriter(
00086 topic_octets_,
00087 writer_qos,
00088 nullptr,
00089 DDS_STATUS_MASK_NONE)
00090 );
00091
00092 if (octets_writer_ == nullptr)
00093 {
00094 TLOG(TLVL_WARNING) << name_ << ": Problem setting up the RTI-DDS writer objects" ;
00095 }
00096 }
00097 else
00098 {
00099 octets_reader_ = participant_->create_datareader(
00100 topic_octets_,
00101 DDS_DATAREADER_QOS_DEFAULT,
00102 &octets_listener_,
00103 DDS_DATA_AVAILABLE_STATUS);
00104
00105 if (octets_reader_ == nullptr)
00106 {
00107 TLOG(TLVL_WARNING) << name_ << ": Problem setting up the RTI-DDS reader objects" ;
00108 }
00109 }
00110 }
00111
00112 void artdaq::RTIDDS::moveFragmentToDDS_(artdaq::Fragment&& fragment) { copyFragmentToDDS_(fragment); }
00113
00114 void artdaq::RTIDDS::copyFragmentToDDS_(artdaq::Fragment& fragment)
00115 {
00116
00117 size_t fragmentType = fragment.type();
00118
00119 if (octets_writer_ == NULL) { return; }
00120
00121
00122
00123
00124
00125
00126 size_t max_fragment_size = boost::lexical_cast<size_t>(max_size_) -
00127 detail::RawFragmentHeader::num_words() * sizeof(RawDataType);
00128
00129 if (fragment.type() != artdaq::Fragment::InvalidFragmentType &&
00130 fragment.sizeBytes() < max_fragment_size)
00131 {
00132 if (fragment.type() == artdaq::Fragment::InitFragmentType)
00133 {
00134 usleep(500000);
00135 }
00136
00137 DDS_ReturnCode_t retcode = octets_writer_->write(reinterpret_cast<unsigned char*>(fragment.headerBeginBytes()),
00138 fragment.sizeBytes(),
00139 DDS_HANDLE_NIL);
00140
00141 if (retcode != DDS_RETCODE_OK)
00142 {
00143 TLOG(TLVL_WARNING) << name_ << ": Problem writing octets (bytes), retcode was " << retcode ;
00144
00145 TLOG(TLVL_WARNING) << name_ << ": Fragment failed for DDS! "
00146 << "fragment address and size = "
00147 << static_cast<void*>(fragment.headerBeginBytes()) << " " << static_cast<int>(fragment.sizeBytes()) << " "
00148 << "sequence ID, fragment ID, and type = "
00149 << fragment.sequenceID() << " "
00150 << fragment.fragmentID() << " "
00151 << ((int) fragment.type()) ;
00152 }
00153 }
00154 else
00155 {
00156 TLOG(TLVL_WARNING) << name_ << ": Fragment invalid for DDS! "
00157 << "fragment address and size = "
00158 << static_cast<void*>(fragment.headerBeginBytes()) << " " << static_cast<int>(fragment.sizeBytes()) << " "
00159 << "sequence ID, fragment ID, and type = "
00160 << fragment.sequenceID() << " "
00161 << fragment.fragmentID() << " "
00162 << ((int) fragment.type()) ;
00163 }
00164 }
00165
00166 void artdaq::RTIDDS::OctetsListener::on_data_available(DDSDataReader* reader)
00167 {
00168 DDSOctetsDataReader* octets_reader = NULL;
00169 DDS_SampleInfo info;
00170 DDS_ReturnCode_t retcode;
00171
00172 TLOG(TLVL_DEBUG) << name_ << ": In OctetsListener::on_data_available" ;
00173
00174
00175 octets_reader = DDSOctetsDataReader::narrow(reader);
00176 if (octets_reader == nullptr)
00177 {
00178 TLOG(TLVL_ERROR) << name_ << ": Error: Very unexpected - DDSOctetsDataReader::narrow failed" ;
00179 return;
00180 }
00181
00182
00183
00184
00185 for (;;)
00186 {
00187 retcode = octets_reader->take_next_sample(
00188 dds_octets_,
00189 info);
00190 if (retcode == DDS_RETCODE_NO_DATA)
00191 {
00192
00193 break;
00194 }
00195 else if (retcode != DDS_RETCODE_OK)
00196 {
00197 TLOG(TLVL_WARNING) << "Unable to take data from data reader, error "
00198 << retcode ;
00199 return;
00200 }
00201 if (info.valid_data)
00202 {
00203
00204
00205
00206
00207
00208 std::lock_guard<std::mutex> lock(queue_mutex_);
00209
00210 dds_octets_queue_.push(dds_octets_);
00211 }
00212 }
00213 }
00214
00215
00216
00217
00218 bool artdaq::RTIDDS::OctetsListener::receiveFragmentFromDDS(artdaq::Fragment& fragment,
00219 const size_t receiveTimeout)
00220 {
00221 int loopCount = 0;
00222 size_t sleepTime = 1000;
00223 size_t nloops = receiveTimeout / sleepTime;
00224
00225 while (dds_octets_queue_.empty() && loopCount < nloops)
00226 {
00227 usleep(sleepTime);
00228 ++loopCount;
00229 }
00230
00231
00232
00233
00234
00235
00236 std::lock_guard<std::mutex> lock(queue_mutex_);
00237
00238 if (!dds_octets_queue_.empty())
00239 {
00240 fragment.resizeBytes(dds_octets_queue_.front().length);
00241 memcpy(fragment.headerAddress(), dds_octets_queue_.front().value, dds_octets_queue_.front().length);
00242
00243 dds_octets_queue_.pop();
00244
00245 TLOG(TLVL_DEBUG) << name_
00246 << ": Received fragment from DDS, type ="
00247 << ((int)fragment.type()) << ", sequenceID = "
00248 << fragment.sequenceID() << ", size in bytes = "
00249 << fragment.sizeBytes()
00250 ;
00251
00252 return true;
00253 }
00254
00255 return false;
00256 }