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.
- checksums.yaml +4 -4
- data/ext/libcouchbase/CMakeLists.txt +6 -8
- data/ext/libcouchbase/README.markdown +2 -2
- data/ext/libcouchbase/RELEASE_NOTES.markdown +229 -2
- data/ext/libcouchbase/cmake/Modules/ConfigureDtrace.cmake +11 -0
- data/ext/libcouchbase/cmake/Modules/GenerateConfigDotH.cmake +18 -0
- data/ext/libcouchbase/cmake/Modules/GetLibcouchbaseFlags.cmake +3 -2
- data/ext/libcouchbase/cmake/Modules/GetVersionInfo.cmake +3 -3
- data/ext/libcouchbase/cmake/config-cmake.h.in +4 -0
- data/ext/libcouchbase/cmake/defs.mk.in +0 -2
- data/ext/libcouchbase/cmake/source_files.cmake +21 -5
- data/ext/libcouchbase/contrib/cJSON/cJSON.c +1 -1
- data/ext/libcouchbase/contrib/cbsasl/src/client.c +2 -0
- data/ext/libcouchbase/example/users/README +48 -0
- data/ext/libcouchbase/example/users/users.c +147 -0
- data/ext/libcouchbase/include/libcouchbase/auth.h +175 -31
- data/ext/libcouchbase/include/libcouchbase/cntl.h +82 -1
- data/ext/libcouchbase/include/libcouchbase/couchbase.h +45 -3
- data/ext/libcouchbase/include/libcouchbase/error.h +19 -1
- data/ext/libcouchbase/include/libcouchbase/iops.h +3 -0
- data/ext/libcouchbase/include/libcouchbase/n1ql.h +31 -1
- data/ext/libcouchbase/include/libcouchbase/plugins/io/bsdio-inl.c +4 -1
- data/ext/libcouchbase/include/libcouchbase/subdoc.h +36 -2
- data/ext/libcouchbase/include/libcouchbase/views.h +7 -1
- data/ext/libcouchbase/include/libcouchbase/visibility.h +1 -0
- data/ext/libcouchbase/include/memcached/protocol_binary.h +24 -1146
- data/ext/libcouchbase/packaging/parse-git-describe.pl +1 -1
- data/ext/libcouchbase/plugins/io/libev/libev_io_opts.h +3 -2
- data/ext/libcouchbase/src/README.md +0 -2
- data/ext/libcouchbase/src/auth-priv.h +23 -4
- data/ext/libcouchbase/src/auth.cc +51 -43
- data/ext/libcouchbase/src/bootstrap.cc +244 -0
- data/ext/libcouchbase/src/bootstrap.h +58 -38
- data/ext/libcouchbase/src/bucketconfig/bc_cccp.cc +120 -158
- data/ext/libcouchbase/src/bucketconfig/bc_file.cc +281 -0
- data/ext/libcouchbase/src/bucketconfig/bc_http.cc +526 -0
- data/ext/libcouchbase/src/bucketconfig/bc_http.h +50 -25
- data/ext/libcouchbase/src/bucketconfig/bc_static.cc +150 -0
- data/ext/libcouchbase/src/bucketconfig/clconfig.h +410 -386
- data/ext/libcouchbase/src/bucketconfig/confmon.cc +393 -0
- data/ext/libcouchbase/src/cbft.cc +22 -27
- data/ext/libcouchbase/src/cntl.cc +56 -22
- data/ext/libcouchbase/src/connspec.cc +47 -6
- data/ext/libcouchbase/src/connspec.h +27 -0
- data/ext/libcouchbase/src/dns-srv.cc +147 -0
- data/ext/libcouchbase/src/dump.cc +3 -3
- data/ext/libcouchbase/src/errmap.cc +173 -0
- data/ext/libcouchbase/src/errmap.h +198 -0
- data/ext/libcouchbase/src/getconfig.cc +7 -33
- data/ext/libcouchbase/src/handler.cc +118 -7
- data/ext/libcouchbase/src/hostlist.cc +0 -36
- data/ext/libcouchbase/src/hostlist.h +44 -62
- data/ext/libcouchbase/src/http/http-priv.h +125 -112
- data/ext/libcouchbase/src/http/http.cc +27 -35
- data/ext/libcouchbase/src/http/http.h +1 -34
- data/ext/libcouchbase/src/http/http_io.cc +28 -36
- data/ext/libcouchbase/src/instance.cc +131 -34
- data/ext/libcouchbase/src/internal.h +58 -26
- data/ext/libcouchbase/src/jsparse/parser.cc +136 -210
- data/ext/libcouchbase/src/jsparse/parser.h +84 -98
- data/ext/libcouchbase/src/lcbht/lcbht.cc +177 -0
- data/ext/libcouchbase/src/lcbht/lcbht.h +174 -163
- data/ext/libcouchbase/src/lcbio/connect.cc +569 -0
- data/ext/libcouchbase/src/lcbio/connect.h +16 -7
- data/ext/libcouchbase/src/lcbio/ctx.c +1 -1
- data/ext/libcouchbase/src/lcbio/iotable.h +101 -16
- data/ext/libcouchbase/src/lcbio/{ioutils.c → ioutils.cc} +30 -51
- data/ext/libcouchbase/src/lcbio/ioutils.h +29 -90
- data/ext/libcouchbase/src/lcbio/manager.cc +543 -0
- data/ext/libcouchbase/src/lcbio/manager.h +133 -96
- data/ext/libcouchbase/src/lcbio/protoctx.c +2 -2
- data/ext/libcouchbase/src/lcbio/timer-cxx.h +87 -0
- data/ext/libcouchbase/src/mc/mcreq.c +11 -2
- data/ext/libcouchbase/src/mc/mcreq.h +9 -2
- data/ext/libcouchbase/src/mcserver/mcserver.cc +175 -43
- data/ext/libcouchbase/src/mcserver/mcserver.h +9 -13
- data/ext/libcouchbase/src/mcserver/negotiate.cc +181 -62
- data/ext/libcouchbase/src/mcserver/negotiate.h +1 -3
- data/ext/libcouchbase/src/mctx-helper.h +51 -0
- data/ext/libcouchbase/src/n1ql/ixmgmt.cc +1 -2
- data/ext/libcouchbase/src/n1ql/n1ql.cc +74 -42
- data/ext/libcouchbase/src/netbuf/netbuf.c +4 -4
- data/ext/libcouchbase/src/newconfig.cc +6 -6
- data/ext/libcouchbase/src/nodeinfo.cc +2 -2
- data/ext/libcouchbase/src/operations/{cbflush.c → cbflush.cc} +7 -15
- data/ext/libcouchbase/src/operations/{counter.c → counter.cc} +0 -0
- data/ext/libcouchbase/src/operations/durability.cc +6 -26
- data/ext/libcouchbase/src/operations/durability_internal.h +6 -3
- data/ext/libcouchbase/src/operations/{get.c → get.cc} +24 -26
- data/ext/libcouchbase/src/operations/{observe.c → observe.cc} +68 -93
- data/ext/libcouchbase/src/operations/{pktfwd.c → pktfwd.cc} +0 -0
- data/ext/libcouchbase/src/operations/{remove.c → remove.cc} +0 -0
- data/ext/libcouchbase/src/operations/stats.cc +3 -8
- data/ext/libcouchbase/src/operations/{store.c → store.cc} +27 -32
- data/ext/libcouchbase/src/operations/subdoc.cc +129 -42
- data/ext/libcouchbase/src/operations/{touch.c → touch.cc} +0 -0
- data/ext/libcouchbase/src/packetutils.h +30 -2
- data/ext/libcouchbase/src/probes.d +1 -1
- data/ext/libcouchbase/src/rdb/rope.c +1 -1
- data/ext/libcouchbase/src/{retrychk.c → retrychk.cc} +2 -3
- data/ext/libcouchbase/src/retryq.cc +52 -14
- data/ext/libcouchbase/src/retryq.h +3 -3
- data/ext/libcouchbase/src/settings.c +5 -0
- data/ext/libcouchbase/src/settings.h +11 -0
- data/ext/libcouchbase/src/ssl/ssl_c.c +1 -0
- data/ext/libcouchbase/src/ssl/ssl_common.c +2 -0
- data/ext/libcouchbase/src/ssl/ssl_e.c +0 -1
- data/ext/libcouchbase/src/strcodecs/strcodecs.h +1 -1
- data/ext/libcouchbase/src/trace.h +4 -4
- data/ext/libcouchbase/src/vbucket/vbucket.c +6 -10
- data/ext/libcouchbase/src/views/{docreq.c → docreq.cc} +48 -54
- data/ext/libcouchbase/src/views/docreq.h +24 -30
- data/ext/libcouchbase/src/views/viewreq.cc +318 -0
- data/ext/libcouchbase/src/views/viewreq.h +43 -13
- data/ext/libcouchbase/tests/basic/t_connstr.cc +88 -50
- data/ext/libcouchbase/tests/basic/t_creds.cc +47 -5
- data/ext/libcouchbase/tests/basic/t_host.cc +67 -75
- data/ext/libcouchbase/tests/basic/t_jsparse.cc +27 -82
- data/ext/libcouchbase/tests/basic/t_misc.cc +1 -1
- data/ext/libcouchbase/tests/basic/t_n1qlstrings.cc +0 -1
- data/ext/libcouchbase/tests/htparse/t_basic.cc +58 -78
- data/ext/libcouchbase/tests/ioserver/connection.cc +1 -1
- data/ext/libcouchbase/tests/ioserver/ioserver.cc +19 -6
- data/ext/libcouchbase/tests/iotests/mock-environment.cc +28 -2
- data/ext/libcouchbase/tests/iotests/mock-environment.h +51 -1
- data/ext/libcouchbase/tests/iotests/t_behavior.cc +1 -7
- data/ext/libcouchbase/tests/iotests/t_confmon.cc +97 -115
- data/ext/libcouchbase/tests/iotests/t_durability.cc +0 -1
- data/ext/libcouchbase/tests/iotests/t_eerrs.cc +119 -0
- data/ext/libcouchbase/tests/iotests/t_errmap.cc +178 -0
- data/ext/libcouchbase/tests/iotests/t_misc.cc +3 -3
- data/ext/libcouchbase/tests/iotests/t_netfail.cc +1 -1
- data/ext/libcouchbase/tests/iotests/t_obseqno.cc +0 -1
- data/ext/libcouchbase/tests/iotests/t_subdoc.cc +18 -11
- data/ext/libcouchbase/tests/mc/t_alloc.cc +9 -9
- data/ext/libcouchbase/tests/socktests/socktest.cc +7 -10
- data/ext/libcouchbase/tests/socktests/socktest.h +2 -3
- data/ext/libcouchbase/tests/socktests/t_basic.cc +6 -6
- data/ext/libcouchbase/tests/socktests/t_manager.cc +5 -6
- data/ext/libcouchbase/tests/socktests/t_ssl.cc +1 -1
- data/ext/libcouchbase/tests/vbucket/confdata/ketama_expected.json +2562 -0
- data/ext/libcouchbase/tests/vbucket/confdata/memd_ketama_config.json +31 -0
- data/ext/libcouchbase/tests/vbucket/t_config.cc +35 -5
- data/ext/libcouchbase/tools/CMakeLists.txt +2 -2
- data/ext/libcouchbase/tools/cbc-handlers.h +128 -0
- data/ext/libcouchbase/tools/cbc-n1qlback.cc +64 -10
- data/ext/libcouchbase/tools/cbc-pillowfight.cc +2 -2
- data/ext/libcouchbase/tools/cbc.cc +143 -10
- data/ext/libcouchbase/tools/docgen/loc.h +1 -1
- data/lib/libcouchbase/connection.rb +4 -3
- data/lib/libcouchbase/version.rb +1 -1
- metadata +37 -28
- data/ext/libcouchbase/include/memcached/vbucket.h +0 -42
- data/ext/libcouchbase/src/bootstrap.c +0 -269
- data/ext/libcouchbase/src/bucketconfig/bc_file.c +0 -347
- data/ext/libcouchbase/src/bucketconfig/bc_http.c +0 -630
- data/ext/libcouchbase/src/bucketconfig/bc_mcraw.c +0 -150
- data/ext/libcouchbase/src/bucketconfig/confmon.c +0 -474
- data/ext/libcouchbase/src/lcbht/lcbht.c +0 -282
- data/ext/libcouchbase/src/lcbio/connect.c +0 -557
- data/ext/libcouchbase/src/lcbio/manager.c +0 -584
- data/ext/libcouchbase/src/packetutils.c +0 -37
- data/ext/libcouchbase/src/simplestring.c +0 -211
- data/ext/libcouchbase/src/simplestring.h +0 -228
- data/ext/libcouchbase/src/ssobuf.h +0 -82
- data/ext/libcouchbase/src/views/viewreq.c +0 -358
- data/ext/libcouchbase/tests/basic/t_string.cc +0 -112
|
@@ -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
|
-
}
|