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

1 /*
2 * The MIT License
3 *
4 * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Stephen Connolly
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.slaves;
25
26 import hudson.ExtensionPoint;
27 import hudson.Util;
28 import hudson.DescriptorExtensionList;
29 import hudson.Extension;
30 import hudson.model.*;
31 import hudson.model.Queue.*;
32 import hudson.util.DescriptorList;
33 import java.util.Collections;
34 import java.util.HashMap;
35 import jenkins.model.Jenkins;
36 import org.kohsuke.stapler.DataBoundConstructor;
37
38 import java.util.logging.Level;
39 import java.util.logging.Logger;
40
41 /**
42 * Controls when to take {@link Computer} offline, bring it back online, or even to destroy it.
43 *
44 * @author Stephen Connolly
45 * @author Kohsuke Kawaguchi
46 */
47 public abstract class RetentionStrategy<T extends Computer> extends AbstractDescribableImpl<RetentionStrategy<?>> implements ExtensionPoint {
48
49 /**
50 * This method will be called periodically to allow this strategy to decide what to do with it's owning slave.
51 *
52 * @param c {@link Computer} for which this strategy is assigned. This computer may be online or offline.
53 * This object also exposes a bunch of properties that the callee can use to decide what action to take.
54 * @return The number of minutes after which the strategy would like to be checked again. The strategy may be
55 * rechecked earlier or later that this!
56 */
57 public abstract long check(T c);
58
59 /**
60 * This method is called to determine whether manual launching of the slave is allowed at this point in time.
61 * @param c {@link Computer} for which this strategy is assigned. This computer may be online or offline.
62 * This object also exposes a bunch of properties that the callee can use to decide if manual launching is
63 * allowed at this time.
64 * @return {@code true} if manual launching of the slave is allowed at this point in time.
65 */
66 public boolean isManualLaunchAllowed(T c) {
67 return true;
68 }
69
70 /**
71 * Called when a new {@link Computer} object is introduced (such as when Hudson started, or when
72 * a new slave is added.)
73 *
74 * <p>
75 * The default implementation of this method delegates to {@link #check(Computer)},
76 * but this allows {@link RetentionStrategy} to distinguish the first time invocation from the rest.
77 *
78 * @since 1.275
79 */
80 public void start(T c) {
81 check(c);
82 }
83
84 /**
85 * Returns all the registered {@link RetentionStrategy} descriptors.
86 */
87 public static DescriptorExtensionList<RetentionStrategy<?>,Descriptor<RetentionStrategy<?>>> all() {
88 return (DescriptorExtensionList) Jenkins.getInstance().getDescriptorList(RetentionStrategy.class);
89 }
90
91 /**
92 * All registered {@link RetentionStrategy} implementations.
93 * @deprecated as of 1.286
94 * Use {@link #all()} for read access, and {@link Extension} for registration.
95 */
96 public static final DescriptorList<RetentionStrategy<?>> LIST = new DescriptorList<RetentionStrategy<?>>((Class)RetentionStrategy.class);
97
98 /**
99 * Dummy instance that doesn't do any attempt to retention.
100 */
101 public static final RetentionStrategy<Computer> NOOP = new RetentionStrategy<Computer>() {
102 public long check(Computer c) {
103 return 60;
104 }
105
106 @Override
107 public void start(Computer c) {
108 c.connect(false);
109 }
110
111 @Override
112 public Descriptor<RetentionStrategy<?>> getDescriptor() {
113 return DESCRIPTOR;
114 }
115
116 private final DescriptorImpl DESCRIPTOR = new DescriptorImpl();
117
118 class DescriptorImpl extends Descriptor<RetentionStrategy<?>> {
119 public String getDisplayName() {
120 return "";
121 }
122 }
123 };
124
125 /**
126 * Convenient singleton instance, since this {@link RetentionStrategy} is stateless.
127 */
128 public static final Always INSTANCE = new Always();
129
130 /**
131 * {@link RetentionStrategy} that tries to keep the node online all the time.
132 */
133 public static class Always extends RetentionStrategy<SlaveComputer> {
134 /**
135 * Constructs a new Always.
136 */
137 @DataBoundConstructor
138 public Always() {
139 }
140
141 public long check(SlaveComputer c) {
142 if (c.isOffline() && !c.isConnecting() && c.isLaunchSupported())
143 c.tryReconnect();
144 return 1;
145 }
146
147 @Extension(ordinal=100)
148 public static class DescriptorImpl extends Descriptor<RetentionStrategy<?>> {
149 public String getDisplayName() {
150 return Messages.RetentionStrategy_Always_displayName();
151 }
152 }
153 }
154
155 /**
156 * {@link hudson.slaves.RetentionStrategy} that tries to keep the node offline when not in use.
157 */
158 public static class Demand extends RetentionStrategy<SlaveComputer> {
159
160 private static final Logger logger = Logger.getLogger(Demand.class.getName());
161
162 /**
163 * The delay (in minutes) for which the slave must be in demand before tring to launch it.
164 */
165 private final long inDemandDelay;
166
167 /**
168 * The delay (in minutes) for which the slave must be idle before taking it offline.
169 */
170 private final long idleDelay;
171
172 @DataBoundConstructor
173 public Demand(long inDemandDelay, long idleDelay) {
174 this.inDemandDelay = Math.max(0, inDemandDelay);
175 this.idleDelay = Math.max(1, idleDelay);
176 }
177
178 /**
179 * Getter for property 'inDemandDelay'.
180 *
181 * @return Value for property 'inDemandDelay'.
182 */
183 public long getInDemandDelay() {
184 return inDemandDelay;
185 }
186
187 /**
188 * Getter for property 'idleDelay'.
189 *
190 * @return Value for property 'idleDelay'.
191 */
192 public long getIdleDelay() {
193 return idleDelay;
194 }
195
196 public synchronized long check(SlaveComputer c) {
197 if (c.isOffline() && c.isLaunchSupported()) {
198 final HashMap<Computer, Integer> availableComputers = new HashMap<Computer, Integer>();
199 for (Computer o : Jenkins.getInstance().getComputers()) {
200 if ((o.isOnline() || o.isConnecting()) && o.isPartiallyIdle()) {
201 final int idleExecutors = o.countIdle();
202 if (idleExecutors>0)
203 availableComputers.put(o, idleExecutors);
204 }
205 }
206
207 boolean needComputer = false;
208 long demandMilliseconds = 0;
209 for (Queue.BuildableItem item : Queue.getInstance().getBuildableItems()) {
210 // can any of the currently idle executors take this task?
211 // assume the answer is no until we can find such an executor
212 boolean needExecutor = true;
213 for (Computer o : Collections.unmodifiableSet(availableComputers.keySet())) {
214 if (o.getNode().canTake(item) == null) {
215 needExecutor = false;
216 final int availableExecutors = availableComputers.remove(o);
217 if (availableExecutors > 1) {
218 availableComputers.put(o, availableExecutors - 1);
219 } else {
220 availableComputers.remove(o);
221 }
222 break;
223 }
224 }
225
226 // this 'item' cannot be built by any of the existing idle nodes, but it can be built by 'c'
227 if (needExecutor && c.getNode().canTake(item) == null) {
228 demandMilliseconds = System.currentTimeMillis() - item.buildableStartMilliseconds;
229 needComputer = demandMilliseconds > inDemandDelay * 1000 * 60 /*MINS->MILLIS*/;
230 break;
231 }
232 }
233
234 if (needComputer) {
235 // we've been in demand for long enough
236 logger.log(Level.INFO, "Launching computer {0} as it has been in demand for {1}",
237 new Object[]{c.getName(), Util.getTimeSpanString(demandMilliseconds)});
238 c.connect(false);
239 }
240 } else if (c.isIdle()) {
241 final long idleMilliseconds = System.currentTimeMillis() - c.getIdleStartMilliseconds();
242 if (idleMilliseconds > idleDelay * 1000 * 60 /*MINS->MILLIS*/) {
243 // we've been idle for long enough
244 logger.log(Level.INFO, "Disconnecting computer {0} as it has been idle for {1}",
245 new Object[]{c.getName(), Util.getTimeSpanString(idleMilliseconds)});
246 c.disconnect(OfflineCause.create(Messages._RetentionStrategy_Demand_OfflineIdle()));
247 }
248 }
249 return 1;
250 }
251
252 @Extension
253 public static class DescriptorImpl extends Descriptor<RetentionStrategy<?>> {
254 public String getDisplayName() {
255 return Messages.RetentionStrategy_Demand_displayName();
256 }
257 }
258 }
259 }
260