libcouchbase 0.0.7 → 0.0.8

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 (133) hide show
  1. checksums.yaml +4 -4
  2. data/ext/libcouchbase/.gitignore +2 -0
  3. data/ext/libcouchbase/CMakeLists.txt +5 -7
  4. data/ext/libcouchbase/README.markdown +2 -2
  5. data/ext/libcouchbase/RELEASE_NOTES.markdown +49 -0
  6. data/ext/libcouchbase/cmake/Modules/ConfigureDtrace.cmake +11 -0
  7. data/ext/libcouchbase/cmake/Modules/GenerateConfigDotH.cmake +2 -0
  8. data/ext/libcouchbase/cmake/Modules/GetLibcouchbaseFlags.cmake +2 -1
  9. data/ext/libcouchbase/cmake/Modules/GetVersionInfo.cmake +3 -3
  10. data/ext/libcouchbase/cmake/config-cmake.h.in +2 -0
  11. data/ext/libcouchbase/cmake/defs.mk.in +0 -2
  12. data/ext/libcouchbase/cmake/source_files.cmake +34 -14
  13. data/ext/libcouchbase/configure.pl +1 -1
  14. data/ext/libcouchbase/contrib/genhash/genhash.h +6 -0
  15. data/ext/libcouchbase/include/libcouchbase/auth.h +10 -0
  16. data/ext/libcouchbase/include/libcouchbase/couchbase.h +10 -0
  17. data/ext/libcouchbase/include/libcouchbase/error.h +7 -0
  18. data/ext/libcouchbase/include/libcouchbase/n1ql.h +13 -1
  19. data/ext/libcouchbase/include/libcouchbase/plugins/io/bsdio-inl.c +1 -1
  20. data/ext/libcouchbase/include/libcouchbase/subdoc.h +9 -0
  21. data/ext/libcouchbase/include/libcouchbase/views.h +7 -1
  22. data/ext/libcouchbase/include/libcouchbase/visibility.h +1 -0
  23. data/ext/libcouchbase/include/memcached/protocol_binary.h +21 -1132
  24. data/ext/libcouchbase/packaging/parse-git-describe.pl +1 -1
  25. data/ext/libcouchbase/plugins/io/libev/libev_io_opts.h +3 -2
  26. data/ext/libcouchbase/src/README.md +0 -2
  27. data/ext/libcouchbase/src/auth-priv.h +1 -0
  28. data/ext/libcouchbase/src/auth.cc +10 -0
  29. data/ext/libcouchbase/src/bootstrap.cc +216 -0
  30. data/ext/libcouchbase/src/bootstrap.h +50 -39
  31. data/ext/libcouchbase/src/bucketconfig/bc_cccp.cc +455 -0
  32. data/ext/libcouchbase/src/bucketconfig/bc_file.cc +281 -0
  33. data/ext/libcouchbase/src/bucketconfig/bc_http.cc +528 -0
  34. data/ext/libcouchbase/src/bucketconfig/bc_http.h +50 -25
  35. data/ext/libcouchbase/src/bucketconfig/bc_mcraw.cc +115 -0
  36. data/ext/libcouchbase/src/bucketconfig/clconfig.h +407 -386
  37. data/ext/libcouchbase/src/bucketconfig/confmon.cc +378 -0
  38. data/ext/libcouchbase/src/cbft.cc +22 -27
  39. data/ext/libcouchbase/src/cntl.cc +24 -24
  40. data/ext/libcouchbase/src/connspec.cc +30 -1
  41. data/ext/libcouchbase/src/connspec.h +17 -0
  42. data/ext/libcouchbase/src/dns-srv.cc +143 -0
  43. data/ext/libcouchbase/src/{dump.c → dump.cc} +8 -11
  44. data/ext/libcouchbase/src/getconfig.cc +73 -0
  45. data/ext/libcouchbase/src/handler.cc +84 -85
  46. data/ext/libcouchbase/src/hostlist.cc +0 -1
  47. data/ext/libcouchbase/src/hostlist.h +6 -1
  48. data/ext/libcouchbase/src/http/http-priv.h +125 -112
  49. data/ext/libcouchbase/src/http/http.cc +9 -29
  50. data/ext/libcouchbase/src/http/http.h +1 -34
  51. data/ext/libcouchbase/src/http/http_io.cc +22 -26
  52. data/ext/libcouchbase/src/instance.cc +102 -28
  53. data/ext/libcouchbase/src/internal.h +47 -29
  54. data/ext/libcouchbase/src/jsparse/parser.cc +146 -202
  55. data/ext/libcouchbase/src/jsparse/parser.h +91 -98
  56. data/ext/libcouchbase/src/lcbht/lcbht.cc +177 -0
  57. data/ext/libcouchbase/src/lcbht/lcbht.h +174 -163
  58. data/ext/libcouchbase/src/lcbio/connect.cc +562 -0
  59. data/ext/libcouchbase/src/lcbio/connect.h +9 -2
  60. data/ext/libcouchbase/src/lcbio/ctx.c +1 -1
  61. data/ext/libcouchbase/src/lcbio/iotable.h +61 -16
  62. data/ext/libcouchbase/src/lcbio/ioutils.h +1 -1
  63. data/ext/libcouchbase/src/lcbio/manager.c +2 -2
  64. data/ext/libcouchbase/src/lcbio/timer-cxx.h +87 -0
  65. data/ext/libcouchbase/src/mc/mcreq.h +9 -2
  66. data/ext/libcouchbase/src/mcserver/mcserver.cc +723 -0
  67. data/ext/libcouchbase/src/mcserver/mcserver.h +160 -70
  68. data/ext/libcouchbase/src/mcserver/negotiate.cc +118 -152
  69. data/ext/libcouchbase/src/mcserver/negotiate.h +85 -74
  70. data/ext/libcouchbase/src/mctx-helper.h +51 -0
  71. data/ext/libcouchbase/src/n1ql/ixmgmt.cc +1 -2
  72. data/ext/libcouchbase/src/n1ql/n1ql.cc +56 -32
  73. data/ext/libcouchbase/src/{newconfig.c → newconfig.cc} +42 -70
  74. data/ext/libcouchbase/src/nodeinfo.cc +4 -8
  75. data/ext/libcouchbase/src/operations/{cbflush.c → cbflush.cc} +7 -15
  76. data/ext/libcouchbase/src/operations/{counter.c → counter.cc} +0 -0
  77. data/ext/libcouchbase/src/operations/{durability-cas.c → durability-cas.cc} +92 -76
  78. data/ext/libcouchbase/src/operations/{durability-seqno.c → durability-seqno.cc} +55 -49
  79. data/ext/libcouchbase/src/operations/durability.cc +643 -0
  80. data/ext/libcouchbase/src/operations/durability_internal.h +212 -124
  81. data/ext/libcouchbase/src/operations/{get.c → get.cc} +24 -26
  82. data/ext/libcouchbase/src/operations/{observe-seqno.c → observe-seqno.cc} +5 -8
  83. data/ext/libcouchbase/src/operations/{observe.c → observe.cc} +69 -94
  84. data/ext/libcouchbase/src/operations/{pktfwd.c → pktfwd.cc} +0 -0
  85. data/ext/libcouchbase/src/operations/{remove.c → remove.cc} +0 -0
  86. data/ext/libcouchbase/src/operations/{stats.c → stats.cc} +66 -78
  87. data/ext/libcouchbase/src/operations/{store.c → store.cc} +27 -32
  88. data/ext/libcouchbase/src/operations/subdoc.cc +38 -18
  89. data/ext/libcouchbase/src/operations/{touch.c → touch.cc} +0 -0
  90. data/ext/libcouchbase/src/packetutils.h +200 -137
  91. data/ext/libcouchbase/src/probes.d +1 -1
  92. data/ext/libcouchbase/src/{retrychk.c → retrychk.cc} +3 -4
  93. data/ext/libcouchbase/src/retryq.cc +394 -0
  94. data/ext/libcouchbase/src/retryq.h +116 -104
  95. data/ext/libcouchbase/src/settings.h +2 -1
  96. data/ext/libcouchbase/src/ssl/ssl_c.c +1 -0
  97. data/ext/libcouchbase/src/ssl/ssl_e.c +0 -1
  98. data/ext/libcouchbase/src/trace.h +8 -8
  99. data/ext/libcouchbase/src/vbucket/vbucket.c +0 -1
  100. data/ext/libcouchbase/src/views/{docreq.c → docreq.cc} +48 -54
  101. data/ext/libcouchbase/src/views/docreq.h +24 -30
  102. data/ext/libcouchbase/src/views/viewreq.cc +318 -0
  103. data/ext/libcouchbase/src/views/viewreq.h +43 -13
  104. data/ext/libcouchbase/src/{wait.c → wait.cc} +12 -17
  105. data/ext/libcouchbase/tests/basic/t_connstr.cc +89 -50
  106. data/ext/libcouchbase/tests/basic/t_jsparse.cc +27 -78
  107. data/ext/libcouchbase/tests/basic/t_packet.cc +35 -42
  108. data/ext/libcouchbase/tests/htparse/t_basic.cc +58 -78
  109. data/ext/libcouchbase/tests/iotests/t_confmon.cc +94 -111
  110. data/ext/libcouchbase/tests/iotests/t_sched.cc +1 -2
  111. data/ext/libcouchbase/tests/mc/t_alloc.cc +9 -9
  112. data/ext/libcouchbase/tools/cbc-pillowfight.cc +1 -1
  113. data/lib/libcouchbase/version.rb +1 -1
  114. metadata +36 -39
  115. data/ext/libcouchbase/include/memcached/vbucket.h +0 -42
  116. data/ext/libcouchbase/src/bootstrap.c +0 -269
  117. data/ext/libcouchbase/src/bucketconfig/bc_cccp.c +0 -495
  118. data/ext/libcouchbase/src/bucketconfig/bc_file.c +0 -347
  119. data/ext/libcouchbase/src/bucketconfig/bc_http.c +0 -630
  120. data/ext/libcouchbase/src/bucketconfig/bc_mcraw.c +0 -150
  121. data/ext/libcouchbase/src/bucketconfig/confmon.c +0 -474
  122. data/ext/libcouchbase/src/getconfig.c +0 -100
  123. data/ext/libcouchbase/src/lcbht/lcbht.c +0 -282
  124. data/ext/libcouchbase/src/lcbio/connect.c +0 -557
  125. data/ext/libcouchbase/src/mcserver/mcserver.c +0 -784
  126. data/ext/libcouchbase/src/operations/durability.c +0 -668
  127. data/ext/libcouchbase/src/packetutils.c +0 -60
  128. data/ext/libcouchbase/src/retryq.c +0 -424
  129. data/ext/libcouchbase/src/simplestring.c +0 -211
  130. data/ext/libcouchbase/src/simplestring.h +0 -228
  131. data/ext/libcouchbase/src/ssobuf.h +0 -82
  132. data/ext/libcouchbase/src/views/viewreq.c +0 -358
  133. data/ext/libcouchbase/tests/basic/t_string.cc +0 -112
