Crinit -- Configurable Rootfs Init
taskdb.c File Reference

(2023-08-28, commit: 649e63b)

Implementation of the central Task Database and related functions. More...

#include "taskdb.h"
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "common.h"
#include "globopt.h"
#include "logio.h"
#include "optfeat.h"
Include dependency graph for taskdb.c:

Functions

static int crinitFindTask (crinitTask_t **task, const char *taskName, const crinitTaskDB_t *in)
 
static bool crinitTaskIsReady (const crinitTask_t *t)
 
int crinitTaskDBInitWithSize (crinitTaskDB_t *ctx, int(*spawnFunc)(crinitTaskDB_t *ctx, const crinitTask_t *), size_t initialSize)
 
int crinitTaskDBDestroy (crinitTaskDB_t *ctx)
 
int crinitTaskDBInsert (crinitTaskDB_t *ctx, const crinitTask_t *t, bool overwrite)
 
int crinitTaskDBSpawnReady (crinitTaskDB_t *ctx)
 
int crinitTaskDBSetSpawnInhibit (crinitTaskDB_t *ctx, bool inh)
 
int crinitTaskDBSetTaskState (crinitTaskDB_t *ctx, crinitTaskState_t s, const char *taskName)
 
int crinitTaskDBGetTaskState (crinitTaskDB_t *ctx, crinitTaskState_t *s, const char *taskName)
 
int crinitTaskDBSetTaskPID (crinitTaskDB_t *ctx, pid_t pid, const char *taskName)
 
int crinitTaskDBGetTaskPID (crinitTaskDB_t *ctx, pid_t *pid, const char *taskName)
 
int crinitTaskDBGetTaskStateAndPID (crinitTaskDB_t *ctx, crinitTaskState_t *s, pid_t *pid, const char *taskName)
 
int crinitTaskDBAddDepToTask (crinitTaskDB_t *ctx, const crinitTaskDep_t *dep, const char *taskName)
 
int crinitTaskDBRemoveDepFromTask (crinitTaskDB_t *ctx, const crinitTaskDep_t *dep, const char *taskName)
 
int crinitTaskDBFulfillDep (crinitTaskDB_t *ctx, const crinitTaskDep_t *dep, const crinitTask_t *target)
 
int crinitTaskDBProvideFeature (crinitTaskDB_t *ctx, const crinitTask_t *provider, crinitTaskState_t newState)
 
int crinitTaskDBProvideFeatureByTaskName (crinitTaskDB_t *ctx, const char *taskName, crinitTaskState_t newState)
 
int crinitTaskDBExportTaskNamesToArray (crinitTaskDB_t *ctx, char **tasks[], size_t *numTasks)
 

Detailed Description

Implementation of the central Task Database and related functions.

Function Documentation

◆ crinitFindTask()

static int crinitFindTask ( crinitTask_t **  task,
const char *  taskName,
const crinitTaskDB_t in 
)
static

Find index of a task in the crinitTaskDB_t::taskSet of an crinitTaskDB_t by name.

Parameters
taskPointer pointer to return the task with.
taskNameThe crinitTask_t::name to search for.
inThe crinitTaskDB_t_t to search in.
Returns
0 on success, -1 otherwise

◆ crinitTaskDBAddDepToTask()

int crinitTaskDBAddDepToTask ( crinitTaskDB_t ctx,
const crinitTaskDep_t dep,
const char *  taskName 
)

Add a dependency to a specific task inside a task database.

Will search ctx for a task with name taskName and add dep to its crinitTask_t::deps and adjust crinitTask_t::depsSize.

Parameters
ctxThe crinitTaskDb context to work on.
depThe dependency to be added.
taskNameThe name of the relevant task.
Returns
0 on success, -1 otherweise

◆ crinitTaskDBDestroy()

int crinitTaskDBDestroy ( crinitTaskDB_t ctx)

Free memory allocated for crinitTaskDB_t members by functions like crinitTaskDBInit or crinitTaskDBInsert().

Afterwards ctx may not be used anymore until another call to crinitTaskDBInit() or crinitTaskDBInitWithSize().

Parameters
ctxThe crinitTaskDB_t context to be destroyed.
Returns
0 on success, -1 on error

◆ crinitTaskDBExportTaskNamesToArray()

int crinitTaskDBExportTaskNamesToArray ( crinitTaskDB_t ctx,
char **  tasks[],
size_t *  numTasks 
)

Export the list of task names currently in the task database.

The function allocates an array of strings as tasks and returns the number of array elements in numTasks. Each entry in the tasks array will be allocated separately and needs to be freed by the caller.

Parameters
ctxThe TaskDB context from which to get the list of task names.
tasksThe return pointer for the array of task names.
numTasksThe return pointer for the number of array entries.
Returns
0 on success, -1 on error

◆ crinitTaskDBFulfillDep()

int crinitTaskDBFulfillDep ( crinitTaskDB_t ctx,
const crinitTaskDep_t dep,
const crinitTask_t target 
)

