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