Author: sunchao Date: Thu Mar 26 16:38:33 2015 New Revision: 1669367 URL: http://svn.apache.org/r1669367 Log: HIVE-9839 - HiveServer2 leaks OperationHandle on async queries which fail at compile phase (Nemon via Chao)
Added: hive/trunk/itests/hive-unit/src/test/java/org/apache/hive/service/cli/session/ hive/trunk/itests/hive-unit/src/test/java/org/apache/hive/service/cli/session/TestHiveSessionImpl.java Modified: hive/trunk/service/src/java/org/apache/hive/service/cli/session/HiveSessionImpl.java Added: hive/trunk/itests/hive-unit/src/test/java/org/apache/hive/service/cli/session/TestHiveSessionImpl.java URL: http://svn.apache.org/viewvc/hive/trunk/itests/hive-unit/src/test/java/org/apache/hive/service/cli/session/TestHiveSessionImpl.java?rev=1669367&view=auto ============================================================================== --- hive/trunk/itests/hive-unit/src/test/java/org/apache/hive/service/cli/session/TestHiveSessionImpl.java (added) +++ hive/trunk/itests/hive-unit/src/test/java/org/apache/hive/service/cli/session/TestHiveSessionImpl.java Thu Mar 26 16:38:33 2015 @@ -0,0 +1,95 @@ +/** + * 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.hive.service.cli.session; + +import org.apache.hadoop.hive.conf.HiveConf; +import org.apache.hive.service.cli.HiveSQLException; +import org.apache.hive.service.cli.OperationHandle; +import org.apache.hive.service.cli.operation.ExecuteStatementOperation; +import org.apache.hive.service.cli.operation.OperationManager; +import org.apache.hive.service.cli.thrift.TProtocolVersion; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.Mockito; + +import java.util.HashMap; +import java.util.Map; + + + +public class TestHiveSessionImpl { + /** + * Verifying OperationManager.closeOperation(opHandle) is invoked when + * get HiveSQLException during sync query + * @throws HiveSQLException + */ + @Test + public void testLeakOperationHandle() throws HiveSQLException { + //create HiveSessionImpl object + TProtocolVersion protocol = TProtocolVersion.HIVE_CLI_SERVICE_PROTOCOL_V2; + String username = ""; + String password = ""; + HiveConf serverhiveConf = new HiveConf(); + String ipAddress = null; + HiveSessionImpl session = new HiveSessionImpl(protocol, username, password, + serverhiveConf, ipAddress) { + @Override + protected synchronized void acquire(boolean userAccess) { + } + + @Override + protected synchronized void release(boolean userAccess) { + } + }; + + //mock operationManager for session + OperationManager operationManager = Mockito.mock(OperationManager.class); + session.setOperationManager(operationManager); + + //mock operation and opHandle for operationManager + ExecuteStatementOperation operation = Mockito.mock(ExecuteStatementOperation.class); + OperationHandle opHandle = Mockito.mock(OperationHandle.class); + Mockito.when(operation.getHandle()).thenReturn(opHandle); + Map<String, String> confOverlay = new HashMap<String, String>(); + String hql = "drop table if exists table_not_exists"; + Mockito.when(operationManager.newExecuteStatementOperation(session, hql, confOverlay, + true)).thenReturn(operation); + + try { + + //Running a normal async query with no exceptions,then no need to close opHandle + session.executeStatementAsync(hql, confOverlay); + Mockito.verify(operationManager, Mockito.times(0)).closeOperation(opHandle); + + // Throw an HiveSqlException when do async calls + Mockito.doThrow(new HiveSQLException("Fail for clean up test")).when(operation).run(); + session.executeStatementAsync(hql, confOverlay); + Assert.fail("HiveSqlException expected."); + + } catch (HiveSQLException e) { + if (!"Fail for clean up test".equals(e.getMessage())) { + Assert.fail("unexpected exception:" + e.getMessage()); + } + //operationManager.closeOperation() is expected to be invoked once + Mockito.verify(operationManager, Mockito.times(1)).closeOperation(opHandle); + } + } + +} + Modified: hive/trunk/service/src/java/org/apache/hive/service/cli/session/HiveSessionImpl.java URL: http://svn.apache.org/viewvc/hive/trunk/service/src/java/org/apache/hive/service/cli/session/HiveSessionImpl.java?rev=1669367&r1=1669366&r2=1669367&view=diff ============================================================================== --- hive/trunk/service/src/java/org/apache/hive/service/cli/session/HiveSessionImpl.java (original) +++ hive/trunk/service/src/java/org/apache/hive/service/cli/session/HiveSessionImpl.java Thu Mar 26 16:38:33 2015 @@ -382,11 +382,10 @@ public class HiveSessionImpl implements opHandleSet.add(opHandle); return opHandle; } catch (HiveSQLException e) { - // Cleanup opHandle in case the query is synchronous - // Async query needs to retain and pass back the opHandle for error reporting - if (!runAsync) { - operationManager.closeOperation(opHandle); - } + // Refering to SQLOperation.java,there is no chance that a HiveSQLException throws and the asyn + // background operation submits to thread pool successfully at the same time. So, Cleanup + // opHandle directly when got HiveSQLException + operationManager.closeOperation(opHandle); throw e; } finally { release(true);