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

hudson.model.queue.WorkUnitContext Maven / Gradle / Ivy

The newest version!
/*******************************************************************************
 *
 * Copyright (c) 2010, InfraDNA, Inc.
 *
 * 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:
 *
 *
 *
 *
 *******************************************************************************/ 

package hudson.model.queue;

import hudson.model.Action;
import hudson.model.Executor;
import hudson.model.Queue;
import hudson.model.Queue.BuildableItem;
import hudson.model.Queue.Task;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Holds the information shared between {@link WorkUnit}s created from the same
 * {@link Task}.
 *
 * @author Kohsuke Kawaguchi
 */
public final class WorkUnitContext {

    //TODO: review and check whether we can do it private
    public final BuildableItem item;
    //TODO: review and check whether we can do it private
    public final Task task;
    /**
     * Once the execution is complete, update this future object with the
     * outcome.
     */
    //TODO: review and check whether we can do it private
    public final FutureImpl future;
    /**
     * Associated parameters to the build.
     */
    //TODO: review and check whether we can do it private
    public final List actions;
    private final Latch startLatch, endLatch;
    private List workUnits = new ArrayList();
    /**
     * If the execution is aborted, set to non-null that indicates where it was
     * aborted.
     */
    private volatile Throwable aborted;

    public WorkUnitContext(BuildableItem item) {
        this.item = item;
        this.task = item.task;
        this.future = (FutureImpl) item.getFuture();
        this.actions = item.getActions();

        // +1 for the main task
        int workUnitSize = Tasks.getSubTasksOf(task).size();
        startLatch = new Latch(workUnitSize) {
            @Override
            protected void onCriteriaMet() {
                // on behalf of the member Executors,
                // the one that executes the main thing will send notifications
                Executor e = Executor.currentExecutor();
                if (e.getCurrentWorkUnit().isMainWork()) {
                    e.getOwner().taskAccepted(e, task);
                }
            }
        };

        endLatch = new Latch(workUnitSize);
    }

    public BuildableItem getItem() {
        return item;
    }

    public Task getTask() {
        return task;
    }

    public FutureImpl getFuture() {
        return future;
    }

    public List getActions() {
        return actions;
    }

    /**
     * Called by the executor that executes a member {@link SubTask} that
     * belongs to this task to create its {@link WorkUnit}.
     */
    public WorkUnit createWorkUnit(SubTask execUnit) {
        future.addExecutor(Executor.currentExecutor());
        WorkUnit wu = new WorkUnit(this, execUnit);
        workUnits.add(wu);
        return wu;
    }

    public List getWorkUnits() {
        return Collections.unmodifiableList(workUnits);
    }

    public WorkUnit getPrimaryWorkUnit() {
        return workUnits.get(0);
    }

    /**
     * All the {@link Executor}s that jointly execute a {@link Task} call this
     * method to synchronize on the start.
     */
    public void synchronizeStart() throws InterruptedException {
        startLatch.synchronize();
    }

    /**
     * All the {@link Executor}s that jointly execute a {@link Task} call this
     * method to synchronize on the end of the task.
     *
     * @throws InterruptedException If any of the member thread is interrupted
     * while waiting for other threads to join, all the member threads will
     * report {@link InterruptedException}.
     */
    public void synchronizeEnd(Queue.Executable executable, Throwable problems, long duration) throws InterruptedException {
        endLatch.synchronize();

        // the main thread will send a notification
        Executor e = Executor.currentExecutor();
        WorkUnit wu = e.getCurrentWorkUnit();
        if (wu.isMainWork()) {
            if (problems == null) {
                future.set(executable);
                e.getOwner().taskCompleted(e, task, duration);
            } else {
                future.set(problems);
                e.getOwner().taskCompletedWithProblems(e, task, duration, problems);
            }
        }
    }

    /**
     * When one of the work unit is aborted, call this method to abort all the
     * other work units.
     */
    public synchronized void abort(Throwable cause) {
        if (cause == null) {
            throw new IllegalArgumentException();
        }
        if (aborted != null) {
            return; // already aborted    
        }
        aborted = cause;
        startLatch.abort(cause);
        endLatch.abort(cause);

        Thread c = Thread.currentThread();
        for (WorkUnit wu : workUnits) {
            Executor e = wu.getExecutor();
            if (e != null && e != c) {
                e.interrupt();
            }
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy