package com.hubspot.singularity.scheduler; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; import javax.inject.Singleton; import org.apache.mesos.Protos.Offer; import org.apache.mesos.SchedulerDriver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.base.Optional; import com.google.inject.Inject; import com.hubspot.mesos.JavaUtils; import com.hubspot.singularity.SingularityAction; import com.hubspot.singularity.config.SingularityConfiguration; import com.hubspot.singularity.data.DisasterManager; import com.hubspot.singularity.mesos.OfferCache; import com.hubspot.singularity.mesos.SchedulerDriverSupplier; import com.hubspot.singularity.mesos.SingularityMesosOfferScheduler; import com.hubspot.singularity.mesos.SingularityOfferCache.CachedOffer; import com.hubspot.singularity.mesos.SingularityOfferHolder; import com.hubspot.singularity.mesos.SingularitySchedulerLock; @Singleton public class SingularitySchedulerPoller extends SingularityLeaderOnlyPoller { private static final Logger LOG = LoggerFactory.getLogger(SingularitySchedulerPoller.class); private final OfferCache offerCache; private final SchedulerDriverSupplier schedulerDriverSupplier; private final SingularityMesosOfferScheduler offerScheduler; private final DisasterManager disasterManager; private final SingularityConfiguration configuration; @Inject SingularitySchedulerPoller(SingularityMesosOfferScheduler offerScheduler, OfferCache offerCache, SchedulerDriverSupplier schedulerDriverSupplier, SingularityConfiguration configuration, SingularitySchedulerLock lock, DisasterManager disasterManager) { super(configuration.getCheckSchedulerEverySeconds(), TimeUnit.SECONDS, lock, true); this.offerCache = offerCache; this.offerScheduler = offerScheduler; this.schedulerDriverSupplier = schedulerDriverSupplier; this.disasterManager = disasterManager; this.configuration = configuration; } @Override public void runActionOnPoll() { if (disasterManager.isDisabled(SingularityAction.RUN_SCHEDULER_POLLER)) { LOG.warn("Scheduler poller is disabled"); return; } final long start = System.currentTimeMillis(); List<CachedOffer> cachedOffers = offerCache.checkoutOffers(); Map<String, CachedOffer> offerIdToCachedOffer = new HashMap<>(cachedOffers.size()); List<Offer> offers = new ArrayList<>(cachedOffers.size()); for (CachedOffer cachedOffer : cachedOffers) { offerIdToCachedOffer.put(cachedOffer.getOfferId(), cachedOffer); offers.add(cachedOffer.getOffer()); } List<SingularityOfferHolder> offerHolders = offerScheduler.checkOffers(offers); if (offerHolders.isEmpty()) { return; } Optional<SchedulerDriver> driver = schedulerDriverSupplier.get(); if (!driver.isPresent()) { LOG.error("No driver present, can't accept cached offers"); return; } int acceptedOffers = 0; int launchedTasks = 0; for (SingularityOfferHolder offerHolder : offerHolders) { CachedOffer cachedOffer = offerIdToCachedOffer.get(offerHolder.getOffer().getId().getValue()); if (!offerHolder.getAcceptedTasks().isEmpty()) { offerHolder.launchTasks(driver.get()); launchedTasks += offerHolder.getAcceptedTasks().size(); acceptedOffers++; offerCache.useOffer(cachedOffer); } else { offerCache.returnOffer(cachedOffer); } } LOG.info("Launched {} tasks on {} cached offers (returned {}) in {}", launchedTasks, acceptedOffers, offerHolders.size() - acceptedOffers, JavaUtils.duration(start)); } }