DCPS_Utils.cpp

Go to the documentation of this file.
00001 /*
00002  *
00003  *
00004  * Distributed under the OpenDDS License.
00005  * See: http://www.opendds.org/license.html
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"  /* For ACE::wild_match() */
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; // no wildcard
00032 
00033     if (i > 0 && str[i-1] == '\\') str += i + 1; // escaped wildcard
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; // wildcards never match
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; // default
00084 
00085   for (CORBA::ULong i = 0; i < qos.name.length(); ++i) {
00086     if (*qos.name[i] == 0)
00087       return true; // default (empty string)
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     // Zero-length sequences should be treated the same as a
00102     // sequence of length 1 that contains an empty string:
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   // Check transport-type compatibility
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   // Verify compatibility of DataWriterQos and DataReaderQos
00180   compatible = compatible && compatibleQOS(writerQos, readerQos,
00181                                            writerStatus, readerStatus);
00182 
00183   // Verify compatibility of PublisherQos and SubscriberQos
00184   compatible = compatible && compatibleQOS(pubQos, subQos,
00185                                            writerStatus, readerStatus);
00186 
00187   // Verify publisher and subscriber are in a matching partition.
00188   //
00189   // According to the DDS spec:
00190   //
00191   //   Failure to match partitions is not considered an incompatible
00192   //   QoS and does not trigger any listeners nor conditions.
00193   //
00194   // Don't increment the incompatibity count.
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   // PARTITION, GROUP_DATA, and ENTITY_FACTORY are RxO==no.
00210 
00211   // Check the PRESENTATION_QOS_POLICY_ID
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   // Check the RELIABILITY_QOS_POLICY_ID
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   // Check the DURABILITY_QOS_POLICY_ID
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   // Check the LIVELINESS_QOS_POLICY_ID
00257   // invalid if offered kind is less than requested kind OR
00258   //         if offered liveliness duration greater than requested
00259   //         liveliness duration
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   // Check the DEADLINE_QOS_POLICY_ID
00274   //   Offered deadline must be less than or equal to the requested
00275   //   deadline.
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   // Check the LATENCY_BUDGET
00287   //   The reader's duration must be greater than or equal to the writer's
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   // The value of the OWNERSHIP kind offered must exactly match the one
00300   // requested or else they are considered incompatible.
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 & /*qos1*/,
00345                                           const DDS::TopicQos & /*qos2*/)
00346 {
00347   return false;
00348 }
00349 
00350 bool should_check_association_upon_change(const DDS::DomainParticipantQos & /*qos1*/,
00351                                           const DDS::DomainParticipantQos & /*qos2*/)
00352 {
00353   return false;
00354 }
00355 
00356 }}
00357 
00358 OPENDDS_END_VERSIONED_NAMESPACE_DECL
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 10 Aug 2018 for OpenDDS by  doxygen 1.6.1