You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by tv...@apache.org on 2024/06/12 06:20:14 UTC

(commons-jcs) branch master updated (58423681 -> f548e1ab)

This is an automated email from the ASF dual-hosted git repository.

tv pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/commons-jcs.git


    from 58423681 Use Objects.toString()
     new d20016e4 Introduce JDBCConnection to handle commit/rollback properly
     new 6031530a Refactor for better testability
     new f548e1ab Log network interface properties in trace mode

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../jcs3/auxiliary/disk/jdbc/JDBCConnection.java   | 107 ++++++++++
 .../jcs3/auxiliary/disk/jdbc/JDBCDiskCache.java    | 219 +++++++++++----------
 .../auxiliary/disk/jdbc/mysql/MySQLDiskCache.java  |  15 --
 .../jcs3/utils/discovery/UDPDiscoveryReceiver.java | 104 +++-------
 .../jcs3/utils/discovery/UDPDiscoverySender.java   |  14 +-
 .../jcs3/utils/discovery/UDPDiscoveryService.java  |  34 +++-
 .../commons/jcs3/utils/net/HostNameUtil.java       |  10 +
 .../UDPDiscoverySenderEncryptedUnitTest.java       |  68 +++----
 .../discovery/UDPDiscoverySenderUnitTest.java      |  82 ++++----
 .../jcs3/utils/discovery/UDPDiscoveryUnitTest.java |   9 +-
 10 files changed, 375 insertions(+), 287 deletions(-)
 create mode 100644 commons-jcs3-core/src/main/java/org/apache/commons/jcs3/auxiliary/disk/jdbc/JDBCConnection.java


(commons-jcs) 03/03: Log network interface properties in trace mode

Posted by tv...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

tv pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-jcs.git

commit f548e1ab1efdaa979bae5a3df5bd21f8db4c7ec0
Author: Thomas Vandahl <tv...@apache.org>
AuthorDate: Wed Jun 12 08:19:53 2024 +0200

    Log network interface properties in trace mode
---
 .../java/org/apache/commons/jcs3/utils/net/HostNameUtil.java   | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/commons-jcs3-core/src/main/java/org/apache/commons/jcs3/utils/net/HostNameUtil.java b/commons-jcs3-core/src/main/java/org/apache/commons/jcs3/utils/net/HostNameUtil.java
