File D:\maven-qcr-plugin-testsunitaires\qcr4java\jenkins-master\target\site\qc\core\src\main\java\hudson\model\ViewJob.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.model;
25
26 import jenkins.model.Jenkins;
27 import org.kohsuke.stapler.StaplerRequest;
28 import org.kohsuke.stapler.StaplerResponse;
29
30 import javax.servlet.ServletException;
31 import java.io.IOException;
32 import java.util.LinkedHashSet;
33 import java.util.SortedMap;
34
35 import hudson.model.Descriptor.FormException;
36
37 /**
38 * {@link Job} that monitors activities that happen outside Hudson,
39 * which requires occasional batch reload activity to obtain the up-to-date information.
40 *
41 * <p>
42 * This can be used as a base class to derive custom {@link Job} type.
43 *
44 * @author Kohsuke Kawaguchi
45 */
46 public abstract class ViewJob<JobT extends ViewJob<JobT,RunT>, RunT extends Run<JobT,RunT>>
47 extends Job<JobT,RunT> {
48
49 /**
50 * We occasionally update the list of {@link Run}s from a file system.
51 * The next scheduled update time.
52 */
53 private transient long nextUpdate = 0;
54
55 /**
56 * All {@link Run}s. Copy-on-write semantics.
57 */
58 protected transient /*almost final*/ RunMap<RunT> runs = new RunMap<RunT>();
59
60 private transient boolean notLoaded = true;
61
62 /**
63 * If the reloading of runs are in progress (in another thread,
64 * set to true.)
65 */
66 private transient volatile boolean reloadingInProgress;
67
68 /**
69 * {@link ExternalJob}s that need to be reloaded.
70 *
71 * This is a set, so no {@link ExternalJob}s are scheduled twice, yet
72 * it's order is predictable, avoiding starvation.
73 */
74 private static final LinkedHashSet<ViewJob> reloadQueue = new LinkedHashSet<ViewJob>();
75 /*package*/ static final Thread reloadThread = new ReloadThread();
76 static {
77 reloadThread.start();
78 }
79
80 /**
81 * @deprecated as of 1.390
82 */
83 protected ViewJob(Jenkins parent, String name) {
84 super(parent,name);
85 }
86
87 protected ViewJob(ItemGroup parent, String name) {
88 super(parent,name);
89 }
90
91 public boolean isBuildable() {
92 return false;
93 }
94
95 @Override
96 public void onLoad(ItemGroup<? extends Item> parent, String name) throws IOException {
97 super.onLoad(parent, name);
98 notLoaded = true;
99 }
100
101 protected SortedMap<Integer,RunT> _getRuns() {
102 if(notLoaded || runs==null) {
103 // if none is loaded yet, do so immediately.
104 synchronized(this) {
105 if(runs==null)
106 runs = new RunMap<RunT>();
107 if(notLoaded) {
108 notLoaded = false;
109 _reload();
110 }
111 }
112 }
113 if(nextUpdate<System.currentTimeMillis()) {
114 if(!reloadingInProgress) {
115 // schedule a new reloading operation.
116 // we don't want to block the current thread,
117 // so reloading is done asynchronously.
118 reloadingInProgress = true;
119 synchronized(reloadQueue) {
120 reloadQueue.add(this);
121 reloadQueue.notify();
122 }
123 }
124 }
125 return runs;
126 }
127
128 public void removeRun(RunT run) {
129 // reload the info next time
130 nextUpdate = 0;
131 }
132
133 private void _reload() {
134 try {
135 reload();
136 } finally {
137 reloadingInProgress = false;
138 nextUpdate = reloadPeriodically ? System.currentTimeMillis()+1000*60 : Long.MAX_VALUE;
139 }
140 }
141
142 /**
143 * Reloads the list of {@link Run}s. This operation can take a long time.
144 *
145 * <p>
146 * The loaded {@link Run}s should be set to {@link #runs}.
147 */
148 protected abstract void reload();
149
150 @Override
151 protected void submit( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException, FormException {
152 super.submit(req,rsp);
153 // make sure to reload to reflect this config change.
154 nextUpdate = 0;
155 }
156
157
158 /**
159 * Thread that reloads the {@link Run}s.
160 */
161 private static final class ReloadThread extends Thread {
162 private ReloadThread() {
163 setName("ViewJob reload thread");
164 }
165
166 private ViewJob getNext() throws InterruptedException {
167 synchronized(reloadQueue) {
168 // reload operations might eat InterruptException,
169 // so check the status every so often
170 while(reloadQueue.isEmpty() && !terminating())
171 reloadQueue.wait(60*1000);
172 if(terminating())
173 throw new InterruptedException(); // terminate now
174 ViewJob job = reloadQueue.iterator().next();
175 reloadQueue.remove(job);
176 return job;
177 }
178 }
179
180 private boolean terminating() {
181 return Jenkins.getInstance().isTerminating();
182 }
183
184 @Override
185 public void run() {
186 while (!terminating()) {
187 try {
188 getNext()._reload();
189 } catch (InterruptedException e) {
190 // treat this as a death signal
191 return;
192 } catch (Throwable t) {
193 // otherwise ignore any error
194 t.printStackTrace();
195 }
196 }
197 }
198 }
199
200 // private static final Logger logger = Logger.getLogger(ViewJob.class.getName());
201
202 /**
203 * In the very old version of Hudson, an external job submission was just creating files on the file system,
204 * so we needed to periodically reload the jobs from a file system to pick up new records.
205 *
206 * <p>
207 * We then switched to submission via HTTP, so this reloading is no longer necessary, so only do this
208 * when explicitly requested.
209 *
210 */
211 public static boolean reloadPeriodically = Boolean.getBoolean(ViewJob.class.getName()+".reloadPeriodically");
212 }
213