2571 |
13 Aug 14 |
nicklas |
1 |
/** |
2571 |
13 Aug 14 |
nicklas |
$Id$ |
2571 |
13 Aug 14 |
nicklas |
3 |
|
2571 |
13 Aug 14 |
nicklas |
Copyright (C) 2014 Nicklas Nordborg |
2571 |
13 Aug 14 |
nicklas |
5 |
|
2571 |
13 Aug 14 |
nicklas |
This file is part of BASE - BioArray Software Environment. |
2571 |
13 Aug 14 |
nicklas |
Available at http://base.thep.lu.se/ |
2571 |
13 Aug 14 |
nicklas |
8 |
|
2571 |
13 Aug 14 |
nicklas |
BASE is free software; you can redistribute it and/or |
2571 |
13 Aug 14 |
nicklas |
modify it under the terms of the GNU General Public License |
2571 |
13 Aug 14 |
nicklas |
as published by the Free Software Foundation; either version 3 |
2571 |
13 Aug 14 |
nicklas |
of the License, or (at your option) any later version. |
2571 |
13 Aug 14 |
nicklas |
13 |
|
2571 |
13 Aug 14 |
nicklas |
BASE is distributed in the hope that it will be useful, |
2571 |
13 Aug 14 |
nicklas |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
2571 |
13 Aug 14 |
nicklas |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2571 |
13 Aug 14 |
nicklas |
GNU General Public License for more details. |
2571 |
13 Aug 14 |
nicklas |
18 |
|
2571 |
13 Aug 14 |
nicklas |
You should have received a copy of the GNU General Public License |
2571 |
13 Aug 14 |
nicklas |
along with BASE. If not, see <http://www.gnu.org/licenses/>. |
2571 |
13 Aug 14 |
nicklas |
21 |
*/ |
2571 |
13 Aug 14 |
nicklas |
22 |
package net.sf.basedb.xfiles; |
2571 |
13 Aug 14 |
nicklas |
23 |
|
2571 |
13 Aug 14 |
nicklas |
24 |
import java.io.Closeable; |
2571 |
13 Aug 14 |
nicklas |
25 |
import java.util.Comparator; |
2571 |
13 Aug 14 |
nicklas |
26 |
import java.util.Map; |
2571 |
13 Aug 14 |
nicklas |
27 |
import java.util.TreeMap; |
2571 |
13 Aug 14 |
nicklas |
28 |
|
2571 |
13 Aug 14 |
nicklas |
29 |
import net.sf.basedb.core.DbControl; |
2571 |
13 Aug 14 |
nicklas |
30 |
import net.sf.basedb.core.TransactionalAction; |
2571 |
13 Aug 14 |
nicklas |
31 |
|
2571 |
13 Aug 14 |
nicklas |
32 |
/** |
2571 |
13 Aug 14 |
nicklas |
Cache implementation for holding connections to remote server. Caching is done per |
2571 |
13 Aug 14 |
nicklas |
thread so there should not be any multi-threading issues. Before a cache can be |
2571 |
13 Aug 14 |
nicklas |
used it must be initialized with a DbControl, since we need to detect when the |
2571 |
13 Aug 14 |
nicklas |
transaction has ended and remove the cache. |
2571 |
13 Aug 14 |
nicklas |
37 |
|
2571 |
13 Aug 14 |
nicklas |
@since 1.1 |
2571 |
13 Aug 14 |
nicklas |
39 |
*/ |
2571 |
13 Aug 14 |
nicklas |
40 |
public class ConnectionCache<C extends Closeable> |
2571 |
13 Aug 14 |
nicklas |
41 |
implements TransactionalAction |
2571 |
13 Aug 14 |
nicklas |
42 |
{ |
2571 |
13 Aug 14 |
nicklas |
43 |
|
2572 |
13 Aug 14 |
nicklas |
44 |
private final ThreadLocal<Map<ConnectionInfo, C>> cache; |
2571 |
13 Aug 14 |
nicklas |
45 |
private final ThreadLocal<Boolean> initialized; |
2571 |
13 Aug 14 |
nicklas |
46 |
|
2571 |
13 Aug 14 |
nicklas |
47 |
/** |
2571 |
13 Aug 14 |
nicklas |
Create a new cache. The comparator implementation should be such that |
2571 |
13 Aug 14 |
nicklas |
if two sets of connection parameters result in a connection to the same server |
2571 |
13 Aug 14 |
nicklas |
with the same credentials, the parameters shold be considered equal. |
2571 |
13 Aug 14 |
nicklas |
51 |
|
2571 |
13 Aug 14 |
nicklas |
@param comparator A comparator that is used to check if connection parameters |
2571 |
13 Aug 14 |
nicklas |
are equal |
2571 |
13 Aug 14 |
nicklas |
54 |
*/ |
2572 |
13 Aug 14 |
nicklas |
55 |
public ConnectionCache(Comparator<ConnectionInfo> comparator) |
2571 |
13 Aug 14 |
nicklas |
56 |
{ |
2571 |
13 Aug 14 |
nicklas |
57 |
this.cache = new TheCache<C>(comparator); |
2571 |
13 Aug 14 |
nicklas |
58 |
this.initialized = new ThreadLocal<Boolean>(); |
2571 |
13 Aug 14 |
nicklas |
59 |
} |
2571 |
13 Aug 14 |
nicklas |
60 |
|
2571 |
13 Aug 14 |
nicklas |
61 |
/** |
2571 |
13 Aug 14 |
nicklas |
Initialize the cache for the current thread. The cache is tied to |
2571 |
13 Aug 14 |
nicklas |
the given transaction and will live at least as long as until the |
2571 |
13 Aug 14 |
nicklas |
transaction either is committed or rolled back. If there are still |
2571 |
13 Aug 14 |
nicklas |
open files, the cache may live until the last file is closed. |
2571 |
13 Aug 14 |
nicklas |
66 |
*/ |
2571 |
13 Aug 14 |
nicklas |
67 |
public void init(DbControl dc) |
2571 |
13 Aug 14 |
nicklas |
68 |
{ |
2571 |
13 Aug 14 |
nicklas |
69 |
if (cache.get().size() == 0) |
2571 |
13 Aug 14 |
nicklas |
70 |
{ |
2571 |
13 Aug 14 |
nicklas |
71 |
dc.addTransactionalAction(this); |
2571 |
13 Aug 14 |
nicklas |
72 |
initialized.set(true); |
2571 |
13 Aug 14 |
nicklas |
73 |
} |
2571 |
13 Aug 14 |
nicklas |
74 |
} |
2571 |
13 Aug 14 |
nicklas |
75 |
|
2571 |
13 Aug 14 |
nicklas |
76 |
/** |
2571 |
13 Aug 14 |
nicklas |
Get a client for connecting to the remote server with the given connection parameters. |
2571 |
13 Aug 14 |
nicklas |
@return An existing connection or null if no connection has been cached |
2571 |
13 Aug 14 |
nicklas |
79 |
*/ |
2572 |
13 Aug 14 |
nicklas |
80 |
public C getClient(ConnectionInfo cp) |
2571 |
13 Aug 14 |
nicklas |
81 |
{ |
2571 |
13 Aug 14 |
nicklas |
82 |
if (cp == null || initialized.get() == null) |
2571 |
13 Aug 14 |
nicklas |
83 |
{ |
2571 |
13 Aug 14 |
nicklas |
84 |
return null; |
2571 |
13 Aug 14 |
nicklas |
85 |
} |
2571 |
13 Aug 14 |
nicklas |
86 |
return cache.get().get(cp); |
2571 |
13 Aug 14 |
nicklas |
87 |
} |
2571 |
13 Aug 14 |
nicklas |
88 |
|
2571 |
13 Aug 14 |
nicklas |
89 |
/** |
2571 |
13 Aug 14 |
nicklas |
Store the given client connection in the cache. |
2571 |
13 Aug 14 |
nicklas |
@return TRUE if the connection was added to the cache, FALSE if not |
2571 |
13 Aug 14 |
nicklas |
92 |
*/ |
2572 |
13 Aug 14 |
nicklas |
93 |
public boolean setClient(ConnectionInfo cp, C client) |
2571 |
13 Aug 14 |
nicklas |
94 |
{ |
2571 |
13 Aug 14 |
nicklas |
95 |
if (cp == null || initialized.get() == null) return false; |
2571 |
13 Aug 14 |
nicklas |
96 |
cache.get().put(cp, client); |
2571 |
13 Aug 14 |
nicklas |
97 |
return true; |
2571 |
13 Aug 14 |
nicklas |
98 |
} |
2571 |
13 Aug 14 |
nicklas |
99 |
|
2571 |
13 Aug 14 |
nicklas |
100 |
@Override |
2571 |
13 Aug 14 |
nicklas |
101 |
public void onBeforeCommit() |
2571 |
13 Aug 14 |
nicklas |
102 |
{} |
2571 |
13 Aug 14 |
nicklas |
103 |
|
2571 |
13 Aug 14 |
nicklas |
104 |
@Override |
2571 |
13 Aug 14 |
nicklas |
105 |
public void onAfterCommit() |
2571 |
13 Aug 14 |
nicklas |
106 |
{ |
2571 |
13 Aug 14 |
nicklas |
107 |
close(); |
2571 |
13 Aug 14 |
nicklas |
108 |
} |
2571 |
13 Aug 14 |
nicklas |
109 |
|
2571 |
13 Aug 14 |
nicklas |
110 |
@Override |
2571 |
13 Aug 14 |
nicklas |
111 |
public void onRollback() |
2571 |
13 Aug 14 |
nicklas |
112 |
{ |
2571 |
13 Aug 14 |
nicklas |
113 |
close(); |
2571 |
13 Aug 14 |
nicklas |
114 |
} |
2571 |
13 Aug 14 |
nicklas |
115 |
|
2571 |
13 Aug 14 |
nicklas |
116 |
/** |
2571 |
13 Aug 14 |
nicklas |
Close all connections and destroy the cache for the current thread. |
2571 |
13 Aug 14 |
nicklas |
118 |
*/ |
2571 |
13 Aug 14 |
nicklas |
119 |
private void close() |
2571 |
13 Aug 14 |
nicklas |
120 |
{ |
2571 |
13 Aug 14 |
nicklas |
121 |
MultiCloseable.closeAll(cache.get().values()); |
2571 |
13 Aug 14 |
nicklas |
122 |
cache.remove(); |
2571 |
13 Aug 14 |
nicklas |
123 |
initialized.remove(); |
2571 |
13 Aug 14 |
nicklas |
124 |
} |
2571 |
13 Aug 14 |
nicklas |
125 |
|
2571 |
13 Aug 14 |
nicklas |
126 |
static class TheCache<C> |
2572 |
13 Aug 14 |
nicklas |
127 |
extends ThreadLocal<Map<ConnectionInfo, C>> |
2571 |
13 Aug 14 |
nicklas |
128 |
{ |
2572 |
13 Aug 14 |
nicklas |
129 |
private final Comparator<ConnectionInfo> comparator; |
2571 |
13 Aug 14 |
nicklas |
130 |
|
2572 |
13 Aug 14 |
nicklas |
131 |
TheCache(Comparator<ConnectionInfo> comparator) |
2571 |
13 Aug 14 |
nicklas |
132 |
{ |
2571 |
13 Aug 14 |
nicklas |
133 |
this.comparator = comparator; |
2571 |
13 Aug 14 |
nicklas |
134 |
} |
2571 |
13 Aug 14 |
nicklas |
135 |
|
2571 |
13 Aug 14 |
nicklas |
136 |
@Override |
2572 |
13 Aug 14 |
nicklas |
137 |
protected Map<ConnectionInfo, C> initialValue() |
2571 |
13 Aug 14 |
nicklas |
138 |
{ |
2572 |
13 Aug 14 |
nicklas |
139 |
return new TreeMap<ConnectionInfo, C>(this.comparator); |
2571 |
13 Aug 14 |
nicklas |
140 |
} |
2571 |
13 Aug 14 |
nicklas |
141 |
} |
2571 |
13 Aug 14 |
nicklas |
142 |
} |