@@ -68,6 +68,7 @@ class SparkConf(loadDefaults: Boolean) extends Cloneable with Logging {
68
68
if (value == null ) {
69
69
throw new NullPointerException (" null value for " + key)
70
70
}
71
+ logDeprecationWarning(key)
71
72
settings.put(key, value)
72
73
this
73
74
}
@@ -134,13 +135,15 @@ class SparkConf(loadDefaults: Boolean) extends Cloneable with Logging {
134
135
135
136
/** Set multiple parameters together */
136
137
def setAll (settings : Traversable [(String , String )]): SparkConf = {
137
- this . settings.putAll(settings.toMap.asJava)
138
+ settings.foreach { case (k, v) => set(k, v) }
138
139
this
139
140
}
140
141
141
142
/** Set a parameter if it isn't already configured */
142
143
def setIfMissing (key : String , value : String ): SparkConf = {
143
- settings.putIfAbsent(key, value)
144
+ if (settings.putIfAbsent(key, value) == null ) {
145
+ logDeprecationWarning(key)
146
+ }
144
147
this
145
148
}
146
149
@@ -174,45 +177,44 @@ class SparkConf(loadDefaults: Boolean) extends Cloneable with Logging {
174
177
getOption(key).getOrElse(defaultValue)
175
178
}
176
179
177
- /**
178
- * Get a time parameter as seconds; throws a NoSuchElementException if it's not set. If no
180
+ /**
181
+ * Get a time parameter as seconds; throws a NoSuchElementException if it's not set. If no
179
182
* suffix is provided then seconds are assumed.
180
183
* @throws NoSuchElementException
181
184
*/
182
185
def getTimeAsSeconds (key : String ): Long = {
183
186
Utils .timeStringAsSeconds(get(key))
184
187
}
185
188
186
- /**
187
- * Get a time parameter as seconds, falling back to a default if not set. If no
189
+ /**
190
+ * Get a time parameter as seconds, falling back to a default if not set. If no
188
191
* suffix is provided then seconds are assumed.
189
- *
190
192
*/
191
193
def getTimeAsSeconds (key : String , defaultValue : String ): Long = {
192
194
Utils .timeStringAsSeconds(get(key, defaultValue))
193
195
}
194
196
195
- /**
196
- * Get a time parameter as milliseconds; throws a NoSuchElementException if it's not set. If no
197
- * suffix is provided then milliseconds are assumed.
197
+ /**
198
+ * Get a time parameter as milliseconds; throws a NoSuchElementException if it's not set. If no
199
+ * suffix is provided then milliseconds are assumed.
198
200
* @throws NoSuchElementException
199
201
*/
200
202
def getTimeAsMs (key : String ): Long = {
201
203
Utils .timeStringAsMs(get(key))
202
204
}
203
205
204
- /**
205
- * Get a time parameter as milliseconds, falling back to a default if not set. If no
206
- * suffix is provided then milliseconds are assumed.
206
+ /**
207
+ * Get a time parameter as milliseconds, falling back to a default if not set. If no
208
+ * suffix is provided then milliseconds are assumed.
207
209
*/
208
210
def getTimeAsMs (key : String , defaultValue : String ): Long = {
209
211
Utils .timeStringAsMs(get(key, defaultValue))
210
212
}
211
-
213
+
212
214
213
215
/** Get a parameter as an Option */
214
216
def getOption (key : String ): Option [String ] = {
215
- Option (settings.get(key))
217
+ Option (settings.get(key)).orElse(getDeprecatedConfig(key, this ))
216
218
}
217
219
218
220
/** Get all parameters as a list of pairs */
@@ -379,13 +381,6 @@ class SparkConf(loadDefaults: Boolean) extends Cloneable with Logging {
379
381
}
380
382
}
381
383
}
382
-
383
- // Warn against the use of deprecated configs
384
- deprecatedConfigs.values.foreach { dc =>
385
- if (contains(dc.oldName)) {
386
- dc.warn()
387
- }
388
- }
389
384
}
390
385
391
386
/**
@@ -400,19 +395,44 @@ class SparkConf(loadDefaults: Boolean) extends Cloneable with Logging {
400
395
401
396
private [spark] object SparkConf extends Logging {
402
397
398
+ /**
399
+ * Maps deprecated config keys to information about the deprecation.
400
+ *
401
+ * The extra information is logged as a warning when the config is present in the user's
402
+ * configuration.
403
+ */
403
404
private val deprecatedConfigs : Map [String , DeprecatedConfig ] = {
404
405
val configs = Seq (
405
- DeprecatedConfig (" spark.files.userClassPathFirst" , " spark.executor.userClassPathFirst" ,
406
- " 1.3" ),
407
- DeprecatedConfig (" spark.yarn.user.classpath.first" , null , " 1.3" ,
408
- " Use spark.{driver,executor}.userClassPathFirst instead." ),
409
- DeprecatedConfig (" spark.history.fs.updateInterval" ,
410
- " spark.history.fs.update.interval.seconds" ,
411
- " 1.3" , " Use spark.history.fs.update.interval.seconds instead" ),
412
- DeprecatedConfig (" spark.history.updateInterval" ,
413
- " spark.history.fs.update.interval.seconds" ,
414
- " 1.3" , " Use spark.history.fs.update.interval.seconds instead" ))
415
- configs.map { x => (x.oldName, x) }.toMap
406
+ DeprecatedConfig (" spark.yarn.user.classpath.first" , " 1.3" ,
407
+ " Please use spark.{driver,executor}.userClassPathFirst instead." ))
408
+ Map (configs.map { cfg => (cfg.key -> cfg) }:_* )
409
+ }
410
+
411
+ /**
412
+ * Maps a current config key to alternate keys that were used in previous version of Spark.
413
+ *
414
+ * The alternates are used in the order defined in this map. If deprecated configs are
415
+ * present in the user's configuration, a warning is logged.
416
+ */
417
+ private val configsWithAlternatives = Map [String , Seq [AlternateConfig ]](
418
+ " spark.executor.userClassPathFirst" -> Seq (
419
+ AlternateConfig (" spark.files.userClassPathFirst" , " 1.3" )),
420
+ " spark.history.fs.update.interval" -> Seq (
421
+ AlternateConfig (" spark.history.fs.update.interval.seconds" , " 1.4" ),
422
+ AlternateConfig (" spark.history.fs.updateInterval" , " 1.3" ),
423
+ AlternateConfig (" spark.history.updateInterval" , " 1.3" ))
424
+ )
425
+
426
+ /**
427
+ * A view of `configsWithAlternatives` that makes it more efficient to look up deprecated
428
+ * config keys.
429
+ *
430
+ * Maps the deprecated config name to a 2-tuple (new config name, alternate config info).
431
+ */
432
+ private val allAlternatives : Map [String , (String , AlternateConfig )] = {
433
+ configsWithAlternatives.keys.flatMap { key =>
434
+ configsWithAlternatives(key).map { cfg => (cfg.key -> (key -> cfg)) }
435
+ }.toMap
416
436
}
417
437
418
438
/**
@@ -443,61 +463,57 @@ private[spark] object SparkConf extends Logging {
443
463
}
444
464
445
465
/**
446
- * Translate the configuration key if it is deprecated and has a replacement, otherwise just
447
- * returns the provided key.
448
- *
449
- * @param userKey Configuration key from the user / caller.
450
- * @param warn Whether to print a warning if the key is deprecated. Warnings will be printed
451
- * only once for each key.
466
+ * Looks for available deprecated keys for the given config option, and return the first
467
+ * value available.
452
468
*/
453
- private def translateConfKey (userKey : String , warn : Boolean = false ): String = {
454
- deprecatedConfigs.get(userKey)
455
- .map { deprecatedKey =>
456
- if (warn) {
457
- deprecatedKey.warn()
458
- }
459
- deprecatedKey.newName.getOrElse(userKey)
460
- }.getOrElse(userKey)
469
+ def getDeprecatedConfig (key : String , conf : SparkConf ): Option [String ] = {
470
+ configsWithAlternatives.get(key).flatMap { alts =>
471
+ alts.collectFirst { case alt if conf.contains(alt.key) =>
472
+ val value = conf.get(alt.key)
473
+ alt.translation.map(_(value)).getOrElse(value)
474
+ }
475
+ }
461
476
}
462
477
463
478
/**
464
- * Holds information about keys that have been deprecated or renamed.
479
+ * Logs a warning message if the given config key is deprecated.
480
+ */
481
+ def logDeprecationWarning (key : String ): Unit = {
482
+ deprecatedConfigs.get(key).foreach { cfg =>
483
+ logWarning(
484
+ s " The configuration key ' $key' has been deprecated as of Spark ${cfg.version} and " +
485
+ s " may be removed in the future. ${cfg.deprecationMessage}" )
486
+ }
487
+
488
+ allAlternatives.get(key).foreach { case (newKey, cfg) =>
489
+ logWarning(
490
+ s " The configuration key ' $key' has been deprecated as of Spark ${cfg.version} and " +
491
+ s " and may be removed in the future. Please use the new key ' $newKey' instead. " )
492
+ }
493
+ }
494
+
495
+ /**
496
+ * Holds information about keys that have been deprecated and do not have a replacement.
465
497
*
466
- * @param oldName Old configuration key.
467
- * @param newName New configuration key, or `null` if key has no replacement, in which case the
468
- * deprecated key will be used (but the warning message will still be printed).
498
+ * @param key The deprecated key.
469
499
* @param version Version of Spark where key was deprecated.
470
- * @param deprecationMessage Message to include in the deprecation warning; mandatory when
471
- * `newName` is not provided.
500
+ * @param deprecationMessage Message to include in the deprecation warning.
472
501
*/
473
502
private case class DeprecatedConfig (
474
- oldName : String ,
475
- _newName : String ,
503
+ key : String ,
476
504
version : String ,
477
- deprecationMessage : String = null ) {
478
-
479
- private val warned = new AtomicBoolean (false )
480
- val newName = Option (_newName)
505
+ deprecationMessage : String )
481
506
482
- if (newName == null && (deprecationMessage == null || deprecationMessage.isEmpty())) {
483
- throw new IllegalArgumentException (" Need new config name or deprecation message." )
484
- }
485
-
486
- def warn (): Unit = {
487
- if (warned.compareAndSet(false , true )) {
488
- if (newName != null ) {
489
- val message = Option (deprecationMessage).getOrElse(
490
- s " Please use the alternative ' $newName' instead. " )
491
- logWarning(
492
- s " The configuration option ' $oldName' has been replaced as of Spark $version and " +
493
- s " may be removed in the future. $message" )
494
- } else {
495
- logWarning(
496
- s " The configuration option ' $oldName' has been deprecated as of Spark $version and " +
497
- s " may be removed in the future. $deprecationMessage" )
498
- }
499
- }
500
- }
507
+ /**
508
+ * Information about an alternate configuration key that has been deprecated.
509
+ *
510
+ * @param key The deprecated config key.
511
+ * @param version The Spark version in which the key was deprecated.
512
+ * @param translation A translation function for converting old config values into new ones.
513
+ */
514
+ private case class AlternateConfig (
515
+ key : String ,
516
+ version : String ,
517
+ translation : Option [String => String ] = None )
501
518
502
- }
503
519
}
0 commit comments