1414public final class Pools {
1515
1616 private static final AtomicInteger poolIndex = new AtomicInteger ();
17- private static final Map <Configuration , Pool > poolMap = new ConcurrentHashMap <>();
17+ private static final Map <Configuration , PoolHolder > poolMap = new ConcurrentHashMap <>();
1818 private static ScheduledThreadPoolExecutor poolExecutor = null ;
1919
20+ static class PoolHolder {
21+ private final Configuration conf ;
22+ private final int poolIndex ;
23+ private final ScheduledThreadPoolExecutor executor ;
24+ private Pool pool ;
25+
26+ PoolHolder (Configuration conf , int poolIndex , ScheduledThreadPoolExecutor executor ) {
27+ this .conf = conf ;
28+ this .poolIndex = poolIndex ;
29+ this .executor = executor ;
30+ }
31+
32+ synchronized Pool getPool () {
33+ if (pool == null ) {
34+ pool = new Pool (conf , poolIndex , executor );
35+ }
36+ return pool ;
37+ }
38+ }
39+
2040 /**
2141 * Get existing pool for a configuration. Create it if it doesn't exist.
2242 *
2343 * @param conf configuration parser
2444 * @return pool
2545 */
2646 public static Pool retrievePool (Configuration conf ) {
27- if (!poolMap .containsKey (conf )) {
47+ PoolHolder holder = poolMap .get (conf );
48+ if (holder == null ) {
2849 synchronized (poolMap ) {
29- if (!poolMap .containsKey (conf )) {
50+ holder = poolMap .get (conf );
51+ if (holder == null ) {
3052 if (poolExecutor == null ) {
3153 poolExecutor =
3254 new ScheduledThreadPoolExecutor (
3355 1 , new PoolThreadFactory ("MariaDbPool-maxTimeoutIdle-checker" ));
3456 }
35- Pool pool = new Pool (conf , poolIndex .incrementAndGet (), poolExecutor );
36- poolMap .put (conf , pool );
37- return pool ;
57+ holder = new PoolHolder (conf , poolIndex .incrementAndGet (), poolExecutor );
58+ poolMap .put (conf , holder );
3859 }
3960 }
4061 }
41- return poolMap .get (conf );
62+ // Don't initialize a pool while holding a lock on `poolMap`.
63+ return holder .getPool ();
4264 }
4365
4466 /**
@@ -49,12 +71,9 @@ public static Pool retrievePool(Configuration conf) {
4971 public static void remove (Pool pool ) {
5072 if (poolMap .containsKey (pool .getConf ())) {
5173 synchronized (poolMap ) {
52- if (poolMap .containsKey (pool .getConf ())) {
53- poolMap .remove (pool .getConf ());
54-
55- if (poolMap .isEmpty ()) {
56- shutdownExecutor ();
57- }
74+ PoolHolder previous = poolMap .remove (pool .getConf ());
75+ if (previous != null && poolMap .isEmpty ()) {
76+ shutdownExecutor ();
5877 }
5978 }
6079 }
@@ -63,9 +82,9 @@ public static void remove(Pool pool) {
6382 /** Close all pools. */
6483 public static void close () {
6584 synchronized (poolMap ) {
66- for (Pool pool : poolMap .values ()) {
85+ for (PoolHolder holder : poolMap .values ()) {
6786 try {
68- pool .close ();
87+ holder . getPool () .close ();
6988 } catch (Exception exception ) {
7089 // eat
7190 }
@@ -85,10 +104,12 @@ public static void close(String poolName) {
85104 return ;
86105 }
87106 synchronized (poolMap ) {
88- for (Pool pool : poolMap .values ()) {
89- if (poolName .equals (pool . getConf () .poolName ())) {
107+ for (PoolHolder holder : poolMap .values ()) {
108+ if (poolName .equals (holder . conf .poolName ())) {
90109 try {
91- pool .close (); // Pool.close() calls Pools.remove(), which does the rest of the cleanup
110+ holder
111+ .getPool ()
112+ .close (); // Pool.close() calls Pools.remove(), which does the rest of the cleanup
92113 } catch (Exception exception ) {
93114 // eat
94115 }
0 commit comments