libcouchbase 0.3.3 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -19,8 +19,8 @@
19
19
  #define LCBIO_MANAGER_H
20
20
  #include "connect.h"
21
21
  #include "settings.h"
22
- #include "contrib/genhash/genhash.h"
23
22
  #include "list.h"
23
+ #include "ioutils.h"
24
24
  #include <stdio.h>
25
25
 
26
26
 
@@ -42,114 +42,151 @@
42
42
  */
43
43
 
44
44
  #ifdef __cplusplus
45
- extern "C" {
46
- #endif
45
+ #include <map>
47
46
 
48
- /** Cancellable pool request */
49
- struct lcbio_MGRREQ;
47
+ namespace lcb {
48
+ namespace io {
50
49
 
51
50
  /** @brief Socket Pool */
52
- typedef struct lcbio_MGR {
53
- genhash_t* ht;
54
- lcb_settings *settings;
55
- lcbio_pTABLE io;
51
+ class Pool;
56
52
 
57
- /**
58
- * Maximum number of microseconds for a connection to idle inside the pool
59
- * before being closed
60
- */
61
- uint32_t tmoidle;
62
- unsigned maxtotal;
63
- unsigned maxidle; /**< Maximum number of idle connections, per host */
64
- unsigned refcount;
65
- } lcbio_MGR;
53
+ /** @brief Pooled connection */
54
+ struct PoolConnInfo;
66
55
 
67
- /**
68
- * Create a socket pool controlled by the given settings and IO structure.
69
- * This function will increment the refcount on both the settings and table
70
- * objects.
71
- */
72
- LCB_INTERNAL_API
73
- lcbio_MGR*
74
- lcbio_mgr_create(lcb_settings *settings, lcbio_pTABLE io);
56
+ /** @brief Cancellable pool request */
57
+ struct PoolRequest;
75
58
 
76
- /**
77
- * Destroy the socket pool. Note that internally this just decrements the
78
- * reference count. The object is only destroyed when its count hits zero.
79
- */
80
- LCB_INTERNAL_API
81
- void
82
- lcbio_mgr_destroy(lcbio_MGR *);
59
+ struct PoolHost;
60
+ }
61
+ }
83
62
 
84
- /**
85
- * Request a connection from the socket pool. The semantics and prototype
86
- * of this function are by design similar to lcbio_connect() as they do the
87
- * same things.
88
- *
89
- * @param mgr
90
- * @param dest the host to connect to
91
- * @param timeout amount of time to wait for a connection to be estblished
92
- * @param handler a callback to invoke when the result is ready
93
- * @param arg an argument passed to the callback
94
- * @return a request handle which may be cancelled
95
- * @see lcbio_connect()
96
- */
97
- LCB_INTERNAL_API
98
- struct lcbio_MGRREQ *
99
- lcbio_mgr_get(lcbio_MGR *mgr, lcb_host_t *dest, uint32_t timeout,
100
- lcbio_CONNDONE_cb handler, void *arg);
63
+ typedef lcb::io::Pool lcbio_MGR;
64
+ extern "C" {
101
65
 
102
- /**
103
- * Cancel a pending request. The callback for the request must have not already
104
- * been invoked (if it has, use sockpool_put)
105
- * @param req the request to cancel
106
- */
107
- LCB_INTERNAL_API
108
- void
109
- lcbio_mgr_cancel(struct lcbio_MGRREQ *req);
66
+ #else
67
+ /* C only */
68
+ typedef struct lcbio_MGR_CDUMMY lcbio_MGR;
69
+ #endif
110
70
 
111
- /**
112
- * Release a socket back into the pool. This means the socket is no longer
113
- * used and shall be available for reuse for another request. To verify these
114
- * constraints, the socket's reference count must be one. Once the socket
115
- * has been released its reference count should not be modified.
116
- */
117
- LCB_INTERNAL_API
118
- void lcbio_mgr_put(lcbio_SOCKET *sock);
71
+ #ifdef __cplusplus
72
+ }
119
73
 
120
- /**
121
- * Mark a slot as available but discard the current connection. This should be
122
- * done if the connection itself is "dirty", i.e. has a protocol error on it
123
- * or is otherwise not suitable for reuse
124
- */
125
- LCB_INTERNAL_API
126
- void lcbio_mgr_discard(lcbio_SOCKET *sock);
74
+ namespace lcb {
75
+ namespace io {
76
+ class Pool {
77
+ public:
78
+ /**
79
+ * Create a socket pool controlled by the given settings and IO structure.
80
+ * This function will increment the refcount on both the settings and table
81
+ * objects.
82
+ */
83
+ Pool(lcb_settings*, lcbio_pTABLE);
127
84
 
128
- /**
129
- * Like lcbio_mgr_discard() except the source connection is left untouched. It
130
- * is removed from the pool instead.
131
- *
132
- * Because the lcbio_MGR object itself has internal limits and thresholds on how
133
- * many leased and/or open connections it can contain, when a connection receives
134
- * an error it must either be discarded back to the pool (in which case the
135
- * connection is cleaned up and is freed) or it must be detached (in which case
136
- * the connection object itself still remains valid, but the pool does not know
137
- * about it, and all its counters are restored, as with lcbio_mgr_discard()).
138
- *
139
- * lcbio_mgr_discard() itself is now implemented as the equivalent to:
140
- * `lcbio_mgr_detach(mgr, conn)`;
141
- */
142
- LCB_INTERNAL_API
143
- void lcbio_mgr_detach(lcbio_SOCKET *sock);
85
+ /**
86
+ * Destroy the socket pool. Note that internally this just decrements the
87
+ * reference count. The object is only destroyed when its count hits zero.
88
+ */
89
+ void shutdown();
144
90
 
145
- /**
146
- * Dumps the connection manager state to stderr
147
- */
148
- LCB_INTERNAL_API
149
- void lcbio_mgr_dump(lcbio_MGR *mgr, FILE *out);
91
+ /**
92
+ * Request a connection from the socket pool. The semantics and prototype
93
+ * of this function are by design similar to lcbio_connect() as they do the
94
+ * same things.
95
+ *
96
+ * @param dest the host to connect to
97
+ * @param timeout amount of time to wait for a connection to be estblished
98
+ * @param handler a callback to invoke when the result is ready
99
+ * @param arg an argument passed to the callback
100
+ * @return a request handle which may be cancelled
101
+ * @see lcbio_connect()
102
+ */
103
+ ConnectionRequest* get(const lcb_host_t&, uint32_t, lcbio_CONNDONE_cb, void *);
150
104
 
151
- #ifdef __cplusplus
152
- }
105
+ /**
106
+ * Release a socket back into the pool. This means the socket is no longer
107
+ * used and shall be available for reuse for another request. To verify these
108
+ * constraints, the socket's reference count must be one. Once the socket
109
+ * has been released its reference count should not be modified.
110
+ */
111
+ static void put(lcbio_SOCKET *sock);
112
+
113
+ /**
114
+ * Mark a slot as available but discard the current connection. This should be
115
+ * done if the connection itself is "dirty", i.e. has a protocol error on it
116
+ * or is otherwise not suitable for reuse
117
+ */
118
+ static void discard(lcbio_SOCKET *sock);
119
+
120
+ /**
121
+ * Like lcbio_mgr_discard() except the source connection is left untouched. It
122
+ * is removed from the pool instead.
123
+ *
124
+ * Because the lcbio_MGR object itself has internal limits and thresholds on how
125
+ * many leased and/or open connections it can contain, when a connection receives
126
+ * an error it must either be discarded back to the pool (in which case the
127
+ * connection is cleaned up and is freed) or it must be detached (in which case
128
+ * the connection object itself still remains valid, but the pool does not know
129
+ * about it, and all its counters are restored, as with lcbio_mgr_discard()).
130
+ *
131
+ * lcbio_mgr_discard() itself is now implemented as the equivalent to:
132
+ * `lcbio_mgr_detach(mgr, conn)`;
133
+ */
134
+ static void detach(lcbio_SOCKET *sock);
135
+
136
+ static bool is_from_pool(const lcbio_SOCKET *sock);
137
+
138
+ /**
139
+ * Dumps the connection manager state to stderr
140
+ */
141
+ void dump(FILE *) const;
142
+
143
+ inline void ref();
144
+ inline void unref();
145
+
146
+ struct Options {
147
+ Options() : maxtotal(0), maxidle(0), tmoidle(0) {
148
+ }
149
+
150
+ /** Maximum *total* number of connections opened by the pool. If this
151
+ * number is exceeded, the pool will black hole future requests until
152
+ * a new slot becomes available.
153
+ */
154
+ unsigned maxtotal;
155
+
156
+ /**
157
+ * Maximum number of idle connections to keep around
158
+ */
159
+ unsigned maxidle;
160
+
161
+ /**
162
+ * The amount of time the pool should wait before closing idle
163
+ * connections. In microseconds
164
+ */
165
+ uint32_t tmoidle;
166
+ };
167
+
168
+ void set_options(const Options& opts) {
169
+ options = opts;
170
+ }
171
+
172
+ Options& get_options() {
173
+ return options;
174
+ }
175
+
176
+ private:
177
+ friend struct PoolRequest;
178
+ friend struct PoolConnInfo;
179
+ friend struct PoolHost;
180
+
181
+ typedef std::map<std::string, PoolHost*> HostMap;
182
+ HostMap ht;
183
+ lcb_settings *settings;
184
+ lcbio_pTABLE io;
185
+ Options options;
186
+ unsigned refcount;
187
+ };
188
+ } // namespace io
189
+ } // namespace lcb
153
190
  #endif
