X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng%2Fcommands%2Fdisable_rotation.c;h=30dfaa1691db929295cce3cba2a0ef921fd06c57;hp=b179e91ce33e8f91e94a3d741d9ef7a0a34e03ab;hb=66ea93b10c703e1b3dda1e17109eed9138e4ece2;hpb=dbd512ea8aa5349849aeeccda6130aa9e28cf23c diff --git a/src/bin/lttng/commands/disable_rotation.c b/src/bin/lttng/commands/disable_rotation.c index b179e91ce..30dfaa169 100644 --- a/src/bin/lttng/commands/disable_rotation.c +++ b/src/bin/lttng/commands/disable_rotation.c @@ -50,104 +50,177 @@ enum { static struct poptOption long_options[] = { /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */ - {"help", 'h', POPT_ARG_NONE, 0, OPT_HELP, 0, 0}, - {"list-options", 0, POPT_ARG_NONE, NULL, OPT_LIST_OPTIONS, NULL, NULL}, - {"session", 's', POPT_ARG_STRING, &opt_session_name, 0, 0, 0}, + {"help", 'h', POPT_ARG_NONE, 0, OPT_HELP, 0, 0}, + {"list-options", 0, POPT_ARG_NONE, NULL, OPT_LIST_OPTIONS, NULL, NULL}, + {"session", 's', POPT_ARG_STRING, &opt_session_name, 0, 0, 0}, {"timer", 0, POPT_ARG_NONE, 0, OPT_TIMER, 0, 0}, {"size", 0, POPT_ARG_NONE, 0, OPT_SIZE, 0, 0}, {0, 0, 0, 0, 0, 0, 0} }; -static int setup_rotate(char *session_name, uint64_t timer, uint64_t size) +static const char *schedule_type_str[] = { + [LTTNG_ROTATION_SCHEDULE_TYPE_PERIODIC] = "periodic", + [LTTNG_ROTATION_SCHEDULE_TYPE_SIZE_THRESHOLD] = "size-based", +}; + +static const struct lttng_rotation_schedule *get_schedule( + const char *session_name, + const struct lttng_rotation_schedules *schedules, + enum lttng_rotation_schedule_type schedule_type) { - int ret = 0; - struct lttng_rotation_schedule_attr *attr = NULL; + unsigned int count, i; + enum lttng_rotation_status status; + const struct lttng_rotation_schedule *ret = NULL; - attr = lttng_rotation_schedule_attr_create(); - if (!attr) { - goto error; + status = lttng_rotation_schedules_get_count(schedules, &count); + if (status != LTTNG_ROTATION_STATUS_OK) { + ERR("Unable to determine the number of rotation schedules of session %s", + session_name); + goto end; } - if (lttng_opt_mi) { - /* Open rotation_schedule element */ - ret = mi_lttng_writer_open_element(writer, - config_element_rotation_schedule); - if (ret) { - goto error; + for (i = 0; i < count; i++) { + const struct lttng_rotation_schedule *schedule = NULL; + + schedule = lttng_rotation_schedules_get_at_index(schedules, i); + if (!schedule) { + ERR("Unable to retrieve rotation schedule at index %u", + i); + goto end; } - } - if (lttng_opt_mi) { - ret = mi_lttng_writer_write_element_string(writer, - mi_lttng_element_session_name, session_name); - if (ret) { - goto error; + if (lttng_rotation_schedule_get_type(schedule) == + schedule_type) { + ret = schedule; + break; } } - if (timer == -1ULL) { - lttng_rotation_schedule_attr_set_timer_period(attr, timer); - MSG("Disabling rotation timer on session %s", session_name); + if (!ret) { + ERR("No %s rotation schedule active on session %s", + schedule_type_str[schedule_type], session_name); } - if (size == -1ULL) { - lttng_rotation_schedule_attr_set_size(attr, size); - MSG("Disabling rotation based on size on session %s", session_name); +end: + return ret; +} + +static struct lttng_rotation_schedule *create_empty_schedule( + enum lttng_rotation_schedule_type type) +{ + struct lttng_rotation_schedule *schedule = NULL; + + switch (type) { + case LTTNG_ROTATION_SCHEDULE_TYPE_PERIODIC: + schedule = lttng_rotation_schedule_periodic_create(); + break; + case LTTNG_ROTATION_SCHEDULE_TYPE_SIZE_THRESHOLD: + schedule = lttng_rotation_schedule_size_threshold_create(); + break; + default: + abort(); } + return schedule; +} - ret = lttng_rotation_set_schedule(session_name, attr); - if (ret) { - ERR("%s", lttng_strerror(ret)); - if (lttng_opt_mi) { - ret = mi_lttng_writer_write_element_string(writer, - mi_lttng_element_rotate_status, "error"); - if (ret) { - goto end; - } - /* Close rotation_schedule element */ - ret = mi_lttng_writer_close_element(writer); - if (ret) { - goto end; - } - } +static enum cmd_error_code remove_schedule(const char *session_name, + enum lttng_rotation_schedule_type schedule_type) +{ + enum cmd_error_code cmd_ret; + int ret; + const struct lttng_rotation_schedule *schedule = NULL; + struct lttng_rotation_schedules *schedules = NULL; + enum lttng_rotation_status status; + const char *schedule_type_name; + struct lttng_rotation_schedule *empty_schedule = NULL; + + switch (schedule_type) { + case LTTNG_ROTATION_SCHEDULE_TYPE_PERIODIC: + case LTTNG_ROTATION_SCHEDULE_TYPE_SIZE_THRESHOLD: + break; + default: + ERR("Unknown schedule type"); + abort(); + } + + schedule_type_name = schedule_type_str[schedule_type]; + + ret = lttng_session_list_rotation_schedules(session_name, &schedules); + if (ret != LTTNG_OK) { + ERR("Failed to list rotation schedules of session %s", + session_name); goto error; } - if (lttng_opt_mi) { - ret = mi_lttng_writer_write_element_string(writer, - mi_lttng_element_rotate_status, "success"); - if (ret) { - goto end; + schedule = get_schedule(session_name, schedules, schedule_type); + if (!schedule) { + cmd_ret = CMD_ERROR; + /* + * get_schedule() logs its own errors. + * A temporaty schedule is created to serialize an MI rotation + * schedule descriptor of the appropriate type that has no + * attributes set. + */ + empty_schedule = create_empty_schedule(schedule_type); + if (!empty_schedule) { + goto error; } + goto skip_removal; + } - /* Close rotation_schedule element */ - ret = mi_lttng_writer_close_element(writer); - if (ret) { - goto end; - } + status = lttng_session_remove_rotation_schedule(session_name, schedule); + switch (status) { + case LTTNG_ROTATION_STATUS_OK: + MSG("Disabled %s rotation on session %s", + schedule_type_name, session_name); + cmd_ret = CMD_SUCCESS; + break; + case LTTNG_ROTATION_STATUS_SCHEDULE_NOT_SET: + ERR("No %s rotation schedule set on session %s", + schedule_type_name, + session_name); + cmd_ret = CMD_ERROR; + break; + case LTTNG_ROTATION_STATUS_ERROR: + case LTTNG_ROTATION_STATUS_INVALID: + default: + ERR("Failed to disable %s rotation schedule on session %s", + schedule_type_name, session_name); + cmd_ret = CMD_ERROR; + break; } - ret = 0; - goto end; +skip_removal: + if (lttng_opt_mi) { + ret = mi_lttng_rotation_schedule_result(writer, + schedule ? schedule : empty_schedule, + cmd_ret == CMD_SUCCESS); + if (ret < 0) { + goto error; + } + } -error: - ret = -1; end: - return ret; + lttng_rotation_schedules_destroy(schedules); + lttng_rotation_schedule_destroy(empty_schedule); + return cmd_ret; +error: + cmd_ret = CMD_ERROR; + goto end; } /* * cmd_disable_rotation * - * The 'enable-rotation ' first level command + * The 'disable-rotation ' first level command */ int cmd_disable_rotation(int argc, const char **argv) { - int opt, ret = CMD_SUCCESS, command_ret = CMD_SUCCESS, success = 1; - int popt_ret; + int popt_ret, opt, ret = 0; + enum cmd_error_code cmd_ret = CMD_SUCCESS; static poptContext pc; char *session_name = NULL; bool free_session_name = false; - uint64_t timer = 0, size = 0; + bool periodic_rotation = false, size_rotation = false; pc = poptGetContext(NULL, argc, argv, long_options, 0); popt_ret = poptReadDefaultConfig(pc, 0); @@ -166,10 +239,10 @@ int cmd_disable_rotation(int argc, const char **argv) list_cmd_options(stdout, long_options); goto end; case OPT_TIMER: - timer = -1ULL; + periodic_rotation = true; break; case OPT_SIZE: - size = -1ULL; + size_rotation = true; break; default: ret = CMD_UNDEFINED; @@ -180,7 +253,7 @@ int cmd_disable_rotation(int argc, const char **argv) if (opt_session_name == NULL) { session_name = get_session_name(); if (session_name == NULL) { - goto end; + goto error; } free_session_name = true; } else { @@ -191,77 +264,103 @@ int cmd_disable_rotation(int argc, const char **argv) if (lttng_opt_mi) { writer = mi_lttng_writer_create(fileno(stdout), lttng_opt_mi); if (!writer) { - ret = -LTTNG_ERR_NOMEM; - goto end; + goto error; } /* Open command element */ ret = mi_lttng_writer_command_open(writer, mi_lttng_element_command_disable_rotation); if (ret) { - ret = CMD_ERROR; - goto end; + goto error; } /* Open output element */ ret = mi_lttng_writer_open_element(writer, mi_lttng_element_command_output); if (ret) { - ret = CMD_ERROR; - goto end; + goto error; } } - /* No config options, just rotate the session now */ - if (timer == 0 && size == 0) { - ERR("Missing timer period (--timer) or size limit (--size) option"); - success = 0; - command_ret = -1; - } else { - command_ret = setup_rotate(session_name, timer, size); + if (!periodic_rotation && !size_rotation) { + ERR("No session rotation schedule type provided."); + cmd_ret = CMD_ERROR; + goto close_command; } - if (command_ret) { - ERR("%s", lttng_strerror(command_ret)); - success = 0; + if (lttng_opt_mi) { + ret = mi_lttng_writer_open_element(writer, + mi_lttng_element_rotation_schedule_results); + if (ret) { + goto error; + } + + ret = mi_lttng_writer_write_element_string(writer, + mi_lttng_element_session_name, + session_name); + if (ret) { + goto error; + } } + if (periodic_rotation) { + /* + * Continue processing even on error as multiple schedules can + * be specified at once. + */ + cmd_ret = remove_schedule(session_name, + LTTNG_ROTATION_SCHEDULE_TYPE_PERIODIC); + } + + if (size_rotation) { + enum lttng_error_code tmp_ret; + + /* Don't overwrite cmd_ret if it already indicates an error. */ + tmp_ret = remove_schedule(session_name, + LTTNG_ROTATION_SCHEDULE_TYPE_SIZE_THRESHOLD); + cmd_ret = cmd_ret ? cmd_ret : tmp_ret; + } + + if (lttng_opt_mi) { + /* Close rotation schedule results element */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto error; + } + } + +close_command: /* Mi closing */ if (lttng_opt_mi) { /* Close output element */ ret = mi_lttng_writer_close_element(writer); if (ret) { - goto end; + goto error; } /* Success ? */ ret = mi_lttng_writer_write_element_bool(writer, - mi_lttng_element_command_success, success); + mi_lttng_element_command_success, + cmd_ret == CMD_SUCCESS); if (ret) { - ret = CMD_ERROR; - goto end; + goto error; } /* Command element close */ ret = mi_lttng_writer_command_close(writer); if (ret) { - ret = CMD_ERROR; - goto end; + goto error; } } end: - /* Mi clean-up */ - if (writer && mi_lttng_writer_destroy(writer)) { - /* Preserve original error code */ - ret = ret ? ret : -LTTNG_ERR_MI_IO_FAIL; - } - - /* Overwrite ret if an error occurred with start_tracing */ - ret = command_ret ? command_ret : ret; + (void) mi_lttng_writer_destroy(writer); poptFreeContext(pc); if (free_session_name) { free(session_name); } - return ret; + return cmd_ret; +error: + cmd_ret = CMD_ERROR; + goto end; }