sig_mgmt.h

include/sig/mgmt/sig_mgmt.h

SIG_MGMT_MODULE_NAME

#define SIG_MGMT_MODULE_NAME "mgmt"

The management module: reads and controls the runtime through plain operations (below) that take and return sig_value trees and sig_status_t codes. It knows nothing of any transport or wire format; a transport (sig_mgmt_http, or anything else) maps its own framing onto these calls. Register the module with sig_runtime_register_module(rt, sig_mgmt_module(), NULL) BEFORE any module that depends on it.

sig_mgmt

typedef struct sig_mgmt sig_mgmt;

sig_mgmt_module

const sig_runtime_module * sig_mgmt_module()

sig_mgmt_from_runtime

sig_status_t sig_mgmt_from_runtime(sig_runtime * rt, sig_mgmt ** out)
ParameterType
rtsig_runtime *
outsig_mgmt **

Finds the mgmt instance created for `rt` (SIG_ERR_NOT_FOUND if the module is not registered, SIG_ERR_STATE if it is registered but not yet created).

sig_mgmt_system

sig_status_t sig_mgmt_system(sig_mgmt * m, sig_value * out)
ParameterType
msig_mgmt *
outsig_value *

---- Read operations --------------------------------------------------- Each fills *out with a map/list tree the caller releases with sig_value_dtor() on SIG_OK (*out is untouched on failure). The tree is built while the shared lock is held and owns all its memory (deep copies, no pointers into runtime state), so it stays valid after the call returns, and concurrent readers do not block one another. Lists are sorted by name. A property value is copied into the tree as it is, whatever its kind; deciding how to show kinds a transport cannot express is the transport's business. Errors: SIG_ERR_INVALID_ARG for a NULL argument; SIG_ERR_NOT_FOUND for an object that does not exist, which includes any name that could not name one (empty, over 64 characters, or containing a character other than letters, digits, '_' and '-', e.g. ".." or "/"); SIG_ERR_STATE when there is no project (runtime not running); SIG_ERR_ALLOC. Trees (field names are part of the contract; state is "running" or "stopped"): system: {version, uptime_seconds, modules: [name]} list_services: {services: [{name, state, dirty, instances}]} get_service: {name, state, dirty, instances: [{name, configuration, type, inputs: [name], outputs: [name]}], links: [{from: {instance, terminal}, to: {instance, terminal}}]} get_instance: {name, service, configuration, type, properties: {key: value}} list_capsules: {capsules: [{name, category?, inputs, outputs, properties: [{name, type, required, default?, min?, max?, choices?, description}]}]} list_configurations: {configurations: [{name, type}]} get_configuration: {name, type, config: <definition>, used_by: [service]} get_service_config: {name, config: <definition>, dirty}

sig_mgmt_list_services

sig_status_t sig_mgmt_list_services(sig_mgmt * m, sig_value * out)
ParameterType
msig_mgmt *
outsig_value *

shared with sig_mgmt_system

---- Read operations --------------------------------------------------- Each fills *out with a map/list tree the caller releases with sig_value_dtor() on SIG_OK (*out is untouched on failure). The tree is built while the shared lock is held and owns all its memory (deep copies, no pointers into runtime state), so it stays valid after the call returns, and concurrent readers do not block one another. Lists are sorted by name. A property value is copied into the tree as it is, whatever its kind; deciding how to show kinds a transport cannot express is the transport's business. Errors: SIG_ERR_INVALID_ARG for a NULL argument; SIG_ERR_NOT_FOUND for an object that does not exist, which includes any name that could not name one (empty, over 64 characters, or containing a character other than letters, digits, '_' and '-', e.g. ".." or "/"); SIG_ERR_STATE when there is no project (runtime not running); SIG_ERR_ALLOC. Trees (field names are part of the contract; state is "running" or "stopped"): system: {version, uptime_seconds, modules: [name]} list_services: {services: [{name, state, dirty, instances}]} get_service: {name, state, dirty, instances: [{name, configuration, type, inputs: [name], outputs: [name]}], links: [{from: {instance, terminal}, to: {instance, terminal}}]} get_instance: {name, service, configuration, type, properties: {key: value}} list_capsules: {capsules: [{name, category?, inputs, outputs, properties: [{name, type, required, default?, min?, max?, choices?, description}]}]} list_configurations: {configurations: [{name, type}]} get_configuration: {name, type, config: <definition>, used_by: [service]} get_service_config: {name, config: <definition>, dirty}

