Example #1
0
        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);
        }
 /// <summary>Removes a resource for the specified interval</summary>
 /// <param name="reservationInterval">
 /// the interval for which the resource is to be
 /// removed
 /// </param>
 /// <param name="capacity">the resource to be removed</param>
 /// <returns>true if removal is successful, false otherwise</returns>
 public virtual bool RemoveInterval(ReservationInterval reservationInterval, ReservationRequest
                                    capacity)
 {
     Org.Apache.Hadoop.Yarn.Api.Records.Resource totCap = Resources.Multiply(capacity.
                                                                             GetCapability(), (float)capacity.GetNumContainers());
     if (totCap.Equals(ZeroResource))
     {
         return(true);
     }
     writeLock.Lock();
     try
     {
         long startKey = reservationInterval.GetStartTime();
         long endKey   = reservationInterval.GetEndTime();
         // update the start key
         NavigableMap <long, Org.Apache.Hadoop.Yarn.Api.Records.Resource> ticks = cumulativeCapacity
                                                                                  .HeadMap(endKey, false);
         // Decrease all the capacities of overlapping intervals
         SortedDictionary <long, Org.Apache.Hadoop.Yarn.Api.Records.Resource> overlapSet =
             ticks.TailMap(startKey);
         if (overlapSet != null && !overlapSet.IsEmpty())
         {
             Org.Apache.Hadoop.Yarn.Api.Records.Resource updatedCapacity = Org.Apache.Hadoop.Yarn.Api.Records.Resource
                                                                           .NewInstance(0, 0);
             long currentKey = -1;
             for (IEnumerator <KeyValuePair <long, Org.Apache.Hadoop.Yarn.Api.Records.Resource> >
                  overlapEntries = overlapSet.GetEnumerator(); overlapEntries.HasNext();)
             {
                 KeyValuePair <long, Org.Apache.Hadoop.Yarn.Api.Records.Resource> entry = overlapEntries
                                                                                          .Next();
                 currentKey      = entry.Key;
                 updatedCapacity = Resources.Subtract(entry.Value, totCap);
                 // update each entry between start and end key
                 cumulativeCapacity[currentKey] = updatedCapacity;
             }
             // Remove the first overlap entry if it is same as previous after
             // updation
             long firstKey = overlapSet.FirstKey();
             if (IsSameAsPrevious(firstKey, overlapSet[firstKey]))
             {
                 Sharpen.Collections.Remove(cumulativeCapacity, firstKey);
             }
             // Remove the next entry if it is same as end entry after updation
             if ((currentKey != -1) && (IsSameAsNext(currentKey, updatedCapacity)))
             {
                 Sharpen.Collections.Remove(cumulativeCapacity, cumulativeCapacity.HigherKey(currentKey
                                                                                             ));
             }
         }
         return(true);
     }
     finally
     {
         writeLock.Unlock();
     }
 }
Example #3
0
        public virtual void ArchiveCompletedReservations(long tick)
        {
            // Since we are looking for old reservations, read lock is optimal
            Log.Debug("Running archival at time: {}", tick);
            IList <InMemoryReservationAllocation> expiredReservations = new AList <InMemoryReservationAllocation
                                                                                   >();

            readLock.Lock();
            // archive reservations and delete the ones which are beyond
            // the reservation policy "window"
            try
            {
                long archivalTime = tick - policy.GetValidWindow();
                ReservationInterval searchInterval = new ReservationInterval(archivalTime, archivalTime
                                                                             );
                SortedDictionary <ReservationInterval, ICollection <InMemoryReservationAllocation> >
                reservations = currentReservations.HeadMap(searchInterval, true);
                if (!reservations.IsEmpty())
                {
                    foreach (ICollection <InMemoryReservationAllocation> reservationEntries in reservations
                             .Values)
                    {
                        foreach (InMemoryReservationAllocation reservation in reservationEntries)
                        {
                            if (reservation.GetEndTime() <= archivalTime)
                            {
                                expiredReservations.AddItem(reservation);
                            }
                        }
                    }
                }
            }
            finally
            {
                readLock.Unlock();
            }
            if (expiredReservations.IsEmpty())
            {
                return;
            }
            // Need write lock only if there are any reservations to be deleted
            writeLock.Lock();
            try
            {
                foreach (InMemoryReservationAllocation expiredReservation in expiredReservations)
                {
                    RemoveReservation(expiredReservation);
                }
            }
            finally
            {
                writeLock.Unlock();
            }
        }
Example #4
0
        /// <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();
            }
        }
        /// <summary>Add multiple resources for the specified interval</summary>
        /// <param name="reservationInterval">
        /// the interval for which the resource is to be
        /// added
        /// </param>
        /// <param name="ReservationRequests">the resources to be added</param>
        /// <param name="clusterResource">the total resources in the cluster</param>
        /// <returns>true if addition is successful, false otherwise</returns>
        public virtual bool AddCompositeInterval(ReservationInterval reservationInterval,
                                                 IList <ReservationRequest> ReservationRequests, Org.Apache.Hadoop.Yarn.Api.Records.Resource
                                                 clusterResource)
        {
            ReservationRequest aggregateReservationRequest = Org.Apache.Hadoop.Yarn.Util.Records
                                                             .NewRecord <ReservationRequest>();

            Org.Apache.Hadoop.Yarn.Api.Records.Resource capacity = Org.Apache.Hadoop.Yarn.Api.Records.Resource
                                                                   .NewInstance(0, 0);
            foreach (ReservationRequest ReservationRequest in ReservationRequests)
            {
                Resources.AddTo(capacity, Resources.Multiply(ReservationRequest.GetCapability(),
                                                             ReservationRequest.GetNumContainers()));
            }
            aggregateReservationRequest.SetNumContainers((int)Math.Ceil(Resources.Divide(resourceCalculator
                                                                                         , clusterResource, capacity, minAlloc)));
            aggregateReservationRequest.SetCapability(minAlloc);
            return(AddInterval(reservationInterval, aggregateReservationRequest));
        }