154
191
  /**@}*/
155
192
 
@@ -24,9 +24,9 @@ lcbio_protoctx_add(lcbio_SOCKET *sock, lcbio_PROTOCTX *ctx)
24
24
  }
25
25
 
26
26
  lcbio_PROTOCTX *
27
- lcbio_protoctx_get(lcbio_SOCKET *sock, lcbio_PROTOID id)
27
+ lcbio_protoctx_get(const lcbio_SOCKET *sock, lcbio_PROTOID id)
28
28
  {
29
- lcb_list_t *ll;
29
+ const lcb_list_t *ll;
30
30
  LCB_LIST_FOR(ll, &sock->protos) {
31
31
  lcbio_PROTOCTX *cur = LCB_LIST_ITEM(ll, lcbio_PROTOCTX, ll);
32
32
  if (cur->id == id) {
@@ -0,0 +1,87 @@
1
+ /*
2
+ * Copyright 2016 Couchbase, Inc.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ #ifndef LCBIO_TIMER_CXX
18
+ #define LCBIO_TIMER_CXX
19
+
20
+ #include <lcbio/timer-ng.h>
21
+ #include <cstdlib>
22
+
23
+ namespace lcb {
24
+ namespace io {
25
+
26
+ class SimpleTimer {
27
+ public:
28
+ typedef void (Callback)(void*);
29
+ SimpleTimer(lcbio_pTABLE iot, void *data, Callback cb)
30
+ : inner(lcbio_timer_new(iot, data, cb)) {
31
+ }
32
+ ~SimpleTimer() {
33
+ release();
34
+ }
35
+ void release() {
36
+ if (inner != NULL) {
37
+ lcbio_timer_destroy(inner);
38
+ inner = NULL;
39
+ }
40
+ }
41
+ void signal() {
42
+ lcbio_async_signal(inner);
43
+ }
44
+ void cancel() {
45
+ lcbio_timer_disarm(inner);
46
+ }
47
+ bool is_armed() const {
48
+ return lcbio_timer_armed(inner);
49
+ }
50
+ void rearm(uint32_t usec) {
51
+ lcbio_timer_rearm(inner, usec);
52
+ }
53
+ void arm_if_disarmed(uint32_t usec) {
54
+ if (!is_armed()) {
55
+ rearm(usec);
56
+ }
57
+ }
58
+ void dump(FILE *fp) const {
59
+ lcbio_timer_dump(inner, fp);
60
+ }
61
+ private:
62
+ lcbio_pTIMER inner;
63
+ SimpleTimer(const SimpleTimer&);
64
+ };
65
+
66
+ template <typename T, void (T::*M)(void)>
67
+ class Timer : public SimpleTimer {
68
+ public:
69
+ Timer(lcbio_pTABLE iot, T* ptr)
70
+ : SimpleTimer(iot, ptr, cb) {
71
+ }
72
+
73
+ ~Timer() {
74
+ release();
75
+ }
76
+
77
+ private:
78
+ static void cb(void *arg) {
79
+ T *obj = reinterpret_cast<T*>(arg);
80
+ (obj->*M)();
81
+ }
82
+ Timer(const Timer&);
83
+ };
84
+
85
+ }
86
+ }
87
+ #endif
@@ -543,6 +543,15 @@ int
543
543
  mcreq_pipeline_init(mc_PIPELINE *pipeline)
544
544
  {
545
545
  nb_SETTINGS settings;
546
+
547
+ /* Initialize all members to 0 */
548
+ memset(&pipeline->requests, 0, sizeof pipeline->requests);
549
+ pipeline->parent = NULL;
550
+ pipeline->flush_start = NULL;
551
+ pipeline->index = 0;
552
+ memset(&pipeline->ctxqueued, 0, sizeof pipeline->ctxqueued);
553
+ pipeline->buf_done_callback = NULL;
554
+
546
555
  netbuf_default_settings(&settings);
547
556
 
548
557
  /** Initialize datapool */
@@ -550,7 +559,7 @@ mcreq_pipeline_init(mc_PIPELINE *pipeline)
550
559
 
551
560
  /** Initialize request pool */
552
561
  settings.data_basealloc = sizeof(mc_PACKET) * 32;
553
- netbuf_init(&pipeline->reqpool, &settings);
562
+ netbuf_init(&pipeline->reqpool, &settings);;
554
563
  return 0;
555
564
  }
556
565
 
@@ -911,7 +920,7 @@ mcreq_dump_packet(const mc_PACKET *packet, FILE *fp, mcreq_payload_dump_fn dumpf
911
920
  fprintf(fp, "%sValue is user allocated\n", indent);
912
921
  }
913
922
  fprintf(fp, "%sValue: %p, %u bytes\n", indent,
914
- SPAN_BUFFER(&packet->u_value.single), packet->u_value.single.size);
923
+ (void *)SPAN_BUFFER(&packet->u_value.single), packet->u_value.single.size);
915
924
  }
