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
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 <async.h>
30#include <errno.h>
31#include <fibril.h>
32#include <ipc/sysman.h>
33#include <macros.h>
34#include <ns.h>
35#include <stddef.h>
36#include <stdio.h>
37#include <str.h>
38
39#include "repo.h"
40#include "connection_broker.h"
41#include "connection_ctl.h"
42#include "edge.h"
43#include "job_queue.h"
44#include "log.h"
45#include "sysman.h"
46#include "sm_task.h"
47#include "unit.h"
48
49#define NAME "sysman"
50
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
62
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)
80{
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 }
93}
94
95/** Build hard coded configuration */
96static int create_entry_configuration(void) {
97 int rc;
98 unit_t *mnt_initrd = NULL;
99 unit_t *cfg_init = NULL;
100 unit_t *tgt_init = NULL;
101
102 mnt_initrd = unit_create(UNIT_MOUNT);
103 if (mnt_initrd == NULL) {
104 rc = ENOMEM;
105 goto fail;
106 }
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;
113
114 cfg_init = unit_create(UNIT_CONFIGURATION);
115 if (cfg_init == NULL) {
116 rc = ENOMEM;
117 goto fail;
118 }
119 cfg_init->name = str_dup(UNIT_CFG_INITRD);
120 CAST_CFG(cfg_init)->path = str_dup(INITRD_CFG_PATH);
121
122 tgt_init = unit_create(UNIT_TARGET);
123 if (tgt_init == NULL) {
124 rc = ENOMEM;
125 goto fail;
126 }
127 tgt_init->name = str_dup(TARGET_INIT);
128
129
130 /*
131 * Add units to configuration and start the default target.
132 */
133 repo_begin_update();
134
135 repo_add_unit(mnt_initrd);
136 repo_add_unit(cfg_init);
137 repo_add_unit(tgt_init);
138
139 rc = edge_connect(tgt_init, cfg_init);
140 if (rc != EOK) {
141 goto rollback;
142 }
143
144 rc = edge_connect(cfg_init, mnt_initrd);
145 if (rc != EOK) {
146 goto rollback;
147 }
148
149 repo_commit();
150
151 return EOK;
152
153fail:
154 unit_destroy(&tgt_init);
155 unit_destroy(&cfg_init);
156 unit_destroy(&mnt_initrd);
157 return rc;
158
159rollback:
160 repo_rollback();
161 return rc;
162}
163
164static void sequence_job_handler(void *object, void *arg)
165{
166 job_t *job = object;
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 }
172 job_del_ref(&job);
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 */
188 unit_t *tgt = repo_find_unit_by_name(target_name);
189 if (tgt == NULL) {
190 sysman_log(LVL_ERROR,
191 "Expected unit '%s' not found in configuration.",
192 target_name);
193 return;
194 }
195
196 int rc = sysman_run_job(tgt, STATE_STARTED, &sequence_job_handler,
197 target_name_ptr);
198
199 if (rc != EOK) {
200 sysman_log(LVL_FATAL, "Cannot create job for '%s'.", target_name);
201 }
202}
203
204int main(int argc, char *argv[])
205{
206 printf(NAME ": HelenOS system daemon\n");
207
208 /*
209 * Initialize global structures
210 */
211 // TODO check return values and abort start
212 repo_init();
213 sysman_events_init();
214 job_queue_init();
215 sm_task_init();
216
217 /*
218 * Create initial configuration while we are in a single fibril
219 */
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 }
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
234 sysman_log(LVL_DEBUG, "Debugging pause...\n");
235 async_usleep(1 * 1000000);
236 sysman_log(LVL_DEBUG, "Debugging pause ended.\n");
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 }
247
248 /* Start sysman server */
249 async_set_client_connection(sysman_connection);
250
251 printf(NAME ": Accepting connections\n");
252 async_manager();
253
254 /* not reached */
255 return 0;
256}
Note: See TracBrowser for help on using the repository browser.