You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by sr...@apache.org on 2018/10/29 08:41:52 UTC
[incubator-plc4x] branch master updated: [plc4j-pool] use native
KeyedObjectPool and ditch custom implementation Custom keys per protocol
are still needed
This is an automated email from the ASF dual-hosted git repository.
sruehl pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-plc4x.git
The following commit(s) were added to refs/heads/master by this push:
new 4e440a9 [plc4j-pool] use native KeyedObjectPool and ditch custom implementation Custom keys per protocol are still needed
4e440a9 is described below
commit 4e440a942ee34e659c0916ca630cf451e62f73d4
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Mon Oct 29 09:38:46 2018 +0100
[plc4j-pool] use native KeyedObjectPool and ditch custom implementation
Custom keys per protocol are still needed
---
.../plc4x/java/utils/connectionpool/PoolKey.java | 74 ++++++++
.../connectionpool/PooledPlcConnectionFactory.java | 8 +-
.../connectionpool/PooledPlcDriverManager.java | 198 ++++++---------------
.../connectionpool/PooledPlcDriverManagerTest.java | 110 +++---------
4 files changed, 156 insertions(+), 234 deletions(-)
diff --git a/plc4j/utils/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PoolKey.java b/plc4j/utils/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PoolKey.java
new file mode 100644
index 0000000..166589c
--- /dev/null
+++ b/plc4j/utils/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PoolKey.java
@@ -0,0 +1,74 @@
+/*
+ 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.plc4x.java.utils.connectionpool;
+
+import org.apache.plc4x.java.api.authentication.PlcAuthentication;
+
+import java.util.Objects;
+
+public class PoolKey {
+ final String url;
+ final PlcAuthentication plcAuthentication;
+
+ // TODO: we need to extract relevant parts of the url as key as we don't want many connections for different racks in s7 for example.
+ // TODO: So we might end up need a generic key and special keys for all known protocols which parses the relevant portions.
+ public PoolKey(String url, PlcAuthentication plcAuthentication) {
+ this.url = url;
+ this.plcAuthentication = plcAuthentication;
+ }
+
+ public static PoolKey of(String host, PlcAuthentication plcAuthentication) {
+ return new PoolKey(host, plcAuthentication);
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public PlcAuthentication getPlcAuthentication() {
+ return plcAuthentication;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof PoolKey)) {
+ return false;
+ }
+ PoolKey poolKey = (PoolKey) o;
+ return Objects.equals(url, poolKey.url) &&
+ Objects.equals(plcAuthentication, poolKey.plcAuthentication);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(url, plcAuthentication);
+ }
+
+ @Override
+ public String toString() {
+ return "PoolKey{" +
+ "url='" + url + '\'' +
+ (plcAuthentication != PooledPlcDriverManager.noPlcAuthentication ? ", plcAuthentication=" + plcAuthentication : "") +
+ '}';
+ }
+}
\ No newline at end of file
diff --git a/plc4j/utils/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PooledPlcConnectionFactory.java b/plc4j/utils/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PooledPlcConnectionFactory.java
index 72d3deb..03879eb 100644
--- a/plc4j/utils/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PooledPlcConnectionFactory.java
+++ b/plc4j/utils/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PooledPlcConnectionFactory.java
@@ -17,14 +17,14 @@
package org.apache.plc4x.java.utils.connectionpool;
-import org.apache.commons.pool2.BasePooledObjectFactory;
+import org.apache.commons.pool2.BaseKeyedPooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.apache.plc4x.java.api.PlcConnection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public abstract class PooledPlcConnectionFactory extends BasePooledObjectFactory<PlcConnection> {
+public abstract class PooledPlcConnectionFactory extends BaseKeyedPooledObjectFactory<PoolKey, PlcConnection> {
private static final Logger LOGGER = LoggerFactory.getLogger(PooledPlcConnectionFactory.class);
@@ -35,12 +35,12 @@ public abstract class PooledPlcConnectionFactory extends BasePooledObjectFactory
}
@Override
- public void destroyObject(PooledObject<PlcConnection> p) throws Exception {
+ public void destroyObject(PoolKey key, PooledObject<PlcConnection> p) throws Exception {
p.getObject().close();
}
@Override
- public boolean validateObject(PooledObject<PlcConnection> p) {
+ public boolean validateObject(PoolKey key, PooledObject<PlcConnection> p) {
return p.getObject().isConnected();
}
}
diff --git a/plc4j/utils/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PooledPlcDriverManager.java b/plc4j/utils/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PooledPlcDriverManager.java
index b0f9701..d10dc20 100644
--- a/plc4j/utils/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PooledPlcDriverManager.java
+++ b/plc4j/utils/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PooledPlcDriverManager.java
@@ -17,54 +17,65 @@
package org.apache.plc4x.java.utils.connectionpool;
-import org.apache.commons.pool2.ObjectPool;
-import org.apache.commons.pool2.impl.GenericObjectPool;
+import org.apache.commons.lang3.reflect.FieldUtils;
+import org.apache.commons.pool2.KeyedObjectPool;
+import org.apache.commons.pool2.impl.GenericKeyedObjectPool;
import org.apache.plc4x.java.PlcDriverManager;
import org.apache.plc4x.java.api.PlcConnection;
import org.apache.plc4x.java.api.authentication.PlcAuthentication;
import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
+import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Proxy;
-import java.util.*;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
+import java.util.HashMap;
+import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReadWriteLock;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
public class PooledPlcDriverManager extends PlcDriverManager {
private static final Logger LOGGER = LoggerFactory.getLogger(PooledPlcDriverManager.class);
- private PoolCreator poolCreator;
-
- private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
-
- private ConcurrentMap<PoolKey, ObjectPool<PlcConnection>> poolMap = new ConcurrentHashMap<>();
+ private KeyedObjectPool<PoolKey, PlcConnection> keyedObjectPool;
// Marker class do detected a non null value
- private static final NoPlcAuthentication noPlcAuthentication = new NoPlcAuthentication();
+ static final NoPlcAuthentication noPlcAuthentication = new NoPlcAuthentication();
public PooledPlcDriverManager() {
- this(GenericObjectPool::new);
+ this(GenericKeyedObjectPool::new);
}
public PooledPlcDriverManager(ClassLoader classLoader) {
super(classLoader);
- this.poolCreator = GenericObjectPool::new;
+ setFromPoolCreator(GenericKeyedObjectPool::new);
}
public PooledPlcDriverManager(PoolCreator poolCreator) {
- this.poolCreator = poolCreator;
+ setFromPoolCreator(poolCreator);
}
public PooledPlcDriverManager(ClassLoader classLoader, PoolCreator poolCreator) {
super(classLoader);
- this.poolCreator = poolCreator;
+ setFromPoolCreator(poolCreator);
+ }
+
+ private void setFromPoolCreator(PoolCreator poolCreator) {
+ this.keyedObjectPool = poolCreator.createPool(new PooledPlcConnectionFactory() {
+ @Override
+ public PlcConnection create(PoolKey key) throws Exception {
+ PlcAuthentication plcAuthentication = key.plcAuthentication;
+ String url = key.url;
+ if (plcAuthentication == noPlcAuthentication) {
+ LOGGER.debug("getting actual connection for {}", url);
+ return PooledPlcDriverManager.super.getConnection(url);
+ } else {
+ LOGGER.debug("getting actual connection for {} and plcAuthentication {}", url, plcAuthentication);
+ return PooledPlcDriverManager.super.getConnection(url, plcAuthentication);
+ }
+ }
+ });
}
@Override
@@ -75,7 +86,6 @@ public class PooledPlcDriverManager extends PlcDriverManager {
@Override
public PlcConnection getConnection(String url, PlcAuthentication authentication) throws PlcConnectionException {
PoolKey poolKey = PoolKey.of(url, authentication);
- ObjectPool<PlcConnection> pool = retrieveFromPool(poolKey);
if (LOGGER.isDebugEnabled()) {
if (authentication != noPlcAuthentication) {
LOGGER.debug("Try to borrow an object for url {} and authentication {}", url, authentication);
@@ -85,7 +95,7 @@ public class PooledPlcDriverManager extends PlcDriverManager {
}
PlcConnection plcConnection;
try {
- plcConnection = pool.borrowObject();
+ plcConnection = keyedObjectPool.borrowObject(poolKey);
} catch (Exception e) {
throw new PlcConnectionException(e);
}
@@ -96,16 +106,16 @@ public class PooledPlcDriverManager extends PlcDriverManager {
throw new IllegalStateException("Proxy not valid anymore");
}
if ("close".equals(method.getName())) {
- LOGGER.debug("close called on {}. Returning to {}", plcConnection, pool);
+ LOGGER.debug("close called on {}", plcConnection);
proxyInvalidated.set(true);
- pool.returnObject(plcConnection);
+ keyedObjectPool.returnObject(poolKey, plcConnection);
return null;
} else {
try {
return method.invoke(plcConnection, args);
} catch (InvocationTargetException e) {
if (e.getCause().getClass() == PlcConnectionException.class) {
- pool.invalidateObject(plcConnection);
+ keyedObjectPool.invalidateObject(poolKey, plcConnection);
proxyInvalidated.set(true);
}
throw e;
@@ -114,139 +124,35 @@ public class PooledPlcDriverManager extends PlcDriverManager {
});
}
- private ObjectPool<PlcConnection> retrieveFromPool(PoolKey poolKey) {
- ObjectPool<PlcConnection> pool = poolMap.get(poolKey);
- if (pool == null) {
- LOGGER.debug("No pool found for poolKey {}", poolKey);
- String url = poolKey.getUrl();
- PlcAuthentication plcAuthentication = poolKey.getPlcAuthentication();
-
- Lock lock = readWriteLock.writeLock();
- lock.lock();
- try {
- pool = poolMap.computeIfAbsent(poolKey, pair -> poolCreator.createPool(new PooledPlcConnectionFactory() {
- @Override
- public PlcConnection create() throws PlcConnectionException {
- if (plcAuthentication == noPlcAuthentication) {
- LOGGER.debug("getting actual connection for {}", url);
- return PooledPlcDriverManager.super.getConnection(url);
- } else {
- LOGGER.debug("getting actual connection for {} and plcAuthentication {}", url, plcAuthentication);
- return PooledPlcDriverManager.super.getConnection(url, plcAuthentication);
- }
- }
- }));
- LOGGER.debug("Using pool {}:{} for poolKey {}", pool.hashCode(), pool, poolKey);
- } finally {
- lock.unlock();
- }
- }
- return pool;
- }
-
@FunctionalInterface
interface PoolCreator {
- ObjectPool<PlcConnection> createPool(PooledPlcConnectionFactory pooledPlcConnectionFactory);
- }
-
- // TODO: maybe add a Thread which calls this cyclic
- public void removedUnusedPools() {
- Lock lock = readWriteLock.writeLock();
- lock.lock();
- try {
- LOGGER.debug("doing cleanup now on {}", poolMap);
- Set<PoolKey> itemsToBeremoved = new LinkedHashSet<>();
- poolMap.forEach((key, value) -> {
- // TODO: check if this pool has been used in the last time and if not remove it.
- // TODO: evicting empty pools for now
- LOGGER.debug("pool {}:{} has numActive: {} numIdle: {}", key, value, value.getNumActive(), value.getNumIdle());
- if (value.getNumActive() == 0 && value.getNumIdle() == 0) {
- LOGGER.info("Removing unused pool {}", value);
- itemsToBeremoved.add(key);
- }
- });
- LOGGER.debug("items to be removed {} on {}", itemsToBeremoved, poolMap);
- itemsToBeremoved.forEach(poolMap::remove);
- } finally {
- lock.unlock();
- }
+ KeyedObjectPool<PoolKey, PlcConnection> createPool(PooledPlcConnectionFactory pooledPlcConnectionFactory);
}
- // TODO: maybe export to jmx
+ // TODO: maybe export to jmx // generic poolKey has builting jmx too
public Map<String, Number> getStatistics() {
- Lock lock = readWriteLock.readLock();
- try {
- lock.lock();
- HashMap<String, Number> statistics = new HashMap<>();
- statistics.put("pools.count", poolMap.size());
- for (Map.Entry<PoolKey, ObjectPool<PlcConnection>> poolEntry : poolMap.entrySet()) {
- PoolKey pair = poolEntry.getKey();
- ObjectPool<PlcConnection> objectPool = poolEntry.getValue();
- String url = pair.getUrl();
- PlcAuthentication plcAuthentication = pair.getPlcAuthentication();
-
- String authSuffix = plcAuthentication != noPlcAuthentication ? "/" + plcAuthentication : "";
- statistics.put(url + authSuffix + ".numActive", objectPool.getNumActive());
- statistics.put(url + authSuffix + ".numIdle", objectPool.getNumIdle());
+ HashMap<String, Number> statistics = new HashMap<>();
+ statistics.put("numActive", keyedObjectPool.getNumActive());
+ statistics.put("numIdle", keyedObjectPool.getNumIdle());
+ if (keyedObjectPool instanceof GenericKeyedObjectPool) {
+ GenericKeyedObjectPool<PoolKey, PlcConnection> genericKeyedObjectPool = (GenericKeyedObjectPool<PoolKey, PlcConnection>) this.keyedObjectPool;
+ // Thats pretty ugly and we really should't do that...
+ try {
+ Map poolMap = (Map) FieldUtils.getField(GenericKeyedObjectPool.class, "poolMap", true).get(this.keyedObjectPool);
+ statistics.put("pools.count", poolMap.size());
+ } catch (IllegalAccessException e) {
+ throw new PlcRuntimeException(e);
+ }
+ Map<String, Integer> numActivePerKey = genericKeyedObjectPool.getNumActivePerKey();
+ for (Map.Entry<String, Integer> entry : numActivePerKey.entrySet()) {
+ statistics.put(entry.getKey() + ".numActive", entry.getValue());
}
-
- return statistics;
- } finally {
- lock.unlock();
}
- }
-
- private static final class NoPlcAuthentication implements PlcAuthentication {
+ return statistics;
}
- private static final class PoolKey {
- final String url;
- final PlcAuthentication plcAuthentication;
-
- // TODO: we need to extract relevant parts of the url as key as we don't want many connections for different racks in s7 for example.
- // TODO: So we might end up need a generic key and special keys for all known protocols which parses the relevant portions.
- public PoolKey(String url, PlcAuthentication plcAuthentication) {
- this.url = url;
- this.plcAuthentication = plcAuthentication;
- }
-
- public static PoolKey of(String host, PlcAuthentication plcAuthentication) {
- return new PoolKey(host, plcAuthentication);
- }
-
- public String getUrl() {
- return url;
- }
-
- public PlcAuthentication getPlcAuthentication() {
- return plcAuthentication;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (!(o instanceof PoolKey)) {
- return false;
- }
- PoolKey poolKey = (PoolKey) o;
- return Objects.equals(url, poolKey.url) &&
- Objects.equals(plcAuthentication, poolKey.plcAuthentication);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(url, plcAuthentication);
- }
+ private static final class NoPlcAuthentication implements PlcAuthentication {
- @Override
- public String toString() {
- return "PoolKey{" +
- "url='" + url + '\'' +
- (plcAuthentication != noPlcAuthentication ? ", plcAuthentication=" + plcAuthentication : "") +
- '}';
- }
}
}
diff --git a/plc4j/utils/connection-pool/src/test/java/org/apache/plc4x/java/utils/connectionpool/PooledPlcDriverManagerTest.java b/plc4j/utils/connection-pool/src/test/java/org/apache/plc4x/java/utils/connectionpool/PooledPlcDriverManagerTest.java
index 9ab3972..bbe8ea8 100644
--- a/plc4j/utils/connection-pool/src/test/java/org/apache/plc4x/java/utils/connectionpool/PooledPlcDriverManagerTest.java
+++ b/plc4j/utils/connection-pool/src/test/java/org/apache/plc4x/java/utils/connectionpool/PooledPlcDriverManagerTest.java
@@ -18,8 +18,8 @@
package org.apache.plc4x.java.utils.connectionpool;
import org.apache.commons.lang3.reflect.FieldUtils;
-import org.apache.commons.pool2.impl.GenericObjectPool;
-import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
+import org.apache.commons.pool2.impl.GenericKeyedObjectPool;
+import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig;
import org.apache.plc4x.java.api.PlcConnection;
import org.apache.plc4x.java.api.authentication.PlcAuthentication;
import org.apache.plc4x.java.api.authentication.PlcUsernamePasswordAuthentication;
@@ -34,7 +34,6 @@ import org.apache.plc4x.java.spi.PlcDriver;
import org.assertj.core.api.WithAssertions;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Answers;
@@ -48,7 +47,6 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.IntStream;
import static org.mockito.ArgumentMatchers.any;
@@ -61,11 +59,11 @@ class PooledPlcDriverManagerTest implements WithAssertions {
private static Logger LOGGER = LoggerFactory.getLogger(PooledPlcDriverManagerTest.class);
private PooledPlcDriverManager SUT = new PooledPlcDriverManager(pooledPlcConnectionFactory -> {
- GenericObjectPoolConfig<PlcConnection> plcConnectionGenericObjectPoolConfig = new GenericObjectPoolConfig<>();
- plcConnectionGenericObjectPoolConfig.setMinIdle(1);
- plcConnectionGenericObjectPoolConfig.setTestOnBorrow(true);
- plcConnectionGenericObjectPoolConfig.setTestOnReturn(true);
- return new GenericObjectPool<>(pooledPlcConnectionFactory, plcConnectionGenericObjectPoolConfig);
+ GenericKeyedObjectPoolConfig<PlcConnection> config = new GenericKeyedObjectPoolConfig<>();
+ config.setMinIdlePerKey(1);
+ config.setTestOnBorrow(true);
+ config.setTestOnReturn(true);
+ return new GenericKeyedObjectPool<>(pooledPlcConnectionFactory, config);
});
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
@@ -80,7 +78,11 @@ class PooledPlcDriverManagerTest implements WithAssertions {
driverMap.put("dummydummy", plcDriver);
executorService = Executors.newFixedThreadPool(100);
- assertThat(SUT.getStatistics()).containsOnly(entry("pools.count", 0));
+ assertThat(SUT.getStatistics()).containsOnly(
+ entry("pools.count", 0),
+ entry("numActive", 0),
+ entry("numIdle", 0)
+ );
}
@AfterEach
@@ -128,8 +130,7 @@ class PooledPlcDriverManagerTest implements WithAssertions {
verify(plcDriver, times(13)).connect(anyString());
assertThat(SUT.getStatistics()).contains(
- entry("dummydummy:single/socket1/socket2?fancyOption=true.numActive", 8),
- entry("dummydummy:single/socket1/socket2?fancyOption=true.numIdle", 0)
+ entry("PoolKey{url='dummydummy:single/socket1/socket2?fancyOption=true'}.numActive", 8)
);
futures.forEach(plcConnectionFuture -> {
@@ -141,8 +142,7 @@ class PooledPlcDriverManagerTest implements WithAssertions {
});
assertThat(SUT.getStatistics()).contains(
- entry("dummydummy:single/socket1/socket2?fancyOption=true.numActive", 0),
- entry("dummydummy:single/socket1/socket2?fancyOption=true.numIdle", 8)
+ entry("PoolKey{url='dummydummy:single/socket1/socket2?fancyOption=true'}.numActive", 0)
);
}
@@ -164,7 +164,7 @@ class PooledPlcDriverManagerTest implements WithAssertions {
// This should result in five open connections
IntStream.range(0, 5).forEach(i -> callables.add(() -> {
try {
- return SUT.getConnection("dummydummy:single-" + i + "/socket1/socket2?fancyOption=true", new PlcUsernamePasswordAuthentication("user", "passwordp954368564098ß"));
+ return SUT.getConnection("dummydummy:multi-" + i + "/socket1/socket2?fancyOption=true", new PlcUsernamePasswordAuthentication("user", "passwordp954368564098ß"));
} catch (PlcConnectionException e) {
throw new RuntimeException(e);
}
@@ -186,8 +186,7 @@ class PooledPlcDriverManagerTest implements WithAssertions {
verify(plcDriver, times(13)).connect(anyString(), any());
assertThat(SUT.getStatistics()).contains(
- entry("dummydummy:single/socket1/socket2?fancyOption=true/PlcUsernamePasswordAuthentication{username='user', password='*****************'}.numActive", 8),
- entry("dummydummy:single/socket1/socket2?fancyOption=true/PlcUsernamePasswordAuthentication{username='user', password='*****************'}.numIdle", 0)
+ entry("PoolKey{url='dummydummy:single/socket1/socket2?fancyOption=true', plcAuthentication=PlcUsernamePasswordAuthentication{username='user', password='*****************'}}.numActive", 8)
);
futures.forEach(plcConnectionFuture -> {
@@ -199,8 +198,7 @@ class PooledPlcDriverManagerTest implements WithAssertions {
});
assertThat(SUT.getStatistics()).contains(
- entry("dummydummy:single/socket1/socket2?fancyOption=true/PlcUsernamePasswordAuthentication{username='user', password='*****************'}.numActive", 0),
- entry("dummydummy:single/socket1/socket2?fancyOption=true/PlcUsernamePasswordAuthentication{username='user', password='*****************'}.numIdle", 8)
+ entry("PoolKey{url='dummydummy:single/socket1/socket2?fancyOption=true', plcAuthentication=PlcUsernamePasswordAuthentication{username='user', password='*****************'}}.numActive", 0)
);
}
@@ -241,13 +239,16 @@ class PooledPlcDriverManagerTest implements WithAssertions {
});
assertThat(SUT.getStatistics()).containsOnly(
- entry("pools.count", 0)
+ entry("pools.count", 0),
+ entry("numActive", 0),
+ entry("numIdle", 0)
);
PlcConnection connection = SUT.getConnection("dummydummy:breakIt");
assertThat(SUT.getStatistics()).containsOnly(
entry("pools.count", 1),
- entry("dummydummy:breakIt.numActive", 1),
- entry("dummydummy:breakIt.numIdle", 0)
+ entry("numActive", 1),
+ entry("numIdle", 0),
+ entry("PoolKey{url='dummydummy:breakIt'}.numActive", 1)
);
failNow.set(true);
try {
@@ -260,71 +261,12 @@ class PooledPlcDriverManagerTest implements WithAssertions {
}
// Faulty connection should have been discarded
assertThat(SUT.getStatistics()).containsOnly(
- entry("pools.count", 1),
- entry("dummydummy:breakIt.numActive", 0),
- entry("dummydummy:breakIt.numIdle", 0)
+ entry("pools.count", 0),
+ entry("numActive", 0),
+ entry("numIdle", 0)
);
}
- @Nested
- class PoolCleanup {
- @Test
- void poolRemovedUnusedPoolsNormal() throws Exception {
- // special config needed
- SUT = new PooledPlcDriverManager(pooledPlcConnectionFactory -> {
- GenericObjectPoolConfig<PlcConnection> plcConnectionGenericObjectPoolConfig = new GenericObjectPoolConfig<>();
- plcConnectionGenericObjectPoolConfig.setMinIdle(1);
- return new GenericObjectPool<>(pooledPlcConnectionFactory, plcConnectionGenericObjectPoolConfig);
- });
- setUp();
-
- assertThat(SUT.getStatistics()).containsEntry("pools.count", 0);
- SUT.removedUnusedPools();
- assertThat(SUT.getStatistics()).containsEntry("pools.count", 0);
- PlcConnection connection = SUT.getConnection("dummydummy:single/socket1/socket2?fancyOption=true");
- connection.close();
- assertThat(SUT.getStatistics()).containsEntry("pools.count", 1);
- SUT.removedUnusedPools();
- assertThat(SUT.getStatistics()).containsEntry("pools.count", 1);
- // Usually the removedUnusedPools should do nothing at this place.
- }
-
- @Test
- void poolRemovedUnusedPoolsNoIdles() throws Exception {
- // special config needed
- AtomicReference<GenericObjectPool<PlcConnection>> atomicReference = new AtomicReference<>();
- SUT = new PooledPlcDriverManager(pooledPlcConnectionFactory -> {
- GenericObjectPoolConfig<PlcConnection> plcConnectionGenericObjectPoolConfig = new GenericObjectPoolConfig<>();
- plcConnectionGenericObjectPoolConfig.setMinIdle(0);
- GenericObjectPool<PlcConnection> plcConnectionGenericObjectPool = new GenericObjectPool<>(pooledPlcConnectionFactory, plcConnectionGenericObjectPoolConfig);
- atomicReference.set(plcConnectionGenericObjectPool);
- // Evict under all circumstances
- plcConnectionGenericObjectPool.setEvictionPolicy((config, underTest, idleCount) -> true);
- return plcConnectionGenericObjectPool;
- });
- setUp();
-
- // Pool should be empty at the beginning
- assertThat(SUT.getStatistics()).containsEntry("pools.count", 0);
- SUT.removedUnusedPools();
- assertThat(SUT.getStatistics()).containsEntry("pools.count", 0);
- PlcConnection connection = SUT.getConnection("dummydummy:single/socket1/socket2?fancyOption=true");
- connection.close();
-
- // after a connection we should have one pool
- GenericObjectPool<PlcConnection> pool = atomicReference.get();
- assertThat(SUT.getStatistics()).containsEntry("pools.count", 1);
- SUT.removedUnusedPools();
- assertThat(SUT.getStatistics()).containsEntry("pools.count", 1);
-
- // now we force a eviction with your dummy policy
- pool.evict();
- SUT.removedUnusedPools();
- assertThat(SUT.getStatistics()).containsEntry("pools.count", 0);
- // and have no more open pools
- }
- }
-
class DummyPlcConnection implements PlcConnection, PlcConnectionMetadata {
private final String url;