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.
28 #include <sys/types.h>
44 struct apprun *next_by_runid;
45 struct apprun *next_by_pgid;
53 #define ROOT_RUNNERS_COUNT 32
54 #define MAX_RUNNER_COUNT 32767
56 static struct apprun *runners_by_runid[ROOT_RUNNERS_COUNT];
57 static struct apprun *runners_by_pgid[ROOT_RUNNERS_COUNT];
58 static int runnercount = 0;
59 static int runnerid = 0;
61 /****************** manages pgids **********************/
63 /* get a runner by its pgid */
64 static struct apprun *runner_of_pgid(pid_t pgid)
66 struct apprun *result = runners_by_pgid[(int)(pgid & (ROOT_RUNNERS_COUNT - 1))];
67 while (result && result->backend != pgid)
68 result = result->next_by_pgid;
72 /* insert a runner for its pgid */
73 static void pgid_insert(struct apprun *runner)
75 struct apprun **prev = &runners_by_runid[(int)(runner->backend & (ROOT_RUNNERS_COUNT - 1))];
76 runner->next_by_pgid = *prev;
80 /* remove a runner for its pgid */
81 static void pgid_remove(struct apprun *runner)
83 struct apprun **prev = &runners_by_runid[(int)(runner->backend & (ROOT_RUNNERS_COUNT - 1))];
84 runner->next_by_pgid = *prev;
88 /****************** manages pids **********************/
90 /* get a runner by its pid */
91 static struct apprun *runner_of_pid(pid_t pid)
93 /* try avoiding system call */
94 struct apprun *result = runner_of_pgid(pid);
96 result = runner_of_pgid(getpgid(pid));
100 /****************** manages runners (by runid) **********************/
102 /* get a runner by its runid */
103 static struct apprun *getrunner(int runid)
105 struct apprun *result = runners_by_runid[runid & (ROOT_RUNNERS_COUNT - 1)];
106 while (result && result->runid != runid)
107 result = result->next_by_runid;
111 /* free an existing runner */
112 static void freerunner(struct apprun *runner)
114 struct apprun **prev = &runners_by_runid[runner->runid & (ROOT_RUNNERS_COUNT - 1)];
116 while(*prev != runner) {
117 prev = &(*prev)->next_by_runid;
120 *prev = runner->next_by_runid;
121 json_object_put(runner->appli);
126 /* create a new runner */
127 static struct apprun *createrunner(json_object *appli)
129 struct apprun *result;
130 struct apprun **prev;
132 if (runnercount >= MAX_RUNNER_COUNT)
136 if (runnerid > MAX_RUNNER_COUNT)
138 } while(getrunner(runnerid));
139 result = calloc(1, sizeof * result);
141 prev = &runners_by_runid[runnerid & (ROOT_RUNNERS_COUNT - 1)];
142 result->next_by_runid = *prev;
143 result->next_by_pgid = NULL;
144 result->runid = runnerid;
146 result->frontend = 0;
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->backend, sig);
197 runner->state = tostate;
202 /**************** API handling ************************/
204 int appfwk_run_start(struct json_object *appli)
209 int appfwk_run_terminate(int runid)
211 return killrunner(runid, SIGTERM, as_terminating);
214 int appfwk_run_stop(int runid)
216 return killrunner(runid, SIGSTOP, as_stopped);
219 int appfwk_run_continue(int runid)
221 return killrunner(runid, SIGCONT, as_running);
224 static json_object *mkstate(struct apprun *runner, const char **runidstr)
227 struct json_object *result, *obj, *runid;
231 result = json_object_new_object();
236 runid = json_object_new_int(runner->runid);
239 json_object_object_add(result, "runid", obj); /* TODO TEST STATUS */
242 switch(runner->state) {
251 state = "terminated";
254 obj = json_object_new_string(state);
257 json_object_object_add(result, "state", obj); /* TODO TEST STATUS */
259 /* the application id */
260 rc = json_object_object_get_ex(runner->appli, "public", &obj);
262 rc = json_object_object_get_ex(obj, "id", &obj);
264 json_object_object_add(result, "id", obj); /* TODO TEST STATUS */
265 json_object_get(obj);
269 *runidstr = json_object_get_string(runid);
273 json_object_put(result);
279 struct json_object *appfwk_run_list()
281 struct json_object *result, *obj;
282 struct apprun *runner;
283 const char *runidstr;
286 /* creates the object */
287 result = json_object_new_object();
288 if (result == NULL) {
293 for (i = 0 ; i < ROOT_RUNNERS_COUNT ; i++) {
294 for (runner = runners_by_runid[i] ; runner ; runner = runner->next_by_runid) {
295 if (runner->state != as_terminating && runner->state != as_terminated) {
296 obj = mkstate(runner, &runidstr);
298 json_object_put(result);
302 json_object_object_add(result, runidstr, obj);
309 struct json_object *appfwk_run_state(int runid)
311 struct apprun *runner = getrunner(runid);
312 if (runner == NULL || runner->state == as_terminating || runner->state == as_terminated) {
316 return mkstate(runner, NULL);