@@ -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,16 @@ 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 = {
138
+ settings.foreach { case (k, v) => logDeprecationWarning(k) }
137
139
this .settings.putAll(settings.toMap.asJava)
138
140
this
139
141
}
140
142
141
143
/** Set a parameter if it isn't already configured */
142
144
def setIfMissing (key : String , value : String ): SparkConf = {
143
- settings.putIfAbsent(key, value)
145
+ if (settings.putIfAbsent(key, value) == null ) {
146
+ logDeprecationWarning(key)
147
+ }
144
148
this
145
149
}
146
150
@@ -174,45 +178,45 @@ class SparkConf(loadDefaults: Boolean) extends Cloneable with Logging {
174
178
getOption(key).getOrElse(defaultValue)
175
179
}
176
180
177
- /**
178
- * Get a time parameter as seconds; throws a NoSuchElementException if it's not set. If no
181
+ /**
182
+ * Get a time parameter as seconds; throws a NoSuchElementException if it's not set. If no
179
183
* suffix is provided then seconds are assumed.
180
184
* @throws NoSuchElementException
181
185
*/
182
186
def getTimeAsSeconds (key : String ): Long = {
183
187
Utils .timeStringAsSeconds(get(key))
184
188
}
185
189
186
- /**
187
- * Get a time parameter as seconds, falling back to a default if not set. If no
190
+ /**
191
+ * Get a time parameter as seconds, falling back to a default if not set. If no
188
192
* suffix is provided then seconds are assumed.
189
- *
193
+ *
190
194
*/
191
195
def getTimeAsSeconds (key : String , defaultValue : String ): Long = {
192
196
Utils .timeStringAsSeconds(get(key, defaultValue))
193
197
}
194
198
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.
199
+ /**
200
+ * Get a time parameter as milliseconds; throws a NoSuchElementException if it's not set. If no
201
+ * suffix is provided then milliseconds are assumed.
198
202
* @throws NoSuchElementException
199
203
*/
200
204
def getTimeAsMs (key : String ): Long = {
201
205
Utils .timeStringAsMs(get(key))
202
206
}
203
207
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.
208
+ /**
209
+ * Get a time parameter as milliseconds, falling back to a default if not set. If no
210
+ * suffix is provided then milliseconds are assumed.
207
211
*/
208
212
def getTimeAsMs (key : String , defaultValue : String ): Long = {
209
213
Utils .timeStringAsMs(get(key, defaultValue))
210
214
}
211
-
215
+
212
216
213
217
/** Get a parameter as an Option */
214
218
def getOption (key : String ): Option [String ] = {
215
- Option (settings.get(key))
219
+ Option (settings.get(key)).orElse(getDeprecatedConfig(key, this ))
216
220
}
217
221
218
222
/** Get all parameters as a list of pairs */
@@ -379,13 +383,6 @@ class SparkConf(loadDefaults: Boolean) extends Cloneable with Logging {
379
383
}
380
384
}
381
385
}
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
386
}
390
387
391
388
/**
@@ -400,19 +397,39 @@ class SparkConf(loadDefaults: Boolean) extends Cloneable with Logging {
400
397
401
398
private [spark] object SparkConf extends Logging {
402
399
403
- private val deprecatedConfigs : Map [String , DeprecatedConfig ] = {
404
- 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
400
+ /**
401
+ * Maps deprecated config keys to information about the deprecation.
402
+ *
403
+ * The extra information is logged as a warning when the config is present in the user's
404
+ * configuration.
405
+ */
406
+ private val deprecatedConfigs = Map [String , DeprecatedConfig ](
407
+ " spark.yarn.user.classpath.first" ->
408
+ DeprecatedConfig (" 1.3" , " Use spark.{driver,executor}.userClassPathFirst instead." )
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.seconds" -> Seq (
421
+ AlternateConfig (" spark.history.fs.updateInterval" , " 1.3" ),
422
+ AlternateConfig (" spark.history.updateInterval" , " 1.3" ))
423
+ )
424
+
425
+ /**
426
+ * A view of `configsWithAlternatives` that makes it more efficient to look up deprecated
427
+ * config keys.
428
+ */
429
+ private val allAlternatives : Map [String , (String , AlternateConfig )] = {
430
+ configsWithAlternatives.keys.flatMap { key =>
431
+ configsWithAlternatives(key).map { cfg => (cfg.key -> (key -> cfg)) }
432
+ }.toMap
416
433
}
417
434
418
435
/**
@@ -443,61 +460,55 @@ private[spark] object SparkConf extends Logging {
443
460
}
444
461
445
462
/**
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.
463
+ * Looks for available deprecated keys for the given config option, and return the first
464
+ * value available.
452
465
*/
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)
466
+ def getDeprecatedConfig (key : String , conf : SparkConf ): Option [String ] = {
467
+ configsWithAlternatives.get(key).flatMap(
468
+ _.collectFirst {
469
+ case x if conf.contains(x.key) =>
470
+ val value = conf.get(x.key)
471
+ x.translation.map(_(value)).getOrElse(value)
472
+ })
473
+ }
474
+
475
+ /**
476
+ * Logs a warning message if the given config key is deprecated.
477
+ */
478
+ def logDeprecationWarning (key : String ): Unit = {
479
+ deprecatedConfigs.get(key).foreach { cfg =>
480
+ logWarning(
481
+ s " The configuration option ' $key' has been deprecated as of Spark ${cfg.version} and " +
482
+ s " may be removed in the future. ${cfg.deprecationMessage}" )
483
+ }
484
+
485
+ allAlternatives.get(key).foreach { case (newKey, cfg) =>
486
+ logWarning(
487
+ s " The configuration option ' $key' has been replaced as of Spark ${cfg.version} " +
488
+ s " and may be removed in the future. Please use the new config ' $newKey' instead. " )
489
+ }
461
490
}
462
491
463
492
/**
464
- * Holds information about keys that have been deprecated or renamed .
493
+ * Holds information about keys that have been deprecated and do not have a replacement .
465
494
*
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).
469
495
* @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.
496
+ * @param deprecationMessage Message to include in the deprecation warning.
472
497
*/
473
498
private case class DeprecatedConfig (
474
- oldName : String ,
475
- _newName : String ,
476
499
version : String ,
477
- deprecationMessage : String = null ) {
478
-
479
- private val warned = new AtomicBoolean (false )
480
- val newName = Option (_newName)
481
-
482
- if (newName == null && (deprecationMessage == null || deprecationMessage.isEmpty())) {
483
- throw new IllegalArgumentException (" Need new config name or deprecation message." )
484
- }
500
+ deprecationMessage : String = null )
485
501
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
- }
502
+ /**
503
+ * Information about an alternate configuration key that has been deprecated.
504
+ *
505
+ * @param key The deprecated config key.
506
+ * @param version The Spark version in which the key was deprecated.
507
+ * @param translation A translation function for converting old config values into new ones.
508
+ */
509
+ private case class AlternateConfig (
510
+ key : String ,
511
+ version : String ,
512
+ translation : Option [String => String ] = None )
501
513
502
- }
503
514
}
0 commit comments