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
@@ -179,7 +179,8 @@ LCB_INTERNAL_API
179
179
  void
180
180
  lcb_settings_unref(lcb_settings *);
181
181
 
182
- #define lcb_settings_ref(settings) (settings)->refcount++
182
+ #define lcb_settings_ref(settings) ((void)(settings)->refcount++)
183
+ #define lcb_settings_ref2(settings) ((settings)->refcount++, settings)
183
184
 
184
185
  #ifdef __cplusplus
185
186
  }
@@ -137,6 +137,7 @@ async_write(void *arg)
137
137
  {
138
138
  lcbio_CSSL *cs = arg;
139
139
  appdata_encode(cs);
140
+ schedule_wants(cs);
140
141
  appdata_free_flushed(cs);
141
142
  }
142
143
 
@@ -16,7 +16,6 @@
16
16
  */
17
17
 
18
18
  #include "ssl_iot_common.h"
19
- #include "simplestring.h"
20
19
  #include <openssl/err.h>
21
20
  /**
22
21
  * Event-Style SSL Wrapping.
@@ -40,33 +40,33 @@
40
40
 
41
41
  #define TRACE_BEGIN_COMMON(TGT, req, cmd, ...) \
42
42
  TGT((req)->request.opaque, ntohs((req)->request.vbucket), (req)->request.opcode, \
43
- (cmd)->key.contig.bytes, (cmd)->key.contig.nbytes, ## __VA_ARGS__)
43
+ (const char *)((cmd)->key.contig.bytes), (cmd)->key.contig.nbytes, ## __VA_ARGS__)
44
44
 
45
45
  #define TRACE_BEGIN_SIMPLE(TGT, req, cmd) \
46
46
  TGT((req)->request.opaque, ntohs((req)->request.vbucket), (req)->request.opcode, \
47
- (cmd)->key.contig.bytes, (cmd)->key.contig.nbytes)
47
+ (const char *)(cmd)->key.contig.bytes, (cmd)->key.contig.nbytes)
48
48
 
49
49
  #define TRACE_END_COMMON(TGT, mcresp, resp, ...) \
50
- TGT(PACKET_OPAQUE(mcresp), 0, PACKET_OPCODE(mcresp), (resp)->rc, (const char *)(resp)->key, (resp)->nkey, \
50
+ TGT(mcresp->opaque(), 0, mcresp->opcode(), (resp)->rc, (const char *)(resp)->key, (resp)->nkey, \
51
51
  ## __VA_ARGS__)
52
52
 
53
53
  #define TRACE_END_SIMPLE(TGT, mcresp, resp) \
54
- TGT(PACKET_OPAQUE(mcresp), 0, PACKET_OPCODE(mcresp), (resp)->rc, (const char *)(resp)->key, (resp)->nkey)
54
+ TGT(mcresp->opaque(), 0, mcresp->opcode(), (resp)->rc, (const char *)(resp)->key, (resp)->nkey)
55
55
 
56
56
  #define TRACE_GET_BEGIN(req, cmd) \
57
57
  TRACE(TRACE_BEGIN_COMMON(LIBCOUCHBASE_GET_BEGIN, req, cmd, (cmd)->exptime))
58
58
 
59
59
  #define TRACE_GET_END(mcresp, resp) \
60
60
  TRACE(TRACE_END_COMMON(LIBCOUCHBASE_GET_END, mcresp, resp, \
61
- (char*)(resp)->value, (resp)->nvalue, (resp)->itmflags, (resp)->cas, \
62
- PACKET_DATATYPE(mcresp)))
61
+ (const char*)(resp)->value, (resp)->nvalue, (resp)->itmflags, (resp)->cas, \
62
+ mcresp->datatype()))
63
63
 
64
64
  #define TRACE_UNLOCK_BEGIN(req, cmd) TRACE(TRACE_BEGIN_SIMPLE(LIBCOUCHBASE_UNLOCK_BEGIN, req, cmd))
65
65
  #define TRACE_UNLOCK_END(mcresp, resp) TRACE(TRACE_END_SIMPLE(LIBCOUCHBASE_UNLOCK_END, mcresp, resp))
66
66
 
67
67
  #define TRACE_STORE_BEGIN(req, cmd) \
68
68
  TRACE(TRACE_BEGIN_COMMON(LIBCOUCHBASE_STORE_BEGIN, req, cmd, \
69
- ( (cmd)->value.vtype == LCB_KV_IOV ? NULL : (cmd)->value.u_buf.contig.bytes ),\
69
+ (const char *)( (cmd)->value.vtype == LCB_KV_IOV ? NULL : (cmd)->value.u_buf.contig.bytes ),\
70
70
  ( (cmd)->value.vtype == LCB_KV_IOV ? 0 : (cmd)->value.u_buf.contig.nbytes ),\
71
71
  (cmd)->flags, (cmd)->cas, (req)->request.datatype, (cmd)->exptime))
72
72
 
@@ -98,7 +98,7 @@
98
98
  (resp)->cas, (resp)->status, (resp)->ismaster, (resp)->ttp, (resp)->ttr))
99
99
 
100
100
  #define TRACE_OBSERVE_END(mcresp) \
101
- TRACE(LIBCOUCHBASE_OBSERVE_END(PACKET_OPAQUE(mcresp), 0, PACKET_OPCODE(mcresp), LCB_SUCCESS))
101
+ TRACE(LIBCOUCHBASE_OBSERVE_END(mcresp->opaque(), 0, mcresp->opcode(), LCB_SUCCESS))
102
102
 
103
103
  #define TRACE_HTTP_BEGIN(req) TRACE(LIBCOUCHBASE_HTTP_BEGIN((req)->url, (req)->nurl, (req)->method))
104
104
  #define TRACE_HTTP_END(req, rc, resp) TRACE(LIBCOUCHBASE_HTTP_END((req)->url, (req)->nurl, (req)->method, (resp)->rc, (resp)->htstatus
@@ -26,7 +26,6 @@
26
26
  #include "json-inl.h"
27
27
  #include "hash.h"
28
28
  #include "crc32.h"
29
- #include "simplestring.h"
30
29
 
31
30
  #define STRINGIFY_(X) #X
32
31
  #define STRINGIFY(X) STRINGIFY_(X)
@@ -2,56 +2,53 @@
2
2
  #include "internal.h"
3
3
  #include "sllist-inl.h"
4
4
 
5
+ using namespace lcb::docreq;
6
+
5
7
  static void docreq_handler(void *arg);
6
- static void invoke_pending(lcb_DOCQUEUE*);
8
+ static void invoke_pending(Queue*);
7
9
  static void doc_callback(lcb_t,int, const lcb_RESPBASE *);
8
10
 
9
11
  #define MAX_PENDING_DOCREQ 10
10
12
  #define MIN_SCHED_SIZE 5
11
13
  #define DOCQ_DELAY_US 200000
12
14
 
13
- #define DOCQ_REF(q) (q)->refcount++
14
- #define DOCQ_UNREF(q) if (!--(q)->refcount) { docq_free(q); }
15
-
16
- lcb_DOCQUEUE *
17
- lcbdocq_create(lcb_t instance)
18
- {
19
- lcb_DOCQUEUE *q = calloc(1, sizeof *q);
20
- q->timer = lcbio_timer_new(instance->iotable, q, docreq_handler);
21
- q->refcount = 1;
22
- q->instance = instance;
23
- q->max_pending_response = MAX_PENDING_DOCREQ;
24
- q->min_batch_size = MIN_SCHED_SIZE;
25
- return q;
15
+ Queue::Queue(lcb_t instance_)
16
+ : instance(instance_),
17
+ parent(NULL),
18
+ timer(lcbio_timer_new(instance->iotable, this, docreq_handler)),
19
+ cb_ready(NULL), cb_throttle(NULL),
20
+ n_awaiting_schedule(0),
21
+ n_awaiting_response(0),
22
+ max_pending_response(MAX_PENDING_DOCREQ),
23
+ min_batch_size(MIN_SCHED_SIZE),
24
+ cancelled(false),
25
+ refcount(1)
26
+ {
27
+
28
+ memset(&pending_gets, 0, sizeof pending_gets);
29
+ memset(&cb_queue, 0, sizeof cb_queue);
26
30
  }
27
31
 
28
- static void
29
- docq_free(lcb_DOCQUEUE *q)
30
- {
31
- lcbdocq_cancel(q);
32
- lcbio_timer_destroy(q->timer);
33
- free(q);
32
+ Queue::~Queue() {
33
+ cancel();
34
+ lcbio_timer_destroy(timer);
34
35
  }
35
36
 
36
- void
37
- lcbdocq_unref(lcb_DOCQUEUE *q)
38
- {
39
- DOCQ_UNREF(q);
37
+ void Queue::unref() {
38
+ if (!--refcount) {
39
+ delete this;
40
+ }
40
41
  }
41
42
 
42
- void
43
- lcbdocq_cancel(lcb_DOCQUEUE *q)
44
- {
45
- if (!q->cancelled) {
46
- q->cancelled = 1;
47
- }
43
+ void Queue::cancel() {
44
+ cancelled = true;
48
45
  }
49
46
 
50
47
  /* Calling this function ensures that the request will be scheduled in due
51
48
  * time. This may be done at the next event loop iteration, or after a delay
52
49
  * depending on how many items are actually found within the queue. */
