Implements Ketama cosistent hashing, compatible with the "spymemcached" Java memcachedClient
Inheritance: IMemcachedNodeLocator
        IMemcachedNode INodeLocator.Locate(string key)
        {
            if (key == null)
            {
                throw new ArgumentNullException("key");
            }

            var id = this._lookupData;

            switch (id.Servers.Length)
            {
            case 0:
                return(null);

            case 1:
                var tmp = id.Servers[0];
                return(tmp.IsAlive ? tmp : null);
            }

            var node = KetamaNodeLocator.LocateNode(id, this.GetKeyHash(key));

            // if the result is not alive then try to mutate the item key and
            // find another node this way we do not have to reinitialize every
            // time a node dies/comes back
            // (DefaultServerPool will resurrect the nodes in the background without affecting the hashring)
            if (!node.IsAlive)
            {
                for (var i = 0; i < id.Servers.Length; i++)
                {
                    // -- this is from spymemcached so we select the same node for the same items
                    var tmpKey = (ulong)GetKeyHash(i + key);
                    tmpKey += (uint)(tmpKey ^ (tmpKey >> 32));
                    tmpKey &= 0xffffffffL;                     /* truncate to 32-bits */
                    // -- end

                    node = KetamaNodeLocator.LocateNode(id, (uint)tmpKey);

                    if (node.IsAlive)
                    {
                        return(node);
                    }
                }
            }

            return(node.IsAlive ? node : null);
        }
Esempio n. 2
0
        public void TestLocator()
        {
            String[] servers = new[]{
                "10.0.1.1:11211",
                "10.0.1.2:11211",
                "10.0.1.3:11211",
                "10.0.1.4:11211",
                "10.0.1.5:11211",
                "10.0.1.6:11211",
                "10.0.1.7:11211",
                "10.0.1.8:11211"};

            var nodes = servers.
                            Select(s => new MockNode(new IPEndPoint(IPAddress.Parse(s.Substring(0, s.IndexOf(":"))), 11211))).
                            Cast<IMemcachedNode>().
                            ToList();

            IMemcachedNodeLocator ketama = new KetamaNodeLocator();
            ketama.Initialize(nodes.ToList());

            foreach (var pair in exp)
            {
                var node = ketama.Locate(pair[0]);

                Assert.AreEqual(node.EndPoint.ToString(), pair[1]);
            }
        }