libcouchbase 0.3.3 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (167) hide show
  1. checksums.yaml +4 -4
  2. data/ext/libcouchbase/CMakeLists.txt +6 -8
  3. data/ext/libcouchbase/README.markdown +2 -2
  4. data/ext/libcouchbase/RELEASE_NOTES.markdown +229 -2
  5. data/ext/libcouchbase/cmake/Modules/ConfigureDtrace.cmake +11 -0
  6. data/ext/libcouchbase/cmake/Modules/GenerateConfigDotH.cmake +18 -0
  7. data/ext/libcouchbase/cmake/Modules/GetLibcouchbaseFlags.cmake +3 -2
  8. data/ext/libcouchbase/cmake/Modules/GetVersionInfo.cmake +3 -3
  9. data/ext/libcouchbase/cmake/config-cmake.h.in +4 -0
  10. data/ext/libcouchbase/cmake/defs.mk.in +0 -2
  11. data/ext/libcouchbase/cmake/source_files.cmake +21 -5
  12. data/ext/libcouchbase/contrib/cJSON/cJSON.c +1 -1
  13. data/ext/libcouchbase/contrib/cbsasl/src/client.c +2 -0
  14. data/ext/libcouchbase/example/users/README +48 -0
  15. data/ext/libcouchbase/example/users/users.c +147 -0
  16. data/ext/libcouchbase/include/libcouchbase/auth.h +175 -31
  17. data/ext/libcouchbase/include/libcouchbase/cntl.h +82 -1
  18. data/ext/libcouchbase/include/libcouchbase/couchbase.h +45 -3
  19. data/ext/libcouchbase/include/libcouchbase/error.h +19 -1
  20. data/ext/libcouchbase/include/libcouchbase/iops.h +3 -0
  21. data/ext/libcouchbase/include/libcouchbase/n1ql.h +31 -1
  22. data/ext/libcouchbase/include/libcouchbase/plugins/io/bsdio-inl.c +4 -1
  23. data/ext/libcouchbase/include/libcouchbase/subdoc.h +36 -2
  24. data/ext/libcouchbase/include/libcouchbase/views.h +7 -1
  25. data/ext/libcouchbase/include/libcouchbase/visibility.h +1 -0
  26. data/ext/libcouchbase/include/memcached/protocol_binary.h +24 -1146
  27. data/ext/libcouchbase/packaging/parse-git-describe.pl +1 -1
  28. data/ext/libcouchbase/plugins/io/libev/libev_io_opts.h +3 -2
  29. data/ext/libcouchbase/src/README.md +0 -2
  30. data/ext/libcouchbase/src/auth-priv.h +23 -4
  31. data/ext/libcouchbase/src/auth.cc +51 -43
  32. data/ext/libcouchbase/src/bootstrap.cc +244 -0
  33. data/ext/libcouchbase/src/bootstrap.h +58 -38
  34. data/ext/libcouchbase/src/bucketconfig/bc_cccp.cc +120 -158
  35. data/ext/libcouchbase/src/bucketconfig/bc_file.cc +281 -0
  36. data/ext/libcouchbase/src/bucketconfig/bc_http.cc +526 -0
  37. data/ext/libcouchbase/src/bucketconfig/bc_http.h +50 -25
  38. data/ext/libcouchbase/src/bucketconfig/bc_static.cc +150 -0
  39. data/ext/libcouchbase/src/bucketconfig/clconfig.h +410 -386
  40. data/ext/libcouchbase/src/bucketconfig/confmon.cc +393 -0
  41. data/ext/libcouchbase/src/cbft.cc +22 -27
  42. data/ext/libcouchbase/src/cntl.cc +56 -22
  43. data/ext/libcouchbase/src/connspec.cc +47 -6
  44. data/ext/libcouchbase/src/connspec.h +27 -0
  45. data/ext/libcouchbase/src/dns-srv.cc +147 -0
  46. data/ext/libcouchbase/src/dump.cc +3 -3
  47. data/ext/libcouchbase/src/errmap.cc +173 -0
  48. data/ext/libcouchbase/src/errmap.h +198 -0
  49. data/ext/libcouchbase/src/getconfig.cc +7 -33
  50. data/ext/libcouchbase/src/handler.cc +118 -7
  51. data/ext/libcouchbase/src/hostlist.cc +0 -36
  52. data/ext/libcouchbase/src/hostlist.h +44 -62
  53. data/ext/libcouchbase/src/http/http-priv.h +125 -112
  54. data/ext/libcouchbase/src/http/http.cc +27 -35
  55. data/ext/libcouchbase/src/http/http.h +1 -34
  56. data/ext/libcouchbase/src/http/http_io.cc +28 -36
  57. data/ext/libcouchbase/src/instance.cc +131 -34
  58. data/ext/libcouchbase/src/internal.h +58 -26
  59. data/ext/libcouchbase/src/jsparse/parser.cc +136 -210
  60. data/ext/libcouchbase/src/jsparse/parser.h +84 -98
  61. data/ext/libcouchbase/src/lcbht/lcbht.cc +177 -0
  62. data/ext/libcouchbase/src/lcbht/lcbht.h +174 -163
  63. data/ext/libcouchbase/src/lcbio/connect.cc +569 -0
  64. data/ext/libcouchbase/src/lcbio/connect.h +16 -7
  65. data/ext/libcouchbase/src/lcbio/ctx.c +1 -1
  66. data/ext/libcouchbase/src/lcbio/iotable.h +101 -16
  67. data/ext/libcouchbase/src/lcbio/{ioutils.c → ioutils.cc} +30 -51
  68. data/ext/libcouchbase/src/lcbio/ioutils.h +29 -90
  69. data/ext/libcouchbase/src/lcbio/manager.cc +543 -0
  70. data/ext/libcouchbase/src/lcbio/manager.h +133 -96
  71. data/ext/libcouchbase/src/lcbio/protoctx.c +2 -2
  72. data/ext/libcouchbase/src/lcbio/timer-cxx.h +87 -0
  73. data/ext/libcouchbase/src/mc/mcreq.c +11 -2
  74. data/ext/libcouchbase/src/mc/mcreq.h +9 -2
  75. data/ext/libcouchbase/src/mcserver/mcserver.cc +175 -43
  76. data/ext/libcouchbase/src/mcserver/mcserver.h +9 -13
  77. data/ext/libcouchbase/src/mcserver/negotiate.cc +181 -62
  78. data/ext/libcouchbase/src/mcserver/negotiate.h +1 -3
  79. data/ext/libcouchbase/src/mctx-helper.h +51 -0
  80. data/ext/libcouchbase/src/n1ql/ixmgmt.cc +1 -2
  81. data/ext/libcouchbase/src/n1ql/n1ql.cc +74 -42
  82. data/ext/libcouchbase/src/netbuf/netbuf.c +4 -4
  83. data/ext/libcouchbase/src/newconfig.cc +6 -6
  84. data/ext/libcouchbase/src/nodeinfo.cc +2 -2
  85. data/ext/libcouchbase/src/operations/{cbflush.c → cbflush.cc} +7 -15
  86. data/ext/libcouchbase/src/operations/{counter.c → counter.cc} +0 -0
  87. data/ext/libcouchbase/src/operations/durability.cc +6 -26
  88. data/ext/libcouchbase/src/operations/durability_internal.h +6 -3
  89. data/ext/libcouchbase/src/operations/{get.c → get.cc} +24 -26
  90. data/ext/libcouchbase/src/operations/{observe.c → observe.cc} +68 -93
  91. data/ext/libcouchbase/src/operations/{pktfwd.c → pktfwd.cc} +0 -0
  92. data/ext/libcouchbase/src/operations/{remove.c → remove.cc} +0 -0
  93. data/ext/libcouchbase/src/operations/stats.cc +3 -8
  94. data/ext/libcouchbase/src/operations/{store.c → store.cc} +27 -32
  95. data/ext/libcouchbase/src/operations/subdoc.cc +129 -42
  96. data/ext/libcouchbase/src/operations/{touch.c → touch.cc} +0 -0
  97. data/ext/libcouchbase/src/packetutils.h +30 -2
  98. data/ext/libcouchbase/src/probes.d +1 -1
  99. data/ext/libcouchbase/src/rdb/rope.c +1 -1
  100. data/ext/libcouchbase/src/{retrychk.c → retrychk.cc} +2 -3
  101. data/ext/libcouchbase/src/retryq.cc +52 -14
  102. data/ext/libcouchbase/src/retryq.h +3 -3
  103. data/ext/libcouchbase/src/settings.c +5 -0
  104. data/ext/libcouchbase/src/settings.h +11 -0
  105. data/ext/libcouchbase/src/ssl/ssl_c.c +1 -0
  106. data/ext/libcouchbase/src/ssl/ssl_common.c +2 -0
  107. data/ext/libcouchbase/src/ssl/ssl_e.c +0 -1
  108. data/ext/libcouchbase/src/strcodecs/strcodecs.h +1 -1
  109. data/ext/libcouchbase/src/trace.h +4 -4
  110. data/ext/libcouchbase/src/vbucket/vbucket.c +6 -10
  111. data/ext/libcouchbase/src/views/{docreq.c → docreq.cc} +48 -54
  112. data/ext/libcouchbase/src/views/docreq.h +24 -30
  113. data/ext/libcouchbase/src/views/viewreq.cc +318 -0
  114. data/ext/libcouchbase/src/views/viewreq.h +43 -13
  115. data/ext/libcouchbase/tests/basic/t_connstr.cc +88 -50
  116. data/ext/libcouchbase/tests/basic/t_creds.cc +47 -5
  117. data/ext/libcouchbase/tests/basic/t_host.cc +67 -75
  118. data/ext/libcouchbase/tests/basic/t_jsparse.cc +27 -82
  119. data/ext/libcouchbase/tests/basic/t_misc.cc +1 -1
  120. data/ext/libcouchbase/tests/basic/t_n1qlstrings.cc +0 -1
  121. data/ext/libcouchbase/tests/htparse/t_basic.cc +58 -78
  122. data/ext/libcouchbase/tests/ioserver/connection.cc +1 -1
  123. data/ext/libcouchbase/tests/ioserver/ioserver.cc +19 -6
  124. data/ext/libcouchbase/tests/iotests/mock-environment.cc +28 -2
  125. data/ext/libcouchbase/tests/iotests/mock-environment.h +51 -1
  126. data/ext/libcouchbase/tests/iotests/t_behavior.cc +1 -7
  127. data/ext/libcouchbase/tests/iotests/t_confmon.cc +97 -115
  128. data/ext/libcouchbase/tests/iotests/t_durability.cc +0 -1
  129. data/ext/libcouchbase/tests/iotests/t_eerrs.cc +119 -0
  130. data/ext/libcouchbase/tests/iotests/t_errmap.cc +178 -0
  131. data/ext/libcouchbase/tests/iotests/t_misc.cc +3 -3
  132. data/ext/libcouchbase/tests/iotests/t_netfail.cc +1 -1
  133. data/ext/libcouchbase/tests/iotests/t_obseqno.cc +0 -1
  134. data/ext/libcouchbase/tests/iotests/t_subdoc.cc +18 -11
  135. data/ext/libcouchbase/tests/mc/t_alloc.cc +9 -9
  136. data/ext/libcouchbase/tests/socktests/socktest.cc +7 -10
  137. data/ext/libcouchbase/tests/socktests/socktest.h +2 -3
  138. data/ext/libcouchbase/tests/socktests/t_basic.cc +6 -6
  139. data/ext/libcouchbase/tests/socktests/t_manager.cc +5 -6
  140. data/ext/libcouchbase/tests/socktests/t_ssl.cc +1 -1
  141. data/ext/libcouchbase/tests/vbucket/confdata/ketama_expected.json +2562 -0
  142. data/ext/libcouchbase/tests/vbucket/confdata/memd_ketama_config.json +31 -0
  143. data/ext/libcouchbase/tests/vbucket/t_config.cc +35 -5
  144. data/ext/libcouchbase/tools/CMakeLists.txt +2 -2
  145. data/ext/libcouchbase/tools/cbc-handlers.h +128 -0
  146. data/ext/libcouchbase/tools/cbc-n1qlback.cc +64 -10
  147. data/ext/libcouchbase/tools/cbc-pillowfight.cc +2 -2
  148. data/ext/libcouchbase/tools/cbc.cc +143 -10
  149. data/ext/libcouchbase/tools/docgen/loc.h +1 -1
  150. data/lib/libcouchbase/connection.rb +4 -3
  151. data/lib/libcouchbase/version.rb +1 -1
  152. metadata +37 -28
  153. data/ext/libcouchbase/include/memcached/vbucket.h +0 -42
  154. data/ext/libcouchbase/src/bootstrap.c +0 -269
  155. data/ext/libcouchbase/src/bucketconfig/bc_file.c +0 -347
  156. data/ext/libcouchbase/src/bucketconfig/bc_http.c +0 -630
  157. data/ext/libcouchbase/src/bucketconfig/bc_mcraw.c +0 -150
  158. data/ext/libcouchbase/src/bucketconfig/confmon.c +0 -474
  159. data/ext/libcouchbase/src/lcbht/lcbht.c +0 -282
  160. data/ext/libcouchbase/src/lcbio/connect.c +0 -557
  161. data/ext/libcouchbase/src/lcbio/manager.c +0 -584
  162. data/ext/libcouchbase/src/packetutils.c +0 -37
  163. data/ext/libcouchbase/src/simplestring.c +0 -211
  164. data/ext/libcouchbase/src/simplestring.h +0 -228
  165. data/ext/libcouchbase/src/ssobuf.h +0 -82
  166. data/ext/libcouchbase/src/views/viewreq.c +0 -358
  167. data/ext/libcouchbase/tests/basic/t_string.cc +0 -112