sig_mgmt_get_service

sig_status_t sig_mgmt_get_service(sig_mgmt * m, const char * name, sig_value * out)
ParameterType
msig_mgmt *
nameconst char *
outsig_value *

shared with sig_mgmt_system

---- Read operations --------------------------------------------------- Each fills *out with a map/list tree the caller releases with sig_value_dtor() on SIG_OK (*out is untouched on failure). The tree is built while the shared lock is held and owns all its memory (deep copies, no pointers into runtime state), so it stays valid after the call returns, and concurrent readers do not block one another. Lists are sorted by name. A property value is copied into the tree as it is, whatever its kind; deciding how to show kinds a transport cannot express is the transport's business. Errors: SIG_ERR_INVALID_ARG for a NULL argument; SIG_ERR_NOT_FOUND for an object that does not exist, which includes any name that could not name one (empty, over 64 characters, or containing a character other than letters, digits, '_' and '-', e.g. ".." or "/"); SIG_ERR_STATE when there is no project (runtime not running); SIG_ERR_ALLOC. Trees (field names are part of the contract; state is "running" or "stopped"): system: {version, uptime_seconds, modules: [name]} list_services: {services: [{name, state, dirty, instances}]} get_service: {name, state, dirty, instances: [{name, configuration, type, inputs: [name], outputs: [name]}], links: [{from: {instance, terminal}, to: {instance, terminal}}]} get_instance: {name, service, configuration, type, properties: {key: value}} list_capsules: {capsules: [{name, category?, inputs, outputs, properties: [{name, type, required, default?, min?, max?, choices?, description}]}]} list_configurations: {configurations: [{name, type}]} get_configuration: {name, type, config: <definition>, used_by: [service]} get_service_config: {name, config: <definition>, dirty}

sig_mgmt_get_instance

sig_status_t sig_mgmt_get_instance(sig_mgmt * m, const char * service, const char * instance, sig_value * out)
ParameterType
msig_mgmt *
serviceconst char *
instanceconst char *
outsig_value *

shared with sig_mgmt_system

---- Read operations --------------------------------------------------- Each fills *out with a map/list tree the caller releases with sig_value_dtor() on SIG_OK (*out is untouched on failure). The tree is built while the shared lock is held and owns all its memory (deep copies, no pointers into runtime state), so it stays valid after the call returns, and concurrent readers do not block one another. Lists are sorted by name. A property value is copied into the tree as it is, whatever its kind; deciding how to show kinds a transport cannot express is the transport's business. Errors: SIG_ERR_INVALID_ARG for a NULL argument; SIG_ERR_NOT_FOUND for an object that does not exist, which includes any name that could not name one (empty, over 64 characters, or containing a character other than letters, digits, '_' and '-', e.g. ".." or "/"); SIG_ERR_STATE when there is no project (runtime not running); SIG_ERR_ALLOC. Trees (field names are part of the contract; state is "running" or "stopped"): system: {version, uptime_seconds, modules: [name]} list_services: {services: [{name, state, dirty, instances}]} get_service: {name, state, dirty, instances: [{name, configuration, type, inputs: [name], outputs: [name]}], links: [{from: {instance, terminal}, to: {instance, terminal}}]} get_instance: {name, service, configuration, type, properties: {key: value}} list_capsules: {capsules: [{name, category?, inputs, outputs, properties: [{name, type, required, default?, min?, max?, choices?, description}]}]} list_configurations: {configurations: [{name, type}]} get_configuration: {name, type, config: <definition>, used_by: [service]} get_service_config: {name, config: <definition>, dirty}

