+
+ 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);
+ }
+
+ FCGI_AcceptJSON(context, "Ok", NULL);
+ }
+}
+
+/**
+ * Sets the mode to the desired mode, if possible.
+ * @param desired_mode The mode to be set to
+ * @param arg An argument specific to the mode to be set.
+ * @return NULL on success, an error message on failure.
+ */
+const char* Control_SetMode(ControlModes desired_mode, void * arg)
+{
+ const char *ret = NULL;
+
+ pthread_mutex_lock(&(g_controls.mutex));
+ if (g_controls.current_mode == desired_mode)
+ ret = "Already in the desired mode.";
+ else if (g_controls.current_mode == CONTROL_EMERGENCY && desired_mode != CONTROL_STOP)
+ ret = "In emergency mode. You must stop before continuing.";
+ else switch (desired_mode) {
+ case CONTROL_START:
+ if (g_controls.current_mode == CONTROL_STOP) {
+ const char * path = arg;
+ if (mkdir(path, 0777) != 0 && errno != EEXIST) {
+ Log(LOGERR, "Couldn't create experiment directory %s - %s",
+ path, strerror(errno));
+ ret = "Couldn't create experiment directory.";
+ } else {
+ clock_gettime(CLOCK_MONOTONIC, &(g_controls.start_time));
+ }
+ } else
+ ret = "Cannot start when not in a stopped state.";
+ break;
+ case CONTROL_PAUSE:
+ if (g_controls.current_mode != CONTROL_START)
+ ret = "Cannot pause when not in a running state.";
+ break;
+ case CONTROL_RESUME:
+ if (g_controls.current_mode != CONTROL_PAUSE)
+ ret = "Cannot resume when not in a paused state.";
+ break;
+ case CONTROL_EMERGENCY:
+ if (g_controls.current_mode != CONTROL_START) //pfft
+ ret = "Not running so how can there be an emergency?";
+ break;
+ default:
+ break;
+ }
+
+ if (ret == NULL) {
+ Actuator_SetModeAll(desired_mode, arg);
+ Sensor_SetModeAll(desired_mode, arg);
+ if (desired_mode != CONTROL_RESUME)
+ g_controls.current_mode = desired_mode;
+ else
+ g_controls.current_mode = CONTROL_START;