Changeset bb154c6 in mainline for uspace/srv/sysman/units/unit_cfg.c
- Timestamp:
- 2019-08-03T08:15:25Z (6 years ago)
- 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)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
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> 1 7 #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 16 static const char *section_name = "Configuration"; 17 18 static 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 */ 28 static 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 105 dump_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 112 finish: 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 123 static 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 } 4 164 5 165 static void unit_cfg_init(unit_t *unit) 6 166 { 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 175 static 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 183 static 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); 8 199 } 9 200 10 201 static int unit_cfg_start(unit_t *unit) 11 202 { 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 224 DEFINE_UNIT_VMT(unit_cfg) 225
Note:
See TracChangeset
for help on using the changeset viewer.