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.
Files changed (133) hide show
  1. checksums.yaml +4 -4
  2. data/ext/libcouchbase/.gitignore +2 -0
  3. data/ext/libcouchbase/CMakeLists.txt +5 -7
  4. data/ext/libcouchbase/README.markdown +2 -2
  5. data/ext/libcouchbase/RELEASE_NOTES.markdown +49 -0
  6. data/ext/libcouchbase/cmake/Modules/ConfigureDtrace.cmake +11 -0
  7. data/ext/libcouchbase/cmake/Modules/GenerateConfigDotH.cmake +2 -0
  8. data/ext/libcouchbase/cmake/Modules/GetLibcouchbaseFlags.cmake +2 -1
  9. data/ext/libcouchbase/cmake/Modules/GetVersionInfo.cmake +3 -3
  10. data/ext/libcouchbase/cmake/config-cmake.h.in +2 -0
  11. data/ext/libcouchbase/cmake/defs.mk.in +0 -2
  12. data/ext/libcouchbase/cmake/source_files.cmake +34 -14
  13. data/ext/libcouchbase/configure.pl +1 -1
  14. data/ext/libcouchbase/contrib/genhash/genhash.h +6 -0
  15. data/ext/libcouchbase/include/libcouchbase/auth.h +10 -0
  16. data/ext/libcouchbase/include/libcouchbase/couchbase.h +10 -0
  17. data/ext/libcouchbase/include/libcouchbase/error.h +7 -0
  18. data/ext/libcouchbase/include/libcouchbase/n1ql.h +13 -1
  19. data/ext/libcouchbase/include/libcouchbase/plugins/io/bsdio-inl.c +1 -1
  20. data/ext/libcouchbase/include/libcouchbase/subdoc.h +9 -0
  21. data/ext/libcouchbase/include/libcouchbase/views.h +7 -1
  22. data/ext/libcouchbase/include/libcouchbase/visibility.h +1 -0
  23. data/ext/libcouchbase/include/memcached/protocol_binary.h +21 -1132
  24. data/ext/libcouchbase/packaging/parse-git-describe.pl +1 -1
  25. data/ext/libcouchbase/plugins/io/libev/libev_io_opts.h +3 -2
  26. data/ext/libcouchbase/src/README.md +0 -2
  27. data/ext/libcouchbase/src/auth-priv.h +1 -0
  28. data/ext/libcouchbase/src/auth.cc +10 -0
  29. data/ext/libcouchbase/src/bootstrap.cc +216 -0
  30. data/ext/libcouchbase/src/bootstrap.h +50 -39
  31. data/ext/libcouchbase/src/bucketconfig/bc_cccp.cc +455 -0
  32. data/ext/libcouchbase/src/bucketconfig/bc_file.cc +281 -0
  33. data/ext/libcouchbase/src/bucketconfig/bc_http.cc +528 -0
  34. data/ext/libcouchbase/src/bucketconfig/bc_http.h +50 -25
  35. data/ext/libcouchbase/src/bucketconfig/bc_mcraw.cc +115 -0
  36. data/ext/libcouchbase/src/bucketconfig/clconfig.h +407 -386
  37. data/ext/libcouchbase/src/bucketconfig/confmon.cc +378 -0
  38. data/ext/libcouchbase/src/cbft.cc +22 -27
  39. data/ext/libcouchbase/src/cntl.cc +24 -24
  40. data/ext/libcouchbase/src/connspec.cc +30 -1
  41. data/ext/libcouchbase/src/connspec.h +17 -0
  42. data/ext/libcouchbase/src/dns-srv.cc +143 -0
  43. data/ext/libcouchbase/src/{dump.c → dump.cc} +8 -11
  44. data/ext/libcouchbase/src/getconfig.cc +73 -0
  45. data/ext/libcouchbase/src/handler.cc +84 -85
  46. data/ext/libcouchbase/src/hostlist.cc +0 -1
  47. data/ext/libcouchbase/src/hostlist.h +6 -1
  48. data/ext/libcouchbase/src/http/http-priv.h +125 -112
  49. data/ext/libcouchbase/src/http/http.cc +9 -29
  50. data/ext/libcouchbase/src/http/http.h +1 -34
  51. data/ext/libcouchbase/src/http/http_io.cc +22 -26
  52. data/ext/libcouchbase/src/instance.cc +102 -28
  53. data/ext/libcouchbase/src/internal.h +47 -29
  54. data/ext/libcouchbase/src/jsparse/parser.cc +146 -202
  55. data/ext/libcouchbase/src/jsparse/parser.h +91 -98
  56. data/ext/libcouchbase/src/lcbht/lcbht.cc +177 -0
  57. data/ext/libcouchbase/src/lcbht/lcbht.h +174 -163
  58. data/ext/libcouchbase/src/lcbio/connect.cc +562 -0
  59. data/ext/libcouchbase/src/lcbio/connect.h +9 -2
  60. data/ext/libcouchbase/src/lcbio/ctx.c +1 -1
  61. data/ext/libcouchbase/src/lcbio/iotable.h +61 -16
  62. data/ext/libcouchbase/src/lcbio/ioutils.h +1 -1
  63. data/ext/libcouchbase/src/lcbio/manager.c +2 -2
  64. data/ext/libcouchbase/src/lcbio/timer-cxx.h +87 -0
  65. data/ext/libcouchbase/src/mc/mcreq.h +9 -2
  66. data/ext/libcouchbase/src/mcserver/mcserver.cc +723 -0
  67. data/ext/libcouchbase/src/mcserver/mcserver.h +160 -70
  68. data/ext/libcouchbase/src/mcserver/negotiate.cc +118 -152
  69. data/ext/libcouchbase/src/mcserver/negotiate.h +85 -74
  70. data/ext/libcouchbase/src/mctx-helper.h +51 -0
  71. data/ext/libcouchbase/src/n1ql/ixmgmt.cc +1 -2
  72. data/ext/libcouchbase/src/n1ql/n1ql.cc +56 -32
  73. data/ext/libcouchbase/src/{newconfig.c → newconfig.cc} +42 -70
  74. data/ext/libcouchbase/src/nodeinfo.cc +4 -8
  75. data/ext/libcouchbase/src/operations/{cbflush.c → cbflush.cc} +7 -15
  76. data/ext/libcouchbase/src/operations/{counter.c → counter.cc} +0 -0
  77. data/ext/libcouchbase/src/operations/{durability-cas.c → durability-cas.cc} +92 -76
  78. data/ext/libcouchbase/src/operations/{durability-seqno.c → durability-seqno.cc} +55 -49
  79. data/ext/libcouchbase/src/operations/durability.cc +643 -0
  80. data/ext/libcouchbase/src/operations/durability_internal.h +212 -124
  81. data/ext/libcouchbase/src/operations/{get.c → get.cc} +24 -26
  82. data/ext/libcouchbase/src/operations/{observe-seqno.c → observe-seqno.cc} +5 -8
  83. data/ext/libcouchbase/src/operations/{observe.c → observe.cc} +69 -94
  84. data/ext/libcouchbase/src/operations/{pktfwd.c → pktfwd.cc} +0 -0
  85. data/ext/libcouchbase/src/operations/{remove.c → remove.cc} +0 -0
  86. data/ext/libcouchbase/src/operations/{stats.c → stats.cc} +66 -78
  87. data/ext/libcouchbase/src/operations/{store.c → store.cc} +27 -32
  88. data/ext/libcouchbase/src/operations/subdoc.cc +38 -18
  89. data/ext/libcouchbase/src/operations/{touch.c → touch.cc} +0 -0
  90. data/ext/libcouchbase/src/packetutils.h +200 -137
  91. data/ext/libcouchbase/src/probes.d +1 -1
  92. data/ext/libcouchbase/src/{retrychk.c → retrychk.cc} +3 -4
  93. data/ext/libcouchbase/src/retryq.cc +394 -0
  94. data/ext/libcouchbase/src/retryq.h +116 -104
  95. data/ext/libcouchbase/src/settings.h +2 -1
  96. data/ext/libcouchbase/src/ssl/ssl_c.c +1 -0
  97. data/ext/libcouchbase/src/ssl/ssl_e.c +0 -1
  98. data/ext/libcouchbase/src/trace.h +8 -8
  99. data/ext/libcouchbase/src/vbucket/vbucket.c +0 -1
  100. data/ext/libcouchbase/src/views/{docreq.c → docreq.cc} +48 -54
  101. data/ext/libcouchbase/src/views/docreq.h +24 -30
  102. data/ext/libcouchbase/src/views/viewreq.cc +318 -0
  103. data/ext/libcouchbase/src/views/viewreq.h +43 -13
  104. data/ext/libcouchbase/src/{wait.c → wait.cc} +12 -17
  105. data/ext/libcouchbase/tests/basic/t_connstr.cc +89 -50
  106. data/ext/libcouchbase/tests/basic/t_jsparse.cc +27 -78
  107. data/ext/libcouchbase/tests/basic/t_packet.cc +35 -42
  108. data/ext/libcouchbase/tests/htparse/t_basic.cc +58 -78
  109. data/ext/libcouchbase/tests/iotests/t_confmon.cc +94 -111
  110. data/ext/libcouchbase/tests/iotests/t_sched.cc +1 -2
  111. data/ext/libcouchbase/tests/mc/t_alloc.cc +9 -9
  112. data/ext/libcouchbase/tools/cbc-pillowfight.cc +1 -1
  113. data/lib/libcouchbase/version.rb +1 -1
  114. metadata +36 -39
  115. data/ext/libcouchbase/include/memcached/vbucket.h +0 -42
  116. data/ext/libcouchbase/src/bootstrap.c +0 -269
  117. data/ext/libcouchbase/src/bucketconfig/bc_cccp.c +0 -495
  118. data/ext/libcouchbase/src/bucketconfig/bc_file.c +0 -347
  119. data/ext/libcouchbase/src/bucketconfig/bc_http.c +0 -630
  120. data/ext/libcouchbase/src/bucketconfig/bc_mcraw.c +0 -150
  121. data/ext/libcouchbase/src/bucketconfig/confmon.c +0 -474
  122. data/ext/libcouchbase/src/getconfig.c +0 -100
  123. data/ext/libcouchbase/src/lcbht/lcbht.c +0 -282
  124. data/ext/libcouchbase/src/lcbio/connect.c +0 -557
  125. data/ext/libcouchbase/src/mcserver/mcserver.c +0 -784
  126. data/ext/libcouchbase/src/operations/durability.c +0 -668
  127. data/ext/libcouchbase/src/packetutils.c +0 -60
  128. data/ext/libcouchbase/src/retryq.c +0 -424
  129. data/ext/libcouchbase/src/simplestring.c +0 -211
  130. data/ext/libcouchbase/src/simplestring.h +0 -228
  131. data/ext/libcouchbase/src/ssobuf.h +0 -82
  132. data/ext/libcouchbase/src/views/viewreq.c +0 -358
  133. 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
- }