예제 #1
0
        public virtual void TestZeroAlloaction()
        {
            ResourceCalculator resCalc = new DefaultResourceCalculator();

            Org.Apache.Hadoop.Yarn.Api.Records.Resource minAlloc = Org.Apache.Hadoop.Yarn.Api.Records.Resource
                                                                   .NewInstance(1, 1);
            RLESparseResourceAllocation rleSparseVector = new RLESparseResourceAllocation(resCalc
                                                                                          , minAlloc);

            rleSparseVector.AddInterval(new ReservationInterval(0, long.MaxValue), ReservationRequest
                                        .NewInstance(Org.Apache.Hadoop.Yarn.Api.Records.Resource.NewInstance(0, 0), (0))
                                        );
            Log.Info(rleSparseVector.ToString());
            NUnit.Framework.Assert.AreEqual(Org.Apache.Hadoop.Yarn.Api.Records.Resource.NewInstance
                                                (0, 0), rleSparseVector.GetCapacityAtTime(new Random().NextLong()));
            NUnit.Framework.Assert.IsTrue(rleSparseVector.IsEmpty());
        }
예제 #2
0
        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);
            }
        }
예제 #3
0
        public virtual void TestSteps()
        {
            ResourceCalculator resCalc = new DefaultResourceCalculator();

            Org.Apache.Hadoop.Yarn.Api.Records.Resource minAlloc = Org.Apache.Hadoop.Yarn.Api.Records.Resource
                                                                   .NewInstance(1, 1);
            RLESparseResourceAllocation rleSparseVector = new RLESparseResourceAllocation(resCalc
                                                                                          , minAlloc);

            int[] alloc = new int[] { 10, 10, 10, 10, 10, 10 };
            int   start = 100;
            ICollection <KeyValuePair <ReservationInterval, ReservationRequest> > inputs = GenerateAllocation
                                                                                               (start, alloc, true);

            foreach (KeyValuePair <ReservationInterval, ReservationRequest> ip in inputs)
            {
                rleSparseVector.AddInterval(ip.Key, ip.Value);
            }
            Log.Info(rleSparseVector.ToString());
            NUnit.Framework.Assert.IsFalse(rleSparseVector.IsEmpty());
            NUnit.Framework.Assert.AreEqual(Org.Apache.Hadoop.Yarn.Api.Records.Resource.NewInstance
                                                (0, 0), rleSparseVector.GetCapacityAtTime(99));
            NUnit.Framework.Assert.AreEqual(Org.Apache.Hadoop.Yarn.Api.Records.Resource.NewInstance
                                                (0, 0), rleSparseVector.GetCapacityAtTime(start + alloc.Length + 1));
            for (int i = 0; i < alloc.Length; i++)
            {
                NUnit.Framework.Assert.AreEqual(Org.Apache.Hadoop.Yarn.Api.Records.Resource.NewInstance
                                                    (1024 * (alloc[i] + i), (alloc[i] + i)), rleSparseVector.GetCapacityAtTime(start
                                                                                                                               + i));
            }
            NUnit.Framework.Assert.AreEqual(Org.Apache.Hadoop.Yarn.Api.Records.Resource.NewInstance
                                                (0, 0), rleSparseVector.GetCapacityAtTime(start + alloc.Length + 2));
            foreach (KeyValuePair <ReservationInterval, ReservationRequest> ip_1 in inputs)
            {
                rleSparseVector.RemoveInterval(ip_1.Key, ip_1.Value);
            }
            Log.Info(rleSparseVector.ToString());
            for (int i_1 = 0; i_1 < alloc.Length; i_1++)
            {
                NUnit.Framework.Assert.AreEqual(Org.Apache.Hadoop.Yarn.Api.Records.Resource.NewInstance
                                                    (0, 0), rleSparseVector.GetCapacityAtTime(start + i_1));
            }
            NUnit.Framework.Assert.IsTrue(rleSparseVector.IsEmpty());
        }
예제 #4
0
        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);
            }
        }
예제 #5
0
 internal InMemoryPlan(QueueMetrics queueMetrics, SharingPolicy policy, ReservationAgent
                       agent, Org.Apache.Hadoop.Yarn.Api.Records.Resource totalCapacity, long step, ResourceCalculator
                       resCalc, Org.Apache.Hadoop.Yarn.Api.Records.Resource minAlloc, Org.Apache.Hadoop.Yarn.Api.Records.Resource
                       maxAlloc, string queueName, Planner replanner, bool getMoveOnExpiry, Clock clock
                       )
 {
     this.queueMetrics    = queueMetrics;
     this.policy          = policy;
     this.agent           = agent;
     this.step            = step;
     this.totalCapacity   = totalCapacity;
     this.resCalc         = resCalc;
     this.minAlloc        = minAlloc;
     this.maxAlloc        = maxAlloc;
     this.rleSparseVector = new RLESparseResourceAllocation(resCalc, minAlloc);
     this.queueName       = queueName;
     this.replanner       = replanner;
     this.getMoveOnExpiry = getMoveOnExpiry;
     this.clock           = clock;
 }
예제 #6
0
 public virtual Org.Apache.Hadoop.Yarn.Api.Records.Resource GetConsumptionForUser(
     string user, long t)
 {
     readLock.Lock();
     try
     {
         RLESparseResourceAllocation userResAlloc = userResourceAlloc[user];
         if (userResAlloc != null)
         {
             return(userResAlloc.GetCapacityAtTime(t));
         }
         else
         {
             return(Resources.Clone(ZeroResource));
         }
     }
     finally
     {
         readLock.Unlock();
     }
 }
 internal InMemoryReservationAllocation(ReservationId reservationID, ReservationDefinition
                                        contract, string user, string planName, long startTime, long endTime, IDictionary
                                        <ReservationInterval, ReservationRequest> allocationRequests, ResourceCalculator
                                        calculator, Org.Apache.Hadoop.Yarn.Api.Records.Resource minAlloc)
 {
     this.contract           = contract;
     this.startTime          = startTime;
     this.endTime            = endTime;
     this.reservationID      = reservationID;
     this.user               = user;
     this.allocationRequests = allocationRequests;
     this.planName           = planName;
     resourcesOverTime       = new RLESparseResourceAllocation(calculator, minAlloc);
     foreach (KeyValuePair <ReservationInterval, ReservationRequest> r in allocationRequests)
     {
         resourcesOverTime.AddInterval(r.Key, r.Value);
         if (r.Value.GetConcurrency() > 1)
         {
             hasGang = true;
         }
     }
 }
예제 #8
0
        /// <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));
            }
        }
예제 #9
0
        /// <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);
            }
        }