916
925
  }
917
926
 
@@ -179,10 +179,17 @@ typedef struct {
179
179
  * packets, or when the packet itself is generated internally rather than
180
180
  * on behalf of an API request.
181
181
  */
182
- typedef struct {
182
+ typedef struct mc_REQDATAEX {
183
183
  const void *cookie; /**< User data */
184
184
  hrtime_t start; /**< Start time */
185
- mc_REQDATAPROCS *procs; /**< Common routines for the packet */
185
+ const mc_REQDATAPROCS *procs; /**< Common routines for the packet */
186
+
187
+ #ifdef __cplusplus
188
+ mc_REQDATAEX(const void *cookie_,
189
+ const mc_REQDATAPROCS &procs_, hrtime_t start_)
190
+ : cookie(cookie_), start(start_), procs(&procs_) {
191
+ }
192
+ #endif
186
193
  } mc_REQDATAEX;
187
194
 
188
195
  /**
@@ -29,6 +29,8 @@
29
29
  #define LOGARGS_T(lvl) LOGARGS(this, lvl)
30
30
 
31
31
  #define LOGFMT "<%s:%s> (SRV=%p,IX=%d) "
32
+ #define PKTFMT "OP=0x%x, RC=0x%x, SEQ=%u"
33
+ #define PKTARGS(pkt) (pkt).opcode(), (pkt).status(), (pkt).opaque()
32
34
 
33
35
  #define LOGID(server) get_ctx_host(server->connctx), get_ctx_port(server->connctx), (void*)server, server->index
34
36
  #define LOGID_T() LOGID(this)
@@ -97,7 +99,7 @@ void
97
99
  lcb_sched_flush(lcb_t instance)
98
100
  {
99
101
  for (size_t ii = 0; ii < LCBT_NSERVERS(instance); ii++) {
100
- Server *server = LCBT_GET_SERVER(instance, ii);
102
+ Server *server = instance->get_server(ii);
101
103
 
102
104
  if (!server->has_pending()) {
103
105
  continue;
@@ -120,8 +122,8 @@ Server::handle_nmv(MemcachedResponse& resinfo, mc_PACKET *oldpkt)
120
122
  protocol_binary_request_header hdr;
121
123
  lcb_error_t err = LCB_ERROR;
122
124
  lcb_U16 vbid;
123
- clconfig_provider *cccp = lcb_confmon_get_provider(instance->confmon,
124
- LCB_CLCONFIG_CCCP);
125
+ lcb::clconfig::Provider *cccp =
126
+ instance->confmon->get_provider(lcb::clconfig::CLCONFIG_CCCP);
125
127
 
126
128
  mcreq_read_hdr(oldpkt, &hdr);
127
129
  vbid = ntohs(hdr.request.vbucket);
@@ -132,12 +134,12 @@ Server::handle_nmv(MemcachedResponse& resinfo, mc_PACKET *oldpkt)
132
134
 
133
135
  if (resinfo.bodylen() && cccp->enabled) {
134
136
  std::string s(resinfo.body<const char*>(), resinfo.vallen());
135
- err = lcb_cccp_update(cccp, curhost->host, s.c_str());
137
+ err = lcb::clconfig::cccp_update(cccp, curhost->host, s.c_str());
136
138
  }
137
139
 
138
140
  if (err != LCB_SUCCESS) {
139
141
  int bs_options;
140
- if (instance->cur_configinfo->origin == LCB_CLCONFIG_CCCP) {
142
+ if (instance->cur_configinfo->get_origin() == lcb::clconfig::CLCONFIG_CCCP) {
141
143
  /**
142
144
  * XXX: Not enough to see if cccp was enabled, since cccp might
143
145
  * be requested by a user, but would still not actually be active
@@ -146,11 +148,11 @@ Server::handle_nmv(MemcachedResponse& resinfo, mc_PACKET *oldpkt)
146
148
  *
147
149
  * For this reason, we don't use if (cccp->enabled) {...}
148
150
  */
149
- bs_options = LCB_BS_REFRESH_THROTTLE;
151
+ bs_options = BS_REFRESH_THROTTLE;
150
152
  } else {
151
- bs_options = LCB_BS_REFRESH_ALWAYS;
153
+ bs_options = BS_REFRESH_ALWAYS;
152
154
  }
153
- lcb_bootstrap_common(instance, bs_options);
155
+ instance->bootstrap(bs_options);
154
156
  }
