libcouchbase 0.0.9 → 0.1.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 (40) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +4 -4
  3. data/README.md +4 -0
  4. data/ext/libcouchbase/CMakeLists.txt +1 -1
  5. data/ext/libcouchbase/RELEASE_NOTES.markdown +42 -0
  6. data/ext/libcouchbase/cmake/Modules/GetVersionInfo.cmake +3 -3
  7. data/ext/libcouchbase/cmake/source_files.cmake +1 -0
  8. data/ext/libcouchbase/include/libcouchbase/cntl.h +27 -1
  9. data/ext/libcouchbase/include/libcouchbase/couchbase.h +0 -10
  10. data/ext/libcouchbase/include/libcouchbase/error.h +8 -1
  11. data/ext/libcouchbase/include/memcached/protocol_binary.h +12 -3
  12. data/ext/libcouchbase/src/auth.cc +0 -4
  13. data/ext/libcouchbase/src/cntl.cc +11 -1
  14. data/ext/libcouchbase/src/connspec.cc +18 -0
  15. data/ext/libcouchbase/src/connspec.h +10 -0
  16. data/ext/libcouchbase/src/dns-srv.cc +13 -14
  17. data/ext/libcouchbase/src/errmap.cc +107 -0
  18. data/ext/libcouchbase/src/errmap.h +113 -0
  19. data/ext/libcouchbase/src/hostlist.cc +0 -35
  20. data/ext/libcouchbase/src/hostlist.h +38 -64
  21. data/ext/libcouchbase/src/http/http.cc +6 -1
  22. data/ext/libcouchbase/src/instance.cc +1 -1
  23. data/ext/libcouchbase/src/internal.h +10 -0
  24. data/ext/libcouchbase/src/mcserver/mcserver.cc +119 -3
  25. data/ext/libcouchbase/src/mcserver/mcserver.h +3 -1
  26. data/ext/libcouchbase/src/mcserver/negotiate.cc +130 -37
  27. data/ext/libcouchbase/src/nodeinfo.cc +1 -1
  28. data/ext/libcouchbase/src/settings.c +3 -0
  29. data/ext/libcouchbase/src/settings.h +5 -0
  30. data/ext/libcouchbase/src/ssl/ssl_common.c +2 -0
  31. data/ext/libcouchbase/tests/basic/t_host.cc +67 -75
  32. data/ext/libcouchbase/tests/iotests/mock-environment.h +2 -1
  33. data/ext/libcouchbase/tests/iotests/t_confmon.cc +3 -4
  34. data/ext/libcouchbase/tests/iotests/t_errmap.cc +97 -0
  35. data/lib/libcouchbase/bucket.rb +27 -12
  36. data/lib/libcouchbase/callbacks.rb +1 -1
  37. data/lib/libcouchbase/connection.rb +18 -5
  38. data/lib/libcouchbase/version.rb +1 -1
  39. data/spec/connection_spec.rb +1 -1
  40. metadata +5 -2
@@ -173,10 +173,12 @@ public:
173
173
 
174
174
  enum ReadState {
175
175
  PKT_READ_COMPLETE,
176
- PKT_READ_PARTIAL
176
+ PKT_READ_PARTIAL,
177
+ PKT_READ_ABORT
177
178
  };
178
179
 
179
180
  ReadState try_read(lcbio_CTX *ctx, rdb_IOROPE *ior);
181
+ bool handle_unknown_error(const MemcachedResponse& resinfo, lcb_error_t& newerr);
180
182
  bool handle_nmv(MemcachedResponse& resinfo, mc_PACKET *oldpkt);
181
183
  bool maybe_retry_packet(mc_PACKET *pkt, lcb_error_t err);
182
184
  bool maybe_reconnect_on_fake_timeout(lcb_error_t received_error);
@@ -16,6 +16,10 @@
16
16
  */
17
17
 
18
18
  #include <algorithm>
19
+ #include <string>
20
+ #include <sstream>
21
+ #include <vector>
22
+
19
23
  #include "packetutils.h"
20
24
  #include "mcserver.h"
21
25
  #include "logging.h"
@@ -26,6 +30,7 @@
26
30
  #include <cbsasl/cbsasl.h>
