From 8cfb7809dc8f34b6e2977bc6f00626a3938026dc Mon Sep 17 00:00:00 2001 From: Brett Wooldridge Date: Thu, 15 May 2014 11:20:59 +0900 Subject: [PATCH] Use the generic FastList in more places, fix some JavaDoc warnings from Java 8. --- .../com/zaxxer/hikari/pool/HikariPool.java | 1 + .../zaxxer/hikari/proxy/ConnectionProxy.java | 8 +- .../hikari/proxy/IHikariConnectionProxy.java | 3 +- .../com/zaxxer/hikari/proxy/ProxyFactory.java | 1 + .../com/zaxxer/hikari/util/ConcurrentBag.java | 29 ++-- .../java/com/zaxxer/hikari/util/FastList.java | 151 ++++++++++++++++++ .../java/com/zaxxer/hikari/TestFastList.java | 10 +- 7 files changed, 179 insertions(+), 24 deletions(-) create mode 100644 src/main/java/com/zaxxer/hikari/util/FastList.java diff --git a/src/main/java/com/zaxxer/hikari/pool/HikariPool.java b/src/main/java/com/zaxxer/hikari/pool/HikariPool.java index bcb46306..72580789 100644 --- a/src/main/java/com/zaxxer/hikari/pool/HikariPool.java +++ b/src/main/java/com/zaxxer/hikari/pool/HikariPool.java @@ -197,6 +197,7 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener * Release a connection back to the pool, or permanently close it if it is broken. * * @param connectionProxy the connection to release back to the pool + * @param isBroken true if the connection was detected as broken */ public void releaseConnection(final IHikariConnectionProxy connectionProxy, final boolean isBroken) { diff --git a/src/main/java/com/zaxxer/hikari/proxy/ConnectionProxy.java b/src/main/java/com/zaxxer/hikari/proxy/ConnectionProxy.java index aadd4bbc..445328f7 100644 --- a/src/main/java/com/zaxxer/hikari/proxy/ConnectionProxy.java +++ b/src/main/java/com/zaxxer/hikari/proxy/ConnectionProxy.java @@ -31,7 +31,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.zaxxer.hikari.pool.HikariPool; -import com.zaxxer.hikari.util.FastStatementList; +import com.zaxxer.hikari.util.FastList; /** * This is the proxy class for java.sql.Connection. @@ -46,7 +46,7 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy protected final Connection delegate; - private final FastStatementList openStatements; + private final FastList openStatements; private final HikariPool parentPool; private final AtomicInteger state; private final String defaultCatalog; @@ -94,7 +94,7 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy long now = System.currentTimeMillis(); this.expirationTime = (maxLifetime > 0 ? now + maxLifetime : Long.MAX_VALUE); this.lastAccess = now; - this.openStatements = new FastStatementList(); + this.openStatements = new FastList(Statement.class); this.hashCode = System.identityHashCode(this); isCatalogDirty = true; @@ -233,7 +233,7 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy /** {@inheritDoc} */ @Override - public final void untrackStatement(Object statement) + public final void untrackStatement(Statement statement) { // If the connection is not closed. If it is closed, it means this is being // called back as a result of the close() method below in which case we diff --git a/src/main/java/com/zaxxer/hikari/proxy/IHikariConnectionProxy.java b/src/main/java/com/zaxxer/hikari/proxy/IHikariConnectionProxy.java index 17f31cc4..9b4d491f 100644 --- a/src/main/java/com/zaxxer/hikari/proxy/IHikariConnectionProxy.java +++ b/src/main/java/com/zaxxer/hikari/proxy/IHikariConnectionProxy.java @@ -18,6 +18,7 @@ package com.zaxxer.hikari.proxy; import java.sql.Connection; import java.sql.SQLException; +import java.sql.Statement; import java.util.Timer; import com.zaxxer.hikari.util.ConcurrentBag.IBagManagable; @@ -101,5 +102,5 @@ public interface IHikariConnectionProxy extends Connection, IBagManagable * * @param statement the Statement to remove from tracking */ - void untrackStatement(Object statement); + void untrackStatement(Statement statement); } diff --git a/src/main/java/com/zaxxer/hikari/proxy/ProxyFactory.java b/src/main/java/com/zaxxer/hikari/proxy/ProxyFactory.java index 0ac16edd..057e7917 100644 --- a/src/main/java/com/zaxxer/hikari/proxy/ProxyFactory.java +++ b/src/main/java/com/zaxxer/hikari/proxy/ProxyFactory.java @@ -41,6 +41,7 @@ public final class ProxyFactory * * @param pool the {@link HikariPool} that will own this proxy * @param connection the {@link Connection} that will be wrapped by this proxy + * @param maxLifeTime the lifetime of the connection * @param defaultIsolationLevel the default transaction isolation level of the underlying {@link Connection} * @param defaultAutoCommit the default auto-commit state of the underlying {@link Connection} * @param defaultIReadOnly the default readOnly state of the underlying {@link Connection} diff --git a/src/main/java/com/zaxxer/hikari/util/ConcurrentBag.java b/src/main/java/com/zaxxer/hikari/util/ConcurrentBag.java index 07ab3ae5..165e2845 100644 --- a/src/main/java/com/zaxxer/hikari/util/ConcurrentBag.java +++ b/src/main/java/com/zaxxer/hikari/util/ConcurrentBag.java @@ -17,7 +17,6 @@ package com.zaxxer.hikari.util; import java.lang.ref.WeakReference; import java.util.ArrayList; -import java.util.LinkedList; import java.util.List; import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.TimeUnit; @@ -74,7 +73,7 @@ public class ConcurrentBag>> threadList; + private ThreadLocal>> threadList; private CopyOnWriteArraySet sharedList; private Synchronizer synchronizer; private IBagStateListener listener; @@ -86,7 +85,7 @@ public class ConcurrentBag(); this.synchronizer = new Synchronizer(); - this.threadList = new ThreadLocal>>(); + this.threadList = new ThreadLocal>>(); } /** @@ -101,20 +100,22 @@ public class ConcurrentBag> list = threadList.get(); + FastList> list = threadList.get(); if (list == null) { - list = new LinkedList>(); + list = new FastList>(WeakReference.class); threadList.set(list); } - - while (!list.isEmpty()) + else { - final WeakReference reference = list.removeFirst(); - final T element = reference.get(); - if (element != null && element.compareAndSetState(STATE_NOT_IN_USE, STATE_IN_USE)) + for (int i = list.size() - 1; i >= 0; i--) { - return element; + final WeakReference reference = list.removeLast(); + final T element = reference.get(); + if (element != null && element.compareAndSetState(STATE_NOT_IN_USE, STATE_IN_USE)) + { + return element; + } } } @@ -161,14 +162,14 @@ public class ConcurrentBag> list = threadList.get(); + FastList> list = threadList.get(); if (list == null) { - list = new LinkedList>(); + list = new FastList>(WeakReference.class); threadList.set(list); } - list.addLast(new WeakReference(value)); + list.add(new WeakReference(value)); synchronizer.releaseShared(System.nanoTime()); } else diff --git a/src/main/java/com/zaxxer/hikari/util/FastList.java b/src/main/java/com/zaxxer/hikari/util/FastList.java new file mode 100644 index 00000000..90e882c4 --- /dev/null +++ b/src/main/java/com/zaxxer/hikari/util/FastList.java @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2013, 2014 Brett Wooldridge + * + * Licensed 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 com.zaxxer.hikari.util; + +import java.lang.reflect.Array; + + +/** + * Fast list without range checking. + * + * @author Brett Wooldridge + */ +public final class FastList +{ + private T[] elementData; + + private int size; + + /** + * Construct a FastList with a default size of 32. + * @param clazz the Class stored in the collection + */ + @SuppressWarnings("unchecked") + public FastList(Class clazz) + { + this.elementData = (T[]) Array.newInstance(clazz, 32); + } + + /** + * Construct a FastList with a specfied size. + * @param clazz the Class stored in the collection + * @param size the initial size of the FastList + */ + @SuppressWarnings("unchecked") + public FastList(Class clazz, int size) + { + this.elementData = (T[]) Array.newInstance(clazz, size); + } + + /** + * Add an element to the tail of the FastList. + * + * @param element the element to add + */ + public void add(T element) + { + try + { + elementData[size] = element; + size++; + } + catch (ArrayIndexOutOfBoundsException e) + { + // overflow-conscious code + final int oldCapacity = elementData.length; + final int newCapacity = oldCapacity << 1; + @SuppressWarnings("unchecked") + final T[] newElementData = (T[]) Array.newInstance(element.getClass(), newCapacity); //new Statement[newCapacity]; + System.arraycopy(elementData, 0, newElementData, 0, oldCapacity); + newElementData[size++] = element; + elementData = newElementData; + } + } + + /** + * Get the element at the specified index. + * + * @param index the index of the element to get + * @return the element, or ArrayIndexOutOfBounds is thrown if the index is invalid + */ + public T get(int index) + { + return elementData[index]; + } + + /** + * This remove method is most efficient when the element being removed + * is the last element. Equality is identity based, not equals() based. + * Only the first matching element is removed. + * + * @return the last element of the list + */ + public T removeLast() + { + T t = elementData[--size]; + elementData[size] = null; + return t; + } + + /** + * This remove method is most efficient when the element being removed + * is the last element. Equality is identity based, not equals() based. + * Only the first matching element is removed. + * + * @param element the element to remove + */ + public void remove(T element) + { + for (int index = size - 1; index >= 0; index--) + { + if (element == elementData[index]) + { + final int numMoved = size - index - 1; + if (numMoved > 0) + { + System.arraycopy(elementData, index + 1, elementData, index, numMoved); + } + elementData[--size] = null; + break; + } + } + } + + /** + * Clear the FastList. + */ + public void clear() + { + for (int i = 0; i < size; i++) + { + elementData[i] = null; + } + + size = 0; + } + + + /** + * Get the current number of elements in the FastList. + * + * @return the number of current elements + */ + public int size() + { + return size; + } +} diff --git a/src/test/java/com/zaxxer/hikari/TestFastList.java b/src/test/java/com/zaxxer/hikari/TestFastList.java index 7d392ee8..3be6b00f 100644 --- a/src/test/java/com/zaxxer/hikari/TestFastList.java +++ b/src/test/java/com/zaxxer/hikari/TestFastList.java @@ -7,16 +7,16 @@ import org.junit.Assert; import org.junit.Test; import com.zaxxer.hikari.mocks.StubStatement; -import com.zaxxer.hikari.util.FastStatementList; +import com.zaxxer.hikari.util.FastList; -public class TestFastStatementList +public class TestFastList { @Test public void testAddRemove() { ArrayList verifyList = new ArrayList(); - FastStatementList list = new FastStatementList(); + FastList list = new FastList(Statement.class); for (int i = 0; i < 32; i++) { StubStatement statement = new StubStatement(null); @@ -38,7 +38,7 @@ public class TestFastStatementList { ArrayList verifyList = new ArrayList(); - FastStatementList list = new FastStatementList(); + FastList list = new FastList(Statement.class); for (int i = 0; i < 32; i++) { StubStatement statement = new StubStatement(null); @@ -60,7 +60,7 @@ public class TestFastStatementList { ArrayList verifyList = new ArrayList(); - FastStatementList list = new FastStatementList(); + FastList list = new FastList(Statement.class); for (int i = 0; i < 100; i++) { StubStatement statement = new StubStatement(null);