source: mainline/uspace/srv/sysman/main.c@ 25a9fec

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

sysman: Refactor job.c into job_queue.c and job_closure.c

  • Property mode set to 100644
File size: 6.3 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 <async.h>
30#include <errno.h>
31#include <fibril.h>
[5559712]32#include <ipc/sysman.h>
33#include <macros.h>
34#include <ns.h>
[f42ee6f]35#include <stddef.h>
36#include <stdio.h>
[6efec7e3]37#include <str.h>
[f42ee6f]38
[af92309]39#include "repo.h"
[5559712]40#include "connection_broker.h"
41#include "connection_ctl.h"
[9532981]42#include "edge.h"
[25a9fec]43#include "job_queue.h"
[3f7e1f24]44#include "log.h"
[f42ee6f]45#include "sysman.h"
[e8747bd8]46#include "sm_task.h"
[f42ee6f]47#include "unit.h"
48
49#define NAME "sysman"
50
[5559712]51#define INITRD_DEVICE "bd/initrd"
52#define INITRD_MOUNT_POINT "/"
53#define INITRD_CFG_PATH "/cfg/sysman"
54
55#define TARGET_INIT "initrd.tgt"
56#define TARGET_ROOTFS "rootfs.tgt"
57#define TARGET_DEFAULT "default.tgt"
58
59#define UNIT_MNT_INITRD "initrd.mnt"
60#define UNIT_CFG_INITRD "init.cfg"
61
[73f7c4e]62
[5559712]63static const char *target_sequence[] = {
64 TARGET_INIT,
65 TARGET_ROOTFS,
66 TARGET_DEFAULT,
67 NULL
68};
69
70/*
71 * Forward declarations
72 */
73static void prepare_and_run_job(const char **target_name_ptr);
74
75/*
76 * Static functions
77 */
78
79static void sysman_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
[f42ee6f]80{
[5559712]81 sysman_interface_t iface = IPC_GET_ARG1(*icall);
82 switch (iface) {
83 case SYSMAN_PORT_BROKER:
84 sysman_connection_broker(iid, icall);
85 break;
86 case SYSMAN_PORT_CTL:
87 sysman_connection_ctl(iid, icall);
88 break;
89 default:
90 /* Unknown interface */
91 async_answer_0(iid, ENOENT);
92 }
[f42ee6f]93}
94
[3f7e1f24]95/** Build hard coded configuration */
[5559712]96static int create_entry_configuration(void) {
97 int rc;
[f42ee6f]98 unit_t *mnt_initrd = NULL;
99 unit_t *cfg_init = NULL;
[5559712]100 unit_t *tgt_init = NULL;
[f42ee6f]101
102 mnt_initrd = unit_create(UNIT_MOUNT);
103 if (mnt_initrd == NULL) {
[5559712]104 rc = ENOMEM;
[f42ee6f]105 goto fail;
106 }
[5559712]107 mnt_initrd->name = str_dup(UNIT_MNT_INITRD);
108 CAST_MNT(mnt_initrd)->type = str_dup(STRING(RDFMT));
109 CAST_MNT(mnt_initrd)->mountpoint = str_dup(INITRD_MOUNT_POINT);
110 CAST_MNT(mnt_initrd)->device = str_dup(INITRD_DEVICE);
111 CAST_MNT(mnt_initrd)->autostart = false;
112 CAST_MNT(mnt_initrd)->blocking = true;
[f42ee6f]113
114 cfg_init = unit_create(UNIT_CONFIGURATION);
115 if (cfg_init == NULL) {
[5559712]116 rc = ENOMEM;
[f42ee6f]117 goto fail;
118 }
[5559712]119 cfg_init->name = str_dup(UNIT_CFG_INITRD);
120 CAST_CFG(cfg_init)->path = str_dup(INITRD_CFG_PATH);
[f42ee6f]121
[5559712]122 tgt_init = unit_create(UNIT_TARGET);
123 if (tgt_init == NULL) {
124 rc = ENOMEM;
[f42ee6f]125 goto fail;
126 }
[5559712]127 tgt_init->name = str_dup(TARGET_INIT);
[f42ee6f]128
129
130 /*
131 * Add units to configuration and start the default target.
132 */
[af92309]133 repo_begin_update();
[bb154c6]134
[af92309]135 repo_add_unit(mnt_initrd);
136 repo_add_unit(cfg_init);
137 repo_add_unit(tgt_init);
[f42ee6f]138
[9532981]139 rc = edge_connect(tgt_init, cfg_init);
[5559712]140 if (rc != EOK) {
141 goto rollback;
[f42ee6f]142 }
143
[9532981]144 rc = edge_connect(cfg_init, mnt_initrd);
[5559712]145 if (rc != EOK) {
146 goto rollback;
[f42ee6f]147 }
148
[af92309]149 repo_commit();
[f42ee6f]150
[5559712]151 return EOK;
[f42ee6f]152
153fail:
[5559712]154 unit_destroy(&tgt_init);
[f42ee6f]155 unit_destroy(&cfg_init);
156 unit_destroy(&mnt_initrd);
[5559712]157 return rc;
158
159rollback:
[af92309]160 repo_rollback();
[5559712]161 return rc;
[3f7e1f24]162}
163
[5559712]164static void sequence_job_handler(void *object, void *arg)
[3f7e1f24]165{
166 job_t *job = object;
[5559712]167 if (job->retval == JOB_FAILED) {
168 sysman_log(LVL_ERROR, "Failed to start '%s'.", unit_name(job->unit));
169 job_del_ref(&job);
170 return;
171 }
[3f7e1f24]172 job_del_ref(&job);
[5559712]173
174 const char **target_name_ptr = arg;
175 prepare_and_run_job(target_name_ptr + 1);
176}
177
178static void prepare_and_run_job(const char **target_name_ptr)
179{
180 const char *target_name = *target_name_ptr;
181
182 if (target_name == NULL) {
183 sysman_log(LVL_NOTE, "All initial units started.");
184 return;
185 }
186
187 /* Previous targets should have loaded new units */
[af92309]188 unit_t *tgt = repo_find_unit_by_name(target_name);
[5559712]189 if (tgt == NULL) {
190 sysman_log(LVL_ERROR,
191 "Expected unit '%s' not found in configuration.",
192 target_name);
193 return;
194 }
195
[73f7c4e]196 int rc = sysman_run_job(tgt, STATE_STARTED, &sequence_job_handler,
[5559712]197 target_name_ptr);
198
199 if (rc != EOK) {
200 sysman_log(LVL_FATAL, "Cannot create job for '%s'.", target_name);
201 }
[f42ee6f]202}
203
204int main(int argc, char *argv[])
205{
206 printf(NAME ": HelenOS system daemon\n");
207
[3f7e1f24]208 /*
209 * Initialize global structures
210 */
[e8747bd8]211 // TODO check return values and abort start
[af92309]212 repo_init();
[3f7e1f24]213 sysman_events_init();
[694253c]214 job_queue_init();
[e8747bd8]215 sm_task_init();
[f42ee6f]216
217 /*
[5559712]218 * Create initial configuration while we are in a single fibril
[f42ee6f]219 */
[5559712]220 int rc = create_entry_configuration();
221 if (rc != EOK) {
222 sysman_log(LVL_FATAL,
223 "Could not create initial configuration (%i).", rc);
224 return rc;
225 }
[3f7e1f24]226
227 /*
228 * Event loop runs in separate fibril, all consequent access to global
229 * structure is made from this fibril only.
230 */
231 fid_t event_loop_fibril = fibril_create(sysman_events_loop, NULL);
232 fibril_add_ready(event_loop_fibril);
233
[012dd8e]234 sysman_log(LVL_DEBUG, "Debugging pause...\n");
[e8747bd8]235 async_usleep(1 * 1000000);
236 sysman_log(LVL_DEBUG, "Debugging pause ended.\n");
[5559712]237 /* Queue first job from sequence */
238 prepare_and_run_job(&target_sequence[0]);
239
240 /* We're service too */
241 rc = service_register(SERVICE_SYSMAN);
242 if (rc != EOK) {
243 sysman_log(LVL_FATAL,
244 "Cannot register at naming service (%i).", rc);
245 return rc;
246 }
[f42ee6f]247
[3f7e1f24]248 /* Start sysman server */
[f42ee6f]249 async_set_client_connection(sysman_connection);
250
251 printf(NAME ": Accepting connections\n");
252 async_manager();
253
[3f7e1f24]254 /* not reached */
[f42ee6f]255 return 0;
256}
Note: See TracBrowser for help on using the repository browser.