sig_mgmt_list_capsules

sig_status_t sig_mgmt_list_capsules(sig_mgmt * m, sig_value * out)
ParameterType
msig_mgmt *
outsig_value *

shared with sig_mgmt_system

---- Read operations --------------------------------------------------- Each fills *out with a map/list tree the caller releases with sig_value_dtor() on SIG_OK (*out is untouched on failure). The tree is built while the shared lock is held and owns all its memory (deep copies, no pointers into runtime state), so it stays valid after the call returns, and concurrent readers do not block one another. Lists are sorted by name. A property value is copied into the tree as it is, whatever its kind; deciding how to show kinds a transport cannot express is the transport's business. Errors: SIG_ERR_INVALID_ARG for a NULL argument; SIG_ERR_NOT_FOUND for an object that does not exist, which includes any name that could not name one (empty, over 64 characters, or containing a character other than letters, digits, '_' and '-', e.g. ".." or "/"); SIG_ERR_STATE when there is no project (runtime not running); SIG_ERR_ALLOC. Trees (field names are part of the contract; state is "running" or "stopped"): system: {version, uptime_seconds, modules: [name]} list_services: {services: [{name, state, dirty, instances}]} get_service: {name, state, dirty, instances: [{name, configuration, type, inputs: [name], outputs: [name]}], links: [{from: {instance, terminal}, to: {instance, terminal}}]} get_instance: {name, service, configuration, type, properties: {key: value}} list_capsules: {capsules: [{name, category?, inputs, outputs, properties: [{name, type, required, default?, min?, max?, choices?, description}]}]} list_configurations: {configurations: [{name, type}]} get_configuration: {name, type, config: <definition>, used_by: [service]} get_service_config: {name, config: <definition>, dirty}

sig_mgmt_list_configurations

sig_status_t sig_mgmt_list_configurations(sig_mgmt * m, sig_value * out)
ParameterType
msig_mgmt *
outsig_value *

shared with sig_mgmt_system

---- Read operations --------------------------------------------------- Each fills *out with a map/list tree the caller releases with sig_value_dtor() on SIG_OK (*out is untouched on failure). The tree is built while the shared lock is held and owns all its memory (deep copies, no pointers into runtime state), so it stays valid after the call returns, and concurrent readers do not block one another. Lists are sorted by name. A property value is copied into the tree as it is, whatever its kind; deciding how to show kinds a transport cannot express is the transport's business. Errors: SIG_ERR_INVALID_ARG for a NULL argument; SIG_ERR_NOT_FOUND for an object that does not exist, which includes any name that could not name one (empty, over 64 characters, or containing a character other than letters, digits, '_' and '-', e.g. ".." or "/"); SIG_ERR_STATE when there is no project (runtime not running); SIG_ERR_ALLOC. Trees (field names are part of the contract; state is "running" or "stopped"): system: {version, uptime_seconds, modules: [name]} list_services: {services: [{name, state, dirty, instances}]} get_service: {name, state, dirty, instances: [{name, configuration, type, inputs: [name], outputs: [name]}], links: [{from: {instance, terminal}, to: {instance, terminal}}]} get_instance: {name, service, configuration, type, properties: {key: value}} list_capsules: {capsules: [{name, category?, inputs, outputs, properties: [{name, type, required, default?, min?, max?, choices?, description}]}]} list_configurations: {configurations: [{name, type}]} get_configuration: {name, type, config: <definition>, used_by: [service]} get_service_config: {name, config: <definition>, dirty}

sig_mgmt_get_configuration

sig_status_t sig_mgmt_get_configuration(sig_mgmt * m, const char * name, sig_value * out)
ParameterType
msig_mgmt *
nameconst char *
outsig_value *

shared with sig_mgmt_system