27
31
  #include "negotiate.h"
28
32
  #include "ctx-log-inl.h"
33
+ #include "auth-priv.h"
29
34
 
30
35
  using namespace lcb;
31
36
 
@@ -34,6 +39,7 @@ static void cleanup_negotiated(SessionInfo* info);
34
39
  static void handle_ioerr(lcbio_CTX *ctx, lcb_error_t err);
35
40
  #define SESSREQ_LOGFMT "<%s:%s> (SASLREQ=%p) "
36
41
 
42
+
37
43
  static void timeout_handler(void *arg);
38
44
 
39
45
  #define SESSREQ_LOGID(s) get_ctx_host(s->ctx), get_ctx_port(s->ctx), (void*)s
@@ -65,9 +71,12 @@ public:
65
71
  bool read_hello(const lcb::MemcachedResponse& packet);
66
72
  void send_auth(const char *sasl_data, unsigned ndata);
67
73
  void handle_read(lcbio_CTX *ioctx);
74
+ bool maybe_select_bucket();
68
75
 
69
76
  enum MechStatus { MECH_UNAVAILABLE, MECH_NOT_NEEDED, MECH_OK };
70
77
  MechStatus set_chosen_mech(std::string& mechlist, const char **data, unsigned int *ndata);
78
+ bool request_errmap();
79
+ bool update_errmap(const lcb::MemcachedResponse& packet);
71
80
 
72
81
  SessionRequestImpl(lcbio_CONNDONE_cb callback, void *data, uint32_t timeout, lcbio_TABLE *iot, lcb_settings* settings_)
73
82
  : ctx(NULL), cb(callback), cbdata(data),
@@ -324,6 +333,10 @@ SessionRequestImpl::send_hello()
324
333
  unsigned nfeatures = 0;
325
334
  features[nfeatures++] = PROTOCOL_BINARY_FEATURE_TLS;
326
335
  features[nfeatures++] = PROTOCOL_BINARY_FEATURE_XATTR;
336
+ features[nfeatures++] = PROTOCOL_BINARY_FEATURE_SELECT_BUCKET;
337
+ if (settings->use_errmap) {
338
+ features[nfeatures++] = PROTOCOL_BINARY_FEATURE_XERROR;
339
+ }
327
340
  if (settings->tcp_nodelay) {
328
341
  features[nfeatures++] = PROTOCOL_BINARY_FEATURE_TCPNODELAY;
329
342
  }
@@ -360,6 +373,7 @@ SessionRequestImpl::send_hello()
360
373
  lcb_U16 tmp = htons(features[ii]);
361
374
  lcbio_ctx_put(ctx, &tmp, sizeof tmp);
362
375
  }
376
+
363
377
  lcbio_ctx_rwant(ctx, 24);
364
378
  return true;
365
379
  }
@@ -381,12 +395,68 @@ SessionRequestImpl::read_hello(const lcb::MemcachedResponse& resp)
381
395
  return true;
382
396
  }
383
397
 
