1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package nl.toolforge.karma.core.vc.threads;
20
21 import nl.toolforge.karma.core.KarmaRuntimeException;
22 import nl.toolforge.karma.core.manifest.Manifest;
23 import nl.toolforge.karma.core.module.Module;
24 import org.apache.commons.logging.Log;
25 import org.apache.commons.logging.LogFactory;
26
27 import java.lang.reflect.Constructor;
28 import java.util.HashMap;
29 import java.util.Iterator;
30 import java.util.Map;
31
32 /***
33 * The ParallelRunner handles parallel <code>RunnerThread</code>s. This concept should be used when parallel read
34 * actions on version control repositories are possible to speed up the process of performing commands for
35 * <strong>each</strong> module in a manifest.
36 *
37 * @author D.A. Smedes
38 * @version $Id: ParallelRunner.java,v 1.10 2004/11/16 22:31:58 asmedes Exp $
39 */
40 public class ParallelRunner {
41
42 Log logger = LogFactory.getLog(ParallelRunner.class);
43
44 private Map results = null;
45
46 private Manifest manifest = null;
47 private RunnerThread[] threads = null;
48
49 private Class impl = null;
50
51 /***
52 * Initializes this <code>ParallelRunner</code> with the correct <code>Manifest</code>. Call {@link #execute()} or
53 * {@link #execute(int, long)} to start all threads.
54 *
55 * @param manifest The manifest.
56 * @param threadClass A Class instance, extending {@link Thread}.
57 */
58 public ParallelRunner(Manifest manifest, Class threadClass) {
59 this.manifest = manifest;
60 this.impl = threadClass;
61 }
62
63 /***
64 * Starts all threads, and processes the results. Results can be retrieved by calling {@link #retrieveResults}.
65 *
66 * @param delayInMilliseconds The delay in milliseconds between the start of each thread.
67 */
68 public void execute(long delayInMilliseconds) {
69 execute(0, delayInMilliseconds);
70 }
71
72
73 /***
74 * Starts all threads, and processes the results. Results can be retrieved by calling {@link #retrieveResults}. Note
75 * that no restriction is imposed on the amount of threads, and they are started as soon as possible.
76 *
77 * @see #execute(long)
78 * @see #execute(int, long)
79 */
80 public void execute() {
81 execute(0,0);
82 }
83
84
85 /***
86 * Starts all threads, and processes the results. Results can be retrieved by calling {@link #retrieveResults}.
87 *
88 * @param blockSize Determines the amount of threads that will be started in one block, with a delay of
89 * <code>delayInMilliseconds</code>. If all threads should be started as one block, a
90 * negative <code>blockSize</code> should be provided. When a positive blocksize is
91 * provided, a default delay of 1000 milliseconds is used between blocks. <b>Note</b>
92 * this feature is currently ignored.
93 * @param delayInMilliseconds The delay in milliseconds between threads in a block (or all threads if
94 * <code>blockSize</code> is negative.
95 */
96 public void execute(int blockSize, long delayInMilliseconds) {
97
98 Map modules = manifest.getAllModules();
99
100
101
102 results = new HashMap();
103
104
105
106 threads = new RunnerThread[modules.size()];
107
108 int index = 0;
109
110 logger.debug("Starting " + modules.size() + " threads, with a delay of " + delayInMilliseconds + " ms.");
111
112
113
114 for (Iterator i = modules.values().iterator(); i.hasNext();) {
115
116 try {
117 Constructor constructor = impl.getConstructor(new Class[]{Module.class});
118 threads[index] = (RunnerThread) constructor.newInstance(new Object[]{(Module) i.next()});
119 } catch (Exception e) {
120 logger.error(e);
121 throw new KarmaRuntimeException("Could not start a RunnerThread instance.");
122 }
123
124 threads[index].start();
125 try {
126 Thread.sleep(delayInMilliseconds);
127 } catch (InterruptedException e) {
128
129 }
130 index++;
131 }
132
133 for (int i = 0; i < threads.length; i++) {
134
135 try {
136 threads[i].join();
137 addResult(threads[i].getModule(), threads[i].getResult());
138 } catch (InterruptedException e) {
139 throw new KarmaRuntimeException(e.getMessage());
140 }
141 }
142 }
143
144
145 private void addResult(Module module, RunnerResult result) {
146 results.put(module, result);
147 }
148
149
150 /***
151 * Returns a map of {@link nl.toolforge.karma.core.vc.ModuleStatus} objects, each accessible by the the corresponding
152 * {@link nl.toolforge.karma.core.module.Module} instance.
153 *
154 * @return A map, containing {@link nl.toolforge.karma.core.vc.ModuleStatus} objects.
155 */
156 public Map retrieveResults() {
157 return results;
158 }
159
160 }