Changeset bb154c6 in mainline for uspace/srv/sysman/configuration.c


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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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
Note: See TracChangeset for help on using the changeset viewer.