Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEike Stepper2012-08-13 06:41:44 +0000
committerEike Stepper2012-08-13 06:41:44 +0000
commitd17bf370acd221b30117d815f0f5e7056ec3ad0b (patch)
tree1294d023db49bcb4d53442dbc053dd901c187542
parent2e3366ce7f4d707ff34839dcc693defac9162250 (diff)
downloadcdo-d17bf370acd221b30117d815f0f5e7056ec3ad0b.tar.gz
cdo-d17bf370acd221b30117d815f0f5e7056ec3ad0b.tar.xz
cdo-d17bf370acd221b30117d815f0f5e7056ec3ad0b.zip
[386289] [DB] DBStoreAccessor pooling strategy
https://bugs.eclipse.org/bugs/show_bug.cgi?id=386289
-rw-r--r--features/org.eclipse.emf.cdo.server.db-feature/feature.xml2
-rw-r--r--plugins/org.eclipse.emf.cdo.server.db/META-INF/MANIFEST.MF18
-rw-r--r--plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/IDBStore.java10
-rw-r--r--plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStore.java19
-rw-r--r--plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStoreAccessor.java31
-rw-r--r--plugins/org.eclipse.emf.cdo.server.product/config/cdo-server.xml6
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/StoreAccessorPool.java91
7 files changed, 148 insertions, 29 deletions
diff --git a/features/org.eclipse.emf.cdo.server.db-feature/feature.xml b/features/org.eclipse.emf.cdo.server.db-feature/feature.xml
index 569074d061..bb4bc5ace1 100644
--- a/features/org.eclipse.emf.cdo.server.db-feature/feature.xml
+++ b/features/org.eclipse.emf.cdo.server.db-feature/feature.xml
@@ -12,7 +12,7 @@
<feature
id="org.eclipse.emf.cdo.server.db"
label="%featureName"
- version="4.1.100.qualifier"
+ version="4.2.0.qualifier"
provider-name="%providerName"
image="eclipse_update_120.jpg" license-feature="org.eclipse.emf.cdo.license" license-feature-version="4.1.0.qualifier">
diff --git a/plugins/org.eclipse.emf.cdo.server.db/META-INF/MANIFEST.MF b/plugins/org.eclipse.emf.cdo.server.db/META-INF/MANIFEST.MF
index abc75361f8..b864c538c5 100644
--- a/plugins/org.eclipse.emf.cdo.server.db/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.emf.cdo.server.db/META-INF/MANIFEST.MF
@@ -1,7 +1,7 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: org.eclipse.emf.cdo.server.db;singleton:=true
-Bundle-Version: 4.1.100.qualifier
+Bundle-Version: 4.2.0.qualifier
Bundle-Name: %pluginName
Bundle-Vendor: %providerName
Bundle-Localization: plugin
@@ -12,11 +12,11 @@ Bundle-ClassPath: .
Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.4.0,4.0.0)",
org.eclipse.net4j.db;bundle-version="[4.0.0,5.0.0)";visibility:=reexport,
org.eclipse.emf.cdo.server;bundle-version="[4.0.0,5.0.0)";visibility:=reexport
-Export-Package: org.eclipse.emf.cdo.server.db;version="4.1.100",
- org.eclipse.emf.cdo.server.db.mapping;version="4.1.100",
- org.eclipse.emf.cdo.server.internal.db;version="4.1.100";x-friends:="org.eclipse.emf.cdo.tests,org.eclipse.emf.cdo.tests.db",
- org.eclipse.emf.cdo.server.internal.db.bundle;version="4.1.100";x-internal:=true,
- org.eclipse.emf.cdo.server.internal.db.jdbc;version="4.1.100";x-friends:="org.eclipse.emf.cdo.tests,org.eclipse.emf.cdo.tests.db",
- org.eclipse.emf.cdo.server.internal.db.mapping;version="4.1.100";x-friends:="org.eclipse.emf.cdo.tests,org.eclipse.emf.cdo.tests.db",
- org.eclipse.emf.cdo.server.internal.db.mapping.horizontal;version="4.1.100";x-friends:="org.eclipse.emf.cdo.tests,org.eclipse.emf.cdo.tests.db",
- org.eclipse.emf.cdo.server.internal.db.messages;version="4.1.100";x-internal:=true
+Export-Package: org.eclipse.emf.cdo.server.db;version="4.2.0",
+ org.eclipse.emf.cdo.server.db.mapping;version="4.2.0",
+ org.eclipse.emf.cdo.server.internal.db;version="4.2.0";x-friends:="org.eclipse.emf.cdo.tests,org.eclipse.emf.cdo.tests.db",
+ org.eclipse.emf.cdo.server.internal.db.bundle;version="4.2.0";x-internal:=true,
+ org.eclipse.emf.cdo.server.internal.db.jdbc;version="4.2.0";x-friends:="org.eclipse.emf.cdo.tests,org.eclipse.emf.cdo.tests.db",
+ org.eclipse.emf.cdo.server.internal.db.mapping;version="4.2.0";x-friends:="org.eclipse.emf.cdo.tests,org.eclipse.emf.cdo.tests.db",
+ org.eclipse.emf.cdo.server.internal.db.mapping.horizontal;version="4.2.0";x-friends:="org.eclipse.emf.cdo.tests,org.eclipse.emf.cdo.tests.db",
+ org.eclipse.emf.cdo.server.internal.db.messages;version="4.2.0";x-internal:=true
diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/IDBStore.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/IDBStore.java
index f8636b6299..1220afe6bf 100644
--- a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/IDBStore.java
+++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/IDBStore.java
@@ -74,5 +74,15 @@ public interface IDBStore extends IStore, IDBConnectionProvider, CanHandleClient
public interface Props
{
public static final String CONNECTION_KEEPALIVE_PERIOD = "connectionKeepAlivePeriod"; //$NON-NLS-1$
+
+ /**
+ * @since 4.2
+ */
+ public static final String READER_POOL_CAPACITY = "readerPoolCapacity"; //$NON-NLS-1$
+
+ /**
+ * @since 4.2
+ */
+ public static final String WRITER_POOL_CAPACITY = "writerPoolCapacity"; //$NON-NLS-1$
}
}
diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStore.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStore.java
index 1c90d83224..f0275577c6 100644
--- a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStore.java
+++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStore.java
@@ -517,6 +517,12 @@ public class DBStore extends Store implements IDBStore, CDOAllRevisionsProvider
setObjectIDTypes(idHandler.getObjectIDTypes());
connectionKeepAliveTimer = new Timer("Connection-Keep-Alive-" + this); //$NON-NLS-1$
+ if (properties != null)
+ {
+ configureAccessorPool(readerPool, IDBStore.Props.READER_POOL_CAPACITY);
+ configureAccessorPool(writerPool, IDBStore.Props.WRITER_POOL_CAPACITY);
+ }
+
Set<IDBTable> createdTables = null;
Connection connection = getConnection();
@@ -725,4 +731,17 @@ public class DBStore extends Store implements IDBStore, CDOAllRevisionsProvider
String name = getRepository().getName();
return new DBSchema(name);
}
+
+ protected void configureAccessorPool(StoreAccessorPool pool, String property)
+ {
+ if (pool != null)
+ {
+ String value = properties.get(property);
+ if (value != null)
+ {
+ int capacity = Integer.parseInt(value);
+ pool.setCapacity(capacity);
+ }
+ }
+ }
}
diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStoreAccessor.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStoreAccessor.java
index 4132088e45..c879e32079 100644
--- a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStoreAccessor.java
+++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStoreAccessor.java
@@ -755,7 +755,7 @@ public class DBStoreAccessor extends StoreAccessor implements IDBStoreAccessor,
{
DBStore store = getStore();
connection = store.getConnection();
- connectionKeepAliveTask = new ConnectionKeepAliveTask();
+ connectionKeepAliveTask = new ConnectionKeepAliveTask(this);
long keepAlivePeriod = ConnectionKeepAliveTask.EXECUTION_PERIOD;
Map<String, String> storeProps = store.getProperties();
@@ -780,7 +780,10 @@ public class DBStoreAccessor extends StoreAccessor implements IDBStoreAccessor,
protected void doDeactivate() throws Exception
{
LifecycleUtil.deactivate(statementCache);
+
connectionKeepAliveTask.cancel();
+ connectionKeepAliveTask = null;
+
DBUtil.close(connection);
connection = null;
}
@@ -1363,13 +1366,25 @@ public class DBStoreAccessor extends StoreAccessor implements IDBStoreAccessor,
/**
* @author Stefan Winkler
*/
- private class ConnectionKeepAliveTask extends TimerTask
+ private static final class ConnectionKeepAliveTask extends TimerTask
{
public static final long EXECUTION_PERIOD = 1000 * 60 * 60 * 4; // 4 hours
+ private DBStoreAccessor accessor;
+
+ public ConnectionKeepAliveTask(DBStoreAccessor accessor)
+ {
+ this.accessor = accessor;
+ }
+
@Override
public void run()
{
+ if (accessor == null)
+ {
+ return;
+ }
+
Statement stmt = null;
try
@@ -1379,6 +1394,7 @@ public class DBStoreAccessor extends StoreAccessor implements IDBStoreAccessor,
TRACER.trace("DB connection keep-alive task activated"); //$NON-NLS-1$
}
+ Connection connection = accessor.getConnection();
stmt = connection.createStatement();
stmt.executeQuery("SELECT 1 FROM " + CDODBSchema.PROPERTIES); //$NON-NLS-1$
}
@@ -1389,8 +1405,8 @@ public class DBStoreAccessor extends StoreAccessor implements IDBStoreAccessor,
// Assume the connection has failed.
try
{
- LifecycleUtil.deactivate(DBStoreAccessor.this);
- LifecycleUtil.activate(DBStoreAccessor.this);
+ LifecycleUtil.deactivate(accessor);
+ LifecycleUtil.activate(accessor);
}
catch (Exception ex2)
{
@@ -1406,5 +1422,12 @@ public class DBStoreAccessor extends StoreAccessor implements IDBStoreAccessor,
DBUtil.close(stmt);
}
}
+
+ @Override
+ public boolean cancel()
+ {
+ accessor = null;
+ return super.cancel();
+ }
}
}
diff --git a/plugins/org.eclipse.emf.cdo.server.product/config/cdo-server.xml b/plugins/org.eclipse.emf.cdo.server.product/config/cdo-server.xml
index 72c7f7d230..4feec27434 100644
--- a/plugins/org.eclipse.emf.cdo.server.product/config/cdo-server.xml
+++ b/plugins/org.eclipse.emf.cdo.server.product/config/cdo-server.xml
@@ -44,6 +44,12 @@
<!-- Period at which to execute an SQL statement to keep DB connection alive, in minutes -->
<property name="connectionKeepAlivePeriod" value="60"/>
+ <!-- Maximum number of store accessors (JDBC connections) to keep in the reader pool. The default value is 15. -->
+ <property name="readerPoolCapacity" value="20"/>
+
+ <!-- Maximum number of store accessors (JDBC connections) to keep in the writer pool. The default value is 15. -->
+ <property name="writerPoolCapacity" value="20"/>
+
<mappingStrategy type="horizontal"> <!-- callout -->
<property name="qualifiedNames" value="true"/>
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/StoreAccessorPool.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/StoreAccessorPool.java
index 01edd1ebf1..e71e872f96 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/StoreAccessorPool.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/StoreAccessorPool.java
@@ -18,7 +18,7 @@ import org.eclipse.emf.cdo.server.IView;
import org.eclipse.net4j.util.lifecycle.LifecycleUtil;
import org.eclipse.net4j.util.om.log.OMLogger;
-import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.LinkedList;
/**
* @author Eike Stepper
@@ -27,6 +27,11 @@ import java.util.concurrent.ConcurrentLinkedQueue;
public class StoreAccessorPool
{
/**
+ * @since 4.2
+ */
+ public static final int DEFAULT_CAPACITY = 15;
+
+ /**
* The {@link IStore store} instance that manages this pool.
*/
private IStore store;
@@ -37,7 +42,9 @@ public class StoreAccessorPool
*/
private Object context;
- private ConcurrentLinkedQueue<StoreAccessorBase> accessors = new ConcurrentLinkedQueue<StoreAccessorBase>();
+ private int capacity = DEFAULT_CAPACITY;
+
+ private LinkedList<StoreAccessorBase> accessors = new LinkedList<StoreAccessorBase>();
public StoreAccessorPool(IStore store, Object context)
{
@@ -56,8 +63,26 @@ public class StoreAccessorPool
}
/**
- * Passivates the given {@link StoreAccessor store accessor} and adds it to this pool.
- *
+ * @since 4.2
+ */
+ public int getCapacity()
+ {
+ return capacity;
+ }
+
+ /**
+ * @since 4.2
+ */
+ public void setCapacity(int capacity)
+ {
+ this.capacity = capacity;
+ retainStoreAccessors(capacity);
+ }
+
+ /**
+ * Passivates the given {@link StoreAccessor store accessor} and adds it to this pool if the pool size is smaller than the {@link #getCapacity() capacity},
+ * or disposes of the store accessor otherwise.
+ *
* @since 4.0
*/
public void addStoreAccessor(StoreAccessorBase storeAccessor)
@@ -65,7 +90,24 @@ public class StoreAccessorPool
try
{
storeAccessor.doPassivate();
- accessors.add(storeAccessor);
+
+ boolean full = false;
+ synchronized (accessors)
+ {
+ if (accessors.size() >= capacity)
+ {
+ full = true;
+ }
+ else
+ {
+ accessors.addFirst(storeAccessor);
+ }
+ }
+
+ if (full)
+ {
+ disposeStoreAccessor(storeAccessor);
+ }
}
catch (Exception ex)
{
@@ -76,12 +118,17 @@ public class StoreAccessorPool
/**
* Returns a {@link StoreAccessor store accessor} from this pool if one is available, or <code>null</code> otherwise.
* If a store accessor is available it is removed from this pool and its unpassivate method is called.
- *
+ *
* @since 4.0
*/
public StoreAccessorBase removeStoreAccessor(Object context)
{
- StoreAccessorBase accessor = accessors.poll();
+ StoreAccessorBase accessor;
+ synchronized (accessors)
+ {
+ accessor = accessors.poll();
+ }
+
if (accessor != null)
{
try
@@ -104,18 +151,32 @@ public class StoreAccessorPool
*/
public void dispose()
{
- for (;;)
+ retainStoreAccessors(0);
+
+ context = null;
+ store = null;
+ }
+
+ /**
+ * @since 4.2
+ */
+ protected void retainStoreAccessors(int targetSize)
+ {
+ synchronized (accessors)
{
- StoreAccessorBase accessor = accessors.poll();
- if (accessor == null)
+ while (accessors.size() > targetSize)
{
- break;
+ StoreAccessorBase accessor = accessors.removeLast();
+ disposeStoreAccessor(accessor);
}
-
- LifecycleUtil.deactivate(accessor, OMLogger.Level.WARN);
}
+ }
- context = null;
- store = null;
+ /**
+ * @since 4.2
+ */
+ protected void disposeStoreAccessor(StoreAccessorBase accessor)
+ {
+ LifecycleUtil.deactivate(accessor, OMLogger.Level.WARN);
}
}

Back to the top