You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by pd...@apache.org on 2014/03/18 22:40:06 UTC
svn commit: r1579057 -
/felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/ComponentImpl.java
Author: pderop
Date: Tue Mar 18 21:40:05 2014
New Revision: 1579057
URL: http://svn.apache.org/r1579057
Log:
The state specific code which was done in DependencyImpl is now implemented in the ComponentImpl.handleAdded/handleChanged/handleRemoved methods.
All dependency events are now stored in the component m_dependencyEvents map.
Fixed a bug in allRequiredAvailable() method.
Added invokeRemoveOptionalDependencies() method, which is now called from performTransition method.
Modified:
felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/ComponentImpl.java
Modified: felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/ComponentImpl.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/ComponentImpl.java?rev=1579057&r1=1579056&r2=1579057&view=diff
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/ComponentImpl.java (original)
+++ felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/ComponentImpl.java Tue Mar 18 21:40:05 2014
@@ -12,7 +12,9 @@ import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Properties;
+import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicLong;
@@ -29,6 +31,7 @@ import dm.admin.ComponentDeclaration;
import dm.admin.ComponentDependencyDeclaration;
import dm.context.ComponentContext;
import dm.context.DependencyContext;
+import dm.context.Event;
public class ComponentImpl implements Component, ComponentContext, ComponentDeclaration {
private static final ServiceRegistration NULL_REGISTRATION = (ServiceRegistration) Proxy
@@ -54,6 +57,7 @@ public class ComponentImpl implements Co
private final Map m_autoConfigInstance = new ConcurrentHashMap();
private final long m_id;
private static AtomicLong m_idGenerator = new AtomicLong();
+ private final Map<DependencyContext, ConcurrentSkipListSet<Event>> m_dependencyEvents = new ConcurrentHashMap<>();
// configuration (static)
private volatile String m_callbackInit;
@@ -126,6 +130,7 @@ public class ComponentImpl implements Co
List<DependencyContext> instanceBoundDeps = new ArrayList();
for (Dependency d : dependencies) {
DependencyContext dc = (DependencyContext) d;
+ m_dependencyEvents.put(dc, new ConcurrentSkipListSet<Event>());
m_dependencies.add(dc);
dc.add(ComponentImpl.this);
if (!(m_state == ComponentState.INACTIVE)) {
@@ -150,6 +155,7 @@ public class ComponentImpl implements Co
dc.stop();
}
m_dependencies.remove(d);
+ m_dependencyEvents.remove(d);
dc.remove(ComponentImpl.this);
handleChange();
}
@@ -165,7 +171,6 @@ public class ComponentImpl implements Co
handleChange();
}
});
-
}
public void stop() {
@@ -195,27 +200,92 @@ public class ComponentImpl implements Co
}
@Override
- public void handleChange() {
- ComponentState oldState;
- ComponentState newState;
- do {
- oldState = m_state;
- newState = calculateNewState(oldState);
- m_state = newState;
- }
- while (performTransition(oldState, newState));
- }
-
- @Override
- public void updateInstance(DependencyContext d) {
- if (d.isAutoConfig()) {
- configureImplementation(d.getAutoConfigType(), d.getAutoConfigInstance(), d.getAutoConfigName());
- }
- if (d.isPropagated() && m_registration != null) {
- m_registration.setProperties(calculateServiceProperties());
- }
+ public void handleAdded(DependencyContext dc, Event e) {
+ Set<Event> dependencyEvents = m_dependencyEvents.get(dc);
+ dependencyEvents.add(e);
+ dc.setAvailable(true);
+
+ switch (m_state) {
+ case WAITING_FOR_REQUIRED:
+ if (dc.isRequired())
+ handleChange();
+ break;
+ case INSTANTIATED_AND_WAITING_FOR_REQUIRED:
+ if (!dc.isInstanceBound()) {
+ if (dc.isRequired()) {
+ dc.invokeAdd(e);
+ }
+ updateInstance(dc);
+ }
+ else {
+ if (dc.isRequired())
+ handleChange();
+ }
+ break;
+ case TRACKING_OPTIONAL:
+ dc.invokeAdd(e);
+ updateInstance(dc);
+ break;
+ default:
+ }
}
+ @Override
+ public void handleChanged(DependencyContext dc, Event e) {
+ Set<Event> dependencyEvents = m_dependencyEvents.get(dc);
+ dependencyEvents.remove(e);
+ dependencyEvents.add(e);
+
+ switch (m_state) {
+ case TRACKING_OPTIONAL:
+ dc.invokeChange(e);
+ updateInstance(dc);
+ break;
+
+ case INSTANTIATED_AND_WAITING_FOR_REQUIRED:
+ if (!dc.isInstanceBound()) {
+ dc.invokeChange(e);
+ updateInstance(dc);
+ }
+ break;
+ }
+ }
+
+ @Override
+ public void handleRemoved(DependencyContext dc, Event e) {
+ Set<Event> dependencyEvents = m_dependencyEvents.get(dc);
+ dc.setAvailable(!(dependencyEvents.contains(e) && dependencyEvents.size() == 1));
+ handleChange();
+
+ // Now, really remove the dependency event, because next, we'll possibly invoke updateInstance, which will
+ // trigger getAutoConfigInstance, and at this point, we don't want to return the removed service, which might
+ // be the highest ranked service.
+ dependencyEvents.remove(e);
+
+ // Depending on the state, we possible have to invoke the callbacks and update the component instance.
+ switch (m_state) {
+ case INSTANTIATED_AND_WAITING_FOR_REQUIRED:
+ if (! dc.isInstanceBound()) {
+ if (dc.isRequired()) {
+ dc.invokeRemove(e);
+ }
+ updateInstance(dc);
+ }
+ break;
+ case TRACKING_OPTIONAL:
+ dc.invokeRemove(e);
+ updateInstance(dc);
+ break;
+ default:
+ }
+ }
+
+ @Override
+ public Event getDependencyEvent(DependencyContext dc) {
+ ConcurrentSkipListSet<Event> events = m_dependencyEvents.get(dc);
+ return events.size() > 0 ? events.last() : null;
+ }
+
public Component setAutoConfig(Class clazz, boolean autoConfig) {
m_autoConfig.put(clazz, Boolean.valueOf(autoConfig));
return this;
@@ -236,6 +306,17 @@ public class ComponentImpl implements Co
return (String) m_autoConfigInstance.get(clazz);
}
+ private void handleChange() {
+ ComponentState oldState;
+ ComponentState newState;
+ do {
+ oldState = m_state;
+ newState = calculateNewState(oldState);
+ m_state = newState;
+ }
+ while (performTransition(oldState, newState));
+ }
+
/** Based on the current state, calculate the new state. */
private ComponentState calculateNewState(ComponentState currentState) {
if (currentState == INACTIVE) {
@@ -269,41 +350,6 @@ public class ComponentImpl implements Co
return currentState;
}
- private boolean allRequiredAvailable() {
- boolean available = true;
- for (DependencyContext d : m_dependencies) {
- if (d.isRequired() && !d.isInstanceBound()) {
- if (!d.isAvailable()) {
- available = false;
- break;
- }
- }
- }
- return available;
- }
-
- private boolean allInstanceBoundAvailable() {
- boolean available = true;
- for (DependencyContext d : m_dependencies) {
- if (d.isRequired() && d.isInstanceBound()) {
- if (!d.isAvailable()) {
- available = false;
- break;
- }
- }
- }
- return available;
- }
-
- private boolean someDependenciesNeedInstance() {
- for (DependencyContext d : m_dependencies) {
- if (d.needsInstance()) {
- return true;
- }
- }
- return false;
- }
-
/** Perform all the actions associated with state transitions. Returns true if a transition was performed. */
private boolean performTransition(ComponentState oldState, ComponentState newState) {
// System.out.println("transition from " + oldState + " to " + newState);
@@ -330,7 +376,8 @@ public class ComponentImpl implements Co
return true;
}
if (oldState == ComponentState.TRACKING_OPTIONAL && newState == ComponentState.INSTANTIATED_AND_WAITING_FOR_REQUIRED) {
- unregisterService();
+ unregisterService();
+ invokeRemoveOptionalDependencies();
invoke(m_callbackStop);
invokeRemoveInstanceBoundDependencies();
notifyListeners(newState);
@@ -354,6 +401,50 @@ public class ComponentImpl implements Co
return false;
}
+ private boolean allRequiredAvailable() {
+ boolean available = true;
+ for (DependencyContext d : m_dependencies) {
+ if (d.isRequired() && !d.isInstanceBound()) {
+ if (!d.isAvailable()) {
+ available = false;
+ break;
+ }
+ }
+ }
+ return available;
+ }
+
+ private boolean allInstanceBoundAvailable() {
+ boolean available = true;
+ for (DependencyContext d : m_dependencies) {
+ if (d.isRequired() && d.isInstanceBound()) {
+ if (!d.isAvailable()) {
+ available = false;
+ break;
+ }
+ }
+ }
+ return available;
+ }
+
+ private boolean someDependenciesNeedInstance() {
+ for (DependencyContext d : m_dependencies) {
+ if (d.needsInstance()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void updateInstance(DependencyContext d) {
+ if (d.isAutoConfig()) {
+ configureImplementation(d.getAutoConfigType(), d.getAutoConfigInstance(), d.getAutoConfigName());
+ }
+ if (d.isPropagated() && m_registration != null) {
+ m_registration.setProperties(calculateServiceProperties());
+ }
+ }
+
private void startDependencies(List<DependencyContext> dependencies) {
// Start first optional dependencies first.
List<DependencyContext> requiredDeps = new ArrayList();
@@ -535,7 +626,9 @@ public class ComponentImpl implements Co
private void invokeAddRequiredDependencies() {
for (DependencyContext d : m_dependencies) {
if (d.isRequired() && !d.isInstanceBound()) {
- d.invokeAdd();
+ for (Event e : m_dependencyEvents.get(d)) {
+ d.invokeAdd(e);
+ }
}
}
}
@@ -559,7 +652,9 @@ public class ComponentImpl implements Co
private void invokeAddRequiredInstanceBoundDependencies() {
for (DependencyContext d : m_dependencies) {
if (d.isRequired() && d.isInstanceBound()) {
- d.invokeAdd();
+ for (Event e : m_dependencyEvents.get(d)) {
+ d.invokeAdd(e);
+ }
}
}
}
@@ -567,23 +662,39 @@ public class ComponentImpl implements Co
private void invokeAddOptionalDependencies() {
for (DependencyContext d : m_dependencies) {
if (! d.isRequired()) {
- d.invokeAdd();
+ for (Event e : m_dependencyEvents.get(d)) {
+ d.invokeAdd(e);
+ }
}
}
}
- private void invokeRemoveRequiredDependencies() {
+ private void invokeRemoveRequiredDependencies() {
for (DependencyContext d : m_dependencies) {
- if (!d.isInstanceBound()) {
- d.invokeRemove();
+ if (!d.isInstanceBound() && d.isRequired()) {
+ for (Event e : m_dependencyEvents.get(d)) {
+ d.invokeRemove(e);
+ }
}
}
}
+ private void invokeRemoveOptionalDependencies() {
+ for (DependencyContext d : m_dependencies) {
+ if (!d.isInstanceBound() && ! d.isRequired()) {
+ for (Event e : m_dependencyEvents.get(d)) {
+ d.invokeRemove(e);
+ }
+ }
+ }
+ }
+
private void invokeRemoveInstanceBoundDependencies() {
for (DependencyContext d : m_dependencies) {
if (d.isInstanceBound()) {
- d.invokeRemove();
+ for (Event e : m_dependencyEvents.get(d)) {
+ d.invokeRemove(e);
+ }
}
}
}
@@ -642,10 +753,6 @@ public class ComponentImpl implements Co
return m_state == TRACKING_OPTIONAL;
}
- public ComponentState getComponentState() {
- return m_state;
- }
-
@Override
public Component add(final ComponentStateListener l) {
m_listeners.add(l);