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.
- checksums.yaml +4 -4
 - data/.travis.yml +4 -4
 - data/README.md +4 -0
 - data/ext/libcouchbase/CMakeLists.txt +1 -1
 - data/ext/libcouchbase/RELEASE_NOTES.markdown +42 -0
 - data/ext/libcouchbase/cmake/Modules/GetVersionInfo.cmake +3 -3
 - data/ext/libcouchbase/cmake/source_files.cmake +1 -0
 - data/ext/libcouchbase/include/libcouchbase/cntl.h +27 -1
 - data/ext/libcouchbase/include/libcouchbase/couchbase.h +0 -10
 - data/ext/libcouchbase/include/libcouchbase/error.h +8 -1
 - data/ext/libcouchbase/include/memcached/protocol_binary.h +12 -3
 - data/ext/libcouchbase/src/auth.cc +0 -4
 - data/ext/libcouchbase/src/cntl.cc +11 -1
 - data/ext/libcouchbase/src/connspec.cc +18 -0
 - data/ext/libcouchbase/src/connspec.h +10 -0
 - data/ext/libcouchbase/src/dns-srv.cc +13 -14
 - data/ext/libcouchbase/src/errmap.cc +107 -0
 - data/ext/libcouchbase/src/errmap.h +113 -0
 - data/ext/libcouchbase/src/hostlist.cc +0 -35
 - data/ext/libcouchbase/src/hostlist.h +38 -64
 - data/ext/libcouchbase/src/http/http.cc +6 -1
 - data/ext/libcouchbase/src/instance.cc +1 -1
 - data/ext/libcouchbase/src/internal.h +10 -0
 - data/ext/libcouchbase/src/mcserver/mcserver.cc +119 -3
 - data/ext/libcouchbase/src/mcserver/mcserver.h +3 -1
 - data/ext/libcouchbase/src/mcserver/negotiate.cc +130 -37
 - data/ext/libcouchbase/src/nodeinfo.cc +1 -1
 - data/ext/libcouchbase/src/settings.c +3 -0
 - data/ext/libcouchbase/src/settings.h +5 -0
 - data/ext/libcouchbase/src/ssl/ssl_common.c +2 -0
 - data/ext/libcouchbase/tests/basic/t_host.cc +67 -75
 - data/ext/libcouchbase/tests/iotests/mock-environment.h +2 -1
 - data/ext/libcouchbase/tests/iotests/t_confmon.cc +3 -4
 - data/ext/libcouchbase/tests/iotests/t_errmap.cc +97 -0
 - data/lib/libcouchbase/bucket.rb +27 -12
 - data/lib/libcouchbase/callbacks.rb +1 -1
 - data/lib/libcouchbase/connection.rb +18 -5
 - data/lib/libcouchbase/version.rb +1 -1
 - data/spec/connection_spec.rb +1 -1
 - 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 
     | 
    
         
            -
             
     | 
| 
       385 
     | 
    
         
            -
             
     | 
| 
       386 
     | 
    
         
            -
                 
     | 
| 
       387 
     | 
    
         
            -
                 
     | 
| 
       388 
     | 
    
         
            -
                 
     | 
| 
       389 
     | 
    
         
            -
             
     | 
| 
      
 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 
     | 
    
         
            -
                 
     | 
| 
      
 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 
     | 
    
         
            -
                         
     | 
| 
      
 490 
     | 
    
         
            +
                        // Do nothing - error already set
         
     | 
| 
       422 
491 
     | 
    
         
             
                    } else {
         
     | 
| 
       423 
     | 
    
         
            -
                         
     | 
| 
      
 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 
     | 
    
         
            -
                         
     | 
| 
       431 
     | 
    
         
            -
                        state = SREQ_S_AUTHDONE;
         
     | 
| 
      
 499 
     | 
    
         
            +
                        completed = !maybe_select_bucket();
         
     | 
| 
       432 
500 
     | 
    
         
             
                        break;
         
     | 
| 
       433 
     | 
    
         
            -
                    }
         
     | 
| 
       434 
     | 
    
         
            -
             
     | 
| 
       435 
     | 
    
         
            -
                     
     | 
| 
      
 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  
     | 
| 
      
 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  
     | 
| 
       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 
     | 
    
         
            -
                         
     | 
