Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
View | Details | Raw Unified | Return to bug 287096 | Differences between
and this patch

Collapse All | Expand All

(-)src/org/eclipse/wst/sse/core/internal/SSECorePlugin.java (+4 lines)
Lines 16-21 Link Here
16
import org.eclipse.core.runtime.Preferences;
16
import org.eclipse.core.runtime.Preferences;
17
import org.eclipse.wst.sse.core.StructuredModelManager;
17
import org.eclipse.wst.sse.core.StructuredModelManager;
18
import org.eclipse.wst.sse.core.internal.encoding.CommonEncodingPreferenceNames;
18
import org.eclipse.wst.sse.core.internal.encoding.CommonEncodingPreferenceNames;
19
import org.eclipse.wst.sse.core.internal.model.ModelManagerImpl;
19
import org.eclipse.wst.sse.core.internal.modelhandler.ModelHandlerRegistry;
20
import org.eclipse.wst.sse.core.internal.modelhandler.ModelHandlerRegistry;
20
import org.eclipse.wst.sse.core.internal.preferences.CommonModelPreferenceNames;
21
import org.eclipse.wst.sse.core.internal.preferences.CommonModelPreferenceNames;
21
import org.eclipse.wst.sse.core.internal.provisional.IModelManager;
22
import org.eclipse.wst.sse.core.internal.provisional.IModelManager;
Lines 62-71 Link Here
62
	public void stop(BundleContext context) throws Exception {
63
	public void stop(BundleContext context) throws Exception {
63
		savePluginPreferences();
64
		savePluginPreferences();
64
		
65
		
66
		((ModelManagerImpl) ModelManagerImpl.getInstance()).removePreferenceListener();
67
65
		TaskScanningScheduler.shutdown();
68
		TaskScanningScheduler.shutdown();
66
69
67
		FileBufferModelManager.shutdown();
70
		FileBufferModelManager.shutdown();
68
71
72
69
		super.stop(context);
73
		super.stop(context);
70
	}
74
	}
71
75
(-)src/org/eclipse/wst/sse/core/internal/model/ModelManagerImpl.java (-22 / +172 lines)
Lines 40-45 Link Here
40
import org.eclipse.core.runtime.IPath;
40
import org.eclipse.core.runtime.IPath;
41
import org.eclipse.core.runtime.IStatus;
41
import org.eclipse.core.runtime.IStatus;
42
import org.eclipse.core.runtime.NullProgressMonitor;
42
import org.eclipse.core.runtime.NullProgressMonitor;
43
import org.eclipse.core.runtime.OperationCanceledException;
43
import org.eclipse.core.runtime.Path;
44
import org.eclipse.core.runtime.Path;
44
import org.eclipse.core.runtime.Platform;
45
import org.eclipse.core.runtime.Platform;
45
import org.eclipse.core.runtime.QualifiedName;
46
import org.eclipse.core.runtime.QualifiedName;
Lines 47-55 Link Here
47
import org.eclipse.core.runtime.content.IContentDescription;
48
import org.eclipse.core.runtime.content.IContentDescription;
48
import org.eclipse.core.runtime.jobs.ILock;
49
import org.eclipse.core.runtime.jobs.ILock;
49
import org.eclipse.core.runtime.jobs.Job;
50
import org.eclipse.core.runtime.jobs.Job;
51
import org.eclipse.core.runtime.preferences.ConfigurationScope;
52
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
53
import org.eclipse.core.runtime.preferences.IPreferencesService;
54
import org.eclipse.core.runtime.preferences.IScopeContext;
55
import org.eclipse.core.runtime.preferences.InstanceScope;
56
import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent;
50
import org.eclipse.jface.text.BadLocationException;
57
import org.eclipse.jface.text.BadLocationException;
51
import org.eclipse.jface.text.IDocument;
58
import org.eclipse.jface.text.IDocument;
52
import org.eclipse.jface.text.IRegion;
59
import org.eclipse.jface.text.IRegion;
60
import org.eclipse.osgi.util.NLS;
53
import org.eclipse.text.edits.MultiTextEdit;
61
import org.eclipse.text.edits.MultiTextEdit;
54
import org.eclipse.text.edits.ReplaceEdit;
62
import org.eclipse.text.edits.ReplaceEdit;
55
import org.eclipse.text.edits.TextEdit;
63
import org.eclipse.text.edits.TextEdit;
Lines 96-101 Link Here
96
 */
