Spark-scala 源码-StaticSQLConf
StaticSQLConf源码阅读
StaticSQLConf Object
StaticSQLConf 的作用就是设置一些不可变的 spark configuration,而且是跨session的,这些 spark configuration可以通过SparkSession.conf查看,但是不能修改。
里面已经预置了一些配置,(ConfigEntry是一个抽象类):
1.WAREHOUSE_PATH:ConfigEntry
在生成warehouse_path 的时候,会尝试解析网络uri,当失败的时候,会生成此目录下路径的file uri
2.CATALOG_IMPLEMENTATION:ConfigEntry
3.GLOBAL_TEMP_DATABASE:ConfigEntry
4.SCHEMA_STRING_LENGTH_THRESHOLD:ConfigEntry
5.FILESOURCE_TABLE_RELATION_CACHE_SIZE:ConfigEntry
6.CODEGEN_CACHE_MAX_ENTRIES:ConfigEntry
7.CODEGEN_COMMENTS:ConfigEntry
8.DEBUG_MODE:ConfigEntry
9.HIVE_THRIFT_SERVER_SINGLESESSION:ConfigEntry
10.SPARK_SESSION_EXTENSIONS:ConfigEntry
11.QUERY_EXECUTION_LISTENERS:ConfigEntry
12.STREAMING_QUERY_LISTENERS:ConfigEntry
13.UI_RETAINED_EXECUTIONS:ConfigEntry
以上的配置都是通过SQLConf Object的buildStaticConf方法产生的ConfigEntry;SQLConf Object还有一个buildConf方法,这2个方法不同的是传入的回调函数的不同而已,往下浏览SQLConf Object。
SQLConf Object&class
这个文件定义了 Spark SQL的configuration options ;
这个对象里面有2个属性:
1.sqlConfEntries = java.util.Collections.synchronizedMap(
new java.util.HashMapString, ConfigEntry[_]) 存放已经生成的ConfigEntry,用以检测是否重复覆盖,重复的话则会抛出异常
2.staticConfKeys: java.util.Set[String] =
java.util.Collections.synchronizedSet(new java.util.HashSetString)存放已经生成的ConfigEntry的key
方法解读:
// 传入回调函数生成ConfigBuilder,q1何时调用回调函数(在 TypedConfigBuilder 的 create* 的方法中的_onCreate foreach 中)
def buildConf(key: String): ConfigBuilder = ConfigBuilder(key).onCreate(register)
// 传入回调函数生成ConfigBuilder
def buildStaticConf(key: String): ConfigBuilder = {
ConfigBuilder(key).onCreate { entry =>
staticConfKeys.add(entry.key)
SQLConf.register(entry)
}
}
ConfigBuilder case class
ConfigBuilder是一个case class,这个类的主要作用是用来产生下面的TypedConfigBuilder 这个类。
ConfigBuilder有4个属性:
1.var _public = true
2.var _doc = “” 这个表示注释文档
3.var onCreate: Option[ConfigEntry[] => Unit] = None 存放ConfigEntry的实例对象 到 null 的函数转化,在TypedConfigBuilder中的createWithDefault、createWithDefaultFunction、createWithDefaultString 方法中 有一个 parent.onCreate.foreach((entry)) 的 语句,这个parent就是在实例化TypedConfigBuilder的时候传进来的ConfigBuilder的实例,即此时会执行 _onCreate 里面的函数,而这个函数是SQLConf的buildStaticConf方法中的匿名函数,这个匿名函数的主要 是把这个entry 注册到 SQLConf有HashMap类型的sqlConfEntries和Set类型的staticConfKeys 中去。
4.var _alternatives = List.empty[String]
ConfigBuilder有13个方法:
//1
def internal(): ConfigBuilder = {
// 改变 _public 的boolean值
_public = false
this
}
//2
def doc(s: String): ConfigBuilder = {
// 赋予 _doc 的值
_doc = s
this
}
//3
def onCreate(callback: ConfigEntry[_] => Unit): ConfigBuilder = {
// _onCreate 赋予 回调函数
_onCreate = Option(callback)
this
}
//4
def withAlternative(key: String): ConfigBuilder = {
_alternatives = _alternatives :+ key
this
}
//5
def intConf: TypedConfigBuilder[Int] = {
//这个使用的是 TypedConfigBuilder的2个参数的构造方法,converter 就是这个toNumber.. 函数,
//stringConverter就是这个构造方法写死的函数
new TypedConfigBuilder(this, toNumber(_, _.toInt, key, "int"))
}
def longConf: TypedConfigBuilder[Long] = {
new TypedConfigBuilder(this, toNumber(_, _.toLong, key, "long"))
}
def doubleConf: TypedConfigBuilder[Double] = {
new TypedConfigBuilder(this, toNumber(_, _.toDouble, key, "double"))
}
def booleanConf: TypedConfigBuilder[Boolean] = {
new TypedConfigBuilder(this, toBoolean(_, key))
}
def stringConf: TypedConfigBuilder[String] = {
new TypedConfigBuilder(this, v => v)
}
def timeConf(unit: TimeUnit): TypedConfigBuilder[Long] = {
new TypedConfigBuilder(this, timeFromString(_, unit), timeToString(_, unit))
}
def bytesConf(unit: ByteUnit): TypedConfigBuilder[Long] = {
new TypedConfigBuilder(this, byteFromString(_, unit), byteToString(_, unit))
}
def fallbackConf[T](fallback: ConfigEntry[T]): ConfigEntry[T] = {
val entry = new FallbackConfigEntry(key, _alternatives, _doc, _public, fallback)
_onCreate.foreach(_(entry))
entry
}
def regexConf: TypedConfigBuilder[Regex] = {
new TypedConfigBuilder(this, regexFromString(_, this.key), _.toString)
}
TypedConfigBuilder class
这个类的目的是进行统一的类型转化,包括类型和范围的校验(通过函数的嵌套调用),通过其自己的方法(createWithDefault、createWithDefaultFunction、createWithDefaultString)转化为所需的ConfigEntry的子类。
其有3个属性:
1.parent: ConfigBuilder,
2.converter: String => T, 这个是函数类型的属性
3.stringConverter: T => String, 转String类型的函数属性
2个构造方法,
class TypedConfigBuilder[T](
val parent: ConfigBuilder,
val converter: String => T,
val stringConverter: T => String){
def this(parent: ConfigBuilder, converter: String => T) = {
this(parent, converter, Option(_).map(_.toString).orNull)
}
//注意这个方法,是对函数进行递归调用,形成函数作用链,
//最主要的作用在于用户自定义的参数检查
def transform(fn: T => T): TypedConfigBuilder[T] = {
new TypedConfigBuilder(parent, s => fn(converter(s)), stringConverter)
}
// 注意内部调用了 transform 函数
def checkValue(validator: T => Boolean, errorMsg: String): TypedConfigBuilder[T] = {
transform { v =>
if (!validator(v)) throw new IllegalArgumentException(errorMsg)
v
}
}
// 注意内部调用了 transform 函数
def checkValues(validValues: Set[T]): TypedConfigBuilder[T] = {
transform { v =>
if (!validValues.contains(v)) {
throw new IllegalArgumentException(
s"The value of ${parent.key} should be one of ${validValues.mkString(", ")}, but was $v")
}
v
}
}
//这个方法是使用频率最高的,当传进来的值是String类型的时候,走的是 if 这个分支,程序跳转到createWithDefaultString这个函数去了
def createWithDefault(default: T): ConfigEntry[T] = {
// Treat "String" as a special case, so that both createWithDefault and createWithDefaultString
// behave the same w.r.t. variable expansion of default values.
if (default.isInstanceOf[String]) {
createWithDefaultString(default.asInstanceOf[String])
} else {
val transformedDefault = converter(stringConverter(default))
val entry = new ConfigEntryWithDefault[T](parent.key, parent._alternatives,
transformedDefault, converter, stringConverter, parent._doc, parent._public)
parent._onCreate.foreach(_(entry))
entry
}
}
//这里的parent是 ConfigBuilder
def createWithDefaultString(default: String): ConfigEntry[T] = {
val entry = new ConfigEntryWithDefaultString[T](parent.key, parent._alternatives, default,
converter, stringConverter, parent._doc, parent._public)
// 调用 注册的回调函数,
//这个函数是**SQLConf**的buildStaticConf方法中的匿名函数,
//这个匿名函数的主要 是把这个entry 注册到 **SQLConf**有HashMap类型的
//sqlConfEntries和Set类型的staticConfKeys 中去。
parent._onCreate.foreach(_(entry))
entry
}
}
ConfigEntry abstract class
ConfigEntry 是一个抽象类,有
1.key:String
2.alternatives: List[String]
3.valueConverter: String => T 注意这个是函数类型
4.stringConverter: T => String 注意这个是函数类型
5.doc: String,isPublic: Boolean
这5个属性;
1.ConfigEntryWithDefault 默认值Entry
2.ConfigEntryWithDefaultFunction 默认函数Entry
3.ConfigEntryWithDefaultString 默认String类型值Entry
4.OptionalConfigEntry
5.FallbackConfigEntry
5 个非抽象子类。
并且有伴生对象object ConfigEntry,这个伴生对象的主要作用在于,其内部有一个ConcurrentHashMap[String, ConfigEntry[]],用来缓存ConfigEntry,用ConfigEntry.key 做键,用ConfigEntry对象做值;所以里面有 ConfigEntry 的注册和find 方法(def registerEntry(entry: ConfigEntry[]): Unit,def findEntry(key: String): ConfigEntry[_])
看这个类的构造方法里面会通过其伴生对象来注册自己的实例。
这个类主要通过TypedConfigBuilder 类的方法 配合生成对象