You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by jf...@apache.org on 2021/01/03 15:21:11 UTC
[plc4x] 01/02: Renamed to pool2 and readded "old" connection-pool.
This is an automated email from the ASF dual-hosted git repository.
jfeinauer pushed a commit to branch feature/integrate-pool2
in repository https://gitbox.apache.org/repos/asf/plc4x.git
commit f4224876f2be47e33765148b590f1314f1b346b0
Author: Julian Feinauer <j....@pragmaticminds.de>
AuthorDate: Sun Jan 3 14:58:06 2021 +0100
Renamed to pool2 and readded "old" connection-pool.
---
plc4j/tools/connection-pool/pom.xml | 56 +---
.../connectionpool/CachedDriverManagerMBean.java | 19 --
.../plc4x/java/utils/connectionpool/PoolKey.java | 73 ++++
.../java/utils/connectionpool/PoolKeyFactory.java | 110 ++++++
.../connectionpool/PooledPlcConnectionFactory.java | 46 +++
.../connectionpool/PooledPlcDriverManager.java | 179 ++++++++++
.../utils/connectionpool/PoolKeyFactoryTest.java | 97 ++++++
.../utils/connectionpool/PooledDummyDriver.java | 52 +++
.../connectionpool/PooledPlcDriverManagerTest.java | 367 +++++++++++++++++++++
.../services/org.apache.plc4x.java.api.PlcDriver | 19 ++
.../connection-pool/src/test/resources/log4j2.xml | 15 -
.../connection-pool/src/test/resources/logback.xml | 34 ++
.../{connection-pool => connection-pool2}/pom.xml | 0
.../connectionpool2}/CachedDriverManager.java | 2 +-
.../connectionpool2/CachedDriverManagerMBean.java} | 19 +-
.../connectionpool2}/CachedPlcConnection.java | 2 +-
.../utils/connectionpool2}/CachedReadRequest.java | 2 +-
.../connectionpool2}/CachedReadRequestBuilder.java | 2 +-
.../connectionpool2}/PlcConnectionFactory.java | 2 +-
.../connectionpool2}/PooledDriverManager.java | 2 +-
.../connectionpool2}/PooledDriverManagerMBean.java | 2 +-
.../connectionpool2}/CachedDriverManagerIT.java | 2 +-
.../connectionpool2}/CachedDriverManagerMT.java | 2 +-
.../connectionpool2}/CachedDriverManagerTest.java | 2 +-
.../connectionpool2}/CachedPlcConnectionTest.java | 4 +-
.../connectionpool2}/PooledDriverManagerTest.java | 4 +-
.../connection-pool2/src/test/resources/log4j2.xml | 34 ++
plc4j/tools/pom.xml | 1 +
28 files changed, 1044 insertions(+), 105 deletions(-)
diff --git a/plc4j/tools/connection-pool/pom.xml b/plc4j/tools/connection-pool/pom.xml
index 84051c2..66c8463 100644
--- a/plc4j/tools/connection-pool/pom.xml
+++ b/plc4j/tools/connection-pool/pom.xml
@@ -37,63 +37,15 @@
<groupId>org.apache.plc4x</groupId>
<artifactId>plc4j-api</artifactId>
<version>0.8.0-SNAPSHOT</version>
- <scope>compile</scope>
</dependency>
+
<dependency>
<groupId>org.apache.commons</groupId>
- <artifactId>commons-lang3</artifactId>
- <scope>compile</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.logging.log4j</groupId>
- <artifactId>log4j-slf4j-impl</artifactId>
- <version>2.11.1</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.logging.log4j</groupId>
- <artifactId>log4j-core</artifactId>
- <version>2.11.1</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.plc4x</groupId>
- <artifactId>plc4j-driver-mock</artifactId>
- <version>0.8.0-SNAPSHOT</version>
- <scope>test</scope>
- <exclusions>
- <exclusion>
- <artifactId>junit</artifactId>
- <groupId>junit</groupId>
- </exclusion>
- </exclusions>
+ <artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
- <groupId>org.assertj</groupId>
- <artifactId>assertj-core</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.mockito</groupId>
- <artifactId>mockito-core</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.awaitility</groupId>
- <artifactId>awaitility</artifactId>
- <version>3.0.0</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.awaitility</groupId>
- <artifactId>awaitility-proxy</artifactId>
- <version>3.0.0</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.junit.jupiter</groupId>
- <artifactId>junit-jupiter</artifactId>
- <scope>test</scope>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-lang3</artifactId>
</dependency>
</dependencies>
diff --git a/plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/CachedDriverManagerMBean.java b/plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/CachedDriverManagerMBean.java
deleted file mode 100644
index 121c7ff..0000000
--- a/plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/CachedDriverManagerMBean.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package org.apache.plc4x.java.utils.connectionpool;
-
-public interface CachedDriverManagerMBean {
-
- String getStateString();
-
- int getNumberOfConnects();
-
- int getNumberOfBorrows();
-
- int getNumberOfWachtdogs();
-
- int getNumberOfRejections();
-
- void triggerReconnect();
-
- int getQueueSize();
-
-}
diff --git a/plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PoolKey.java b/plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PoolKey.java
new file mode 100644
index 0000000..7cd719a
--- /dev/null
+++ b/plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PoolKey.java
@@ -0,0 +1,73 @@
+/*
+ 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 abstract class PoolKey {
+ protected final String url;
+ protected final PlcAuthentication plcAuthentication;
+
+ public PoolKey(String url, PlcAuthentication plcAuthentication) {
+ this.url = url;
+ this.plcAuthentication = plcAuthentication;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public PlcAuthentication getPlcAuthentication() {
+ return plcAuthentication;
+ }
+
+ /**
+ * @return the part of the url that should be pooled.
+ */
+ public abstract String getPoolableKey();
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof PoolKey)) {
+ return false;
+ }
+ PoolKey poolKey = (PoolKey) o;
+ return Objects.equals(getPoolableKey(), poolKey.getPoolableKey()) &&
+ Objects.equals(plcAuthentication, poolKey.plcAuthentication);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(getPoolableKey(), plcAuthentication);
+ }
+
+ @Override
+ public String toString() {
+ return "PoolKey{" +
+ "url='" + url + '\'' +
+ (plcAuthentication != PooledPlcDriverManager.noPlcAuthentication ? ", plcAuthentication=" + plcAuthentication : "") +
+ '}';
+ }
+}
\ No newline at end of file
diff --git a/plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PoolKeyFactory.java b/plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PoolKeyFactory.java
new file mode 100644
index 0000000..4341312
--- /dev/null
+++ b/plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PoolKeyFactory.java
@@ -0,0 +1,110 @@
+/*
+ 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 org.apache.plc4x.java.api.exceptions.PlcConnectionException;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Objects;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class PoolKeyFactory {
+
+ // TODO 11.12.18 jf: add a property to the drivers to keep this generic
+ public PoolKey getPoolKey(String url, PlcAuthentication plcAuthentication) throws PlcConnectionException {
+ Objects.requireNonNull(url);
+ URI connectionUri;
+ try {
+ connectionUri = new URI(url);
+ } catch (URISyntaxException e) {
+ throw new PlcConnectionException("Invalid plc4j connection string '" + url + "'", e);
+ }
+ String protocol = connectionUri.getScheme().toLowerCase();
+ switch (protocol) {
+ // Currently this is disabled due to 2 reasons
+ // First, see PLC4X-223 it needs to be migrated to new URI Syntax
+ // Second, we have to decide which parameters uniquely identify a connection and which
+ // not. See PLC4X-224
+ /*
+ case "s7":
+ return new PoolKey(url, plcAuthentication) {
+ private final Pattern s7URIPattern = Pattern.compile("^(?<poolablePart>s7://((?<ip>[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3})|(?<hostname>[a-zA-Z0-9\\.\\-]+))(:(?<port>[0-9]{1,5}))?)(?<params>\\?.*)?");
+
+ @Override
+ public String getPoolableKey() {
+ Matcher matcher = s7URIPattern.matcher(url);
+ if (!matcher.matches()) {
+ throw new IllegalArgumentException(url + " doesn't match " + s7URIPattern);
+ }
+ return Objects.requireNonNull(matcher.group("poolablePart"));
+ }
+ };
+ case "ads":
+ return new PoolKey(url, plcAuthentication) {
+ private final Pattern amsPortPattern = Pattern.compile("\\d+");
+ private final Pattern amsNetIdPattern = Pattern.compile("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}");
+ private final Pattern adsAddressPattern =
+ Pattern.compile("(?<targetAmsNetId>" + amsNetIdPattern + "):(?<targetAmsPort>" + amsPortPattern + ")"
+ + "(/"
+ + "(?<sourceAmsNetId>" + amsNetIdPattern + "):(?<sourceAmsPort>" + amsPortPattern + ")"
+ + ")?");
+ private final Pattern inetAddressPattern = Pattern.compile("tcp://(?<host>[\\w.]+)(:(?<port>\\d*))?");
+ private final Pattern serialPattern = Pattern.compile("serial://(?<serialDefinition>((?!/\\d).)*)");
+ private final Pattern adsUriPattern = Pattern.compile("^(?<poolablePart>ads:(" + inetAddressPattern + "|" + serialPattern + "))/" + adsAddressPattern + "(\\?.*)?");
+
+ @Override
+ public String getPoolableKey() {
+ Matcher matcher =
+ adsUriPattern.matcher(url);
+ if (!matcher.matches()) {
+ throw new IllegalArgumentException(url + " doesn't match " + adsUriPattern);
+ }
+ return Objects.requireNonNull(matcher.group("poolablePart"));
+ }
+ };
+ case "modbus":
+ return new PoolKey(url, plcAuthentication) {
+ private final Pattern inetAddressPattern = Pattern.compile("tcp://(?<host>[\\w.]+)(:(?<port>\\d*))?");
+ private final Pattern serialPattern = Pattern.compile("serial://(?<serialDefinition>((?!/\\d).)*)");
+ private final Pattern modbusUriPattern = Pattern.compile("^(?<poolablePart>modbus:(" + inetAddressPattern + "|" + serialPattern + "))/?" + "(?<params>\\?.*)?");
+
+ @Override
+ public String getPoolableKey() {
+ Matcher matcher = modbusUriPattern.matcher(url);
+ if (!matcher.matches()) {
+ throw new IllegalArgumentException(url + " doesn't match " + modbusUriPattern);
+ }
+ return Objects.requireNonNull(matcher.group("poolablePart"));
+ }
+ };
+ */
+ default:
+ return new PoolKey(url, plcAuthentication) {
+ @Override
+ public String getPoolableKey() {
+ return url;
+ }
+ };
+ }
+ }
+}
diff --git a/plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PooledPlcConnectionFactory.java b/plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PooledPlcConnectionFactory.java
new file mode 100644
index 0000000..03879eb
--- /dev/null
+++ b/plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PooledPlcConnectionFactory.java
@@ -0,0 +1,46 @@
+/*
+ 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.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 BaseKeyedPooledObjectFactory<PoolKey, PlcConnection> {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(PooledPlcConnectionFactory.class);
+
+ @Override
+ public PooledObject<PlcConnection> wrap(PlcConnection plcConnection) {
+ LOGGER.debug("Wrapping connection {}", plcConnection);
+ return new DefaultPooledObject<>(plcConnection);
+ }
+
+ @Override
+ public void destroyObject(PoolKey key, PooledObject<PlcConnection> p) throws Exception {
+ p.getObject().close();
+ }
+
+ @Override
+ public boolean validateObject(PoolKey key, PooledObject<PlcConnection> p) {
+ return p.getObject().isConnected();
+ }
+}
diff --git a/plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PooledPlcDriverManager.java b/plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PooledPlcDriverManager.java
new file mode 100644
index 0000000..c164491
--- /dev/null
+++ b/plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PooledPlcDriverManager.java
@@ -0,0 +1,179 @@
+/*
+ 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.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.HashMap;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+public class PooledPlcDriverManager extends PlcDriverManager {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(PooledPlcDriverManager.class);
+
+ private KeyedObjectPool<PoolKey, PlcConnection> keyedObjectPool;
+
+ // Marker class do detected a non null value
+ static final NoPlcAuthentication noPlcAuthentication = new NoPlcAuthentication();
+
+ private final PoolKeyFactory poolKeyFactory;
+
+ public PooledPlcDriverManager() {
+ this(GenericKeyedObjectPool::new);
+ }
+
+ public PooledPlcDriverManager(PoolKeyFactory poolKeyFactory) {
+ this(GenericKeyedObjectPool::new, poolKeyFactory);
+ }
+
+ public PooledPlcDriverManager(ClassLoader classLoader) {
+ this(classLoader, new PoolKeyFactory());
+ }
+
+ public PooledPlcDriverManager(ClassLoader classLoader, PoolKeyFactory poolKeyFactory) {
+ super(classLoader);
+ setFromPoolCreator(GenericKeyedObjectPool::new);
+ this.poolKeyFactory = poolKeyFactory;
+ }
+
+ public PooledPlcDriverManager(PoolCreator poolCreator) {
+ this(poolCreator, new PoolKeyFactory());
+ }
+
+ public PooledPlcDriverManager(PoolCreator poolCreator, PoolKeyFactory poolKeyFactory) {
+ setFromPoolCreator(poolCreator);
+ this.poolKeyFactory = poolKeyFactory;
+ }
+
+ public PooledPlcDriverManager(ClassLoader classLoader, PoolCreator poolCreator) {
+ super(classLoader);
+ setFromPoolCreator(poolCreator);
+ poolKeyFactory = new PoolKeyFactory();
+ }
+
+ 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
+ public PlcConnection getConnection(String url) throws PlcConnectionException {
+ return getConnection(url, noPlcAuthentication);
+ }
+
+ @Override
+ public PlcConnection getConnection(String url, PlcAuthentication authentication) throws PlcConnectionException {
+ PoolKey poolKey = poolKeyFactory.getPoolKey(url, authentication);
+ if (LOGGER.isDebugEnabled()) {
+ if (authentication != noPlcAuthentication) {
+ LOGGER.debug("Try to borrow an object for url {} and authentication {}", url, authentication);
+ } else {
+ LOGGER.debug("Try to borrow an object for url {}", url);
+ }
+ }
+ PlcConnection plcConnection;
+ try {
+ plcConnection = keyedObjectPool.borrowObject(poolKey);
+ if (plcConnection.isConnected() == false) {
+ LOGGER.debug("Attempting to reconnect to device");
+ plcConnection.connect();
+ }
+ } catch (Exception e) {
+ throw new PlcConnectionException(e);
+ }
+ // Used to invalidate a proxy
+ AtomicBoolean proxyInvalidated = new AtomicBoolean(false);
+ return (PlcConnection) Proxy.newProxyInstance(classLoader, new Class[]{PlcConnection.class}, (proxy, method, args) -> {
+ if (proxyInvalidated.get()) {
+ throw new IllegalStateException("Proxy not valid anymore");
+ }
+ if ("close".equals(method.getName())) {
+ LOGGER.debug("close called on {}", plcConnection);
+ proxyInvalidated.set(true);
+ keyedObjectPool.returnObject(poolKey, plcConnection);
+ return null;
+ } else {
+ try {
+ return method.invoke(plcConnection, args);
+ } catch (InvocationTargetException e) {
+ if (e.getCause().getClass() == PlcConnectionException.class) {
+ keyedObjectPool.invalidateObject(poolKey, plcConnection);
+ proxyInvalidated.set(true);
+ }
+ throw e;
+ }
+ }
+ });
+ }
+
+ @FunctionalInterface
+ public interface PoolCreator {
+ KeyedObjectPool<PoolKey, PlcConnection> createPool(PooledPlcConnectionFactory pooledPlcConnectionFactory);
+ }
+
+ // TODO: maybe export to jmx // generic poolKey has builtin jmx too
+ public Map<String, Number> getStatistics() {
+ 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;
+ }
+
+ private static final class NoPlcAuthentication implements PlcAuthentication {
+
+ }
+}
diff --git a/plc4j/tools/connection-pool/src/test/java/org/apache/plc4x/java/utils/connectionpool/PoolKeyFactoryTest.java b/plc4j/tools/connection-pool/src/test/java/org/apache/plc4x/java/utils/connectionpool/PoolKeyFactoryTest.java
new file mode 100644
index 0000000..7e345ef
--- /dev/null
+++ b/plc4j/tools/connection-pool/src/test/java/org/apache/plc4x/java/utils/connectionpool/PoolKeyFactoryTest.java
@@ -0,0 +1,97 @@
+/*
+ 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.assertj.core.api.WithAssertions;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+
+/**
+ * See Cahnges due to PLC4X-223 and PLC4X-224
+ */
+@Disabled
+class PoolKeyFactoryTest implements WithAssertions {
+
+ private PoolKeyFactory SUT = new PoolKeyFactory();
+
+ @Nested
+ class Generic {
+ @Test
+ void getPoolKey() throws Exception {
+ PoolKey poolKey = SUT.getPoolKey("randomProtocol://randomHost/1/1?someOptions", PooledPlcDriverManager.noPlcAuthentication);
+ assertThat(poolKey.getUrl()).isEqualTo("randomProtocol://randomHost/1/1?someOptions");
+ assertThat(poolKey.getPlcAuthentication()).isEqualTo(PooledPlcDriverManager.noPlcAuthentication);
+ assertThat(poolKey.getPoolableKey()).isEqualTo("randomProtocol://randomHost/1/1?someOptions");
+ }
+ }
+
+ @Nested
+ class S7 {
+ @Test
+ void getPoolKey() throws Exception {
+ PoolKey poolKey = SUT.getPoolKey("s7://localhost?randomOption=true", PooledPlcDriverManager.noPlcAuthentication);
+ assertThat(poolKey.getUrl()).isEqualTo("s7://localhost?randomOption=true");
+ assertThat(poolKey.getPlcAuthentication()).isEqualTo(PooledPlcDriverManager.noPlcAuthentication);
+ assertThat(poolKey.getPoolableKey()).isEqualTo("s7://localhost");
+ }
+ }
+
+ @Nested
+ class ADS {
+ @Test
+ void getPoolKey_TCP() throws Exception {
+ PoolKey poolKey = SUT.getPoolKey("ads:tcp://10.10.64.40/10.10.64.40.1.1:851/10.10.56.23.1.1:30000", PooledPlcDriverManager.noPlcAuthentication);
+ assertThat(poolKey.getUrl()).isEqualTo("ads:tcp://10.10.64.40/10.10.64.40.1.1:851/10.10.56.23.1.1:30000");
+ assertThat(poolKey.getPlcAuthentication()).isEqualTo(PooledPlcDriverManager.noPlcAuthentication);
+ assertThat(poolKey.getPoolableKey()).isEqualTo("ads:tcp://10.10.64.40");
+ }
+
+ @Test
+ void getPoolKey_SERIAL() throws Exception {
+ PoolKey poolKey = SUT.getPoolKey("ads:serial:///dev/ttys003/10.10.64.40.1.1:851/10.10.56.23.1.1:30000", PooledPlcDriverManager.noPlcAuthentication);
+ assertThat(poolKey.getUrl()).isEqualTo("ads:serial:///dev/ttys003/10.10.64.40.1.1:851/10.10.56.23.1.1:30000");
+ assertThat(poolKey.getPlcAuthentication()).isEqualTo(PooledPlcDriverManager.noPlcAuthentication);
+ assertThat(poolKey.getPoolableKey()).isEqualTo("ads:serial:///dev/ttys003");
+ }
+ }
+
+ @Nested
+ class Modbus {
+ @Test
+ void getPoolKey_TCP() throws Exception {
+ PoolKey poolKey = SUT.getPoolKey("modbus:tcp://10.10.64.40?someRandomOption=true", PooledPlcDriverManager.noPlcAuthentication);
+ assertThat(poolKey.getUrl()).isEqualTo("modbus:tcp://10.10.64.40?someRandomOption=true");
+ assertThat(poolKey.getPlcAuthentication()).isEqualTo(PooledPlcDriverManager.noPlcAuthentication);
+ assertThat(poolKey.getPoolableKey()).isEqualTo("modbus:tcp://10.10.64.40");
+ }
+
+ @Disabled("Modbus serial pooling doesn't work right now as intended")
+ @Test
+ void getPoolKey_SERIAL() throws Exception {
+ PoolKey poolKey = SUT.getPoolKey("modbus:serial:///dev/ttys003?someRandomOption=true", PooledPlcDriverManager.noPlcAuthentication);
+ assertThat(poolKey.getUrl()).isEqualTo("modbus:serial:///dev/ttys003?someRandomOption=true");
+ assertThat(poolKey.getPlcAuthentication()).isEqualTo(PooledPlcDriverManager.noPlcAuthentication);
+ assertThat(poolKey.getPoolableKey()).isEqualTo("modbus:serial:///dev/ttys003");
+ }
+ }
+
+
+}
\ No newline at end of file
diff --git a/plc4j/tools/connection-pool/src/test/java/org/apache/plc4x/java/utils/connectionpool/PooledDummyDriver.java b/plc4j/tools/connection-pool/src/test/java/org/apache/plc4x/java/utils/connectionpool/PooledDummyDriver.java
new file mode 100644
index 0000000..c572e8d
--- /dev/null
+++ b/plc4j/tools/connection-pool/src/test/java/org/apache/plc4x/java/utils/connectionpool/PooledDummyDriver.java
@@ -0,0 +1,52 @@
+/*
+ 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.PlcConnection;
+import org.apache.plc4x.java.api.authentication.PlcAuthentication;
+import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
+import org.apache.plc4x.java.api.PlcDriver;
+
+import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
+import static org.mockito.Mockito.mock;
+
+public class PooledDummyDriver implements PlcDriver {
+
+ private PlcDriver mockedPlcDriver = mock(PlcDriver.class, RETURNS_DEEP_STUBS);
+
+ @Override
+ public String getProtocolCode() {
+ return PooledDummyDriver.class.getName();
+ }
+
+ @Override
+ public String getProtocolName() {
+ return mockedPlcDriver.getProtocolCode();
+ }
+
+ @Override
+ public PlcConnection getConnection(String url) throws PlcConnectionException {
+ return mockedPlcDriver.getConnection(url);
+ }
+
+ @Override
+ public PlcConnection getConnection(String url, PlcAuthentication authentication) throws PlcConnectionException {
+ return mockedPlcDriver.getConnection(url, authentication);
+ }
+
+}
diff --git a/plc4j/tools/connection-pool/src/test/java/org/apache/plc4x/java/utils/connectionpool/PooledPlcDriverManagerTest.java b/plc4j/tools/connection-pool/src/test/java/org/apache/plc4x/java/utils/connectionpool/PooledPlcDriverManagerTest.java
new file mode 100644
index 0000000..aedd2c4
--- /dev/null
+++ b/plc4j/tools/connection-pool/src/test/java/org/apache/plc4x/java/utils/connectionpool/PooledPlcDriverManagerTest.java
@@ -0,0 +1,367 @@
+/*
+ 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.commons.lang3.reflect.FieldUtils;
+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;
+import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
+import org.apache.plc4x.java.api.exceptions.PlcUnsupportedOperationException;
+import org.apache.plc4x.java.api.messages.PlcReadRequest;
+import org.apache.plc4x.java.api.messages.PlcSubscriptionRequest;
+import org.apache.plc4x.java.api.messages.PlcUnsubscriptionRequest;
+import org.apache.plc4x.java.api.messages.PlcWriteRequest;
+import org.apache.plc4x.java.api.metadata.PlcConnectionMetadata;
+import org.apache.plc4x.java.api.PlcDriver;
+import org.assertj.core.api.WithAssertions;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.stream.IntStream;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.*;
+
+@ExtendWith(MockitoExtension.class)
+class PooledPlcDriverManagerTest implements WithAssertions {
+
+ private static Logger LOGGER = LoggerFactory.getLogger(PooledPlcDriverManagerTest.class);
+
+ private PooledPlcDriverManager SUT = new PooledPlcDriverManager(pooledPlcConnectionFactory -> {
+ 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)
+ PlcDriver plcDriver;
+
+ private ExecutorService executorService;
+
+ @SuppressWarnings("unchecked")
+ @BeforeEach
+ void setUp() throws Exception {
+ Map<String, PlcDriver> driverMap = (Map) FieldUtils.getField(PooledPlcDriverManager.class, "driverMap", true).get(SUT);
+ driverMap.put("dummydummy", plcDriver);
+ executorService = Executors.newFixedThreadPool(100);
+
+ assertThat(SUT.getStatistics()).containsOnly(
+ entry("pools.count", 0),
+ entry("numActive", 0),
+ entry("numIdle", 0)
+ );
+ }
+
+ @AfterEach
+ void tearDown() {
+ executorService.shutdown();
+ }
+
+ @Test
+ void getConnection() throws Exception {
+ when(plcDriver.getConnection(anyString())).then(invocationOnMock -> new DummyPlcConnection(invocationOnMock.getArgument(0)));
+
+ LinkedList<Callable<PlcConnection>> callables = new LinkedList<>();
+
+ // This: should result in one open connection
+ IntStream.range(0, 8).forEach(i -> callables.add(() -> {
+ try {
+ return SUT.getConnection("dummydummy:single/socket1/socket2?fancyOption=true");
+ } catch (PlcConnectionException e) {
+ throw new RuntimeException(e);
+ }
+ }));
+
+ // This should result in five open connections
+ IntStream.range(0, 5).forEach(i -> callables.add(() -> {
+ try {
+ return SUT.getConnection("dummydummy:multi-" + i + "/socket1/socket2?fancyOption=true");
+ } catch (PlcConnectionException e) {
+ throw new RuntimeException(e);
+ }
+ }));
+
+ List<Future<PlcConnection>> futures = executorService.invokeAll(callables);
+
+ // Wait for existing connections
+ futures.forEach(plcConnectionFuture1 -> {
+ try {
+ plcConnectionFuture1.get();
+ } catch (InterruptedException | ExecutionException e) {
+ throw new RuntimeException(e);
+ }
+ });
+ LOGGER.info("Statistics after execution {}", SUT.getStatistics());
+
+ // As we have a pool size of 8 we should have only 8 + 5 calls for the separate pools
+ verify(plcDriver, times(13)).getConnection(anyString());
+
+ assertThat(SUT.getStatistics()).contains(
+ entry("PoolKey{url='dummydummy:single/socket1/socket2?fancyOption=true'}.numActive", 8)
+ );
+
+ futures.forEach(plcConnectionFuture -> {
+ try {
+ plcConnectionFuture.get().close();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ });
+
+ assertThat(SUT.getStatistics()).contains(
+ entry("PoolKey{url='dummydummy:single/socket1/socket2?fancyOption=true'}.numActive", 0)
+ );
+ }
+
+ @Test
+ void getConnectionWithAuth() throws Exception {
+ when(plcDriver.getConnection(anyString(), any())).then(invocationOnMock -> new DummyPlcConnection(invocationOnMock.getArgument(0), invocationOnMock.getArgument(1)));
+
+ LinkedList<Callable<PlcConnection>> callables = new LinkedList<>();
+
+ // This: should result in one open connection
+ IntStream.range(0, 8).forEach(i -> callables.add(() -> {
+ try {
+ return SUT.getConnection("dummydummy:single/socket1/socket2?fancyOption=true", new PlcUsernamePasswordAuthentication("user", "passwordp954368564098ß"));
+ } catch (PlcConnectionException e) {
+ throw new RuntimeException(e);
+ }
+ }));
+
+ // This should result in five open connections
+ IntStream.range(0, 5).forEach(i -> callables.add(() -> {
+ try {
+ return SUT.getConnection("dummydummy:multi-" + i + "/socket1/socket2?fancyOption=true", new PlcUsernamePasswordAuthentication("user", "passwordp954368564098ß"));
+ } catch (PlcConnectionException e) {
+ throw new RuntimeException(e);
+ }
+ }));
+
+ List<Future<PlcConnection>> futures = executorService.invokeAll(callables);
+
+ futures.forEach(plcConnectionFuture1 -> {
+ try {
+ plcConnectionFuture1.get();
+ } catch (InterruptedException | ExecutionException e) {
+ throw new RuntimeException(e);
+ }
+ });
+
+ LOGGER.info("Statistics after execution {}", SUT.getStatistics());
+
+ // As we have a pool size of 8 we should have only 8 + 5 calls for the separate pools
+ verify(plcDriver, times(13)).getConnection(anyString(), any());
+
+ assertThat(SUT.getStatistics()).contains(
+ entry("PoolKey{url='dummydummy:single/socket1/socket2?fancyOption=true', plcAuthentication=PlcUsernamePasswordAuthentication{username='user', password='*****************'}}.numActive", 8)
+ );
+
+ futures.forEach(plcConnectionFuture -> {
+ try {
+ plcConnectionFuture.get().close();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ });
+
+ assertThat(SUT.getStatistics()).contains(
+ entry("PoolKey{url='dummydummy:single/socket1/socket2?fancyOption=true', plcAuthentication=PlcUsernamePasswordAuthentication{username='user', password='*****************'}}.numActive", 0)
+ );
+ }
+
+ @Test
+ void connectionInvalidation() throws Exception {
+ when(plcDriver.getConnection(anyString())).then(invocationOnMock -> new DummyPlcConnection(invocationOnMock.getArgument(0)));
+
+ PlcConnection connection = SUT.getConnection("dummydummy:single/socket1/socket2?fancyOption=true");
+ assertThat(connection.isConnected()).isEqualTo(true);
+ assertThat(connection.getMetadata().canRead()).isEqualTo(false);
+ assertThat(connection.getMetadata().canWrite()).isEqualTo(false);
+ assertThat(connection.getMetadata().canSubscribe()).isEqualTo(false);
+
+ connection.close();
+ assertThatThrownBy(connection::connect).isInstanceOf(IllegalStateException.class).hasMessage("Proxy not valid anymore");
+ assertThatThrownBy(connection::isConnected).isInstanceOf(IllegalStateException.class).hasMessage("Proxy not valid anymore");
+ assertThatThrownBy(connection::close).isInstanceOf(IllegalStateException.class).hasMessage("Proxy not valid anymore");
+ assertThatThrownBy(connection::getMetadata).isInstanceOf(IllegalStateException.class).hasMessage("Proxy not valid anymore");
+ assertThatThrownBy(connection::readRequestBuilder).isInstanceOf(IllegalStateException.class).hasMessage("Proxy not valid anymore");
+ assertThatThrownBy(connection::writeRequestBuilder).isInstanceOf(IllegalStateException.class).hasMessage("Proxy not valid anymore");
+ assertThatThrownBy(connection::subscriptionRequestBuilder).isInstanceOf(IllegalStateException.class).hasMessage("Proxy not valid anymore");
+ assertThatThrownBy(connection::unsubscriptionRequestBuilder).isInstanceOf(IllegalStateException.class).hasMessage("Proxy not valid anymore");
+ }
+
+ @Test
+ void cleanupOfBrokenConnections() throws Exception {
+ AtomicBoolean failNow = new AtomicBoolean(false);
+ when(plcDriver.getConnection(anyString())).then(invocationOnMock -> {
+ DummyPlcConnection dummyPlcConnection = spy(new DummyPlcConnection(invocationOnMock.getArgument(0)));
+ // we fake an connection which breaks at this call
+ doAnswer(invocation -> {
+ if (failNow.get()) {
+ throw new PlcConnectionException("blub");
+ }
+ return invocation.callRealMethod();
+ }).when(dummyPlcConnection).connect();
+ return dummyPlcConnection;
+ });
+
+ assertThat(SUT.getStatistics()).containsOnly(
+ 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("numActive", 1),
+ entry("numIdle", 0),
+ entry("PoolKey{url='dummydummy:breakIt'}.numActive", 1)
+ );
+ failNow.set(true);
+ try {
+ connection.connect();
+ fail("This should throw an exception");
+ } catch (Exception e) {
+ // TODO: currently UndeclaredThrowableException is the top one which should be InvocationTargetException
+ //assertThat(e).isInstanceOf(InvocationTargetException.class);
+ assertThat(e).hasRootCauseInstanceOf(PlcConnectionException.class);
+ }
+ // Faulty connection should have been discarded
+ assertThat(SUT.getStatistics()).containsOnly(
+ entry("pools.count", 0),
+ entry("numActive", 0),
+ entry("numIdle", 0)
+ );
+ }
+
+ @Test
+ public void testOtherConstructors() {
+ assertThat(new PooledPlcDriverManager()).isNotNull();
+ assertThat(new PooledPlcDriverManager(new PoolKeyFactory())).isNotNull();
+ assertThat(new PooledPlcDriverManager(PooledPlcDriverManager.class.getClassLoader())).isNotNull();
+ assertThat(new PooledPlcDriverManager(
+ PooledPlcDriverManager.class.getClassLoader(), new PoolKeyFactory())).isNotNull();
+ }
+
+ class DummyPlcConnection implements PlcConnection, PlcConnectionMetadata {
+
+ private final String url;
+
+ private final PlcAuthentication plcAuthentication;
+
+ boolean connected = false;
+
+ public DummyPlcConnection(String url) {
+ this(url, null);
+ }
+
+ public DummyPlcConnection(String url, PlcAuthentication plcAuthentication) {
+ this.url = url;
+ this.plcAuthentication = plcAuthentication;
+ }
+
+ @Override
+ public void connect() {
+ connected = true;
+ }
+
+ @Override
+ public CompletableFuture<Void> ping() {
+ CompletableFuture<Void> future = new CompletableFuture<>();
+ future.completeExceptionally(new UnsupportedOperationException());
+ return future;
+ }
+
+ @Override
+ public boolean isConnected() {
+ return connected;
+ }
+
+ @Override
+ public PlcConnectionMetadata getMetadata() {
+ return this;
+ }
+
+ @Override
+ public boolean canRead() {
+ return false;
+ }
+
+ @Override
+ public boolean canWrite() {
+ return false;
+ }
+
+ @Override
+ public boolean canSubscribe() {
+ return false;
+ }
+
+ @Override
+ public void close() {
+ connected = false;
+ }
+
+ @Override
+ public PlcReadRequest.Builder readRequestBuilder() {
+ throw new PlcUnsupportedOperationException("The connection does not support reading");
+ }
+
+ @Override
+ public PlcWriteRequest.Builder writeRequestBuilder() {
+ throw new PlcUnsupportedOperationException("The connection does not support writing");
+ }
+
+ @Override
+ public PlcSubscriptionRequest.Builder subscriptionRequestBuilder() {
+ throw new PlcUnsupportedOperationException("The connection does not support subscription");
+ }
+
+ @Override
+ public PlcUnsubscriptionRequest.Builder unsubscriptionRequestBuilder() {
+ throw new PlcUnsupportedOperationException("The connection does not support subscription");
+ }
+
+ @Override
+ public String toString() {
+ return "DummyPlcConnection{" +
+ "url='" + url + '\'' +
+ ", plcAuthentication=" + plcAuthentication +
+ ", connected=" + connected +
+ '}';
+ }
+ }
+}
\ No newline at end of file
diff --git a/plc4j/tools/connection-pool/src/test/resources/META-INF/services/org.apache.plc4x.java.api.PlcDriver b/plc4j/tools/connection-pool/src/test/resources/META-INF/services/org.apache.plc4x.java.api.PlcDriver
new file mode 100644
index 0000000..a2d97ed
--- /dev/null
+++ b/plc4j/tools/connection-pool/src/test/resources/META-INF/services/org.apache.plc4x.java.api.PlcDriver
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+org.apache.plc4x.java.utils.connectionpool.PooledDummyDriver
diff --git a/plc4j/tools/connection-pool/src/test/resources/log4j2.xml b/plc4j/tools/connection-pool/src/test/resources/log4j2.xml
deleted file mode 100644
index e8efef9..0000000
--- a/plc4j/tools/connection-pool/src/test/resources/log4j2.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<Configuration status="WARN">
- <Appenders>
- <Console name="Console" target="SYSTEM_OUT">
- <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
- </Console>
- </Appenders>
- <Loggers>
- <Root level="WARN">
- <AppenderRef ref="Console"/>
- </Root>
- <Logger name="org.pragmaticindustries.cockpit.plc" level="DEBUG"/>
- <Logger name="org.pragmaticindustries.cockpit.plc.pool2" level="DEBUG"/>
- </Loggers>
-</Configuration>
\ No newline at end of file
diff --git a/plc4j/tools/connection-pool/src/test/resources/logback.xml b/plc4j/tools/connection-pool/src/test/resources/logback.xml
new file mode 100644
index 0000000..31c49f0
--- /dev/null
+++ b/plc4j/tools/connection-pool/src/test/resources/logback.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+<configuration xmlns="http://ch.qos.logback/xml/ns/logback"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://ch.qos.logback/xml/ns/logback https://raw.githubusercontent.com/enricopulatzo/logback-XSD/master/src/main/xsd/logback.xsd">
+
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <!-- encoders are assigned the type
+ ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
+ <encoder>
+ <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
+ </encoder>
+ </appender>
+
+ <root level="DEBUG">
+ <appender-ref ref="STDOUT" />
+ </root>
+
+</configuration>
\ No newline at end of file
diff --git a/plc4j/tools/connection-pool/pom.xml b/plc4j/tools/connection-pool2/pom.xml
similarity index 100%
copy from plc4j/tools/connection-pool/pom.xml
copy to plc4j/tools/connection-pool2/pom.xml
diff --git a/plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/CachedDriverManager.java b/plc4j/tools/connection-pool2/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedDriverManager.java
similarity index 99%
rename from plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/CachedDriverManager.java
rename to plc4j/tools/connection-pool2/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedDriverManager.java
index 89e4428..06a881d 100644
--- a/plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/CachedDriverManager.java
+++ b/plc4j/tools/connection-pool2/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedDriverManager.java
@@ -17,7 +17,7 @@
* under the License.
*/
-package org.apache.plc4x.java.utils.connectionpool;
+package org.apache.plc4x.java.utils.connectionpool2;
import org.apache.commons.lang3.NotImplementedException;
import org.apache.plc4x.java.PlcDriverManager;
diff --git a/plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PooledDriverManagerMBean.java b/plc4j/tools/connection-pool2/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedDriverManagerMBean.java
similarity index 72%
copy from plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PooledDriverManagerMBean.java
copy to plc4j/tools/connection-pool2/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedDriverManagerMBean.java
index 9b63ec2..7b26538 100644
--- a/plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PooledDriverManagerMBean.java
+++ b/plc4j/tools/connection-pool2/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedDriverManagerMBean.java
@@ -17,9 +17,22 @@
* under the License.
*/
-package org.apache.plc4x.java.utils.connectionpool;
+package org.apache.plc4x.java.utils.connectionpool2;
-public interface PooledDriverManagerMBean {
+public interface CachedDriverManagerMBean {
+
+ String getStateString();
+
+ int getNumberOfConnects();
+
+ int getNumberOfBorrows();
+
+ int getNumberOfWachtdogs();
+
+ int getNumberOfRejections();
+
+ void triggerReconnect();
+
+ int getQueueSize();
- String[] getConnectedUrls();
}
diff --git a/plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/CachedPlcConnection.java b/plc4j/tools/connection-pool2/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedPlcConnection.java
similarity index 99%
rename from plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/CachedPlcConnection.java
rename to plc4j/tools/connection-pool2/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedPlcConnection.java
index 4e7a1af..d97fc93 100644
--- a/plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/CachedPlcConnection.java
+++ b/plc4j/tools/connection-pool2/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedPlcConnection.java
@@ -17,7 +17,7 @@
* under the License.
*/
-package org.apache.plc4x.java.utils.connectionpool;
+package org.apache.plc4x.java.utils.connectionpool2;
import org.apache.plc4x.java.api.PlcConnection;
import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
diff --git a/plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/CachedReadRequest.java b/plc4j/tools/connection-pool2/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedReadRequest.java
similarity index 97%
rename from plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/CachedReadRequest.java
rename to plc4j/tools/connection-pool2/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedReadRequest.java
index a7b0213..51a3a0a 100644
--- a/plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/CachedReadRequest.java
+++ b/plc4j/tools/connection-pool2/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedReadRequest.java
@@ -17,7 +17,7 @@
* under the License.
*/
-package org.apache.plc4x.java.utils.connectionpool;
+package org.apache.plc4x.java.utils.connectionpool2;
import org.apache.plc4x.java.api.messages.PlcReadRequest;
import org.apache.plc4x.java.api.messages.PlcReadResponse;
diff --git a/plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/CachedReadRequestBuilder.java b/plc4j/tools/connection-pool2/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedReadRequestBuilder.java
similarity index 97%
rename from plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/CachedReadRequestBuilder.java
rename to plc4j/tools/connection-pool2/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedReadRequestBuilder.java
index eda1f32..742e5b3 100644
--- a/plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/CachedReadRequestBuilder.java
+++ b/plc4j/tools/connection-pool2/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedReadRequestBuilder.java
@@ -17,7 +17,7 @@
* under the License.
*/
-package org.apache.plc4x.java.utils.connectionpool;
+package org.apache.plc4x.java.utils.connectionpool2;
import org.apache.plc4x.java.api.messages.PlcReadRequest;
import org.apache.plc4x.java.api.model.PlcField;
diff --git a/plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PlcConnectionFactory.java b/plc4j/tools/connection-pool2/src/main/java/org/apache/plc4x/java/utils/connectionpool2/PlcConnectionFactory.java
similarity index 95%
rename from plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PlcConnectionFactory.java
rename to plc4j/tools/connection-pool2/src/main/java/org/apache/plc4x/java/utils/connectionpool2/PlcConnectionFactory.java
index 4d72c04..b5b58da 100644
--- a/plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PlcConnectionFactory.java
+++ b/plc4j/tools/connection-pool2/src/main/java/org/apache/plc4x/java/utils/connectionpool2/PlcConnectionFactory.java
@@ -17,7 +17,7 @@
* under the License.
*/
-package org.apache.plc4x.java.utils.connectionpool;
+package org.apache.plc4x.java.utils.connectionpool2;
import org.apache.plc4x.java.api.PlcConnection;
import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
diff --git a/plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PooledDriverManager.java b/plc4j/tools/connection-pool2/src/main/java/org/apache/plc4x/java/utils/connectionpool2/PooledDriverManager.java
similarity index 98%
rename from plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PooledDriverManager.java
rename to plc4j/tools/connection-pool2/src/main/java/org/apache/plc4x/java/utils/connectionpool2/PooledDriverManager.java
index 1056c00..fc36879 100644
--- a/plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PooledDriverManager.java
+++ b/plc4j/tools/connection-pool2/src/main/java/org/apache/plc4x/java/utils/connectionpool2/PooledDriverManager.java
@@ -17,7 +17,7 @@
* under the License.
*/
-package org.apache.plc4x.java.utils.connectionpool;
+package org.apache.plc4x.java.utils.connectionpool2;
import org.apache.plc4x.java.PlcDriverManager;
import org.apache.plc4x.java.api.PlcConnection;
diff --git a/plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PooledDriverManagerMBean.java b/plc4j/tools/connection-pool2/src/main/java/org/apache/plc4x/java/utils/connectionpool2/PooledDriverManagerMBean.java
similarity index 94%
rename from plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PooledDriverManagerMBean.java
rename to plc4j/tools/connection-pool2/src/main/java/org/apache/plc4x/java/utils/connectionpool2/PooledDriverManagerMBean.java
index 9b63ec2..8555e6b 100644
--- a/plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PooledDriverManagerMBean.java
+++ b/plc4j/tools/connection-pool2/src/main/java/org/apache/plc4x/java/utils/connectionpool2/PooledDriverManagerMBean.java
@@ -17,7 +17,7 @@
* under the License.
*/
-package org.apache.plc4x.java.utils.connectionpool;
+package org.apache.plc4x.java.utils.connectionpool2;
public interface PooledDriverManagerMBean {
diff --git a/plc4j/tools/connection-pool/src/test/java/org/apache/plc4x/java/utils/connectionpool/CachedDriverManagerIT.java b/plc4j/tools/connection-pool2/src/test/java/org/apache/plc4x/java/utils/connectionpool2/CachedDriverManagerIT.java
similarity index 97%
rename from plc4j/tools/connection-pool/src/test/java/org/apache/plc4x/java/utils/connectionpool/CachedDriverManagerIT.java
rename to plc4j/tools/connection-pool2/src/test/java/org/apache/plc4x/java/utils/connectionpool2/CachedDriverManagerIT.java
index 9e618b4..086863b 100644
--- a/plc4j/tools/connection-pool/src/test/java/org/apache/plc4x/java/utils/connectionpool/CachedDriverManagerIT.java
+++ b/plc4j/tools/connection-pool2/src/test/java/org/apache/plc4x/java/utils/connectionpool2/CachedDriverManagerIT.java
@@ -17,7 +17,7 @@
* under the License.
*/
-package org.apache.plc4x.java.utils.connectionpool;
+package org.apache.plc4x.java.utils.connectionpool2;
import org.apache.plc4x.java.api.exceptions.PlcException;
import org.apache.plc4x.java.mock.connection.MockConnection;
diff --git a/plc4j/tools/connection-pool/src/test/java/org/apache/plc4x/java/utils/connectionpool/CachedDriverManagerMT.java b/plc4j/tools/connection-pool2/src/test/java/org/apache/plc4x/java/utils/connectionpool2/CachedDriverManagerMT.java
similarity index 98%
rename from plc4j/tools/connection-pool/src/test/java/org/apache/plc4x/java/utils/connectionpool/CachedDriverManagerMT.java
rename to plc4j/tools/connection-pool2/src/test/java/org/apache/plc4x/java/utils/connectionpool2/CachedDriverManagerMT.java
index 7727a98..cb69a2f 100644
--- a/plc4j/tools/connection-pool/src/test/java/org/apache/plc4x/java/utils/connectionpool/CachedDriverManagerMT.java
+++ b/plc4j/tools/connection-pool2/src/test/java/org/apache/plc4x/java/utils/connectionpool2/CachedDriverManagerMT.java
@@ -17,7 +17,7 @@
* under the License.
*/
-package org.apache.plc4x.java.utils.connectionpool;
+package org.apache.plc4x.java.utils.connectionpool2;
import org.apache.plc4x.java.PlcDriverManager;
import org.apache.plc4x.java.api.PlcConnection;
diff --git a/plc4j/tools/connection-pool/src/test/java/org/apache/plc4x/java/utils/connectionpool/CachedDriverManagerTest.java b/plc4j/tools/connection-pool2/src/test/java/org/apache/plc4x/java/utils/connectionpool2/CachedDriverManagerTest.java
similarity index 99%
rename from plc4j/tools/connection-pool/src/test/java/org/apache/plc4x/java/utils/connectionpool/CachedDriverManagerTest.java
rename to plc4j/tools/connection-pool2/src/test/java/org/apache/plc4x/java/utils/connectionpool2/CachedDriverManagerTest.java
index 47abf78..f3f130b 100644
--- a/plc4j/tools/connection-pool/src/test/java/org/apache/plc4x/java/utils/connectionpool/CachedDriverManagerTest.java
+++ b/plc4j/tools/connection-pool2/src/test/java/org/apache/plc4x/java/utils/connectionpool2/CachedDriverManagerTest.java
@@ -17,7 +17,7 @@
* under the License.
*/
-package org.apache.plc4x.java.utils.connectionpool;
+package org.apache.plc4x.java.utils.connectionpool2;
import org.apache.plc4x.java.api.PlcConnection;
import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
diff --git a/plc4j/tools/connection-pool/src/test/java/org/apache/plc4x/java/utils/connectionpool/CachedPlcConnectionTest.java b/plc4j/tools/connection-pool2/src/test/java/org/apache/plc4x/java/utils/connectionpool2/CachedPlcConnectionTest.java
similarity index 95%
rename from plc4j/tools/connection-pool/src/test/java/org/apache/plc4x/java/utils/connectionpool/CachedPlcConnectionTest.java
rename to plc4j/tools/connection-pool2/src/test/java/org/apache/plc4x/java/utils/connectionpool2/CachedPlcConnectionTest.java
index 096b058..1df6766 100644
--- a/plc4j/tools/connection-pool/src/test/java/org/apache/plc4x/java/utils/connectionpool/CachedPlcConnectionTest.java
+++ b/plc4j/tools/connection-pool2/src/test/java/org/apache/plc4x/java/utils/connectionpool2/CachedPlcConnectionTest.java
@@ -17,12 +17,10 @@
* under the License.
*/
-package org.apache.plc4x.java.utils.connectionpool;
+package org.apache.plc4x.java.utils.connectionpool2;
import org.apache.plc4x.java.api.PlcConnection;
import org.apache.plc4x.java.api.messages.PlcReadResponse;
-import org.apache.plc4x.java.utils.connectionpool.CachedDriverManager;
-import org.apache.plc4x.java.utils.connectionpool.CachedPlcConnection;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
diff --git a/plc4j/tools/connection-pool/src/test/java/org/apache/plc4x/java/utils/connectionpool/PooledDriverManagerTest.java b/plc4j/tools/connection-pool2/src/test/java/org/apache/plc4x/java/utils/connectionpool2/PooledDriverManagerTest.java
similarity index 90%
rename from plc4j/tools/connection-pool/src/test/java/org/apache/plc4x/java/utils/connectionpool/PooledDriverManagerTest.java
rename to plc4j/tools/connection-pool2/src/test/java/org/apache/plc4x/java/utils/connectionpool2/PooledDriverManagerTest.java
index b1285df..06b341c 100644
--- a/plc4j/tools/connection-pool/src/test/java/org/apache/plc4x/java/utils/connectionpool/PooledDriverManagerTest.java
+++ b/plc4j/tools/connection-pool2/src/test/java/org/apache/plc4x/java/utils/connectionpool2/PooledDriverManagerTest.java
@@ -17,12 +17,10 @@
* under the License.
*/
-package org.apache.plc4x.java.utils.connectionpool;
+package org.apache.plc4x.java.utils.connectionpool2;
import org.apache.plc4x.java.api.PlcConnection;
import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
-import org.apache.plc4x.java.utils.connectionpool.CachedDriverManager;
-import org.apache.plc4x.java.utils.connectionpool.PooledDriverManager;
import org.assertj.core.api.WithAssertions;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
diff --git a/plc4j/tools/connection-pool2/src/test/resources/log4j2.xml b/plc4j/tools/connection-pool2/src/test/resources/log4j2.xml
new file mode 100644
index 0000000..2db650b
--- /dev/null
+++ b/plc4j/tools/connection-pool2/src/test/resources/log4j2.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<Configuration status="WARN">
+ <Appenders>
+ <Console name="Console" target="SYSTEM_OUT">
+ <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
+ </Console>
+ </Appenders>
+ <Loggers>
+ <Root level="WARN">
+ <AppenderRef ref="Console"/>
+ </Root>
+ <Logger name="org.pragmaticindustries.cockpit.plc" level="DEBUG"/>
+ <Logger name="org.pragmaticindustries.cockpit.plc.pool2" level="DEBUG"/>
+ </Loggers>
+</Configuration>
\ No newline at end of file
diff --git a/plc4j/tools/pom.xml b/plc4j/tools/pom.xml
index aaba917..af74031 100644
--- a/plc4j/tools/pom.xml
+++ b/plc4j/tools/pom.xml
@@ -36,6 +36,7 @@
<modules>
<module>capture-replay</module>
<module>connection-pool</module>
+ <module>connection-pool2</module>
<module>opm</module>
<module>scraper</module>
</modules>