104
 */
97
public class ModelManagerImpl implements IModelManager {
105
public class ModelManagerImpl implements IModelManager {
98
106
107
	private static int WAIT_DELAY = getInt("org.eclipse.wst.sse.core.modelmanager.maxWaitDuringConcurrentLoad");
108
	private static boolean ALLOW_INTERRUPT_WAITING_THREAD = getBoolean("org.eclipse.wst.sse.core.modelmanager.allowInterruptsDuringConcurrentLoad");
109
	private static IEclipsePreferences.IPreferenceChangeListener LISTENER;
110
	static {
111
		InstanceScope scope = new InstanceScope();
112
		IEclipsePreferences instancePrefs = scope.getNode(SSECorePlugin.ID);
113
		LISTENER = new IEclipsePreferences.IPreferenceChangeListener() {
114
115
					public void preferenceChange(PreferenceChangeEvent event) {
116
117
				if ("modelmanager.maxWaitDuringConcurrentLoad".equals(event.getKey())) {
118
					WAIT_DELAY = getInt("org.eclipse.wst.sse.core.modelmanager.maxWaitDuringConcurrentLoad");
119
				}
120
				else if ("modelmanager.allowInterruptsDuringConcurrentLoad".equals(event.getKey())) {
121
					ALLOW_INTERRUPT_WAITING_THREAD = getBoolean("org.eclipse.wst.sse.core.modelmanager.allowInterruptsDuringConcurrentLoad");
122
				}
123
			}
124
		};
125
		instancePrefs.addPreferenceChangeListener(LISTENER);
126
	}
127
99
	static class ReadEditType {
128
	static class ReadEditType {
100
		ReadEditType(String type) {
129
		ReadEditType(String type) {
101
		}
130
		}
Lines 109-115 Link Here
109
		int referenceCountForRead;
138
		int referenceCountForRead;
110
		IStructuredModel theSharedModel;
139
		IStructuredModel theSharedModel;
111
		boolean initializing = true;
140
		boolean initializing = true;
112
		boolean doWait = true;
141
		volatile boolean doWait = true;
142
		final Object loadCondition = new Object();
113
		
143
		
114
		SharedObject(IStructuredModel sharedModel) {
144
		SharedObject(IStructuredModel sharedModel) {
115
			theSharedModel = sharedModel;
145
			theSharedModel = sharedModel;
Lines 121-135 Link Here
121
		 * Waits until this shared object has been attempted to be loaded. 
151
		 * Waits until this shared object has been attempted to be loaded. 
122
		 * The load is "attempted" because not all loads result in a model. 
152
		 * The load is "attempted" because not all loads result in a model. 
123
		 * However, upon leaving this method, theShareModel variable
153
		 * However, upon leaving this method, theShareModel variable
124
		 * is up-to-date.
154
		 * is up-to-date. Should not be called if holding a lock on this object.
125
		 */
155
		 */
126
		public synchronized void waitForLoadAttempt() {
156
		public void waitForLoadAttempt() {
127
			while(initializing) {
157
			synchronized(loadCondition) {
128
				try {
158
				long start = System.currentTimeMillis();
129
					wait();
159
				// Note: A WAIT_DELAY of 0 is infinite
160
				int maxTimeMs = Math.max(0, WAIT_DELAY);
161
				final int waitInterval = Math.min(250, maxTimeMs);
162
				boolean interrupted = false;
163
				while (initializing && maxTimeMs >= 0) {
164
					try {
165
						wait(waitInterval);
166
						maxTimeMs -= waitInterval;
167
					}
168
					catch (InterruptedException e) {
169
						interrupted = true;
170
						if (ALLOW_INTERRUPT_WAITING_THREAD) {
171
							break;
172
						}
173
					}
174
				}
175
				if (initializing) {
176
					long totalWaitTime = System.currentTimeMillis() - start;
177
					if (interrupted) {
178
						throw new OperationCanceledException(
179
								"Waiting thread interrupted during simultenous model load. Load aborted. (Waited "
180
										+ totalWaitTime + "ms)");
181
					}
182
					else {
183
						throw new OperationCanceledException(
184
								"Waiting thread timed-out during simultenous model load. Load aborted. (Waited "
185
										+ totalWaitTime + "ms)");
186
					}
130
				}
187
				}
131
				catch (InterruptedException e) {
188
				if (interrupted) {
132
					// ignore interruption!
189
					// Propagate (don't swallow) the interrupt
190
					Thread.currentThread().interrupt();
133
				}
191
				}
134
			}
192
			}
135
		}
193
		}
Lines 139-147 Link Here
139
		 * {@link #waitForLoadAttempt()} will proceed after this 
197
		 * {@link #waitForLoadAttempt()} will proceed after this 
140
		 * method returns. 
198
		 * method returns. 
141
		 */
199
		 */
142
		public synchronized void setLoaded() {
200
		public void setLoaded() {
143
			initializing = false;
201
			synchronized(loadCondition) {
144
			notifyAll();
202
				initializing = false;
203
				loadCondition.notifyAll();
204
			}
145
		}
205
		}
146
	}
206
	}
147
207
Lines 166-171 Link Here
166
		return instance;
226
		return instance;
167
	}
227
	}
168
228
229
	public void removePreferenceListener() {
230
		InstanceScope scope = new InstanceScope();
231
		IEclipsePreferences instancePrefs = scope.getNode(SSECorePlugin.ID);
232
		instancePrefs.removePreferenceChangeListener(LISTENER);
233
	}
234
169
	/**
235
	/**
170
	 * Our cache of managed objects
236
	 * Our cache of managed objects
171
	 */
237
	 */
Lines 183-191 Link Here
183
	ModelManagerImpl() {
249
	ModelManagerImpl() {
184
		super();
250
		super();
185
		fManagedObjects = new HashMap();
251
		fManagedObjects = new HashMap();
186
		// To prevent deadlocks:  always acquire multiple locks in this order: SYNC, sharedObject. 
252
		/**
187
		// DO NOT acquire a SYNC within a sharedObject lock, unless you already own the SYNC lock
253
		 * NOTES: To prevent deadlocks: always acquire multiple locks in this
188
		// Tip: Try to hold the smallest number of locks you can
254
		 * order: SYNC->sharedObject->sharedObject.loadCondition DO NOT acquire a
255
		 * SYNC within a sharedObject lock, unless you already own the SYNC lock
256
		 * Tip: Try to hold the smallest number of locks you can
257
		 */
189
	}
258
	}
190
259
191
	private IStructuredModel _commonCreateModel(IFile file, String id, IModelHandler handler, URIResolver resolver, ReadEditType rwType, EncodingRule encodingRule) throws IOException,CoreException {
260
	private IStructuredModel _commonCreateModel(IFile file, String id, IModelHandler handler, URIResolver resolver, ReadEditType rwType, EncodingRule encodingRule) throws IOException,CoreException {
Lines 380-386 Link Here
380
						((AbstractStructuredModel) model).setContentTypeIdentifier(description.getContentType().getId());
449
						((AbstractStructuredModel) model).setContentTypeIdentifier(description.getContentType().getId());
381
					}
450
					}
382
				}
451
				}
383
384
				sharedObject.theSharedModel = model;
452
				sharedObject.theSharedModel = model;
385
				_initCount(sharedObject, rwType);
453
				_initCount(sharedObject, rwType);
386
			} else {
454
			} else {
Lines 1159-1168 Link Here
1159
				// and return the object.
1227
				// and return the object.
1160
				SYNC.release();
1228
				SYNC.release();
1161
				doRelease=false;
1229
				doRelease=false;
1230
				if (sharedObject.doWait) {
1231
					sharedObject.waitForLoadAttempt();
1232
				}
1162
				synchronized(sharedObject) {
1233
				synchronized(sharedObject) {
1163
					if (sharedObject.doWait) {
1164
						sharedObject.waitForLoadAttempt();
1165
					}
1166
					if (sharedObject.theSharedModel!=null) {
1234
					if (sharedObject.theSharedModel!=null) {
1167
						_incrCount(sharedObject, EDIT);
1235
						_incrCount(sharedObject, EDIT);
1168
					}
1236
					}
Lines 1241-1251 Link Here
1241
				// and return the object.
1309
				// and return the object.
1242
				SYNC.release();
1310
				SYNC.release();
1243
				doRelease=false;
1311
				doRelease=false;
1244
1312
				if (sharedObject.doWait) {
1313
					sharedObject.waitForLoadAttempt();
1314
				}
1245
				synchronized(sharedObject) {
1315
				synchronized(sharedObject) {
1246
					if (sharedObject.doWait) {
1247
						sharedObject.waitForLoadAttempt();
1248
					}
1249
					if (sharedObject.theSharedModel!=null) {
1316
					if (sharedObject.theSharedModel!=null) {
1250
						_incrCount(sharedObject, READ);
1317
						_incrCount(sharedObject, READ);
1251
					}
1318
					}
Lines 2098-2101 Link Here
2098
			SYNC.release();
2165
			SYNC.release();
2099
			return inUse;
2166
			return inUse;
2100
		}
2167
		}
2168
2169
	private static String getProperty(String property) {
2170
		// Preference overrides system property overrides env-var
2171
2172
		IPreferencesService preferencesService = Platform.getPreferencesService();
2173
		IScopeContext[] lookupOrder = new IScopeContext[] {
2174
				new InstanceScope(), new ConfigurationScope()
2175
		};
2176
		String key = property;
2177
		if (property != null && property.startsWith(SSECorePlugin.ID)) {
2178
			// +1, include the "."
2179
			key = property.substring(SSECorePlugin.ID.length() + 1, property.length());
2180
		}
2181
		String value = preferencesService.getString(SSECorePlugin.ID, key, null, lookupOrder);
2182
		if (value == null) {
2183
			value = System.getProperty(property);
2184
		}
2185
		if (value == null) {
2186
			value = System.getenv(property);
2187
		}
2188
		return value;
2189
	}
2190
2191
	private static String getDefault(String property) {
2192
		// this is the "default-default"
2193
		if ("org.eclipse.wst.sse.core.modelmanager.maxWaitDuringConcurrentLoad".equals(property)) {
2194
			return "0";
2195
		}
2196
		else if ("org.eclipse.wst.sse.core.modelmanager.allowInterruptsDuringConcurrentLoad"
2197
				.equals(property)) {
2198
			return "false";
2199
		}
2200
		return null;
2201
	}
2202
2203
	private static boolean getBoolean(String key) {
2204
		String property = getProperty(key);
2205
		// if (property != null) {
2206
		//			System.out.println("Tweak: " + key + "=" + Boolean.parseBoolean(property)); //$NON-NLS-1$ //$NON-NLS-2$
2207
		// }
2208
		return property != null ? Boolean.parseBoolean(property) : Boolean
2209
				.parseBoolean(getDefault(key));
2210
	}
2211
2212
	private static int getInt(String key) {
2213
		String property = getProperty(key);
2214
		int size = 0;
2215
		if (property != null) {
2216
			try {
2217
				size = Integer.parseInt(property);
2218
				//	System.out.println("Tweak: " + key + "=" + size); //$NON-NLS-1$ //$NON-NLS-2$
2219
			}
2220
			catch (NumberFormatException e) {
2221
				size = getDefaultInt(key, property, size);
2222
			}
2223
		}
2224
		else {
2225
			size = getDefaultInt(key, property, size);
2226
		}
2227
		return size;
2228
	}
2229
2230
	private static int getDefaultInt(String key, String property, int size) {
2231
		// ignored
2232
		try {
2233
			size = Integer.parseInt(getDefault(key));
2234
		}
2235
		catch (NumberFormatException e1) {
2236
			handleIntParseException(key, property, e1);
2237
			size = 0;
2238
		}
2239
		return size;
2240
	}
2241
2242
	private static void handleIntParseException(String key, String property,
2243
			NumberFormatException e1) {
2244
		Exception n = new Exception(
2245
				NLS
2246
						.bind(
2247
								"Exception during parse of default value for key ''{0}'' value was ''{1}''. Using 0 instead", //$NON-NLS-1$
2248
								key, property), e1);
2249
		n.printStackTrace();
2250
	}
2101
}
2251
}

Return to bug 287096