384
- typedef enum {
385
- SREQ_S_WAIT,
386
- SREQ_S_AUTHDONE,
387
- SREQ_S_HELLODONE,
388
- SREQ_S_ERROR
389
- } sreq_STATE;
398
+ bool
399
+ SessionRequestImpl::request_errmap() {
400
+ lcb::MemcachedRequest hdr(PROTOCOL_BINARY_CMD_GET_ERROR_MAP);
401
+ uint16_t version = htons(1);
402
+ hdr.sizes(0, 0, 2);
403
+ const char *p = reinterpret_cast<const char *>(&version);
404
+
405
+ lcbio_ctx_put(ctx, hdr.data(), hdr.size());
406
+ lcbio_ctx_put(ctx, p, 2);
407
+ lcbio_ctx_rwant(ctx, 24);
408
+ return true;
409
+ }
410
+
411
+ bool
412
+ SessionRequestImpl::update_errmap(const lcb::MemcachedResponse& resp)
413
+ {
414
+ // Get the error map object
415
+ using lcb::errmap::ErrorMap;
416
+
417
+ std::string errmsg;
418
+ ErrorMap& mm = *settings->errmap;
419
+ ErrorMap::ParseStatus status = mm.parse(
420
+ resp.body<const char*>(), resp.bodylen(), errmsg);
421
+
422
+ if (status != ErrorMap::UPDATED && status != ErrorMap::NOT_UPDATED) {
423
+ errmsg = "Couldn't update error map: " + errmsg;
424
+ set_error(LCB_PROTOCOL_ERROR, errmsg.c_str());
425
+ return false;
426
+ }
427
+
428
+ return true;
429
+ }
430
+
431
+ // Returns true if sending the SELECT_BUCKET command, false otherwise.
432
+ bool
433
+ SessionRequestImpl::maybe_select_bucket() {
434
+
435
+ // Only send a SELECT_BUCKET if we have the SELECT_BUCKET bit enabled.
436
+ if (!info->has_feature(PROTOCOL_BINARY_FEATURE_SELECT_BUCKET)) {
437
+ return false;
438
+ }
439
+
440
+ if (!settings->select_bucket) {
441
+ lcb_log(LOGARGS(this, WARN), SESSREQ_LOGFMT "SELECT_BUCKET Disabled by application", SESSREQ_LOGID(this));
442
+ return false;
443
+ }
444
+
445
+ // send the SELECT_BUCKET command:
446
+ lcb_log(LOGARGS(this, INFO), SESSREQ_LOGFMT "Sending SELECT_BUCKET", SESSREQ_LOGID(this));
447
+ lcb::MemcachedRequest req(PROTOCOL_BINARY_CMD_SELECT_BUCKET);
448
+ req.sizes(0, strlen(settings->bucket), 0);
449
+ lcbio_ctx_put(ctx, req.data(), req.size());
450
+ lcbio_ctx_put(ctx, settings->bucket, strlen(settings->bucket));
451
+ LCBIO_CTX_RSCHEDULE(ctx, 24);
452
+ return true;
453
+ }
454
+
455
+ static bool isUnsupported(uint16_t status) {
456
+ return status == PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED ||
457
+ status == PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND ||
458
+ status == PROTOCOL_BINARY_RESPONSE_EACCESS;
459
+ }
390
460
 
391
461
  /**
392
462
  * It's assumed the server buffers will be reset upon close(), so we must make
@@ -397,7 +467,7 @@ SessionRequestImpl::handle_read(lcbio_CTX *ioctx)
397
467
  {
398
468
  lcb::MemcachedResponse resp;
399
469
  unsigned required;
400
- sreq_STATE state = SREQ_S_WAIT;
470
+ bool completed = false;
401
471
 
402
472
  GT_NEXT_PACKET:
403
473
 
@@ -416,66 +486,92 @@ SessionRequestImpl::handle_read(lcbio_CTX *ioctx)
416
486
  MechStatus mechrc = set_chosen_mech(mechs, &mechlist_data, &nmechlist_data);
417
487
  if (mechrc == MECH_OK) {
418
488
  send_auth(mechlist_data, nmechlist_data);
419
- state = SREQ_S_WAIT;
420
489
  } else if (mechrc == MECH_UNAVAILABLE) {
421
- state = SREQ_S_ERROR;
490
+ // Do nothing - error already set
422
491
  } else {
423
- state = SREQ_S_HELLODONE;
492
+ completed = !maybe_select_bucket();
424
493
  }
425
494
  break;
426
495
  }
427
496
 
428
497
  case PROTOCOL_BINARY_CMD_SASL_AUTH: {
429
498
  if (status == PROTOCOL_BINARY_RESPONSE_SUCCESS) {
430
- send_hello();
431
- state = SREQ_S_AUTHDONE;
499
+ completed = !maybe_select_bucket();
432
500
  break;
433
- }
434
-
435
- if (status != PROTOCOL_BINARY_RESPONSE_AUTH_CONTINUE) {
501
+ } else if (status == PROTOCOL_BINARY_RESPONSE_AUTH_CONTINUE) {
502
+ send_step(resp);
503
+ } else {
436
504
  set_error(LCB_AUTH_ERROR, "SASL AUTH failed");
437
- state = SREQ_S_ERROR;
438
505
  break;
439
506
  }
440
- if (send_step(resp) && send_hello()) {
441
- state = SREQ_S_WAIT;
442
- } else {
443
- state = SREQ_S_ERROR;
444
- }
445
507
  break;
446
508
  }
447
509
 
448
510
  case PROTOCOL_BINARY_CMD_SASL_STEP: {
449
- if (status != PROTOCOL_BINARY_RESPONSE_SUCCESS) {
511
+ if (status == PROTOCOL_BINARY_RESPONSE_SUCCESS) {
512
+ completed = !maybe_select_bucket();
513
+ } else {
450
514
  lcb_log(LOGARGS(this, WARN), SESSREQ_LOGFMT "SASL auth failed with STATUS=0x%x", SESSREQ_LOGID(this), status);
451
515
  set_error(LCB_AUTH_ERROR, "SASL Step Failed");
452
- state = SREQ_S_ERROR;
453
- } else {
454
- /* Wait for pipelined HELLO response */
455
- state = SREQ_S_AUTHDONE;
456
516
  }