Example #6
0
        public virtual ICollection <ReservationAllocation> GetReservationsAtTime(long tick
                                                                                 )
        {
            ReservationInterval searchInterval = new ReservationInterval(tick, long.MaxValue);

            readLock.Lock();
            try
            {
                SortedDictionary <ReservationInterval, ICollection <InMemoryReservationAllocation> >
                reservations = currentReservations.HeadMap(searchInterval, true);
                if (!reservations.IsEmpty())
                {
                    ICollection <ReservationAllocation> flattenedReservations = new HashSet <ReservationAllocation
                                                                                             >();
                    foreach (ICollection <InMemoryReservationAllocation> reservationEntries in reservations
                             .Values)
                    {
                        foreach (InMemoryReservationAllocation reservation in reservationEntries)
                        {
                            if (reservation.GetEndTime() > tick)
                            {
                                flattenedReservations.AddItem(reservation);
                            }
                        }
                    }
                    return(Sharpen.Collections.UnmodifiableSet(flattenedReservations));
                }
                else
                {
                    return(Sharpen.Collections.EmptySet());
                }
            }
            finally
            {
                readLock.Unlock();
            }
        }
 /// <summary>Add a resource for the specified interval</summary>
 /// <param name="reservationInterval">
 /// the interval for which the resource is to be
 /// added
 /// </param>
 /// <param name="capacity">the resource to be added</param>
 /// <returns>true if addition is successful, false otherwise</returns>
 public virtual bool AddInterval(ReservationInterval reservationInterval, ReservationRequest
                                 capacity)
 {
     Org.Apache.Hadoop.Yarn.Api.Records.Resource totCap = Resources.Multiply(capacity.
                                                                             GetCapability(), (float)capacity.GetNumContainers());
     if (totCap.Equals(ZeroResource))
     {
         return(true);
     }
     writeLock.Lock();
     try
     {
         long startKey = reservationInterval.GetStartTime();
         long endKey   = reservationInterval.GetEndTime();
         NavigableMap <long, Org.Apache.Hadoop.Yarn.Api.Records.Resource> ticks = cumulativeCapacity
                                                                                  .HeadMap(endKey, false);
         if (ticks != null && !ticks.IsEmpty())
         {
             Org.Apache.Hadoop.Yarn.Api.Records.Resource updatedCapacity = Org.Apache.Hadoop.Yarn.Api.Records.Resource
                                                                           .NewInstance(0, 0);
             KeyValuePair <long, Org.Apache.Hadoop.Yarn.Api.Records.Resource> lowEntry = ticks.
                                                                                         FloorEntry(startKey);
             if (lowEntry == null)
             {
                 // This is the earliest starting interval
                 cumulativeCapacity[startKey] = totCap;
             }
             else
             {
                 updatedCapacity = Resources.Add(lowEntry.Value, totCap);
                 // Add a new tick only if the updated value is different
                 // from the previous tick
                 if ((startKey == lowEntry.Key) && (IsSameAsPrevious(lowEntry.Key, updatedCapacity
                                                                     )))
                 {
                     Sharpen.Collections.Remove(cumulativeCapacity, lowEntry.Key);
                 }
                 else
                 {
                     cumulativeCapacity[startKey] = updatedCapacity;
                 }
             }
             // Increase all the capacities of overlapping intervals
             ICollection <KeyValuePair <long, Org.Apache.Hadoop.Yarn.Api.Records.Resource> > overlapSet
                 = ticks.TailMap(startKey, false);
             foreach (KeyValuePair <long, Org.Apache.Hadoop.Yarn.Api.Records.Resource> entry in
                      overlapSet)
             {
                 updatedCapacity = Resources.Add(entry.Value, totCap);
                 entry.SetValue(updatedCapacity);
             }
         }
         else
         {
             // This is the first interval to be added
             cumulativeCapacity[startKey] = totCap;
         }
         Org.Apache.Hadoop.Yarn.Api.Records.Resource nextTick = cumulativeCapacity[endKey];
         if (nextTick != null)
         {
             // If there is overlap, remove the duplicate entry
             if (IsSameAsPrevious(endKey, nextTick))
             {
                 Sharpen.Collections.Remove(cumulativeCapacity, endKey);
             }
         }
         else
         {
             // Decrease capacity as this is end of the interval
             cumulativeCapacity[endKey] = Resources.Subtract(cumulativeCapacity.FloorEntry(endKey
                                                                                           ).Value, totCap);
         }
         return(true);
     }
     finally
     {
         writeLock.Unlock();
     }
 }
Example #8
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);
            }
        }