@@ -1,42 +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
- #ifndef MEMCACHED_VBUCKET_H
19
- #define MEMCACHED_VBUCKET_H 1
20
-
21
- #ifdef __cplusplus
22
- extern "C"
23
- {
24
- #endif
25
-
26
- typedef enum {
27
- vbucket_state_active = 1, /**< Actively servicing a vbucket. */
28
- vbucket_state_replica, /**< Servicing a vbucket as a replica only. */
29
- vbucket_state_pending, /**< Pending active. */
30
- vbucket_state_dead /**< Not in use, pending deletion. */
31
- } vbucket_state_t;
32
-
33
- #define is_valid_vbucket_state_t(state) \
34
- (state == vbucket_state_active || \
35
- state == vbucket_state_replica || \
36
- state == vbucket_state_pending || \
37
- state == vbucket_state_dead)
38
-
39
- #ifdef __cplusplus
40
- }
41
- #endif
42
- #endif
@@ -1,269 +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
- #define LCB_BOOTSTRAP_DEFINE_STRUCT 1
19
- #include "internal.h"
20
-
21
-
22
- #define LOGARGS(instance, lvl) instance->settings, "bootstrap", LCB_LOG_##lvl, __FILE__, __LINE__
23
-
24
- static void async_step_callback(clconfig_listener*,clconfig_event_t,clconfig_info*);
25
- static void initial_bootstrap_error(lcb_t, lcb_error_t,const char*);
26
-
27
- /**
28
- * This function is where the configuration actually takes place. We ensure
29
- * in other functions that this is only ever called directly from an event
30
- * loop stack frame (or one of the small mini functions here) so that we
31
- * don't accidentally end up destroying resources underneath us.
32
- */
33
- static void
34
- config_callback(clconfig_listener *listener, clconfig_event_t event,
35
- clconfig_info *info)
36
- {
37
- struct lcb_BOOTSTRAP *bs = (struct lcb_BOOTSTRAP *)listener;
38
- lcb_t instance = bs->parent;
39
-
40
- if (event != CLCONFIG_EVENT_GOT_NEW_CONFIG) {
41
- if (event == CLCONFIG_EVENT_PROVIDERS_CYCLED) {
42
- if (!LCBT_VBCONFIG(instance)) {
43
- initial_bootstrap_error(
44
- instance, LCB_ERROR, "No more bootstrap providers remain");
45
- }
46
- }
47
- return;
48
- }
49
-
50
- instance->last_error = LCB_SUCCESS;
51
- /** Ensure we're not called directly twice again */
52
- listener->callback = async_step_callback;
53
- lcbio_timer_disarm(bs->tm);
54
-
55
- lcb_log(LOGARGS(instance, DEBUG), "Instance configured!");
56
-
57
- if (info->origin != LCB_CLCONFIG_FILE) {
58
- /* Set the timestamp for the current config to control throttling,
59
- * but only if it's not an initial file-based config. See CCBC-482 */
60
- bs->last_refresh = gethrtime();
61
- bs->errcounter = 0;
62
- }
63
-
64
- if (info->origin == LCB_CLCONFIG_CCCP) {
65
- /* Disable HTTP provider if we've received something via CCCP */
66
-
67
- if (instance->cur_configinfo == NULL ||
68
- instance->cur_configinfo->origin != LCB_CLCONFIG_HTTP) {
69
- /* Never disable HTTP if it's still being used */
70
- lcb_confmon_set_provider_active(
71
- instance->confmon, LCB_CLCONFIG_HTTP, 0);
72
- }
73
- }
74
-
75
- if (instance->type != LCB_TYPE_CLUSTER) {
76
- lcb_update_vbconfig(instance, info);
77
- }
78
-
79
- if (!bs->bootstrapped) {
80
- bs->bootstrapped = 1;
81
- lcb_aspend_del(&instance->pendops, LCB_PENDTYPE_COUNTER, NULL);
82
-
83
- if (instance->type == LCB_TYPE_BUCKET &&
84
- LCBVB_DISTTYPE(LCBT_VBCONFIG(instance)) == LCBVB_DIST_KETAMA &&
85
- instance->cur_configinfo->origin != LCB_CLCONFIG_MCRAW) {
86
-
87
- lcb_log(LOGARGS(instance, INFO), "Reverting to HTTP Config for memcached buckets");
88
- instance->settings->bc_http_stream_time = -1;
89
- lcb_confmon_set_provider_active(
90
- instance->confmon, LCB_CLCONFIG_HTTP, 1);
91
- lcb_confmon_set_provider_active(
92
- instance->confmon, LCB_CLCONFIG_CCCP, 0);
93
- }
94
- instance->callbacks.bootstrap(instance, LCB_SUCCESS);
95
- }
96
-
97
- lcb_maybe_breakout(instance);
98
- }
99
-
100
-
101
- static void
102
- initial_bootstrap_error(lcb_t instance, lcb_error_t err, const char *errinfo)
103
- {
104
- struct lcb_BOOTSTRAP *bs = instance->bootstrap;
105
-
106
- instance->last_error = lcb_confmon_last_error(instance->confmon);
107
- if (instance->last_error == LCB_SUCCESS) {
108
- instance->last_error = err;
109
- }
110
- instance->callbacks.error(instance, instance->last_error, errinfo);
111
- lcb_log(LOGARGS(instance, ERR), "Failed to bootstrap client=%p. Code=0x%x, Message=%s", (void *)instance, err, errinfo);
112
- lcbio_timer_disarm(bs->tm);
113
-
114
- instance->callbacks.bootstrap(instance, instance->last_error);
115
-
116
- lcb_aspend_del(&instance->pendops, LCB_PENDTYPE_COUNTER, NULL);
117
- lcb_maybe_breakout(instance);
118
- }
119
-
120
- /**
121
- * This it the initial bootstrap timeout handler. This timeout pins down the
122
- * instance. It is only scheduled during the initial bootstrap and is only
123
- * triggered if the initial bootstrap fails to configure in time.
124
- */
125
- static void initial_timeout(void *arg)
126
- {
127
- struct lcb_BOOTSTRAP *bs = arg;
128
- initial_bootstrap_error(bs->parent, LCB_ETIMEDOUT, "Failed to bootstrap in time");
129
- }
130
-
131
- /**
132
- * Proxy async call to config_callback
133
- */
134
- static void async_refresh(void *arg)
135
- {
136
- /** Get the best configuration and run stuff.. */
137
- struct lcb_BOOTSTRAP *bs = arg;
138
- clconfig_info *info;
139
-
140
- info = lcb_confmon_get_config(bs->parent->confmon);
141
- config_callback(&bs->listener, CLCONFIG_EVENT_GOT_NEW_CONFIG, info);
142
- }
143
-
144
- /**
145
- * set_next listener callback which schedules an async call to our config
146
- * callback.
147
- */
148
- static void
149
- async_step_callback(clconfig_listener *listener, clconfig_event_t event,
150
- clconfig_info *info)
151
- {
152
- struct lcb_BOOTSTRAP *bs = (struct lcb_BOOTSTRAP *)listener;
153
-
154
- if (event != CLCONFIG_EVENT_GOT_NEW_CONFIG) {
155
- return;
156
- }
157
-
158
- if (lcbio_timer_armed(bs->tm) && lcbio_timer_get_target(bs->tm) == async_refresh) {
159
- lcb_log(LOGARGS(bs->parent, DEBUG), "Timer already present..");
160
- return;
161
- }
162
-
163
- lcb_log(LOGARGS(bs->parent, INFO), "Got async step callback..");
164
- lcbio_timer_set_target(bs->tm, async_refresh);
165
- lcbio_async_signal(bs->tm);
166
- (void)info;
167
- }
168
-
169
- lcb_error_t
170
- lcb_bootstrap_common(lcb_t instance, int options)
171
- {
172
- struct lcb_BOOTSTRAP *bs = instance->bootstrap;
173
- hrtime_t now = gethrtime();
174
-
175
- if (!bs) {
176
- bs = calloc(1, sizeof(*instance->bootstrap));
177
- if (!bs) {
178
- return LCB_CLIENT_ENOMEM;
179
- }
180
-
181
- bs->tm = lcbio_timer_new(instance->iotable, bs, initial_timeout);
182
- instance->bootstrap = bs;
183
- bs->parent = instance;
184
- lcb_confmon_add_listener(instance->confmon, &bs->listener);
185
- }
186
-
187
- if (lcb_confmon_is_refreshing(instance->confmon)) {
188
- return LCB_SUCCESS;
189
- }
190
-
191
- if (options & LCB_BS_REFRESH_THROTTLE) {
192
- /* Refresh throttle requested. This is not true if options == ALWAYS */
193
- hrtime_t next_ts;
194
- unsigned errthresh = LCBT_SETTING(instance, weird_things_threshold);
195
-
196
- if (options & LCB_BS_REFRESH_INCRERR) {
197
- bs->errcounter++;
198
- }
199
- next_ts = bs->last_refresh;
200
- next_ts += LCB_US2NS(LCBT_SETTING(instance, weird_things_delay));
201
- if (now < next_ts && bs->errcounter < errthresh) {
202
- lcb_log(LOGARGS(instance, INFO),
203
- "Not requesting a config refresh because of throttling parameters. Next refresh possible in %ums or %u errors. "
204
- "See LCB_CNTL_CONFDELAY_THRESH and LCB_CNTL_CONFERRTHRESH to modify the throttling settings",
205
- LCB_NS2US(next_ts-now)/1000, (unsigned)errthresh-bs->errcounter);
206
- return LCB_SUCCESS;
207
- }
208
- }
209
-
210
- if (options == LCB_BS_REFRESH_INITIAL) {
211
- lcb_confmon_prepare(instance->confmon);
212
-
213
- bs->listener.callback = config_callback;
214
- lcbio_timer_set_target(bs->tm, initial_timeout);
215
- lcbio_timer_rearm(bs->tm, LCBT_SETTING(instance, config_timeout));
216
- lcb_aspend_add(&instance->pendops, LCB_PENDTYPE_COUNTER, NULL);
217
- } else {
218
- /** No initial timer */
219
- bs->listener.callback = async_step_callback;
220
- }
221
-
222
- /* Reset the counters */
223
- bs->errcounter = 0;
224
- if (options != LCB_BS_REFRESH_INITIAL) {
225
- bs->last_refresh = now;
226
- }
227
- return lcb_confmon_start(instance->confmon);
228
- }
229
-
230
- void lcb_bootstrap_destroy(lcb_t instance)
231
- {
232
- struct lcb_BOOTSTRAP *bs = instance->bootstrap;
233
- if (!bs) {
234
- return;
235
- }
236
- if (bs->tm) {
237
- lcbio_timer_destroy(bs->tm);
238
- }
239
-
240
- lcb_confmon_remove_listener(instance->confmon, &bs->listener);
241
- free(bs);
242
- instance->bootstrap = NULL;
243
- }
244
-
245
- LIBCOUCHBASE_API
246
- lcb_error_t
247
- lcb_get_bootstrap_status(lcb_t instance)
248
- {
249
- if (instance->cur_configinfo) {
250
- return LCB_SUCCESS;
251
- }
252
- if (instance->last_error != LCB_SUCCESS) {
253
- return instance->last_error;
254
- }
255
- if (instance->type == LCB_TYPE_CLUSTER) {
256
- lcbio_SOCKET *restconn = lcb_confmon_get_rest_connection(instance->confmon);
257
- if (restconn) {
258
- return LCB_SUCCESS;
259
- }
260
- }
261
- return LCB_ERROR;
262
- }
263
-
264
- LIBCOUCHBASE_API
265
- void
266
- lcb_refresh_config(lcb_t instance)
267
- {
268
- lcb_bootstrap_common(instance, LCB_BS_REFRESH_ALWAYS);
269
- }
@@ -1,495 +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
- /**
19
- * This file contains the CCCP (Cluster Carrier Configuration Protocol)
20
- * implementation of the confmon provider. It utilizes a memcached connection
21
- * to retrieve configuration information.
22
- */
23
-
24
- #include "internal.h"
25
- #include "clconfig.h"
26
- #include "packetutils.h"
27
- #include "simplestring.h"
28
- #include <mcserver/negotiate.h>
29
- #include <lcbio/lcbio.h>
30
- #include <lcbio/timer-ng.h>
31
- #include <lcbio/ssl.h>
32
- #include "ctx-log-inl.h"
33
- #define LOGARGS(cccp, lvl) cccp->base.parent->settings, "cccp", LCB_LOG_##lvl, __FILE__, __LINE__
34
- #define LOGFMT "<%s:%s> "
35
- #define LOGID(cccp) get_ctx_host(cccp->ioctx), get_ctx_port(cccp->ioctx)
36
-
37
- struct cccp_cookie_st;
38
-
39
- typedef struct {
40
- clconfig_provider base;
41
- hostlist_t nodes;
42
- clconfig_info *config;
43
- int server_active;
44
- int disabled;
45
- lcbio_pTIMER timer;
46
- lcb_t instance;
47
- lcbio_CONNREQ creq;
48
- lcbio_CTX *ioctx;
49
- struct cccp_cookie_st *cmdcookie;
50
- } cccp_provider;
51
-
52
- typedef struct cccp_cookie_st {
53
- /** Parent object */
54
- cccp_provider *parent;
55
-
56
- /** Whether to ignore errors on this cookie object */
57
- int ignore_errors;
58
- } cccp_cookie;
59
-
60
- static void io_error_handler(lcbio_CTX *, lcb_error_t);
61
- static void io_read_handler(lcbio_CTX *, unsigned nr);
62
- static void request_config(cccp_provider *);
63
- static void on_connected(lcbio_SOCKET *, void*, lcb_error_t, lcbio_OSERR);
64
-
65
- static void
66
- pooled_close_cb(lcbio_SOCKET *sock, int reusable, void *arg)
67
- {
68
- int *ru_ex = arg;
69
- lcbio_ref(sock);
70
- if (reusable && *ru_ex) {
71
- lcbio_mgr_put(sock);
72
- } else {
73
- lcbio_mgr_discard(sock);
74
- }
75
- }
76
-
77
- static void release_socket(cccp_provider *cccp, int can_reuse)
78
- {
79
- if (cccp->cmdcookie) {
80
- cccp->cmdcookie->ignore_errors = 1;
81
- cccp->cmdcookie = NULL;
82
- return;
83
- }
84
-
85
- lcbio_connreq_cancel(&cccp->creq);
86
-
87
- if (cccp->ioctx) {
88
- lcbio_ctx_close(cccp->ioctx, pooled_close_cb, &can_reuse);
89
- cccp->ioctx = NULL;
90
- }
91
- }
92
-
93
- static lcb_error_t
94
- schedule_next_request(cccp_provider *cccp, lcb_error_t err, int can_rollover)
95
- {
96
- mc_SERVER *server;
97
- lcb_host_t *next_host = hostlist_shift_next(cccp->nodes, can_rollover);
98
- if (!next_host) {
99
- lcbio_timer_disarm(cccp->timer);
100
- lcb_confmon_provider_failed(&cccp->base, err);
101
- cccp->server_active = 0;
102
- return err;
103
- }
104
-
105
- server = lcb_find_server_by_host(cccp->instance, next_host);
106
- if (server) {
107
- cccp_cookie *cookie = calloc(1, sizeof(*cookie));
108
- cccp->cmdcookie = cookie;
109
- cookie->parent = cccp;
110
- lcb_log(LOGARGS(cccp, INFO), "Re-Issuing CCCP Command on server struct %p (%s:%s)", (void*)server, next_host->host, next_host->port);
111
- lcbio_timer_rearm(
112
- cccp->timer, PROVIDER_SETTING(&cccp->base, config_node_timeout));
113
- return lcb_getconfig(cccp->instance, cookie, server);
114
-
115
- } else {
116
- lcbio_pMGRREQ preq;
117
-
118
- lcb_log(LOGARGS(cccp, INFO), "Requesting connection to node %s:%s for CCCP configuration", next_host->host, next_host->port);
119
- preq = lcbio_mgr_get(
120
- cccp->instance->memd_sockpool, next_host,
121
- PROVIDER_SETTING(&cccp->base, config_node_timeout),
122
- on_connected, cccp);
123
- LCBIO_CONNREQ_MKPOOLED(&cccp->creq, preq);
124
- }
125
-
126
- cccp->server_active = 1;
127
- return LCB_SUCCESS;
128
- }
129
-
130
- static lcb_error_t mcio_error(cccp_provider *cccp, lcb_error_t err)
131
- {
132
- if (err != LCB_NOT_SUPPORTED && err != LCB_UNKNOWN_COMMAND) {
133
- lcb_log(LOGARGS(cccp, ERR), LOGFMT "Got I/O Error=0x%x", LOGID(cccp), err);
134
- }
135
-
136
- release_socket(cccp, err == LCB_NOT_SUPPORTED);
137
- return schedule_next_request(cccp, err, 0);
138
- }
139
-
140
- static void socket_timeout(void *arg)
141
- {
142
- cccp_provider *cccp = arg;
143
- mcio_error(cccp, LCB_ETIMEDOUT);
144
- }
145
-
146
- void lcb_clconfig_cccp_enable(clconfig_provider *pb, lcb_t instance)
147
- {
148
- cccp_provider *cccp = (cccp_provider *)pb;
149
- lcb_assert(pb->type == LCB_CLCONFIG_CCCP);
150
- cccp->instance = instance;
151
- pb->enabled = 1;
152
- }
153
-
154
- static hostlist_t get_nodes(const clconfig_provider *pb)
155
- {
156
- return ((cccp_provider *)pb)->nodes;
157
- }
158
-
159
- /** Update the configuration from a server. */
160
- lcb_error_t lcb_cccp_update(clconfig_provider *provider,
161
- const char *host,
162
- lcb_string *data)
163
- {
164
- /** TODO: replace this with lcbvb_ names */
165
-
166
- lcbvb_CONFIG* vbc;
167
- int rv;
168
- clconfig_info *new_config;
169
- cccp_provider *cccp = (cccp_provider *)provider;
170
- vbc = lcbvb_create();
171
-
172
- if (!vbc) {
173
- return LCB_CLIENT_ENOMEM;
174
- }
175
- rv = lcbvb_load_json(vbc, data->base);
176
-
177
- if (rv) {
178
- lcb_log(LOGARGS(cccp, ERROR), LOGFMT "Failed to parse config", LOGID(cccp));
179
- lcb_log_badconfig(LOGARGS(cccp, ERROR), vbc, data->base);
180
- lcbvb_destroy(vbc);
181
- return LCB_PROTOCOL_ERROR;
182
- }
183
-
184
- lcbvb_replace_host(vbc, host);
185
- new_config = lcb_clconfig_create(vbc, LCB_CLCONFIG_CCCP);
186
-
187
- if (!new_config) {
188
- lcbvb_destroy(vbc);
189
- return LCB_CLIENT_ENOMEM;
190
- }
191
-
192
- if (cccp->config) {
193
- lcb_clconfig_decref(cccp->config);
194
- }
195
-
196
- /** TODO: Figure out the comparison vector */
197
- new_config->cmpclock = gethrtime();
198
- cccp->config = new_config;
199
- lcb_confmon_provider_success(provider, new_config);
200
- return LCB_SUCCESS;
201
- }
202
-
203
- void lcb_cccp_update2(const void *cookie, lcb_error_t err,
204
- const void *bytes, lcb_size_t nbytes,
205
- const lcb_host_t *origin)
206
- {
207
- cccp_cookie *ck = (cccp_cookie *)cookie;
208
- cccp_provider *cccp = ck->parent;
209
-
210
- if (ck == cccp->cmdcookie) {
211
- lcbio_timer_disarm(cccp->timer);
212
- cccp->cmdcookie = NULL;
213
- }
214
-
215
- if (err == LCB_SUCCESS) {
216
- lcb_string ss;
217
-
218
- lcb_string_init(&ss);
219
- lcb_string_append(&ss, bytes, nbytes);
220
- err = lcb_cccp_update(&cccp->base, origin->host, &ss);
221
- lcb_string_release(&ss);
222
- }
223
-
224
- if (err != LCB_SUCCESS && ck->ignore_errors == 0) {
225
- mcio_error(cccp, err);
226
- }
227
-
228
- free(ck);
229
- }
230
-
231
- static void
232
- on_connected(lcbio_SOCKET *sock, void *data, lcb_error_t err, lcbio_OSERR syserr)
233
- {
234
- lcbio_CTXPROCS ioprocs;
235
- cccp_provider *cccp = data;
236
- lcb_settings *settings = cccp->base.parent->settings;
237
-
238
- LCBIO_CONNREQ_CLEAR(&cccp->creq);
239
- if (err != LCB_SUCCESS) {
240
- if (sock) {
241
- lcbio_mgr_discard(sock);
242
- }
243
- mcio_error(cccp, err);
244
- return;
245
- }
246
-
247
- if (lcbio_protoctx_get(sock, LCBIO_PROTOCTX_SESSINFO) == NULL) {
248
- mc_pSESSREQ sreq;
249
- sreq = mc_sessreq_start(
250
- sock, settings, settings->config_node_timeout, on_connected,
251
- cccp);
252
- LCBIO_CONNREQ_MKGENERIC(&cccp->creq, sreq, mc_sessreq_cancel);
253
- return;
254
- }
255
-
256
- ioprocs.cb_err = io_error_handler;
257
- ioprocs.cb_read = io_read_handler;
258
- cccp->ioctx = lcbio_ctx_new(sock, data, &ioprocs);
259
- cccp->ioctx->subsys = "bc_cccp";
260
- request_config(cccp);
261
-
262
- (void)syserr;
263
- }
264
-
265
- static lcb_error_t cccp_get(clconfig_provider *pb)
266
- {
267
- cccp_provider *cccp = (cccp_provider *)pb;
268
- if (cccp->creq.u.p_generic || cccp->server_active || cccp->cmdcookie) {
269
- return LCB_BUSY;
270
- }
271
-
272
- return schedule_next_request(cccp, LCB_SUCCESS, 1);
273
- }
274
-
275
- static clconfig_info *cccp_get_cached(clconfig_provider *pb)
276
- {
277
- cccp_provider *cccp = (cccp_provider *)pb;
278
- return cccp->config;
279
- }
280
-
281
- static lcb_error_t cccp_pause(clconfig_provider *pb)
282
- {
283
- cccp_provider *cccp = (cccp_provider *)pb;
284
- if (!cccp->server_active) {
285
- return LCB_SUCCESS;
286
- }
287
-
288
- cccp->server_active = 0;
289
- release_socket(cccp, 0);
290
- lcbio_timer_disarm(cccp->timer);
291
- return LCB_SUCCESS;
292
- }
293
-
294
- static void cccp_cleanup(clconfig_provider *pb)
295
- {
296
- cccp_provider *cccp = (cccp_provider *)pb;
297
-
298
- release_socket(cccp, 0);
299
- if (cccp->config) {
300
- lcb_clconfig_decref(cccp->config);
301
- }
302
- if (cccp->nodes) {
303
- hostlist_destroy(cccp->nodes);
304
- }
305
- if (cccp->timer) {
306
- lcbio_timer_destroy(cccp->timer);
307
- }
308
- if (cccp->cmdcookie) {
309
- cccp->cmdcookie->ignore_errors = 1;
310
- }
311
- free(cccp);
312
- }
313
-
314
- static void
315
- configure_nodes(clconfig_provider *pb, const hostlist_t nodes)
316
- {
317
- cccp_provider *cccp = (cccp_provider *)pb;
318
- hostlist_assign(cccp->nodes, nodes);
319
- if (PROVIDER_SETTING(pb, randomize_bootstrap_nodes)) {
320
- hostlist_randomize(cccp->nodes);
321
- }
322
- }
323
-
324
- static void
325
- config_updated(clconfig_provider *provider, lcbvb_CONFIG* vbc)
326
- {
327
- unsigned ii;
328
- lcbvb_SVCMODE mode;
329
- cccp_provider *cccp = (cccp_provider *)provider;
330
- if (LCBVB_NSERVERS(vbc) < 1) {
331
- return;
332
- }
333
-
334
- hostlist_clear(cccp->nodes);
335
- if (PROVIDER_SETTING(provider, sslopts) & LCB_SSL_ENABLED) {
336
- mode = LCBVB_SVCMODE_SSL;
337
- } else {
338
- mode = LCBVB_SVCMODE_PLAIN;
339
- }
340
- for (ii = 0; ii < LCBVB_NSERVERS(vbc); ii++) {
341
- const char *mcaddr = lcbvb_get_hostport(vbc,
342
- ii, LCBVB_SVCTYPE_DATA, mode);
343
- if (!mcaddr) {
344
- lcb_log(LOGARGS(cccp, DEBUG), "Node %d has no data service", ii);
345
- continue;
346
- }
347
- hostlist_add_stringz(cccp->nodes, mcaddr, LCB_CONFIG_MCD_PORT);
348
- }
349
-
350
- if (PROVIDER_SETTING(provider, randomize_bootstrap_nodes)) {
351
- hostlist_randomize(cccp->nodes);
352
- }
353
- }
354
-
355
- static void
356
- io_error_handler(lcbio_CTX *ctx, lcb_error_t err)
357
- {
358
- cccp_provider *cccp = lcbio_ctx_data(ctx);
359
- mcio_error(cccp, err);
360
- }
361
-
362
- static void
363
- io_read_handler(lcbio_CTX *ioctx, unsigned nr)
364
- {
365
- packet_info pi;
366
- cccp_provider *cccp = lcbio_ctx_data(ioctx);
367
- lcb_string jsonstr;
368
- lcb_error_t err;
369
- int rv;
370
- unsigned required;
371
- lcb_host_t curhost;
372
-
373
- (void)nr;
374
-
375
- #define return_error(e) \
376
- lcb_pktinfo_ectx_done(&pi, ioctx); \
377
- mcio_error(cccp, e); \
378
- return
379
-
380
- memset(&pi, 0, sizeof(pi));
381
- rv = lcb_pktinfo_ectx_get(&pi, ioctx, &required);
382
- if (!rv) {
383
- lcbio_ctx_rwant(ioctx, required);
384
- lcbio_ctx_schedule(ioctx);
385
- return;
386
- }
387
-
388
- if (PACKET_STATUS(&pi) != PROTOCOL_BINARY_RESPONSE_SUCCESS) {
389
- lcb_log(LOGARGS(cccp, WARN), LOGFMT "CCCP Packet responded with 0x%x; nkey=%d, nbytes=%lu, cmd=0x%x, seq=0x%x", LOGID(cccp),
390
- PACKET_STATUS(&pi), PACKET_NKEY(&pi), (unsigned long)PACKET_NBODY(&pi),
391
- PACKET_OPCODE(&pi), PACKET_OPAQUE(&pi));
392
-
393
- switch (PACKET_STATUS(&pi)) {
394
- case PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED:
395
- case PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND:
396
- return_error(LCB_NOT_SUPPORTED);
397
- default:
398
- return_error(LCB_PROTOCOL_ERROR);
399
- }
400
-
401
- return;
402
- }
403
-
404
- if (!PACKET_NBODY(&pi)) {
405
- return_error(LCB_PROTOCOL_ERROR);
406
- }
407
-
408
- if (lcb_string_init(&jsonstr)) {
409
- return_error(LCB_CLIENT_ENOMEM);
410
- }
411
-
412
- if (lcb_string_append(&jsonstr, PACKET_BODY(&pi), PACKET_NBODY(&pi))) {
413
- return_error(LCB_CLIENT_ENOMEM);
414
- }
415
-
416
- curhost = *lcbio_get_host(lcbio_ctx_sock(ioctx));
417
- lcb_pktinfo_ectx_done(&pi, ioctx);
418
- release_socket(cccp, 1);
419
-
420
- err = lcb_cccp_update(&cccp->base, curhost.host, &jsonstr);
421
- lcb_string_release(&jsonstr);
422
- if (err == LCB_SUCCESS) {
423
- lcbio_timer_disarm(cccp->timer);
424
- cccp->server_active = 0;
425
- } else {
426
- schedule_next_request(cccp, LCB_PROTOCOL_ERROR, 0);
427
- }
428
-
429
- #undef return_error
430
- }
431
-
432
- static void request_config(cccp_provider *cccp)
433
- {
434
- protocol_binary_request_set_cluster_config req;
435
- memset(&req, 0, sizeof(req));
436
- req.message.header.request.magic = PROTOCOL_BINARY_REQ;
437
- req.message.header.request.opcode = PROTOCOL_BINARY_CMD_GET_CLUSTER_CONFIG;
438
- req.message.header.request.opaque = 0xF00D;
439
- lcbio_ctx_put(cccp->ioctx, req.bytes, sizeof(req.bytes));
440
- lcbio_ctx_rwant(cccp->ioctx, 24);
441
- lcbio_ctx_schedule(cccp->ioctx);
442
- lcbio_timer_rearm(cccp->timer, PROVIDER_SETTING(&cccp->base, config_node_timeout));
443
- }
444
-
445
- static void do_dump(clconfig_provider *pb, FILE *fp)
446
- {
447
- cccp_provider *cccp = (cccp_provider *)pb;
448
- unsigned ii;
449
-
450
- if (!cccp->base.enabled) {
451
- return;
452
- }
453
-
454
- fprintf(fp, "## BEGIN CCCP PROVIDER DUMP ##\n");
455
- fprintf(fp, "TIMER ACTIVE: %s\n", lcbio_timer_armed(cccp->timer) ? "YES" : "NO");
456
- fprintf(fp, "PIPELINE RESPONSE COOKIE: %p\n", (void*)cccp->cmdcookie);
457
- if (cccp->ioctx) {
458
- fprintf(fp, "CCCP Owns connection:\n");
459
- lcbio_ctx_dump(cccp->ioctx, fp);
460
- } else if (cccp->creq.u.p_generic) {
461
- fprintf(fp, "CCCP Is connecting\n");
462
- } else {
463
- fprintf(fp, "CCCP does not have a dedicated connection\n");
464
- }
465
-
466
- for (ii = 0; ii < hostlist_size(cccp->nodes); ii++) {
467
- const lcb_host_t *curhost = hostlist_get(cccp->nodes, ii);
468
- fprintf(fp, "CCCP NODE: %s:%s\n", curhost->host, curhost->port);
469
- }
470
- fprintf(fp, "## END CCCP PROVIDER DUMP ##\n");
471
- }
472
-
473
- clconfig_provider * lcb_clconfig_create_cccp(lcb_confmon *mon)
474
- {
475
- cccp_provider *cccp = calloc(1, sizeof(*cccp));
476
- cccp->nodes = hostlist_create();
477
- cccp->base.type = LCB_CLCONFIG_CCCP;
478
- cccp->base.refresh = cccp_get;
479
- cccp->base.get_cached = cccp_get_cached;
480
- cccp->base.pause = cccp_pause;
481
- cccp->base.shutdown = cccp_cleanup;
482
- cccp->base.config_updated = config_updated;
483
- cccp->base.configure_nodes = configure_nodes;
484
- cccp->base.get_nodes = get_nodes;
485
- cccp->base.dump = do_dump;
486
- cccp->base.parent = mon;
487
- cccp->base.enabled = 0;
488
- cccp->timer = lcbio_timer_new(mon->iot, cccp, socket_timeout);
489
-
490
- if (!cccp->nodes) {
491
- free(cccp);
492
- return NULL;
493
- }
494
- return &cccp->base;
495
- }