KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > hudson > model > Computer


1 package hudson.model;
2
3 import hudson.EnvVars;
4 import hudson.remoting.Callable;
5 import hudson.remoting.VirtualChannel;
6 import hudson.util.DaemonThreadFactory;
7 import hudson.util.RunList;
8 import org.kohsuke.stapler.StaplerRequest;
9 import org.kohsuke.stapler.StaplerResponse;
10
11 import javax.servlet.ServletException JavaDoc;
12 import java.io.IOException JavaDoc;
13 import java.util.ArrayList JavaDoc;
14 import java.util.List JavaDoc;
15 import java.util.Map JavaDoc;
16 import java.util.TreeMap JavaDoc;
17 import java.util.Collections JavaDoc;
18 import java.util.concurrent.ExecutorService JavaDoc;
19 import java.util.concurrent.Executors JavaDoc;
20
21 /**
22  * Represents a set of {@link Executor}s on the same computer.
23  *
24  * <p>
25  * {@link Executor}s on one {@link Computer} are transparently interchangeable
26  * (that is the definition of {@link Computer}.)
27  *
28  * <p>
29  * This object is related to {@link Node} but they have some significant difference.
30  * {@link Computer} primarily works as a holder of {@link Executor}s, so
31  * if a {@link Node} is configured (probably temporarily) with 0 executors,
32  * you won't have a {@link Computer} object for it.
33  *
34  * Also, even if you remove a {@link Node}, it takes time for the corresponding
35  * {@link Computer} to be removed, if some builds are already in progress on that
36  * node.
37  *
38  * <p>
39  * This object also serves UI (since {@link Node} is an interface and can't have
40  * related side pages.)
41  *
42  * @author Kohsuke Kawaguchi
43  */

