diff --git a/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java b/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java index 0c2cf05715..0e1d1e4c69 100644 --- a/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java +++ b/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java @@ -1031,6 +1031,10 @@ private static void populateLlapDaemonVarsSet(Set llapDaemonVarsSetLocal // whether session is running in silent mode or not HIVESESSIONSILENT("hive.session.silent", false, ""), + HIVE_SERVER2_SESSION_HANDLE_NULL("hive.server2.session.handle.null", false, + "Should be used when pinging server without creating a session or fs dirs." + + "A null session handle will be created."), + HIVE_LOCAL_TIME_ZONE("hive.local.time.zone", "LOCAL", "Sets the time-zone for displaying and interpreting time stamps. If this property value is set to\n" + "LOCAL, it is not specified, or it is not a correct time-zone, the system default time-zone will be\n " + diff --git a/service/src/java/org/apache/hive/service/cli/thrift/ThriftCLIService.java b/service/src/java/org/apache/hive/service/cli/thrift/ThriftCLIService.java index c64c99120a..4586e700e6 100644 --- a/service/src/java/org/apache/hive/service/cli/thrift/ThriftCLIService.java +++ b/service/src/java/org/apache/hive/service/cli/thrift/ThriftCLIService.java @@ -28,12 +28,14 @@ import java.net.UnknownHostException; import java.util.HashMap; import java.util.Map; +import java.util.UUID; import java.util.concurrent.TimeUnit; import javax.security.auth.login.LoginException; import org.apache.hadoop.hive.common.ServerUtils; import org.apache.hadoop.hive.common.log.ProgressMonitor; import org.apache.hadoop.hive.conf.HiveConf; import org.apache.hadoop.hive.conf.HiveConf.ConfVars; +import org.apache.hadoop.hive.conf.SystemVariables; import org.apache.hadoop.hive.ql.session.SessionState; import org.apache.hadoop.hive.shims.HadoopShims.KerberosNameShim; import org.apache.hadoop.hive.shims.ShimLoader; @@ -48,6 +50,7 @@ import org.apache.hive.service.cli.FetchType; import org.apache.hive.service.cli.GetInfoType; import org.apache.hive.service.cli.GetInfoValue; +import org.apache.hive.service.cli.HandleIdentifier; import org.apache.hive.service.cli.HiveSQLException; import org.apache.hive.service.cli.JobProgressUpdate; import org.apache.hive.service.cli.OperationHandle; @@ -158,6 +161,12 @@ public SessionHandle getSessionHandle() { return sessionHandle; } } + + // Hiveconnection will prefix "set:hiveconf:" to all hive conf + public static final String HIVE_SERVER2_SESSION_HANDLE_NULL = "set:" + SystemVariables.HIVECONF_PREFIX + + ConfVars.HIVE_SERVER2_SESSION_HANDLE_NULL.varname; + + final private static HandleIdentifier NULL_HANDLE_IDENTIFIER = new HandleIdentifier(new UUID( 0L , 0L ),new UUID( 0L , 0L )); public ThriftCLIService(CLIService service, String serviceName) { super(serviceName); @@ -325,7 +334,10 @@ public TOpenSessionResp OpenSession(TOpenSessionReq req) throws TException { resp.setSessionHandle(sessionHandle.toTSessionHandle()); Map configurationMap = new HashMap(); // Set the updated fetch size from the server into the configuration map for the client - HiveConf sessionConf = cliService.getSessionConf(sessionHandle); + HiveConf sessionConf = null; + if (!sessionHandle.getHandleIdentifier().equals(NULL_HANDLE_IDENTIFIER)) { + sessionConf = cliService.getSessionConf(sessionHandle); + } configurationMap.put( HiveConf.ConfVars.HIVE_SERVER2_THRIFT_RESULTSET_DEFAULT_FETCH_SIZE.varname, Integer.toString(sessionConf != null ? @@ -465,19 +477,27 @@ SessionHandle getSessionHandle(TOpenSessionReq req, TOpenSessionResp res) throws HiveSQLException, LoginException, IOException { String userName = getUserName(req); String ipAddress = getIpAddress(); - TProtocolVersion protocol = getMinVersion(CLIService.SERVER_VERSION, - req.getClient_protocol()); + TProtocolVersion protocol = getMinVersion(CLIService.SERVER_VERSION, req.getClient_protocol()); SessionHandle sessionHandle; - if (cliService.getHiveConf().getBoolVar(ConfVars.HIVE_SERVER2_ENABLE_DOAS) && - (userName != null)) { - String delegationTokenStr = getDelegationToken(userName); - sessionHandle = cliService.openSessionWithImpersonation(protocol, userName, - req.getPassword(), ipAddress, req.getConfiguration(), delegationTokenStr); - } else { - sessionHandle = cliService.openSession(protocol, userName, req.getPassword(), - ipAddress, req.getConfiguration()); + if (req.getConfiguration() != null + && (Boolean.parseBoolean(req.getConfiguration().get(HIVE_SERVER2_SESSION_HANDLE_NULL)) || + Boolean.parseBoolean(req.getConfiguration().get(ConfVars.HIVE_SERVER2_SESSION_HANDLE_NULL.varname)))) { + // set a null UUID + sessionHandle = new SessionHandle(NULL_HANDLE_IDENTIFIER, protocol); + LOG.debug("Null session handle created"); + } + else { + if (cliService.getHiveConf().getBoolVar(ConfVars.HIVE_SERVER2_ENABLE_DOAS) && (userName != null)) { + String delegationTokenStr = getDelegationToken(userName); + sessionHandle = cliService.openSessionWithImpersonation(protocol, userName, req.getPassword(), ipAddress, + req.getConfiguration(), delegationTokenStr); + } + else { + sessionHandle = cliService.openSession(protocol, userName, req.getPassword(), ipAddress, + req.getConfiguration()); + } + res.setServerProtocolVersion(protocol); } - res.setServerProtocolVersion(protocol); return sessionHandle; } @@ -521,7 +541,13 @@ public TCloseSessionResp CloseSession(TCloseSessionReq req) throws TException { TCloseSessionResp resp = new TCloseSessionResp(); try { SessionHandle sessionHandle = new SessionHandle(req.getSessionHandle()); - cliService.closeSession(sessionHandle); + if (sessionHandle.getHandleIdentifier().equals(NULL_HANDLE_IDENTIFIER)) { + //ignore close session if UUID is null, which means it's a null session handle + LOG.debug("Not closing null session"); + } + else{ + cliService.closeSession(sessionHandle); + } resp.setStatus(OK_STATUS); ThriftCLIServerContext context = (ThriftCLIServerContext)currentServerContext.get(); diff --git a/service/src/test/org/apache/hive/service/cli/thrift/TestThriftCLISession.java b/service/src/test/org/apache/hive/service/cli/thrift/TestThriftCLISession.java new file mode 100644 index 0000000000..017225b57c --- /dev/null +++ b/service/src/test/org/apache/hive/service/cli/thrift/TestThriftCLISession.java @@ -0,0 +1,69 @@ +package org.apache.hive.service.cli.thrift; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.fail; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import org.apache.hadoop.fs.FileSystem; +import org.apache.hadoop.fs.Path; +import org.apache.hadoop.hive.conf.HiveConf; +import org.apache.hadoop.hive.conf.HiveConf.ConfVars; +import org.apache.hive.service.cli.SessionHandle; +import org.junit.Test; + +public class TestThriftCLISession extends ThriftCliServiceTestWithCookie { + + @Test + public void testStateLessSession() throws Exception { + Map map = new HashMap(); + map.put(ThriftCLIService.HIVE_SERVER2_SESSION_HANDLE_NULL, "true"); + validateStateLessSession(map); + map.clear(); + map.put(ConfVars.HIVE_SERVER2_SESSION_HANDLE_NULL.varname, "true"); + validateStateLessSession(map); + } + + @Test + public void testStateLessSessionOp() throws Exception { + Map map = new HashMap(); + map.put(ThriftCLIService.HIVE_SERVER2_SESSION_HANDLE_NULL, "true"); + validateStateLessSessionOp(map); + map.clear(); + map.put(ConfVars.HIVE_SERVER2_SESSION_HANDLE_NULL.varname, "true"); + validateStateLessSessionOp(map); + } + + private void validateStateLessSession(Map map) throws Exception { + // Open a new client session + SessionHandle sessHandle = client.openSession(USERNAME, PASSWORD, map); + Path rootHDFSDirPath = new Path(hiveConf.getVar(HiveConf.ConfVars.SCRATCHDIR)); + FileSystem fs = rootHDFSDirPath.getFileSystem(hiveConf); + Path hdfsSessionPath = new Path(new Path(rootHDFSDirPath, USERNAME), sessHandle.getSessionId().toString()); + + assertEquals("Stateless session id is not null UUID", sessHandle.getSessionId(), new UUID(0l, 0l)); + assertFalse(fs.exists(hdfsSessionPath)); + client.closeSession(sessHandle); + sessHandle = client.openSession(USERNAME, PASSWORD, new HashMap()); + assertFalse("Stateless session id is null UUID", sessHandle.getSessionId().equals(new UUID(0l, 0l))); + client.closeSession(sessHandle); + } + + private void validateStateLessSessionOp(Map map) throws Exception { + // Open a new client session + SessionHandle sessHandle = null; + + try { + sessHandle = client.openSession(USERNAME, PASSWORD, map); + client.getFunctions(sessHandle, "", "", ""); + fail("getFunctions should fail for null session handle"); + } + catch (Exception e) { + assertEquals(e.getMessage(), "Invalid SessionHandle: SessionHandle [00000000-0000-0000-0000-000000000000]"); + } + client.closeSession(sessHandle); + } +} \ No newline at end of file