Skip to content

Commit d1c738a

Browse files
committed
Cancel scheduled task for change count update when inactive
After at least 10 seconds of inactivity this will cancel the ScheduledFuture for updating the change count service property. If later the change count is updated then a new ScheduledFuture is submitted.
1 parent a07a307 commit d1c738a

1 file changed

Lines changed: 55 additions & 8 deletions

File tree

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

Lines changed: 55 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,12 @@
3131
import java.util.concurrent.ConcurrentHashMap;
3232
import java.util.concurrent.ConcurrentMap;
3333
import java.util.concurrent.ScheduledExecutorService;
34+
import java.util.concurrent.ScheduledFuture;
3435
import java.util.concurrent.TimeUnit;
36+
import java.util.concurrent.atomic.AtomicInteger;
3537
import java.util.concurrent.atomic.AtomicLong;
38+
import java.util.concurrent.atomic.AtomicReference;
39+
import java.util.function.UnaryOperator;
3640

3741
import org.apache.felix.scr.impl.inject.ComponentMethods;
3842
import org.apache.felix.scr.impl.inject.internal.ComponentMethodsImpl;
@@ -132,9 +136,12 @@ public class ComponentRegistry
132136

133137
private final ScheduledExecutorService m_componentActor;
134138

139+
private final UpdateChangeCountProperty m_updateChangeCountPropertyTask;
140+
135141
public ComponentRegistry(final ScrConfiguration scrConfiguration, final ScrLogger logger, final ScheduledExecutorService componentActor )
136142
{
137143
m_configuration = scrConfiguration;
144+
m_updateChangeCountPropertyTask = new UpdateChangeCountProperty(m_configuration.serviceChangecountTimeout());
138145
m_logger = logger;
139146
m_componentActor = componentActor;
140147
m_componentHoldersByName = new HashMap<>();
@@ -716,44 +723,84 @@ public Dictionary<String, Object> getServiceRegistrationProperties()
716723

717724
public void setRegistration(final ServiceRegistration<ServiceComponentRuntime> reg)
718725
{
719-
long delay = m_configuration.serviceChangecountTimeout();
720-
m_componentActor.scheduleWithFixedDelay(new UpdateChangeCountProperty(reg), delay, delay, TimeUnit.MILLISECONDS);
726+
m_updateChangeCountPropertyTask.setRegistration(reg);
727+
m_updateChangeCountPropertyTask.schedule();
721728
}
722729

723730
class UpdateChangeCountProperty implements Runnable {
724-
private final ServiceRegistration<ServiceComponentRuntime> registration;
731+
private volatile ServiceRegistration<ServiceComponentRuntime> registration;
732+
private final long maxNumberOfNoChanges;
733+
private final long delay;
734+
735+
// guarded by this
736+
private int noChangesCount = 0;
737+
// guarded by this
738+
private ScheduledFuture<?> scheduledFuture = null;
725739

726-
public UpdateChangeCountProperty(ServiceRegistration<ServiceComponentRuntime> registration)
740+
public UpdateChangeCountProperty(long delay)
727741
{
728-
this.registration = registration;
742+
this.delay = delay;
743+
// calculate the max number of no changes; must be at least 1 to avoid missing events
744+
maxNumberOfNoChanges = Long.max(10000 / delay, 1);
745+
}
746+
747+
public void setRegistration(ServiceRegistration<ServiceComponentRuntime> reg)
748+
{
749+
this.registration = reg;
750+
}
751+
752+
public synchronized void schedule()
753+
{
754+
// reset noChangesCount to ensure task runs at least once more if it exists
755+
noChangesCount = 0;
756+
if (scheduledFuture != null) {
757+
return;
758+
}
759+
scheduledFuture = m_componentActor.scheduleWithFixedDelay(this , delay, delay, TimeUnit.MILLISECONDS);
729760
}
730761

731762
@Override
732763
public void run()
733764
{
765+
ServiceRegistration<ServiceComponentRuntime> currentReg = registration;
766+
if (currentReg == null) {
767+
return;
768+
}
734769
try {
735-
Long registeredChangeCount = (Long) registration.getReference().getProperty(PROP_CHANGECOUNT);
770+
Long registeredChangeCount = (Long) currentReg.getReference().getProperty(PROP_CHANGECOUNT);
736771
if (registeredChangeCount == null || registeredChangeCount.longValue() != changeCount.get()) {
737772
try
738773
{
739-
registration.setProperties(getServiceRegistrationProperties());
774+
currentReg.setProperties(getServiceRegistrationProperties());
740775
}
741776
catch ( final IllegalStateException ise)
742777
{
743778
// we ignore this as this might happen on shutdown
744779
}
780+
} else {
781+
synchronized (this) {
782+
noChangesCount++;
783+
if (noChangesCount > maxNumberOfNoChanges) {
784+
// haven't had any changes for max number of tries;
785+
// cancel the scheduled future if it exists.
786+
if (scheduledFuture != null) {
787+
scheduledFuture.cancel(false);
788+
scheduledFuture = null;
789+
}
790+
}
791+
}
745792
}
746793
} catch (Exception e) {
747794
m_logger.log(Level.WARN,
748795
"Service changecount update for {0} had a problem", e,
749796
registration.getReference());
750797
}
751798
}
752-
753799
}
754800

755801
public void updateChangeCount()
756802
{
757803
this.changeCount.incrementAndGet();
804+
m_updateChangeCountPropertyTask.schedule();
758805
}
759806
}

0 commit comments

Comments
 (0)