public void MoveObjectCallBack(object state) { Node targetNode = (Node)state; string nodeKeyHash = Hasher.GetHash(targetNode.EndPoint.ToString()); string previousNodeHash = Hasher.GetHash(_nodeResolver.GetPreviousItemInCircle(targetNode.EndPoint.ToString())); //if self is B, typical scenarios -> A-newnode-MID-B, MID-A-newnode-B-C //A being the previous node, B being the current node and newnode being the new node. string lowerBound = previousNodeHash; string upperBound = nodeKeyHash; IEnumerable<KeyValuePair<string, ServerCacheItem>> candidateList = _cache.Where<KeyValuePair<string, ServerCacheItem>>(x => ((x.Value.Hash.CompareTo(upperBound) < 0) && (x.Value.Hash.CompareTo(lowerBound) > 0))); //special case: A-MID-newnode-B if (lowerBound.CompareTo(upperBound) > 0) { candidateList = _cache.Where<KeyValuePair<string, ServerCacheItem>>(x => ((x.Value.Hash.CompareTo(upperBound) < 0) || (x.Value.Hash.CompareTo(lowerBound) > 0))); } if (candidateList.Count() == 0) return; Node self = new Node() { EndPoint = TcpHelper.SelfIPAddress, NodeState= NodeState.Active}; //prepare the connection string endPoint = string.Format("net.tcp://{0}:{1}/HoCCacheService", targetNode.EndPoint.ToString(), targetNode.ServicePort); CacheServiceReference.CacheServiceClient nodeService = new CacheServiceReference.CacheServiceClient(new NetTcpBinding(SecurityMode.None), new EndpointAddress(endPoint)); try { //move each of the object to the other node async foreach (KeyValuePair<string, ServerCacheItem> valuePair in candidateList) { nodeService.DoInterNodeObjectTransfer(self, valuePair.Key, valuePair.Value); valuePair.Value.ItemState = CacheItemState.Moved; valuePair.Value.RelocatedTo = targetNode; }; nodeService.EndInterNodeObjectTransfer(self); Thread.Sleep(2000);//wait the current thread - note that this is not the main thread RemoveOrResetMovedItems(targetNode); //note that any object update that happens during this time is handled by the CacheService. //basically it copies the update to the new node too. } catch { ResetMovedObjectState(); //in case of any issues revert back to normal state. } }
public void PerformShutdownMove() { //targetnode is the one which comes next in the circle, effectively returned by GetObjectLocation Node targetNode = _nodeResolver.GetObjectLocation(TcpHelper.SelfIPAddress.ToString()); //is targetnode self? (am I the only node in the circle?) if (targetNode.EndPoint.ToString().CompareTo(TcpHelper.SelfIPAddress.ToString()) == 0) return; string endPoint = string.Format("net.tcp://{0}:{1}/HoCCacheService", targetNode.EndPoint.ToString(), targetNode.ServicePort); CacheServiceReference.CacheServiceClient nodeService = new CacheServiceReference.CacheServiceClient(new NetTcpBinding(SecurityMode.None), new EndpointAddress(endPoint)); Node self = new Node() { EndPoint = TcpHelper.SelfIPAddress, NodeState= NodeState.Active}; //move the objects to the nearest node async Parallel.ForEach<KeyValuePair<string, ServerCacheItem>>(_cache, valuePair => { nodeService.DoInterNodeObjectTransfer(self, valuePair.Key, valuePair.Value); valuePair.Value.ItemState = CacheItemState.Moved; valuePair.Value.RelocatedTo = targetNode; }); }