PageRenderTime 23ms CodeModel.GetById 15ms app.highlight 6ms RepoModel.GetById 1ms app.codeStats 0ms

/hudson-core/src/main/java/hudson/model/queue/WorkUnitContext.java

http://github.com/hudson/hudson
Java | 176 lines | 89 code | 25 blank | 62 comment | 10 complexity | e946382d07b2fdc44e18e10c79abfab6 MD5 | raw file
  1/*
  2 * The MIT License
  3 *
  4 * Copyright (c) 2010, InfraDNA, Inc.
  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.queue;
 25
 26import hudson.model.Action;
 27import hudson.model.Executor;
 28import hudson.model.Queue;
 29import hudson.model.Queue.BuildableItem;
 30import hudson.model.Queue.Task;
 31
 32import java.util.ArrayList;
 33import java.util.Collections;
 34import java.util.List;
 35
 36/**
 37 * Holds the information shared between {@link WorkUnit}s created from the same {@link Task}.
 38 *
 39 * @author Kohsuke Kawaguchi
 40 */
 41public final class WorkUnitContext {
 42
 43    //TODO: review and check whether we can do it private
 44    public final BuildableItem item;
 45
 46    //TODO: review and check whether we can do it private
 47    public final Task task;
 48
 49    /**
 50     * Once the execution is complete, update this future object with the outcome.
 51     */
 52    //TODO: review and check whether we can do it private
 53    public final FutureImpl future;
 54
 55    /**
 56     * Associated parameters to the build.
 57     */
 58    //TODO: review and check whether we can do it private
 59    public final List<Action> actions;
 60
 61    private final Latch startLatch, endLatch;
 62
 63    private List<WorkUnit> workUnits = new ArrayList<WorkUnit>();
 64
 65    /**
 66     * If the execution is aborted, set to non-null that indicates where it was aborted.
 67     */
 68    private volatile Throwable aborted;
 69
 70    public WorkUnitContext(BuildableItem item) {
 71        this.item = item;
 72        this.task = item.task;
 73        this.future = (FutureImpl)item.getFuture();
 74        this.actions = item.getActions();
 75        
 76        // +1 for the main task
 77        int workUnitSize = Tasks.getSubTasksOf(task).size();
 78        startLatch = new Latch(workUnitSize) {
 79            @Override
 80            protected void onCriteriaMet() {
 81                // on behalf of the member Executors,
 82                // the one that executes the main thing will send notifications
 83                Executor e = Executor.currentExecutor();
 84                if (e.getCurrentWorkUnit().isMainWork()) {
 85                    e.getOwner().taskAccepted(e,task);
 86                }
 87            }
 88        };
 89
 90        endLatch = new Latch(workUnitSize);
 91    }
 92
 93    public BuildableItem getItem() {
 94        return item;
 95    }
 96
 97    public Task getTask() {
 98        return task;
 99    }
100
101    public FutureImpl getFuture() {
102        return future;
103    }
104
105    public List<Action> getActions() {
106        return actions;
107    }
108
109    /**
110     * Called by the executor that executes a member {@link SubTask} that belongs to this task
111     * to create its {@link WorkUnit}.
112     */
113    public WorkUnit createWorkUnit(SubTask execUnit) {
114        future.addExecutor(Executor.currentExecutor());
115        WorkUnit wu = new WorkUnit(this, execUnit);
116        workUnits.add(wu);
117        return wu;
118    }
119
120    public List<WorkUnit> getWorkUnits() {
121        return Collections.unmodifiableList(workUnits);
122    }
123
124    public WorkUnit getPrimaryWorkUnit() {
125        return workUnits.get(0);
126    }
127
128    /**
129     * All the {@link Executor}s that jointly execute a {@link Task} call this method to synchronize on the start.
130     */
131    public void synchronizeStart() throws InterruptedException {
132        startLatch.synchronize();
133    }
134
135    /**
136     * All the {@link Executor}s that jointly execute a {@link Task} call this method to synchronize on the end of the task.
137     *
138     * @throws InterruptedException
139     *      If any of the member thread is interrupted while waiting for other threads to join, all
140     *      the member threads will report {@link InterruptedException}.
141     */
142    public void synchronizeEnd(Queue.Executable executable, Throwable problems, long duration) throws InterruptedException {
143        endLatch.synchronize();
144
145        // the main thread will send a notification
146        Executor e = Executor.currentExecutor();
147        WorkUnit wu = e.getCurrentWorkUnit();
148        if (wu.isMainWork()) {
149            if (problems == null) {
150                future.set(executable);
151                e.getOwner().taskCompleted(e, task, duration);
152            } else {
153                future.set(problems);
154                e.getOwner().taskCompletedWithProblems(e, task, duration, problems);
155            }
156        }
157    }
158
159    /**
160     * When one of the work unit is aborted, call this method to abort all the other work units.
161     */
162    public synchronized void abort(Throwable cause) {
163        if (cause==null)        throw new IllegalArgumentException();
164        if (aborted!=null)      return; // already aborted    
165        aborted = cause;
166        startLatch.abort(cause);
167        endLatch.abort(cause);
168
169        Thread c = Thread.currentThread();
170        for (WorkUnit wu : workUnits) {
171            Executor e = wu.getExecutor();
172            if (e!=null && e!=c)
173                e.interrupt();
174        }
175    }
176}