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
@@ -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
  {