PageRenderTime 49ms CodeModel.GetById 41ms app.highlight 6ms RepoModel.GetById 1ms app.codeStats 0ms

/hudson-core/src/main/java/hudson/model/ResourceController.java

http://github.com/hudson/hudson
Java | 136 lines | 54 code | 13 blank | 69 comment | 2 complexity | abd9125c68698632e4a3bdf92dd86e27 MD5 | raw file
  1/*
  2 * The MIT License
  3 * 
  4 * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
  5 * 
  6 * Permission is hereby granted, free of charge, to any person obtaining a copy
  7 * of this software and associated documentation files (the "Software"), to deal
  8 * in the Software without restriction, including without limitation the rights
  9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 10 * copies of the Software, and to permit persons to whom the Software is
 11 * furnished to do so, subject to the following conditions:
 12 * 
 13 * The above copyright notice and this permission notice shall be included in
 14 * all copies or substantial portions of the Software.
 15 * 
 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 22 * THE SOFTWARE.
 23 */
 24package hudson.model;
 25
 26import hudson.util.AdaptedIterator;
 27
 28import java.util.Set;
 29import java.util.HashSet;
 30import java.util.Collection;
 31import java.util.AbstractCollection;
 32import java.util.Iterator;
 33
 34/**
 35 * Controls mutual exclusion of {@link ResourceList}.
 36 * @author Kohsuke Kawaguchi
 37 */
 38public class ResourceController {
 39    /**
 40     * {@link ResourceList}s that are used by activities that are in progress.
 41     */
 42    private final Set<ResourceActivity> inProgress = new HashSet<ResourceActivity>();
 43
 44    /**
 45     * View of {@link #inProgress} that exposes its {@link ResourceList}.
 46     */
 47    private final Collection<ResourceList> resourceView = new AbstractCollection<ResourceList>() {
 48        public Iterator<ResourceList> iterator() {
 49            return new AdaptedIterator<ResourceActivity,ResourceList>(inProgress.iterator()) {
 50                protected ResourceList adapt(ResourceActivity item) {
 51                    return item.getResourceList();
 52                }
 53            };
 54        }
 55
 56        public int size() {
 57            return inProgress.size();
 58        }
 59    };
 60
 61    /**
 62     * Union of all {@link Resource}s that are currently in use.
 63     * Updated as a task starts/completes executing. 
 64     */
 65    private ResourceList inUse = ResourceList.EMPTY;
 66
 67    /**
 68     * Performs the task that requires the given list of resources.
 69     *
 70     * <p>
 71     * The execution is blocked until the resource is available.
 72     *
 73     * @throws InterruptedException
 74     *      the thread can be interrupted while waiting for the available resources.
 75     */
 76    public void execute( Runnable task, ResourceActivity activity ) throws InterruptedException {
 77        ResourceList resources = activity.getResourceList();
 78        synchronized(this) {
 79            while(inUse.isCollidingWith(resources))
 80                wait();
 81
 82            // we have a go
 83            inProgress.add(activity);
 84            inUse = ResourceList.union(inUse,resources);
 85        }
 86
 87        try {
 88            task.run();
 89        } finally {
 90            synchronized(this) {
 91                inProgress.remove(activity);
 92                inUse = ResourceList.union(resourceView);
 93                notifyAll();
 94            }
 95        }
 96    }
 97
 98    /**
 99     * Checks if an activity that requires the given resource list
100     * can run immediately.
101     *
102     * <p>
103     * This method is really only useful as a hint, since
104     * another activity might acquire resources before the caller
105     * gets to call {@link #execute(Runnable, ResourceActivity)}.
106     */
107    public synchronized boolean canRun(ResourceList resources) {
108        return !inUse.isCollidingWith(resources);
109    }
110
111    /**
112     * Of the resource in the given resource list, return the one that's
113     * currently in use.
114     *
115     * <p>
116     * If more than one such resource exists, one is chosen and returned.
117     * This method is used for reporting what's causing the blockage.
118     */
119    public synchronized Resource getMissingResource(ResourceList resources) {
120        return resources.getConflict(inUse);
121    }
122
123    /**
124     * Of the activities that are in progress, return one that's blocking
125     * the given activity, or null if it's not blocked (and thus the
126     * given activity can be executed immediately.)
127     */
128    public synchronized ResourceActivity getBlockingActivity(ResourceActivity activity) {
129        ResourceList res = activity.getResourceList();
130        for (ResourceActivity a : inProgress)
131            if(res.isCollidingWith(a.getResourceList()))
132                return a;
133        return null;
134    }
135}
136