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
@@ -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
- }