From e812a72d7db5c1f288254316057491bc8420796d Mon Sep 17 00:00:00 2001 From: Khai Do Date: Mon, 28 Jan 2013 16:59:21 -0800 Subject: [PATCH] Change to spawn a thread for each jenkins executor instead of just thread per jenkins nodes. Also added functionality to wait until a StartJobWorker can service a build request. This change eliminates putting builds on the jenkins queue. Now jobs are either running or it's not. The only cancel that makes sense is an abort (currently running jobs). AbstractWorkerThread.java - add comments, set worker id to name instead of random uuid ExectorWorkerThread.java - create thread of each jenkins executor GearmanPlugin.java - refactor to spawn a thread for every executor NodeAssignmentAction.java - provide access to label name StartJobWorker.java - make thread block execution until there is an available jenkins executor to run the job. Also set the gearman job return parameters. StopJobWorker.java - Set gearman job return parameters. Change-Id: I30cec8ca3900eb7976c38077383505ea73e744dd --- .../plugins/gearman/AbstractWorkerThread.java | 10 +++--- .../plugins/gearman/ExecutorWorkerThread.java | 16 +++------ .../hudson/plugins/gearman/GearmanPlugin.java | 20 ++++++----- .../plugins/gearman/StartJobWorker.java | 33 ++++++++++++++++--- .../hudson/plugins/gearman/StopJobWorker.java | 18 +++++++--- 5 files changed, 64 insertions(+), 33 deletions(-) diff --git a/src/main/java/hudson/plugins/gearman/AbstractWorkerThread.java b/src/main/java/hudson/plugins/gearman/AbstractWorkerThread.java index 647bec1..c43e3b2 100644 --- a/src/main/java/hudson/plugins/gearman/AbstractWorkerThread.java +++ b/src/main/java/hudson/plugins/gearman/AbstractWorkerThread.java @@ -19,7 +19,6 @@ package hudson.plugins.gearman; import java.util.Date; -import java.util.UUID; import org.gearman.common.GearmanNIOJobServerConnection; import org.gearman.worker.GearmanWorker; @@ -28,8 +27,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -/* - * Thread to run gearman worker +/** + * Base object for gearman worker threads + * + * + * @author Khai Do */ public abstract class AbstractWorkerThread implements Runnable { @@ -110,7 +112,7 @@ public abstract class AbstractWorkerThread implements Runnable { if (!worker.isRunning()) { logger.info("Starting Worker "+ name +" ("+new Date().toString()+")"); - worker.setWorkerID(UUID.randomUUID().toString()); + worker.setWorkerID(name); worker.addServer(conn); worker.work(); } diff --git a/src/main/java/hudson/plugins/gearman/ExecutorWorkerThread.java b/src/main/java/hudson/plugins/gearman/ExecutorWorkerThread.java index b1d8e6a..4c98e5c 100644 --- a/src/main/java/hudson/plugins/gearman/ExecutorWorkerThread.java +++ b/src/main/java/hudson/plugins/gearman/ExecutorWorkerThread.java @@ -44,13 +44,12 @@ public class ExecutorWorkerThread extends AbstractWorkerThread{ private final Node node; - public ExecutorWorkerThread(String host, int port, String nodeName){ - super(host, port, nodeName); - this.node = findNode(nodeName); - + // constructor + public ExecutorWorkerThread(String host, int port, String name, Node node) { + super(host, port, name); + this.node = node; } - /** * This function finds the node with the corresponding node name Returns the * node if found, otherwise returns null @@ -75,11 +74,6 @@ public class ExecutorWorkerThread extends AbstractWorkerThread{ return myNode; } - public ExecutorWorkerThread(String host, int port, String name, Node node){ - super(host, port, name); - this.node = node; - } - /** * This function tokenizes the labels in a label string @@ -183,7 +177,7 @@ public class ExecutorWorkerThread extends AbstractWorkerThread{ // "build:projectName" on all nodes String jobFunctionName = "build:" + projectName; logger.info("Registering job " + jobFunctionName + " on " - + this.node.getNodeName()); + + name); worker.registerFunctionFactory(new CustomGearmanFunctionFactory( jobFunctionName, StartJobWorker.class.getName(), project, this.node)); diff --git a/src/main/java/hudson/plugins/gearman/GearmanPlugin.java b/src/main/java/hudson/plugins/gearman/GearmanPlugin.java index 11da0d2..953d4ec 100644 --- a/src/main/java/hudson/plugins/gearman/GearmanPlugin.java +++ b/src/main/java/hudson/plugins/gearman/GearmanPlugin.java @@ -165,8 +165,8 @@ public class GearmanPlugin extends Builder { /* * Purpose here is to create a 1:1 mapping of 'gearman - * worker':'jenkins node' then use the gearman worker to execute - * builds on that jenkins node + * worker':'jenkins executor' then use the gearman worker to execute + * builds on that jenkins nodes */ List nodes = jenkins.getNodes(); @@ -177,12 +177,16 @@ public class GearmanPlugin extends Builder { for (Node node : nodes) { Computer c = node.toComputer(); if (c.isOnline()) { - // create a gearman executor for every node - gwt = new ExecutorWorkerThread(host, port, - node.getNodeName()); - gwt.registerJobs(); - gwt.start(); - gewtHandles.push(gwt); + int numExecutors = c.getExecutors().size(); + for (int i=0; i future = project.scheduleBuild2(0, new Cause.UserIdCause(), actions); - GearmanJobResult gjr = new GearmanJobResultImpl(this.jobHandle, true, - decoded.toString().getBytes(), new byte[0], new byte[0], 0, 0); + String jobResultMsg = ""; + boolean jobResult = false; + + try { + future.get(); + jobResult = true; + jobResultMsg = "Build completed on " + node.getNodeName() + + " with UUID " + uuid + " and build params " + buildParams; + } catch (InterruptedException e1) { + // TODO Auto-generated catch block + jobResultMsg = "Build interrupted on " + node.getNodeName(); + e1.printStackTrace(); + } catch (ExecutionException e1) { + // TODO Auto-generated catch block + jobResultMsg = "Build failed on " + node.getNodeName(); + } + + GearmanJobResult gjr = new GearmanJobResultImpl(this.jobHandle, jobResult, + jobResultMsg.getBytes(), new byte[0], new byte[0], 0, 0); return gjr; } } diff --git a/src/main/java/hudson/plugins/gearman/StopJobWorker.java b/src/main/java/hudson/plugins/gearman/StopJobWorker.java index e4f4622..f734788 100644 --- a/src/main/java/hudson/plugins/gearman/StopJobWorker.java +++ b/src/main/java/hudson/plugins/gearman/StopJobWorker.java @@ -19,14 +19,12 @@ package hudson.plugins.gearman; -import hudson.model.Action; import hudson.model.Computer; import hudson.model.Executor; import hudson.model.Label; import hudson.model.Node; import hudson.model.Queue; import hudson.model.Queue.Executable; -import hudson.model.Queue.Task; import hudson.model.queue.SubTask; import java.io.UnsupportedEncodingException; @@ -92,12 +90,22 @@ public class StopJobWorker extends AbstractGearmanFunction { } + // Cancel jenkins jobs that contain matching uuid from client - boolean canceled = cancelBuild(inUuid); + + boolean jobResult = cancelBuild(inUuid); + String jobResultMsg = null; + if (jobResult){ + jobResultMsg = "Canceled jenkins build " + inUuid; + + } else { + jobResultMsg = "Could not cancel build " + inUuid; + + } - GearmanJobResult gjr = new GearmanJobResultImpl(this.jobHandle, true, - decoded.toString().getBytes(), new byte[0], new byte[0], 0, 0); + GearmanJobResult gjr = new GearmanJobResultImpl(this.jobHandle, jobResult, + jobResultMsg.getBytes(), new byte[0], new byte[0], 0, 0); return gjr; }