libcouchbase 0.3.3 → 1.0.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.
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;