LCOV - code coverage report
Current view: top level - DCPS - AddressCache.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 77 77 100.0 %
Date: 2023-04-30 01:32:43 Functions: 12 13 92.3 %

          Line data    Source code
       1             : /*
       2             :  *
       3             :  *
       4             :  * Distributed under the OpenDDS License.
       5             :  * See: http://www.opendds.org/license.html
       6             :  */
       7             : 
       8             : #ifndef OPENDDS_DCPS_ADDRESSCACHE_H
       9             : #define OPENDDS_DCPS_ADDRESSCACHE_H
      10             : 
      11             : #include "dcps_export.h"
      12             : 
      13             : #ifndef ACE_LACKS_PRAGMA_ONCE
      14             : #  pragma once
      15             : #endif /* ACE_LACKS_PRAGMA_ONCE */
      16             : 
      17             : #include "Definitions.h"
      18             : #include "GuidUtils.h"
      19             : #include "NetworkAddress.h"
      20             : #include "PoolAllocator.h"
      21             : #include "RcObject.h"
      22             : #include "TimeTypes.h"
      23             : 
      24             : #include "ace/INET_Addr.h"
      25             : 
      26             : OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL
      27             : 
      28             : namespace OpenDDS {
      29             : namespace DCPS {
      30             : 
      31             : typedef OPENDDS_SET_CMP(GUID_t, GUID_tKeyLessThan) GuidSet;
      32             : 
      33             : struct AddressCacheEntry : public virtual RcObject {
      34             : 
      35           1 :   AddressCacheEntry() : addrs_(), expires_(MonotonicTimePoint::max_value)
      36             : #if defined ACE_HAS_CPP11
      37           1 :     , addrs_hash_(0)
      38             : #endif
      39           1 :   {}
      40             : 
      41           6 :   AddressCacheEntry(const AddrSet& addrs, const MonotonicTimePoint& expires) : addrs_(addrs), expires_(expires)
      42             : #if defined ACE_HAS_CPP11
      43          12 :   , addrs_hash_(calculate_hash(addrs_))
      44             : #endif
      45           6 :   {}
      46             : 
      47             :   AddrSet addrs_;
      48             :   MonotonicTimePoint expires_;
      49             : #if defined ACE_HAS_CPP11
      50             :   size_t addrs_hash_;
      51             : #endif
      52             : };
      53             : 
      54             : struct AddressCacheEntryProxy {
      55             :   AddressCacheEntryProxy(RcHandle<AddressCacheEntry> rch) : entry_(rch) {}
      56             : 
      57             :   bool operator==(const AddressCacheEntryProxy& rhs) const {
      58             : #if defined ACE_HAS_CPP11
      59             :     return entry_ && rhs.entry_ && entry_->addrs_hash_ == rhs.entry_->addrs_hash_ && entry_->addrs_ == rhs.entry_->addrs_;
      60             : #else
      61             :     return entry_ && rhs.entry_ && entry_->addrs_ == rhs.entry_->addrs_;
      62             : #endif
      63             :   }
      64             : 
      65             :   bool operator<(const AddressCacheEntryProxy& rhs) const {
      66             : #if defined ACE_HAS_CPP11
      67             :     return (rhs.entry_ && (!entry_ || (entry_->addrs_hash_ < rhs.entry_->addrs_hash_ || (entry_->addrs_hash_ == rhs.entry_->addrs_hash_ && entry_->addrs_ < rhs.entry_->addrs_))));
      68             : #else
      69             :     return (rhs.entry_ && (!entry_ || (entry_->addrs_ < rhs.entry_->addrs_)));
      70             : #endif
      71             :   }
      72             : 
      73             :   const AddrSet& addrs() const { return entry_->addrs_; }
      74             : 
      75             : #if defined ACE_HAS_CPP11
      76             :   size_t hash() const noexcept { return entry_ ? entry_->addrs_hash_ : 0; }
      77             : #endif
      78             : 
      79             : private:
      80             :   RcHandle<AddressCacheEntry> entry_;
      81             : };
      82             : 
      83             : template <typename Key>
      84             : class AddressCache {
      85             : public:
      86             : 
      87             : #if defined ACE_HAS_CPP11
      88             :   typedef OPENDDS_UNORDERED_MAP_T(Key, RcHandle<AddressCacheEntry>) MapType;
      89             :   typedef OPENDDS_VECTOR(Key) KeyVec;
      90             :   typedef OPENDDS_UNORDERED_MAP_T(GUID_t, KeyVec) IdMapType;
      91             : #else
      92             :   typedef OPENDDS_MAP_T(Key, RcHandle<AddressCacheEntry>) MapType;
      93             :   typedef OPENDDS_VECTOR(Key) KeyVec;
      94             :   typedef OPENDDS_MAP_T(GUID_t, KeyVec) IdMapType;
      95             : #endif
      96             : 
      97           8 :   AddressCache() {}
      98           8 :   virtual ~AddressCache() {}
      99             : 
     100             :   struct ScopedAccess {
     101             :     ScopedAccess(AddressCache& cache)
     102             :       : guard_(cache.mutex_)
     103             :       , rch_()
     104             :       , is_new_(false)
     105             : #if defined ACE_HAS_CPP11
     106             :       , non_const_touch_(false)
     107             : #endif
     108             :     {
     109             :     }
     110             : 
     111           3 :     ScopedAccess(AddressCache& cache, const Key& key, bool block = true, const MonotonicTimePoint& now = MonotonicTimePoint::now())
     112           3 :       : guard_(cache.mutex_, block)
     113           3 :       , rch_()
     114           3 :       , is_new_(false)
     115             : #if defined ACE_HAS_CPP11
     116           3 :       , non_const_touch_(false)
     117             : #endif
     118             :     {
     119           3 :       const typename MapType::iterator pos = cache.map_.find(key);
     120           3 :       if (pos == cache.map_.end()) {
     121           1 :         rch_ = make_rch<AddressCacheEntry>();
     122           1 :         cache.map_[key] = rch_;
     123           1 :         GuidSet set;
     124           1 :         key.get_contained_guids(set);
     125           2 :         for (GuidSet::const_iterator it = set.begin(), limit = set.end(); it != limit; ++it) {
     126           1 :           cache.id_map_[*it].push_back(key);
     127             :         }
     128           1 :         is_new_ = true;
     129           1 :       } else {
     130           2 :         rch_ = pos->second;
     131             :       }
     132             : 
     133           3 :       if (rch_->expires_ < now) {
     134           1 :         rch_->addrs_.clear();
     135           1 :         rch_->expires_ = MonotonicTimePoint::max_value;
     136           1 :         is_new_ = true;
     137             :       }
     138           3 :     }
     139             : 
     140           3 :     ~ScopedAccess()
     141             :     {
     142             : #if defined ACE_HAS_CPP11
     143           3 :       recalculate_hash();
     144             : #endif
     145           3 :     }
     146             : 
     147           3 :     inline AddressCacheEntry& value() {
     148           3 :       OPENDDS_ASSERT(rch_);
     149             : #if defined ACE_HAS_CPP11
     150           3 :       non_const_touch_ = true;
     151             : #endif
     152           3 :       return *rch_;
     153             :     }
     154             : 
     155             :     inline const AddressCacheEntry& value() const {
     156             :       OPENDDS_ASSERT(rch_);
     157             :       return *rch_;
     158             :     }
     159             : 
     160             : #if defined ACE_HAS_CPP11
     161           3 :     inline void recalculate_hash() {
     162           3 :       if (non_const_touch_) {
     163           3 :         rch_->addrs_hash_ = calculate_hash(rch_->addrs_);
     164           3 :         non_const_touch_ = false;
     165             :       }
     166           3 :     }
     167             : #endif
     168             : 
     169             :     ACE_Guard<ACE_Thread_Mutex> guard_;
     170             :     RcHandle<AddressCacheEntry> rch_;
     171             :     bool is_new_;
     172             : #if defined ACE_HAS_CPP11
     173             :     bool non_const_touch_;
     174             : #endif
     175             : 
     176             :   private:
     177             :     ScopedAccess();
     178             :     ScopedAccess(const ScopedAccess&);
     179             :     ScopedAccess& operator=(const ScopedAccess&);
     180             :   };
     181             : 
     182           6 :   bool load(const Key& key, AddrSet& addrs) const
     183             :   {
     184           6 :     ACE_Guard<ACE_Thread_Mutex> guard(mutex_);
     185           6 :     const typename MapType::const_iterator pos = map_.find(key);
     186           6 :     if (pos != map_.end()) {
     187           3 :       if (MonotonicTimePoint::now() < pos->second->expires_) {
     188           3 :         const AddrSet& as = pos->second->addrs_;
     189           7 :         for (AddrSet::const_iterator it = as.begin(), limit = as.end(); it != limit; ++it) {
     190           4 :           addrs.insert(*it);
     191             :         }
     192           3 :         return true;
     193             :       }
     194             :     }
     195           3 :     return false;
     196           6 :   }
     197             : 
     198           7 :   void store(const Key& key, const AddrSet& addrs, const MonotonicTimePoint& expires = MonotonicTimePoint::max_value)
     199             :   {
     200           7 :     ACE_Guard<ACE_Thread_Mutex> guard(mutex_);
     201           7 :     RcHandle<AddressCacheEntry>& rch = map_[key];
     202           7 :     if (rch) {
     203           1 :       rch->addrs_ = addrs;
     204           1 :       rch->expires_ = expires;
     205             :     } else {
     206           6 :       rch = make_rch<AddressCacheEntry>(addrs, expires);
     207           6 :       GuidSet set;
     208           6 :       key.get_contained_guids(set);
     209          12 :       for (GuidSet::const_iterator it = set.begin(), limit = set.end(); it != limit; ++it) {
     210           6 :         id_map_[*it].push_back(key);
     211             :       }
     212           6 :     }
     213           7 :   }
     214             : 
     215           1 :   bool remove(const Key& key)
     216             :   {
     217           1 :     ACE_Guard<ACE_Thread_Mutex> guard(mutex_);
     218           2 :     return map_.erase(key) != 0;
     219           1 :   }
     220             : 
     221           1 :   void remove_id(const GUID_t& val)
     222             :   {
     223           1 :     ACE_Guard<ACE_Thread_Mutex> guard(mutex_);
     224           1 :     const typename IdMapType::iterator pos = id_map_.find(val);
     225           1 :     if (pos != id_map_.end()) {
     226           2 :       for (typename KeyVec::iterator it = pos->second.begin(), limit = pos->second.end(); it != limit; ++it) {
     227           1 :         map_.erase(*it);
     228             :       }
     229           1 :       id_map_.erase(pos);
     230             :     }
     231           1 :   }
     232             : 
     233             : private:
     234             : 
     235             :   mutable ACE_Thread_Mutex mutex_;
     236             :   MapType map_;
     237             :   IdMapType id_map_;
     238             : };
     239             : 
     240             : } // namespace DCPS
     241             : } // namespace OpenDDS
     242             : 
     243             : OPENDDS_END_VERSIONED_NAMESPACE_DECL
     244             : 
     245             : #endif /* OPENDDS_DCPS_RADDRESSCACHE_H */

Generated by: LCOV version 1.16