libcouchbase 0.3.3 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (167) hide show
  1. checksums.yaml +4 -4
  2. data/ext/libcouchbase/CMakeLists.txt +6 -8
  3. data/ext/libcouchbase/README.markdown +2 -2
  4. data/ext/libcouchbase/RELEASE_NOTES.markdown +229 -2
  5. data/ext/libcouchbase/cmake/Modules/ConfigureDtrace.cmake +11 -0
  6. data/ext/libcouchbase/cmake/Modules/GenerateConfigDotH.cmake +18 -0
  7. data/ext/libcouchbase/cmake/Modules/GetLibcouchbaseFlags.cmake +3 -2
  8. data/ext/libcouchbase/cmake/Modules/GetVersionInfo.cmake +3 -3
  9. data/ext/libcouchbase/cmake/config-cmake.h.in +4 -0
  10. data/ext/libcouchbase/cmake/defs.mk.in +0 -2
  11. data/ext/libcouchbase/cmake/source_files.cmake +21 -5
  12. data/ext/libcouchbase/contrib/cJSON/cJSON.c +1 -1
  13. data/ext/libcouchbase/contrib/cbsasl/src/client.c +2 -0
  14. data/ext/libcouchbase/example/users/README +48 -0
  15. data/ext/libcouchbase/example/users/users.c +147 -0
  16. data/ext/libcouchbase/include/libcouchbase/auth.h +175 -31
  17. data/ext/libcouchbase/include/libcouchbase/cntl.h +82 -1
  18. data/ext/libcouchbase/include/libcouchbase/couchbase.h +45 -3
  19. data/ext/libcouchbase/include/libcouchbase/error.h +19 -1
  20. data/ext/libcouchbase/include/libcouchbase/iops.h +3 -0
  21. data/ext/libcouchbase/include/libcouchbase/n1ql.h +31 -1
  22. data/ext/libcouchbase/include/libcouchbase/plugins/io/bsdio-inl.c +4 -1
  23. data/ext/libcouchbase/include/libcouchbase/subdoc.h +36 -2
  24. data/ext/libcouchbase/include/libcouchbase/views.h +7 -1
  25. data/ext/libcouchbase/include/libcouchbase/visibility.h +1 -0
  26. data/ext/libcouchbase/include/memcached/protocol_binary.h +24 -1146
  27. data/ext/libcouchbase/packaging/parse-git-describe.pl +1 -1
  28. data/ext/libcouchbase/plugins/io/libev/libev_io_opts.h +3 -2
  29. data/ext/libcouchbase/src/README.md +0 -2
  30. data/ext/libcouchbase/src/auth-priv.h +23 -4
  31. data/ext/libcouchbase/src/auth.cc +51 -43
  32. data/ext/libcouchbase/src/bootstrap.cc +244 -0
  33. data/ext/libcouchbase/src/bootstrap.h +58 -38
  34. data/ext/libcouchbase/src/bucketconfig/bc_cccp.cc +120 -158
  35. data/ext/libcouchbase/src/bucketconfig/bc_file.cc +281 -0
  36. data/ext/libcouchbase/src/bucketconfig/bc_http.cc +526 -0
  37. data/ext/libcouchbase/src/bucketconfig/bc_http.h +50 -25
  38. data/ext/libcouchbase/src/bucketconfig/bc_static.cc +150 -0
  39. data/ext/libcouchbase/src/bucketconfig/clconfig.h +410 -386
  40. data/ext/libcouchbase/src/bucketconfig/confmon.cc +393 -0
  41. data/ext/libcouchbase/src/cbft.cc +22 -27
  42. data/ext/libcouchbase/src/cntl.cc +56 -22
  43. data/ext/libcouchbase/src/connspec.cc +47 -6
  44. data/ext/libcouchbase/src/connspec.h +27 -0
  45. data/ext/libcouchbase/src/dns-srv.cc +147 -0
  46. data/ext/libcouchbase/src/dump.cc +3 -3
  47. data/ext/libcouchbase/src/errmap.cc +173 -0
  48. data/ext/libcouchbase/src/errmap.h +198 -0
  49. data/ext/libcouchbase/src/getconfig.cc +7 -33
  50. data/ext/libcouchbase/src/handler.cc +118 -7
  51. data/ext/libcouchbase/src/hostlist.cc +0 -36
  52. data/ext/libcouchbase/src/hostlist.h +44 -62
  53. data/ext/libcouchbase/src/http/http-priv.h +125 -112
  54. data/ext/libcouchbase/src/http/http.cc +27 -35
  55. data/ext/libcouchbase/src/http/http.h +1 -34
  56. data/ext/libcouchbase/src/http/http_io.cc +28 -36
  57. data/ext/libcouchbase/src/instance.cc +131 -34
  58. data/ext/libcouchbase/src/internal.h +58 -26
  59. data/ext/libcouchbase/src/jsparse/parser.cc +136 -210
  60. data/ext/libcouchbase/src/jsparse/parser.h +84 -98
  61. data/ext/libcouchbase/src/lcbht/lcbht.cc +177 -0
  62. data/ext/libcouchbase/src/lcbht/lcbht.h +174 -163
  63. data/ext/libcouchbase/src/lcbio/connect.cc +569 -0
  64. data/ext/libcouchbase/src/lcbio/connect.h +16 -7
  65. data/ext/libcouchbase/src/lcbio/ctx.c +1 -1
  66. data/ext/libcouchbase/src/lcbio/iotable.h +101 -16
  67. data/ext/libcouchbase/src/lcbio/{ioutils.c → ioutils.cc} +30 -51
  68. data/ext/libcouchbase/src/lcbio/ioutils.h +29 -90
  69. data/ext/libcouchbase/src/lcbio/manager.cc +543 -0
  70. data/ext/libcouchbase/src/lcbio/manager.h +133 -96
  71. data/ext/libcouchbase/src/lcbio/protoctx.c +2 -2
  72. data/ext/libcouchbase/src/lcbio/timer-cxx.h +87 -0
  73. data/ext/libcouchbase/src/mc/mcreq.c +11 -2
  74. data/ext/libcouchbase/src/mc/mcreq.h +9 -2
  75. data/ext/libcouchbase/src/mcserver/mcserver.cc +175 -43
  76. data/ext/libcouchbase/src/mcserver/mcserver.h +9 -13
  77. data/ext/libcouchbase/src/mcserver/negotiate.cc +181 -62
  78. data/ext/libcouchbase/src/mcserver/negotiate.h +1 -3
  79. data/ext/libcouchbase/src/mctx-helper.h +51 -0
  80. data/ext/libcouchbase/src/n1ql/ixmgmt.cc +1 -2
  81. data/ext/libcouchbase/src/n1ql/n1ql.cc +74 -42
  82. data/ext/libcouchbase/src/netbuf/netbuf.c +4 -4
  83. data/ext/libcouchbase/src/newconfig.cc +6 -6
  84. data/ext/libcouchbase/src/nodeinfo.cc +2 -2
  85. data/ext/libcouchbase/src/operations/{cbflush.c → cbflush.cc} +7 -15
  86. data/ext/libcouchbase/src/operations/{counter.c → counter.cc} +0 -0
  87. data/ext/libcouchbase/src/operations/durability.cc +6 -26
  88. data/ext/libcouchbase/src/operations/durability_internal.h +6 -3
  89. data/ext/libcouchbase/src/operations/{get.c → get.cc} +24 -26
  90. data/ext/libcouchbase/src/operations/{observe.c → observe.cc} +68 -93
  91. data/ext/libcouchbase/src/operations/{pktfwd.c → pktfwd.cc} +0 -0
  92. data/ext/libcouchbase/src/operations/{remove.c → remove.cc} +0 -0
  93. data/ext/libcouchbase/src/operations/stats.cc +3 -8
  94. data/ext/libcouchbase/src/operations/{store.c → store.cc} +27 -32
  95. data/ext/libcouchbase/src/operations/subdoc.cc +129 -42
  96. data/ext/libcouchbase/src/operations/{touch.c → touch.cc} +0 -0
  97. data/ext/libcouchbase/src/packetutils.h +30 -2
  98. data/ext/libcouchbase/src/probes.d +1 -1
  99. data/ext/libcouchbase/src/rdb/rope.c +1 -1
  100. data/ext/libcouchbase/src/{retrychk.c → retrychk.cc} +2 -3
  101. data/ext/libcouchbase/src/retryq.cc +52 -14
  102. data/ext/libcouchbase/src/retryq.h +3 -3
  103. data/ext/libcouchbase/src/settings.c +5 -0
  104. data/ext/libcouchbase/src/settings.h +11 -0
  105. data/ext/libcouchbase/src/ssl/ssl_c.c +1 -0
  106. data/ext/libcouchbase/src/ssl/ssl_common.c +2 -0
  107. data/ext/libcouchbase/src/ssl/ssl_e.c +0 -1
  108. data/ext/libcouchbase/src/strcodecs/strcodecs.h +1 -1
  109. data/ext/libcouchbase/src/trace.h +4 -4
  110. data/ext/libcouchbase/src/vbucket/vbucket.c +6 -10
  111. data/ext/libcouchbase/src/views/{docreq.c → docreq.cc} +48 -54
  112. data/ext/libcouchbase/src/views/docreq.h +24 -30
  113. data/ext/libcouchbase/src/views/viewreq.cc +318 -0
  114. data/ext/libcouchbase/src/views/viewreq.h +43 -13
  115. data/ext/libcouchbase/tests/basic/t_connstr.cc +88 -50
  116. data/ext/libcouchbase/tests/basic/t_creds.cc +47 -5
  117. data/ext/libcouchbase/tests/basic/t_host.cc +67 -75
  118. data/ext/libcouchbase/tests/basic/t_jsparse.cc +27 -82
  119. data/ext/libcouchbase/tests/basic/t_misc.cc +1 -1
  120. data/ext/libcouchbase/tests/basic/t_n1qlstrings.cc +0 -1
  121. data/ext/libcouchbase/tests/htparse/t_basic.cc +58 -78
  122. data/ext/libcouchbase/tests/ioserver/connection.cc +1 -1
  123. data/ext/libcouchbase/tests/ioserver/ioserver.cc +19 -6
  124. data/ext/libcouchbase/tests/iotests/mock-environment.cc +28 -2
  125. data/ext/libcouchbase/tests/iotests/mock-environment.h +51 -1
  126. data/ext/libcouchbase/tests/iotests/t_behavior.cc +1 -7
  127. data/ext/libcouchbase/tests/iotests/t_confmon.cc +97 -115
  128. data/ext/libcouchbase/tests/iotests/t_durability.cc +0 -1
  129. data/ext/libcouchbase/tests/iotests/t_eerrs.cc +119 -0
  130. data/ext/libcouchbase/tests/iotests/t_errmap.cc +178 -0
  131. data/ext/libcouchbase/tests/iotests/t_misc.cc +3 -3
  132. data/ext/libcouchbase/tests/iotests/t_netfail.cc +1 -1
  133. data/ext/libcouchbase/tests/iotests/t_obseqno.cc +0 -1
  134. data/ext/libcouchbase/tests/iotests/t_subdoc.cc +18 -11
  135. data/ext/libcouchbase/tests/mc/t_alloc.cc +9 -9
  136. data/ext/libcouchbase/tests/socktests/socktest.cc +7 -10
  137. data/ext/libcouchbase/tests/socktests/socktest.h +2 -3
  138. data/ext/libcouchbase/tests/socktests/t_basic.cc +6 -6
  139. data/ext/libcouchbase/tests/socktests/t_manager.cc +5 -6
  140. data/ext/libcouchbase/tests/socktests/t_ssl.cc +1 -1
  141. data/ext/libcouchbase/tests/vbucket/confdata/ketama_expected.json +2562 -0
  142. data/ext/libcouchbase/tests/vbucket/confdata/memd_ketama_config.json +31 -0
  143. data/ext/libcouchbase/tests/vbucket/t_config.cc +35 -5
  144. data/ext/libcouchbase/tools/CMakeLists.txt +2 -2
  145. data/ext/libcouchbase/tools/cbc-handlers.h +128 -0
  146. data/ext/libcouchbase/tools/cbc-n1qlback.cc +64 -10
  147. data/ext/libcouchbase/tools/cbc-pillowfight.cc +2 -2
  148. data/ext/libcouchbase/tools/cbc.cc +143 -10
  149. data/ext/libcouchbase/tools/docgen/loc.h +1 -1
  150. data/lib/libcouchbase/connection.rb +4 -3
  151. data/lib/libcouchbase/version.rb +1 -1
  152. metadata +37 -28
  153. data/ext/libcouchbase/include/memcached/vbucket.h +0 -42
  154. data/ext/libcouchbase/src/bootstrap.c +0 -269
  155. data/ext/libcouchbase/src/bucketconfig/bc_file.c +0 -347
  156. data/ext/libcouchbase/src/bucketconfig/bc_http.c +0 -630
  157. data/ext/libcouchbase/src/bucketconfig/bc_mcraw.c +0 -150
  158. data/ext/libcouchbase/src/bucketconfig/confmon.c +0 -474
  159. data/ext/libcouchbase/src/lcbht/lcbht.c +0 -282
  160. data/ext/libcouchbase/src/lcbio/connect.c +0 -557
  161. data/ext/libcouchbase/src/lcbio/manager.c +0 -584
  162. data/ext/libcouchbase/src/packetutils.c +0 -37
  163. data/ext/libcouchbase/src/simplestring.c +0 -211
  164. data/ext/libcouchbase/src/simplestring.h +0 -228
  165. data/ext/libcouchbase/src/ssobuf.h +0 -82
  166. data/ext/libcouchbase/src/views/viewreq.c +0 -358
  167. data/ext/libcouchbase/tests/basic/t_string.cc +0 -112
