public INode Locate(Key key)
		{
			var keyArray = key.Array;
			if (keyArray == null) throw new ArgumentNullException("key");

			switch (nodes.Length)
			{
				case 0: return AlreadyFailedNode.Instance;
				case 1: return nodes[0];
				default:

					var retval = LocateNode(GetKeyHash(keyArray, key.Length));

					// 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)
					//
					// Key mutation logic is taken from spymemcached (https://code.google.com/p/spymemcached/)
					if (!retval.IsAlive)
					{
						var alteredKey = new byte[key.Length + 1];
						Buffer.BlockCopy(keyArray, 0, alteredKey, 1, key.Length);

						for (var i = (byte)'0'; i < (byte)'7'; i++)
						{
							// -- this is from spymemcached
							alteredKey[0] = i;
							var tmpKey = (ulong)GetKeyHash(alteredKey, alteredKey.Length);
							tmpKey += (uint)(tmpKey ^ (tmpKey >> 32));
							tmpKey &= 0xffffffffL; /* truncate to 32-bits */
							retval = LocateNode((uint)tmpKey);
							// -- end

							if (retval.IsAlive) return retval;
						}
					}

					return retval;
			}
		}
Example #2
0
		public bool Equals(Key obj)
		{
			return obj.array == array && obj.length == length;
		}