diff --git ql/src/java/org/apache/hadoop/hive/ql/Driver.java ql/src/java/org/apache/hadoop/hive/ql/Driver.java index d1db215..94cd44a 100644 --- ql/src/java/org/apache/hadoop/hive/ql/Driver.java +++ ql/src/java/org/apache/hadoop/hive/ql/Driver.java @@ -118,12 +118,14 @@ import org.apache.hadoop.mapred.ClusterStatus; import org.apache.hadoop.mapred.JobClient; import org.apache.hadoop.mapred.JobConf; +import org.apache.hive.common.util.ShutdownHookManager; public class Driver implements CommandProcessor { static final private String CLASS_NAME = Driver.class.getName(); static final private Log LOG = LogFactory.getLog(CLASS_NAME); static final private LogHelper console = new LogHelper(LOG); + static final int SHUTDOWN_HOOK_PRIORITY = 0; private static final Object compileMonitor = new Object(); @@ -386,7 +388,20 @@ public int compile(String command, boolean resetTaskIds) { try { // Initialize the transaction manager. This must be done before analyze is called. - SessionState.get().initTxnMgr(conf); + final HiveTxnManager txnManager = SessionState.get().initTxnMgr(conf); + // In case when user Ctrl-C twice to kill Hive CLI JVM, we want to release locks + ShutdownHookManager.addShutdownHook( + new Runnable() { + @Override + public void run() { + try { + releaseLocksAndCommitOrRollback(ctx.getHiveLocks(), false, txnManager); + } catch (LockException e) { + LOG.warn("Exception when releasing locks in ShutdownHook for Driver: " + + e.getMessage()); + } + } + }, SHUTDOWN_HOOK_PRIORITY); command = new VariableSubstitution().substitute(conf, command); ctx = new Context(conf); @@ -1036,16 +1051,22 @@ private boolean haveAcidWrite() { * list of hive locks to be released Release all the locks specified. If some of the * locks have already been released, ignore them * @param commit if there is an open transaction and if true, commit, - * if false rollback. If there is no open transaction this parameter is ignored. + * @param txnManager an optional existing transaction manager retrieved earlier from the session * **/ - private void releaseLocksAndCommitOrRollback(List hiveLocks, boolean commit) + private void releaseLocksAndCommitOrRollback(List hiveLocks, boolean commit, + HiveTxnManager txnManager) throws LockException { PerfLogger perfLogger = PerfLogger.getPerfLogger(); perfLogger.PerfLogBegin(CLASS_NAME, PerfLogger.RELEASE_LOCKS); - SessionState ss = SessionState.get(); - HiveTxnManager txnMgr = ss.getTxnMgr(); + HiveTxnManager txnMgr; + if (txnManager == null) { + SessionState ss = SessionState.get(); + txnMgr = ss.getTxnMgr(); + } else { + txnMgr = txnManager; + } // If we've opened a transaction we need to commit or rollback rather than explicitly // releasing the locks. if (txnMgr.isTxnOpen()) { @@ -1145,7 +1166,7 @@ private int compileInternal(String command) { } if (ret != 0) { try { - releaseLocksAndCommitOrRollback(ctx.getHiveLocks(), false); + releaseLocksAndCommitOrRollback(ctx.getHiveLocks(), false, null); } catch (LockException e) { LOG.warn("Exception in releasing locks. " + org.apache.hadoop.util.StringUtils.stringifyException(e)); @@ -1230,7 +1251,7 @@ private CommandProcessorResponse runInternal(String command, boolean alreadyComp if(plan.getAutoCommitValue() && !txnManager.getAutoCommit()) { /*here, if there is an open txn, we want to commit it; this behavior matches * https://docs.oracle.com/javase/6/docs/api/java/sql/Connection.html#setAutoCommit(boolean)*/ - releaseLocksAndCommitOrRollback(ctx.getHiveLocks(), true); + releaseLocksAndCommitOrRollback(ctx.getHiveLocks(), true, null); txnManager.setAutoCommit(true); } else if(!plan.getAutoCommitValue() && txnManager.getAutoCommit()) { @@ -1258,10 +1279,10 @@ else if(!plan.getAutoCommitValue() && txnManager.getAutoCommit()) { //if needRequireLock is false, the release here will do nothing because there is no lock try { if(txnManager.getAutoCommit() || plan.getOperation() == HiveOperation.COMMIT) { - releaseLocksAndCommitOrRollback(ctx.getHiveLocks(), true); + releaseLocksAndCommitOrRollback(ctx.getHiveLocks(), true, null); } else if(plan.getOperation() == HiveOperation.ROLLBACK) { - releaseLocksAndCommitOrRollback(ctx.getHiveLocks(), false); + releaseLocksAndCommitOrRollback(ctx.getHiveLocks(), false, null); } else { //txn (if there is one started) is not finished @@ -1293,7 +1314,7 @@ else if(plan.getOperation() == HiveOperation.ROLLBACK) { private CommandProcessorResponse rollback(CommandProcessorResponse cpr) { //console.printError(cpr.toString()); try { - releaseLocksAndCommitOrRollback(ctx.getHiveLocks(), false); + releaseLocksAndCommitOrRollback(ctx.getHiveLocks(), false, null); } catch (LockException e) { LOG.error("rollback() FAILED: " + cpr);//make sure not to loose @@ -1864,7 +1885,7 @@ public void destroy() { destroyed = true; if (ctx != null) { try { - releaseLocksAndCommitOrRollback(ctx.getHiveLocks(), false); + releaseLocksAndCommitOrRollback(ctx.getHiveLocks(), false, null); } catch (LockException e) { LOG.warn("Exception when releasing locking in destroy: " + e.getMessage());