FELIX-4011 move edge info tracking to component context
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1463768 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
index 2a1fbd0..e214400 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
@@ -851,6 +851,8 @@
m_dependenciesCollected = false;
}
+ abstract EdgeInfo getEdgeInfo( S implObject, DependencyManager<S, ?> dependencyManager);
+
abstract <T> void invokeUpdatedMethod( DependencyManager<S, T> dependencyManager, RefPair<T> refPair, int trackingCount );
abstract <T> void invokeBindMethod( DependencyManager<S, T> dependencyManager, RefPair<T> refPair, int trackingCount );
@@ -966,9 +968,10 @@
// If this component has got dependencies, create dependency managers for each one of them.
if ( metadata.getDependencies().size() != 0 )
{
+ int index = 0;
for ( ReferenceMetadata currentdependency: metadata.getDependencies() )
{
- DependencyManager depmanager = new DependencyManager( this, currentdependency );
+ DependencyManager depmanager = new DependencyManager( this, currentdependency, index++ );
depMgrList.add( depmanager );
}
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentContextImpl.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentContextImpl.java
index 9df5fb3..70a67ef 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentContextImpl.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentContextImpl.java
@@ -19,6 +19,7 @@
package org.apache.felix.scr.impl.manager;
+import java.util.Arrays;
import java.util.Dictionary;
import org.apache.felix.scr.component.ExtComponentContext;
@@ -35,14 +36,31 @@
*/
public class ComponentContextImpl implements ExtComponentContext, ComponentInstance {
- private AbstractComponentManager m_componentManager;
+ private final AbstractComponentManager m_componentManager;
+
+ private final EdgeInfo[] edgeInfos;
ComponentContextImpl( AbstractComponentManager componentManager )
{
m_componentManager = componentManager;
+ edgeInfos = new EdgeInfo[componentManager.getComponentMetadata().getDependencies().size()];
+ }
+
+ EdgeInfo getEdgeInfo(DependencyManager dm)
+ {
+ int index = dm.getIndex();
+ if (edgeInfos[index] == null)
+ {
+ edgeInfos[index] = new EdgeInfo();
+ }
+ return edgeInfos[index];
}
+ void clearEdgeInfos()
+ {
+ Arrays.fill( edgeInfos, null );
+ }
protected AbstractComponentManager getComponentManager()
{
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java
index 56fae25..8ff8956 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java
@@ -123,7 +123,7 @@
cm.activateInternal( getTrackingCount().get() );
instance = cm.getComponentInstance();
- if ( instance == null )
+ if ( instance == null || instance.getInstance() == null )
{
// activation failed, clean up component manager
cm.disposeInternal( ComponentConstants.DEACTIVATION_REASON_DISPOSED );
@@ -278,6 +278,11 @@
return true;
}
+ EdgeInfo getEdgeInfo( S implObject, DependencyManager<S, ?> dependencyManager)
+ {
+ return null;
+ }
+
<T> void invokeUpdatedMethod( DependencyManager<S, T> dependencyManager, RefPair<T> ref, int trackingCount )
{
}
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java
index a0dd549..e41c26a 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java
@@ -67,6 +67,8 @@
// Reference to the metadata
private final ReferenceMetadata m_dependencyMetadata;
+
+ private final int m_index;
private final AtomicReference<ServiceTracker<T, RefPair<T>>> trackerRef = new AtomicReference<ServiceTracker<T, RefPair<T>>>();
@@ -82,50 +84,16 @@
private boolean registered;
- private final Map<S, EdgeInfo> edgeInfoMap = new IdentityHashMap<S, EdgeInfo>( );
-
- private static class EdgeInfo
- {
- private int open = -1;
- private int close = -1;
- private CountDownLatch latch;
-
- public void setClose( int close )
- {
- this.close = close;
- }
-
- public CountDownLatch getLatch()
- {
- return latch;
- }
-
- public void setLatch( CountDownLatch latch )
- {
- this.latch = latch;
- }
-
- public void setOpen( int open )
- {
- this.open = open;
- }
-
- public boolean outOfRange( int trackingCount )
- {
- return (open != -1 && trackingCount < open)
- || (close != -1 && trackingCount > close);
- }
- }
-
/**
* Constructor that receives several parameters.
- *
* @param dependency An object that contains data about the dependency
+ * @param index TODO
*/
- DependencyManager( AbstractComponentManager<S> componentManager, ReferenceMetadata dependency )
+ DependencyManager( AbstractComponentManager<S> componentManager, ReferenceMetadata dependency, int index )
{
m_componentManager = componentManager;
m_dependencyMetadata = dependency;
+ m_index = index;
customizer = newCustomizer();
// dump the reference information if DEBUG is enabled
@@ -140,6 +108,11 @@
dependency.getCardinality(), dependency.getBind(), dependency.getUnbind() }, null );
}
}
+
+ int getIndex()
+ {
+ return m_index;
+ }
/**
* Initialize binding methods.
@@ -1383,14 +1356,9 @@
private EdgeInfo getEdgeInfo( S componentInstance )
{
- EdgeInfo info = edgeInfoMap.get( componentInstance );
- if ( info == null )
- {
- info = new EdgeInfo();
- edgeInfoMap.put( componentInstance, info );
- }
- return info;
+ return m_componentManager.getEdgeInfo( componentInstance, this );
}
+
/**
* Revoke the given bindings. This method cannot throw an exception since
* it must try to complete all that it can
@@ -1427,11 +1395,6 @@
latch.countDown();
}
- void cleanup( S componentInstance)
- {
- edgeInfoMap.remove( componentInstance );
- }
-
public void invokeBindMethodLate( final ServiceReference<T> ref, int trackingCount )
{
if ( !isSatisfied() )
@@ -1497,8 +1460,8 @@
{
synchronized ( trackerRef.get().tracked() )
{
- EdgeInfo info = edgeInfoMap.get( componentInstance );
- if (info != null && info.outOfRange( trackingCount ) )
+ EdgeInfo info = getEdgeInfo( componentInstance );
+ if (info.outOfRange( trackingCount ) )
{
//ignore events before open started or we will have duplicate binds.
return true;
@@ -1556,8 +1519,8 @@
}
synchronized ( trackerRef.get().tracked() )
{
- EdgeInfo info = edgeInfoMap.get( componentInstance );
- if (info != null && info.outOfRange( trackingCount ) )
+ EdgeInfo info = getEdgeInfo( componentInstance );
+ if (info.outOfRange( trackingCount ) )
{
//ignore events after close started or we will have duplicate unbinds.
return;
@@ -1608,9 +1571,9 @@
EdgeInfo info;
synchronized ( trackerRef.get().tracked() )
{
- info = edgeInfoMap.get( componentInstance );
+ info = getEdgeInfo( componentInstance );
}
- if (info != null && info.outOfRange( trackingCount ) )
+ if (info.outOfRange( trackingCount ) )
{
//wait for unbinds to complete
if (info.getLatch() != null)
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/EdgeInfo.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/EdgeInfo.java
new file mode 100644
index 0000000..eae4d9a
--- /dev/null
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/EdgeInfo.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.scr.impl.manager;
+
+import java.util.concurrent.CountDownLatch;
+
+class EdgeInfo
+{
+ private int open = -1;
+ private int close = -1;
+ private CountDownLatch latch;
+
+ public void setClose( int close )
+ {
+ this.close = close;
+ }
+
+ public CountDownLatch getLatch()
+ {
+ return latch;
+ }
+
+ public void setLatch( CountDownLatch latch )
+ {
+ this.latch = latch;
+ }
+
+ public void setOpen( int open )
+ {
+ this.open = open;
+ }
+
+ public boolean outOfRange( int trackingCount )
+ {
+ return (open != -1 && trackingCount < open)
+ || (close != -1 && trackingCount > close);
+ }
+}
\ No newline at end of file
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java
index a943602..33af8c3 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java
@@ -121,11 +121,11 @@
if ( m_implementationObject == null )
{
final ComponentContextImpl tmpContext = new ComponentContextImpl( this );
+ m_componentContext = tmpContext;
S tmpComponent = createImplementationObject( tmpContext, new SetImplementationObject<S>()
{
public void setImplementationObject( S implementationObject )
{
- m_componentContext = tmpContext;
m_implementationObject = implementationObject;
m_tmpImplementationObject = null;
}
@@ -172,7 +172,7 @@
m_tmpImplementationObject = implementationObject;
m_implementationObject = null;
disposeImplementationObject( implementationObject, m_componentContext, reason );
- m_implementationObject = null;
+ m_tmpImplementationObject = null;
cleanupImplementationObject( implementationObject );
log( LogService.LOG_DEBUG, "Unset and deconfigured implementation object for component {0} in deleteComponent for reason {1}", new Object[] { getName(), REASONS[ reason ] }, null );
m_componentContext = null;
@@ -342,12 +342,7 @@
protected void cleanupImplementationObject( Object implementationObject )
{
-
- for ( DependencyManager md: getReversedDependencyManagers() )
- {
- md.cleanup( implementationObject );
- }
-
+ m_componentContext.clearEdgeInfos();
}
State getSatisfiedState()
@@ -359,11 +354,10 @@
{
return Active.getInstance();
}
-
- <T> void invokeUpdatedMethod( DependencyManager<S, T> dependencyManager, RefPair<T> refPair, int trackingCount )
+
+ EdgeInfo getEdgeInfo( S implObject, DependencyManager<S, ?> dependencyManager)
{
- final S impl = ( m_tmpImplementationObject != null ) ? m_tmpImplementationObject : m_implementationObject;
- dependencyManager.invokeUpdatedMethod( impl, refPair, trackingCount );
+ return m_componentContext.getEdgeInfo( dependencyManager );
}
<T> void invokeBindMethod( DependencyManager<S, T> dependencyManager, RefPair<T> refPair, int trackingCount )
@@ -372,6 +366,12 @@
dependencyManager.invokeBindMethod( impl, refPair, trackingCount );
}
+ <T> void invokeUpdatedMethod( DependencyManager<S, T> dependencyManager, RefPair<T> refPair, int trackingCount )
+ {
+ final S impl = ( m_tmpImplementationObject != null ) ? m_tmpImplementationObject : m_implementationObject;
+ dependencyManager.invokeUpdatedMethod( impl, refPair, trackingCount );
+ }
+
<T> void invokeUnbindMethod( DependencyManager<S, T> dependencyManager, RefPair<T> oldRefPair, int trackingCount )
{
final S impl = ( m_tmpImplementationObject != null ) ? m_tmpImplementationObject : m_implementationObject;
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceFactoryComponentManager.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceFactoryComponentManager.java
index 749b7c1..92f5823 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceFactoryComponentManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceFactoryComponentManager.java
@@ -143,7 +143,6 @@
{
serviceContext.setImplementationObject( implementationObject );
serviceContexts.put( implementationObject, serviceContext );
-
}
@@ -201,6 +200,16 @@
}
}
+ EdgeInfo getEdgeInfo( S implObject, DependencyManager<S, ?> dependencyManager)
+ {
+ return serviceContexts.get( implObject ).getEdgeInfo( dependencyManager );
+ }
+
+ protected void cleanupImplementationObject( Object implementationObject )
+ {
+ serviceContexts.get( implementationObject ).clearEdgeInfos();
+ }
+
<T> void invokeBindMethod( DependencyManager<S, T> dependencyManager, RefPair<T> refPair, int trackingCount )
{
for ( S implementationObject : serviceContexts.keySet() )
diff --git a/scr/src/test/java/org/apache/felix/scr/integration/ComponentTestBase.java b/scr/src/test/java/org/apache/felix/scr/integration/ComponentTestBase.java
index b88ec11..df5e10d 100644
--- a/scr/src/test/java/org/apache/felix/scr/integration/ComponentTestBase.java
+++ b/scr/src/test/java/org/apache/felix/scr/integration/ComponentTestBase.java
@@ -114,7 +114,7 @@
protected static boolean NONSTANDARD_COMPONENT_FACTORY_BEHAVIOR = false;
protected volatile Log log;
-
+
//set to true to only get last 1000 lines of log.
protected static boolean restrictedLogging;
@@ -677,6 +677,8 @@
private volatile PrintStream m_realOut;
private volatile PrintStream m_realErr;
+ protected Throwable firstFrameworkThrowable;
+
private final boolean restrictedLogging;
private final String[] log = new String[1000];
private int i = 0;
@@ -732,6 +734,12 @@
{
return m_warnings;
}
+
+ Throwable getFirstFrameworkThrowable()
+ {
+ return firstFrameworkThrowable;
+ }
+
public void run()
@@ -767,6 +775,7 @@
sw.append( System.getProperty( "line.separator" ) );
PrintWriter pw = new PrintWriter( sw );
entry.getError().printStackTrace( pw );
+ pw.flush();
}
if ( restrictedLogging )
{
@@ -795,6 +804,10 @@
String msg = getFrameworkEventMessage( eventType );
int level = ( eventType == FrameworkEvent.ERROR ) ? LogService.LOG_ERROR : LogService.LOG_WARNING;
log( level, msg, event.getThrowable() );
+ if (event.getThrowable() != null && firstFrameworkThrowable == null)
+ {
+ firstFrameworkThrowable = event.getThrowable();
+ }
}
diff --git a/scr/src/test/java/org/apache/felix/scr/integration/Felix3680_2Test.java b/scr/src/test/java/org/apache/felix/scr/integration/Felix3680_2Test.java
index 701508e..c232ca6 100644
--- a/scr/src/test/java/org/apache/felix/scr/integration/Felix3680_2Test.java
+++ b/scr/src/test/java/org/apache/felix/scr/integration/Felix3680_2Test.java
@@ -63,19 +63,25 @@
@Test
- public void test_concurrent_injection_with_bundleContext()
+ public void test_concurrent_injection_with_bundleContext() throws Throwable
{
- final Component main = findComponentByName( "org.apache.felix.scr.integration.components.felix3680_2.Main" );
- TestCase.assertNotNull( main );
- main.enable();
-
- delay( 30 );
- main.disable();
- delay(); //async deactivate
- for ( Iterator it = log.foundWarnings().iterator(); it.hasNext(); )
+ for ( int i = 0; i < 6; i++ )
{
- String message = ( String ) it.next();
- TestCase.fail( "unexpected warning or error logged: " + message );
+ final Component main = findComponentByName( "org.apache.felix.scr.integration.components.felix3680_2.Main" );
+ TestCase.assertNotNull( main );
+ main.enable();
+ delay( 5 ); //run test for 30 seconds
+ main.disable();
+ delay(); //async deactivate
+ if ( log.getFirstFrameworkThrowable() != null )
+ {
+ throw log.getFirstFrameworkThrowable();
+ }
+ for ( Iterator it = log.foundWarnings().iterator(); it.hasNext(); )
+ {
+ String message = ( String ) it.next();
+ TestCase.fail( "unexpected warning or error logged: " + message );
+ }
}
}
}
diff --git a/scr/src/test/java/org/apache/felix/scr/integration/components/felix3680_2/Main.java b/scr/src/test/java/org/apache/felix/scr/integration/components/felix3680_2/Main.java
index ecb6cb2..91539ac 100644
--- a/scr/src/test/java/org/apache/felix/scr/integration/components/felix3680_2/Main.java
+++ b/scr/src/test/java/org/apache/felix/scr/integration/components/felix3680_2/Main.java
@@ -202,19 +202,29 @@
new Thread( this ).start();
}
- void stop()
+ void stop() throws InterruptedException
{
- running = false;
+ synchronized ( this )
+ {
+ running = false;
+ }
+ if (m_enabledLatch != null)
+ {
+ m_enabledLatch.await( 1, TimeUnit.MILLISECONDS );
+ }
+ if (m_disabledLatch != null)
+ {
+ m_disabledLatch.await( 1, TimeUnit.MILLISECONDS );
+ }
}
public void run()
{
int loop = 0;
- while ( running )
+ while ( iterate() )
{
- m_enabledLatch = new CountDownLatch( 11 ); // 10 for registrations of B,C,D,E,F,G,H,I,J,K + 1 for Main.bindA
- m_disabledLatch = new CountDownLatch( 11 ); // 10 for unregistrations of B,C,D,E,F,G,H,I,J,K + 1 for Main.unbindA
+
RegistrationHelper registry = new RegistrationHelper();
registry.registerBCDEFGHIJK( m_exec );
@@ -258,6 +268,17 @@
}
}
+
+ private synchronized boolean iterate()
+ {
+ if ( running )
+ {
+ m_enabledLatch = new CountDownLatch( 11 ); // 10 for registrations of B,C,D,E,F,G,H,I,J,K + 1 for Main.bindA
+ m_disabledLatch = new CountDownLatch( 11 ); // 10 for unregistrations of B,C,D,E,F,G,H,I,J,K + 1 for Main.unbindA
+ }
+ return running;
+ }
+
private String dumpThreads()
{
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();