---- Read operations --------------------------------------------------- Each fills *out with a map/list tree the caller releases with sig_value_dtor() on SIG_OK (*out is untouched on failure). The tree is built while the shared lock is held and owns all its memory (deep copies, no pointers into runtime state), so it stays valid after the call returns, and concurrent readers do not block one another. Lists are sorted by name. A property value is copied into the tree as it is, whatever its kind; deciding how to show kinds a transport cannot express is the transport's business. Errors: SIG_ERR_INVALID_ARG for a NULL argument; SIG_ERR_NOT_FOUND for an object that does not exist, which includes any name that could not name one (empty, over 64 characters, or containing a character other than letters, digits, '_' and '-', e.g. ".." or "/"); SIG_ERR_STATE when there is no project (runtime not running); SIG_ERR_ALLOC. Trees (field names are part of the contract; state is "running" or "stopped"): system: {version, uptime_seconds, modules: [name]} list_services: {services: [{name, state, dirty, instances}]} get_service: {name, state, dirty, instances: [{name, configuration, type, inputs: [name], outputs: [name]}], links: [{from: {instance, terminal}, to: {instance, terminal}}]} get_instance: {name, service, configuration, type, properties: {key: value}} list_capsules: {capsules: [{name, category?, inputs, outputs, properties: [{name, type, required, default?, min?, max?, choices?, description}]}]} list_configurations: {configurations: [{name, type}]} get_configuration: {name, type, config: <definition>, used_by: [service]} get_service_config: {name, config: <definition>, dirty}

sig_mgmt_get_service_config

sig_status_t sig_mgmt_get_service_config(sig_mgmt * m, const char * name, sig_value * out)
ParameterType
msig_mgmt *
nameconst char *
outsig_value *

shared with sig_mgmt_system

---- Read operations --------------------------------------------------- Each fills *out with a map/list tree the caller releases with sig_value_dtor() on SIG_OK (*out is untouched on failure). The tree is built while the shared lock is held and owns all its memory (deep copies, no pointers into runtime state), so it stays valid after the call returns, and concurrent readers do not block one another. Lists are sorted by name. A property value is copied into the tree as it is, whatever its kind; deciding how to show kinds a transport cannot express is the transport's business. Errors: SIG_ERR_INVALID_ARG for a NULL argument; SIG_ERR_NOT_FOUND for an object that does not exist, which includes any name that could not name one (empty, over 64 characters, or containing a character other than letters, digits, '_' and '-', e.g. ".." or "/"); SIG_ERR_STATE when there is no project (runtime not running); SIG_ERR_ALLOC. Trees (field names are part of the contract; state is "running" or "stopped"): system: {version, uptime_seconds, modules: [name]} list_services: {services: [{name, state, dirty, instances}]} get_service: {name, state, dirty, instances: [{name, configuration, type, inputs: [name], outputs: [name]}], links: [{from: {instance, terminal}, to: {instance, terminal}}]} get_instance: {name, service, configuration, type, properties: {key: value}} list_capsules: {capsules: [{name, category?, inputs, outputs, properties: [{name, type, required, default?, min?, max?, choices?, description}]}]} list_configurations: {configurations: [{name, type}]} get_configuration: {name, type, config: <definition>, used_by: [service]} get_service_config: {name, config: <definition>, dirty}

sig_mgmt_start_service

sig_status_t sig_mgmt_start_service(sig_mgmt * m, const char * name, sig_value * out_state)
ParameterType
msig_mgmt *
nameconst char *
out_statesig_value *

