source: mainline/uspace/srv/sysman/connection_ctl.c@ 9532981

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

sysman: Rename configuration to repo(sitory)

It's better suited for dynamic nature of the storage.

  • Property mode set to 100644
File size: 6.0 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 <errno.h>
30#include <ipc/sysman.h>
31#include <macros.h>
32#include <stdlib.h>
33#include <str.h>
34
35#include "repo.h"
36#include "connection_ctl.h"
37#include "job.h"
38#include "log.h"
39#include "sysman.h"
40
41
42// TODO possibly provide as type-safe function + macro in sysman.h for generic boxing
43static ipc_callid_t *box_callid(ipc_callid_t iid)
44{
45 ipc_callid_t *result = malloc(sizeof(ipc_callid_t));
46 if (result) {
47 *result = iid;
48 }
49 return result;
50}
51
52static void answer_callback(void *object, void *arg)
53{
54 job_t *job = object;
55 assert(job->state == JOB_FINISHED);
56 assert(job->retval != JOB_UNDEFINED_);
57
58 ipc_callid_t *iid_ptr = arg;
59 // TODO use descriptive return value (probably refactor job retval)
60 sysarg_t retval = (job->retval == JOB_OK) ? EOK : EIO;
61 async_answer_0(*iid_ptr, retval);
62 free(iid_ptr);
63 job_del_ref(&job);
64}
65static void sysman_unit_start(ipc_callid_t iid, ipc_call_t *icall)
66{
67 char *unit_name = NULL;
68 sysarg_t retval;
69
70 int rc = async_data_write_accept((void **) &unit_name, true,
71 0, 0, 0, NULL);
72 if (rc != EOK) {
73 retval = rc;
74 goto answer;
75 }
76
77 int flags = IPC_GET_ARG1(*icall);
78 sysman_log(LVL_DEBUG2, "%s(%s, %x)", __func__, unit_name, flags);
79
80 // TODO this is connection fibril, UNSYNCHRONIZED access to units!
81 unit_t *unit = repo_find_unit_by_name(unit_name);
82 if (unit == NULL) {
83 sysman_log(LVL_NOTE, "Unit '%s' not found.", unit_name);
84 retval = ENOENT;
85 goto answer;
86 }
87
88 if (!(flags & IPC_FLAG_BLOCKING)) {
89 retval = sysman_run_job(unit, STATE_STARTED, NULL, NULL);
90 goto answer;
91 }
92
93 ipc_callid_t *iid_ptr = box_callid(iid);
94 if (iid_ptr == NULL) {
95 retval = ENOMEM;
96 goto answer;
97 }
98 retval = sysman_run_job(unit, STATE_STARTED, &answer_callback,
99 iid_ptr);
100 if (retval != EOK) {
101 goto answer;
102 }
103
104 /* Answer asynchronously from callback */
105 goto finish;
106
107answer:
108 async_answer_0(iid, retval);
109finish:
110 free(unit_name);
111}
112
113static int fill_handles_buffer(unit_handle_t *buffer, size_t size,
114 size_t *act_size)
115{
116 if (size % sizeof(unit_handle_t) != 0) {
117 return EINVAL;
118 }
119
120 size_t filled = 0;
121 size_t to_fill = size / sizeof(unit_handle_t);
122 size_t total = 0;
123 list_foreach(units, units, unit_t, u) {
124 if (filled < to_fill) {
125 buffer[filled++] = u->handle;
126 }
127 ++total;
128 }
129 *act_size = total * sizeof(unit_handle_t);
130 return EOK;
131}
132
133static void sysman_get_units(ipc_callid_t iid, ipc_call_t *icall)
134{
135 ipc_callid_t callid;
136 size_t size;
137 size_t act_size;
138 int rc;
139
140 if (!async_data_read_receive(&callid, &size)) {
141 async_answer_0(callid, EREFUSED);
142 async_answer_0(iid, EREFUSED);
143 return;
144 }
145
146
147 unit_handle_t *handles = malloc(size);
148 if (handles == NULL && size > 0) {
149 async_answer_0(callid, ENOMEM);
150 async_answer_0(iid, ENOMEM);
151 return;
152 }
153
154
155 // TODO UNSYNCHRONIZED access to units!
156 rc = fill_handles_buffer(handles, size, &act_size);
157 if (rc != EOK) {
158 async_answer_0(callid, rc);
159 async_answer_0(iid, rc);
160 return;
161 }
162
163 size_t real_size = min(act_size, size);
164 sysarg_t retval = async_data_read_finalize(callid, handles, real_size);
165 free(handles);
166
167 async_answer_1(iid, retval, act_size);
168}
169
170static void sysman_unit_get_name(ipc_callid_t iid, ipc_call_t *icall)
171{
172 ipc_callid_t callid;
173 size_t size;
174
175 if (!async_data_read_receive(&callid, &size)) {
176 async_answer_0(callid, EREFUSED);
177 async_answer_0(iid, EREFUSED);
178 return;
179 }
180
181 // TODO UNSYNCHRONIZED access to units!
182 unit_t *u = repo_find_unit_by_handle(IPC_GET_ARG1(*icall));
183 if (u == NULL) {
184 async_answer_0(callid, ENOENT);
185 async_answer_0(iid, ENOENT);
186 return;
187 }
188
189 size_t real_size = min(str_size(u->name) + 1, size);
190 sysarg_t retval = async_data_read_finalize(callid, u->name, real_size);
191
192 async_answer_0(iid, retval);
193}
194
195static void sysman_unit_get_state(ipc_callid_t iid, ipc_call_t *icall)
196{
197 // TODO UNSYNCHRONIZED access to units!
198 unit_t *u = repo_find_unit_by_handle(IPC_GET_ARG1(*icall));
199 if (u == NULL) {
200 async_answer_0(iid, ENOENT);
201 } else {
202 async_answer_1(iid, EOK, u->state);
203 }
204}
205
206void sysman_connection_ctl(ipc_callid_t iid, ipc_call_t *icall)
207{
208 sysman_log(LVL_DEBUG2, "%s", __func__);
209 /* First, accept connection */
210 async_answer_0(iid, EOK);
211
212 while (true) {
213 ipc_call_t call;
214 ipc_callid_t callid = async_get_call(&call);
215
216 if (!IPC_GET_IMETHOD(call)) {
217 /* Client disconnected */
218 break;
219 }
220
221 switch (IPC_GET_IMETHOD(call)) {
222 case SYSMAN_CTL_UNIT_START:
223 sysman_unit_start(callid, &call);
224 break;
225 case SYSMAN_CTL_GET_UNITS:
226 sysman_get_units(callid, &call);
227 break;
228 case SYSMAN_CTL_UNIT_GET_NAME:
229 sysman_unit_get_name(callid, &call);
230 break;
231 case SYSMAN_CTL_UNIT_GET_STATE:
232 sysman_unit_get_state(callid, &call);
233 break;
234 default:
235 async_answer_0(callid, ENOENT);
236 }
237 }
238}
239
Note: See TracBrowser for help on using the repository browser.