summaryrefslogtreecommitdiff
path: root/TAO/tao/Transport_Cache_Manager_T.h
blob: 7cc7c188264633e70f448158ee84866f29b63947 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
// -*- C++ -*-

//=============================================================================
/**
 *  @file    Transport_Cache_Manager_T.h
 *
 *  @author Balachandran Natarajan <bala@cs.wustl.edu>
 */
//=============================================================================

#ifndef TAO_CONNECTION_CACHE_MANAGER_T_H
#define TAO_CONNECTION_CACHE_MANAGER_T_H

#include /**/ "ace/pre.h"
#include "ace/Null_Mutex.h"
#include "ace/Thread_Mutex.h"

#if !defined (ACE_LACKS_PRAGMA_ONCE)
#define  ACE_LACKS_PRAGMA_ONCE
#endif /* ACE_LACKS_PRAGMA_ONCE */

#include "ace/Hash_Map_Manager_T.h"

#include "tao/Cache_Entries_T.h"
#include "tao/orbconf.h"

#if defined (TAO_HAS_MONITOR_POINTS) && (TAO_HAS_MONITOR_POINTS == 1)
#include "ace/Monitor_Size.h"
#endif /* TAO_HAS_MONITOR_POINTS==1 */

ACE_BEGIN_VERSIONED_NAMESPACE_DECL
class ACE_Handle_Set;
template <class T> class ACE_Unbounded_Set;
template <class T> class ACE_Unbounded_Set_Iterator;
ACE_END_VERSIONED_NAMESPACE_DECL

TAO_BEGIN_VERSIONED_NAMESPACE_DECL

class TAO_Connection_Handler;
class TAO_Resource_Factory;

template <class ACE_COND_MUTEX> class TAO_Condition;

namespace TAO
{
  typedef ACE_Unbounded_Set<TAO_Connection_Handler*> Connection_Handler_Set;
  /**
   * @brief The Transport Cache Manager for TAO
   *
   * This class provides interfaces associating a TAO_Cache_ExtId
   * & TAO_Cache_IntId. This class is wrapper around the
   * ACE_Hash_Map_Manager  class which is used as a container to Cache
   * the connections. This class protects the entries with a lock. The
   * map is updated only by holding the lock. The more compeling reason
   * to have the lock in this class and not in the Hash_Map is that, we
   * do quite a bit of work in this class for which we need a lock.
   */
  template <typename TT, typename TRDT, typename PSTRAT>
  class Transport_Cache_Manager_T
  {
  public:
    typedef TT transport_type;
    typedef TRDT transport_descriptor_type;
    typedef PSTRAT purging_strategy;

    /// results of a find
    enum Find_Result
    {
      CACHE_FOUND_NONE,
      CACHE_FOUND_CONNECTING,
      CACHE_FOUND_BUSY,
      CACHE_FOUND_AVAILABLE
    };

    typedef Cache_ExtId_T <transport_descriptor_type> Cache_ExtId;
    typedef Cache_IntId_T <transport_type> Cache_IntId;

    // Some useful typedef's
    typedef ACE_Hash_Map_Manager_Ex <Cache_ExtId,
                                     Cache_IntId,
                                     ACE_Hash<Cache_ExtId>,
                                     ACE_Equal_To<Cache_ExtId>,
                                     ACE_Null_Mutex>
    HASH_MAP;

    typedef typename HASH_MAP::iterator HASH_MAP_ITER;

    typedef ACE_Hash_Map_Entry <Cache_ExtId,
                                Cache_IntId>
    HASH_MAP_ENTRY;

    typedef TAO_Condition<TAO_SYNCH_MUTEX> CONDITION;

    // == Public methods
    /// Constructor
    Transport_Cache_Manager_T (
      int percent,
      purging_strategy* purging_strategy,
      size_t cache_maximum,
      bool locked,
      const char *orbid);

    /// Destructor
    ~Transport_Cache_Manager_T ();

    /// Add the transport to the cache.
    /**
     * The transport has the property definition based on which caching
     * can be done. This method sets the cache entry status.  By
     * default the status is set to <CODE>ENTRY_IDLE_AND_PURGABLE</CODE>
     */
    int cache_transport (transport_descriptor_type *prop,
                         transport_type *transport,
                         Cache_Entries_State state =
                           ENTRY_IDLE_AND_PURGABLE);

    /// Check the Transport Cache to check whether the connection exists
    /// in the Cache and return the connection
    Find_Result find_transport (
      transport_descriptor_type *prop,
      transport_type *&transport,
      size_t & busy_count);

    /// Remove entries from the cache depending upon the strategy.
    int purge ();

    /// Purge the entry from the Cache Map
    int purge_entry (HASH_MAP_ENTRY *& entry);

    /// Mark the entry as connected.
    void mark_connected (HASH_MAP_ENTRY *& entry, bool state);

