libcouchbase 0.0.9 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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
  }