44 public abstract class Computer implements ModelObject {
45     private final List<Executor> executors = new ArrayList JavaDoc<Executor>();
46
47     private int numExecutors;
48
49     /**
50      * True if Hudson shouldn't start new builds on this node.
51      */

52     private boolean temporarilyOffline;
53
54     /**
55      * {@link Node} object may be created and deleted independently
56      * from this object.
57      */

58     protected String JavaDoc nodeName;
59
60     public Computer(Node node) {
61         assert node.getNumExecutors()!=0 : "Computer created with 0 executors";
62         setNode(node);
63     }
64
65     /**
66      * Gets the channel that can be used to run a program on this computer.
67      *
68      * @return
69      * never null when {@link #isOffline()}==false.
70      */

71     public abstract VirtualChannel getChannel();
72
73     /**
74      * If {@link #getChannel()}==null, attempts to relaunch the slave agent.
75      */

76     public abstract void doLaunchSlaveAgent( StaplerRequest req, StaplerResponse rsp ) throws IOException JavaDoc, ServletException JavaDoc;
77
78     /**
79      * Number of {@link Executor}s that are configured for this computer.
80      *
81      * <p>
82      * When this value is decreased, it is temporarily possible
83      * for {@link #executors} to have a larger number than this.
84      */

85     // ugly name to let EL access this
86
public int getNumExecutors() {
87         return numExecutors;
88     }
89
90     /**
91      * Returns the {@link Node} that this computer represents.
92      */

93     public Node getNode() {
94         if(nodeName==null)
95             return Hudson.getInstance();
96         return Hudson.getInstance().getSlave(nodeName);
97     }
98
99     public boolean isOffline() {
100         return temporarilyOffline || getChannel()==null;
101     }
102
103     /**
104      * Returns true if this computer is supposed to be launched via JNLP.
105      */

106     public boolean isJnlpAgent() {
107         return false;
108     }
109
110     /**
111      * Returns true if this node is marked temporarily offline by the user.
112      *
113      * <p>
114      * In contrast, {@link #isOffline()} represents the actual online/offline
115      * state. For example, this method may return false while {@link #isOffline()}
116      * returns true if the slave agent failed to launch.
117      *
118      * @deprecated
119      * You should almost always want {@link #isOffline()}.
120      * This method is marked as deprecated to warn people when they
121      * accidentally call this method.
122      */

123     public boolean isTemporarilyOffline() {
124         return temporarilyOffline;
125     }
126
127     public void setTemporarilyOffline(boolean temporarilyOffline) {
128         this.temporarilyOffline = temporarilyOffline;
129         Hudson.getInstance().getQueue().scheduleMaintenance();
130     }
131
132     public String JavaDoc getIcon() {
133         if(isOffline())
134             return "computer-x.gif";
135         else
136             return "computer.gif";
137     }
138
139     public String JavaDoc getDisplayName() {
140         return nodeName;
141     }
142
143     public String JavaDoc getUrl() {
144         return "computer/"+getDisplayName()+"/";
145     }
146
147     /**
148      * Returns projects that are tied on this node.
149      */

150     public List<Project> getTiedJobs() {
151         List<Project> r = new ArrayList JavaDoc<Project>();
152         for( Project p : Hudson.getInstance().getProjects() ) {
153             if(p.getAssignedNode()==getNode())
154                 r.add(p);
155         }
156         return r;
157     }
158
159     /**
160      * Called to notify {@link Computer} that its corresponding {@link Node}
161      * configuration is updated.
162      */

163     protected void setNode(Node node) {
164         assert node!=null;
165         if(node instanceof Slave)
166             this.nodeName = node.getNodeName();
167         else
168             this.nodeName = null;
169
170         setNumExecutors(node.getNumExecutors());
171     }
172
173     /**
174      * Called to notify {@link Computer} that it will be discarded.
175      */

176     protected void kill() {
177         setNumExecutors(0);
178     }
179
180     private synchronized void setNumExecutors(int n) {
181         this.numExecutors = n;
182
183         // send signal to all idle executors to potentially kill them off
184
for( Executor e : executors )
185             if(e.getCurrentBuild()==null)
186                 e.interrupt();
187
188         // if the number is increased, add new ones
189
while(executors.size()<numExecutors)
190             executors.add(new Executor(this));
191     }
192
193     /**
194      * Returns the number of idle {@link Executor}s that can start working immediately.
195      */

196     public synchronized int countIdle() {
197         int n = 0;
198         for (Executor e : executors) {
199             if(e.isIdle())
200                 n++;
201         }
202         return n;
203     }
204
205     /**
206      * Gets the read-only view of all {@link Executor}s.
207      */

208     public synchronized List<Executor> getExecutors() {
209         return new ArrayList JavaDoc<Executor>(executors);
210     }
211
212     /**
213      * Called by {@link Executor} to kill excessive executors from this computer.
214      */

215     /*package*/ synchronized void removeExecutor(Executor e) {
216         executors.remove(e);
217         if(executors.isEmpty())
218             Hudson.getInstance().removeComputer(this);
219     }
220
221     /**
222      * Interrupt all {@link Executor}s.
223      */

224     public synchronized void interrupt() {
225         for (Executor e : executors) {
226             e.interrupt();
227         }
228     }
229
230     /**
231      * Gets the system properties of the JVM on this computer.
232      * If this is the master, it returns the system property of the master computer.
233      */

234     public Map JavaDoc<Object JavaDoc,Object JavaDoc> getSystemProperties() throws IOException JavaDoc, InterruptedException JavaDoc {
235         return getChannel().call(new GetSystemProperties());
236     }
237
238     private static final class GetSystemProperties implements Callable<Map JavaDoc<Object JavaDoc,Object JavaDoc>,RuntimeException JavaDoc> {
239         public Map JavaDoc<Object JavaDoc,Object JavaDoc> call() {
240             return new TreeMap JavaDoc<Object JavaDoc,Object JavaDoc>(System.getProperties());
241         }
242         private static final long serialVersionUID = 1L;
243     }
244
245     /**
246      * Gets the environment variables of the JVM on this computer.
247      * If this is the master, it returns the system property of the master computer.
248      */

249     public Map JavaDoc<String JavaDoc,String JavaDoc> getEnvVars() throws IOException JavaDoc, InterruptedException JavaDoc {
250         VirtualChannel channel = getChannel();
251         if(channel==null)
252             return Collections.singletonMap("N/A","N/A");
253         return channel.call(new GetEnvVars());
254     }
255
256     private static final class GetEnvVars implements Callable<Map JavaDoc<String JavaDoc,String JavaDoc>,RuntimeException JavaDoc> {
257         public Map JavaDoc<String JavaDoc,String JavaDoc> call() {
258             return new TreeMap JavaDoc<String JavaDoc,String JavaDoc>(EnvVars.masterEnvVars);
259         }
260         private static final long serialVersionUID = 1L;
261     }
262
263
264     public static final ExecutorService JavaDoc threadPoolForRemoting = Executors.newCachedThreadPool(new DaemonThreadFactory());
265
266 //
267
//
268
// UI
269
//
270
//
271
public void doRssAll( StaplerRequest req, StaplerResponse rsp ) throws IOException JavaDoc, ServletException JavaDoc {
272         rss(req, rsp, " all builds", new RunList(getTiedJobs()));
273     }
274     public void doRssFailed( StaplerRequest req, StaplerResponse rsp ) throws IOException JavaDoc, ServletException JavaDoc {
275         rss(req, rsp, " failed builds", new RunList(getTiedJobs()).failureOnly());
276     }
277     private void rss(StaplerRequest req, StaplerResponse rsp, String JavaDoc suffix, RunList runs) throws IOException JavaDoc, ServletException JavaDoc {
278         RSS.forwardToRss(getDisplayName()+ suffix, getUrl(),
279             runs.newBuilds(), Run.FEED_ADAPTER, req, rsp );
280     }
281
282     public void doToggleOffline( StaplerRequest req, StaplerResponse rsp ) throws IOException JavaDoc, ServletException JavaDoc {
283         if(!Hudson.adminCheck(req,rsp))
284             return;
285
286         setTemporarilyOffline(!temporarilyOffline);
287         rsp.forwardToPreviousPage(req);
288     }
289 }
290
Popular Tags