---- Action and edit operations ----------------------------------------- Locking. An operation never calls another operation while holding the lock. Edit operations hold the exclusive lock only while the project is edited (they wait for in-flight readers to drain, and readers wait for them); the result tree is built afterwards from text the edit copied out, so no project pointer outlives the lock. start/stop/restart/shutdown hold none of this module's lock while the runtime runs the service's hooks, which may block for long; only the short lookup that builds `out_state` takes the shared lock, plus a short exclusive section when a stopped service has to be rebuilt from an edited definition (the old live service is freed, which no reader may be looking at). The rebuild only ever runs in that exclusive section; the hooks never do. Residual stall, inherent in sig_runtime_edit(): an edit or rebuild that waits on the runtime's control mutex behind a slow start of another service holds the exclusive lock while it waits, so reads stall until that start returns. Actions. sig_mgmt_start_service / _stop_service / _restart_service: on SIG_OK *out_state is the map {name, state} ("running" | "stopped"), owned by the caller (sig_value_dtor), untouched on failure. Stopping a stopped service is SIG_OK. They block until the service's hooks have run. Restart is not one atomic runtime call: it is a stop followed by a start, so a concurrent start can win in between (SIG_ERR_EXISTS), and if the rebuild or the start fails the service is left stopped. A start that is repeatedly overtaken by a concurrent stop or edit of the same service gives up after a few attempts with SIG_ERR_STATE. Errors: SIG_ERR_NOT_FOUND (no such service, including any name that could not name one); SIG_ERR_EXISTS (start of a running service); SIG_ERR_STATE (runtime not running, or the service vanished before its state could be read); SIG_ERR_INVALID_ARG (a NULL argument, or the service could not start because a capsule configuration is invalid; the host log has the detail); anything else the runtime returns is passed through. sig_mgmt_request_shutdown asks the runtime to shut down and returns SIG_OK (SIG_ERR_INVALID_ARG for NULL); it does not wait. Edits. Each takes the document as text, `doc` of `doc_len` bytes, exactly as the project layer's put/patch functions do; `errmsg` (optional, may be NULL) receives a NUL-terminated reason of at most errmsg_len-1 bytes, empty unless stated below. `out` receives an owned tree on SIG_OK and is untouched on failure: put/patch_configuration: {name, config: <definition>} put/patch_service: {name, config: <definition>, dirty} rename_configuration: {name: <new name>, config: <definition>} `*created` (put only) tells whether the object is new. Rename takes the new name as a plain string. On failure nothing was changed. Errors, and what `errmsg` carries with each: SIG_ERR_INVALID_ARG a NULL argument; a name or new name the project refuses (empty, too long, or with a character other than letters, digits, '_' and '-'); a new name of 80 bytes or more; an empty or NULL `doc` (errmsg is "document required"). errmsg is empty for every other cause, so a non-empty errmsg names the empty document. SIG_ERR_PARSE the document failed validation; errmsg is the project's reason for configurations, and empty for services (the reason is only in the host log). SIG_ERR_NOT_FOUND no such configuration or service (put creates, so only patch, delete and rename report it). SIG_ERR_EXISTS delete of a configuration a service uses (errmsg empty), or rename onto a name that is taken, which includes renaming to its own name (errmsg is the sentence naming the taken name). SIG_ERR_STATE the runtime is not running. other a failure inside the runtime or project. An edit that succeeded in the project but could not build `out` returns SIG_ERR_ALLOC with the edit already applied.

sig_mgmt_stop_service

sig_status_t sig_mgmt_stop_service(sig_mgmt * m, const char * name, sig_value * out_state)
ParameterType
msig_mgmt *
nameconst char *
out_statesig_value *

shared with sig_mgmt_start_service

