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
|
||||
|
||||
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.utility.Environment
|
||||
import de.staropensource.engine.base.utility.FileAccess
|
||||
|
@ -70,6 +71,14 @@ class Engine private constructor() {
|
|||
*/
|
||||
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
|
||||
* providing information about the running
|
||||
|
@ -81,6 +90,51 @@ class Engine private constructor() {
|
|||
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
|
||||
/**
|
||||
* Bootstraps the engine.
|
||||
|
@ -107,6 +161,20 @@ class Engine private constructor() {
|
|||
// Run bootstrapping code
|
||||
// *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
|
||||
return true
|
||||
} catch (exception: Exception) {
|
||||
|
@ -150,6 +218,20 @@ class Engine private constructor() {
|
|||
FileAccess.updateDefaultPaths()
|
||||
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
|
||||
|
||||
// Print initialization message
|
||||
|
@ -300,6 +382,20 @@ class Engine private constructor() {
|
|||
FileAccess.unsetDefaultPaths()
|
||||
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
|
||||
if (final)
|
||||
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