Exemplo n.º 1
0
        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.
            }
        }