-
Notifications
You must be signed in to change notification settings - Fork 29.3k
[SPARK-31926][SQL][TESTS][FOLLOWUP][test-hive1.2][test-maven] Fix concurrency issue for ThriftCLIService to getPortNumber #28835
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 6 commits
03f41ab
9c6ac83
5e79ad9
9cdd7fa
5ce343a
d5341ea
e409f9a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -22,13 +22,14 @@ import java.util.{List => JList} | |
| import javax.security.auth.login.LoginException | ||
|
|
||
| import scala.collection.JavaConverters._ | ||
| import scala.util.control.NonFatal | ||
|
|
||
| import org.apache.commons.logging.Log | ||
| import org.apache.hadoop.hive.conf.HiveConf | ||
| import org.apache.hadoop.hive.conf.HiveConf.ConfVars | ||
| import org.apache.hadoop.hive.shims.Utils | ||
| import org.apache.hadoop.security.{SecurityUtil, UserGroupInformation} | ||
| import org.apache.hive.service.{AbstractService, Service, ServiceException} | ||
| import org.apache.hive.service.{AbstractService, CompositeService, Service, ServiceException} | ||
| import org.apache.hive.service.Service.STATE | ||
| import org.apache.hive.service.auth.HiveAuthFactory | ||
| import org.apache.hive.service.cli._ | ||
|
|
@@ -94,6 +95,12 @@ private[hive] class SparkSQLCLIService(hiveServer: HiveServer2, sqlContext: SQLC | |
| initCompositeService(hiveConf) | ||
| } | ||
|
|
||
| /** | ||
| * the super class [[CLIService#start]] starts a useless dummy metastore client, skip it and call | ||
| * the ancestor [[CompositeService#start]] directly. | ||
| */ | ||
| override def start(): Unit = startCompositeService() | ||
|
|
||
| override def getInfo(sessionHandle: SessionHandle, getInfoType: GetInfoType): GetInfoValue = { | ||
| getInfoType match { | ||
| case GetInfoType.CLI_SERVER_NAME => new GetInfoValue("Spark SQL") | ||
|
|
@@ -105,6 +112,19 @@ private[hive] class SparkSQLCLIService(hiveServer: HiveServer2, sqlContext: SQLC | |
| } | ||
|
|
||
| private[thriftserver] trait ReflectedCompositeService { this: AbstractService => | ||
|
|
||
| private val logInfo = (msg: String) => if (HiveUtils.isHive23) { | ||
| getAncestorField[Logger](this, 3, "LOG").info(msg) | ||
| } else { | ||
| getAncestorField[Log](this, 3, "LOG").info(msg) | ||
| } | ||
|
|
||
| private val logError = (msg: String, e: Throwable) => if (HiveUtils.isHive23) { | ||
| getAncestorField[Logger](this, 3, "LOG").error(msg, e) | ||
| } else { | ||
| getAncestorField[Log](this, 3, "LOG").error(msg, e) | ||
| } | ||
|
|
||
| def initCompositeService(hiveConf: HiveConf): Unit = { | ||
| // Emulating `CompositeService.init(hiveConf)` | ||
| val serviceList = getAncestorField[JList[Service]](this, 2, "serviceList") | ||
|
|
@@ -114,10 +134,31 @@ private[thriftserver] trait ReflectedCompositeService { this: AbstractService => | |
| invoke(classOf[AbstractService], this, "ensureCurrentState", classOf[STATE] -> STATE.NOTINITED) | ||
| setAncestorField(this, 3, "hiveConf", hiveConf) | ||
| invoke(classOf[AbstractService], this, "changeState", classOf[STATE] -> STATE.INITED) | ||
| if (HiveUtils.isHive23) { | ||
| getAncestorField[Logger](this, 3, "LOG").info(s"Service: $getName is inited.") | ||
| } else { | ||
| getAncestorField[Log](this, 3, "LOG").info(s"Service: $getName is inited.") | ||
| logInfo(s"Service: $getName is inited.") | ||
| } | ||
|
|
||
| def startCompositeService(): Unit = { | ||
| // Emulating `CompositeService.start` | ||
| val serviceList = getAncestorField[JList[Service]](this, 2, "serviceList") | ||
| var serviceStartCount = 0 | ||
| try { | ||
| serviceList.asScala.foreach { service => | ||
| service.start() | ||
| serviceStartCount += 1 | ||
| } | ||
| } catch { | ||
| case NonFatal(e) => | ||
| logError(s"Error starting services $getName", e) | ||
| invoke(classOf[CompositeService], this, "stop", | ||
| classOf[Int] -> new Integer(serviceStartCount)) | ||
| throw new ServiceException("Failed to Start " + getName, e) | ||
| } | ||
|
|
||
| // Emulating `AbstractService.start` | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. AbstractService.start does also
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice catch! |
||
| val startTime = new java.lang.Long(System.currentTimeMillis()) | ||
| setAncestorField(this, 3, "startTime", startTime) | ||
| invoke(classOf[AbstractService], this, "ensureCurrentState", classOf[STATE] -> STATE.INITED) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This can throw IllegalStateException, and in the original implementation it is inside the try catch block, which would turn it into ServiceException.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, I see. |
||
| invoke(classOf[AbstractService], this, "changeState", classOf[STATE] -> STATE.STARTED) | ||
| logInfo(s"Service: $getName is started.") | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| # | ||
| # 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. | ||
| # | ||
|
|
||
| # Set everything to be logged to the file hive-thriftserver/target/unit-tests.log | ||
| log4j.rootLogger=DEBUG, CA, FA | ||
|
|
||
| #Console Appender | ||
| log4j.appender.CA=org.apache.log4j.ConsoleAppender | ||
| log4j.appender.CA.layout=org.apache.log4j.PatternLayout | ||
| log4j.appender.CA.layout.ConversionPattern=%d{HH:mm:ss.SSS} %p %c: %m%n | ||
| log4j.appender.CA.Threshold = WARN | ||
|
|
||
|
|
||
| #File Appender | ||
| log4j.appender.FA=org.apache.log4j.FileAppender | ||
| log4j.appender.FA.append=false | ||
| log4j.appender.FA.file=target/unit-tests.log | ||
| log4j.appender.FA.layout=org.apache.log4j.PatternLayout | ||
| log4j.appender.FA.layout.ConversionPattern=%d{HH:mm:ss.SSS} %t %p %c{1}: %m%n | ||
|
|
||
| # Set the logger level of File Appender to WARN | ||
| log4j.appender.FA.Threshold = DEBUG | ||
|
|
||
| # Some packages are noisy for no good reason. | ||
| log4j.additivity.org.apache.hadoop.hive.serde2.lazy.LazyStruct=false | ||
| log4j.logger.org.apache.hadoop.hive.serde2.lazy.LazyStruct=OFF | ||
|
|
||
| log4j.additivity.org.apache.hadoop.hive.metastore.RetryingHMSHandler=false | ||
| log4j.logger.org.apache.hadoop.hive.metastore.RetryingHMSHandler=OFF | ||
|
|
||
| log4j.additivity.hive.log=false | ||
| log4j.logger.hive.log=OFF | ||
|
|
||
| log4j.additivity.parquet.hadoop.ParquetRecordReader=false | ||
| log4j.logger.parquet.hadoop.ParquetRecordReader=OFF | ||
|
|
||
| log4j.additivity.org.apache.parquet.hadoop.ParquetRecordReader=false | ||
| log4j.logger.org.apache.parquet.hadoop.ParquetRecordReader=OFF | ||
|
|
||
| log4j.additivity.org.apache.parquet.hadoop.ParquetOutputCommitter=false | ||
| log4j.logger.org.apache.parquet.hadoop.ParquetOutputCommitter=OFF | ||
|
|
||
| log4j.additivity.hive.ql.metadata.Hive=false | ||
| log4j.logger.hive.ql.metadata.Hive=OFF | ||
|
|
||
| log4j.additivity.org.apache.hadoop.hive.ql.io.RCFile=false | ||
| log4j.logger.org.apache.hadoop.hive.ql.io.RCFile=ERROR | ||
|
|
||
| # Parquet related logging | ||
| log4j.logger.org.apache.parquet.CorruptStatistics=ERROR | ||
| log4j.logger.parquet.CorruptStatistics=ERROR |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CLIService will create a metastore connection during start, which is useless for our dummy execution hive conf and will cause class cast issue though different classloader
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here we bypass it and start the registered services as CompositeService does