@@ -22,14 +22,9 @@ struct BcastCookie : mc_REQDATAEX {
22
22
  int remaining;
23
23
 
24
24
  BcastCookie(lcb_CALLBACKTYPE type_,
25
- mc_REQDATAPROCS* procs_,
26
- const void *cookie_) {
27
-
28
- mc_REQDATAEX::procs = procs_;
29
- mc_REQDATAEX::cookie = cookie_;
30
- mc_REQDATAEX::start = gethrtime();
31
- type = type_;
32
- remaining = 0;
25
+ const mc_REQDATAPROCS* procs_, const void *cookie_)
26
+ : mc_REQDATAEX(cookie_, *procs_, gethrtime()),
27
+ type(type_), remaining(0) {
33
28
  }
34
29
  };
35
30
 
@@ -19,23 +19,30 @@
19
19
  #include "trace.h"
20
20
  #include "durability_internal.h"
21
21
 
22
- typedef struct {
23
- mc_REQDATAEX base;
22
+ struct DurStoreCtx : mc_REQDATAEX {
24
23
  lcb_t instance;
25
24
  lcb_U16 persist_to;
26
25
  lcb_U16 replicate_to;
27
- } DURSTORECTX;
26
+
27
+ static mc_REQDATAPROCS proctable;
28
+
29
+ DurStoreCtx(lcb_t instance_, lcb_U16 persist_, lcb_U16 replicate_,
30
+ const void *cookie_)
31
+ : mc_REQDATAEX(cookie_, proctable, gethrtime()),
32
+ instance(instance_), persist_to(persist_), replicate_to(replicate_) {
33
+ }
34
+ };
28
35
 
