1 /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /*
3  *     Copyright 2014-2020 Couchbase, Inc.
4  *
5  *   Licensed under the Apache License, Version 2.0 (the "License");
6  *   you may not use this file except in compliance with the License.
7  *   You may obtain a copy of the License at
8  *
9  *       http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *   Unless required by applicable law or agreed to in writing, software
12  *   distributed under the License is distributed on an "AS IS" BASIS,
13  *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *   See the License for the specific language governing permissions and
15  *   limitations under the License.
16  */
17 
18 #ifndef LCBIO_MANAGER_H
19 #define LCBIO_MANAGER_H
20 #include "connect.h"
21 #include "settings.h"
22 #include "list.h"
23 #include "ioutils.h"
24 #include <stdio.h>
25 
26 /**
27  * @file
28  * @brief Socket pooling routines
29  *
30  * @details
31  * General purpose connection manager for LCB sockets. This object is
32  * responsible for maintaining and properly handling idle connections
33  * and pooling them (optionally).
34  */
35 
36 /**
37  * @ingroup lcbio
38  * @defgroup lcbio-mgr Socket Pooling
39  * @addtogroup lcbio-mgr
40  * @{
41  */
42 
43 #ifdef __cplusplus
44 #include <map>
45 
46 namespace lcb
47 {
48 namespace io
49 {
50 
51 /** @brief Socket Pool */
52 class Pool;
53 
54 /** @brief Pooled connection */
55 struct PoolConnInfo;
56 
57 /** @brief Cancellable pool request */
58 struct PoolRequest;
59 
60 struct PoolHost;
61 } // namespace io
62 } // namespace lcb
63 
64 typedef lcb::io::Pool lcbio_MGR;
65 extern "C" {
66 
67 #else
68 /* C only */
69 typedef struct lcbio_MGR_CDUMMY lcbio_MGR;
70 #endif
71 
72 #ifdef __cplusplus
73 }
74 
75 namespace lcb
76 {
77 namespace io
78 {
79 class Pool
80 {
81   public:
82     /**
83      * Create a socket pool controlled by the given settings and IO structure.
84      * This function will increment the refcount on both the settings and table
85      * objects.
86      */
87     Pool(lcb_settings *, lcbio_pTABLE);
88 
89     /**
90      * Destroy the socket pool. Note that internally this just decrements the
91      * reference count. The object is only destroyed when its count hits zero.
92      */
93     void shutdown();
94 
95     /**
96      * Request a connection from the socket pool. The semantics and prototype
97      * of this function are by design similar to lcbio_connect() as they do the
98      * same things.
99      *
100      * @param dest the host to connect to
101      * @param timeout amount of time to wait for a connection to be estblished
102      * @param handler a callback to invoke when the result is ready
103      * @param arg an argument passed to the callback
104      * @return a request handle which may be cancelled
105      * @see lcbio_connect()
106      */
107     ConnectionRequest *get(const lcb_host_t &, uint32_t, lcbio_CONNDONE_cb, void *);
108 
109     /**
110      * Release a socket back into the pool. This means the socket is no longer
111      * used and shall be available for reuse for another request. To verify these
112      * constraints, the socket's reference count must be one. Once the socket
113      * has been released its reference count should not be modified.
114      */
115     static void put(lcbio_SOCKET *sock);
116 
117     /**
118      * Mark a slot as available but discard the current connection. This should be
119      * done if the connection itself is "dirty", i.e. has a protocol error on it
120      * or is otherwise not suitable for reuse
121      */
122     static void discard(lcbio_SOCKET *sock);
123 
124     /**
125      * Like lcbio_mgr_discard() except the source connection is left untouched. It
126      * is removed from the pool instead.
127      *
128      * Because the lcbio_MGR object itself has internal limits and thresholds on how
129      * many leased and/or open connections it can contain, when a connection receives
130      * an error it must either be discarded back to the pool (in which case the
131      * connection is cleaned up and is freed) or it must be detached (in which case
132      * the connection object itself still remains valid, but the pool does not know
133      * about it, and all its counters are restored, as with lcbio_mgr_discard()).
134      *
135      * lcbio_mgr_discard() itself is now implemented as the equivalent to:
136      *  `lcbio_mgr_detach(mgr, conn)`;
137      */
138     static void detach(lcbio_SOCKET *sock);
139 
140     static bool is_from_pool(const lcbio_SOCKET *sock);
141 
142     /**
143      * Dumps the connection manager state to stderr
144      */
145     void dump(FILE *) const;
146 
147     inline void ref();
148     inline void unref();
149 
150     struct Options {
Optionslcb::io::Pool::Options151         Options() : maxtotal(0), maxidle(0), tmoidle(0) {}
152 
153         /** Maximum *total* number of connections opened by the pool. If this
154          * number is exceeded, the pool will black hole future requests until
155          * a new slot becomes available.
156          */
157         unsigned maxtotal;
158 
159         /**
160          * Maximum number of idle connections to keep around
161          */
162         unsigned maxidle;
163 
164         /**
165          * The amount of time the pool should wait before closing idle
166          * connections. In microseconds
167          */
168         uint32_t tmoidle;
169     };
170 
set_options(const Options &opts)171     void set_options(const Options &opts)
172     {
173         options = opts;
174     }
175 
get_options()176     Options &get_options()
177     {
178         return options;
179     }
180 
181     void toJSON(hrtime_t now, Json::Value &node);
182 
183   private:
184     friend struct PoolRequest;
185     friend struct PoolConnInfo;
186     friend struct PoolHost;
187 
188     typedef std::map< std::string, PoolHost * > HostMap;
189     HostMap ht;
190     lcb_settings *settings;
191     lcbio_pTABLE io;
192     Options options;
193     unsigned refcount;
194 };
195 } // namespace io
196 } // namespace lcb
197 #endif
198 /**@}*/
199 
200 #endif /* LCB_SOCKPOOL_H */
201