File D:\maven-qcr-plugin-testsunitaires\qcr4java\jenkins-master\target\site\qc\core\src\main\java\hudson\node_monitors\AbstractNodeMonitorDescriptor.java.html

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 */
24 package hudson.node_monitors;
25
26 import hudson.model.Computer;
27 import hudson.model.Descriptor;
28 import jenkins.model.Jenkins;
29 import hudson.model.ComputerSet;
30 import hudson.model.AdministrativeMonitor;
31 import hudson.triggers.Trigger;
32 import hudson.triggers.SafeTimerTask;
33 import hudson.slaves.OfflineCause;
34
35 import java.io.IOException;
36 import java.util.Date;
37 import java.util.HashMap;
38 import java.util.Map;
39 import java.util.Timer;
40 import java.util.logging.Level;
41 import java.util.logging.Logger;
42
43 /**
44 * Convenient base class for common {@link NodeMonitor} implementation
45 * where the "monitoring" consists of executing something periodically on every node
46 * and taking some action based on its result.
47 *
48 * <p>
49 * "T" represents the the result of the monitoring.
50 *
51 * @author Kohsuke Kawaguchi
52 */
53 public abstract class AbstractNodeMonitorDescriptor<T> extends Descriptor<NodeMonitor> {
54 protected AbstractNodeMonitorDescriptor() {
55 this(HOUR);
56 }
57
58 protected AbstractNodeMonitorDescriptor(long interval) {
59 schedule(interval);
60
61 }
62
63 protected AbstractNodeMonitorDescriptor(Class<? extends NodeMonitor> clazz) {
64 this(clazz,HOUR);
65 }
66
67 protected AbstractNodeMonitorDescriptor(Class<? extends NodeMonitor> clazz, long interval) {
68 super(clazz);
69
70 schedule(interval);
71 }
72
73 private void schedule(long interval) {
74 Timer timer = Trigger.timer;
75 if (timer != null) {
76 timer.scheduleAtFixedRate(new SafeTimerTask() {
77 public void doRun() {
78 triggerUpdate();
79 }
80 }, interval, interval);
81 }
82 }
83
84 /**
85 * Represents the last record of the update
86 */
87 private volatile Record record = null;
88
89 /**
90 * Represents the update activity in progress.
91 */
92 private volatile Record inProgress = null;
93
94 /**
95 * Performs monitoring of the given computer object.
96 * This method is invoked periodically to perform the monitoring of the computer.
97 *
98 * @return
99 * Application-specific value that represents the observed monitoring value
100 * on the given node. This value will be returned from the {@link #get(Computer)} method.
101 * If null is returned, it will be interpreted as "no observed value." This is
102 * convenient way of abandoning the observation on a particular computer,
103 * whereas {@link IOException} is useful for indicating a hard error that needs to be
104 * corrected.
105 */
106 protected abstract T monitor(Computer c) throws IOException,InterruptedException;
107
108 /**
109 * Obtains the monitoring result currently available, or null if no data is available.
110 *
111 * <p>
112 * If no data is available, a background task to collect data will be started.
113 */
114 public T get(Computer c) {
115 if(record==null) {
116 // if this is the first time, schedule the check now
117 if(inProgress==null) {
118 synchronized(this) {
119 if(inProgress==null)
120 new Record().start();
121 }
122 }
123 return null;
124 }
125 return record.data.get(c);
126 }
127
128 /**
129 * Is this monitor currently ignored?
130 */
131 public boolean isIgnored() {
132 NodeMonitor m = ComputerSet.getMonitors().get(this);
133 return m==null || m.isIgnored();
134 }
135
136 /**
137 * Utility method to mark the computer online for derived classes.
138 *
139 * @return true
140 * if the node was actually taken online by this act (as opposed to us deciding not to do it,
141 * or the computer was already online.)
142 */
143 protected boolean markOnline(Computer c) {
144 if(isIgnored() || c.isOnline()) return false; // noop
145 c.setTemporarilyOffline(false,null);
146 return true;
147 }
148
149 /**
150 * Utility method to mark the computer offline for derived classes.
151 *
152 * @return true
153 * if the node was actually taken offline by this act (as opposed to us deciding not to do it,
154 * or the computer already marked offline.)
155 */
156 protected boolean markOffline(Computer c, OfflineCause oc) {
157 if(isIgnored() || c.isTemporarilyOffline()) return false; // noop
158
159 c.setTemporarilyOffline(true, oc);
160
161 // notify the admin
162 MonitorMarkedNodeOffline no = AdministrativeMonitor.all().get(MonitorMarkedNodeOffline.class);
163 if(no!=null)
164 no.active = true;
165 return true;
166 }
167
168 /**
169 * @deprecated as of 1.320
170 * Use {@link #markOffline(Computer, OfflineCause)} to specify the cause.
171 */
172 protected boolean markOffline(Computer c) {
173 return markOffline(c,null);
174 }
175
176 /**
177 * @see NodeMonitor#triggerUpdate()
178 */
179 /*package*/ Thread triggerUpdate() {
180 Record t = new Record();
181 t.start();
182 return t;
183 }
184
185 /**
186 * Thread that monitors nodes, as well as the data structure to record
187 * the result.
188 */
189 private final class Record extends Thread {
190 /**
191 * Last computed monitoring result.
192 */
193 private final Map<Computer,T> data = new HashMap<Computer,T>();
194
195 public Record() {
196 super("Monitoring thread for "+getDisplayName()+" started on "+new Date());
197 synchronized(AbstractNodeMonitorDescriptor.this) {
198 if(inProgress!=null) {
199 // maybe it got stuck?
200 LOGGER.warning("Previous "+getDisplayName()+" monitoring activity still in progress. Interrupting");
201 inProgress.interrupt();
202 }
203 inProgress = this;
204 }
205 }
206
207 @Override
208 public void run() {
209 long startTime = System.currentTimeMillis();
210 String oldName = getName();
211
212 for( Computer c : Jenkins.getInstance().getComputers() ) {
213 try {
214 setName("Monitoring "+c.getDisplayName()+" for "+getDisplayName());
215
216 if(c.getChannel()==null)
217 data.put(c,null);
218 else
219 data.put(c,monitor(c));
220 } catch (IOException e) {
221 LOGGER.log(Level.WARNING, "Failed to monitor "+c.getDisplayName()+" for "+getDisplayName(), e);
222 } catch (InterruptedException e) {
223 LOGGER.log(Level.WARNING,"Node monitoring "+c.getDisplayName()+" for "+getDisplayName()+" aborted.",e);
224 }
225 }
226 setName(oldName);
227
228 synchronized(AbstractNodeMonitorDescriptor.this) {
229 assert inProgress==this;
230 inProgress = null;
231 record = this;
232 }
233
234 LOGGER.fine("Node monitoring "+getDisplayName()+" completed in "+(System.currentTimeMillis()-startTime)+"ms");
235 }
236 }
237
238 private final Logger LOGGER = Logger.getLogger(getClass().getName());
239
240 private static final long HOUR = 1000*60*60L;
241 }
242