29
36
  /** Observe stuff */
30
37
  static void
31
- handle_dur_storecb(mc_PIPELINE *pl, mc_PACKET *pkt,
38
+ handle_dur_storecb(mc_PIPELINE *, mc_PACKET *pkt,
32
39
  lcb_error_t err, const void *arg)
33
40
  {
34
41
  lcb_RESPCALLBACK cb;
35
42
  lcb_RESPSTOREDUR resp = { 0 };
36
43
  lcb_CMDENDURE dcmd = { 0 };
37
44
  const lcb_MUTATION_TOKEN *mt;
38
- DURSTORECTX *dctx = (DURSTORECTX *)pkt->u_rdata.exdata;
45
+ DurStoreCtx *dctx = static_cast<DurStoreCtx*>(pkt->u_rdata.exdata);
39
46
  lcb_MULTICMD_CTX *mctx;
40
47
  lcb_durability_opts_t opts = { 0 };
41
48
  const lcb_RESPSTORE *sresp = (const lcb_RESPSTORE *)arg;
@@ -78,7 +85,7 @@ handle_dur_storecb(mc_PIPELINE *pl, mc_PACKET *pkt,
78
85
 
79
86
  if (err == LCB_SUCCESS) {
80
87
  /* Everything OK? */
81
- free(dctx);
88
+ delete dctx;
82
89
  return;
83
90
  }
84
91
 
@@ -92,20 +99,15 @@ handle_dur_storecb(mc_PIPELINE *pl, mc_PACKET *pkt,
92
99
  resp.dur_resp = &dresp;
93
100
  cb = lcb_find_callback(dctx->instance, LCB_CALLBACK_STOREDUR);
94
101
  cb(dctx->instance, LCB_CALLBACK_STOREDUR, (const lcb_RESPBASE*)&resp);
95
- free(dctx);
102
+ delete dctx;
96
103
  }
97
-
98
- (void)pl;
99
104
  }
100
105
 
101
- static void
102
- handle_dur_schedfail(mc_PACKET *pkt)
103
- {
104
- DURSTORECTX *dctx = (void *)pkt->u_rdata.exdata;
105
- free(dctx);
106
+ static void handle_dur_schedfail(mc_PACKET *pkt) {
107
+ delete static_cast<DurStoreCtx*>(pkt->u_rdata.exdata);
106
108
  }
107
109
 
108
- mc_REQDATAPROCS storedur_procs = {
110
+ mc_REQDATAPROCS DurStoreCtx::proctable = {
109
111
  handle_dur_storecb,
110
112
  handle_dur_schedfail
111
113
  };
@@ -150,7 +152,7 @@ static int
150
152
  can_compress(lcb_t instance, const mc_PIPELINE *pipeline,
151
153
  const lcb_VALBUF *vbuf, lcb_datatype_t datatype)
152
154
  {
153
- mc_SERVER *server = (mc_SERVER *)pipeline;
155
+ const lcb::Server *server = static_cast<const lcb::Server*>(pipeline);
154
156
  int compressopts = LCBT_SETTING(instance, compressopts);
155
157
 
156
158
  if (mcreq_compression_supported() == 0) {
@@ -163,7 +165,8 @@ can_compress(lcb_t instance, const mc_PIPELINE *pipeline,
163
165
  if ((compressopts & LCB_COMPRESS_OUT) == 0) {
164
166
  return 0;
165
167
  }
166
- if (mcserver_supports_compression(server) == 0 && (compressopts & LCB_COMPRESS_FORCE) == 0) {
168
+ if (server->supports_compression() == false &&
169
+ (compressopts & LCB_COMPRESS_FORCE) == 0) {
167
170
  return 0;
168
171
  }
169
172
  if (datatype & LCB_VALUE_F_SNAPPYCOMP) {
@@ -178,7 +181,6 @@ do_store3(lcb_t instance, const void *cookie,
178
181
  {
179
182
  mc_PIPELINE *pipeline;
180
183
  mc_PACKET *packet;
181
- mc_REQDATA *rdata;
182
184
  mc_CMDQUEUE *cq = &instance->cmdq;
183
185
  int hsize;
184
186
  int should_compress = 0;
@@ -256,8 +258,6 @@ do_store3(lcb_t instance, const void *cookie,
256
258
  int duropts = 0;
257
259
  lcb_U16 persist_u , replicate_u;
258
260
  const lcb_CMDSTOREDUR *dcmd = (const lcb_CMDSTOREDUR *)cmd;
259
- DURSTORECTX *dctx = calloc(1, sizeof(*dctx));
260
-
261
261
  persist_u = dcmd->persist_to;
262
262
  replicate_u = dcmd->replicate_to;
263
263
  if (dcmd->replicate_to == -1 || dcmd->persist_to == -1) {
@@ -268,24 +268,19 @@ do_store3(lcb_t instance, const void *cookie,
268
268
  if (err != LCB_SUCCESS) {
269
269
  mcreq_wipe_packet(pipeline, packet);
270
270
  mcreq_release_packet(pipeline, packet);
271
- free(dctx);
272
271
  return err;
273
272
  }
274
273
 
275
- dctx->instance = instance;
276
- dctx->persist_to = persist_u;
277
- dctx->replicate_to = replicate_u;
278
- packet->u_rdata.exdata = &dctx->base;
274
+ DurStoreCtx *dctx = new DurStoreCtx(instance, persist_u, replicate_u,
275
+ cookie);
276
+ packet->u_rdata.exdata = dctx;
279
277
  packet->flags |= MCREQ_F_REQEXT;
280
-
281
- dctx->base.cookie = cookie;
282
- dctx->base.procs = &storedur_procs;
278
+ } else {
279
+ mc_REQDATA *rdata = MCREQ_PKT_RDATA(packet);
280
+ rdata->cookie = cookie;
281
+ rdata->start = gethrtime();
283
282
  }
284
283
 
285
- rdata = MCREQ_PKT_RDATA(packet);
286
- rdata->cookie = cookie;
287
- rdata->start = gethrtime();
288
-
289
284
  scmd.message.body.expiration = htonl(cmd->exptime);
290
285
  scmd.message.body.flags = htonl(flags);
291
286
  hdr->request.magic = PROTOCOL_BINARY_REQ;
@@ -39,7 +39,9 @@ enum Options {
39
39
  ALLOW_EXPIRY = 1<<1,
40
40
  HAS_VALUE = 1<<2,
41
41
  ALLOW_MKDIRP = 1<<3,
42
- IS_LOOKUP = 1<<4
42
+ IS_LOOKUP = 1<<4,
43
+ // Must encapsulate in 'multi' spec
44
+ NO_STANDALONE = 1<<5
43
45
  };
44
46
 
45
47
  struct Traits {
@@ -51,13 +53,24 @@ struct Traits {
51
53
  const uint8_t opcode;
52
54
 
53
55
  inline bool valid() const {
54
- return opcode != 0;
56
+ return opcode != PROTOCOL_BINARY_CMD_INVALID;
55
57
  }
56
58
 
57
59
  inline unsigned mode() const {
58
60
  return is_lookup ? LCB_SDMULTI_MODE_LOOKUP : LCB_SDMULTI_MODE_MUTATE;
59
61
  }
60
62
 
63
+ inline bool chk_allow_empty_path(uint32_t options) const {
64
+ if (allow_empty_path) {
65
+ return true;
66
+ }
67
+ if (!is_lookup) {
68
+ return false;
69
+ }
70
+
71
+ return (options & LCB_SDSPEC_F_XATTRPATH) != 0;
72
+ }
73
+
61
74
  inline Traits(uint8_t op, unsigned options) :
62
75
  allow_empty_path(options & EMPTY_PATH),
63
76
  allow_expiry(options & ALLOW_EXPIRY),
@@ -109,7 +122,13 @@ static const Traits
109
122
  Counter(PROTOCOL_BINARY_CMD_SUBDOC_COUNTER, ALLOW_EXPIRY|HAS_VALUE|ALLOW_MKDIRP);
110
123
 
111
124
  static const Traits
112
- Invalid(0, 0);
125
+ GetDoc(PROTOCOL_BINARY_CMD_GET, IS_LOOKUP|EMPTY_PATH|NO_STANDALONE);
126
+
127
+ static const Traits
128
+ SetDoc(PROTOCOL_BINARY_CMD_SET, EMPTY_PATH|NO_STANDALONE);
129
+
130
+ static const Traits
131
+ Invalid(PROTOCOL_BINARY_CMD_INVALID, 0);
113
132
 
114
133
  const Traits&
115
134
  find(unsigned mode)
@@ -139,12 +158,28 @@ find(unsigned mode)
139
158
  return Remove;
140
159
  case LCB_SDCMD_COUNTER:
141
160
  return Counter;
161
+ case LCB_SDCMD_GET_FULLDOC:
162
+ return GetDoc;
163
+ case LCB_SDCMD_SET_FULLDOC:
164
+ return SetDoc;
142
165
  default:
143
166
  return Invalid;
144
167
  }
145
168
  }
146
169
  }
147
170
 
171
+ namespace SubdocPathFlags {
172
+ static const uint8_t MKDIR_P = 0x01;
173
+ static const uint8_t XATTR = 0x04;
174
+ static const uint8_t EXPAND_MACROS = 0x010;
175
+ }
176
+
177
+ namespace SubdocDocFlags {
178
+ static const uint8_t MKDOC = 0x01;
179
+ static const uint8_t ADDDOC = 0x02;
180
+ static const uint8_t ACCESS_DELETED = 0x04;
181
+ }
182
+
148
183
  static size_t
149
184
  get_valbuf_size(const lcb_VALBUF& vb)
150
185
  {
@@ -163,6 +198,36 @@ get_valbuf_size(const lcb_VALBUF& vb)
163
198
  }
164
199
  }
165
200
 
201
+ static uint8_t
202
+ make_path_flags(const uint32_t user) {
203
+ uint8_t flags = 0;
204
+ if (user & LCB_SDSPEC_F_MKINTERMEDIATES) {
205
+ flags |= SubdocPathFlags::MKDIR_P;
206
+ }
207
+ if (user & LCB_SDSPEC_F_XATTRPATH) {
208
+ flags |= SubdocPathFlags::XATTR;
209
+ }
210
+ if (user & LCB_SDSPEC_F_XATTR_MACROVALUES) {
211
+ flags |= SubdocPathFlags::XATTR | SubdocPathFlags::EXPAND_MACROS;
212
+ }
213
+ return flags;
214
+ }
215
+
216
+ static uint8_t
217
+ make_doc_flags(const uint32_t user) {
218
+ uint8_t flags = 0;
219
+ if (user & LCB_CMDSUBDOC_F_INSERT_DOC) {
220
+ flags |= SubdocDocFlags::ADDDOC;
221
+ }
222
+ if (user & LCB_CMDSUBDOC_F_UPSERT_DOC) {
223
+ flags |= SubdocDocFlags::MKDOC;
224
+ }
225
+ if (user & LCB_CMDSUBDOC_F_ACCESS_DELETED) {
226
+ flags |= SubdocDocFlags::ACCESS_DELETED;
227
+ }
228
+ return flags;
229
+ }
230
+
166
231
  struct MultiBuilder {
167
232
  MultiBuilder(const lcb_CMDSUBDOC *cmd_)
168
233
  : cmd(cmd_), payload_size(0), mode(0) {
@@ -266,17 +331,10 @@ MultiBuilder::add_spec(const lcb_SDSPEC *spec)
266
331
  // opcode
267
332
  add_field(trait.opcode, 1);
268
333
  // flags
269
- uint8_t sdflags = 0;
270
- if (spec->options & LCB_SDSPEC_F_MKINTERMEDIATES) {
271
- sdflags = SUBDOC_FLAG_MKDIR_P;
272
- }
273
- if (spec->options & LCB_SDSPEC_F_MKDOCUMENT) {
274
- sdflags |= SUBDOC_FLAG_MKDOC;
275
- }
276
- add_field(sdflags, 1);
334
+ add_field(make_path_flags(spec->options), 1);
277
335
 
278
336
  uint16_t npath = static_cast<uint16_t>(spec->path.contig.nbytes);
279
- if (!npath && !trait.allow_empty_path) {
337
+ if (!npath && !trait.chk_allow_empty_path(spec->options)) {
280
338
  return LCB_EMPTY_PATH;
281
339
  }
282
340
 
@@ -329,7 +387,8 @@ sd3_single(lcb_t instance, const void *cookie, const lcb_CMDSUBDOC *cmd)
329
387
  if (LCB_KEYBUF_IS_EMPTY(&cmd->key)) {
330
388
  return LCB_EMPTY_KEY;
331
389
  }
332
- if (LCB_KEYBUF_IS_EMPTY(&spec->path) && !traits.allow_empty_path) {
390
+ if (LCB_KEYBUF_IS_EMPTY(&spec->path) &&
391
+ !traits.chk_allow_empty_path(spec->options)) {
333
392
  return LCB_EMPTY_PATH;
334
393
  }
335
394
 
@@ -367,14 +426,18 @@ sd3_single(lcb_t instance, const void *cookie, const lcb_CMDSUBDOC *cmd)
367
426
  extlen = 7;
368
427
  }
369
428
 
370
- protocol_binary_request_subdocument request;
371
- protocol_binary_request_header *hdr = &request.message.header;
429
+ uint8_t docflags = make_doc_flags(cmd->cmdflags);
430
+ if (docflags) {
431
+ extlen++;
432
+ }
433
+
434
+ protocol_binary_request_header hdr = {{0}};
372
435
  mc_PACKET *packet;
373
436
  mc_PIPELINE *pipeline;
374
437
 
375
438
  rc = mcreq_basic_packet(&instance->cmdq,
376
439
  (const lcb_CMDBASE*)cmd,
377
- hdr, extlen, &packet, &pipeline, MCREQ_BASICPACKET_F_FALLBACKOK);
440
+ &hdr, extlen, &packet, &pipeline, MCREQ_BASICPACKET_F_FALLBACKOK);
378
441
 
379
442
  if (rc != LCB_SUCCESS) {
380
443
  return rc;
@@ -390,29 +453,36 @@ sd3_single(lcb_t instance, const void *cookie, const lcb_CMDSUBDOC *cmd)
390
453
  MCREQ_PKT_RDATA(packet)->cookie = cookie;
391
454
  MCREQ_PKT_RDATA(packet)->start = gethrtime();
392
455
 
393
- hdr->request.magic = PROTOCOL_BINARY_REQ;
394
- hdr->request.datatype = PROTOCOL_BINARY_RAW_BYTES;
395
- hdr->request.extlen = packet->extlen;
396
- hdr->request.opaque = packet->opaque;
397
- hdr->request.cas = lcb_htonll(cmd->cas);
398
- hdr->request.bodylen = htonl(hdr->request.extlen +
399
- ntohs(hdr->request.keylen) + get_value_size(packet));
456
+ hdr.request.magic = PROTOCOL_BINARY_REQ;
457
+ hdr.request.datatype = PROTOCOL_BINARY_RAW_BYTES;
458
+ hdr.request.extlen = packet->extlen;
459
+ hdr.request.opaque = packet->opaque;
460
+ hdr.request.opcode = traits.opcode;
461
+ hdr.request.cas = lcb_htonll(cmd->cas);
462
+ hdr.request.bodylen = htonl(hdr.request.extlen +
463
+ ntohs(hdr.request.keylen) + get_value_size(packet));
464
+
465
+ memcpy(SPAN_BUFFER(&packet->kh_span), hdr.bytes, sizeof hdr.bytes);
400
466
 
401
- request.message.extras.pathlen = htons(spec->path.contig.nbytes);
402
- request.message.extras.subdoc_flags = 0;
467
+ char *extras = SPAN_BUFFER(&packet->kh_span) + MCREQ_PKT_BASESIZE;
468
+ // Path length:
469
+ uint16_t enc_pathlen = htons(spec->path.contig.nbytes);
470
+ memcpy(extras, &enc_pathlen, 2);
471
+ extras += 2;
403
472
 
404
- if (spec->options & LCB_SDSPEC_F_MKINTERMEDIATES) {
405
- request.message.extras.subdoc_flags |= SUBDOC_FLAG_MKDIR_P;
406
- }
407
- if (spec->options & LCB_SDSPEC_F_MKDOCUMENT) {
408
- request.message.extras.subdoc_flags |= SUBDOC_FLAG_MKDOC;
409
- }
473
+ uint8_t path_flags = make_path_flags(spec->options);
474
+ memcpy(extras, &path_flags, 1);
475
+ extras += 1;
410
476
 
411
- hdr->request.opcode = traits.opcode;
412
- memcpy(SPAN_BUFFER(&packet->kh_span), request.bytes, sizeof request.bytes);
413
477
  if (exptime) {
414
- exptime = htonl(exptime);
415
- memcpy(SPAN_BUFFER(&packet->kh_span) + sizeof request.bytes, &exptime, 4);
478
+ uint32_t enc_exptime = htonl(exptime);
479
+ memcpy(extras, &enc_exptime, 4);
480
+ extras += 4;
481
+ }
482
+
483
+ if (docflags) {
484
+ memcpy(extras, &docflags, 1);
485
+ extras += 1;
416
486
  }
417
487
 
418
488
  LCB_SCHED_ADD(instance, pipeline, packet);
@@ -429,10 +499,17 @@ lcb_subdoc3(lcb_t instance, const void *cookie, const lcb_CMDSUBDOC *cmd)
429
499
  }
430
500
 
431
501
  if (cmd->nspecs == 1) {
432
- return sd3_single(instance, cookie, cmd);
502
+ switch (cmd->specs[0].sdcmd) {
503
+ case LCB_SDCMD_GET_FULLDOC:
504
+ case LCB_SDCMD_SET_FULLDOC:
505
+ break;
506
+ default:
507
+ return sd3_single(instance, cookie, cmd);
508
+ }
433
509
  }
434
510
 
435
- uint32_t exp = cmd->exptime;
511
+ uint32_t expiry = cmd->exptime;
512
+ uint8_t docflags = make_doc_flags(cmd->cmdflags);
436
513
  lcb_error_t rc = LCB_SUCCESS;
437
514
 
438
515
  MultiBuilder ctx(cmd);
@@ -440,7 +517,7 @@ lcb_subdoc3(lcb_t instance, const void *cookie, const lcb_CMDSUBDOC *cmd)
440
517
  *cmd->error_index = -1;
441
518
  }
442
519
 
443
- if (exp && !ctx.is_mutate()) {
520
+ if (expiry && !ctx.is_mutate()) {
444
521
  return LCB_OPTIONS_CONFLICT;
445
522
  }
446
523
 
@@ -456,7 +533,14 @@ lcb_subdoc3(lcb_t instance, const void *cookie, const lcb_CMDSUBDOC *cmd)
456
533
 
457
534
  mc_PIPELINE *pl;
458
535
  mc_PACKET *pkt;
459
- uint8_t extlen = exp ? 4 : 0;
536
+ uint8_t extlen = 0;
537
+ if (expiry) {
538
+ extlen += 4;
539
+ }
540
+ if (docflags) {
541
+ extlen ++;
542
+ }
543
+
460
544
  protocol_binary_request_header hdr;
461
545
 
462
546
  if (cmd->error_index) {
@@ -497,9 +581,12 @@ lcb_subdoc3(lcb_t instance, const void *cookie, const lcb_CMDSUBDOC *cmd)
497
581
  hdr.request.bodylen = htonl(hdr.request.extlen +
498
582
  ntohs(hdr.request.keylen) + ctx.payload_size);
499
583
  memcpy(SPAN_BUFFER(&pkt->kh_span), hdr.bytes, sizeof hdr.bytes);
500
- if (exp) {
501
- exp = htonl(exp);
502
- memcpy(SPAN_BUFFER(&pkt->kh_span) + 24, &exp, 4);
584
+ if (expiry) {
585
+ expiry = htonl(expiry);
586
+ memcpy(SPAN_BUFFER(&pkt->kh_span) + 24, &expiry, 4);
587
+ }
588
+ if (docflags) {
589
+ memcpy(SPAN_BUFFER(&pkt->kh_span) + 24 + (extlen -1), &docflags, 1);
503
590
  }
504
591
 
505
592
  MCREQ_PKT_RDATA(pkt)->cookie = cookie;
@@ -27,6 +27,7 @@
27
27
  #ifndef __cplusplus
28
28
  typedef struct packet_info_st packet_info;
29
29
  #else
30
+ #include "contrib/lcb-jsoncpp/lcb-jsoncpp.h"
30
31
  namespace lcb {
31
32
  class Server;
32
33
 
@@ -43,8 +44,8 @@ public:
43
44
  }
44
45
 
45
46
  MemcachedResponse(protocol_binary_command cmd, uint32_t opaque_,
46
- protocol_binary_response_status code) {
47
- std::memset(this, 0, sizeof *this);
47
+ protocol_binary_response_status code)
48
+ : res(), payload(NULL), bufh(NULL) {
48
49
  res.response.opcode = cmd;
49
50
  res.response.opaque = opaque_;
50
51
  res.response.status = htons(code);
@@ -211,6 +212,33 @@ public:
211
212
  return bufh;
212
213
  }
213
214
 
215
+ static lcb_error_t
216
+ parse_enhanced_error(const char *value, lcb_SIZE nvalue, char **err_ref, char **err_ctx)
217
+ {
218
+ if (value == NULL || nvalue == 0) {
219
+ return LCB_EINVAL;
220
+ }
221
+ Json::Value jval;
222
+ if (!Json::Reader().parse(value, value + nvalue, jval)) {
223
+ return LCB_EINVAL;
224
+ }
225
+ if (jval.empty()) {
226
+ return LCB_EINVAL;
227
+ }
228
+ Json::Value jerr = jval["error"];
229
+ if (jerr.empty()) {
230
+ return LCB_EINVAL;
231
+ }
232
+ std::string emsg;
233
+ if (!jerr["ref"].empty()) {
234
+ *err_ref = strdup(jerr["ref"].asString().c_str());
235
+ }
236
+ if (!jerr["context"].empty()) {
237
+ *err_ctx = strdup(jerr["context"].asString().c_str());
238
+ }
239
+ return LCB_SUCCESS;
240
+ }
241
+
214
242
  protected:
215
243
  /** The response header */
216
244
  protocol_binary_response_header res;