Example #1
0
 public void Start()
 {
     nodeLocator = configuration.CreateNodeLocator();
     nodes       = new Dictionary <string, IMemcachedNode>();
     nodeLocator.Initialize(new List <IMemcachedNode>());
     Poll(null); // seed it once before returning from Start()
     pollingTimer = new Timer(Poll, null, pollingInterval, pollingInterval);
 }
Example #2
0
        private void Poll(object state)
        {
            lock (PollSync)                                                                  // pattern taken from DefaultNodeLocator, presumably to avoid two threads from colliding in here
            {
                var instances = RoleEnvironment.Roles[memcachedRoleName].Instances.ToList(); // potential memcached servers according to Windows Azure

                var changed = false;

                foreach (var instance in instances)
                {
                    if (!nodes.ContainsKey(instance.Id)) // new server
                    {
                        var endpoint = instance.InstanceEndpoints[memcachedEndpointName].IPEndpoint;

                        // if and only if server's alive (accepts socket connection)
                        using (var socket = new Socket(endpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp))
                        {
                            try
                            {
                                socket.Connect(endpoint);
                                if (socket.Connected)
                                {
                                    socket.Disconnect(false);

                                    // add the server
                                    nodes[instance.Id]         = new MemcachedNode(endpoint, this.configuration.SocketPool);
                                    nodes[instance.Id].Failed += Poll;
                                    changed = true;
                                }
                            }
                            catch (SocketException) { }
                        }
                    }
                }

                foreach (var key in nodes.Keys.ToList())
                {
                    // prune dead nodes (either found to be dead by trying to use them or by dropping off Windows Azure's list)
                    if (!nodes[key].IsAlive || !instances.Any(i => i.Id == key))
                    {
                        nodes[key].Failed -= Poll;
                        nodes.Remove(key);
                        changed = true;
                    }
                }

                if (changed)
                {
                    // Note: Enyim documentation says it's important to always use the same order (for consistent hashing)
                    nodeLocator.Initialize(nodes.OrderBy(p => p.Key).Select(p => p.Value).ToList());
                }
            }
        }
Example #3
0
        private void RebuildIndexes()
        {
            this.serverAccessLock.UpgradeToWriterLock(Timeout.Infinite);

            try
            {
                Type ltype = this.configuration.NodeLocator;

                IMemcachedNodeLocator l = ltype == null ? new DefaultNodeLocator() : (IMemcachedNodeLocator)Enyim.Reflection.FastActivator.CreateInstance(ltype);
                l.Initialize(this.workingServers);

                this.nodeLocator = l;

                this.publicWorkingServers = null;
            }
            finally
            {
                this.serverAccessLock.ReleaseLock();
            }
        }
 public void Start()
 {
     nodeLocator = configuration.CreateNodeLocator();
     nodes = new Dictionary<string, IMemcachedNode>();
     nodeLocator.Initialize(new List<IMemcachedNode>());
     Poll(null); // seed it once before returning from Start()
     pollingTimer = new Timer(Poll, null, pollingInterval, pollingInterval);
 }
Example #5
0
        private void RezCallback(object state)
        {
            _log.LogDebug("Checking the dead servers.");

            // how this works:
            // 1. timer is created but suspended
            // 2. Locate encounters a dead server, so it starts the timer which will trigger after deadTimeout has elapsed
            // 3. if another server goes down before the timer is triggered, nothing happens in Locate (isRunning == true).
            //		however that server will be inspected sooner than Dead Timeout.
            //		   S1 died   S2 died    dead timeout
            //		|----*--------*------------*-
            //           |                     |
            //          timer start           both servers are checked here
            // 4. we iterate all the servers and record it in another list
            // 5. if we found a dead server whihc responds to Ping(), the locator will be reinitialized
            // 6. if at least one server is still down (Ping() == false), we restart the timer
            // 7. if all servers are up, we set isRunning to false, so the timer is suspended
            // 8. GOTO 2
            lock (_deadSync)
            {
                if (_isDisposed)
                {
                    _log.LogWarning("IsAlive timer was triggered but the pool is already disposed. Ignoring.");

                    return;
                }

                var nodes     = _allNodes;
                var aliveList = new List <IMemcachedNode>(nodes.Length);
                var changed   = false;
                var deadCount = 0;

                for (var i = 0; i < nodes.Length; i++)
                {
                    var n = nodes[i];
                    if (n.IsAlive)
                    {
                        _log.LogDebug("Alive: {EndPoint}", n.EndPoint);

                        aliveList.Add(n);
                    }
                    else
                    {
                        _log.LogDebug("Dead: {EndPoint}", n.EndPoint);

                        if (n.Ping())
                        {
                            changed = true;
                            aliveList.Add(n);

                            _log.LogDebug("Ping ok.");
                        }
                        else
                        {
                            _log.LogDebug("Still dead.");

                            deadCount++;
                        }
                    }
                }

                // reinit the locator
                if (changed)
                {
                    _log.LogDebug("Reinitializing the locator.");

                    NodeLocator.Initialize(aliveList);
                }

                // stop or restart the timer
                if (deadCount == 0)
                {
                    _log.LogDebug("deadCount == 0, stopping the timer.");

                    _isTimerActive = false;
                }
                else
                {
                    _log.LogDebug("deadCount == {deadCount}, starting the timer.", deadCount);

                    _resurrectTimer.Change(_deadTimeoutMsec, Timeout.Infinite);
                }
            }
        }