#include <common/error.h>
#include <common/fd-tracker/fd-tracker.h>
#include <common/fd-tracker/utils.h>
+#include <common/fs-handle.h>
#include <common/fs-handle-internal.h>
#include <common/hashtable/hashtable.h>
#include <common/hashtable/utils.h>
char *path;
/* An unset id means the chunk is anonymous. */
LTTNG_OPTIONAL(uint64_t) id;
+
+ /*
+ * The creation and close timestamps are NOT monotonic.
+ * They must not be used in context were monotonicity is required.
+ */
LTTNG_OPTIONAL(time_t) timestamp_creation;
LTTNG_OPTIONAL(time_t) timestamp_close;
+
LTTNG_OPTIONAL(struct chunk_credentials) credentials;
struct lttng_directory_handle *session_output_directory;
struct lttng_directory_handle *chunk_directory;
bool reference_acquired;
char *path_copy = strdup(path);
- assert(fd >= 0);
+ LTTNG_ASSERT(fd >= 0);
if (!path_copy) {
PERROR("Failed to copy file path while creating untracked filesystem handle");
goto end;
handle->fd = fd;
reference_acquired = lttng_directory_handle_get(directory_handle);
- assert(reference_acquired);
+ LTTNG_ASSERT(reference_acquired);
handle->location.directory_handle = directory_handle;
/* Ownership is transferred. */
handle->location.path = path_copy;
}
if (chunk->chunk_directory) {
lttng_directory_handle_put(chunk->chunk_directory);
- chunk->chunk_directory = NULL;
+ chunk->chunk_directory = NULL;
}
free(chunk->name);
chunk->name = NULL;
return chunk;
}
-LTTNG_HIDDEN
struct lttng_trace_chunk *lttng_trace_chunk_create_anonymous(void)
{
DBG("Creating anonymous trace chunk");
return lttng_trace_chunk_allocate();
}
-LTTNG_HIDDEN
struct lttng_trace_chunk *lttng_trace_chunk_create(
uint64_t chunk_id, time_t chunk_creation_time, const char *path)
{
struct lttng_trace_chunk *chunk;
- char chunk_creation_datetime_buf[16] = {};
+ char chunk_creation_datetime_buf[16] = {};
const char *chunk_creation_datetime_str = "(formatting error)";
- struct tm timeinfo_buf, *timeinfo;
+ struct tm timeinfo_buf, *timeinfo;
timeinfo = localtime_r(&chunk_creation_time, &timeinfo_buf);
if (timeinfo) {
ERR("Failed to allocate trace chunk name storage");
goto error;
}
- }
+ }
if (path) {
chunk->path = strdup(path);
if (!chunk->path) {
}
}
- DBG("Chunk name set to \"%s\"", chunk->name ? : "(none)");
+ DBG("Chunk name set to \"%s\"", chunk->name ? : "(none)");
end:
return chunk;
error:
return NULL;
}
-LTTNG_HIDDEN
void lttng_trace_chunk_set_fd_tracker(struct lttng_trace_chunk *chunk,
struct fd_tracker *fd_tracker)
{
- assert(!chunk->session_output_directory);
- assert(!chunk->chunk_directory);
- assert(lttng_dynamic_pointer_array_get_count(&chunk->files) == 0);
+ LTTNG_ASSERT(!chunk->session_output_directory);
+ LTTNG_ASSERT(!chunk->chunk_directory);
+ LTTNG_ASSERT(lttng_dynamic_pointer_array_get_count(&chunk->files) == 0);
chunk->fd_tracker = fd_tracker;
}
-LTTNG_HIDDEN
struct lttng_trace_chunk *lttng_trace_chunk_copy(
struct lttng_trace_chunk *source_chunk)
{
const bool reference_acquired = lttng_directory_handle_get(
source_chunk->session_output_directory);
- assert(reference_acquired);
+ LTTNG_ASSERT(reference_acquired);
new_chunk->session_output_directory =
source_chunk->session_output_directory;
}
const bool reference_acquired = lttng_directory_handle_get(
source_chunk->chunk_directory);
- assert(reference_acquired);
+ LTTNG_ASSERT(reference_acquired);
new_chunk->chunk_directory = source_chunk->chunk_directory;
}
new_chunk->close_command = source_chunk->close_command;
return NULL;
}
-LTTNG_HIDDEN
enum lttng_trace_chunk_status lttng_trace_chunk_get_id(
struct lttng_trace_chunk *chunk, uint64_t *id)
{
return status;
}
-LTTNG_HIDDEN
enum lttng_trace_chunk_status lttng_trace_chunk_get_creation_timestamp(
struct lttng_trace_chunk *chunk, time_t *creation_ts)
return status;
}
-LTTNG_HIDDEN
enum lttng_trace_chunk_status lttng_trace_chunk_get_close_timestamp(
struct lttng_trace_chunk *chunk, time_t *close_ts)
{
return status;
}
-LTTNG_HIDDEN
enum lttng_trace_chunk_status lttng_trace_chunk_set_close_timestamp(
struct lttng_trace_chunk *chunk, time_t close_ts)
{
status = LTTNG_TRACE_CHUNK_STATUS_INVALID_OPERATION;
goto end;
}
+
+ /*
+ * Note: we do not enforce that the closing timestamp be greater or
+ * equal to the begin timestamp. These timestamps are used for
+ * generating the chunk name and should only be used in context where
+ * the monotonicity of time is not important. The source of those
+ * timestamps is NOT monotonic and represent the system calendar time,
+ * also know as the wall time.
+ */
if (chunk->timestamp_creation.value > close_ts) {
- ERR("Failed to set trace chunk close timestamp: close timestamp is before creation timestamp");
- status = LTTNG_TRACE_CHUNK_STATUS_INVALID_ARGUMENT;
- goto end;
+ WARN("Set trace chunk close timestamp: close timestamp is before creation timestamp, begin : %ld, close : %ld",
+ chunk->timestamp_creation.value, close_ts);
}
+
LTTNG_OPTIONAL_SET(&chunk->timestamp_close, close_ts);
if (!chunk->name_overridden) {
free(chunk->name);
return status;
}
-LTTNG_HIDDEN
enum lttng_trace_chunk_status lttng_trace_chunk_get_name(
struct lttng_trace_chunk *chunk, const char **name,
bool *name_overridden)
enum lttng_trace_chunk_status status = LTTNG_TRACE_CHUNK_STATUS_OK;
pthread_mutex_lock(&chunk->lock);
- if (name_overridden) {
+ if (name_overridden) {
*name_overridden = chunk->name_overridden;
- }
- if (!chunk->name) {
+ }
+ if (!chunk->name) {
status = LTTNG_TRACE_CHUNK_STATUS_NONE;
goto end;
}
return status;
}
-LTTNG_HIDDEN
bool lttng_trace_chunk_get_name_overridden(struct lttng_trace_chunk *chunk)
{
bool name_overridden;
return true;
}
-LTTNG_HIDDEN
enum lttng_trace_chunk_status lttng_trace_chunk_override_name(
struct lttng_trace_chunk *chunk, const char *name)
const bool reference_acquired = lttng_directory_handle_get(
chunk->session_output_directory);
- assert(reference_acquired);
+ LTTNG_ASSERT(reference_acquired);
rename_directory = chunk->session_output_directory;
/* Move toplevel directories. */
return status;
}
-LTTNG_HIDDEN
enum lttng_trace_chunk_status lttng_trace_chunk_rename_path(
struct lttng_trace_chunk *chunk, const char *path)
return status;
}
-LTTNG_HIDDEN
enum lttng_trace_chunk_status lttng_trace_chunk_get_credentials(
struct lttng_trace_chunk *chunk,
struct lttng_credentials *credentials)
pthread_mutex_lock(&chunk->lock);
if (chunk->credentials.is_set) {
if (chunk->credentials.value.use_current_user) {
- credentials->uid = geteuid();
- credentials->gid = getegid();
+ LTTNG_OPTIONAL_SET(&credentials->uid, geteuid());
+ LTTNG_OPTIONAL_SET(&credentials->gid, getegid());
} else {
*credentials = chunk->credentials.value.user;
}
return status;
}
-LTTNG_HIDDEN
enum lttng_trace_chunk_status lttng_trace_chunk_set_credentials(
struct lttng_trace_chunk *chunk,
const struct lttng_credentials *user_credentials)
return status;
}
-LTTNG_HIDDEN
enum lttng_trace_chunk_status lttng_trace_chunk_set_credentials_current_user(
struct lttng_trace_chunk *chunk)
{
}
-LTTNG_HIDDEN
enum lttng_trace_chunk_status lttng_trace_chunk_set_as_owner(
struct lttng_trace_chunk *chunk,
struct lttng_directory_handle *session_output_directory)
status = LTTNG_TRACE_CHUNK_STATUS_ERROR;
goto end;
}
- if (chunk->path[0] != '\0') {
+ if (chunk->path && chunk->path[0] != '\0') {
ret = lttng_directory_handle_create_subdirectory_as_user(
session_output_directory,
chunk->path,
* A nameless chunk does not need its own output directory.
* The session's output directory will be used.
*/
- const bool reference_acquired =
- lttng_directory_handle_get(
- session_output_directory);
+ reference_acquired = lttng_directory_handle_get(
+ session_output_directory);
- assert(reference_acquired);
+ LTTNG_ASSERT(reference_acquired);
chunk_directory_handle = session_output_directory;
}
chunk->chunk_directory = chunk_directory_handle;
chunk_directory_handle = NULL;
reference_acquired = lttng_directory_handle_get(
session_output_directory);
- assert(reference_acquired);
+ LTTNG_ASSERT(reference_acquired);
chunk->session_output_directory = session_output_directory;
LTTNG_OPTIONAL_SET(&chunk->mode, TRACE_CHUNK_MODE_OWNER);
end:
return status;
}
-LTTNG_HIDDEN
enum lttng_trace_chunk_status lttng_trace_chunk_set_as_user(
struct lttng_trace_chunk *chunk,
struct lttng_directory_handle *chunk_directory)
goto end;
}
reference_acquired = lttng_directory_handle_get(chunk_directory);
- assert(reference_acquired);
+ LTTNG_ASSERT(reference_acquired);
chunk->chunk_directory = chunk_directory;
LTTNG_OPTIONAL_SET(&chunk->mode, TRACE_CHUNK_MODE_USER);
end:
return status;
}
-LTTNG_HIDDEN
enum lttng_trace_chunk_status
lttng_trace_chunk_get_session_output_directory_handle(
struct lttng_trace_chunk *chunk,
const bool reference_acquired = lttng_directory_handle_get(
chunk->session_output_directory);
- assert(reference_acquired);
+ LTTNG_ASSERT(reference_acquired);
*handle = chunk->session_output_directory;
}
end:
return status;
}
-LTTNG_HIDDEN
enum lttng_trace_chunk_status lttng_trace_chunk_borrow_chunk_directory_handle(
struct lttng_trace_chunk *chunk,
const struct lttng_directory_handle **handle)
return ret;
}
-LTTNG_HIDDEN
enum lttng_trace_chunk_status lttng_trace_chunk_create_subdirectory(
struct lttng_trace_chunk *chunk,
const char *path)
}
ret = lttng_dynamic_pointer_array_remove_pointer(
&chunk->files, index);
- assert(!ret);
+ LTTNG_ASSERT(!ret);
}
static
goto end;
}
if (chunk->fd_tracker) {
- assert(chunk->credentials.value.use_current_user);
+ LTTNG_ASSERT(chunk->credentials.value.use_current_user);
*out_handle = fd_tracker_open_fs_handle(chunk->fd_tracker,
chunk->chunk_directory, file_path, flags, &mode);
ret = *out_handle ? 0 : -1;
return status;
}
-LTTNG_HIDDEN
enum lttng_trace_chunk_status lttng_trace_chunk_open_fs_handle(
struct lttng_trace_chunk *chunk,
const char *file_path,
return status;
}
-LTTNG_HIDDEN
enum lttng_trace_chunk_status lttng_trace_chunk_open_file(
struct lttng_trace_chunk *chunk,
const char *file_path,
* Using this method is never valid when an fd_tracker is being
* used since the resulting file descriptor would not be tracked.
*/
- assert(!chunk->fd_tracker);
+ LTTNG_ASSERT(!chunk->fd_tracker);
status = _lttng_trace_chunk_open_fs_handle_locked(chunk, file_path,
flags, mode, &fs_handle, expect_no_file);
pthread_mutex_unlock(&chunk->lock);
return status;
}
-LTTNG_HIDDEN
int lttng_trace_chunk_unlink_file(struct lttng_trace_chunk *chunk,
const char *file_path)
{
goto end;
}
- assert(trace_chunk->mode.value == TRACE_CHUNK_MODE_OWNER);
- assert(!trace_chunk->name_overridden);
- assert(trace_chunk->path);
+ LTTNG_ASSERT(trace_chunk->mode.value == TRACE_CHUNK_MODE_OWNER);
+ LTTNG_ASSERT(!trace_chunk->name_overridden);
+ LTTNG_ASSERT(trace_chunk->path);
archived_chunk_name = generate_chunk_name(chunk_id, creation_timestamp,
&close_timestamp);
ret = lttng_directory_handle_create_subdirectory_as_user(
trace_chunk->session_output_directory,
- DEFAULT_ARCHIVED_TRACE_CHUNKS_DIRECTORY,
+ DEFAULT_ARCHIVED_TRACE_CHUNKS_DIRECTORY,
DIR_CREATION_MODE,
!trace_chunk->credentials.value.use_current_user ?
&trace_chunk->credentials.value.user :
DBG("Trace chunk \"delete\" close command post-release (Owner)");
- assert(trace_chunk->session_output_directory);
- assert(trace_chunk->chunk_directory);
+ LTTNG_ASSERT(trace_chunk->session_output_directory);
+ LTTNG_ASSERT(trace_chunk->chunk_directory);
/* Remove empty directories. */
count = lttng_dynamic_pointer_array_get_count(
}
}
-LTTNG_HIDDEN
enum lttng_trace_chunk_status lttng_trace_chunk_get_close_command(
struct lttng_trace_chunk *chunk,
enum lttng_trace_chunk_command_type *command_type)
return status;
}
-LTTNG_HIDDEN
enum lttng_trace_chunk_status lttng_trace_chunk_set_close_command(
struct lttng_trace_chunk *chunk,
enum lttng_trace_chunk_command_type close_command)
DBG("Overriding trace chunk close command from \"%s\" to \"%s\"",
close_command_names[chunk->close_command.value],
close_command_names[close_command]);
- } else {
+ } else {
DBG("Setting trace chunk close command to \"%s\"",
close_command_names[close_command]);
- }
+ }
/*
* Unset close command for no-op for backward compatibility with relayd
* 2.11.
return status;
}
-LTTNG_HIDDEN
const char *lttng_trace_chunk_command_type_get_name(
enum lttng_trace_chunk_command_type command)
{
}
}
-LTTNG_HIDDEN
+bool lttng_trace_chunk_ids_equal(const struct lttng_trace_chunk *chunk_a,
+ const struct lttng_trace_chunk *chunk_b)
+{
+ bool equal = false;
+
+ if (chunk_a == chunk_b) {
+ equal = true;
+ goto end;
+ }
+
+ if (!!chunk_a ^ !!chunk_b) {
+ goto end;
+ }
+
+ if (chunk_a->id.is_set ^ chunk_a->id.is_set) {
+ /* One id is set and not the other, thus they are not equal. */
+ goto end;
+ }
+
+ if (!chunk_a->id.is_set) {
+ /* Both ids are unset. */
+ equal = true;
+ } else {
+ equal = chunk_a->id.value == chunk_b->id.value;
+ }
+
+end:
+ return equal;
+}
+
bool lttng_trace_chunk_get(struct lttng_trace_chunk *chunk)
{
return urcu_ref_get_unless_zero(&chunk->ref);
}
}
-LTTNG_HIDDEN
void lttng_trace_chunk_put(struct lttng_trace_chunk *chunk)
{
if (!chunk) {
return;
}
- assert(chunk->ref.refcount);
+ LTTNG_ASSERT(chunk->ref.refcount);
urcu_ref_put(&chunk->ref, lttng_trace_chunk_release);
}
-LTTNG_HIDDEN
struct lttng_trace_chunk_registry *lttng_trace_chunk_registry_create(void)
{
struct lttng_trace_chunk_registry *registry;
return NULL;
}
-LTTNG_HIDDEN
void lttng_trace_chunk_registry_destroy(
struct lttng_trace_chunk_registry *registry)
{
}
if (registry->ht) {
int ret = cds_lfht_destroy(registry->ht, NULL);
- assert(!ret);
+ LTTNG_ASSERT(!ret);
}
free(registry);
}
return element;
}
-LTTNG_HIDDEN
struct lttng_trace_chunk *
lttng_trace_chunk_registry_publish_chunk(
struct lttng_trace_chunk_registry *registry,
struct lttng_trace_chunk_registry_element *published_element;
published_node = cds_lfht_add_unique(registry->ht,
- element_hash,
+ element_hash,
lttng_trace_chunk_registry_element_match,
- element,
+ element,
&element->trace_chunk_registry_ht_node);
if (published_node == &element->trace_chunk_registry_ht_node) {
/* Successfully published the new element. */
- element->registry = registry;
+ element->registry = registry;
/* Acquire a reference for the caller. */
if (lttng_trace_chunk_get(&element->chunk)) {
break;
return published_chunk;
}
-LTTNG_HIDDEN
struct lttng_trace_chunk *
lttng_trace_chunk_registry_find_chunk(
const struct lttng_trace_chunk_registry *registry,
uint64_t session_id, uint64_t chunk_id)
{
- return _lttng_trace_chunk_registry_find_chunk(registry,
+ return _lttng_trace_chunk_registry_find_chunk(registry,
session_id, &chunk_id);
}
-LTTNG_HIDDEN
int lttng_trace_chunk_registry_chunk_exists(
const struct lttng_trace_chunk_registry *registry,
uint64_t session_id, uint64_t chunk_id, bool *chunk_exists)
return ret;
}
-LTTNG_HIDDEN
struct lttng_trace_chunk *
lttng_trace_chunk_registry_find_anonymous_chunk(
const struct lttng_trace_chunk_registry *registry,
uint64_t session_id)
{
- return _lttng_trace_chunk_registry_find_chunk(registry,
+ return _lttng_trace_chunk_registry_find_chunk(registry,
session_id, NULL);
}
-LTTNG_HIDDEN
unsigned int lttng_trace_chunk_registry_put_each_chunk(
const struct lttng_trace_chunk_registry *registry)
{