Changeset bb154c6 in mainline


Ignore:
Timestamp:
2019-08-03T08:15:25Z (5 years ago)
Author:
Matthieu Riolo <matthieu.riolo@…>
Children:
09a8006
Parents:
6006f35
git-author:
Michal Koutný <xm.koutny+hos@…> (2015-04-15 15:14:58)
git-committer:
Matthieu Riolo <matthieu.riolo@…> (2019-08-03 08:15:25)
Message:

Add skeleton for configuration files loading

  • Create content of /cfg directory,
  • create sample configuration file,
  • refactored polymorphism.

Conflicts:

boot/Makefile

Files:
3 added
1 deleted
18 edited

Legend:

Unmodified
Added
Removed
  • boot/Makefile

    r6006f35 rbb154c6  
    7070endif
    7171
     72        cp -r -L $(INITRD_CFG_PATH)/* $(DIST_PATH)/cfg
    7273        for app in $(RD_APPS) ; do \
    7374                app_dir="`dirname "$$app"`" ; \
  • boot/Makefile.common

    r6006f35 rbb154c6  
    5050TOOLS_PATH = $(ROOT_PATH)/tools
    5151DRVS_PATH = drv
     52INITRD_CFG_PATH = $(USPACE_PATH)/cfg
     53# TODO configuration separation may change
     54ROOTFS_CFG_PATH = $(USPACE_PATH)/cfg
    5255
    5356MKARRAY = $(TOOLS_PATH)/mkarray.py
  • uspace/srv/sysman/Makefile

    r6006f35 rbb154c6  
    2929
    3030USPACE_PREFIX = ../..
    31 EXTRA_CFLAGS = -I. -I./units
     31LIBS = $(LIBCONF_PREFIX)/libconf.a
     32EXTRA_CFLAGS += -I. -I./units -I$(LIBCONF_PREFIX)/include
    3233BINARY = sysman
    3334STATIC_NEEDED = y
     
    4142        unit.c \
    4243        units/unit_cfg.c \
    43         units/unit_mnt.c  \
    44         units/unit_tgt.c
     44        units/unit_mnt.c \
     45        units/unit_tgt.c \
     46        util.c
    4547
    4648include $(USPACE_PREFIX)/Makefile.common
  • uspace/srv/sysman/configuration.c

    r6006f35 rbb154c6  
     1#include <adt/hash.h>
     2#include <adt/hash_table.h>
    13#include <adt/list.h>
    24#include <assert.h>
     
    57
    68#include "configuration.h"
     9#include "dep.h"
    710#include "log.h"
    811
    9 static list_t units;
    10 static fibril_mutex_t units_mtx;
     12static hash_table_t units;
     13static fibril_rwlock_t units_rwl;
     14
     15/* Hash table functions */
     16static size_t units_ht_hash(const ht_link_t *item)
     17{
     18        unit_t *unit =
     19            hash_table_get_inst(item, unit_t, units);
     20        return hash_string(unit->name);
     21}
     22
     23static size_t units_ht_key_hash(void *key)
     24{
     25        return hash_string((const char *)key);
     26}
     27
     28static bool units_ht_equal(const ht_link_t *item1, const ht_link_t *item2)
     29{
     30        return str_cmp(
     31            hash_table_get_inst(item1, unit_t, units)->name,
     32            hash_table_get_inst(item2, unit_t, units)->name) == 0;
     33}
     34
     35static bool units_ht_key_equal(void *key, const ht_link_t *item)
     36{
     37        return str_cmp((const char *)key,
     38            hash_table_get_inst(item, unit_t, units)->name) == 0;
     39}
     40
     41
     42static hash_table_ops_t units_ht_ops = {
     43        .hash            = &units_ht_hash,
     44        .key_hash        = &units_ht_key_hash,
     45        .equal           = &units_ht_equal,
     46        .key_equal       = &units_ht_key_equal,
     47        .remove_callback = NULL // TODO realy unneeded?
     48};
     49
     50/* Configuration functions */
    1151
    1252void configuration_init(void)
    1353{
    14         list_initialize(&units);
    15         fibril_mutex_initialize(&units_mtx);
     54        hash_table_create(&units, 0, 0, &units_ht_ops);
     55        fibril_rwlock_initialize(&units_rwl);
    1656}
    1757
    1858int configuration_add_unit(unit_t *unit)
    1959{
    20         sysman_log(LVL_DEBUG2, "%s(%p)", __func__, unit);
    2160        assert(unit);
    2261        assert(unit->state == STATE_EMBRYO);
     62        assert(unit->name != NULL);
     63        assert(fibril_rwlock_is_write_locked(&units_rwl));
     64        sysman_log(LVL_DEBUG2, "%s('%s')", __func__, unit_name(unit));
    2365
    24         fibril_mutex_lock(&units_mtx);
    25         list_append(&unit->units, &units);
    26        
    27         // TODO check name uniqueness
    28         fibril_mutex_unlock(&units_mtx);
    29         return EOK;
     66        if (hash_table_insert_unique(&units, &unit->units)) {
     67                return EOK;
     68        } else {
     69                return EEXISTS;
     70        }
     71}
     72
     73void configuration_start_update(void) {
     74        assert(!fibril_rwlock_is_write_locked(&units_rwl));
     75        sysman_log(LVL_DEBUG2, "%s", __func__);
     76        fibril_rwlock_write_lock(&units_rwl);
     77}
     78
     79static bool configuration_commit_unit(ht_link_t *ht_link, void *arg)
     80{
     81        unit_t *unit = hash_table_get_inst(ht_link, unit_t, units);
     82        // TODO state locking?
     83        if (unit->state == STATE_EMBRYO) {
     84                unit->state = STATE_STOPPED;
     85        }
     86
     87        list_foreach(unit->dependencies, dependencies, unit_dependency_t, dep) {
     88                if (dep->state == DEP_EMBRYO) {
     89                        dep->state = DEP_VALID;
     90                }
     91        }
     92        return true;
    3093}
    3194
    3295/** Marks newly added units as usable (via state change) */
    33 int configuration_commit(void)
     96void configuration_commit(void)
    3497{
     98        assert(fibril_rwlock_is_write_locked(&units_rwl));
    3599        sysman_log(LVL_DEBUG2, "%s", __func__);
    36100
    37         fibril_mutex_lock(&units_mtx);
    38         list_foreach(units, units, unit_t, u) {
    39                 if (u->state == STATE_EMBRYO) {
    40                         u->state = STATE_STOPPED;
     101        /*
     102         * Apply commit to all units, each commited unit commits its outgoing
     103         * deps, thus eventually commiting all embryo deps as well.
     104         */
     105        hash_table_apply(&units, &configuration_commit_unit, NULL);
     106        fibril_rwlock_write_unlock(&units_rwl);
     107}
     108
     109static bool configuration_rollback_unit(ht_link_t *ht_link, void *arg)
     110{
     111        unit_t *unit = hash_table_get_inst(ht_link, unit_t, units);
     112
     113        list_foreach_safe(unit->dependencies, cur_link, next_link) {
     114                unit_dependency_t *dep =
     115                    list_get_instance(cur_link, unit_dependency_t, dependencies);
     116                if (dep->state == DEP_EMBRYO) {
     117                        dep_remove_dependency(&dep);
    41118                }
    42119        }
    43         fibril_mutex_unlock(&units_mtx);
    44120
    45         return EOK;
     121        if (unit->state == STATE_EMBRYO) {
     122                hash_table_remove_item(&units, ht_link);
     123                unit_destroy(&unit);
     124        }
     125
     126        return true;
    46127}
     128
     129void configuration_rollback(void)
     130{
     131        assert(fibril_rwlock_is_write_locked(&units_rwl));
     132        sysman_log(LVL_DEBUG2, "%s", __func__);
     133
     134        hash_table_apply(&units, &configuration_rollback_unit, NULL);
     135        fibril_rwlock_write_unlock(&units_rwl);
     136}
     137
     138static bool configuration_resolve_unit(ht_link_t *ht_link, void *arg)
     139{
     140        bool *has_error_ptr = arg;
     141        unit_t *unit = hash_table_get_inst(ht_link, unit_t, units);
     142
     143        list_foreach(unit->dependencies, dependencies, unit_dependency_t, dep) {
     144                assert(dep->dependant == unit);
     145                assert((dep->dependency != NULL) != (dep->dependency_name != NULL));
     146                if (dep->dependency) {
     147                        continue;
     148                }
     149
     150                unit_t *dependency =
     151                    configuration_find_unit_by_name(dep->dependency_name);
     152                if (dependency == NULL) {
     153                        sysman_log(LVL_ERROR,
     154                            "Cannot resolve dependency of '%s' to unit '%s'",
     155                            unit_name(unit), dep->dependency_name);
     156                        *has_error_ptr = true;
     157                        // TODO should we just leave the sprout untouched?
     158                } else {
     159                        dep_resolve_dependency(dep, dependency);
     160                }
     161        }
     162
     163        return true;
     164}
     165
     166/** Resolve unresolved dependencies between any pair of units
     167 *
     168 * @return EOK      on success
     169 * @return ENONENT  when one or more resolution fails, information is logged
     170 */
     171int configuration_resolve_dependecies(void)
     172{
     173        assert(fibril_rwlock_is_write_locked(&units_rwl));
     174        sysman_log(LVL_DEBUG2, "%s", __func__);
     175
     176        bool has_error = false;
     177        hash_table_apply(&units, &configuration_resolve_unit, &has_error);
     178
     179        return has_error ? ENOENT : EOK;
     180}
     181
     182unit_t *configuration_find_unit_by_name(const char *name)
     183{
     184        ht_link_t *ht_link = hash_table_find(&units, (void *)name);
     185        if (ht_link != NULL) {
     186                return hash_table_get_inst(ht_link, unit_t, units);
     187        } else {
     188                return NULL;
     189        }
     190}
     191
  • uspace/srv/sysman/configuration.h

    r6006f35 rbb154c6  
    88extern int configuration_add_unit(unit_t *);
    99
    10 extern int configuration_commit(void);
     10extern void configuration_start_update(void);
     11
     12extern void configuration_commit(void);
     13
     14extern void configuration_rollback(void);
     15
     16extern int configuration_resolve_dependecies(void);
     17
     18extern unit_t *configuration_find_unit_by_name(const char *);
     19
    1120
    1221#endif
  • uspace/srv/sysman/dep.c

    r6006f35 rbb154c6  
     1#include <assert.h>
    12#include <errno.h>
    23#include <stdlib.h>
     4#include <str.h>
    35
    46#include "dep.h"
     7
     8static void dep_dependency_init(unit_dependency_t *dep)
     9{
     10        link_initialize(&dep->dependants);
     11        link_initialize(&dep->dependencies);
     12
     13        dep->dependency_name = NULL;
     14        dep->state = DEP_EMBRYO;
     15}
     16
     17unit_dependency_t *dep_dependency_create(void)
     18{
     19        unit_dependency_t *dep = malloc(sizeof(unit_dependency_t));
     20        if (dep) {
     21                dep_dependency_init(dep);
     22        }
     23        return dep;
     24}
     25
     26void dep_dependency_destroy(unit_dependency_t **dep_ptr)
     27{
     28        unit_dependency_t *dep = *dep_ptr;
     29        if (dep == NULL) {
     30                return;
     31        }
     32
     33        list_remove(&dep->dependencies);
     34        list_remove(&dep->dependants);
     35
     36        free(dep->dependency_name);
     37        free(dep);
     38
     39        *dep_ptr = NULL;
     40}
     41
     42int dep_sprout_dependency(unit_t *dependant, const char *dependency_name)
     43{
     44        unit_dependency_t *dep = dep_dependency_create();
     45        int rc;
     46
     47        if (dep == NULL) {
     48                rc = ENOMEM;
     49                goto finish;
     50        }
     51
     52        dep->dependency_name = str_dup(dependency_name);
     53        if (dep->dependency_name == NULL) {
     54                rc = ENOMEM;
     55                goto finish;
     56        }
     57
     58        list_append(&dep->dependencies, &dependant->dependencies);
     59        dep->dependant = dependant;
     60
     61        rc = EOK;
     62
     63finish:
     64        if (rc != EOK) {
     65                dep_dependency_destroy(&dep);
     66        }
     67        return rc;
     68}
     69
     70void dep_resolve_dependency(unit_dependency_t *dep, unit_t *unit)
     71{
     72        assert(dep->dependency == NULL);
     73        assert(dep->dependency_name != NULL);
     74
     75        // TODO add to other side dependants list
     76        dep->dependency = unit;
     77        free(dep->dependency_name);
     78        dep->dependency_name = NULL;
     79}
     80
    581
    682/**
     
    1086int dep_add_dependency(unit_t *dependant, unit_t *dependency)
    1187{
    12         unit_dependency_t *edge = malloc(sizeof(unit_dependency_t));
    13         if (edge == NULL) {
     88        unit_dependency_t *dep = dep_dependency_create();
     89        if (dep == NULL) {
    1490                return ENOMEM;
    1591        }
    16         link_initialize(&edge->dependants);
    17         link_initialize(&edge->dependencies);
    1892
    19         // TODO check existence of the edge
     93        // TODO check existence of the dep
    2094        // TODO locking
    2195        // TODO check types and states of connected units
    22         list_append(&edge->dependants, &dependency->dependants);
    23         list_append(&edge->dependencies, &dependant->dependencies);
     96        list_append(&dep->dependants, &dependency->dependants);
     97        list_append(&dep->dependencies, &dependant->dependencies);
    2498
    25         edge->dependant = dependant;
    26         edge->dependency = dependency;
     99        dep->dependant = dependant;
     100        dep->dependency = dependency;
    27101        return EOK;
    28102}
     103
     104/** Remove dependency from dependency graph
     105 *
     106 * Given dependency is removed from graph and unallocated.
     107 */
     108void dep_remove_dependency(unit_dependency_t **dep_ptr)
     109{
     110        // TODO here should be some checks, othewise replace this wrapper with
     111        //      direct destroy
     112        dep_dependency_destroy(dep_ptr);
     113}
  • uspace/srv/sysman/dep.h

    r6006f35 rbb154c6  
    66#include "unit.h"
    77
    8 /** Dependency edge between unit in dependency graph */
     8typedef enum {
     9        DEP_EMBRYO,
     10        DEP_VALID
     11} dependency_state_t;
     12
     13/** Dependency edge between unit in dependency graph
     14 *
     15 * @code
     16 * dependant ---> dependency
     17 * @endcode
     18 *
     19 */
    920typedef struct {
     21        /** Link to dependants list */
    1022        link_t dependants;
     23        /** Link to dependencies list */
    1124        link_t dependencies;
     25
     26        dependency_state_t state;
    1227
    1328        /** Unit that depends on another */
    1429        unit_t *dependant;
     30
    1531        /** Unit that is dependency for another */
    1632        unit_t *dependency;
     33
     34        /** Name of the dependency unit, for resolved dependencies it's NULL
     35         *
     36         * @note Either dependency or dependency_name is set. Never both nor
     37         *       none.
     38         */
     39        char *dependency_name;
    1740} unit_dependency_t;
    1841
     42extern unit_dependency_t *dep_dependency_create(void);
     43extern void dep_dependency_destroy(unit_dependency_t **);
     44
     45extern int dep_sprout_dependency(unit_t *, const char *);
     46extern void dep_resolve_dependency(unit_dependency_t *, unit_t *);
     47
    1948extern int dep_add_dependency(unit_t *, unit_t *);
     49extern void dep_remove_dependency(unit_dependency_t **);
     50
    2051
    2152#endif
  • uspace/srv/sysman/job.c

    r6006f35 rbb154c6  
    137137
    138138        /* Enqueue jobs */
    139         list_foreach_safe(*jobs, cur_link, next_lin) {
     139        list_foreach_safe(*jobs, cur_link, next_link) {
    140140                list_remove(cur_link);
    141141                list_append(cur_link, &job_queue);
  • uspace/srv/sysman/main.c

    r6006f35 rbb154c6  
    3636                goto fail;
    3737        }
     38        mnt_initrd->name                 = str_dup("initrd.mnt");
    3839        // TODO Use RDFMT
    39         mnt_initrd->data.mnt.type       = str_dup("ext4fs");
    40         mnt_initrd->data.mnt.mountpoint = str_dup("/");
    41         mnt_initrd->data.mnt.device     = str_dup("bd/initrd");
     40        CAST_MNT(mnt_initrd)->type       = str_dup("ext4fs");
     41        CAST_MNT(mnt_initrd)->mountpoint = str_dup("/");
     42        CAST_MNT(mnt_initrd)->device     = str_dup("bd/initrd");
    4243
    4344        cfg_init = unit_create(UNIT_CONFIGURATION);
     
    4647                goto fail;
    4748        }
    48         cfg_init->data.cfg.path = str_dup("/cfg/");
     49        cfg_init->name           = str_dup("init.cfg");
     50        CAST_CFG(cfg_init)->path = str_dup("/cfg/sysman");
    4951       
    5052        tgt_default = unit_create(UNIT_TARGET);
     
    5355                goto fail;
    5456        }
     57        tgt_default->name = str_dup("default.tgt");
    5558       
    5659
     
    5861         * Add units to configuration and start the default target.
    5962         */
     63        configuration_start_update();
     64
    6065        configuration_add_unit(mnt_initrd);
    6166        configuration_add_unit(cfg_init);
  • uspace/srv/sysman/sysman.c

    r6006f35 rbb154c6  
    2222        job->unit = unit;
    2323
    24         list_foreach(unit->dependencies, dependencies, unit_dependency_t, edge) {
     24        list_foreach(unit->dependencies, dependencies, unit_dependency_t, dep) {
    2525                job_t *blocking_job = NULL;
    26                 rc = sysman_create_closure_jobs(edge->dependency, &blocking_job,
     26                rc = sysman_create_closure_jobs(dep->dependency, &blocking_job,
    2727                    accumulator, type);
    2828                if (rc != EOK) {
     
    5555
    5656        job_t *job = NULL;
     57        // TODO shouldn't be here read-lock on configuration?
    5758        int rc = sysman_create_closure_jobs(unit, &job, &new_jobs, JOB_START);
    5859        if (rc != EOK) {
  • uspace/srv/sysman/unit.c

    r6006f35 rbb154c6  
    22#include <errno.h>
    33#include <fibril_synch.h>
     4#include <conf/configuration.h>
     5#include <conf/ini.h>
    46#include <mem.h>
     7#include <stddef.h>
    58#include <stdio.h>
    69#include <stdlib.h>
     10#include <str.h>
    711
     12#include "dep.h"
    813#include "log.h"
    914#include "unit.h"
    1015
    1116/** Virtual method table for each unit type */
    12 static unit_ops_t *unit_type_vmts[] = {
     17unit_vmt_t *unit_type_vmts[] = {
    1318        [UNIT_TARGET]        = &unit_tgt_ops,
    1419        [UNIT_MOUNT]         = &unit_mnt_ops,
     
    1621};
    1722
     23static const char *section_name = "Unit";
     24
     25static config_item_t unit_configuration[] = {
     26        {"After", &unit_parse_unit_list, 0, ""},
     27        CONFIGURATION_ITEM_SENTINEL
     28};
     29
     30
    1831static void unit_init(unit_t *unit, unit_type_t type)
    1932{
    2033        assert(unit);
    2134
     35        // TODO is this necessary?
    2236        memset(unit, 0, sizeof(unit_t));
    23         link_initialize(&unit->units);
    2437       
    2538        unit->type = type;
     39        unit->name = NULL;
     40
    2641        unit->state = STATE_EMBRYO;
    2742        fibril_mutex_initialize(&unit->state_mtx);
     
    3146        list_initialize(&unit->dependencies);
    3247
    33         unit_type_vmts[unit->type]->init(unit);
     48        UNIT_VMT(unit)->init(unit);
    3449}
    3550
    3651unit_t *unit_create(unit_type_t type)
    3752{
    38         unit_t *unit = malloc(sizeof(unit_t));
     53        size_t size = unit_type_vmts[type]->size;
     54        unit_t *unit = malloc(size);
    3955        if (unit != NULL) {
    4056                unit_init(unit, type);
     
    5066                return;
    5167
    52         unit_type_vmts[unit->type]->destroy(unit);
     68        UNIT_VMT(unit)->destroy(unit);
    5369        /* TODO:
    5470         *      edges,
     
    5672         *      other resources to come
    5773         */
     74        free(unit->name);
    5875        free(unit);
    5976        unit_ptr = NULL;
     
    7592int unit_start(unit_t *unit)
    7693{
    77         sysman_log(LVL_DEBUG, "%s(%p)", __func__, unit);
    78         return unit_type_vmts[unit->type]->start(unit);
     94        sysman_log(LVL_DEBUG, "%s('%s')", __func__, unit_name(unit));
     95        return UNIT_VMT(unit)->start(unit);
    7996}
     97
     98int unit_load(unit_t *unit, ini_configuration_t *ini_conf,
     99    text_parse_t *text_parse)
     100{
     101        sysman_log(LVL_DEBUG, "%s('%s')", __func__, unit_name(unit));
     102
     103        int rc = EOK;
     104        ini_section_t *unit_section = ini_get_section(ini_conf, section_name);
     105        if (unit_section) {
     106                rc = config_load_ini_section(unit_configuration,
     107                    unit_section, unit, text_parse);
     108        }
     109                               
     110        if (rc != EOK) {
     111                return rc;
     112        } else {
     113                return UNIT_VMT(unit)->load(unit, ini_conf, text_parse);
     114        }
     115}
     116
     117unit_type_t unit_type_name_to_type(const char *type_name)
     118{
     119        if (str_cmp(type_name, "cfg") == 0)
     120                return UNIT_CONFIGURATION;
     121
     122        else if (str_cmp(type_name, "mnt") == 0)
     123                return UNIT_MOUNT;
     124
     125        else if (str_cmp(type_name, "tgt") == 0)
     126                return UNIT_TARGET;
     127
     128        else
     129                return UNIT_TYPE_INVALID;
     130}
     131
     132/** Format unit name to be presented to user */
     133const char *unit_name(const unit_t *unit)
     134{
     135        return unit->name ? unit->name : "";
     136}
     137
     138
     139
     140
     141bool unit_parse_unit_list(const char *value, void *dst, text_parse_t *parse,
     142    size_t lineno)
     143{
     144        unit_t *unit = dst;
     145        bool result;
     146        char *my_value = str_dup(value);
     147
     148        if (!my_value) {
     149                result = false;
     150                goto finish;
     151        }
     152
     153        char *to_split = my_value;
     154        char *cur_tok;
     155
     156        while ((cur_tok = str_tok(to_split, " ", &to_split))) {
     157                if (dep_sprout_dependency(unit, cur_tok) != EOK) {
     158                        result = false;
     159                        goto finish;
     160                }
     161        }
     162
     163        result = true;
     164
     165finish:
     166        free(my_value);
     167        return result;
     168}
  • uspace/srv/sysman/unit.h

    r6006f35 rbb154c6  
     1/*
     2 * Unit terminology and OOP based on systemd.
     3 */
    14#ifndef SYSMAN_UNIT_H
    25#define SYSMAN_UNIT_H
    36
     7#include <adt/hash_table.h>
    48#include <adt/list.h>
     9#include <conf/configuration.h>
     10#include <conf/ini.h>
     11#include <conf/text_parse.h>
    512#include <fibril_synch.h>
    613
    7 #include "unit_mnt.h"
    8 #include "unit_cfg.h"
    9 #include "unit_tgt.h"
    10 #include "unit_types.h"
     14typedef enum {
     15        UNIT_TYPE_INVALID = -1,
     16        UNIT_TARGET = 0,
     17        UNIT_MOUNT,
     18        UNIT_CONFIGURATION,
     19} unit_type_t;
    1120
    12 struct unit {
    13         link_t units;
     21typedef enum {
     22        STATE_EMBRYO = 0,
     23        STATE_STARTING,
     24        STATE_STARTED,
     25        STATE_STOPPED,
     26        STATE_FAILED
     27} unit_state_t;
     28
     29typedef struct {
     30        ht_link_t units;
    1431
    1532        unit_type_t type;
     33        char *name;
    1634
    1735        unit_state_t state;
     
    2139        list_t dependencies;
    2240        list_t dependants;
     41} unit_t;
    2342
    24         union {
    25                 unit_mnt_t mnt;
    26                 unit_cfg_t cfg;
    27         } data;
     43typedef struct unit_vmt unit_vmt_t;
     44struct unit_vmt;
     45
     46#include "unit_cfg.h"
     47#include "unit_mnt.h"
     48#include "unit_tgt.h"
     49
     50#define DEFINE_CAST(NAME, TYPE, ENUM_TYPE)                           \
     51        static inline TYPE *CAST_##NAME(unit_t *u)                   \
     52        {                                                            \
     53                if (u->type == ENUM_TYPE)                            \
     54                        return (TYPE *)u;                            \
     55                else                                                 \
     56                        return NULL;                                 \
     57        }                                                            \
     58
     59DEFINE_CAST(CFG, unit_cfg_t, UNIT_CONFIGURATION)
     60DEFINE_CAST(MNT, unit_mnt_t, UNIT_MOUNT)
     61DEFINE_CAST(TGT, unit_tgt_t, UNIT_TARGET)
     62
     63struct unit_vmt {
     64        size_t size;
     65
     66        void (*init)(unit_t *);
     67
     68        void (*destroy)(unit_t *);
     69
     70        int (*load)(unit_t *, ini_configuration_t *, text_parse_t *);
     71
     72        int (*start)(unit_t *);
    2873};
    2974
     75extern unit_vmt_t *unit_type_vmts[];
     76
     77#define DEFINE_UNIT_VMT(PREFIX)                                      \
     78        unit_vmt_t PREFIX##_ops = {                                  \
     79                .size    = sizeof(PREFIX##_t),                       \
     80                .init    = &PREFIX##_init,                           \
     81                .load    = &PREFIX##_load,                           \
     82                .destroy = &PREFIX##_destroy,                        \
     83                .start   = &PREFIX##_start                           \
     84        };
     85
     86#define UNIT_VMT(UNIT) unit_type_vmts[(UNIT)->type]
    3087
    3188extern unit_t *unit_create(unit_type_t);
     
    3592extern void unit_set_state(unit_t *, unit_state_t);
    3693
     94extern int unit_load(unit_t *, ini_configuration_t *, text_parse_t *);
    3795extern int unit_start(unit_t *);
    3896
     97extern unit_type_t unit_type_name_to_type(const char *);
     98
     99extern const char *unit_name(const unit_t *);
     100
     101extern bool unit_parse_unit_list(const char *, void *, text_parse_t *, size_t);
     102
    39103#endif
  • uspace/srv/sysman/units/unit_cfg.c

    r6006f35 rbb154c6  
     1#include <adt/list.h>
     2#include <assert.h>
     3#include <conf/configuration.h>
     4#include <conf/ini.h>
     5#include <conf/text_parse.h>
     6#include <dirent.h>
    17#include <errno.h>
    2 
    3 #include "unit_cfg.h"
     8#include <stdlib.h>
     9#include <str.h>
     10
     11#include "configuration.h"
     12#include "log.h"
     13#include "unit.h"
     14#include "util.h"
     15
     16static const char *section_name = "Configuration";
     17
     18static config_item_t unit_configuration[] = {
     19        {"Path", &config_parse_string, offsetof(unit_cfg_t, path), NULL},
     20        CONFIGURATION_ITEM_SENTINEL
     21};
     22
     23/**
     24 * TODO refactor path handling and rename to 'load from file'
     25 *
     26 * @param[out]  unit_ptr   Unit loaded from the file. Undefined when function fails.
     27 */
     28static int cfg_parse_file(const char *dirname, const char *filename,
     29    unit_t **unit_ptr)
     30{
     31        int rc = EOK;
     32        unit_t *new_unit = NULL;
     33        char *fn = NULL;
     34        ini_configuration_t ini_conf;
     35        text_parse_t text_parse;
     36
     37        ini_configuration_init(&ini_conf);
     38        text_parse_init(&text_parse);
     39
     40        const char *last_dot = str_rchr(filename, '.');
     41        if (last_dot == NULL) {
     42                rc = EINVAL;
     43                goto finish;
     44        }
     45
     46        const char *unit_name = filename;
     47        const char *unit_type_name = last_dot + 1;
     48
     49        unit_type_t unit_type = unit_type_name_to_type(unit_type_name);
     50        if (unit_type == UNIT_TYPE_INVALID) {
     51                rc = EINVAL;
     52                goto finish;
     53        }
     54       
     55        unit_t *u = configuration_find_unit_by_name(unit_name);
     56        if (u != NULL) {
     57                // TODO allow updating configuration of existing unit
     58                rc = EEXISTS;
     59                goto finish;
     60        } else {
     61                new_unit = u = unit_create(unit_type);
     62                new_unit->name = str_dup(unit_name);
     63                if (new_unit->name == NULL) {
     64                        rc = ENOMEM;
     65                        goto finish;
     66                }
     67        }
     68        if (u == NULL) {
     69                rc = ENOMEM;
     70                goto finish;
     71        }
     72        assert(u->type == unit_type);
     73
     74        fn = compose_path(dirname, filename);
     75        if (fn == NULL) {
     76                rc = ENOMEM;
     77                goto finish;
     78        }
     79
     80        /* Parse INI file to ini_conf structure */
     81        rc = ini_parse_file(fn, &ini_conf, &text_parse);
     82        switch (rc) {
     83        case EOK:
     84                /* This is fine */
     85                break;
     86        case EINVAL:
     87                goto dump_parse;
     88                break;
     89        default:
     90                sysman_log(LVL_WARN,
     91                    "Cannot parse '%s' (%i).", fn, rc);
     92                goto finish;
     93        }
     94
     95        /* Parse ini structure */
     96        rc = unit_load(u, &ini_conf, &text_parse);
     97        *unit_ptr = u;
     98
     99        /*
     100         * Here we just continue undisturbed by errors, they'll be returned in
     101         * 'finish' block and potential parse errors (or none) will be logged
     102         * in 'dump_parse' block.
     103         */
     104
     105dump_parse:
     106        list_foreach(text_parse.errors, link, text_parse_error_t, err) {
     107                sysman_log(LVL_WARN,
     108                    "Error (%i) when parsing '%s' on line %i.",
     109                    err->parse_errno, fn, err->lineno);
     110        }
     111
     112finish:
     113        free(fn);
     114        ini_configuration_deinit(&ini_conf);
     115        text_parse_deinit(&text_parse);
     116        if (rc != EOK) {
     117                unit_destroy(&new_unit);
     118        }
     119
     120        return rc;
     121}
     122
     123static int cfg_load_configuration(const char *path)
     124{
     125        DIR *dir;
     126        struct dirent *de;
     127
     128        dir = opendir(path);
     129        if (dir == NULL) {
     130                sysman_log(LVL_ERROR,
     131                    "Cannot open configuration directory '%s'", path);
     132                return EIO;
     133        }
     134
     135        configuration_start_update();
     136
     137        while ((de = readdir(dir))) {
     138                unit_t *unit = NULL;
     139                int rc = cfg_parse_file(path, de->d_name, &unit);
     140                if (rc != EOK) {
     141                        sysman_log(LVL_WARN, "Cannot load unit from file %s/%s",
     142                            path, de->d_name);
     143                        /*
     144                         * Ignore error for now, we'll fail only when we're
     145                         * unable to resolve dependency names.
     146                         */
     147                        continue;
     148                }
     149
     150                assert(unit->state = STATE_EMBRYO);
     151                configuration_add_unit(unit);
     152        }
     153        closedir(dir);
     154
     155        int rc = configuration_resolve_dependecies();
     156        if (rc != EOK) {
     157                configuration_rollback();
     158                return rc;
     159        }
     160
     161        configuration_commit();
     162        return EOK;
     163}
    4164
    5165static void unit_cfg_init(unit_t *unit)
    6166{
    7         // TODO
     167        unit_cfg_t *u_cfg = CAST_CFG(unit);
     168        assert(u_cfg);
     169
     170        u_cfg->path = NULL;
     171}
     172
     173
     174
     175static void unit_cfg_destroy(unit_t *unit)
     176{
     177        unit_cfg_t *u_cfg = CAST_CFG(unit);
     178        assert(u_cfg);
     179
     180        free(u_cfg->path);
     181}
     182
     183static int unit_cfg_load(unit_t *unit, ini_configuration_t *ini_conf,
     184    text_parse_t *text_parse)
     185{
     186        unit_cfg_t *u_cfg = CAST_CFG(unit);
     187        assert(u_cfg);
     188
     189        ini_section_t *section = ini_get_section(ini_conf, section_name);
     190        if (section == NULL) {
     191                sysman_log(LVL_ERROR,
     192                    "Expected section '%s' in configuration of unit '%s'",
     193                    section_name, unit_name(unit));
     194                return ENOENT;
     195        }
     196
     197        return config_load_ini_section(unit_configuration, section, u_cfg,
     198            text_parse);
    8199}
    9200
    10201static int unit_cfg_start(unit_t *unit)
    11202{
    12         //TODO
    13         return EOK;
    14 }
    15 
    16 static void unit_cfg_destroy(unit_t *unit)
    17 {
    18         //TODO
    19 }
    20 
    21 
    22 DEFINE_UNIT_OPS(unit_cfg)
    23 
     203        unit_cfg_t *u_cfg = CAST_CFG(unit);
     204        assert(u_cfg);
     205
     206        /*
     207         * Skip starting state and hold state lock during whole configuration
     208         * load.
     209         */
     210        fibril_mutex_lock(&unit->state_mtx);
     211        int rc = cfg_load_configuration(u_cfg->path);
     212       
     213        if (rc == EOK) {
     214                unit->state = STATE_STARTED;
     215        } else {
     216                unit->state = STATE_FAILED;
     217        }
     218        fibril_condvar_broadcast(&unit->state_cv);
     219        fibril_mutex_unlock(&unit->state_mtx);
     220
     221        return rc;
     222}
     223
     224DEFINE_UNIT_VMT(unit_cfg)
     225
  • uspace/srv/sysman/units/unit_cfg.h

    r6006f35 rbb154c6  
    22#define SYSMAN_UNIT_CFG_H
    33
    4 #include "unit_types.h"
     4#include "unit.h"
    55
    66typedef struct {
    7         const char *path;
     7        unit_t unit;
     8
     9        char *path;
    810} unit_cfg_t;
    911
    10 extern unit_ops_t unit_cfg_ops;
     12extern unit_vmt_t unit_cfg_ops;
    1113
    1214#endif
  • uspace/srv/sysman/units/unit_mnt.c

    r6006f35 rbb154c6  
    77#include "log.h"
    88#include "unit.h"
    9 #include "unit_mnt.h"
     9
     10static const char *section_name = "Mount";
     11
     12static config_item_t unit_configuration[] = {
     13        {"What",  &config_parse_string, offsetof(unit_mnt_t, device),     NULL},
     14        {"Where", &config_parse_string, offsetof(unit_mnt_t, mountpoint), NULL},
     15        {"Type",  &config_parse_string, offsetof(unit_mnt_t, type),       NULL},
     16        CONFIGURATION_ITEM_SENTINEL
     17};
    1018
    1119static void unit_mnt_init(unit_t *unit)
    1220{
    13         assert(unit->data.mnt.type == NULL);
    14         assert(unit->data.mnt.mountpoint == NULL);
    15         assert(unit->data.mnt.device == NULL);
     21        unit_mnt_t *u_mnt = CAST_MNT(unit);
     22        assert(u_mnt);
     23
     24        u_mnt->type = NULL;
     25        u_mnt->mountpoint = NULL;
     26        u_mnt->device = NULL;
     27}
     28
     29static void unit_mnt_destroy(unit_t *unit)
     30{
     31        assert(unit->type == UNIT_MOUNT);
     32        unit_mnt_t *u_mnt = CAST_MNT(unit);
     33
     34        sysman_log(LVL_DEBUG2, "%s, %p, %p, %p", __func__,
     35            u_mnt->type, u_mnt->mountpoint, u_mnt->device);
     36        free(u_mnt->type);
     37        free(u_mnt->mountpoint);
     38        free(u_mnt->device);
     39}
     40
     41static int unit_mnt_load(unit_t *unit, ini_configuration_t *ini_conf,
     42    text_parse_t *text_parse)
     43{
     44        unit_mnt_t *u_mnt = CAST_MNT(unit);
     45        assert(u_mnt);
     46
     47        ini_section_t *section = ini_get_section(ini_conf, section_name);
     48        if (section == NULL) {
     49                sysman_log(LVL_ERROR,
     50                    "Expected section '%s' in configuration of unit '%s'",
     51                    section_name, unit_name(unit));
     52                return ENOENT;
     53        }
     54
     55        return config_load_ini_section(unit_configuration, section, u_mnt,
     56            text_parse);
    1657}
    1758
    1859static int unit_mnt_start(unit_t *unit)
    1960{
     61        unit_mnt_t *u_mnt = CAST_MNT(unit);
     62        assert(u_mnt);
     63
    2064        fibril_mutex_lock(&unit->state_mtx);
    2165       
     
    2872
    2973
    30         unit_mnt_t *data = &unit->data.mnt;
    31 
    3274        // TODO use other mount parameters
    33         int rc = mount(data->type, data->mountpoint, data->device, "",
     75        int rc = mount(u_mnt->type, u_mnt->mountpoint, u_mnt->device, "",
    3476            IPC_FLAG_BLOCKING, 0);
    3577
    3678        if (rc == EOK) {
    37                 sysman_log(LVL_NOTE, "Mount (%p) mounted", unit);
     79                sysman_log(LVL_NOTE, "Mount ('%s') mounted", unit_name(unit));
    3880                unit_set_state(unit, STATE_STARTED);
    3981        } else {
    40                 sysman_log(LVL_ERROR, "Mount (%p) failed (%i)", unit, rc);
     82                sysman_log(LVL_ERROR, "Mount ('%s') failed (%i)",
     83                    unit_name(unit), rc);
    4184                unit_set_state(unit, STATE_FAILED);
    4285        }
     
    4588}
    4689
    47 static void unit_mnt_destroy(unit_t *unit)
    48 {
    49         free(unit->data.mnt.type);
    50         free(unit->data.mnt.mountpoint);
    51         free(unit->data.mnt.device);
    52 }
     90DEFINE_UNIT_VMT(unit_mnt)
    5391
    54 
    55 DEFINE_UNIT_OPS(unit_mnt)
    56 
  • uspace/srv/sysman/units/unit_mnt.h

    r6006f35 rbb154c6  
    22#define SYSMAN_UNIT_MNT_H
    33
    4 #include "unit_types.h"
     4#include "unit.h"
    55
    66typedef struct {
    7         const char *type;
    8         const char *mountpoint;
    9         const char *device;
     7        unit_t unit;
     8
     9        char *type;
     10        char *mountpoint;
     11        char *device;
    1012} unit_mnt_t;
    1113
    12 extern unit_ops_t unit_mnt_ops;
    13 
     14extern unit_vmt_t unit_mnt_ops;
    1415
    1516#endif
  • uspace/srv/sysman/units/unit_tgt.c

    r6006f35 rbb154c6  
    11#include <errno.h>
    22
    3 #include "unit_tgt.h"
     3#include "unit.h"
    44
    55static void unit_tgt_init(unit_t *unit)
    66{
    7         // TODO
     7        unit_tgt_t *u_tgt = CAST_TGT(unit);
     8        assert(u_tgt);
     9        /* Nothing more to do */
     10}
     11
     12static void unit_tgt_destroy(unit_t *unit)
     13{
     14        unit_tgt_t *u_tgt = CAST_TGT(unit);
     15        assert(u_tgt);
     16        /* Nothing more to do */
     17}
     18
     19static int unit_tgt_load(unit_t *unit, ini_configuration_t *ini_conf,
     20    text_parse_t *text_parse)
     21{
     22        unit_tgt_t *u_tgt = CAST_TGT(unit);
     23        assert(u_tgt);
     24
     25        return EOK;
    826}
    927
    1028static int unit_tgt_start(unit_t *unit)
    1129{
    12         //TODO
     30        unit_tgt_t *u_tgt = CAST_TGT(unit);
     31        assert(u_tgt);
     32
    1333        return EOK;
    1434}
    1535
    16 static void unit_tgt_destroy(unit_t *unit)
    17 {
    18         //TODO
    19 }
     36DEFINE_UNIT_VMT(unit_tgt)
    2037
    21 
    22 DEFINE_UNIT_OPS(unit_tgt)
    23 
  • uspace/srv/sysman/units/unit_tgt.h

    r6006f35 rbb154c6  
    22#define SYSMAN_UNIT_TGT_H
    33
    4 #include "unit_types.h"
     4#include "unit.h"
    55
    6 extern unit_ops_t unit_tgt_ops;
     6typedef struct {
     7        unit_t unit;
     8} unit_tgt_t;
     9
     10extern unit_vmt_t unit_tgt_ops;
    711
    812#endif
Note: See TracChangeset for help on using the changeset viewer.