public void Setup() { #if !NET_CORE CallContext.LogicalSetData(CallContextKey, "Fail"); #endif var dummyExecutionContext = ExecutionContext.Capture(); #if !NET_CORE CallContext.FreeNamedDataSlot(CallContextKey); #endif var nodeMock = new Mock <IMemcacheNode>(); nodeMock.Setup(n => n.EndPoint).Returns(new IPEndPoint(new IPAddress(new byte[] { 127, 0, 0, 1 }), 11211)); nodeMock.Setup(n => n.IsDead).Returns(false); nodeMock.Setup(n => n.TrySend(It.IsAny <IMemcacheRequest>(), It.IsAny <int>())) .Callback((IMemcacheRequest req, int timeout) => ExecutionContext.Run(dummyExecutionContext, _ => req.HandleResponse(_responseHeader, _key, _extra, _message), null)) .Returns(true); _nodeMock = nodeMock.Object; var locatorMoq = new Mock <INodeLocator>(); locatorMoq.Setup(l => l.Locate(It.IsAny <IMemcacheRequest>())).Returns(Enumerable.Repeat(_nodeMock, 1)); _locatorMock = locatorMoq.Object; var clusterMoq = new Mock <IMemcacheCluster>(); clusterMoq.Setup(c => c.Locator).Returns(_locatorMock); clusterMoq.Setup(c => c.Nodes).Returns(Enumerable.Repeat(_nodeMock, 1)); _clusterMock = clusterMoq.Object; _key = null; _extra = null; _message = null; _responseHeader = default(MemcacheResponseHeader); }
public void TransportDeadThenAliveTest() { IMemcacheNode theNode = null; FakeTransport transport = new FakeTransport(); transport.Kill(); // Memcache client config var config = new MemcacheClientConfiguration { DeadTimeout = TimeSpan.FromSeconds(1), TransportFactory = transport.Factory, NodeFactory = (e, c) => MemcacheClientConfiguration.DefaultNodeFactory(e, c), PoolSize = 1, }; theNode = config.NodeFactory(null, config); Assert.IsFalse(theNode.IsDead, "The node should be alive before any failure"); Assert.IsFalse(theNode.TrySend(null, 1), "The TrySend should fail with a broken transport"); Assert.IsTrue(theNode.IsDead, "The node should be dead after the first send failed"); transport.Resurect(); Assert.IsFalse(theNode.IsDead, "The node should be alive after the transport resurected"); Assert.IsTrue(theNode.TrySend(null, 1), "The TrySend should be able to send a request after the transport is up again"); transport.Kill(); Assert.IsFalse(theNode.TrySend(null, 1), "The TrySend should fail with a killed transport"); Assert.IsTrue(theNode.IsDead, "The node should be dead after the a send failed"); }
private void OnNodeError(IMemcacheNode node) { if (NodeError != null) { NodeError(node); } }
/// <summary> /// This function gets rid of successive keys that reference the same node. /// This is a slight performance improvement for the LocateNode function. /// </summary> /// <returns></returns> public static uint[] CleanRepeatedNodes(List <uint> sortedKeys, Dictionary <uint, IMemcacheNode> keyToServer) { int Length = sortedKeys.Count; if (Length == 0) { return(new uint[0]); } Stack <uint> keyStack = new Stack <uint>(Length); uint previousKey = sortedKeys[0]; IMemcacheNode previousNode = keyToServer[previousKey]; // Traverse the list of keys backwards for (int idx = Length - 1; idx >= 0; idx--) { uint currentKey = sortedKeys[idx]; IMemcacheNode currentNode = keyToServer[currentKey]; if (currentNode != previousNode) { keyStack.Push(currentKey); previousNode = currentNode; } previousKey = currentKey; } // Treat the case where all keys point to the same node if (keyStack.Count == 0) { keyStack.Push(sortedKeys[0]); } return(keyStack.ToArray()); }
public void Setup() { var nodeMock = new Mock <IMemcacheNode>(); nodeMock.Setup(n => n.EndPoint).Returns(new IPEndPoint(new IPAddress(new byte[] { 127, 0, 0, 1 }), 11211)); nodeMock.Setup(n => n.IsDead).Returns(false); nodeMock.Setup(n => n.TrySend(It.IsAny <IMemcacheRequest>(), It.IsAny <int>())) .Callback((IMemcacheRequest req, int timeout) => req.HandleResponse(_responseHeader, _key, _extra, _message)) .Returns(true); _nodeMock = nodeMock.Object; var locatorMoq = new Mock <INodeLocator>(); locatorMoq.Setup(l => l.Locate(It.IsAny <IMemcacheRequest>())).Returns(Enumerable.Repeat(_nodeMock, 1)); _locatorMock = locatorMoq.Object; var clusterMoq = new Mock <IMemcacheCluster>(); clusterMoq.Setup(c => c.Locator).Returns(_locatorMock); clusterMoq.Setup(c => c.Nodes).Returns(Enumerable.Repeat(_nodeMock, 1)); _clusterMock = clusterMoq.Object; _key = null; _extra = null; _message = null; _responseHeader = default(MemcacheResponseHeader); }
private void UnregisterEvents(IMemcacheNode node) { node.MemcacheError -= OnMemcacheError; node.TransportError -= OnTransportError; node.NodeDead -= OnNodeError; }
private void RegisterEvents(IMemcacheNode node) { node.MemcacheError += OnMemcacheError; node.TransportError += OnTransportError; node.NodeDead += NodeError; }
/// <summary> /// Enumerate server nodes in the order they appear in the consistent hashing table. /// </summary> /// <param name="ld">Consistent hashing lookup table</param> /// <param name="itemKeyHash">Hash key used to identify the first server node to be returned by the function</param> /// <returns></returns> private static IEnumerable <IMemcacheNode> LocateNode(LookupData ld, uint itemKeyHash) { // get the index of the server assigned to this hash int foundIndex = Array.BinarySearch <uint>(ld.sortedKeys, itemKeyHash); IMemcacheNode node1 = null; IMemcacheNode node2 = null; HashSet <IMemcacheNode> usedNodes = null; // no exact match if (foundIndex < 0) { // this is the next greater index in the list foundIndex = ~foundIndex; if (foundIndex >= ld.sortedKeys.Length) { // the key was larger than all server keys, so return the first server foundIndex = 0; } } // Paranoid check if (foundIndex < 0 || foundIndex >= ld.sortedKeys.Length) { yield break; } // Return distinct nodes. Exit after a complete loop over the keys. int startingIndex = foundIndex; do { IMemcacheNode node = ld.keyToServer[ld.sortedKeys[foundIndex]]; if (node1 == null) { node1 = node; yield return(node1); } else if (node2 == null) { // Because the list of keys is filtered with function CleanRepeatedNodes, we have node2 != node1 node2 = node; yield return(node2); } else { if (usedNodes == null) { usedNodes = new HashSet <IMemcacheNode>() { node1, node2 }; } if (!usedNodes.Contains(node)) { usedNodes.Add(node); yield return(node); } } foundIndex++; if (foundIndex >= ld.sortedKeys.Length) { foundIndex = 0; } } while (foundIndex != startingIndex); }
public void Setup() { var nodeMock = new Mock<IMemcacheNode>(); nodeMock.Setup(n => n.EndPoint).Returns(new IPEndPoint(new IPAddress(new byte[] { 127, 0, 0, 1 }), 11211)); nodeMock.Setup(n => n.IsDead).Returns(false); nodeMock.Setup(n => n.TrySend(It.IsAny<IMemcacheRequest>(), It.IsAny<int>())) .Callback((IMemcacheRequest req, int timeout) => req.HandleResponse(_responseHeader, _key, _extra, _message)) .Returns(true); _nodeMock = nodeMock.Object; var locatorMoq = new Mock<INodeLocator>(); locatorMoq.Setup(l => l.Locate(It.IsAny<IMemcacheRequest>())).Returns(Enumerable.Repeat(_nodeMock, 1)); _locatorMock = locatorMoq.Object; var clusterMoq = new Mock<IMemcacheCluster>(); clusterMoq.Setup(c => c.Locator).Returns(_locatorMock); clusterMoq.Setup(c => c.Nodes).Returns(Enumerable.Repeat(_nodeMock, 1)); _clusterMock = clusterMoq.Object; _key = null; _extra = null; _message = null; _responseHeader = default(MemcacheResponseHeader); }