Author: kristwaa
Date: Thu Jun 16 10:22:46 2011
New Revision: 1136363
URL: http://svn.apache.org/viewvc?rev=1136363&view=rev
Log:
DERBY-4137: OOM issue using XA with timeouts
Reduce the memory footprint when executing successful XA transactions that
have a timeout set by nulling out the reference to the XATransactionState
object in the timer task. The timer task will stay around in the timer queue
until reaching the scheduled time - even if the task is canceled.
Added a regression test (run as part of 'ant junit-lowmem').
Patch file: derby-4137-2a-reduce_memory_footprint.diff
Added:
db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/memory/XAMemTest.java
(with props)
Modified:
db/derby/code/trunk/java/engine/org/apache/derby/jdbc/XATransactionState.java
db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/memory/_Suite.java
Modified: db/derby/code/trunk/java/engine/org/apache/derby/jdbc/XATransactionState.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/jdbc/XATransactionState.java?rev=1136363&r1=1136362&r2=1136363&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/jdbc/XATransactionState.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/jdbc/XATransactionState.java Thu Jun
16 10:22:46 2011
@@ -90,17 +90,29 @@ final class XATransactionState extends C
/** The implementation of TimerTask to cancel a global transaction. */
- private class CancelXATransactionTask extends TimerTask {
+ private static class CancelXATransactionTask extends TimerTask {
- /** Creates the cancelation object to be passed to a timer. */
- public CancelXATransactionTask() {
- XATransactionState.this.timeoutTask = this;
+ private XATransactionState xaState;
+
+ /**
+ * Creates the cancellation task to be passed to a timer.
+ *
+ * @param xaState the XA state object for the transaction to cancel
+ */
+ public CancelXATransactionTask(XATransactionState xaState) {
+ this.xaState = xaState;
+ }
+
+ public boolean cancel() {
+ // nullify reference to reduce memory footprint of canceled tasks
+ xaState = null;
+ return super.cancel();
}
/** Runs the cancel task of the global transaction */
public void run() {
try {
- XATransactionState.this.cancel(MessageId.CONN_XA_TRANSACTION_TIMED_OUT);
+ xaState.cancel(MessageId.CONN_XA_TRANSACTION_TIMED_OUT);
} catch (Throwable th) {
Monitor.logThrowable(th);
}
@@ -313,10 +325,10 @@ final class XATransactionState extends C
// schedule a time out task if the timeout was specified
if (timeoutMillis > 0) {
// take care of the transaction timeout
- TimerTask cancelTask = new CancelXATransactionTask();
TimerFactory timerFactory = Monitor.getMonitor().getTimerFactory();
Timer timer = timerFactory.getCancellationTimer();
- timer.schedule(cancelTask, timeoutMillis);
+ timeoutTask = new CancelXATransactionTask(this);
+ timer.schedule(timeoutTask, timeoutMillis);
} else {
timeoutTask = null;
}
@@ -354,6 +366,7 @@ final class XATransactionState extends C
synchronized void xa_finalize() {
if (timeoutTask != null) {
timeoutTask.cancel();
+ timeoutTask = null;
}
performTimeoutRollback = false;
}
Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/memory/XAMemTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/memory/XAMemTest.java?rev=1136363&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/memory/XAMemTest.java
(added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/memory/XAMemTest.java
Thu Jun 16 10:22:46 2011
@@ -0,0 +1,91 @@
+/*
+
+ Derby - Class org.apache.derbyTesting.functionTests.tests.memory.XAMemTest
+
+ 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.derbyTesting.functionTests.tests.memory;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import javax.sql.XAConnection;
+import javax.sql.XADataSource;
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+
+import junit.framework.Test;
+
+import org.apache.derbyTesting.junit.BaseJDBCTestCase;
+import org.apache.derbyTesting.junit.J2EEDataSource;
+import org.apache.derbyTesting.junit.TestConfiguration;
+import org.apache.derbyTesting.junit.XATestUtil;
+
+/**
+ * Tests verifying that the memory usage for certain XA operations / access
+ * patterns isn't unreasonably high.
+ */
+public class XAMemTest
+ extends BaseJDBCTestCase {
+
+ public XAMemTest(String name) {
+ super(name);
+ }
+
+ public void setUp()
+ throws SQLException {
+ // Create the default wombat database if it doesn't exist.
+ // Required to run some of the test cases individually.
+ getConnection();
+ }
+
+ /**
+ * DERBY-4137: Execute a bunch of successful XA transactions with a
+ * transaction timeout specified.
+ *
+ * @throws Exception if something goes wrong
+ */
+ public void testDerby4137_TransactionTimeoutSpecifiedNotExceeded()
+ throws Exception {
+ XADataSource xads = J2EEDataSource.getXADataSource();
+ XAConnection xac = xads.getXAConnection();
+ XAResource xar = xac.getXAResource();
+ Xid xid = XATestUtil.getXid(8, 9, 10);
+ Connection con = xac.getConnection();
+ Statement stmt = con.createStatement();
+
+ // Set a long timeout such that the queue won't be able to clean
+ // itself as part of normal processing.
+ xar.setTransactionTimeout(100000);
+
+ // 60'000 iterations was selected to balance duration versus chance of
+ // detecting a "memory leak". The test failed before DERBY-4137 was
+ // addressed.
+ for (int i=0; i < 60000; i++) {
+ xar.start(xid, XAResource.TMNOFLAGS);
+ stmt.executeQuery("values 1");
+ xar.end(xid, XAResource.TMSUCCESS);
+ xar.commit(xid, true);
+ }
+ xac.close();
+ }
+
+ public static Test suite() {
+ return TestConfiguration.defaultSuite(XAMemTest.class);
+ }
+}
Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/memory/XAMemTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/memory/_Suite.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/memory/_Suite.java?rev=1136363&r1=1136362&r2=1136363&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/memory/_Suite.java
(original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/memory/_Suite.java
Thu Jun 16 10:22:46 2011
@@ -41,6 +41,7 @@ public class _Suite extends BaseJDBCTest
suite.addTest(MultiByteClobTest.suite());
suite.addTest(RolesDependencyTest.suite());
suite.addTest(Derby3009Test.suite());
+ suite.addTest(XAMemTest.suite());
return suite;
}
}
|