Skip to content

Commit 2310266

Browse files
authored
HIVE-29609: HPL/SQL leaving behind hive-staging directories (apache#6500)
1 parent 52b8b1a commit 2310266

3 files changed

Lines changed: 140 additions & 6 deletions

File tree

itests/hive-unit/src/test/java/org/apache/hive/beeline/TestHplSqlViaBeeLine.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
import static org.apache.hive.beeline.TestBeeLineWithArgs.OutStream;
2424
import static org.apache.hive.beeline.TestBeeLineWithArgs.testCommandLineScript;
25+
import static org.junit.Assert.assertFalse;
2526
import static org.junit.Assert.fail;
2627

2728
import java.io.File;
@@ -37,8 +38,12 @@
3738
import java.util.regex.Matcher;
3839
import java.util.regex.Pattern;
3940

41+
import org.apache.hadoop.fs.FileStatus;
42+
import org.apache.hadoop.fs.FileSystem;
43+
import org.apache.hadoop.fs.Path;
4044
import org.apache.hadoop.hive.UtilsForTest;
4145
import org.apache.hadoop.hive.conf.HiveConf;
46+
import org.apache.hadoop.hive.metastore.conf.MetastoreConf;
4247
import org.apache.hive.jdbc.miniHS2.MiniHS2;
4348
import org.junit.AfterClass;
4449
import org.junit.BeforeClass;
@@ -1480,6 +1485,30 @@ public void testERRORCODEForExecuteStatements() throws Throwable {
14801485
testScriptFile(scriptText, args(), "First ERRORCODE: -1.*Second ERRORCODE: 0", OutStream.ERR);
14811486
}
14821487

1488+
@Test
1489+
public void testHplSqlInsertRemovesStagingDirsUnderTable() throws Throwable {
1490+
String scriptText =
1491+
"DROP TABLE IF EXISTS result;\n" +
1492+
"CREATE TABLE result (s string);\n" +
1493+
"INSERT INTO result VALUES('Hello');\n" +
1494+
"execute 'INSERT INTO result VALUES(''World'')';\n" +
1495+
"SELECT * FROM result;";
1496+
testScriptFile(scriptText, args(), "Hello.*World");
1497+
1498+
HiveConf conf = miniHS2.getHiveConf();
1499+
String stagingDirPrefix = HiveConf.getVar(conf, HiveConf.ConfVars.STAGING_DIR);
1500+
Path wh = new Path(MetastoreConf.getVar(conf, MetastoreConf.ConfVars.WAREHOUSE));
1501+
FileSystem fs = wh.getFileSystem(conf);
1502+
Path tableDir = fs.makeQualified(new Path(wh, "result"));
1503+
FileStatus[] children = fs.listStatus(tableDir);
1504+
if (children != null) {
1505+
for (FileStatus child : children) {
1506+
assertFalse("Staging directory was not cleaned up: " + child.getPath(),
1507+
child.getPath().getName().startsWith(stagingDirPrefix));
1508+
}
1509+
}
1510+
}
1511+
14831512
private static List<String> args() {
14841513
return Arrays.asList("-d", BeeLine.BEELINE_DEFAULT_JDBC_DRIVER,
14851514
"-u", miniHS2.getBaseJdbcURL() + ";mode=hplsql", "-n", USER_NAME);

service/src/java/org/apache/hive/service/cli/operation/SQLOperation.java

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -403,11 +403,7 @@ private synchronized void cleanup(OperationState state) throws HiveSQLException
403403
}
404404
}
405405

406-
if (driver != null) {
407-
driver.close();
408-
driver.destroy();
409-
}
410-
driver = null;
406+
closeDriver();
411407

412408
SessionState ss = SessionState.get();
413409
if (ss == null) {
@@ -423,6 +419,14 @@ private synchronized void cleanup(OperationState state) throws HiveSQLException
423419
}
424420
}
425421

