Skip to content

Commit ddec246

Browse files
committed
#10 - ENH: Add DataSourcePool online() and offline()
1 parent a74329e commit ddec246

5 files changed

Lines changed: 107 additions & 20 deletions

File tree

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
<dependency>
2323
<groupId>io.ebean</groupId>
2424
<artifactId>ebean-datasource-api</artifactId>
25-
<version>4.3</version>
25+
<version>4.4-SNAPSHOT</version>
2626
</dependency>
2727

2828
<dependency>

src/main/java/io/ebean/datasource/pool/ConnectionPool.java

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -140,10 +140,9 @@ public class ConnectionPool implements DataSourcePool {
140140
private long lastTrimTime;
141141

142142
/**
143-
* Assume that the DataSource is up. heartBeat checking will discover when
144-
* it goes down, and comes back up again.
143+
* HeartBeat checking will discover when it goes down, and comes back up again.
145144
*/
146-
private boolean dataSourceUp = true;
145+
private boolean dataSourceUp;
147146

148147
/**
149148
* Stores the dataSourceDown-reason (if there is any)
@@ -182,7 +181,7 @@ public class ConnectionPool implements DataSourcePool {
182181

183182
private final PooledConnectionQueue queue;
184183

185-
private final Timer heartBeatTimer;
184+
private Timer heartBeatTimer;
186185

187186
/**
188187
* Used to find and close() leaked connections. Leaked connections are
@@ -241,13 +240,13 @@ public ConnectionPool(String name, DataSourceConfig params) {
241240
this.connectionProps.setProperty(entry.getKey(), entry.getValue());
242241
}
243242
}
244-
243+
checkDriver();
245244
try {
246-
initialise();
247-
int freqMillis = heartbeatFreqSecs * 1000;
248-
heartBeatTimer = new Timer(name + ".heartBeat", true);
249-
if (freqMillis > 0) {
250-
heartBeatTimer.scheduleAtFixedRate(new HeartBeatRunnable(), freqMillis, freqMillis);
245+
if (!params.isOffline()) {
246+
if (config.useInitDatabase()) {
247+
initialiseDatabase();
248+
}
249+
initialise();
251250
}
252251
} catch (SQLException e) {
253252
throw new DataSourceInitialiseException("Error initialising DataSource: " + e.getMessage(), e);
@@ -261,13 +260,12 @@ public void run() {
261260
}
262261
}
263262

264-
265263
@Override
266264
public java.util.logging.Logger getParentLogger() throws SQLFeatureNotSupportedException {
267265
throw new SQLFeatureNotSupportedException("We do not support java.util.logging");
268266
}
269267

270-
private void initialise() throws SQLException {
268+
private void checkDriver() {
271269

272270
// Ensure database driver is loaded
273271
try {
@@ -280,25 +278,29 @@ private void initialise() throws SQLException {
280278
} catch (Throwable e) {
281279
throw new IllegalStateException("Problem loading Database Driver [" + this.databaseDriver + "]: " + e.getMessage(), e);
282280
}
281+
}
283282

284-
String transIsolation = TransactionIsolation.getDescription(transactionIsolation);
283+
@Override
284+
public void online() throws SQLException {
285+
initialise();
286+
}
287+
288+
private void initialise() throws SQLException {
285289

286290
//noinspection StringBufferReplaceableByString
287291
StringBuilder sb = new StringBuilder(70);
288292
sb.append("DataSourcePool [").append(name);
289293
sb.append("] autoCommit[").append(autoCommit);
290-
sb.append("] transIsolation[").append(transIsolation);
294+
sb.append("] transIsolation[").append(TransactionIsolation.getDescription(transactionIsolation));
291295
sb.append("] min[").append(minConnections);
292296
sb.append("] max[").append(maxConnections).append("]");
293297

294298
logger.info(sb.toString());
295299

296-
if (config.useInitDatabase()) {
297-
initialiseDatabase();
298-
}
299-
300300
try {
301+
dataSourceUp = true;
301302
queue.ensureMinimumConnections();
303+
startHeartBeat();
302304
} catch (SQLException e) {
303305
if (failOnStart) {
304306
throw e;
@@ -307,6 +309,14 @@ private void initialise() throws SQLException {
307309
}
308310
}
309311

312+
private void startHeartBeat() {
313+
int freqMillis = heartbeatFreqSecs * 1000;
314+
if (freqMillis > 0) {
315+
heartBeatTimer = new Timer(name + ".heartBeat", true);
316+
heartBeatTimer.scheduleAtFixedRate(new HeartBeatRunnable(), freqMillis, freqMillis);
317+
}
318+
}
319+
310320
/**
311321
* Initialise the database using the owner credentials if we can't connect using the normal credentials.
312322
* <p>
@@ -857,6 +867,13 @@ public void shutdown(boolean deregisterDriver) {
857867
}
858868
}
859869

870+
@Override
871+
public void offline() {
872+
heartBeatTimer.cancel();
873+
queue.shutdown();
874+
dataSourceUp = false;
875+
}
876+
860877
/**
861878
* Return the default autoCommit setting Connections in this pool will use.
862879
*

src/main/java/io/ebean/datasource/pool/PooledConnectionQueue.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,7 @@ public void shutdown() {
387387
}
388388
} finally {
389389
lock.unlock();
390+
doingShutdown = false;
390391
}
391392
}
392393

src/test/java/io/ebean/datasource/PostgresInitTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public void test() throws SQLException {
3636
ds.setOwnerUsername("db_owner");
3737
ds.setOwnerPassword("test");
3838

39-
DataSourcePool pool = DataSourceFactory.get().createPool("app", ds);
39+
DataSourcePool pool = DataSourceFactory.create("app", ds);
4040

4141
try (Connection connection = pool.getConnection()) {
4242
try (PreparedStatement statement = connection.prepareStatement("create table my_table (acol integer);")) {
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package io.ebean.datasource.pool;
2+
3+
import io.ebean.datasource.DataSourceConfig;
4+
import org.slf4j.Logger;
5+
import org.slf4j.LoggerFactory;
6+
import org.testng.annotations.Test;
7+
8+
import java.sql.SQLException;
9+
10+
import static org.testng.Assert.assertEquals;
11+
12+
public class ConnectionPoolOfflineTest {
13+
14+
private static final Logger log = LoggerFactory.getLogger(ConnectionPoolOfflineTest.class);
15+
16+
private DataSourceConfig config() {
17+
18+
DataSourceConfig config = new DataSourceConfig();
19+
config.setDriver("org.h2.Driver");
20+
config.setUrl("jdbc:h2:mem:tests");
21+
config.setUsername("sa");
22+
config.setPassword("");
23+
config.setMinConnections(2);
24+
config.setMaxConnections(4);
25+
config.setOffline(true);
26+
config.setHeartbeatFreqSecs(1);
27+
28+
return config;
29+
}
30+
31+
@Test
32+
public void testOffline() throws InterruptedException, SQLException {
33+
34+
DataSourceConfig config = config();
35+
36+
ConnectionPool pool = new ConnectionPool("test", config);
37+
log.info("pool created ");
38+
Thread.sleep(3000);
39+
40+
assertEquals(0, pool.getStatus(false).getFree());
41+
assertEquals(0, pool.getStatus(false).getBusy());
42+
43+
pool.online();
44+
log.info("pool online");
45+
assertEquals(2, pool.getStatus(false).getFree());
46+
assertEquals(0, pool.getStatus(false).getBusy());
47+
48+
Thread.sleep(3000);
49+
50+
pool.offline();
51+
log.info("pool offline");
52+
assertEquals(0, pool.getStatus(false).getFree());
53+
assertEquals(0, pool.getStatus(false).getBusy());
54+
55+
Thread.sleep(3000);
56+
57+
pool.online();
58+
log.info("pool online");
59+
assertEquals(2, pool.getStatus(false).getFree());
60+
assertEquals(0, pool.getStatus(false).getBusy());
61+
Thread.sleep(3000);
62+
63+
pool.shutdown(false);
64+
65+
assertEquals(0, pool.getStatus(false).getFree());
66+
assertEquals(0, pool.getStatus(false).getBusy());
67+
}
68+
69+
}

0 commit comments

Comments
 (0)