Fulfill a dependency for all tasks inside a task database.

Will search ctx for tasks containing a dependency equal to dep (i.e. specifying the same name and event, according to strcmp()) and, if found, remove the dependency from crinitTask_t::deps. Will signal crinitTaskDB_t::changed on successful completion. The function uses crinitTaskDB_t::lock for synchronization and is thread-safe.

Parameters
ctxThe crinitTaskDB_t context in which to fulfill the dependency.
depThe dependency to be fulfilled.
targetThe targeted task or NULL.
Returns
0 on success, -1 otherwise

◆ crinitTaskDBGetTaskPID()

int crinitTaskDBGetTaskPID ( crinitTaskDB_t ctx,
pid_t *  pid,
const char *  taskName 
)

Get the PID of a task in a task database

Will search ctx for an crinitTask_t with crinitTask_t::name lexicographically equal to taskName and write its PID to pid. If such a task does not exit in ctx, an error is returned. If the task does not currently have a running process, pid will be -1 but the function will indicate success. The function uses crinitTaskDB_t::lock for synchronization and is thread-safe.

Parameters
ctxThe crinitTaskDB_t context in which the task is held.
pidPointer to store the returned PID.
taskNameThe task's name.
Returns
0 on success, -1 otherwise.

◆ crinitTaskDBGetTaskState()

int crinitTaskDBGetTaskState ( crinitTaskDB_t ctx,
crinitTaskState_t s,
const char *  taskName 
)

Get the crinitTaskState_t of a task in a task database

Will search ctx for an crinitTask_t with crinitTask_t::name lexicographically equal to taskName and write its crinitTask_t::state to s. If such a task does not exist in ctx, an error is returned. The function uses crinitTaskDB_t::lock for synchronization and is thread-safe.

Parameters
ctxThe crinitTaskDB_t context in which the task is held.
sPointer to store the returned crinitTaskState_t.
taskNameThe task's name.
Returns
0 on success, -1 otherwise.

◆ crinitTaskDBGetTaskStateAndPID()

int crinitTaskDBGetTaskStateAndPID ( crinitTaskDB_t ctx,
crinitTaskState_t s,
pid_t *  pid,
const char *  taskName 
)

Get the crinitTaskState_t and the PID of a task in a task database

Will search ctx for an crinitTask_t with crinitTask_t::name lexicographically equal to taskName and write its crinitTask_t::state to s and its PID to pid. If such a task does not exist in ctx, an error is returned. If the task does not currently have a running process, pid will be -1 but the function will indicate success. The function uses crinitTaskDB_t::lock for synchronization and is thread-safe.

Parameters
ctxThe crinitTaskDB_t context in which the task is held.
sPointer to store the returned crinitTaskState_t.
pidPointer to store the returned PID.
taskNameThe task's name.
Returns
0 on success, -1 otherwise.

◆ crinitTaskDBInitWithSize()

int crinitTaskDBInitWithSize ( crinitTaskDB_t ctx,
int(*)(crinitTaskDB_t *ctx, const crinitTask_t *)  spawnFunc,
size_t  initialSize 
)

Initialize the internals of an crinitTaskDB_t with a specified initial size for crinitTaskDB_t::taskSet.

If the initialized TaskDB is no longer needed the internally held dynamic memory should be freed using crinitTaskDBDestroy().

Parameters
ctxThe crinitTaskDB_t whose internal members should be initialized.
spawnFuncPointer to the task spawn function to be used by crinitTaskDBSpawnReady()
initialSizeInitial size of crinitTaskDB_t::taskSet for ctx.
Returns
0 on success, -1 otherwise

◆ crinitTaskDBInsert()

int crinitTaskDBInsert ( crinitTaskDB_t ctx,
const crinitTask_t t,
bool  overwrite 
)

Insert a task into a task database.

Will store a copy of t in the crinitTaskDB_t::taskSet of ctx. crinitTaskDB_t::taskSetItems will be incremented and if crinitTaskDB_t::taskSetSize is not sufficient, the set will be grown. If overwrite is true, a task with the same name in the set will be overwritten. If it is false, an existing task with the same name will cause an error. If the task has been successfully inserted, the function will signal crinitTaskDB_t::changed. The function uses crinitTaskDB_t::lock for synchronization and is thread-safe.

Parameters
ctxThe crinitTaskDB_t context, into which task should be inserted.
tThe task to be inserted.
overwriteOverwrite a colliding task with the same name (true) or return an error (false).
Returns
0 on success, -1 otherwise

◆ crinitTaskDBProvideFeature()

int crinitTaskDBProvideFeature ( crinitTaskDB_t ctx,
const crinitTask_t provider,
crinitTaskState_t  newState 
)

Fulfill feature dependencies implemented by a provider task.

Will search ctx for tasks containing feature dependencies PROVIDE-ed by provider given its new state newState and, if found, remove the dependency from crinitTask_t::dep by using crinitTaskDBFulfillDep(). Synchronization and signalling remains the same as with a direct call to crinitTaskDBFulfillDep().