index 8b933786..f9868a55 100644
--- a/commons-jcs3-core/src/main/java/org/apache/commons/jcs3/utils/net/HostNameUtil.java
+++ b/commons-jcs3-core/src/main/java/org/apache/commons/jcs3/utils/net/HostNameUtil.java
@@ -198,10 +198,20 @@ public class HostNameUtil
         while (networkInterfaces.hasMoreElements())
         {
             final NetworkInterface networkInterface = networkInterfaces.nextElement();
+            if (!networkInterface.supportsMulticast())
+            {
+                log.trace("found network interface [{0}]: no multicast support", networkInterface::getDisplayName);
+                continue;
+            }
             final Enumeration<InetAddress> addressesFromNetworkInterface = networkInterface.getInetAddresses();
             while (addressesFromNetworkInterface.hasMoreElements())
             {
                 final InetAddress inetAddress = addressesFromNetworkInterface.nextElement();
+                log.trace("found network interface [{0}]: address: {1}, site local: {2}, any local {3}, link local {4}, loopback {5}, multicast {6}",
+                        networkInterface::getDisplayName, inetAddress::getHostAddress, inetAddress::isSiteLocalAddress,
+                        inetAddress::isAnyLocalAddress, inetAddress::isLinkLocalAddress, inetAddress::isLoopbackAddress,
+                        inetAddress::isMulticastAddress);
+
                 if (inetAddress.isSiteLocalAddress()
                         && !inetAddress.isAnyLocalAddress()
                         && !inetAddress.isLinkLocalAddress()


(commons-jcs) 02/03: Refactor for better testability

Posted by tv...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

tv pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-jcs.git

commit 6031530a501ee9c0511f042a15b6b9a5c6f5cdfa
Author: Thomas Vandahl <tv...@apache.org>
AuthorDate: Wed Jun 12 08:18:45 2024 +0200

    Refactor for better testability
---
 .../jcs3/utils/discovery/UDPDiscoveryReceiver.java | 104 ++++++---------------
 .../jcs3/utils/discovery/UDPDiscoverySender.java   |  14 ++-
 .../jcs3/utils/discovery/UDPDiscoveryService.java  |  34 ++++++-
 .../UDPDiscoverySenderEncryptedUnitTest.java       |  68 ++++++--------
 .../discovery/UDPDiscoverySenderUnitTest.java      |  82 +++++++---------
 .../jcs3/utils/discovery/UDPDiscoveryUnitTest.java |   9 +-
 6 files changed, 139 insertions(+), 172 deletions(-)

diff --git a/commons-jcs3-core/src/main/java/org/apache/commons/jcs3/utils/discovery/UDPDiscoveryReceiver.java b/commons-jcs3-core/src/main/java/org/apache/commons/jcs3/utils/discovery/UDPDiscoveryReceiver.java
index 4c0d3380..b003822c 100644
--- a/commons-jcs3-core/src/main/java/org/apache/commons/jcs3/utils/discovery/UDPDiscoveryReceiver.java
+++ b/commons-jcs3-core/src/main/java/org/apache/commons/jcs3/utils/discovery/UDPDiscoveryReceiver.java
@@ -32,17 +32,19 @@ import java.nio.channels.MembershipKey;
 import java.nio.channels.SelectionKey;
 import java.nio.channels.Selector;
 import java.util.Iterator;
-import java.util.concurrent.ArrayBlockingQueue;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Consumer;
 
 import org.apache.commons.jcs3.engine.CacheInfo;
 import org.apache.commons.jcs3.engine.behavior.IElementSerializer;
 import org.apache.commons.jcs3.engine.behavior.IShutdownObserver;
 import org.apache.commons.jcs3.log.Log;
 import org.apache.commons.jcs3.log.LogManager;
+import org.apache.commons.jcs3.utils.discovery.UDPDiscoveryMessage.BroadcastType;
 import org.apache.commons.jcs3.utils.net.HostNameUtil;
+import org.apache.commons.jcs3.utils.serialization.StandardSerializer;
 import org.apache.commons.jcs3.utils.threadpool.PoolConfiguration;
 import org.apache.commons.jcs3.utils.threadpool.PoolConfiguration.WhenBlockedPolicy;
 import org.apache.commons.jcs3.utils.threadpool.ThreadPoolManager;
@@ -76,17 +78,14 @@ public class UDPDiscoveryReceiver
     private final AtomicInteger cnt = new AtomicInteger();
 
     /** Service to get cache names and handle request broadcasts */
-    private final UDPDiscoveryService service;
+    private Consumer<UDPDiscoveryMessage> service;
 
     /** Serializer */
-    private IElementSerializer serializer;
+    private IElementSerializer serializer = new StandardSerializer();
 
     /** Is it shutdown. */
     private final AtomicBoolean shutdown = new AtomicBoolean();
 
-    private final ArrayBlockingQueue<UDPDiscoveryMessage> msgQueue =
-            new ArrayBlockingQueue<>(maxPoolSize);
-
     /**
      * Constructor for the UDPDiscoveryReceiver object.
      * <p>
@@ -95,19 +94,15 @@ public class UDPDiscoveryReceiver
      * @param multicastAddress
      * @param multicastPort
      * @throws IOException
-     * @since 3.1
+     * @since 4.0
      */
-    public UDPDiscoveryReceiver( final UDPDiscoveryService service,
+    public UDPDiscoveryReceiver( final Consumer<UDPDiscoveryMessage> service,
             final String multicastInterfaceString,
             final InetAddress multicastAddress,
             final int multicastPort )
         throws IOException
     {
-        this.service = service;
-        if (service != null)
-        {
-            this.serializer = service.getSerializer();
-        }
+        setService(service);
 
         // create a small thread pool to handle a barrage
         this.pooledExecutor = ThreadPoolManager.getInstance().createPool(
@@ -130,7 +125,7 @@ public class UDPDiscoveryReceiver
      * @param multicastPort
      * @throws IOException
      */
-    public UDPDiscoveryReceiver( final UDPDiscoveryService service,
+    public UDPDiscoveryReceiver( final Consumer<UDPDiscoveryMessage> service,
             final String multicastInterfaceString,
             final String multicastAddressString,
             final int multicastPort )
@@ -215,44 +210,19 @@ public class UDPDiscoveryReceiver
             log.debug( "Process message sent from another" );
             log.debug( "Message = {0}", message );
 
-            if ( message.getHost() == null || message.getCacheNames() == null || message.getCacheNames().isEmpty() )
+            if (message.getHost() == null ||
+                message.getMessageType() != BroadcastType.REQUEST &&
+                (message.getCacheNames() == null || message.getCacheNames().isEmpty()) )
             {
                 log.debug( "Ignoring invalid message: {0}", message );
             }
             else
             {
-                processMessage(message);
+                service.accept(message);
             }
         }
     }
 
-    /**
-     * Process the incoming message.
-     */
-    private void processMessage(UDPDiscoveryMessage message)
-    {
-        final DiscoveredService discoveredService = new DiscoveredService(message);
-
-        switch (message.getMessageType())
-        {
-            case REMOVE:
-                log.debug( "Removing service from set {0}", discoveredService );
-                service.removeDiscoveredService( discoveredService );
-                break;
-            case REQUEST:
-                // if this is a request message, have the service handle it and
-                // return
-                log.debug( "Message is a Request Broadcast, will have the service handle it." );
-                service.serviceRequestBroadcast();
-                break;
-            case PASSIVE:
-            default:
-                log.debug( "Adding or updating service to set {0}", discoveredService );
-                service.addOrUpdateService( discoveredService );
-                break;
-        }
-    }
-
     /** Main processing method for the UDPDiscoveryReceiver object */
     @Override
     public void run()
@@ -277,6 +247,7 @@ public class UDPDiscoveryReceiver
                     }
 
                     SelectionKey key = i.next();
+                    i.remove();
 
                     if (!key.isValid())
                     {
@@ -313,19 +284,6 @@ public class UDPDiscoveryReceiver
                                 log.debug( "Read object from address [{0}], object=[{1}]",
                                         sourceAddress, obj );
 
-                                // Just to keep the functionality of the test waitForMessage method
-                                synchronized (msgQueue)
-                                {
-                                    // Check if queue full already?
-                                    if (msgQueue.remainingCapacity() == 0)
-                                    {
-                                        // remove oldest element from queue
-                                        msgQueue.remove();
-                                    }
-
-                                    msgQueue.add(msg);
-                                }
-
                                 pooledExecutor.execute(() -> handleMessage(msg));
                                 log.debug( "Passed handler to executor." );
                             }
@@ -334,8 +292,6 @@ public class UDPDiscoveryReceiver
                         {
                             log.error( "Error receiving multicast packet", e );
                         }
-
-                        i.remove();
                     }
                 }
             } // end while
@@ -355,7 +311,7 @@ public class UDPDiscoveryReceiver
     }
 
     /**
-     * For testing
+     * Set the serializer implementation
      *
      * @param serializer the serializer to set
      * @since 3.1
@@ -365,6 +321,17 @@ public class UDPDiscoveryReceiver
         this.serializer = serializer;
     }
 
+    /**
+     * Set the service implementation
+     *
+     * @param service the service to set
+     * @since 4.0
+     */
+    protected void setService(Consumer<UDPDiscoveryMessage> service)
+    {
+        this.service = service;
+    }
+
     /** Shuts down the socket. */
     @Override
     public void shutdown()
@@ -383,23 +350,4 @@ public class UDPDiscoveryReceiver
             }
         }
     }
-
-    /**
-     * Wait for multicast message (used for testing)
-     *
-     * @return the object message
-     * @throws IOException
-     */
-    protected Object waitForMessage()
-        throws IOException
-    {
-        try
-        {
-            return msgQueue.take();
-        }
-        catch (InterruptedException e)
-        {
-            throw new IOException("Interrupted waiting for message", e);
-        }
-    }
 }
diff --git a/commons-jcs3-core/src/main/java/org/apache/commons/jcs3/utils/discovery/UDPDiscoverySender.java b/commons-jcs3-core/src/main/java/org/apache/commons/jcs3/utils/discovery/UDPDiscoverySender.java
index 55e7645e..e13d4874 100644
--- a/commons-jcs3-core/src/main/java/org/apache/commons/jcs3/utils/discovery/UDPDiscoverySender.java
+++ b/commons-jcs3-core/src/main/java/org/apache/commons/jcs3/utils/discovery/UDPDiscoverySender.java
@@ -232,13 +232,25 @@ public class UDPDiscoverySender implements AutoCloseable
      */
     public void requestBroadcast()
         throws IOException
