private InternalState InitBasic(ClusterConfig config, ISaslAuthenticationProvider auth)
        {
            if (log.IsInfoEnabled)
            {
                log.Info("No vbucket. Server count: " + (config.nodes == null ? 0 : config.nodes.Length));
            }

            // the cluster can return host names in the server list, so
            // we ha ve to make sure they are converted to IP addresses
            var nodes = config == null
                                                ? Enumerable.Empty <IMemcachedNode>()
                                                        : (from node in config.nodes
                                                           let ip = new IPEndPoint(GetFirstAddress(node.HostName), node.Port)
                                                                        where node.Status == "healthy"
                                                                    select CreateNode(ip, auth, node.ConfigurationData));

            return(new InternalState
            {
                CurrentNodes = nodes.ToArray(),
                Locator = configuration.CreateNodeLocator() ?? new KetamaNodeLocator(),
                OpFactory = BasicMembaseOperationFactory.Instance
            });
        }
        private void ReconfigurePool(ClusterConfig config)
        {
            // kill the timer first
            this.isTimerActive = false;
            if (this.resurrectTimer != null)
            {
                this.resurrectTimer.Change(Timeout.Infinite, Timeout.Infinite);
            }

            if (config == null)
            {
                if (log.IsInfoEnabled)
                {
                    log.Info("Config is empty, all nodes are down.");
                }

                Interlocked.Exchange(ref this.state, InternalState.Empty);

                return;
            }

            var currentState = this.state;

            // these should be disposed after we've been reinitialized
            var oldNodes = currentState == null ? null : currentState.CurrentNodes;

            // default bucket does not require authentication
            // membase 1.6 tells us if a bucket needs authentication,
            // so let's try to use the config's password
            var password = config.authType == "sasl"
                                                        ? config.saslPassword
                                                        : this.configuration.BucketPassword;

            var authenticator = this.configuration.Bucket == null
                                                                   ? null
                                                                   : new PlainTextAuthenticator(null, this.configuration.Bucket, password);

            try
            {
                var state = (config == null || config.vBucketServerMap == null)
                                                                ? this.InitBasic(config, authenticator)
                                                                : this.InitVBucket(config, authenticator);

                var nodes = state.CurrentNodes;

                state.Locator.Initialize(nodes);

                // we need to subscribe the failed event,
                // so we can periodically check the dead
                // nodes, since we do not get a config
                // update every time a node dies
                for (var i = 0; i < nodes.Length; i++)
                {
                    nodes[i].Failed += this.NodeFail;
                }

                Interlocked.Exchange(ref this.state, state);
            }
            catch (Exception e)
            {
                log.Error("Failed to initialize the pool.", e);

                Interlocked.Exchange(ref this.state, InternalState.Empty);
            }

            // kill the old nodes
            if (oldNodes != null)
            {
                for (var i = 0; i < oldNodes.Length; i++)
                {
                    try
                    {
                        oldNodes[i].Failed -= this.NodeFail;
                        oldNodes[i].Dispose();
                    }
                    catch { }
                }
            }
        }