Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 28a31ae2d5a57b03186e61a4f3d77ace97458701 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
/*******************************************************************************
 * Copyright (c) 2006, 2007 Intel Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 * Intel Corporation - Initial API and implementation
 *******************************************************************************/

package org.eclipse.cdt.managedbuilder.internal.buildmodel;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.eclipse.cdt.managedbuilder.buildmodel.IBuildCommand;
import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager;
import org.eclipse.cdt.managedbuilder.envvar.IBuildEnvironmentVariable;
import org.eclipse.cdt.managedbuilder.envvar.IEnvironmentVariableProvider;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;

/**
 * This class implements process pool management for internal builder 
 *
 * NOTE: This class is subject to change and discuss, 
 * and is currently available in experimental mode only
 */
public class BuildProcessManager {
	protected OutputStream out;
	protected OutputStream err;
	protected boolean show;
	protected ProcessLauncher[] processes;
	protected int maxProcesses;  
	
//	 Number of CPUs is not dependent of object instance.
//   But user can change UI settings for processes number.
//   So we cannot set procNumber directly to maxProcesses. 	
	static int procNumber = 0;
	
	/**
	 * Initializes process manager
	 * 
	 * @param _out Output stream
	 * @param _err Error output stream
	 * @param _show If true, print command line before launching
	 */
	public BuildProcessManager(OutputStream _out, OutputStream _err, boolean _show, int _procNumber) {
		out = _out;
		err = _err;
		show = _show;
		maxProcesses = _procNumber;
		processes = new ProcessLauncher[maxProcesses];
	}
	
	/**
	 * Returns maximum number of processes
	 */
	public int getMaxProcesses() {
		return maxProcesses;
	}
	
	/**
	 * Performs an attempt to launch new process. Returns BuildProcessLauncher 
	 * if it was successfully launched, null if there is no room for it yet in 
	 * the process pool.
	 * 
	 * @param cmd Command to launch
	 * @param cwd Command working directory
	 * @param monitor Progress monitor for this task 
	 */
	public ProcessLauncher launchProcess(IBuildCommand cmd, IPath cwd, IProgressMonitor monitor) {
		if (hasEmpty()) {
			int i = 0;
			for (; i < maxProcesses; i++) {
				if (processes[i] == null || processes[i].queryState() == ProcessLauncher.STATE_DONE) {
					break;
				}
			}
			
			if (i < maxProcesses) {
				processes[i] = new ProcessLauncher(cmd.getCommand(), cmd.getArgs(), mapToStringArray(cmd.getEnvironment()), cwd, out, err, monitor, show);
				processes[i].launch();
				return processes[i];
			}
		}
		return null;
	}
	
	/**
	 * Checks states of all currently running processes. If it finds 
	 * one with state other than STATE_DONE or STATE_RUNNING, it is
	 * returned as a result. Otherwise this method returns null.
	 */
	public ProcessLauncher queryStates() {
		ProcessLauncher result = null;
		
		for (int i = 0; i < maxProcesses; i++) {
			if (processes[i] != null) {
				int state = processes[i].queryState();
				if (state != ProcessLauncher.STATE_RUNNING) {
					if (state != ProcessLauncher.STATE_DONE && result == null)
						result = processes[i];
				}
			}
		}
		
		return result;
	}

	/**
	 * Checks states of all currently running processes. 
	 */
	public boolean hasEmpty() {
		for (int i = 0; i < maxProcesses; i++) {
			if (processes[i] == null) 
				return true;
			else {
				if (processes[i].queryState() != ProcessLauncher.STATE_RUNNING) 
					return true;
			}
		}
		return false;
	}

	
	/**
	 * Converts map to strings array
	 */
	protected String[] mapToStringArray(Map<String, String> map){
		if(map == null)
			return null;
		
		List<String> list = new ArrayList<String>();
		
		Set<Entry<String, String>> entrySet = map.entrySet();
		for (Entry<String, String> entry : entrySet) {
			list.add(entry.getKey() + '=' + entry.getValue());
		}
		
		return list.toArray(new String[list.size()]);
	}
	
	/**
	 * @return Number of processors detected
	 */
	static public int checkCPUNumber() {
		if (procNumber > 0) return procNumber;
		
		procNumber = 1;
		int x = 0;
		String os = System.getProperty("os.name"); //$NON-NLS-1$
		if (os != null) {
			if (os.startsWith("Win")) { //$NON-NLS-1$
				IEnvironmentVariableProvider evp = ManagedBuildManager.getEnvironmentVariableProvider();
				if (evp != null) {
					IBuildEnvironmentVariable var = evp.getVariable("NUMBER_OF_PROCESSORS", null, false, false); //$NON-NLS-1$
					if (var != null) {
						try {
							x = new Integer(var.getValue()).intValue();
							if (x > 0) { procNumber = x; }
						} catch (NumberFormatException e) {} // fallthrough and return default
					}
				}
			} else { // linux
				String p = "/proc/cpuinfo"; //$NON-NLS-1$
				try {
					BufferedReader r = new BufferedReader(new InputStreamReader(new FileInputStream(p)));
					String s;
					while ((s = r.readLine() ) != null ) 
					   { if (s.startsWith("processor\t:")) x++; } //$NON-NLS-1$
					r.close();
					if (x > 0) { procNumber = x; }
				} 
				catch (IOException e) {} // fallthrough and return default
			}
		}
		if(DbgUtil.DEBUG)
			DbgUtil.trace("Number of processors detected: " + procNumber);	//$NON-NLS-1$
		return procNumber;
	}
}

Back to the top