---- Action and edit operations ----------------------------------------- Locking. An operation never calls another operation while holding the lock. Edit operations hold the exclusive lock only while the project is edited (they wait for in-flight readers to drain, and readers wait for them); the result tree is built afterwards from text the edit copied out, so no project pointer outlives the lock. start/stop/restart/shutdown hold none of this module's lock while the runtime runs the service's hooks, which may block for long; only the short lookup that builds `out_state` takes the shared lock, plus a short exclusive section when a stopped service has to be rebuilt from an edited definition (the old live service is freed, which no reader may be looking at). The rebuild only ever runs in that exclusive section; the hooks never do. Residual stall, inherent in sig_runtime_edit(): an edit or rebuild that waits on the runtime's control mutex behind a slow start of another service holds the exclusive lock while it waits, so reads stall until that start returns. Actions. sig_mgmt_start_service / _stop_service / _restart_service: on SIG_OK *out_state is the map {name, state} ("running" | "stopped"), owned by the caller (sig_value_dtor), untouched on failure. Stopping a stopped service is SIG_OK. They block until the service's hooks have run. Restart is not one atomic runtime call: it is a stop followed by a start, so a concurrent start can win in between (SIG_ERR_EXISTS), and if the rebuild or the start fails the service is left stopped. A start that is repeatedly overtaken by a concurrent stop or edit of the same service gives up after a few attempts with SIG_ERR_STATE. Errors: SIG_ERR_NOT_FOUND (no such service, including any name that could not name one); SIG_ERR_EXISTS (start of a running service); SIG_ERR_STATE (runtime not running, or the service vanished before its state could be read); SIG_ERR_INVALID_ARG (a NULL argument, or the service could not start because a capsule configuration is invalid; the host log has the detail); anything else the runtime returns is passed through. sig_mgmt_request_shutdown asks the runtime to shut down and returns SIG_OK (SIG_ERR_INVALID_ARG for NULL); it does not wait. Edits. Each takes the document as text, `doc` of `doc_len` bytes, exactly as the project layer's put/patch functions do; `errmsg` (optional, may be NULL) receives a NUL-terminated reason of at most errmsg_len-1 bytes, empty unless stated below. `out` receives an owned tree on SIG_OK and is untouched on failure: put/patch_configuration: {name, config: <definition>} put/patch_service: {name, config: <definition>, dirty} rename_configuration: {name: <new name>, config: <definition>} `*created` (put only) tells whether the object is new. Rename takes the new name as a plain string. On failure nothing was changed. Errors, and what `errmsg` carries with each: SIG_ERR_INVALID_ARG a NULL argument; a name or new name the project refuses (empty, too long, or with a character other than letters, digits, '_' and '-'); a new name of 80 bytes or more; an empty or NULL `doc` (errmsg is "document required"). errmsg is empty for every other cause, so a non-empty errmsg names the empty document. SIG_ERR_PARSE the document failed validation; errmsg is the project's reason for configurations, and empty for services (the reason is only in the host log). SIG_ERR_NOT_FOUND no such configuration or service (put creates, so only patch, delete and rename report it). SIG_ERR_EXISTS delete of a configuration a service uses (errmsg empty), or rename onto a name that is taken, which includes renaming to its own name (errmsg is the sentence naming the taken name). SIG_ERR_STATE the runtime is not running. other a failure inside the runtime or project. An edit that succeeded in the project but could not build `out` returns SIG_ERR_ALLOC with the edit already applied.

sig_mgmt_restart_service

sig_status_t sig_mgmt_restart_service(sig_mgmt * m, const char * name, sig_value * out_state)
ParameterType
msig_mgmt *
nameconst char *
out_statesig_value *

shared with sig_mgmt_start_service

