diff options
author | Glyn Normington | 2012-08-30 15:43:32 +0000 |
---|---|---|
committer | Glyn Normington | 2012-08-30 15:43:32 +0000 |
commit | 708b8669657659cc392e098dce046300a2cad747 (patch) | |
tree | 3609686f6b6ea88c345d68b2c5d1387892215d1a /extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/dependencies/startup/DependencyServiceManager.java | |
parent | b545a6b9cd440d0da5d8a11e7c04adf672867b02 (diff) | |
download | org.eclipse.gemini.blueprint-708b8669657659cc392e098dce046300a2cad747.tar.gz org.eclipse.gemini.blueprint-708b8669657659cc392e098dce046300a2cad747.tar.xz org.eclipse.gemini.blueprint-708b8669657659cc392e098dce046300a2cad747.zip |
384748: thread safety improvements
Diffstat (limited to 'extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/dependencies/startup/DependencyServiceManager.java')
-rw-r--r-- | extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/dependencies/startup/DependencyServiceManager.java | 148 |
1 files changed, 102 insertions, 46 deletions
diff --git a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/dependencies/startup/DependencyServiceManager.java b/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/dependencies/startup/DependencyServiceManager.java index 8d303fa..676ecda 100644 --- a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/dependencies/startup/DependencyServiceManager.java +++ b/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/dependencies/startup/DependencyServiceManager.java | |||
@@ -22,6 +22,8 @@ import java.security.PrivilegedExceptionAction; | |||
22 | import java.util.ArrayList; | 22 | import java.util.ArrayList; |
23 | import java.util.Collection; | 23 | import java.util.Collection; |
24 | import java.util.Collections; | 24 | import java.util.Collections; |
25 | import java.util.HashMap; | ||
26 | import java.util.HashSet; | ||
25 | import java.util.Iterator; | 27 | import java.util.Iterator; |
26 | import java.util.LinkedHashMap; | 28 | import java.util.LinkedHashMap; |
27 | import java.util.List; | 29 | import java.util.List; |
@@ -63,13 +65,15 @@ import org.eclipse.gemini.blueprint.util.OsgiStringUtils; | |||
63 | */ | 65 | */ |
64 | public class DependencyServiceManager { | 66 | public class DependencyServiceManager { |
65 | 67 | ||
66 | private static final Log log = LogFactory.getLog(DependencyServiceManager.class); | 68 | private static final Map<MandatoryServiceDependency, String> UNMODIFIABLE_DEPENDENCY_MAP = Collections.unmodifiableMap(new HashMap<MandatoryServiceDependency, String>(0)); |
69 | |||
70 | private static final Log log = LogFactory.getLog(DependencyServiceManager.class); | ||
71 | |||
72 | private final Object monitor = new Object(); | ||
67 | 73 | ||
68 | protected final Map<MandatoryServiceDependency, String> dependencies = | 74 | protected final Map<MandatoryServiceDependency, String> dependencies = new LinkedHashMap<MandatoryServiceDependency, String>(); |
69 | Collections.synchronizedMap(new LinkedHashMap<MandatoryServiceDependency, String>()); | ||
70 | 75 | ||
71 | protected final Map<MandatoryServiceDependency, String> unsatisfiedDependencies = | 76 | protected final Map<MandatoryServiceDependency, String> unsatisfiedDependencies = new LinkedHashMap<MandatoryServiceDependency, String>(); |
72 | Collections.synchronizedMap(new LinkedHashMap<MandatoryServiceDependency, String>()); | ||
73 | 77 | ||
74 | private final ContextExecutorAccessor contextStateAccessor; | 78 | private final ContextExecutorAccessor contextStateAccessor; |
75 | 79 | ||
@@ -108,7 +112,7 @@ public class DependencyServiceManager { | |||
108 | boolean trace = log.isTraceEnabled(); | 112 | boolean trace = log.isTraceEnabled(); |
109 | 113 | ||
110 | try { | 114 | try { |
111 | if (unsatisfiedDependencies.isEmpty()) { | 115 | if (isSatisfied()) { |
112 | 116 | ||
113 | // already completed but likely called due to threading | 117 | // already completed but likely called due to threading |
114 | if (trace) { | 118 | if (trace) { |
@@ -136,7 +140,7 @@ public class DependencyServiceManager { | |||
136 | } | 140 | } |
137 | 141 | ||
138 | // Good to go! | 142 | // Good to go! |
139 | if (unsatisfiedDependencies.isEmpty()) { | 143 | if (isSatisfied()) { |
140 | deregister(); | 144 | deregister(); |
141 | // context.listener = null; | 145 | // context.listener = null; |
142 | log.info("No unsatisfied OSGi service dependencies; completing initialization for " | 146 | log.info("No unsatisfied OSGi service dependencies; completing initialization for " |
@@ -153,9 +157,9 @@ public class DependencyServiceManager { | |||
153 | log.error("Exception during dependency processing for " + context.getDisplayName(), th); | 157 | log.error("Exception during dependency processing for " + context.getDisplayName(), th); |
154 | contextStateAccessor.fail(th); | 158 | contextStateAccessor.fail(th); |
155 | } | 159 | } |
156 | } | 160 | } |
157 | 161 | ||
158 | private void updateDependencies(ServiceEvent serviceEvent) { | 162 | private void updateDependencies(ServiceEvent serviceEvent) { |
159 | boolean trace = log.isTraceEnabled(); | 163 | boolean trace = log.isTraceEnabled(); |
160 | boolean debug = log.isDebugEnabled(); | 164 | boolean debug = log.isDebugEnabled(); |
161 | 165 | ||
@@ -167,7 +171,12 @@ public class DependencyServiceManager { | |||
167 | contextToString = context.getDisplayName(); | 171 | contextToString = context.getDisplayName(); |
168 | } | 172 | } |
169 | 173 | ||
170 | for (MandatoryServiceDependency dependency : dependencies.keySet()) { | 174 | Set<MandatoryServiceDependency> mandatoryServiceDependencies; |
175 | synchronized (monitor) { | ||
176 | mandatoryServiceDependencies = new HashSet<MandatoryServiceDependency>(dependencies.keySet()); | ||
177 | } | ||
178 | |||
179 | for (MandatoryServiceDependency dependency : mandatoryServiceDependencies) { | ||
171 | // check all dependencies (there might be multiple imports for the same service) | 180 | // check all dependencies (there might be multiple imports for the same service) |
172 | if (dependency.matches(serviceEvent)) { | 181 | if (dependency.matches(serviceEvent)) { |
173 | if (trace) { | 182 | if (trace) { |
@@ -179,18 +188,24 @@ public class DependencyServiceManager { | |||
179 | case ServiceEvent.REGISTERED: | 188 | case ServiceEvent.REGISTERED: |
180 | case ServiceEvent.MODIFIED: | 189 | case ServiceEvent.MODIFIED: |
181 | dependency.increment(); | 190 | dependency.increment(); |
182 | if (unsatisfiedDependencies.remove(dependency) != null) { | 191 | String removedDependency; |
183 | if (debug) { | 192 | synchronized (monitor) { |
184 | log.debug("Registered dependency for " + contextToString + "; eliminating " | 193 | removedDependency = unsatisfiedDependencies.remove(dependency); |
185 | + dependency + ", remaining [" + unsatisfiedDependencies + "]"); | 194 | } |
186 | } | 195 | if (removedDependency != null) { |
187 | 196 | Map<MandatoryServiceDependency, String> unsatisfiedDependenciesSnapshot = getUnsatisfiedDependencies(); | |
188 | sendDependencySatisfiedEvent(dependency); | 197 | if (debug) { |
189 | sendBootstrappingDependenciesEvent(unsatisfiedDependencies.keySet()); | 198 | log.debug("Registered dependency for " + contextToString + "; eliminating " |
199 | + dependency + ", remaining [" + unsatisfiedDependenciesSnapshot + "]"); | ||
200 | } | ||
201 | |||
202 | sendDependencySatisfiedEvent(dependency); | ||
203 | sendBootstrappingDependenciesEvent(unsatisfiedDependenciesSnapshot.keySet()); | ||
190 | } else { | 204 | } else { |
191 | if (debug) { | 205 | if (debug) { |
206 | Map<MandatoryServiceDependency, String> unsatisfiedDependenciesSnapshot = getUnsatisfiedDependencies(); | ||
192 | log.debug("Increasing the number of matching services for " + contextToString + "; " | 207 | log.debug("Increasing the number of matching services for " + contextToString + "; " |
193 | + dependency + ", remaining [" + unsatisfiedDependencies + "]"); | 208 | + dependency + ", remaining [" + unsatisfiedDependenciesSnapshot + "]"); |
194 | } | 209 | } |
195 | } | 210 | } |
196 | 211 | ||
@@ -199,14 +214,17 @@ public class DependencyServiceManager { | |||
199 | case ServiceEvent.UNREGISTERING: | 214 | case ServiceEvent.UNREGISTERING: |
200 | int count = dependency.decrement(); | 215 | int count = dependency.decrement(); |
201 | if (count == 0) { | 216 | if (count == 0) { |
202 | unsatisfiedDependencies.put(dependency, dependency.getBeanName()); | 217 | synchronized (monitor) { |
203 | if (debug) { | 218 | unsatisfiedDependencies.put(dependency, dependency.getBeanName()); |
219 | } | ||
220 | Map<MandatoryServiceDependency, String> unsatisfiedDependenciesSnapshot = getUnsatisfiedDependencies(); | ||
221 | if (debug) { | ||
204 | log.debug("Unregistered dependency for " + contextToString + " adding " + dependency | 222 | log.debug("Unregistered dependency for " + contextToString + " adding " + dependency |
205 | + "; total unsatisfied [" + unsatisfiedDependencies + "]"); | 223 | + "; total unsatisfied [" + unsatisfiedDependenciesSnapshot + "]"); |
206 | } | 224 | } |
207 | 225 | ||
208 | sendDependencyUnsatisfiedEvent(dependency); | 226 | sendDependencyUnsatisfiedEvent(dependency); |
209 | sendBootstrappingDependenciesEvent(unsatisfiedDependencies.keySet()); | 227 | sendBootstrappingDependenciesEvent(unsatisfiedDependenciesSnapshot.keySet()); |
210 | } else { | 228 | } else { |
211 | if (debug) { | 229 | if (debug) { |
212 | log.debug("Decreasing the number of matching services for " + contextToString + "; " | 230 | log.debug("Decreasing the number of matching services for " + contextToString + "; " |
@@ -226,7 +244,8 @@ public class DependencyServiceManager { | |||
226 | } | 244 | } |
227 | } | 245 | } |
228 | } | 246 | } |
229 | } | 247 | } |
248 | |||
230 | } | 249 | } |
231 | 250 | ||
232 | /** | 251 | /** |
@@ -280,19 +299,31 @@ public class DependencyServiceManager { | |||
280 | throw (Error) th; | 299 | throw (Error) th; |
281 | } | 300 | } |
282 | 301 | ||
283 | if (log.isDebugEnabled()) { | 302 | Collection<String> unsatisfiedDependencyValues = getUnsatisfiedDependencies().values(); |
284 | log.debug(dependencies.size() + " OSGi service dependencies, " + unsatisfiedDependencies.size() | 303 | |
285 | + " unsatisfied (for beans " + unsatisfiedDependencies.values() + ") in " | 304 | if (log.isDebugEnabled()) { |
305 | int numDependencies; | ||
306 | int numUnsatisfiedDependencies; | ||
307 | synchronized (monitor) { | ||
308 | numDependencies = dependencies.size(); | ||
309 | numUnsatisfiedDependencies = unsatisfiedDependencies.size(); | ||
310 | } | ||
311 | log.debug(numDependencies + " OSGi service dependencies, " + numUnsatisfiedDependencies | ||
312 | + " unsatisfied (for beans " + unsatisfiedDependencyValues + ") in " | ||
286 | + context.getDisplayName()); | 313 | + context.getDisplayName()); |
287 | } | 314 | } |
288 | 315 | ||
289 | if (!unsatisfiedDependencies.isEmpty()) { | 316 | if (!isSatisfied()) { |
290 | log.info(context.getDisplayName() + " is waiting for unsatisfied dependencies [" | 317 | log.info(context.getDisplayName() + " is waiting for unsatisfied dependencies [" |
291 | + unsatisfiedDependencies.values() + "]"); | 318 | + unsatisfiedDependencyValues + "]"); |
292 | } | 319 | } |
293 | if (log.isTraceEnabled()) { | 320 | if (log.isTraceEnabled()) { |
294 | log.trace("Total OSGi service dependencies beans " + dependencies.values()); | 321 | Collection<String> dependencyValues; |
295 | log.trace("Unsatified OSGi service dependencies beans " + unsatisfiedDependencies.values()); | 322 | synchronized (monitor) { |
323 | dependencyValues = new ArrayList<String>(dependencies.values()); | ||
324 | } | ||
325 | log.trace("Total OSGi service dependencies beans " + dependencyValues); | ||
326 | log.trace("Unsatified OSGi service dependencies beans " + unsatisfiedDependencyValues); | ||
296 | } | 327 | } |
297 | } | 328 | } |
298 | 329 | ||
@@ -332,13 +363,17 @@ public class DependencyServiceManager { | |||
332 | if (discoveredDependencies != null) | 363 | if (discoveredDependencies != null) |
333 | for (OsgiServiceDependency dependency : discoveredDependencies) { | 364 | for (OsgiServiceDependency dependency : discoveredDependencies) { |
334 | if (dependency.isMandatory()) { | 365 | if (dependency.isMandatory()) { |
335 | MandatoryServiceDependency msd = new MandatoryServiceDependency(bundleContext, dependency); | 366 | MandatoryServiceDependency msd = new MandatoryServiceDependency(bundleContext, dependency); |
336 | dependencies.put(msd, dependency.getBeanName()); | 367 | synchronized (monitor) { |
368 | dependencies.put(msd, dependency.getBeanName()); | ||
369 | } | ||
337 | 370 | ||
338 | if (!msd.isServicePresent()) { | 371 | if (!msd.isServicePresent()) { |
339 | log.info("Adding OSGi service dependency for importer [" + msd.getBeanName() | 372 | log.info("Adding OSGi service dependency for importer [" + msd.getBeanName() |
340 | + "] matching OSGi filter [" + msd.filterAsString + "]"); | 373 | + "] matching OSGi filter [" + msd.filterAsString + "]"); |
341 | unsatisfiedDependencies.put(msd, dependency.getBeanName()); | 374 | synchronized (monitor) { |
375 | unsatisfiedDependencies.put(msd, dependency.getBeanName()); | ||
376 | } | ||
342 | } else { | 377 | } else { |
343 | if (debug) | 378 | if (debug) |
344 | log.debug("OSGi service dependency for importer [" + msd.getBeanName() | 379 | log.debug("OSGi service dependency for importer [" + msd.getBeanName() |
@@ -349,12 +384,20 @@ public class DependencyServiceManager { | |||
349 | } | 384 | } |
350 | } | 385 | } |
351 | 386 | ||
352 | protected boolean isSatisfied() { | 387 | public boolean isSatisfied() { |
353 | return unsatisfiedDependencies.isEmpty(); | 388 | synchronized (monitor) { |
389 | return unsatisfiedDependencies.isEmpty(); | ||
390 | } | ||
354 | } | 391 | } |
355 | 392 | ||
356 | public Map<MandatoryServiceDependency, String> getUnsatisfiedDependencies() { | 393 | public Map<MandatoryServiceDependency, String> getUnsatisfiedDependencies() { |
357 | return unsatisfiedDependencies; | 394 | if (isSatisfied()) { |
395 | return UNMODIFIABLE_DEPENDENCY_MAP; | ||
396 | } else { | ||
397 | synchronized (monitor) { | ||
398 | return Collections.unmodifiableMap(new HashMap<MandatoryServiceDependency, String>(unsatisfiedDependencies)); | ||
399 | } | ||
400 | } | ||
358 | } | 401 | } |
359 | 402 | ||
360 | protected void register() { | 403 | protected void register() { |
@@ -365,7 +408,7 @@ public class DependencyServiceManager { | |||
365 | } | 408 | } |
366 | 409 | ||
367 | // send dependency event before registering the filter | 410 | // send dependency event before registering the filter |
368 | sendInitialBootstrappingEvents(unsatisfiedDependencies.keySet()); | 411 | sendInitialBootstrappingEvents(getUnsatisfiedDependencies().keySet()); |
369 | 412 | ||
370 | if (System.getSecurityManager() != null) { | 413 | if (System.getSecurityManager() != null) { |
371 | AccessControlContext acc = getAcc(); | 414 | AccessControlContext acc = getAcc(); |
@@ -386,12 +429,16 @@ public class DependencyServiceManager { | |||
386 | * | 429 | * |
387 | * @return | 430 | * @return |
388 | */ | 431 | */ |
389 | private String createDependencyFilter() { | 432 | private String createDependencyFilter() { |
390 | return createDependencyFilter(dependencies.keySet()); | 433 | synchronized (monitor) { |
434 | return createDependencyFilter(dependencies.keySet()); | ||
435 | } | ||
391 | } | 436 | } |
392 | 437 | ||
393 | String createUnsatisfiedDependencyFilter() { | 438 | String createUnsatisfiedDependencyFilter() { |
394 | return createDependencyFilter(unsatisfiedDependencies.keySet()); | 439 | synchronized (monitor) { |
440 | return createDependencyFilter(unsatisfiedDependencies.keySet()); | ||
441 | } | ||
395 | } | 442 | } |
396 | 443 | ||
397 | private String createDependencyFilter(Collection<MandatoryServiceDependency> dependencies) { | 444 | private String createDependencyFilter(Collection<MandatoryServiceDependency> dependencies) { |
@@ -425,7 +472,9 @@ public class DependencyServiceManager { | |||
425 | } | 472 | } |
426 | 473 | ||
427 | List<OsgiServiceDependencyEvent> getUnsatisfiedDependenciesAsEvents() { | 474 | List<OsgiServiceDependencyEvent> getUnsatisfiedDependenciesAsEvents() { |
428 | return getUnsatisfiedDependenciesAsEvents(unsatisfiedDependencies.keySet()); | 475 | synchronized (monitor) { |
476 | return getUnsatisfiedDependenciesAsEvents(unsatisfiedDependencies.keySet()); | ||
477 | } | ||
429 | } | 478 | } |
430 | 479 | ||
431 | private List<OsgiServiceDependencyEvent> getUnsatisfiedDependenciesAsEvents( | 480 | private List<OsgiServiceDependencyEvent> getUnsatisfiedDependenciesAsEvents( |
@@ -497,5 +546,12 @@ public class DependencyServiceManager { | |||
497 | return ((ConfigurableBeanFactory) beanFactory).getAccessControlContext(); | 546 | return ((ConfigurableBeanFactory) beanFactory).getAccessControlContext(); |
498 | } | 547 | } |
499 | return null; | 548 | return null; |
500 | } | 549 | } |
550 | |||
551 | public boolean allDependenciesSatisfied() { | ||
552 | synchronized (monitor) { | ||
553 | return unsatisfiedDependencies.isEmpty(); | ||
554 | } | ||
555 | } | ||
556 | |||
501 | } \ No newline at end of file | 557 | } \ No newline at end of file |