457
517
  break;
458
518
  }
459
519
 
460
520
  case PROTOCOL_BINARY_CMD_HELLO: {
461
- state = SREQ_S_HELLODONE;
462
521
  if (status == PROTOCOL_BINARY_RESPONSE_SUCCESS) {
463
522
  if (!read_hello(resp)) {
464
523
  set_error(LCB_PROTOCOL_ERROR, "Couldn't parse HELLO");
524
+ break;
465
525
  }
466
- } else if (status == PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND ||
467
- status == PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED) {
526
+ } else if (isUnsupported(status)) {
468
527
  lcb_log(LOGARGS(this, DEBUG), SESSREQ_LOGFMT "Server does not support HELLO", SESSREQ_LOGID(this));
469
- /* nothing */
470
528
  } else {
471
529
  set_error(LCB_PROTOCOL_ERROR, "Hello response unexpected");
472
- state = SREQ_S_ERROR;
530
+ break;
531
+ }
532
+
533
+ if (info->has_feature(PROTOCOL_BINARY_FEATURE_XERROR)) {
534
+ request_errmap();
535
+ } else {
536
+ lcb_log(LOGARGS(this, TRACE), SESSREQ_LOGFMT "GET_ERRORMAP unsupported/disabled", SESSREQ_LOGID(this));
537
+ }
538
+
539
+ // In any event, it's also time to send the LIST_MECHS request
540
+ lcb::MemcachedRequest req(PROTOCOL_BINARY_CMD_SASL_LIST_MECHS);
541
+ lcbio_ctx_put(ctx, req.data(), req.size());
542
+ LCBIO_CTX_RSCHEDULE(ctx, 24);
543
+
544
+ break;
545
+ }
546
+
547
+ case PROTOCOL_BINARY_CMD_GET_ERROR_MAP: {
548
+ if (status == PROTOCOL_BINARY_RESPONSE_SUCCESS) {
549
+ if (!update_errmap(resp)) {
550
+ }
551
+ } else if (isUnsupported(status)) {
552
+ lcb_log(LOGARGS(this, DEBUG), SESSREQ_LOGFMT "Server does not support GET_ERRMAP (0x%x)", SESSREQ_LOGID(this), status);
553
+ } else {
554
+ lcb_log(LOGARGS(this, ERROR), SESSREQ_LOGFMT "Unexpected status 0x%x received for GET_ERRMAP", SESSREQ_LOGID(this), status);
555
+ set_error(LCB_PROTOCOL_ERROR, "GET_ERRMAP response unexpected");
556
+ }
557
+ // Note, there is no explicit state transition here. LIST_MECHS is
558
+ // pipelined after this request.
559
+ break;
560
+ }
561
+
562
+ case PROTOCOL_BINARY_CMD_SELECT_BUCKET: {
563
+ if (status == PROTOCOL_BINARY_RESPONSE_SUCCESS) {
564
+ completed = true;
565
+ } else if (status == PROTOCOL_BINARY_RESPONSE_EACCESS) {
566
+ set_error(LCB_AUTH_ERROR, "Provided credentials not allowed for bucket");
567
+ } else {
568
+ lcb_log(LOGARGS(this, ERROR), SESSREQ_LOGFMT "Unexpected status 0x%x received for SELECT_BUCKET", SESSREQ_LOGID(this), status);
569
+ set_error(LCB_PROTOCOL_ERROR, "Other auth error");
473
570
  }
474
571
  break;
475
572
  }