53
50
  static void
54
- docq_poke(lcb_DOCQUEUE *q)
51
+ docq_poke(Queue *q)
55
52
  {
56
53
  if (q->n_awaiting_response < q->max_pending_response) {
57
54
  if (q->n_awaiting_schedule > q->min_batch_size) {
@@ -65,27 +62,26 @@ docq_poke(lcb_DOCQUEUE *q)
65
62
  }
66
63
  }
67
64
 
68
- void
69
- lcbdocq_add(lcb_DOCQUEUE *q, lcb_DOCQREQ *req)
65
+ void Queue::add(DocRequest *req)
70
66
  {
71
- sllist_append(&q->pending_gets, &req->slnode);
72
- q->n_awaiting_schedule++;
73
- req->parent = q;
67
+ sllist_append(&pending_gets, &req->slnode);
68
+ n_awaiting_schedule++;
69
+ req->parent = this;
74
70
  req->ready = 0;
75
- DOCQ_REF(q);
76
- docq_poke(q);
71
+ ref();
72
+ docq_poke(this);
77
73
  }
78
74
 
79
75
  static void
80
76
  docreq_handler(void *arg)
81
77
  {
82
- lcb_DOCQUEUE *q = arg;
78
+ Queue *q = reinterpret_cast<Queue*>(arg);
83
79
  sllist_iterator iter;
84
80
  lcb_t instance = q->instance;
85
81
 
86
82
  lcb_sched_enter(instance);
87
83
  SLLIST_ITERFOR(&q->pending_gets, &iter) {
88
- lcb_DOCQREQ *cont = SLLIST_ITEM(iter.cur, lcb_DOCQREQ, slnode);
84
+ DocRequest *cont = SLLIST_ITEM(iter.cur, DocRequest, slnode);
89
85
 
90
86
  if (q->n_awaiting_response > q->max_pending_response) {
91
87
  lcbio_timer_rearm(q->timer, DOCQ_DELAY_US);
@@ -136,13 +132,12 @@ docreq_handler(void *arg)
136
132
  /* Invokes the callback on all requests which are ready, until a request which
137
133
  * is not yet ready is reached. */
138
134
  static void
139
- invoke_pending(lcb_DOCQUEUE *q)
135
+ invoke_pending(Queue *q)
140
136
  {
141
137
  sllist_iterator iter = { NULL };
142
-
143
- DOCQ_REF(q);
138
+ q->ref();
144
139
  SLLIST_ITERFOR(&q->cb_queue, &iter) {
145
- lcb_DOCQREQ *dreq = SLLIST_ITEM(iter.cur, lcb_DOCQREQ, slnode);
140
+ DocRequest *dreq = SLLIST_ITEM(iter.cur, DocRequest, slnode);
146
141
  void *bufh = NULL;
147
142
 
148
143
  if (dreq->ready == 0) {
@@ -157,21 +152,21 @@ invoke_pending(lcb_DOCQUEUE *q)
157
152
 
158
153
  q->cb_ready(q, dreq);
159
154
  if (bufh) {
160
- lcb_backbuf_unref(bufh);
155
+ lcb_backbuf_unref(reinterpret_cast<lcb_BACKBUF>(bufh));
161
156
  }
162
- DOCQ_UNREF(q);
157
+ q->unref();
163
158
  }
164
- DOCQ_UNREF(q);
159
+ q->unref();
165
160
  }
166
161
 
167
162
  static void
168
- doc_callback(lcb_t instance, int cbtype, const lcb_RESPBASE *rb)
163
+ doc_callback(lcb_t, int, const lcb_RESPBASE *rb)
169
164
  {
170
165
  const lcb_RESPGET *rg = (const lcb_RESPGET *)rb;
171
- lcb_DOCQREQ *dreq = rb->cookie;
172
- lcb_DOCQUEUE *q = dreq->parent;
166
+ DocRequest *dreq = reinterpret_cast<DocRequest*>(rb->cookie);
167
+ Queue *q = dreq->parent;
173
168
 
174
- DOCQ_REF(q);
169
+ q->ref();
175
170
 
176
171
  q->n_awaiting_response--;
177
172
  dreq->docresp = *rg;
@@ -182,13 +177,12 @@ doc_callback(lcb_t instance, int cbtype, const lcb_RESPBASE *rb)
182
177
  /* Reference the response data, since we might not be invoking this right
183
178
  * away */
184
179
  if (rg->rc == LCB_SUCCESS) {
185
- lcb_backbuf_ref(dreq->docresp.bufh);
180
+ lcb_backbuf_ref(reinterpret_cast<lcb_BACKBUF>(dreq->docresp.bufh));
186
181
  }
187
182
 
188
183
  /* Ensure the invoke_pending doesn't destroy us */
189
184
  invoke_pending(q);
190
185
  docq_poke(q);
191
186
 
192
- DOCQ_UNREF(q);
193
- (void)instance; (void)cbtype;
187
+ q->unref();
194
188
  }
@@ -10,14 +10,23 @@
10
10
  #include <lcbio/lcbio.h>
11
11
  #include "sllist.h"
12
12
 
13
- #ifdef __cplusplus
14
- extern "C" {
15
- #endif
16
-
17
- struct lcb_DOCQUEUE_st;
18
- struct lcb_DOCREQ_st;
13
+ namespace lcb {
14
+ namespace docreq {
15
+
16
+ struct Queue;
17
+ struct DocRequest;
18
+
19
+ struct Queue {
20
+ Queue(lcb_t);
21
+ ~Queue();
22
+ void add(DocRequest*);
23
+ void unref();
24
+ void ref() {refcount++;}
25
+ void cancel();
26
+ bool has_pending() const {
27
+ return n_awaiting_response || n_awaiting_schedule;
28
+ }
19
29
 
20
- typedef struct lcb_DOCQUEUE_st{
21
30
  lcb_t instance;
22
31
  void *parent;
23
32
  lcbio_pTIMER timer;
@@ -25,13 +34,13 @@ typedef struct lcb_DOCQUEUE_st{
25
34
  /**Called when a document is ready
26
35
  * @param The queue
27
36
  * @param The document */
28
- void (*cb_ready)(struct lcb_DOCQUEUE_st*,struct lcb_DOCREQ_st*);
37
+ void (*cb_ready)(struct Queue*,struct DocRequest*);
29
38
 
30
39
  /**Called when throttle state changes. This may be used by higher layers
31
40
  * for appropriate flow control
32
41
  * @param The queue
33
42
  * @param enabled Whether throttling has been enabled or disabled */
34
- void (*cb_throttle)(struct lcb_DOCQUEUE_st*, int enabled);
43
+ void (*cb_throttle)(struct Queue*, int enabled);
35
44
 
36
45
  /**This queue holds requests which were not yet issued to the library
37
46
  * via lcb_get3(). This list is aggregated after each chunk callback and
@@ -49,35 +58,20 @@ typedef struct lcb_DOCQUEUE_st{
49
58
  unsigned min_batch_size;
50
59
  unsigned cancelled;
51
60
  unsigned refcount;
52
- } lcb_DOCQUEUE;
61
+ };
53
62
 
54
- typedef struct lcb_DOCREQ_st {
63
+ struct DocRequest {
55
64
  /* Callback. Must be first */
56
65
  lcb_RESPCALLBACK callback;
57
66
  sllist_node slnode;
58
- lcb_DOCQUEUE *parent;
67
+ Queue *parent;
59
68
  lcb_RESPGET docresp;
60
69
  /* To be filled in by the subclass */
61
70
  lcb_IOV docid;
62
71
  unsigned ready;
63
- } lcb_DOCQREQ;
64
-
65
- lcb_DOCQUEUE *
66
- lcbdocq_create(lcb_t instance);
67
-
68
- void
69
- lcbdocq_add(lcb_DOCQUEUE *q, lcb_DOCQREQ *req);
72
+ };
70
73
 
71
- void
72
- lcbdocq_unref(lcb_DOCQUEUE *);
73
74
 
74
- void
75
- lcbdocq_cancel(lcb_DOCQUEUE *q);
76
-
77
- #define lcbdocq_has_pending(q) \
78
- ((q)->n_awaiting_response || (q)->n_awaiting_schedule)
79
-
80
- #ifdef __cplusplus
81
- }
82
- #endif
75
+ } // namespace docreq
76
+ } // namespace lcb
83
77
  #endif
@@ -0,0 +1,318 @@
1
+ #include "viewreq.h"
2
+ #include "sllist-inl.h"
3
+ #include "http/http.h"
4
+ #include "internal.h"
5
+
6
+ #define MAX_GET_URI_LENGTH 2048
7
+ using namespace lcb::views;
8
+
9
+ static void chunk_callback(lcb_t, int, const lcb_RESPBASE*);
10
+
11
+ template <typename value_type, typename size_type>
12
+ void IOV2PTRLEN(const lcb_IOV* iov, value_type*& ptr, size_type& len) {
13
+ ptr = reinterpret_cast<const value_type*>(iov->iov_base);
14
+ len = iov->iov_len;
15
+ }
16
+
17
+ /* Whether the request (from the user side) is still ongoing */
18
+ #define CAN_CONTINUE(req) ((req)->callback != NULL)
19
+ #define LOGARGS(instance, lvl) instance->settings, "views", LCB_LOG_##lvl, __FILE__, __LINE__
20
+
21
+ void ViewRequest::invoke_last(lcb_error_t err) {
22
+ lcb_RESPVIEWQUERY resp = { 0 };
23
+ if (callback == NULL) {
24
+ return;
25
+ }
26
+ if (docq && docq->has_pending()) {
27
+ return;
28
+ }
29
+
30
+ resp.rc = err;
31
+ resp.htresp = cur_htresp;
32
+ resp.cookie = const_cast<void*>(cookie);
33
+ resp.rflags = LCB_RESP_F_FINAL;
34
+ if (parser && parser->meta_complete) {
35
+ resp.value = parser->meta_buf.c_str();
36
+ resp.nvalue = parser->meta_buf.size();
37
+ } else {
38
+ resp.rflags |= LCB_RESP_F_CLIENTGEN;
39
+ }
40
+ callback(instance, LCB_CALLBACK_VIEWQUERY, &resp);
41
+ cancel();
42
+ }
43
+
44
+ void ViewRequest::invoke_row(lcb_RESPVIEWQUERY *resp) {
45
+ if (callback == NULL) {
46
+ return;
47
+ }
48
+ resp->htresp = cur_htresp;
49
+ resp->cookie = const_cast<void*>(cookie);
50
+ callback(instance, LCB_CALLBACK_VIEWQUERY, resp);
51
+ }
52
+
53
+ static void
54
+ chunk_callback(lcb_t instance, int, const lcb_RESPBASE *rb)
55
+ {
56
+ const lcb_RESPHTTP *rh = (const lcb_RESPHTTP *)rb;
57
+ ViewRequest *req = reinterpret_cast<ViewRequest*>(rh->cookie);
58
+
59
+ req->cur_htresp = rh;
60
+
61
+ if (rh->rc != LCB_SUCCESS || rh->htstatus != 200 || (rh->rflags & LCB_RESP_F_FINAL)) {
62
+ if (req->lasterr == LCB_SUCCESS && rh->htstatus != 200) {
63
+ if (rh->rc != LCB_SUCCESS) {
64
+ req->lasterr = rh->rc;
65
+ } else {
66
+ lcb_log(LOGARGS(instance, DEBUG), "Got not ok http status %d", rh->htstatus);
67
+ req->lasterr = LCB_HTTP_ERROR;
68
+ }
69
+ }
70
+ req->ref();
71
+ req->invoke_last();
72
+ if (rh->rflags & LCB_RESP_F_FINAL) {
73
+ req->htreq = NULL;
74
+ req->unref();
75
+ }
76
+ req->cur_htresp = NULL;
77
+ req->unref();
78
+ return;
79
+ }
80
+
81
+ if (!CAN_CONTINUE(req)) {
82
+ return;
83
+ }
84
+
85
+ req->refcount++;
86
+ req->parser->feed(reinterpret_cast<const char*>(rh->body), rh->nbody);
87
+ req->cur_htresp = NULL;
88
+ req->unref();
89
+ }
90
+
91
+ static void
92
+ do_copy_iov(std::string& dstbuf, lcb_IOV *dstiov, const lcb_IOV *srciov)
93
+ {
94
+ dstiov->iov_len = srciov->iov_len;
95
+ dstiov->iov_base = const_cast<char*>(dstbuf.c_str() + dstbuf.size());
96
+ dstbuf.append(reinterpret_cast<const char*>(srciov->iov_base), srciov->iov_len);
97
+ }
98
+
99
+ static VRDocRequest *
100
+ mk_docreq(const lcb::jsparse::Row *datum)
101
+ {
102
+ size_t extra_alloc = 0;
103
+ VRDocRequest *dreq;
104
+ extra_alloc =
105
+ datum->key.iov_len + datum->value.iov_len +
106
+ datum->geo.iov_len + datum->docid.iov_len;
107
+
108
+ dreq = new VRDocRequest();
109
+ dreq->rowbuf.reserve(extra_alloc);
110
+ do_copy_iov(dreq->rowbuf, &dreq->key, &datum->key);
111
+ do_copy_iov(dreq->rowbuf, &dreq->value, &datum->value);
112
+ do_copy_iov(dreq->rowbuf, &dreq->docid, &datum->docid);
113
+ do_copy_iov(dreq->rowbuf, &dreq->geo, &datum->geo);
114
+ return dreq;
115
+ }
116
+
117
+ void ViewRequest::JSPARSE_on_row(const lcb::jsparse::Row& datum) {
118
+ using lcb::jsparse::Row;
119
+ if (!is_no_rowparse()) {
120
+ parser->parse_viewrow(const_cast<Row&>(datum));
121
+ }
122
+
123
+ if (is_include_docs() && datum.docid.iov_len && callback) {
124
+ VRDocRequest *dreq = mk_docreq(&datum);
125
+ dreq->parent = this;
126
+ docq->add(dreq);
127
+ ref();
128
+
129
+ } else {
130
+ lcb_RESPVIEWQUERY resp = { 0 };
131
+ if (is_no_rowparse()) {
132
+ IOV2PTRLEN(&datum.row, resp.value, resp.nvalue);
133
+ } else {
134
+ IOV2PTRLEN(&datum.key, resp.key, resp.nkey);
135
+ IOV2PTRLEN(&datum.docid, resp.docid, resp.ndocid);
136
+ IOV2PTRLEN(&datum.value, resp.value, resp.nvalue);
137
+ IOV2PTRLEN(&datum.geo, resp.geometry, resp.ngeometry);
138
+ }
139
+ resp.htresp = cur_htresp;
140
+ invoke_row(&resp);
141
+ }
142
+ }
143
+
144
+ void ViewRequest::JSPARSE_on_error(const std::string&) {
145
+ invoke_last(LCB_PROTOCOL_ERROR);
146
+ }
147
+
148
+ void ViewRequest::JSPARSE_on_complete(const std::string&) {
149
+ // Nothing
150
+ }
151
+
152
+ static void
153
+ cb_doc_ready(lcb::docreq::Queue *q, lcb::docreq::DocRequest *req_base)
154
+ {
155
+ lcb_RESPVIEWQUERY resp = { 0 };
156
+ VRDocRequest *dreq = (VRDocRequest*)req_base;
157
+ resp.docresp = &dreq->docresp;
158
+ IOV2PTRLEN(&dreq->key, resp.key, resp.nkey);
159
+ IOV2PTRLEN(&dreq->value, resp.value, resp.nvalue);
160
+ IOV2PTRLEN(&dreq->docid, resp.docid, resp.ndocid);
161
+ IOV2PTRLEN(&dreq->geo, resp.geometry, resp.ngeometry);
162
+
163
+ if (q->parent) {
164
+ reinterpret_cast<ViewRequest*>(q->parent)->invoke_row(&resp);
165
+ }
166
+
167
+ delete dreq;
168
+
169
+ if (q->parent) {
170
+ reinterpret_cast<ViewRequest*>(q->parent)->unref();
171
+ }
172
+ }
173
+
174
+ static void
175
+ cb_docq_throttle(lcb::docreq::Queue *q, int enabled)
176
+ {
177
+ ViewRequest *req = reinterpret_cast<ViewRequest*>(q->parent);
178
+ if (req == NULL || req->htreq == NULL) {
179
+ return;
180
+ }
181
+ if (enabled) {
182
+ req->htreq->pause();
183
+ } else {
184
+ req->htreq->resume();
185
+ }
186
+ }
187
+
188
+ ViewRequest::~ViewRequest() {
189
+ invoke_last();
190
+
191
+ if (parser != NULL) {
192
+ delete parser;
193
+ }
194
+ if (htreq != NULL) {
195
+ lcb_cancel_http_request(instance, htreq);
196
+ }
197
+ if (docq != NULL) {
198
+ docq->parent = NULL;
199
+ docq->unref();
200
+ }
201
+ }
202
+
203
+ lcb_error_t ViewRequest::request_http(const lcb_CMDVIEWQUERY *cmd) {
204
+ lcb_CMDHTTP htcmd = { 0 };
205
+ htcmd.method = LCB_HTTP_METHOD_GET;
206
+ htcmd.type = LCB_HTTP_TYPE_VIEW;
207
+ htcmd.cmdflags = LCB_CMDHTTP_F_STREAM;
208
+
209
+ std::string path;
210
+ path.append("_design/");
211
+ path.append(cmd->ddoc, cmd->nddoc);
212
+ path.append(is_spatial() ? "/_spatial/" : "/_view/");
213
+ path.append(cmd->view, cmd->nview);
214
+ if (cmd->noptstr) {
215
+ path.append("?").append(cmd->optstr, cmd->noptstr);
216
+ }
217
+
218
+ if (cmd->npostdata) {
219
+ htcmd.method = LCB_HTTP_METHOD_POST;
220
+ htcmd.body = cmd->postdata;
221
+ htcmd.nbody = cmd->npostdata;
222
+ htcmd.content_type = "application/json";
223
+ }
224
+
225
+ LCB_CMD_SET_KEY(&htcmd, path.c_str(), path.size());
226
+ htcmd.reqhandle = &htreq;
227
+
228
+ lcb_error_t err = lcb_http3(instance, this, &htcmd);
229
+ if (err == LCB_SUCCESS) {
230
+ htreq->set_callback(chunk_callback);
231
+ }
232
+ return err;
233
+ }
234
+
235
+ ViewRequest::ViewRequest(lcb_t instance_, const void *cookie_,
236
+ const lcb_CMDVIEWQUERY* cmd)
237
+ : cur_htresp(NULL), htreq(NULL),
238
+ parser(new lcb::jsparse::Parser(lcb::jsparse::Parser::MODE_VIEWS, this)),
239
+ cookie(cookie_), docq(NULL), callback(cmd->callback),
240
+ instance(instance_), refcount(1),
241
+ cmdflags(cmd->cmdflags),
242
+ lasterr(LCB_SUCCESS) {
243
+
244
+ // Validate:
245
+ if (cmd->nddoc == 0 || cmd->nview == 0 || callback == NULL) {
246
+ lasterr = LCB_EINVAL;
247
+ } else if (is_include_docs() && is_no_rowparse()) {
248
+ lasterr = LCB_OPTIONS_CONFLICT;
249
+ } else if (cmd->noptstr > MAX_GET_URI_LENGTH) {
250
+ lasterr = LCB_E2BIG;
251
+ }
252
+ if (lasterr != LCB_SUCCESS) {
253
+ return;
254
+ }
255
+
256
+ if (is_include_docs()) {
257
+ docq = new lcb::docreq::Queue(instance);
258
+ docq->parent = this;
259
+ docq->cb_ready = cb_doc_ready;
260
+ docq->cb_throttle = cb_docq_throttle;
261
+ if (cmd->docs_concurrent_max) {
262
+ docq->max_pending_response = cmd->docs_concurrent_max;
263
+ }
264
+ }
265
+
266
+ if (cmd->handle) {
267
+ *cmd->handle = this;
268
+ }
269
+
270
+ lcb_aspend_add(&instance->pendops, LCB_PENDTYPE_COUNTER, NULL);
271
+
272
+ lasterr = request_http(cmd);
273
+ }
274
+
275
+ LIBCOUCHBASE_API
276
+ lcb_error_t
277
+ lcb_view_query(lcb_t instance, const void *cookie, const lcb_CMDVIEWQUERY *cmd)
278
+ {
279
+ ViewRequest *req = new ViewRequest(instance, cookie, cmd);
280
+ lcb_error_t err = req->lasterr;
281
+ if (err != LCB_SUCCESS) {
282
+ req->cancel();
283
+ delete req;
284
+ }
285
+ return err;
286
+ }
287
+
288
+ LIBCOUCHBASE_API
289
+ void
290
+ lcb_view_query_initcmd(lcb_CMDVIEWQUERY *vq,
291
+ const char *design, const char *view, const char *options,
292
+ lcb_VIEWQUERYCALLBACK callback)
293
+ {
294
+ vq->view = view;
295
+ vq->nview = strlen(view);
296
+ vq->ddoc = design;
297
+ vq->nddoc = strlen(design);
298
+ if (options != NULL) {
299
+ vq->optstr = options;
300
+ vq->noptstr = strlen(options);
301
+ }
302
+ vq->callback = callback;
303
+ }
304
+
305
+ LIBCOUCHBASE_API
306
+ void lcb_view_cancel(lcb_t, lcb_VIEWHANDLE handle) {
307
+ handle->cancel();
308
+ }
309
+
310
+ void ViewRequest::cancel() {
311
+ if (callback) {
312
+ callback = NULL;
313
+ lcb_aspend_del(&instance->pendops, LCB_PENDTYPE_COUNTER, NULL);
314
+ if (docq) {
315
+ docq->cancel();
316
+ }
317
+ }
318
+ }