4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
8 http://www.apache.org/licenses/LICENSE-2.0
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
21 #include <sys/types.h>
31 #include "utils-dir.h"
43 struct apprun *next_by_runid;
44 struct apprun *next_by_pgid;
51 #define ROOT_RUNNERS_COUNT 32
52 #define MAX_RUNNER_COUNT 32767
54 static struct apprun *runners_by_runid[ROOT_RUNNERS_COUNT];
55 static struct apprun *runners_by_pgid[ROOT_RUNNERS_COUNT];
56 static int runnercount = 0;
57 static int runnerid = 0;
59 static const char fwk_user_app_dir[] = FWK_USER_APP_DIR;
60 static char *homeappdir;
62 /****************** manages pgids **********************/
64 /* get a runner by its pgid */
65 static struct apprun *runner_of_pgid(pid_t pgid)
67 struct apprun *result = runners_by_pgid[(int)(pgid & (ROOT_RUNNERS_COUNT - 1))];
68 while (result && result->pgid != pgid)
69 result = result->next_by_pgid;
73 /* insert a runner for its pgid */
74 static void pgid_insert(struct apprun *runner)
76 struct apprun **prev = &runners_by_runid[(int)(runner->pgid & (ROOT_RUNNERS_COUNT - 1))];
77 runner->next_by_pgid = *prev;
81 /* remove a runner for its pgid */
82 static void pgid_remove(struct apprun *runner)
84 struct apprun **prev = &runners_by_runid[(int)(runner->pgid & (ROOT_RUNNERS_COUNT - 1))];
85 runner->next_by_pgid = *prev;
89 /****************** manages pids **********************/
91 /* get a runner by its pid */
92 static struct apprun *runner_of_pid(pid_t pid)
94 /* try avoiding system call */
95 struct apprun *result = runner_of_pgid(pid);
97 result = runner_of_pgid(getpgid(pid));
101 /****************** manages runners (by runid) **********************/
103 /* get a runner by its runid */
104 static struct apprun *getrunner(int runid)
106 struct apprun *result = runners_by_runid[runid & (ROOT_RUNNERS_COUNT - 1)];
107 while (result && result->runid != runid)
108 result = result->next_by_runid;
112 /* free an existing runner */
113 static void freerunner(struct apprun *runner)
115 struct apprun **prev = &runners_by_runid[runner->runid & (ROOT_RUNNERS_COUNT - 1)];
117 while(*prev != runner) {
118 prev = &(*prev)->next_by_runid;
121 *prev = runner->next_by_runid;
122 json_object_put(runner->appli);
127 /* create a new runner */
128 static struct apprun *createrunner(json_object *appli)
130 struct apprun *result;
131 struct apprun **prev;
133 if (runnercount >= MAX_RUNNER_COUNT)
137 if (runnerid > MAX_RUNNER_COUNT)
139 } while(getrunner(runnerid));
140 result = calloc(1, sizeof * result);
142 prev = &runners_by_runid[runnerid & (ROOT_RUNNERS_COUNT - 1)];
143 result->next_by_runid = *prev;
144 result->next_by_pgid = NULL;
145 result->runid = runnerid;
147 result->state = as_starting;
148 result->appli = json_object_get(appli);
155 /**************** signaling ************************/
157 static void started(int runid)
161 static void stopped(int runid)
165 static void continued(int runid)
169 static void terminated(int runid)
173 static void removed(int runid)
177 /**************** running ************************/
179 static int killrunner(int runid, int sig, enum appstate tostate)
182 struct apprun *runner = getrunner(runid);
183 if (runner == NULL) {
187 else if (runner->state != as_running && runner->state != as_stopped) {
191 else if (runner->state == tostate) {
195 rc = killpg(runner->pgid, sig);
197 runner->state = tostate;
202 /**************** summarizing the application *********************/
215 /**************** API handling ************************/
217 int af_run_start(struct json_object *appli)
224 int af_run_terminate(int runid)
226 return killrunner(runid, SIGTERM, as_terminating);
229 int af_run_stop(int runid)
231 return killrunner(runid, SIGSTOP, as_stopped);
234 int af_run_continue(int runid)
236 return killrunner(runid, SIGCONT, as_running);
239 static json_object *mkstate(struct apprun *runner, const char **runidstr)
242 struct json_object *result, *obj, *runid;
246 result = json_object_new_object();
251 runid = json_object_new_int(runner->runid);
254 json_object_object_add(result, "runid", obj); /* TODO TEST STATUS */
257 switch(runner->state) {
266 state = "terminated";
269 obj = json_object_new_string(state);
272 json_object_object_add(result, "state", obj); /* TODO TEST STATUS */
274 /* the application id */
275 rc = json_object_object_get_ex(runner->appli, "public", &obj);
277 rc = json_object_object_get_ex(obj, "id", &obj);
279 json_object_object_add(result, "id", obj); /* TODO TEST STATUS */
280 json_object_get(obj);
284 *runidstr = json_object_get_string(runid);
288 json_object_put(result);
294 struct json_object *af_run_list()
296 struct json_object *result, *obj;
297 struct apprun *runner;
298 const char *runidstr;
301 /* creates the object */
302 result = json_object_new_object();
303 if (result == NULL) {
308 for (i = 0 ; i < ROOT_RUNNERS_COUNT ; i++) {
309 for (runner = runners_by_runid[i] ; runner ; runner = runner->next_by_runid) {
310 if (runner->state != as_terminating && runner->state != as_terminated) {
311 obj = mkstate(runner, &runidstr);
313 json_object_put(result);
317 json_object_object_add(result, runidstr, obj);
324 struct json_object *af_run_state(int runid)
326 struct apprun *runner = getrunner(runid);
327 if (runner == NULL || runner->state == as_terminating || runner->state == as_terminated) {
331 return mkstate(runner, NULL);
334 /**************** INITIALISATION **********************/
342 struct passwd passwd, *pw;
344 /* computes the 'homeappdir' */
346 rc = getpwuid_r(me, &passwd, buf, sizeof buf, &pw);
347 if (rc || pw == NULL) {
348 errno = rc ? errno : ENOENT;
349 ERROR("getpwuid_r failed for uid=%d: %m",(int)me);
352 rc = snprintf(dir, sizeof dir, "%s/%s", passwd.pw_dir, fwk_user_app_dir);
353 if (rc >= sizeof dir) {
354 ERROR("buffer overflow in user_app_dir for uid=%d",(int)me);
357 rc = create_directory(dir, 0755, 1);
358 if (rc && errno != EEXIST) {
359 ERROR("creation of directory %s failed in user_app_dir: %m", dir);
362 homeappdir = strdup(dir);
363 if (homeappdir == NULL) {
365 ERROR("out of memory in user_app_dir for %s : %m", dir);
369 /* install signal handlers */