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