+    {
+        requestBroadcast(CacheInfo.listenerId);
+    }
+
+    /**
+     * This allows you to set the sender id. This is mainly for testing.
+     * <p>
+     * @param listenerId listener ID
+     * @throws IOException on error
+     */
+    protected void requestBroadcast(final long listenerId)
+        throws IOException
     {
         log.debug( "sending requestBroadcast" );
 
         final UDPDiscoveryMessage message = new UDPDiscoveryMessage();
         message.setHost(multicastAddress.getHostAddress());
         message.setPort(multicastPort);
-        message.setRequesterId( CacheInfo.listenerId );
+        message.setRequesterId( listenerId );
         message.setMessageType( BroadcastType.REQUEST );
         send( message );
     }
diff --git a/commons-jcs3-core/src/main/java/org/apache/commons/jcs3/utils/discovery/UDPDiscoveryService.java b/commons-jcs3-core/src/main/java/org/apache/commons/jcs3/utils/discovery/UDPDiscoveryService.java
index b85d8b36..7a1862d9 100644
--- a/commons-jcs3-core/src/main/java/org/apache/commons/jcs3/utils/discovery/UDPDiscoveryService.java
+++ b/commons-jcs3-core/src/main/java/org/apache/commons/jcs3/utils/discovery/UDPDiscoveryService.java
@@ -172,10 +172,11 @@ public class UDPDiscoveryService
             }
 
             // todo need some kind of recovery here.
-            receiver = new UDPDiscoveryReceiver( this,
+            receiver = new UDPDiscoveryReceiver( this::processMessage,
                     getUdpDiscoveryAttributes().getUdpDiscoveryInterface(),
                     multicastAddress,
                     getUdpDiscoveryAttributes().getUdpDiscoveryPort() );
+            receiver.setSerializer(serializer);
         }
         catch ( final IOException e )
         {
@@ -382,13 +383,40 @@ public class UDPDiscoveryService
         return getDiscoveryListeners().remove( listener );
     }
 
+    /**
+     * Process the incoming message.
+     */
+    protected void processMessage(UDPDiscoveryMessage message)
+    {
+        final DiscoveredService discoveredService = new DiscoveredService(message);
+
+        switch (message.getMessageType())
+        {
+            case REMOVE:
+                log.debug( "Removing service from set {0}", discoveredService );
+                removeDiscoveredService( discoveredService );
+                break;
+            case REQUEST:
+                // if this is a request message, have the service handle it and
+                // return
+                log.debug( "Message is a Request Broadcast, will have the service handle it." );
+                serviceRequestBroadcast();
+                break;
+            case PASSIVE:
+            default:
+                log.debug( "Adding or updating service to set {0}", discoveredService );
+                addOrUpdateService( discoveredService );
+                break;
+        }
+    }
+
     /**
      * Send a passive broadcast in response to a request broadcast. Never send a request for a
      * request. We can respond to our own requests, since a request broadcast is not intended as a
      * connection request. We might want to only send messages, so we would send a request, but
      * never a passive broadcast.
      */
