-
Notifications
You must be signed in to change notification settings - Fork 5.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Gradle] Introduce KotlinBuildStatsServicesRegistry to manage FUS ser…
…vices KT-57371 introduced a legacy JMX service without proper management. #KT-62318 Fixed (cherry picked from commit afdd846)
- Loading branch information
1 parent
74c0b1a
commit a438a00
Showing
6 changed files
with
151 additions
and
88 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
103 changes: 103 additions & 0 deletions
103
.../kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/KotlinBuildStatsServicesRegistry.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
/* | ||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. | ||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. | ||
*/ | ||
|
||
package org.jetbrains.kotlin.gradle.plugin.statistics | ||
|
||
import org.gradle.api.Project | ||
import org.gradle.api.logging.Logging | ||
import org.jetbrains.kotlin.gradle.plugin.statistics.old.Pre232IdeaKotlinBuildStatsMXBean | ||
import org.jetbrains.kotlin.gradle.plugin.statistics.old.Pre232IdeaKotlinBuildStatsService | ||
import java.io.Closeable | ||
import java.lang.management.ManagementFactory | ||
import javax.management.MBeanServer | ||
import javax.management.ObjectName | ||
import javax.management.StandardMBean | ||
|
||
/** | ||
* A registry of Kotlin FUS services scoped to a project. | ||
* In general, we use only one instance of a service either it is a real service or a JMX wrapper. | ||
* However, we also register legacy variants of the services so previous IDEA versions could access them. | ||
* We must properly manage the lifecycle of such services. | ||
* | ||
* The implementation is not thread-safe! | ||
*/ | ||
internal class KotlinBuildStatsServicesRegistry : Closeable { | ||
internal val logger = Logging.getLogger(this::class.java) | ||
private val services = hashMapOf<String, KotlinBuildStatsService>() | ||
|
||
/** | ||
* Registers the Kotlin build stats services for the given project. | ||
* | ||
* After a call of that method, [getDefaultService] is expected to return a non-null value. | ||
* | ||
* The registry must be closed at the end of the usage. | ||
*/ | ||
fun registerServices(project: Project) { | ||
val defaultBeanName = getBeanName(DEFAULT_SERVICE_QUALIFIER) | ||
val mbs: MBeanServer = ManagementFactory.getPlatformMBeanServer() | ||
if (mbs.isRegistered(defaultBeanName)) { | ||
// because we use only the default service, and it's already registered in the MBean server, then there's no need in caring of legacy services as they're already registered | ||
logger.debug("${KotlinBuildStatsService::class.simpleName} $defaultBeanName is already instantiated in another classpath. Creating JMX wrapper for the main service") | ||
services[DEFAULT_SERVICE_QUALIFIER] = JMXKotlinBuildStatsService(mbs, defaultBeanName) | ||
} else { | ||
registerStatsService( | ||
mbs, | ||
DefaultKotlinBuildStatsService(project, getBeanName(DEFAULT_SERVICE_QUALIFIER)), | ||
KotlinBuildStatsMXBean::class.java, | ||
DEFAULT_SERVICE_QUALIFIER | ||
) | ||
// to support backward compatibility with Idea before version 232 | ||
registerStatsService( | ||
mbs, | ||
Pre232IdeaKotlinBuildStatsService(project, getBeanName(LEGACY_SERVICE_QUALIFIER)), | ||
Pre232IdeaKotlinBuildStatsMXBean::class.java, | ||
LEGACY_SERVICE_QUALIFIER | ||
) | ||
} | ||
} | ||
|
||
private fun <T : KotlinBuildStatsService> registerStatsService( | ||
mbs: MBeanServer, | ||
service: T, | ||
beanInterfaceType: Class<in T>, | ||
qualifier: String, | ||
) { | ||
val beanName = getBeanName(qualifier) | ||
if (!mbs.isRegistered(beanName)) { | ||
mbs.registerMBean(StandardMBean(service, beanInterfaceType), beanName) | ||
services[qualifier] = service | ||
val loggedServiceName = "${KotlinBuildStatsService::class.java}" + if (qualifier.isNotEmpty()) "_$qualifier" else "" | ||
logger.debug("Instantiated $loggedServiceName: new instance $service") | ||
} | ||
} | ||
|
||
/** | ||
* Retrieves the default Kotlin build stats service. That's the main service we are working with. | ||
*/ | ||
fun getDefaultService() = services[DEFAULT_SERVICE_QUALIFIER] | ||
|
||
/** | ||
* Unregisters all the registered JMX services and may release other resources allocated by a service. | ||
*/ | ||
override fun close() { | ||
for (service in services.values) { | ||
service.close() | ||
} | ||
services.clear() | ||
} | ||
|
||
companion object { | ||
private const val JXM_BEAN_BASE_NAME = "org.jetbrains.kotlin.gradle.plugin.statistics:type=StatsService" | ||
|
||
// Do not rename this bean otherwise compatibility with the older Kotlin Gradle Plugins would be lost | ||
private const val LEGACY_SERVICE_QUALIFIER = "" | ||
|
||
// Update name when API changed | ||
internal const val DEFAULT_SERVICE_QUALIFIER = "v2" | ||
|
||
internal fun getBeanName(qualifier: String) = | ||
ObjectName(JXM_BEAN_BASE_NAME + if (qualifier.isNotEmpty()) ",name=$qualifier" else "") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters