Fix SpringOpenTTP thread leak
- It was creating 2 theads everytime a Device connected.
Now uses thread pool shared across Devices, where threads will die out on idle.
Should resolve ONOS-3579
Change-Id: I490b2ef677853677fbd151af27f6ac2be563774c
diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTP.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTP.java
index 4f52e16..ca50df8 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTP.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTP.java
@@ -15,6 +15,7 @@
*/
package org.onosproject.driver.pipeline;
+import static java.util.concurrent.Executors.newScheduledThreadPool;
import static org.onlab.util.Tools.groupedThreads;
import static org.slf4j.LoggerFactory.getLogger;
@@ -86,8 +87,8 @@
import java.util.List;
import java.util.Objects;
import java.util.Set;
-import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@@ -97,6 +98,11 @@
public class SpringOpenTTP extends AbstractHandlerBehaviour
implements Pipeliner {
+ /**
+ * GroupCheck delay.
+ */
+ private static final int CHECK_DELAY = 500;
+
// Default table ID - compatible with CpqD switch
private static final int TABLE_VLAN = 0;
private static final int TABLE_TMAC = 1;
@@ -118,7 +124,7 @@
protected int aclTableId = TABLE_ACL;
protected int srcMacTableId = TABLE_SMAC;
- protected final Logger log = getLogger(getClass());
+ private static final Logger log = getLogger(SpringOpenTTP.class);
private ServiceDirectory serviceDirectory;
private FlowRuleService flowRuleService;
@@ -130,11 +136,19 @@
private Cache<GroupKey, NextObjective> pendingGroups;
- private ScheduledExecutorService groupChecker = Executors
- .newScheduledThreadPool(2,
- groupedThreads("onos/pipeliner",
- "spring-open-%d",
- log));
+ private static final ScheduledExecutorService GROUP_CHECKER
+ = newScheduledThreadPool(2,
+ groupedThreads("onos/pipeliner",
+ "spring-open-%d", log));
+ static {
+ // ONOS-3579 workaround, let core threads die out on idle
+ if (GROUP_CHECKER instanceof ScheduledThreadPoolExecutor) {
+ ScheduledThreadPoolExecutor executor = (ScheduledThreadPoolExecutor) GROUP_CHECKER;
+ executor.setKeepAliveTime(CHECK_DELAY * 2, TimeUnit.MILLISECONDS);
+ executor.allowCoreThreadTimeOut(true);
+ }
+ }
+
protected KryoNamespace appKryo = new KryoNamespace.Builder()
.register(KryoNamespaces.API)
.register(GroupKey.class)
@@ -158,9 +172,6 @@
}
}).build();
- groupChecker.scheduleAtFixedRate(new GroupChecker(), 0, 500,
- TimeUnit.MILLISECONDS);
-
coreService = serviceDirectory.get(CoreService.class);
flowRuleService = serviceDirectory.get(FlowRuleService.class);
groupService = serviceDirectory.get(GroupService.class);
@@ -342,6 +353,7 @@
+ " in dev:{}", nextObjective.id(), deviceId);
pendingGroups.put(key, nextObjective);
groupService.addGroup(groupDescription);
+ verifyPendingGroupLater();
}
}
break;
@@ -367,6 +379,7 @@
+ "in device {}", nextObjective.id(), deviceId);
pendingGroups.put(key, nextObjective);
groupService.addGroup(groupDescription);
+ verifyPendingGroupLater();
}
break;
case FAILOVER:
@@ -1130,6 +1143,10 @@
}
}
+ private void verifyPendingGroupLater() {
+ GROUP_CHECKER.schedule(new GroupChecker(), CHECK_DELAY, TimeUnit.MILLISECONDS);
+ }
+
private class GroupChecker implements Runnable {
@Override
@@ -1158,6 +1175,13 @@
obj.id(),
new SpringOpenGroup(key, null));
});
+
+ if (!pendingGroups.asMap().isEmpty()) {
+ // Periodically execute only if entry remains in pendingGroups.
+ // Iterating pendingGroups trigger cleanUp and expiration,
+ // which will eventually empty the pendingGroups.
+ verifyPendingGroupLater();
+ }
}
}
diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTPDell.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTPDell.java
index e3afc0b..2774349 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTPDell.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTPDell.java
@@ -15,6 +15,8 @@
*/
package org.onosproject.driver.pipeline;
+import static org.slf4j.LoggerFactory.getLogger;
+
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -42,6 +44,7 @@
import org.onosproject.net.flowobjective.ForwardingObjective;
import org.onosproject.net.flowobjective.ObjectiveError;
import org.onosproject.net.group.Group;
+import org.slf4j.Logger;
/**
* Spring-open driver implementation for Dell hardware switches.
@@ -55,6 +58,8 @@
private static final int DELL_TABLE_MPLS = 25;
private static final int DELL_TABLE_ACL = 40;
+ private final Logger log = getLogger(getClass());
+
//TODO: Store this info in the distributed store.
private MacAddress deviceTMac = null;