internal override Task<PlacementResult> OnSelectActivation(
            PlacementStrategy strategy, GrainId target, IPlacementContext context)
        {
            if (target.IsClient)
                throw new InvalidOperationException("Cannot use StatelessWorkerStrategy to route messages to client grains.");

            // If there are available (not busy with a request) activations, it returns the first one.
            // If all are busy and the number of local activations reached or exceeded MaxLocal, it randomly returns one of them.
            // Otherwise, it requests creation of a new activation.
            List<ActivationData> local;

            if (!context.LocalLookup(target, out local) || local.Count == 0)
                return Task.FromResult((PlacementResult)null);

            var placement = (StatelessWorkerPlacement)strategy;

            foreach (var activation in local)
            {
                ActivationData info;
                if (!context.TryGetActivationData(activation.ActivationId, out info) ||
                    info.State != ActivationState.Valid || !info.IsInactive) continue;

                return Task.FromResult(PlacementResult.IdentifySelection(ActivationAddress.GetAddress(context.LocalSilo, target, activation.ActivationId)));
            }

            if (local.Count >= placement.MaxLocal)
            {
                var id = local[local.Count == 1 ? 0 : random.Next(local.Count)].ActivationId;
                return Task.FromResult(PlacementResult.IdentifySelection(ActivationAddress.GetAddress(context.LocalSilo, target, id)));
            }

            return Task.FromResult((PlacementResult)null);
        }
        public override async Task<PlacementResult> OnSelectActivation(PlacementStrategy strategy, GrainId target, IPlacementContext context)
        {
            // first, check if we can find an activation for this client in the cache or local directory partition
            AddressesAndTag addresses;
            if (context.FastLookup(target, out addresses))
                return ChooseRandomActivation(addresses.Addresses, context);

            // we need to look up the directory entry for this grain on a remote silo
            switch (target.Category)
            {
                case UniqueKey.Category.Client:
                    {
                        addresses = await context.FullLookup(target);
                        return ChooseRandomActivation(addresses.Addresses, context);
                    }

                case UniqueKey.Category.GeoClient:
                    {
                        // we need to look up the activations in the remote cluster
                        addresses = await context.LookupInCluster(target, target.Key.ClusterId);
                        return ChooseRandomActivation(addresses.Addresses, context);
                    }

                default:
                    throw new InvalidOperationException("Unsupported client type. Grain " + target);
            }
        }
 internal override Task<PlacementResult> OnAddActivation(
     PlacementStrategy strategy, GrainId grain, IPlacementContext context)
 {
     var grainType = context.GetGrainTypeName(grain);
     var allSilos = context.AllActiveSilos;
     return Task.FromResult(
         PlacementResult.SpecifyCreation(allSilos[random.Next(allSilos.Count)], strategy, grainType));
 }
        private Task<PlacementResult> MakePlacement(PlacementStrategy strategy, GrainId grain, IPlacementContext context, CachedLocalStat minLoadedSilo)
        {
            // Increment placement by number of silos instead of by one.
            // This is our trick to get more balanced placement, accounting to the probable
            // case when multiple silos place on the same silo at the same time, before stats are refreshed.
            minLoadedSilo.IncrementActivationCount(localCache.Count);

            return Task.FromResult(PlacementResult.SpecifyCreation(
                minLoadedSilo.Address,
                strategy,
                context.GetGrainTypeName(grain)));
        }
        protected PlacementResult ChooseRandomActivation(List<ActivationAddress> places, IPlacementContext context)
        {
            if (places.Count <= 0)
            {
                // we return null to indicate that we were unable to select a target from places activations.
                return null;
            }
            if (places.Count == 1)
            {
                return PlacementResult.IdentifySelection(places[0]);
            }
            // places.Count >= 2
            // Choose randomly if there is one, else make a new activation of the target
            // pick local if available (consider making this a purely random assignment of grains).
            var here = context.LocalSilo;
            var local = places.Where(a => a.Silo.Equals(here)).ToList();
            if (local.Count > 0)
                return PlacementResult.IdentifySelection(local[random.Next(local.Count)]);

            return PlacementResult.IdentifySelection(places[random.Next(places.Count)]);
        }
        internal override async Task<PlacementResult> OnSelectActivation(
            PlacementStrategy strategy, GrainId target, IPlacementContext context)
        {
            List<ActivationAddress> places = await context.Lookup(target);
            if (places.Count <= 0)
            {
                // we return null to indicate that we were unable to select a target from places activations.
                return null;
            }

            if (places.Count == 1) return PlacementResult.IdentifySelection(places[0]);

            // places.Count > 0
            // Choose randomly if there is one, else make a new activation of the target
            // pick local if available (consider making this a purely random assignment of grains).
            var here = context.LocalSilo;
            var local = places.Where(a => a.Silo.Equals(here)).ToList();
            if (local.Count > 0) 
                return PlacementResult.IdentifySelection(local[random.Next(local.Count)]);
            if (places.Count > 0)
                return PlacementResult.IdentifySelection(places[random.Next(places.Count)]);
            // we return null to indicate that we were unable to select a target from places activations.
            return null;
        }
     OnAddActivation(PlacementStrategy strategy, GrainId grain, IPlacementContext context)
 {
     var grainType = context.GetGrainTypeName(grain);
     return Task.FromResult( 
         PlacementResult.SpecifyCreation(context.LocalSilo, strategy, grainType));
 }