476
573
 
477
574
  default: {
478
- state = SREQ_S_ERROR;
479
575
  lcb_log(LOGARGS(this, ERROR), SESSREQ_LOGFMT "Received unknown response. OP=0x%x. RC=0x%x", SESSREQ_LOGID(this), resp.opcode(), resp.status());
480
576
  set_error(LCB_NOT_SUPPORTED, "Received unknown response");
481
577
  break;
@@ -490,9 +586,7 @@ SessionRequestImpl::handle_read(lcbio_CTX *ioctx)
490
586
  // or fail the request, potentially destroying the underlying connection
491
587
  if (has_error()) {
492
588
  fail();
493
- } else if (state == SREQ_S_ERROR) {
494
- fail(LCB_ERROR, "FIXME: Error code set without description");
495
- } else if (state == SREQ_S_HELLODONE) {
589
+ } else if (completed) {
496
590
  success();
497
591
  } else {
498
592
  goto GT_NEXT_PACKET;
@@ -537,8 +631,7 @@ SessionRequestImpl::start(lcbio_SOCKET *sock) {
537
631
  return;
538
632
  }
539
633
 
540
- lcb::MemcachedRequest hdr(PROTOCOL_BINARY_CMD_SASL_LIST_MECHS);
541
- lcbio_ctx_put(ctx, hdr.data(), hdr.size());
634
+ send_hello();
542
635
  LCBIO_CTX_RSCHEDULE(ctx, 24);
543
636
  }
544
637
 
@@ -167,7 +167,7 @@ lcb_int32_t lcb_get_num_nodes(lcb_t instance)
167
167
  LIBCOUCHBASE_API
168
168
  const char *const *lcb_get_server_list(lcb_t instance)
169
169
  {
170
- return hostlist_strents(instance->ht_nodes);
170
+ return instance->ht_nodes->get_strlist();
171
171
  }
172
172
 
173
173
  LIBCOUCHBASE_API
@@ -57,6 +57,7 @@ void lcb_default_settings(lcb_settings *settings)
57
57
  settings->tcp_nodelay = LCB_DEFAULT_TCP_NODELAY;
58
58
  settings->retry_nmv_interval = LCB_DEFAULT_RETRY_NMV_INTERVAL;
59
59
  settings->vb_noguess = LCB_DEFAULT_VB_NOGUESS;
60
+ settings->select_bucket = LCB_DEFAULT_SELECT_BUCKET;
60
61
  }
61
62
 
62
63
  LCB_INTERNAL_API
@@ -67,6 +68,7 @@ lcb_settings_new(void)
67
68
  lcb_default_settings(settings);
68
69
  settings->refcount = 1;
69
70
  settings->auth = lcbauth_new();
71
+ settings->errmap = lcb_errmap_new();
70
72
  return settings;
71
73
  }
72
74
 
@@ -83,6 +85,7 @@ lcb_settings_unref(lcb_settings *settings)
83
85
  free(settings->client_string);
84
86
 
85
87
  lcbauth_unref(settings->auth);
88
+ lcb_errmap_free(settings->errmap);
86
89
 
