All Downloads are FREE. Search and download functionalities are using the official Maven repository.

hudson.model.LoadBalancer Maven / Gradle / Ivy

The newest version!
/*******************************************************************************
 *
 * Copyright (c) 2004-2010 Oracle Corporation.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *
 *    Kohsuke Kawaguchi
 *
 *
 *******************************************************************************/ 

package hudson.model;

import hudson.model.Queue.Task;
import hudson.model.queue.MappingWorksheet;
import hudson.model.queue.MappingWorksheet.ExecutorChunk;
import hudson.model.queue.MappingWorksheet.Mapping;
import hudson.util.ConsistentHash;
import hudson.util.ConsistentHash.Hash;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

/**
 * Strategy that decides which {@link Task} gets run on which {@link Executor}.
 *
 * @author Kohsuke Kawaguchi
 * @since 1.301
 */
public abstract class LoadBalancer /*implements ExtensionPoint*/ {

    /**
     * Chooses the executor(s) to carry out the build for the given task.
     *
     * 

This method is invoked from different threads, but the execution is * serialized by the caller. The thread that invokes this method always * holds a lock to {@link Queue}, so queue contents can be safely * introspected from this method, if that information is necessary to make * decisions. * * @param task The task whose execution is being considered. Never null. * @param worksheet The work sheet that represents the matching that needs * to be made. The job of this method is to determine which work units on * this worksheet are executed on which executors (also on this worksheet.) * * @return Build up the mapping by using the given worksheet and return it. * Return null if you don't want the task to be executed right now, in which * case this method will be called some time later with the same task. */ public abstract Mapping map(Task task, MappingWorksheet worksheet); /** * Uses a consistent hash for scheduling. */ public static final LoadBalancer CONSISTENT_HASH = new LoadBalancer() { @Override public Mapping map(Task task, MappingWorksheet ws) { // build consistent hash for each work chunk List> hashes = new ArrayList>(ws.works.size()); for (int i = 0; i < ws.works.size(); i++) { ConsistentHash hash = new ConsistentHash(new Hash() { public String hash(ExecutorChunk node) { return node.getName(); } }); for (ExecutorChunk ec : ws.works(i).applicableExecutorChunks()) { hash.add(ec, ec.size() * 100); } hashes.add(hash); } // do a greedy assignment Mapping m = ws.new Mapping(); assert m.size() == ws.works.size(); // just so that you the reader of the source code don't get confused with the for loop index if (assignGreedily(m, task, hashes, 0)) { assert m.isCompletelyValid(); return m; } else { return null; } } private boolean assignGreedily(Mapping m, Task task, List> hashes, int i) { if (i == hashes.size()) { return true; // fully assigned } String key = task.getFullDisplayName() + (i > 0 ? String.valueOf(i) : ""); for (ExecutorChunk ec : hashes.get(i).list(key)) { // let's attempt this assignment m.assign(i, ec); if (m.isPartiallyValid() && assignGreedily(m, task, hashes, i + 1)) { return true; // successful greedily allocation } // otherwise 'ec' wasn't a good fit for us. try next. } // every attempt failed m.assign(i, null); return false; } }; /** * Traditional implementation of this. * * @deprecated as of 1.377 The only implementation in the core now is the * one based on consistent hash. */ public static final LoadBalancer DEFAULT = CONSISTENT_HASH; /** * Wraps this {@link LoadBalancer} into a decorator that tests the basic * sanity of the implementation. Only override this if you find some of the * checks excessive, but beware that it's like driving without a seat belt. */ protected LoadBalancer sanitize() { final LoadBalancer base = this; return new LoadBalancer() { @Override public Mapping map(Task task, MappingWorksheet worksheet) { if (Queue.ifBlockedByHudsonShutdown(task)) { // if we are quieting down, don't start anything new so that // all executors will be eventually free. return null; } return base.map(task, worksheet); } /** * Double-sanitization is pointless. */ @Override protected LoadBalancer sanitize() { return this; } private final Logger LOGGER = Logger.getLogger(LoadBalancer.class.getName()); }; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy