libcouchbase 0.0.9 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +4 -4
- data/README.md +4 -0
- data/ext/libcouchbase/CMakeLists.txt +1 -1
- data/ext/libcouchbase/RELEASE_NOTES.markdown +42 -0
- data/ext/libcouchbase/cmake/Modules/GetVersionInfo.cmake +3 -3
- data/ext/libcouchbase/cmake/source_files.cmake +1 -0
- data/ext/libcouchbase/include/libcouchbase/cntl.h +27 -1
- data/ext/libcouchbase/include/libcouchbase/couchbase.h +0 -10
- data/ext/libcouchbase/include/libcouchbase/error.h +8 -1
- data/ext/libcouchbase/include/memcached/protocol_binary.h +12 -3
- data/ext/libcouchbase/src/auth.cc +0 -4
- data/ext/libcouchbase/src/cntl.cc +11 -1
- data/ext/libcouchbase/src/connspec.cc +18 -0
- data/ext/libcouchbase/src/connspec.h +10 -0
- data/ext/libcouchbase/src/dns-srv.cc +13 -14
- data/ext/libcouchbase/src/errmap.cc +107 -0
- data/ext/libcouchbase/src/errmap.h +113 -0
- data/ext/libcouchbase/src/hostlist.cc +0 -35
- data/ext/libcouchbase/src/hostlist.h +38 -64
- data/ext/libcouchbase/src/http/http.cc +6 -1
- data/ext/libcouchbase/src/instance.cc +1 -1
- data/ext/libcouchbase/src/internal.h +10 -0
- data/ext/libcouchbase/src/mcserver/mcserver.cc +119 -3
- data/ext/libcouchbase/src/mcserver/mcserver.h +3 -1
- data/ext/libcouchbase/src/mcserver/negotiate.cc +130 -37
- data/ext/libcouchbase/src/nodeinfo.cc +1 -1
- data/ext/libcouchbase/src/settings.c +3 -0
- data/ext/libcouchbase/src/settings.h +5 -0
- data/ext/libcouchbase/src/ssl/ssl_common.c +2 -0
- data/ext/libcouchbase/tests/basic/t_host.cc +67 -75
- data/ext/libcouchbase/tests/iotests/mock-environment.h +2 -1
- data/ext/libcouchbase/tests/iotests/t_confmon.cc +3 -4
- data/ext/libcouchbase/tests/iotests/t_errmap.cc +97 -0
- data/lib/libcouchbase/bucket.rb +27 -12
- data/lib/libcouchbase/callbacks.rb +1 -1
- data/lib/libcouchbase/connection.rb +18 -5
- data/lib/libcouchbase/version.rb +1 -1
- data/spec/connection_spec.rb +1 -1
- metadata +5 -2
@@ -0,0 +1,113 @@
|
|
1
|
+
#ifndef LCB_ERRMAP_H
|
2
|
+
#define LCB_ERRMAP_H
|
3
|
+
|
4
|
+
#ifdef __cplusplus
|
5
|
+
|
6
|
+
#include <map>
|
7
|
+
#include <set>
|
8
|
+
#include <string>
|
9
|
+
|
10
|
+
namespace lcb {
|
11
|
+
namespace errmap {
|
12
|
+
|
13
|
+
enum ErrorAttribute {
|
14
|
+
#define LCB_XERRMAP_ATTRIBUTES(X) \
|
15
|
+
X(TEMPORARY, "temp") \
|
16
|
+
X(SUBDOC, "subdoc") \
|
17
|
+
X(RETRY_NOW, "retry-now") \
|
18
|
+
X(RETRY_LATER, "retry-later") \
|
19
|
+
X(INVALID_INPUT, "invalid-input") \
|
20
|
+
X(NOT_ENABLED, "support") \
|
21
|
+
X(AUTH, "auth") \
|
22
|
+
X(CONN_STATE_INVALIDATED, "conn-state-invalidated") \
|
23
|
+
X(CONSTRAINT_FAILURE, "item-only") \
|
24
|
+
X(RETRY_EXP_BACKOFF, "retry-exp-backoff") \
|
25
|
+
X(RETRY_LINEAR_BACKOFF, "retry-linear-backoff") \
|
26
|
+
X(INTERNAL, "internal") \
|
27
|
+
X(DCP, "dcp") \
|
28
|
+
X(FETCH_CONFIG, "fetch-config") \
|
29
|
+
X(SPECIAL_HANDLING, "special-handling")
|
30
|
+
|
31
|
+
#define X(c, s) c,
|
32
|
+
LCB_XERRMAP_ATTRIBUTES(X)
|
33
|
+
#undef X
|
34
|
+
|
35
|
+
INVALID_ATTRIBUTE
|
36
|
+
};
|
37
|
+
|
38
|
+
struct Error {
|
39
|
+
uint16_t code;
|
40
|
+
std::string shortname;
|
41
|
+
std::string description;
|
42
|
+
std::set<ErrorAttribute> attributes;
|
43
|
+
|
44
|
+
Error() : code(-1) {
|
45
|
+
}
|
46
|
+
|
47
|
+
bool isValid() const {
|
48
|
+
return code != uint16_t(-1);
|
49
|
+
}
|
50
|
+
|
51
|
+
bool hasAttribute(ErrorAttribute attr) const {
|
52
|
+
return attributes.find(attr) != attributes.end();
|
53
|
+
}
|
54
|
+
};
|
55
|
+
|
56
|
+
class ErrorMap {
|
57
|
+
public:
|
58
|
+
enum ParseStatus {
|
59
|
+
/** Couldn't parse JSON!*/
|
60
|
+
PARSE_ERROR,
|
61
|
+
|
62
|
+
/** Version is too high */
|
63
|
+
UNKNOWN_VERSION,
|
64
|
+
|
65
|
+
/** Current version/revision is higher or equal */
|
66
|
+
NOT_UPDATED,
|
67
|
+
|
68
|
+
/** Updated */
|
69
|
+
UPDATED
|
70
|
+
};
|
71
|
+
|
72
|
+
ErrorMap();
|
73
|
+
ParseStatus parse(const char *s, size_t n, std::string& errmsg);
|
74
|
+
ParseStatus parse(const char *s, size_t n) {
|
75
|
+
std::string tmp;
|
76
|
+
return parse(s, n, tmp);
|
77
|
+
}
|
78
|
+
size_t getVersion() const { return version; }
|
79
|
+
size_t getRevision() const { return revision; };
|
80
|
+
const Error& getError(uint16_t code) const;
|
81
|
+
bool isLoaded() const {
|
82
|
+
return !errors.empty();
|
83
|
+
}
|
84
|
+
|
85
|
+
private:
|
86
|
+
static const uint32_t MAX_VERSION;
|
87
|
+
ErrorMap(const ErrorMap&);
|
88
|
+
typedef std::map<uint16_t, Error> MapType;
|
89
|
+
MapType errors;
|
90
|
+
uint32_t revision;
|
91
|
+
uint32_t version;
|
92
|
+
};
|
93
|
+
|
94
|
+
} // namespace
|
95
|
+
} // namespace
|
96
|
+
|
97
|
+
typedef lcb::errmap::ErrorMap* lcb_pERRMAP;
|
98
|
+
#else
|
99
|
+
typedef struct lcb_ERRMAP* lcb_pERRMAP;
|
100
|
+
#endif /* __cplusplus */
|
101
|
+
|
102
|
+
#ifdef __cplusplus
|
103
|
+
extern "C" {
|
104
|
+
#endif
|
105
|
+
|
106
|
+
lcb_pERRMAP lcb_errmap_new(void);
|
107
|
+
void lcb_errmap_free(lcb_pERRMAP);
|
108
|
+
|
109
|
+
#ifdef __cplusplus
|
110
|
+
}
|
111
|
+
#endif
|
112
|
+
|
113
|
+
#endif /* LCB_ERRMAP_H */
|
@@ -263,38 +263,3 @@ Hostlist::assign(const Hostlist& src)
|
|
263
263
|
}
|
264
264
|
return *this;
|
265
265
|
}
|
266
|
-
|
267
|
-
extern "C" {
|
268
|
-
Hostlist* hostlist_create(void) { return new Hostlist(); }
|
269
|
-
void hostlist_destroy(hostlist_t l) { delete l; }
|
270
|
-
void hostlist_clear(hostlist_t l) { l->clear(); }
|
271
|
-
void hostlist_reset_strlist(hostlist_t l) { l->reset_strlist(); }
|
272
|
-
lcb_error_t hostlist_add_host(hostlist_t l, const lcb_host_t *h) { l->add(*h); return LCB_SUCCESS; }
|
273
|
-
lcb_host_t *hostlist_shift_next(hostlist_t hl, int wrap) { return hl->next(wrap); }
|
274
|
-
int hostlist_finished(hostlist_t l) { return l->ix == l->hosts.size(); }
|
275
|
-
size_t hostlist_size(hostlist_t l) { return l->size(); }
|
276
|
-
void hostlist_randomize(hostlist_t l) { l->randomize(); }
|
277
|
-
|
278
|
-
lcb_error_t
|
279
|
-
hostlist_add_string(hostlist_t hl, const char *spec, int len, int deflport) {
|
280
|
-
return hl->add(spec, len, deflport);
|
281
|
-
}
|
282
|
-
|
283
|
-
void
|
284
|
-
hostlist_assign(hostlist_t dst, const hostlist_t src) {
|
285
|
-
dst->assign(*src);
|
286
|
-
}
|
287
|
-
|
288
|
-
const lcb_host_t*
|
289
|
-
hostlist_get(const hostlist_t h, size_t ix) { return &h->hosts[ix]; }
|
290
|
-
|
291
|
-
const char * const *
|
292
|
-
hostlist_strents(const hostlist_t h) {
|
293
|
-
h->ensure_strlist();
|
294
|
-
if (h->hoststrs.size()) {
|
295
|
-
return &h->hoststrs[0];
|
296
|
-
} else {
|
297
|
-
return NULL;
|
298
|
-
}
|
299
|
-
}
|
300
|
-
}
|
@@ -45,56 +45,74 @@ struct Hostlist {
|
|
45
45
|
Hostlist() : ix(0) {}
|
46
46
|
~Hostlist();
|
47
47
|
|
48
|
-
|
48
|
+
/**
|
49
|
+
* Adds a string to the hostlist. See lcb_host_parse for details.
|
50
|
+
* Note that if the host already exists (see 'lcb_host_equals') it will
|
51
|
+
* not be added
|
52
|
+
* @param s the string to parse
|
53
|
+
* @param len the length of the string
|
54
|
+
* @param deflport If `s` does not contain an explicit port, use this
|
55
|
+
* port instead.
|
56
|
+
* @return LCB_EINVAL if the host string is not valid
|
57
|
+
*/
|
49
58
|
lcb_error_t add(const char *s, long len, int deflport);
|
50
59
|
lcb_error_t add(const char *s, int deflport) { return add(s, -1, deflport); }
|
60
|
+
void add(const lcb_host_t&);
|
61
|
+
|
51
62
|
bool exists(const lcb_host_t&) const;
|
52
63
|
bool exists(const char *hostport) const;
|
64
|
+
|
65
|
+
/**
|
66
|
+
* Return the next host in the list.
|
67
|
+
* @param wrap If the internal iterator has reached its limit, this
|
68
|
+
* indicates whether it should be reset, or if it should return NULL
|
69
|
+
* @return a new host if available, or NULL if the list is empty or the
|
70
|
+
* iterator is finished.
|
71
|
+
*/
|
53
72
|
lcb_host_t *next(bool wrap);
|
54
73
|
bool finished() const;
|
55
74
|
|
56
75
|
size_t size() const { return hosts.size(); }
|
57
76
|
bool empty() const { return hosts.empty(); }
|
58
77
|
Hostlist& assign(const Hostlist& other);
|
78
|
+
|
79
|
+
/** Clears the hostlist */
|
59
80
|
void clear() { hosts.clear(); reset_strlist(); ix = 0; }
|
81
|
+
|
82
|
+
/** Randomize the hostlist by shuffling the order. */
|
60
83
|
void randomize();
|
84
|
+
|
85
|
+
/**
|
86
|
+
* String list handling functions. These are used to return the hostlist via
|
87
|
+
* the API where we return a char*[] terminated by a NULL pointer.
|
88
|
+
*/
|
89
|
+
|
90
|
+
/** Ensure that the string list contains at least one entry */
|
61
91
|
void ensure_strlist();
|
92
|
+
|
93
|
+
/** Frees the current list of strings */
|
62
94
|
void reset_strlist();
|
95
|
+
|
96
|
+
const char * const *get_strlist() const { return &hoststrs[0]; }
|
97
|
+
|
63
98
|
unsigned int ix;
|
64
99
|
const lcb_host_t& operator[](size_t ix_) const { return hosts[ix_]; }
|
65
100
|
|
66
101
|
std::vector<lcb_host_t> hosts;
|
67
102
|
std::vector<const char *> hoststrs;
|
68
|
-
static Hostlist* from_c(hostlist_st* src) {
|
69
|
-
return reinterpret_cast<Hostlist*>(src);
|
70
|
-
}
|
71
103
|
};
|
72
104
|
}
|
73
105
|
typedef lcb::Hostlist* hostlist_t;
|
74
106
|
|
75
107
|
struct hostlist_st : lcb::Hostlist {
|
108
|
+
hostlist_st() : Hostlist() {
|
109
|
+
}
|
76
110
|
};
|
77
111
|
#endif
|
78
112
|
|
79
113
|
#ifdef __cplusplus
|
80
114
|
extern "C" {
|
81
115
|
#endif
|
82
|
-
|
83
|
-
/**
|
84
|
-
* Creates a new hostlist. Returns NULL on allocation failure
|
85
|
-
*/
|
86
|
-
hostlist_t hostlist_create(void);
|
87
|
-
|
88
|
-
/**
|
89
|
-
* Frees resources associated with the hostlist
|
90
|
-
*/
|
91
|
-
void hostlist_destroy(hostlist_t hostlist);
|
92
|
-
|
93
|
-
/**
|
94
|
-
* Clears the hostlist
|
95
|
-
*/
|
96
|
-
void hostlist_clear(hostlist_t hostlist);
|
97
|
-
|
98
116
|
/**
|
99
117
|
* Parses a string into a hostlist
|
100
118
|
* @param host the target host to populate
|
@@ -126,50 +144,6 @@ lcb_host_parse(lcb_host_t *host, const char *spec, int speclen, int deflport);
|
|
126
144
|
*/
|
127
145
|
int lcb_host_equals(const lcb_host_t *a, const lcb_host_t *b);
|
128
146
|
|
129
|
-
/**
|
130
|
-
* Adds a string to the hostlist. See lcb_host_parse for details.
|
131
|
-
* Note that if the host already exists (see 'lcb_host_equals') it will
|
132
|
-
* not be added
|
133
|
-
* @return LCB_EINVAL if the host string is not value, LCB_CLIENT_ENOMEM on
|
134
|
-
* allocation failure.
|
135
|
-
*/
|
136
|
-
lcb_error_t hostlist_add_string(hostlist_t hostlist,
|
137
|
-
const char *spec,
|
138
|
-
int speclen,
|
139
|
-
int deflport);
|
140
|
-
|
141
|
-
#define hostlist_add_stringz(hostlist, spec, deflport) \
|
142
|
-
hostlist_add_string(hostlist, spec, -1, deflport)
|
143
|
-
|
144
|
-
lcb_error_t hostlist_add_host(hostlist_t hostlist, const lcb_host_t *host);
|
145
|
-
|
146
|
-
/**
|
147
|
-
* Return the next host in the list.
|
148
|
-
* @param hostlist the hostlist to use
|
149
|
-
* @param rollover If the internal iterator has reached its limit, this
|
150
|
-
* indicates whether it should be reset, or if it should return NULL
|
151
|
-
* @return a new host if available, or NULL if the list is empty or the
|
152
|
-
* iterator is finished.
|
153
|
-
*/
|
154
|
-
lcb_host_t *hostlist_shift_next(hostlist_t hostlist, int rollover);
|
155
|
-
|
156
|
-
/**
|
157
|
-
* Randomize the hostlist
|
158
|
-
*/
|
159
|
-
void hostlist_randomize(hostlist_t hostlist);
|
160
|
-
|
161
|
-
/**
|
162
|
-
* String list handling functions. These are used to return the hostlist via
|
163
|
-
* the API where we return a char*[] terminated by a NULL pointer.
|
164
|
-
*/
|
165
|
-
void hostlist_reset_strlist(hostlist_t hostlist);
|
166
|
-
|
167
|
-
/** Whether the internal iterator has finished. */
|
168
|
-
int hostlist_finished(hostlist_t);
|
169
|
-
size_t hostlist_size(const hostlist_t hl);
|
170
|
-
void hostlist_assign(hostlist_t dst, const hostlist_t src);
|
171
|
-
const lcb_host_t *hostlist_get(const hostlist_t, size_t);
|
172
|
-
const char * const *hostlist_strents(const hostlist_t hl);
|
173
147
|
#ifdef __cplusplus
|
174
148
|
}
|
175
149
|
#endif
|
@@ -459,7 +459,12 @@ Request::setup_inputs(const lcb_CMDHTTP *cmd)
|
|
459
459
|
return rc;
|
460
460
|
}
|
461
461
|
|
462
|
-
|
462
|
+
std::string ua("libcouchbase/" LCB_VERSION_STRING);
|
463
|
+
if (instance->settings->client_string) {
|
464
|
+
ua.append(" ").append(instance->settings->client_string);
|
465
|
+
}
|
466
|
+
add_header("User-Agent", ua);
|
467
|
+
|
463
468
|
if (instance->http_sockpool->maxidle == 0 || !is_data_request()) {
|
464
469
|
add_header("Connection", "close");
|
465
470
|
}
|
@@ -129,7 +129,7 @@ lcb_st::process_dns_srv(Connspec& spec)
|
|
129
129
|
|
130
130
|
const Spechost& host = spec.hosts().front();
|
131
131
|
lcb_error_t rc = LCB_ERROR;
|
132
|
-
Hostlist* hl =
|
132
|
+
Hostlist* hl = dnssrv_getbslist(host.hostname.c_str(), host.isSSL(), rc);
|
133
133
|
|
134
134
|
if (hl == NULL) {
|
135
135
|
lcb_log(LOGARGS(this, INFO), "DNS SRV lookup failed: %s. Ignore this if not relying on DNS SRV records", lcb_strerror(this, rc));
|
@@ -165,6 +165,16 @@ struct lcb_st {
|
|
165
165
|
}
|
166
166
|
return bs_state->bootstrap(options);
|
167
167
|
}
|
168
|
+
|
169
|
+
lcbvb_CONFIG *getConfig() const {
|
170
|
+
return cur_configinfo->vbc;
|
171
|
+
}
|
172
|
+
|
173
|
+
int map_key(const std::string& key) {
|
174
|
+
int srvix, tmpvb;
|
175
|
+
lcbvb_map_key(getConfig(), key.c_str(), key.size(), &tmpvb, &srvix);
|
176
|
+
return srvix;
|
177
|
+
}
|
168
178
|
#endif
|
169
179
|
};
|
170
180
|
|
@@ -29,6 +29,8 @@
|
|
29
29
|
#define LOGARGS_T(lvl) LOGARGS(this, lvl)
|
30
30
|
|
31
31
|
#define LOGFMT "<%s:%s> (SRV=%p,IX=%d) "
|
32
|
+
#define PKTFMT "OP=0x%x, RC=0x%x, SEQ=%u"
|
33
|
+
#define PKTARGS(pkt) (pkt).opcode(), (pkt).status(), (pkt).opaque()
|
32
34
|
|
33
35
|
#define LOGID(server) get_ctx_host(server->connctx), get_ctx_port(server->connctx), (void*)server, server->index
|
34
36
|
#define LOGID_T() LOGID(this)
|
@@ -164,6 +166,107 @@ Server::handle_nmv(MemcachedResponse& resinfo, mc_PACKET *oldpkt)
|
|
164
166
|
return true;
|
165
167
|
}
|
166
168
|
|
169
|
+
/**
|
170
|
+
* Determine if this is an error code that we can pass to the user, or can
|
171
|
+
* otherwise handle "innately"
|
172
|
+
*/
|
173
|
+
static bool is_fastpath_error(uint16_t rc) {
|
174
|
+
switch (rc) {
|
175
|
+
case PROTOCOL_BINARY_RESPONSE_SUCCESS:
|
176
|
+
case PROTOCOL_BINARY_RESPONSE_KEY_ENOENT:
|
177
|
+
case PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS:
|
178
|
+
case PROTOCOL_BINARY_RESPONSE_E2BIG:
|
179
|
+
case PROTOCOL_BINARY_RESPONSE_NOT_STORED:
|
180
|
+
case PROTOCOL_BINARY_RESPONSE_DELTA_BADVAL:
|
181
|
+
case PROTOCOL_BINARY_RESPONSE_ERANGE:
|
182
|
+
case PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED:
|
183
|
+
case PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND:
|
184
|
+
case PROTOCOL_BINARY_RESPONSE_ETMPFAIL:
|
185
|
+
case PROTOCOL_BINARY_RESPONSE_ENOMEM:
|
186
|
+
case PROTOCOL_BINARY_RESPONSE_SUBDOC_PATH_ENOENT:
|
187
|
+
case PROTOCOL_BINARY_RESPONSE_SUBDOC_PATH_EEXISTS:
|
188
|
+
case PROTOCOL_BINARY_RESPONSE_SUBDOC_PATH_MISMATCH:
|
189
|
+
case PROTOCOL_BINARY_RESPONSE_SUBDOC_PATH_EINVAL:
|
190
|
+
case PROTOCOL_BINARY_RESPONSE_SUBDOC_PATH_E2BIG:
|
191
|
+
case PROTOCOL_BINARY_RESPONSE_SUBDOC_VALUE_CANTINSERT:
|
192
|
+
case PROTOCOL_BINARY_RESPONSE_SUBDOC_VALUE_ETOODEEP:
|
193
|
+
case PROTOCOL_BINARY_RESPONSE_SUBDOC_DOC_NOTJSON:
|
194
|
+
case PROTOCOL_BINARY_RESPONSE_SUBDOC_NUM_ERANGE:
|
195
|
+
case PROTOCOL_BINARY_RESPONSE_SUBDOC_DELTA_ERANGE:
|
196
|
+
case PROTOCOL_BINARY_RESPONSE_SUBDOC_INVALID_COMBO:
|
197
|
+
case PROTOCOL_BINARY_RESPONSE_SUBDOC_MULTI_PATH_FAILURE:
|
198
|
+
return true;
|
199
|
+
default:
|
200
|
+
if (rc >= 0xc0 && rc <= 0xcc) {
|
201
|
+
// other subdoc?
|
202
|
+
return true;
|
203
|
+
} else {
|
204
|
+
return false;
|
205
|
+
}
|
206
|
+
break;
|
207
|
+
}
|
208
|
+
}
|
209
|
+
|
210
|
+
/**
|
211
|
+
* Handle an unknown memcached error
|
212
|
+
*
|
213
|
+
* @param mcresp Response which contains the unknown error
|
214
|
+
* @param[out] newerr more user-friendly based on error map attributes
|
215
|
+
*
|
216
|
+
* @return true if this function handled the error specially (by disconnecting)
|
217
|
+
* or false if normal handling should continue.
|
218
|
+
*/
|
219
|
+
bool Server::handle_unknown_error(const MemcachedResponse& mcresp,
|
220
|
+
lcb_error_t& newerr) {
|
221
|
+
|
222
|
+
if (!settings->errmap->isLoaded() || !settings->use_errmap) {
|
223
|
+
// If there's no error map, just return false
|
224
|
+
return false;
|
225
|
+
}
|
226
|
+
|
227
|
+
// Look up the error map definition for this error
|
228
|
+
const errmap::Error& err = settings->errmap->getError(mcresp.status());
|
229
|
+
|
230
|
+
if (!err.isValid() || err.hasAttribute(errmap::SPECIAL_HANDLING)) {
|
231
|
+
lcb_log(LOGARGS_T(ERR), LOGFMT "Received error not in error map or requires special handling! " PKTFMT, LOGID_T(), PKTARGS(mcresp));
|
232
|
+
lcbio_ctx_senderr(connctx, LCB_PROTOCOL_ERROR);
|
233
|
+
return true;
|
234
|
+
} else {
|
235
|
+
lcb_log(LOGARGS_T(WARN), LOGFMT "Received server error %s (0x%x) on packet: " PKTFMT, LOGID_T(), err.shortname.c_str(), err.code, PKTARGS(mcresp));
|
236
|
+
}
|
237
|
+
|
238
|
+
if (err.hasAttribute(errmap::FETCH_CONFIG)) {
|
239
|
+
instance->bootstrap(BS_REFRESH_THROTTLE);
|
240
|
+
}
|
241
|
+
|
242
|
+
if (err.hasAttribute(errmap::TEMPORARY)) {
|
243
|
+
newerr = LCB_GENERIC_TMPERR;
|
244
|
+
}
|
245
|
+
|
246
|
+
if (err.hasAttribute(errmap::CONSTRAINT_FAILURE)) {
|
247
|
+
newerr = LCB_GENERIC_CONSTRAINT_ERR;
|
248
|
+
}
|
249
|
+
|
250
|
+
if (err.hasAttribute(errmap::AUTH)) {
|
251
|
+
newerr = LCB_AUTH_ERROR;
|
252
|
+
}
|
253
|
+
|
254
|
+
if (err.hasAttribute(errmap::SUBDOC) && newerr == LCB_SUCCESS) {
|
255
|
+
newerr = LCB_GENERIC_SUBDOCERR;
|
256
|
+
}
|
257
|
+
|
258
|
+
if (err.hasAttribute(errmap::CONN_STATE_INVALIDATED)) {
|
259
|
+
if (newerr != LCB_SUCCESS) {
|
260
|
+
newerr = LCB_ERROR;
|
261
|
+
}
|
262
|
+
lcbio_ctx_senderr(connctx, newerr);
|
263
|
+
return true;
|
264
|
+
}
|
265
|
+
|
266
|
+
return false;
|
267
|
+
|
268
|
+
}
|
269
|
+
|
167
270
|
/* This function is called within a loop to process a single packet.
|
168
271
|
*
|
169
272
|
* If a full packet is available, it will process the packet and return
|
@@ -224,7 +327,14 @@ Server::try_read(lcbio_CTX *ctx, rdb_IOROPE *ior)
|
|
224
327
|
return PKT_READ_COMPLETE;
|
225
328
|
}
|
226
329
|
|
227
|
-
|
330
|
+
lcb_error_t err_override = LCB_SUCCESS;
|
331
|
+
ReadState rdstate = PKT_READ_COMPLETE;
|
332
|
+
|
333
|
+
/* Check if the status code is one which must be handled carefully by the
|
334
|
+
* client */
|
335
|
+
if (is_fastpath_error(mcresp.status())) {
|
336
|
+
// Nothing here!
|
337
|
+
} else if (mcresp.status() == PROTOCOL_BINARY_RESPONSE_NOT_MY_VBUCKET) {
|
228
338
|
/* consume the header */
|
229
339
|
DO_ASSIGN_PAYLOAD()
|
230
340
|
if (!handle_nmv(mcresp, request)) {
|
@@ -232,13 +342,19 @@ Server::try_read(lcbio_CTX *ctx, rdb_IOROPE *ior)
|
|
232
342
|
}
|
233
343
|
DO_SWALLOW_PAYLOAD()
|
234
344
|
goto GT_DONE;
|
345
|
+
} else if (handle_unknown_error(mcresp, err_override)) {
|
346
|
+
DO_ASSIGN_PAYLOAD()
|
347
|
+
mcreq_dispatch_response(this, request, &mcresp, err_override);
|
348
|
+
DO_SWALLOW_PAYLOAD()
|
349
|
+
rdstate = PKT_READ_ABORT;
|
350
|
+
goto GT_DONE;
|
235
351
|
}
|
236
352
|
|
237
353
|
/* Figure out if the request is 'ufwd' or not */
|
238
354
|
if (!(request->flags & MCREQ_F_UFWD)) {
|
239
355
|
DO_ASSIGN_PAYLOAD();
|
240
356
|
mcresp.bufh = rdb_get_first_segment(ior);
|
241
|
-
mcreq_dispatch_response(this, request, &mcresp,
|
357
|
+
mcreq_dispatch_response(this, request, &mcresp, err_override);
|
242
358
|
DO_SWALLOW_PAYLOAD()
|
243
359
|
|
244
360
|
} else {
|
@@ -265,7 +381,7 @@ Server::try_read(lcbio_CTX *ctx, rdb_IOROPE *ior)
|
|
265
381
|
if (is_last) {
|
266
382
|
mcreq_packet_handled(this, request);
|
267
383
|
}
|
268
|
-
return
|
384
|
+
return rdstate;
|
269
385
|
}
|
270
386
|
|
271
387
|
static void
|