libcouchbase 0.0.9 → 0.1.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/.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
|