/**
* 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.hadoop.hive.ql.exec.spark.session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.hadoop.hive.conf.HiveConf;
import org.apache.hadoop.util.StringUtils;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
public class TestSparkSessionManagerImpl {
private static final Logger LOG = LoggerFactory.getLogger(TestSparkSessionManagerImpl.class);
private SparkSessionManagerImpl sessionManagerHS2 = null;
private boolean anyFailedSessionThread; // updated only when a thread has failed.
/** Tests CLI scenario where we get a single session and use it multiple times. */
@Test
public void testSingleSessionMultipleUse() throws Exception {
HiveConf conf = new HiveConf();
conf.set("spark.master", "local");
SparkSessionManager sessionManager = SparkSessionManagerImpl.getInstance();
SparkSession sparkSession1 = sessionManager.getSession(null, conf, true);
assertTrue(sparkSession1.isOpen());
SparkSession sparkSession2 = sessionManager.getSession(sparkSession1, conf, true);
assertTrue(sparkSession1 == sparkSession2); // Same session object is expected.
assertTrue(sparkSession2.isOpen());
sessionManager.shutdown();
sessionManager.closeSession(sparkSession1);
}
/**
* Tests multi-user scenario (like HiveServer2) where each user gets a session
* and uses it multiple times.
*/
@Test
public void testMultiSessionMultipleUse() throws Exception {
sessionManagerHS2 = SparkSessionManagerImpl.getInstance();
// Shutdown existing session manager
sessionManagerHS2.shutdown();
HiveConf hiveConf = new HiveConf();
hiveConf.set("spark.master", "local");
sessionManagerHS2.setup(hiveConf);
List<Thread> threadList = new ArrayList<Thread>();
for (int i = 0; i < 10; i++) {
Thread t = new Thread(new SessionThread(), "Session thread " + i);
t.start();
threadList.add(t);
}
for (Thread t : threadList) {
try {
t.join();
} catch (InterruptedException e) {
String msg = "Interrupted while waiting for test session threads.";
LOG.error(msg, e);
fail(msg);
}
}
assertFalse("At least one of the session threads failed. See the test output for details.",
anyFailedSessionThread);
System.out.println("Ending SessionManagerHS2");
sessionManagerHS2.shutdown();
}
/* Thread simulating a user session in HiveServer2. */
public class SessionThread implements Runnable {
@Override
public void run() {
try {
Random random = new Random(Thread.currentThread().getId());
String threadName = Thread.currentThread().getName();
System.out.println(threadName + " started.");
HiveConf conf = new HiveConf();
conf.set("spark.master", "local");
SparkSession prevSession = null;
SparkSession currentSession = null;
for(int i = 0; i < 5; i++) {
currentSession = sessionManagerHS2.getSession(prevSession, conf, true);
assertTrue(prevSession == null || prevSession == currentSession);
assertTrue(currentSession.isOpen());
System.out.println(String.format("%s got session (%d): %s",
threadName, i, currentSession.getSessionId()));
Thread.sleep((random.nextInt(3)+1) * 1000);
sessionManagerHS2.returnSession(currentSession);
prevSession = currentSession;
}
sessionManagerHS2.closeSession(currentSession);
System.out.println(threadName + " ended.");
} catch (Throwable e) {
anyFailedSessionThread = true;
String msg = String.format("Error executing '%s'", Thread.currentThread().getName());
LOG.error(msg, e);
fail(msg + " " + StringUtils.stringifyException(e));
}
}
}
}