155
157
 
156
158
  if (!lcb_should_retry(settings, oldpkt, LCB_NOT_MY_VBUCKET)) {
@@ -164,6 +166,124 @@ Server::handle_nmv(MemcachedResponse& resinfo, mc_PACKET *oldpkt)
164
166
  return true;
165
167
  }
166
168
 
169
+ /**
170
+ * Determine if this is an error code that we can pass to the user, or can
171
+ * otherwise handle "innately"
172
+ */
173
+ static bool is_fastpath_error(uint16_t rc) {
174
+ switch (rc) {
175
+ case PROTOCOL_BINARY_RESPONSE_SUCCESS:
176
+ case PROTOCOL_BINARY_RESPONSE_KEY_ENOENT:
177
+ case PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS:
178
+ case PROTOCOL_BINARY_RESPONSE_E2BIG:
179
+ case PROTOCOL_BINARY_RESPONSE_NOT_STORED:
180
+ case PROTOCOL_BINARY_RESPONSE_DELTA_BADVAL:
181
+ case PROTOCOL_BINARY_RESPONSE_ERANGE:
182
+ case PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED:
183
+ case PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND:
184
+ case PROTOCOL_BINARY_RESPONSE_ETMPFAIL:
185
+ case PROTOCOL_BINARY_RESPONSE_ENOMEM:
186
+ case PROTOCOL_BINARY_RESPONSE_SUBDOC_PATH_ENOENT:
187
+ case PROTOCOL_BINARY_RESPONSE_SUBDOC_PATH_EEXISTS:
188
+ case PROTOCOL_BINARY_RESPONSE_SUBDOC_PATH_MISMATCH:
189
+ case PROTOCOL_BINARY_RESPONSE_SUBDOC_PATH_EINVAL:
190
+ case PROTOCOL_BINARY_RESPONSE_SUBDOC_PATH_E2BIG:
191
+ case PROTOCOL_BINARY_RESPONSE_SUBDOC_VALUE_CANTINSERT:
192
+ case PROTOCOL_BINARY_RESPONSE_SUBDOC_VALUE_ETOODEEP:
193
+ case PROTOCOL_BINARY_RESPONSE_SUBDOC_DOC_NOTJSON:
194
+ case PROTOCOL_BINARY_RESPONSE_SUBDOC_NUM_ERANGE:
195
+ case PROTOCOL_BINARY_RESPONSE_SUBDOC_DELTA_ERANGE:
196
+ case PROTOCOL_BINARY_RESPONSE_SUBDOC_INVALID_COMBO:
197
+ case PROTOCOL_BINARY_RESPONSE_SUBDOC_MULTI_PATH_FAILURE:
198
+ case PROTOCOL_BINARY_RESPONSE_EACCESS:
199
+ return true;
200
+ default:
201
+ if (rc >= 0xc0 && rc <= 0xcc) {
202
+ // other subdoc?
203
+ return true;
204
+ } else {
205
+ return false;
206
+ }
207
+ break;
208
+ }
209
+ }
210
+
211
+ #define ERRMAP_HANDLE_CONTINUE 0
212
+ #define ERRMAP_HANDLE_DISCONN 1
213
+ #define ERRMAP_HANDLE_RETRY 2
214
+
215
+ /**
216
+ * Handle an unknown memcached error
217
+ *
218
+ * @param mcresp Response which contains the unknown error
219
+ * @param[out] newerr more user-friendly based on error map attributes
220
+ *
221
+ * @return true if this function handled the error specially (by disconnecting)
222
+ * or false if normal handling should continue.
223
+ */
224
+ int Server::handle_unknown_error(const mc_PACKET *request,
225
+ const MemcachedResponse& mcresp,
226
+ lcb_error_t& newerr) {
227
+
228
+ if (!settings->errmap->isLoaded() || !settings->use_errmap) {
229
+ // If there's no error map, just return false
230
+ return ERRMAP_HANDLE_CONTINUE;
231
+ }
232
+
233
+ // Look up the error map definition for this error
234
+ const errmap::Error& err = settings->errmap->getError(mcresp.status());
235
+
236
+ if (!err.isValid() || err.hasAttribute(errmap::SPECIAL_HANDLING)) {
237
+ lcb_log(LOGARGS_T(ERR), LOGFMT "Received error not in error map or requires special handling! " PKTFMT, LOGID_T(), PKTARGS(mcresp));
238
+ lcbio_ctx_senderr(connctx, LCB_PROTOCOL_ERROR);
239
+ return ERRMAP_HANDLE_DISCONN;
240
+ } else {
241
+ lcb_log(LOGARGS_T(WARN), LOGFMT "Received server error %s (0x%x) on packet: " PKTFMT, LOGID_T(), err.shortname.c_str(), err.code, PKTARGS(mcresp));
242
+ }
243
+
244
+ if (err.hasAttribute(errmap::FETCH_CONFIG)) {
245
+ instance->bootstrap(BS_REFRESH_THROTTLE);
246
+ }
247
+
248
+ if (err.hasAttribute(errmap::TEMPORARY)) {
249
+ newerr = LCB_GENERIC_TMPERR;
250
+ }
251
+
252
+ if (err.hasAttribute(errmap::CONSTRAINT_FAILURE)) {
253
+ newerr = LCB_GENERIC_CONSTRAINT_ERR;
254
+ }
255
+
256
+ if (err.hasAttribute(errmap::AUTH)) {
257
+ newerr = LCB_AUTH_ERROR;
258
+ }
259
+
260
+ if (err.hasAttribute(errmap::SUBDOC) && newerr == LCB_SUCCESS) {
261
+ newerr = LCB_GENERIC_SUBDOCERR;
262
+ }
263
+
264
+ int rv = 0;
265
+
266
+ if (err.hasAttribute(errmap::AUTO_RETRY)) {
267
+ errmap::RetrySpec *spec = err.getRetrySpec();
268
+
269
+ mc_PACKET *newpkt = mcreq_renew_packet(request);
270
+ newpkt->flags &= ~MCREQ_STATE_FLAGS;
271
+ instance->retryq->add((mc_EXPACKET *)newpkt, newerr ? newerr : LCB_ERROR, spec);
272
+ rv |= ERRMAP_HANDLE_RETRY;
273
+ }
274
+
275
+ if (err.hasAttribute(errmap::CONN_STATE_INVALIDATED)) {
276
+ if (newerr != LCB_SUCCESS) {
277
+ newerr = LCB_ERROR;
278
+ }
279
+ lcbio_ctx_senderr(connctx, newerr);
280
+ rv |= ERRMAP_HANDLE_DISCONN;
281
+ }
282
+
283
+ return rv;
284
+
285
+ }
286
+
167
287
  /* This function is called within a loop to process a single packet.
168
288
  *
169
289
  * If a full packet is available, it will process the packet and return
@@ -219,12 +339,20 @@ Server::try_read(lcbio_CTX *ctx, rdb_IOROPE *ior)
219
339
  }
220
340
 
221
341
  if (!request) {
222
- lcb_log(LOGARGS_T(WARN), LOGFMT "Found stale packet (OP=0x%x, RC=0x%x, SEQ=%u)", LOGID_T(), mcresp.opcode(), mcresp.status(), mcresp.opaque());
342
+ lcb_log(LOGARGS_T(WARN), LOGFMT "Server sent us reply for a timed-out command. (OP=0x%x, RC=0x%x, SEQ=%u)", LOGID_T(), mcresp.opcode(), mcresp.status(), mcresp.opaque());
223
343
  rdb_consumed(ior, pktsize);
224
344
  return PKT_READ_COMPLETE;
225
345
  }
226
346
 
227
- if (mcresp.status() == PROTOCOL_BINARY_RESPONSE_NOT_MY_VBUCKET) {
347
+ lcb_error_t err_override = LCB_SUCCESS;
348
+ ReadState rdstate = PKT_READ_COMPLETE;
349
+ int unknown_err_rv;
350
+
351
+ /* Check if the status code is one which must be handled carefully by the
352
+ * client */
353
+ if (is_fastpath_error(mcresp.status())) {
354
+ // Nothing here!
355
+ } else if (mcresp.status() == PROTOCOL_BINARY_RESPONSE_NOT_MY_VBUCKET) {
228
356
  /* consume the header */
229
357
  DO_ASSIGN_PAYLOAD()
230
358
  if (!handle_nmv(mcresp, request)) {
@@ -232,13 +360,25 @@ Server::try_read(lcbio_CTX *ctx, rdb_IOROPE *ior)
232
360
  }
233
361
  DO_SWALLOW_PAYLOAD()
234
362
  goto GT_DONE;
363
+ } else if ((unknown_err_rv =
364
+ handle_unknown_error(request, mcresp, err_override)) !=
365
+ ERRMAP_HANDLE_CONTINUE) {
366
+ DO_ASSIGN_PAYLOAD()
367
+ if (!(unknown_err_rv & ERRMAP_HANDLE_RETRY)) {
368
+ mcreq_dispatch_response(this, request, &mcresp, err_override);
369
+ }
370
+ DO_SWALLOW_PAYLOAD()
371
+ if (unknown_err_rv & ERRMAP_HANDLE_DISCONN) {
372
+ rdstate = PKT_READ_ABORT;
373
+ }
374
+ goto GT_DONE;
235
375
  }