422+
private void closeDriver() {
423+
if (driver != null) {
424+
driver.close();
425+
driver.destroy();
426+
}
427+
driver = null;
428+
}
429+
426430
@Override
427431
public void cancel(OperationState stateAfterCancel) throws HiveSQLException {
428432
String queryId = null;
@@ -439,7 +443,9 @@ public void cancel(OperationState stateAfterCancel) throws HiveSQLException {
439443

440444
@Override
441445
public void close() throws HiveSQLException {
442-
if (!embedded) {
446+
if (embedded) {
447+
closeDriver();
448+
} else {
443449
cleanup(OperationState.CLOSED);
444450
cleanupOperationLog(0);
445451
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package org.apache.hive.service.cli.operation;
20+
21+
import com.google.common.collect.ImmutableMap;
22+
import org.apache.hadoop.hive.conf.HiveConf;
23+
import org.apache.hadoop.hive.ql.IDriver;
24+
import org.apache.hadoop.hive.ql.session.SessionState;
25+
import org.apache.hive.service.cli.HandleIdentifier;
26+
import org.apache.hive.service.cli.OperationState;
27+
import org.apache.hive.service.cli.SessionHandle;
28+
import org.apache.hive.service.cli.session.HiveSession;
29+
import org.junit.Before;
30+
import org.junit.Test;
31+
import org.mockito.InOrder;
32+
33+
import java.lang.reflect.Field;
34+
35+
import static org.junit.Assert.assertEquals;
36+
import static org.junit.Assert.assertNull;
37+
import static org.mockito.Mockito.inOrder;
38+
import static org.mockito.Mockito.mock;
39+
import static org.mockito.Mockito.when;
40+
41+
public class TestSQLOperationDriverCleanup {
42+
43+
private HiveSession session;
44+
private IDriver driver;
45+
46+
@Before
47+
public void setUp() {
48+
HiveConf conf = new HiveConf();
49+
session = mock(HiveSession.class);
50+
when(session.getHiveConf()).thenReturn(conf);
51+
when(session.getSessionState()).thenReturn(mock(SessionState.class));
52+
when(session.getUserName()).thenReturn("user");
53+
SessionHandle sessionHandle = mock(SessionHandle.class);
54+
when(sessionHandle.getHandleIdentifier()).thenReturn(new HandleIdentifier());
55+
when(session.getSessionHandle()).thenReturn(sessionHandle);
56+
driver = mock(IDriver.class);
57+
}
58+
59+
@Test
60+
public void testSQLOperationCloseReleasesDriverInHPLSQLMode() throws Exception {
61+
SQLOperation operation = new SQLOperation(session, "insert into test values (1)",
62+
ImmutableMap.of(), false, 0L, true);
63+
setDriver(operation, driver);
64+
65+
operation.close();
66+
67+
InOrder order = inOrder(driver);
68+
order.verify(driver).close();
69+
order.verify(driver).destroy();
70+
assertNull(getDriver(operation));
71+
}
72+
73+
@Test
74+
public void testSQLOperationCloseReleasesDriverInNonHPLSQLMode() throws Exception {
75+
SQLOperation operation = new SQLOperation(session, "insert into test values (1)",
76+
ImmutableMap.of(), false, 0L, false);
77+
setDriver(operation, driver);
78+
79+
operation.close();
80+
81+
InOrder order = inOrder(driver);
82+
order.verify(driver).close();
83+
order.verify(driver).destroy();
84+
assertEquals(OperationState.CLOSED, operation.getStatus().getState());
85+
assertNull(getDriver(operation));
86+
}
87+
88+
private static void setDriver(SQLOperation operation, IDriver driver) throws Exception {
89+
Field driverField = SQLOperation.class.getDeclaredField("driver");
90+
driverField.setAccessible(true);
91+
driverField.set(operation, driver);
92+
}
93+
94+
private static IDriver getDriver(SQLOperation operation) throws Exception {
95+
Field driverField = SQLOperation.class.getDeclaredField("driver");
96+
driverField.setAccessible(true);
97+
return (IDriver) driverField.get(operation);
98+
}
99+
}

0 commit comments

Comments
 (0)