-    protected void serviceRequestBroadcast()
+    private void serviceRequestBroadcast()
     {
         // create this connection each time.
         // more robust
@@ -477,7 +505,7 @@ public class UDPDiscoveryService
      *
      * @since 3.1
      */
-    protected void shutdownBroadcast()
+    private void shutdownBroadcast()
     {
         // create this connection each time.
         // more robust
diff --git a/commons-jcs3-core/src/test/java/org/apache/commons/jcs3/utils/discovery/UDPDiscoverySenderEncryptedUnitTest.java b/commons-jcs3-core/src/test/java/org/apache/commons/jcs3/utils/discovery/UDPDiscoverySenderEncryptedUnitTest.java
index 12cd19fb..bb586b2c 100644
--- a/commons-jcs3-core/src/test/java/org/apache/commons/jcs3/utils/discovery/UDPDiscoverySenderEncryptedUnitTest.java
+++ b/commons-jcs3-core/src/test/java/org/apache/commons/jcs3/utils/discovery/UDPDiscoverySenderEncryptedUnitTest.java
@@ -1,9 +1,5 @@
 package org.apache.commons.jcs3.utils.discovery;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -23,16 +19,16 @@ import static org.junit.Assert.assertTrue;
  * under the License.
  */
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assume.assumeNotNull;
+
 import java.util.ArrayList;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
+import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
 
 import org.apache.commons.jcs3.utils.discovery.UDPDiscoveryMessage.BroadcastType;
+import org.apache.commons.jcs3.utils.net.HostNameUtil;
 import org.apache.commons.jcs3.utils.serialization.EncryptingSerializer;
 import org.junit.After;
 import org.junit.Before;
@@ -61,25 +57,8 @@ public class UDPDiscoverySenderEncryptedUnitTest
     /** Sender instance for tests */
     private UDPDiscoverySender sender;
 
-    /**
-     * Wait for multicast message for 3 seconds
-     *
-     * @return the object message or null if nothing received within 3 seconds
-     */
-    private UDPDiscoveryMessage getMessage() {
-    	ExecutorService executor = Executors.newCachedThreadPool();
-        Callable<Object> task = () -> receiver.waitForMessage();
-        Future<Object> future = executor.submit(task);
-        try {
-        	Object obj = future.get(3, TimeUnit.SECONDS);
-
-        	assertTrue( "unexpected crap received", obj instanceof UDPDiscoveryMessage );
-
-            return (UDPDiscoveryMessage) obj;
-        } catch (InterruptedException | ExecutionException | TimeoutException ex) {
-        	return null;
-        }
-    }
+    /** Delayed message */
+    private CompletableFuture<UDPDiscoveryMessage> futureMsg;
 
     /**
      * Sets up the receiver. Maybe better to just code sockets here? Set up the sender for sending
@@ -91,10 +70,15 @@ public class UDPDiscoverySenderEncryptedUnitTest
     public void setUp()
         throws Exception
     {
+        assumeNotNull("This machine does not support multicast", HostNameUtil.getMulticastNetworkInterface());
+
         EncryptingSerializer serializer = new EncryptingSerializer();
         serializer.setPreSharedKey("my_key");
 
-        receiver = new UDPDiscoveryReceiver( null, null, ADDRESS, PORT );
+        futureMsg = new CompletableFuture<>();
+        receiver = new UDPDiscoveryReceiver( msg -> {
+            futureMsg.complete(msg);
+        }, null, ADDRESS, PORT );
         receiver.setSerializer(serializer);
         final Thread t = new Thread( receiver );
         t.start();
@@ -111,8 +95,14 @@ public class UDPDiscoverySenderEncryptedUnitTest
     public void tearDown()
         throws Exception
     {
-        receiver.shutdown();
-        sender.close();
+        if (receiver != null)
+        {
+            receiver.shutdown();
+        }
+        if (sender != null)
+        {
+            sender.close();
+        }
     }
 
     /**
@@ -126,13 +116,13 @@ public class UDPDiscoverySenderEncryptedUnitTest
     {
         // SETUP
         final ArrayList<String> cacheNames = new ArrayList<>();
+        cacheNames.add("testCache");
 
         // DO WORK
         sender.passiveBroadcast( SENDING_HOST, SENDING_PORT, cacheNames, 1L );
 
         // VERIFY
-        // grab the sent message
-        final UDPDiscoveryMessage msg = getMessage();
+        UDPDiscoveryMessage msg = futureMsg.get(3, TimeUnit.SECONDS);
         assertNotNull("message not received", msg);
         assertEquals( "wrong port", SENDING_PORT, msg.getPort() );
         assertEquals( "wrong message type", BroadcastType.PASSIVE, msg.getMessageType() );
@@ -149,13 +139,13 @@ public class UDPDiscoverySenderEncryptedUnitTest
     {
         // SETUP
         final ArrayList<String> cacheNames = new ArrayList<>();
+        cacheNames.add("testCache");
 
         // DO WORK
         sender.removeBroadcast( SENDING_HOST, SENDING_PORT, cacheNames, 1L );
 
         // VERIFY
-        // grab the sent message
-        final UDPDiscoveryMessage msg = getMessage();
+        UDPDiscoveryMessage msg = futureMsg.get(3, TimeUnit.SECONDS);
         assertNotNull("message not received", msg);
         assertEquals( "wrong port", SENDING_PORT, msg.getPort() );
         assertEquals( "wrong message type", BroadcastType.REMOVE, msg.getMessageType() );
@@ -171,13 +161,11 @@ public class UDPDiscoverySenderEncryptedUnitTest
         throws Exception
     {
         // DO WORK
-        sender.requestBroadcast();
+        sender.requestBroadcast(1L);
 
         // VERIFY
-        // grab the sent message
-        final UDPDiscoveryMessage msg = getMessage();
+        UDPDiscoveryMessage msg = futureMsg.get(3, TimeUnit.SECONDS);
         assertNotNull("message not received", msg);
         assertEquals( "wrong message type", BroadcastType.REQUEST, msg.getMessageType() );
-
     }
 }
diff --git a/commons-jcs3-core/src/test/java/org/apache/commons/jcs3/utils/discovery/UDPDiscoverySenderUnitTest.java b/commons-jcs3-core/src/test/java/org/apache/commons/jcs3/utils/discovery/UDPDiscoverySenderUnitTest.java
index 01a8ae74..a343ffde 100644
--- a/commons-jcs3-core/src/test/java/org/apache/commons/jcs3/utils/discovery/UDPDiscoverySenderUnitTest.java
+++ b/commons-jcs3-core/src/test/java/org/apache/commons/jcs3/utils/discovery/UDPDiscoverySenderUnitTest.java
@@ -1,8 +1,5 @@
 package org.apache.commons.jcs3.utils.discovery;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -22,30 +19,17 @@ import static org.junit.Assert.assertTrue;
  * under the License.
  */
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assume.assumeNotNull;
+
 import java.util.ArrayList;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
 
 import org.apache.commons.jcs3.utils.discovery.UDPDiscoveryMessage.BroadcastType;
+import org.apache.commons.jcs3.utils.net.HostNameUtil;
 import org.apache.commons.jcs3.utils.serialization.StandardSerializer;
-
-/*
- * 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.
- */
-
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -73,6 +57,9 @@ public class UDPDiscoverySenderUnitTest
     /** Sender instance for tests */
     private UDPDiscoverySender sender;
 
+    /** Delayed message */
+    private CompletableFuture<UDPDiscoveryMessage> futureMsg;
+
     /**
      * Sets up the receiver. Maybe better to just code sockets here? Set up the sender for sending
      * the message.
@@ -83,7 +70,12 @@ public class UDPDiscoverySenderUnitTest
     public void setUp()
         throws Exception
     {
-        receiver = new UDPDiscoveryReceiver( null, null, ADDRESS, PORT );
+        assumeNotNull("This machine does not support multicast", HostNameUtil.getMulticastNetworkInterface());
+
+        futureMsg = new CompletableFuture<>();
+        receiver = new UDPDiscoveryReceiver( msg -> {
+            futureMsg.complete(msg);
+        }, null, ADDRESS, PORT );
         receiver.setSerializer(new StandardSerializer());
         final Thread t = new Thread( receiver );
         t.start();
@@ -100,8 +92,14 @@ public class UDPDiscoverySenderUnitTest
     public void tearDown()
         throws Exception
     {
-        receiver.shutdown();
-        sender.close();
+        if (receiver != null)
+        {
+            receiver.shutdown();
+        }
+        if (sender != null)
+        {
+            sender.close();
+        }
     }
 
     /**
@@ -115,19 +113,14 @@ public class UDPDiscoverySenderUnitTest
     {
         // SETUP
         final ArrayList<String> cacheNames = new ArrayList<>();
+        cacheNames.add("testCache");
 
         // DO WORK
         sender.passiveBroadcast( SENDING_HOST, SENDING_PORT, cacheNames, 1L );
 
         // VERIFY
-        // grab the sent message
-        final Object obj = receiver.waitForMessage() ;
-
-        assertTrue( "unexpected crap received", obj instanceof UDPDiscoveryMessage );
-
-        final UDPDiscoveryMessage msg = (UDPDiscoveryMessage) obj;
-        // disabled test because of JCS-89
-        // assertEquals( "wrong host", SENDING_HOST, msg.getHost() );
+        UDPDiscoveryMessage msg = futureMsg.get(3, TimeUnit.SECONDS);
+        assertNotNull("message not received", msg);
         assertEquals( "wrong port", SENDING_PORT, msg.getPort() );
         assertEquals( "wrong message type", BroadcastType.PASSIVE, msg.getMessageType() );
     }
@@ -143,19 +136,14 @@ public class UDPDiscoverySenderUnitTest
     {
         // SETUP
         final ArrayList<String> cacheNames = new ArrayList<>();
+        cacheNames.add("testCache");
 
         // DO WORK
         sender.removeBroadcast( SENDING_HOST, SENDING_PORT, cacheNames, 1L );
 
         // VERIFY
-        // grab the sent message
-        final Object obj = receiver.waitForMessage();
-
-        assertTrue( "unexpected crap received", obj instanceof UDPDiscoveryMessage );
-
-        final UDPDiscoveryMessage msg = (UDPDiscoveryMessage) obj;
-        // disabled test because of JCS-89
-        // assertEquals( "wrong host", SENDING_HOST, msg.getHost() );
+        UDPDiscoveryMessage msg = futureMsg.get(3, TimeUnit.SECONDS);
+        assertNotNull("message not received", msg);
         assertEquals( "wrong port", SENDING_PORT, msg.getPort() );
         assertEquals( "wrong message type", BroadcastType.REMOVE, msg.getMessageType() );
     }
@@ -170,15 +158,11 @@ public class UDPDiscoverySenderUnitTest
         throws Exception
     {
         // DO WORK
-        sender.requestBroadcast();
+        sender.requestBroadcast(1L);
 
         // VERIFY
-        // grab the sent message
-        final Object obj = receiver.waitForMessage();
-
-        assertTrue( "unexpected crap received", obj instanceof UDPDiscoveryMessage );
-
-        final UDPDiscoveryMessage msg = (UDPDiscoveryMessage) obj;
+        UDPDiscoveryMessage msg = futureMsg.get(3, TimeUnit.SECONDS);
+        assertNotNull("message not received", msg);
         assertEquals( "wrong message type", BroadcastType.REQUEST, msg.getMessageType() );
     }
 }
diff --git a/commons-jcs3-core/src/test/java/org/apache/commons/jcs3/utils/discovery/UDPDiscoveryUnitTest.java b/commons-jcs3-core/src/test/java/org/apache/commons/jcs3/utils/discovery/UDPDiscoveryUnitTest.java
index a3ddc5f2..1af70837 100644
--- a/commons-jcs3-core/src/test/java/org/apache/commons/jcs3/utils/discovery/UDPDiscoveryUnitTest.java
+++ b/commons-jcs3-core/src/test/java/org/apache/commons/jcs3/utils/discovery/UDPDiscoveryUnitTest.java
@@ -1,6 +1,7 @@
 package org.apache.commons.jcs3.utils.discovery;
 
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeNotNull;
 
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
@@ -23,6 +24,7 @@ import static org.junit.Assert.assertTrue;
 
 import java.util.ArrayList;
 
+import org.apache.commons.jcs3.utils.net.HostNameUtil;
 import org.apache.commons.jcs3.utils.serialization.StandardSerializer;
 import org.apache.commons.jcs3.utils.timing.SleepUtil;
 import org.junit.Test;
@@ -54,10 +56,11 @@ public class UDPDiscoveryUnitTest
         service.addDiscoveryListener( discoveryListener );
 
         // create a receiver with the service
-        final UDPDiscoveryReceiver receiver = new UDPDiscoveryReceiver( service,
+        final UDPDiscoveryReceiver receiver = new UDPDiscoveryReceiver( service::processMessage,
                 null,
                 attributes.getUdpDiscoveryAddr(),
                 attributes.getUdpDiscoveryPort() );
+        receiver.setSerializer(service.getSerializer());
         final Thread t = new Thread( receiver );
         t.start();
 
@@ -103,6 +106,8 @@ public class UDPDiscoveryUnitTest
     public void testSimpleUDPDiscoveryIPv4()
         throws Exception
     {
+        assumeNotNull("This machine does not support multicast", HostNameUtil.getMulticastNetworkInterface());
+
         simpleUDPDiscovery("228.5.6.7");
     }
 
@@ -114,6 +119,8 @@ public class UDPDiscoveryUnitTest
     public void testSimpleUDPDiscoveryIPv6()
         throws Exception
     {
+        assumeNotNull("This machine does not support multicast", HostNameUtil.getMulticastNetworkInterface());
+
         simpleUDPDiscovery("FF02::5678");
     }
 }


(commons-jcs) 01/03: Introduce JDBCConnection to handle commit/rollback properly

Posted by tv...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

tv pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-jcs.git

commit d20016e48cbef19d79e78000ba12069be7363b6a
Author: Thomas Vandahl <tv...@apache.org>
AuthorDate: Wed Jun 12 08:15:35 2024 +0200

    Introduce JDBCConnection to handle commit/rollback properly
---
 .../jcs3/auxiliary/disk/jdbc/JDBCConnection.java   | 107 ++++++++++
 .../jcs3/auxiliary/disk/jdbc/JDBCDiskCache.java    | 219 +++++++++++----------
 .../auxiliary/disk/jdbc/mysql/MySQLDiskCache.java  |  15 --
 3 files changed, 226 insertions(+), 115 deletions(-)

diff --git a/commons-jcs3-core/src/main/java/org/apache/commons/jcs3/auxiliary/disk/jdbc/JDBCConnection.java b/commons-jcs3-core/src/main/java/org/apache/commons/jcs3/auxiliary/disk/jdbc/JDBCConnection.java
new file mode 100644
index 00000000..4763265d
--- /dev/null
+++ b/commons-jcs3-core/src/main/java/org/apache/commons/jcs3/auxiliary/disk/jdbc/JDBCConnection.java
@@ -0,0 +1,107 @@
+package org.apache.commons.jcs3.auxiliary.disk.jdbc;
+
+/*
+ * 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
+ *
+ *   https://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.
+ */
+
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+
+/**
+ * Encapsulates connection status tracking and allows AutoClosing within JCS.
+ */
+public class JDBCConnection implements AutoCloseable
+{
+    /** Has this transaction already been committed? */
+    private boolean committed;
+
+    /** Save state of auto-commit */
+    private boolean autoCommit;
+
+    /** The wrapped connection instance */
+    private Connection connection;
+
+    /**
+     * Constructor
+     * @param con Connection object
+     * @throws SQLException if a database error occurs
+     */
+    public JDBCConnection(Connection con) throws SQLException
+    {
+        this.committed = false;
+        this.autoCommit = con.getAutoCommit();
+        this.connection = con;
+        this.connection.setAutoCommit(false);
+    }
+
+    /**
+     * @see java.sql.Connection#prepareStatement(java.lang.String)
+     */
+    public PreparedStatement prepareStatement(String sql) throws SQLException
+    {
+        return connection.prepareStatement(sql);
+    }
+
+    /**
+     * @see java.sql.Connection#commit()
+     */
+    public void commit() throws SQLException
+    {
+        connection.commit();
+        this.committed = true;
+    }
+
+    /**
+     * @see java.sql.Connection#rollback()
+     */
+    public void rollback() throws SQLException
+    {
+        connection.rollback();
+        this.committed = false;
+    }
+
+    /**
+     * @see java.sql.Connection#close()
+     */
+    @Override
+    public void close() throws SQLException
+    {
+        if (!this.committed)
+        {
+            connection.rollback();
+        }
+
+        connection.setAutoCommit(this.autoCommit);
+
+        // Justin Case
+        if (!connection.isClosed())
+        {
+            connection.close();
+        }
+    }
+
+    /**
+     * @see java.sql.Connection#getMetaData()
+     */
+    public DatabaseMetaData getMetaData() throws SQLException
+    {
+        return connection.getMetaData();
+    }
+}
diff --git a/commons-jcs3-core/src/main/java/org/apache/commons/jcs3/auxiliary/disk/jdbc/JDBCDiskCache.java b/commons-jcs3-core/src/main/java/org/apache/commons/jcs3/auxiliary/disk/jdbc/JDBCDiskCache.java
index 70c6cdbf..a160a9dc 100644
--- a/commons-jcs3-core/src/main/java/org/apache/commons/jcs3/auxiliary/disk/jdbc/JDBCDiskCache.java
+++ b/commons-jcs3-core/src/main/java/org/apache/commons/jcs3/auxiliary/disk/jdbc/JDBCDiskCache.java
@@ -20,7 +20,6 @@ package org.apache.commons.jcs3.auxiliary.disk.jdbc;
  */
 
 import java.io.IOException;
-import java.sql.Connection;
 import java.sql.DatabaseMetaData;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
@@ -100,6 +99,28 @@ public class JDBCDiskCache<K, V>
     /** Tracks optimization */
     private TableState tableState;
 
+    /** SQL prepared statements */
+    private static final String SQL_DELETE_EXPIRED =
+        "delete from %s where IS_ETERNAL = ? and REGION = ? and ? > SYSTEM_EXPIRE_TIME_SECONDS";
+    private static final String SQL_GET_SIZE = "select count(*) from %s where REGION = ?";
+    private static final String SQL_DOES_ELEMENT_EXIST = "select CACHE_KEY from %s where REGION = ? and CACHE_KEY = ?";
+    private static final String SQL_REMOVE_ALL = "delete from %s where REGION = ?";
+    private static final String SQL_REMOVE_PARTIAL = "delete from %s where REGION = ? and CACHE_KEY like ?";
+    private static final String SQL_REMOVE_SINGLE = "delete from %s where REGION = ? and CACHE_KEY = ?";
+    private static final String SQL_GET_ELEMENT_MATCHING = "select ELEMENT from %s where REGION = ? and CACHE_KEY like ?";
+    private static final String SQL_GET_ELEMENT = "select ELEMENT from %s where REGION = ? and CACHE_KEY = ?";
+    private static final String SQL_INSERT_ROW = """
+        insert into %s\
+         (CACHE_KEY, REGION, ELEMENT, MAX_LIFE_SECONDS, IS_ETERNAL, CREATE_TIME, UPDATE_TIME_SECONDS,\
+         SYSTEM_EXPIRE_TIME_SECONDS)\s\
+         values (?, ?, ?, ?, ?, ?, ?, ?)""";
+
+    private static final String SQL_UPDATE_ROW = """
+            update %s\
+             set ELEMENT  = ?, CREATE_TIME = ?, UPDATE_TIME_SECONDS = ?,\s\
+             SYSTEM_EXPIRE_TIME_SECONDS = ?\s\
+             where CACHE_KEY = ? and REGION = ?""";
+
     /**
      * Constructs a JDBC Disk Cache for the provided cache attributes. The table state object is
      * used to mark deletions.
@@ -128,7 +149,7 @@ public class JDBCDiskCache<K, V>
      * @param pattern
      * @return String to use in the like query.
      */
-    public String constructLikeParameterFromPattern( final String pattern )
+    protected String constructLikeParameterFromPattern( final String pattern )
     {
         String likePattern = pattern.replace( ".+", "%" );
         likePattern = likePattern.replace( ".", "_" );
@@ -138,6 +159,17 @@ public class JDBCDiskCache<K, V>
         return likePattern;
     }
 
+    /**
+     * Get a connection from the data source and prepare it for use
+     *
+     * @return A database connection
+     * @throws SQLException if getting the connection goes wrong
+     */
+    protected JDBCConnection getConnection() throws SQLException
+    {
+        return new JDBCConnection(getDataSource().getConnection());
+    }
+
     /**
      * Removed the expired. (now - create time) &gt; max life seconds * 1000
      * <p>
@@ -147,21 +179,19 @@ public class JDBCDiskCache<K, V>
     {
         int deleted = 0;
 
-        try (Connection con = getDataSource().getConnection())
+        try (JDBCConnection con = getConnection())
         {
             // The shrinker thread might kick in before the table is created
             // So check if the table exists first
             final DatabaseMetaData dmd = con.getMetaData();
-            final ResultSet result = dmd.getTables(null, null,
-                    getJdbcDiskCacheAttributes().getTableName(), null);
+            final ResultSet result = dmd.getTables(null, null, getTableName(), null);
 
             if (result.next())
             {
                 getTableState().setState( TableState.DELETE_RUNNING );
                 final long now = System.currentTimeMillis() / 1000;
 
-                final String sql = String.format("delete from %s where IS_ETERNAL = ? and REGION = ?"
-                        + " and ? > SYSTEM_EXPIRE_TIME_SECONDS", getJdbcDiskCacheAttributes().getTableName());
+                final String sql = String.format(SQL_DELETE_EXPIRED, getTableName());
 
                 try (PreparedStatement psDelete = con.prepareStatement( sql ))
                 {
@@ -184,8 +214,7 @@ public class JDBCDiskCache<K, V>
             }
             else
             {
-                log.warn( "Trying to shrink non-existing table [{0}]",
-                        getJdbcDiskCacheAttributes().getTableName() );
+                log.warn( "Trying to shrink non-existing table [{0}]", getTableName() );
             }
         }
         catch ( final SQLException e )
@@ -210,12 +239,11 @@ public class JDBCDiskCache<K, V>
      * @param con a database connection
      * @return boolean
      */
-    protected boolean doesElementExist( final ICacheElement<K, V> ce, final Connection con )
+    protected boolean doesElementExist( final ICacheElement<K, V> ce, final JDBCConnection con )
     {
         boolean exists = false;
         // don't select the element, since we want this to be fast.
-        final String sqlS = String.format("select CACHE_KEY from %s where REGION = ? and CACHE_KEY = ?",
-                getJdbcDiskCacheAttributes().getTableName());
+        final String sqlS = String.format(SQL_DOES_ELEMENT_EXIST, getTableName());
 
         try (PreparedStatement psSelect = con.prepareStatement( sqlS ))
         {
@@ -275,6 +303,14 @@ public class JDBCDiskCache<K, V>
         return jdbcDiskCacheAttributes;
     }
 
+    /**
+     * @param jdbcDiskCacheAttributes The jdbcDiskCacheAttributes to set.
+     */
+    protected void setJdbcDiskCacheAttributes( final JDBCDiskCacheAttributes jdbcDiskCacheAttributes )
+    {
+        this.jdbcDiskCacheAttributes = jdbcDiskCacheAttributes;
+    }
+
     /**
      * Return the keys in this cache.
      * <p>
@@ -298,10 +334,9 @@ public class JDBCDiskCache<K, V>
         int size = 0;
 
         // region, key
-        final String selectString = String.format("select count(*) from %s where REGION = ?",
-                getJdbcDiskCacheAttributes().getTableName());
+        final String selectString = String.format(SQL_GET_SIZE, getTableName());
 
-        try (Connection con = getDataSource().getConnection())
+        try (JDBCConnection con = getConnection())
         {
             try (PreparedStatement psSelect = con.prepareStatement( selectString ))
             {
@@ -340,7 +375,7 @@ public class JDBCDiskCache<K, V>
         elems.add(new StatElement<>( "Update Count", updateCount ) );
         elems.add(new StatElement<>( "Get Count", getCount ) );
         elems.add(new StatElement<>( "Get Matching Count", getMatchingCount ) );
-        elems.add(new StatElement<>( "DB URL", getJdbcDiskCacheAttributes().getUrl()) );
+        elems.add(new StatElement<>( "DB URL", getDiskLocation()) );
 
         stats.setStatElements( elems );
 
@@ -354,12 +389,8 @@ public class JDBCDiskCache<K, V>
      */
     protected String getTableName()
     {
-        String name = "UNDEFINED";
-        if ( this.getJdbcDiskCacheAttributes() != null )
-        {
-            name = this.getJdbcDiskCacheAttributes().getTableName();
-        }
-        return name;
+        return this.jdbcDiskCacheAttributes != null ?
+                this.jdbcDiskCacheAttributes.getTableName() : "UNDEFINED";
     }
 
     /**
@@ -370,6 +401,14 @@ public class JDBCDiskCache<K, V>
         return tableState;
     }
 
+    /**
+     * @param tableState The tableState to set.
+     */
+    public void setTableState( final TableState tableState )
+    {
+        this.tableState = tableState;
+    }
+
     /**
      * If test before insert it true, we check to see if the element exists. If the element exists
      * we will update. Otherwise, we try inserting.  If this fails because the item exists, we will
@@ -379,7 +418,7 @@ public class JDBCDiskCache<K, V>
      * @param con
      * @param element
      */
-    private void insertOrUpdate( final ICacheElement<K, V> ce, final Connection con, final byte[] element )
+    private void insertOrUpdate( final ICacheElement<K, V> ce, final JDBCConnection con, final byte[] element )
     {
         boolean exists = false;
 
@@ -410,14 +449,10 @@ public class JDBCDiskCache<K, V>
      * @param element
      * @return true if the insertion fails because the record exists.
      */
-    private boolean insertRow( final ICacheElement<K, V> ce, final Connection con, final byte[] element )
+    private boolean insertRow( final ICacheElement<K, V> ce, final JDBCConnection con, final byte[] element )
     {
         boolean exists = false;
-        final String sqlI = String.format("""
-        	insert into %s\
-        	 (CACHE_KEY, REGION, ELEMENT, MAX_LIFE_SECONDS, IS_ETERNAL, CREATE_TIME, UPDATE_TIME_SECONDS,\
-        	 SYSTEM_EXPIRE_TIME_SECONDS)\s\
-        	 values (?, ?, ?, ?, ?, ?, ?, ?)""", getJdbcDiskCacheAttributes().getTableName());
+        final String sqlI = String.format(SQL_INSERT_ROW, getTableName());
 
         try (PreparedStatement psInsert = con.prepareStatement( sqlI ))
         {
@@ -459,6 +494,42 @@ public class JDBCDiskCache<K, V>
         return exists;
     }
 
+    /**
+     * This updates a row in the database.
+     * <p>
+     * @param ce
+     * @param con
+     * @param element
+     */
+    private void updateRow( final ICacheElement<K, V> ce, final JDBCConnection con, final byte[] element )
+    {
+        final String sqlU = String.format(SQL_UPDATE_ROW, getTableName());
+
+        try (PreparedStatement psUpdate = con.prepareStatement( sqlU ))
+        {
+            psUpdate.setBytes( 1, element );
+
+            final Timestamp createTime = new Timestamp( ce.getElementAttributes().getCreateTime() );
+            psUpdate.setTimestamp( 2, createTime );
+
+            final long now = System.currentTimeMillis() / 1000;
+            psUpdate.setLong( 3, now );
+
+            final long expireTime = now + ce.getElementAttributes().getMaxLife();
+            psUpdate.setLong( 4, expireTime );
+
+            psUpdate.setString( 5, (String) ce.getKey() );
+            psUpdate.setString( 6, this.getCacheName() );
+            psUpdate.execute();
+
+            log.debug( "ran update {0}", sqlU );
+        }
+        catch ( final SQLException e )
+        {
+            log.error( "Error executing update sql [{0}]", sqlU, e );
+        }
+    }
+
     /** Shuts down the pool */
     @Override
     public void processDispose()
@@ -501,10 +572,9 @@ public class JDBCDiskCache<K, V>
         ICacheElement<K, V> obj = null;
 
         // region, key
-        final String selectString = String.format("select ELEMENT from %s where REGION = ? and CACHE_KEY = ?",
-                getJdbcDiskCacheAttributes().getTableName());
+        final String selectString = String.format(SQL_GET_ELEMENT, getTableName());
 
-        try (Connection con = getDataSource().getConnection())
+        try (JDBCConnection con = getConnection())
         {
             try (PreparedStatement psSelect = con.prepareStatement( selectString ))
             {
@@ -534,6 +604,8 @@ public class JDBCDiskCache<K, V>
                     }
                 }
             }
+
+            con.commit();
         }
         catch ( final SQLException sqle )
         {
@@ -566,10 +638,9 @@ public class JDBCDiskCache<K, V>
         final Map<K, ICacheElement<K, V>> results = new HashMap<>();
 
         // region, key
-        final String selectString = String.format("select ELEMENT from %s where REGION = ? and CACHE_KEY like ?",
-                getJdbcDiskCacheAttributes().getTableName());
+        final String selectString = String.format(SQL_GET_ELEMENT_MATCHING, getTableName());
 
-        try (Connection con = getDataSource().getConnection())
+        try (JDBCConnection con = getConnection())
         {
             try (PreparedStatement psSelect = con.prepareStatement( selectString ))
             {
@@ -597,6 +668,8 @@ public class JDBCDiskCache<K, V>
                     }
                 }
             }
+
+            con.commit();
         }
         catch ( final SQLException sqle )
         {
@@ -618,13 +691,11 @@ public class JDBCDiskCache<K, V>
     protected boolean processRemove( final K key )
     {
         // remove single item.
-        final String sqlSingle = String.format("delete from %s where REGION = ? and CACHE_KEY = ?",
-                getJdbcDiskCacheAttributes().getTableName());
+        final String sqlSingle = String.format(SQL_REMOVE_SINGLE, getTableName());
         // remove all keys of the same name group.
-        final String sqlPartial = String.format("delete from %s where REGION = ? and CACHE_KEY like ?",
-                getJdbcDiskCacheAttributes().getTableName());
+        final String sqlPartial = String.format(SQL_REMOVE_PARTIAL, getTableName());
 
-        try (Connection con = getDataSource().getConnection())
+        try (JDBCConnection con = getConnection())
         {
             boolean partial = key.toString().endsWith(ICache.NAME_COMPONENT_DELIMITER);
             String sql = partial ? sqlPartial : sqlSingle;
@@ -644,6 +715,7 @@ public class JDBCDiskCache<K, V>
                 psSelect.executeUpdate();
 
                 setAlive(true);
+                con.commit();
             }
             catch ( final SQLException e )
             {
@@ -669,10 +741,9 @@ public class JDBCDiskCache<K, V>
         // it should never get here from the abstract disk cache.
         if ( this.jdbcDiskCacheAttributes.isAllowRemoveAll() )
         {
-            final String sql = String.format("delete from %s where REGION = ?",
-                    getJdbcDiskCacheAttributes().getTableName());
+            final String sql = String.format(SQL_REMOVE_ALL, getTableName());
 
-            try (Connection con = getDataSource().getConnection())
+            try (JDBCConnection con = getConnection())
             {
                 try (PreparedStatement psDelete = con.prepareStatement( sql ))
                 {
@@ -685,6 +756,8 @@ public class JDBCDiskCache<K, V>
                     log.error( "Problem creating statement.", e );
                     setAlive(false);
                 }
+
+                con.commit();
             }
             catch ( final SQLException e )
             {
@@ -713,7 +786,7 @@ public class JDBCDiskCache<K, V>
 
         log.debug( "updating, ce = {0}", ce );
 
-        try (Connection con = getDataSource().getConnection())
+        try (JDBCConnection con = getConnection())
         {
             log.debug( "Putting [{0}] on disk.", ce::getKey);
 
@@ -726,6 +799,8 @@ public class JDBCDiskCache<K, V>
             {
                 log.error( "Could not serialize element", e );
             }
+
+            con.commit();
         }
         catch ( final SQLException e )
         {
@@ -741,22 +816,6 @@ public class JDBCDiskCache<K, V>
         // nothing
     }
 
-    /**
-     * @param jdbcDiskCacheAttributes The jdbcDiskCacheAttributes to set.
-     */
-    protected void setJdbcDiskCacheAttributes( final JDBCDiskCacheAttributes jdbcDiskCacheAttributes )
-    {
-        this.jdbcDiskCacheAttributes = jdbcDiskCacheAttributes;
-    }
-
-    /**
-     * @param tableState The tableState to set.
-     */
-    public void setTableState( final TableState tableState )
-    {
-        this.tableState = tableState;
-    }
-
     /**
      * For debugging.
      * <p>
@@ -767,44 +826,4 @@ public class JDBCDiskCache<K, V>
     {
         return this.getStats();
     }
-
-    /**
-     * This updates a row in the database.
-     * <p>
-     * @param ce
-     * @param con
-     * @param element
-     */
-    private void updateRow( final ICacheElement<K, V> ce, final Connection con, final byte[] element )
-    {
-        final String sqlU = String.format("""
-        	update %s\
-        	 set ELEMENT  = ?, CREATE_TIME = ?, UPDATE_TIME_SECONDS = ?,\s\
-        	 SYSTEM_EXPIRE_TIME_SECONDS = ?\s\
-        	 where CACHE_KEY = ? and REGION = ?""", getJdbcDiskCacheAttributes().getTableName());
-
-        try (PreparedStatement psUpdate = con.prepareStatement( sqlU ))
-        {
-            psUpdate.setBytes( 1, element );
-
-            final Timestamp createTime = new Timestamp( ce.getElementAttributes().getCreateTime() );
-            psUpdate.setTimestamp( 2, createTime );
-
-            final long now = System.currentTimeMillis() / 1000;
-            psUpdate.setLong( 3, now );
-
-            final long expireTime = now + ce.getElementAttributes().getMaxLife();
-            psUpdate.setLong( 4, expireTime );
-
-            psUpdate.setString( 5, (String) ce.getKey() );
-            psUpdate.setString( 6, this.getCacheName() );
-            psUpdate.execute();
-
-            log.debug( "ran update {0}", sqlU );
-        }
-        catch ( final SQLException e )
-        {
-            log.error( "Error executing update sql [{0}]", sqlU, e );
-        }
-    }
 }
diff --git a/commons-jcs3-core/src/main/java/org/apache/commons/jcs3/auxiliary/disk/jdbc/mysql/MySQLDiskCache.java b/commons-jcs3-core/src/main/java/org/apache/commons/jcs3/auxiliary/disk/jdbc/mysql/MySQLDiskCache.java
index fe004b3a..ec1668f8 100644
--- a/commons-jcs3-core/src/main/java/org/apache/commons/jcs3/auxiliary/disk/jdbc/mysql/MySQLDiskCache.java
+++ b/commons-jcs3-core/src/main/java/org/apache/commons/jcs3/auxiliary/disk/jdbc/mysql/MySQLDiskCache.java
@@ -64,21 +64,6 @@ public class MySQLDiskCache<K, V>
         log.debug( "MySQLDiskCacheAttributes = {0}", attributes );
     }
 
-    /**
-     * @param pattern
-     * @return String to use in the like query.
-     */
-    @Override
-    public String constructLikeParameterFromPattern( final String pattern )
-    {
-        String likePattern = pattern.replace( ".+", "%" );
-        likePattern = likePattern.replace( ".", "_" );
-
-        log.debug( "pattern = [{0}]", likePattern );
-
-        return likePattern;
-    }
-
     /**
      * Removed the expired. (now - create time) &gt; max life seconds * 1000
      * <p>