You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by aa...@apache.org on 2015/05/03 12:16:13 UTC
cayenne git commit: CAY-2009 Non-blocking connection pool
Repository: cayenne
Updated Branches:
refs/heads/master c2ce2dfa6 -> e1a3d9788
CAY-2009 Non-blocking connection pool
* unit tests
* upgrade notes
Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/e1a3d978
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/e1a3d978
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/e1a3d978
Branch: refs/heads/master
Commit: e1a3d978891dad12a730dd7bc5cb0c284378abce
Parents: c2ce2df
Author: aadamchik <aa...@apache.org>
Authored: Sun May 3 05:14:19 2015 -0400
Committer: aadamchik <aa...@apache.org>
Committed: Sun May 3 06:13:21 2015 -0400
----------------------------------------------------------------------
.../datasource/ManagedPoolingDataSource.java | 17 +++-
.../datasource/PoolingDataSourceManager.java | 25 +++--
.../ManagedPoolingDataSourceTest.java | 97 ++++++++++++++++++++
.../datasource/PoolDataSourceManagerTest.java | 80 ++++++++++++++++
docs/doc/src/main/resources/UPGRADE.txt | 10 ++
5 files changed, 219 insertions(+), 10 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cayenne/blob/e1a3d978/cayenne-server/src/main/java/org/apache/cayenne/datasource/ManagedPoolingDataSource.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/datasource/ManagedPoolingDataSource.java b/cayenne-server/src/main/java/org/apache/cayenne/datasource/ManagedPoolingDataSource.java
index 65083b1..182ad75 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/datasource/ManagedPoolingDataSource.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/datasource/ManagedPoolingDataSource.java
@@ -42,20 +42,33 @@ public class ManagedPoolingDataSource implements DataSource, ScopeEventListener
public ManagedPoolingDataSource(PoolingDataSource dataSource) {
this.dataSource = dataSource;
- this.dataSourceManager = new PoolingDataSourceManager(dataSource);
+
+ // wake every 2 minutes...
+ this.dataSourceManager = new PoolingDataSourceManager(dataSource, 120000);
dataSourceManager.start();
}
+ PoolingDataSourceManager getDataSourceManager() {
+ return dataSourceManager;
+ }
+
+ /**
+ * Calls {@link #shutdown()} to drain the underlying pool, close open
+ * connections and block the DataSource from creating any new connections.
+ */
@Override
public void beforeScopeEnd() {
+ shutdown();
+ }
+ public void shutdown() {
// swap the underlying DataSource to prevent further interaction with
// the callers
this.dataSource = new StoppedDataSource(dataSource);
// shut down the thread..
- dataSourceManager.shutdown();
+ this.dataSourceManager.shutdown();
}
@Override
http://git-wip-us.apache.org/repos/asf/cayenne/blob/e1a3d978/cayenne-server/src/main/java/org/apache/cayenne/datasource/PoolingDataSourceManager.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/datasource/PoolingDataSourceManager.java b/cayenne-server/src/main/java/org/apache/cayenne/datasource/PoolingDataSourceManager.java
index 6dacdd6..3d2f93a 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/datasource/PoolingDataSourceManager.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/datasource/PoolingDataSourceManager.java
@@ -19,9 +19,9 @@
package org.apache.cayenne.datasource;
/**
- * Manages the state of a {@link PoolingDataSource} instance, performing
- * periodic expansion/contraction of pooled connections, and orchestrating
- * shutdown.
+ * A thread that manages the state of a {@link PoolingDataSource} instance,
+ * performing periodic expansion/contraction of pooled connections, and
+ * orchestrating shutdown.
*
* @since 4.0
*/
@@ -29,28 +29,37 @@ class PoolingDataSourceManager extends Thread {
private volatile boolean shouldStop;
private PoolingDataSource dataSource;
+ private long managerWakeTime;
- PoolingDataSourceManager(PoolingDataSource dataSource) {
- setName("PoolManagerCleanup-" + dataSource.hashCode());
+ PoolingDataSourceManager(PoolingDataSource dataSource, long managerWakeTime) {
+ setName("PoolingDataSourceManager-" + dataSource.hashCode());
setDaemon(true);
this.dataSource = dataSource;
this.shouldStop = false;
+ this.managerWakeTime = managerWakeTime;
}
- public void shutdown() {
+ void shutdown() {
shouldStop = true;
dataSource.shutdown();
interrupt();
}
+ PoolingDataSource getDataSource() {
+ return dataSource;
+ }
+
+ boolean isStopped() {
+ return shouldStop;
+ }
+
@Override
public void run() {
while (true) {
try {
- // don't do it too often
- Thread.sleep(600000);
+ Thread.sleep(managerWakeTime);
} catch (InterruptedException iex) {
// ignore...
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/e1a3d978/cayenne-server/src/test/java/org/apache/cayenne/datasource/ManagedPoolingDataSourceTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/datasource/ManagedPoolingDataSourceTest.java b/cayenne-server/src/test/java/org/apache/cayenne/datasource/ManagedPoolingDataSourceTest.java
new file mode 100644
index 0000000..c728956
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/datasource/ManagedPoolingDataSourceTest.java
@@ -0,0 +1,97 @@
+/*****************************************************************
+ * 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.
+ ****************************************************************/
+package org.apache.cayenne.datasource;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class ManagedPoolingDataSourceTest {
+
+ private Connection[] mockConnections;
+ private PoolingDataSource mockPoolingDataSource;
+ private ManagedPoolingDataSource dataSource;
+
+ @Before
+ public void before() throws SQLException {
+
+ this.mockConnections = new Connection[4];
+ for (int i = 0; i < mockConnections.length; i++) {
+ mockConnections[i] = mock(Connection.class);
+ }
+
+ this.mockPoolingDataSource = mock(PoolingDataSource.class);
+ when(mockPoolingDataSource.getConnection()).thenReturn(mockConnections[0], mockConnections[1],
+ mockConnections[2], mockConnections[3]);
+
+ this.dataSource = new ManagedPoolingDataSource(mockPoolingDataSource);
+ }
+
+ @After
+ public void after() {
+ dataSource.beforeScopeEnd();
+ }
+
+ @Test
+ public void testGetConnection() throws SQLException {
+ assertSame(mockConnections[0], dataSource.getConnection());
+ assertSame(mockConnections[1], dataSource.getConnection());
+ assertSame(mockConnections[2], dataSource.getConnection());
+ assertSame(mockConnections[3], dataSource.getConnection());
+ }
+
+ @Test
+ public void testShutdown() throws SQLException, InterruptedException {
+ assertNotNull(dataSource.getConnection());
+
+ // state before shutdown
+ verify(mockPoolingDataSource, times(0)).shutdown();
+ assertFalse(dataSource.getDataSourceManager().isStopped());
+ assertTrue(dataSource.getDataSourceManager().isAlive());
+
+ dataSource.shutdown();
+
+ // state after shutdown
+ verify(mockPoolingDataSource, times(1)).shutdown();
+ assertTrue(dataSource.getDataSourceManager().isStopped());
+
+ // give the thread some time to process interrupt and die
+ Thread.sleep(200);
+ assertFalse(dataSource.getDataSourceManager().isAlive());
+
+ try {
+ dataSource.getConnection();
+ } catch (SQLException e) {
+ // expected , DataSource should not give out connections any longer
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/e1a3d978/cayenne-server/src/test/java/org/apache/cayenne/datasource/PoolDataSourceManagerTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/datasource/PoolDataSourceManagerTest.java b/cayenne-server/src/test/java/org/apache/cayenne/datasource/PoolDataSourceManagerTest.java
new file mode 100644
index 0000000..58b8983
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/datasource/PoolDataSourceManagerTest.java
@@ -0,0 +1,80 @@
+/*****************************************************************
+ * 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.
+ ****************************************************************/
+package org.apache.cayenne.datasource;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+
+import java.sql.SQLException;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+public class PoolDataSourceManagerTest {
+
+ private PoolingDataSource mockPoolingDataSource;
+ private PoolingDataSourceManager dataSourceManager;
+
+ @Before
+ public void before() throws SQLException {
+ this.mockPoolingDataSource = mock(PoolingDataSource.class);
+ this.dataSourceManager = new PoolingDataSourceManager(mockPoolingDataSource, 100);
+ }
+
+ @After
+ public void after() {
+ dataSourceManager.shutdown();
+ }
+
+ @Test
+ public void testRun_Manage() throws InterruptedException {
+
+ final int[] counter = new int[1];
+
+ doAnswer(new Answer<Object>() {
+ @Override
+ public Object answer(InvocationOnMock invocation) throws Throwable {
+ counter[0]++;
+ return null;
+ }
+ }).when(mockPoolingDataSource).managePool();
+
+ dataSourceManager.start();
+
+ // we can't predict the number of 'managePool' invocations, but it
+ // should be incrementing as the time goes
+
+ int c0 = counter[0];
+ assertEquals(0, c0);
+ Thread.sleep(300);
+
+ int c1 = counter[0];
+ assertTrue(c1 > c0);
+
+ Thread.sleep(300);
+
+ int c2 = counter[0];
+ assertTrue(c2 > c1);
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/e1a3d978/docs/doc/src/main/resources/UPGRADE.txt
----------------------------------------------------------------------
diff --git a/docs/doc/src/main/resources/UPGRADE.txt b/docs/doc/src/main/resources/UPGRADE.txt
index cc5cda1..c29320d 100644
--- a/docs/doc/src/main/resources/UPGRADE.txt
+++ b/docs/doc/src/main/resources/UPGRADE.txt
@@ -12,6 +12,16 @@ UPGRADING TO 4.0.M3
Note if you have references to @Deprecated String properties and you run cgen without "createPropertyNames" flag,
there will be errors. Reference Jira: CAY-1991
+* Per CAY-2010 DataSource building methods were refactored out of ServerRuntimeBuilder and into a standalone
+ org.apache.cayenne.datasource.DataSourceBuilder. So creating a DataSource in runtime may look like this:
+
+ DataSource ds = DataSourceBuilder.url(dbUrl).driver(dbDriver).build();
+ ServerRuntime runtime = ServerRuntimeBuilder.builder().dataSource(ds).build();
+
+* Per CAY-2008, CAY-2009 we got rid of org.apache.cayenne.conn.PoolManager and associated classes that made up a
+ pooling DataSource. A replacement is non-blocking DataSource under org.apache.cayenne.datasource (PoolingDataSource, ManagedPoolingDataSource),
+ best assembled using org.apache.cayenne.datasource.DataSourceBuilder.
+
UPGRADING TO 4.0.M2