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)); }
internal abstract Task<PlacementResult> OnAddActivation( PlacementStrategy strategy, GrainId grain, IPlacementContext context);
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); }
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)); }