@@ -1,584 +0,0 @@
1
- /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
- /*
3
- * Copyright 2014 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
- #include "manager.h"
19
- #include "hostlist.h"
20
- #include "iotable.h"
21
- #include "timer-ng.h"
22
- #include "internal.h"
23
-
24
- #define LOGARGS(mgr, lvl) mgr->settings, "lcbio_mgr", LCB_LOG_##lvl, __FILE__, __LINE__
25
-
26
- typedef enum {
27
- CS_PENDING,
28
- CS_IDLE,
29
- CS_LEASED
30
- } cinfo_state;
31
-
32
- typedef enum {
33
- RS_PENDING,
34
- RS_ASSIGNED
35
- } request_state;
36
-
37
- typedef char mgr_KEY[NI_MAXSERV + NI_MAXHOST + 2];
38
-
39
- typedef struct lcbio_MGRHOST {
40
- lcb_clist_t ll_idle; /* idle connections */
41
- lcb_clist_t ll_pending; /* pending cinfo */
42
- lcb_clist_t requests; /* pending requests */
43
- mgr_KEY key; /* host:port */
44
- struct lcbio_MGR *parent;
45
- lcbio_pASYNC async;
46
- unsigned n_total; /* number of total connections */
47
- unsigned refcount;
48
- } mgr_HOST;
49
-
50
- typedef struct mgr_CINFO_st {
51
- lcbio_PROTOCTX base;
52
- lcb_list_t llnode;
53
- mgr_HOST *parent;
54
- lcbio_SOCKET *sock;
55
- struct lcbio_CONNSTART *cs;
56
- lcbio_pTIMER idle_timer;
57
- int state;
58
- } mgr_CINFO;
59
-
60
- typedef struct lcbio_MGRREQ {
61
- lcb_list_t llnode;
62
- lcbio_CONNDONE_cb callback;
63
- void *arg;
64
- mgr_HOST *host;
65
- lcbio_pTIMER timer;
66
- int state;
67
- lcbio_SOCKET *sock;
68
- lcb_error_t err;
69
- } mgr_REQ;
70
-
71
- #define HE_NPEND(he) LCB_CLIST_SIZE(&(he)->ll_pending)
72
- #define HE_NIDLE(he) LCB_CLIST_SIZE(&(he)->ll_idle)
73
- #define HE_NREQS(he) LCB_CLIST_SIZE(&(he)->requests)
74
- #define HE_NLEASED(he) ((he)->n_total - (HE_NIDLE(he) + HE_NPEND(he)))
75
-
76
- static void on_idle_timeout(void *cookie);
77
- static void he_available_notify(void *cookie);
78
- static void he_dump(mgr_HOST *he, FILE *out);
79
- static void he_unref(mgr_HOST *he);
80
- static void mgr_unref(lcbio_MGR *mgr);
81
-
82
- #define he_ref(he) (he)->refcount++
83
- #define mgr_ref(mgr) (mgr)->refcount++
84
-
85
- static const char *get_hehost(mgr_HOST *h) {
86
- if (!h) { return "NOHOST:NOPORT"; }
87
- return h->key;
88
- }
89
-
90
- /** Format string arguments for %p%s:%s */
91
- #define HE_LOGID(h) get_hehost(h), (void*)h
92
- #define HE_LOGFMT "<%s> (HE=%p) "
93
-
94
- static mgr_CINFO *
95
- cinfo_from_sock(lcbio_SOCKET *sock)
96
- {
97
- lcbio_PROTOCTX *ctx = lcbio_protoctx_get(sock, LCBIO_PROTOCTX_POOL);
98
- return (mgr_CINFO *)ctx;
99
- }
100
-
101
- static void
102
- destroy_cinfo(mgr_CINFO *info)
103
- {
104
- info->parent->n_total--;
105
- if (info->state == CS_IDLE) {
106
- lcb_clist_delete(&info->parent->ll_idle, &info->llnode);
107
-
108
- } else if (info->state == CS_PENDING && info->cs) {
109
- lcbio_connect_cancel(info->cs);
110
- }
111
-
112
- if (info->sock) {
113
- lcbio_SOCKET *s = info->sock;
114
- info->sock = NULL;
115
- lcbio_protoctx_delptr(s, &info->base, 0);
116
- lcbio_unref(s);
117
- }
118
- lcbio_timer_destroy(info->idle_timer);
119
- he_unref(info->parent);
120
- free(info);
121
- }
122
-
123
- static void
124
- cinfo_protoctx_dtor(lcbio_PROTOCTX *ctx)
125
- {
126
- mgr_CINFO *info = (void *)ctx;
127
- info->sock = NULL;
128
- destroy_cinfo(info);
129
- }
130
-
131
- lcbio_MGR *
132
- lcbio_mgr_create(lcb_settings *settings, lcbio_TABLE *io)
133
- {
134
- lcbio_MGR *pool = calloc(1, sizeof(*pool));
135
- if (!pool) {
136
- return NULL;
137
- }
138
-
139
- if ((pool->ht = lcb_hashtable_nc_new(32)) == NULL) {
140
- free(pool);
141
- return NULL;
142
- }
143
-
144
- pool->settings = settings;
145
- pool->io = io;
146
- mgr_ref(pool);
147
- return pool;
148
- }
149
-
150
- static void
151
- iterfunc(const void *k, lcb_size_t nk, const void *v, lcb_size_t nv, void *arg)
152
- {
153
- lcb_clist_t *he_list = (lcb_clist_t *)arg;
154
- mgr_HOST *he = (mgr_HOST *)v;
155
- lcb_list_t *cur, *next;
156
-
157
- LCB_LIST_SAFE_FOR(cur, next, (lcb_list_t *)&he->ll_idle) {
158
- mgr_CINFO *info = LCB_LIST_ITEM(cur, mgr_CINFO, llnode);
159
- destroy_cinfo(info);
160
- }
161
-
162
- LCB_LIST_SAFE_FOR(cur, next, (lcb_list_t *)&he->ll_pending) {
163
- mgr_CINFO *info = LCB_LIST_ITEM(cur, mgr_CINFO, llnode);
164
- destroy_cinfo(info);
165
- }
166
-
167
- memset(&he->ll_idle, 0, sizeof(he->ll_idle));
168
- lcb_clist_append(he_list, (lcb_list_t *)&he->ll_idle);
169
-
170
- (void)k; (void)nk; (void)nv;
171
- }
172
-
173
- static void
174
- he_unref(mgr_HOST *host)
175
- {
176
- if (--host->refcount) {
177
- return;
178
- }
179
-
180
- mgr_unref(host->parent);
181
- free(host);
182
- }
183
-
184
- static void
185
- mgr_unref(lcbio_MGR *mgr)
186
- {
187
- if (--mgr->refcount) {
188
- return;
189
- }
190
- genhash_free(mgr->ht);
191
- free(mgr);
192
- }
193
-
194
- void
195
- lcbio_mgr_destroy(lcbio_MGR *mgr)
196
- {
197
- lcb_clist_t hes;
198
- lcb_list_t *cur, *next;
199
- lcb_clist_init(&hes);
200
-
201
- genhash_iter(mgr->ht, iterfunc, &hes);
202
-
203
- LCB_LIST_SAFE_FOR(cur, next, (lcb_list_t*)&hes) {
204
- mgr_HOST *he = LCB_LIST_ITEM(cur, mgr_HOST, ll_idle);
205
- genhash_delete(mgr->ht, he->key, strlen(he->key));
206
- lcb_clist_delete(&hes, (lcb_list_t *)&he->ll_idle);
207
- lcbio_timer_destroy(he->async);
208
- he->async = NULL;
209
- he_unref(he);
210
- }
211
- mgr_unref(mgr);
212
- }
213
-
214
- static void
215
- invoke_request(mgr_REQ *req)
216
- {
217
- if (req->sock) {
218
- mgr_CINFO *info = cinfo_from_sock(req->sock);
219
- lcb_assert(info->state == CS_IDLE);
220
- info->state = CS_LEASED;
221
- req->state = RS_ASSIGNED;
222
- lcbio_timer_disarm(info->idle_timer);
223
- lcb_log(LOGARGS(info->parent->parent, DEBUG), HE_LOGFMT "Assigning R=%p SOCKET=%p",HE_LOGID(info->parent), (void*)req, (void*)req->sock);
224
- }
225
-
226
- if (req->timer) {
227
- lcbio_timer_destroy(req->timer);
228
- req->timer = NULL;
229
- }
230
-
231
- req->callback(req->sock, req->arg, req->err, 0);
232
- if (req->sock) {
233
- lcbio_unref(req->sock);
234
- }
235
- free(req);
236
- }
237
-
238
- /**
239
- * Called to notify that a connection has become available.
240
- */
241
- static void
242
- connection_available(mgr_HOST *he)
243
- {
244
- while (LCB_CLIST_SIZE(&he->requests) && LCB_CLIST_SIZE(&he->ll_idle)) {
245
- mgr_REQ *req;
246
- mgr_CINFO *info;
247
- lcb_list_t *reqitem, *connitem;
248
-
249
- reqitem = lcb_clist_shift(&he->requests);
250
- connitem = lcb_clist_pop(&he->ll_idle);
251
-
252
- req = LCB_LIST_ITEM(reqitem, mgr_REQ, llnode);
253
- info = LCB_LIST_ITEM(connitem, mgr_CINFO, llnode);
254
- req->sock = info->sock;
255
- req->err = LCB_SUCCESS;
256
- invoke_request(req);
257
- }
258
- }
259
-
260
- /**
261
- * Connection callback invoked from lcbio_connect() when a result is received
262
- */
263
- static void
264
- on_connected(lcbio_SOCKET *sock, void *arg, lcb_error_t err, lcbio_OSERR oserr)
265
- {
266
- mgr_CINFO *info = arg;
267
- mgr_HOST *he = info->parent;
268
- lcb_assert(info->state == CS_PENDING);
269
- info->cs = NULL;
270
-
271
- lcb_log(LOGARGS(he->parent, DEBUG), HE_LOGFMT "Received result for I=%p,C=%p; E=0x%x", HE_LOGID(he), (void*)info, (void*)sock, err);
272
- lcb_clist_delete(&he->ll_pending, &info->llnode);
273
-
274
- if (err != LCB_SUCCESS) {
275
- /** If the connection failed, fail out all remaining requests */
276
- lcb_list_t *cur, *next;
277
- LCB_LIST_SAFE_FOR(cur, next, (lcb_list_t *)&he->requests) {
278
- mgr_REQ *req = LCB_LIST_ITEM(cur, mgr_REQ, llnode);
279
- lcb_clist_delete(&he->requests, &req->llnode);
280
- req->sock = NULL;
281
- req->err = err;
282
- invoke_request(req);
283
- }
284
-
285
- destroy_cinfo(info);
286
-
287
- } else {
288
- info->state = CS_IDLE;
289
- info->sock = sock;
290
- lcbio_ref(info->sock);
291
- lcbio_protoctx_add(sock, &info->base);
292
-
293
- lcb_clist_append(&he->ll_idle, &info->llnode);
294
- lcbio_timer_rearm(info->idle_timer, he->parent->tmoidle);
295
- connection_available(info->parent);
296
- }
297
-
298
- (void)oserr;
299
- }
300
-
301
- static void
302
- start_new_connection(mgr_HOST *he, uint32_t tmo)
303
- {
304
- lcb_host_t tmphost;
305
- lcb_error_t err;
306
-
307
- mgr_CINFO *info = calloc(1, sizeof(*info));
308
- info->state = CS_PENDING;
309
- info->parent = he;
310
-
311
- info->base.id = LCBIO_PROTOCTX_POOL;
312
- info->base.dtor = cinfo_protoctx_dtor;
313
- info->idle_timer = lcbio_timer_new(he->parent->io, info, on_idle_timeout);
314
-
315
- err = lcb_host_parsez(&tmphost, he->key, 80);
316
- if (err != LCB_SUCCESS) {
317
- lcb_log(LOGARGS(he->parent, ERROR), HE_LOGFMT "Could not parse host! Will supply dummy host", HE_LOGID(he));
318
- strcpy(tmphost.host, "BADHOST");
319
- strcpy(tmphost.port, "BADPORT");
320
- }
321
- lcb_log(LOGARGS(he->parent, DEBUG), HE_LOGFMT "Starting connection on I=%p", HE_LOGID(he), (void*)info);
322
-
323
- info->cs = lcbio_connect(he->parent->io, he->parent->settings, &tmphost,
324
- tmo, on_connected, info);
325
-
326
- lcb_clist_append(&he->ll_pending, &info->llnode);
327
- he->n_total++;
328
- he_ref(he);
329
- }
330
-
331
- static void
332
- on_request_timeout(void *cookie)
333
- {
334
- mgr_REQ *req = cookie;
335
- lcb_clist_delete(&req->host->requests, &req->llnode);
336
- req->err = LCB_ETIMEDOUT;
337
- invoke_request(req);
338
- }
339
-
340
- static void
341
- async_invoke_request(void *cookie)
342
- {
343
-
344
- mgr_REQ *req = cookie;
345
- mgr_CINFO *cinfo = cinfo_from_sock(req->sock);
346
- cinfo->state = CS_IDLE;
347
- invoke_request(req);
348
- }
349
-
350
- mgr_REQ *
351
- lcbio_mgr_get(lcbio_MGR *pool, lcb_host_t *dest, uint32_t timeout,
352
- lcbio_CONNDONE_cb handler, void *arg)
353
- {
354
- mgr_HOST *he;
355
- lcb_list_t *cur;
356
- mgr_REQ *req = calloc(1, sizeof(*req));
357
- mgr_KEY key = { 0 };
358
-
359
- sprintf(key, "%s:%s", dest->host, dest->port);
360
-
361
- req->callback = handler;
362
- req->arg = arg;
363
-
364
- he = genhash_find(pool->ht, key, strlen(key));
365
- if (!he) {
366
- he = calloc(1, sizeof(*he));
367
- he->parent = pool;
368
- he->async = lcbio_timer_new(pool->io, he, he_available_notify);
369
- strcpy(he->key, key);
370
-
371
- lcb_clist_init(&he->ll_idle);
372
- lcb_clist_init(&he->ll_pending);
373
- lcb_clist_init(&he->requests);
374
-
375
- /** Not copied */
376
- genhash_store(pool->ht, he->key, strlen(he->key), he, 0);
377
- he_ref(he);
378
- mgr_ref(pool);
379
- }
380
-
381
- req->host = he;
382
-
383
- GT_POPAGAIN:
384
-
385
- cur = lcb_clist_pop(&he->ll_idle);
386
- if (cur) {
387
- int clstatus;
388
- mgr_CINFO *info = LCB_LIST_ITEM(cur, mgr_CINFO, llnode);
389
-
390
- clstatus = lcbio_is_netclosed(info->sock, LCB_IO_SOCKCHECK_PEND_IS_ERROR);
391
-
392
- if (clstatus == LCB_IO_SOCKCHECK_STATUS_CLOSED) {
393
- lcb_log(LOGARGS(pool, WARN), HE_LOGFMT "Pooled socket is dead. Continuing to next one", HE_LOGID(he));
394
-
395
- /* Set to CS_LEASED, since it's not inside any of our lists */
396
- info->state = CS_LEASED;
397
- destroy_cinfo(info);
398
- goto GT_POPAGAIN;
399
- }
400
-
401
- lcbio_timer_disarm(info->idle_timer);
402
- req->sock = info->sock;
403
- req->state = RS_ASSIGNED;
404
- req->timer = lcbio_timer_new(pool->io, req, async_invoke_request);
405
- info->state = CS_LEASED;
406
- lcbio_async_signal(req->timer);
407
- lcb_log(LOGARGS(pool, INFO), HE_LOGFMT "Found ready connection in pool. Reusing socket and not creating new connection", HE_LOGID(he));
408
-
409
- } else {
410
- req->state = RS_PENDING;
411
- req->timer = lcbio_timer_new(pool->io, req, on_request_timeout);
412
- lcbio_timer_rearm(req->timer, timeout);
413
-
414
- lcb_clist_append(&he->requests, &req->llnode);
415
- if (HE_NPEND(he) < HE_NREQS(he)) {
416
- lcb_log(LOGARGS(pool, DEBUG), HE_LOGFMT "Creating new connection because none are available in the pool", HE_LOGID(he));
417
- start_new_connection(he, timeout);
418
-
419
- } else {
420
- lcb_log(LOGARGS(pool, DEBUG), HE_LOGFMT "Not creating a new connection. There are still pending ones", HE_LOGID(he));
421
- }
422
- }
423
-
424
- return req;
425
- }
426
-
427
- /**
428
- * Invoked when a new socket is available for allocation within the
429
- * request queue.
430
- */
431
- static void
432
- he_available_notify(void *cookie)
433
- {
434
- connection_available((mgr_HOST *)cookie);
435
- }
436
-
437
- void
438
- lcbio_mgr_cancel(mgr_REQ *req)
439
- {
440
- mgr_HOST *he = req->host;
441
- lcbio_MGR *mgr = he->parent;
442
- if (req->timer) {
443
- lcbio_timer_destroy(req->timer);
444
- req->timer = NULL;
445
- }
446
-
447
- if (req->sock) {
448
- lcb_log(LOGARGS(mgr, DEBUG), HE_LOGFMT "Cancelling request=%p with existing connection", HE_LOGID(he), (void*)req);
449
- lcbio_mgr_put(req->sock);
450
- lcbio_async_signal(he->async);
451
-
452
- } else {
453
- lcb_log(LOGARGS(mgr, DEBUG), HE_LOGFMT "Request=%p has no connection.. yet", HE_LOGID(he), (void*)req);
454
- lcb_clist_delete(&he->requests, &req->llnode);
455
- }
456
- free(req);
457
- }
458
-
459
- static void
460
- on_idle_timeout(void *cookie)
461
- {
462
- mgr_CINFO *info = cookie;
463
-
464
- lcb_log(LOGARGS(info->parent->parent, DEBUG), HE_LOGFMT "Idle connection expired", HE_LOGID(info->parent));
465
-
466
- lcbio_unref(info->sock);
467
- }
468
-
469
- void
470
- lcbio_mgr_put(lcbio_SOCKET *sock)
471
- {
472
- mgr_HOST *he;
473
- lcbio_MGR *mgr;
474
- mgr_CINFO *info = cinfo_from_sock(sock);
475
-
476
- if (!info) {
477
- fprintf(stderr, "Requested put() for non-pooled (or detached) socket=%p\n", (void *)sock);
478
- lcbio_unref(sock);
479
- return;
480
- }
481
-
482
- he = info->parent;
483
- mgr = he->parent;
484
-
485
- if (HE_NIDLE(he) >= mgr->maxidle) {
486
- lcb_log(LOGARGS(mgr, INFO), HE_LOGFMT "Closing idle connection. Too many in quota", HE_LOGID(he));
487
- lcbio_unref(info->sock);
488
- return;
489
- }
490
-
491
- lcb_log(LOGARGS(mgr, INFO), HE_LOGFMT "Placing socket back into the pool. I=%p,C=%p", HE_LOGID(he), (void*)info, (void*)sock);
492
- lcbio_timer_rearm(info->idle_timer, mgr->tmoidle);
493
- lcb_clist_append(&he->ll_idle, &info->llnode);
494
- info->state = CS_IDLE;
495
- }
496
-
497
- void
498
- lcbio_mgr_discard(lcbio_SOCKET *sock)
499
- {
500
- lcbio_unref(sock);
501
- }
502
-
503
- void
504
- lcbio_mgr_detach(lcbio_SOCKET *sock)
505
- {
506
- lcbio_protoctx_delid(sock, LCBIO_PROTOCTX_POOL, 1);
507
- }
508
-
509
-
510
- #define CONN_INDENT " "
511
-
512
- static void
513
- write_he_list(lcb_clist_t *ll, FILE *out)
514
- {
515
- lcb_list_t *llcur;
516
- LCB_LIST_FOR(llcur, (lcb_list_t *)ll) {
517
- mgr_CINFO *info = LCB_LIST_ITEM(llcur, mgr_CINFO, llnode);
518
- fprintf(out, "%sCONN [I=%p,C=%p ",
519
- CONN_INDENT, (void *)info, (void *)&info->sock);
520
-
521
- if (info->sock->io->model == LCB_IOMODEL_EVENT) {
522
- fprintf(out, "SOCKFD=%d", (int)info->sock->u.fd);
523
- } else {
524
- fprintf(out, "SOCKDATA=%p", (void *)info->sock->u.sd);
525
- }
526
- fprintf(out, " STATE=0x%x", info->state);
527
- fprintf(out, "]\n");
528
- }
529
-
530
- }
531
-
532
- static void
533
- he_dump(mgr_HOST *he, FILE *out)
534
- {
535
- lcb_list_t *llcur;
536
- fprintf(out, "HOST=%s", he->key);
537
- fprintf(out, "Requests=%d, Idle=%d, Pending=%d, Leased=%d\n",
538
- (int)HE_NREQS(he), (int)HE_NIDLE(he), (int)HE_NPEND(he), (int)HE_NLEASED(he));
539
-
540
- fprintf(out, CONN_INDENT "Idle Connections:\n");
541
- write_he_list(&he->ll_idle, out);
542
- fprintf(out, CONN_INDENT "Pending Connections: \n");
543
- write_he_list(&he->ll_pending, out);
544
- fprintf(out, CONN_INDENT "Pending Requests:\n");
545
-
546
- LCB_LIST_FOR(llcur, (lcb_list_t *)&he->requests) {
547
- mgr_REQ *req = LCB_LIST_ITEM(llcur, mgr_REQ, llnode);
548
- union {
549
- lcbio_CONNDONE_cb cb;
550
- void *ptr;
551
- } u_cb;
552
-
553
- u_cb.cb = req->callback;
554
-
555
- fprintf(out, "%sREQ [R=%p, Callback=%p, Data=%p, State=0x%x]\n",
556
- CONN_INDENT, (void *)req, u_cb.ptr, (void *)req->arg,
557
- req->state);
558
- }
559
-
560
- fprintf(out, "\n");
561
-
562
- }
563
-
564
- static void
565
- dumpfunc(const void *k, lcb_size_t nk, const void *v, lcb_size_t nv, void *arg)
566
- {
567
- FILE *out = (FILE *)arg;
568
- mgr_HOST *he = (void *)v;
569
- he_dump(he, out);
570
- (void)nk;(void)k;(void)nv;
571
- }
572
-
573
- /**
574
- * Dumps the connection manager state to stderr
575
- */
576
- LCB_INTERNAL_API
577
- void lcbio_mgr_dump(lcbio_MGR *mgr, FILE *out)
578
- {
579
- if (out == NULL) {
580
- out = stderr;
581
- }
582
-
583
- genhash_iter(mgr->ht, dumpfunc, out);
584
- }