public virtual void TestSimple() { PrepareBasicPlan(); // create a request with a single atomic ask ReservationDefinition rr = new ReservationDefinitionPBImpl(); rr.SetArrival(5 * step); rr.SetDeadline(20 * step); ReservationRequest r = ReservationRequest.NewInstance(Org.Apache.Hadoop.Yarn.Api.Records.Resource .NewInstance(2048, 2), 10, 5, 10 * step); ReservationRequests reqs = new ReservationRequestsPBImpl(); reqs.SetReservationResources(Collections.SingletonList(r)); rr.SetReservationRequests(reqs); ReservationId reservationID = ReservationSystemTestUtil.GetNewReservationId(); agent.CreateReservation(reservationID, "u1", plan, rr); NUnit.Framework.Assert.IsTrue("Agent-based allocation failed", reservationID != null ); NUnit.Framework.Assert.IsTrue("Agent-based allocation failed", plan.GetAllReservations ().Count == 3); ReservationAllocation cs = plan.GetReservationById(reservationID); System.Console.Out.WriteLine("--------AFTER SIMPLE ALLOCATION (queue: " + reservationID + ")----------"); System.Console.Out.WriteLine(plan.ToString()); System.Console.Out.WriteLine(plan.ToCumulativeString()); for (long i = 10 * step; i < 20 * step; i++) { NUnit.Framework.Assert.IsTrue("Agent-based allocation unexpected", Resources.Equals (cs.GetResourcesAtTime(i), Org.Apache.Hadoop.Yarn.Api.Records.Resource.NewInstance (2048 * 10, 2 * 10))); } }
private bool RemoveReservation(ReservationAllocation reservation) { System.Diagnostics.Debug.Assert((readWriteLock.IsWriteLockedByCurrentThread())); ReservationInterval searchInterval = new ReservationInterval(reservation.GetStartTime (), reservation.GetEndTime()); ICollection <InMemoryReservationAllocation> reservations = currentReservations[searchInterval ]; if (reservations != null) { if (!reservations.Remove(reservation)) { Log.Error("Unable to remove reservation: {} from plan.", reservation.GetReservationId ()); return(false); } if (reservations.IsEmpty()) { Sharpen.Collections.Remove(currentReservations, searchInterval); } } else { string errMsg = "The specified Reservation with ID " + reservation.GetReservationId () + " does not exist in the plan"; Log.Error(errMsg); throw new ArgumentException(errMsg); } Sharpen.Collections.Remove(reservationTable, reservation.GetReservationId()); DecrementAllocation(reservation); Log.Info("Sucessfully deleted reservation: {} in plan.", reservation.GetReservationId ()); return(true); }
private bool Check(ReservationAllocation cs, long start, long end, int containers , int mem, int cores) { bool res = true; for (long i = start; i < end; i++) { res = res && Resources.Equals(cs.GetResourcesAtTime(i), Org.Apache.Hadoop.Yarn.Api.Records.Resource .NewInstance(mem * containers, cores * containers)); } return(res); }
/// <exception cref="Org.Apache.Hadoop.Yarn.Server.Resourcemanager.Reservation.Exceptions.PlanningException /// "/> public virtual bool UpdateReservation(ReservationAllocation reservation) { writeLock.Lock(); bool result = false; try { ReservationId resId = reservation.GetReservationId(); ReservationAllocation currReservation = GetReservationById(resId); if (currReservation == null) { string errMsg = "The specified Reservation with ID " + resId + " does not exist in the plan"; Log.Error(errMsg); throw new ArgumentException(errMsg); } // validate if we can accept this reservation, throws exception if // validation fails policy.Validate(this, reservation); if (!RemoveReservation(currReservation)) { Log.Error("Unable to replace reservation: {} from plan.", reservation.GetReservationId ()); return(result); } try { result = AddReservation(reservation); } catch (PlanningException e) { Log.Error("Unable to update reservation: {} from plan due to {}.", reservation.GetReservationId (), e.Message); } if (result) { Log.Info("Sucessfully updated reservation: {} in plan.", reservation.GetReservationId ()); return(result); } else { // rollback delete AddReservation(currReservation); Log.Info("Rollbacked update reservation: {} from plan.", reservation.GetReservationId ()); return(result); } } finally { writeLock.Unlock(); } }
public virtual void TestOrder() { PrepareBasicPlan(); // create a completely utilized segment around time 30 int[] f = new int[] { 100, 100 }; NUnit.Framework.Assert.IsTrue(plan.ToString(), plan.AddReservation(new InMemoryReservationAllocation (ReservationSystemTestUtil.GetNewReservationId(), null, "u1", "dedicated", 30 * step, 30 * step + f.Length * step, ReservationSystemTestUtil.GenerateAllocation( 30 * step, step, f), res, minAlloc))); // create a chain of 4 RR, mixing gang and non-gang ReservationDefinition rr = new ReservationDefinitionPBImpl(); rr.SetArrival(0 * step); rr.SetDeadline(70 * step); ReservationRequests reqs = new ReservationRequestsPBImpl(); reqs.SetInterpreter(ReservationRequestInterpreter.ROrder); ReservationRequest r = ReservationRequest.NewInstance(Org.Apache.Hadoop.Yarn.Api.Records.Resource .NewInstance(2048, 2), 10, 1, 10 * step); ReservationRequest r2 = ReservationRequest.NewInstance(Org.Apache.Hadoop.Yarn.Api.Records.Resource .NewInstance(1024, 1), 10, 10, 20 * step); IList <ReservationRequest> list = new AList <ReservationRequest>(); list.AddItem(r); list.AddItem(r2); list.AddItem(r); list.AddItem(r2); reqs.SetReservationResources(list); rr.SetReservationRequests(reqs); // submit to agent ReservationId reservationID = ReservationSystemTestUtil.GetNewReservationId(); agent.CreateReservation(reservationID, "u1", plan, rr); // validate NUnit.Framework.Assert.IsTrue("Agent-based allocation failed", reservationID != null ); NUnit.Framework.Assert.IsTrue("Agent-based allocation failed", plan.GetAllReservations ().Count == 4); ReservationAllocation cs = plan.GetReservationById(reservationID); NUnit.Framework.Assert.IsTrue(cs.ToString(), Check(cs, 0 * step, 10 * step, 20, 1024 , 1)); NUnit.Framework.Assert.IsTrue(cs.ToString(), Check(cs, 10 * step, 30 * step, 10, 1024, 1)); NUnit.Framework.Assert.IsTrue(cs.ToString(), Check(cs, 40 * step, 50 * step, 20, 1024, 1)); NUnit.Framework.Assert.IsTrue(cs.ToString(), Check(cs, 50 * step, 70 * step, 10, 1024, 1)); System.Console.Out.WriteLine("--------AFTER ORDER ALLOCATION (queue: " + reservationID + ")----------"); System.Console.Out.WriteLine(plan.ToString()); System.Console.Out.WriteLine(plan.ToCumulativeString()); }
/// <exception cref="Org.Apache.Hadoop.Yarn.Server.Resourcemanager.Reservation.Exceptions.PlanningException /// "/> public virtual bool AddReservation(ReservationAllocation reservation) { // Verify the allocation is memory based otherwise it is not supported InMemoryReservationAllocation inMemReservation = (InMemoryReservationAllocation)reservation; if (inMemReservation.GetUser() == null) { string errMsg = "The specified Reservation with ID " + inMemReservation.GetReservationId () + " is not mapped to any user"; Log.Error(errMsg); throw new ArgumentException(errMsg); } writeLock.Lock(); try { if (reservationTable.Contains(inMemReservation.GetReservationId())) { string errMsg = "The specified Reservation with ID " + inMemReservation.GetReservationId () + " already exists"; Log.Error(errMsg); throw new ArgumentException(errMsg); } // Validate if we can accept this reservation, throws exception if // validation fails policy.Validate(this, inMemReservation); // we record here the time in which the allocation has been accepted reservation.SetAcceptanceTimestamp(clock.GetTime()); ReservationInterval searchInterval = new ReservationInterval(inMemReservation.GetStartTime (), inMemReservation.GetEndTime()); ICollection <InMemoryReservationAllocation> reservations = currentReservations[searchInterval ]; if (reservations == null) { reservations = new HashSet <InMemoryReservationAllocation>(); } if (!reservations.AddItem(inMemReservation)) { Log.Error("Unable to add reservation: {} to plan.", inMemReservation.GetReservationId ()); return(false); } currentReservations[searchInterval] = reservations; reservationTable[inMemReservation.GetReservationId()] = inMemReservation; IncrementAllocation(inMemReservation); Log.Info("Sucessfully added reservation: {} to plan.", inMemReservation.GetReservationId ()); return(true); } finally { writeLock.Unlock(); } }
public virtual int CompareTo(ReservationAllocation other) { // reverse order of acceptance if (this.GetAcceptanceTime() > other.GetAcceptanceTime()) { return(-1); } if (this.GetAcceptanceTime() < other.GetAcceptanceTime()) { return(1); } return(0); }
private void DoAssertions(ReservationAllocation rAllocation, ReservationId reservationID , ReservationDefinition rDef, IDictionary <ReservationInterval, ReservationRequest > allocations, int start, int[] alloc) { NUnit.Framework.Assert.AreEqual(reservationID, rAllocation.GetReservationId()); NUnit.Framework.Assert.AreEqual(rDef, rAllocation.GetReservationDefinition()); NUnit.Framework.Assert.AreEqual(allocations, rAllocation.GetAllocationRequests()); NUnit.Framework.Assert.AreEqual(user, rAllocation.GetUser()); NUnit.Framework.Assert.AreEqual(planName, rAllocation.GetPlanName()); NUnit.Framework.Assert.AreEqual(start, rAllocation.GetStartTime()); NUnit.Framework.Assert.AreEqual(start + alloc.Length + 1, rAllocation.GetEndTime( )); }
private void DoAssertions(Plan plan, ReservationAllocation rAllocation) { ReservationId reservationID = rAllocation.GetReservationId(); NUnit.Framework.Assert.IsNotNull(plan.GetReservationById(reservationID)); NUnit.Framework.Assert.AreEqual(rAllocation, plan.GetReservationById(reservationID )); NUnit.Framework.Assert.IsTrue(((InMemoryPlan)plan).GetAllReservations().Count == 1); NUnit.Framework.Assert.AreEqual(rAllocation.GetEndTime(), plan.GetLastEndTime()); NUnit.Framework.Assert.AreEqual(totalCapacity, plan.GetTotalCapacity()); NUnit.Framework.Assert.AreEqual(minAlloc, plan.GetMinimumAllocation()); NUnit.Framework.Assert.AreEqual(maxAlloc, plan.GetMaximumAllocation()); NUnit.Framework.Assert.AreEqual(resCalc, plan.GetResourceCalculator()); NUnit.Framework.Assert.AreEqual(planName, plan.GetQueueName()); NUnit.Framework.Assert.IsTrue(plan.GetMoveOnExpiry()); }
private void DecrementAllocation(ReservationAllocation reservation) { System.Diagnostics.Debug.Assert((readWriteLock.IsWriteLockedByCurrentThread())); IDictionary <ReservationInterval, ReservationRequest> allocationRequests = reservation .GetAllocationRequests(); string user = reservation.GetUser(); RLESparseResourceAllocation resAlloc = userResourceAlloc[user]; foreach (KeyValuePair <ReservationInterval, ReservationRequest> r in allocationRequests) { resAlloc.RemoveInterval(r.Key, r.Value); rleSparseVector.RemoveInterval(r.Key, r.Value); } if (resAlloc.IsEmpty()) { Sharpen.Collections.Remove(userResourceAlloc, user); } }
public virtual bool DeleteReservation(ReservationId reservationID) { writeLock.Lock(); try { ReservationAllocation reservation = GetReservationById(reservationID); if (reservation == null) { string errMsg = "The specified Reservation with ID " + reservationID + " does not exist in the plan"; Log.Error(errMsg); throw new ArgumentException(errMsg); } return(RemoveReservation(reservation)); } finally { writeLock.Unlock(); } }
public virtual void TestAny() { PrepareBasicPlan(); // create an ANY request, with an impossible step (last in list, first // considered), // and two satisfiable ones. We expect the second one to be returned. ReservationDefinition rr = new ReservationDefinitionPBImpl(); rr.SetArrival(100 * step); rr.SetDeadline(120 * step); ReservationRequests reqs = new ReservationRequestsPBImpl(); reqs.SetInterpreter(ReservationRequestInterpreter.RAny); ReservationRequest r = ReservationRequest.NewInstance(Org.Apache.Hadoop.Yarn.Api.Records.Resource .NewInstance(1024, 1), 5, 5, 10 * step); ReservationRequest r2 = ReservationRequest.NewInstance(Org.Apache.Hadoop.Yarn.Api.Records.Resource .NewInstance(2048, 2), 10, 5, 10 * step); ReservationRequest r3 = ReservationRequest.NewInstance(Org.Apache.Hadoop.Yarn.Api.Records.Resource .NewInstance(1024, 1), 110, 110, 10 * step); IList <ReservationRequest> list = new AList <ReservationRequest>(); list.AddItem(r); list.AddItem(r2); list.AddItem(r3); reqs.SetReservationResources(list); rr.SetReservationRequests(reqs); // submit to agent ReservationId reservationID = ReservationSystemTestUtil.GetNewReservationId(); bool res = agent.CreateReservation(reservationID, "u1", plan, rr); // validate results, we expect the second one to be accepted NUnit.Framework.Assert.IsTrue("Agent-based allocation failed", res); NUnit.Framework.Assert.IsTrue("Agent-based allocation failed", plan.GetAllReservations ().Count == 3); ReservationAllocation cs = plan.GetReservationById(reservationID); NUnit.Framework.Assert.IsTrue(cs.ToString(), Check(cs, 110 * step, 120 * step, 20 , 1024, 1)); System.Console.Out.WriteLine("--------AFTER ANY ALLOCATION (queue: " + reservationID + ")----------"); System.Console.Out.WriteLine(plan.ToString()); System.Console.Out.WriteLine(plan.ToCumulativeString()); }
private void IncrementAllocation(ReservationAllocation reservation) { System.Diagnostics.Debug.Assert((readWriteLock.IsWriteLockedByCurrentThread())); IDictionary <ReservationInterval, ReservationRequest> allocationRequests = reservation .GetAllocationRequests(); // check if we have encountered the user earlier and if not add an entry string user = reservation.GetUser(); RLESparseResourceAllocation resAlloc = userResourceAlloc[user]; if (resAlloc == null) { resAlloc = new RLESparseResourceAllocation(resCalc, minAlloc); userResourceAlloc[user] = resAlloc; } foreach (KeyValuePair <ReservationInterval, ReservationRequest> r in allocationRequests) { resAlloc.AddInterval(r.Key, r.Value); rleSparseVector.AddInterval(r.Key, r.Value); } }
/// <exception cref="Org.Apache.Hadoop.Yarn.Server.Resourcemanager.Reservation.Exceptions.PlanningException /// "/> public virtual void Plan(Org.Apache.Hadoop.Yarn.Server.Resourcemanager.Reservation.Plan plan, IList <ReservationDefinition> contracts) { if (contracts != null) { throw new RuntimeException("SimpleCapacityReplanner cannot handle new reservation contracts" ); } ResourceCalculator resCalc = plan.GetResourceCalculator(); Org.Apache.Hadoop.Yarn.Api.Records.Resource totCap = plan.GetTotalCapacity(); long now = clock.GetTime(); // loop on all moment in time from now to the end of the check Zone // or the end of the planned sessions whichever comes first for (long t = now; (t < plan.GetLastEndTime() && t < (now + lengthOfCheckZone)); t += plan.GetStep()) { Org.Apache.Hadoop.Yarn.Api.Records.Resource excessCap = Resources.Subtract(plan.GetTotalCommittedResources (t), totCap); // if we are violating if (Resources.GreaterThan(resCalc, totCap, excessCap, ZeroResource)) { // sorted on reverse order of acceptance, so newest reservations first ICollection <ReservationAllocation> curReservations = new TreeSet <ReservationAllocation >(plan.GetReservationsAtTime(t)); for (IEnumerator <ReservationAllocation> resIter = curReservations.GetEnumerator() ; resIter.HasNext() && Resources.GreaterThan(resCalc, totCap, excessCap, ZeroResource );) { ReservationAllocation reservation = resIter.Next(); plan.DeleteReservation(reservation.GetReservationId()); excessCap = Resources.Subtract(excessCap, reservation.GetResourcesAtTime(t)); Log.Info("Removing reservation " + reservation.GetReservationId() + " to repair physical-resource constraints in the plan: " + plan.GetQueueName()); } } } }
/// <exception cref="Org.Apache.Hadoop.Yarn.Server.Resourcemanager.Reservation.Exceptions.PlanningException /// "/> public virtual void Validate(Plan plan, ReservationAllocation reservation) { ReservationAllocation oldReservation = plan.GetReservationById(reservation.GetReservationId ()); // check updates are using same name if (oldReservation != null && !oldReservation.GetUser().Equals(reservation.GetUser ())) { throw new MismatchedUserException("Updating an existing reservation with mismatching user:"******" != " + reservation.GetUser()); } long startTime = reservation.GetStartTime(); long endTime = reservation.GetEndTime(); long step = plan.GetStep(); // for every instant in time, check we are respecting cluster capacity for (long t = startTime; t < endTime; t += step) { Resource currExistingAllocTot = plan.GetTotalCommittedResources(t); Resource currNewAlloc = reservation.GetResourcesAtTime(t); Resource currOldAlloc = Resource.NewInstance(0, 0); if (oldReservation != null) { oldReservation.GetResourcesAtTime(t); } // check the cluster is never over committed // currExistingAllocTot + currNewAlloc - currOldAlloc > // capPlan.getTotalCapacity() if (Resources.GreaterThan(plan.GetResourceCalculator(), plan.GetTotalCapacity(), Resources.Subtract(Resources.Add(currExistingAllocTot, currNewAlloc), currOldAlloc ), plan.GetTotalCapacity())) { throw new ResourceOverCommitException("Resources at time " + t + " would be overcommitted by " + "accepting reservation: " + reservation.GetReservationId()); } } }
public virtual void TestDeleteReservationNormal() { ReservationDeleteRequest request = new ReservationDeleteRequestPBImpl(); ReservationId reservationID = ReservationSystemTestUtil.GetNewReservationId(); request.SetReservationId(reservationID); ReservationAllocation reservation = Org.Mockito.Mockito.Mock <ReservationAllocation >(); Org.Mockito.Mockito.When(plan.GetReservationById(reservationID)).ThenReturn(reservation ); Plan plan = null; try { plan = rrValidator.ValidateReservationDeleteRequest(rSystem, request); } catch (YarnException e) { NUnit.Framework.Assert.Fail(e.Message); } NUnit.Framework.Assert.IsNotNull(plan); }
public virtual void TestSingleSliding() { PrepareBasicPlan(); // create a single request for which we need subsequent (tight) packing. ReservationDefinition rr = new ReservationDefinitionPBImpl(); rr.SetArrival(100 * step); rr.SetDeadline(120 * step); ReservationRequests reqs = new ReservationRequestsPBImpl(); reqs.SetInterpreter(ReservationRequestInterpreter.RAll); ReservationRequest r = ReservationRequest.NewInstance(Org.Apache.Hadoop.Yarn.Api.Records.Resource .NewInstance(1024, 1), 200, 10, 10 * step); IList <ReservationRequest> list = new AList <ReservationRequest>(); list.AddItem(r); reqs.SetReservationResources(list); rr.SetReservationRequests(reqs); // submit to agent ReservationId reservationID = ReservationSystemTestUtil.GetNewReservationId(); agent.CreateReservation(reservationID, "u1", plan, rr); // validate results, we expect the second one to be accepted NUnit.Framework.Assert.IsTrue("Agent-based allocation failed", reservationID != null ); NUnit.Framework.Assert.IsTrue("Agent-based allocation failed", plan.GetAllReservations ().Count == 3); ReservationAllocation cs = plan.GetReservationById(reservationID); NUnit.Framework.Assert.IsTrue(cs.ToString(), Check(cs, 100 * step, 120 * step, 100 , 1024, 1)); System.Console.Out.WriteLine("--------AFTER packed ALLOCATION (queue: " + reservationID + ")----------"); System.Console.Out.WriteLine(plan.ToString()); System.Console.Out.WriteLine(plan.ToCumulativeString()); }
/// <exception cref="Org.Apache.Hadoop.Yarn.Server.Resourcemanager.Reservation.Exceptions.PlanningException /// "/> public virtual void Validate(Plan plan, ReservationAllocation reservation) { // this is entire method invoked under a write-lock on the plan, no need // to synchronize accesses to the plan further // Try to verify whether there is already a reservation with this ID in // the system (remove its contribution during validation to simulate a // try-n-swap // update). ReservationAllocation oldReservation = plan.GetReservationById(reservation.GetReservationId ()); // sanity check that the update of a reservation is not changing username if (oldReservation != null && !oldReservation.GetUser().Equals(reservation.GetUser ())) { throw new MismatchedUserException("Updating an existing reservation with mismatched user:"******" != " + reservation.GetUser()); } long startTime = reservation.GetStartTime(); long endTime = reservation.GetEndTime(); long step = plan.GetStep(); Resource planTotalCapacity = plan.GetTotalCapacity(); Org.Apache.Hadoop.Yarn.Api.Records.Resource maxAvgRes = Resources.Multiply(planTotalCapacity , maxAvg); Org.Apache.Hadoop.Yarn.Api.Records.Resource maxInsRes = Resources.Multiply(planTotalCapacity , maxInst); // define variable that will store integral of resources (need diff class to // avoid overflow issues for long/large allocations) CapacityOverTimePolicy.IntegralResource runningTot = new CapacityOverTimePolicy.IntegralResource (0L, 0L); CapacityOverTimePolicy.IntegralResource maxAllowed = new CapacityOverTimePolicy.IntegralResource (maxAvgRes); maxAllowed.MultiplyBy(validWindow / step); // check that the resources offered to the user during any window of length // "validWindow" overlapping this allocation are within maxAllowed // also enforce instantaneous and physical constraints during this pass for (long t = startTime - validWindow; t < endTime + validWindow; t += step) { Org.Apache.Hadoop.Yarn.Api.Records.Resource currExistingAllocTot = plan.GetTotalCommittedResources (t); Org.Apache.Hadoop.Yarn.Api.Records.Resource currExistingAllocForUser = plan.GetConsumptionForUser (reservation.GetUser(), t); Org.Apache.Hadoop.Yarn.Api.Records.Resource currNewAlloc = reservation.GetResourcesAtTime (t); Org.Apache.Hadoop.Yarn.Api.Records.Resource currOldAlloc = Resources.None(); if (oldReservation != null) { currOldAlloc = oldReservation.GetResourcesAtTime(t); } // throw exception if the cluster is overcommitted // tot_allocated - old + new > capacity Org.Apache.Hadoop.Yarn.Api.Records.Resource inst = Resources.Subtract(Resources.Add (currExistingAllocTot, currNewAlloc), currOldAlloc); if (Resources.GreaterThan(plan.GetResourceCalculator(), planTotalCapacity, inst, planTotalCapacity)) { throw new ResourceOverCommitException(" Resources at time " + t + " would be overcommitted (" + inst + " over " + plan.GetTotalCapacity() + ") by accepting reservation: " + reservation.GetReservationId()); } // throw exception if instantaneous limits are violated // tot_alloc_to_this_user - old + new > inst_limit if (Resources.GreaterThan(plan.GetResourceCalculator(), planTotalCapacity, Resources .Subtract(Resources.Add(currExistingAllocForUser, currNewAlloc), currOldAlloc), maxInsRes)) { throw new PlanningQuotaException("Instantaneous quota capacity " + maxInst + " would be passed at time " + t + " by accepting reservation: " + reservation.GetReservationId()); } // throw exception if the running integral of utilization over validWindow // is violated. We perform a delta check, adding/removing instants at the // boundary of the window from runningTot. // runningTot = previous_runningTot + currExistingAllocForUser + // currNewAlloc - currOldAlloc - pastNewAlloc - pastOldAlloc; // Where: // 1) currNewAlloc, currExistingAllocForUser represent the contribution of // the instant in time added in this pass. // 2) pastNewAlloc, pastOldAlloc are the contributions relative to time // instants that are being retired from the the window // 3) currOldAlloc is the contribution (if any) of the previous version of // this reservation (the one we are updating) runningTot.Add(currExistingAllocForUser); runningTot.Add(currNewAlloc); runningTot.Subtract(currOldAlloc); // expire contributions from instant in time before (t - validWindow) if (t > startTime) { Org.Apache.Hadoop.Yarn.Api.Records.Resource pastOldAlloc = plan.GetConsumptionForUser (reservation.GetUser(), t - validWindow); Org.Apache.Hadoop.Yarn.Api.Records.Resource pastNewAlloc = reservation.GetResourcesAtTime (t - validWindow); // runningTot = runningTot - pastExistingAlloc - pastNewAlloc; runningTot.Subtract(pastOldAlloc); runningTot.Subtract(pastNewAlloc); } // check integral // runningTot > maxAvg * validWindow // NOTE: we need to use comparator of IntegralResource directly, as // Resource and ResourceCalculator assume "int" amount of resources, // which is not sufficient when comparing integrals (out-of-bound) if (maxAllowed.CompareTo(runningTot) < 0) { throw new PlanningQuotaException("Integral (avg over time) quota capacity " + maxAvg + " over a window of " + validWindow / 1000 + " seconds, " + " would be passed at time " + t + "(" + Sharpen.Extensions.CreateDate(t) + ") by accepting reservation: " + reservation.GetReservationId()); } } }
/// <exception cref="Org.Apache.Hadoop.Yarn.Server.Resourcemanager.Reservation.Exceptions.PlanningException /// "/> /// <exception cref="Org.Apache.Hadoop.Yarn.Server.Resourcemanager.Reservation.Exceptions.ContractValidationException /// "/> private bool ComputeAllocation(ReservationId reservationId, string user, Plan plan , ReservationDefinition contract, ReservationAllocation oldReservation) { Log.Info("placing the following ReservationRequest: " + contract); Resource totalCapacity = plan.GetTotalCapacity(); // Here we can addd logic to adjust the ResourceDefinition to account for // system "imperfections" (e.g., scheduling delays for large containers). // Align with plan step conservatively (i.e., ceil arrival, and floor // deadline) long earliestStart = contract.GetArrival(); long step = plan.GetStep(); if (earliestStart % step != 0) { earliestStart = earliestStart + (step - (earliestStart % step)); } long deadline = contract.GetDeadline() - contract.GetDeadline() % plan.GetStep(); // setup temporary variables to handle time-relations between stages and // intermediate answers long curDeadline = deadline; long oldDeadline = -1; IDictionary <ReservationInterval, ReservationRequest> allocations = new Dictionary <ReservationInterval, ReservationRequest>(); RLESparseResourceAllocation tempAssigned = new RLESparseResourceAllocation(plan.GetResourceCalculator (), plan.GetMinimumAllocation()); IList <ReservationRequest> stages = contract.GetReservationRequests().GetReservationResources (); ReservationRequestInterpreter type = contract.GetReservationRequests().GetInterpreter (); // Iterate the stages in backward from deadline for (ListIterator <ReservationRequest> li = stages.ListIterator(stages.Count); li. HasPrevious();) { ReservationRequest currentReservationStage = li.Previous(); // validate the RR respect basic constraints ValidateInput(plan, currentReservationStage, totalCapacity); // run allocation for a single stage IDictionary <ReservationInterval, ReservationRequest> curAlloc = PlaceSingleStage( plan, tempAssigned, currentReservationStage, earliestStart, curDeadline, oldReservation , totalCapacity); if (curAlloc == null) { // if we did not find an allocation for the currentReservationStage // return null, unless the ReservationDefinition we are placing is of // type ANY if (type != ReservationRequestInterpreter.RAny) { throw new PlanningException("The GreedyAgent" + " couldn't find a valid allocation for your request" ); } else { continue; } } else { // if we did find an allocation add it to the set of allocations allocations.PutAll(curAlloc); // if this request is of type ANY we are done searching (greedy) // and can return the current allocation (break-out of the search) if (type == ReservationRequestInterpreter.RAny) { break; } // if the request is of ORDER or ORDER_NO_GAP we constraint the next // round of allocation to precede the current allocation, by setting // curDeadline if (type == ReservationRequestInterpreter.ROrder || type == ReservationRequestInterpreter .ROrderNoGap) { curDeadline = FindEarliestTime(curAlloc.Keys); // for ORDER_NO_GAP verify that the allocation found so far has no // gap, return null otherwise (the greedy procedure failed to find a // no-gap // allocation) if (type == ReservationRequestInterpreter.ROrderNoGap && oldDeadline > 0) { if (oldDeadline - FindLatestTime(curAlloc.Keys) > plan.GetStep()) { throw new PlanningException("The GreedyAgent" + " couldn't find a valid allocation for your request" ); } } // keep the variable oldDeadline pointing to the last deadline we // found oldDeadline = curDeadline; } } } // / If we got here is because we failed to find an allocation for the // ReservationDefinition give-up and report failure to the user if (allocations.IsEmpty()) { throw new PlanningException("The GreedyAgent" + " couldn't find a valid allocation for your request" ); } // create reservation with above allocations if not null/empty ReservationRequest ZeroRes = ReservationRequest.NewInstance(Resource.NewInstance( 0, 0), 0); long firstStartTime = FindEarliestTime(allocations.Keys); // add zero-padding from arrival up to the first non-null allocation // to guarantee that the reservation exists starting at arrival if (firstStartTime > earliestStart) { allocations[new ReservationInterval(earliestStart, firstStartTime)] = ZeroRes; firstStartTime = earliestStart; } // consider to add trailing zeros at the end for simmetry // Actually add/update the reservation in the plan. // This is subject to validation as other agents might be placing // in parallel and there might be sharing policies the agent is not // aware off. ReservationAllocation capReservation = new InMemoryReservationAllocation(reservationId , contract, user, plan.GetQueueName(), firstStartTime, FindLatestTime(allocations .Keys), allocations, plan.GetResourceCalculator(), plan.GetMinimumAllocation()); if (oldReservation != null) { return(plan.UpdateReservation(capReservation)); } else { return(plan.AddReservation(capReservation)); } }
/// <summary> /// This method actually perform the placement of an atomic stage of the /// reservation. /// </summary> /// <remarks> /// This method actually perform the placement of an atomic stage of the /// reservation. The key idea is to traverse the plan backward for a /// "lease-duration" worth of time, and compute what is the maximum multiple of /// our concurrency (gang) parameter we can fit. We do this and move towards /// previous instant in time until the time-window is exhausted or we placed /// all the user request. /// </remarks> private IDictionary <ReservationInterval, ReservationRequest> PlaceSingleStage(Plan plan, RLESparseResourceAllocation tempAssigned, ReservationRequest rr, long earliestStart , long curDeadline, ReservationAllocation oldResAllocation, Org.Apache.Hadoop.Yarn.Api.Records.Resource totalCapacity) { IDictionary <ReservationInterval, ReservationRequest> allocationRequests = new Dictionary <ReservationInterval, ReservationRequest>(); // compute the gang as a resource and get the duration Org.Apache.Hadoop.Yarn.Api.Records.Resource gang = Resources.Multiply(rr.GetCapability (), rr.GetConcurrency()); long dur = rr.GetDuration(); long step = plan.GetStep(); // ceil the duration to the next multiple of the plan step if (dur % step != 0) { dur += (step - (dur % step)); } // we know for sure that this division has no remainder (part of contract // with user, validate before int gangsToPlace = rr.GetNumContainers() / rr.GetConcurrency(); int maxGang = 0; // loop trying to place until we are done, or we are considering // an invalid range of times while (gangsToPlace > 0 && curDeadline - dur >= earliestStart) { // as we run along we remember how many gangs we can fit, and what // was the most constraining moment in time (we will restart just // after that to place the next batch) maxGang = gangsToPlace; long minPoint = curDeadline; int curMaxGang = maxGang; // start placing at deadline (excluded due to [,) interval semantics and // move backward for (long t = curDeadline - plan.GetStep(); t >= curDeadline - dur && maxGang > 0 ; t = t - plan.GetStep()) { // As we run along we will logically remove the previous allocation for // this reservation // if one existed Org.Apache.Hadoop.Yarn.Api.Records.Resource oldResCap = Org.Apache.Hadoop.Yarn.Api.Records.Resource .NewInstance(0, 0); if (oldResAllocation != null) { oldResCap = oldResAllocation.GetResourcesAtTime(t); } // compute net available resources Org.Apache.Hadoop.Yarn.Api.Records.Resource netAvailableRes = Resources.Clone(totalCapacity ); Resources.AddTo(netAvailableRes, oldResCap); Resources.SubtractFrom(netAvailableRes, plan.GetTotalCommittedResources(t)); Resources.SubtractFrom(netAvailableRes, tempAssigned.GetCapacityAtTime(t)); // compute maximum number of gangs we could fit curMaxGang = (int)Math.Floor(Resources.Divide(plan.GetResourceCalculator(), totalCapacity , netAvailableRes, gang)); // pick the minimum between available resources in this instant, and how // many gangs we have to place curMaxGang = Math.Min(gangsToPlace, curMaxGang); // compare with previous max, and set it. also remember *where* we found // the minimum (useful for next attempts) if (curMaxGang <= maxGang) { maxGang = curMaxGang; minPoint = t; } } // if we were able to place any gang, record this, and decrement // gangsToPlace if (maxGang > 0) { gangsToPlace -= maxGang; ReservationInterval reservationInt = new ReservationInterval(curDeadline - dur, curDeadline ); ReservationRequest reservationRes = ReservationRequest.NewInstance(rr.GetCapability (), rr.GetConcurrency() * maxGang, rr.GetConcurrency(), rr.GetDuration()); // remember occupied space (plan is read-only till we find a plausible // allocation for the entire request). This is needed since we might be // placing other ReservationRequest within the same // ReservationDefinition, // and we must avoid double-counting the available resources tempAssigned.AddInterval(reservationInt, reservationRes); allocationRequests[reservationInt] = reservationRes; } // reset our new starting point (curDeadline) to the most constraining // point so far, we will look "left" of that to find more places where // to schedule gangs (for sure nothing on the "right" of this point can // fit a full gang. curDeadline = minPoint; } // if no gangs are left to place we succeed and return the allocation if (gangsToPlace == 0) { return(allocationRequests); } else { // If we are here is becasue we did not manage to satisfy this request. // So we need to remove unwanted side-effect from tempAssigned (needed // for ANY). foreach (KeyValuePair <ReservationInterval, ReservationRequest> tempAllocation in allocationRequests) { tempAssigned.RemoveInterval(tempAllocation.Key, tempAllocation.Value); } // and return null to signal failure in this allocation return(null); } }