| 
      
 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 ( 
     | 
| 
       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 
     | 
    
         
            -
                 
     | 
| 
       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  
     | 
| 
      
 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 
     | 
    
         
            -
                 
     | 
| 
       86 
     | 
    
         
            -
                ASSERT_FALSE(NULL == hosts);
         
     | 
| 
      
 85 
     | 
    
         
            +
                lcb::Hostlist hosts;
         
     | 
| 
       87 
86 
     | 
    
         | 
| 
       88 
87 
     | 
    
         
             
                lcb_error_t err;
         
     | 
| 
       89 
     | 
    
         
            -
                err =  
     | 
| 
      
 88 
     | 
    
         
            +
                err = hosts.add("1.1.1.1",  8091);
         
     | 
| 
       90 
89 
     | 
    
         
             
                ASSERT_EQ(LCB_SUCCESS, err);
         
     | 
| 
       91 
     | 
    
         
            -
                ASSERT_EQ(1, hosts 
     | 
| 
       92 
     | 
    
         
            -
                ASSERT_TRUE(hosts 
     | 
| 
      
 90 
     | 
    
         
            +
                ASSERT_EQ(1, hosts.size());
         
     | 
| 
      
 91 
     | 
    
         
            +
                ASSERT_TRUE(hosts.exists("1.1.1.1:8091"));
         
     | 
| 
       93 
92 
     | 
    
         | 
| 
       94 
     | 
    
         
            -
             
     | 
| 
       95 
     | 
    
         
            -
                 
     | 
| 
       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 
     | 
| 
       99 
     | 
    
         
            -
                ASSERT_TRUE(hosts 
     | 
| 
      
 96 
     | 
    
         
            +
                ASSERT_EQ(1, hosts.size());
         
     | 
| 
      
 97 
     | 
    
         
            +
                ASSERT_TRUE(hosts.exists("1.1.1.1:8091"));
         
     | 
| 
       100 
98 
     | 
    
         | 
| 
       101 
     | 
    
         
            -
                 
     | 
| 
       102 
     | 
    
         
            -
                err =  
     | 
| 
      
 99 
     | 
    
         
            +
                hosts.clear();
         
     | 
| 
      
 100 
     | 
    
         
            +
                err = hosts.add(";",  8091);
         
     | 
| 
       103 
101 
     | 
    
         
             
                ASSERT_EQ(LCB_SUCCESS, err);
         
     | 
| 
       104 
     | 
    
         
            -
                ASSERT_EQ(0, hosts 
     | 
| 
      
 102 
     | 
    
         
            +
                ASSERT_EQ(0, hosts.size());
         
     | 
| 
       105 
103 
     | 
    
         | 
| 
       106 
     | 
    
         
            -
                 
     | 
| 
       107 
     | 
    
         
            -
                err =  
     | 
| 
      
 104 
     | 
    
         
            +
                hosts.clear();
         
     | 
| 
      
 105 
     | 
    
         
            +
                err = hosts.add(";;;;",  8091);
         
     | 
| 
       108 
106 
     | 
    
         
             
                ASSERT_EQ(LCB_SUCCESS, err);
         
     | 
| 
       109 
     | 
    
         
            -
                ASSERT_EQ(0, hosts 
     | 
| 
      
 107 
     | 
    
         
            +
                ASSERT_EQ(0, hosts.size());
         
     | 
| 
       110 
108 
     | 
    
         | 
| 
       111 
     | 
    
         
            -
                 
     | 
| 
       112 
     | 
    
         
            -
                err =  
     | 
| 
      
 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 
     | 
| 
       115 
     | 
    
         
            -
                ASSERT_TRUE(hosts 
     | 
| 
       116 
     | 
    
         
            -
                ASSERT_TRUE(hosts 
     | 
| 
       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 
     | 
    
         
            -
                 
     | 
| 
       120 
     | 
    
         
            -
                err =  
     | 
| 
      
 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 
     | 
| 
       123 
     | 
    
         
            -
                ASSERT_TRUE(hosts 
     | 
| 
       124 
     | 
    
         
            -
                ASSERT_TRUE(hosts 
     | 
| 
       125 
     | 
    
         
            -
                ASSERT_TRUE(hosts 
     | 
| 
      
 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 
     | 
    
         
            -
                 
     | 
| 
       128 
     | 
    
         
            -
                err =  
     | 
| 
      
 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 
     | 
| 
       131 
     | 
    
         
            -
                ASSERT_TRUE(hosts 
     | 
| 
      
 127 
     | 
    
         
            +
                ASSERT_EQ(1, hosts.size());
         
     | 
| 
      
 128 
     | 
    
         
            +
                ASSERT_TRUE(hosts.exists("1.1.1.1:8091"));
         
     | 
| 
       132 
129 
     | 
    
         | 
| 
       133 
130 
     | 
    
         | 
| 
       134 
     | 
    
         
            -
                 
     | 
| 
       135 
     | 
    
         
            -
                err =  
     | 
| 
      
 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 
     | 
| 
       138 
     | 
    
         
            -
                ASSERT_TRUE(hosts 
     | 
| 
       139 
     | 
    
         
            -
                ASSERT_TRUE(hosts 
     | 
| 
       140 
     | 
    
         
            -
                ASSERT_TRUE(hosts 
     | 
| 
       141 
     | 
    
         
            -
             
     | 
| 
       142 
     | 
    
         
            -
                 
     | 
| 
       143 
     | 
    
         
            -
                ASSERT_EQ(LCB_SUCCESS,  
     | 
| 
       144 
     | 
    
         
            -
                ASSERT_EQ(LCB_SUCCESS,  
     | 
| 
       145 
     | 
    
         
            -
                ASSERT_EQ(LCB_SUCCESS,  
     | 
| 
       146 
     | 
    
         
            -
                ASSERT_EQ(3, hosts 
     | 
| 
       147 
     | 
    
         
            -
             
     | 
| 
       148 
     | 
    
         
            -
                ASSERT_TRUE(hosts 
     | 
| 
       149 
     | 
    
         
            -
                ASSERT_TRUE(hosts 
     | 
| 
       150 
     | 
    
         
            -
                ASSERT_TRUE(hosts 
     | 
| 
       151 
     | 
    
         
            -
             
     | 
| 
       152 
     | 
    
         
            -
                 
     | 
| 
       153 
     | 
    
         
            -
                 
     | 
| 
       154 
     | 
    
         
            -
                 
     | 
| 
       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 
     | 
    
         
            -
                 
     | 
| 
      
 156 
     | 
    
         
            +
                lcb::Hostlist hosts;
         
     | 
| 
       162 
157 
     | 
    
         
             
                lcb_host_t *curhost;
         
     | 
| 
       163 
158 
     | 
    
         | 
| 
       164 
     | 
    
         
            -
             
     | 
| 
       165 
159 
     | 
    
         
             
                // Empty list
         
     | 
| 
       166 
     | 
    
         
            -
                ASSERT_EQ(NULL,  
     | 
| 
       167 
     | 
    
         
            -
                ASSERT_EQ(NULL,  
     | 
| 
       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 
     | 
    
         
            -
                 
     | 
| 
       172 
     | 
    
         
            -
                 
     | 
| 
      
 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 =  
     | 
| 
       177 
     | 
    
         
            -
                ASSERT_TRUE( 
     | 
| 
       178 
     | 
    
         
            -
                ASSERT_TRUE( 
     | 
| 
       179 
     | 
    
         
            -
                ASSERT_TRUE(hosts 
     | 
| 
      
 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 =  
     | 
| 
      
 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 
     | 
    
         
            -
                 
     | 
| 
       186 
     | 
    
         
            -
                curhost =  
     | 
| 
      
 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( 
     | 
| 
      
 181 
     | 
    
         
            +
                ASSERT_TRUE(hosts.next(false) == NULL);
         
     | 
| 
       189 
182 
     | 
    
         | 
| 
       190 
     | 
    
         
            -
                curhost =  
     | 
| 
      
 183 
     | 
    
         
            +
                curhost = hosts.next(true);
         
     | 
| 
       191 
184 
     | 
    
         
             
                ASSERT_TRUE(hostEquals(*curhost, "1.1.1.1", "8091"));
         
     | 
| 
       192 
     | 
    
         
            -
                curhost =  
     | 
| 
      
 185 
     | 
    
         
            +
                curhost = hosts.next(false);
         
     | 
| 
       193 
186 
     | 
    
         
             
                ASSERT_TRUE(hostEquals(*curhost, "2.2.2.2", "8091"));
         
     | 
| 
       194 
187 
     | 
    
         | 
| 
       195 
     | 
    
         
            -
                 
     | 
| 
       196 
     | 
    
         
            -
                ASSERT_TRUE( 
     | 
| 
       197 
     | 
    
         
            -
                hostlist_destroy(hosts);
         
     | 
| 
      
 188 
     | 
    
         
            +
                hosts.clear();
         
     | 
| 
      
 189 
     | 
    
         
            +
                ASSERT_TRUE(hosts.next(true) == NULL);
         
     | 
| 
       198 
190 
     | 
    
         
             
            }
         
     |