Skip to content

Commit ec96dd3

Browse files
committed
Add test for min timeout for change count update
Also fix logging for when timeout is less than 1
1 parent e786254 commit ec96dd3

2 files changed

Lines changed: 119 additions & 24 deletions

File tree

scr/src/main/java/org/apache/felix/scr/impl/ComponentRegistry.java

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ public class ComponentRegistry
138138
public ComponentRegistry(final ScrConfiguration scrConfiguration, final ScrLogger logger, final ScheduledExecutorService componentActor )
139139
{
140140
m_configuration = scrConfiguration;
141-
m_updateChangeCountPropertyTask = new UpdateChangeCountProperty(m_configuration.serviceChangecountTimeout());
141+
m_updateChangeCountPropertyTask = new UpdateChangeCountProperty(m_configuration.serviceChangecountTimeout(), logger, componentActor);
142142
m_logger = logger;
143143
m_componentActor = componentActor;
144144
m_componentHoldersByName = new HashMap<>();
@@ -708,38 +708,43 @@ public void unregisterRegionConfigurationSupport(
708708

709709
}
710710

711-
private final AtomicLong changeCount = new AtomicLong();
712-
713-
public Dictionary<String, Object> getServiceRegistrationProperties()
711+
Dictionary<String, Object> getServiceRegistrationProperties()
714712
{
715-
final Dictionary<String, Object> props = new Hashtable<>();
716-
props.put(PROP_CHANGECOUNT, this.changeCount.get());
717-
718-
return props;
713+
return m_updateChangeCountPropertyTask.getServiceRegistrationProperties();
719714
}
720715

721-
public void setRegistration(final ServiceRegistration<ServiceComponentRuntime> reg)
716+
public void setRegistration(final ServiceRegistration<ServiceComponentRuntime> reg)
722717
{
723718
m_updateChangeCountPropertyTask.setRegistration(reg);
724719
m_updateChangeCountPropertyTask.schedule();
725720
}
726721

727-
class UpdateChangeCountProperty implements Runnable {
728-
// TODO Is 100 ms an appropriate minimum?
729-
private static final long MIN_ALLOWED_DELAY = 100;
722+
public void updateChangeCount()
723+
{
724+
m_updateChangeCountPropertyTask.updateChangeCount();
725+
}
726+
727+
static class UpdateChangeCountProperty implements Runnable {
728+
// TODO 1 seems really low?
729+
private static final long MIN_ALLOWED_DELAY = 1;
730+
private final AtomicLong changeCount = new AtomicLong();
730731
private volatile ServiceRegistration<ServiceComponentRuntime> registration;
731732
private final long maxNumberOfNoChanges;
732733
private final long delay;
734+
private final ScrLogger logger;
735+
private final ScheduledExecutorService executor;
733736

734737
// guarded by this
735738
private int noChangesCount = 0;
736739
// guarded by this
737740
private ScheduledFuture<?> scheduledFuture = null;
738741

739-
public UpdateChangeCountProperty(long delay)
742+
UpdateChangeCountProperty(long delay, ScrLogger logger, ScheduledExecutorService executor)
740743
{
744+
this.logger = logger;
745+
this.executor = executor;
741746
if (delay < MIN_ALLOWED_DELAY) {
742-
m_logger.log(Level.INFO,
747+
logger.log(Level.INFO,
743748
"The service change count timeout {0} is less than the allowable minimum {1}. Using the allowable minimum instead.", null,
744749
delay, MIN_ALLOWED_DELAY);
745750
delay = MIN_ALLOWED_DELAY;
@@ -750,19 +755,31 @@ public UpdateChangeCountProperty(long delay)
750755
maxNumberOfNoChanges = Long.max(10000 / delay, 1);
751756
}
752757

753-
public void setRegistration(ServiceRegistration<ServiceComponentRuntime> reg)
758+
void setRegistration(ServiceRegistration<ServiceComponentRuntime> reg)
754759
{
755760
this.registration = reg;
756761
}
757762

758-
public synchronized void schedule()
763+
Dictionary<String, Object> getServiceRegistrationProperties()
764+
{
765+
final Dictionary<String, Object> props = new Hashtable<>();
766+
props.put(PROP_CHANGECOUNT, this.changeCount.get());
767+
768+
return props;
769+
}
770+
771+
public void updateChangeCount() {
772+
this.changeCount.incrementAndGet();
773+
schedule();
774+
}
775+
synchronized void schedule()
759776
{
760777
// reset noChangesCount to ensure task runs at least once more if it exists
761778
noChangesCount = 0;
762779
if (scheduledFuture != null) {
763780
return;
764781
}
765-
scheduledFuture = m_componentActor.scheduleWithFixedDelay(this , delay, delay, TimeUnit.MILLISECONDS);
782+
scheduledFuture = executor.scheduleWithFixedDelay(this , delay, delay, TimeUnit.MILLISECONDS);
766783
}
767784

768785
@Override
@@ -802,16 +819,10 @@ public void run()
802819
}
803820
}
804821
} catch (Exception e) {
805-
m_logger.log(Level.WARN,
822+
logger.log(Level.WARN,
806823
"Service changecount update for {0} had a problem", e,
807824
registration.getReference());
808825
}
809826
}
810827
}
811-
812-
public void updateChangeCount()
813-
{
814-
this.changeCount.incrementAndGet();
815-
m_updateChangeCountPropertyTask.schedule();
816-
}
817828
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.felix.scr.integration;
20+
21+
import static org.junit.Assert.assertEquals;
22+
import static org.ops4j.pax.exam.CoreOptions.systemProperty;
23+
24+
import org.junit.Before;
25+
import org.junit.Test;
26+
import org.junit.runner.RunWith;
27+
import org.ops4j.pax.exam.Configuration;
28+
import org.ops4j.pax.exam.Option;
29+
import org.ops4j.pax.exam.OptionUtils;
30+
import org.ops4j.pax.exam.junit.PaxExam;
31+
import org.osgi.framework.BundleException;
32+
import org.osgi.framework.Constants;
33+
import org.osgi.framework.InvalidSyntaxException;
34+
import org.osgi.framework.ServiceReference;
35+
import org.osgi.service.component.runtime.ServiceComponentRuntime;
36+
37+
@RunWith(PaxExam.class)
38+
public class GithubPR486Test extends ComponentTestBase
39+
{
40+
41+
// test min timeout checking
42+
private static final long DS_SERVICE_CHANGECOUNT_TIMEOUT = 0;
43+
44+
static
45+
{
46+
descriptorFile = "/integration_test_simple_components.xml";
47+
// uncomment to enable debugging of this test class
48+
//paxRunnerVmOption = DEBUG_VM_OPTION;
49+
}
50+
51+
@Configuration
52+
public static Option[] configuration()
53+
{
54+
return OptionUtils.combine(ComponentTestBase.configuration(),
55+
systemProperty( "ds.service.changecount.timeout" ).value( Long.toString(DS_SERVICE_CHANGECOUNT_TIMEOUT) ));
56+
}
57+
58+
59+
private ServiceReference<ServiceComponentRuntime> scrRef;
60+
@Before
61+
public void addServiceListener() throws InvalidSyntaxException
62+
{
63+
scrRef = bundleContext.getServiceReference(ServiceComponentRuntime.class);
64+
}
65+
66+
@Test
67+
public void verify_changecount_updates_with_min_timeout() throws InterruptedException, BundleException
68+
{
69+
// Wait a second the changecount timeout`to account for the asynchronous service.changecount property update
70+
Thread.sleep(1000);
71+
72+
// Check that the service.changecount update was recorded
73+
assertEquals(13L, scrRef.getProperty(Constants.SERVICE_CHANGECOUNT));
74+
75+
// Trigger a change by stopping the bundle with components
76+
bundle.stop();
77+
78+
// Wait a second the changecount timeout`to account for the asynchronous service.changecount property update
79+
Thread.sleep(1000);
80+
81+
// Check that another service.changecount update was recorded
82+
assertEquals(26L, scrRef.getProperty(Constants.SERVICE_CHANGECOUNT));
83+
}
84+
}

0 commit comments

Comments
 (0)