Add subsystem support
This commit is contained in:
parent
8913f5a678
commit
60ce99305b
2 changed files with 199 additions and 0 deletions
|
@ -20,6 +20,7 @@
|
||||||
package de.staropensource.engine.base
|
package de.staropensource.engine.base
|
||||||
|
|
||||||
import de.staropensource.engine.base.exception.EngineInitializationFailureException
|
import de.staropensource.engine.base.exception.EngineInitializationFailureException
|
||||||
|
import de.staropensource.engine.base.implementable.Subsystem
|
||||||
import de.staropensource.engine.base.logging.Logger
|
import de.staropensource.engine.base.logging.Logger
|
||||||
import de.staropensource.engine.base.utility.Environment
|
import de.staropensource.engine.base.utility.Environment
|
||||||
import de.staropensource.engine.base.utility.FileAccess
|
import de.staropensource.engine.base.utility.FileAccess
|
||||||
|
@ -70,6 +71,14 @@ class Engine private constructor() {
|
||||||
*/
|
*/
|
||||||
var bootstrapping: Boolean? = null
|
var bootstrapping: Boolean? = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains a set of all registered [Subsystem]s.
|
||||||
|
*
|
||||||
|
* @see Subsystem
|
||||||
|
* @since v1-alpha10
|
||||||
|
*/
|
||||||
|
private val subsystems: MutableSet<Subsystem> = mutableSetOf()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains a [BuildInformation] instance
|
* Contains a [BuildInformation] instance
|
||||||
* providing information about the running
|
* providing information about the running
|
||||||
|
@ -81,6 +90,51 @@ class Engine private constructor() {
|
||||||
var info: BuildInformation? = null
|
var info: BuildInformation? = null
|
||||||
|
|
||||||
|
|
||||||
|
// -----> Subsystems
|
||||||
|
/**
|
||||||
|
* Returns an array of
|
||||||
|
* registered [Subsystem]s.
|
||||||
|
*
|
||||||
|
* @return array of registered [Subsystem]s
|
||||||
|
* @since v1-alpha10
|
||||||
|
*/
|
||||||
|
fun getSubsystems(): Array<Subsystem> = subsystems.toTypedArray()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers the specified subsystem.
|
||||||
|
*
|
||||||
|
* Does not work if the engine is
|
||||||
|
* initializing, shutting down,
|
||||||
|
* has already shut down for good
|
||||||
|
* or crashed fatally.
|
||||||
|
*
|
||||||
|
* @param subsystem [Subsystem] to register
|
||||||
|
* @see Subsystem
|
||||||
|
* @since v1-alpha10
|
||||||
|
*/
|
||||||
|
fun registerSubsystem(subsystem: Subsystem) {
|
||||||
|
// Check for state
|
||||||
|
if (bootstrapping == true)
|
||||||
|
return
|
||||||
|
when (state) {
|
||||||
|
State.INITIALIZING, State.SHUTTING_DOWN, State.SHUT_DOWN_FINAL, State.CRASHED -> return
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
|
||||||
|
subsystems.add(subsystem)
|
||||||
|
|
||||||
|
when (state) {
|
||||||
|
State.UNINITIALIZED -> {}
|
||||||
|
State.INITIALIZED -> {
|
||||||
|
subsystem.bootstrap()
|
||||||
|
subsystem.initialize()
|
||||||
|
}
|
||||||
|
State.SHUT_DOWN -> subsystem.bootstrap()
|
||||||
|
else -> logger.crash("Engine changed state during subsystem registration")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// -----> Lifecycle
|
// -----> Lifecycle
|
||||||
/**
|
/**
|
||||||
* Bootstraps the engine.
|
* Bootstraps the engine.
|
||||||
|
@ -107,6 +161,20 @@ class Engine private constructor() {
|
||||||
// Run bootstrapping code
|
// Run bootstrapping code
|
||||||
// *none yet*
|
// *none yet*
|
||||||
|
|
||||||
|
// Bootstrap subsystems
|
||||||
|
logger.verb("Bootstrapping subsystems")
|
||||||
|
for (subsystem: Subsystem in subsystems)
|
||||||
|
try {
|
||||||
|
logger.diag("Bootstrapping subsystem '${subsystem.getName()}' [${subsystem::class.qualifiedName ?: "<anonymous>"}]")
|
||||||
|
subsystem.bootstrap()
|
||||||
|
} catch (throwable: Throwable) {
|
||||||
|
logger.crash(
|
||||||
|
"Failed to bootstrap subsystem '${subsystem.getName()}' [${subsystem::class.qualifiedName ?: "<anonymous>"}]",
|
||||||
|
throwable = throwable,
|
||||||
|
fatal = true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
bootstrapping = false
|
bootstrapping = false
|
||||||
return true
|
return true
|
||||||
} catch (exception: Exception) {
|
} catch (exception: Exception) {
|
||||||
|
@ -150,6 +218,20 @@ class Engine private constructor() {
|
||||||
FileAccess.updateDefaultPaths()
|
FileAccess.updateDefaultPaths()
|
||||||
info = BuildInformation(loadPrefix = "sosengine-base")
|
info = BuildInformation(loadPrefix = "sosengine-base")
|
||||||
|
|
||||||
|
// Initialize subsystems
|
||||||
|
logger.verb("Initializing subsystems")
|
||||||
|
for (subsystem: Subsystem in subsystems)
|
||||||
|
try {
|
||||||
|
logger.diag("Initializing subsystem '${subsystem.getName()}' [${subsystem::class.qualifiedName ?: "<anonymous>"}]")
|
||||||
|
subsystem.initialize()
|
||||||
|
} catch (throwable: Throwable) {
|
||||||
|
logger.crash(
|
||||||
|
"Failed to initialize subsystem '${subsystem.getName()}' [${subsystem::class.qualifiedName ?: "<anonymous>"}]",
|
||||||
|
throwable = throwable,
|
||||||
|
fatal = true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
state = State.INITIALIZED
|
state = State.INITIALIZED
|
||||||
|
|
||||||
// Print initialization message
|
// Print initialization message
|
||||||
|
@ -300,6 +382,20 @@ class Engine private constructor() {
|
||||||
FileAccess.unsetDefaultPaths()
|
FileAccess.unsetDefaultPaths()
|
||||||
info = null
|
info = null
|
||||||
|
|
||||||
|
// Initialize subsystems
|
||||||
|
logger.verb("Shutting subsystems down")
|
||||||
|
for (subsystem: Subsystem in subsystems)
|
||||||
|
try {
|
||||||
|
logger.diag("Shutting subsystem '${subsystem.getName()}' [${subsystem::class.qualifiedName ?: "<anonymous>"}] down")
|
||||||
|
subsystem.shutdown(final = final, fatalCrash = crashed)
|
||||||
|
} catch (throwable: Throwable) {
|
||||||
|
logger.crash(
|
||||||
|
"Failed to shutdown subsystem '${subsystem.getName()}' [${subsystem::class.qualifiedName ?: "<anonymous>"}]",
|
||||||
|
throwable = throwable,
|
||||||
|
fatal = true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// Print shutdown message
|
// Print shutdown message
|
||||||
if (final)
|
if (final)
|
||||||
logger.info("""
|
logger.info("""
|
||||||
|
|
|
@ -0,0 +1,103 @@
|
||||||
|
/*
|
||||||
|
* STAROPENSOURCE ENGINE SOURCE FILE
|
||||||
|
* Copyright (c) 2024 The StarOpenSource Engine Authors
|
||||||
|
* Licensed under the GNU General Public License v3.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.staropensource.engine.base.implementable
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides an API for the engine to talk to subsystems.
|
||||||
|
*
|
||||||
|
* @since v1-alpha10
|
||||||
|
*/
|
||||||
|
abstract class Subsystem {
|
||||||
|
/**
|
||||||
|
* Returns the name of this subsystem.
|
||||||
|
*
|
||||||
|
* @return name
|
||||||
|
* @since v1-alpha10
|
||||||
|
*/
|
||||||
|
abstract fun getName(): String
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the version of this subsystem.
|
||||||
|
*
|
||||||
|
* Not called by the engine
|
||||||
|
* before [bootstrap].
|
||||||
|
*
|
||||||
|
* @return version
|
||||||
|
* @since v1-alpha10
|
||||||
|
*/
|
||||||
|
abstract fun getVersion(): String
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bootstraps this subsystem.
|
||||||
|
*
|
||||||
|
* Invoked during the engine's bootstrapping
|
||||||
|
* phase or after this subsystem has been
|
||||||
|
* registered, if registered after the
|
||||||
|
* engine has already bootstrapped itself.
|
||||||
|
*
|
||||||
|
* Always run before [initialize].
|
||||||
|
*
|
||||||
|
* @throws Throwable on error
|
||||||
|
* @since v1-alpha10
|
||||||
|
*/
|
||||||
|
@Throws(Throwable::class)
|
||||||
|
open fun bootstrap() = Unit
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes this subsystem.
|
||||||
|
*
|
||||||
|
* Invoked during the engine's initialization
|
||||||
|
* phase or after this subsystem has been
|
||||||
|
* registered, if registered after the engine
|
||||||
|
* has already initialized itself.
|
||||||
|
*
|
||||||
|
* @throws Throwable on error
|
||||||
|
* @since v1-alpha10
|
||||||
|
*/
|
||||||
|
@Throws(Throwable::class)
|
||||||
|
open fun initialize() = Unit
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reloads this subsystem's configuration
|
||||||
|
* and data.
|
||||||
|
*
|
||||||
|
* Invoked during the engine's reloading phase.
|
||||||
|
*
|
||||||
|
* @throws Throwable on error
|
||||||
|
* @since v1-alpha10
|
||||||
|
*/
|
||||||
|
@Throws(Throwable::class)
|
||||||
|
open fun reload() = Unit
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shuts this subsystem down.
|
||||||
|
*
|
||||||
|
* Invoked during the engine shutdown phase.
|
||||||
|
* The supplied booleans indicate which
|
||||||
|
* shutdown method was used.
|
||||||
|
*
|
||||||
|
* @param final indicates if the engine will shutdown for good
|
||||||
|
* @param fatalCrash indicates if the engine crashed fatally
|
||||||
|
* @throws Throwable on error
|
||||||
|
* @since v1-alpha10
|
||||||
|
*/
|
||||||
|
@Throws(Throwable::class)
|
||||||
|
open fun shutdown(final: Boolean, fatalCrash: Boolean) = Unit
|
||||||
|
}
|
Loading…
Reference in a new issue