source: mainline/uspace/srv/sysman/unit.c@ aa0faeca

Last change on this file since aa0faeca was aa0faeca, checked in by Matthieu Riolo <matthieu.riolo@…>, 5 years ago

Adding "ConditionArchitecture" to sysman's unit

the services s3c24xx_uart and s3c24xx_ts are specific for
arm32. This newly flag allows sysman to ignore those units
when they are asked to be loaded

  • Property mode set to 100644
File size: 7.2 KB
RevLine 
[09a8006]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
[f42ee6f]29#include <assert.h>
[694253c]30#include <errno.h>
31#include <fibril_synch.h>
[bb154c6]32#include <conf/configuration.h>
33#include <conf/ini.h>
[f42ee6f]34#include <mem.h>
[bb154c6]35#include <stddef.h>
[694253c]36#include <stdio.h>
[f42ee6f]37#include <stdlib.h>
[bb154c6]38#include <str.h>
[5559712]39#include <sysman/unit.h>
[f42ee6f]40
[9532981]41#include "edge.h"
[6efec7e3]42#include "log.h"
[5559712]43#include "sysman.h"
[f42ee6f]44#include "unit.h"
45
[6efec7e3]46/** Virtual method table for each unit type */
[bb154c6]47unit_vmt_t *unit_type_vmts[] = {
[5559712]48 [UNIT_CONFIGURATION] = &unit_cfg_vmt,
49 [UNIT_MOUNT] = &unit_mnt_vmt,
50 [UNIT_TARGET] = &unit_tgt_vmt,
51 [UNIT_SERVICE] = &unit_svc_vmt
[6efec7e3]52};
53
[bb154c6]54static const char *section_name = "Unit";
55
56static config_item_t unit_configuration[] = {
[102f641]57 { "After", &unit_parse_unit_list, 0, "" },
[aa0faeca]58 { "ConditionArchitecture", &unit_parse_condition_architecture, 0, "" },
[bb154c6]59 CONFIGURATION_ITEM_SENTINEL
60};
61
[f42ee6f]62static void unit_init(unit_t *unit, unit_type_t type)
63{
64 assert(unit);
65
[5559712]66 size_t size = unit_type_vmts[type]->size;
67 memset(unit, 0, size);
[102f641]68
[f42ee6f]69 unit->type = type;
[8ae8262]70 unit->state = STATE_STOPPED;
71 unit->repo_state = REPO_EMBRYO;
[aa0faeca]72 unit->conditions = UNIT_CONDITION_NONE;
[694253c]73
[dda2602]74 link_initialize(&unit->units);
75 link_initialize(&unit->bfs_link);
[9532981]76 list_initialize(&unit->edges_in);
77 list_initialize(&unit->edges_out);
[6efec7e3]78
[bb154c6]79 UNIT_VMT(unit)->init(unit);
[f42ee6f]80}
81
82unit_t *unit_create(unit_type_t type)
83{
[bb154c6]84 size_t size = unit_type_vmts[type]->size;
85 unit_t *unit = malloc(size);
[f42ee6f]86 if (unit != NULL) {
87 unit_init(unit, type);
88 }
89 return unit;
90}
91
92/** Release resources used by unit structure */
[6efec7e3]93void unit_destroy(unit_t **unit_ptr)
[f42ee6f]94{
[6efec7e3]95 unit_t *unit = *unit_ptr;
96 if (unit == NULL)
[f42ee6f]97 return;
[6efec7e3]98
[bb154c6]99 UNIT_VMT(unit)->destroy(unit);
[102f641]100 /*
101 * TODO:
[01e68af]102 * edges
[f42ee6f]103 */
[bb154c6]104 free(unit->name);
[6efec7e3]105 free(unit);
106 unit_ptr = NULL;
107}
108
[25697163]109errno_t unit_load(unit_t *unit, ini_configuration_t *ini_conf,
[5559712]110 text_parse_t *text_parse)
111{
112 sysman_log(LVL_DEBUG, "%s('%s')", __func__, unit_name(unit));
113
[25697163]114 errno_t rc = EOK;
[5559712]115 ini_section_t *unit_section = ini_get_section(ini_conf, section_name);
116 if (unit_section) {
117 rc = config_load_ini_section(unit_configuration,
118 unit_section, unit, text_parse);
119 }
[102f641]120
[5559712]121 if (rc != EOK) {
122 return rc;
123 } else {
124 return UNIT_VMT(unit)->load(unit, ini_conf, text_parse);
125 }
126}
[694253c]127
128/** Issue request to restarter to start a unit
129 *
[3f7e1f24]130 * Ideally this function is non-blocking synchronous, however, some units
131 * cannot be started synchronously and thus return from this function generally
132 * means that start was requested.
133 *
134 * Check state of the unit for actual result, start method can end in states:
135 * - STATE_STARTED, (succesful synchronous start)
136 * - STATE_STARTING, (succesful asynchronous start request)
[5559712]137 * - STATE_FAILED. (unit state changed and error occured)
[694253c]138 */
[25697163]139errno_t unit_start(unit_t *unit)
[694253c]140{
[aa0faeca]141 assert(unit->conditions == UNIT_CONDITION_NONE);
[f92b315]142 sysman_log(LVL_NOTE, "%s('%s')", __func__, unit_name(unit));
[bb154c6]143 return UNIT_VMT(unit)->start(unit);
144}
145
[ed5367b]146/** Issue request to restarter to stop a unit
147 *
148 * Same semantics like for unit_start applies.
149 */
[25697163]150errno_t unit_stop(unit_t *unit)
[ed5367b]151{
[aa0faeca]152 assert(unit->conditions == UNIT_CONDITION_NONE);
[f92b315]153 sysman_log(LVL_NOTE, "%s('%s')", __func__, unit_name(unit));
[ed5367b]154 return UNIT_VMT(unit)->stop(unit);
155}
156
[5559712]157void unit_exposee_created(unit_t *unit)
[bb154c6]158{
[f92b315]159 sysman_log(LVL_DEBUG2, "%s('%s')", __func__, unit_name(unit));
[5559712]160 return UNIT_VMT(unit)->exposee_created(unit);
161}
[bb154c6]162
[5559712]163void unit_fail(unit_t *unit)
164{
[f92b315]165 sysman_log(LVL_WARN, "%s('%s')", __func__, unit_name(unit));
[5559712]166 return UNIT_VMT(unit)->fail(unit);
167}
168
169void unit_notify_state(unit_t *unit)
170{
171 sysman_raise_event(&sysman_event_unit_state_changed, unit);
[bb154c6]172}
173
[9532981]174// TODO move to libsysman
[bb154c6]175unit_type_t unit_type_name_to_type(const char *type_name)
176{
[5559712]177 if (str_cmp(type_name, UNIT_CFG_TYPE_NAME) == 0)
[bb154c6]178 return UNIT_CONFIGURATION;
179
[5559712]180 else if (str_cmp(type_name, UNIT_MNT_TYPE_NAME) == 0)
[bb154c6]181 return UNIT_MOUNT;
182
[5559712]183 else if (str_cmp(type_name, UNIT_TGT_TYPE_NAME) == 0)
[bb154c6]184 return UNIT_TARGET;
185
[5559712]186 else if (str_cmp(type_name, UNIT_SVC_TYPE_NAME) == 0)
187 return UNIT_SERVICE;
188
[bb154c6]189 else
190 return UNIT_TYPE_INVALID;
191}
192
193/** Format unit name to be presented to user */
194const char *unit_name(const unit_t *unit)
195{
196 return unit->name ? unit->name : "";
197}
198
[aa0faeca]199/**
200 * Logs a message for the failed conditions of a unit
201 */
202void unit_log_condition(unit_t *unit)
203{
204 assert(unit->conditions != UNIT_CONDITION_NONE);
205 unit_condition_t conditions = unit->conditions;
206 while (conditions != UNIT_CONDITION_NONE) {
207 const char *type = NULL;
208 if (conditions & UNIT_CONDITION_ARCHITECTURE) {
209 conditions ^= UNIT_CONDITION_ARCHITECTURE;
210 type = "architecture";
211 } else {
212 sysman_log(
213 LVL_NOTE,
214 "Condition restriction: unit '%s' does not meet the unkown condition '%d'",
215 unit_name(unit),
216 conditions);
217 return;
218 }
219
220 sysman_log(
221 LVL_NOTE,
222 "Condition restriction: unit '%s' does not meet the '%s' condition",
223 unit_name(unit),
224 type);
225 }
226}
227
[dda2602]228bool unit_parse_unit_list(const char *string, void *dst, text_parse_t *parse,
[bb154c6]229 size_t lineno)
230{
231 unit_t *unit = dst;
232 bool result;
[dda2602]233 char *my_string = str_dup(string);
[bb154c6]234
[dda2602]235 if (!my_string) {
[bb154c6]236 result = false;
237 goto finish;
238 }
239
[dda2602]240 char *to_split = my_string;
[bb154c6]241 char *cur_tok;
242
243 while ((cur_tok = str_tok(to_split, " ", &to_split))) {
[9532981]244 if (edge_sprout_out(unit, cur_tok) != EOK) {
[bb154c6]245 result = false;
246 goto finish;
247 }
248 }
249
250 result = true;
251
252finish:
[dda2602]253 free(my_string);
[bb154c6]254 return result;
[694253c]255}
[aa0faeca]256
257bool unit_parse_condition_architecture(const char *string, void *dst, text_parse_t *parse,
258 size_t lineno)
259{
260 unit_t *unit = dst;
261 bool result = true;
262 char *str = NULL;
263
264 if (str_length(string) == 0) {
265 goto finish;
266 }
267
268 str = str_dup(string);
269 if (str == NULL) {
270 result = false;
271 goto finish;
272 }
273
274 char *split = str;
275 char *tok;
276 bool conditions = false;
277 while ((tok = str_tok(split, " ", &split))) {
278 if (str_casecmp(tok, STRING(UARCH)) == 0) {
279 conditions = true;
280 break;
281 }
282 }
283
284 if (!conditions) {
285 unit->conditions |= UNIT_CONDITION_ARCHITECTURE;
286 }
287
288finish:
289 free(str);
290 return result;
291}
Note: See TracBrowser for help on using the repository browser.