Example #8
0
 internal abstract Task<PlacementResult> OnAddActivation(
     PlacementStrategy strategy, GrainId grain, IPlacementContext context);
Example #9
0
 internal abstract Task<PlacementResult> OnSelectActivation(
     PlacementStrategy strategy, GrainId target, IPlacementContext context);
     OnAddActivation(PlacementStrategy strategy, GrainId grain, IPlacementContext context)
 {
     throw new InvalidOperationException("Client Observers are not activated using the placement subsystem. Grain " + grain);
 }
        public Task<PlacementResult> SelectSiloPowerOfK(PlacementStrategy strategy, GrainId grain, IPlacementContext context)
        {
            // Exclude overloaded silos
            var relevantSilos = new List<CachedLocalStat>();
            foreach (CachedLocalStat current in localCache.Values)
            {
                if (IsSiloOverloaded(current.SiloStats)) continue;

                relevantSilos.Add(current);
            }

            if (relevantSilos.Count > 0)
            {
                int chooseFrom = Math.Min(relevantSilos.Count, chooseHowMany);
                var chooseFromThoseSilos = new List<CachedLocalStat>();
                while (chooseFromThoseSilos.Count < chooseFrom)
                {
                    int index = random.Next(relevantSilos.Count);
                    var pickedSilo = relevantSilos[index];
                    relevantSilos.RemoveAt(index);
                    chooseFromThoseSilos.Add(pickedSilo);
                }

                CachedLocalStat minLoadedSilo = chooseFromThoseSilos.First();
                foreach (CachedLocalStat s in chooseFromThoseSilos)
                {
                    if (SiloLoad_ByRecentActivations(s) < SiloLoad_ByRecentActivations(minLoadedSilo))
                        minLoadedSilo = s;
                }

                return MakePlacement(strategy, grain, context, minLoadedSilo);
            }
            
            var debugLog = string.Format("Unable to select a candidate from {0} silos: {1}", localCache.Count,
                Utils.EnumerableToString(
                    localCache,
                    kvp => String.Format("SiloAddress = {0} -> {1}", kvp.Key.ToString(), kvp.Value.ToString())));
            logger.Warn(ErrorCode.Placement_ActivationCountBasedDirector_NoSilos, debugLog);
            throw new OrleansException(debugLog);
        }
 internal override Task<PlacementResult> OnAddActivation(
     PlacementStrategy strategy, GrainId grain, IPlacementContext context)
 {
     return SelectSilo(strategy, grain, context);
 }
        /// <summary>
        /// Selects the best match from list of silos, updates local statistics.
        /// </summary>
        /// <note>
        /// This is equivalent with SelectSiloPowerOfK() with chooseHowMany = #Silos
        /// </note>
        private Task<PlacementResult> SelectSiloGreedy(PlacementStrategy strategy, GrainId grain, IPlacementContext context)
        {
            int minLoad = int.MaxValue;
            CachedLocalStat minLoadedSilo = null;
            foreach (CachedLocalStat current in localCache.Values)
            {
                if (IsSiloOverloaded(current.SiloStats)) continue;

                int load = SiloLoad_ByRecentActivations(current);
                if (load >= minLoad) continue;

                minLoadedSilo = current;
                minLoad = load;
            }

            if (minLoadedSilo != null) 
                return MakePlacement(strategy, grain, context, minLoadedSilo);
            
            var debugLog = string.Format("Unable to select a candidate from {0} silos: {1}", localCache.Count, 
                Utils.EnumerableToString(
                    localCache, 
                    kvp => String.Format("SiloAddress = {0} -> {1}", kvp.Key.ToString(), kvp.Value.ToString())));
            logger.Warn(ErrorCode.Placement_ActivationCountBasedDirector_NoSilos, debugLog);
            throw new OrleansException(debugLog);
        }
 internal override async Task<PlacementResult> OnSelectActivation(
     PlacementStrategy strategy, GrainId target, IPlacementContext context)
 {
     List<ActivationAddress> places = (await context.Lookup(target)).Addresses;
     return ChooseRandomActivation(places, context);
 }
Example #15
0
        public static Task <List <ActivationAddress> > Lookup(this IPlacementContext @this, GrainId grainId)
        {
            List <ActivationAddress> l;

            return(@this.FastLookup(grainId, out l) ? Task.FromResult(l) : @this.FullLookup(grainId));
        }