    /// Make the entry idle and ready for use.
    int make_idle (HASH_MAP_ENTRY *&entry);

    /// Modify the state setting on the provided entry.
    void set_entry_state (HASH_MAP_ENTRY *&entry,
                          TAO::Cache_Entries_State state);

    /// Mark the entry as touched. This call updates the purging
    /// strategy policy information.
    int update_entry (HASH_MAP_ENTRY *&entry);

    /// Close the underlying hash map manager and return any handlers
    /// still registered
    int close (Connection_Handler_Set &handlers);

    /// Return a set of connection handlers that belong to transports
    /// that have a RW wait strategy.
    /**
     * This call is used for a specific use case by the ORB_Core
     * during shutdown. The only way the ORB can wake up threads
     * waiting on these sockets for replies is to iterate over
     * these blockable transports and close the socket
     * handles. Without these the threads will continue to wait there
     * for ever.
     */
    bool blockable_client_transports (Connection_Handler_Set &handlers);

    /// Return the current size of the cache.
    size_t current_size () const;

    /// Return the total size of the cache.
    size_t total_size () const;

    /// Return the underlying cache map
    HASH_MAP &map ();

  private:
    /// Lookup entry<key,value> in the cache. Grabs the lock and calls the
    /// implementation function find_i.
    Find_Result find (
      transport_descriptor_type *prop,
      transport_type *&transport,
      size_t & busy_count);

    /**
     * Non-Locking version and actual implementation of bind ()
     * call. Calls bind on the Hash_Map_Manager that it holds. If the
     * bind succeeds, it adds the Hash_Map_Entry in to the
     * Transport for its reference.
     */
    int bind_i (Cache_ExtId &ext_id, Cache_IntId &int_id);

    /**
     * Non-locking version and actual implementation of find ()
     * call. This calls the find () on the underlying
     * Hash_Map_Manager. If the find succeeds, it calls the
     * get_idle_transport ().
     */
    Find_Result find_i (
      transport_descriptor_type *prop,
      transport_type *&transport,
      size_t & busy_count);

    /// Non-locking version and actual implementation of make_idle ().
    int make_idle_i (HASH_MAP_ENTRY *entry);

    /// Non-locking version and actual implementation of close ()
    int close_i (Connection_Handler_Set &handlers);

    /// Purge the entry from the Cache Map
    int purge_entry_i (HASH_MAP_ENTRY *entry);

  private:
    /**
     * Tries to find if the @c int_id_ in @a entry is available for use.
     */
    bool is_entry_available_i (const HASH_MAP_ENTRY &entry);

    /**
     * Tries to find if the @c int_id_ in @a entry is connect pending
     */
    bool is_entry_connecting_i (const HASH_MAP_ENTRY &entry);

    /**
     * Tries to find if the @c int_id_ in @a entry is purgable
     */
    bool is_entry_purgable_i (HASH_MAP_ENTRY &entry);

#if !defined(ACE_LACKS_QSORT)
    /// Used by qsort
    static int cpscmp(const void* a, const void* b);
#endif

    typedef HASH_MAP_ENTRY** DESCRIPTOR_SET;

    /// Sort the list of entries
    void sort_set (DESCRIPTOR_SET& entries, int size);

    /// Fill sorted_set in with the transport_descriptor_type's in
    /// a sorted order.
    int fill_set_i (DESCRIPTOR_SET& sorted_set);

    /// Non-locking version of blockable_client_transports ().
    bool blockable_client_transports_i (Connection_Handler_Set &handlers);

  private:
    /// The percentage of the cache to purge at one time
    int percent_;

    /// The underlying connection purging strategy
    purging_strategy *purging_strategy_;

    /// The hash map that has the connections
    HASH_MAP cache_map_;

    TAO_SYNCH_MUTEX cache_map_mutex_;

    /// The lock that is used by the cache map
    ACE_Lock *cache_lock_;

    /// Maximum size of the cache
    size_t cache_maximum_;

#if defined (TAO_HAS_MONITOR_POINTS) && (TAO_HAS_MONITOR_POINTS == 1)
    /// Connection cache purge monitor.
    ACE::Monitor_Control::Size_Monitor *purge_monitor_;

    /// Connection cache size monitor.
    ACE::Monitor_Control::Size_Monitor *size_monitor_;
#endif /* TAO_HAS_MONITOR_POINTS==1 */
  };
}

TAO_END_VERSIONED_NAMESPACE_DECL

#if defined (__ACE_INLINE__)
# include "tao/Transport_Cache_Manager_T.inl"
#endif /* __ACE_INLINE__ */

#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
#include "tao/Transport_Cache_Manager_T.cpp"
#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */

#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
#pragma implementation ("tao/Transport_Cache_Manager_T.cpp")
#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */

#include /**/ "ace/post.h"

#endif /*TAO_CONNECTION_CACHE_MANAGER_T_H*/