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
@@ -19,6 +19,7 @@
19
19
  #include "bucketconfig/clconfig.h"
20
20
  #include "http/http.h"
21
21
  #include "http/http-priv.h"
22
+ #include "auth-priv.h"
22
23
  using namespace lcb::http;
23
24
 
24
25
  #define LOGFMT "<%s:%s> "
@@ -43,7 +44,7 @@ Request::decref()
43
44
  close_io();
44
45
 
45
46
  if (parser) {
46
- lcbht_free(parser);
47
+ delete parser;
47
48
  }
48
49
 
49
50
  if (timer) {
@@ -103,7 +104,6 @@ void
103
104
  Request::maybe_refresh_config(lcb_error_t err)
104
105
  {
105
106
  int htstatus_ok;
106
- lcbht_RESPONSE *resp;
107
107
  if (!parser) {
108
108
  return;
109
109
  }
@@ -112,25 +112,25 @@ Request::maybe_refresh_config(lcb_error_t err)
112
112
  return;
113
113
  }
114
114
 
115
- resp = lcbht_get_response(parser);
116
- htstatus_ok = resp->status >= 200 && resp->status < 299;
115
+ const lcb::htparse::Response& resp = parser->get_cur_response();
116
+ htstatus_ok = resp.status >= 200 && resp.status < 299;
117
117
 
118
118
  if (err != LCB_SUCCESS && (err == LCB_ESOCKSHUTDOWN && htstatus_ok) == 0) {
119
119
  /* ignore graceful close */
120
- lcb_bootstrap_common(instance, LCB_BS_REFRESH_ALWAYS);
120
+ instance->bootstrap(BS_REFRESH_ALWAYS);
121
121
  return;
122
122
  }
123
123
 
124
124
  if (htstatus_ok) {
125
125
  return;
126
126
  }
127
- lcb_bootstrap_common(instance, LCB_BS_REFRESH_ALWAYS);
127
+ instance->bootstrap(BS_REFRESH_ALWAYS);
128
128
  }
129
129
 
130
130
  void
131
131
  Request::init_resp(lcb_RESPHTTP *res)
132
132
  {
133
- const lcbht_RESPONSE *htres = lcbht_get_response(parser);
133
+ const lcb::htparse::Response& htres = parser->get_cur_response();
134
134
 
135
135
  res->cookie = const_cast<void*>(command_cookie);
136
136
  res->key = url.c_str() + url_info.field_data[UF_PATH].off;
@@ -139,9 +139,7 @@ Request::init_resp(lcb_RESPHTTP *res)
139
139
  if (!response_headers.empty()) {
140
140
  res->headers = &response_headers_clist[0];
141
141
  }
142
- if (htres) {
143
- res->htstatus = htres->status;
144
- }
142
+ res->htstatus = htres.status;
145
143
  }
146
144
 
147
145
  void
@@ -254,9 +252,9 @@ Request::submit()
254
252
  // Only wipe old parser/response information if current I/O request
255
253
  // was a success
256
254
  if (parser) {
257
- lcbht_reset(parser);
255
+ parser->reset();
258
256
  } else {
259
- parser = lcbht_new(instance->settings);
257
+ parser = new lcb::htparse::Parser(instance->settings);
260
258
  }
261
259
  response_headers.clear();
262
260
  response_headers_clist.clear();
@@ -408,6 +406,10 @@ Request::get_api_node(lcb_error_t &rc)
408
406
  return lcbvb_get_resturl(vbc, ix, svc, mode);
409
407
  }
410
408
 
409
+ static bool is_nonempty(const char *s) {
410
+ return s != NULL && *s != '\0';
411
+ }
412
+
411
413
  lcb_error_t
412
414
  Request::setup_inputs(const lcb_CMDHTTP *cmd)
