Add subsystem support
Some checks failed
PRs & Pushes / build (push) Failing after 1m57s
PRs & Pushes / test (push) Failing after 2m3s
PRs & Pushes / build-apidoc (push) Successful in 2m25s

This commit is contained in:
JeremyStar™ 2024-12-20 01:38:41 +01:00
parent 8913f5a678
commit 60ce99305b
Signed by: JeremyStarTM
GPG key ID: E366BAEF67E4704D
2 changed files with 199 additions and 0 deletions

View file

@ -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("""

View file

@ -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
}