Skip to content

Commit d234fc6

Browse files
committed
Cancel change count task on inactivity
Final changes from apache/felix-dev#486
1 parent 6289305 commit d234fc6

1 file changed

Lines changed: 91 additions & 22 deletions

File tree

dev/com.ibm.ws.org.apache.felix.scr/src/org/apache/felix/scr/impl/ComponentRegistry.java

Lines changed: 91 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
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;
3536
import java.util.concurrent.atomic.AtomicLong;
3637

@@ -132,9 +133,12 @@ public class ComponentRegistry
132133

133134
private final ScheduledExecutorService m_componentActor;
134135

136+
private final UpdateChangeCountProperty m_updateChangeCountPropertyTask;
137+
135138
public ComponentRegistry(final ScrConfiguration scrConfiguration, final ScrLogger logger, final ScheduledExecutorService componentActor )
136139
{
137140
m_configuration = scrConfiguration;
141+
m_updateChangeCountPropertyTask = new UpdateChangeCountProperty(m_configuration.serviceChangecountTimeout(), logger, componentActor);
138142
m_logger = logger;
139143
m_componentActor = componentActor;
140144
m_componentHoldersByName = new HashMap<>();
@@ -704,56 +708,121 @@ public void unregisterRegionConfigurationSupport(
704708

705709
}
706710

707-
private final AtomicLong changeCount = new AtomicLong();
708-
709-
public Dictionary<String, Object> getServiceRegistrationProperties()
711+
Dictionary<String, Object> getServiceRegistrationProperties()
710712
{
711-
final Dictionary<String, Object> props = new Hashtable<>();
712-
props.put(PROP_CHANGECOUNT, this.changeCount.get());
713+
return m_updateChangeCountPropertyTask.getServiceRegistrationProperties();
714+
}
713715

714-
return props;
716+
public void setRegistration(final ServiceRegistration<ServiceComponentRuntime> reg)
717+
{
718+
m_updateChangeCountPropertyTask.setRegistration(reg);
719+
m_updateChangeCountPropertyTask.schedule();
715720
}
716721

717-
public void setRegistration(final ServiceRegistration<ServiceComponentRuntime> reg)
722+
public void updateChangeCount()
718723
{
719-
long delay = m_configuration.serviceChangecountTimeout();
720-
m_componentActor.scheduleWithFixedDelay(new UpdateChangeCountProperty(reg), delay, delay, TimeUnit.MILLISECONDS);
724+
m_updateChangeCountPropertyTask.updateChangeCount();
721725
}
722726

723-
class UpdateChangeCountProperty implements Runnable {
724-
private final ServiceRegistration<ServiceComponentRuntime> registration;
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();
731+
private volatile ServiceRegistration<ServiceComponentRuntime> registration;
732+
private final long maxNumberOfNoChanges;
733+
private final long delay;
734+
private final ScrLogger logger;
735+
private final ScheduledExecutorService executor;
736+
737+
// guarded by this
738+
private int noChangesCount = 0;
739+
// guarded by this
740+
private ScheduledFuture<?> scheduledFuture = null;
741+
742+
UpdateChangeCountProperty(long delay, ScrLogger logger, ScheduledExecutorService executor)
743+
{
744+
this.logger = logger;
745+
this.executor = executor;
746+
if (delay < MIN_ALLOWED_DELAY) {
747+
logger.log(Level.INFO,
748+
"The service change count timeout {0} is less than the allowable minimum {1}. Using the allowable minimum instead.", null,
749+
delay, MIN_ALLOWED_DELAY);
750+
delay = MIN_ALLOWED_DELAY;
751+
}
752+
this.delay = delay;
753+
// Calculate the max number of no changes; must be at least 1 to avoid missing events
754+
// The calculation is intended to let at least 10 seconds pass before canceling the scheduledFuture
755+
maxNumberOfNoChanges = Long.max(10000 / delay, 1);
756+
}
757+
758+
void setRegistration(ServiceRegistration<ServiceComponentRuntime> reg)
759+
{
760+
this.registration = reg;
761+
}
762+
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+
}
725770

726-
public UpdateChangeCountProperty(ServiceRegistration<ServiceComponentRuntime> registration)
771+
public void updateChangeCount() {
772+
this.changeCount.incrementAndGet();
773+
schedule();
774+
}
775+
synchronized void schedule()
727776
{
728-
this.registration = registration;
777+
// reset noChangesCount to ensure task runs at least once more if it exists
778+
noChangesCount = 0;
779+
if (scheduledFuture != null) {
780+
return;
781+
}
782+
scheduledFuture = executor.scheduleWithFixedDelay(this , delay, delay, TimeUnit.MILLISECONDS);
729783
}
730784

731785
@Override
732786
public void run()
733787
{
788+
ServiceRegistration<ServiceComponentRuntime> currentReg = registration;
789+
if (currentReg == null) {
790+
return;
791+
}
734792
try {
735-
Long registeredChangeCount = (Long) registration.getReference().getProperty(PROP_CHANGECOUNT);
793+
Long registeredChangeCount = null;
794+
try {
795+
registeredChangeCount = (Long) currentReg.getReference().getProperty(PROP_CHANGECOUNT);
796+
} catch ( final IllegalStateException ise) {
797+
// we ignore this as this might happen on shutdown
798+
}
736799
if (registeredChangeCount == null || registeredChangeCount.longValue() != changeCount.get()) {
737800
try
738801
{
739-
registration.setProperties(getServiceRegistrationProperties());
802+
currentReg.setProperties(getServiceRegistrationProperties());
740803
}
741804
catch ( final IllegalStateException ise)
742805
{
743806
// we ignore this as this might happen on shutdown
744807
}
808+
} else {
809+
synchronized (this) {
810+
noChangesCount++;
811+
if (noChangesCount > maxNumberOfNoChanges) {
812+
// haven't had any changes for max number of tries;
813+
// cancel the scheduled future if it exists.
814+
if (scheduledFuture != null) {
815+
scheduledFuture.cancel(false);
816+
scheduledFuture = null;
817+
}
818+
}
819+
}
745820
}
746821
} catch (Exception e) {
747-
m_logger.log(Level.WARN,
822+
logger.log(Level.WARN,
748823
"Service changecount update for {0} had a problem", e,
749824
registration.getReference());
750825
}
751826
}
752-
753-
}
754-
755-
public void updateChangeCount()
756-
{
757-
this.changeCount.incrementAndGet();
758827
}
759828
}

0 commit comments

Comments
 (0)