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 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; // no wildcard
00030 
00031     if (i > 0 && str[i-1] == '\\') str += i + 1; // escaped wildcard
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; // wildcards never match
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; // default
00082 
00083   for (CORBA::ULong i = 0; i < qos.name.length(); ++i) {
00084     if (*qos.name[i] == 0)
00085       return true; // default (empty string)
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     // Zero-length sequences should be treated the same as a
00100     // sequence of length 1 that contains an empty string:
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   // Check transport-type compatibility
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   // Verify compatibility of DataWriterQos and DataReaderQos
00178   compatible = compatible && compatibleQOS(writerQos, readerQos,
00179                                            writerStatus, readerStatus);
00180 
00181   // Verify compatibility of PublisherQos and SubscriberQos
00182   compatible = compatible && compatibleQOS(pubQos, subQos,
00183                                            writerStatus, readerStatus);
00184 
00185   // Verify publisher and subscriber are in a matching partition.
00186   //
00187   // According to the DDS spec:
00188   //
00189   //   Failure to match partitions is not considered an incompatible
00190   //   QoS and does not trigger any listeners nor conditions.
00191   //
00192   // Don't increment the incompatibity count.
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   // PARTITION, GROUP_DATA, and ENTITY_FACTORY are RxO==no.
00208 
00209   // Check the PRESENTATION_QOS_POLICY_ID
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   // Check the RELIABILITY_QOS_POLICY_ID
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   // Check the DURABILITY_QOS_POLICY_ID
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   // Check the LIVELINESS_QOS_POLICY_ID
00255   // invalid if offered kind is less than requested kind OR
00256   //         if offered liveliness duration greater than requested
00257   //         liveliness duration
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   // Check the DEADLINE_QOS_POLICY_ID
00272   //   Offered deadline must be less than or equal to the requested
00273   //   deadline.
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   // Check the LATENCY_BUDGET
00285   //   The reader's duration must be greater than or equal to the writer's
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   // The value of the OWNERSHIP kind offered must exactly match the one
00298   // requested or else they are considered incompatible.
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 & /*qos1*/,
00343                                           const DDS::TopicQos & /*qos2*/)
00344 {
00345   return false;
00346 }
00347 
00348 bool should_check_association_upon_change(const DDS::DomainParticipantQos & /*qos1*/,
00349                                           const DDS::DomainParticipantQos & /*qos2*/)
00350 {
00351   return false;
00352 }
00353 
00354 }}

Generated on Fri Feb 12 20:05:20 2016 for OpenDDS by  doxygen 1.4.7