libcouchbase 0.0.7 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
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,347 +0,0 @@
1
- /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
- /*
3
- * Copyright 2013 Couchbase, Inc.
4
- *
5
- * Licensed under the Apache License, Version 2.0 (the "License");
6
- * you may not use this file except in compliance with the License.
7
- * You may obtain a copy of the License at
8
- *
9
- * http://www.apache.org/licenses/LICENSE-2.0
10
- *
11
- * Unless required by applicable law or agreed to in writing, software
12
- * distributed under the License is distributed on an "AS IS" BASIS,
13
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
- * See the License for the specific language governing permissions and
15
- * limitations under the License.
16
- */
17
-
18
- #include "internal.h"
19
- #include "clconfig.h"
20
- #include "simplestring.h"
21
- #include <lcbio/lcbio.h>
22
- #include <lcbio/timer-ng.h>
23
-
24
- #define CONFIG_CACHE_MAGIC "{{{fb85b563d0a8f65fa8d3d58f1b3a0708}}}"
25
-
26
- #define LOGARGS(pb, lvl) pb->base.parent->settings, "bc_file", LCB_LOG_##lvl, __FILE__, __LINE__
27
- #define LOGFMT "(cache=%s) "
28
- #define LOGID(fb) fb->filename
29
-
30
- typedef struct {
31
- clconfig_provider base;
32
- char *filename;
33
- clconfig_info *config;
34
- time_t last_mtime;
35
- int last_errno;
36
- int ro_mode; /* Whether the config cache should _not_ overwrite the file */
37
- lcbio_pTIMER timer;
38
- clconfig_listener listener;
39
- } file_provider;
40
-
41
- static int load_cache(file_provider *provider)
42
- {
43
- lcb_string str;
44
- char line[1024];
45
- lcb_ssize_t nr;
46
- int fail;
47
- FILE *fp = NULL;
48
- lcbvb_CONFIG *config = NULL;
49
- char *end;
50
- struct stat st;
51
- int status = -1;
52
-
53
- lcb_string_init(&str);
54
-
55
- if (provider->filename == NULL) {
56
- return -1;
57
- }
58
-
59
- fp = fopen(provider->filename, "r");
60
- if (fp == NULL) {
61
- int save_errno = errno;
62
- lcb_log(LOGARGS(provider, ERROR), LOGFMT "Couldn't open for reading: %s", LOGID(provider), strerror(save_errno));
63
- return -1;
64
- }
65
-
66
- if (fstat(fileno(fp), &st)) {
67
- provider->last_errno = errno;
68
- goto GT_DONE;
69
- }
70
-
71
- if (provider->last_mtime == st.st_mtime) {
72
- lcb_log(LOGARGS(provider, WARN), LOGFMT "Modification time too old", LOGID(provider));
73
- goto GT_DONE;
74
- }
75
-
76
- config = lcbvb_create();
77
- if (config == NULL) {
78
- goto GT_DONE;
79
- }
80
-
81
- lcb_string_init(&str);
82
-
83
- while ((nr = fread(line, 1, sizeof(line), fp)) > 0) {
84
- if (lcb_string_append(&str, line, nr)) {
85
- goto GT_DONE;
86
- }
87
- }
88
-
89
- if (ferror(fp)) {
90
- goto GT_DONE;
91
- }
92
-
93
- fclose(fp);
94
- fp = NULL;
95
-
96
- if (!str.nused) {
97
- status = -1;
98
- goto GT_DONE;
99
- }
100
-
101
- end = strstr(str.base, CONFIG_CACHE_MAGIC);
102
- if (end == NULL) {
103
- lcb_log(LOGARGS(provider, ERROR), LOGFMT "Couldn't find magic", LOGID(provider));
104
- if (!provider->ro_mode) {
105
- remove(provider->filename);
106
- }
107
- status = -1;
108
- goto GT_DONE;
109
- }
110
-
111
- fail = lcbvb_load_json(config, str.base);
112
- if (fail) {
113
- status = -1;
114
- lcb_log(LOGARGS(provider, ERROR), LOGFMT "Couldn't parse configuration", LOGID(provider));
115
- lcb_log_badconfig(LOGARGS(provider, ERROR), config, str.base);
116
- if (!provider->ro_mode) {
117
- remove(provider->filename);
118
- }
119
- goto GT_DONE;
120
- }
121
-
122
- if (lcbvb_get_distmode(config) != LCBVB_DIST_VBUCKET) {
123
- status = -1;
124
- lcb_log(LOGARGS(provider, ERROR), LOGFMT "Not applying cached memcached config", LOGID(provider));
125
- goto GT_DONE;
126
- }
127
-
128
- if (strcmp(config->bname, PROVIDER_SETTING(&provider->base, bucket)) != 0) {
129
- status = -1;
130
- lcb_log(LOGARGS(provider, ERROR), LOGFMT "Bucket name in file is different from the one requested", LOGID(provider));
131
- }
132
-
133
- if (provider->config) {
134
- lcb_clconfig_decref(provider->config);
135
- }
136
-
137
- provider->config = lcb_clconfig_create(config, LCB_CLCONFIG_FILE);
138
- provider->config->cmpclock = gethrtime();
139
- provider->config->origin = provider->base.type;
140
- provider->last_mtime = st.st_mtime;
141
- status = 0;
142
- config = NULL;
143
-
144
- GT_DONE:
145
- if (fp != NULL) {
146
- fclose(fp);
147
- }
148
-
149
- if (config != NULL) {
150
- lcbvb_destroy(config);
151
- }
152
-
153
- lcb_string_release(&str);
154
- return status;
155
- }
156
-
157
- static void
158
- write_to_file(file_provider *provider, lcbvb_CONFIG *cfg)
159
- {
160
- FILE *fp;
161
-
162
- if (provider->filename == NULL || provider->ro_mode) {
163
- return;
164
- }
165
-
166
- fp = fopen(provider->filename, "w");
167
- if (fp) {
168
- char *json = lcbvb_save_json(cfg);
169
- lcb_log(LOGARGS(provider, INFO), LOGFMT "Writing configuration to file", LOGID(provider));
170
- fprintf(fp, "%s%s", json, CONFIG_CACHE_MAGIC);
171
- fclose(fp);
172
- free(json);
173
- } else {
174
- int save_errno = errno;
175
- lcb_log(LOGARGS(provider, ERROR), LOGFMT "Couldn't open file for writing: %s", LOGID(provider), strerror(save_errno));
176
- }
177
- }
178
-
179
- static clconfig_info * get_cached(clconfig_provider *pb)
180
- {
181
- file_provider *provider = (file_provider *)pb;
182
- if (!provider->filename) {
183
- return NULL;
184
- }
185
-
186
- return provider->config;
187
- }
188
-
189
- static void async_callback(void *cookie)
190
- {
191
- time_t last_mtime;
192
- file_provider *provider = (file_provider *)cookie;
193
- last_mtime = provider->last_mtime;
194
- if (load_cache(provider) == 0) {
195
- if (last_mtime != provider->last_mtime) {
196
- lcb_confmon_provider_success(&provider->base, provider->config);
197
- return;
198
- }
199
- }
200
-
201
- lcb_confmon_provider_failed(&provider->base, LCB_ERROR);
202
- }
203
-
204
- static lcb_error_t refresh_file(clconfig_provider *pb)
205
- {
206
- file_provider *provider = (file_provider *)pb;
207
- if (lcbio_timer_armed(provider->timer)) {
208
- return LCB_SUCCESS;
209
- }
210
-
211
- lcbio_async_signal(provider->timer);
212
- return LCB_SUCCESS;
213
- }
214
-
215
- static lcb_error_t pause_file(clconfig_provider *pb)
216
- {
217
- (void)pb;
218
- return LCB_SUCCESS;
219
- }
220
-
221
- static void shutdown_file(clconfig_provider *pb)
222
- {
223
- file_provider *provider = (file_provider *)pb;
224
- free(provider->filename);
225
- if (provider->timer) {
226
- lcbio_timer_destroy(provider->timer);
227
- }
228
- if (provider->config) {
229
- lcb_clconfig_decref(provider->config);
230
- }
231
- free(provider);
232
- }
233
-
234
- static void config_listener(clconfig_listener *lsn, clconfig_event_t event,
235
- clconfig_info *info)
236
- {
237
- file_provider *provider;
238
-
239
- if (event != CLCONFIG_EVENT_GOT_NEW_CONFIG) {
240
- return;
241
- }
242
-
243
- provider = (file_provider *) (void*)(((char *)lsn) - offsetof(file_provider, listener));
244
- if (!provider->base.enabled) {
245
- return;
246
- }
247
-
248
- if (info->origin == LCB_CLCONFIG_PHONY || info->origin == LCB_CLCONFIG_FILE) {
249
- lcb_log(LOGARGS(provider, TRACE), "Not writing configuration originating from PHONY or FILE to cache");
250
- return;
251
- }
252
-
253
- write_to_file(provider, info->vbc);
254
- }
255
-
256
- static void
257
- do_file_dump(clconfig_provider *pb, FILE *fp)
258
- {
259
- file_provider *pr = (file_provider *)pb;
260
-
261
- fprintf(fp, "## BEGIN FILE PROVIEDER DUMP ##\n");
262
- if (pr->filename) {
263
- fprintf(fp, "FILENAME: %s\n", pr->filename);
264
- }
265
- fprintf(fp, "LAST SYSTEM ERRNO: %d\n", pr->last_errno);
266
- fprintf(fp, "LAST MTIME: %lu\n", (unsigned long)pr->last_mtime);
267
- fprintf(fp, "## END FILE PROVIDER DUMP ##\n");
268
-
269
- }
270
-
271
- clconfig_provider * lcb_clconfig_create_file(lcb_confmon *parent)
272
- {
273
- file_provider *provider = calloc(1, sizeof(*provider));
274
-
275
- if (!provider) {
276
- return NULL;
277
- }
278
-
279
- provider->base.get_cached = get_cached;
280
- provider->base.refresh = refresh_file;
281
- provider->base.pause = pause_file;
282
- provider->base.shutdown = shutdown_file;
283
- provider->base.dump = do_file_dump;
284
- provider->base.type = LCB_CLCONFIG_FILE;
285
- provider->listener.callback = config_listener;
286
- provider->timer = lcbio_timer_new(parent->iot, provider, async_callback);
287
-
288
- lcb_confmon_add_listener(parent, &provider->listener);
289
-
290
- return &provider->base;
291
- }
292
-
293
-
294
- static char *mkcachefile(const char *name, const char *bucket)
295
- {
296
- if (name != NULL) {
297
- return strdup(name);
298
- } else {
299
- char buffer[1024];
300
- const char *tmpdir = lcb_get_tmpdir();
301
-
302
- snprintf(buffer, sizeof(buffer),
303
- "%s/%s", tmpdir ? tmpdir : ".", bucket);
304
- return strdup(buffer);
305
- }
306
- }
307
-
308
- int lcb_clconfig_file_set_filename(clconfig_provider *p, const char *f, int ro)
309
- {
310
- file_provider *provider = (file_provider *)p;
311
- lcb_assert(provider->base.type == LCB_CLCONFIG_FILE);
312
- provider->base.enabled = 1;
313
-
314
- if (provider->filename) {
315
- free(provider->filename);
316
- }
317
-
318
- provider->filename = mkcachefile(f, p->parent->settings->bucket);
319
-
320
- if (ro) {
321
- FILE *fp_tmp;
322
- provider->ro_mode = 1;
323
-
324
- fp_tmp = fopen(provider->filename, "r");
325
- if (!fp_tmp) {
326
- lcb_log(LOGARGS(provider, ERROR), LOGFMT "Couldn't open for reading: %s", LOGID(provider), strerror(errno));
327
- return -1;
328
- } else {
329
- fclose(fp_tmp);
330
- }
331
- }
332
-
333
- return 0;
334
- }
335
-
336
- const char *
337
- lcb_clconfig_file_get_filename(clconfig_provider *p)
338
- {
339
- file_provider *fp = (file_provider *)p;
340
- return fp->filename;
341
- }
342
-
343
- void
344
- lcb_clconfig_file_set_readonly(clconfig_provider *p, int val)
345
- {
346
- ((file_provider *)p)->ro_mode = val;
347
- }
@@ -1,630 +0,0 @@
1
- /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
- /*
3
- * Copyright 2013 Couchbase, Inc.
4
- *
5
- * Licensed under the Apache License, Version 2.0 (the "License");
6
- * you may not use this file except in compliance with the License.
7
- * You may obtain a copy of the License at
8
- *
9
- * http://www.apache.org/licenses/LICENSE-2.0
10
- *
11
- * Unless required by applicable law or agreed to in writing, software
12
- * distributed under the License is distributed on an "AS IS" BASIS,
13
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
- * See the License for the specific language governing permissions and
15
- * limitations under the License.
16
- */
17
-
18
- #include "internal.h"
19
- #include "clconfig.h"
20
- #include "bc_http.h"
21
- #include <lcbio/ssl.h>
22
- #include "ctx-log-inl.h"
23
- #define LOGARGS(ht, lvlbase) ht->base.parent->settings, "htconfig", LCB_LOG_##lvlbase, __FILE__, __LINE__
24
- #define LOGFMT "<%s:%s> "
25
- #define LOGID(h) get_ctx_host(h->ioctx), get_ctx_port(h->ioctx)
26
-
27
- static void io_error_handler(lcbio_CTX *, lcb_error_t);
28
- static void on_connected(lcbio_SOCKET *, void *, lcb_error_t, lcbio_OSERR);
29
- static lcb_error_t connect_next(http_provider *);
30
- static void read_common(lcbio_CTX *, unsigned);
31
- static lcb_error_t setup_request_header(http_provider *, const lcb_host_t *);
32
-
33
- /**
34
- * Determine if we're in compatibility mode with the previous versions of the
35
- * library - where the idle timeout is disabled and a perpetual streaming
36
- * connection will always remain open (regardless of whether it was triggered
37
- * by start_refresh/get_refresh).
38
- */
39
- static int is_v220_compat(http_provider *http)
40
- {
41
- lcb_uint32_t setting = PROVIDER_SETTING(&http->base, bc_http_stream_time);
42
- if (setting == (lcb_uint32_t)-1) {
43
- return 1;
44
- }
45
- return 0;
46
- }
47
-
48
- /**
49
- * Closes the current connection and removes the disconn timer along with it
50
- */
51
- static void close_current(http_provider *http)
52
- {
53
- lcbio_timer_disarm(http->disconn_timer);
54
- if (http->ioctx) {
55
- lcbio_ctx_close(http->ioctx, NULL, NULL);
56
- } else if (http->creq){
57
- lcbio_connect_cancel(http->creq);
58
- }
59
- http->creq = NULL;
60
- http->ioctx = NULL;
61
- }
62
-
63
- /**
64
- * Call when there is an error in I/O. This includes read, write, connect
65
- * and timeouts.
66
- */
67
- static lcb_error_t
68
- io_error(http_provider *http, lcb_error_t origerr)
69
- {
70
- lcb_confmon *mon = http->base.parent;
71
- lcb_settings *settings = mon->settings;
72
-
73
- close_current(http);
74
-
75
- http->creq = lcbio_connect_hl(
76
- mon->iot, settings, http->nodes, 0, settings->config_node_timeout,
77
- on_connected, http);
78
- if (http->creq) {
79
- return LCB_SUCCESS;
80
- }
81
-
82
- lcb_confmon_provider_failed(&http->base, origerr);
83
- lcbio_timer_disarm(http->io_timer);
84
- if (is_v220_compat(http) && http->base.parent->config != NULL) {
85
- lcb_log(LOGARGS(http, INFO), "HTTP node list finished. Trying to obtain connection from first node in list");
86
- if (!lcbio_timer_armed(http->as_reconnect)) {
87
- lcbio_timer_rearm(http->as_reconnect,
88
- PROVIDER_SETTING(&http->base, grace_next_cycle));
89
- }
90
- }
91
- return origerr;
92
- }
93
-
94
- /**
95
- * Call this if the configuration generation has changed.
96
- */
97
- static void set_new_config(http_provider *http)
98
- {
99
- const lcb_host_t *curhost;
100
- if (http->current_config) {
101
- lcb_clconfig_decref(http->current_config);
102
- }
103
-
104
- curhost = lcbio_get_host(lcbio_ctx_sock(http->ioctx));
105
- http->current_config = http->last_parsed;
106
- lcb_clconfig_incref(http->current_config);
107
- lcbvb_replace_host(http->current_config->vbc, curhost->host);
108
- lcb_confmon_provider_success(&http->base, http->current_config);
109
- }
110
-
111
- static lcb_error_t
112
- process_chunk(http_provider *http, const void *buf, unsigned nbuf)
113
- {
114
- lcb_error_t err = LCB_SUCCESS;
115
- char *term;
116
- int rv;
117
- lcbvb_CONFIG *cfgh;
118
- lcbht_RESPSTATE state, oldstate, diff;
119
- lcbht_RESPONSE *resp = lcbht_get_response(http->htp);
120
-
121
- oldstate = resp->state;
122
- state = lcbht_parse(http->htp, buf, nbuf);
123
- diff = state ^ oldstate;
124
-
125
- if (state & LCBHT_S_ERROR) {
126
- return LCB_PROTOCOL_ERROR;
127
- }
128
-
129
- if (diff & LCBHT_S_HEADER) {
130
- /* see that we got a success? */
131
- if (resp->status == 200) {
132
- /* nothing */
133
- } else if (resp->status == 404) {
134
- const int urlmode = PROVIDER_SETTING(&http->base, bc_http_urltype);
135
- err = LCB_BUCKET_ENOENT;
136
-
137
- if (++http->uritype > LCB_HTCONFIG_URLTYPE_COMPAT) {
138
- lcb_log(LOGARGS(http, ERR), LOGFMT "Got 404 on config stream. Assuming bucket does not exist as we've tried both URL types", LOGID(http));
139
- goto GT_HT_ERROR;
140
-
141
- } else if ((urlmode & LCB_HTCONFIG_URLTYPE_COMPAT) == 0) {
142
- lcb_log(LOGARGS(http, ERR), LOGFMT "Got 404 on config stream for terse URI. Compat URI disabled, so not trying", LOGID(http));
143
-
144
- } else {
145
- /* reissue the request; but wait for it to drain */
146
- lcb_log(LOGARGS(http, WARN), LOGFMT "Got 404 on config stream. Assuming terse URI not supported on cluster", LOGID(http));
147
- http->try_nexturi = 1;
148
- err = LCB_SUCCESS;
149
- goto GT_CHECKDONE;
150
- }
151
- } else if (resp->status == 401) {
152
- err = LCB_AUTH_ERROR;
153
- } else {
154
- err = LCB_ERROR;
155
- }
156
-
157
- GT_HT_ERROR:
158
- if (err != LCB_SUCCESS) {
159
- lcb_log(LOGARGS(http, ERR), LOGFMT "Got non-success HTTP status code %d", LOGID(http), resp->status);
160
- return err;
161
- }
162
- }
163
-
164
- GT_CHECKDONE:
165
- if (http->try_nexturi) {
166
- lcb_host_t *host;
167
- if (!(state & LCBHT_S_DONE)) {
168
- return LCB_SUCCESS;
169
- }
170
- host = lcbio_get_host(lcbio_ctx_sock(http->ioctx));
171
- http->try_nexturi = 0;
172
- if ((err = setup_request_header(http, host)) != LCB_SUCCESS) {
173
- return err;
174
- }
175
-
176
- /* reset the state? */
177
- lcbht_reset(http->htp);
178
- lcbio_ctx_put(http->ioctx, http->request_buf, strlen(http->request_buf));
179
- return LCB_SUCCESS;
180
- }
181
-
182
- if (PROVIDER_SETTING(&http->base, conntype) == LCB_TYPE_CLUSTER) {
183
- /* don't bother with parsing the actual config */
184
- resp->body.nused = 0;
185
- return LCB_SUCCESS;
186
- }
187
- if (!(state & LCBHT_S_BODY)) {
188
- /* nothing to parse yet */
189
- return LCB_SUCCESS;
190
- }
191
-
192
- /* seek ahead for strstr */
193
- term = strstr(resp->body.base, CONFIG_DELIMITER);
194
- if (!term) {
195
- return LCB_SUCCESS;
196
- }
197
-
198
- *term = '\0';
199
- cfgh = lcbvb_create();
200
- if (!cfgh) {
201
- return LCB_CLIENT_ENOMEM;
202
- }
203
- rv = lcbvb_load_json(cfgh, resp->body.base);
204
- if (rv != 0) {
205
- lcb_log(LOGARGS(http, ERR), LOGFMT "Failed to parse a valid config from HTTP stream", LOGID(http));
206
- lcb_log_badconfig(LOGARGS(http, ERR), cfgh, resp->body.base);
207
- lcbvb_destroy(cfgh);
208
- return LCB_PROTOCOL_ERROR;
209
- }
210
- if (http->last_parsed) {
211
- lcb_clconfig_decref(http->last_parsed);
212
- }
213
- http->last_parsed = lcb_clconfig_create(cfgh, LCB_CLCONFIG_HTTP);
214
- http->last_parsed->cmpclock = gethrtime();
215
- http->generation++;
216
-
217
- /** Relocate the stream */
218
- lcb_string_erase_beginning(&resp->body,
219
- (term+sizeof(CONFIG_DELIMITER)-1)-resp->body.base);
220
-
221
- return LCB_SUCCESS;
222
- }
223
-
224
- /**
225
- * Common function to handle parsing the HTTP stream for both v0 and v1 io
226
- * implementations.
227
- */
228
- static void
229
- read_common(lcbio_CTX *ctx, unsigned nr)
230
- {
231
- lcbio_CTXRDITER riter;
232
- http_provider *http = lcbio_ctx_data(ctx);
233
- int old_generation = http->generation;
234
-
235
- lcb_log(LOGARGS(http, TRACE), LOGFMT "Received %d bytes on HTTP stream", LOGID(http), nr);
236
-
237
- lcbio_timer_rearm(http->io_timer,
238
- PROVIDER_SETTING(&http->base, config_node_timeout));
239
-
240
- LCBIO_CTX_ITERFOR(ctx, &riter, nr) {
241
- unsigned nbuf = lcbio_ctx_risize(&riter);
242
- void *buf = lcbio_ctx_ribuf(&riter);
243
- lcb_error_t err = process_chunk(http, buf, nbuf);
244
-
245
- if (err != LCB_SUCCESS) {
246
- io_error(http, err);
247
- return;
248
- }
249
- }
250
-
251
- if (http->generation != old_generation) {
252
- lcb_log(LOGARGS(http, DEBUG), LOGFMT "Generation %d -> %d", LOGID(http), old_generation, http->generation);
253
- lcbio_timer_disarm(http->io_timer);
254
- set_new_config(http);
255
- }
256
-
257
- lcbio_ctx_rwant(ctx, 1);
258
- lcbio_ctx_schedule(ctx);
259
- }
260
-
261
- static lcb_error_t
262
- setup_request_header(http_provider *http, const lcb_host_t *host)
263
- {
264
- lcb_settings *settings = http->base.parent->settings;
265
-
266
- char *buf = http->request_buf;
267
- const char *username = NULL, *password = NULL;
268
- lcb_size_t nbuf = sizeof(http->request_buf);
269
-
270
- lcb_size_t offset = 0;
271
- http->request_buf[0] = '\0';
272
-
273
- if (settings->conntype == LCB_TYPE_BUCKET) {
274
- const char *fmt;
275
- if (http->uritype == LCB_HTCONFIG_URLTYPE_25PLUS) {
276
- fmt = REQBUCKET_TERSE_FMT;
277
- } else {
278
- fmt = REQBUCKET_COMPAT_FMT;
279
- }
280
- offset = snprintf(buf, nbuf, fmt, settings->bucket);
281
-
282
- } else if (settings->conntype == LCB_TYPE_CLUSTER) {
283
- offset = snprintf(buf, nbuf, REQPOOLS_FMT);
284
-
285
- } else {
286
- return LCB_EINVAL;
287
- }
288
- lcbauth_get_upass(settings->auth, &username, &password);
289
-
290
- if (password) {
291
- char cred[256], b64[256];
292
- snprintf(cred, sizeof(cred), "%s:%s", username, password);
293
-
294
- if (lcb_base64_encode(cred, b64, sizeof(b64)) == -1) {
295
- return LCB_EINTERNAL;
296
- }
297
-
298
- offset += snprintf(buf + offset, nbuf - offset, AUTHDR_FMT, b64);
299
- }
300
-
301
- offset += snprintf(buf + offset, nbuf - offset, HOSTHDR_FMT,
302
- host->host, host->port);
303
-
304
- offset += snprintf(buf + offset, nbuf - offset, "%s\r\n", LAST_HTTP_HEADER);
305
-
306
- return LCB_SUCCESS;
307
- }
308
-
309
- static void reset_stream_state(http_provider *http)
310
- {
311
- const int urlmode = PROVIDER_SETTING(&http->base, bc_http_urltype);
312
- if (http->last_parsed) {
313
- lcb_clconfig_decref(http->last_parsed);
314
- http->last_parsed = NULL;
315
- }
316
- if (urlmode & LCB_HTCONFIG_URLTYPE_25PLUS) {
317
- http->uritype = LCB_HTCONFIG_URLTYPE_25PLUS;
318
- } else {
319
- http->uritype = LCB_HTCONFIG_URLTYPE_COMPAT;
320
- }
321
- http->try_nexturi = 0;
322
- lcbht_reset(http->htp);
323
- }
324
-
325
- static void
326
- on_connected(lcbio_SOCKET *sock, void *arg, lcb_error_t err, lcbio_OSERR syserr)
327
- {
328
- http_provider *http = arg;
329
- lcb_host_t *host;
330
- lcbio_CTXPROCS procs;
331
- http->creq = NULL;
332
-
333
- if (err != LCB_SUCCESS) {
334
- lcb_log(LOGARGS(http, ERR), "Connection to REST API failed with code=0x%x (%d)", err, syserr);
335
- io_error(http, err);
336
- return;
337
- }
338
- host = lcbio_get_host(sock);
339
- lcb_log(LOGARGS(http, DEBUG), "Successfuly connected to REST API %s:%s", host->host, host->port);
340
-
341
- lcbio_sslify_if_needed(sock, http->base.parent->settings);
342
- reset_stream_state(http);
343
-
344
- if ((err = setup_request_header(http, host)) != LCB_SUCCESS) {
345
- lcb_log(LOGARGS(http, ERR), "Couldn't setup request header");
346
- io_error(http, err);
347
- return;
348
- }
349
-
350
- memset(&procs, 0, sizeof(procs));
351
- procs.cb_err = io_error_handler;
352
- procs.cb_read = read_common;
353
- http->ioctx = lcbio_ctx_new(sock, http, &procs);
354
- http->ioctx->subsys = "bc_http";
355
-
356
- lcbio_ctx_put(http->ioctx, http->request_buf, strlen(http->request_buf));
357
- lcbio_ctx_rwant(http->ioctx, 1);
358
- lcbio_ctx_schedule(http->ioctx);
359
- lcbio_timer_rearm(http->io_timer,
360
- PROVIDER_SETTING(&http->base, config_node_timeout));
361
- }
362
-
363
- static void
364
- timeout_handler(void *arg)
365
- {
366
- http_provider *http = arg;
367
-
368
- lcb_log(LOGARGS(http, ERR), LOGFMT "HTTP Provider timed out waiting for I/O", LOGID(http));
369
-
370
- /**
371
- * If we're not the current provider then ignore the timeout until we're
372
- * actively requested to do so
373
- */
374
- if (&http->base != http->base.parent->cur_provider ||
375
- lcb_confmon_is_refreshing(http->base.parent) == 0) {
376
- lcb_log(LOGARGS(http, DEBUG), LOGFMT "Ignoring timeout because we're either not in a refresh or not the current provider", LOGID(http));
377
- return;
378
- }
379
-
380
- io_error(http, LCB_ETIMEDOUT);
381
- }
382
-
383
-
384
- static lcb_error_t
385
- connect_next(http_provider *http)
386
- {
387
- lcb_settings *settings = http->base.parent->settings;
388
- lcb_log(LOGARGS(http, TRACE), "Starting HTTP Configuration Provider %p", (void*)http);
389
- close_current(http);
390
- lcbio_timer_disarm(http->as_reconnect);
391
-
392
- if (!hostlist_size(http->nodes)) {
393
- lcb_log(LOGARGS(http, ERROR), "Not scheduling HTTP provider since no nodes have been configured for HTTP bootstrap");
394
- return LCB_CONNECT_ERROR;
395
- }
396
-
397
- http->creq = lcbio_connect_hl(http->base.parent->iot, settings, http->nodes, 1,
398
- settings->config_node_timeout, on_connected, http);
399
- if (http->creq) {
400
- return LCB_SUCCESS;
401
- }
402
- lcb_log(LOGARGS(http, ERROR), "%p: Couldn't schedule connection", (void*)http);
403
- return LCB_CONNECT_ERROR;
404
- }
405
-
406
- static void delayed_disconn(void *arg)
407
- {
408
- http_provider *http = arg;
409
- lcb_log(LOGARGS(http, DEBUG), "Stopping HTTP provider %p", (void*)http);
410
-
411
- /** closes the connection and cleans up the timer */
412
- close_current(http);
413
- lcbio_timer_disarm(http->io_timer);
414
- }
415
-
416
- static void delayed_reconnect(void *arg)
417
- {
418
- http_provider *http = arg;
419
- lcb_error_t err;
420
- if (http->ioctx) {
421
- /* have a context already */
422
- return;
423
- }
424
- err = connect_next(http);
425
- if (err != LCB_SUCCESS) {
426
- io_error(http, err);
427
- }
428
- }
429
-
430
- static lcb_error_t pause_http(clconfig_provider *pb)
431
- {
432
- http_provider *http = (http_provider *)pb;
433
- if (is_v220_compat(http)) {
434
- return LCB_SUCCESS;
435
- }
436
-
437
- if (!lcbio_timer_armed(http->disconn_timer)) {
438
- lcbio_timer_rearm(http->disconn_timer,
439
- PROVIDER_SETTING(pb, bc_http_stream_time));
440
- }
441
- return LCB_SUCCESS;
442
- }
443
-
444
- static lcb_error_t get_refresh(clconfig_provider *provider)
445
- {
446
- http_provider *http = (http_provider *)provider;
447
-
448
- /**
449
- * We want a grace interval here because we might already be fetching a
450
- * connection. HOWEVER we don't want to indefinitely wait on a socket
451
- * so we issue a timer indicating how long we expect to wait for a
452
- * streaming update until we get something.
453
- */
454
-
455
- /** If we need a new socket, we do connect_next. */
456
- if (http->ioctx == NULL && http->creq == NULL) {
457
- lcbio_async_signal(http->as_reconnect);
458
- }
459
-
460
- lcbio_timer_disarm(http->disconn_timer);
461
- if (http->ioctx) {
462
- lcbio_timer_rearm(http->io_timer,
463
- PROVIDER_SETTING(provider, config_node_timeout));
464
- }
465
- return LCB_SUCCESS;
466
- }
467
-
468
- static clconfig_info* http_get_cached(clconfig_provider *provider)
469
- {
470
- http_provider *http = (http_provider *)provider;
471
- return http->current_config;
472
- }
473
-
474
- static void
475
- config_updated(clconfig_provider *pb, lcbvb_CONFIG *newconfig)
476
- {
477
- unsigned int ii;
478
- http_provider *http = (http_provider *)pb;
479
- lcb_SSLOPTS sopts;
480
- lcbvb_SVCMODE mode;
481
-
482
- hostlist_clear(http->nodes);
483
-
484
- sopts = PROVIDER_SETTING(pb, sslopts);
485
- if (sopts & LCB_SSL_ENABLED) {
486
- mode = LCBVB_SVCMODE_SSL;
487
- } else {
488
- mode = LCBVB_SVCMODE_PLAIN;
489
- }
490
-
491
- for (ii = 0; ii < newconfig->nsrv; ++ii) {
492
- const char *ss;
493
- lcb_error_t status;
494
- ss = lcbvb_get_hostport(newconfig, ii, LCBVB_SVCTYPE_MGMT, mode);
495
- if (!ss) {
496
- /* not supported? */
497
- continue;
498
- }
499
- status = hostlist_add_stringz(http->nodes, ss, LCB_CONFIG_HTTP_PORT);
500
- lcb_assert(status == LCB_SUCCESS);
501
- }
502
- if (!hostlist_size(http->nodes)) {
503
- lcb_log(LOGARGS(http, FATAL), "New nodes do not contain management ports");
504
- }
505
-
506
- if (PROVIDER_SETTING(pb, randomize_bootstrap_nodes)) {
507
- hostlist_randomize(http->nodes);
508
- }
509
- }
510
-
511
- static void
512
- configure_nodes(clconfig_provider *pb, const hostlist_t newnodes)
513
- {
514
- http_provider *http = (void *)pb;
515
- hostlist_assign(http->nodes, newnodes);
516
- if (PROVIDER_SETTING(pb, randomize_bootstrap_nodes)) {
517
- hostlist_randomize(http->nodes);
518
- }
519
- }
520
-
521
- static hostlist_t
522
- get_nodes(const clconfig_provider *pb)
523
- {
524
- return ((http_provider *)pb)->nodes;
525
- }
526
-
527
- static void shutdown_http(clconfig_provider *provider)
528
- {
529
- http_provider *http = (http_provider *)provider;
530
- reset_stream_state(http);
531
- close_current(http);
532
- lcbht_free(http->htp);
533
-
534
- if (http->current_config) {
535
- lcb_clconfig_decref(http->current_config);
536
- }
537
- if (http->disconn_timer) {
538
- lcbio_timer_destroy(http->disconn_timer);
539
- }
540
- if (http->io_timer) {
541
- lcbio_timer_destroy(http->io_timer);
542
- }
543
- if (http->as_reconnect) {
544
- lcbio_timer_destroy(http->as_reconnect);
545
- }
546
- if (http->nodes) {
547
- hostlist_destroy(http->nodes);
548
- }
549
- free(http);
550
- }
551
-
552
- static void
553
- do_http_dump(clconfig_provider *pb, FILE *fp)
554
- {
555
- http_provider *ht = (http_provider *)pb;
556
- fprintf(fp, "## BEGIN HTTP PROVIDER DUMP\n");
557
- fprintf(fp, "NUMBER OF CONFIGS RECEIVED: %u\n", ht->generation);
558
- fprintf(fp, "DUMPING I/O TIMER\n");
559
- lcbio_timer_dump(ht->io_timer, fp);
560
- if (ht->ioctx) {
561
- fprintf(fp, "DUMPING CURRENT CONNECTION:\n");
562
- lcbio_ctx_dump(ht->ioctx, fp);
563
- } else if (ht->creq) {
564
- fprintf(fp, "CURRENTLY CONNECTING..\n");
565
- } else {
566
- fprintf(fp, "NO CONNECTION ACTIVE\n");
567
- }
568
- }
569
-
570
- clconfig_provider * lcb_clconfig_create_http(lcb_confmon *parent)
571
- {
572
- http_provider *http = calloc(1, sizeof(*http));
573
-
574
- if (!http) {
575
- return NULL;
576
- }
577
-
578
- if (! (http->nodes = hostlist_create())) {
579
- free(http);
580
- return NULL;
581
- }
582
-
583
- http->base.type = LCB_CLCONFIG_HTTP;
584
- http->base.refresh = get_refresh;
585
- http->base.pause = pause_http;
586
- http->base.get_cached = http_get_cached;
587
- http->base.shutdown = shutdown_http;
588
- http->base.config_updated = config_updated;
589
- http->base.configure_nodes = configure_nodes;
590
- http->base.get_nodes = get_nodes;
591
- http->base.dump = do_http_dump;
592
- http->base.enabled = 0;
593
- http->io_timer = lcbio_timer_new(parent->iot, http, timeout_handler);
594
- http->disconn_timer = lcbio_timer_new(parent->iot, http, delayed_disconn);
595
- http->as_reconnect = lcbio_timer_new(parent->iot, http, delayed_reconnect);
596
- http->htp = lcbht_new(parent->settings);
597
- return &http->base;
598
- }
599
-
600
- static void
601
- io_error_handler(lcbio_CTX *ctx, lcb_error_t err)
602
- {
603
- io_error((http_provider *)lcbio_ctx_data(ctx), err);
604
- }
605
-
606
- void lcb_clconfig_http_enable(clconfig_provider *http)
607
- {
608
- http->enabled = 1;
609
- }
610
-
611
- lcbio_SOCKET *
612
- lcb_confmon_get_rest_connection(lcb_confmon *mon)
613
- {
614
- http_provider *http = (http_provider *)mon->all_providers[LCB_CLCONFIG_HTTP];
615
- if (!http->ioctx) {
616
- return NULL;
617
- }
618
- return lcbio_ctx_sock(http->ioctx);
619
-
620
- }
621
-
622
- lcb_host_t *
623
- lcb_confmon_get_rest_host(lcb_confmon *mon)
624
- {
625
- lcbio_SOCKET *sock = lcb_confmon_get_rest_connection(mon);
626
- if (sock) {
627
- return lcbio_get_host(sock);
628
- }
629
- return NULL;
630
- }