Skip to content

Commit

Permalink
GG-17339 Backport [IGNITE-11524] Memory leak caused by executing a jd…
Browse files Browse the repository at this point in the history
…bc prepared statement
  • Loading branch information
tledkov committed May 6, 2019
1 parent c4783d3 commit 55f6ed0
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
/*
* Copyright 2019 GridGain Systems, Inc. and Contributors.
*
*
* Licensed under the GridGain Community Edition License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
*
*
* 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.
Expand Down Expand Up @@ -70,6 +70,7 @@
import org.apache.ignite.jdbc.thin.JdbcThinMetadataSelfTest;
import org.apache.ignite.jdbc.thin.JdbcThinMissingLongArrayResultsTest;
import org.apache.ignite.jdbc.thin.JdbcThinNoDefaultSchemaTest;
import org.apache.ignite.jdbc.thin.JdbcThinPreparedStatementLeakTest;
import org.apache.ignite.jdbc.thin.JdbcThinPreparedStatementSelfTest;
import org.apache.ignite.jdbc.thin.JdbcThinResultSetSelfTest;
import org.apache.ignite.jdbc.thin.JdbcThinSchemaCaseTest;
Expand Down Expand Up @@ -223,6 +224,8 @@ public static TestSuite suite() {
suite.addTest(new JUnit4TestAdapter(JdbcThinAuthenticateConnectionSelfTest.class));
suite.addTest(new JUnit4TestAdapter(JdbcThinTransactionsLeaksMvccTest.class));

suite.addTest(new JUnit4TestAdapter(JdbcThinPreparedStatementLeakTest.class));

return suite;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* Copyright 2019 GridGain Systems, Inc. and Contributors.
*
* Licensed under the GridGain Community Edition License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
*
* 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.ignite.jdbc.thin;

import org.apache.ignite.IgniteJdbcThinDriver;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.junit.Test;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Properties;
import java.util.Set;

/**
* Prepared statement leaks test.
*/
@SuppressWarnings("ThrowableNotThrown")
public class JdbcThinPreparedStatementLeakTest extends JdbcThinAbstractSelfTest {
/** URL. */
private static final String URL = "jdbc:ignite:thin://127.0.0.1/";


/** {@inheritDoc} */
@Override protected void beforeTest() throws Exception {
super.beforeTest();

startGrid();
}

/** {@inheritDoc} */
@Override protected void afterTest() throws Exception {
stopAllGrids();

super.afterTest();
}

/**
* @throws Exception If failed.
*/
@SuppressWarnings("StatementWithEmptyBody")
@Test
public void test() throws Exception {
try (Connection conn = new IgniteJdbcThinDriver().connect(URL, new Properties())) {
for (int i = 0; i < 50000; ++i) {
try (PreparedStatement st = conn.prepareStatement("select 1")) {
ResultSet rs = st.executeQuery();

while (rs.next()) {
// No-op.
}

rs.close();
}
}

Set stmts = U.field(conn, "stmts");

assertEquals(0, stmts.size());
}
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
/*
* Copyright 2019 GridGain Systems, Inc. and Contributors.
*
*
* Licensed under the GridGain Community Edition License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
*
*
* 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.
Expand Down Expand Up @@ -34,9 +34,12 @@
import java.sql.Statement;
import java.sql.Struct;
import java.util.ArrayList;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.Semaphore;
import java.util.logging.Level;
Expand Down Expand Up @@ -114,7 +117,7 @@ public class JdbcThinConnection implements Connection {
private boolean connected;

/** Tracked statements to close on disconnect. */
private final ArrayList<JdbcThinStatement> stmts = new ArrayList<>();
private final Set<JdbcThinStatement> stmts = Collections.newSetFromMap(new IdentityHashMap<>());

/**
* Creates new connection.
Expand Down Expand Up @@ -380,6 +383,12 @@ private void doCommit() throws SQLException {
streamState = null;
}

synchronized (stmtsMux) {
stmts.clear();
}

SQLException err = null;

closed = true;

cliIo.close();
Expand Down Expand Up @@ -834,6 +843,15 @@ private static String normalizeSchema(String schemaName) {
return res;
}

/**
* @param stmt Statement to close.
*/
void closeStatement(JdbcThinStatement stmt) {
synchronized (stmtsMux) {
stmts.remove(stmt);
}
}

/**
* Streamer state and
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,6 @@
import org.apache.ignite.internal.processors.odbc.jdbc.JdbcResult;
import org.apache.ignite.internal.processors.odbc.jdbc.JdbcResultInfo;
import org.apache.ignite.internal.processors.odbc.jdbc.JdbcStatementType;
import org.apache.ignite.internal.processors.odbc.jdbc.JdbcBulkLoadBatchRequest;
import org.apache.ignite.internal.processors.odbc.jdbc.JdbcStatementType;
import org.apache.ignite.internal.processors.query.IgniteSQLException;
import org.apache.ignite.internal.sql.SqlKeyword;
import org.apache.ignite.internal.sql.SqlParseException;
Expand Down Expand Up @@ -353,6 +351,8 @@ private JdbcResult sendFile(JdbcBulkLoadAckResult cmdRes) throws SQLException {

try {
closeResults();

conn.closeStatement(this);
}
finally {
closed = true;
Expand Down

0 comments on commit 55f6ed0

Please sign in to comment.