87
90
  if (settings->ssl_ctx) {
88
91
  lcbio_ssl_free(settings->ssl_ctx);
@@ -84,9 +84,11 @@
84
84
  #define LCB_DEFAULT_RETRY_NMV_INTERVAL LCB_MS2US(100)
85
85
  #define LCB_DEFAULT_VB_NOGUESS 1
86
86
  #define LCB_DEFAULT_TCP_NODELAY 1
87
+ #define LCB_DEFAULT_SELECT_BUCKET 0
87
88
 
88
89
  #include "config.h"
89
90
  #include <libcouchbase/couchbase.h>
91
+ #include "errmap.h"
90
92
 
91
93
  #ifdef __cplusplus
92
94
  extern "C" {
@@ -148,6 +150,8 @@ typedef struct lcb_settings_st {
148
150
  unsigned ipv6 : 2;
149
151
  unsigned tcp_nodelay : 1;
150
152
  unsigned readj_ts_wait : 1;
153
+ unsigned use_errmap : 1;
154
+ unsigned select_bucket : 1;
151
155
 
152
156
  short max_redir;
153
157
  unsigned refcount;
@@ -165,6 +169,7 @@ typedef struct lcb_settings_st {
165
169
  void (*dtorcb)(const void *);
166
170
  void *dtorarg;
167
171
  char *client_string;
172
+ lcb_pERRMAP errmap;
168
173
  lcb_U32 retry_nmv_interval;
169
174
  } lcb_settings;
170
175
 
@@ -156,7 +156,9 @@ iotssl_log_errors(lcbio_XSSL *xs)
156
156
  if (ERR_GET_LIB(curerr) == ERR_LIB_SSL) {
157
157
  switch (ERR_GET_REASON(curerr)) {
158
158
  case SSL_R_CERTIFICATE_VERIFY_FAILED:
159
+ #ifdef SSL_R_MISSING_VERIFY_MESSAGE
159
160
  case SSL_R_MISSING_VERIFY_MESSAGE:
161
+ #endif
160
162
  xs->errcode = LCB_SSL_CANTVERIFY;
161
163
  break;
162
164
 
@@ -82,117 +82,109 @@ TEST_F(Hostlist, testEquals)
82
82
 
83
83
  TEST_F(Hostlist, testParseList)
84
84
  {
85
- hostlist_t hosts = hostlist_create();
86
- ASSERT_FALSE(NULL == hosts);
85
+ lcb::Hostlist hosts;
87
86
 
88
87
  lcb_error_t err;
89
- err = hostlist_add_stringz(hosts, "1.1.1.1", 8091);
88
+ err = hosts.add("1.1.1.1", 8091);
90
89
  ASSERT_EQ(LCB_SUCCESS, err);
91
- ASSERT_EQ(1, hosts->size());
92
- ASSERT_TRUE(hosts->exists("1.1.1.1:8091"));
90
+ ASSERT_EQ(1, hosts.size());
91
+ ASSERT_TRUE(hosts.exists("1.1.1.1:8091"));
93
92
 
94
-
95
- hostlist_clear(hosts);
96
- err = hostlist_add_stringz(hosts, "1.1.1.1;", 8091);
93
+ hosts.clear();
94
+ err = hosts.add("1.1.1.1;", 8091);
97
95
  ASSERT_EQ(LCB_SUCCESS, err);
98
- ASSERT_EQ(1, hosts->size());
99
- ASSERT_TRUE(hosts->exists("1.1.1.1:8091"));
96
+ ASSERT_EQ(1, hosts.size());
97
+ ASSERT_TRUE(hosts.exists("1.1.1.1:8091"));
100
98
 
101
- hostlist_clear(hosts);
102
- err = hostlist_add_stringz(hosts, ";", 8091);
99
+ hosts.clear();
100
+ err = hosts.add(";", 8091);
103
101
  ASSERT_EQ(LCB_SUCCESS, err);
104
- ASSERT_EQ(0, hosts->size());
102
+ ASSERT_EQ(0, hosts.size());
105
103
 
106
- hostlist_clear(hosts);
107
- err = hostlist_add_stringz(hosts, ";;;;", 8091);
104
+ hosts.clear();
105
+ err = hosts.add(";;;;", 8091);
108
106
  ASSERT_EQ(LCB_SUCCESS, err);
109
- ASSERT_EQ(0, hosts->size());
107
+ ASSERT_EQ(0, hosts.size());
110
108
 
111
- hostlist_clear(hosts);
112
- err = hostlist_add_stringz(hosts, "1.1.1.1;2.2.2.2", 8091);
109
+ hosts.clear();
110
+ err = hosts.add("1.1.1.1;2.2.2.2", 8091);
113
111
  ASSERT_EQ(LCB_SUCCESS, err);
114
- ASSERT_EQ(2, hosts->size());
115
- ASSERT_TRUE(hosts->exists("1.1.1.1:8091"));
116
- ASSERT_TRUE(hosts->exists("2.2.2.2:8091"));
117
-
112
+ ASSERT_EQ(2, hosts.size());
113
+ ASSERT_TRUE(hosts.exists("1.1.1.1:8091"));
114
+ ASSERT_TRUE(hosts.exists("2.2.2.2:8091"));
118
115
 
119
- hostlist_clear(hosts);
120
- err = hostlist_add_stringz(hosts, "1.1.1.1:1000;2.2.2.2:2000;3.3.3.3", 8091);
116
+ hosts.clear();
117
+ err = hosts.add("1.1.1.1:1000;2.2.2.2:2000;3.3.3.3", 8091);
121
118
  ASSERT_EQ(LCB_SUCCESS, err);
122
- ASSERT_EQ(3, hosts->size());
123
- ASSERT_TRUE(hosts->exists("1.1.1.1:1000"));
124
- ASSERT_TRUE(hosts->exists("2.2.2.2:2000"));
125
- ASSERT_TRUE(hosts->exists("3.3.3.3:8091"));
119
+ ASSERT_EQ(3, hosts.size());
120
+ ASSERT_TRUE(hosts.exists("1.1.1.1:1000"));
121
+ ASSERT_TRUE(hosts.exists("2.2.2.2:2000"));
122
+ ASSERT_TRUE(hosts.exists("3.3.3.3:8091"));
126
123
 
127
- hostlist_clear(hosts);
128
- err = hostlist_add_stringz(hosts, "1.1.1.1;1.1.1.1;1.1.1.1", 8091);
124
+ hosts.clear();
125
+ err = hosts.add("1.1.1.1;1.1.1.1;1.1.1.1", 8091);
129
126
  ASSERT_EQ(LCB_SUCCESS, err);
130
- ASSERT_EQ(1, hosts->size());
131
- ASSERT_TRUE(hosts->exists("1.1.1.1:8091"));
127
+ ASSERT_EQ(1, hosts.size());
128
+ ASSERT_TRUE(hosts.exists("1.1.1.1:8091"));
132
129
 
133
130
 
134
- hostlist_clear(hosts);
135
- err = hostlist_add_stringz(hosts, "1.1.1.1:9000;1.1.1.1:9001;1.1.1.1:9002", 8091);
131
+ hosts.clear();
132
+ err = hosts.add("1.1.1.1:9000;1.1.1.1:9001;1.1.1.1:9002", 8091);
136
133
  ASSERT_EQ(LCB_SUCCESS, err);
137
- ASSERT_EQ(3, hosts->size());
138
- ASSERT_TRUE(hosts->exists("1.1.1.1:9000"));
139
- ASSERT_TRUE(hosts->exists("1.1.1.1:9001"));
140
- ASSERT_TRUE(hosts->exists("1.1.1.1:9002"));
141
-
142
- hostlist_clear(hosts);
143
- ASSERT_EQ(LCB_SUCCESS, hostlist_add_stringz(hosts, "1.1.1.1", 8091));
144
- ASSERT_EQ(LCB_SUCCESS, hostlist_add_stringz(hosts, "2.2.2.2", 8091));
145
- ASSERT_EQ(LCB_SUCCESS, hostlist_add_stringz(hosts, "3.3.3.3", 8091));
146
- ASSERT_EQ(3, hosts->size());
147
-
148
- ASSERT_TRUE(hosts->exists("1.1.1.1:8091"));
149
- ASSERT_TRUE(hosts->exists("2.2.2.2:8091"));
150
- ASSERT_TRUE(hosts->exists("3.3.3.3:8091"));
151
-
152
- hostlist_randomize(hosts);
153
- hostlist_clear(hosts);
154
- hostlist_randomize(hosts);
155
-
156
- hostlist_destroy(hosts);
134
+ ASSERT_EQ(3, hosts.size());
135
+ ASSERT_TRUE(hosts.exists("1.1.1.1:9000"));
136
+ ASSERT_TRUE(hosts.exists("1.1.1.1:9001"));
137
+ ASSERT_TRUE(hosts.exists("1.1.1.1:9002"));
138
+
139
+ hosts.clear();
140
+ ASSERT_EQ(LCB_SUCCESS, hosts.add("1.1.1.1", 8091));
141
+ ASSERT_EQ(LCB_SUCCESS, hosts.add("2.2.2.2", 8091));
142
+ ASSERT_EQ(LCB_SUCCESS, hosts.add("3.3.3.3", 8091));
143
+ ASSERT_EQ(3, hosts.size());
144
+
145
+ ASSERT_TRUE(hosts.exists("1.1.1.1:8091"));
146
+ ASSERT_TRUE(hosts.exists("2.2.2.2:8091"));
147
+ ASSERT_TRUE(hosts.exists("3.3.3.3:8091"));
148
+
149
+ hosts.randomize();
150
+ hosts.clear();
151
+ hosts.randomize();
157
152
  }
158
153
 
159
154
  TEST_F(Hostlist, testCycle)
160
155
  {
161
- hostlist_t hosts = hostlist_create();
156
+ lcb::Hostlist hosts;
162
157
  lcb_host_t *curhost;
163
158
 
164
-
165
159
  // Empty list
166
- ASSERT_EQ(NULL, hostlist_shift_next(hosts, 0));
167
- ASSERT_EQ(NULL, hostlist_shift_next(hosts, 1));
168
- hostlist_destroy(hosts);
169
- hosts = hostlist_create();
160
+ ASSERT_EQ(NULL, hosts.next(false));
161
+ ASSERT_EQ(NULL, hosts.next(true));
170
162
 
171
- hostlist_add_stringz(hosts, "1.1.1.1", 8091);
172
- curhost = hostlist_shift_next(hosts, 0);
163
+ hosts.clear();
164
+ hosts.add("1.1.1.1", 8091);
165
+ curhost = hosts.next(false);
173
166
  ASSERT_TRUE(curhost != NULL);
174
167
  ASSERT_TRUE(hostEquals(*curhost, "1.1.1.1", "8091"));
175
168
 
176
- curhost = hostlist_shift_next(hosts, 0);
177
- ASSERT_TRUE(hostlist_shift_next(hosts, 0) == NULL);
178
- ASSERT_TRUE(hostlist_shift_next(hosts, 0) == NULL);
179
- ASSERT_TRUE(hosts->ix == 1);
169
+ curhost = hosts.next(false);
170
+ ASSERT_TRUE(hosts.next(false) == NULL);
171
+ ASSERT_TRUE(hosts.next(false) == NULL);
172
+ ASSERT_TRUE(hosts.ix == 1);
180
173
 
181
- curhost = hostlist_shift_next(hosts, 1);
174
+ curhost = hosts.next(true);
182
175
  ASSERT_TRUE(curhost != NULL);
183
176
  ASSERT_TRUE(hostEquals(*curhost, "1.1.1.1", "8091"));
184
177
 
185
- hostlist_add_stringz(hosts, "2.2.2.2", 8091);
186
- curhost = hostlist_shift_next(hosts, 0);
178
+ hosts.add("2.2.2.2", 8091);
179
+ curhost = hosts.next(false);
187
180
  ASSERT_TRUE(hostEquals(*curhost, "2.2.2.2", "8091"));
188
- ASSERT_TRUE(hostlist_shift_next(hosts, 0) == NULL);
181
+ ASSERT_TRUE(hosts.next(false) == NULL);
189
182
 
190
- curhost = hostlist_shift_next(hosts, 1);
183
+ curhost = hosts.next(true);
191
184
  ASSERT_TRUE(hostEquals(*curhost, "1.1.1.1", "8091"));
192
- curhost = hostlist_shift_next(hosts, 0);
185
+ curhost = hosts.next(false);
193
186
  ASSERT_TRUE(hostEquals(*curhost, "2.2.2.2", "8091"));
194
187
 
195
- hostlist_clear(hosts);
196
- ASSERT_TRUE(hostlist_shift_next(hosts, 1) == NULL);
197
- hostlist_destroy(hosts);
188
+ hosts.clear();
189
+ ASSERT_TRUE(hosts.next(true) == NULL);
198
190
  }