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