---- Action and edit operations ----------------------------------------- Locking. An operation never calls another operation while holding the lock. Edit operations hold the exclusive lock only while the project is edited (they wait for in-flight readers to drain, and readers wait for them); the result tree is built afterwards from text the edit copied out, so no project pointer outlives the lock. start/stop/restart/shutdown hold none of this module's lock while the runtime runs the service's hooks, which may block for long; only the short lookup that builds `out_state` takes the shared lock, plus a short exclusive section when a stopped service has to be rebuilt from an edited definition (the old live service is freed, which no reader may be looking at). The rebuild only ever runs in that exclusive section; the hooks never do. Residual stall, inherent in sig_runtime_edit(): an edit or rebuild that waits on the runtime's control mutex behind a slow start of another service holds the exclusive lock while it waits, so reads stall until that start returns. Actions. sig_mgmt_start_service / _stop_service / _restart_service: on SIG_OK *out_state is the map {name, state} ("running" | "stopped"), owned by the caller (sig_value_dtor), untouched on failure. Stopping a stopped service is SIG_OK. They block until the service's hooks have run. Restart is not one atomic runtime call: it is a stop followed by a start, so a concurrent start can win in between (SIG_ERR_EXISTS), and if the rebuild or the start fails the service is left stopped. A start that is repeatedly overtaken by a concurrent stop or edit of the same service gives up after a few attempts with SIG_ERR_STATE. Errors: SIG_ERR_NOT_FOUND (no such service, including any name that could not name one); SIG_ERR_EXISTS (start of a running service); SIG_ERR_STATE (runtime not running, or the service vanished before its state could be read); SIG_ERR_INVALID_ARG (a NULL argument, or the service could not start because a capsule configuration is invalid; the host log has the detail); anything else the runtime returns is passed through. sig_mgmt_request_shutdown asks the runtime to shut down and returns SIG_OK (SIG_ERR_INVALID_ARG for NULL); it does not wait. Edits. Each takes the document as text, `doc` of `doc_len` bytes, exactly as the project layer's put/patch functions do; `errmsg` (optional, may be NULL) receives a NUL-terminated reason of at most errmsg_len-1 bytes, empty unless stated below. `out` receives an owned tree on SIG_OK and is untouched on failure: put/patch_configuration: {name, config: <definition>} put/patch_service: {name, config: <definition>, dirty} rename_configuration: {name: <new name>, config: <definition>} `*created` (put only) tells whether the object is new. Rename takes the new name as a plain string. On failure nothing was changed. Errors, and what `errmsg` carries with each: SIG_ERR_INVALID_ARG a NULL argument; a name or new name the project refuses (empty, too long, or with a character other than letters, digits, '_' and '-'); a new name of 80 bytes or more; an empty or NULL `doc` (errmsg is "document required"). errmsg is empty for every other cause, so a non-empty errmsg names the empty document. SIG_ERR_PARSE the document failed validation; errmsg is the project's reason for configurations, and empty for services (the reason is only in the host log). SIG_ERR_NOT_FOUND no such configuration or service (put creates, so only patch, delete and rename report it). SIG_ERR_EXISTS delete of a configuration a service uses (errmsg empty), or rename onto a name that is taken, which includes renaming to its own name (errmsg is the sentence naming the taken name). SIG_ERR_STATE the runtime is not running. other a failure inside the runtime or project. An edit that succeeded in the project but could not build `out` returns SIG_ERR_ALLOC with the edit already applied.

sig_mgmt_request_shutdown

sig_status_t sig_mgmt_request_shutdown(sig_mgmt * m)
ParameterType
msig_mgmt *

shared with sig_mgmt_start_service

