+++ /dev/null
-/*
- * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#include "common/time.h"
-#include <assert.h>
-#include <regex.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <common/common.h>
-#include <common/defaults.h>
-#include <common/utils.h>
-
-#include "backward-compatibility-group-by.h"
-
-#define DATETIME_STRING_SIZE 16
-#define DATETIME_REGEX \
- ".*-[1-2][0-9][0-9][0-9][0-1][0-9][0-3][0-9]-[0-2][0-9][0-5][0-9][0-5][0-9]$"
-
-/*
- * Provide support for --group-output-by-session for producer >= 2.4 and < 2.11.
- * Take the stream path, extract all available information, craft a new path to
- * the best of our ability enforcing the group by session.
- *
- * Return the allocated string containing the new stream path or else NULL.
- */
-char *backward_compat_group_by_session(const char *path,
- const char *local_session_name,
- time_t relay_session_creation_time)
-{
- int ret;
- size_t len;
- char *leftover_ptr;
- char *local_copy = NULL;
- char *datetime = NULL;
- char *partial_base_path = NULL;
- char *filepath_per_session = NULL;
- const char *second_token_ptr;
- const char *leftover_second_token_ptr;
- const char *hostname_ptr;
- regex_t regex;
-
- assert(path);
- assert(local_session_name);
- assert(local_session_name[0] != '\0');
-
- DBG("Parsing path \"%s\" of session \"%s\" to create a new path that is grouped by session",
- path, local_session_name);
-
- /* Get a local copy for strtok */
- local_copy = strdup(path);
- if (!local_copy) {
- PERROR("Failed to parse session path: couldn't copy input path");
- goto error;
- }
-
- /*
- * The use of strtok with '/' as delimiter is valid since we refuse '/'
- * in session name and '/' is not a valid hostname character based on
- * RFC-952 [1], RFC-921 [2] and refined in RFC-1123 [3].
- * [1] https://tools.ietf.org/html/rfc952
- * [2] https://tools.ietf.org/html/rfc921
- * [3] https://tools.ietf.org/html/rfc1123#page-13
- */
-
- /*
- * Get the hostname and possible session_name.
- * Note that we can get the hostname and session name from the
- * relay_session object we already have. Still, it is easier to
- * tokenized the passed path to obtain the start of the path leftover.
- */
- hostname_ptr = strtok_r(local_copy, "/", &leftover_ptr);
- if (!hostname_ptr) {
- ERR("Failed to parse session path \"%s\": couldn't identify hostname",
- path);
- goto error;
- }
-
- second_token_ptr = strtok_r(NULL, "/", &leftover_ptr);
- if (!second_token_ptr) {
- ERR("Failed to parse session path \"%s\": couldn't identify session name",
- path);
- goto error;
- }
-
- /*
- * Check if the second token is a base path set at url level. This is
- * legal in streaming, live and snapshot [1]. Otherwise it is the
- * session name with possibly a datetime attached [2]. Note that when
- * "adding" snapshot output (lttng snapshot add-output), no session name
- * is present in the path by default. The handling for "base path" take
- * care of this case as well.
- * [1] e.g --set-url net://localhost/my_marvellous_path
- * [2] Can be:
- * <session_name>
- * When using --snapshot on session create.
- * <session_name>-<date>-<time>
- * <auto>-<date>-<time>
- */
- if (strncmp(second_token_ptr, local_session_name,
- strlen(local_session_name)) != 0) {
- /*
- * Token does not start with session name.
- * This mean this is an extra path scenario.
- * Duplicate the current token since it is part of an
- * base_path.
- * Set secDuplicate the current token since it is part of an
- * base_path. The rest is the leftover.
- * Set second_token_ptr to the local_session_name for further
- * processing.
- */
- partial_base_path = strdup(second_token_ptr);
- if (!partial_base_path) {
- PERROR("Failed to parse session path: couldn't copy partial base path");
- goto error;
- }
-
- second_token_ptr = local_session_name;
- }
-
- /*
- * Based on the previous test, we can move inside the token ptr to
- * remove the "local_session_name" and inspect the rest of the token.
- * We are looking into extracting the creation datetime from either the
- * session_name or the token. We need to to all this gymnastic because
- * an extra path could decide to append a datetime to its first
- * subdirectory.
- * Possible scenario:
- * <session_name>
- * <session_name>-<date>-<time>
- * <auto>-<date>-<time>
- * <session_name>_base_path_foo_bar
- * <session_name>-<false date>-<false-time> (via a base path)
- *
- * We have no way to discern from the basic scenario of:
- * <session_name>-<date>-<time>
- * and one done using a base path with the exact format we normally
- * expect.
- *
- * e.g:
- * lttng create my_session -U
- * net://localhost/my_session-19910319-120000/
- */
- ret = regcomp(®ex, DATETIME_REGEX, 0);
- if (ret) {
- ERR("Failed to parse session path: regex compilation failed with code %d", ret);
- goto error;
- }
-
- leftover_second_token_ptr =
- second_token_ptr + strlen(local_session_name);
- len = strlen(leftover_second_token_ptr);
- if (len == 0) {
- /*
- * We are either dealing with an auto session name or only the
- * session_name. If this is a auto session name, we need to
- * fetch the creation datetime.
- */
- ret = regexec(®ex, local_session_name, 0, NULL, 0);
- if (ret == 0) {
- const ssize_t local_session_name_offset =
- strlen(local_session_name) - DATETIME_STR_LEN + 1;
-
- assert(local_session_name_offset >= 0);
- datetime = strdup(local_session_name +
- local_session_name_offset);
- if (!datetime) {
- PERROR("Failed to parse session path: couldn't copy datetime on regex match");
- goto error_regex;
- }
- } else {
- datetime = zmalloc(DATETIME_STR_LEN);
- if (!datetime) {
- PERROR("Failed to allocate DATETIME string");
- goto error;
- }
-
- ret = time_to_datetime_str(relay_session_creation_time,
- datetime, DATETIME_STR_LEN);
- if (ret) {
- /* time_to_datetime_str already logs errors. */
- goto error;
- }
- }
- } else if (len == DATETIME_STR_LEN &&
- !regexec(®ex, leftover_second_token_ptr, 0, NULL,
- 0)) {
- /*
- * The leftover from the second token is of format
- * "-<datetime>", use it as the creation time.
- * Ignore leading "-".
- */
- datetime = strdup(&leftover_second_token_ptr[1]);
- if (!datetime) {
- PERROR("Failed to parse session path: couldn't copy datetime on regex match");
- goto error_regex;
- }
- } else {
- /*
- * Base path scenario.
- * We cannot try to extract the datetime from the session name
- * since nothing prevent a user to name a session in the
- * "name-<datetime>" format. Using the datetime from such a
- * session would be invalid.
- * */
- assert(partial_base_path == NULL);
- assert(datetime == NULL);
-
- partial_base_path = strdup(second_token_ptr);
- if (!partial_base_path) {
- PERROR("Failed to parse session path: couldn't copy partial base path");
- goto error_regex;
- }
- }
-
- ret = asprintf(&filepath_per_session, "%s/%s%s%s/%s%s%s",
- local_session_name, hostname_ptr, datetime ? "-" : "",
- datetime ? datetime : "",
- partial_base_path ? partial_base_path : "",
- partial_base_path ? "/" : "", leftover_ptr);
- if (ret < 0) {
- filepath_per_session = NULL;
- goto error;
- }
-error_regex:
- regfree(®ex);
-error:
- free(local_copy);
- free(partial_base_path);
- free(datetime);
- return filepath_per_session;
-}