236
376
 
237
377
  /* Figure out if the request is 'ufwd' or not */
238
378
  if (!(request->flags & MCREQ_F_UFWD)) {
239
379
  DO_ASSIGN_PAYLOAD();
240
380
  mcresp.bufh = rdb_get_first_segment(ior);
241
- mcreq_dispatch_response(this, request, &mcresp, LCB_SUCCESS);
381
+ mcreq_dispatch_response(this, request, &mcresp, err_override);
242
382
  DO_SWALLOW_PAYLOAD()
243
383
 
244
384
  } else {
@@ -265,7 +405,7 @@ Server::try_read(lcbio_CTX *ctx, rdb_IOROPE *ior)
265
405
  if (is_last) {
266
406
  mcreq_packet_handled(this, request);
267
407
  }
268
- return PKT_READ_COMPLETE;
408
+ return rdstate;
269
409
  }
270
410
 
271
411
  static void
@@ -307,7 +447,8 @@ Server::maybe_retry_packet(mc_PACKET *pkt, lcb_error_t err)
307
447
 
308
448
  mc_PACKET *newpkt = mcreq_renew_packet(pkt);
309
449
  newpkt->flags &= ~MCREQ_STATE_FLAGS;
310
- instance->retryq->add((mc_EXPACKET *)newpkt, err);
450
+ // TODO: Load the 4th argument from the error map
451
+ instance->retryq->add((mc_EXPACKET *)newpkt, err, NULL);
311
452
  return true;
