source: mainline/uspace/srv/sysman/configuration.c@ 2dda1d4

Last change on this file since 2dda1d4 was 3f7e1f24, checked in by Matthieu Riolo <matthieu.riolo@…>, 6 years ago

sysman: Refactored job manipulation (event loop + one main fibril)

  • Property mode set to 100644
File size: 5.7 KB
Line 
1/*
2 * Copyright (c) 2015 Michal Koutny
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <adt/hash.h>
30#include <adt/hash_table.h>
31#include <adt/list.h>
32#include <assert.h>
33#include <errno.h>
34#include <fibril_synch.h>
35
36#include "configuration.h"
37#include "dep.h"
38#include "log.h"
39
40static hash_table_t units;
41
42/* Hash table functions */
43static size_t units_ht_hash(const ht_link_t *item)
44{
45 unit_t *unit =
46 hash_table_get_inst(item, unit_t, units);
47 return hash_string(unit->name);
48}
49
50static size_t units_ht_key_hash(void *key)
51{
52 return hash_string((const char *)key);
53}
54
55static bool units_ht_equal(const ht_link_t *item1, const ht_link_t *item2)
56{
57 return str_cmp(
58 hash_table_get_inst(item1, unit_t, units)->name,
59 hash_table_get_inst(item2, unit_t, units)->name) == 0;
60}
61
62static bool units_ht_key_equal(void *key, const ht_link_t *item)
63{
64 return str_cmp((const char *)key,
65 hash_table_get_inst(item, unit_t, units)->name) == 0;
66}
67
68
69static hash_table_ops_t units_ht_ops = {
70 .hash = &units_ht_hash,
71 .key_hash = &units_ht_key_hash,
72 .equal = &units_ht_equal,
73 .key_equal = &units_ht_key_equal,
74 .remove_callback = NULL // TODO realy unneeded?
75};
76
77/* Configuration functions */
78
79void configuration_init(void)
80{
81 hash_table_create(&units, 0, 0, &units_ht_ops);
82}
83
84int configuration_add_unit(unit_t *unit)
85{
86 assert(unit);
87 assert(unit->state == STATE_EMBRYO);
88 assert(unit->name != NULL);
89 sysman_log(LVL_DEBUG2, "%s('%s')", __func__, unit_name(unit));
90
91 if (hash_table_insert_unique(&units, &unit->units)) {
92 return EOK;
93 } else {
94 return EEXISTS;
95 }
96}
97
98void configuration_start_update(void) {
99 sysman_log(LVL_DEBUG2, "%s", __func__);
100}
101
102static bool configuration_commit_unit(ht_link_t *ht_link, void *arg)
103{
104 unit_t *unit = hash_table_get_inst(ht_link, unit_t, units);
105 // TODO state locking?
106 if (unit->state == STATE_EMBRYO) {
107 unit->state = STATE_STOPPED;
108 }
109
110 list_foreach(unit->dependencies, dependencies, unit_dependency_t, dep) {
111 if (dep->state == DEP_EMBRYO) {
112 dep->state = DEP_VALID;
113 }
114 }
115 return true;
116}
117
118/** Marks newly added units as usable (via state change) */
119void configuration_commit(void)
120{
121 sysman_log(LVL_DEBUG2, "%s", __func__);
122
123 /*
124 * Apply commit to all units, each commited unit commits its outgoing
125 * deps, thus eventually commiting all embryo deps as well.
126 */
127 hash_table_apply(&units, &configuration_commit_unit, NULL);
128}
129
130static bool configuration_rollback_unit(ht_link_t *ht_link, void *arg)
131{
132 unit_t *unit = hash_table_get_inst(ht_link, unit_t, units);
133
134 list_foreach_safe(unit->dependencies, cur_link, next_link) {
135 unit_dependency_t *dep =
136 list_get_instance(cur_link, unit_dependency_t, dependencies);
137 if (dep->state == DEP_EMBRYO) {
138 dep_remove_dependency(&dep);
139 }
140 }
141
142 if (unit->state == STATE_EMBRYO) {
143 hash_table_remove_item(&units, ht_link);
144 unit_destroy(&unit);
145 }
146
147 return true;
148}
149
150void configuration_rollback(void)
151{
152 sysman_log(LVL_DEBUG2, "%s", __func__);
153
154 hash_table_apply(&units, &configuration_rollback_unit, NULL);
155}
156
157static bool configuration_resolve_unit(ht_link_t *ht_link, void *arg)
158{
159 bool *has_error_ptr = arg;
160 unit_t *unit = hash_table_get_inst(ht_link, unit_t, units);
161
162 list_foreach(unit->dependencies, dependencies, unit_dependency_t, dep) {
163 assert(dep->dependant == unit);
164 assert((dep->dependency != NULL) != (dep->dependency_name != NULL));
165 if (dep->dependency) {
166 continue;
167 }
168
169 unit_t *dependency =
170 configuration_find_unit_by_name(dep->dependency_name);
171 if (dependency == NULL) {
172 sysman_log(LVL_ERROR,
173 "Cannot resolve dependency of '%s' to unit '%s'",
174 unit_name(unit), dep->dependency_name);
175 *has_error_ptr = true;
176 // TODO should we just leave the sprout untouched?
177 } else {
178 dep_resolve_dependency(dep, dependency);
179 }
180 }
181
182 return true;
183}
184
185/** Resolve unresolved dependencies between any pair of units
186 *
187 * @return EOK on success
188 * @return ENONENT when one or more resolution fails, information is logged
189 */
190int configuration_resolve_dependecies(void)
191{
192 sysman_log(LVL_DEBUG2, "%s", __func__);
193
194 bool has_error = false;
195 hash_table_apply(&units, &configuration_resolve_unit, &has_error);
196
197 return has_error ? ENOENT : EOK;
198}
199
200unit_t *configuration_find_unit_by_name(const char *name)
201{
202 ht_link_t *ht_link = hash_table_find(&units, (void *)name);
203 if (ht_link != NULL) {
204 return hash_table_get_inst(ht_link, unit_t, units);
205 } else {
206 return NULL;
207 }
208}
209
Note: See TracBrowser for help on using the repository browser.