00001
00002
00003
00004
00005
00006
00007
00008 #include "DCPS/DdsDcps_pch.h"
00009 #include "dds/DCPS/DCPS_Utils.h"
00010 #include "dds/DCPS/Qos_Helper.h"
00011 #include "dds/DCPS/Definitions.h"
00012
00013 #include "ace/ACE.h"
00014 #include "ace/OS_NS_string.h"
00015
00016 #include <cstring>
00017
00018 namespace OpenDDS {
00019 namespace DCPS {
00020
00021 bool
00022 is_wildcard(const char *str)
00023 {
00024 static const char wild[] = "?*[";
00025
00026 while (*str) {
00027 size_t i = ACE_OS::strcspn(str, wild);
00028
00029 if (!str[i]) return false;
00030
00031 if (i > 0 && str[i-1] == '\\') str += i + 1;
00032
00033 else return true;
00034 }
00035
00036 return false;
00037 }
00038
00039 class PartitionName {
00040 public:
00041 PartitionName(const char* name)
00042 : name_(name),
00043 wildcard_(is_wildcard(name)) {}
00044
00045 bool matches(const PartitionName& n) {
00046 if (wildcard_ && n.wildcard_)
00047 return false;
00048
00049 if (wildcard_)
00050 return ACE::wild_match(n.name_, name_, true, true);
00051
00052 else if (n.wildcard_)
00053 return ACE::wild_match(name_, n.name_, true, true);
00054
00055 else
00056 return ACE_OS::strcmp(name_, n.name_) == 0;
00057 }
00058
00059 private:
00060 const char* name_;
00061 bool wildcard_;
00062 };
00063
00064 bool
00065 matches_name(const DDS::PartitionQosPolicy& qos, const PartitionName& name)
00066 {
00067 for (CORBA::ULong i = 0; i < qos.name.length(); ++i) {
00068 PartitionName qos_name(qos.name[i]);
00069
00070 if (qos_name.matches(name))
00071 return true;
00072 }
00073
00074 return false;
00075 }
00076
00077 bool
00078 matches_default(const DDS::PartitionQosPolicy& qos)
00079 {
00080 if (qos.name.length() == 0)
00081 return true;
00082
00083 for (CORBA::ULong i = 0; i < qos.name.length(); ++i) {
00084 if (*qos.name[i] == 0)
00085 return true;
00086 }
00087
00088 return false;
00089 }
00090
00091 bool
00092 matching_partitions(const DDS::PartitionQosPolicy& pub,
00093 const DDS::PartitionQosPolicy& sub)
00094 {
00095 if (matches_default(pub)) {
00096 if (matches_default(sub))
00097 return true;
00098
00099
00100
00101 if (pub.name.length() == 0)
00102 return matches_name(sub, "");
00103 }
00104
00105 for (CORBA::ULong i = 0; i < pub.name.length(); ++i) {
00106 const char* name = pub.name[i];
00107
00108 if (matches_name(sub, name))
00109 return true;
00110 }
00111
00112 return false;
00113 }
00114
00115 void
00116 increment_incompatibility_count(OpenDDS::DCPS::IncompatibleQosStatus* status,
00117 DDS::QosPolicyId_t incompatible_policy)
00118 {
00119 ++status->total_count;
00120 ++status->count_since_last_send;
00121 status->last_policy_id = incompatible_policy;
00122 CORBA::ULong const size = status->policies.length();
00123 CORBA::ULong count = 0;
00124 bool updated = false;
00125
00126 for (; !updated && count < size; ++count) {
00127 if (status->policies[count].policy_id == incompatible_policy) {
00128 ++status->policies[count].count;
00129 updated = true;
00130 }
00131 }
00132
00133 if (!updated) {
00134 DDS::QosPolicyCount policy;
00135 policy.policy_id = incompatible_policy;
00136 policy.count = 1;
00137 status->policies.length(count + 1);
00138 status->policies[count] = policy;
00139 }
00140 }
00141
00142 bool
00143 compatibleTransports(const OpenDDS::DCPS::TransportLocatorSeq& s1,
00144 const OpenDDS::DCPS::TransportLocatorSeq& s2)
00145 {
00146 for (CORBA::ULong i = 0; i < s1.length(); ++i) {
00147 for (CORBA::ULong j = 0; j < s2.length(); ++j) {
00148 if (0 == std::strcmp(s1[i].transport_type, s2[j].transport_type)) {
00149 return true;
00150 }
00151 }
00152 }
00153 return false;
00154 }
00155
00156 bool
00157 compatibleQOS(OpenDDS::DCPS::IncompatibleQosStatus* writerStatus,
00158 OpenDDS::DCPS::IncompatibleQosStatus* readerStatus,
00159 const OpenDDS::DCPS::TransportLocatorSeq& pubTLS,
00160 const OpenDDS::DCPS::TransportLocatorSeq& subTLS,
00161 DDS::DataWriterQos const * const writerQos,
00162 DDS::DataReaderQos const * const readerQos,
00163 DDS::PublisherQos const * const pubQos,
00164 DDS::SubscriberQos const * const subQos)
00165 {
00166 bool compatible = true;
00167
00168
00169 if (!compatibleTransports(pubTLS, subTLS)) {
00170 compatible = false;
00171 increment_incompatibility_count(writerStatus,
00172 OpenDDS::TRANSPORTTYPE_QOS_POLICY_ID);
00173 increment_incompatibility_count(readerStatus,
00174 OpenDDS::TRANSPORTTYPE_QOS_POLICY_ID);
00175 }
00176
00177
00178 compatible = compatible && compatibleQOS(writerQos, readerQos,
00179 writerStatus, readerStatus);
00180
00181
00182 compatible = compatible && compatibleQOS(pubQos, subQos,
00183 writerStatus, readerStatus);
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193 compatible = compatible && matching_partitions(pubQos->partition,
00194 subQos->partition);
00195
00196 return compatible;
00197 }
00198
00199 bool
00200 compatibleQOS(const DDS::PublisherQos* pubQos,
00201 const DDS::SubscriberQos* subQos,
00202 OpenDDS::DCPS::IncompatibleQosStatus* writerStatus,
00203 OpenDDS::DCPS::IncompatibleQosStatus* readerStatus)
00204 {
00205 bool compatible = true;
00206
00207
00208
00209
00210 if ((pubQos->presentation.access_scope < subQos->presentation.access_scope)
00211 || ((pubQos->presentation.coherent_access == false)
00212 &&(subQos->presentation.coherent_access == true))
00213 || ((pubQos->presentation.ordered_access == false)
00214 &&(subQos->presentation.ordered_access == true))) {
00215 compatible = false;
00216
00217 increment_incompatibility_count(writerStatus,
00218 DDS::PRESENTATION_QOS_POLICY_ID);
00219 increment_incompatibility_count(readerStatus,
00220 DDS::PRESENTATION_QOS_POLICY_ID);
00221 }
00222
00223 return compatible;
00224 }
00225
00226 bool
00227 compatibleQOS(const DDS::DataWriterQos * writerQos,
00228 const DDS::DataReaderQos * readerQos,
00229 OpenDDS::DCPS::IncompatibleQosStatus* writerStatus,
00230 OpenDDS::DCPS::IncompatibleQosStatus* readerStatus)
00231 {
00232 bool compatible = true;
00233
00234
00235 if (writerQos->reliability.kind < readerQos->reliability.kind) {
00236 compatible = false;
00237
00238 increment_incompatibility_count(writerStatus,
00239 DDS::RELIABILITY_QOS_POLICY_ID);
00240 increment_incompatibility_count(readerStatus,
00241 DDS::RELIABILITY_QOS_POLICY_ID);
00242 }
00243
00244
00245 if (writerQos->durability.kind < readerQos->durability.kind) {
00246 compatible = false;
00247
00248 increment_incompatibility_count(writerStatus,
00249 DDS::DURABILITY_QOS_POLICY_ID);
00250 increment_incompatibility_count(readerStatus,
00251 DDS::DURABILITY_QOS_POLICY_ID);
00252 }
00253
00254
00255
00256
00257
00258 using OpenDDS::DCPS::operator>;
00259 if (writerQos->liveliness.kind < readerQos->liveliness.kind
00260 || writerQos->liveliness.lease_duration
00261 > readerQos->liveliness.lease_duration) {
00262
00263 compatible = false;
00264
00265 increment_incompatibility_count(writerStatus,
00266 DDS::LIVELINESS_QOS_POLICY_ID);
00267 increment_incompatibility_count(readerStatus,
00268 DDS::LIVELINESS_QOS_POLICY_ID);
00269 }
00270
00271
00272
00273
00274 if (writerQos->deadline.period > readerQos->deadline.period) {
00275
00276 compatible = false;
00277
00278 increment_incompatibility_count(writerStatus,
00279 DDS::DEADLINE_QOS_POLICY_ID);
00280 increment_incompatibility_count(readerStatus,
00281 DDS::DEADLINE_QOS_POLICY_ID);
00282 }
00283
00284
00285
00286 using OpenDDS::DCPS::operator<;
00287 if (readerQos->latency_budget.duration < writerQos->latency_budget.duration) {
00288
00289 compatible = false;
00290
00291 increment_incompatibility_count(writerStatus,
00292 DDS::LATENCYBUDGET_QOS_POLICY_ID);
00293 increment_incompatibility_count(readerStatus,
00294 DDS::LATENCYBUDGET_QOS_POLICY_ID);
00295 }
00296
00297
00298
00299 if (writerQos->ownership.kind != readerQos->ownership.kind) {
00300 compatible = false;
00301
00302 increment_incompatibility_count(writerStatus,
00303 DDS::OWNERSHIP_QOS_POLICY_ID);
00304 increment_incompatibility_count(readerStatus,
00305 DDS::OWNERSHIP_QOS_POLICY_ID);
00306 }
00307
00308 return compatible;
00309 }
00310
00311 #ifndef OPENDDS_SAFETY_PROFILE
00312 using OpenDDS::DCPS::operator==;
00313 #endif
00314 bool should_check_association_upon_change(const DDS::DataReaderQos & qos1,
00315 const DDS::DataReaderQos & qos2)
00316 {
00317 return !(
00318 (qos1.deadline == qos2.deadline) &&
00319 (qos1.latency_budget == qos2.latency_budget));
00320 }
00321
00322 bool should_check_association_upon_change(const DDS::DataWriterQos & qos1,
00323 const DDS::DataWriterQos & qos2)
00324 {
00325 return !(
00326 (qos1.deadline == qos2.deadline) &&
00327 (qos1.latency_budget == qos2.latency_budget));
00328 }
00329
00330 bool should_check_association_upon_change(const DDS::SubscriberQos & qos1,
00331 const DDS::SubscriberQos & qos2)
00332 {
00333 return !(qos1.partition == qos2.partition);
00334 }
00335
00336 bool should_check_association_upon_change(const DDS::PublisherQos & qos1,
00337 const DDS::PublisherQos & qos2)
00338 {
00339 return !(qos1.partition == qos2.partition);
00340 }
00341
00342 bool should_check_association_upon_change(const DDS::TopicQos & ,
00343 const DDS::TopicQos & )
00344 {
00345 return false;
00346 }
00347
00348 bool should_check_association_upon_change(const DDS::DomainParticipantQos & ,
00349 const DDS::DomainParticipantQos & )
00350 {
00351 return false;
00352 }
00353
00354 }}