312
453
  }
313
454
 
@@ -340,7 +481,7 @@ void Server::purge_single(mc_PACKET *pkt, lcb_error_t err) {
340
481
  hdr.request.opaque,
341
482
  PROTOCOL_BINARY_RESPONSE_EINVAL);
342
483
 
343
- lcb_log(LOGARGS_T(WARN), LOGFMT "Failing command (pkt=%p, opaque=%lu, opcode=0x%x) with error 0x%x", LOGID_T(), (void*)pkt, (unsigned long)pkt->opaque, hdr.request.opcode, err);
484
+ lcb_log(LOGARGS_T(WARN), LOGFMT "Failing command (pkt=%p, opaque=%lu, opcode=0x%x) with error %s", LOGID_T(), (void*)pkt, (unsigned long)pkt->opaque, hdr.request.opcode, lcb_strerror_short(err));
344
485
  int rv = mcreq_dispatch_response(this, pkt, &resp, err);
345
486
  lcb_assert(rv == 0);
346
487
  }
@@ -365,8 +506,7 @@ Server::purge(lcb_error_t error, hrtime_t thresh, hrtime_t *next,
365
506
  }
366
507
 
367
508
  if (affected || policy == REFRESH_ALWAYS) {
368
- lcb_bootstrap_common(instance,
369
- LCB_BS_REFRESH_THROTTLE|LCB_BS_REFRESH_INCRERR);
509
+ instance->bootstrap(BS_REFRESH_THROTTLE|BS_REFRESH_INCRERR);
370
510
  }
