public void ConsistentRingProvider_Test3()
        {
            int    NUM_SILOS  = 100;
            double NUM_QUEUES = 10024.0;
            int    NUM_AGENTS = 4;

            Random      random = new Random();
            SiloAddress silo1  = SiloAddress.NewLocalAddress(random.Next(100000));
            VirtualBucketsRingProvider ring = new VirtualBucketsRingProvider(silo1, 50);

            //ring.logger.SetSeverityLevel(Severity.Warning);

            for (int i = 1; i <= NUM_SILOS - 1; i++)
            {
                ring.SiloStatusChangeNotification(SiloAddress.NewLocalAddress(random.Next(100000)), SiloStatus.Active);
            }

            IDictionary <SiloAddress, IRingRangeInternal>   siloRanges       = ring.GetRanges();
            List <Tuple <SiloAddress, IRingRangeInternal> > sortedSiloRanges =
                siloRanges.Select(kv => new Tuple <SiloAddress, IRingRangeInternal>(kv.Key, kv.Value)).ToList();

            sortedSiloRanges.Sort((t1, t2) => t1.Item2.RangePercentage().CompareTo(t2.Item2.RangePercentage()));

            Dictionary <SiloAddress, List <IRingRangeInternal> > allAgentRanges = new Dictionary <SiloAddress, List <IRingRangeInternal> >();

            foreach (var siloRange in siloRanges)
            {
                var multiRange = new EquallyDevidedMultiRange(siloRange.Value, NUM_AGENTS);
                List <IRingRangeInternal> agentRanges = new List <IRingRangeInternal>();
                for (int i = 0; i < NUM_AGENTS; i++)
                {
                    IRingRangeInternal agentRange = (IRingRangeInternal)multiRange.GetSubRange(i);
                    agentRanges.Add(agentRange);
                }
                allAgentRanges.Add(siloRange.Key, agentRanges);
            }

            Dictionary <SiloAddress, List <int> > queueHistogram = GetQueueHistogram(allAgentRanges, (int)NUM_QUEUES);
            string str = Utils.EnumerableToString(sortedSiloRanges,
                                                  tuple => String.Format("Silo {0} -> Range {1:0.000}%, {2} queues: {3}",
                                                                         tuple.Item1,
                                                                         tuple.Item2.RangePercentage(),
                                                                         queueHistogram[tuple.Item1].Sum(),
                                                                         Utils.EnumerableToString(queueHistogram[tuple.Item1])), "\n");

            output.WriteLine("\n\n*** The whole ring with {0} silos is:\n{1}\n\n", NUM_SILOS, str);

            output.WriteLine("Total number of queues is: {0}", queueHistogram.Values.Select(list => list.Sum()).Sum());
            output.WriteLine("Expected average range per silo is: {0:0.00}%, expected #queues per silo is: {1:0.00}, expected #queues per agent is: {2:0.000}.",
                             100.0 / NUM_SILOS, NUM_QUEUES / NUM_SILOS, NUM_QUEUES / (NUM_SILOS * NUM_AGENTS));
            output.WriteLine("Min #queues per silo is: {0}, Max #queues per silo is: {1}.",
                             queueHistogram.Values.Select(list => list.Sum()).ToList().Min(), queueHistogram.Values.Select(list => list.Sum()).ToList().Max());
        }
        public void ConsistentRingProvider_Test3()
        {
            int NUM_SILOS = 100;
            double NUM_QUEUES = 10024.0;
            int NUM_AGENTS = 4;

            Random random = new Random();
            SiloAddress silo1 = SiloAddress.NewLocalAddress(random.Next(100000));
            VirtualBucketsRingProvider ring = new VirtualBucketsRingProvider(silo1, 50);
            //ring.logger.SetSeverityLevel(Severity.Warning);
            
            for (int i = 1; i <= NUM_SILOS - 1; i++)
            {
                ring.SiloStatusChangeNotification(SiloAddress.NewLocalAddress(random.Next(100000)), SiloStatus.Active);
            }
  
            IDictionary<SiloAddress, IRingRangeInternal> siloRanges = ring.GetRanges();
            List<Tuple<SiloAddress, IRingRangeInternal>> sortedSiloRanges =
                siloRanges.Select(kv => new Tuple<SiloAddress, IRingRangeInternal>(kv.Key, kv.Value)).ToList();
            sortedSiloRanges.Sort((t1, t2) => t1.Item2.RangePercentage().CompareTo(t2.Item2.RangePercentage()));

            Dictionary<SiloAddress, List<IRingRangeInternal>> allAgentRanges = new Dictionary<SiloAddress, List<IRingRangeInternal>>();
            foreach (var siloRange in siloRanges)
            {
                var multiRange = new EquallyDevidedMultiRange(siloRange.Value, NUM_AGENTS);
                List<IRingRangeInternal> agentRanges = new List<IRingRangeInternal>();
                for(int i=0; i < NUM_AGENTS; i++)
                {
                    IRingRangeInternal agentRange = (IRingRangeInternal)multiRange.GetSubRange(i);
                    agentRanges.Add(agentRange);
                }
                allAgentRanges.Add(siloRange.Key, agentRanges);
            }

            Dictionary<SiloAddress, List<int>> queueHistogram = GetQueueHistogram(allAgentRanges, (int)NUM_QUEUES);
            string str = Utils.EnumerableToString(sortedSiloRanges,
                tuple => String.Format("Silo {0} -> Range {1:0.000}%, {2} queues: {3}", 
                    tuple.Item1,
                    tuple.Item2.RangePercentage(),
                    queueHistogram[tuple.Item1].Sum(),
                    Utils.EnumerableToString(queueHistogram[tuple.Item1])), "\n");

            Console.WriteLine("\n\n*** The whole ring with {0} silos is:\n{1}\n\n", NUM_SILOS, str);

            Console.WriteLine("Total number of queues is: {0}", queueHistogram.Values.Select(list => list.Sum()).Sum());
            Console.WriteLine("Expected average range per silo is: {0:0.00}%, expected #queues per silo is: {1:0.00}, expected #queues per agent is: {2:0.000}.",
                100.0 / NUM_SILOS, NUM_QUEUES / NUM_SILOS, NUM_QUEUES / (NUM_SILOS * NUM_AGENTS));
            Console.WriteLine("Min #queues per silo is: {0}, Max #queues per silo is: {1}.",
                queueHistogram.Values.Select(list => list.Sum()).ToList().Min(), queueHistogram.Values.Select(list => list.Sum()).ToList().Max());
        }
        public void ConsistentRingProvider_Test2()
        {
            SiloAddress silo1 = SiloAddress.NewLocalAddress(0);
            VirtualBucketsRingProvider ring = new VirtualBucketsRingProvider(silo1, 30);
            //ring.logger.SetSeverityLevel(Severity.Warning);
            Console.WriteLine("\n\n*** Silo1 range: {0}.\n*** The whole ring with 1 silo is:\n{1}\n\n", ring.GetMyRange(), ring.ToString());

            for (int i = 1; i <= 10; i++)
            {
                ring.SiloStatusChangeNotification(SiloAddress.NewLocalAddress(i), SiloStatus.Active);
                var range = new EquallyDevidedMultiRange(ring.GetMyRange(), 5);
                Console.WriteLine("\n\n*** Silo1 range: {0}. \n*** The whole ring with {1} silos is:\n{2}\n\n", range.ToCompactString(), i + 1, ring.ToString());
            }
        }
        public void ConsistentRingProvider_Test2()
        {
            SiloAddress silo1 = SiloAddress.NewLocalAddress(0);
            VirtualBucketsRingProvider ring = new VirtualBucketsRingProvider(silo1, 30);

            //ring.logger.SetSeverityLevel(Severity.Warning);
            output.WriteLine("\n\n*** Silo1 range: {0}.\n*** The whole ring with 1 silo is:\n{1}\n\n", ring.GetMyRange(), ring.ToString());

            for (int i = 1; i <= 10; i++)
            {
                ring.SiloStatusChangeNotification(SiloAddress.NewLocalAddress(i), SiloStatus.Active);
                var range = new EquallyDevidedMultiRange(ring.GetMyRange(), 5);
                output.WriteLine("\n\n*** Silo1 range: {0}. \n*** The whole ring with {1} silos is:\n{2}\n\n", range.ToCompactString(), i + 1, ring.ToString());
            }
        }
        public void RangeChangeNotification(IRingRange old, IRingRange now, bool increased)
        {
            myRange = CalcMyRange();

            var        oldMultiRange = new EquallyDevidedMultiRange(old, numSubRanges);
            IRingRange oldSubRange   = oldMultiRange.GetSubRange(mySubRangeIndex);
            var        newMultiRange = new EquallyDevidedMultiRange(now, numSubRanges);
            IRingRange newSubRange   = newMultiRange.GetSubRange(mySubRangeIndex);

            if (oldSubRange.Equals(newSubRange))
            {
                return;
            }

            // For now, always say your range increased and the listeners need to deal with the situation when they get the same range again anyway.
            // In the future, check sub range inclusion. Note that it is NOT correct to just return the passed increased argument.
            // It will be wrong: the multi range may have decreased, while some individual sub range may partialy increase (shift).

            logger.Info("-NotifyLocal GrainRangeSubscribers about old {0} and new {1} increased? {2}.", oldSubRange.ToString(), newSubRange.ToString(), increased);

            List <IGrainRingRangeListener> copy;

            lock (grainStatusListeners)
            {
                copy = grainStatusListeners.ToList();
            }
            foreach (IGrainRingRangeListener listener in copy)
            {
                try
                {
                    Task task = listener.RangeChangeNotification(oldSubRange, newSubRange);
                    // We don't want to await it here since it will delay delivering notifications to other listeners.
                    // We only want to log an error if it happends, so use ContinueWith.
                    task.LogException(logger, ErrorCode.CRP_ForGrains_Local_Subscriber_Exception_1,
                                      String.Format("Local IGrainRingRangeListener {0} has thrown an asynchronous exception when was notified about RangeChangeNotification about old {1} new {2}.",
                                                    listener.GetType().FullName, oldSubRange, newSubRange))
                    .Ignore();
                }
                catch (Exception exc)
                {
                    logger.Error(ErrorCode.CRP_ForGrains_Local_Subscriber_Exception_2,
                                 String.Format("Local IGrainRingRangeListener {0} has thrown an exception when was notified about RangeChangeNotification about old {1} new {2}.",
                                               listener.GetType().FullName, oldSubRange, newSubRange), exc);
                }
            }
        }
        public void RangeChangeNotification(IRingRange old, IRingRange now, bool increased)
        {
            myRange = CalcMyRange();

            var oldMultiRange = new EquallyDevidedMultiRange(old, numSubRanges);
            IRingRange oldSubRange = oldMultiRange.GetSubRange(mySubRangeIndex);
            var newMultiRange = new EquallyDevidedMultiRange(now, numSubRanges);
            IRingRange newSubRange = newMultiRange.GetSubRange(mySubRangeIndex);

            if (oldSubRange.Equals(newSubRange)) return;

            // For now, always say your range increased and the listeners need to deal with the situation when they get the same range again anyway.
            // In the future, check sub range inclusion. Note that it is NOT correct to just return the passed increased argument. 
            // It will be wrong: the multi range may have decreased, while some individual sub range may partialy increase (shift).

            logger.Info("-NotifyLocal GrainRangeSubscribers about old {0} and new {1} increased? {2}.", oldSubRange.ToString(), newSubRange.ToString(), increased);

            List<IAsyncRingRangeListener> copy;
            lock (grainStatusListeners)
            {
                copy = grainStatusListeners.ToList();
            }
            foreach (IAsyncRingRangeListener listener in copy)
            {
                try
                {
                    Task task = listener.RangeChangeNotification(oldSubRange, newSubRange);
                    // We don't want to await it here since it will delay delivering notifications to other listeners.
                    // We only want to log an error if it happends, so use ContinueWith.
                    task.LogException(logger, ErrorCode.CRP_ForGrains_Local_Subscriber_Exception_1, 
                                        String.Format("Local IGrainRingRangeListener {0} has thrown an asynchronous exception when was notified about RangeChangeNotification about old {1} new {2}.",
                                        listener.GetType().FullName, oldSubRange, newSubRange))
                        .Ignore();
                }
                catch (Exception exc)
                {
                    logger.Error(ErrorCode.CRP_ForGrains_Local_Subscriber_Exception_2,
                        String.Format("Local IGrainRingRangeListener {0} has thrown an exception when was notified about RangeChangeNotification about old {1} new {2}.",
                        listener.GetType().FullName, oldSubRange, newSubRange), exc);
                }
            }
        }
 private IRingRange CalcMyRange()
 {
     var equallyDevidedMultiRange = new EquallyDevidedMultiRange(ringProvider.GetMyRange(), numSubRanges);
     return equallyDevidedMultiRange.GetSubRange(mySubRangeIndex);
 }
        private IRingRange CalcMyRange()
        {
            var equallyDevidedMultiRange = new EquallyDevidedMultiRange(ringProvider.GetMyRange(), numSubRanges);

            return(equallyDevidedMultiRange.GetSubRange(mySubRangeIndex));
        }