- if (!strcmp(action, "gain")) {
- FCGI_BeginControl(context, force);
- } else {
- if (!FCGI_HasControl(context, key)) {
- FCGI_RejectJSONEx(context,
- STATUS_UNAUTHORIZED, "Invalid control key specified.");
-
- } else if (!strcmp(action, "release")) {
- FCGI_EndControl(context);
- } else if (!strcmp(action, "experiment")) {
- if (!strcmp(mode, "start")) {
- FCGI_BeginJSON(context, STATUS_OK);
- FCGI_JSONPair("description", mode);
- FCGI_EndJSON();
- } else if (!strcmp(mode, "pause")) {
- FCGI_BeginJSON(context, STATUS_OK);
- FCGI_JSONPair("description", mode);
- FCGI_EndJSON();
- } else if (!strcmp(mode, "stop")) {
- FCGI_BeginJSON(context, STATUS_OK);
- FCGI_JSONPair("description", mode);
- FCGI_EndJSON();
- } else {
- FCGI_RejectJSON(context, "Unknown experiment mode specified");
- }
- } else {
- FCGI_RejectJSON(context, "Unknown action specified");
+ if (!strcmp(action, "identify")) {
+ FCGI_BeginJSON(context, STATUS_OK);
+ FCGI_JSONLong("control_state_id", g_controls.current_mode);
+ FCGI_JSONPair("control_user_name", g_controls.user_name);
+ FCGI_JSONPair("control_experiment_name", g_controls.experiment_name);
+ FCGI_EndJSON();
+ return;
+ } else if (!strcmp(action, "list")) {
+ ListExperiments(context);
+ return;
+ }
+ //TODO: Need a "load" action to set data files (but not run) from a past experiment
+
+ //TODO: Need a "delete" action so that people can overwrite experiments (without all this "force" shenanigans)
+
+ if (!strcmp(action, "emergency")) {
+ desired_mode = CONTROL_EMERGENCY;
+ } else if (!strcmp(action, "start")) {
+ desired_mode = CONTROL_START;
+ } else if (!strcmp(action, "pause")) {
+ desired_mode = CONTROL_PAUSE;
+ } else if (!strcmp(action, "resume")) {
+ desired_mode = CONTROL_RESUME;
+ } else if (!strcmp(action, "stop")) {
+ desired_mode = CONTROL_STOP;
+ } else {
+ FCGI_RejectJSON(context, "Unknown action specified.");
+ return;
+ }
+
+ if ((*g_controls.user_name) != '\0' && strcmp(g_controls.user_name, context->user_name) != 0)
+ {
+ if (context->user_type != USER_ADMIN) {
+ FCGI_RejectJSON(context, "Another user has an experiment in progress.");
+ return;
+ }
+
+ if (!force) {
+ Log(LOGERR, "User %s is currently running an experiment!", g_controls.user_name);
+ FCGI_RejectJSON(context, "Pass \"force\" to take control over another user's experiment");
+ return;
+ }
+ }
+
+ void *arg = NULL;
+ char experiment_dir[BUFSIZ] = {0};
+ if (desired_mode == CONTROL_START) {
+ int ret;
+
+ if (*name == '\0') {
+ FCGI_RejectJSON(context, "An experiment name must be specified.");
+ return;
+ } if (strpbrk(name, INVALID_CHARACTERS)) {
+ FCGI_RejectJSON(context,
+ "An experiment name must not contain: " INVALID_CHARACTERS_JSON);
+ return;
+ }
+
+ if (*(context->user_dir) == '\0') {
+ FCGI_RejectJSON(context, "Not creating experiment in root dir.");
+ return;
+ }
+
+ ret = snprintf(experiment_dir, BUFSIZ, "%s/%s.exp",
+ context->user_dir, name);
+ if (ret >= BUFSIZ) {
+ FCGI_RejectJSON(context, "The experiment name is too long.");
+ return;
+ } else if (DirExists(experiment_dir) && !force) {
+ FCGI_RejectJSON(context, "An experiment with that name already exists.");
+ return;
+ }
+
+ arg = (void*) experiment_dir;
+ }
+
+ const char *ret;
+ if ((ret = Control_SetMode(desired_mode, arg)) != NULL) {
+ FCGI_RejectJSON(context, ret);
+ } else {
+ if (desired_mode == CONTROL_STOP) {
+ g_controls.user_name[0] = '\0';
+ g_controls.experiment_dir[0] = '\0';
+ g_controls.experiment_name[0] = '\0';
+ } else if (desired_mode == CONTROL_START) {
+ snprintf(g_controls.user_name, sizeof(g_controls.user_name),
+ "%s", context->user_name);
+ snprintf(g_controls.experiment_dir, sizeof(g_controls.experiment_dir),
+ "%s", experiment_dir);
+ snprintf(g_controls.experiment_name, sizeof(g_controls.experiment_name),
+ "%s", name);