libcouchbase 0.0.7 → 0.0.8
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/.gitignore +2 -0
- data/ext/libcouchbase/CMakeLists.txt +5 -7
- data/ext/libcouchbase/README.markdown +2 -2
- data/ext/libcouchbase/RELEASE_NOTES.markdown +49 -0
- data/ext/libcouchbase/cmake/Modules/ConfigureDtrace.cmake +11 -0
- data/ext/libcouchbase/cmake/Modules/GenerateConfigDotH.cmake +2 -0
- data/ext/libcouchbase/cmake/Modules/GetLibcouchbaseFlags.cmake +2 -1
- data/ext/libcouchbase/cmake/Modules/GetVersionInfo.cmake +3 -3
- data/ext/libcouchbase/cmake/config-cmake.h.in +2 -0
- data/ext/libcouchbase/cmake/defs.mk.in +0 -2
- data/ext/libcouchbase/cmake/source_files.cmake +34 -14
- data/ext/libcouchbase/configure.pl +1 -1
- data/ext/libcouchbase/contrib/genhash/genhash.h +6 -0
- data/ext/libcouchbase/include/libcouchbase/auth.h +10 -0
- data/ext/libcouchbase/include/libcouchbase/couchbase.h +10 -0
- data/ext/libcouchbase/include/libcouchbase/error.h +7 -0
- data/ext/libcouchbase/include/libcouchbase/n1ql.h +13 -1
- data/ext/libcouchbase/include/libcouchbase/plugins/io/bsdio-inl.c +1 -1
- data/ext/libcouchbase/include/libcouchbase/subdoc.h +9 -0
- 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 +21 -1132
- 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 +1 -0
- data/ext/libcouchbase/src/auth.cc +10 -0
- data/ext/libcouchbase/src/bootstrap.cc +216 -0
- data/ext/libcouchbase/src/bootstrap.h +50 -39
- data/ext/libcouchbase/src/bucketconfig/bc_cccp.cc +455 -0
- data/ext/libcouchbase/src/bucketconfig/bc_file.cc +281 -0
- data/ext/libcouchbase/src/bucketconfig/bc_http.cc +528 -0
- data/ext/libcouchbase/src/bucketconfig/bc_http.h +50 -25
- data/ext/libcouchbase/src/bucketconfig/bc_mcraw.cc +115 -0
- data/ext/libcouchbase/src/bucketconfig/clconfig.h +407 -386
- data/ext/libcouchbase/src/bucketconfig/confmon.cc +378 -0
- data/ext/libcouchbase/src/cbft.cc +22 -27
- data/ext/libcouchbase/src/cntl.cc +24 -24
- data/ext/libcouchbase/src/connspec.cc +30 -1
- data/ext/libcouchbase/src/connspec.h +17 -0
- data/ext/libcouchbase/src/dns-srv.cc +143 -0
- data/ext/libcouchbase/src/{dump.c → dump.cc} +8 -11
- data/ext/libcouchbase/src/getconfig.cc +73 -0
- data/ext/libcouchbase/src/handler.cc +84 -85
- data/ext/libcouchbase/src/hostlist.cc +0 -1
- data/ext/libcouchbase/src/hostlist.h +6 -1
- data/ext/libcouchbase/src/http/http-priv.h +125 -112
- data/ext/libcouchbase/src/http/http.cc +9 -29
- data/ext/libcouchbase/src/http/http.h +1 -34
- data/ext/libcouchbase/src/http/http_io.cc +22 -26
- data/ext/libcouchbase/src/instance.cc +102 -28
- data/ext/libcouchbase/src/internal.h +47 -29
- data/ext/libcouchbase/src/jsparse/parser.cc +146 -202
- data/ext/libcouchbase/src/jsparse/parser.h +91 -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 +562 -0
- data/ext/libcouchbase/src/lcbio/connect.h +9 -2
- data/ext/libcouchbase/src/lcbio/ctx.c +1 -1
- data/ext/libcouchbase/src/lcbio/iotable.h +61 -16
- data/ext/libcouchbase/src/lcbio/ioutils.h +1 -1
- data/ext/libcouchbase/src/lcbio/manager.c +2 -2
- data/ext/libcouchbase/src/lcbio/timer-cxx.h +87 -0
- data/ext/libcouchbase/src/mc/mcreq.h +9 -2
- data/ext/libcouchbase/src/mcserver/mcserver.cc +723 -0
- data/ext/libcouchbase/src/mcserver/mcserver.h +160 -70
- data/ext/libcouchbase/src/mcserver/negotiate.cc +118 -152
- data/ext/libcouchbase/src/mcserver/negotiate.h +85 -74
- 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 +56 -32
- data/ext/libcouchbase/src/{newconfig.c → newconfig.cc} +42 -70
- data/ext/libcouchbase/src/nodeinfo.cc +4 -8
- 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-cas.c → durability-cas.cc} +92 -76
- data/ext/libcouchbase/src/operations/{durability-seqno.c → durability-seqno.cc} +55 -49
- data/ext/libcouchbase/src/operations/durability.cc +643 -0
- data/ext/libcouchbase/src/operations/durability_internal.h +212 -124
- data/ext/libcouchbase/src/operations/{get.c → get.cc} +24 -26
- data/ext/libcouchbase/src/operations/{observe-seqno.c → observe-seqno.cc} +5 -8
- data/ext/libcouchbase/src/operations/{observe.c → observe.cc} +69 -94
- 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.c → stats.cc} +66 -78
- data/ext/libcouchbase/src/operations/{store.c → store.cc} +27 -32
- data/ext/libcouchbase/src/operations/subdoc.cc +38 -18
- data/ext/libcouchbase/src/operations/{touch.c → touch.cc} +0 -0
- data/ext/libcouchbase/src/packetutils.h +200 -137
- data/ext/libcouchbase/src/probes.d +1 -1
- data/ext/libcouchbase/src/{retrychk.c → retrychk.cc} +3 -4
- data/ext/libcouchbase/src/retryq.cc +394 -0
- data/ext/libcouchbase/src/retryq.h +116 -104
- data/ext/libcouchbase/src/settings.h +2 -1
- data/ext/libcouchbase/src/ssl/ssl_c.c +1 -0
- data/ext/libcouchbase/src/ssl/ssl_e.c +0 -1
- data/ext/libcouchbase/src/trace.h +8 -8
- data/ext/libcouchbase/src/vbucket/vbucket.c +0 -1
- 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/src/{wait.c → wait.cc} +12 -17
- data/ext/libcouchbase/tests/basic/t_connstr.cc +89 -50
- data/ext/libcouchbase/tests/basic/t_jsparse.cc +27 -78
- data/ext/libcouchbase/tests/basic/t_packet.cc +35 -42
- data/ext/libcouchbase/tests/htparse/t_basic.cc +58 -78
- data/ext/libcouchbase/tests/iotests/t_confmon.cc +94 -111
- data/ext/libcouchbase/tests/iotests/t_sched.cc +1 -2
- data/ext/libcouchbase/tests/mc/t_alloc.cc +9 -9
- data/ext/libcouchbase/tools/cbc-pillowfight.cc +1 -1
- data/lib/libcouchbase/version.rb +1 -1
- metadata +36 -39
- data/ext/libcouchbase/include/memcached/vbucket.h +0 -42
- data/ext/libcouchbase/src/bootstrap.c +0 -269
- data/ext/libcouchbase/src/bucketconfig/bc_cccp.c +0 -495
- 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/getconfig.c +0 -100
- data/ext/libcouchbase/src/lcbht/lcbht.c +0 -282
- data/ext/libcouchbase/src/lcbio/connect.c +0 -557
- data/ext/libcouchbase/src/mcserver/mcserver.c +0 -784
- data/ext/libcouchbase/src/operations/durability.c +0 -668
- data/ext/libcouchbase/src/packetutils.c +0 -60
- data/ext/libcouchbase/src/retryq.c +0 -424
- 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,668 +0,0 @@
|
|
|
1
|
-
/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
2
|
-
/*
|
|
3
|
-
* Copyright 2012 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
|
-
#define LCBDUR_PRIV_SYMS 1
|
|
19
|
-
|
|
20
|
-
#include "internal.h"
|
|
21
|
-
#include "durability_internal.h"
|
|
22
|
-
#include <lcbio/iotable.h>
|
|
23
|
-
#define LOGARGS(c, lvl) (c)->instance->settings, "endure", LCB_LOG_##lvl, __FILE__, __LINE__
|
|
24
|
-
|
|
25
|
-
static void timer_callback(lcb_socket_t sock, short which, void *arg);
|
|
26
|
-
static void poll_once(lcb_DURSET *dset);
|
|
27
|
-
|
|
28
|
-
int
|
|
29
|
-
lcbdur_ent_check_done(lcb_DURITEM *ent)
|
|
30
|
-
{
|
|
31
|
-
lcb_DURABILITYOPTSv0 *opts = &ent->parent->opts;
|
|
32
|
-
|
|
33
|
-
if (!RESFLD(ent, exists_master)) {
|
|
34
|
-
/** Primary cache doesn't have correct version */
|
|
35
|
-
return 0;
|
|
36
|
-
}
|
|
37
|
-
if (opts->persist_to) {
|
|
38
|
-
if (!RESFLD(ent, persisted_master)) {
|
|
39
|
-
return 0;
|
|
40
|
-
}
|
|
41
|
-
if (RESFLD(ent, npersisted) < opts->persist_to) {
|
|
42
|
-
return 0;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (opts->replicate_to) {
|
|
47
|
-
if (RESFLD(ent, nreplicated) < opts->replicate_to) {
|
|
48
|
-
return 0;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
return 1;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
static int
|
|
56
|
-
server_criteria_satisfied(const lcb_DURITEM *item,
|
|
57
|
-
const lcbdur_SERVINFO *info, int is_master)
|
|
58
|
-
{
|
|
59
|
-
const lcb_DURSET *dset = item->parent;
|
|
60
|
-
if (!info->exists) {
|
|
61
|
-
return 0;
|
|
62
|
-
}
|
|
63
|
-
if (info->persisted) {
|
|
64
|
-
return 1;
|
|
65
|
-
}
|
|
66
|
-
if (DSET_OPTFLD(dset, persist_to) == 0) {
|
|
67
|
-
return 1;
|
|
68
|
-
}
|
|
69
|
-
if (DSET_OPTFLD(dset, persist_to) == 1 && !is_master) {
|
|
70
|
-
return 1;
|
|
71
|
-
}
|
|
72
|
-
return 0;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
void
|
|
76
|
-
lcbdur_prepare_item(lcb_DURITEM *ent, lcb_U16 *ixarray, size_t *nitems)
|
|
77
|
-
{
|
|
78
|
-
size_t ii, oix = 0, maxix = 0;
|
|
79
|
-
lcb_DURSET *dset = ent->parent;
|
|
80
|
-
lcb_t instance = dset->instance;
|
|
81
|
-
lcbvb_CONFIG *vbc = LCBT_VBCONFIG(instance);
|
|
82
|
-
|
|
83
|
-
RESFLD(ent, persisted_master) = 0;
|
|
84
|
-
RESFLD(ent, exists_master) = 0;
|
|
85
|
-
RESFLD(ent, npersisted) = 0;
|
|
86
|
-
RESFLD(ent, nreplicated) = 0;
|
|
87
|
-
RESFLD(ent, cas) = 0;
|
|
88
|
-
RESFLD(ent, rc) = LCB_SUCCESS;
|
|
89
|
-
|
|
90
|
-
if (DSET_OPTFLD(dset, persist_to) == 1 &&
|
|
91
|
-
DSET_OPTFLD(dset, replicate_to) == 0) {
|
|
92
|
-
maxix = 1; /* Only master! */
|
|
93
|
-
} else {
|
|
94
|
-
maxix = LCBT_NREPLICAS(instance) + 1;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
for (ii = 0; ii < maxix; ii++) {
|
|
98
|
-
int cur_ix;
|
|
99
|
-
lcbdur_SERVINFO *info = &ent->sinfo[ii];
|
|
100
|
-
const mc_SERVER *s_exp;
|
|
101
|
-
|
|
102
|
-
cur_ix = lcbvb_vbserver(vbc, ent->vbid, ii);
|
|
103
|
-
if (cur_ix < 0) {
|
|
104
|
-
memset(info, 0, sizeof(*info));
|
|
105
|
-
continue;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
s_exp = LCBT_GET_SERVER(instance, cur_ix);
|
|
109
|
-
if (s_exp != info->server) {
|
|
110
|
-
memset(info, 0, sizeof(*info));
|
|
111
|
-
|
|
112
|
-
} else if (server_criteria_satisfied(ent, info, ii==0)) {
|
|
113
|
-
/* Update counters as required */
|
|
114
|
-
if (ii == 0) {
|
|
115
|
-
RESFLD(ent, exists_master) = 1;
|
|
116
|
-
} else {
|
|
117
|
-
RESFLD(ent, nreplicated)++;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
if (info->persisted) {
|
|
121
|
-
RESFLD(ent, npersisted)++;
|
|
122
|
-
if (ii == 0) {
|
|
123
|
-
RESFLD(ent, persisted_master) = 1;
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
continue;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/* Otherwise, write the expected server out */
|
|
130
|
-
ixarray[oix++] = s_exp->pipeline.index;
|
|
131
|
-
}
|
|
132
|
-
*nitems = oix;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
void
|
|
136
|
-
lcbdur_update_item(lcb_DURITEM *item, int flags, int srvix)
|
|
137
|
-
{
|
|
138
|
-
lcbdur_SERVINFO *info;
|
|
139
|
-
lcb_t instance;
|
|
140
|
-
int is_master;
|
|
141
|
-
const mc_SERVER *server;
|
|
142
|
-
|
|
143
|
-
if (!flags || item->done) {
|
|
144
|
-
return;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
info = lcbdur_ent_getinfo(item, srvix);
|
|
148
|
-
if (!info) {
|
|
149
|
-
lcb_log(LOGARGS(item->parent, DEBUG), "Ignoring response from server %d. Not a master or replica for vBucket %d", srvix, item->vbid);
|
|
150
|
-
return;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
instance = item->parent->instance;
|
|
154
|
-
is_master = lcbvb_vbmaster(LCBT_VBCONFIG(instance), item->vbid) == srvix;
|
|
155
|
-
server = LCBT_GET_SERVER(instance, srvix);
|
|
156
|
-
|
|
157
|
-
memset(info, 0, sizeof(*info));
|
|
158
|
-
info->server = server;
|
|
159
|
-
|
|
160
|
-
if (flags & LCBDUR_UPDATE_PERSISTED) {
|
|
161
|
-
info->persisted = 1;
|
|
162
|
-
RESFLD(item, npersisted)++;
|
|
163
|
-
if (is_master) {
|
|
164
|
-
RESFLD(item, persisted_master) = 1;
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
if (flags & LCBDUR_UPDATE_REPLICATED) {
|
|
168
|
-
info->exists = 1;
|
|
169
|
-
if (is_master) {
|
|
170
|
-
RESFLD(item, exists_master) = 1;
|
|
171
|
-
} else {
|
|
172
|
-
RESFLD(item, nreplicated)++;
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
if (lcbdur_ent_check_done(item)) {
|
|
176
|
-
RESFLD(item, rc) = LCB_SUCCESS;
|
|
177
|
-
lcbdur_ent_finish(item);
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
lcbdur_SERVINFO *
|
|
182
|
-
lcbdur_ent_getinfo(lcb_DURITEM *item, int srvix)
|
|
183
|
-
{
|
|
184
|
-
size_t ii;
|
|
185
|
-
lcb_t instance = item->parent->instance;
|
|
186
|
-
|
|
187
|
-
for (ii = 0; ii < LCBT_NREPLICAS(instance)+1; ii++) {
|
|
188
|
-
int ix = lcbvb_vbserver(LCBT_VBCONFIG(instance), item->vbid, ii);
|
|
189
|
-
if (ix > -1 && ix == srvix) {
|
|
190
|
-
return &item->sinfo[ii];
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
return NULL;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
void lcbdur_ent_finish(lcb_DURITEM *ent)
|
|
197
|
-
{
|
|
198
|
-
lcb_RESPCALLBACK callback;
|
|
199
|
-
lcb_t instance;
|
|
200
|
-
|
|
201
|
-
if (ent->done) {
|
|
202
|
-
return;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
ent->done = 1;
|
|
206
|
-
ent->parent->nremaining--;
|
|
207
|
-
|
|
208
|
-
/** Invoke the callback now :) */
|
|
209
|
-
ent->result.cookie = (void *)ent->parent->cookie;
|
|
210
|
-
instance = ent->parent->instance;
|
|
211
|
-
|
|
212
|
-
if (ent->parent->is_durstore) {
|
|
213
|
-
lcb_RESPSTOREDUR resp = { 0 };
|
|
214
|
-
resp.key = ent->result.key;
|
|
215
|
-
resp.nkey = ent->result.nkey;
|
|
216
|
-
resp.rc = ent->result.rc;
|
|
217
|
-
resp.cas = ent->reqcas;
|
|
218
|
-
resp.cookie = ent->result.cookie;
|
|
219
|
-
resp.store_ok = 1;
|
|
220
|
-
resp.dur_resp = &ent->result;
|
|
221
|
-
|
|
222
|
-
callback = lcb_find_callback(instance, LCB_CALLBACK_STOREDUR);
|
|
223
|
-
callback(instance, LCB_CALLBACK_STOREDUR, (lcb_RESPBASE*)&resp);
|
|
224
|
-
} else {
|
|
225
|
-
callback = lcb_find_callback(instance, LCB_CALLBACK_ENDURE);
|
|
226
|
-
callback(instance, LCB_CALLBACK_ENDURE, (lcb_RESPBASE*)&ent->result);
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
if (ent->parent->nremaining == 0) {
|
|
230
|
-
lcbdur_unref(ent->parent);
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
/**
|
|
235
|
-
* Called when the last (primitive) OBSERVE response is received for the entry.
|
|
236
|
-
*/
|
|
237
|
-
void lcbdur_reqs_done(lcb_DURSET *dset)
|
|
238
|
-
{
|
|
239
|
-
lcb_assert(dset->waiting || ("Got NULL callback twice!" && 0));
|
|
240
|
-
|
|
241
|
-
dset->waiting = 0;
|
|
242
|
-
|
|
243
|
-
if (dset->nremaining > 0) {
|
|
244
|
-
lcbdur_switch_state(dset, LCBDUR_STATE_OBSPOLL);
|
|
245
|
-
}
|
|
246
|
-
lcbdur_unref(dset);
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
/**
|
|
250
|
-
* Schedules a single sweep of observe requests.
|
|
251
|
-
* The `initial` parameter determines if this is a retry or if this is the
|
|
252
|
-
* initial scheduling.
|
|
253
|
-
*/
|
|
254
|
-
static void poll_once(lcb_DURSET *dset)
|
|
255
|
-
{
|
|
256
|
-
lcb_error_t err;
|
|
257
|
-
|
|
258
|
-
/* We should never be called while an 'iter' operation is still in progress */
|
|
259
|
-
lcb_assert(dset->waiting == 0);
|
|
260
|
-
lcbdur_ref(dset);
|
|
261
|
-
|
|
262
|
-
err = DSET_PROCS(dset)->poll(dset);
|
|
263
|
-
if (err == LCB_SUCCESS) {
|
|
264
|
-
lcbdur_ref(dset);
|
|
265
|
-
lcbdur_switch_state(dset, LCBDUR_STATE_TIMEOUT);
|
|
266
|
-
} else {
|
|
267
|
-
dset->lasterr = err;
|
|
268
|
-
lcbdur_switch_state(dset, LCBDUR_STATE_OBSPOLL);
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
lcbdur_unref(dset);
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
#define DUR_MIN(a,b) (a) < (b) ? (a) : (b)
|
|
275
|
-
|
|
276
|
-
LIBCOUCHBASE_API
|
|
277
|
-
lcb_error_t
|
|
278
|
-
lcb_durability_validate(lcb_t instance,
|
|
279
|
-
lcb_U16 *persist_to, lcb_U16 *replicate_to, int options)
|
|
280
|
-
{
|
|
281
|
-
int replica_max = DUR_MIN(
|
|
282
|
-
LCBT_NREPLICAS(instance),
|
|
283
|
-
LCBT_NDATASERVERS(instance)-1);
|
|
284
|
-
int persist_max = replica_max + 1;
|
|
285
|
-
|
|
286
|
-
if (*persist_to == 0 && *replicate_to == 0) {
|
|
287
|
-
/* Empty values! */
|
|
288
|
-
return LCB_EINVAL;
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
/* persist_max is always one more than replica_max */
|
|
292
|
-
if ((int)*persist_to > persist_max) {
|
|
293
|
-
if (options & LCB_DURABILITY_VALIDATE_CAPMAX) {
|
|
294
|
-
*persist_to = persist_max;
|
|
295
|
-
} else {
|
|
296
|
-
return LCB_DURABILITY_ETOOMANY;
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
if (*replicate_to == 0) {
|
|
301
|
-
return LCB_SUCCESS;
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
if (replica_max < 0) {
|
|
305
|
-
replica_max = 0;
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
/* now, we need at least as many nodes as we have replicas */
|
|
309
|
-
if ((int)*replicate_to > replica_max) {
|
|
310
|
-
if (options & LCB_DURABILITY_VALIDATE_CAPMAX) {
|
|
311
|
-
*replicate_to = replica_max;
|
|
312
|
-
} else {
|
|
313
|
-
return LCB_DURABILITY_ETOOMANY;
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
return LCB_SUCCESS;
|
|
317
|
-
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
#define CTX_FROM_MULTI(mcmd) (void *) ((((char *) (mcmd))) - offsetof(lcb_DURSET, mctx))
|
|
321
|
-
|
|
322
|
-
static lcb_error_t
|
|
323
|
-
dset_ctx_add(lcb_MULTICMD_CTX *mctx, const lcb_CMDBASE *cmd)
|
|
324
|
-
{
|
|
325
|
-
lcb_DURSET *dset = CTX_FROM_MULTI(mctx);
|
|
326
|
-
lcb_DURITEM *ent;
|
|
327
|
-
int vbid, srvix;
|
|
328
|
-
|
|
329
|
-
if (LCB_KEYBUF_IS_EMPTY(&cmd->key)) {
|
|
330
|
-
return LCB_EMPTY_KEY;
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
LCB_SSOBUF_ALLOC(&ent, &dset->entries_, lcb_DURITEM);
|
|
334
|
-
if (!ent) {
|
|
335
|
-
return LCB_CLIENT_ENOMEM;
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
mcreq_map_key(&dset->instance->cmdq, &cmd->key, &cmd->_hashkey,
|
|
339
|
-
MCREQ_PKT_BASESIZE, &vbid, &srvix);
|
|
340
|
-
|
|
341
|
-
/* ok. now let's initialize the entry..*/
|
|
342
|
-
memset(ent, 0, sizeof (*ent));
|
|
343
|
-
RESFLD(ent, nkey) = cmd->key.contig.nbytes;
|
|
344
|
-
ent->reqcas = cmd->cas;
|
|
345
|
-
ent->parent = dset;
|
|
346
|
-
ent->vbid = vbid;
|
|
347
|
-
|
|
348
|
-
lcb_string_append(&dset->kvbufs,
|
|
349
|
-
cmd->key.contig.bytes, cmd->key.contig.nbytes);
|
|
350
|
-
if (DSET_PROCS(dset)->ent_add) {
|
|
351
|
-
return DSET_PROCS(dset)->ent_add(dset, ent, (lcb_CMDENDURE*)cmd);
|
|
352
|
-
} else {
|
|
353
|
-
return LCB_SUCCESS;
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
static lcb_error_t
|
|
358
|
-
dset_ctx_schedule(lcb_MULTICMD_CTX *mctx, const void *cookie)
|
|
359
|
-
{
|
|
360
|
-
size_t ii;
|
|
361
|
-
lcb_error_t err;
|
|
362
|
-
lcb_DURSET *dset = CTX_FROM_MULTI(mctx);
|
|
363
|
-
char *kptr = dset->kvbufs.base;
|
|
364
|
-
|
|
365
|
-
if (!DSET_COUNT(dset)) {
|
|
366
|
-
lcbdur_destroy(dset);
|
|
367
|
-
return LCB_EINVAL;
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
for (ii = 0; ii < DSET_COUNT(dset); ii++) {
|
|
371
|
-
lcb_DURITEM *ent = DSET_ENTRIES(dset) + ii;
|
|
372
|
-
RESFLD(ent, key) = kptr;
|
|
373
|
-
kptr += RESFLD(ent, nkey);
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
if (DSET_PROCS(dset)->schedule) {
|
|
377
|
-
err = DSET_PROCS(dset)->schedule(dset);
|
|
378
|
-
if (err != LCB_SUCCESS) {
|
|
379
|
-
lcbdur_destroy(dset);
|
|
380
|
-
return err;
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
lcbdur_ref(dset);
|
|
385
|
-
dset->cookie = cookie;
|
|
386
|
-
dset->nremaining = DSET_COUNT(dset);
|
|
387
|
-
dset->ns_timeout = gethrtime() + LCB_US2NS(DSET_OPTFLD(dset, timeout));
|
|
388
|
-
|
|
389
|
-
lcb_aspend_add(&dset->instance->pendops, LCB_PENDTYPE_DURABILITY, dset);
|
|
390
|
-
lcbdur_switch_state(dset, LCBDUR_STATE_INIT);
|
|
391
|
-
return LCB_SUCCESS;
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
static void
|
|
395
|
-
dset_ctx_fail(lcb_MULTICMD_CTX *mctx)
|
|
396
|
-
{
|
|
397
|
-
lcb_DURSET *dset = CTX_FROM_MULTI(mctx);
|
|
398
|
-
lcbdur_destroy(dset);
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
void lcbdurctx_set_durstore(lcb_MULTICMD_CTX *mctx, int enabled)
|
|
402
|
-
{
|
|
403
|
-
|
|
404
|
-
lcb_DURSET *dset = CTX_FROM_MULTI(mctx);
|
|
405
|
-
dset->is_durstore = enabled;
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
static lcb_U8
|
|
409
|
-
get_poll_meth(lcb_t instance, const lcb_DURABILITYOPTSv0 *options)
|
|
410
|
-
{
|
|
411
|
-
/* Need to call this first, so we can actually allocate the appropriate
|
|
412
|
-
* data for this.. */
|
|
413
|
-
lcb_U8 meth = options->pollopts;
|
|
414
|
-
if (meth == LCB_DURABILITY_MODE_DEFAULT) {
|
|
415
|
-
meth = LCB_DURABILITY_MODE_CAS;
|
|
416
|
-
|
|
417
|
-
if (LCBT_SETTING(instance, fetch_mutation_tokens) &&
|
|
418
|
-
LCBT_SETTING(instance, dur_mutation_tokens)) {
|
|
419
|
-
size_t ii;
|
|
420
|
-
for (ii = 0; ii < LCBT_NSERVERS(instance); ii++) {
|
|
421
|
-
mc_SERVER *s = LCBT_GET_SERVER(instance, ii);
|
|
422
|
-
if (s->mutation_tokens) {
|
|
423
|
-
meth = LCB_DURABILITY_MODE_SEQNO;
|
|
424
|
-
break;
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
return meth;
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
LIBCOUCHBASE_API
|
|
433
|
-
lcb_MULTICMD_CTX *
|
|
434
|
-
lcb_endure3_ctxnew(lcb_t instance, const lcb_durability_opts_t *options,
|
|
435
|
-
lcb_error_t *errp)
|
|
436
|
-
{
|
|
437
|
-
lcb_DURSET *dset;
|
|
438
|
-
lcb_error_t err_s;
|
|
439
|
-
lcbio_pTABLE io = instance->iotable;
|
|
440
|
-
const lcb_DURABILITYOPTSv0 *opts_in = &options->v.v0;
|
|
441
|
-
|
|
442
|
-
if (!errp) {
|
|
443
|
-
errp = &err_s;
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
*errp = LCB_SUCCESS;
|
|
447
|
-
|
|
448
|
-
if (!LCBT_VBCONFIG(instance)) {
|
|
449
|
-
*errp = LCB_CLIENT_ETMPFAIL;
|
|
450
|
-
return NULL;
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
dset = calloc(1, sizeof(*dset));
|
|
454
|
-
if (!dset) {
|
|
455
|
-
*errp = LCB_CLIENT_ENOMEM;
|
|
456
|
-
return NULL;
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
/* Ensure we don't clobber options from older versions */
|
|
460
|
-
dset->opts.cap_max = opts_in->cap_max;
|
|
461
|
-
dset->opts.check_delete = opts_in->check_delete;
|
|
462
|
-
dset->opts.interval = opts_in->interval;
|
|
463
|
-
dset->opts.persist_to = opts_in->persist_to;
|
|
464
|
-
dset->opts.replicate_to = opts_in->replicate_to;
|
|
465
|
-
dset->opts.timeout = opts_in->timeout;
|
|
466
|
-
|
|
467
|
-
if (options->version > 0) {
|
|
468
|
-
dset->opts.pollopts = opts_in->pollopts;
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
dset->opts.pollopts = get_poll_meth(instance, &dset->opts);
|
|
472
|
-
|
|
473
|
-
dset->instance = instance;
|
|
474
|
-
dset->mctx.addcmd = dset_ctx_add;
|
|
475
|
-
dset->mctx.done = dset_ctx_schedule;
|
|
476
|
-
dset->mctx.fail = dset_ctx_fail;
|
|
477
|
-
|
|
478
|
-
if (!DSET_OPTFLD(dset, timeout)) {
|
|
479
|
-
DSET_OPTFLD(dset, timeout) = LCBT_SETTING(instance, durability_timeout);
|
|
480
|
-
}
|
|
481
|
-
if (!DSET_OPTFLD(dset, interval)) {
|
|
482
|
-
DSET_OPTFLD(dset, interval) = LCBT_SETTING(instance, durability_interval);
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
*errp = lcb_durability_validate(instance,
|
|
486
|
-
&dset->opts.persist_to, &dset->opts.replicate_to,
|
|
487
|
-
dset->opts.cap_max ? LCB_DURABILITY_VALIDATE_CAPMAX : 0);
|
|
488
|
-
|
|
489
|
-
if (*errp != LCB_SUCCESS) {
|
|
490
|
-
free(dset);
|
|
491
|
-
return NULL;
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
dset->timer = io->timer.create(io->p);
|
|
495
|
-
lcb_string_init(&dset->kvbufs);
|
|
496
|
-
return &dset->mctx;
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
LIBCOUCHBASE_API
|
|
500
|
-
lcb_error_t
|
|
501
|
-
lcb_durability_poll(lcb_t instance, const void *cookie,
|
|
502
|
-
const lcb_durability_opts_t *options, lcb_size_t ncmds,
|
|
503
|
-
const lcb_durability_cmd_t *const *cmds)
|
|
504
|
-
{
|
|
505
|
-
lcb_MULTICMD_CTX *mctx;
|
|
506
|
-
unsigned ii;
|
|
507
|
-
lcb_error_t err;
|
|
508
|
-
|
|
509
|
-
if (ncmds == 0) {
|
|
510
|
-
return LCB_EINVAL;
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
mctx = lcb_endure3_ctxnew(instance, options, &err);
|
|
514
|
-
if (!mctx) {
|
|
515
|
-
return err;
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
for (ii = 0; ii < ncmds; ii++) {
|
|
519
|
-
lcb_CMDENDURE cmd = { 0 };
|
|
520
|
-
const lcb_DURABILITYCMDv0 *src = &cmds[ii]->v.v0;
|
|
521
|
-
cmd.key.contig.bytes = src->key;
|
|
522
|
-
cmd.key.contig.nbytes = src->nkey;
|
|
523
|
-
cmd._hashkey.contig.bytes = src->hashkey;
|
|
524
|
-
cmd._hashkey.contig.nbytes = src->nhashkey;
|
|
525
|
-
cmd.cas = src->cas;
|
|
526
|
-
|
|
527
|
-
err = mctx->addcmd(mctx, (lcb_CMDBASE*)&cmd);
|
|
528
|
-
if (err != LCB_SUCCESS) {
|
|
529
|
-
mctx->fail(mctx);
|
|
530
|
-
return err;
|
|
531
|
-
}
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
lcb_sched_enter(instance);
|
|
535
|
-
err = mctx->done(mctx, cookie);
|
|
536
|
-
if (err != LCB_SUCCESS) {
|
|
537
|
-
lcb_sched_fail(instance);
|
|
538
|
-
return err;
|
|
539
|
-
} else {
|
|
540
|
-
lcb_sched_leave(instance);
|
|
541
|
-
SYNCMODE_INTERCEPT(instance)
|
|
542
|
-
}
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
/**
|
|
546
|
-
* Decrement the refcount for the 'dset'. When it hits zero then the dset is
|
|
547
|
-
* freed.
|
|
548
|
-
*/
|
|
549
|
-
void lcbdur_unref(lcb_DURSET *dset)
|
|
550
|
-
{
|
|
551
|
-
if (--dset->refcnt == 0) {
|
|
552
|
-
lcbdur_destroy(dset);
|
|
553
|
-
}
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
/**
|
|
557
|
-
* Actually free the resources allocated by the dset (and all its entries).
|
|
558
|
-
* Called by some other functions in libcouchbase
|
|
559
|
-
*/
|
|
560
|
-
void lcbdur_destroy(lcb_DURSET *dset)
|
|
561
|
-
{
|
|
562
|
-
lcb_t instance = dset->instance;
|
|
563
|
-
|
|
564
|
-
if (DSET_PROCS(dset)->clean) {
|
|
565
|
-
DSET_PROCS(dset)->clean(dset);
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
if (dset->timer) {
|
|
569
|
-
lcbio_TABLE *io = instance->iotable;
|
|
570
|
-
io->timer.cancel(io->p, dset->timer);
|
|
571
|
-
io->timer.destroy(io->p, dset->timer);
|
|
572
|
-
dset->timer = NULL;
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
lcb_aspend_del(&dset->instance->pendops, LCB_PENDTYPE_DURABILITY, dset);
|
|
576
|
-
LCB_SSOBUF_CLEAN(&dset->entries_);
|
|
577
|
-
lcb_string_release(&dset->kvbufs);
|
|
578
|
-
free(dset);
|
|
579
|
-
lcb_maybe_breakout(instance);
|
|
580
|
-
}
|
|
581
|
-
|
|
582
|
-
/**
|
|
583
|
-
* All-purpose callback dispatcher.
|
|
584
|
-
*/
|
|
585
|
-
static void timer_callback(lcb_socket_t sock, short which, void *arg)
|
|
586
|
-
{
|
|
587
|
-
lcb_DURSET *dset = arg;
|
|
588
|
-
hrtime_t now = gethrtime();
|
|
589
|
-
|
|
590
|
-
if (dset->ns_timeout && now > dset->ns_timeout) {
|
|
591
|
-
dset->next_state = LCBDUR_STATE_TIMEOUT;
|
|
592
|
-
}
|
|
593
|
-
|
|
594
|
-
switch (dset->next_state) {
|
|
595
|
-
case LCBDUR_STATE_OBSPOLL:
|
|
596
|
-
case LCBDUR_STATE_INIT:
|
|
597
|
-
poll_once(dset);
|
|
598
|
-
break;
|
|
599
|
-
|
|
600
|
-
case LCBDUR_STATE_TIMEOUT: {
|
|
601
|
-
lcb_size_t ii;
|
|
602
|
-
lcb_error_t err = dset->lasterr ? dset->lasterr : LCB_ETIMEDOUT;
|
|
603
|
-
dset->ns_timeout = 0;
|
|
604
|
-
dset->next_state = LCBDUR_STATE_IGNORE;
|
|
605
|
-
|
|
606
|
-
lcb_log(LOGARGS(dset, WARN), "Polling durability timed out!");
|
|
607
|
-
|
|
608
|
-
lcbdur_ref(dset);
|
|
609
|
-
|
|
610
|
-
for (ii = 0; ii < DSET_COUNT(dset); ii++) {
|
|
611
|
-
lcb_DURITEM *ent = DSET_ENTRIES(dset) + ii;
|
|
612
|
-
if (ent->done) {
|
|
613
|
-
continue;
|
|
614
|
-
}
|
|
615
|
-
if (RESFLD(ent, rc) == LCB_SUCCESS) {
|
|
616
|
-
RESFLD(ent, rc) = err;
|
|
617
|
-
}
|
|
618
|
-
lcbdur_ent_finish(ent);
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
lcbdur_unref(dset);
|
|
622
|
-
break;
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
case LCBDUR_STATE_IGNORE:
|
|
626
|
-
break;
|
|
627
|
-
|
|
628
|
-
default:
|
|
629
|
-
lcb_assert("unexpected state" && 0);
|
|
630
|
-
break;
|
|
631
|
-
}
|
|
632
|
-
|
|
633
|
-
(void)sock;
|
|
634
|
-
(void)which;
|
|
635
|
-
}
|
|
636
|
-
|
|
637
|
-
/**
|
|
638
|
-
* Schedules us to be notified with the given state within a particular amount
|
|
639
|
-
* of time. This is used both for the timeout and for the interval
|
|
640
|
-
*/
|
|
641
|
-
void
|
|
642
|
-
lcbdur_switch_state(lcb_DURSET *dset, unsigned int state)
|
|
643
|
-
{
|
|
644
|
-
lcb_U32 delay = 0;
|
|
645
|
-
lcbio_TABLE* io = dset->instance->iotable;
|
|
646
|
-
hrtime_t now = gethrtime();
|
|
647
|
-
|
|
648
|
-
if (state == LCBDUR_STATE_TIMEOUT) {
|
|
649
|
-
if (dset->ns_timeout && now < dset->ns_timeout) {
|
|
650
|
-
delay = LCB_NS2US(dset->ns_timeout - now);
|
|
651
|
-
} else {
|
|
652
|
-
delay = 0;
|
|
653
|
-
}
|
|
654
|
-
} else if (state == LCBDUR_STATE_OBSPOLL) {
|
|
655
|
-
if (now + LCB_US2NS(DSET_OPTFLD(dset, interval)) < dset->ns_timeout) {
|
|
656
|
-
delay = DSET_OPTFLD(dset, interval);
|
|
657
|
-
} else {
|
|
658
|
-
delay = 0;
|
|
659
|
-
state = LCBDUR_STATE_TIMEOUT;
|
|
660
|
-
}
|
|
661
|
-
} else if (state == LCBDUR_STATE_INIT) {
|
|
662
|
-
delay = 0;
|
|
663
|
-
}
|
|
664
|
-
|
|
665
|
-
dset->next_state = state;
|
|
666
|
-
io->timer.cancel(io->p, dset->timer);
|
|
667
|
-
io->timer.schedule(io->p, dset->timer, delay, dset, timer_callback);
|
|
668
|
-
}
|