---- Action and edit operations ----------------------------------------- Locking. An operation never calls another operation while holding the lock. Edit operations hold the exclusive lock only while the project is edited (they wait for in-flight readers to drain, and readers wait for them); the result tree is built afterwards from text the edit copied out, so no project pointer outlives the lock. start/stop/restart/shutdown hold none of this module's lock while the runtime runs the service's hooks, which may block for long; only the short lookup that builds `out_state` takes the shared lock, plus a short exclusive section when a stopped service has to be rebuilt from an edited definition (the old live service is freed, which no reader may be looking at). The rebuild only ever runs in that exclusive section; the hooks never do. Residual stall, inherent in sig_runtime_edit(): an edit or rebuild that waits on the runtime's control mutex behind a slow start of another service holds the exclusive lock while it waits, so reads stall until that start returns. Actions. sig_mgmt_start_service / _stop_service / _restart_service: on SIG_OK *out_state is the map {name, state} ("running" | "stopped"), owned by the caller (sig_value_dtor), untouched on failure. Stopping a stopped service is SIG_OK. They block until the service's hooks have run. Restart is not one atomic runtime call: it is a stop followed by a start, so a concurrent start can win in between (SIG_ERR_EXISTS), and if the rebuild or the start fails the service is left stopped. A start that is repeatedly overtaken by a concurrent stop or edit of the same service gives up after a few attempts with SIG_ERR_STATE. Errors: SIG_ERR_NOT_FOUND (no such service, including any name that could not name one); SIG_ERR_EXISTS (start of a running service); SIG_ERR_STATE (runtime not running, or the service vanished before its state could be read); SIG_ERR_INVALID_ARG (a NULL argument, or the service could not start because a capsule configuration is invalid; the host log has the detail); anything else the runtime returns is passed through. sig_mgmt_request_shutdown asks the runtime to shut down and returns SIG_OK (SIG_ERR_INVALID_ARG for NULL); it does not wait. Edits. Each takes the document as text, `doc` of `doc_len` bytes, exactly as the project layer's put/patch functions do; `errmsg` (optional, may be NULL) receives a NUL-terminated reason of at most errmsg_len-1 bytes, empty unless stated below. `out` receives an owned tree on SIG_OK and is untouched on failure: put/patch_configuration: {name, config: <definition>} put/patch_service: {name, config: <definition>, dirty} rename_configuration: {name: <new name>, config: <definition>} `*created` (put only) tells whether the object is new. Rename takes the new name as a plain string. On failure nothing was changed. Errors, and what `errmsg` carries with each: SIG_ERR_INVALID_ARG a NULL argument; a name or new name the project refuses (empty, too long, or with a character other than letters, digits, '_' and '-'); a new name of 80 bytes or more; an empty or NULL `doc` (errmsg is "document required"). errmsg is empty for every other cause, so a non-empty errmsg names the empty document. SIG_ERR_PARSE the document failed validation; errmsg is the project's reason for configurations, and empty for services (the reason is only in the host log). SIG_ERR_NOT_FOUND no such configuration or service (put creates, so only patch, delete and rename report it). SIG_ERR_EXISTS delete of a configuration a service uses (errmsg empty), or rename onto a name that is taken, which includes renaming to its own name (errmsg is the sentence naming the taken name). SIG_ERR_STATE the runtime is not running. other a failure inside the runtime or project. An edit that succeeded in the project but could not build `out` returns SIG_ERR_ALLOC with the edit already applied.

sig_mgmt_put_configuration

sig_status_t sig_mgmt_put_configuration(sig_mgmt * m, const char * name, const char * doc, size_t doc_len, bool * created, sig_value * out, char * errmsg, size_t errmsg_len)
ParameterType
msig_mgmt *
nameconst char *
docconst char *
doc_lensize_t
createdbool *
outsig_value *
errmsgchar *
errmsg_lensize_t

sig_mgmt_patch_configuration

sig_status_t sig_mgmt_patch_configuration(sig_mgmt * m, const char * name, const char * doc, size_t doc_len, sig_value * out, char * errmsg, size_t errmsg_len)
ParameterType
msig_mgmt *
nameconst char *
docconst char *
doc_lensize_t
outsig_value *
errmsgchar *
errmsg_lensize_t

sig_mgmt_delete_configuration

sig_status_t sig_mgmt_delete_configuration(sig_mgmt * m, const char * name)
ParameterType
msig_mgmt *
nameconst char *

sig_mgmt_rename_configuration

sig_status_t sig_mgmt_rename_configuration(sig_mgmt * m, const char * name, const char * new_name, sig_value * out, char * errmsg, size_t errmsg_len)
ParameterType
msig_mgmt *
nameconst char *
new_nameconst char *
outsig_value *
errmsgchar *
errmsg_lensize_t

sig_mgmt_put_service

sig_status_t sig_mgmt_put_service(sig_mgmt * m, const char * name, const char * doc, size_t doc_len, bool * created, sig_value * out, char * errmsg, size_t errmsg_len)
ParameterType
msig_mgmt *
nameconst char *
docconst char *
doc_lensize_t
createdbool *
outsig_value *
errmsgchar *
errmsg_lensize_t

sig_mgmt_patch_service

sig_status_t sig_mgmt_patch_service(sig_mgmt * m, const char * name, const char * doc, size_t doc_len, sig_value * out, char * errmsg, size_t errmsg_len)
ParameterType
msig_mgmt *
nameconst char *
docconst char *
doc_lensize_t
outsig_value *
errmsgchar *
errmsg_lensize_t

sig_mgmt_delete_service

sig_status_t sig_mgmt_delete_service(sig_mgmt * m, const char * name)
ParameterType
msig_mgmt *
nameconst char *