} else {
chunk_id_str = chunk_id_buf;
}
- session->has_rotated = true;
}
DBG("Rotate %" PRIu32 " streams of session \"%s\" to chunk \"%s\"",
enum lttng_error_code reply_code = LTTNG_OK;
enum lttng_trace_chunk_status chunk_status;
struct lttng_directory_handle *session_output = NULL;
+ const char *new_path;
if (!session || !conn->version_check_done) {
ERR("Trying to create a trace chunk before version check");
msg->creation_timestamp = be64toh(msg->creation_timestamp);
msg->override_name_length = be32toh(msg->override_name_length);
+ if (session->current_trace_chunk &&
+ !lttng_trace_chunk_get_name_overridden(session->current_trace_chunk)) {
+ chunk_status = lttng_trace_chunk_rename_path(session->current_trace_chunk,
+ DEFAULT_CHUNK_TMP_OLD_DIRECTORY);
+ if (chunk_status != LTTNG_TRACE_CHUNK_STATUS_OK) {
+ ERR("Failed to rename old chunk");
+ ret = -1;
+ reply_code = LTTNG_ERR_UNK;
+ goto end;
+ }
+ }
+ session->ongoing_rotation = true;
+ if (!session->current_trace_chunk) {
+ if (!session->has_rotated) {
+ new_path = "";
+ } else {
+ new_path = NULL;
+ }
+ } else {
+ new_path = DEFAULT_CHUNK_TMP_NEW_DIRECTORY;
+ }
chunk = lttng_trace_chunk_create(
- msg->chunk_id, msg->creation_timestamp);
+ msg->chunk_id, msg->creation_timestamp, new_path);
if (!chunk) {
ERR("Failed to create trace chunk in trace chunk creation command");
ret = -1;
conn->session->current_trace_chunk;
conn->session->current_trace_chunk = published_chunk;
published_chunk = NULL;
+ if (!conn->session->pending_closure_trace_chunk) {
+ session->ongoing_rotation = false;
+ }
end_unlock_session:
pthread_mutex_unlock(&conn->session->lock);
end:
size_t path_length = 0;
const char *chunk_name = NULL;
struct lttng_dynamic_buffer reply_payload;
+ const char *new_path;
lttng_dynamic_buffer_init(&reply_payload);
}
pthread_mutex_lock(&session->lock);
+ if (close_command.is_set &&
+ close_command.value == LTTNG_TRACE_CHUNK_COMMAND_TYPE_DELETE) {
+ /*
+ * Clear command. It is a protocol error to ask for a
+ * clear on a relay which does not allow it. Querying
+ * the configuration allows figuring out whether
+ * clearing is allowed before doing the clear.
+ */
+ if (!opt_allow_clear) {
+ ret = -1;
+ reply_code = LTTNG_ERR_INVALID_PROTOCOL;
+ goto end_unlock_session;
+ }
+ }
if (session->pending_closure_trace_chunk &&
session->pending_closure_trace_chunk != chunk) {
ERR("Trace chunk close command for session \"%s\" does not target the trace chunk pending closure",
goto end_unlock_session;
}
+ if (session->current_trace_chunk && session->current_trace_chunk != chunk &&
+ !lttng_trace_chunk_get_name_overridden(session->current_trace_chunk)) {
+ if (close_command.is_set &&
+ close_command.value == LTTNG_TRACE_CHUNK_COMMAND_TYPE_DELETE &&
+ !session->has_rotated) {
+ /* New chunk stays in session output directory. */
+ new_path = "";
+ } else {
+ /* Use chunk name for new chunk. */
+ new_path = NULL;
+ }
+ /* Rename new chunk path. */
+ chunk_status = lttng_trace_chunk_rename_path(session->current_trace_chunk,
+ new_path);
+ if (chunk_status != LTTNG_TRACE_CHUNK_STATUS_OK) {
+ ret = -1;
+ goto end;
+ }
+ session->ongoing_rotation = false;
+ }
+ if ((!close_command.is_set ||
+ close_command.value == LTTNG_TRACE_CHUNK_COMMAND_TYPE_NO_OPERATION) &&
+ !lttng_trace_chunk_get_name_overridden(chunk)) {
+ const char *old_path;
+
+ if (!session->has_rotated) {
+ old_path = "";
+ } else {
+ old_path = NULL;
+ }
+ /* We need to move back the .tmp_old_chunk to its rightful place. */
+ chunk_status = lttng_trace_chunk_rename_path(chunk, old_path);
+ if (chunk_status != LTTNG_TRACE_CHUNK_STATUS_OK) {
+ ret = -1;
+ goto end;
+ }
+ }
chunk_status = lttng_trace_chunk_set_close_timestamp(
chunk, close_timestamp);
if (chunk_status != LTTNG_TRACE_CHUNK_STATUS_OK) {
goto end_unlock_session;
}
}
+ if (close_command.is_set &&
+ close_command.value == LTTNG_TRACE_CHUNK_COMMAND_TYPE_MOVE_TO_COMPLETED) {
+ session->has_rotated = true;
+ }
DBG("Reply chunk path on close: %s", closed_trace_chunk_path);
path_length = strlen(closed_trace_chunk_path) + 1;
if (path_length > UINT32_MAX) {
return ret;
}
+/*
+ * relay_get_configuration: query whether feature is available
+ */
+static int relay_get_configuration(const struct lttcomm_relayd_hdr *recv_hdr,
+ struct relay_connection *conn,
+ const struct lttng_buffer_view *payload)
+{
+ int ret = 0;
+ ssize_t send_ret;
+ struct lttcomm_relayd_get_configuration *msg;
+ struct lttcomm_relayd_get_configuration_reply reply = {};
+ struct lttng_buffer_view header_view;
+ uint64_t query_flags = 0;
+ uint64_t result_flags = 0;
+
+ header_view = lttng_buffer_view_from_view(payload, 0, sizeof(*msg));
+ if (!header_view.data) {
+ ERR("Failed to receive payload of chunk close command");
+ ret = -1;
+ goto end_no_reply;
+ }
+
+ /* Convert to host endianness. */
+ msg = (typeof(msg)) header_view.data;
+ query_flags = be64toh(msg->query_flags);
+
+ if (query_flags) {
+ ret = LTTNG_ERR_INVALID_PROTOCOL;
+ goto reply;
+ }
+ if (opt_allow_clear) {
+ result_flags |= LTTCOMM_RELAYD_CONFIGURATION_FLAG_CLEAR_ALLOWED;
+ }
+ ret = 0;
+reply:
+ reply = (typeof(reply)){
+ .generic.ret_code = htobe32((uint32_t)
+ (ret == 0 ? LTTNG_OK : LTTNG_ERR_INVALID_PROTOCOL)),
+ .relayd_configuration_flags = htobe64(result_flags),
+ };
+ send_ret = conn->sock->ops->sendmsg(
+ conn->sock, &reply, sizeof(reply), 0);
+ if (send_ret < (ssize_t) sizeof(reply)) {
+ ERR("Failed to send \"get configuration\" command reply (ret = %zd)",
+ send_ret);
+ ret = -1;
+ }
+end_no_reply:
+ return ret;
+}
+
#define DBG_CMD(cmd_name, conn) \
DBG3("Processing \"%s\" command for socket %i", cmd_name, conn->sock->fd);
DBG_CMD("RELAYD_TRACE_CHUNK_EXISTS", conn);
ret = relay_trace_chunk_exists(header, conn, payload);
break;
+ case RELAYD_GET_CONFIGURATION:
+ DBG_CMD("RELAYD_GET_CONFIGURATION", conn);
+ ret = relay_get_configuration(header, conn, payload);
+ break;
case RELAYD_UPDATE_SYNC_INFO:
default:
ERR("Received unknown command (%u)", header->cmd);