Parameters
ctxThe crinitTaskDB_t context in which to fulfill the feature dependency.
providerThe crinitTask_t providing the feature(s).
newStateThe crinitTaskState_t which has been newly reached by provider.
Returns
0 on success, -1 otherwise

◆ crinitTaskDBProvideFeatureByTaskName()

int crinitTaskDBProvideFeatureByTaskName ( crinitTaskDB_t ctx,
const char *  taskName,
crinitTaskState_t  newState 
)

Fulfill feature dependencies implemented by a provider task (searched for by name).

Will search ctx for the provider task referenced by taskName and then call crinitTaskDBProvideFeature() on it (see there for details).

Parameters
ctxThe crinitTaskDB_t context in which to fulfill the feature dependency.
taskNameThe name of the task providing the feature(s).
newStateThe crinitTaskState_t which has been newly reached by the provider task.
Returns
0 on success, -1 otherwise

◆ crinitTaskDBRemoveDepFromTask()

int crinitTaskDBRemoveDepFromTask ( crinitTaskDB_t ctx,
const crinitTaskDep_t dep,
const char *  taskName 
)

Remove a dependency from a specific task inside a task database.

Will search ctx for a task with name taskName and remove a dependency equal to dep from its crinitTask_t::deps and adjust crinitTask_t::depsSize, if such a dependency is present. The equality condition between two crinitTaskDep_t instances is the same as in crinitTaskDBFulfillDep(), i.e. their contents are lexicographically equal.

Parameters
ctxThe crinitTaskDb context to work on.
depThe dependency to be removed.
taskNameThe name of the relevant task.
Returns
0 on success, -1 otherweise

◆ crinitTaskDBSetSpawnInhibit()

int crinitTaskDBSetSpawnInhibit ( crinitTaskDB_t ctx,
bool  inh 
)

Inhibit or un-inhibit spawning of processes by setting crinitTaskDB_t::spawnInhibit.

The function uses crinitTaskDB_t::lock for synchronization and is thread-safe. It will also signal crinitTaskDB_t::changed if crinitTaskDB_t::spawnInhibit was changed to false.

Parameters
ctxThe TaskDB context in which to set the variable.
inhThe value which crinitTaskDB_t:spawnInhibit shall be set to.
Returns
0 on success, -1 otherwise

◆ crinitTaskDBSetTaskPID()

int crinitTaskDBSetTaskPID ( crinitTaskDB_t ctx,
pid_t  pid,
const char *  taskName 
)

Set the PID a task in a task database

Will search ctx for an crinitTask_t with crinitTask_t::name lexicographically equal to taskName and set its crinitTask_t::pid to pid. If such a task does not exit in ctx, an error is returned. The function uses crinitTaskDB_t::lock for synchronization and is thread-safe.

Parameters
ctxThe crinitTaskDB_t context in which the task is held.
pidThe task's new PID.
taskNameThe task's name.
Returns
0 on success, -1 otherwise.

◆ crinitTaskDBSetTaskState()

int crinitTaskDBSetTaskState ( crinitTaskDB_t ctx,
crinitTaskState_t  s,
const char *  taskName 
)

Set the crinitTaskState_t of a task in a task database

Will search ctx for an crinitTask_t with crinitTask_t::name lexicographically equal to taskName and set its crinitTask_t::state to s. If such a task does not exist in ctx, an error is returned. If s equals CRINIT_TASK_STATE_FAILED, crinitTask_t::failCount will be incremented by 1. If s equals CRINIT_TASK_STATE_DONE, crinitTask_t::failCount will be reset to 0. The function uses crinitTaskDB_t::lock for synchronization and is thread-safe.

Parameters
ctxThe crinitTaskDB_t context in which the task is held.
sThe task's new state.
taskNameThe task's name.
Returns
0 on success, -1 otherwise.

◆ crinitTaskDBSpawnReady()

int crinitTaskDBSpawnReady ( crinitTaskDB_t ctx)

Run crinitTaskDB_t::spawnFunc for each startable task in a task database.

A task is startable if and only if it has no remaining crinitTask_t::deps and it has either not been started before according to crinitTask_t::state or it should be respawned. A task should be respawned if and only if crinitTask_t::opts contains the flag CRINIT_TASK_OPT_RESPAWN and either crinitTask_t::maxRetries is -1 or crinitTask_t::failCount is less than crinitTask_t::maxRetries. The function uses crinitTaskDB_t::lock for synchronization and is thread-safe.

If crinitTaskDB::spawnInhibit is true, no tasks are considered startable and this function will return successfully without starting anything.

Parameters
ctxThe TaskDB context from which tasks will be started.
Returns
0 on success, -1 otherwise

◆ crinitTaskIsReady()

static bool crinitTaskIsReady ( const crinitTask_t t)
static

Check if an crinitTask_t is considered ready to be started (startable).

See crinitTaskDBSpawnReady() for further explanation.

Parameters
tThe task to be checked for readiness.
Returns
true if t is ready, false otherwise