OpenDDS  Snapshot(2023/04/28-20:55)
AddressCache.h
Go to the documentation of this file.
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 
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 
36 #if defined ACE_HAS_CPP11
37  , addrs_hash_(0)
38 #endif
39  {}
40 
41  AddressCacheEntry(const AddrSet& addrs, const MonotonicTimePoint& expires) : addrs_(addrs), expires_(expires)
42 #if defined ACE_HAS_CPP11
43  , addrs_hash_(calculate_hash(addrs_))
44 #endif
45  {}
46 
47  AddrSet addrs_;
49 #if defined ACE_HAS_CPP11
50  size_t addrs_hash_;
51 #endif
52 };
53 
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:
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 
98  virtual ~AddressCache() {}
99 
100  struct ScopedAccess {
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  ScopedAccess(AddressCache& cache, const Key& key, bool block = true, const MonotonicTimePoint& now = MonotonicTimePoint::now())
112  : guard_(cache.mutex_, block)
113  , rch_()
114  , is_new_(false)
115 #if defined ACE_HAS_CPP11
116  , non_const_touch_(false)
117 #endif
118  {
119  const typename MapType::iterator pos = cache.map_.find(key);
120  if (pos == cache.map_.end()) {
121  rch_ = make_rch<AddressCacheEntry>();
122  cache.map_[key] = rch_;
123  GuidSet set;
124  key.get_contained_guids(set);
125  for (GuidSet::const_iterator it = set.begin(), limit = set.end(); it != limit; ++it) {
126  cache.id_map_[*it].push_back(key);
127  }
128  is_new_ = true;
129  } else {
130  rch_ = pos->second;
131  }
132 
133  if (rch_->expires_ < now) {
134  rch_->addrs_.clear();
135  rch_->expires_ = MonotonicTimePoint::max_value;
136  is_new_ = true;
137  }
138  }
139 
141  {
142 #if defined ACE_HAS_CPP11
143  recalculate_hash();
144 #endif
145  }
146 
148  OPENDDS_ASSERT(rch_);
149 #if defined ACE_HAS_CPP11
150  non_const_touch_ = true;
151 #endif
152  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  inline void recalculate_hash() {
162  if (non_const_touch_) {
163  rch_->addrs_hash_ = calculate_hash(rch_->addrs_);
164  non_const_touch_ = false;
165  }
166  }
167 #endif
168 
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&);
180  };
181 
182  bool load(const Key& key, AddrSet& addrs) const
183  {
184  ACE_Guard<ACE_Thread_Mutex> guard(mutex_);
185  const typename MapType::const_iterator pos = map_.find(key);
186  if (pos != map_.end()) {
187  if (MonotonicTimePoint::now() < pos->second->expires_) {
188  const AddrSet& as = pos->second->addrs_;
189  for (AddrSet::const_iterator it = as.begin(), limit = as.end(); it != limit; ++it) {
190  addrs.insert(*it);
191  }
192  return true;
193  }
194  }
195  return false;
196  }
197 
198  void store(const Key& key, const AddrSet& addrs, const MonotonicTimePoint& expires = MonotonicTimePoint::max_value)
199  {
200  ACE_Guard<ACE_Thread_Mutex> guard(mutex_);
201  RcHandle<AddressCacheEntry>& rch = map_[key];
202  if (rch) {
203  rch->addrs_ = addrs;
204  rch->expires_ = expires;
205  } else {
206  rch = make_rch<AddressCacheEntry>(addrs, expires);
207  GuidSet set;
208  key.get_contained_guids(set);
209  for (GuidSet::const_iterator it = set.begin(), limit = set.end(); it != limit; ++it) {
210  id_map_[*it].push_back(key);
211  }
212  }
213  }
214 
215  bool remove(const Key& key)
216  {
217  ACE_Guard<ACE_Thread_Mutex> guard(mutex_);
218  return map_.erase(key) != 0;
219  }
220 
221  void remove_id(const GUID_t& val)
222  {
223  ACE_Guard<ACE_Thread_Mutex> guard(mutex_);
224  const typename IdMapType::iterator pos = id_map_.find(val);
225  if (pos != id_map_.end()) {
226  for (typename KeyVec::iterator it = pos->second.begin(), limit = pos->second.end(); it != limit; ++it) {
227  map_.erase(*it);
228  }
229  id_map_.erase(pos);
230  }
231  }
232 
233 private:
234 
236  MapType map_;
237  IdMapType id_map_;
238 };
239 
240 } // namespace DCPS
241 } // namespace OpenDDS
242 
244 
245 #endif /* OPENDDS_DCPS_RADDRESSCACHE_H */
AddressCacheEntryProxy(RcHandle< AddressCacheEntry > rch)
Definition: AddressCache.h:55
const AddressCacheEntry & value() const
Definition: AddressCache.h:155
bool operator<(const AddressCacheEntryProxy &rhs) const
Definition: AddressCache.h:65
void store(const Key &key, const AddrSet &addrs, const MonotonicTimePoint &expires=MonotonicTimePoint::max_value)
Definition: AddressCache.h:198
ScopedAccess(AddressCache &cache, const Key &key, bool block=true, const MonotonicTimePoint &now=MonotonicTimePoint::now())
Definition: AddressCache.h:111
if(!(yy_init))
int hash(const std::vector< const DDS::OctetSeq *> &src, DDS::OctetSeq &dst)
sequence< octet > key
#define OPENDDS_ASSERT(C)
Definition: Definitions.h:72
static TimePoint_T< MonotonicClock > now()
Definition: TimePoint_T.inl:41
bool load(const Key &key, AddrSet &addrs) const
Definition: AddressCache.h:182
void remove_id(const GUID_t &val)
Definition: AddressCache.h:221
RcObject & operator=(const RcObject &)
#define OPENDDS_MAP_T
typedef OPENDDS_SET_CMP(GUID_t, GUID_tKeyLessThan) GuidSet
bool operator==(const AddressCacheEntryProxy &rhs) const
Definition: AddressCache.h:57
static const TimePoint_T< MonotonicClock > max_value
Definition: TimePoint_T.h:41
RcHandle< AddressCacheEntry > entry_
Definition: AddressCache.h:80
ACE_Guard< ACE_Thread_Mutex > guard_
Definition: AddressCache.h:169
AddressCacheEntry(const AddrSet &addrs, const MonotonicTimePoint &expires)
Definition: AddressCache.h:41
const AddrSet & addrs() const
Definition: AddressCache.h:73
#define OPENDDS_END_VERSIONED_NAMESPACE_DECL
typedef OPENDDS_VECTOR(ActionConnectionRecord) ConnectionRecords
RcHandle< AddressCacheEntry > rch_
Definition: AddressCache.h:170
The Internal API and Implementation of OpenDDS.
Definition: AddressCache.h:28