371
511
  return affected;
372
512
  }
@@ -420,7 +560,7 @@ void Server::io_timeout()
420
560
  }
421
561
 
422
562
  uint32_t next_us = next_timeout();
423
- lcb_log(LOGARGS_T(DEBUG), LOGFMT "Scheduling next timeout for %u ms", LOGID_T(), next_us / 1000);
563
+ lcb_log(LOGARGS_T(TRACE), LOGFMT "Scheduling next timeout for %u ms. This is not an error", LOGID_T(), next_us / 1000);
424
564
  lcbio_timer_rearm(io_timer, next_us);
425
565
  lcb_maybe_breakout(instance);
426
566
  }
@@ -462,10 +602,10 @@ static void mcserver_flush(Server *s) { s->flush(); }
462
602
  void
463
603
  Server::handle_connected(lcbio_SOCKET *sock, lcb_error_t err, lcbio_OSERR syserr)
464
604
  {
465
- LCBIO_CONNREQ_CLEAR(&connreq);
605
+ connreq = NULL;
466
606
 
467
607
  if (err != LCB_SUCCESS) {
468
- lcb_log(LOGARGS_T(ERR), LOGFMT "Got error for connection! (OS=%d)", LOGID_T(), syserr);
608
+ lcb_log(LOGARGS_T(ERR), LOGFMT "Connection attempt failed. Received %s from libcouchbase, received %d from operating system", LOGID_T(), lcb_strerror_short(err), syserr);
469
609
  if (!maybe_reconnect_on_fake_timeout(err)) {
470
610
  socket_failed(err);
471
611
  }
@@ -478,9 +618,8 @@ Server::handle_connected(lcbio_SOCKET *sock, lcb_error_t err, lcbio_OSERR syserr
478
618
  SessionInfo* sessinfo = SessionInfo::get(sock);
479
619
  if (sessinfo == NULL) {
480
620
  lcb_log(LOGARGS_T(TRACE), "<%s:%s> (SRV=%p) Session not yet negotiated. Negotiating", curhost->host, curhost->port, (void*)this);
481
- SessionRequest *sreq = SessionRequest::start(
621
+ connreq = SessionRequest::start(
482
622
  sock, settings, default_timeout(), on_connected, this);
483
- LCBIO_CONNREQ_MKGENERIC(&connreq, sreq, lcb::sessreq_cancel);
484
623
  return;
485
624
  } else {
486
625
  compsupport = sessinfo->has_feature(PROTOCOL_BINARY_FEATURE_DATATYPE);
@@ -494,10 +633,9 @@ Server::handle_connected(lcbio_SOCKET *sock, lcb_error_t err, lcbio_OSERR syserr
494
633
  procs.cb_flush_ready = on_flush_ready;
495
634
  connctx = lcbio_ctx_new(sock, this, &procs);
496
635
  connctx->subsys = "memcached";
497
- mc_PIPELINE::flush_start = (mcreq_flushstart_fn)mcserver_flush;
636
+ flush_start = (mcreq_flushstart_fn)mcserver_flush;
498
637
 
499
638
  uint32_t tmo = next_timeout();
500
- lcb_log(LOGARGS_T(DEBUG), LOGFMT "Setting initial timeout=%ums", LOGID_T(), tmo/1000);
501
639
  lcbio_timer_rearm(io_timer, tmo);
502
640
  flush();
503
641
  }
@@ -505,10 +643,9 @@ Server::handle_connected(lcbio_SOCKET *sock, lcb_error_t err, lcbio_OSERR syserr
505
643
  void
506
644
  Server::connect()
507
645
  {
508
- lcbio_pMGRREQ mr = lcbio_mgr_get(instance->memd_sockpool, curhost,
646
+ connreq = instance->memd_sockpool->get(*curhost,
509
647
  default_timeout(), on_connected, this);
510
- LCBIO_CONNREQ_MKPOOLED(&connreq, mr);
511
- mc_PIPELINE::flush_start = flush_noop;
648
+ flush_start = flush_noop;
512
649
  state = Server::S_CLEAN;
513
650
  }
514
651
 
@@ -520,7 +657,7 @@ buf_done_cb(mc_PIPELINE *pl, const void *cookie, void *, void *)
520
657
  }
521
658
 
522
659
  Server::Server(lcb_t instance_, int ix)
523
- : state(S_CLEAN),
660
+ : mc_PIPELINE(), state(S_CLEAN),
524
661
  io_timer(lcbio_timer_new(instance_->iotable, this, timeout_server)),
525
662
  instance(instance_),
526
663
  settings(lcb_settings_ref2(instance_->settings)),
@@ -529,11 +666,10 @@ Server::Server(lcb_t instance_, int ix)
529
666
  connctx(NULL),
530
667
  curhost(new lcb_host_t())
531
668
  {
532
- std::memset(static_cast<mc_PIPELINE*>(this), 0, sizeof(mc_PIPELINE));
533
669
  mcreq_pipeline_init(this);
534
- mc_PIPELINE::flush_start = (mcreq_flushstart_fn)server_connect;
535
- mc_PIPELINE::buf_done_callback = buf_done_cb;
536
- mc_PIPELINE::index = ix;
670
+ flush_start = (mcreq_flushstart_fn)server_connect;
671
+ buf_done_callback = buf_done_cb;
672
+ index = ix;
537
673
 
538
674
  std::memset(&connreq, 0, sizeof connreq);
539
675
  std::memset(curhost, 0, sizeof *curhost);
@@ -550,7 +686,7 @@ Server::Server(lcb_t instance_, int ix)
550
686
  Server::Server()
551
687
  : state(S_TEMPORARY),
552
688
  io_timer(NULL), instance(NULL), settings(NULL), compsupport(0),
553
- mutation_tokens(0), connctx(NULL), curhost(NULL)
689
+ mutation_tokens(0), connctx(NULL), connreq(NULL), curhost(NULL)
554
690
  {
555
691
  }
556
692
 
@@ -573,14 +709,14 @@ static void
573
709
  close_cb(lcbio_SOCKET *sock, int, void *)
574
710
  {
575
711
  lcbio_ref(sock);
576
- lcbio_mgr_discard(sock);
712
+ lcb::io::Pool::discard(sock);
577
713
  }
578
714
 
579
715
  static void
580
716
  on_error(lcbio_CTX *ctx, lcb_error_t err)
581
717
  {
582
718
  Server *server = Server::get(ctx);
583
- lcb_log(LOGARGS(server, WARN), LOGFMT "Got socket error 0x%x", LOGID(server), err);
719
+ lcb_log(LOGARGS(server, WARN), LOGFMT "Got socket error %s", LOGID(server), lcb_strerror_short(err));
584
720
  if (server->check_closed()) {
585
721
  return;
586
722
  }
@@ -622,7 +758,7 @@ Server::start_errored_ctx(State next_state)
622
758
 
623
759
  state = next_state;
624
760
  /* Cancel any pending connection attempt? */
625
- lcbio_connreq_cancel(&connreq);
761
+ lcb::io::ConnectionRequest::cancel(&connreq);
626
762
 
627
763
  /* If the server is being destroyed, silence the timer */
628
764
  if (next_state == Server::S_CLOSED && io_timer != NULL) {
@@ -636,13 +772,15 @@ Server::start_errored_ctx(State next_state)
636
772
  return;
637
773
  } else {
638
774
  /* Not closed but don't have a current context */
639
- mc_PIPELINE::flush_start = (mcreq_flushstart_fn)server_connect;
640
775
  if (has_pending()) {
641
776
  if (!lcbio_timer_armed(io_timer)) {
642
777
  /* TODO: Maybe throttle reconnection attempts? */
643
778
  lcbio_timer_rearm(io_timer, default_timeout());
644
779
  }
645
780
  connect();
781
+ } else {
782
+ // Connect once someone actually wants a connection.
783
+ flush_start = (mcreq_flushstart_fn)server_connect;
646
784
  }
647
785
  }
648
786
 
@@ -656,7 +794,7 @@ Server::start_errored_ctx(State next_state)
656
794
  /* Close the socket not to leak resources */
657
795
  lcbio_shutdown(lcbio_ctx_sock(ctx));
658
796
  if (next_state == Server::S_ERRDRAIN) {
659
- mc_PIPELINE::flush_start = (mcreq_flushstart_fn)flush_errdrain;
797
+ flush_start = (mcreq_flushstart_fn)flush_errdrain;
660
798
  }
661
799
  } else {
662
800
  finalize_errored_ctx();
@@ -701,7 +839,6 @@ Server::finalize_errored_ctx()
701
839
  /* Otherwise, cycle the state back to CLEAN and reinit
702
840
  * the connection */
703
841
  state = Server::S_CLEAN;
704
- mc_PIPELINE::flush_start = (mcreq_flushstart_fn)server_connect;
705
842
  connect();
706
843
  }
707
844
  }
@@ -723,8 +860,3 @@ Server::check_closed()
723
860
  finalize_errored_ctx();
724
861
  return 1;
725
862
  }
726
-
727
- int
728
- mcserver_supports_compression(mc_SERVER *server) {
729
- return server->compsupport;
730
- }