libcouchbase 0.3.3 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -34,7 +34,7 @@ lcb_dump(lcb_t instance, FILE *fp, lcb_U32 flags)
|
|
34
34
|
fprintf(fp, "Settings=%p\n", (void*)instance->settings);
|
35
35
|
|
36
36
|
if (instance->cur_configinfo) {
|
37
|
-
|
37
|
+
lcb::clconfig::ConfigInfo *cfg = instance->cur_configinfo;
|
38
38
|
fprintf(fp, "Current VBC=%p\n", (void*)cfg->vbc);
|
39
39
|
fprintf(fp, "Config RevID=%d\n", cfg->vbc->revid);
|
40
40
|
if (flags & LCB_DUMP_VBCONFIG) {
|
@@ -67,7 +67,7 @@ lcb_dump(lcb_t instance, FILE *fp, lcb_U32 flags)
|
|
67
67
|
fprintf(fp, "** == BEGIN SOCKET INFO\n");
|
68
68
|
lcbio_ctx_dump(server->connctx, fp);
|
69
69
|
fprintf(fp, "** == END SOCKET INFO\n");
|
70
|
-
} else if (server->connreq
|
70
|
+
} else if (server->connreq) {
|
71
71
|
fprintf(fp, "** == STILL CONNECTING\n");
|
72
72
|
} else {
|
73
73
|
fprintf(fp, "** == NOT CONNECTED\n");
|
@@ -90,6 +90,6 @@ lcb_dump(lcb_t instance, FILE *fp, lcb_U32 flags)
|
|
90
90
|
fprintf(fp, "=== END PIPELINE DUMP ===\n");
|
91
91
|
|
92
92
|
fprintf(fp, "=== BEGIN CONFMON DUMP ===\n");
|
93
|
-
|
93
|
+
instance->confmon->dump(fp);
|
94
94
|
fprintf(fp, "=== END CONFMON DUMP ===\n");
|
95
95
|
}
|
@@ -0,0 +1,173 @@
|
|
1
|
+
#include "internal.h"
|
2
|
+
#include "errmap.h"
|
3
|
+
#include "contrib/lcb-jsoncpp/lcb-jsoncpp.h"
|
4
|
+
|
5
|
+
using namespace lcb::errmap;
|
6
|
+
|
7
|
+
ErrorMap::ErrorMap() : revision(0), version(0) {
|
8
|
+
}
|
9
|
+
|
10
|
+
static ErrorAttribute getAttribute(const std::string& s) {
|
11
|
+
#define X(c, s_) if (s == s_) { return c; }
|
12
|
+
LCB_XERRMAP_ATTRIBUTES(X)
|
13
|
+
#undef X
|
14
|
+
return INVALID_ATTRIBUTE;
|
15
|
+
}
|
16
|
+
|
17
|
+
RetrySpec *Error::getRetrySpec() const {
|
18
|
+
return retry.specptr;
|
19
|
+
}
|
20
|
+
|
21
|
+
RetrySpec* RetrySpec::parse(const Json::Value& retryJson, std::string& emsg) {
|
22
|
+
|
23
|
+
RetrySpec *spec = new RetrySpec();
|
24
|
+
spec->refcount = 1;
|
25
|
+
|
26
|
+
#define FAIL_RETRY(s) \
|
27
|
+
emsg = s; \
|
28
|
+
delete spec; \
|
29
|
+
return NULL;
|
30
|
+
|
31
|
+
if (!retryJson.isObject()) {
|
32
|
+
FAIL_RETRY("Missing retry specification");
|
33
|
+
}
|
34
|
+
|
35
|
+
const Json::Value& strategyJson = retryJson["strategy"];
|
36
|
+
if (!strategyJson.isString()) {
|
37
|
+
FAIL_RETRY("Missing `strategy`");
|
38
|
+
}
|
39
|
+
const char* strategy = strategyJson.asCString();
|
40
|
+
if (!strcasecmp(strategy, "constant")) {
|
41
|
+
spec->strategy = CONSTANT;
|
42
|
+
} else if (!strcasecmp(strategy, "linear")) {
|
43
|
+
spec->strategy = LINEAR;
|
44
|
+
} else if (!strcasecmp(strategy, "exponential")) {
|
45
|
+
spec->strategy = EXPONENTIAL;
|
46
|
+
} else {
|
47
|
+
FAIL_RETRY("Unknown strategy");
|
48
|
+
}
|
49
|
+
|
50
|
+
#define GET_TIMEFLD(srcname, dstname, required) { \
|
51
|
+
Json::Value dstname##Json = retryJson[srcname]; \
|
52
|
+
if (dstname##Json.isNumeric()) { \
|
53
|
+
spec->dstname = (dstname##Json).asUInt() * 1000; \
|
54
|
+
} else if (required) { \
|
55
|
+
FAIL_RETRY("Missing " # srcname); \
|
56
|
+
} else { \
|
57
|
+
spec->dstname = 0; \
|
58
|
+
} \
|
59
|
+
}
|
60
|
+
|
61
|
+
GET_TIMEFLD("interval", interval, true);
|
62
|
+
GET_TIMEFLD("after", after, true);
|
63
|
+
GET_TIMEFLD("ceil", ceil, false);
|
64
|
+
GET_TIMEFLD("max-duration", max_duration, false);
|
65
|
+
|
66
|
+
return spec;
|
67
|
+
|
68
|
+
#undef FAIL_RETRY
|
69
|
+
#undef GET_TIMEFLD
|
70
|
+
|
71
|
+
}
|
72
|
+
|
73
|
+
const uint32_t ErrorMap::MAX_VERSION = 1;
|
74
|
+
|
75
|
+
ErrorMap::ParseStatus
|
76
|
+
ErrorMap::parse(const char *s, size_t n, std::string& errmsg) {
|
77
|
+
Json::Value root_nonconst;
|
78
|
+
Json::Reader reader;
|
79
|
+
if (!reader.parse(s, s + n, root_nonconst)) {
|
80
|
+
errmsg = "Invalid JSON";
|
81
|
+
return PARSE_ERROR;
|
82
|
+
}
|
83
|
+
|
84
|
+
const Json::Value& root = root_nonconst;
|
85
|
+
const Json::Value& verJson = root["version"];
|
86
|
+
if (!verJson.isNumeric()) {
|
87
|
+
errmsg = "'version' is not a number";
|
88
|
+
return PARSE_ERROR;
|
89
|
+
}
|
90
|
+
|
91
|
+
if (verJson.asUInt() > MAX_VERSION) {
|
92
|
+
errmsg = "'version' is unreasonably high";
|
93
|
+
return UNKNOWN_VERSION;
|
94
|
+
}
|
95
|
+
|
96
|
+
const Json::Value& revJson = root["revision"];
|
97
|
+
if (!revJson.isNumeric()) {
|
98
|
+
errmsg = "'revision' is not a number";
|
99
|
+
return PARSE_ERROR;
|
100
|
+
}
|
101
|
+
|
102
|
+
if (revJson.asUInt() <= revision) {
|
103
|
+
return NOT_UPDATED;
|
104
|
+
}
|
105
|
+
|
106
|
+
const Json::Value& errsJson = root["errors"];
|
107
|
+
if (!errsJson.isObject()) {
|
108
|
+
errmsg = "'errors' is not an object";
|
109
|
+
return PARSE_ERROR;
|
110
|
+
}
|
111
|
+
|
112
|
+
Json::Value::const_iterator ii = errsJson.begin();
|
113
|
+
for (; ii != errsJson.end(); ++ii) {
|
114
|
+
// Key is the version in hex
|
115
|
+
unsigned ec = 0;
|
116
|
+
if (sscanf(ii.key().asCString(), "%x", &ec) != 1) {
|
117
|
+
errmsg = "key " + ii.key().asString() + " is not a hex number";
|
118
|
+
return PARSE_ERROR;
|
119
|
+
}
|
120
|
+
|
121
|
+
const Json::Value& errorJson = *ii;
|
122
|
+
|
123
|
+
// Descend into the error attributes
|
124
|
+
Error error;
|
125
|
+
error.code = static_cast<uint16_t>(ec);
|
126
|
+
|
127
|
+
error.shortname = errorJson["name"].asString();
|
128
|
+
error.description = errorJson["desc"].asString();
|
129
|
+
|
130
|
+
const Json::Value& attrs = errorJson["attrs"];
|
131
|
+
if (!attrs.isArray()) {
|
132
|
+
errmsg = "'attrs' is not an array";
|
133
|
+
return PARSE_ERROR;
|
134
|
+
}
|
135
|
+
|
136
|
+
Json::Value::const_iterator jj = attrs.begin();
|
137
|
+
for (; jj != attrs.end(); ++jj) {
|
138
|
+
ErrorAttribute attr = getAttribute(jj->asString());
|
139
|
+
if (attr == INVALID_ATTRIBUTE) {
|
140
|
+
errmsg = "unknown attribute received";
|
141
|
+
return UNKNOWN_VERSION;
|
142
|
+
}
|
143
|
+
error.attributes.insert(attr);
|
144
|
+
}
|
145
|
+
if (error.hasAttribute(AUTO_RETRY)) {
|
146
|
+
const Json::Value& retryJson = errorJson["retry"];
|
147
|
+
if (!retryJson.isObject()) {
|
148
|
+
errmsg = "Need `retry` specification for `auto-retry` attribute";
|
149
|
+
return PARSE_ERROR;
|
150
|
+
}
|
151
|
+
if ((error.retry.specptr = RetrySpec::parse(retryJson, errmsg)) == NULL) {
|
152
|
+
return PARSE_ERROR;
|
153
|
+
}
|
154
|
+
}
|
155
|
+
errors.insert(MapType::value_type(ec, error));
|
156
|
+
}
|
157
|
+
|
158
|
+
return UPDATED;
|
159
|
+
}
|
160
|
+
|
161
|
+
const Error& ErrorMap::getError(uint16_t code) const {
|
162
|
+
static const Error invalid;
|
163
|
+
MapType::const_iterator it = errors.find(code);
|
164
|
+
|
165
|
+
if (it != errors.end()) {
|
166
|
+
return it->second;
|
167
|
+
} else {
|
168
|
+
return invalid;
|
169
|
+
}
|
170
|
+
}
|
171
|
+
|
172
|
+
ErrorMap *lcb_errmap_new() { return new ErrorMap(); }
|
173
|
+
void lcb_errmap_free(ErrorMap* m) { delete m; }
|
@@ -0,0 +1,198 @@
|
|
1
|
+
#ifndef LCB_ERRMAP_H
|
2
|
+
#define LCB_ERRMAP_H
|
3
|
+
|
4
|
+
#ifdef __cplusplus
|
5
|
+
#include <map>
|
6
|
+
#include <set>
|
7
|
+
#include <string>
|
8
|
+
#include <cmath>
|
9
|
+
|
10
|
+
namespace Json { class Value; }
|
11
|
+
|
12
|
+
namespace lcb {
|
13
|
+
namespace errmap {
|
14
|
+
|
15
|
+
enum ErrorAttribute {
|
16
|
+
#define LCB_XERRMAP_ATTRIBUTES(X) \
|
17
|
+
X(TEMPORARY, "temp") \
|
18
|
+
X(SUBDOC, "subdoc") \
|
19
|
+
X(RETRY_NOW, "retry-now") \
|
20
|
+
X(RETRY_LATER, "retry-later") \
|
21
|
+
X(INVALID_INPUT, "invalid-input") \
|
22
|
+
X(NOT_ENABLED, "support") \
|
23
|
+
X(AUTH, "auth") \
|
24
|
+
X(CONN_STATE_INVALIDATED, "conn-state-invalidated") \
|
25
|
+
X(CONSTRAINT_FAILURE, "item-only") \
|
26
|
+
X(RETRY_EXP_BACKOFF, "retry-exp-backoff") \
|
27
|
+
X(RETRY_LINEAR_BACKOFF, "retry-linear-backoff") \
|
28
|
+
X(INTERNAL, "internal") \
|
29
|
+
X(DCP, "dcp") \
|
30
|
+
X(FETCH_CONFIG, "fetch-config") \
|
31
|
+
X(SPECIAL_HANDLING, "special-handling") \
|
32
|
+
X(AUTO_RETRY, "auto-retry")
|
33
|
+
|
34
|
+
#define X(c, s) c,
|
35
|
+
LCB_XERRMAP_ATTRIBUTES(X)
|
36
|
+
#undef X
|
37
|
+
|
38
|
+
INVALID_ATTRIBUTE
|
39
|
+
};
|
40
|
+
|
41
|
+
class RetrySpec {
|
42
|
+
public:
|
43
|
+
enum Strategy { CONSTANT, LINEAR, EXPONENTIAL };
|
44
|
+
// Grace time
|
45
|
+
uint32_t after;
|
46
|
+
|
47
|
+
// Maximum duration for retry.
|
48
|
+
uint32_t max_duration;
|
49
|
+
|
50
|
+
uint32_t get_next_interval(size_t num_attempts) const {
|
51
|
+
uint32_t cur_interval = 0; // 50ms is a safe bet.
|
52
|
+
if (strategy == CONSTANT) {
|
53
|
+
return interval;
|
54
|
+
} else if (strategy == LINEAR) {
|
55
|
+
cur_interval = num_attempts * interval;
|
56
|
+
} else if (strategy == EXPONENTIAL) {
|
57
|
+
// Convert to ms for pow(), convert result back to us.
|
58
|
+
cur_interval = std::pow((double)(interval / 1000), (int)num_attempts) * 1000;
|
59
|
+
}
|
60
|
+
if (ceil != 0) {
|
61
|
+
// Note, I *could* use std::min here, but this file gets
|
62
|
+
// included by other files, and Windows is giving a hard time
|
63
|
+
// because it defines std::min as a macro. NOMINMAX is a possible
|
64
|
+
// definition, but I'd rather not touch all including files
|
65
|
+
// to contain that macro, and I don't want to add additional
|
66
|
+
// preprocessor defs at this time.
|
67
|
+
cur_interval = ceil > cur_interval ? cur_interval : ceil;
|
68
|
+
}
|
69
|
+
return cur_interval;
|
70
|
+
}
|
71
|
+
|
72
|
+
void ref() {
|
73
|
+
refcount++;
|
74
|
+
}
|
75
|
+
|
76
|
+
void unref() {
|
77
|
+
if (!--refcount) {
|
78
|
+
delete this;
|
79
|
+
}
|
80
|
+
}
|
81
|
+
|
82
|
+
static inline RetrySpec* parse(const Json::Value& specJson,
|
83
|
+
std::string& errmsg);
|
84
|
+
|
85
|
+
private:
|
86
|
+
Strategy strategy;
|
87
|
+
|
88
|
+
// Base interval
|
89
|
+
uint32_t interval;
|
90
|
+
|
91
|
+
// Max interval
|
92
|
+
uint32_t ceil;
|
93
|
+
|
94
|
+
|
95
|
+
size_t refcount;
|
96
|
+
};
|
97
|
+
|
98
|
+
class SpecWrapper {
|
99
|
+
private:
|
100
|
+
friend class RetrySpec;
|
101
|
+
friend struct Error;
|
102
|
+
friend class ErrorMap;
|
103
|
+
|
104
|
+
RetrySpec *specptr;
|
105
|
+
SpecWrapper() : specptr(NULL) {}
|
106
|
+
SpecWrapper(const SpecWrapper& other) {
|
107
|
+
specptr = other.specptr;
|
108
|
+
if (specptr != NULL) {
|
109
|
+
specptr->ref();
|
110
|
+
}
|
111
|
+
}
|
112
|
+
~SpecWrapper() {
|
113
|
+
if (specptr) {
|
114
|
+
specptr->unref();
|
115
|
+
}
|
116
|
+
specptr = NULL;
|
117
|
+
}
|
118
|
+
};
|
119
|
+
|
120
|
+
struct Error {
|
121
|
+
uint16_t code;
|
122
|
+
std::string shortname;
|
123
|
+
std::string description;
|
124
|
+
std::set<ErrorAttribute> attributes;
|
125
|
+
SpecWrapper retry;
|
126
|
+
|
127
|
+
Error() : code(-1) {
|
128
|
+
}
|
129
|
+
|
130
|
+
bool isValid() const {
|
131
|
+
return code != uint16_t(-1);
|
132
|
+
}
|
133
|
+
|
134
|
+
bool hasAttribute(ErrorAttribute attr) const {
|
135
|
+
return attributes.find(attr) != attributes.end();
|
136
|
+
}
|
137
|
+
|
138
|
+
RetrySpec *getRetrySpec() const;
|
139
|
+
};
|
140
|
+
|
141
|
+
class ErrorMap {
|
142
|
+
public:
|
143
|
+
enum ParseStatus {
|
144
|
+
/** Couldn't parse JSON!*/
|
145
|
+
PARSE_ERROR,
|
146
|
+
|
147
|
+
/** Version is too high */
|
148
|
+
UNKNOWN_VERSION,
|
149
|
+
|
150
|
+
/** Current version/revision is higher or equal */
|
151
|
+
NOT_UPDATED,
|
152
|
+
|
153
|
+
/** Updated */
|
154
|
+
UPDATED
|
155
|
+
};
|
156
|
+
|
157
|
+
ErrorMap();
|
158
|
+
ParseStatus parse(const char *s, size_t n, std::string& errmsg);
|
159
|
+
ParseStatus parse(const char *s, size_t n) {
|
160
|
+
std::string tmp;
|
161
|
+
return parse(s, n, tmp);
|
162
|
+
}
|
163
|
+
size_t getVersion() const { return version; }
|
164
|
+
size_t getRevision() const { return revision; };
|
165
|
+
const Error& getError(uint16_t code) const;
|
166
|
+
bool isLoaded() const {
|
167
|
+
return !errors.empty();
|
168
|
+
}
|
169
|
+
|
170
|
+
private:
|
171
|
+
static const uint32_t MAX_VERSION;
|
172
|
+
ErrorMap(const ErrorMap&);
|
173
|
+
typedef std::map<uint16_t, Error> MapType;
|
174
|
+
MapType errors;
|
175
|
+
uint32_t revision;
|
176
|
+
uint32_t version;
|
177
|
+
};
|
178
|
+
|
179
|
+
} // namespace
|
180
|
+
} // namespace
|
181
|
+
|
182
|
+
typedef lcb::errmap::ErrorMap* lcb_pERRMAP;
|
183
|
+
#else
|
184
|
+
typedef struct lcb_ERRMAP* lcb_pERRMAP;
|
185
|
+
#endif /* __cplusplus */
|
186
|
+
|
187
|
+
#ifdef __cplusplus
|
188
|
+
extern "C" {
|
189
|
+
#endif
|
190
|
+
|
191
|
+
lcb_pERRMAP lcb_errmap_new(void);
|
192
|
+
void lcb_errmap_free(lcb_pERRMAP);
|
193
|
+
|
194
|
+
#ifdef __cplusplus
|
195
|
+
}
|
196
|
+
#endif
|
197
|
+
|
198
|
+
#endif /* LCB_ERRMAP_H */
|
@@ -18,31 +18,6 @@
|
|
18
18
|
#include "internal.h"
|
19
19
|
#include "packetutils.h"
|
20
20
|
#include <bucketconfig/clconfig.h>
|
21
|
-
LCB_INTERNAL_API
|
22
|
-
lcb::Server *
|
23
|
-
lcb_find_server_by_host(lcb_t instance, const lcb_host_t *host)
|
24
|
-
{
|
25
|
-
mc_CMDQUEUE *cq = &instance->cmdq;
|
26
|
-
unsigned ii;
|
27
|
-
for (ii = 0; ii < cq->npipelines; ii++) {
|
28
|
-
lcb::Server *server = static_cast<lcb::Server*>(cq->pipelines[ii]);
|
29
|
-
if (lcb_host_equals(&server->get_host(), host)) {
|
30
|
-
return server;
|
31
|
-
}
|
32
|
-
}
|
33
|
-
return NULL;
|
34
|
-
}
|
35
|
-
|
36
|
-
LCB_INTERNAL_API
|
37
|
-
lcb::Server *
|
38
|
-
lcb_find_server_by_index(lcb_t instance, int ix)
|
39
|
-
{
|
40
|
-
mc_CMDQUEUE *cq = &instance->cmdq;
|
41
|
-
if (ix < 0 || ix >= static_cast<int>(cq->npipelines)) {
|
42
|
-
return NULL;
|
43
|
-
}
|
44
|
-
return static_cast<lcb::Server*>(cq->pipelines[ix]);
|
45
|
-
}
|
46
21
|
|
47
22
|
static void
|
48
23
|
ext_callback_proxy(mc_PIPELINE *pl, mc_PACKET *req, lcb_error_t rc,
|
@@ -53,19 +28,18 @@ ext_callback_proxy(mc_PIPELINE *pl, mc_PACKET *req, lcb_error_t rc,
|
|
53
28
|
const lcb::MemcachedResponse *res =
|
54
29
|
reinterpret_cast<const lcb::MemcachedResponse*>(resdata);
|
55
30
|
|
56
|
-
|
57
|
-
|
31
|
+
lcb::clconfig::cccp_update(
|
32
|
+
rd->cookie, rc, res->body<const char*>(), res->bodylen(),
|
33
|
+
&server->get_host());
|
58
34
|
free(rd);
|
59
35
|
}
|
60
36
|
|
61
37
|
static mc_REQDATAPROCS procs = { ext_callback_proxy };
|
62
38
|
|
63
|
-
LCB_INTERNAL_API
|
64
39
|
lcb_error_t
|
65
|
-
|
40
|
+
lcb_st::request_config(const void *cookie_, lcb::Server *server)
|
66
41
|
{
|
67
42
|
lcb_error_t err;
|
68
|
-
mc_CMDQUEUE *cq = &instance->cmdq;
|
69
43
|
mc_PACKET *packet;
|
70
44
|
mc_REQDATAEX *rd;
|
71
45
|
|
@@ -82,7 +56,7 @@ lcb_getconfig(lcb_t instance, const void *cookie, lcb::Server *server)
|
|
82
56
|
|
83
57
|
rd = reinterpret_cast<mc_REQDATAEX*>(calloc(1, sizeof(*rd)));
|
84
58
|
rd->procs = &procs;
|
85
|
-
rd->cookie =
|
59
|
+
rd->cookie = cookie_;
|
86
60
|
rd->start = gethrtime();
|
87
61
|
packet->u_rdata.exdata = rd;
|
88
62
|
packet->flags |= MCREQ_F_REQEXT;
|
@@ -92,8 +66,8 @@ lcb_getconfig(lcb_t instance, const void *cookie, lcb::Server *server)
|
|
92
66
|
hdr.opaque(packet->opaque);
|
93
67
|
memcpy(SPAN_BUFFER(&packet->kh_span), hdr.data(), hdr.size());
|
94
68
|
|
95
|
-
mcreq_sched_enter(
|
69
|
+
mcreq_sched_enter(&cmdq);
|
96
70
|
mcreq_sched_add(server, packet);
|
97
|
-
mcreq_sched_leave(
|
71
|
+
mcreq_sched_leave(&cmdq, 1);
|
98
72
|
return LCB_SUCCESS;
|
99
73
|
}
|