413
415
  {
@@ -433,11 +435,13 @@ Request::setup_inputs(const lcb_CMDHTTP *cmd)
433
435
  if (cmd->cmdflags & LCB_CMDHTTP_F_NOUPASS) {
434
436
  username = password = NULL;
435
437
  } else if (username == NULL && password == NULL) {
438
+ const Authenticator& auth = *LCBT_SETTING(instance, auth);
436
439
  if (reqtype == LCB_HTTP_TYPE_MANAGEMENT) {
437
- lcbauth_get_upass(LCBT_SETTING(instance, auth), &username, &password);
440
+ username = auth.username().c_str();
441
+ password = auth.password().c_str();
438
442
  } else {
439
- username = LCBT_SETTING(instance, bucket);
440
- password = lcbauth_get_bpass(LCBT_SETTING(instance, auth), username);
443
+ username = auth.username_for(LCBT_SETTING(instance, bucket)).c_str();
444
+ password = auth.password_for(LCBT_SETTING(instance, bucket)).c_str();
441
445
  }
442
446
  }
443
447
 
@@ -462,13 +466,18 @@ Request::setup_inputs(const lcb_CMDHTTP *cmd)
462
466
  return rc;
463
467
  }
464
468
 
465
- add_header("User-Agent", "libcouchbase/" LCB_VERSION_STRING);
466
- if (instance->http_sockpool->maxidle == 0 || !is_data_request()) {
469
+ std::string ua("libcouchbase/" LCB_VERSION_STRING);
470
+ if (instance->settings->client_string) {
471
+ ua.append(" ").append(instance->settings->client_string);
472
+ }
473
+ add_header("User-Agent", ua);
474
+
475
+ if (instance->http_sockpool->get_options().maxidle == 0 || !is_data_request()) {
467
476
  add_header("Connection", "close");
468
477
  }
469
478
 
470
479
  add_header("Accept", "application/json");
471
- if (password && username) {
480
+ if (is_nonempty(password) && is_nonempty(username)) {
472
481
  char auth[256];
473
482
  std::string upassbuf;
474
483
  upassbuf.append(username).append(":").append(password);
@@ -613,23 +622,6 @@ Request::cancel()
613
622
  finish(LCB_SUCCESS);
614
623
  }
615
624
 
616
- // Wrappers
617
- void lcb_htreq_setcb(lcb_http_request_t req, lcb_RESPCALLBACK callback) {
618
- req->callback = callback;
619
- }
620
- void lcb_htreq_block_callback(lcb_http_request_t req) {
621
- req->block_callback();
622
- }
623
- void lcb_htreq_pause(lcb_http_request_t req) {
624
- req->pause();
625
- }
626
- void lcb_htreq_resume(lcb_http_request_t req) {
627
- req->resume();
628
- }
629
- void lcb_htreq_finish(lcb_t, lcb_http_request_t req, lcb_error_t rc) {
630
- req->finish(rc);
631
- }
632
-
633
625
  LIBCOUCHBASE_API
634
626
  void
635
627
  lcb_cancel_http_request(lcb_t, lcb_http_request_t req)
@@ -1,34 +1 @@
1
- #ifndef LCB_HTTPAPI_H
2
- #define LCB_HTTPAPI_H
3
-
4
- /* This file contains the internal API for HTTP requests. This allows us to
5
- * change the internals without exposing the object structure to the rest
6
- * of the library
7
- */
8
-
9
- #ifdef __cplusplus
10
- extern "C" {
11
- #endif
12
-
13
- void
14
- lcb_htreq_setcb(lcb_http_request_t, lcb_RESPCALLBACK);
15
-
16
- void
17
- lcb_htreq_pause(lcb_http_request_t);
18
-
19
- void
20
- lcb_htreq_resume(lcb_http_request_t);
21
-
22
- void
23
- lcb_htreq_finish(lcb_t, lcb_http_request_t, lcb_error_t);
24
-
25
- /* Prevents the callback from being invoked. This is different than a full
26
- * destruction of the object. This is only called in lcb_destroy() to
27
- * prevent dereferencing the instance itself.
28
- */
29
- void
30
- lcb_htreq_block_callback(lcb_http_request_t);
31
- #ifdef __cplusplus
32
- }
33
- #endif
34
- #endif
1
+ #include "http-priv.h"
@@ -30,19 +30,13 @@ using namespace lcb::http;
30
30
  #define LOGARGS(req, lvl) req->instance->settings, "http-io", LCB_LOG_##lvl, __FILE__, __LINE__
31
31
 
32
32
  void
33
- Request::assign_response_headers(const lcbht_RESPONSE *resp)
33
+ Request::assign_response_headers(const lcb::htparse::Response& resp)
34
34
  {
35
- response_headers.clear();
35
+ response_headers.assign(resp.headers.begin(), resp.headers.end());
36
36
  response_headers_clist.clear();
37
37
 
38
- sllist_node *curnode;
39
- SLLIST_ITERBASIC(&resp->headers, curnode) {
40
- lcbht_MIMEHDR *hdr = SLLIST_ITEM(curnode, lcbht_MIMEHDR, slnode);
41
- response_headers.push_back(Header(hdr->key, hdr->value));
42
- }
43
-
44
- std::vector<Header>::const_iterator ii = response_headers.begin();
45
- for (; ii != response_headers.end(); ++ii) {
38
+ std::vector<lcb::htparse::MimeHeader>::const_iterator ii;
39
+ for (ii = response_headers.begin(); ii != response_headers.end(); ++ii) {
46
40
  response_headers_clist.push_back(ii->key.c_str());
47
41
  response_headers_clist.push_back(ii->value.c_str());
48
42
  }
@@ -53,29 +47,30 @@ int
53
47
  Request::handle_parse_chunked(const char *buf, unsigned nbuf)
54
48
  {
55
49
  int parse_state, oldstate, diff;
56
- lcbht_RESPONSE *res = lcbht_get_response(parser);
50
+ using lcb::htparse::Parser;
51
+ lcb::htparse::Response& res = parser->get_cur_response();
57
52
 
58
53
  do {
59
54
  const char *rbody;
60
55
  unsigned nused = -1, nbody = -1;
61
- oldstate = res->state;
56
+ oldstate = res.state;
62
57
 
63
- parse_state = lcbht_parse_ex(parser, buf, nbuf, &nused, &nbody, &rbody);
58
+ parse_state = parser->parse_ex(buf, nbuf, &nused, &nbody, &rbody);
64
59
  diff = oldstate ^ parse_state;
65
60
 
66
61
  /* Got headers now for the first time */
67
- if (diff & LCBHT_S_HEADER) {
62
+ if (diff & Parser::S_HEADER) {
68
63
  assign_response_headers(res);
69
- if (res->status >= 300 && res->status <= 400) {
70
- const char *redir = lcbht_get_resphdr(res, "Location");
64
+ if (res.status >= 300 && res.status <= 400) {
65
+ const char *redir = res.get_header_value("Location");
71
66
  if (redir != NULL) {
72
67
  pending_redirect.assign(redir);
73
- return LCBHT_S_DONE;
68
+ return Parser::S_DONE;
74
69
  }
75
70
  }
76
71
  }
77
72
 
78
- if (parse_state & LCBHT_S_ERROR) {
73
+ if (parse_state & Parser::S_ERROR) {
79
74
  /* nothing to do here */
80
75
  return parse_state;
81
76
  }
@@ -91,22 +86,22 @@ Request::handle_parse_chunked(const char *buf, unsigned nbuf)
91
86
  callback(instance, LCB_CALLBACK_HTTP, (const lcb_RESPBASE *)&htresp);
92
87
 
93
88
  } else {
94
- lcb_string_append(&res->body, rbody, nbody);
89
+ res.body.append(rbody, nbody);
95
90
  }
96
91
  }
97
92
 
98
93
  buf += nused;
99
94
  nbuf -= nused;
100
- } while ((parse_state & LCBHT_S_DONE) == 0 && is_ongoing() && nbuf);
95
+ } while ((parse_state & Parser::S_DONE) == 0 && is_ongoing() && nbuf);
101
96
 
102
- if ( (parse_state & LCBHT_S_DONE) && is_ongoing()) {
97
+ if ( (parse_state & Parser::S_DONE) && is_ongoing()) {
103
98
  lcb_RESPHTTP resp = { 0 };
104
99
  if (chunked) {
105
100
  buf = NULL;
106
101
  nbuf = 0;
107
102
  } else {
108
- buf = res->body.base;
109
- nbuf = res->body.nused;
103
+ buf = res.body.c_str();
104
+ nbuf = res.body.size();
110
105
  }
111
106
 
112
107
  init_resp(&resp);
@@ -143,7 +138,8 @@ io_read(lcbio_CTX *ctx, unsigned nr)
143
138
  nbuf = lcbio_ctx_risize(&iter);
144
139
  parse_state = req->handle_parse_chunked(buf, nbuf);
145
140
 
146
- if ((parse_state & LCBHT_S_ERROR) || req->has_pending_redirect()) {
141
+ if ((parse_state & lcb::htparse::Parser::S_ERROR) ||
142
+ req->has_pending_redirect()) {
147
143
  rv = -1;
148
144
  break;
149
145
  } else if (!req->is_ongoing()) {
@@ -156,7 +152,7 @@ io_read(lcbio_CTX *ctx, unsigned nr)
156
152
  // parse error or redirect
157
153
  lcb_error_t err;
158
154
  if (req->has_pending_redirect()) {
159
- lcb_bootstrap_common(instance, LCB_BS_REFRESH_THROTTLE);
155
+ instance->bootstrap(lcb::BS_REFRESH_THROTTLE);
160
156
  // Transfer control to redirect function()
161
157
  lcb_log(LOGARGS(req, DEBUG), LOGFMT "Attempting redirect to %s", LOGID(req), req->pending_redirect.c_str());
162
158
  req->redirect();
@@ -224,8 +220,7 @@ on_connected(lcbio_SOCKET *sock, void *arg, lcb_error_t err, lcbio_OSERR syserr)
224
220
  Request *req = reinterpret_cast<Request*>(arg);
225
221
  lcbio_CTXPROCS procs;
226
222
  lcb_settings *settings = req->instance->settings;
227
-
228
- LCBIO_CONNREQ_CLEAR(&req->creq);
223
+ req->creq = NULL;
229
224
 
230
225
  if (err != LCB_SUCCESS) {
231
226
  lcb_log(LOGARGS(req, ERR), "Connection to failed with Err=0x%x", err);
@@ -252,15 +247,12 @@ lcb_error_t
252
247
  Request::start_io(lcb_host_t& dest)
253
248
  {
254
249
  lcbio_MGR *pool = instance->http_sockpool;
255
- lcbio_pMGRREQ poolreq;
256
250
 
257
- poolreq = lcbio_mgr_get(pool, &dest, timeout(), on_connected, this);
258
- if (!poolreq) {
251
+ creq = pool->get(dest, timeout(), on_connected, this);
252
+ if (!creq) {
259
253
  return LCB_CONNECT_ERROR;
260
254
  }
261
255
 
262
- LCBIO_CONNREQ_MKPOOLED(&creq, poolreq);
263
-
264
256
  if (!timer) {
265
257
  timer = lcbio_timer_new(io, this, request_timed_out);
266
258
  }
@@ -279,16 +271,16 @@ pool_close_cb(lcbio_SOCKET *sock, int reusable, void *arg)
279
271
 
280
272
  lcbio_ref(sock);
281
273
  if (reusable && close_ok) {
282
- lcbio_mgr_put(sock);
274
+ lcb::io::Pool::put(sock);
283
275
  } else {
284
- lcbio_mgr_discard(sock);
276
+ lcb::io::Pool::discard(sock);
285
277
  }
286
278
  }
287
279
 
288
280
  void
289
281
  Request::close_io()
290
282
  {
291
- lcbio_connreq_cancel(&creq);
283
+ lcb::io::ConnectionRequest::cancel(&creq);
292
284
 
293
285
  if (!ioctx) {
294
286
  return;
@@ -297,7 +289,7 @@ Request::close_io()
297
289
  int can_ka;
298
290
 
299
291
  if (parser && is_data_request()) {
300
- can_ka = lcbht_can_keepalive(parser);
292
+ can_ka = parser->can_keepalive();
301
293
  } else {
302
294
  can_ka = 0;
303
295
  }
@@ -116,17 +116,57 @@ lcb_st::populate_nodes(const Connspec& spec)
116
116
  }
117
117
  }
118
118
 
119
+ lcb_error_t
120
+ lcb_st::process_dns_srv(Connspec& spec)
121
+ {
122
+ if (!spec.can_dnssrv()) {
123
+ return LCB_SUCCESS;
124
+ }
125
+ if (spec.hosts().empty()) {
126
+ lcb_log(LOGARGS(this, ERR), "Cannot use DNS SRV without a hostname");
127
+ return spec.is_explicit_dnssrv() ? LCB_EINVAL : LCB_SUCCESS;
128
+ }
129
+
130
+ const Spechost& host = spec.hosts().front();
131
+ lcb_error_t rc = LCB_ERROR;
132
+ Hostlist* hl = dnssrv_getbslist(host.hostname.c_str(), host.isSSL(), rc);
133
+
134
+ if (hl == NULL) {
135
+ lcb_log(LOGARGS(this, INFO), "DNS SRV lookup failed: %s. Ignore this if not relying on DNS SRV records", lcb_strerror(this, rc));
136
+ if (spec.is_explicit_dnssrv()) {
137
+ return rc;
138
+ } else {
139
+ return LCB_SUCCESS;
140
+ }
141
+ }
142
+
143
+ spec.clear_hosts();
144
+ for (size_t ii = 0; ii < hl->size(); ++ii) {
145
+ const lcb_host_t& src = (*hl)[ii];
146
+ Spechost sh;
147
+ sh.hostname = src.host;
148
+ sh.port = std::atoi(src.port);
149
+ sh.type = spec.default_port();
150
+ spec.add_host(sh);
151
+ lcb_log(LOGARGS(this, INFO), "Found host %s:%d via DNS SRV", sh.hostname.c_str(), sh.port);
152
+ }
153
+ delete hl;
154
+
155
+ return LCB_SUCCESS;
156
+ }
157
+
119
158
  static lcb_error_t
120
159
  init_providers(lcb_t obj, const Connspec &spec)
121
160
  {
122
- clconfig_provider *http, *cccp, *mcraw;
123
- http = lcb_confmon_get_provider(obj->confmon, LCB_CLCONFIG_HTTP);
124
- cccp = lcb_confmon_get_provider(obj->confmon, LCB_CLCONFIG_CCCP);
125
- mcraw = lcb_confmon_get_provider(obj->confmon, LCB_CLCONFIG_MCRAW);
161
+ using namespace lcb::clconfig;
162
+ Provider *http, *cccp, *mcraw;
163
+ http = obj->confmon->get_provider(CLCONFIG_HTTP);
164
+ cccp = obj->confmon->get_provider(CLCONFIG_CCCP);
165
+ mcraw = obj->confmon->get_provider(CLCONFIG_MCRAW);
126
166
 
127
167
  if (spec.default_port() == LCB_CONFIG_MCCOMPAT_PORT) {
128
- lcb_confmon_set_provider_active(obj->confmon, LCB_CLCONFIG_MCRAW, 1);
129
- mcraw->configure_nodes(mcraw, obj->mc_nodes);
168
+ obj->confmon->set_active(CLCONFIG_MCRAW, true);
169
+ mcraw->configure_nodes(*obj->mc_nodes);
130
170
  return LCB_SUCCESS;
131
171
  }
132
172
 
@@ -155,26 +195,34 @@ init_providers(lcb_t obj, const Connspec &spec)
155
195
  if (spec.is_bs_file()) {
156
196
  /* If the 'file_only' provider is set, just assume something else
157
197
  * will provide us with the config, and forget about it. */
158
- clconfig_provider *prov = lcb_confmon_get_provider(obj->confmon, LCB_CLCONFIG_FILE);
198
+ Provider *prov = obj->confmon->get_provider(CLCONFIG_FILE);
159
199
  if (prov && prov->enabled) {
160
200
  return LCB_SUCCESS;
161
201
  }
162
202
  }
163
- return LCB_BAD_ENVIRONMENT;
203
+ if (obj->type == LCB_TYPE_CLUSTER) {
204
+ /* Cluster-level connection always falls back to static config */
205
+ Provider *cladmin;
206
+ cladmin = obj->confmon->get_provider(CLCONFIG_CLADMIN);
207
+ cladmin->enable();
208
+ cladmin->configure_nodes(*obj->ht_nodes);
209
+ } else {
210
+ return LCB_BAD_ENVIRONMENT;
211
+ }
164
212
  }
165
213
 
166
214
  if (http_enabled) {
167
- lcb_clconfig_http_enable(http);
168
- lcb_clconfig_http_set_nodes(http, obj->ht_nodes);
215
+ http->enable();
216
+ http->configure_nodes(*obj->ht_nodes);
169
217
  } else {
170
- lcb_confmon_set_provider_active(obj->confmon, LCB_CLCONFIG_HTTP, 0);
218
+ obj->confmon->set_active(CLCONFIG_HTTP, false);
171
219
  }
172
220
 
173
221
  if (cccp_enabled && obj->type != LCB_TYPE_CLUSTER) {
174
- lcb_clconfig_cccp_enable(cccp, obj);
175
- lcb_clconfig_cccp_set_nodes(cccp, obj->mc_nodes);
222
+ cccp->enable(obj);
223
+ cccp->configure_nodes(*obj->mc_nodes);
176
224
  } else {
177
- lcb_confmon_set_provider_active(obj->confmon, LCB_CLCONFIG_CCCP, 0);
225
+ obj->confmon->set_active(CLCONFIG_CCCP, false);
178
226
  }
179
227
  return LCB_SUCCESS;
180
228
  }
@@ -345,10 +393,20 @@ lcb_error_t lcb_create(lcb_t *instance,
345
393
  /* initialize the settings */
346
394
  obj->type = type;
347
395
  obj->settings = settings;
396
+ obj->settings->conntype = type;
348
397
 
349
398
  settings->bucket = strdup(spec.bucket().c_str());
350
- if ((err = settings->auth->init(spec.username(), spec.bucket(),
351
- spec.password(), type)) != LCB_SUCCESS) {
399
+
400
+ if (!spec.username().empty()) {
401
+ settings->auth->set_mode(LCBAUTH_MODE_RBAC);
402
+ err = settings->auth->add(spec.username(), spec.password(),
403
+ LCBAUTH_F_CLUSTER);
404
+ } else {
405
+ settings->auth->set_mode(LCBAUTH_MODE_CLASSIC);
406
+ err = settings->auth->add(spec.bucket(), spec.password(),
407
+ LCBAUTH_F_BUCKET);
408
+ }
409
+ if (err != LCB_SUCCESS) {
352
410
  goto GT_DONE;
353
411
  }
354
412
 
@@ -373,13 +431,19 @@ lcb_error_t lcb_create(lcb_t *instance,
373
431
 
374
432
  obj->cmdq.cqdata = obj;
375
433
  obj->iotable = lcbio_table_new(io_priv);
376
- obj->memd_sockpool = lcbio_mgr_create(settings, obj->iotable);
377
- obj->http_sockpool = lcbio_mgr_create(settings, obj->iotable);
378
- obj->memd_sockpool->maxidle = 1;
379
- obj->memd_sockpool->tmoidle = 10000000;
380
- obj->http_sockpool->maxidle = 1;
381
- obj->http_sockpool->tmoidle = 10000000;
382
- obj->confmon = lcb_confmon_create(settings, obj->iotable);
434
+ obj->memd_sockpool = new io::Pool(settings, obj->iotable);
435
+ obj->http_sockpool = new io::Pool(settings, obj->iotable);
436
+
437
+ {
438
+ // Needs its own scope because there are prior GOTOs
439
+ io::Pool::Options pool_opts;
440
+ pool_opts.maxidle = 1;
441
+ pool_opts.tmoidle = LCB_MS2US(10000); // 10 seconds
442
+ obj->memd_sockpool->set_options(pool_opts);
443
+ obj->http_sockpool->set_options(pool_opts);
444
+ }
445
+
446
+ obj->confmon = new clconfig::Confmon(settings, obj->iotable);
383
447
  obj->ht_nodes = new Hostlist();
384
448
  obj->mc_nodes = new Hostlist();
385
449
  obj->retryq = new RetryQueue(&obj->cmdq, obj->iotable, obj->settings);
@@ -398,8 +462,15 @@ lcb_error_t lcb_create(lcb_t *instance,
398
462
  goto GT_DONE;
399
463
  }
400
464
 
465
+ if ((err = obj->process_dns_srv(spec)) != LCB_SUCCESS) {
466
+ goto GT_DONE;
467
+ }
468
+
401
469
  obj->populate_nodes(spec);
402
- err = init_providers(obj, spec);
470
+ if ((err = init_providers(obj, spec)) != LCB_SUCCESS) {
471
+ goto GT_DONE;
472
+ }
473
+
403
474
  if (err != LCB_SUCCESS) {
404
475
  lcb_destroy(obj);
405
476
  return err;
@@ -437,6 +508,8 @@ extern "C" {
437
508
  void lcbdur_destroy(void*);
438
509
  }
439
510
 
511
+ static void do_pool_shutdown(io::Pool *pool) { pool->shutdown(); }
512
+
440
513
  LIBCOUCHBASE_API
441
514
  void lcb_destroy(lcb_t instance)
442
515
  {
@@ -446,10 +519,12 @@ void lcb_destroy(lcb_t instance)
446
519
  lcb_ASPEND_SETTYPE::iterator it;
447
520
  lcb_ASPEND_SETTYPE *pendq;
448
521
 
449
- DESTROY(lcb_clconfig_decref, cur_configinfo);
522
+ if (instance->cur_configinfo) {
523
+ instance->cur_configinfo->decref();
524
+ instance->cur_configinfo = NULL;
525
+ }
450
526
  instance->cmdq.config = NULL;
451
-
452
- lcb_bootstrap_destroy(instance);
527
+ DESTROY(delete, bs_state);
453
528
  DESTROY(delete, ht_nodes);
454
529
  DESTROY(delete, mc_nodes);
455
530
 
@@ -473,16 +548,16 @@ void lcb_destroy(lcb_t instance)
473
548
 
474
549
  if ((pendq = po->items[LCB_PENDTYPE_HTTP])) {
475
550
  for (it = pendq->begin(); it != pendq->end(); ++it) {
476
- lcb_http_request_t htreq = reinterpret_cast<lcb_http_request_t>(*it);
477
- lcb_htreq_block_callback(htreq);
478
- lcb_htreq_finish(instance, htreq, LCB_ERROR);
551
+ http::Request *htreq = reinterpret_cast<http::Request*>(*it);
552
+ htreq->block_callback();
553
+ htreq->finish(LCB_ERROR);
479
554
  }
480
555
  }
481
556
 
482
557
  DESTROY(delete, retryq);
483
- DESTROY(lcb_confmon_destroy, confmon);
484
- DESTROY(lcbio_mgr_destroy, memd_sockpool);
485
- DESTROY(lcbio_mgr_destroy, http_sockpool);
558
+ DESTROY(delete, confmon);
559
+ DESTROY(do_pool_shutdown, memd_sockpool);
560
+ DESTROY(do_pool_shutdown, http_sockpool);
486
561
  DESTROY(lcb_vbguess_destroy, vbguess);
487
562
  DESTROY(lcb_n1qlcache_destroy, n1ql_cache);
488
563
 
@@ -534,10 +609,23 @@ lcb_destroy_async(lcb_t instance, const void *arg)
534
609
  lcbio_async_signal(instance->dtor_timer);
535
610
  }
536
611
 
612
+ lcb::Server *
613
+ lcb_st::find_server(const lcb_host_t& host) const
614
+ {
615
+ unsigned ii;
616
+ for (ii = 0; ii < cmdq.npipelines; ii++) {
617
+ lcb::Server *server = static_cast<lcb::Server*>(cmdq.pipelines[ii]);
618
+ if (lcb_host_equals(&server->get_host(), &host)) {
619
+ return server;
620
+ }
621
+ }
622
+ return NULL;
623
+ }
624
+
537
625
  LIBCOUCHBASE_API
538
626
  lcb_error_t lcb_connect(lcb_t instance)
539
627
  {
540
- lcb_error_t err = lcb_bootstrap_common(instance, LCB_BS_REFRESH_INITIAL);
628
+ lcb_error_t err = instance->bootstrap(BS_REFRESH_INITIAL);
541
629
  if (err == LCB_SUCCESS) {
542
630
  SYNCMODE_INTERCEPT(instance);
543
631
  } else {
@@ -718,6 +806,15 @@ const char *lcb_strerror(lcb_t instance, lcb_error_t error)
718
806
  return "Unknown error";
719
807
  }
720
808
 
809
+ LCB_INTERNAL_API
810
+ const char *lcb_strerror_short(lcb_error_t error)
811
+ {
812
+ #define X(c, v, t, s) if (error == c) { return #c " (" #v ")"; }
813
+ LCB_XERR(X)
814
+ #undef X
815
+ return "<FIXME: Not an LCB error>";
816
+ }
817
+
721
818
  LIBCOUCHBASE_API
722
819
  int lcb_get_errtype(lcb_error_t err)
723
820
  {