AM_CONDITIONAL([BUILD_LIB_TESTPOINT], [test x$build_lib_testpoint = xyes])
AM_CONDITIONAL([BUILD_LIB_UST_CONSUMER], [test x$build_lib_ust_consumer = xyes])
-AM_CFLAGS="$OPT_CFLAGS $WARN_CFLAGS $PTHREAD_CFLAGS"
+AM_CFLAGS="-fvisibility=hidden $OPT_CFLAGS $WARN_CFLAGS $PTHREAD_CFLAGS"
AC_SUBST(AM_CFLAGS)
-AM_CXXFLAGS="$OPT_CXXFLAGS $WARN_CXXFLAGS $PTHREAD_CFLAGS"
+AM_CXXFLAGS="-fvisibility=hidden -fvisibility-inlines-hidden $OPT_CXXFLAGS $WARN_CXXFLAGS $PTHREAD_CFLAGS"
AC_SUBST(AM_CXXFLAGS)
# This is set even though it is empty, so Makefiles can do "AM_LDFLAGS += ...".
lttng/location.h \
lttng/log-level-rule.h \
lttng/lttng-error.h \
+ lttng/lttng-export.h \
lttng/lttng.h \
lttng/rotation.h \
lttng/save.h \
#ifndef LTTNG_ACTION_H
#define LTTNG_ACTION_H
+#include <lttng/lttng-export.h>
+
struct lttng_action;
#ifdef __cplusplus
*
* Returns the type of an action on success, LTTNG_ACTION_TYPE_UNKNOWN on error.
*/
-extern enum lttng_action_type lttng_action_get_type(
+LTTNG_EXPORT extern enum lttng_action_type lttng_action_get_type(
const struct lttng_action *action);
/*
* Destroy (frees) an action object.
*/
-extern void lttng_action_destroy(struct lttng_action *action);
+LTTNG_EXPORT extern void lttng_action_destroy(struct lttng_action *action);
#ifdef __cplusplus
}
#ifndef LTTNG_ACTION_LIST_H
#define LTTNG_ACTION_LIST_H
+#include <lttng/lttng-export.h>
+
struct lttng_action;
#ifdef __cplusplus
* Returns a new action list on success, NULL on failure. This action list
* must be destroyed using lttng_action_list_destroy().
*/
-extern struct lttng_action *lttng_action_list_create(void);
+LTTNG_EXPORT extern struct lttng_action *lttng_action_list_create(void);
/*
* Add an action to an lttng_action object of type LTTNG_ACTION_LIST.
*
* Adding an action list to an action list is not supported.
*/
-extern enum lttng_action_status lttng_action_list_add_action(
+LTTNG_EXPORT extern enum lttng_action_status lttng_action_list_add_action(
struct lttng_action *list, struct lttng_action *action);
/*
* Get the number of actions in an action list.
*/
-extern enum lttng_action_status lttng_action_list_get_count(
+LTTNG_EXPORT extern enum lttng_action_status lttng_action_list_get_count(
const struct lttng_action *list, unsigned int *count);
/*
*
* Returns an action, or NULL on error.
*/
-extern const struct lttng_action *lttng_action_list_get_at_index(
+LTTNG_EXPORT extern const struct lttng_action *lttng_action_list_get_at_index(
const struct lttng_action *list,
unsigned int index);
#ifndef LTTNG_ACTION_NOTIFY_H
#define LTTNG_ACTION_NOTIFY_H
+#include <lttng/lttng-export.h>
+
struct lttng_action;
struct lttng_rate_policy;
* Returns a new action on success, NULL on failure. This action must be
* destroyed using lttng_action_destroy().
*/
-extern struct lttng_action *lttng_action_notify_create(void);
+LTTNG_EXPORT extern struct lttng_action *lttng_action_notify_create(void);
/*
* Set the rate policy of a notify action.
* LTTNG_ACTION_STATUS_ERROR on internal error,
* LTTNG_ACTION_STATUS_INVALID if invalid parameters are passed.
*/
-extern enum lttng_action_status lttng_action_notify_set_rate_policy(
+LTTNG_EXPORT extern enum lttng_action_status lttng_action_notify_set_rate_policy(
struct lttng_action *action,
const struct lttng_rate_policy *policy);
* Returns LTTNG_ACTION_STATUS_OK on success,
* LTTNG_ACTION_STATUS_INVALID if invalid parameters are passed.
*/
-extern enum lttng_action_status lttng_action_notify_get_rate_policy(
+LTTNG_EXPORT extern enum lttng_action_status lttng_action_notify_get_rate_policy(
const struct lttng_action *action,
const struct lttng_rate_policy **policy);
#ifndef LTTNG_ACTION_PATH_H
#define LTTNG_ACTION_PATH_H
+#include <lttng/lttng-export.h>
#include <stdint.h>
#include <stddef.h>
*
* The `indexes` are copied internally and can be disposed-of by the caller.
*/
-extern struct lttng_action_path *lttng_action_path_create(
+LTTNG_EXPORT extern struct lttng_action_path *lttng_action_path_create(
const uint64_t *indexes, size_t index_count);
/*
* Get the count of indexes in an action path.
*/
-extern enum lttng_action_path_status lttng_action_path_get_index_count(
+LTTNG_EXPORT extern enum lttng_action_path_status lttng_action_path_get_index_count(
const struct lttng_action_path *path, size_t *index_count);
/*
* Get an index from an action path.
*/
-extern enum lttng_action_path_status lttng_action_path_get_index_at_index(
+LTTNG_EXPORT extern enum lttng_action_path_status lttng_action_path_get_index_at_index(
const struct lttng_action_path *path,
size_t path_index,
uint64_t *out_index);
/*
* Destroy an action path object.
*/
-extern void lttng_action_path_destroy(struct lttng_action_path *action_path);
+LTTNG_EXPORT extern void lttng_action_path_destroy(struct lttng_action_path *action_path);
#ifdef __cplusplus
}
#define LTTNG_RATE_POLICY_H
#include <inttypes.h>
+#include <lttng/lttng-export.h>
#include <sys/types.h>
struct lttng_rate_policy;
/*
* Get the type of a rate policy.
*/
-extern enum lttng_rate_policy_type lttng_rate_policy_get_type(
+LTTNG_EXPORT extern enum lttng_rate_policy_type lttng_rate_policy_get_type(
const struct lttng_rate_policy *policy);
/*
* rate_policy objects must be destroyed using the lttng_rate_policy_destroy()
* function.
*/
-extern struct lttng_rate_policy *lttng_rate_policy_every_n_create(
+LTTNG_EXPORT extern struct lttng_rate_policy *lttng_rate_policy_every_n_create(
uint64_t interval);
/*
* on success, LTTNG_RATE_FIRING_POLICY_STATUS_INVALID if an invalid
* parameter is passed.
*/
-extern enum lttng_rate_policy_status lttng_rate_policy_every_n_get_interval(
+LTTNG_EXPORT extern enum lttng_rate_policy_status lttng_rate_policy_every_n_get_interval(
const struct lttng_rate_policy *policy, uint64_t *interval);
/*
* rate_policy objects must be destroyed using the lttng_rate_policy_destroy()
* function.
*/
-extern struct lttng_rate_policy *lttng_rate_policy_once_after_n_create(
+LTTNG_EXPORT extern struct lttng_rate_policy *lttng_rate_policy_once_after_n_create(
uint64_t threshold);
/*
* on success, LTTNG_RATE_POLICY_STATUS_INVALID if an invalid
* parameter is passed.
*/
-extern enum lttng_rate_policy_status
+LTTNG_EXPORT extern enum lttng_rate_policy_status
lttng_rate_policy_once_after_n_get_threshold(
const struct lttng_rate_policy *policy, uint64_t *threshold);
/*
* Destroy (frees) a rate policy object.
*/
-extern void lttng_rate_policy_destroy(struct lttng_rate_policy *policy);
+LTTNG_EXPORT extern void lttng_rate_policy_destroy(struct lttng_rate_policy *policy);
#ifdef __cplusplus
}
#ifndef LTTNG_ACTION_ROTATE_SESSION_H
#define LTTNG_ACTION_ROTATE_SESSION_H
+#include <lttng/lttng-export.h>
+
struct lttng_action;
struct lttng_rate_policy;
* Returns a new action on success, NULL on failure. This action must be
* destroyed using lttng_action_destroy().
*/
-extern struct lttng_action *lttng_action_rotate_session_create(void);
+LTTNG_EXPORT extern struct lttng_action *lttng_action_rotate_session_create(void);
/*
* Set the session name of an lttng_action object of type
* LTTNG_ACTION_TYPE_ROTATE_SESSION.
*/
-extern enum lttng_action_status lttng_action_rotate_session_set_session_name(
+LTTNG_EXPORT extern enum lttng_action_status lttng_action_rotate_session_set_session_name(
struct lttng_action *action, const char *session_name);
/*
* Get the session name of an lttng_action object of type
* LTTNG_ACTION_TYPE_ROTATE_SESSION.
*/
-extern enum lttng_action_status lttng_action_rotate_session_get_session_name(
+LTTNG_EXPORT extern enum lttng_action_status lttng_action_rotate_session_get_session_name(
const struct lttng_action *action, const char **session_name);
/*
* LTTNG_ACTION_STATUS_ERROR on internal error,
* LTTNG_ACTION_STATUS_INVALID if invalid parameters are passed.
*/
-extern enum lttng_action_status lttng_action_rotate_session_set_rate_policy(
+LTTNG_EXPORT extern enum lttng_action_status lttng_action_rotate_session_set_rate_policy(
struct lttng_action *action,
const struct lttng_rate_policy *policy);
* Returns LTTNG_ACTION_STATUS_OK on success,
* LTTNG_ACTION_STATUS_INVALID if invalid parameters are passed.
*/
-extern enum lttng_action_status lttng_action_rotate_session_get_rate_policy(
+LTTNG_EXPORT extern enum lttng_action_status lttng_action_rotate_session_get_rate_policy(
const struct lttng_action *action,
const struct lttng_rate_policy **policy);
#ifndef LTTNG_ACTION_SNAPSHOT_SESSION_H
#define LTTNG_ACTION_SNAPSHOT_SESSION_H
+#include <lttng/lttng-export.h>
+
#ifdef __cplusplus
extern "C" {
#endif
* Returns a new action on success, NULL on failure. This action must be
* destroyed using lttng_action_destroy().
*/
-extern struct lttng_action *lttng_action_snapshot_session_create(void);
+LTTNG_EXPORT extern struct lttng_action *lttng_action_snapshot_session_create(void);
/*
* Set the session name of an lttng_action object of type
* LTTNG_ACTION_TYPE_SNAPSHOT_SESSION.
*/
-extern enum lttng_action_status lttng_action_snapshot_session_set_session_name(
+LTTNG_EXPORT extern enum lttng_action_status lttng_action_snapshot_session_set_session_name(
struct lttng_action *action, const char *session_name);
/*
* Get the session name of an lttng_action object of type
* LTTNG_ACTION_TYPE_SNAPSHOT_SESSION.
*/
-extern enum lttng_action_status lttng_action_snapshot_session_get_session_name(
+LTTNG_EXPORT extern enum lttng_action_status lttng_action_snapshot_session_get_session_name(
const struct lttng_action *action, const char **session_name);
/*
*
* This function takes ownership of the given snapshot output.
*/
-extern enum lttng_action_status lttng_action_snapshot_session_set_output(
+LTTNG_EXPORT extern enum lttng_action_status lttng_action_snapshot_session_set_output(
struct lttng_action *action,
struct lttng_snapshot_output *output);
/*
* Get the explicit snapshot output for this snapshot session action.
*/
-extern enum lttng_action_status lttng_action_snapshot_session_get_output(
+LTTNG_EXPORT extern enum lttng_action_status lttng_action_snapshot_session_get_output(
const struct lttng_action *action,
const struct lttng_snapshot_output **output);
* LTTNG_ACTION_STATUS_ERROR on internal error,
* LTTNG_ACTION_STATUS_INVALID if invalid parameters are passed.
*/
-extern enum lttng_action_status lttng_action_snapshot_session_set_rate_policy(
+LTTNG_EXPORT extern enum lttng_action_status lttng_action_snapshot_session_set_rate_policy(
struct lttng_action *action,
const struct lttng_rate_policy *policy);
* Returns LTTNG_ACTION_STATUS_OK on success,
* LTTNG_ACTION_STATUS_INVALID if invalid parameters are passed.
*/
-extern enum lttng_action_status lttng_action_snapshot_session_get_rate_policy(
+LTTNG_EXPORT extern enum lttng_action_status lttng_action_snapshot_session_get_rate_policy(
const struct lttng_action *action,
const struct lttng_rate_policy **policy);
#ifndef LTTNG_ACTION_START_SESSION_H
#define LTTNG_ACTION_START_SESSION_H
+#include <lttng/lttng-export.h>
+
struct lttng_action;
struct lttng_rate_policy;
* Returns a new action on success, NULL on failure. This action must be
* destroyed using lttng_action_destroy().
*/
-extern struct lttng_action *lttng_action_start_session_create(void);
+LTTNG_EXPORT extern struct lttng_action *lttng_action_start_session_create(void);
/*
* Set the session name of an lttng_action object of type
* LTTNG_ACTION_TYPE_START_SESSION.
*/
-extern enum lttng_action_status lttng_action_start_session_set_session_name(
+LTTNG_EXPORT extern enum lttng_action_status lttng_action_start_session_set_session_name(
struct lttng_action *action, const char *session_name);
/*
* Get the session name of an lttng_action object of type
* LTTNG_ACTION_TYPE_START_SESSION.
*/
-extern enum lttng_action_status lttng_action_start_session_get_session_name(
+LTTNG_EXPORT extern enum lttng_action_status lttng_action_start_session_get_session_name(
const struct lttng_action *action, const char **session_name);
/*
* LTTNG_ACTION_STATUS_ERROR on internal error,
* LTTNG_ACTION_STATUS_INVALID if invalid parameters are passed.
*/
-extern enum lttng_action_status lttng_action_start_session_set_rate_policy(
+LTTNG_EXPORT extern enum lttng_action_status lttng_action_start_session_set_rate_policy(
struct lttng_action *action,
const struct lttng_rate_policy *policy);
* Returns LTTNG_ACTION_STATUS_OK on success,
* LTTNG_ACTION_STATUS_INVALID if invalid parameters are passed.
*/
-extern enum lttng_action_status lttng_action_start_session_get_rate_policy(
+LTTNG_EXPORT extern enum lttng_action_status lttng_action_start_session_get_rate_policy(
const struct lttng_action *action,
const struct lttng_rate_policy **policy);
#ifndef LTTNG_ACTION_STOP_SESSION_H
#define LTTNG_ACTION_STOP_SESSION_H
+#include <lttng/lttng-export.h>
+
struct lttng_action;
struct lttng_rate_policy;
* Returns a new action on success, NULL on failure. This action must be
* destroyed using lttng_action_destroy().
*/
-extern struct lttng_action *lttng_action_stop_session_create(void);
+LTTNG_EXPORT extern struct lttng_action *lttng_action_stop_session_create(void);
/*
* Set the session name of an lttng_action object of type
* LTTNG_ACTION_TYPE_STOP_SESSION.
*/
-extern enum lttng_action_status lttng_action_stop_session_set_session_name(
+LTTNG_EXPORT extern enum lttng_action_status lttng_action_stop_session_set_session_name(
struct lttng_action *action, const char *session_name);
/*
* Get the session name of an lttng_action object of type
* LTTNG_ACTION_TYPE_STOP_SESSION.
*/
-extern enum lttng_action_status lttng_action_stop_session_get_session_name(
+LTTNG_EXPORT extern enum lttng_action_status lttng_action_stop_session_get_session_name(
const struct lttng_action *action, const char **session_name);
/*
* LTTNG_ACTION_STATUS_ERROR on internal error,
* LTTNG_ACTION_STATUS_INVALID if invalid parameters are passed.
*/
-extern enum lttng_action_status lttng_action_stop_session_set_rate_policy(
+LTTNG_EXPORT extern enum lttng_action_status lttng_action_stop_session_set_rate_policy(
struct lttng_action *action,
const struct lttng_rate_policy *policy);
* Returns LTTNG_ACTION_STATUS_OK on success,
* LTTNG_ACTION_STATUS_INVALID if invalid parameters are passed.
*/
-extern enum lttng_action_status lttng_action_stop_session_get_rate_policy(
+LTTNG_EXPORT extern enum lttng_action_status lttng_action_stop_session_get_rate_policy(
const struct lttng_action *action,
const struct lttng_rate_policy **policy);
#include <lttng/domain.h>
#include <lttng/event.h>
+#include <lttng/lttng-export.h>
#include <stdint.h>
#ifdef __cplusplus
/*
*/
-extern struct lttng_channel *lttng_channel_create(struct lttng_domain *domain);
+LTTNG_EXPORT extern struct lttng_channel *lttng_channel_create(struct lttng_domain *domain);
/*
*/
-extern void lttng_channel_destroy(struct lttng_channel *channel);
+LTTNG_EXPORT extern void lttng_channel_destroy(struct lttng_channel *channel);
/*
* List the channel(s) of a session.
* Return the size (number of entries) of the "lttng_channel" array. Caller
* must free channels. On error, a negative LTTng error code is returned.
*/
-extern int lttng_list_channels(struct lttng_handle *handle,
+LTTNG_EXPORT extern int lttng_list_channels(struct lttng_handle *handle,
struct lttng_channel **channels);
/*
*
* Return 0 on success else a negative LTTng error code.
*/
-extern int lttng_enable_channel(struct lttng_handle *handle,
+LTTNG_EXPORT extern int lttng_enable_channel(struct lttng_handle *handle,
struct lttng_channel *chan);
/*
*
* Return 0 on success else a negative LTTng error code.
*/
-extern int lttng_disable_channel(struct lttng_handle *handle,
+LTTNG_EXPORT extern int lttng_disable_channel(struct lttng_handle *handle,
const char *name);
/*
*
* If one or both arguments are NULL, nothing happens.
*/
-extern void lttng_channel_set_default_attr(struct lttng_domain *domain,
+LTTNG_EXPORT extern void lttng_channel_set_default_attr(struct lttng_domain *domain,
struct lttng_channel_attr *attr);
/*
*
* Returns 0 on success, or a negative LTTng error code on error.
*/
-extern int lttng_channel_get_discarded_event_count(struct lttng_channel *chan,
+LTTNG_EXPORT extern int lttng_channel_get_discarded_event_count(struct lttng_channel *chan,
uint64_t *discarded_events);
/*
*
* Returns 0 on success, or a negative LTTng error code on error.
*/
-extern int lttng_channel_get_lost_packet_count(struct lttng_channel *chan,
+LTTNG_EXPORT extern int lttng_channel_get_lost_packet_count(struct lttng_channel *chan,
uint64_t *lost_packets);
-extern int lttng_channel_get_monitor_timer_interval(struct lttng_channel *chan,
+LTTNG_EXPORT extern int lttng_channel_get_monitor_timer_interval(struct lttng_channel *chan,
uint64_t *monitor_timer_interval);
-extern int lttng_channel_set_monitor_timer_interval(struct lttng_channel *chan,
+LTTNG_EXPORT extern int lttng_channel_set_monitor_timer_interval(struct lttng_channel *chan,
uint64_t monitor_timer_interval);
-extern int lttng_channel_get_blocking_timeout(struct lttng_channel *chan,
+LTTNG_EXPORT extern int lttng_channel_get_blocking_timeout(struct lttng_channel *chan,
int64_t *blocking_timeout);
-extern int lttng_channel_set_blocking_timeout(struct lttng_channel *chan,
+LTTNG_EXPORT extern int lttng_channel_set_blocking_timeout(struct lttng_channel *chan,
int64_t blocking_timeout);
#ifdef __cplusplus
#define LTTNG_CLEAR_HANDLE_H
#include <lttng/lttng-error.h>
+#include <lttng/lttng-export.h>
#ifdef __cplusplus
extern "C" {
* Destroy an lttng_clear_handle.
* The handle should be discarded after this call.
*/
-extern void lttng_clear_handle_destroy(struct lttng_clear_handle *handle);
+LTTNG_EXPORT extern void lttng_clear_handle_destroy(struct lttng_clear_handle *handle);
/*
* Wait for a session clear operation to complete.
* the clear operation itself succeeded; it indicates that the _wait_
* operation completed successfully.
*/
-extern enum lttng_clear_handle_status
+LTTNG_EXPORT extern enum lttng_clear_handle_status
lttng_clear_handle_wait_for_completion(
struct lttng_clear_handle *handle, int timeout_ms);
* was not waited-on using the handle or if the arguments of the function are
* invalid (e.g. NULL).
*/
-extern enum lttng_clear_handle_status
+LTTNG_EXPORT extern enum lttng_clear_handle_status
lttng_clear_handle_get_result(
const struct lttng_clear_handle *handle,
enum lttng_error_code *result);
#define LTTNG_CLEAR_H
#include <lttng/lttng-error.h>
+#include <lttng/lttng-export.h>
#ifdef __cplusplus
extern "C" {
* LTTNG_ERR_CLEAR_NOT_AVAILABLE_RELAY
* LTTNG_ERR_CLEAR_FAIL_CONSUMER
*/
-extern enum lttng_error_code lttng_clear_session(const char *session_name,
+LTTNG_EXPORT extern enum lttng_error_code lttng_clear_session(const char *session_name,
struct lttng_clear_handle **handle);
#ifdef __cplusplus
}
#include <lttng/condition/condition.h>
#include <stdint.h>
#include <lttng/domain.h>
+#include <lttng/lttng-export.h>
#ifdef __cplusplus
extern "C" {
* Returns a new condition on success, NULL on failure. This condition must be
* destroyed using lttng_condition_destroy().
*/
-extern struct lttng_condition *
+LTTNG_EXPORT extern struct lttng_condition *
lttng_condition_buffer_usage_low_create(void);
/*
* Returns a new condition on success, NULL on failure. This condition must be
* destroyed using lttng_condition_destroy().
*/
-extern struct lttng_condition *
+LTTNG_EXPORT extern struct lttng_condition *
lttng_condition_buffer_usage_high_create(void);
/*
* expressed as a ratio of total buffer capacity, was not set prior to this
* call.
*/
-extern enum lttng_condition_status
+LTTNG_EXPORT extern enum lttng_condition_status
lttng_condition_buffer_usage_get_threshold_ratio(
const struct lttng_condition *condition,
double *threshold_ratio);
* Returns LTTNG_CONDITION_STATUS_OK on success, LTTNG_CONDITION_STATUS_INVALID
* if invalid paramenters are passed.
*/
-extern enum lttng_condition_status
+LTTNG_EXPORT extern enum lttng_condition_status
lttng_condition_buffer_usage_set_threshold_ratio(
struct lttng_condition *condition,
double threshold_ratio);
* LTTNG_CONDITION_STATUS_UNSET if a threshold, expressed as an absolute size in
* bytes, was not set prior to this call.
*/
-extern enum lttng_condition_status
+LTTNG_EXPORT extern enum lttng_condition_status
lttng_condition_buffer_usage_get_threshold(
const struct lttng_condition *condition,
uint64_t *threshold_bytes);
* Returns LTTNG_CONDITION_STATUS_OK on success, LTTNG_CONDITION_STATUS_INVALID
* if invalid paramenters are passed.
*/
-extern enum lttng_condition_status
+LTTNG_EXPORT extern enum lttng_condition_status
lttng_condition_buffer_usage_set_threshold(
struct lttng_condition *condition,
uint64_t threshold_bytes);
* parameter is passed, or LTTNG_CONDITION_STATUS_UNSET if a session name
* was not set prior to this call.
*/
-extern enum lttng_condition_status
+LTTNG_EXPORT extern enum lttng_condition_status
lttng_condition_buffer_usage_get_session_name(
const struct lttng_condition *condition,
const char **session_name);
* Returns LTTNG_CONDITION_STATUS_OK on success, LTTNG_CONDITION_STATUS_INVALID
* if invalid paramenters are passed.
*/
-extern enum lttng_condition_status
+LTTNG_EXPORT extern enum lttng_condition_status
lttng_condition_buffer_usage_set_session_name(
struct lttng_condition *condition,
const char *session_name);
* parameter is passed, or LTTNG_CONDITION_STATUS_UNSET if a channel name
* was not set prior to this call.
*/
-extern enum lttng_condition_status
+LTTNG_EXPORT extern enum lttng_condition_status
lttng_condition_buffer_usage_get_channel_name(
const struct lttng_condition *condition,
const char **channel_name);
* Returns LTTNG_CONDITION_STATUS_OK on success, LTTNG_CONDITION_STATUS_INVALID
* if invalid paramenters are passed.
*/
-extern enum lttng_condition_status
+LTTNG_EXPORT extern enum lttng_condition_status
lttng_condition_buffer_usage_set_channel_name(
struct lttng_condition *condition,
const char *channel_name);
* or LTTNG_CONDITION_STATUS_UNSET if a domain type was not set prior to this
* call.
*/
-extern enum lttng_condition_status
+LTTNG_EXPORT extern enum lttng_condition_status
lttng_condition_buffer_usage_get_domain_type(
const struct lttng_condition *condition,
enum lttng_domain_type *type);
* Returns LTTNG_CONDITION_STATUS_OK on success, LTTNG_CONDITION_STATUS_INVALID
* if invalid paramenters are passed.
*/
-extern enum lttng_condition_status
+LTTNG_EXPORT extern enum lttng_condition_status
lttng_condition_buffer_usage_set_domain_type(
struct lttng_condition *condition,
enum lttng_domain_type type);
* as a ratio of the buffer's capacity, or LTTNG_EVALUATION_STATUS_INVALID if
* an invalid parameter is passed.
*/
-extern enum lttng_evaluation_status
+LTTNG_EXPORT extern enum lttng_evaluation_status
lttng_evaluation_buffer_usage_get_usage_ratio(
const struct lttng_evaluation *evaluation,
double *usage_ratio);
* Returns LTTNG_EVALUATION_STATUS_OK on success and a threshold expressed in
* bytes, or LTTNG_EVALUATION_STATUS_INVALID if an invalid parameter is passed.
*/
-extern enum lttng_evaluation_status
+LTTNG_EXPORT extern enum lttng_evaluation_status
lttng_evaluation_buffer_usage_get_usage(
const struct lttng_evaluation *evaluation,
uint64_t *usage_bytes);
#ifndef LTTNG_CONDITION_H
#define LTTNG_CONDITION_H
+#include <lttng/lttng-export.h>
+
#ifdef __cplusplus
extern "C" {
#endif
* Returns the type of a condition on success, LTTNG_CONDITION_TYPE_UNKNOWN on
* error.
*/
-extern enum lttng_condition_type lttng_condition_get_type(
+LTTNG_EXPORT extern enum lttng_condition_type lttng_condition_get_type(
const struct lttng_condition *condition);
/*
* Destroy (release) a condition object.
*/
-extern void lttng_condition_destroy(struct lttng_condition *condition);
+LTTNG_EXPORT extern void lttng_condition_destroy(struct lttng_condition *condition);
#ifdef __cplusplus
}
#define LTTNG_EVALUATION_H
#include <lttng/condition/condition.h>
+#include <lttng/lttng-export.h>
#ifdef __cplusplus
extern "C" {
* Returns the type of a condition on success, LTTNG_CONDITION_TYPE_UNKNOWN on
* error.
*/
-extern enum lttng_condition_type lttng_evaluation_get_type(
+LTTNG_EXPORT extern enum lttng_condition_type lttng_evaluation_get_type(
const struct lttng_evaluation *evaluation);
/*
* Destroy (frees) an evaluation object.
*/
-extern void lttng_evaluation_destroy(struct lttng_evaluation *evaluation);
+LTTNG_EXPORT extern void lttng_evaluation_destroy(struct lttng_evaluation *evaluation);
#ifdef __cplusplus
}
#include <lttng/event-rule/event-rule.h>
#include <lttng/condition/condition.h>
#include <lttng/condition/evaluation.h>
+#include <lttng/lttng-export.h>
#ifdef __cplusplus
extern "C" {
* Returns a new condition on success, NULL on failure. This condition must be
* destroyed using lttng_condition_destroy().
*/
-extern struct lttng_condition *lttng_condition_event_rule_matches_create(
+LTTNG_EXPORT extern struct lttng_condition *lttng_condition_event_rule_matches_create(
struct lttng_event_rule *rule);
/*
* Returns LTTNG_CONDITION_STATUS_OK and a pointer to the condition's rule
* on success, LTTNG_CONDITION_STATUS_INVALID if an invalid
* parameter is passed. */
-extern enum lttng_condition_status lttng_condition_event_rule_matches_get_rule(
+LTTNG_EXPORT extern enum lttng_condition_status lttng_condition_event_rule_matches_get_rule(
const struct lttng_condition *condition,
const struct lttng_event_rule **rule);
* `LTTNG_EVALUATION_EVENT_RULE_MATCHES_STATUS_NONE`:
* * The condition of `evaluation` has no capture descriptors.
*/
-extern enum lttng_evaluation_event_rule_matches_status
+LTTNG_EXPORT extern enum lttng_evaluation_event_rule_matches_status
lttng_evaluation_event_rule_matches_get_captured_values(
const struct lttng_evaluation *evaluation,
const struct lttng_event_field_value **field_val);
* `LTTNG_CONDITION_STATUS_UNSUPPORTED`:
* * The associated event-rule does not support runtime capture.
*/
-extern enum lttng_condition_status
+LTTNG_EXPORT extern enum lttng_condition_status
lttng_condition_event_rule_matches_append_capture_descriptor(
struct lttng_condition *condition,
struct lttng_event_expr *expr);
* `LTTNG_CONDITION_TYPE_EVENT_RULE_MATCHES`.
* * `count` is `NULL`.
*/
-extern enum lttng_condition_status
+LTTNG_EXPORT extern enum lttng_condition_status
lttng_condition_event_rule_matches_get_capture_descriptor_count(
const struct lttng_condition *condition, unsigned int *count);
* descriptors in `condition` (as returned by
* lttng_condition_event_rule_matches_get_capture_descriptor_count()).
*/
-extern const struct lttng_event_expr *
+LTTNG_EXPORT extern const struct lttng_event_expr *
lttng_condition_event_rule_matches_get_capture_descriptor_at_index(
const struct lttng_condition *condition, unsigned int index);
#include <lttng/condition/evaluation.h>
#include <lttng/condition/condition.h>
+#include <lttng/lttng-export.h>
#include <stdint.h>
#ifdef __cplusplus
* Returns a new condition on success, NULL on failure. This condition must be
* destroyed using lttng_condition_destroy().
*/
-extern struct lttng_condition *
+LTTNG_EXPORT extern struct lttng_condition *
lttng_condition_session_consumed_size_create(void);
/*
* LTTNG_CONDITION_STATUS_UNSET if a threshold, expressed as an absolute size in
* bytes, was not set prior to this call.
*/
-extern enum lttng_condition_status
+LTTNG_EXPORT extern enum lttng_condition_status
lttng_condition_session_consumed_size_get_threshold(
const struct lttng_condition *condition,
uint64_t *consumed_threshold_bytes);
* Returns LTTNG_CONDITION_STATUS_OK on success, LTTNG_CONDITION_STATUS_INVALID
* if invalid parameters are passed.
*/
-extern enum lttng_condition_status
+LTTNG_EXPORT extern enum lttng_condition_status
lttng_condition_session_consumed_size_set_threshold(
struct lttng_condition *condition,
uint64_t consumed_threshold_bytes);
* parameter is passed, or LTTNG_CONDITION_STATUS_UNSET if a session name
* was not set prior to this call.
*/
-extern enum lttng_condition_status
+LTTNG_EXPORT extern enum lttng_condition_status
lttng_condition_session_consumed_size_get_session_name(
const struct lttng_condition *condition,
const char **session_name);
* Returns LTTNG_CONDITION_STATUS_OK on success, LTTNG_CONDITION_STATUS_INVALID
* if invalid parameters are passed.
*/
-extern enum lttng_condition_status
+LTTNG_EXPORT extern enum lttng_condition_status
lttng_condition_session_consumed_size_set_session_name(
struct lttng_condition *condition,
const char *session_name);
* Returns LTTNG_EVALUATION_STATUS_OK on success and a threshold expressed in
* bytes, or LTTNG_EVALUATION_STATUS_INVALID if an invalid parameter is passed.
*/
-extern enum lttng_evaluation_status
+LTTNG_EXPORT extern enum lttng_evaluation_status
lttng_evaluation_session_consumed_size_get_consumed_size(
const struct lttng_evaluation *evaluation,
uint64_t *session_consumed);
#include <stdint.h>
#include <lttng/domain.h>
#include <lttng/location.h>
+#include <lttng/lttng-export.h>
#ifdef __cplusplus
extern "C" {
* Returns a new condition on success, NULL on failure. This condition must be
* destroyed using lttng_condition_destroy().
*/
-extern struct lttng_condition *
+LTTNG_EXPORT extern struct lttng_condition *
lttng_condition_session_rotation_ongoing_create(void);
/*
* Returns a new condition on success, NULL on failure. This condition must be
* destroyed using lttng_condition_destroy().
*/
-extern struct lttng_condition *
+LTTNG_EXPORT extern struct lttng_condition *
lttng_condition_session_rotation_completed_create(void);
/*
* parameter is passed, or LTTNG_CONDITION_STATUS_UNSET if a session name
* was not set prior to this call.
*/
-extern enum lttng_condition_status
+LTTNG_EXPORT extern enum lttng_condition_status
lttng_condition_session_rotation_get_session_name(
const struct lttng_condition *condition,
const char **session_name);
* Returns LTTNG_CONDITION_STATUS_OK on success, LTTNG_CONDITION_STATUS_INVALID
* if invalid paramenters are passed.
*/
-extern enum lttng_condition_status
+LTTNG_EXPORT extern enum lttng_condition_status
lttng_condition_session_rotation_set_session_name(
struct lttng_condition *condition,
const char *session_name);
* rotation, or LTTNG_EVALUATION_STATUS_INVALID if an invalid parameter is
* passed.
*/
-extern enum lttng_evaluation_status
+LTTNG_EXPORT extern enum lttng_evaluation_status
lttng_evaluation_session_rotation_get_id(
const struct lttng_evaluation *evaluation, uint64_t *id);
* LTTNG_EVALUATION_STATUS_INVALID is returned if an invalid parameter is
* passed.
*/
-extern enum lttng_evaluation_status
+LTTNG_EXPORT extern enum lttng_evaluation_status
lttng_evaluation_session_rotation_completed_get_location(
const struct lttng_evaluation *evaluation,
const struct lttng_trace_archive_location **location);
#include <lttng/rotation.h>
#include <lttng/lttng-error.h>
+#include <lttng/lttng-export.h>
#ifdef __cplusplus
extern "C" {
* Destroy an lttng_destruction_session handle.
* The handle should be discarded after this call.
*/
-extern void lttng_destruction_handle_destroy(
+LTTNG_EXPORT extern void lttng_destruction_handle_destroy(
struct lttng_destruction_handle *handle);
/*
* the destruction operation itself succeeded; it indicates that the _wait_
* operation completed successfully.
*/
-extern enum lttng_destruction_handle_status
+LTTNG_EXPORT extern enum lttng_destruction_handle_status
lttng_destruction_handle_wait_for_completion(
struct lttng_destruction_handle *handle, int timeout_ms);
* was not waited-on using the handle or if the arguments of the function are
* invalid (e.g. NULL).
*/
-extern enum lttng_destruction_handle_status
+LTTNG_EXPORT extern enum lttng_destruction_handle_status
lttng_destruction_handle_get_result(
const struct lttng_destruction_handle *handle,
enum lttng_error_code *result);
* Note that if no rotation was performed, rotation_state will be set to
* LTTNG_ROTATION_STATE_NO_ROTATION.
*/
-extern enum lttng_destruction_handle_status
+LTTNG_EXPORT extern enum lttng_destruction_handle_status
lttng_destruction_handle_get_rotation_state(
const struct lttng_destruction_handle *handle,
enum lttng_rotation_state *rotation_state);
* of the session's destruction, or if the arguments of the function are
* invalid (e.g. NULL).
*/
-extern enum lttng_destruction_handle_status
+LTTNG_EXPORT extern enum lttng_destruction_handle_status
lttng_destruction_handle_get_archive_location(
const struct lttng_destruction_handle *handle,
const struct lttng_trace_archive_location **location);
#endif
#include <lttng/constant.h>
+#include <lttng/lttng-export.h>
/*
* Domain types: the different possible tracers.
* Return the size (number of entries) of the "lttng_domain" array. Caller
* must free domains. On error, a negative LTTng error code is returned.
*/
-extern int lttng_list_domains(const char *session_name,
+LTTNG_EXPORT extern int lttng_list_domains(const char *session_name,
struct lttng_domain **domains);
#ifdef __cplusplus
#ifndef LTTNG_ENDPOINT_H
#define LTTNG_ENDPOINT_H
+#include <lttng/lttng-export.h>
+
#ifdef __cplusplus
extern "C" {
#endif
* - Otherwise (caller is an unpriviliged user):
* - Attempt to connect to the session daemon running as the caller's user.
*/
-extern struct lttng_endpoint *lttng_session_daemon_notification_endpoint;
+LTTNG_EXPORT extern struct lttng_endpoint *lttng_session_daemon_notification_endpoint;
/*
* Default LTTng session daemon command endpoint singleton.
* - Otherwise (caller is an unpriviliged user):
* - Attempt to connect to the session daemon running as the caller's user.
*/
-extern struct lttng_endpoint *lttng_session_daemon_command_endpoint;
+LTTNG_EXPORT extern struct lttng_endpoint *lttng_session_daemon_command_endpoint;
#ifdef __cplusplus
}
#define LTTNG_ERROR_QUERY_H
#include <lttng/lttng.h>
+#include <lttng/lttng-export.h>
#include <lttng/trigger/trigger.h>
#include <stdint.h>
};
/* Create an error query targetting a trigger object. */
-extern struct lttng_error_query *lttng_error_query_trigger_create(
+LTTNG_EXPORT extern struct lttng_error_query *lttng_error_query_trigger_create(
const struct lttng_trigger *trigger);
/* Create an error query targetting a trigger's condition object. */
-extern struct lttng_error_query *lttng_error_query_condition_create(
+LTTNG_EXPORT extern struct lttng_error_query *lttng_error_query_condition_create(
const struct lttng_trigger *trigger);
/*
* `action_path` is copied internally. The root of the `action_path` is the
* action of `trigger`.
*/
-extern struct lttng_error_query *lttng_error_query_action_create(
+LTTNG_EXPORT extern struct lttng_error_query *lttng_error_query_action_create(
const struct lttng_trigger *trigger,
const struct lttng_action_path *action_path);
/* Destroy an error query. */
-extern void lttng_error_query_destroy(struct lttng_error_query *query);
+LTTNG_EXPORT extern void lttng_error_query_destroy(struct lttng_error_query *query);
/*
* Run an error query against an endpoint.
* Currently, only the `lttng_session_daemon_command_endpoint` is supported,
* see `lttng/endpoint.h`.
*/
-extern enum lttng_error_code lttng_error_query_execute(
+LTTNG_EXPORT extern enum lttng_error_code lttng_error_query_execute(
const struct lttng_error_query *query,
const struct lttng_endpoint *endpoint,
struct lttng_error_query_results **results);
/* Get the number of results in a result set. */
-extern enum lttng_error_query_results_status
+LTTNG_EXPORT LTTNG_EXPORT extern enum lttng_error_query_results_status
lttng_error_query_results_get_count(
const struct lttng_error_query_results *results,
unsigned int *count);
/* Get a result from a result set by index. */
-extern enum lttng_error_query_results_status
+LTTNG_EXPORT extern enum lttng_error_query_results_status
lttng_error_query_results_get_result(
const struct lttng_error_query_results *results,
const struct lttng_error_query_result **result,
unsigned int index);
/* Destroy an error query result set. */
-extern void lttng_error_query_results_destroy(
+LTTNG_EXPORT extern void lttng_error_query_results_destroy(
struct lttng_error_query_results *results);
/* Get the type of an error query result. */
-extern enum lttng_error_query_result_type lttng_error_query_result_get_type(
+LTTNG_EXPORT extern enum lttng_error_query_result_type lttng_error_query_result_get_type(
const struct lttng_error_query_result *result);
/* Get the name of result. */
-extern enum lttng_error_query_result_status lttng_error_query_result_get_name(
+LTTNG_EXPORT extern enum lttng_error_query_result_status lttng_error_query_result_get_name(
const struct lttng_error_query_result *result,
const char **name);
/* Get the description of a result. */
-extern enum lttng_error_query_result_status
+LTTNG_EXPORT extern enum lttng_error_query_result_status
lttng_error_query_result_get_description(
const struct lttng_error_query_result *result,
const char **description);
/* Get the value of an error counter. */
-extern enum lttng_error_query_result_status
+LTTNG_EXPORT extern enum lttng_error_query_result_status
lttng_error_query_result_counter_get_value(
const struct lttng_error_query_result *result, uint64_t *value);
#ifndef LTTNG_EVENT_EXPR_H
#define LTTNG_EVENT_EXPR_H
+#include <lttng/lttng-export.h>
#include <stdbool.h>
struct lttng_event_expr;
* Returns the type of the event expression `expr`, or
* `LTTNG_EVENT_EXPR_TYPE_INVALID` if `expr` is `NULL`.
*/
-extern enum lttng_event_expr_type lttng_event_expr_get_type(
+LTTNG_EXPORT extern enum lttng_event_expr_type lttng_event_expr_get_type(
const struct lttng_event_expr *expr);
/*
* * There's a memory error.
* * `field_name` is `NULL`.
*/
-extern struct lttng_event_expr *lttng_event_expr_event_payload_field_create(
+LTTNG_EXPORT extern struct lttng_event_expr *lttng_event_expr_event_payload_field_create(
const char *field_name);
/*
* * The type of `expr` is not
* `LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD`.
*/
-extern const char *lttng_event_expr_event_payload_field_get_name(
+LTTNG_EXPORT extern const char *lttng_event_expr_event_payload_field_get_name(
const struct lttng_event_expr *expr);
/*
* * There's a memory error.
* * `field_name` is `NULL`.
*/
-extern struct lttng_event_expr *
+LTTNG_EXPORT extern struct lttng_event_expr *
lttng_event_expr_channel_context_field_create(const char *field_name);
/*
* * The type of `expr` is not
* `LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD`.
*/
-extern const char *lttng_event_expr_channel_context_field_get_name(
+LTTNG_EXPORT extern const char *lttng_event_expr_channel_context_field_get_name(
const struct lttng_event_expr *expr);
/*
* * `provider_name` is `NULL`.
* * `type_name` is `NULL`.
*/
-extern struct lttng_event_expr *
+LTTNG_EXPORT extern struct lttng_event_expr *
lttng_event_expr_app_specific_context_field_create(
const char *provider_name, const char *type_name);
* * The type of `expr` is not
* `LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD`.
*/
-extern const char *
+LTTNG_EXPORT extern const char *
lttng_event_expr_app_specific_context_field_get_provider_name(
const struct lttng_event_expr *expr);
* * The type of `expr` is not
* `LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD`.
*/
-extern const char *
+LTTNG_EXPORT extern const char *
lttng_event_expr_app_specific_context_field_get_type_name(
const struct lttng_event_expr *expr);
* * `LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD`
* * `LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT`
*/
-extern struct lttng_event_expr *lttng_event_expr_array_field_element_create(
+LTTNG_EXPORT extern struct lttng_event_expr *lttng_event_expr_array_field_element_create(
struct lttng_event_expr *array_field_expr,
unsigned int index);
* * The type of `expr` is not
* `LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT`.
*/
-extern const struct lttng_event_expr *
+LTTNG_EXPORT extern const struct lttng_event_expr *
lttng_event_expr_array_field_element_get_parent_expr(
const struct lttng_event_expr *expr);
* `LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT`.
* * `index` is `NULL`.
*/
-extern enum lttng_event_expr_status
+LTTNG_EXPORT extern enum lttng_event_expr_status
lttng_event_expr_array_field_element_get_index(
const struct lttng_event_expr *expr, unsigned int *index);
*
* `expr_a` and `expr_b` can be `NULL`.
*/
-extern bool lttng_event_expr_is_equal(const struct lttng_event_expr *expr_a,
+LTTNG_EXPORT extern bool lttng_event_expr_is_equal(const struct lttng_event_expr *expr_a,
const struct lttng_event_expr *expr_b);
/*
* Destroys the event expression `expr` if not `NULL`.
*/
-extern void lttng_event_expr_destroy(struct lttng_event_expr *expr);
+LTTNG_EXPORT extern void lttng_event_expr_destroy(struct lttng_event_expr *expr);
#ifdef __cplusplus
}
#ifndef LTTNG_EVENT_FIELD_VALUE_H
#define LTTNG_EVENT_FIELD_VALUE_H
+#include <lttng/lttng-export.h>
#include <stdint.h>
struct lttng_event_field_value;
* `LTTNG_EVENT_FIELD_VALUE_TYPE_INVALID`:
* `field_val` is `NULL`.
*/
-extern enum lttng_event_field_value_type lttng_event_field_value_get_type(
+LTTNG_EXPORT extern enum lttng_event_field_value_type lttng_event_field_value_get_type(
const struct lttng_event_field_value *field_val);
/*
* `LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_ENUM`.
* * `val` is `NULL`.
*/
-extern enum lttng_event_field_value_status
+LTTNG_EXPORT extern enum lttng_event_field_value_status
lttng_event_field_value_unsigned_int_get_value(
const struct lttng_event_field_value *field_val, uint64_t *val);
* `LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_ENUM`.
* * `val` is `NULL`.
*/
-extern enum lttng_event_field_value_status
+LTTNG_EXPORT extern enum lttng_event_field_value_status
lttng_event_field_value_signed_int_get_value(
const struct lttng_event_field_value *field_val, int64_t *val);
* `LTTNG_EVENT_FIELD_VALUE_TYPE_REAL`.
* * `val` is `NULL`.
*/
-extern enum lttng_event_field_value_status
+LTTNG_EXPORT extern enum lttng_event_field_value_status
lttng_event_field_value_real_get_value(
const struct lttng_event_field_value *field_val, double *val);
* * The type of `field_val` is not
* `LTTNG_EVENT_FIELD_VALUE_TYPE_STRING`.
*/
-extern enum lttng_event_field_value_status
+LTTNG_EXPORT extern enum lttng_event_field_value_status
lttng_event_field_value_string_get_value(
const struct lttng_event_field_value *field_val,
const char **value);
* `LTTNG_EVENT_FIELD_VALUE_TYPE_ARRAY`.
* * `length` is `NULL`.
*/
-extern enum lttng_event_field_value_status
+LTTNG_EXPORT extern enum lttng_event_field_value_status
lttng_event_field_value_array_get_length(
const struct lttng_event_field_value *field_val,
unsigned int *length);
* * No event field value exists at index `index` within
* `field_val`.
*/
-extern enum lttng_event_field_value_status
+LTTNG_EXPORT extern enum lttng_event_field_value_status
lttng_event_field_value_array_get_element_at_index(
const struct lttng_event_field_value *field_val,
unsigned int index,
#ifndef LTTNG_EVENT_RULE_H
#define LTTNG_EVENT_RULE_H
+#include <lttng/lttng-export.h>
+
#ifdef __cplusplus
extern "C" {
#endif
* Returns the type of an event rule on success, LTTNG_EVENT_RULE_UNKNOWN on
* error.
*/
-extern enum lttng_event_rule_type lttng_event_rule_get_type(
+LTTNG_EXPORT extern enum lttng_event_rule_type lttng_event_rule_get_type(
const struct lttng_event_rule *event_rule);
/*
* Destroy an event rule object.
*/
-extern void lttng_event_rule_destroy(struct lttng_event_rule *rule);
+LTTNG_EXPORT extern void lttng_event_rule_destroy(struct lttng_event_rule *rule);
#ifdef __cplusplus
}
#include <lttng/event-rule/event-rule.h>
#include <lttng/log-level-rule.h>
+#include <lttng/lttng-export.h>
#include <lttng/event.h>
#ifdef __cplusplus
* Returns a new event rule on success, NULL on failure. This event rule must be
* destroyed using lttng_event_rule_destroy().
*/
-extern struct lttng_event_rule *lttng_event_rule_jul_logging_create(void);
+LTTNG_EXPORT extern struct lttng_event_rule *lttng_event_rule_jul_logging_create(void);
/*
* Set the name pattern of a jul logging event rule.
* Return LTTNG_EVENT_RULE_STATUS_OK on success, LTTNG_EVENT_RULE_STATUS_INVALID
* if invalid parameters are passed.
*/
-extern enum lttng_event_rule_status lttng_event_rule_jul_logging_set_name_pattern(
+LTTNG_EXPORT extern enum lttng_event_rule_status lttng_event_rule_jul_logging_set_name_pattern(
struct lttng_event_rule *rule, const char *pattern);
/*
* parameter is passed, or LTTNG_EVENT_RULE_STATUS_UNSET if a pattern
* was not set prior to this call.
*/
-extern enum lttng_event_rule_status lttng_event_rule_jul_logging_get_name_pattern(
+LTTNG_EXPORT extern enum lttng_event_rule_status lttng_event_rule_jul_logging_get_name_pattern(
const struct lttng_event_rule *rule, const char **pattern);
/*
* Return LTTNG_EVENT_RULE_STATUS_OK on success, LTTNG_EVENT_RULE_STATUS_INVALID
* if invalid parameters are passed.
*/
-extern enum lttng_event_rule_status lttng_event_rule_jul_logging_set_filter(
+LTTNG_EXPORT extern enum lttng_event_rule_status lttng_event_rule_jul_logging_set_filter(
struct lttng_event_rule *rule, const char *expression);
/*
* parameter is passed, or LTTNG_EVENT_RULE_STATUS_UNSET if a filter expression
* was not set prior to this call.
*/
-extern enum lttng_event_rule_status lttng_event_rule_jul_logging_get_filter(
+LTTNG_EXPORT extern enum lttng_event_rule_status lttng_event_rule_jul_logging_get_filter(
const struct lttng_event_rule *rule, const char **expression);
/*
* Return LTTNG_EVENT_RULE_STATUS_OK on success, LTTNG_EVENT_RULE_STATUS_INVALID
* if invalid parameters are passed.
*/
-extern enum lttng_event_rule_status
+LTTNG_EXPORT extern enum lttng_event_rule_status
lttng_event_rule_jul_logging_set_log_level_rule(struct lttng_event_rule *rule,
const struct lttng_log_level_rule *log_level_rule);
* is passed, or LTTNG_EVENT_RULE_STATUS_UNSET if a log level rule was not set prior
* to this call.
*/
-extern enum lttng_event_rule_status
+LTTNG_EXPORT extern enum lttng_event_rule_status
lttng_event_rule_jul_logging_get_log_level_rule(
const struct lttng_event_rule *rule,
const struct lttng_log_level_rule **log_level_rule);
#define LTTNG_EVENT_RULE_KERNEL_KPROBE_H
#include <lttng/event-rule/event-rule.h>
+#include <lttng/lttng-export.h>
#ifdef __cplusplus
extern "C" {
* Returns a new event rule on success, NULL on failure. The returned event rule
* must be destroyed using lttng_event_rule_destroy().
*/
-extern struct lttng_event_rule *lttng_event_rule_kernel_kprobe_create(
+LTTNG_EXPORT extern struct lttng_event_rule *lttng_event_rule_kernel_kprobe_create(
const struct lttng_kernel_probe_location *location);
/*
* passed, or LTTNG_EVENT_RULE_STATUS_UNSET if a location was not set prior to
* this call.
*/
-extern enum lttng_event_rule_status lttng_event_rule_kernel_kprobe_get_location(
+LTTNG_EXPORT extern enum lttng_event_rule_status lttng_event_rule_kernel_kprobe_get_location(
const struct lttng_event_rule *rule,
const struct lttng_kernel_probe_location **location);
* Returns LTTNG_EVENT_RULE_STATUS_OK on success, LTTNG_EVENT_RULE_STATUS_INVALID
* if invalid parameters are passed.
*/
-extern enum lttng_event_rule_status lttng_event_rule_kernel_kprobe_set_event_name(
+LTTNG_EXPORT extern enum lttng_event_rule_status lttng_event_rule_kernel_kprobe_set_event_name(
struct lttng_event_rule *rule, const char *name);
/*
* success, LTTNG_EVENT_RULE_STATUS_INVALID if an invalid parameter is passed,
* or LTTNG_EVENT_RULE_STATUS_UNSET if a name was not set prior to this call.
*/
-extern enum lttng_event_rule_status lttng_event_rule_kernel_kprobe_get_event_name(
+LTTNG_EXPORT extern enum lttng_event_rule_status lttng_event_rule_kernel_kprobe_get_event_name(
const struct lttng_event_rule *rule, const char **name);
#ifdef __cplusplus
#define LTTNG_EVENT_RULE_KERNEL_SYSCALL_H
#include <lttng/event-rule/event-rule.h>
+#include <lttng/lttng-export.h>
#ifdef __cplusplus
extern "C" {
* Returns a new event rule on success, NULL on failure. This event rule must be
* destroyed using lttng_event_rule_destroy().
*/
-extern struct lttng_event_rule *lttng_event_rule_kernel_syscall_create(enum
+LTTNG_EXPORT extern struct lttng_event_rule *lttng_event_rule_kernel_syscall_create(enum
lttng_event_rule_kernel_syscall_emission_site emission_site);
/*
* Returns LTTNG_EVENT_RULE_STATUS_OK on success, LTTNG_EVENT_RULE_STATUS_INVALID
* if invalid parameters are passed.
*/
-extern enum lttng_event_rule_status lttng_event_rule_kernel_syscall_set_name_pattern(
+LTTNG_EXPORT extern enum lttng_event_rule_status lttng_event_rule_kernel_syscall_set_name_pattern(
struct lttng_event_rule *rule, const char *pattern);
/*
* parameter is passed, or LTTNG_EVENT_RULE_STATUS_UNSET if a pattern
* was not set prior to this call.
*/
-extern enum lttng_event_rule_status lttng_event_rule_kernel_syscall_get_name_pattern(
+LTTNG_EXPORT extern enum lttng_event_rule_status lttng_event_rule_kernel_syscall_get_name_pattern(
const struct lttng_event_rule *rule, const char **pattern);
/*
* Returns LTTNG_EVENT_RULE_STATUS_OK on success, LTTNG_EVENT_RULE_STATUS_INVALID
* if invalid parameters are passed.
*/
-extern enum lttng_event_rule_status lttng_event_rule_kernel_syscall_set_filter(
+LTTNG_EXPORT extern enum lttng_event_rule_status lttng_event_rule_kernel_syscall_set_filter(
struct lttng_event_rule *rule, const char *expression);
/*
* parameter is passed, or LTTNG_EVENT_RULE_STATUS_UNSET if a filter expression
* was not set prior to this call.
*/
-extern enum lttng_event_rule_status lttng_event_rule_kernel_syscall_get_filter(
+LTTNG_EXPORT extern enum lttng_event_rule_status lttng_event_rule_kernel_syscall_get_filter(
const struct lttng_event_rule *rule, const char **expression);
/*
*
* Returns a enum lttng_event_rule_kernel_syscall_emission_site.
*/
-extern enum lttng_event_rule_kernel_syscall_emission_site
+LTTNG_EXPORT extern enum lttng_event_rule_kernel_syscall_emission_site
lttng_event_rule_kernel_syscall_get_emission_site(
const struct lttng_event_rule *rule);
#include <lttng/event-rule/event-rule.h>
#include <lttng/event.h>
+#include <lttng/lttng-export.h>
#ifdef __cplusplus
extern "C" {
* Returns a new event rule on success, NULL on failure. This event rule must be
* destroyed using lttng_event_rule_destroy().
*/
-extern struct lttng_event_rule *lttng_event_rule_kernel_tracepoint_create(void);
+LTTNG_EXPORT extern struct lttng_event_rule *lttng_event_rule_kernel_tracepoint_create(void);
/*
* Set the name pattern of a kernel tracepoint event rule.
* Return LTTNG_EVENT_RULE_STATUS_OK on success, LTTNG_EVENT_RULE_STATUS_INVALID
* if invalid parameters are passed.
*/
-extern enum lttng_event_rule_status lttng_event_rule_kernel_tracepoint_set_name_pattern(
+LTTNG_EXPORT extern enum lttng_event_rule_status lttng_event_rule_kernel_tracepoint_set_name_pattern(
struct lttng_event_rule *rule, const char *pattern);
/*
* parameter is passed, or LTTNG_EVENT_RULE_STATUS_UNSET if a pattern
* was not set prior to this call.
*/
-extern enum lttng_event_rule_status lttng_event_rule_kernel_tracepoint_get_name_pattern(
+LTTNG_EXPORT extern enum lttng_event_rule_status lttng_event_rule_kernel_tracepoint_get_name_pattern(
const struct lttng_event_rule *rule, const char **pattern);
/*
* Return LTTNG_EVENT_RULE_STATUS_OK on success, LTTNG_EVENT_RULE_STATUS_INVALID
* if invalid parameters are passed.
*/
-extern enum lttng_event_rule_status lttng_event_rule_kernel_tracepoint_set_filter(
+LTTNG_EXPORT extern enum lttng_event_rule_status lttng_event_rule_kernel_tracepoint_set_filter(
struct lttng_event_rule *rule, const char *expression);
/*
* parameter is passed, or LTTNG_EVENT_RULE_STATUS_UNSET if a filter expression
* was not set prior to this call.
*/
-extern enum lttng_event_rule_status lttng_event_rule_kernel_tracepoint_get_filter(
+LTTNG_EXPORT extern enum lttng_event_rule_status lttng_event_rule_kernel_tracepoint_get_filter(
const struct lttng_event_rule *rule, const char **expression);
#ifdef __cplusplus
#define LTTNG_EVENT_RULE_KERNEL_UPROBE_H
#include <lttng/event-rule/event-rule.h>
+#include <lttng/lttng-export.h>
#include <lttng/userspace-probe.h>
#ifdef __cplusplus
* Returns a new event rule on success, NULL on failure. This event rule must be
* destroyed using lttng_event_rule_destroy().
*/
-extern struct lttng_event_rule *lttng_event_rule_kernel_uprobe_create(
+LTTNG_EXPORT extern struct lttng_event_rule *lttng_event_rule_kernel_uprobe_create(
const struct lttng_userspace_probe_location *location);
/*
* passed, or LTTNG_EVENT_RULE_STATUS_UNSET if a location was not set prior to
* this call.
*/
-extern enum lttng_event_rule_status lttng_event_rule_kernel_uprobe_get_location(
+LTTNG_EXPORT extern enum lttng_event_rule_status lttng_event_rule_kernel_uprobe_get_location(
const struct lttng_event_rule *rule,
const struct lttng_userspace_probe_location **location);
* Return LTTNG_EVENT_RULE_STATUS_OK on success, LTTNG_EVENT_RULE_STATUS_INVALID
* if invalid parameters are passed.
*/
-extern enum lttng_event_rule_status lttng_event_rule_kernel_uprobe_set_event_name(
+LTTNG_EXPORT extern enum lttng_event_rule_status lttng_event_rule_kernel_uprobe_set_event_name(
struct lttng_event_rule *rule, const char *name);
/*
* success, LTTNG_EVENT_RULE_STATUS_INVALID if an invalid parameter is passed,
* or LTTNG_EVENT_RULE_STATUS_UNSET if a name was not set prior to this call.
*/
-extern enum lttng_event_rule_status lttng_event_rule_kernel_uprobe_get_event_name(
+LTTNG_EXPORT extern enum lttng_event_rule_status lttng_event_rule_kernel_uprobe_get_event_name(
const struct lttng_event_rule *rule, const char **name);
#ifdef __cplusplus
#include <lttng/event-rule/event-rule.h>
#include <lttng/log-level-rule.h>
+#include <lttng/lttng-export.h>
#include <lttng/event.h>
#ifdef __cplusplus
* Returns a new event rule on success, NULL on failure. This event rule must be
* destroyed using lttng_event_rule_destroy().
*/
-extern struct lttng_event_rule *lttng_event_rule_log4j_logging_create(void);
+LTTNG_EXPORT extern struct lttng_event_rule *lttng_event_rule_log4j_logging_create(void);
/*
* Set the name pattern of a log4j logging event rule.
* Return LTTNG_EVENT_RULE_STATUS_OK on success, LTTNG_EVENT_RULE_STATUS_INVALID
* if invalid parameters are passed.
*/
-extern enum lttng_event_rule_status lttng_event_rule_log4j_logging_set_name_pattern(
+LTTNG_EXPORT extern enum lttng_event_rule_status lttng_event_rule_log4j_logging_set_name_pattern(
struct lttng_event_rule *rule, const char *pattern);
/*
* parameter is passed, or LTTNG_EVENT_RULE_STATUS_UNSET if a pattern
* was not set prior to this call.
*/
-extern enum lttng_event_rule_status lttng_event_rule_log4j_logging_get_name_pattern(
+LTTNG_EXPORT extern enum lttng_event_rule_status lttng_event_rule_log4j_logging_get_name_pattern(
const struct lttng_event_rule *rule, const char **pattern);
/*
* Return LTTNG_EVENT_RULE_STATUS_OK on success, LTTNG_EVENT_RULE_STATUS_INVALID
* if invalid parameters are passed.
*/
-extern enum lttng_event_rule_status lttng_event_rule_log4j_logging_set_filter(
+LTTNG_EXPORT extern enum lttng_event_rule_status lttng_event_rule_log4j_logging_set_filter(
struct lttng_event_rule *rule, const char *expression);
/*
* parameter is passed, or LTTNG_EVENT_RULE_STATUS_UNSET if a filter expression
* was not set prior to this call.
*/
-extern enum lttng_event_rule_status lttng_event_rule_log4j_logging_get_filter(
+LTTNG_EXPORT extern enum lttng_event_rule_status lttng_event_rule_log4j_logging_get_filter(
const struct lttng_event_rule *rule, const char **expression);
/*
* Return LTTNG_EVENT_RULE_STATUS_OK on success, LTTNG_EVENT_RULE_STATUS_INVALID
* if invalid parameters are passed.
*/
-extern enum lttng_event_rule_status
+LTTNG_EXPORT extern enum lttng_event_rule_status
lttng_event_rule_log4j_logging_set_log_level_rule(struct lttng_event_rule *rule,
const struct lttng_log_level_rule *log_level_rule);
* is passed, or LTTNG_EVENT_RULE_STATUS_UNSET if a log level rule was not set prior
* to this call.
*/
-extern enum lttng_event_rule_status
+LTTNG_EXPORT extern enum lttng_event_rule_status
lttng_event_rule_log4j_logging_get_log_level_rule(
const struct lttng_event_rule *rule,
const struct lttng_log_level_rule **log_level_rule);
#include <lttng/event-rule/event-rule.h>
#include <lttng/log-level-rule.h>
+#include <lttng/lttng-export.h>
#include <lttng/event.h>
#ifdef __cplusplus
* Returns a new event rule on success, NULL on failure. This event rule must be
* destroyed using lttng_event_rule_destroy().
*/
-extern struct lttng_event_rule *lttng_event_rule_python_logging_create(void);
+LTTNG_EXPORT extern struct lttng_event_rule *lttng_event_rule_python_logging_create(void);
/*
* Set the name pattern of a python logging event rule.
* Return LTTNG_EVENT_RULE_STATUS_OK on success, LTTNG_EVENT_RULE_STATUS_INVALID
* if invalid parameters are passed.
*/
-extern enum lttng_event_rule_status lttng_event_rule_python_logging_set_name_pattern(
+LTTNG_EXPORT extern enum lttng_event_rule_status lttng_event_rule_python_logging_set_name_pattern(
struct lttng_event_rule *rule, const char *pattern);
/*
* parameter is passed, or LTTNG_EVENT_RULE_STATUS_UNSET if a pattern
* was not set prior to this call.
*/
-extern enum lttng_event_rule_status lttng_event_rule_python_logging_get_name_pattern(
+LTTNG_EXPORT extern enum lttng_event_rule_status lttng_event_rule_python_logging_get_name_pattern(
const struct lttng_event_rule *rule, const char **pattern);
/*
* Return LTTNG_EVENT_RULE_STATUS_OK on success, LTTNG_EVENT_RULE_STATUS_INVALID
* if invalid parameters are passed.
*/
-extern enum lttng_event_rule_status lttng_event_rule_python_logging_set_filter(
+LTTNG_EXPORT extern enum lttng_event_rule_status lttng_event_rule_python_logging_set_filter(
struct lttng_event_rule *rule, const char *expression);
/*
* parameter is passed, or LTTNG_EVENT_RULE_STATUS_UNSET if a filter expression
* was not set prior to this call.
*/
-extern enum lttng_event_rule_status lttng_event_rule_python_logging_get_filter(
+LTTNG_EXPORT extern enum lttng_event_rule_status lttng_event_rule_python_logging_get_filter(
const struct lttng_event_rule *rule, const char **expression);
/*
* Return LTTNG_EVENT_RULE_STATUS_OK on success, LTTNG_EVENT_RULE_STATUS_INVALID
* if invalid parameters are passed.
*/
-extern enum lttng_event_rule_status
+LTTNG_EXPORT extern enum lttng_event_rule_status
lttng_event_rule_python_logging_set_log_level_rule(struct lttng_event_rule *rule,
const struct lttng_log_level_rule *log_level_rule);
* is passed, or LTTNG_EVENT_RULE_STATUS_UNSET if a log level rule was not set prior
* to this call.
*/
-extern enum lttng_event_rule_status
+LTTNG_EXPORT extern enum lttng_event_rule_status
lttng_event_rule_python_logging_get_log_level_rule(
const struct lttng_event_rule *rule,
const struct lttng_log_level_rule **log_level_rule);
#include <lttng/domain.h>
#include <lttng/event-rule/event-rule.h>
#include <lttng/log-level-rule.h>
+#include <lttng/lttng-export.h>
#include <lttng/event.h>
#ifdef __cplusplus
* Returns a new event rule on success, NULL on failure. This event rule must be
* destroyed using lttng_event_rule_destroy().
*/
-extern struct lttng_event_rule *lttng_event_rule_user_tracepoint_create(void);
+LTTNG_EXPORT extern struct lttng_event_rule *lttng_event_rule_user_tracepoint_create(void);
/*
* Set the name pattern of a user tracepoint event rule.
* Return LTTNG_EVENT_RULE_STATUS_OK on success, LTTNG_EVENT_RULE_STATUS_INVALID
* if invalid parameters are passed.
*/
-extern enum lttng_event_rule_status lttng_event_rule_user_tracepoint_set_name_pattern(
+LTTNG_EXPORT extern enum lttng_event_rule_status lttng_event_rule_user_tracepoint_set_name_pattern(
struct lttng_event_rule *rule, const char *pattern);
/*
* parameter is passed, or LTTNG_EVENT_RULE_STATUS_UNSET if a pattern
* was not set prior to this call.
*/
-extern enum lttng_event_rule_status lttng_event_rule_user_tracepoint_get_name_pattern(
+LTTNG_EXPORT extern enum lttng_event_rule_status lttng_event_rule_user_tracepoint_get_name_pattern(
const struct lttng_event_rule *rule, const char **pattern);
/*
* Return LTTNG_EVENT_RULE_STATUS_OK on success, LTTNG_EVENT_RULE_STATUS_INVALID
* if invalid parameters are passed.
*/
-extern enum lttng_event_rule_status lttng_event_rule_user_tracepoint_set_filter(
+LTTNG_EXPORT extern enum lttng_event_rule_status lttng_event_rule_user_tracepoint_set_filter(
struct lttng_event_rule *rule, const char *expression);
/*
* parameter is passed, or LTTNG_EVENT_RULE_STATUS_UNSET if a filter expression
* was not set prior to this call.
*/
-extern enum lttng_event_rule_status lttng_event_rule_user_tracepoint_get_filter(
+LTTNG_EXPORT extern enum lttng_event_rule_status lttng_event_rule_user_tracepoint_get_filter(
const struct lttng_event_rule *rule, const char **expression);
/*
* Return LTTNG_EVENT_RULE_STATUS_OK on success, LTTNG_EVENT_RULE_STATUS_INVALID
* if invalid parameters are passed.
*/
-extern enum lttng_event_rule_status
+LTTNG_EXPORT extern enum lttng_event_rule_status
lttng_event_rule_user_tracepoint_set_log_level_rule(struct lttng_event_rule *rule,
const struct lttng_log_level_rule *log_level_rule);
* is passed, or LTTNG_EVENT_RULE_STATUS_UNSET if a log level rule was not set prior
* to this call.
*/
-extern enum lttng_event_rule_status
+LTTNG_EXPORT extern enum lttng_event_rule_status
lttng_event_rule_user_tracepoint_get_log_level_rule(
const struct lttng_event_rule *rule,
const struct lttng_log_level_rule **log_level_rule);
* Returns LTTNG_EVENT_RULE_STATUS_OK on success,
* LTTNG_EVENT_RULE_STATUS_INVALID if invalid parameters are passed.
*/
-extern enum lttng_event_rule_status lttng_event_rule_user_tracepoint_add_name_pattern_exclusion(
+LTTNG_EXPORT extern enum lttng_event_rule_status lttng_event_rule_user_tracepoint_add_name_pattern_exclusion(
struct lttng_event_rule *rule,
const char *exclusion);
* on success, LTTNG_EVENT_RULE_STATUS_INVALID if an invalid parameter is
* passed.
*/
-extern enum lttng_event_rule_status
+LTTNG_EXPORT extern enum lttng_event_rule_status
lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(
const struct lttng_event_rule *rule, unsigned int *count);
* on success, LTTNG_EVENT_RULE_STATUS_INVALID if an invalid parameter is
* passed.
*/
-extern enum lttng_event_rule_status
+LTTNG_EXPORT extern enum lttng_event_rule_status
lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
const struct lttng_event_rule *rule,
unsigned int index,
#ifndef LTTNG_EVENT_H
#define LTTNG_EVENT_H
+#include <lttng/handle.h>
+#include <lttng/lttng-export.h>
+#include <lttng/userspace-probe.h>
+
#ifdef __cplusplus
extern "C" {
#endif
-#include <lttng/handle.h>
-#include <lttng/userspace-probe.h>
-
/*
* Instrumentation type of tracing event.
*/
* Return the size (number of entries) of the "lttng_event" array. Caller must
* free events. On error a negative LTTng error code is returned.
*/
-extern int lttng_list_events(struct lttng_handle *handle,
+LTTNG_EXPORT extern int lttng_list_events(struct lttng_handle *handle,
const char *channel_name, struct lttng_event **events);
/*
*
* Returns a zeroed lttng_event on success, NULL on error.
*/
-extern struct lttng_event *lttng_event_create(void);
+LTTNG_EXPORT extern struct lttng_event *lttng_event_create(void);
/*
* Destroy an lttng_event.
* This destruction function, introduced in LTTng 2.11, should only
* be used with events created by lttng_event_create().
*/
-extern void lttng_event_destroy(struct lttng_event *event);
+LTTNG_EXPORT extern void lttng_event_destroy(struct lttng_event *event);
/*
* Get the filter expression of a specific LTTng event.
*
* Returns 0 on success, or a negative LTTng error code on error.
*/
-extern int lttng_event_get_filter_expression(struct lttng_event *event,
+LTTNG_EXPORT extern int lttng_event_get_filter_expression(struct lttng_event *event,
const char **filter_string);
/*
* Returns the number of exclusion names on success, or a negative
* LTTng error code on error.
*/
-extern int lttng_event_get_exclusion_name_count(struct lttng_event *event);
+LTTNG_EXPORT extern int lttng_event_get_exclusion_name_count(struct lttng_event *event);
/*
* Get an LTTng event's exclusion name at a given index.
*
* Returns 0 on success, or a negative LTTng error code on error.
*/
-extern int lttng_event_get_exclusion_name(struct lttng_event *event,
+LTTNG_EXPORT extern int lttng_event_get_exclusion_name(struct lttng_event *event,
size_t index, const char **exclusion_name);
/*
* If the event has no probe location a NULL pointer is returned. The caller
* does not own the returned probe location.
*/
-extern const struct lttng_userspace_probe_location *
+LTTNG_EXPORT extern const struct lttng_userspace_probe_location *
lttng_event_get_userspace_probe_location(const struct lttng_event *event);
/*
*
* Returns 0 on success, or a negative LTTng error code on error.
*/
-extern int lttng_event_set_userspace_probe_location(struct lttng_event *event,
+LTTNG_EXPORT extern int lttng_event_set_userspace_probe_location(struct lttng_event *event,
struct lttng_userspace_probe_location *probe_location);
/*
* Return the size (number of entries) of the "lttng_event" array. Caller must
* free events. On error a negative LTTng error code is returned.
*/
-extern int lttng_list_tracepoints(struct lttng_handle *handle,
+LTTNG_EXPORT extern int lttng_list_tracepoints(struct lttng_handle *handle,
struct lttng_event **events);
/*
* Caller must free fields. On error a negative LTTng error code is
* returned.
*/
-extern int lttng_list_tracepoint_fields(struct lttng_handle *handle,
+LTTNG_EXPORT extern int lttng_list_tracepoint_fields(struct lttng_handle *handle,
struct lttng_event_field **fields);
/*
* All events in will be of type syscall. Caller must free events. On error a
* negative LTTng error code is returned.
*/
-extern int lttng_list_syscalls(struct lttng_event **events);
+LTTNG_EXPORT extern int lttng_list_syscalls(struct lttng_event **events);
/*
* Add context to event(s) for a specific channel (or for all).
*
* Return 0 on success else a negative LTTng error code.
*/
-extern int lttng_add_context(struct lttng_handle *handle,
+LTTNG_EXPORT extern int lttng_add_context(struct lttng_handle *handle,
struct lttng_event_context *ctx, const char *event_name,
const char *channel_name);
*
* Return 0 on success else a negative LTTng error code.
*/
-extern int lttng_enable_event(struct lttng_handle *handle,
+LTTNG_EXPORT extern int lttng_enable_event(struct lttng_handle *handle,
struct lttng_event *ev, const char *channel_name);
/*
*
* Return 0 on success else a negative LTTng error code.
*/
-extern int lttng_enable_event_with_filter(struct lttng_handle *handle,
+LTTNG_EXPORT extern int lttng_enable_event_with_filter(struct lttng_handle *handle,
struct lttng_event *event, const char *channel_name,
const char *filter_expression);
*
* Return 0 on success else a negative LTTng error code.
*/
-extern int lttng_enable_event_with_exclusions(struct lttng_handle *handle,
+LTTNG_EXPORT extern int lttng_enable_event_with_exclusions(struct lttng_handle *handle,
struct lttng_event *event, const char *channel_name,
const char *filter_expression,
int exclusion_count, char **exclusion_names);
*
* Return 0 on success else a negative LTTng error code.
*/
-extern int lttng_disable_event(struct lttng_handle *handle,
+LTTNG_EXPORT extern int lttng_disable_event(struct lttng_handle *handle,
const char *name, const char *channel_name);
/*
*
* Return 0 on success else a negative LTTng error code.
*/
-extern int lttng_disable_event_ext(struct lttng_handle *handle,
+LTTNG_EXPORT extern int lttng_disable_event_ext(struct lttng_handle *handle,
struct lttng_event *ev, const char *channel_name,
const char *filter_expression);
#define LTTNG_HANDLE_H
#include <lttng/domain.h>
+#include <lttng/lttng-export.h>
#ifdef __cplusplus
extern "C" {
* Return a newly allocated handle that should be freed using
* lttng_destroy_handle. On error, NULL is returned.
*/
-extern struct lttng_handle *lttng_create_handle(const char *session_name,
+LTTNG_EXPORT extern struct lttng_handle *lttng_create_handle(const char *session_name,
struct lttng_domain *domain);
/*
*
* It free the given pointer making it unusable.
*/
-extern void lttng_destroy_handle(struct lttng_handle *handle);
+LTTNG_EXPORT extern void lttng_destroy_handle(struct lttng_handle *handle);
#ifdef __cplusplus
*
*/
+#include <lttng/lttng-export.h>
+
#ifdef __cplusplus
extern "C" {
#endif
*
* Return a newly allocated health object, or NULL on error.
*/
-extern struct lttng_health *lttng_health_create_sessiond(void);
+LTTNG_EXPORT extern struct lttng_health *lttng_health_create_sessiond(void);
/**
* lttng_health_create_consumerd - Create consumerd health object
*
* Return a newly allocated health object, or NULL on error.
*/
-extern struct lttng_health *
+LTTNG_EXPORT extern struct lttng_health *
lttng_health_create_consumerd(enum lttng_health_consumerd consumerd);
/**
*
* Return a newly allocated health object, or NULL on error.
*/
-extern struct lttng_health *lttng_health_create_relayd(const char *path);
+LTTNG_EXPORT extern struct lttng_health *lttng_health_create_relayd(const char *path);
/**
* lttng_health_destroy - Destroy health object
* @health: health object to destroy
*/
-extern void lttng_health_destroy(struct lttng_health *health);
+LTTNG_EXPORT extern void lttng_health_destroy(struct lttng_health *health);
/**
* lttng_health_query - Query component health
* reports if the query has been successfully performed, *NOT* the
* actual state. lttng_health_state() should be used for the latter.
*/
-extern int lttng_health_query(struct lttng_health *health);
+LTTNG_EXPORT extern int lttng_health_query(struct lttng_health *health);
/**
* lttng_health_state - Inspect the state of a health structure
* thread in error. It also returns a negative return value if
* lttng_health_query() has not yet successfully completed on @health.
*/
-extern int lttng_health_state(const struct lttng_health *health);
+LTTNG_EXPORT extern int lttng_health_state(const struct lttng_health *health);
/**
* lttng_health_get_nr_threads - Get number of threads in health component
* Return the number of threads (>= 0) on success, else negative value
* on error.
*/
-extern int lttng_health_get_nr_threads(const struct lttng_health *health);
+LTTNG_EXPORT extern int lttng_health_get_nr_threads(const struct lttng_health *health);
/**
* lttng_health_get_thread - Get thread health
* pointer should not be freed by the caller, and can be used until
* lttng_health_destroy() is called on @health.
*/
-extern const struct lttng_health_thread *
+LTTNG_EXPORT extern const struct lttng_health_thread *
lttng_health_get_thread(const struct lttng_health *health,
unsigned int nth_thread);
*
* Return 0 if thread is OK, else negative error value.
*/
-extern int lttng_health_thread_state(const struct lttng_health_thread *thread);
+LTTNG_EXPORT extern int lttng_health_thread_state(const struct lttng_health_thread *thread);
/**
* lttng_health_thread_name - Get thread name
*
* Return thread name, NULL on error.
*/
-extern const char *lttng_health_thread_name(const struct lttng_health_thread *thread);
+LTTNG_EXPORT extern const char *lttng_health_thread_name(const struct lttng_health_thread *thread);
#ifdef __cplusplus
}
#ifndef LTTNG_KERNEL_PROBE_H
#define LTTNG_KERNEL_PROBE_H
+#include <lttng/lttng-export.h>
#include <stdint.h>
#ifdef __cplusplus
/*
* Get the type of the kernel probe location.
*/
-extern enum lttng_kernel_probe_location_type
+LTTNG_EXPORT extern enum lttng_kernel_probe_location_type
lttng_kernel_probe_location_get_type(
const struct lttng_kernel_probe_location *location);
/*
* Destroy the kernel probe location.
*/
-extern void lttng_kernel_probe_location_destroy(
+LTTNG_EXPORT extern void lttng_kernel_probe_location_destroy(
struct lttng_kernel_probe_location *location);
/*
* Create a symbol derived probe location.
* On failure, NULL is returned.
*/
-extern struct lttng_kernel_probe_location *
+LTTNG_EXPORT extern struct lttng_kernel_probe_location *
lttng_kernel_probe_location_symbol_create(const char *symbol_name,
uint64_t offset);
/*
* Get the symbol name of a symbol derived probe location.
*/
-extern const char *lttng_kernel_probe_location_symbol_get_name(
+LTTNG_EXPORT extern const char *lttng_kernel_probe_location_symbol_get_name(
const struct lttng_kernel_probe_location *location);
/*
* Get the offset of a symbol derived location.
*/
-extern enum lttng_kernel_probe_location_status
+LTTNG_EXPORT extern enum lttng_kernel_probe_location_status
lttng_kernel_probe_location_symbol_get_offset(
const struct lttng_kernel_probe_location *location,
uint64_t *offset);
* Create an address derived probe location.
* On failure, NULL is returned.
*/
-extern struct lttng_kernel_probe_location *
+LTTNG_EXPORT extern struct lttng_kernel_probe_location *
lttng_kernel_probe_location_address_create(uint64_t address);
/*
* Get the address of an address derived probe location.
*/
-extern enum lttng_kernel_probe_location_status
+LTTNG_EXPORT extern enum lttng_kernel_probe_location_status
lttng_kernel_probe_location_address_get_address(
const struct lttng_kernel_probe_location *location,
uint64_t *offset);
#ifndef LTTNG_LOAD_H
#define LTTNG_LOAD_H
+#include <lttng/lttng-export.h>
+
#ifdef __cplusplus
extern "C" {
#endif
/*
* Return a newly allocated load session attribute object or NULL on error.
*/
-extern struct lttng_load_session_attr *lttng_load_session_attr_create(void);
+LTTNG_EXPORT extern struct lttng_load_session_attr *lttng_load_session_attr_create(void);
/*
* Free a given load session attribute object.
*/
-extern void lttng_load_session_attr_destroy(struct lttng_load_session_attr *attr);
+LTTNG_EXPORT extern void lttng_load_session_attr_destroy(struct lttng_load_session_attr *attr);
/*
*/
/* Return session name. NULL indicates all sessions must be loaded. */
-extern const char *lttng_load_session_attr_get_session_name(
+LTTNG_EXPORT extern const char *lttng_load_session_attr_get_session_name(
struct lttng_load_session_attr *attr);
/*
* Return input URL. A NULL value indicates the default session
* configuration location. The URL format used is documented in lttng-create(1).
* NULL indicates that the default session configuration path is used.
*/
-extern const char *lttng_load_session_attr_get_input_url(
+LTTNG_EXPORT extern const char *lttng_load_session_attr_get_input_url(
struct lttng_load_session_attr *attr);
/*
* same name already exists. If such a session exists, it is destroyed before
* the replacement is loaded.
*/
-extern int lttng_load_session_attr_get_overwrite(
+LTTNG_EXPORT extern int lttng_load_session_attr_get_overwrite(
struct lttng_load_session_attr *attr);
/*
*
* NULL indicates no override will be applied on configuration load.
*/
-extern const char *lttng_load_session_attr_get_override_url(
+LTTNG_EXPORT extern const char *lttng_load_session_attr_get_override_url(
struct lttng_load_session_attr *attr);
/*
*
* NULL indicates no control URL override will be applied on configuration load.
*/
-extern const char *lttng_load_session_attr_get_override_ctrl_url(
+LTTNG_EXPORT extern const char *lttng_load_session_attr_get_override_ctrl_url(
struct lttng_load_session_attr *attr);
/*
*
* NULL indicates no data URL override will be applied on configuration load.
*/
-extern const char *lttng_load_session_attr_get_override_data_url(
+LTTNG_EXPORT extern const char *lttng_load_session_attr_get_override_data_url(
struct lttng_load_session_attr *attr);
/*
* NULL indicates no session name override will be applied on configuration
* load.
*/
-extern const char *lttng_load_session_attr_get_override_session_name(
+LTTNG_EXPORT extern const char *lttng_load_session_attr_get_override_session_name(
struct lttng_load_session_attr *attr);
/*
* Set the name of the session to load. A NULL name means all sessions
* found at the input URL will be loaded.
*/
-extern int lttng_load_session_attr_set_session_name(
+LTTNG_EXPORT extern int lttng_load_session_attr_set_session_name(
struct lttng_load_session_attr *attr, const char *session_name);
/*
*
* Note that file:// is the only supported URL format.
*/
-extern int lttng_load_session_attr_set_input_url(
+LTTNG_EXPORT extern int lttng_load_session_attr_set_input_url(
struct lttng_load_session_attr *attr, const char *url);
/*
* loaded sessions will be destroyed and be replaced by the session(s) being
* loaded.
*/
-extern int lttng_load_session_attr_set_overwrite(
+LTTNG_EXPORT extern int lttng_load_session_attr_set_overwrite(
struct lttng_load_session_attr *attr, int overwrite);
/*
*
* See lttng-create(1) for more detail.
*/
-extern int lttng_load_session_attr_set_override_url(
+LTTNG_EXPORT extern int lttng_load_session_attr_set_override_url(
struct lttng_load_session_attr *attr, const char *url);
/*
*
* See lttng-create(1) for more detail.
*/
-extern int lttng_load_session_attr_set_override_ctrl_url(
+LTTNG_EXPORT extern int lttng_load_session_attr_set_override_ctrl_url(
struct lttng_load_session_attr *attr, const char *url);
/*
*
* See lttng-create(1) for more detail.
*/
-extern int lttng_load_session_attr_set_override_data_url(
+LTTNG_EXPORT extern int lttng_load_session_attr_set_override_data_url(
struct lttng_load_session_attr *attr, const char *url);
/*
* Loading a configuration file defining multiple sessions will fail if a
* session name is provided.
*/
-extern int lttng_load_session_attr_set_override_session_name(
+LTTNG_EXPORT extern int lttng_load_session_attr_set_override_session_name(
struct lttng_load_session_attr *attr, const char *session_name);
/*
*
* Returns 0 on success or a negative LTTNG_ERR value on error.
*/
-extern int lttng_load_session(struct lttng_load_session_attr *attr);
+LTTNG_EXPORT extern int lttng_load_session(struct lttng_load_session_attr *attr);
#ifdef __cplusplus
}
#ifndef LTTNG_LOCATION_H
#define LTTNG_LOCATION_H
+#include <lttng/lttng-export.h>
#include <stdint.h>
#ifdef __cplusplus
/*
* Get a trace archive location's type.
*/
-extern enum lttng_trace_archive_location_type
+LTTNG_EXPORT extern enum lttng_trace_archive_location_type
lttng_trace_archive_location_get_type(
const struct lttng_trace_archive_location *location);
*
* The trace archive location maintains ownership of the absolute_path.
*/
-extern enum lttng_trace_archive_location_status
+LTTNG_EXPORT extern enum lttng_trace_archive_location_status
lttng_trace_archive_location_local_get_absolute_path(
const struct lttng_trace_archive_location *location,
const char **absolute_path);
*
* The trace archive location maintains ownership of relay_host.
*/
-extern enum lttng_trace_archive_location_status
+LTTNG_EXPORT extern enum lttng_trace_archive_location_status
lttng_trace_archive_location_relay_get_host(
const struct lttng_trace_archive_location *location,
const char **relay_host);
* Get the control port of the relay daemon associated to this trace archive
* location.
*/
-extern enum lttng_trace_archive_location_status
+LTTNG_EXPORT extern enum lttng_trace_archive_location_status
lttng_trace_archive_location_relay_get_control_port(
const struct lttng_trace_archive_location *location,
uint16_t *control_port);
* Get the data port of the relay daemon associated to this trace archive
* location.
*/
-extern enum lttng_trace_archive_location_status
+LTTNG_EXPORT extern enum lttng_trace_archive_location_status
lttng_trace_archive_location_relay_get_data_port(
const struct lttng_trace_archive_location *location,
uint16_t *data_port);
* Get the protocol used to communicate with the relay daemon associated to this
* trace archive location.
*/
-extern enum lttng_trace_archive_location_status
+LTTNG_EXPORT extern enum lttng_trace_archive_location_status
lttng_trace_archive_location_relay_get_protocol_type(
const struct lttng_trace_archive_location *location,
enum lttng_trace_archive_location_relay_protocol_type *protocol);
*
* The trace archive location maintains ownership of relative_path.
*/
-extern enum lttng_trace_archive_location_status
+LTTNG_EXPORT extern enum lttng_trace_archive_location_status
lttng_trace_archive_location_relay_get_relative_path(
const struct lttng_trace_archive_location *location,
const char **relative_path);
#ifndef LTTNG_LOG_LEVEL_RULE_H
#define LTTNG_LOG_LEVEL_RULE_H
+#include <lttng/lttng-export.h>
+
#ifdef __cplusplus
extern "C" {
#endif
* `LTTNG_LOG_LEVEL_RULE_TYPE_UNKNOWN`:
* `rule` is `NULL`.
*/
-extern enum lttng_log_level_rule_type lttng_log_level_rule_get_type(
+LTTNG_EXPORT extern enum lttng_log_level_rule_type lttng_log_level_rule_get_type(
const struct lttng_log_level_rule *rule);
/*
* The returned log level rule must be destroyed using
* lttng_log_level_rule_destroy().
*/
-extern struct lttng_log_level_rule *lttng_log_level_rule_exactly_create(
+LTTNG_EXPORT extern struct lttng_log_level_rule *lttng_log_level_rule_exactly_create(
int level);
/*
* * `level` is NULL.
* * The type of `rule` is not `LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY`.
*/
-extern enum lttng_log_level_rule_status lttng_log_level_rule_exactly_get_level(
+LTTNG_EXPORT extern enum lttng_log_level_rule_status lttng_log_level_rule_exactly_get_level(
const struct lttng_log_level_rule *rule, int *level);
/*
* The returned log level rule must be destroyed using
* lttng_log_level_rule_destroy().
*/
-extern struct lttng_log_level_rule *
+LTTNG_EXPORT extern struct lttng_log_level_rule *
lttng_log_level_rule_at_least_as_severe_as_create(int level);
/*
* * The type of `rule` is not
* `LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS`.
*/
-extern enum lttng_log_level_rule_status
+LTTNG_EXPORT extern enum lttng_log_level_rule_status
lttng_log_level_rule_at_least_as_severe_as_get_level(
const struct lttng_log_level_rule *rule, int *level);
/*
* Destroy the log level rule `log_level_rule` if not `NULL`.
*/
-extern void lttng_log_level_rule_destroy(
+LTTNG_EXPORT extern void lttng_log_level_rule_destroy(
struct lttng_log_level_rule *log_level_rule);
#ifdef __cplusplus
#ifndef LTTNG_ERROR_H
#define LTTNG_ERROR_H
+#include <lttng/lttng-export.h>
+
#ifdef __cplusplus
extern "C" {
#endif
*
* Parameter MUST be a negative value or else you'll get a generic message.
*/
-extern const char *lttng_strerror(int code);
+LTTNG_EXPORT extern const char *lttng_strerror(int code);
#ifdef __cplusplus
}
--- /dev/null
+/*
+ * Copyright (C) 2021 Simon Marchi <simon.marchi@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+#ifndef LTTNG_EXPORT_H
+#define LTTNG_EXPORT_H
+#if defined(_WIN32) || defined(__CYGWIN__)
+# define LTTNG_EXPORT
+#else
+# define LTTNG_EXPORT __attribute__((visibility("default")))
+#endif
+#endif
#include <lttng/location.h>
#include <lttng/log-level-rule.h>
#include <lttng/lttng-error.h>
+#include <lttng/lttng-export.h>
#include <lttng/notification/channel.h>
#include <lttng/notification/notification.h>
#include <lttng/rotation.h>
* Return 1 if alive or 0 if not. On error, returns a negative negative LTTng
* error code.
*/
-extern int lttng_session_daemon_alive(void);
+LTTNG_EXPORT extern int lttng_session_daemon_alive(void);
/*
* Set the tracing group for the *current* flow of execution.
*
* On success, returns 0 else a negative LTTng error code.
*/
-extern int lttng_set_tracing_group(const char *name);
+LTTNG_EXPORT extern int lttng_set_tracing_group(const char *name);
/*
* This call registers an "outside consumer" for a session and an lttng domain.
*
* Return 0 on success else a negative LTTng error code.
*/
-extern int lttng_register_consumer(struct lttng_handle *handle,
+LTTNG_EXPORT extern int lttng_register_consumer(struct lttng_handle *handle,
const char *socket_path);
/*
*
* Return 0 on success else a negative LTTng error code.
*/
-extern int lttng_start_tracing(const char *session_name);
+LTTNG_EXPORT extern int lttng_start_tracing(const char *session_name);
/*
* Stop tracing for *all* domain(s) in the session.
*
* Return 0 on success else a negative LTTng error code.
*/
-extern int lttng_stop_tracing(const char *session_name);
+LTTNG_EXPORT extern int lttng_stop_tracing(const char *session_name);
/*
* Behave exactly like lttng_stop_tracing but does not wait for data
* availability.
*/
-extern int lttng_stop_tracing_no_wait(const char *session_name);
+LTTNG_EXPORT extern int lttng_stop_tracing_no_wait(const char *session_name);
/*
* Deprecated: As of LTTng 2.9, this function always returns
*/
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wshadow"
-extern int lttng_calibrate(struct lttng_handle *handle,
+LTTNG_EXPORT extern int lttng_calibrate(struct lttng_handle *handle,
struct lttng_calibrate *calibrate);
#pragma GCC diagnostic pop
*
* Return 0 on success else a negative LTTng error code.
*/
-extern int lttng_set_consumer_url(struct lttng_handle *handle,
+LTTNG_EXPORT extern int lttng_set_consumer_url(struct lttng_handle *handle,
const char *control_url, const char *data_url);
/*
* traced data is pending. On error, a negative value is returned and readable
* by lttng_strerror().
*/
-extern int lttng_data_pending(const char *session_name);
+LTTNG_EXPORT extern int lttng_data_pending(const char *session_name);
/*
* Deprecated, replaced by lttng_regenerate_metadata.
*/
LTTNG_DEPRECATED("Use lttng_regenerate_metadata")
-extern int lttng_metadata_regenerate(const char *session_name);
+LTTNG_EXPORT extern int lttng_metadata_regenerate(const char *session_name);
/*
* Trigger the regeneration of the metadata for a session.
* the lttng-relayd). Only kernel, per-uid and non-live sessions are supported.
* Return 0 on success, a negative LTTng error code on error.
*/
-extern int lttng_regenerate_metadata(const char *session_name);
+LTTNG_EXPORT extern int lttng_regenerate_metadata(const char *session_name);
/*
* Trigger the regeneration of the statedump for a session. The new statedump
*
* Return 0 on success, a negative LTTng error code on error.
*/
-extern int lttng_regenerate_statedump(const char *session_name);
+LTTNG_EXPORT extern int lttng_regenerate_statedump(const char *session_name);
#ifdef __cplusplus
}
#ifndef LTTNG_NOTIFICATION_CHANNEL_H
#define LTTNG_NOTIFICATION_CHANNEL_H
+#include <lttng/lttng-export.h>
#include <stdbool.h>
#ifdef __cplusplus
* The returned lttng_notification_channel must be destroyed using
* the lttng_notification_channel_destroy() function.
*/
-extern struct lttng_notification_channel *lttng_notification_channel_create(
+LTTNG_EXPORT extern struct lttng_notification_channel *lttng_notification_channel_create(
struct lttng_endpoint *endpoint);
/*
* - LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED if a signal was received
* that caused the reception to fail.
*/
-extern enum lttng_notification_channel_status
+LTTNG_EXPORT extern enum lttng_notification_channel_status
lttng_notification_channel_get_next_notification(
struct lttng_notification_channel *channel,
struct lttng_notification **notification);
* - LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID if an invalid parameter was
* provided.
*/
-extern enum lttng_notification_channel_status
+LTTNG_EXPORT extern enum lttng_notification_channel_status
lttng_notification_channel_has_pending_notification(
struct lttng_notification_channel *channel,
bool *notification_pending);
* provided, or LTTNG_NOTIFICATION_CHANNEL_STATUS_ALREADY_SUBSCRIBED if the
* client was already subscribed to the condition through this channel.
*/
-extern enum lttng_notification_channel_status
+LTTNG_EXPORT extern enum lttng_notification_channel_status
lttng_notification_channel_subscribe(
struct lttng_notification_channel *channel,
const struct lttng_condition *condition);
* provided, or LTTNG_NOTIFICATION_CHANNEL_STATUS_UNKNOWN_CONDITION if the
* client was not already subscribed to the condition through this channel.
*/
-extern enum lttng_notification_channel_status
+LTTNG_EXPORT extern enum lttng_notification_channel_status
lttng_notification_channel_unsubscribe(
struct lttng_notification_channel *channel,
const struct lttng_condition *condition);
/*
* Closes and destroys (frees) a notification channel.
*/
-extern void lttng_notification_channel_destroy(
+LTTNG_EXPORT extern void lttng_notification_channel_destroy(
struct lttng_notification_channel *channel);
#ifdef __cplusplus
#ifndef LTTNG_NOTIFICATION_H
#define LTTNG_NOTIFICATION_H
+#include <lttng/lttng-export.h>
+
#ifdef __cplusplus
extern "C" {
#endif
*
* Returns an lttng_condition object on success, NULL on error.
*/
-extern const struct lttng_condition *lttng_notification_get_condition(
+LTTNG_EXPORT extern const struct lttng_condition *lttng_notification_get_condition(
struct lttng_notification *notification);
/*
*
* Returns an lttng_evaluation object on success, NULL on error.
*/
-extern const struct lttng_evaluation *lttng_notification_get_evaluation(
+LTTNG_EXPORT extern const struct lttng_evaluation *lttng_notification_get_evaluation(
struct lttng_notification *notification);
/*
*
* Returns an lttng_trigger object on success, NULL on error.
*/
-extern const struct lttng_trigger *lttng_notification_get_trigger(
+LTTNG_EXPORT extern const struct lttng_trigger *lttng_notification_get_trigger(
struct lttng_notification *notification);
/*
* Destroys (frees) a notification. The notification's condition and evaluation
* are destroyed as a side-effect.
*/
-extern void lttng_notification_destroy(struct lttng_notification *notification);
+LTTNG_EXPORT extern void lttng_notification_destroy(struct lttng_notification *notification);
#ifdef __cplusplus
}
#include <stdint.h>
#include <lttng/location.h>
+#include <lttng/lttng-export.h>
#ifdef __cplusplus
extern "C" {
* This will issue a request to the session daemon on every call. Hence,
* the result of this call may change over time.
*/
-extern enum lttng_rotation_status lttng_rotation_handle_get_state(
+LTTNG_EXPORT extern enum lttng_rotation_status lttng_rotation_handle_get_state(
struct lttng_rotation_handle *rotation_handle,
enum lttng_rotation_state *rotation_state);
* Note that location will not be set in case of error, or if the session
* rotation handle has expired.
*/
-extern enum lttng_rotation_status lttng_rotation_handle_get_archive_location(
+LTTNG_EXPORT extern enum lttng_rotation_status lttng_rotation_handle_get_archive_location(
struct lttng_rotation_handle *rotation_handle,
const struct lttng_trace_archive_location **location);
/*
* Destroy an lttng_rotate_session handle.
*/
-extern void lttng_rotation_handle_destroy(
+LTTNG_EXPORT extern void lttng_rotation_handle_destroy(
struct lttng_rotation_handle *rotation_handle);
/*
* Return 0 if the rotate action was successfully launched or a negative
* LTTng error code on error.
*/
-extern int lttng_rotate_session(const char *session_name,
+LTTNG_EXPORT extern int lttng_rotate_session(const char *session_name,
struct lttng_rotation_immediate_descriptor *descriptor,
struct lttng_rotation_handle **rotation_handle);
/*
* Get the type of a rotation schedule object.
*/
-extern enum lttng_rotation_schedule_type lttng_rotation_schedule_get_type(
+LTTNG_EXPORT extern enum lttng_rotation_schedule_type lttng_rotation_schedule_get_type(
const struct lttng_rotation_schedule *schedule);
/*
* Return a newly allocated size-based session rotation schedule or NULL on
* error.
*/
-extern struct lttng_rotation_schedule *
+LTTNG_EXPORT extern struct lttng_rotation_schedule *
lttng_rotation_schedule_size_threshold_create(void);
/*
* Returns LTTNG_ROTATION_STATUS_OK on success.
* LTTNG_ROTATION_STATUS_UNAVAILABLE is returned if the value is unset.
*/
-extern enum lttng_rotation_status
+LTTNG_EXPORT extern enum lttng_rotation_status
lttng_rotation_schedule_size_threshold_get_threshold(
const struct lttng_rotation_schedule *schedule,
uint64_t *size_threshold_bytes);
/*
* Set a session rotation schedule's size threshold.
*/
-extern enum lttng_rotation_status
+LTTNG_EXPORT extern enum lttng_rotation_status
lttng_rotation_schedule_size_threshold_set_threshold(
struct lttng_rotation_schedule *schedule,
uint64_t size_threshold_bytes);
* Return a newly allocated periodic session rotation schedule or NULL on
* error.
*/
-extern struct lttng_rotation_schedule *
+LTTNG_EXPORT extern struct lttng_rotation_schedule *
lttng_rotation_schedule_periodic_create(void);
/*
* Returns LTTNG_ROTATION_STATUS_OK on success.
* LTTNG_ROTATION_STATUS_UNAVAILABLE is returned if the value is unset.
*/
-extern enum lttng_rotation_status lttng_rotation_schedule_periodic_get_period(
+LTTNG_EXPORT extern enum lttng_rotation_status lttng_rotation_schedule_periodic_get_period(
const struct lttng_rotation_schedule *schedule,
uint64_t *period_us);
/*
* Set a time-based session rotation schedule's period.
*/
-extern enum lttng_rotation_status lttng_rotation_schedule_periodic_set_period(
+LTTNG_EXPORT extern enum lttng_rotation_status lttng_rotation_schedule_periodic_set_period(
struct lttng_rotation_schedule *schedule,
uint64_t period_us);
/*
* Destroy a rotation schedule.
*/
-extern void lttng_rotation_schedule_destroy(
+LTTNG_EXPORT extern void lttng_rotation_schedule_destroy(
struct lttng_rotation_schedule *schedule);
/*
* Destroy a set of rotation schedules. Pointers to any schedule contained
* in this set become invalid after this call.
*/
-extern void lttng_rotation_schedules_destroy(
+LTTNG_EXPORT extern void lttng_rotation_schedules_destroy(
struct lttng_rotation_schedules *schedules);
/*
* Get the number of schedules in a schedule set.
*/
-extern enum lttng_rotation_status lttng_rotation_schedules_get_count(
+LTTNG_EXPORT extern enum lttng_rotation_status lttng_rotation_schedules_get_count(
const struct lttng_rotation_schedules *schedules,
unsigned int *count);
*
* Returns a rotation schedule, or NULL on error.
*/
-extern const struct lttng_rotation_schedule *
+LTTNG_EXPORT extern const struct lttng_rotation_schedule *
lttng_rotation_schedules_get_at_index(
const struct lttng_rotation_schedules *schedules,
unsigned int index);
* LTTNG_ROTATION_STATUS_SCHEDULE_ALREADY_SET if a rotation of the same type
* is already set.
*/
-extern enum lttng_rotation_status lttng_session_add_rotation_schedule(
+LTTNG_EXPORT extern enum lttng_rotation_status lttng_session_add_rotation_schedule(
const char *session_name,
const struct lttng_rotation_schedule *schedule);
* LTTNG_ROTATION_STATUS_SCHEDULE_INVALID if the provided schedule is
* not set.
*/
-extern enum lttng_rotation_status lttng_session_remove_rotation_schedule(
+LTTNG_EXPORT extern enum lttng_rotation_status lttng_session_remove_rotation_schedule(
const char *session_name,
const struct lttng_rotation_schedule *schedule);
*
* Returns LTTNG_OK on success, or a negative lttng error code on error.
*/
-extern int lttng_session_list_rotation_schedules(
+LTTNG_EXPORT extern int lttng_session_list_rotation_schedules(
const char *session_name,
struct lttng_rotation_schedules **schedules);
#ifndef LTTNG_SAVE_H
#define LTTNG_SAVE_H
+#include <lttng/lttng-export.h>
+
#ifdef __cplusplus
extern "C" {
#endif
/*
* Return a newly allocated save session attribute object or NULL on error.
*/
-extern struct lttng_save_session_attr *lttng_save_session_attr_create(void);
+LTTNG_EXPORT extern struct lttng_save_session_attr *lttng_save_session_attr_create(void);
/*
* Free a given save session attribute object.
*/
-extern void lttng_save_session_attr_destroy(struct lttng_save_session_attr *output);
+LTTNG_EXPORT extern void lttng_save_session_attr_destroy(struct lttng_save_session_attr *output);
/*
*/
/* Return session name. NULL indicated all sessions must be saved. */
-extern const char *lttng_save_session_attr_get_session_name(
+LTTNG_EXPORT extern const char *lttng_save_session_attr_get_session_name(
struct lttng_save_session_attr *attr);
/*
* Return destination URL. A NULL value indicates the default session
* configuration location. The URL format used is documented in lttng(1).
* NULL indicates that the default session configuration path is used.
*/
-extern const char *lttng_save_session_attr_get_output_url(
+LTTNG_EXPORT extern const char *lttng_save_session_attr_get_output_url(
struct lttng_save_session_attr *attr);
/*
* Return the configuration overwrite attribute. This attribute indicates
* whether or not existing configuration files must be overwritten.
*/
-extern int lttng_save_session_attr_get_overwrite(
+LTTNG_EXPORT extern int lttng_save_session_attr_get_overwrite(
struct lttng_save_session_attr *attr);
/*
* Return the omit name configuration attribute. This attribute indicates
* whether or not the saved sessions' names should be omitted.
*/
-extern int lttng_save_session_attr_get_omit_name(
+LTTNG_EXPORT extern int lttng_save_session_attr_get_omit_name(
struct lttng_save_session_attr *attr);
/*
* Return the omit output configuration attribute. This attribute indicates
* whether or not the saved sessions' output configuration should be omitted.
*/
-extern int lttng_save_session_attr_get_omit_output(
+LTTNG_EXPORT extern int lttng_save_session_attr_get_omit_output(
struct lttng_save_session_attr *attr);
/*
* Set the name of the session to save. A NULL name means all sessions
* known to the session daemon will be saved.
*/
-extern int lttng_save_session_attr_set_session_name(
+LTTNG_EXPORT extern int lttng_save_session_attr_set_session_name(
struct lttng_save_session_attr *attr, const char *session_name);
/*
* Set the URL of the session configuration to save. A NULL value indicates the
* use of the default location being the session one. The URL's format is is
* documented in lttng(1).
*/
-extern int lttng_save_session_attr_set_output_url(
+LTTNG_EXPORT extern int lttng_save_session_attr_set_output_url(
struct lttng_save_session_attr *attr, const char *url);
/*
* Set the overwrite attribute. If set to true, files of the same name as the
* current session configuration URL will be overwritten.
*/
-extern int lttng_save_session_attr_set_overwrite(
+LTTNG_EXPORT extern int lttng_save_session_attr_set_overwrite(
struct lttng_save_session_attr *attr, int overwrite);
/*
* Set the omit name attribute. If set to true, the sessions' names are omitted
* from the resulting session configuration file.
*/
-extern int lttng_save_session_attr_set_omit_name(
+LTTNG_EXPORT extern int lttng_save_session_attr_set_omit_name(
struct lttng_save_session_attr *attr, int omit_name);
/*
* Set the omit output attribute. If set to true, the sessions' output
* configurations are omitted from the resulting session configuration file.
*/
-extern int lttng_save_session_attr_set_omit_output(
+LTTNG_EXPORT extern int lttng_save_session_attr_set_omit_output(
struct lttng_save_session_attr *attr, int omit_output);
/*
*
* Returns 0 on success or a negative LTTNG_ERR value on error.
*/
-extern int lttng_save_session(struct lttng_save_session_attr *attr);
+LTTNG_EXPORT extern int lttng_save_session(struct lttng_save_session_attr *attr);
#ifdef __cplusplus
}
#ifndef LTTNG_SESSION_DESCRIPTOR_H
#define LTTNG_SESSION_DESCRIPTOR_H
+#include <lttng/lttng-export.h>
+
#ifdef __cplusplus
extern "C" {
#endif
*
* Returns an lttng_session_descriptor instance on success, NULL on error.
*/
-extern struct lttng_session_descriptor *
+LTTNG_EXPORT extern struct lttng_session_descriptor *
lttng_session_descriptor_create(const char *name);
/*
*
* Returns an lttng_session_descriptor instance on success, NULL on error.
*/
-extern struct lttng_session_descriptor *
+LTTNG_EXPORT extern struct lttng_session_descriptor *
lttng_session_descriptor_local_create(const char *name, const char *path);
/*
*
* Returns an lttng_session_descriptor instance on success, NULL on error.
*/
-extern struct lttng_session_descriptor *
+LTTNG_EXPORT extern struct lttng_session_descriptor *
lttng_session_descriptor_network_create(const char *name,
const char *control_url, const char *data_url);
*
* Returns an lttng_session_descriptor instance on success, NULL on error.
*/
-extern struct lttng_session_descriptor *
+LTTNG_EXPORT extern struct lttng_session_descriptor *
lttng_session_descriptor_snapshot_create(const char *name);
/*
*
* Returns an lttng_session_descriptor instance on success, NULL on error.
*/
-extern struct lttng_session_descriptor *
+LTTNG_EXPORT extern struct lttng_session_descriptor *
lttng_session_descriptor_snapshot_local_create(const char *name,
const char *path);
*
* Returns an lttng_session_descriptor instance on success, NULL on error.
*/
-extern struct lttng_session_descriptor *
+LTTNG_EXPORT extern struct lttng_session_descriptor *
lttng_session_descriptor_snapshot_network_create(const char *name,
const char *control_url, const char *data_url);
*
* Returns an lttng_session_descriptor instance on success, NULL on error.
*/
-extern struct lttng_session_descriptor *
+LTTNG_EXPORT extern struct lttng_session_descriptor *
lttng_session_descriptor_live_create(
const char *name, unsigned long long live_timer_interval_us);
*
* Returns an lttng_session_descriptor instance on success, NULL on error.
*/
-extern struct lttng_session_descriptor *
+LTTNG_EXPORT extern struct lttng_session_descriptor *
lttng_session_descriptor_live_network_create(
const char *name,
const char *control_url, const char *data_url,
* NULL, and LTTNG_SESSION_DESCRIPTOR_STATUS_UNSET if the descriptor's
* name parameter is unset.
*/
-extern enum lttng_session_descriptor_status
+LTTNG_EXPORT extern enum lttng_session_descriptor_status
lttng_session_descriptor_get_session_name(
const struct lttng_session_descriptor *descriptor,
const char **name);
* This does not destroy the session on the session daemon; it releases
* the resources allocated by the descriptor object.
*/
-extern void lttng_session_descriptor_destroy(
+LTTNG_EXPORT extern void lttng_session_descriptor_destroy(
struct lttng_session_descriptor *descriptor);
#ifdef __cplusplus
#endif
#include <lttng/constant.h>
+#include <lttng/lttng-export.h>
struct lttng_handle;
struct lttng_session_descriptor;
* Returns LTTNG_OK on success. See lttng-error.h for the meaning of the other
* return codes.
*/
-extern enum lttng_error_code lttng_create_session_ext(
+LTTNG_EXPORT extern enum lttng_error_code lttng_create_session_ext(
struct lttng_session_descriptor *session_descriptor);
/*
*
* Return 0 on success else a negative LTTng error code.
*/
-extern int lttng_create_session(const char *name, const char *url);
+LTTNG_EXPORT extern int lttng_create_session(const char *name, const char *url);
/*
* Create a tracing session that will exclusively be used for snapshot meaning
*
* Return 0 on success else a negative LTTng error code.
*/
-extern int lttng_create_session_snapshot(const char *name,
+LTTNG_EXPORT extern int lttng_create_session_snapshot(const char *name,
const char *snapshot_url);
/*
*
* Return 0 on success else a negative LTTng error code.
*/
-extern int lttng_create_session_live(const char *name, const char *url,
+LTTNG_EXPORT extern int lttng_create_session_live(const char *name, const char *url,
unsigned int timer_interval);
/*
*
* Return 0 on success else a negative LTTng error code.
*/
-extern int lttng_destroy_session(const char *name);
+LTTNG_EXPORT extern int lttng_destroy_session(const char *name);
/*
* Destroy a tracing session.
* Returns LTTNG_OK on success. The returned handle is owned by the caller
* and must be free'd using lttng_destruction_handle_destroy().
*/
-extern enum lttng_error_code lttng_destroy_session_ext(const char *session_name,
+LTTNG_EXPORT extern enum lttng_error_code lttng_destroy_session_ext(const char *session_name,
struct lttng_destruction_handle **handle);
/*
* Behaves exactly like lttng_destroy_session but does not wait for data
* availability.
*/
-extern int lttng_destroy_session_no_wait(const char *name);
+LTTNG_EXPORT extern int lttng_destroy_session_no_wait(const char *name);
/*
* List all the tracing sessions.
*
* On error, a negative LTTng error code is returned.
*/
-extern int lttng_list_sessions(struct lttng_session **sessions);
+LTTNG_EXPORT extern int lttng_list_sessions(struct lttng_session **sessions);
/*
* Get the creation time of an lttng_session object on the session daemon.
* Returns LTTNG_OK on success. See lttng-error.h for the meaning of the other
* return codes.
*/
-extern enum lttng_error_code lttng_session_get_creation_time(
+LTTNG_EXPORT extern enum lttng_error_code lttng_session_get_creation_time(
const struct lttng_session *session, uint64_t *creation_time);
/*
*
* Return 0 on success else a negative LTTng error code.
*/
-extern int lttng_set_session_shm_path(const char *session_name,
+LTTNG_EXPORT extern int lttng_set_session_shm_path(const char *session_name,
const char *shm_path);
#ifdef __cplusplus
#define LTTNG_SNAPSHOT_H
#include <limits.h>
+#include <lttng/lttng-export.h>
#include <stdint.h>
#include <sys/types.h>
/*
* Return an newly allocated snapshot output object or NULL on error.
*/
-extern struct lttng_snapshot_output *lttng_snapshot_output_create(void);
+LTTNG_EXPORT extern struct lttng_snapshot_output *lttng_snapshot_output_create(void);
/*
* Free a given snapshot output object.
*/
-extern void lttng_snapshot_output_destroy(struct lttng_snapshot_output *output);
+LTTNG_EXPORT extern void lttng_snapshot_output_destroy(struct lttng_snapshot_output *output);
/*
* Snapshot output getter family functions. They all return the value present
*/
/* Return snapshot ID. */
-extern uint32_t lttng_snapshot_output_get_id(const struct lttng_snapshot_output *output);
+LTTNG_EXPORT extern uint32_t lttng_snapshot_output_get_id(const struct lttng_snapshot_output *output);
/* Return maximum size of a snapshot. */
-extern uint64_t lttng_snapshot_output_get_maxsize(const struct lttng_snapshot_output *output);
+LTTNG_EXPORT extern uint64_t lttng_snapshot_output_get_maxsize(const struct lttng_snapshot_output *output);
/* Return snapshot name. */
-extern const char *lttng_snapshot_output_get_name(const struct lttng_snapshot_output *output);
+LTTNG_EXPORT extern const char *lttng_snapshot_output_get_name(const struct lttng_snapshot_output *output);
/* Return snapshot control URL in a text format. */
-extern const char *lttng_snapshot_output_get_ctrl_url(const struct lttng_snapshot_output *output);
+LTTNG_EXPORT extern const char *lttng_snapshot_output_get_ctrl_url(const struct lttng_snapshot_output *output);
/* Return snapshot data URL in a text format. */
-extern const char *lttng_snapshot_output_get_data_url(const struct lttng_snapshot_output *output);
+LTTNG_EXPORT extern const char *lttng_snapshot_output_get_data_url(const struct lttng_snapshot_output *output);
/*
* Snapshot output setter family functions.
*/
/* Set a custom ID. */
-extern int lttng_snapshot_output_set_id(uint32_t id,
+LTTNG_EXPORT extern int lttng_snapshot_output_set_id(uint32_t id,
struct lttng_snapshot_output *output);
/* Set the maximum size. */
-extern int lttng_snapshot_output_set_size(uint64_t size,
+LTTNG_EXPORT extern int lttng_snapshot_output_set_size(uint64_t size,
struct lttng_snapshot_output *output);
/* Set the snapshot name. */
-extern int lttng_snapshot_output_set_name(const char *name,
+LTTNG_EXPORT extern int lttng_snapshot_output_set_name(const char *name,
struct lttng_snapshot_output *output);
/*
*
* Return 0 on success or else a negative LTTNG_ERR code.
*/
-extern int lttng_snapshot_output_set_local_path(const char *path,
+LTTNG_EXPORT extern int lttng_snapshot_output_set_local_path(const char *path,
struct lttng_snapshot_output *output);
/*
*
* Return 0 on success or else a negative LTTNG_ERR code.
*/
-extern int lttng_snapshot_output_set_network_url(const char *url,
+LTTNG_EXPORT extern int lttng_snapshot_output_set_network_url(const char *url,
struct lttng_snapshot_output *output);
/*
*
* Return 0 on success or else a negative LTTNG_ERR code.
*/
-extern int lttng_snapshot_output_set_network_urls(
+LTTNG_EXPORT extern int lttng_snapshot_output_set_network_urls(
const char *ctrl_url, const char *data_url,
struct lttng_snapshot_output *output);
/* Set the control URL. Local and remote URL are supported. */
-extern int lttng_snapshot_output_set_ctrl_url(const char *url,
+LTTNG_EXPORT extern int lttng_snapshot_output_set_ctrl_url(const char *url,
struct lttng_snapshot_output *output);
/* Set the data URL. Local and remote URL are supported. */
-extern int lttng_snapshot_output_set_data_url(const char *url,
+LTTNG_EXPORT extern int lttng_snapshot_output_set_data_url(const char *url,
struct lttng_snapshot_output *output);
/*
*
* Return 0 on success or else a negative LTTNG_ERR code.
*/
-extern int lttng_snapshot_add_output(const char *session_name,
+LTTNG_EXPORT extern int lttng_snapshot_add_output(const char *session_name,
struct lttng_snapshot_output *output);
/*
*
* Return 0 on success or else a negative LTTNG_ERR code.
*/
-extern int lttng_snapshot_del_output(const char *session_name,
+LTTNG_EXPORT extern int lttng_snapshot_del_output(const char *session_name,
struct lttng_snapshot_output *output);
/*
* Return 0 on success or else a negative LTTNG_ERR code and the list pointer
* is untouched.
*/
-extern int lttng_snapshot_list_output(const char *session_name,
+LTTNG_EXPORT extern int lttng_snapshot_list_output(const char *session_name,
struct lttng_snapshot_output_list **list);
/*
* Return the next object on success or else NULL indicating the end of the
* list.
*/
-extern struct lttng_snapshot_output *lttng_snapshot_output_list_get_next(
+LTTNG_EXPORT extern struct lttng_snapshot_output *lttng_snapshot_output_list_get_next(
struct lttng_snapshot_output_list *list);
/*
* Free an output list object.
*/
-extern void lttng_snapshot_output_list_destroy(struct lttng_snapshot_output_list *list);
+LTTNG_EXPORT extern void lttng_snapshot_output_list_destroy(struct lttng_snapshot_output_list *list);
/*
* Snapshot a trace for the given session.
*
* Return 0 on success or else a negative LTTNG_ERR value.
*/
-extern int lttng_snapshot_record(const char *session_name,
+LTTNG_EXPORT extern int lttng_snapshot_record(const char *session_name,
struct lttng_snapshot_output *output, int wait);
#ifdef __cplusplus
#include <lttng/constant.h>
#include <lttng/domain.h>
#include <lttng/lttng-error.h>
+#include <lttng/lttng-export.h>
#include <lttng/session.h>
#include <sys/types.h>
* The tracker's ownership is transfered to the caller. Use
* lttng_process_attr_tracker_handle_destroy() to dispose of it.
*/
-extern enum lttng_error_code lttng_session_get_tracker_handle(
+LTTNG_EXPORT extern enum lttng_error_code lttng_session_get_tracker_handle(
const char *session_name,
enum lttng_domain_type domain,
enum lttng_process_attr process_attr,
/*
* Destroy a process attribute tracker handle.
*/
-extern void lttng_process_attr_tracker_handle_destroy(
+LTTNG_EXPORT extern void lttng_process_attr_tracker_handle_destroy(
struct lttng_process_attr_tracker_handle *tracker_handle);
/*
* policy of a process attribute tracker on success,
* LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID on error.
*/
-extern enum lttng_process_attr_tracker_handle_status
+LTTNG_EXPORT extern enum lttng_process_attr_tracker_handle_status
lttng_process_attr_tracker_handle_get_tracking_policy(
const struct lttng_process_attr_tracker_handle *tracker_handle,
enum lttng_tracking_policy *policy);
* Returns the LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK on success,
* LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID on error.
*/
-extern enum lttng_process_attr_tracker_handle_status
+LTTNG_EXPORT extern enum lttng_process_attr_tracker_handle_status
lttng_process_attr_tracker_handle_set_tracking_policy(
const struct lttng_process_attr_tracker_handle *tracker_handle,
enum lttng_tracking_policy policy);
* LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID if an invalid tracker
* argument was provided.
*/
-extern enum lttng_process_attr_tracker_handle_status
+LTTNG_EXPORT extern enum lttng_process_attr_tracker_handle_status
lttng_process_attr_process_id_tracker_handle_add_pid(
const struct lttng_process_attr_tracker_handle
*process_id_tracker,
* in the inclusion set, and LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_INVALID if
* an invalid tracker argument was provided.
*/
-extern enum lttng_process_attr_tracker_handle_status
+LTTNG_EXPORT extern enum lttng_process_attr_tracker_handle_status
lttng_process_attr_process_id_tracker_handle_remove_pid(
const struct lttng_process_attr_tracker_handle
*process_id_tracker,
* LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_INVALID if an invalid tracker
* argument was provided.
*/
-extern enum lttng_process_attr_tracker_handle_status
+LTTNG_EXPORT extern enum lttng_process_attr_tracker_handle_status
lttng_process_attr_virtual_process_id_tracker_handle_add_pid(
const struct lttng_process_attr_tracker_handle
*process_id_tracker,
* in the inclusion set, and LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_INVALID if
* an invalid tracker argument was provided.
*/
-extern enum lttng_process_attr_tracker_handle_status
+LTTNG_EXPORT extern enum lttng_process_attr_tracker_handle_status
lttng_process_attr_virtual_process_id_tracker_handle_remove_pid(
const struct lttng_process_attr_tracker_handle
*process_id_tracker,
* LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_INVALID if an invalid tracker
* argument was provided.
*/
-extern enum lttng_process_attr_tracker_handle_status
+LTTNG_EXPORT extern enum lttng_process_attr_tracker_handle_status
lttng_process_attr_user_id_tracker_handle_add_uid(
const struct lttng_process_attr_tracker_handle *user_id_tracker,
uid_t uid);
* in the inclusion set, and LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_INVALID if
* an invalid tracker argument was provided.
*/
-extern enum lttng_process_attr_tracker_handle_status
+LTTNG_EXPORT extern enum lttng_process_attr_tracker_handle_status
lttng_process_attr_user_id_tracker_handle_remove_uid(
const struct lttng_process_attr_tracker_handle *user_id_tracker,
uid_t uid);
* LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_INVALID if an invalid tracker
* argument was provided.
*/
-extern enum lttng_process_attr_tracker_handle_status
+LTTNG_EXPORT extern enum lttng_process_attr_tracker_handle_status
lttng_process_attr_user_id_tracker_handle_add_user_name(
const struct lttng_process_attr_tracker_handle *user_id_tracker,
const char *user_name);
* in the inclusion set, and LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_INVALID if
* an invalid tracker argument was provided.
*/
-extern enum lttng_process_attr_tracker_handle_status
+LTTNG_EXPORT extern enum lttng_process_attr_tracker_handle_status
lttng_process_attr_user_id_tracker_handle_remove_user_name(
const struct lttng_process_attr_tracker_handle *user_id_tracker,
const char *user_name);
* LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_INVALID if an invalid tracker
* argument was provided.
*/
-extern enum lttng_process_attr_tracker_handle_status
+LTTNG_EXPORT extern enum lttng_process_attr_tracker_handle_status
lttng_process_attr_virtual_user_id_tracker_handle_add_uid(
const struct lttng_process_attr_tracker_handle *user_id_tracker,
uid_t vuid);
* in the inclusion set, and LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_INVALID if
* an invalid tracker argument was provided.
*/
-extern enum lttng_process_attr_tracker_handle_status
+LTTNG_EXPORT extern enum lttng_process_attr_tracker_handle_status
lttng_process_attr_virtual_user_id_tracker_handle_remove_uid(
const struct lttng_process_attr_tracker_handle *user_id_tracker,
uid_t vuid);
* LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_INVALID if an invalid tracker
* argument was provided.
*/
-extern enum lttng_process_attr_tracker_handle_status
+LTTNG_EXPORT extern enum lttng_process_attr_tracker_handle_status
lttng_process_attr_virtual_user_id_tracker_handle_add_user_name(
const struct lttng_process_attr_tracker_handle *user_id_tracker,
const char *virtual_user_name);
* in the inclusion set, and LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_INVALID if
* an invalid tracker argument was provided.
*/
-extern enum lttng_process_attr_tracker_handle_status
+LTTNG_EXPORT extern enum lttng_process_attr_tracker_handle_status
lttng_process_attr_virtual_user_id_tracker_handle_remove_user_name(
const struct lttng_process_attr_tracker_handle *user_id_tracker,
const char *virtual_user_name);
* LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_INVALID if an invalid tracker
* argument was provided.
*/
-extern enum lttng_process_attr_tracker_handle_status
+LTTNG_EXPORT extern enum lttng_process_attr_tracker_handle_status
lttng_process_attr_group_id_tracker_handle_add_gid(
const struct lttng_process_attr_tracker_handle *group_id_tracker,
gid_t gid);
* in the inclusion set, and LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_INVALID if
* an invalid tracker argument was provided.
*/
-extern enum lttng_process_attr_tracker_handle_status
+LTTNG_EXPORT extern enum lttng_process_attr_tracker_handle_status
lttng_process_attr_group_id_tracker_handle_remove_gid(
const struct lttng_process_attr_tracker_handle *group_id_tracker,
gid_t gid);
* LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_INVALID if an invalid tracker
* argument was provided.
*/
-extern enum lttng_process_attr_tracker_handle_status
+LTTNG_EXPORT extern enum lttng_process_attr_tracker_handle_status
lttng_process_attr_group_id_tracker_handle_add_group_name(
const struct lttng_process_attr_tracker_handle *group_id_tracker,
const char *group_name);
* in the inclusion set, and LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_INVALID if
* an invalid tracker argument was provided.
*/
-extern enum lttng_process_attr_tracker_handle_status
+LTTNG_EXPORT extern enum lttng_process_attr_tracker_handle_status
lttng_process_attr_group_id_tracker_handle_remove_group_name(
const struct lttng_process_attr_tracker_handle *group_id_tracker,
const char *group_name);
* LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_INVALID if an invalid tracker
* argument was provided.
*/
-extern enum lttng_process_attr_tracker_handle_status
+LTTNG_EXPORT extern enum lttng_process_attr_tracker_handle_status
lttng_process_attr_virtual_group_id_tracker_handle_add_gid(
const struct lttng_process_attr_tracker_handle *group_id_tracker,
gid_t vgid);
* in the inclusion set, and LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_INVALID if
* an invalid tracker argument was provided.
*/
-extern enum lttng_process_attr_tracker_handle_status
+LTTNG_EXPORT extern enum lttng_process_attr_tracker_handle_status
lttng_process_attr_virtual_group_id_tracker_handle_remove_gid(
const struct lttng_process_attr_tracker_handle *group_id_tracker,
gid_t vgid);
* LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_INVALID if an invalid tracker
* argument was provided.
*/
-extern enum lttng_process_attr_tracker_handle_status
+LTTNG_EXPORT extern enum lttng_process_attr_tracker_handle_status
lttng_process_attr_virtual_group_id_tracker_handle_add_group_name(
const struct lttng_process_attr_tracker_handle *group_id_tracker,
const char *virtual_group_name);
* in the inclusion set, and LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_INVALID if
* an invalid tracker argument was provided.
*/
-extern enum lttng_process_attr_tracker_handle_status
+LTTNG_EXPORT extern enum lttng_process_attr_tracker_handle_status
lttng_process_attr_virtual_group_id_tracker_handle_remove_group_name(
const struct lttng_process_attr_tracker_handle *group_id_tracker,
const char *virtual_group_name);
* LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID if the tracker's policy is
* not LTTNG_POLICY_INCLUDE_SET.
*/
-extern enum lttng_process_attr_tracker_handle_status
+LTTNG_EXPORT extern enum lttng_process_attr_tracker_handle_status
lttng_process_attr_tracker_handle_get_inclusion_set(
struct lttng_process_attr_tracker_handle *tracker_handle,
const struct lttng_process_attr_values **values);
* Returns LTTNG_PROCESS_ATTR_VALUES_STATUS_OK on success,
* LTTNG_PROCESS_ATTR_VALUES_STATUS_INVALID if an invalid argument is provided.
*/
-extern enum lttng_process_attr_values_status
+LTTNG_EXPORT extern enum lttng_process_attr_values_status
lttng_process_attr_values_get_count(
const struct lttng_process_attr_values *values,
unsigned int *count);
* Returns a process attribute value type on success,
* LTTNG_PROCESS_ATTR_VALUE_TYPE_INVALID if an invalid argument is provided.
*/
-extern enum lttng_process_attr_value_type
+LTTNG_EXPORT extern enum lttng_process_attr_value_type
lttng_process_attr_values_get_type_at_index(
const struct lttng_process_attr_values *values,
unsigned int index);
* LTTNG_PROCESS_ATTR_VALUES_STATUS_INVALID_TYPE if the process attribute value
* is not a process ID.
*/
-extern enum lttng_process_attr_values_status
+LTTNG_EXPORT extern enum lttng_process_attr_values_status
lttng_process_attr_values_get_pid_at_index(
const struct lttng_process_attr_values *values,
unsigned int index,
* LTTNG_PROCESS_ATTR_VALUES_STATUS_INVALID_TYPE if the process attribute value
* is not a user ID.
*/
-extern enum lttng_process_attr_values_status
+LTTNG_EXPORT extern enum lttng_process_attr_values_status
lttng_process_attr_values_get_uid_at_index(
const struct lttng_process_attr_values *values,
unsigned int index,
* LTTNG_PROCESS_ATTR_VALUES_STATUS_INVALID_TYPE if the process attribute value
* is not a user name.
*/
-extern enum lttng_process_attr_values_status
+LTTNG_EXPORT extern enum lttng_process_attr_values_status
lttng_process_attr_values_get_user_name_at_index(
const struct lttng_process_attr_values *values,
unsigned int index,
* LTTNG_PROCESS_ATTR_VALUES_STATUS_INVALID_TYPE if the process attribute value
* is not a group ID.
*/
-extern enum lttng_process_attr_values_status
+LTTNG_EXPORT extern enum lttng_process_attr_values_status
lttng_process_attr_values_get_gid_at_index(
const struct lttng_process_attr_values *values,
unsigned int index,
* LTTNG_PROCESS_ATTR_VALUES_STATUS_INVALID_TYPE if the process attribute value
* is not a group name.
*/
-extern enum lttng_process_attr_values_status
+LTTNG_EXPORT extern enum lttng_process_attr_values_status
lttng_process_attr_values_get_group_name_at_index(
const struct lttng_process_attr_values *values,
unsigned int index,
*
* Returns 0 on success, else a negative LTTng error code.
*/
-extern int lttng_list_tracker_pids(struct lttng_handle *handle,
+LTTNG_EXPORT extern int lttng_list_tracker_pids(struct lttng_handle *handle,
int *enabled,
int32_t **pids,
size_t *nr_pids);
*
* Returns 0 on success, else a negative LTTng error code.
*/
-extern int lttng_track_pid(struct lttng_handle *handle, int pid);
+LTTNG_EXPORT extern int lttng_track_pid(struct lttng_handle *handle, int pid);
/*
* Deprecated: see `lttng_process_attr_process_id_tracker_handle_remove_pid`.
*
* Returns 0 on success, else a negative LTTng error code.
*/
-extern int lttng_untrack_pid(struct lttng_handle *handle, int pid);
+LTTNG_EXPORT extern int lttng_untrack_pid(struct lttng_handle *handle, int pid);
#ifdef __cplusplus
}
#include <lttng/constant.h>
#include <inttypes.h>
#include <lttng/lttng-error.h>
+#include <lttng/lttng-export.h>
struct lttng_action;
struct lttng_condition;
* Trigger objects must be destroyed using the lttng_trigger_destroy()
* function.
*/
-extern struct lttng_trigger *lttng_trigger_create(
+LTTNG_EXPORT extern struct lttng_trigger *lttng_trigger_create(
struct lttng_condition *condition, struct lttng_action *action);
/*
* LTTNG_TRIGGER_STATUS_EPERM if not authorized,
* LTTNG_TRIGGER_STATUS_INVALID if invalid parameters are passed.
*/
-extern enum lttng_trigger_status lttng_trigger_set_owner_uid(
+LTTNG_EXPORT extern enum lttng_trigger_status lttng_trigger_set_owner_uid(
struct lttng_trigger *trigger, uid_t uid);
/*
* LTTNG_TRIGGER_STATUS_UNSET if unset,
* LTTNG_TRIGGER_STATUS_INVALID if invalid parameters are passed.
*/
-extern enum lttng_trigger_status lttng_trigger_get_owner_uid(
+LTTNG_EXPORT extern enum lttng_trigger_status lttng_trigger_get_owner_uid(
const struct lttng_trigger *trigger, uid_t *uid);
/*
*
* Returns a condition on success, NULL on error.
*/
-extern struct lttng_condition *lttng_trigger_get_condition(
+LTTNG_EXPORT extern struct lttng_condition *lttng_trigger_get_condition(
struct lttng_trigger *trigger);
-extern const struct lttng_condition *lttng_trigger_get_const_condition(
+LTTNG_EXPORT extern const struct lttng_condition *lttng_trigger_get_const_condition(
const struct lttng_trigger *trigger);
/*
*
* Returns an action on success, NULL on error.
*/
-extern struct lttng_action *lttng_trigger_get_action(
+LTTNG_EXPORT extern struct lttng_action *lttng_trigger_get_action(
struct lttng_trigger *trigger);
-extern const struct lttng_action *lttng_trigger_get_const_action(
+LTTNG_EXPORT extern const struct lttng_action *lttng_trigger_get_const_action(
const struct lttng_trigger *trigger);
/*
* success, LTTNG_TRIGGER_STATUS_INVALID if an invalid parameter is passed,
* or LTTNG_TRIGGER_STATUS_UNSET if the trigger is unnamed.
*/
-extern enum lttng_trigger_status lttng_trigger_get_name(
+LTTNG_EXPORT extern enum lttng_trigger_status lttng_trigger_get_name(
const struct lttng_trigger *trigger, const char **name);
/*
* Destroy (frees) a trigger object.
*/
-extern void lttng_trigger_destroy(struct lttng_trigger *trigger);
+LTTNG_EXPORT extern void lttng_trigger_destroy(struct lttng_trigger *trigger);
/*
* Register a trigger to the session daemon with a given name.
*
* Returns an LTTng status code.
*/
-extern enum lttng_error_code lttng_register_trigger_with_name(
+LTTNG_EXPORT extern enum lttng_error_code lttng_register_trigger_with_name(
struct lttng_trigger *trigger,
const char *name);
*
* Returns an LTTng status code.
*/
-extern enum lttng_error_code lttng_register_trigger_with_automatic_name(
+LTTNG_EXPORT extern enum lttng_error_code lttng_register_trigger_with_automatic_name(
struct lttng_trigger *trigger);
/*
*
* Return 0 on success, a negative LTTng error code on error.
*/
-extern int lttng_unregister_trigger(const struct lttng_trigger *trigger);
+LTTNG_EXPORT extern int lttng_unregister_trigger(const struct lttng_trigger *trigger);
/*
* List triggers for the current user.
*
* Returns LTTNG_OK on success, else a suitable LTTng error code.
*/
-extern enum lttng_error_code lttng_list_triggers(
+LTTNG_EXPORT extern enum lttng_error_code lttng_list_triggers(
struct lttng_triggers **triggers);
/*
*
* Returns a trigger, or NULL on error.
*/
-extern const struct lttng_trigger *lttng_triggers_get_at_index(
+LTTNG_EXPORT extern const struct lttng_trigger *lttng_triggers_get_at_index(
const struct lttng_triggers *triggers, unsigned int index);
/*
* Return LTTNG_TRIGGER_STATUS_OK on success,
* LTTNG_TRIGGER_STATUS_INVALID when invalid parameters are passed.
*/
-extern enum lttng_trigger_status lttng_triggers_get_count(
+LTTNG_EXPORT extern enum lttng_trigger_status lttng_triggers_get_count(
const struct lttng_triggers *triggers, unsigned int *count);
/*
* Destroy a trigger set.
*/
-extern void lttng_triggers_destroy(struct lttng_triggers *triggers);
+LTTNG_EXPORT extern void lttng_triggers_destroy(struct lttng_triggers *triggers);
/*
* Deprecated: invocations should be replaced by
* Return 0 on success, a negative LTTng error code on error.
*/
LTTNG_DEPRECATED("Use lttng_register_trigger_with_automatic_name")
-extern int lttng_register_trigger(struct lttng_trigger *trigger);
+LTTNG_EXPORT extern int lttng_register_trigger(struct lttng_trigger *trigger);
#ifdef __cplusplus
}
#ifndef LTTNG_USERSPACE_PROBE_H
#define LTTNG_USERSPACE_PROBE_H
+#include <lttng/lttng-export.h>
+
#ifdef __cplusplus
extern "C" {
#endif
/*
* Get the type of a lookup method.
*/
-extern enum lttng_userspace_probe_location_lookup_method_type
+LTTNG_EXPORT extern enum lttng_userspace_probe_location_lookup_method_type
lttng_userspace_probe_location_lookup_method_get_type(
const struct lttng_userspace_probe_location_lookup_method *lookup_method);
/*
* Destroy a lookup method.
*/
-extern void lttng_userspace_probe_location_lookup_method_destroy(
+LTTNG_EXPORT extern void lttng_userspace_probe_location_lookup_method_destroy(
struct lttng_userspace_probe_location_lookup_method *lookup_method);
/*
* Create a tracepoint ELF function lookup method struct.
* Return NULL on failure.
*/
-extern struct lttng_userspace_probe_location_lookup_method *
+LTTNG_EXPORT extern struct lttng_userspace_probe_location_lookup_method *
lttng_userspace_probe_location_lookup_method_function_elf_create(void);
/*
* Create a tracepoint SDT tracepoint lookup method struct.
* Return NULL on failure.
*/
-extern struct lttng_userspace_probe_location_lookup_method *
+LTTNG_EXPORT extern struct lttng_userspace_probe_location_lookup_method *
lttng_userspace_probe_location_lookup_method_tracepoint_sdt_create(void);
/*
* Get the type of the userspace probe location.
*/
-extern enum lttng_userspace_probe_location_type
+LTTNG_EXPORT extern enum lttng_userspace_probe_location_type
lttng_userspace_probe_location_get_type(
const struct lttng_userspace_probe_location *location);
/*
* Destroy the userspace probe location.
*/
-extern void lttng_userspace_probe_location_destroy(
+LTTNG_EXPORT extern void lttng_userspace_probe_location_destroy(
struct lttng_userspace_probe_location *location);
* The ownership of the lookup method is transferred to the created probe
* location.
*/
-extern struct lttng_userspace_probe_location *
+LTTNG_EXPORT extern struct lttng_userspace_probe_location *
lttng_userspace_probe_location_function_create(const char *binary_path,
const char *function_name,
struct lttng_userspace_probe_location_lookup_method *lookup_method);
/*
* Get the target binary path of the probe location of the function type.
*/
-extern const char *lttng_userspace_probe_location_function_get_binary_path(
+LTTNG_EXPORT extern const char *lttng_userspace_probe_location_function_get_binary_path(
const struct lttng_userspace_probe_location *location);
/*
* Get the target function type of the probe location of the function type.
*/
-extern const char *lttng_userspace_probe_location_function_get_function_name(
+LTTNG_EXPORT extern const char *lttng_userspace_probe_location_function_get_function_name(
const struct lttng_userspace_probe_location *location);
/*
* Get the FD to the target binary file to the probe location of the function
* type. The FD is only valid for the duration of the lifetime of `location`.
*/
-extern int lttng_userspace_probe_location_function_get_binary_fd(
+LTTNG_EXPORT extern int lttng_userspace_probe_location_function_get_binary_fd(
const struct lttng_userspace_probe_location *location);
/*
* Get the instrumentation type of the function probe location.
*/
-extern enum lttng_userspace_probe_location_function_instrumentation_type
+LTTNG_EXPORT extern enum lttng_userspace_probe_location_function_instrumentation_type
lttng_userspace_probe_location_function_get_instrumentation_type(
const struct lttng_userspace_probe_location *location);
* LTTNG_USERSPACE_PROBE_LOCATION_STATUS_INVALID if invalid parameters
* are provided.
*/
-extern enum lttng_userspace_probe_location_status
+LTTNG_EXPORT extern enum lttng_userspace_probe_location_status
lttng_userspace_probe_location_function_set_instrumentation_type(
const struct lttng_userspace_probe_location *location,
enum lttng_userspace_probe_location_function_instrumentation_type instrumentation_type);
*
* The ownership of the lookup method is NOT transferred to the caller.
*/
-extern const struct lttng_userspace_probe_location_lookup_method *
+LTTNG_EXPORT extern const struct lttng_userspace_probe_location_lookup_method *
lttng_userspace_probe_location_get_lookup_method(
const struct lttng_userspace_probe_location *location);
* The ownership of the lookup method is transferred to the created probe
* location.
*/
-extern struct lttng_userspace_probe_location *
+LTTNG_EXPORT extern struct lttng_userspace_probe_location *
lttng_userspace_probe_location_tracepoint_create(const char *binary_path,
const char *probe_name, const char *provider_name,
struct lttng_userspace_probe_location_lookup_method *lookup_method);
/*
* Get the target binary path of the probe location of the tracepoint type.
*/
-extern const char *lttng_userspace_probe_location_tracepoint_get_binary_path(
+LTTNG_EXPORT extern const char *lttng_userspace_probe_location_tracepoint_get_binary_path(
const struct lttng_userspace_probe_location *location);
/*
* Get the target probe name of the probe location of the tracepoint type.
*/
-extern const char *lttng_userspace_probe_location_tracepoint_get_probe_name(
+LTTNG_EXPORT extern const char *lttng_userspace_probe_location_tracepoint_get_probe_name(
const struct lttng_userspace_probe_location *location);
/*
* Get the target probe provider name of the probe location of the tracepoint
* type.
*/
-extern const char *lttng_userspace_probe_location_tracepoint_get_provider_name(
+LTTNG_EXPORT extern const char *lttng_userspace_probe_location_tracepoint_get_provider_name(
const struct lttng_userspace_probe_location *location);
/*
* Get the FD to the target binary file to the probe location of the tracepoint
* type. The FD is only valid for the duration of the lifetime of `location`.
*/
-extern int lttng_userspace_probe_location_tracepoint_get_binary_fd(
+LTTNG_EXPORT extern int lttng_userspace_probe_location_tracepoint_get_binary_fd(
const struct lttng_userspace_probe_location *location);
#ifdef __cplusplus
extern const char *tracing_group_name;
/*
- * This function is dlsym-ed from a test, making it have a C linkage name
- * makes it easier.
+ * This function is dlsym-ed from a test, so needs to be exported. Making it
+ * have a C linkage name makes it easier, as it avoids having to look up a
+ * mangled name.
*/
-extern "C" enum lttng_consumer_type lttng_consumer_get_type();
+extern "C" LTTNG_EXPORT
+enum lttng_consumer_type lttng_consumer_get_type();
#endif /* _LTTNG_CONSUMERD_H */
#include <urcu/list.h>
#include <urcu/rculfhash.h>
+/*
+ * Flag used to temporarily pause data consumption from testpoints.
+ *
+ * This variable is dlsym-ed from a test, so needs to be exported.
+ */
+LTTNG_EXPORT int notifier_consumption_paused;
-int notifier_consumption_paused;
/*
* Destroy the thread data previously created by the init function.
*/
#include <lttng/ust-sigbus.h>
#include <lttng/ust-ctl.h>
+#include <lttng/lttng-export.h>
#include "ust-sigbus.h"
-DEFINE_LTTNG_UST_SIGBUS_STATE();
+LTTNG_EXPORT DEFINE_LTTNG_UST_SIGBUS_STATE();
void lttng_ust_handle_sigbus(void *address)
{
#ifndef CONFIG_SESSION_INTERNAL_H
#define CONFIG_SESSION_INTERNAL_H
+#include <lttng/lttng-export.h>
+
extern const char * const config_element_all;
-extern const char * const config_element_channel;
-extern const char * const config_element_channels;
-extern const char * const config_element_domain;
-extern const char * const config_element_domains;
-extern const char * const config_element_event;
-extern const char * const config_element_events;
-extern const char * const config_element_context;
-extern const char * const config_element_contexts;
-extern const char * const config_element_attributes;
-extern const char * const config_element_exclusion;
-extern const char * const config_element_exclusions;
-extern const char * const config_element_function_attributes;
-extern const char * const config_element_probe_attributes;
-extern const char * const config_element_symbol_name;
-extern const char * const config_element_address;
-extern const char * const config_element_offset;
+LTTNG_EXPORT extern const char * const config_element_channel;
+LTTNG_EXPORT extern const char * const config_element_channels;
+LTTNG_EXPORT extern const char * const config_element_domain;
+LTTNG_EXPORT extern const char * const config_element_domains;
+LTTNG_EXPORT extern const char * const config_element_event;
+LTTNG_EXPORT extern const char * const config_element_events;
+LTTNG_EXPORT extern const char * const config_element_context;
+LTTNG_EXPORT extern const char * const config_element_contexts;
+LTTNG_EXPORT extern const char * const config_element_attributes;
+LTTNG_EXPORT extern const char * const config_element_exclusion;
+LTTNG_EXPORT extern const char * const config_element_exclusions;
+LTTNG_EXPORT extern const char * const config_element_function_attributes;
+LTTNG_EXPORT extern const char * const config_element_probe_attributes;
+LTTNG_EXPORT extern const char * const config_element_symbol_name;
+LTTNG_EXPORT extern const char * const config_element_address;
+LTTNG_EXPORT extern const char * const config_element_offset;
extern const char * const config_element_userspace_probe_lookup;
extern const char * const config_element_userspace_probe_lookup_function_default;
extern const char * const config_element_userspace_probe_lookup_function_elf;
extern const char * const config_element_userspace_probe_tracepoint_location_provider_name;
extern const char * const config_element_userspace_probe_tracepoint_location_probe_name;
extern const char * const config_element_name;
-extern const char * const config_element_enabled;
-extern const char * const config_element_overwrite_mode;
-extern const char * const config_element_subbuf_size;
-extern const char * const config_element_num_subbuf;
-extern const char * const config_element_switch_timer_interval;
-extern const char * const config_element_read_timer_interval;
+LTTNG_EXPORT extern const char * const config_element_enabled;
+LTTNG_EXPORT extern const char * const config_element_overwrite_mode;
+LTTNG_EXPORT extern const char * const config_element_subbuf_size;
+LTTNG_EXPORT extern const char * const config_element_num_subbuf;
+LTTNG_EXPORT extern const char * const config_element_switch_timer_interval;
+LTTNG_EXPORT extern const char * const config_element_read_timer_interval;
extern const char * const config_element_monitor_timer_interval;
extern const char * const config_element_blocking_timeout;
-extern const char * const config_element_output;
-extern const char * const config_element_output_type;
-extern const char * const config_element_tracefile_size;
-extern const char * const config_element_tracefile_count;
-extern const char * const config_element_live_timer_interval;
+LTTNG_EXPORT extern const char * const config_element_output;
+LTTNG_EXPORT extern const char * const config_element_output_type;
+LTTNG_EXPORT extern const char * const config_element_tracefile_size;
+LTTNG_EXPORT extern const char * const config_element_tracefile_count;
+LTTNG_EXPORT extern const char * const config_element_live_timer_interval;
extern const char * const config_element_discarded_events;
extern const char * const config_element_lost_packets;
-extern const char * const config_element_type;
-extern const char * const config_element_buffer_type;
-extern const char * const config_element_session;
-extern const char * const config_element_sessions;
+LTTNG_EXPORT extern const char * const config_element_type;
+LTTNG_EXPORT extern const char * const config_element_buffer_type;
+LTTNG_EXPORT extern const char * const config_element_session;
+LTTNG_EXPORT extern const char * const config_element_sessions;
extern const char * const config_element_context_perf;
extern const char * const config_element_context_app;
extern const char * const config_element_context_app_provider_name;
extern const char * const config_element_context_app_ctx_name;
-extern const char * const config_element_config;
-extern const char * const config_element_started;
-extern const char * const config_element_snapshot_mode;
-extern const char * const config_element_loglevel;
-extern const char * const config_element_loglevel_type;
-extern const char * const config_element_filter;
+LTTNG_EXPORT extern const char * const config_element_config;
+LTTNG_EXPORT extern const char * const config_element_started;
+LTTNG_EXPORT extern const char * const config_element_snapshot_mode;
+LTTNG_EXPORT extern const char * const config_element_loglevel;
+LTTNG_EXPORT extern const char * const config_element_loglevel_type;
+LTTNG_EXPORT extern const char * const config_element_filter;
extern const char * const config_element_filter_expression;
-extern const char * const config_element_snapshot_outputs;
-extern const char * const config_element_consumer_output;
-extern const char * const config_element_destination;
-extern const char * const config_element_path;
-extern const char * const config_element_net_output;
-extern const char * const config_element_control_uri;
-extern const char * const config_element_data_uri;
-extern const char * const config_element_max_size;
-extern const char * const config_element_pid;
+LTTNG_EXPORT extern const char * const config_element_snapshot_outputs;
+LTTNG_EXPORT extern const char * const config_element_consumer_output;
+LTTNG_EXPORT extern const char * const config_element_destination;
+LTTNG_EXPORT extern const char * const config_element_path;
+LTTNG_EXPORT extern const char * const config_element_net_output;
+LTTNG_EXPORT extern const char * const config_element_control_uri;
+LTTNG_EXPORT extern const char * const config_element_data_uri;
+LTTNG_EXPORT extern const char * const config_element_max_size;
+LTTNG_EXPORT extern const char * const config_element_pid;
extern const char * const config_element_process_attr_id;
-extern const char * const config_element_pids;
-extern const char * const config_element_name;
-extern const char * const config_element_shared_memory_path;
+LTTNG_EXPORT extern const char * const config_element_pids;
+LTTNG_EXPORT extern const char * const config_element_name;
+LTTNG_EXPORT extern const char * const config_element_shared_memory_path;
extern const char * const config_element_process_attr_tracker_pid;
extern const char * const config_element_process_attr_tracker_vpid;
extern const char * const config_element_process_attr_tracker_uid;
extern const char * const config_element_rotation_size;
extern const char * const config_element_rotation_schedule;
-extern const char * const config_domain_type_kernel;
-extern const char * const config_domain_type_ust;
-extern const char * const config_domain_type_jul;
-extern const char * const config_domain_type_log4j;
-extern const char * const config_domain_type_python;
+LTTNG_EXPORT extern const char * const config_domain_type_kernel;
+LTTNG_EXPORT extern const char * const config_domain_type_ust;
+LTTNG_EXPORT extern const char * const config_domain_type_jul;
+LTTNG_EXPORT extern const char * const config_domain_type_log4j;
+LTTNG_EXPORT extern const char * const config_domain_type_python;
-extern const char * const config_buffer_type_per_pid;
-extern const char * const config_buffer_type_per_uid;
-extern const char * const config_buffer_type_global;
+LTTNG_EXPORT extern const char * const config_buffer_type_per_pid;
+LTTNG_EXPORT extern const char * const config_buffer_type_per_uid;
+LTTNG_EXPORT extern const char * const config_buffer_type_global;
-extern const char * const config_overwrite_mode_discard;
-extern const char * const config_overwrite_mode_overwrite;
+LTTNG_EXPORT extern const char * const config_overwrite_mode_discard;
+LTTNG_EXPORT extern const char * const config_overwrite_mode_overwrite;
-extern const char * const config_output_type_splice;
-extern const char * const config_output_type_mmap;
+LTTNG_EXPORT extern const char * const config_output_type_splice;
+LTTNG_EXPORT extern const char * const config_output_type_mmap;
-extern const char * const config_loglevel_type_all;
-extern const char * const config_loglevel_type_range;
-extern const char * const config_loglevel_type_single;
+LTTNG_EXPORT extern const char * const config_loglevel_type_all;
+LTTNG_EXPORT extern const char * const config_loglevel_type_range;
+LTTNG_EXPORT extern const char * const config_loglevel_type_single;
-extern const char * const config_event_type_all;
-extern const char * const config_event_type_tracepoint;
-extern const char * const config_event_type_probe;
+LTTNG_EXPORT extern const char * const config_event_type_all;
+LTTNG_EXPORT extern const char * const config_event_type_tracepoint;
+LTTNG_EXPORT extern const char * const config_event_type_probe;
extern const char * const config_event_type_userspace_probe;
-extern const char * const config_event_type_function;
-extern const char * const config_event_type_function_entry;
-extern const char * const config_event_type_noop;
-extern const char * const config_event_type_syscall;
-extern const char * const config_event_type_kprobe;
-extern const char * const config_event_type_kretprobe;
+LTTNG_EXPORT extern const char * const config_event_type_function;
+LTTNG_EXPORT extern const char * const config_event_type_function_entry;
+LTTNG_EXPORT extern const char * const config_event_type_noop;
+LTTNG_EXPORT extern const char * const config_event_type_syscall;
+LTTNG_EXPORT extern const char * const config_event_type_kprobe;
+LTTNG_EXPORT extern const char * const config_event_type_kretprobe;
-extern const char * const config_event_context_pid;
-extern const char * const config_event_context_procname;
-extern const char * const config_event_context_prio;
-extern const char * const config_event_context_nice;
-extern const char * const config_event_context_vpid;
-extern const char * const config_event_context_tid;
-extern const char * const config_event_context_vtid;
-extern const char * const config_event_context_ppid;
-extern const char * const config_event_context_vppid;
-extern const char * const config_event_context_pthread_id;
-extern const char * const config_event_context_hostname;
-extern const char * const config_event_context_ip;
-extern const char * const config_event_context_perf_thread_counter;
+LTTNG_EXPORT extern const char * const config_event_context_pid;
+LTTNG_EXPORT extern const char * const config_event_context_procname;
+LTTNG_EXPORT extern const char * const config_event_context_prio;
+LTTNG_EXPORT extern const char * const config_event_context_nice;
+LTTNG_EXPORT extern const char * const config_event_context_vpid;
+LTTNG_EXPORT extern const char * const config_event_context_tid;
+LTTNG_EXPORT extern const char * const config_event_context_vtid;
+LTTNG_EXPORT extern const char * const config_event_context_ppid;
+LTTNG_EXPORT extern const char * const config_event_context_vppid;
+LTTNG_EXPORT extern const char * const config_event_context_pthread_id;
+LTTNG_EXPORT extern const char * const config_event_context_hostname;
+LTTNG_EXPORT extern const char * const config_event_context_ip;
+LTTNG_EXPORT extern const char * const config_event_context_perf_thread_counter;
extern const char * const config_event_context_app;
extern const char * const config_event_context_interruptible;
extern const char * const config_event_context_preemptible;
};
const char * const config_element_all = "all";
-const char * const config_str_yes = "yes";
-const char * const config_str_true = "true";
-const char * const config_str_on = "on";
-const char * const config_str_no = "no";
-const char * const config_str_false = "false";
-const char * const config_str_off = "off";
-const char * const config_xml_encoding = "UTF-8";
-const size_t config_xml_encoding_bytes_per_char = 2; /* Size of the encoding's largest character */
-const char * const config_xml_indent_string = "\t";
-const char * const config_xml_true = "true";
-const char * const config_xml_false = "false";
+LTTNG_EXPORT const char * const config_str_yes = "yes";
+LTTNG_EXPORT const char * const config_str_true = "true";
+LTTNG_EXPORT const char * const config_str_on = "on";
+LTTNG_EXPORT const char * const config_str_no = "no";
+LTTNG_EXPORT const char * const config_str_false = "false";
+LTTNG_EXPORT const char * const config_str_off = "off";
+LTTNG_EXPORT const char * const config_xml_encoding = "UTF-8";
+LTTNG_EXPORT const size_t config_xml_encoding_bytes_per_char = 2; /* Size of the encoding's largest character */
+LTTNG_EXPORT const char * const config_xml_indent_string = "\t";
+LTTNG_EXPORT const char * const config_xml_true = "true";
+LTTNG_EXPORT const char * const config_xml_false = "false";
const char * const config_element_channel = "channel";
const char * const config_element_channels = "channels";
const char * const config_event_context_vsgid = "VSGID";
/* Deprecated symbols */
-const char * const config_element_perf;
+LTTNG_EXPORT const char * const config_element_perf;
enum process_event_node_phase {
CREATION = 0,
*/
extern int consumer_quit;
-/* Flag used to temporarily pause data consumption from testpoints. */
-extern int data_consumption_paused;
+/*
+ * Flag used to temporarily pause data consumption from testpoints.
+ *
+ * This variable is dlsym-ed from a test, so needs to be exported.
+ */
+LTTNG_EXPORT extern int data_consumption_paused;
/* Return a human-readable consumer type string that is suitable for logging. */
static inline
/* Format: 00:00:00.000000000 plus NULL byte. */
char str[19];
};
-extern DECLARE_URCU_TLS(struct log_time, error_log_time);
+extern LTTNG_EXPORT DECLARE_URCU_TLS(struct log_time, error_log_time);
extern DECLARE_URCU_TLS(const char *, logger_thread_name);
extern int lttng_opt_quiet;
#include <stdio.h>
#include "filter-ast.h"
#include "filter-parser.h"
+#include <lttng/lttng-export.h>
static void yyunput (int c, register char * yy_bp , yyscan_t yyscanner)
__attribute__((unused));
[ \t\n]+ ; /* ignore */
. return ERROR;
%%
+
+/*
+ * The lexer symbols were (e.g. lttng_yy_create_buffer) were mistakenly
+ * exported in the past, so must stay exported. Since it is difficult to tweak
+ * how the lexer functions are emitted, the strategy used here was to use a
+ * different prefix for the symbols (`lttng_filter_`) and define aliases with
+ * the old prefix (`lttng_`).
+ *
+ * The `MAKE_ALIAS` macro defines one such alias.
+ */
+LTTNG_EXPORT
+YY_BUFFER_STATE lttng_yy_create_buffer(FILE *file, int size, yyscan_t yyscanner);
+YY_BUFFER_STATE lttng_yy_create_buffer(FILE *file, int size, yyscan_t yyscanner)
+{
+ return yy_create_buffer(file, size, yyscanner);
+}
+
+LTTNG_EXPORT
+void lttng_yy_delete_buffer(YY_BUFFER_STATE b, yyscan_t yyscanner);
+void lttng_yy_delete_buffer(YY_BUFFER_STATE b, yyscan_t yyscanner)
+{
+ return yy_delete_buffer(b, yyscanner);
+}
+
+LTTNG_EXPORT
+void lttng_yy_flush_buffer (YY_BUFFER_STATE b, yyscan_t yyscanner);
+void lttng_yy_flush_buffer (YY_BUFFER_STATE b, yyscan_t yyscanner)
+{
+ return yy_flush_buffer(b, yyscanner);
+}
+
+LTTNG_EXPORT
+YY_BUFFER_STATE lttng_yy_scan_buffer(char *base, yy_size_t size, yyscan_t yyscanner);
+YY_BUFFER_STATE lttng_yy_scan_buffer(char *base, yy_size_t size, yyscan_t yyscanner)
+{
+ return yy_scan_buffer(base, size, yyscanner);
+}
+
+LTTNG_EXPORT
+YY_BUFFER_STATE lttng_yy_scan_bytes(const char *bytes, int len, yyscan_t yyscanner);
+YY_BUFFER_STATE lttng_yy_scan_bytes(const char *bytes, int len, yyscan_t yyscanner)
+{
+ return yy_scan_bytes(bytes, len, yyscanner);
+}
+
+LTTNG_EXPORT
+YY_BUFFER_STATE lttng_yy_scan_string(const char *yy_str, yyscan_t yyscanner);
+YY_BUFFER_STATE lttng_yy_scan_string(const char *yy_str, yyscan_t yyscanner)
+{
+ return yy_scan_string(yy_str, yyscanner);
+}
+
+LTTNG_EXPORT
+void lttng_yy_switch_to_buffer(YY_BUFFER_STATE new_buffer, yyscan_t yyscanner);
+void lttng_yy_switch_to_buffer(YY_BUFFER_STATE new_buffer, yyscan_t yyscanner)
+{
+ return yy_switch_to_buffer(new_buffer, yyscanner);
+}
+
+LTTNG_EXPORT
+void *lttng_yyalloc(yy_size_t s, yyscan_t yyscanner);
+void *lttng_yyalloc(yy_size_t s, yyscan_t yyscanner)
+{
+ return yyalloc(s, yyscanner);
+}
+
+LTTNG_EXPORT
+void lttng_yyfree(void *p, yyscan_t yyscanner);
+void lttng_yyfree(void *p, yyscan_t yyscanner)
+{
+ return yyfree(p, yyscanner);
+}
+
+LTTNG_EXPORT
+int lttng_yyget_column(yyscan_t yyscanner);
+int lttng_yyget_column(yyscan_t yyscanner)
+{
+ return yyget_column(yyscanner);
+}
+
+LTTNG_EXPORT
+int lttng_yyget_debug(yyscan_t yyscanner);
+int lttng_yyget_debug(yyscan_t yyscanner)
+{
+ return yyget_debug(yyscanner);
+}
+
+LTTNG_EXPORT
+YY_EXTRA_TYPE lttng_yyget_extra(yyscan_t yyscanner);
+YY_EXTRA_TYPE lttng_yyget_extra(yyscan_t yyscanner)
+{
+ return yyget_extra(yyscanner);
+}
+
+LTTNG_EXPORT
+FILE *lttng_yyget_in(yyscan_t yyscanner);
+FILE *lttng_yyget_in(yyscan_t yyscanner)
+{
+ return yyget_in(yyscanner);
+}
+
+LTTNG_EXPORT
+int lttng_yyget_leng(yyscan_t yyscanner);
+int lttng_yyget_leng(yyscan_t yyscanner)
+{
+ return yyget_leng(yyscanner);
+}
+
+LTTNG_EXPORT
+int lttng_yyget_lineno(yyscan_t yyscanner);
+int lttng_yyget_lineno(yyscan_t yyscanner)
+{
+ return yyget_lineno(yyscanner);
+}
+
+LTTNG_EXPORT
+YYSTYPE *lttng_yyget_lval(yyscan_t yyscanner);
+YYSTYPE *lttng_yyget_lval(yyscan_t yyscanner)
+{
+ return yyget_lval(yyscanner);
+}
+
+LTTNG_EXPORT
+FILE *lttng_yyget_out(yyscan_t yyscanner);
+FILE *lttng_yyget_out(yyscan_t yyscanner)
+{
+ return yyget_out(yyscanner);
+}
+
+LTTNG_EXPORT
+char *lttng_yyget_text(yyscan_t yyscanner);
+char *lttng_yyget_text(yyscan_t yyscanner)
+{
+ return yyget_text(yyscanner);
+}
+
+LTTNG_EXPORT
+int lttng_yylex_init(yyscan_t *scanner);
+int lttng_yylex_init(yyscan_t *scanner)
+{
+ return yylex_init(scanner);
+}
+
+LTTNG_EXPORT
+void lttng_yypop_buffer_state(yyscan_t yyscanner);
+void lttng_yypop_buffer_state(yyscan_t yyscanner)
+{
+ return yypop_buffer_state(yyscanner);
+}
+
+LTTNG_EXPORT
+void lttng_yypush_buffer_state(YY_BUFFER_STATE new_buffer, yyscan_t yyscanner);
+void lttng_yypush_buffer_state(YY_BUFFER_STATE new_buffer, yyscan_t yyscanner)
+{
+ return yypush_buffer_state(new_buffer, yyscanner);
+}
+
+LTTNG_EXPORT
+void *lttng_yyrealloc(void *p, yy_size_t s, yyscan_t yyscanner);
+void *lttng_yyrealloc(void *p, yy_size_t s, yyscan_t yyscanner)
+{
+ return yyrealloc(p, s, yyscanner);
+}
+
+LTTNG_EXPORT
+void lttng_yyset_column(int _column_no, yyscan_t yyscanner);
+void lttng_yyset_column(int _column_no, yyscan_t yyscanner)
+{
+ return yyset_column(_column_no, yyscanner);
+}
+
+LTTNG_EXPORT
+void lttng_yyset_debug(int debug_flag, yyscan_t yyscanner);
+void lttng_yyset_debug(int debug_flag, yyscan_t yyscanner)
+{
+ return yyset_debug(debug_flag, yyscanner);
+}
+
+LTTNG_EXPORT
+void lttng_yyset_extra(YY_EXTRA_TYPE user_defined, yyscan_t yyscanner);
+void lttng_yyset_extra(YY_EXTRA_TYPE user_defined, yyscan_t yyscanner)
+{
+ return yyset_extra(user_defined, yyscanner);
+}
+
+LTTNG_EXPORT
+void lttng_yyset_in(FILE *_in_str, yyscan_t yyscanner);
+void lttng_yyset_in(FILE *_in_str, yyscan_t yyscanner)
+{
+ return yyset_in(_in_str, yyscanner);
+}
+
+LTTNG_EXPORT
+void lttng_yyset_lineno(int _line_number, yyscan_t yyscanner);
+void lttng_yyset_lineno(int _line_number, yyscan_t yyscanner)
+{
+ return yyset_lineno(_line_number, yyscanner);
+}
+
+LTTNG_EXPORT
+void lttng_yyset_lval(YYSTYPE *yylval_param, yyscan_t yyscanner);
+void lttng_yyset_lval(YYSTYPE *yylval_param, yyscan_t yyscanner)
+{
+ return yyset_lval(yylval_param, yyscanner);
+}
+
+LTTNG_EXPORT
+void lttng_yyset_out(FILE *_out_str, yyscan_t yyscanner);
+void lttng_yyset_out(FILE *_out_str, yyscan_t yyscanner)
+{
+ return yyset_out(_out_str, yyscanner);
+}
*
*/
-#define yy_create_buffer lttng_yy_create_buffer
-#define yy_delete_buffer lttng_yy_delete_buffer
-#define yy_flush_buffer lttng_yy_flush_buffer
-#define yy_scan_buffer lttng_yy_scan_buffer
-#define yy_scan_bytes lttng_yy_scan_bytes
-#define yy_scan_string lttng_yy_scan_string
-#define yy_switch_to_buffer lttng_yy_switch_to_buffer
-#define yyalloc lttng_yyalloc
-#define yyfree lttng_yyfree
-#define yyget_column lttng_yyget_column
-#define yyget_debug lttng_yyget_debug
-#define yyget_extra lttng_yyget_extra
-#define yyget_in lttng_yyget_in
-#define yyget_leng lttng_yyget_leng
-#define yyget_lineno lttng_yyget_lineno
-#define yyget_lval lttng_yyget_lval
-#define yyget_out lttng_yyget_out
-#define yyget_text lttng_yyget_text
-#define yylex_init lttng_yylex_init
-#define yypop_buffer_state lttng_yypop_buffer_state
-#define yypush_buffer_state lttng_yypush_buffer_state
-#define yyrealloc lttng_yyrealloc
-#define yyset_column lttng_yyset_column
-#define yyset_debug lttng_yyset_debug
-#define yyset_extra lttng_yyset_extra
-#define yyset_in lttng_yyset_in
-#define yyset_lineno lttng_yyset_lineno
-#define yyset_lval lttng_yyset_lval
-#define yyset_out lttng_yyset_out
+#define yy_create_buffer lttng_filter_yy_create_buffer
+#define yy_delete_buffer lttng_filter_yy_delete_buffer
+#define yy_flush_buffer lttng_filter_yy_flush_buffer
+#define yy_scan_buffer lttng_filter_yy_scan_buffer
+#define yy_scan_bytes lttng_filter_yy_scan_bytes
+#define yy_scan_string lttng_filter_yy_scan_string
+#define yy_switch_to_buffer lttng_filter_yy_switch_to_buffer
+#define yyalloc lttng_filter_yyalloc
+#define yyfree lttng_filter_yyfree
+#define yyget_column lttng_filter_yyget_column
+#define yyget_debug lttng_filter_yyget_debug
+#define yyget_extra lttng_filter_yyget_extra
+#define yyget_in lttng_filter_yyget_in
+#define yyget_leng lttng_filter_yyget_leng
+#define yyget_lineno lttng_filter_yyget_lineno
+#define yyget_lval lttng_filter_yyget_lval
+#define yyget_out lttng_filter_yyget_out
+#define yyget_text lttng_filter_yyget_text
+#define yylex_init lttng_filter_yylex_init
+#define yypop_buffer_state lttng_filter_yypop_buffer_state
+#define yypush_buffer_state lttng_filter_yypush_buffer_state
+#define yyrealloc lttng_filter_yyrealloc
+#define yyset_column lttng_filter_yyset_column
+#define yyset_debug lttng_filter_yyset_debug
+#define yyset_extra lttng_filter_yyset_extra
+#define yyset_in lttng_filter_yyset_in
+#define yyset_lineno lttng_filter_yyset_lineno
+#define yyset_lval lttng_filter_yyset_lval
+#define yyset_out lttng_filter_yyset_out
#endif /* _FILTER_SYMBOLS_H */
#include <stdint.h>
#include <common/macros.h>
+#include <lttng/lttng-export.h>
#include <urcu/rculfhash.h>
#ifdef __cplusplus
extern "C" {
#endif
-extern unsigned long lttng_ht_seed;
+LTTNG_EXPORT extern unsigned long lttng_ht_seed;
typedef unsigned long (*hash_fct_type)(const void *_key, unsigned long seed);
typedef cds_lfht_match_fct hash_match_fct;
#define _COMMON_INDEX_ALLOCATOR_H
#include <inttypes.h>
+#include <lttng/lttng-export.h>
#ifdef __cplusplus
extern "C" {
/*
* Create an index allocator of `index_count` slots.
*/
-struct lttng_index_allocator *lttng_index_allocator_create(
+LTTNG_EXPORT struct lttng_index_allocator *lttng_index_allocator_create(
uint64_t index_count);
/*
* Get the number of indexes currently in use.
*/
-uint64_t lttng_index_allocator_get_index_count(
+LTTNG_EXPORT uint64_t lttng_index_allocator_get_index_count(
struct lttng_index_allocator *allocator);
/*
* Allocate (i.e. reserve) a slot.
*/
-enum lttng_index_allocator_status lttng_index_allocator_alloc(
+LTTNG_EXPORT enum lttng_index_allocator_status lttng_index_allocator_alloc(
struct lttng_index_allocator *allocator,
uint64_t *index);
* Release a slot by index. The slot will be re-used by the index allocator
* in future 'alloc' calls.
*/
-enum lttng_index_allocator_status lttng_index_allocator_release(
+LTTNG_EXPORT enum lttng_index_allocator_status lttng_index_allocator_release(
struct lttng_index_allocator *allocator, uint64_t index);
/*
* Destroy an index allocator.
*/
-void lttng_index_allocator_destroy(struct lttng_index_allocator *allocator);
+LTTNG_EXPORT void lttng_index_allocator_destroy(struct lttng_index_allocator *allocator);
#ifdef __cplusplus
}
*
*/
-int lttng_elf_get_symbol_offset(int fd, char *symbol, uint64_t *offset);
+#include <lttng/lttng-export.h>
-int lttng_elf_get_sdt_probe_offsets(int fd, const char *provider_name,
+LTTNG_EXPORT int lttng_elf_get_symbol_offset(int fd, char *symbol, uint64_t *offset);
+
+LTTNG_EXPORT int lttng_elf_get_sdt_probe_offsets(int fd, const char *provider_name,
const char *probe_name, uint64_t **offsets, uint32_t *nb_probe);
#endif /* _LTTNG_ELF_H */
const char * const mi_lttng_element_context_symbol = "symbol";
/* Deprecated symbols preserved for ABI compatibility. */
-const char * const mi_lttng_context_type_perf_counter;
-const char * const mi_lttng_context_type_perf_cpu_counter;
-const char * const mi_lttng_context_type_perf_thread_counter;
-const char * const mi_lttng_element_track_untrack_pid_target;
-const char * const mi_lttng_element_track_untrack_targets;
-const char * const mi_lttng_element_calibrate;
-const char * const mi_lttng_element_calibrate_function;
-const char * const mi_lttng_element_command_calibrate;
+LTTNG_EXPORT const char * const mi_lttng_context_type_perf_counter;
+LTTNG_EXPORT const char * const mi_lttng_context_type_perf_cpu_counter;
+LTTNG_EXPORT const char * const mi_lttng_context_type_perf_thread_counter;
+LTTNG_EXPORT const char * const mi_lttng_element_track_untrack_pid_target;
+LTTNG_EXPORT const char * const mi_lttng_element_track_untrack_targets;
+LTTNG_EXPORT const char * const mi_lttng_element_calibrate;
+LTTNG_EXPORT const char * const mi_lttng_element_calibrate_function;
+LTTNG_EXPORT const char * const mi_lttng_element_command_calibrate;
/* This is a merge of jul loglevel and regular loglevel
* Those should never overlap by definition
};
/* Strings related to command */
-extern const char * const mi_lttng_element_command;
-extern const char * const mi_lttng_element_command_action;
-extern const char * const mi_lttng_element_command_add_context;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_action;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_add_context;
extern const char * const mi_lttng_element_command_add_trigger;
-extern const char * const mi_lttng_element_command_create;
-extern const char * const mi_lttng_element_command_destroy;
-extern const char * const mi_lttng_element_command_disable_channel;
-extern const char * const mi_lttng_element_command_disable_event;
-extern const char * const mi_lttng_element_command_enable_channels;
-extern const char * const mi_lttng_element_command_enable_event;
-extern const char * const mi_lttng_element_command_list;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_create;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_destroy;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_disable_channel;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_disable_event;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_enable_channels;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_enable_event;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_list;
extern const char * const mi_lttng_element_command_list_trigger;
-extern const char * const mi_lttng_element_command_load;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_load;
extern const char * const mi_lttng_element_command_metadata;
extern const char * const mi_lttng_element_command_metadata_action;
extern const char * const mi_lttng_element_command_regenerate;
extern const char * const mi_lttng_element_command_regenerate_action;
-extern const char * const mi_lttng_element_command_name;
-extern const char * const mi_lttng_element_command_output;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_name;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_output;
extern const char * const mi_lttng_element_command_remove_trigger;
-extern const char * const mi_lttng_element_command_save;
-extern const char * const mi_lttng_element_command_set_session;
-extern const char * const mi_lttng_element_command_snapshot;
-extern const char * const mi_lttng_element_command_snapshot_add;
-extern const char * const mi_lttng_element_command_snapshot_del;
-extern const char * const mi_lttng_element_command_snapshot_list;
-extern const char * const mi_lttng_element_command_snapshot_record;
-extern const char * const mi_lttng_element_command_start;
-extern const char * const mi_lttng_element_command_stop;
-extern const char * const mi_lttng_element_command_success;
-extern const char * const mi_lttng_element_command_track;
-extern const char * const mi_lttng_element_command_untrack;
-extern const char * const mi_lttng_element_command_version;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_save;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_set_session;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_snapshot;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_snapshot_add;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_snapshot_del;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_snapshot_list;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_snapshot_record;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_start;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_stop;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_success;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_track;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_untrack;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_version;
extern const char * const mi_lttng_element_command_rotate;
extern const char * const mi_lttng_element_command_enable_rotation;
extern const char * const mi_lttng_element_command_disable_rotation;
extern const char * const mi_lttng_element_command_clear;
/* Strings related to version command */
-extern const char * const mi_lttng_element_version;
-extern const char * const mi_lttng_element_version_commit;
-extern const char * const mi_lttng_element_version_description;
-extern const char * const mi_lttng_element_version_license;
-extern const char * const mi_lttng_element_version_major;
-extern const char * const mi_lttng_element_version_minor;
-extern const char * const mi_lttng_element_version_patch_level;
-extern const char * const mi_lttng_element_version_str;
-extern const char * const mi_lttng_element_version_web;
+LTTNG_EXPORT extern const char * const mi_lttng_element_version;
+LTTNG_EXPORT extern const char * const mi_lttng_element_version_commit;
+LTTNG_EXPORT extern const char * const mi_lttng_element_version_description;
+LTTNG_EXPORT extern const char * const mi_lttng_element_version_license;
+LTTNG_EXPORT extern const char * const mi_lttng_element_version_major;
+LTTNG_EXPORT extern const char * const mi_lttng_element_version_minor;
+LTTNG_EXPORT extern const char * const mi_lttng_element_version_patch_level;
+LTTNG_EXPORT extern const char * const mi_lttng_element_version_str;
+LTTNG_EXPORT extern const char * const mi_lttng_element_version_web;
/* String related to a lttng_event_field */
-extern const char * const mi_lttng_element_event_field;
-extern const char * const mi_lttng_element_event_fields;
+LTTNG_EXPORT extern const char * const mi_lttng_element_event_field;
+LTTNG_EXPORT extern const char * const mi_lttng_element_event_fields;
/* String related to lttng_event_perf_counter_ctx */
-extern const char * const mi_lttng_element_perf_counter_context;
+LTTNG_EXPORT extern const char * const mi_lttng_element_perf_counter_context;
/* Strings related to pid */
-extern const char * const mi_lttng_element_pid_id;
+LTTNG_EXPORT extern const char * const mi_lttng_element_pid_id;
/* Strings related to save command */
-extern const char * const mi_lttng_element_save;
+LTTNG_EXPORT extern const char * const mi_lttng_element_save;
/* Strings related to load command */
-extern const char * const mi_lttng_element_load;
+LTTNG_EXPORT extern const char * const mi_lttng_element_load;
extern const char * const mi_lttng_element_load_overrides;
extern const char * const mi_lttng_element_load_override_url;
/* General element of mi_lttng */
-extern const char * const mi_lttng_element_empty;
-extern const char * const mi_lttng_element_id;
-extern const char * const mi_lttng_element_nowrite;
-extern const char * const mi_lttng_element_success;
-extern const char * const mi_lttng_element_type_enum;
-extern const char * const mi_lttng_element_type_float;
-extern const char * const mi_lttng_element_type_integer;
-extern const char * const mi_lttng_element_type_other;
-extern const char * const mi_lttng_element_type_string;
+LTTNG_EXPORT extern const char * const mi_lttng_element_empty;
+LTTNG_EXPORT extern const char * const mi_lttng_element_id;
+LTTNG_EXPORT extern const char * const mi_lttng_element_nowrite;
+LTTNG_EXPORT extern const char * const mi_lttng_element_success;
+LTTNG_EXPORT extern const char * const mi_lttng_element_type_enum;
+LTTNG_EXPORT extern const char * const mi_lttng_element_type_float;
+LTTNG_EXPORT extern const char * const mi_lttng_element_type_integer;
+LTTNG_EXPORT extern const char * const mi_lttng_element_type_other;
+LTTNG_EXPORT extern const char * const mi_lttng_element_type_string;
/* String related to loglevel */
-extern const char * const mi_lttng_loglevel_str_alert;
-extern const char * const mi_lttng_loglevel_str_crit;
-extern const char * const mi_lttng_loglevel_str_debug;
-extern const char * const mi_lttng_loglevel_str_debug_function;
-extern const char * const mi_lttng_loglevel_str_debug_line;
-extern const char * const mi_lttng_loglevel_str_debug_module;
-extern const char * const mi_lttng_loglevel_str_debug_process;
-extern const char * const mi_lttng_loglevel_str_debug_program;
-extern const char * const mi_lttng_loglevel_str_debug_system;
-extern const char * const mi_lttng_loglevel_str_debug_unit;
-extern const char * const mi_lttng_loglevel_str_emerg;
-extern const char * const mi_lttng_loglevel_str_err;
-extern const char * const mi_lttng_loglevel_str_info;
-extern const char * const mi_lttng_loglevel_str_notice;
-extern const char * const mi_lttng_loglevel_str_unknown;
-extern const char * const mi_lttng_loglevel_str_warning;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_alert;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_crit;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_debug;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_debug_function;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_debug_line;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_debug_module;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_debug_process;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_debug_program;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_debug_system;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_debug_unit;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_emerg;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_err;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_info;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_notice;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_unknown;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_warning;
/* String related to loglevel JUL */
-extern const char * const mi_lttng_loglevel_str_jul_all;
-extern const char * const mi_lttng_loglevel_str_jul_config;
-extern const char * const mi_lttng_loglevel_str_jul_fine;
-extern const char * const mi_lttng_loglevel_str_jul_finer;
-extern const char * const mi_lttng_loglevel_str_jul_finest;
-extern const char * const mi_lttng_loglevel_str_jul_info;
-extern const char * const mi_lttng_loglevel_str_jul_off;
-extern const char * const mi_lttng_loglevel_str_jul_severe;
-extern const char * const mi_lttng_loglevel_str_jul_warning;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_jul_all;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_jul_config;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_jul_fine;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_jul_finer;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_jul_finest;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_jul_info;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_jul_off;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_jul_severe;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_jul_warning;
/* String related to loglevel Log4j */
-extern const char * const mi_lttng_loglevel_str_log4j_off;
-extern const char * const mi_lttng_loglevel_str_log4j_fatal;
-extern const char * const mi_lttng_loglevel_str_log4j_error;
-extern const char * const mi_lttng_loglevel_str_log4j_warn;
-extern const char * const mi_lttng_loglevel_str_log4j_info;
-extern const char * const mi_lttng_loglevel_str_log4j_debug;
-extern const char * const mi_lttng_loglevel_str_log4j_trace;
-extern const char * const mi_lttng_loglevel_str_log4j_all;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_log4j_off;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_log4j_fatal;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_log4j_error;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_log4j_warn;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_log4j_info;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_log4j_debug;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_log4j_trace;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_log4j_all;
/* String related to loglevel Python */
-extern const char * const mi_lttng_loglevel_str_python_critical;
-extern const char * const mi_lttng_loglevel_str_python_error;
-extern const char * const mi_lttng_loglevel_str_python_warning;
-extern const char * const mi_lttng_loglevel_str_python_info;
-extern const char * const mi_lttng_loglevel_str_python_debug;
-extern const char * const mi_lttng_loglevel_str_python_notset;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_python_critical;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_python_error;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_python_warning;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_python_info;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_python_debug;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_python_notset;
/* String related to loglevel type */
-extern const char * const mi_lttng_loglevel_type_all;
-extern const char * const mi_lttng_loglevel_type_range;
-extern const char * const mi_lttng_loglevel_type_single;
-extern const char * const mi_lttng_loglevel_type_unknown;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_type_all;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_type_range;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_type_single;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_type_unknown;
/* String related to a lttng_snapshot */
-extern const char * const mi_lttng_element_snapshot_ctrl_url;
-extern const char * const mi_lttng_element_snapshot_data_url;
-extern const char * const mi_lttng_element_snapshot_max_size;
-extern const char * const mi_lttng_element_snapshot_n_ptr;
-extern const char * const mi_lttng_element_snapshot_session_name;
-extern const char * const mi_lttng_element_snapshots;
+LTTNG_EXPORT extern const char * const mi_lttng_element_snapshot_ctrl_url;
+LTTNG_EXPORT extern const char * const mi_lttng_element_snapshot_data_url;
+LTTNG_EXPORT extern const char * const mi_lttng_element_snapshot_max_size;
+LTTNG_EXPORT extern const char * const mi_lttng_element_snapshot_n_ptr;
+LTTNG_EXPORT extern const char * const mi_lttng_element_snapshot_session_name;
+LTTNG_EXPORT extern const char * const mi_lttng_element_snapshots;
/* String related to track/untrack command */
-extern const char * const mi_lttng_element_track_untrack_all_wildcard;
+LTTNG_EXPORT extern const char * const mi_lttng_element_track_untrack_all_wildcard;
extern const char * const mi_lttng_element_session_name;
* Maximum timeout value in seconds of a TCP connection for both send/recv and
* connect operations.
*/
-extern unsigned long lttcomm_inet_tcp_timeout;
+LTTNG_EXPORT extern unsigned long lttcomm_inet_tcp_timeout;
/* Stub */
struct lttcomm_sock;
*
*/
+#include <lttng/lttng-export.h>
#include <stdbool.h>
#if defined(__cplusplus)
* This symbol was mistakenly made public before the 2.12 release. It can't
* be removed (but it can be stubbed-out if necessary).
*/
-int spawn_viewer(const char *trace_path, char *opt_viewer, bool opt_live_mode);
+LTTNG_EXPORT int spawn_viewer(const char *trace_path, char *opt_viewer, bool opt_live_mode);
#if defined(__cplusplus)
}
extern struct lttng_consumer_global_data the_consumer_data;
extern int consumer_poll_timeout;
-DEFINE_LTTNG_UST_SIGBUS_STATE();
+LTTNG_EXPORT DEFINE_LTTNG_UST_SIGBUS_STATE();
/*
* Free channel object and all streams associated with it. This MUST be used
lib_LTLIBRARIES = liblttng-ctl.la
-liblttng_ctl_la_SOURCES = lttng-ctl.c snapshot.c lttng-ctl-helper.h \
- lttng-ctl-health.c save.c load.c deprecated-symbols.c \
- channel.c rotate.c event.c destruction-handle.c clear.c \
- tracker.c
+liblttng_ctl_la_SOURCES = \
+ channel.cpp \
+ clear.cpp \
+ deprecated-symbols.cpp \
+ destruction-handle.cpp \
+ event.cpp \
+ load.cpp \
+ lttng-ctl.cpp \
+ lttng-ctl-health.cpp \
+ lttng-ctl-helper.h \
+ rotate.cpp \
+ save.cpp \
+ snapshot.cpp \
+ tracker.cpp
liblttng_ctl_la_LDFLAGS = \
$(LT_NO_UNDEFINED) \
+++ /dev/null
-/*
- * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#include <lttng/notification/notification-internal.h>
-#include <lttng/notification/channel-internal.h>
-#include <lttng/condition/condition-internal.h>
-#include <lttng/endpoint.h>
-#include <common/defaults.h>
-#include <common/error.h>
-#include <common/dynamic-buffer.h>
-#include <common/utils.h>
-#include <common/defaults.h>
-#include <common/payload.h>
-#include <common/payload-view.h>
-#include <common/unix.h>
-#include "lttng-ctl-helper.h"
-#include <common/compat/poll.h>
-
-static
-int handshake(struct lttng_notification_channel *channel);
-
-/*
- * Populates the reception buffer with the next complete message.
- * The caller must acquire the channel's lock.
- */
-static
-int receive_message(struct lttng_notification_channel *channel)
-{
- ssize_t ret;
- struct lttng_notification_channel_message msg;
-
- lttng_payload_clear(&channel->reception_payload);
-
- ret = lttcomm_recv_unix_sock(channel->socket, &msg, sizeof(msg));
- if (ret <= 0) {
- ret = -1;
- goto error;
- }
-
- if (msg.size > DEFAULT_MAX_NOTIFICATION_CLIENT_MESSAGE_PAYLOAD_SIZE) {
- ret = -1;
- goto error;
- }
-
- /* Add message header at buffer's start. */
- ret = lttng_dynamic_buffer_append(&channel->reception_payload.buffer, &msg,
- sizeof(msg));
- if (ret) {
- goto error;
- }
-
- /* Reserve space for the payload. */
- ret = lttng_dynamic_buffer_set_size(&channel->reception_payload.buffer,
- channel->reception_payload.buffer.size + msg.size);
- if (ret) {
- goto error;
- }
-
- /* Receive message payload. */
- ret = lttcomm_recv_unix_sock(channel->socket,
- channel->reception_payload.buffer.data + sizeof(msg), msg.size);
- if (ret < (ssize_t) msg.size) {
- ret = -1;
- goto error;
- }
-
- /* Receive message fds. */
- if (msg.fds != 0) {
- ret = lttcomm_recv_payload_fds_unix_sock(channel->socket,
- msg.fds, &channel->reception_payload);
- if (ret < sizeof(int) * msg.fds) {
- ret = -1;
- goto error;
- }
- }
- ret = 0;
-end:
- return ret;
-error:
- lttng_payload_clear(&channel->reception_payload);
- goto end;
-}
-
-static
-enum lttng_notification_channel_message_type get_current_message_type(
- struct lttng_notification_channel *channel)
-{
- struct lttng_notification_channel_message *msg;
-
- LTTNG_ASSERT(channel->reception_payload.buffer.size >= sizeof(*msg));
-
- msg = (struct lttng_notification_channel_message *)
- channel->reception_payload.buffer.data;
- return (enum lttng_notification_channel_message_type) msg->type;
-}
-
-static
-struct lttng_notification *create_notification_from_current_message(
- struct lttng_notification_channel *channel)
-{
- ssize_t ret;
- struct lttng_notification *notification = NULL;
-
- if (channel->reception_payload.buffer.size <=
- sizeof(struct lttng_notification_channel_message)) {
- goto end;
- }
-
- {
- struct lttng_payload_view view = lttng_payload_view_from_payload(
- &channel->reception_payload,
- sizeof(struct lttng_notification_channel_message),
- -1);
-
- ret = lttng_notification_create_from_payload(
- &view, ¬ification);
- }
-
- if (ret != channel->reception_payload.buffer.size -
- sizeof(struct lttng_notification_channel_message)) {
- lttng_notification_destroy(notification);
- notification = NULL;
- goto end;
- }
-end:
- return notification;
-}
-
-struct lttng_notification_channel *lttng_notification_channel_create(
- struct lttng_endpoint *endpoint)
-{
- int fd, ret;
- bool is_in_tracing_group = false, is_root = false;
- char *sock_path = NULL;
- struct lttng_notification_channel *channel = NULL;
-
- if (!endpoint ||
- endpoint != lttng_session_daemon_notification_endpoint) {
- goto end;
- }
-
- sock_path = zmalloc(LTTNG_PATH_MAX);
- if (!sock_path) {
- goto end;
- }
-
- channel = zmalloc(sizeof(struct lttng_notification_channel));
- if (!channel) {
- goto end;
- }
- channel->socket = -1;
- pthread_mutex_init(&channel->lock, NULL);
- lttng_payload_init(&channel->reception_payload);
- CDS_INIT_LIST_HEAD(&channel->pending_notifications.list);
-
- is_root = (getuid() == 0);
- if (!is_root) {
- is_in_tracing_group = lttng_check_tracing_group();
- }
-
- if (is_root || is_in_tracing_group) {
- ret = lttng_strncpy(sock_path,
- DEFAULT_GLOBAL_NOTIFICATION_CHANNEL_UNIX_SOCK,
- LTTNG_PATH_MAX);
- if (ret) {
- ret = -LTTNG_ERR_INVALID;
- goto error;
- }
-
- ret = lttcomm_connect_unix_sock(sock_path);
- if (ret >= 0) {
- fd = ret;
- goto set_fd;
- }
- }
-
- /* Fallback to local session daemon. */
- ret = snprintf(sock_path, LTTNG_PATH_MAX,
- DEFAULT_HOME_NOTIFICATION_CHANNEL_UNIX_SOCK,
- utils_get_home_dir());
- if (ret < 0 || ret >= LTTNG_PATH_MAX) {
- goto error;
- }
-
- ret = lttcomm_connect_unix_sock(sock_path);
- if (ret < 0) {
- goto error;
- }
- fd = ret;
-
-set_fd:
- channel->socket = fd;
-
- ret = handshake(channel);
- if (ret) {
- goto error;
- }
-end:
- free(sock_path);
- return channel;
-error:
- lttng_notification_channel_destroy(channel);
- channel = NULL;
- goto end;
-}
-
-enum lttng_notification_channel_status
-lttng_notification_channel_get_next_notification(
- struct lttng_notification_channel *channel,
- struct lttng_notification **_notification)
-{
- int ret;
- struct lttng_notification *notification = NULL;
- enum lttng_notification_channel_status status =
- LTTNG_NOTIFICATION_CHANNEL_STATUS_OK;
- struct lttng_poll_event events;
-
- if (!channel || !_notification) {
- status = LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID;
- goto end;
- }
-
- pthread_mutex_lock(&channel->lock);
-
- if (channel->pending_notifications.count) {
- struct pending_notification *pending_notification;
-
- LTTNG_ASSERT(!cds_list_empty(&channel->pending_notifications.list));
-
- /* Deliver one of the pending notifications. */
- pending_notification = cds_list_first_entry(
- &channel->pending_notifications.list,
- struct pending_notification,
- node);
- notification = pending_notification->notification;
- if (!notification) {
- status = LTTNG_NOTIFICATION_CHANNEL_STATUS_NOTIFICATIONS_DROPPED;
- }
- cds_list_del(&pending_notification->node);
- channel->pending_notifications.count--;
- free(pending_notification);
- goto end_unlock;
- }
-
- /*
- * Block on interruptible epoll/poll() instead of the message reception
- * itself as the recvmsg() wrappers always restart on EINTR. We choose
- * to wait using interruptible epoll/poll() in order to:
- * 1) Return if a signal occurs,
- * 2) Not deal with partially received messages.
- *
- * The drawback to this approach is that we assume that messages
- * are complete/well formed. If a message is shorter than its
- * announced length, receive_message() will block on recvmsg()
- * and never return (even if a signal is received).
- */
- ret = lttng_poll_create(&events, 1, LTTNG_CLOEXEC);
- if (ret < 0) {
- status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
- goto end_unlock;
- }
- ret = lttng_poll_add(&events, channel->socket, LPOLLIN | LPOLLERR);
- if (ret < 0) {
- status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
- goto end_clean_poll;
- }
- ret = lttng_poll_wait_interruptible(&events, -1);
- if (ret <= 0) {
- status = (ret == -1 && errno == EINTR) ?
- LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED :
- LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
- goto end_clean_poll;
- }
-
- ret = receive_message(channel);
- if (ret) {
- status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
- goto end_clean_poll;
- }
-
- switch (get_current_message_type(channel)) {
- case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_NOTIFICATION:
- notification = create_notification_from_current_message(
- channel);
- if (!notification) {
- status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
- goto end_clean_poll;
- }
- break;
- case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_NOTIFICATION_DROPPED:
- /* No payload to consume. */
- status = LTTNG_NOTIFICATION_CHANNEL_STATUS_NOTIFICATIONS_DROPPED;
- break;
- default:
- /* Protocol error. */
- status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
- goto end_clean_poll;
- }
-
-end_clean_poll:
- lttng_poll_clean(&events);
-end_unlock:
- pthread_mutex_unlock(&channel->lock);
- *_notification = notification;
-end:
- return status;
-}
-
-static
-int enqueue_dropped_notification(
- struct lttng_notification_channel *channel)
-{
- int ret = 0;
- struct pending_notification *pending_notification;
- struct cds_list_head *last_element =
- channel->pending_notifications.list.prev;
-
- pending_notification = caa_container_of(last_element,
- struct pending_notification, node);
- if (!pending_notification->notification) {
- /*
- * The last enqueued notification indicates dropped
- * notifications; there is nothing to do as we group
- * dropped notifications together.
- */
- goto end;
- }
-
- if (channel->pending_notifications.count >=
- DEFAULT_CLIENT_MAX_QUEUED_NOTIFICATIONS_COUNT &&
- pending_notification->notification) {
- /*
- * Discard the last enqueued notification to indicate
- * that notifications were dropped at this point.
- */
- lttng_notification_destroy(
- pending_notification->notification);
- pending_notification->notification = NULL;
- goto end;
- }
-
- pending_notification = zmalloc(sizeof(*pending_notification));
- if (!pending_notification) {
- ret = -1;
- goto end;
- }
- CDS_INIT_LIST_HEAD(&pending_notification->node);
- cds_list_add(&pending_notification->node,
- &channel->pending_notifications.list);
- channel->pending_notifications.count++;
-end:
- return ret;
-}
-
-static
-int enqueue_notification_from_current_message(
- struct lttng_notification_channel *channel)
-{
- int ret = 0;
- struct lttng_notification *notification;
- struct pending_notification *pending_notification;
-
- if (channel->pending_notifications.count >=
- DEFAULT_CLIENT_MAX_QUEUED_NOTIFICATIONS_COUNT) {
- /* Drop the notification. */
- ret = enqueue_dropped_notification(channel);
- goto end;
- }
-
- pending_notification = zmalloc(sizeof(*pending_notification));
- if (!pending_notification) {
- ret = -1;
- goto error;
- }
- CDS_INIT_LIST_HEAD(&pending_notification->node);
-
- notification = create_notification_from_current_message(channel);
- if (!notification) {
- ret = -1;
- goto error;
- }
-
- pending_notification->notification = notification;
- cds_list_add(&pending_notification->node,
- &channel->pending_notifications.list);
- channel->pending_notifications.count++;
-end:
- return ret;
-error:
- free(pending_notification);
- goto end;
-}
-
-enum lttng_notification_channel_status
-lttng_notification_channel_has_pending_notification(
- struct lttng_notification_channel *channel,
- bool *_notification_pending)
-{
- int ret;
- enum lttng_notification_channel_status status =
- LTTNG_NOTIFICATION_CHANNEL_STATUS_OK;
- struct lttng_poll_event events;
-
- if (!channel || !_notification_pending) {
- status = LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID;
- goto end;
- }
-
- pthread_mutex_lock(&channel->lock);
-
- if (channel->pending_notifications.count) {
- *_notification_pending = true;
- goto end_unlock;
- }
-
- if (channel->socket < 0) {
- status = LTTNG_NOTIFICATION_CHANNEL_STATUS_CLOSED;
- goto end_unlock;
- }
-
- /*
- * Check, without blocking, if data is available on the channel's
- * socket. If there is data available, it is safe to read (blocking)
- * on the socket for a message from the session daemon.
- *
- * Since all commands wait for the session daemon's reply before
- * releasing the channel's lock, the protocol only allows for
- * notifications and "notification dropped" messages to come
- * through. If we receive a different message type, it is
- * considered a protocol error.
- *
- * Note that this function is not guaranteed not to block. This
- * will block until our peer (the session daemon) has sent a complete
- * message if we see data available on the socket. If the peer does
- * not respect the protocol, this may block indefinitely.
- */
- ret = lttng_poll_create(&events, 1, LTTNG_CLOEXEC);
- if (ret < 0) {
- status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
- goto end_unlock;
- }
- ret = lttng_poll_add(&events, channel->socket, LPOLLIN | LPOLLERR);
- if (ret < 0) {
- status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
- goto end_clean_poll;
- }
- /* timeout = 0: return immediately. */
- ret = lttng_poll_wait_interruptible(&events, 0);
- if (ret == 0) {
- /* No data available. */
- *_notification_pending = false;
- goto end_clean_poll;
- } else if (ret < 0) {
- status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
- goto end_clean_poll;
- }
-
- /* Data available on socket. */
- ret = receive_message(channel);
- if (ret) {
- status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
- goto end_clean_poll;
- }
-
- switch (get_current_message_type(channel)) {
- case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_NOTIFICATION:
- ret = enqueue_notification_from_current_message(channel);
- if (ret) {
- goto end_clean_poll;
- }
- *_notification_pending = true;
- break;
- case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_NOTIFICATION_DROPPED:
- ret = enqueue_dropped_notification(channel);
- if (ret) {
- goto end_clean_poll;
- }
- *_notification_pending = true;
- break;
- default:
- /* Protocol error. */
- status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
- goto end_clean_poll;
- }
-
-end_clean_poll:
- lttng_poll_clean(&events);
-end_unlock:
- pthread_mutex_unlock(&channel->lock);
-end:
- return status;
-}
-
-static
-int receive_command_reply(struct lttng_notification_channel *channel,
- enum lttng_notification_channel_status *status)
-{
- int ret;
- struct lttng_notification_channel_command_reply *reply;
-
- while (true) {
- enum lttng_notification_channel_message_type msg_type;
-
- ret = receive_message(channel);
- if (ret) {
- goto end;
- }
-
- msg_type = get_current_message_type(channel);
- switch (msg_type) {
- case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_COMMAND_REPLY:
- goto exit_loop;
- case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_NOTIFICATION:
- ret = enqueue_notification_from_current_message(
- channel);
- if (ret) {
- goto end;
- }
- break;
- case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_NOTIFICATION_DROPPED:
- ret = enqueue_dropped_notification(channel);
- if (ret) {
- goto end;
- }
- break;
- case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_HANDSHAKE:
- {
- struct lttng_notification_channel_command_handshake *handshake;
-
- handshake = (struct lttng_notification_channel_command_handshake *)
- (channel->reception_payload.buffer.data +
- sizeof(struct lttng_notification_channel_message));
- channel->version.major = handshake->major;
- channel->version.minor = handshake->minor;
- channel->version.set = true;
- break;
- }
- default:
- ret = -1;
- goto end;
- }
- }
-
-exit_loop:
- if (channel->reception_payload.buffer.size <
- (sizeof(struct lttng_notification_channel_message) +
- sizeof(*reply))) {
- /* Invalid message received. */
- ret = -1;
- goto end;
- }
-
- reply = (struct lttng_notification_channel_command_reply *)
- (channel->reception_payload.buffer.data +
- sizeof(struct lttng_notification_channel_message));
- *status = (enum lttng_notification_channel_status) reply->status;
-end:
- return ret;
-}
-
-static
-int handshake(struct lttng_notification_channel *channel)
-{
- ssize_t ret;
- enum lttng_notification_channel_status status =
- LTTNG_NOTIFICATION_CHANNEL_STATUS_OK;
- struct lttng_notification_channel_command_handshake handshake = {
- .major = LTTNG_NOTIFICATION_CHANNEL_VERSION_MAJOR,
- .minor = LTTNG_NOTIFICATION_CHANNEL_VERSION_MINOR,
- };
- struct lttng_notification_channel_message msg_header = {
- .type = LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_HANDSHAKE,
- .size = sizeof(handshake),
- };
- char send_buffer[sizeof(msg_header) + sizeof(handshake)];
-
- memcpy(send_buffer, &msg_header, sizeof(msg_header));
- memcpy(send_buffer + sizeof(msg_header), &handshake, sizeof(handshake));
-
- pthread_mutex_lock(&channel->lock);
-
- ret = lttcomm_send_creds_unix_sock(channel->socket, send_buffer,
- sizeof(send_buffer));
- if (ret < 0) {
- goto end_unlock;
- }
-
- /* Receive handshake info from the sessiond. */
- ret = receive_command_reply(channel, &status);
- if (ret < 0) {
- goto end_unlock;
- }
-
- if (!channel->version.set) {
- ret = -1;
- goto end_unlock;
- }
-
- if (channel->version.major != LTTNG_NOTIFICATION_CHANNEL_VERSION_MAJOR) {
- ret = -1;
- goto end_unlock;
- }
-
-end_unlock:
- pthread_mutex_unlock(&channel->lock);
- return ret;
-}
-
-static
-enum lttng_notification_channel_status send_condition_command(
- struct lttng_notification_channel *channel,
- enum lttng_notification_channel_message_type type,
- const struct lttng_condition *condition)
-{
- int socket;
- ssize_t ret;
- enum lttng_notification_channel_status status =
- LTTNG_NOTIFICATION_CHANNEL_STATUS_OK;
- struct lttng_payload payload;
- struct lttng_notification_channel_message cmd_header = {
- .type = (int8_t) type,
- };
-
- lttng_payload_init(&payload);
-
- if (!channel) {
- status = LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID;
- goto end;
- }
-
- LTTNG_ASSERT(type == LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_SUBSCRIBE ||
- type == LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_UNSUBSCRIBE);
-
- pthread_mutex_lock(&channel->lock);
- socket = channel->socket;
-
- if (!lttng_condition_validate(condition)) {
- status = LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID;
- goto end_unlock;
- }
-
- ret = lttng_dynamic_buffer_append(&payload.buffer, &cmd_header,
- sizeof(cmd_header));
- if (ret) {
- status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
- goto end_unlock;
- }
-
- ret = lttng_condition_serialize(condition, &payload);
- if (ret) {
- status = LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID;
- goto end_unlock;
- }
-
- /* Update payload length. */
- ((struct lttng_notification_channel_message *) payload.buffer.data)->size =
- (uint32_t) (payload.buffer.size - sizeof(cmd_header));
-
- {
- struct lttng_payload_view pv =
- lttng_payload_view_from_payload(
- &payload, 0, -1);
- const int fd_count =
- lttng_payload_view_get_fd_handle_count(&pv);
-
- /* Update fd count. */
- ((struct lttng_notification_channel_message *) payload.buffer.data)->fds =
- (uint32_t) fd_count;
-
- ret = lttcomm_send_unix_sock(
- socket, pv.buffer.data, pv.buffer.size);
- if (ret < 0) {
- status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
- goto end_unlock;
- }
-
- /* Pass fds if present. */
- if (fd_count > 0) {
- ret = lttcomm_send_payload_view_fds_unix_sock(socket,
- &pv);
- if (ret < 0) {
- status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
- goto end_unlock;
- }
- }
- }
-
- ret = receive_command_reply(channel, &status);
- if (ret < 0) {
- status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
- goto end_unlock;
- }
-end_unlock:
- pthread_mutex_unlock(&channel->lock);
-end:
- lttng_payload_reset(&payload);
- return status;
-}
-
-enum lttng_notification_channel_status lttng_notification_channel_subscribe(
- struct lttng_notification_channel *channel,
- const struct lttng_condition *condition)
-{
- return send_condition_command(channel,
- LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_SUBSCRIBE,
- condition);
-}
-
-enum lttng_notification_channel_status lttng_notification_channel_unsubscribe(
- struct lttng_notification_channel *channel,
- const struct lttng_condition *condition)
-{
- return send_condition_command(channel,
- LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_UNSUBSCRIBE,
- condition);
-}
-
-void lttng_notification_channel_destroy(
- struct lttng_notification_channel *channel)
-{
- if (!channel) {
- return;
- }
-
- if (channel->socket >= 0) {
- (void) lttcomm_close_unix_sock(channel->socket);
- }
- pthread_mutex_destroy(&channel->lock);
- lttng_payload_reset(&channel->reception_payload);
- free(channel);
-}
--- /dev/null
+/*
+ * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#include <lttng/notification/notification-internal.h>
+#include <lttng/notification/channel-internal.h>
+#include <lttng/condition/condition-internal.h>
+#include <lttng/endpoint.h>
+#include <common/defaults.h>
+#include <common/error.h>
+#include <common/dynamic-buffer.h>
+#include <common/utils.h>
+#include <common/defaults.h>
+#include <common/payload.h>
+#include <common/payload-view.h>
+#include <common/unix.h>
+#include "lttng-ctl-helper.h"
+#include <common/compat/poll.h>
+
+static
+int handshake(struct lttng_notification_channel *channel);
+
+/*
+ * Populates the reception buffer with the next complete message.
+ * The caller must acquire the channel's lock.
+ */
+static
+int receive_message(struct lttng_notification_channel *channel)
+{
+ ssize_t ret;
+ struct lttng_notification_channel_message msg;
+
+ lttng_payload_clear(&channel->reception_payload);
+
+ ret = lttcomm_recv_unix_sock(channel->socket, &msg, sizeof(msg));
+ if (ret <= 0) {
+ ret = -1;
+ goto error;
+ }
+
+ if (msg.size > DEFAULT_MAX_NOTIFICATION_CLIENT_MESSAGE_PAYLOAD_SIZE) {
+ ret = -1;
+ goto error;
+ }
+
+ /* Add message header at buffer's start. */
+ ret = lttng_dynamic_buffer_append(&channel->reception_payload.buffer, &msg,
+ sizeof(msg));
+ if (ret) {
+ goto error;
+ }
+
+ /* Reserve space for the payload. */
+ ret = lttng_dynamic_buffer_set_size(&channel->reception_payload.buffer,
+ channel->reception_payload.buffer.size + msg.size);
+ if (ret) {
+ goto error;
+ }
+
+ /* Receive message payload. */
+ ret = lttcomm_recv_unix_sock(channel->socket,
+ channel->reception_payload.buffer.data + sizeof(msg), msg.size);
+ if (ret < (ssize_t) msg.size) {
+ ret = -1;
+ goto error;
+ }
+
+ /* Receive message fds. */
+ if (msg.fds != 0) {
+ ret = lttcomm_recv_payload_fds_unix_sock(channel->socket,
+ msg.fds, &channel->reception_payload);
+ if (ret < sizeof(int) * msg.fds) {
+ ret = -1;
+ goto error;
+ }
+ }
+ ret = 0;
+end:
+ return ret;
+error:
+ lttng_payload_clear(&channel->reception_payload);
+ goto end;
+}
+
+static
+enum lttng_notification_channel_message_type get_current_message_type(
+ struct lttng_notification_channel *channel)
+{
+ struct lttng_notification_channel_message *msg;
+
+ LTTNG_ASSERT(channel->reception_payload.buffer.size >= sizeof(*msg));
+
+ msg = (struct lttng_notification_channel_message *)
+ channel->reception_payload.buffer.data;
+ return (enum lttng_notification_channel_message_type) msg->type;
+}
+
+static
+struct lttng_notification *create_notification_from_current_message(
+ struct lttng_notification_channel *channel)
+{
+ ssize_t ret;
+ struct lttng_notification *notification = NULL;
+
+ if (channel->reception_payload.buffer.size <=
+ sizeof(struct lttng_notification_channel_message)) {
+ goto end;
+ }
+
+ {
+ struct lttng_payload_view view = lttng_payload_view_from_payload(
+ &channel->reception_payload,
+ sizeof(struct lttng_notification_channel_message),
+ -1);
+
+ ret = lttng_notification_create_from_payload(
+ &view, ¬ification);
+ }
+
+ if (ret != channel->reception_payload.buffer.size -
+ sizeof(struct lttng_notification_channel_message)) {
+ lttng_notification_destroy(notification);
+ notification = NULL;
+ goto end;
+ }
+end:
+ return notification;
+}
+
+struct lttng_notification_channel *lttng_notification_channel_create(
+ struct lttng_endpoint *endpoint)
+{
+ int fd, ret;
+ bool is_in_tracing_group = false, is_root = false;
+ char *sock_path = NULL;
+ struct lttng_notification_channel *channel = NULL;
+
+ if (!endpoint ||
+ endpoint != lttng_session_daemon_notification_endpoint) {
+ goto end;
+ }
+
+ sock_path = (char *) zmalloc(LTTNG_PATH_MAX);
+ if (!sock_path) {
+ goto end;
+ }
+
+ channel = (lttng_notification_channel *) zmalloc(sizeof(struct lttng_notification_channel));
+ if (!channel) {
+ goto end;
+ }
+ channel->socket = -1;
+ pthread_mutex_init(&channel->lock, NULL);
+ lttng_payload_init(&channel->reception_payload);
+ CDS_INIT_LIST_HEAD(&channel->pending_notifications.list);
+
+ is_root = (getuid() == 0);
+ if (!is_root) {
+ is_in_tracing_group = lttng_check_tracing_group();
+ }
+
+ if (is_root || is_in_tracing_group) {
+ ret = lttng_strncpy(sock_path,
+ DEFAULT_GLOBAL_NOTIFICATION_CHANNEL_UNIX_SOCK,
+ LTTNG_PATH_MAX);
+ if (ret) {
+ ret = -LTTNG_ERR_INVALID;
+ goto error;
+ }
+
+ ret = lttcomm_connect_unix_sock(sock_path);
+ if (ret >= 0) {
+ fd = ret;
+ goto set_fd;
+ }
+ }
+
+ /* Fallback to local session daemon. */
+ ret = snprintf(sock_path, LTTNG_PATH_MAX,
+ DEFAULT_HOME_NOTIFICATION_CHANNEL_UNIX_SOCK,
+ utils_get_home_dir());
+ if (ret < 0 || ret >= LTTNG_PATH_MAX) {
+ goto error;
+ }
+
+ ret = lttcomm_connect_unix_sock(sock_path);
+ if (ret < 0) {
+ goto error;
+ }
+ fd = ret;
+
+set_fd:
+ channel->socket = fd;
+
+ ret = handshake(channel);
+ if (ret) {
+ goto error;
+ }
+end:
+ free(sock_path);
+ return channel;
+error:
+ lttng_notification_channel_destroy(channel);
+ channel = NULL;
+ goto end;
+}
+
+enum lttng_notification_channel_status
+lttng_notification_channel_get_next_notification(
+ struct lttng_notification_channel *channel,
+ struct lttng_notification **_notification)
+{
+ int ret;
+ struct lttng_notification *notification = NULL;
+ enum lttng_notification_channel_status status =
+ LTTNG_NOTIFICATION_CHANNEL_STATUS_OK;
+ struct lttng_poll_event events;
+
+ if (!channel || !_notification) {
+ status = LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID;
+ goto end;
+ }
+
+ pthread_mutex_lock(&channel->lock);
+
+ if (channel->pending_notifications.count) {
+ struct pending_notification *pending_notification;
+
+ LTTNG_ASSERT(!cds_list_empty(&channel->pending_notifications.list));
+
+ /* Deliver one of the pending notifications. */
+ pending_notification = cds_list_first_entry(
+ &channel->pending_notifications.list,
+ struct pending_notification,
+ node);
+ notification = pending_notification->notification;
+ if (!notification) {
+ status = LTTNG_NOTIFICATION_CHANNEL_STATUS_NOTIFICATIONS_DROPPED;
+ }
+ cds_list_del(&pending_notification->node);
+ channel->pending_notifications.count--;
+ free(pending_notification);
+ goto end_unlock;
+ }
+
+ /*
+ * Block on interruptible epoll/poll() instead of the message reception
+ * itself as the recvmsg() wrappers always restart on EINTR. We choose
+ * to wait using interruptible epoll/poll() in order to:
+ * 1) Return if a signal occurs,
+ * 2) Not deal with partially received messages.
+ *
+ * The drawback to this approach is that we assume that messages
+ * are complete/well formed. If a message is shorter than its
+ * announced length, receive_message() will block on recvmsg()
+ * and never return (even if a signal is received).
+ */
+ ret = lttng_poll_create(&events, 1, LTTNG_CLOEXEC);
+ if (ret < 0) {
+ status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
+ goto end_unlock;
+ }
+ ret = lttng_poll_add(&events, channel->socket, LPOLLIN | LPOLLERR);
+ if (ret < 0) {
+ status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
+ goto end_clean_poll;
+ }
+ ret = lttng_poll_wait_interruptible(&events, -1);
+ if (ret <= 0) {
+ status = (ret == -1 && errno == EINTR) ?
+ LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED :
+ LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
+ goto end_clean_poll;
+ }
+
+ ret = receive_message(channel);
+ if (ret) {
+ status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
+ goto end_clean_poll;
+ }
+
+ switch (get_current_message_type(channel)) {
+ case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_NOTIFICATION:
+ notification = create_notification_from_current_message(
+ channel);
+ if (!notification) {
+ status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
+ goto end_clean_poll;
+ }
+ break;
+ case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_NOTIFICATION_DROPPED:
+ /* No payload to consume. */
+ status = LTTNG_NOTIFICATION_CHANNEL_STATUS_NOTIFICATIONS_DROPPED;
+ break;
+ default:
+ /* Protocol error. */
+ status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
+ goto end_clean_poll;
+ }
+
+end_clean_poll:
+ lttng_poll_clean(&events);
+end_unlock:
+ pthread_mutex_unlock(&channel->lock);
+ *_notification = notification;
+end:
+ return status;
+}
+
+static
+int enqueue_dropped_notification(
+ struct lttng_notification_channel *channel)
+{
+ int ret = 0;
+ struct pending_notification *pending_notification;
+ struct cds_list_head *last_element =
+ channel->pending_notifications.list.prev;
+
+ pending_notification = caa_container_of(last_element,
+ struct pending_notification, node);
+ if (!pending_notification->notification) {
+ /*
+ * The last enqueued notification indicates dropped
+ * notifications; there is nothing to do as we group
+ * dropped notifications together.
+ */
+ goto end;
+ }
+
+ if (channel->pending_notifications.count >=
+ DEFAULT_CLIENT_MAX_QUEUED_NOTIFICATIONS_COUNT &&
+ pending_notification->notification) {
+ /*
+ * Discard the last enqueued notification to indicate
+ * that notifications were dropped at this point.
+ */
+ lttng_notification_destroy(
+ pending_notification->notification);
+ pending_notification->notification = NULL;
+ goto end;
+ }
+
+ pending_notification = (struct pending_notification *) zmalloc(sizeof(*pending_notification));
+ if (!pending_notification) {
+ ret = -1;
+ goto end;
+ }
+ CDS_INIT_LIST_HEAD(&pending_notification->node);
+ cds_list_add(&pending_notification->node,
+ &channel->pending_notifications.list);
+ channel->pending_notifications.count++;
+end:
+ return ret;
+}
+
+static
+int enqueue_notification_from_current_message(
+ struct lttng_notification_channel *channel)
+{
+ int ret = 0;
+ struct lttng_notification *notification;
+ struct pending_notification *pending_notification;
+
+ if (channel->pending_notifications.count >=
+ DEFAULT_CLIENT_MAX_QUEUED_NOTIFICATIONS_COUNT) {
+ /* Drop the notification. */
+ ret = enqueue_dropped_notification(channel);
+ goto end;
+ }
+
+ pending_notification = (struct pending_notification *) zmalloc(sizeof(*pending_notification));
+ if (!pending_notification) {
+ ret = -1;
+ goto error;
+ }
+ CDS_INIT_LIST_HEAD(&pending_notification->node);
+
+ notification = create_notification_from_current_message(channel);
+ if (!notification) {
+ ret = -1;
+ goto error;
+ }
+
+ pending_notification->notification = notification;
+ cds_list_add(&pending_notification->node,
+ &channel->pending_notifications.list);
+ channel->pending_notifications.count++;
+end:
+ return ret;
+error:
+ free(pending_notification);
+ goto end;
+}
+
+enum lttng_notification_channel_status
+lttng_notification_channel_has_pending_notification(
+ struct lttng_notification_channel *channel,
+ bool *_notification_pending)
+{
+ int ret;
+ enum lttng_notification_channel_status status =
+ LTTNG_NOTIFICATION_CHANNEL_STATUS_OK;
+ struct lttng_poll_event events;
+
+ if (!channel || !_notification_pending) {
+ status = LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID;
+ goto end;
+ }
+
+ pthread_mutex_lock(&channel->lock);
+
+ if (channel->pending_notifications.count) {
+ *_notification_pending = true;
+ goto end_unlock;
+ }
+
+ if (channel->socket < 0) {
+ status = LTTNG_NOTIFICATION_CHANNEL_STATUS_CLOSED;
+ goto end_unlock;
+ }
+
+ /*
+ * Check, without blocking, if data is available on the channel's
+ * socket. If there is data available, it is safe to read (blocking)
+ * on the socket for a message from the session daemon.
+ *
+ * Since all commands wait for the session daemon's reply before
+ * releasing the channel's lock, the protocol only allows for
+ * notifications and "notification dropped" messages to come
+ * through. If we receive a different message type, it is
+ * considered a protocol error.
+ *
+ * Note that this function is not guaranteed not to block. This
+ * will block until our peer (the session daemon) has sent a complete
+ * message if we see data available on the socket. If the peer does
+ * not respect the protocol, this may block indefinitely.
+ */
+ ret = lttng_poll_create(&events, 1, LTTNG_CLOEXEC);
+ if (ret < 0) {
+ status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
+ goto end_unlock;
+ }
+ ret = lttng_poll_add(&events, channel->socket, LPOLLIN | LPOLLERR);
+ if (ret < 0) {
+ status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
+ goto end_clean_poll;
+ }
+ /* timeout = 0: return immediately. */
+ ret = lttng_poll_wait_interruptible(&events, 0);
+ if (ret == 0) {
+ /* No data available. */
+ *_notification_pending = false;
+ goto end_clean_poll;
+ } else if (ret < 0) {
+ status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
+ goto end_clean_poll;
+ }
+
+ /* Data available on socket. */
+ ret = receive_message(channel);
+ if (ret) {
+ status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
+ goto end_clean_poll;
+ }
+
+ switch (get_current_message_type(channel)) {
+ case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_NOTIFICATION:
+ ret = enqueue_notification_from_current_message(channel);
+ if (ret) {
+ goto end_clean_poll;
+ }
+ *_notification_pending = true;
+ break;
+ case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_NOTIFICATION_DROPPED:
+ ret = enqueue_dropped_notification(channel);
+ if (ret) {
+ goto end_clean_poll;
+ }
+ *_notification_pending = true;
+ break;
+ default:
+ /* Protocol error. */
+ status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
+ goto end_clean_poll;
+ }
+
+end_clean_poll:
+ lttng_poll_clean(&events);
+end_unlock:
+ pthread_mutex_unlock(&channel->lock);
+end:
+ return status;
+}
+
+static
+int receive_command_reply(struct lttng_notification_channel *channel,
+ enum lttng_notification_channel_status *status)
+{
+ int ret;
+ struct lttng_notification_channel_command_reply *reply;
+
+ while (true) {
+ enum lttng_notification_channel_message_type msg_type;
+
+ ret = receive_message(channel);
+ if (ret) {
+ goto end;
+ }
+
+ msg_type = get_current_message_type(channel);
+ switch (msg_type) {
+ case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_COMMAND_REPLY:
+ goto exit_loop;
+ case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_NOTIFICATION:
+ ret = enqueue_notification_from_current_message(
+ channel);
+ if (ret) {
+ goto end;
+ }
+ break;
+ case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_NOTIFICATION_DROPPED:
+ ret = enqueue_dropped_notification(channel);
+ if (ret) {
+ goto end;
+ }
+ break;
+ case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_HANDSHAKE:
+ {
+ struct lttng_notification_channel_command_handshake *handshake;
+
+ handshake = (struct lttng_notification_channel_command_handshake *)
+ (channel->reception_payload.buffer.data +
+ sizeof(struct lttng_notification_channel_message));
+ channel->version.major = handshake->major;
+ channel->version.minor = handshake->minor;
+ channel->version.set = true;
+ break;
+ }
+ default:
+ ret = -1;
+ goto end;
+ }
+ }
+
+exit_loop:
+ if (channel->reception_payload.buffer.size <
+ (sizeof(struct lttng_notification_channel_message) +
+ sizeof(*reply))) {
+ /* Invalid message received. */
+ ret = -1;
+ goto end;
+ }
+
+ reply = (struct lttng_notification_channel_command_reply *)
+ (channel->reception_payload.buffer.data +
+ sizeof(struct lttng_notification_channel_message));
+ *status = (enum lttng_notification_channel_status) reply->status;
+end:
+ return ret;
+}
+
+static
+int handshake(struct lttng_notification_channel *channel)
+{
+ ssize_t ret;
+ enum lttng_notification_channel_status status =
+ LTTNG_NOTIFICATION_CHANNEL_STATUS_OK;
+ struct lttng_notification_channel_command_handshake handshake = {
+ .major = LTTNG_NOTIFICATION_CHANNEL_VERSION_MAJOR,
+ .minor = LTTNG_NOTIFICATION_CHANNEL_VERSION_MINOR,
+ };
+ struct lttng_notification_channel_message msg_header = {
+ .type = LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_HANDSHAKE,
+ .size = sizeof(handshake),
+ };
+ char send_buffer[sizeof(msg_header) + sizeof(handshake)];
+
+ memcpy(send_buffer, &msg_header, sizeof(msg_header));
+ memcpy(send_buffer + sizeof(msg_header), &handshake, sizeof(handshake));
+
+ pthread_mutex_lock(&channel->lock);
+
+ ret = lttcomm_send_creds_unix_sock(channel->socket, send_buffer,
+ sizeof(send_buffer));
+ if (ret < 0) {
+ goto end_unlock;
+ }
+
+ /* Receive handshake info from the sessiond. */
+ ret = receive_command_reply(channel, &status);
+ if (ret < 0) {
+ goto end_unlock;
+ }
+
+ if (!channel->version.set) {
+ ret = -1;
+ goto end_unlock;
+ }
+
+ if (channel->version.major != LTTNG_NOTIFICATION_CHANNEL_VERSION_MAJOR) {
+ ret = -1;
+ goto end_unlock;
+ }
+
+end_unlock:
+ pthread_mutex_unlock(&channel->lock);
+ return ret;
+}
+
+static
+enum lttng_notification_channel_status send_condition_command(
+ struct lttng_notification_channel *channel,
+ enum lttng_notification_channel_message_type type,
+ const struct lttng_condition *condition)
+{
+ int socket;
+ ssize_t ret;
+ enum lttng_notification_channel_status status =
+ LTTNG_NOTIFICATION_CHANNEL_STATUS_OK;
+ struct lttng_payload payload;
+ struct lttng_notification_channel_message cmd_header = {
+ .type = (int8_t) type,
+ };
+
+ lttng_payload_init(&payload);
+
+ if (!channel) {
+ status = LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID;
+ goto end;
+ }
+
+ LTTNG_ASSERT(type == LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_SUBSCRIBE ||
+ type == LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_UNSUBSCRIBE);
+
+ pthread_mutex_lock(&channel->lock);
+ socket = channel->socket;
+
+ if (!lttng_condition_validate(condition)) {
+ status = LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID;
+ goto end_unlock;
+ }
+
+ ret = lttng_dynamic_buffer_append(&payload.buffer, &cmd_header,
+ sizeof(cmd_header));
+ if (ret) {
+ status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
+ goto end_unlock;
+ }
+
+ ret = lttng_condition_serialize(condition, &payload);
+ if (ret) {
+ status = LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID;
+ goto end_unlock;
+ }
+
+ /* Update payload length. */
+ ((struct lttng_notification_channel_message *) payload.buffer.data)->size =
+ (uint32_t) (payload.buffer.size - sizeof(cmd_header));
+
+ {
+ struct lttng_payload_view pv =
+ lttng_payload_view_from_payload(
+ &payload, 0, -1);
+ const int fd_count =
+ lttng_payload_view_get_fd_handle_count(&pv);
+
+ /* Update fd count. */
+ ((struct lttng_notification_channel_message *) payload.buffer.data)->fds =
+ (uint32_t) fd_count;
+
+ ret = lttcomm_send_unix_sock(
+ socket, pv.buffer.data, pv.buffer.size);
+ if (ret < 0) {
+ status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
+ goto end_unlock;
+ }
+
+ /* Pass fds if present. */
+ if (fd_count > 0) {
+ ret = lttcomm_send_payload_view_fds_unix_sock(socket,
+ &pv);
+ if (ret < 0) {
+ status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
+ goto end_unlock;
+ }
+ }
+ }
+
+ ret = receive_command_reply(channel, &status);
+ if (ret < 0) {
+ status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
+ goto end_unlock;
+ }
+end_unlock:
+ pthread_mutex_unlock(&channel->lock);
+end:
+ lttng_payload_reset(&payload);
+ return status;
+}
+
+enum lttng_notification_channel_status lttng_notification_channel_subscribe(
+ struct lttng_notification_channel *channel,
+ const struct lttng_condition *condition)
+{
+ return send_condition_command(channel,
+ LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_SUBSCRIBE,
+ condition);
+}
+
+enum lttng_notification_channel_status lttng_notification_channel_unsubscribe(
+ struct lttng_notification_channel *channel,
+ const struct lttng_condition *condition)
+{
+ return send_condition_command(channel,
+ LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_UNSUBSCRIBE,
+ condition);
+}
+
+void lttng_notification_channel_destroy(
+ struct lttng_notification_channel *channel)
+{
+ if (!channel) {
+ return;
+ }
+
+ if (channel->socket >= 0) {
+ (void) lttcomm_close_unix_sock(channel->socket);
+ }
+ pthread_mutex_destroy(&channel->lock);
+ lttng_payload_reset(&channel->reception_payload);
+ free(channel);
+}
+++ /dev/null
-/*
- * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- * Copyright (C) 2019 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#define _LGPL_SOURCE
-#include <string.h>
-
-#include <lttng/lttng-error.h>
-#include <lttng/clear.h>
-#include <lttng/clear-handle.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <common/macros.h>
-#include <common/compat/poll.h>
-#include <common/dynamic-buffer.h>
-#include <common/buffer-view.h>
-#include <common/optional.h>
-
-#include "lttng-ctl-helper.h"
-
-enum communication_state {
- COMMUNICATION_STATE_RECEIVE_LTTNG_MSG,
- COMMUNICATION_STATE_RECEIVE_COMMAND_HEADER,
- COMMUNICATION_STATE_END,
- COMMUNICATION_STATE_ERROR,
-};
-
-struct lttng_clear_handle {
- LTTNG_OPTIONAL(enum lttng_error_code) clear_return_code;
- struct {
- int socket;
- struct lttng_poll_event events;
- size_t bytes_left_to_receive;
- enum communication_state state;
- struct lttng_dynamic_buffer buffer;
- LTTNG_OPTIONAL(size_t) data_size;
- } communication;
-};
-
-void lttng_clear_handle_destroy(struct lttng_clear_handle *handle)
-{
- int ret;
-
- if (!handle) {
- return;
- }
-
- if (handle->communication.socket >= 0) {
- ret = close(handle->communication.socket);
- if (ret) {
- PERROR("Failed to close lttng-sessiond command socket");
- }
- }
- lttng_poll_clean(&handle->communication.events);
- lttng_dynamic_buffer_reset(&handle->communication.buffer);
- free(handle);
-}
-
-static
-struct lttng_clear_handle *lttng_clear_handle_create(int sessiond_socket)
-{
- int ret;
- struct lttng_clear_handle *handle = zmalloc(sizeof(*handle));
-
- if (!handle) {
- goto end;
- }
- lttng_dynamic_buffer_init(&handle->communication.buffer);
- handle->communication.socket = sessiond_socket;
- ret = lttng_poll_create(&handle->communication.events, 1, 0);
- if (ret) {
- goto error;
- }
-
- ret = lttng_poll_add(&handle->communication.events, sessiond_socket,
- LPOLLIN | LPOLLHUP | LPOLLRDHUP | LPOLLERR);
- if (ret) {
- goto error;
- }
-
- handle->communication.bytes_left_to_receive =
- sizeof(struct lttcomm_lttng_msg);
- handle->communication.state = COMMUNICATION_STATE_RECEIVE_LTTNG_MSG;
-end:
- return handle;
-error:
- lttng_clear_handle_destroy(handle);
- return NULL;
-}
-
-static
-int handle_state_transition(struct lttng_clear_handle *handle)
-{
- int ret = 0;
-
- LTTNG_ASSERT(handle->communication.bytes_left_to_receive == 0);
-
- switch (handle->communication.state) {
- case COMMUNICATION_STATE_RECEIVE_LTTNG_MSG:
- {
- const struct lttcomm_lttng_msg *msg =
- (typeof(msg)) handle->communication.buffer.data;
-
- LTTNG_OPTIONAL_SET(&handle->clear_return_code,
- (enum lttng_error_code) msg->ret_code);
- if (handle->clear_return_code.value != LTTNG_OK) {
- handle->communication.state = COMMUNICATION_STATE_END;
- break;
- } else if (msg->cmd_header_size != 0 || msg->data_size != 0) {
- handle->communication.state = COMMUNICATION_STATE_ERROR;
- ret = -1;
- break;
- }
-
- handle->communication.state = COMMUNICATION_STATE_END;
- handle->communication.bytes_left_to_receive = 0;
- LTTNG_OPTIONAL_SET(&handle->communication.data_size, 0);
- ret = lttng_dynamic_buffer_set_size(
- &handle->communication.buffer, 0);
- LTTNG_ASSERT(!ret);
- break;
- }
- default:
- abort();
- }
-
- /* Clear reception buffer on state transition. */
- if (lttng_dynamic_buffer_set_size(&handle->communication.buffer, 0)) {
- abort();
- }
- return ret;
-}
-
-static
-int handle_incoming_data(struct lttng_clear_handle *handle)
-{
- int ret;
- ssize_t comm_ret;
- const size_t original_buffer_size = handle->communication.buffer.size;
-
- /* Reserve space for reception. */
- ret = lttng_dynamic_buffer_set_size(&handle->communication.buffer,
- original_buffer_size + handle->communication.bytes_left_to_receive);
- if (ret) {
- goto end;
- }
-
- comm_ret = lttcomm_recv_unix_sock(handle->communication.socket,
- handle->communication.buffer.data + original_buffer_size,
- handle->communication.bytes_left_to_receive);
- if (comm_ret <= 0) {
- ret = -1;
- goto end;
- }
-
- handle->communication.bytes_left_to_receive -= comm_ret;
- if (handle->communication.bytes_left_to_receive == 0) {
- ret = handle_state_transition(handle);
- } else {
- ret = lttng_dynamic_buffer_set_size(
- &handle->communication.buffer,
- original_buffer_size + comm_ret);
- }
-end:
- return ret;
-}
-
-extern enum lttng_clear_handle_status
- lttng_clear_handle_wait_for_completion(
- struct lttng_clear_handle *handle, int timeout_ms)
-{
- enum lttng_clear_handle_status status;
- unsigned long time_left_ms = 0;
- const bool has_timeout = timeout_ms > 0;
- struct timespec initial_time;
-
- if (handle->communication.state == COMMUNICATION_STATE_ERROR) {
- status = LTTNG_CLEAR_HANDLE_STATUS_ERROR;
- goto end;
- } else if (handle->communication.state == COMMUNICATION_STATE_END) {
- status = LTTNG_CLEAR_HANDLE_STATUS_COMPLETED;
- goto end;
- }
- if (has_timeout) {
- int ret = lttng_clock_gettime(CLOCK_MONOTONIC, &initial_time);
- if (ret) {
- status = LTTNG_CLEAR_HANDLE_STATUS_ERROR;
- goto end;
- }
- time_left_ms = (unsigned long) timeout_ms;
- }
-
- while (handle->communication.state != COMMUNICATION_STATE_END &&
- (time_left_ms || !has_timeout)) {
- int ret;
- uint32_t revents;
- struct timespec current_time, diff;
- unsigned long diff_ms;
-
- ret = lttng_poll_wait(&handle->communication.events,
- has_timeout ? time_left_ms : -1);
- if (ret == 0) {
- /* timeout */
- break;
- } else if (ret < 0) {
- status = LTTNG_CLEAR_HANDLE_STATUS_ERROR;
- goto end;
- }
-
- /* The sessiond connection socket is the only monitored fd. */
- revents = LTTNG_POLL_GETEV(&handle->communication.events, 0);
- if (revents & LPOLLIN) {
- ret = handle_incoming_data(handle);
- if (ret) {
- handle->communication.state =
- COMMUNICATION_STATE_ERROR;
- status = LTTNG_CLEAR_HANDLE_STATUS_ERROR;
- goto end;
- }
- } else {
- handle->communication.state = COMMUNICATION_STATE_ERROR;
- status = LTTNG_CLEAR_HANDLE_STATUS_ERROR;
- goto end;
- }
- if (!has_timeout) {
- continue;
- }
-
- ret = lttng_clock_gettime(CLOCK_MONOTONIC, ¤t_time);
- if (ret) {
- status = LTTNG_CLEAR_HANDLE_STATUS_ERROR;
- goto end;
- }
- diff = timespec_abs_diff(initial_time, current_time);
- ret = timespec_to_ms(diff, &diff_ms);
- if (ret) {
- ERR("Failed to compute elapsed time while waiting for completion");
- status = LTTNG_CLEAR_HANDLE_STATUS_ERROR;
- goto end;
- }
- DBG("%lums elapsed while waiting for session clear completion",
- diff_ms);
- diff_ms = max_t(unsigned long, diff_ms, 1);
- diff_ms = min_t(unsigned long, diff_ms, time_left_ms);
- time_left_ms -= diff_ms;
- }
-
- status = handle->communication.state == COMMUNICATION_STATE_END ?
- LTTNG_CLEAR_HANDLE_STATUS_COMPLETED :
- LTTNG_CLEAR_HANDLE_STATUS_TIMEOUT;
-end:
- return status;
-}
-
-extern enum lttng_clear_handle_status
- lttng_clear_handle_get_result(
- const struct lttng_clear_handle *handle,
- enum lttng_error_code *result)
-{
- enum lttng_clear_handle_status status =
- LTTNG_CLEAR_HANDLE_STATUS_OK;
-
- if (!handle->clear_return_code.is_set) {
- status = LTTNG_CLEAR_HANDLE_STATUS_INVALID;
- goto end;
- }
- *result = handle->clear_return_code.value;
-end:
- return status;
-}
-
-/*
- * Clear the session
- */
-enum lttng_error_code lttng_clear_session(const char *session_name,
- struct lttng_clear_handle **_handle)
-{
- enum lttng_error_code ret_code = LTTNG_OK;
- struct lttng_clear_handle *handle = NULL;
- struct lttcomm_session_msg lsm = {
- .cmd_type = LTTNG_CLEAR_SESSION,
- };
- int sessiond_socket = -1;
- ssize_t comm_ret;
- int ret;
-
- if (session_name == NULL) {
- ret_code = LTTNG_ERR_INVALID;
- goto error;
- }
- ret = lttng_strncpy(lsm.session.name, session_name,
- sizeof(lsm.session.name));
- if (ret) {
- ret_code = LTTNG_ERR_INVALID;
- goto error;
- }
- ret = connect_sessiond();
- if (ret < 0) {
- ret_code = LTTNG_ERR_NO_SESSIOND;
- goto error;
- } else {
- sessiond_socket = ret;
- }
- handle = lttng_clear_handle_create(sessiond_socket);
- if (!handle) {
- ret_code = LTTNG_ERR_NOMEM;
- goto error;
- }
- comm_ret = lttcomm_send_creds_unix_sock(sessiond_socket, &lsm, sizeof(lsm));
- if (comm_ret < 0) {
- ret_code = LTTNG_ERR_FATAL;
- goto error;
- }
- sessiond_socket = -1;
-
-error:
- /* Transfer the handle to the caller. */
- if (_handle) {
- *_handle = handle;
- handle = NULL;
- }
- if (sessiond_socket >= 0) {
- ret = close(sessiond_socket);
- if (ret < 0) {
- PERROR("Failed to close the LTTng session daemon connection socket");
- }
- }
- if (handle) {
- lttng_clear_handle_destroy(handle);
- }
- return ret_code;
-}
--- /dev/null
+/*
+ * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ * Copyright (C) 2019 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#define _LGPL_SOURCE
+#include <algorithm>
+#include <string.h>
+
+#include <lttng/lttng-error.h>
+#include <lttng/clear.h>
+#include <lttng/clear-handle.h>
+#include <common/sessiond-comm/sessiond-comm.h>
+#include <common/macros.h>
+#include <common/compat/poll.h>
+#include <common/dynamic-buffer.h>
+#include <common/buffer-view.h>
+#include <common/optional.h>
+
+#include "lttng-ctl-helper.h"
+
+enum communication_state {
+ COMMUNICATION_STATE_RECEIVE_LTTNG_MSG,
+ COMMUNICATION_STATE_RECEIVE_COMMAND_HEADER,
+ COMMUNICATION_STATE_END,
+ COMMUNICATION_STATE_ERROR,
+};
+
+struct lttng_clear_handle {
+ LTTNG_OPTIONAL(enum lttng_error_code) clear_return_code;
+ struct {
+ int socket;
+ struct lttng_poll_event events;
+ size_t bytes_left_to_receive;
+ enum communication_state state;
+ struct lttng_dynamic_buffer buffer;
+ LTTNG_OPTIONAL(size_t) data_size;
+ } communication;
+};
+
+void lttng_clear_handle_destroy(struct lttng_clear_handle *handle)
+{
+ int ret;
+
+ if (!handle) {
+ return;
+ }
+
+ if (handle->communication.socket >= 0) {
+ ret = close(handle->communication.socket);
+ if (ret) {
+ PERROR("Failed to close lttng-sessiond command socket");
+ }
+ }
+ lttng_poll_clean(&handle->communication.events);
+ lttng_dynamic_buffer_reset(&handle->communication.buffer);
+ free(handle);
+}
+
+static
+struct lttng_clear_handle *lttng_clear_handle_create(int sessiond_socket)
+{
+ int ret;
+ struct lttng_clear_handle *handle = (lttng_clear_handle *) zmalloc(sizeof(*handle));
+
+ if (!handle) {
+ goto end;
+ }
+ lttng_dynamic_buffer_init(&handle->communication.buffer);
+ handle->communication.socket = sessiond_socket;
+ ret = lttng_poll_create(&handle->communication.events, 1, 0);
+ if (ret) {
+ goto error;
+ }
+
+ ret = lttng_poll_add(&handle->communication.events, sessiond_socket,
+ LPOLLIN | LPOLLHUP | LPOLLRDHUP | LPOLLERR);
+ if (ret) {
+ goto error;
+ }
+
+ handle->communication.bytes_left_to_receive =
+ sizeof(struct lttcomm_lttng_msg);
+ handle->communication.state = COMMUNICATION_STATE_RECEIVE_LTTNG_MSG;
+end:
+ return handle;
+error:
+ lttng_clear_handle_destroy(handle);
+ return NULL;
+}
+
+static
+int handle_state_transition(struct lttng_clear_handle *handle)
+{
+ int ret = 0;
+
+ LTTNG_ASSERT(handle->communication.bytes_left_to_receive == 0);
+
+ switch (handle->communication.state) {
+ case COMMUNICATION_STATE_RECEIVE_LTTNG_MSG:
+ {
+ const struct lttcomm_lttng_msg *msg =
+ (typeof(msg)) handle->communication.buffer.data;
+
+ LTTNG_OPTIONAL_SET(&handle->clear_return_code,
+ (enum lttng_error_code) msg->ret_code);
+ if (handle->clear_return_code.value != LTTNG_OK) {
+ handle->communication.state = COMMUNICATION_STATE_END;
+ break;
+ } else if (msg->cmd_header_size != 0 || msg->data_size != 0) {
+ handle->communication.state = COMMUNICATION_STATE_ERROR;
+ ret = -1;
+ break;
+ }
+
+ handle->communication.state = COMMUNICATION_STATE_END;
+ handle->communication.bytes_left_to_receive = 0;
+ LTTNG_OPTIONAL_SET(&handle->communication.data_size, 0);
+ ret = lttng_dynamic_buffer_set_size(
+ &handle->communication.buffer, 0);
+ LTTNG_ASSERT(!ret);
+ break;
+ }
+ default:
+ abort();
+ }
+
+ /* Clear reception buffer on state transition. */
+ if (lttng_dynamic_buffer_set_size(&handle->communication.buffer, 0)) {
+ abort();
+ }
+ return ret;
+}
+
+static
+int handle_incoming_data(struct lttng_clear_handle *handle)
+{
+ int ret;
+ ssize_t comm_ret;
+ const size_t original_buffer_size = handle->communication.buffer.size;
+
+ /* Reserve space for reception. */
+ ret = lttng_dynamic_buffer_set_size(&handle->communication.buffer,
+ original_buffer_size + handle->communication.bytes_left_to_receive);
+ if (ret) {
+ goto end;
+ }
+
+ comm_ret = lttcomm_recv_unix_sock(handle->communication.socket,
+ handle->communication.buffer.data + original_buffer_size,
+ handle->communication.bytes_left_to_receive);
+ if (comm_ret <= 0) {
+ ret = -1;
+ goto end;
+ }
+
+ handle->communication.bytes_left_to_receive -= comm_ret;
+ if (handle->communication.bytes_left_to_receive == 0) {
+ ret = handle_state_transition(handle);
+ } else {
+ ret = lttng_dynamic_buffer_set_size(
+ &handle->communication.buffer,
+ original_buffer_size + comm_ret);
+ }
+end:
+ return ret;
+}
+
+extern enum lttng_clear_handle_status
+ lttng_clear_handle_wait_for_completion(
+ struct lttng_clear_handle *handle, int timeout_ms)
+{
+ enum lttng_clear_handle_status status;
+ unsigned long time_left_ms = 0;
+ const bool has_timeout = timeout_ms > 0;
+ struct timespec initial_time;
+
+ if (handle->communication.state == COMMUNICATION_STATE_ERROR) {
+ status = LTTNG_CLEAR_HANDLE_STATUS_ERROR;
+ goto end;
+ } else if (handle->communication.state == COMMUNICATION_STATE_END) {
+ status = LTTNG_CLEAR_HANDLE_STATUS_COMPLETED;
+ goto end;
+ }
+ if (has_timeout) {
+ int ret = lttng_clock_gettime(CLOCK_MONOTONIC, &initial_time);
+ if (ret) {
+ status = LTTNG_CLEAR_HANDLE_STATUS_ERROR;
+ goto end;
+ }
+ time_left_ms = (unsigned long) timeout_ms;
+ }
+
+ while (handle->communication.state != COMMUNICATION_STATE_END &&
+ (time_left_ms || !has_timeout)) {
+ int ret;
+ uint32_t revents;
+ struct timespec current_time, diff;
+ unsigned long diff_ms;
+
+ ret = lttng_poll_wait(&handle->communication.events,
+ has_timeout ? time_left_ms : -1);
+ if (ret == 0) {
+ /* timeout */
+ break;
+ } else if (ret < 0) {
+ status = LTTNG_CLEAR_HANDLE_STATUS_ERROR;
+ goto end;
+ }
+
+ /* The sessiond connection socket is the only monitored fd. */
+ revents = LTTNG_POLL_GETEV(&handle->communication.events, 0);
+ if (revents & LPOLLIN) {
+ ret = handle_incoming_data(handle);
+ if (ret) {
+ handle->communication.state =
+ COMMUNICATION_STATE_ERROR;
+ status = LTTNG_CLEAR_HANDLE_STATUS_ERROR;
+ goto end;
+ }
+ } else {
+ handle->communication.state = COMMUNICATION_STATE_ERROR;
+ status = LTTNG_CLEAR_HANDLE_STATUS_ERROR;
+ goto end;
+ }
+ if (!has_timeout) {
+ continue;
+ }
+
+ ret = lttng_clock_gettime(CLOCK_MONOTONIC, ¤t_time);
+ if (ret) {
+ status = LTTNG_CLEAR_HANDLE_STATUS_ERROR;
+ goto end;
+ }
+ diff = timespec_abs_diff(initial_time, current_time);
+ ret = timespec_to_ms(diff, &diff_ms);
+ if (ret) {
+ ERR("Failed to compute elapsed time while waiting for completion");
+ status = LTTNG_CLEAR_HANDLE_STATUS_ERROR;
+ goto end;
+ }
+ DBG("%lums elapsed while waiting for session clear completion",
+ diff_ms);
+ diff_ms = std::max(diff_ms, 1UL);
+ diff_ms = std::min(diff_ms, time_left_ms);
+ time_left_ms -= diff_ms;
+ }
+
+ status = handle->communication.state == COMMUNICATION_STATE_END ?
+ LTTNG_CLEAR_HANDLE_STATUS_COMPLETED :
+ LTTNG_CLEAR_HANDLE_STATUS_TIMEOUT;
+end:
+ return status;
+}
+
+extern enum lttng_clear_handle_status
+ lttng_clear_handle_get_result(
+ const struct lttng_clear_handle *handle,
+ enum lttng_error_code *result)
+{
+ enum lttng_clear_handle_status status =
+ LTTNG_CLEAR_HANDLE_STATUS_OK;
+
+ if (!handle->clear_return_code.is_set) {
+ status = LTTNG_CLEAR_HANDLE_STATUS_INVALID;
+ goto end;
+ }
+ *result = handle->clear_return_code.value;
+end:
+ return status;
+}
+
+/*
+ * Clear the session
+ */
+enum lttng_error_code lttng_clear_session(const char *session_name,
+ struct lttng_clear_handle **_handle)
+{
+ enum lttng_error_code ret_code = LTTNG_OK;
+ struct lttng_clear_handle *handle = NULL;
+ struct lttcomm_session_msg lsm = {
+ .cmd_type = LTTNG_CLEAR_SESSION,
+ };
+ int sessiond_socket = -1;
+ ssize_t comm_ret;
+ int ret;
+
+ if (session_name == NULL) {
+ ret_code = LTTNG_ERR_INVALID;
+ goto error;
+ }
+ ret = lttng_strncpy(lsm.session.name, session_name,
+ sizeof(lsm.session.name));
+ if (ret) {
+ ret_code = LTTNG_ERR_INVALID;
+ goto error;
+ }
+ ret = connect_sessiond();
+ if (ret < 0) {
+ ret_code = LTTNG_ERR_NO_SESSIOND;
+ goto error;
+ } else {
+ sessiond_socket = ret;
+ }
+ handle = lttng_clear_handle_create(sessiond_socket);
+ if (!handle) {
+ ret_code = LTTNG_ERR_NOMEM;
+ goto error;
+ }
+ comm_ret = lttcomm_send_creds_unix_sock(sessiond_socket, &lsm, sizeof(lsm));
+ if (comm_ret < 0) {
+ ret_code = LTTNG_ERR_FATAL;
+ goto error;
+ }
+ sessiond_socket = -1;
+
+error:
+ /* Transfer the handle to the caller. */
+ if (_handle) {
+ *_handle = handle;
+ handle = NULL;
+ }
+ if (sessiond_socket >= 0) {
+ ret = close(sessiond_socket);
+ if (ret < 0) {
+ PERROR("Failed to close the LTTng session daemon connection socket");
+ }
+ }
+ if (handle) {
+ lttng_clear_handle_destroy(handle);
+ }
+ return ret_code;
+}
+++ /dev/null
-/*
- * Copyright (C) 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#include <stddef.h>
-
-/*
- * These are symbols that were erroneously exposed and have since been removed.
- */
-
-size_t default_channel_subbuf_size;
-size_t default_kernel_channel_subbuf_size;
-size_t default_metadata_subbuf_size;
-size_t default_ust_pid_channel_subbuf_size;
-size_t default_ust_uid_channel_subbuf_size;
-
-const char * const config_element_pid_tracker;
-const char * const config_element_target_pid;
-const char * const config_element_targets;
-const char * const config_element_trackers;
--- /dev/null
+/*
+ * Copyright (C) 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#include <lttng/lttng-export.h>
+#include <stddef.h>
+
+/*
+ * These are symbols that were erroneously exposed and have since been removed.
+ */
+
+LTTNG_EXPORT size_t default_channel_subbuf_size;
+LTTNG_EXPORT size_t default_kernel_channel_subbuf_size;
+LTTNG_EXPORT size_t default_metadata_subbuf_size;
+LTTNG_EXPORT size_t default_ust_pid_channel_subbuf_size;
+LTTNG_EXPORT size_t default_ust_uid_channel_subbuf_size;
+
+LTTNG_EXPORT const char *config_element_pid_tracker = nullptr;
+LTTNG_EXPORT const char *config_element_target_pid = nullptr;
+LTTNG_EXPORT const char *config_element_targets = nullptr;
+LTTNG_EXPORT const char *config_element_trackers = nullptr;
+++ /dev/null
-/*
- * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#include <lttng/destruction-handle.h>
-#include <lttng/rotation.h>
-
-#include <common/optional.h>
-#include <common/compat/poll.h>
-#include <common/compat/time.h>
-#include <common/macros.h>
-#include <common/compat/poll.h>
-#include <common/dynamic-buffer.h>
-#include <common/buffer-view.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <lttng/location-internal.h>
-#include "lttng-ctl-helper.h"
-
-#include <stdbool.h>
-
-enum communication_state {
- COMMUNICATION_STATE_RECEIVE_LTTNG_MSG,
- COMMUNICATION_STATE_RECEIVE_COMMAND_HEADER,
- COMMUNICATION_STATE_RECEIVE_PAYLOAD,
- COMMUNICATION_STATE_END,
- COMMUNICATION_STATE_ERROR,
-};
-
-struct lttng_destruction_handle {
- LTTNG_OPTIONAL(enum lttng_error_code) destruction_return_code;
- LTTNG_OPTIONAL(enum lttng_rotation_state) rotation_state;
- struct lttng_trace_archive_location *location;
- struct {
- int socket;
- struct lttng_poll_event events;
- size_t bytes_left_to_receive;
- enum communication_state state;
- struct lttng_dynamic_buffer buffer;
- LTTNG_OPTIONAL(size_t) data_size;
- } communication;
-};
-
-void lttng_destruction_handle_destroy(struct lttng_destruction_handle *handle)
-{
- int ret;
-
- if (!handle) {
- return;
- }
-
- if (handle->communication.socket >= 0) {
- ret = close(handle->communication.socket);
- if (ret) {
- PERROR("Failed to close lttng-sessiond command socket");
- }
- }
- lttng_poll_clean(&handle->communication.events);
- lttng_dynamic_buffer_reset(&handle->communication.buffer);
- lttng_trace_archive_location_put(handle->location);
- free(handle);
-}
-
-static
-struct lttng_destruction_handle *lttng_destruction_handle_create(
- int sessiond_socket)
-{
- int ret;
- struct lttng_destruction_handle *handle = zmalloc(sizeof(*handle));
-
- if (!handle) {
- goto end;
- }
- lttng_dynamic_buffer_init(&handle->communication.buffer);
- handle->communication.socket = sessiond_socket;
- ret = lttng_poll_create(&handle->communication.events, 1, 0);
- if (ret) {
- goto error;
- }
-
- ret = lttng_poll_add(&handle->communication.events, sessiond_socket,
- LPOLLIN | LPOLLHUP | LPOLLRDHUP | LPOLLERR);
- if (ret) {
- goto error;
- }
-
- handle->communication.bytes_left_to_receive =
- sizeof(struct lttcomm_lttng_msg);
- handle->communication.state = COMMUNICATION_STATE_RECEIVE_LTTNG_MSG;
-end:
- return handle;
-error:
- lttng_destruction_handle_destroy(handle);
- return NULL;
-}
-
-static
-int handle_state_transition(struct lttng_destruction_handle *handle)
-{
- int ret = 0;
-
- LTTNG_ASSERT(handle->communication.bytes_left_to_receive == 0);
-
- switch (handle->communication.state) {
- case COMMUNICATION_STATE_RECEIVE_LTTNG_MSG:
- {
- const struct lttcomm_lttng_msg *msg =
- (typeof(msg)) handle->communication.buffer.data;
-
- LTTNG_OPTIONAL_SET(&handle->destruction_return_code,
- (enum lttng_error_code) msg->ret_code);
- if (handle->destruction_return_code.value != LTTNG_OK) {
- handle->communication.state = COMMUNICATION_STATE_END;
- break;
- } else if (msg->cmd_header_size != sizeof(struct lttcomm_session_destroy_command_header) ||
- msg->data_size > DEFAULT_MAX_TRACE_ARCHIVE_LOCATION_PAYLOAD_SIZE) {
- handle->communication.state = COMMUNICATION_STATE_ERROR;
- ret = -1;
- break;
- }
-
- handle->communication.state =
- COMMUNICATION_STATE_RECEIVE_COMMAND_HEADER;
- handle->communication.bytes_left_to_receive =
- msg->cmd_header_size;
- LTTNG_OPTIONAL_SET(&handle->communication.data_size,
- msg->data_size);
- ret = lttng_dynamic_buffer_set_size(
- &handle->communication.buffer, 0);
- LTTNG_ASSERT(!ret);
- break;
- }
- case COMMUNICATION_STATE_RECEIVE_COMMAND_HEADER:
- {
- const struct lttcomm_session_destroy_command_header *hdr =
- (typeof(hdr)) handle->communication.buffer.data;
-
- LTTNG_OPTIONAL_SET(&handle->rotation_state,
- (enum lttng_rotation_state) hdr->rotation_state);
- switch (handle->rotation_state.value) {
- case LTTNG_ROTATION_STATE_COMPLETED:
- handle->communication.state =
- COMMUNICATION_STATE_RECEIVE_PAYLOAD;
- handle->communication.bytes_left_to_receive =
- LTTNG_OPTIONAL_GET(handle->communication.data_size);
- break;
- case LTTNG_ROTATION_STATE_ERROR:
- case LTTNG_ROTATION_STATE_NO_ROTATION:
- handle->communication.state = COMMUNICATION_STATE_END;
- break;
- default:
- handle->communication.state = COMMUNICATION_STATE_ERROR;
- ret = -1;
- break;
- }
- break;
- }
- case COMMUNICATION_STATE_RECEIVE_PAYLOAD:
- {
- ssize_t location_ret;
- struct lttng_trace_archive_location *location;
- const struct lttng_buffer_view view =
- lttng_buffer_view_from_dynamic_buffer(
- &handle->communication.buffer, 0, -1);
-
- location_ret = lttng_trace_archive_location_create_from_buffer(
- &view, &location);
- if (location_ret < 0) {
- ERR("Failed to deserialize trace archive location");
- handle->communication.state = COMMUNICATION_STATE_ERROR;
- ret = -1;
- break;
- } else {
- /* Ownership is transferred to the destruction handle. */
- handle->location = location;
- handle->communication.state = COMMUNICATION_STATE_END;
- }
- break;
- }
- default:
- abort();
- }
-
- /* Clear reception buffer on state transition. */
- if (lttng_dynamic_buffer_set_size(&handle->communication.buffer, 0)) {
- abort();
- }
- return ret;
-}
-
-static
-int handle_incoming_data(struct lttng_destruction_handle *handle)
-{
- int ret;
- ssize_t comm_ret;
- const size_t original_buffer_size = handle->communication.buffer.size;
-
- /* Reserve space for reception. */
- ret = lttng_dynamic_buffer_set_size(&handle->communication.buffer,
- original_buffer_size + handle->communication.bytes_left_to_receive);
- if (ret) {
- goto end;
- }
-
- comm_ret = lttcomm_recv_unix_sock(handle->communication.socket,
- handle->communication.buffer.data + original_buffer_size,
- handle->communication.bytes_left_to_receive);
- if (comm_ret <= 0) {
- ret = -1;
- goto end;
- }
-
- handle->communication.bytes_left_to_receive -= comm_ret;
- if (handle->communication.bytes_left_to_receive == 0) {
- ret = handle_state_transition(handle);
- } else {
- ret = lttng_dynamic_buffer_set_size(
- &handle->communication.buffer,
- original_buffer_size + comm_ret);
- }
-end:
- return ret;
-}
-
-enum lttng_destruction_handle_status
-lttng_destruction_handle_wait_for_completion(
- struct lttng_destruction_handle *handle, int timeout_ms)
-{
- enum lttng_destruction_handle_status status;
- unsigned long time_left_ms = 0;
- const bool has_timeout = timeout_ms > 0;
- struct timespec initial_time;
-
- if (!handle) {
- status = LTTNG_DESTRUCTION_HANDLE_STATUS_INVALID;
- goto end;
- }
-
- if (handle->communication.state == COMMUNICATION_STATE_ERROR) {
- status = LTTNG_DESTRUCTION_HANDLE_STATUS_ERROR;
- goto end;
- } else if (handle->communication.state == COMMUNICATION_STATE_END) {
- status = LTTNG_DESTRUCTION_HANDLE_STATUS_COMPLETED;
- goto end;
- }
- if (has_timeout) {
- int ret = lttng_clock_gettime(CLOCK_MONOTONIC, &initial_time);
- if (ret) {
- status = LTTNG_DESTRUCTION_HANDLE_STATUS_ERROR;
- goto end;
- }
- time_left_ms = (unsigned long) timeout_ms;
- }
-
- while (handle->communication.state != COMMUNICATION_STATE_END &&
- (time_left_ms || !has_timeout)) {
- int ret;
- uint32_t revents;
- struct timespec current_time, diff;
- unsigned long diff_ms;
-
- ret = lttng_poll_wait(&handle->communication.events,
- has_timeout ? time_left_ms : -1);
- if (ret == 0) {
- /* timeout */
- break;
- } else if (ret < 0) {
- status = LTTNG_DESTRUCTION_HANDLE_STATUS_ERROR;
- goto end;
- }
-
- /* The sessiond connection socket is the only monitored fd. */
- revents = LTTNG_POLL_GETEV(&handle->communication.events, 0);
- if (revents & LPOLLIN) {
- ret = handle_incoming_data(handle);
- if (ret) {
- handle->communication.state =
- COMMUNICATION_STATE_ERROR;
- status = LTTNG_DESTRUCTION_HANDLE_STATUS_ERROR;
- goto end;
- }
- } else {
- handle->communication.state = COMMUNICATION_STATE_ERROR;
- status = LTTNG_DESTRUCTION_HANDLE_STATUS_ERROR;
- goto end;
- }
- if (!has_timeout) {
- continue;
- }
-
- ret = lttng_clock_gettime(CLOCK_MONOTONIC, ¤t_time);
- if (ret) {
- status = LTTNG_DESTRUCTION_HANDLE_STATUS_ERROR;
- goto end;
- }
- diff = timespec_abs_diff(initial_time, current_time);
- ret = timespec_to_ms(diff, &diff_ms);
- if (ret) {
- ERR("Failed to compute elapsed time while waiting for completion");
- status = LTTNG_DESTRUCTION_HANDLE_STATUS_ERROR;
- goto end;
- }
- DBG("%lums elapsed while waiting for session destruction completion",
- diff_ms);
- diff_ms = max_t(unsigned long, diff_ms, 1);
- diff_ms = min_t(unsigned long, diff_ms, time_left_ms);
- time_left_ms -= diff_ms;
- }
-
- status = handle->communication.state == COMMUNICATION_STATE_END ?
- LTTNG_DESTRUCTION_HANDLE_STATUS_COMPLETED :
- LTTNG_DESTRUCTION_HANDLE_STATUS_TIMEOUT;
-end:
- return status;
-}
-
-enum lttng_destruction_handle_status
-lttng_destruction_handle_get_rotation_state(
- const struct lttng_destruction_handle *handle,
- enum lttng_rotation_state *rotation_state)
-{
- enum lttng_destruction_handle_status status =
- LTTNG_DESTRUCTION_HANDLE_STATUS_OK;
-
- if (!handle || !rotation_state) {
- status = LTTNG_DESTRUCTION_HANDLE_STATUS_INVALID;
- goto end;
- }
-
- if (!handle->rotation_state.is_set) {
- status = LTTNG_DESTRUCTION_HANDLE_STATUS_INVALID;
- goto end;
- }
- *rotation_state = handle->rotation_state.value;
-end:
- return status;
-}
-
-enum lttng_destruction_handle_status
-lttng_destruction_handle_get_archive_location(
- const struct lttng_destruction_handle *handle,
- const struct lttng_trace_archive_location **location)
-{
- enum lttng_destruction_handle_status status =
- LTTNG_DESTRUCTION_HANDLE_STATUS_OK;
-
- if (!handle || !location) {
- status = LTTNG_DESTRUCTION_HANDLE_STATUS_INVALID;
- goto end;
- }
-
- if (!handle->location) {
- status = LTTNG_DESTRUCTION_HANDLE_STATUS_INVALID;
- goto end;
- }
- *location = handle->location;
-end:
- return status;
-}
-
-enum lttng_destruction_handle_status
-lttng_destruction_handle_get_result(
- const struct lttng_destruction_handle *handle,
- enum lttng_error_code *result)
-{
- enum lttng_destruction_handle_status status =
- LTTNG_DESTRUCTION_HANDLE_STATUS_OK;
-
- if (!handle || !result) {
- status = LTTNG_DESTRUCTION_HANDLE_STATUS_INVALID;
- goto end;
- }
-
- if (!handle->destruction_return_code.is_set) {
- status = LTTNG_DESTRUCTION_HANDLE_STATUS_INVALID;
- goto end;
- }
- *result = handle->destruction_return_code.value;
-end:
- return status;
-}
-
-enum lttng_error_code lttng_destroy_session_ext(const char *session_name,
- struct lttng_destruction_handle **_handle)
-{
- int ret;
- ssize_t comm_ret;
- enum lttng_error_code ret_code = LTTNG_OK;
- struct lttcomm_session_msg lsm = {
- .cmd_type = LTTNG_DESTROY_SESSION,
- };
- int sessiond_socket = -1;
- struct lttng_destruction_handle *handle = NULL;
-
- if (!session_name) {
- ret_code = LTTNG_ERR_INVALID;
- goto error;
- }
-
- ret = lttng_strncpy(lsm.session.name, session_name,
- sizeof(lsm.session.name));
- if (ret) {
- ret_code = LTTNG_ERR_INVALID;
- goto error;
- }
-
- ret = connect_sessiond();
- if (ret < 0) {
- ret_code = LTTNG_ERR_NO_SESSIOND;
- goto error;
- } else {
- sessiond_socket = ret;
- }
-
- handle = lttng_destruction_handle_create(sessiond_socket);
- if (!handle) {
- ret_code = LTTNG_ERR_NOMEM;
- goto error;
- }
-
- comm_ret = lttcomm_send_creds_unix_sock(sessiond_socket, &lsm, sizeof(lsm));
- if (comm_ret < 0) {
- ret_code = LTTNG_ERR_FATAL;
- goto error;
- }
- sessiond_socket = -1;
-
- /* Transfer the handle to the caller. */
- if (_handle) {
- *_handle = handle;
- handle = NULL;
- }
-error:
- if (sessiond_socket >= 0) {
- ret = close(sessiond_socket);
- if (ret < 0) {
- PERROR("Failed to close the LTTng session daemon connection socket");
- }
- }
- if (handle) {
- lttng_destruction_handle_destroy(handle);
- }
- return ret_code;
-}
--- /dev/null
+/*
+ * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#include <lttng/destruction-handle.h>
+#include <lttng/rotation.h>
+
+#include <common/optional.h>
+#include <common/compat/poll.h>
+#include <common/compat/time.h>
+#include <common/macros.h>
+#include <common/compat/poll.h>
+#include <common/dynamic-buffer.h>
+#include <common/buffer-view.h>
+#include <common/sessiond-comm/sessiond-comm.h>
+#include <lttng/location-internal.h>
+#include "lttng-ctl-helper.h"
+
+#include <algorithm>
+#include <stdbool.h>
+
+enum communication_state {
+ COMMUNICATION_STATE_RECEIVE_LTTNG_MSG,
+ COMMUNICATION_STATE_RECEIVE_COMMAND_HEADER,
+ COMMUNICATION_STATE_RECEIVE_PAYLOAD,
+ COMMUNICATION_STATE_END,
+ COMMUNICATION_STATE_ERROR,
+};
+
+struct lttng_destruction_handle {
+ LTTNG_OPTIONAL(enum lttng_error_code) destruction_return_code;
+ LTTNG_OPTIONAL(enum lttng_rotation_state) rotation_state;
+ struct lttng_trace_archive_location *location;
+ struct {
+ int socket;
+ struct lttng_poll_event events;
+ size_t bytes_left_to_receive;
+ enum communication_state state;
+ struct lttng_dynamic_buffer buffer;
+ LTTNG_OPTIONAL(size_t) data_size;
+ } communication;
+};
+
+void lttng_destruction_handle_destroy(struct lttng_destruction_handle *handle)
+{
+ int ret;
+
+ if (!handle) {
+ return;
+ }
+
+ if (handle->communication.socket >= 0) {
+ ret = close(handle->communication.socket);
+ if (ret) {
+ PERROR("Failed to close lttng-sessiond command socket");
+ }
+ }
+ lttng_poll_clean(&handle->communication.events);
+ lttng_dynamic_buffer_reset(&handle->communication.buffer);
+ lttng_trace_archive_location_put(handle->location);
+ free(handle);
+}
+
+static
+struct lttng_destruction_handle *lttng_destruction_handle_create(
+ int sessiond_socket)
+{
+ int ret;
+ struct lttng_destruction_handle *handle = (lttng_destruction_handle *) zmalloc(sizeof(*handle));
+
+ if (!handle) {
+ goto end;
+ }
+ lttng_dynamic_buffer_init(&handle->communication.buffer);
+ handle->communication.socket = sessiond_socket;
+ ret = lttng_poll_create(&handle->communication.events, 1, 0);
+ if (ret) {
+ goto error;
+ }
+
+ ret = lttng_poll_add(&handle->communication.events, sessiond_socket,
+ LPOLLIN | LPOLLHUP | LPOLLRDHUP | LPOLLERR);
+ if (ret) {
+ goto error;
+ }
+
+ handle->communication.bytes_left_to_receive =
+ sizeof(struct lttcomm_lttng_msg);
+ handle->communication.state = COMMUNICATION_STATE_RECEIVE_LTTNG_MSG;
+end:
+ return handle;
+error:
+ lttng_destruction_handle_destroy(handle);
+ return NULL;
+}
+
+static
+int handle_state_transition(struct lttng_destruction_handle *handle)
+{
+ int ret = 0;
+
+ LTTNG_ASSERT(handle->communication.bytes_left_to_receive == 0);
+
+ switch (handle->communication.state) {
+ case COMMUNICATION_STATE_RECEIVE_LTTNG_MSG:
+ {
+ const struct lttcomm_lttng_msg *msg =
+ (typeof(msg)) handle->communication.buffer.data;
+
+ LTTNG_OPTIONAL_SET(&handle->destruction_return_code,
+ (enum lttng_error_code) msg->ret_code);
+ if (handle->destruction_return_code.value != LTTNG_OK) {
+ handle->communication.state = COMMUNICATION_STATE_END;
+ break;
+ } else if (msg->cmd_header_size != sizeof(struct lttcomm_session_destroy_command_header) ||
+ msg->data_size > DEFAULT_MAX_TRACE_ARCHIVE_LOCATION_PAYLOAD_SIZE) {
+ handle->communication.state = COMMUNICATION_STATE_ERROR;
+ ret = -1;
+ break;
+ }
+
+ handle->communication.state =
+ COMMUNICATION_STATE_RECEIVE_COMMAND_HEADER;
+ handle->communication.bytes_left_to_receive =
+ msg->cmd_header_size;
+ LTTNG_OPTIONAL_SET(&handle->communication.data_size,
+ msg->data_size);
+ ret = lttng_dynamic_buffer_set_size(
+ &handle->communication.buffer, 0);
+ LTTNG_ASSERT(!ret);
+ break;
+ }
+ case COMMUNICATION_STATE_RECEIVE_COMMAND_HEADER:
+ {
+ const struct lttcomm_session_destroy_command_header *hdr =
+ (typeof(hdr)) handle->communication.buffer.data;
+
+ LTTNG_OPTIONAL_SET(&handle->rotation_state,
+ (enum lttng_rotation_state) hdr->rotation_state);
+ switch (handle->rotation_state.value) {
+ case LTTNG_ROTATION_STATE_COMPLETED:
+ handle->communication.state =
+ COMMUNICATION_STATE_RECEIVE_PAYLOAD;
+ handle->communication.bytes_left_to_receive =
+ LTTNG_OPTIONAL_GET(handle->communication.data_size);
+ break;
+ case LTTNG_ROTATION_STATE_ERROR:
+ case LTTNG_ROTATION_STATE_NO_ROTATION:
+ handle->communication.state = COMMUNICATION_STATE_END;
+ break;
+ default:
+ handle->communication.state = COMMUNICATION_STATE_ERROR;
+ ret = -1;
+ break;
+ }
+ break;
+ }
+ case COMMUNICATION_STATE_RECEIVE_PAYLOAD:
+ {
+ ssize_t location_ret;
+ struct lttng_trace_archive_location *location;
+ const struct lttng_buffer_view view =
+ lttng_buffer_view_from_dynamic_buffer(
+ &handle->communication.buffer, 0, -1);
+
+ location_ret = lttng_trace_archive_location_create_from_buffer(
+ &view, &location);
+ if (location_ret < 0) {
+ ERR("Failed to deserialize trace archive location");
+ handle->communication.state = COMMUNICATION_STATE_ERROR;
+ ret = -1;
+ break;
+ } else {
+ /* Ownership is transferred to the destruction handle. */
+ handle->location = location;
+ handle->communication.state = COMMUNICATION_STATE_END;
+ }
+ break;
+ }
+ default:
+ abort();
+ }
+
+ /* Clear reception buffer on state transition. */
+ if (lttng_dynamic_buffer_set_size(&handle->communication.buffer, 0)) {
+ abort();
+ }
+ return ret;
+}
+
+static
+int handle_incoming_data(struct lttng_destruction_handle *handle)
+{
+ int ret;
+ ssize_t comm_ret;
+ const size_t original_buffer_size = handle->communication.buffer.size;
+
+ /* Reserve space for reception. */
+ ret = lttng_dynamic_buffer_set_size(&handle->communication.buffer,
+ original_buffer_size + handle->communication.bytes_left_to_receive);
+ if (ret) {
+ goto end;
+ }
+
+ comm_ret = lttcomm_recv_unix_sock(handle->communication.socket,
+ handle->communication.buffer.data + original_buffer_size,
+ handle->communication.bytes_left_to_receive);
+ if (comm_ret <= 0) {
+ ret = -1;
+ goto end;
+ }
+
+ handle->communication.bytes_left_to_receive -= comm_ret;
+ if (handle->communication.bytes_left_to_receive == 0) {
+ ret = handle_state_transition(handle);
+ } else {
+ ret = lttng_dynamic_buffer_set_size(
+ &handle->communication.buffer,
+ original_buffer_size + comm_ret);
+ }
+end:
+ return ret;
+}
+
+enum lttng_destruction_handle_status
+lttng_destruction_handle_wait_for_completion(
+ struct lttng_destruction_handle *handle, int timeout_ms)
+{
+ enum lttng_destruction_handle_status status;
+ unsigned long time_left_ms = 0;
+ const bool has_timeout = timeout_ms > 0;
+ struct timespec initial_time;
+
+ if (!handle) {
+ status = LTTNG_DESTRUCTION_HANDLE_STATUS_INVALID;
+ goto end;
+ }
+
+ if (handle->communication.state == COMMUNICATION_STATE_ERROR) {
+ status = LTTNG_DESTRUCTION_HANDLE_STATUS_ERROR;
+ goto end;
+ } else if (handle->communication.state == COMMUNICATION_STATE_END) {
+ status = LTTNG_DESTRUCTION_HANDLE_STATUS_COMPLETED;
+ goto end;
+ }
+ if (has_timeout) {
+ int ret = lttng_clock_gettime(CLOCK_MONOTONIC, &initial_time);
+ if (ret) {
+ status = LTTNG_DESTRUCTION_HANDLE_STATUS_ERROR;
+ goto end;
+ }
+ time_left_ms = (unsigned long) timeout_ms;
+ }
+
+ while (handle->communication.state != COMMUNICATION_STATE_END &&
+ (time_left_ms || !has_timeout)) {
+ int ret;
+ uint32_t revents;
+ struct timespec current_time, diff;
+ unsigned long diff_ms;
+
+ ret = lttng_poll_wait(&handle->communication.events,
+ has_timeout ? time_left_ms : -1);
+ if (ret == 0) {
+ /* timeout */
+ break;
+ } else if (ret < 0) {
+ status = LTTNG_DESTRUCTION_HANDLE_STATUS_ERROR;
+ goto end;
+ }
+
+ /* The sessiond connection socket is the only monitored fd. */
+ revents = LTTNG_POLL_GETEV(&handle->communication.events, 0);
+ if (revents & LPOLLIN) {
+ ret = handle_incoming_data(handle);
+ if (ret) {
+ handle->communication.state =
+ COMMUNICATION_STATE_ERROR;
+ status = LTTNG_DESTRUCTION_HANDLE_STATUS_ERROR;
+ goto end;
+ }
+ } else {
+ handle->communication.state = COMMUNICATION_STATE_ERROR;
+ status = LTTNG_DESTRUCTION_HANDLE_STATUS_ERROR;
+ goto end;
+ }
+ if (!has_timeout) {
+ continue;
+ }
+
+ ret = lttng_clock_gettime(CLOCK_MONOTONIC, ¤t_time);
+ if (ret) {
+ status = LTTNG_DESTRUCTION_HANDLE_STATUS_ERROR;
+ goto end;
+ }
+ diff = timespec_abs_diff(initial_time, current_time);
+ ret = timespec_to_ms(diff, &diff_ms);
+ if (ret) {
+ ERR("Failed to compute elapsed time while waiting for completion");
+ status = LTTNG_DESTRUCTION_HANDLE_STATUS_ERROR;
+ goto end;
+ }
+ DBG("%lums elapsed while waiting for session destruction completion",
+ diff_ms);
+ diff_ms = std::max(diff_ms, 1UL);
+ diff_ms = std::min(diff_ms, time_left_ms);
+ time_left_ms -= diff_ms;
+ }
+
+ status = handle->communication.state == COMMUNICATION_STATE_END ?
+ LTTNG_DESTRUCTION_HANDLE_STATUS_COMPLETED :
+ LTTNG_DESTRUCTION_HANDLE_STATUS_TIMEOUT;
+end:
+ return status;
+}
+
+enum lttng_destruction_handle_status
+lttng_destruction_handle_get_rotation_state(
+ const struct lttng_destruction_handle *handle,
+ enum lttng_rotation_state *rotation_state)
+{
+ enum lttng_destruction_handle_status status =
+ LTTNG_DESTRUCTION_HANDLE_STATUS_OK;
+
+ if (!handle || !rotation_state) {
+ status = LTTNG_DESTRUCTION_HANDLE_STATUS_INVALID;
+ goto end;
+ }
+
+ if (!handle->rotation_state.is_set) {
+ status = LTTNG_DESTRUCTION_HANDLE_STATUS_INVALID;
+ goto end;
+ }
+ *rotation_state = handle->rotation_state.value;
+end:
+ return status;
+}
+
+enum lttng_destruction_handle_status
+lttng_destruction_handle_get_archive_location(
+ const struct lttng_destruction_handle *handle,
+ const struct lttng_trace_archive_location **location)
+{
+ enum lttng_destruction_handle_status status =
+ LTTNG_DESTRUCTION_HANDLE_STATUS_OK;
+
+ if (!handle || !location) {
+ status = LTTNG_DESTRUCTION_HANDLE_STATUS_INVALID;
+ goto end;
+ }
+
+ if (!handle->location) {
+ status = LTTNG_DESTRUCTION_HANDLE_STATUS_INVALID;
+ goto end;
+ }
+ *location = handle->location;
+end:
+ return status;
+}
+
+enum lttng_destruction_handle_status
+lttng_destruction_handle_get_result(
+ const struct lttng_destruction_handle *handle,
+ enum lttng_error_code *result)
+{
+ enum lttng_destruction_handle_status status =
+ LTTNG_DESTRUCTION_HANDLE_STATUS_OK;
+
+ if (!handle || !result) {
+ status = LTTNG_DESTRUCTION_HANDLE_STATUS_INVALID;
+ goto end;
+ }
+
+ if (!handle->destruction_return_code.is_set) {
+ status = LTTNG_DESTRUCTION_HANDLE_STATUS_INVALID;
+ goto end;
+ }
+ *result = handle->destruction_return_code.value;
+end:
+ return status;
+}
+
+enum lttng_error_code lttng_destroy_session_ext(const char *session_name,
+ struct lttng_destruction_handle **_handle)
+{
+ int ret;
+ ssize_t comm_ret;
+ enum lttng_error_code ret_code = LTTNG_OK;
+ struct lttcomm_session_msg lsm = {
+ .cmd_type = LTTNG_DESTROY_SESSION,
+ };
+ int sessiond_socket = -1;
+ struct lttng_destruction_handle *handle = NULL;
+
+ if (!session_name) {
+ ret_code = LTTNG_ERR_INVALID;
+ goto error;
+ }
+
+ ret = lttng_strncpy(lsm.session.name, session_name,
+ sizeof(lsm.session.name));
+ if (ret) {
+ ret_code = LTTNG_ERR_INVALID;
+ goto error;
+ }
+
+ ret = connect_sessiond();
+ if (ret < 0) {
+ ret_code = LTTNG_ERR_NO_SESSIOND;
+ goto error;
+ } else {
+ sessiond_socket = ret;
+ }
+
+ handle = lttng_destruction_handle_create(sessiond_socket);
+ if (!handle) {
+ ret_code = LTTNG_ERR_NOMEM;
+ goto error;
+ }
+
+ comm_ret = lttcomm_send_creds_unix_sock(sessiond_socket, &lsm, sizeof(lsm));
+ if (comm_ret < 0) {
+ ret_code = LTTNG_ERR_FATAL;
+ goto error;
+ }
+ sessiond_socket = -1;
+
+ /* Transfer the handle to the caller. */
+ if (_handle) {
+ *_handle = handle;
+ handle = NULL;
+ }
+error:
+ if (sessiond_socket >= 0) {
+ ret = close(sessiond_socket);
+ if (ret < 0) {
+ PERROR("Failed to close the LTTng session daemon connection socket");
+ }
+ }
+ if (handle) {
+ lttng_destruction_handle_destroy(handle);
+ }
+ return ret_code;
+}
+++ /dev/null
-/*
- * event.c
- *
- * Linux Trace Toolkit Control Library
- *
- * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#define _LGPL_SOURCE
-#include <stddef.h>
-
-#include <common/error.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <lttng/event-internal.h>
-#include <lttng/event.h>
-#include <lttng/lttng-error.h>
-#include <lttng/userspace-probe-internal.h>
-
-struct lttng_event *lttng_event_create(void)
-{
- struct lttng_event *event;
- struct lttng_event_extended *event_extended;
-
- event = zmalloc(sizeof(*event));
- if (!event) {
- PERROR("Error allocating event structure");
- goto end;
- }
-
- event_extended = zmalloc(sizeof(*event_extended));
- if (!event_extended) {
- PERROR("Error allocating event extended structure");
- goto error;
- }
- event->extended.ptr = event_extended;
-end:
- return event;
-error:
- free(event);
- event = NULL;
- goto end;
-}
-
-void lttng_event_destroy(struct lttng_event *event)
-{
- struct lttng_event_extended *event_extended;
-
- if (!event) {
- return;
- }
-
- event_extended = (struct lttng_event_extended *) event->extended.ptr;
-
- if (event_extended) {
- if (event_extended->probe_location) {
- lttng_userspace_probe_location_destroy(
- event_extended->probe_location);
- }
- free(event_extended);
- }
- free(event);
-}
-
-int lttng_event_get_filter_expression(struct lttng_event *event,
- const char **filter_expression)
-{
- int ret = 0;
- struct lttng_event_extended *event_extended;
-
- if (!event || !filter_expression) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- event_extended = (struct lttng_event_extended *) event->extended.ptr;
- if (!event_extended) {
- /*
- * This can happen since the lttng_event structure is
- * used for other tasks where this pointer is never set.
- */
- *filter_expression = NULL;
- goto end;
- }
-
- *filter_expression = event_extended->filter_expression;
-end:
- return ret;
-}
-
-int lttng_event_get_exclusion_name_count(struct lttng_event *event)
-{
- int ret = 0;
- struct lttng_event_extended *event_extended;
-
- if (!event) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- event_extended = (struct lttng_event_extended *) event->extended.ptr;
- if (!event_extended) {
- /*
- * This can happen since the lttng_event structure is
- * used for other tasks where this pointer is never set.
- */
- goto end;
- }
-
- if (event_extended->exclusions.count > INT_MAX) {
- ret = -LTTNG_ERR_OVERFLOW;
- goto end;
- }
- ret = (int) event_extended->exclusions.count;
-end:
- return ret;
-}
-
-int lttng_event_get_exclusion_name(struct lttng_event *event,
- size_t index, const char **exclusion_name)
-{
- int ret = 0;
- struct lttng_event_extended *event_extended;
-
- if (!event || !exclusion_name) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- if (index > UINT_MAX) {
- ret = -LTTNG_ERR_OVERFLOW;
- goto end;
- }
-
- event_extended = (struct lttng_event_extended *) event->extended.ptr;
- if (!event_extended) {
- /*
- * This can happen since the lttng_event structure is
- * used for other tasks where this pointer is never set.
- */
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- if (index >= event_extended->exclusions.count) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- *exclusion_name = event_extended->exclusions.strings +
- (index * LTTNG_SYMBOL_NAME_LEN);
-end:
- return ret;
-}
-
-const struct lttng_userspace_probe_location *
-lttng_event_get_userspace_probe_location(const struct lttng_event *event)
-{
- struct lttng_userspace_probe_location *probe_location = NULL;
- struct lttng_event_extended *event_extended;
-
- if (!event) {
- goto end;
- }
-
- event_extended = (struct lttng_event_extended *) event->extended.ptr;
- if (!event_extended) {
- goto end;
- }
- probe_location = event_extended->probe_location;
-end:
- return probe_location;
-}
-
-int lttng_event_set_userspace_probe_location(struct lttng_event *event,
- struct lttng_userspace_probe_location *probe_location)
-{
- int ret = 0;
- struct lttng_event_extended *event_extended;
-
- if (!event || !probe_location) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- event_extended = (struct lttng_event_extended *) event->extended.ptr;
- LTTNG_ASSERT(event_extended);
- if (event_extended->probe_location) {
- lttng_userspace_probe_location_destroy(
- event_extended->probe_location);
- }
- event_extended->probe_location = probe_location;
-end:
- return ret;
-}
--- /dev/null
+/*
+ * event.c
+ *
+ * Linux Trace Toolkit Control Library
+ *
+ * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#define _LGPL_SOURCE
+#include <stddef.h>
+
+#include <common/error.h>
+#include <common/sessiond-comm/sessiond-comm.h>
+#include <lttng/event-internal.h>
+#include <lttng/event.h>
+#include <lttng/lttng-error.h>
+#include <lttng/userspace-probe-internal.h>
+
+struct lttng_event *lttng_event_create(void)
+{
+ struct lttng_event *event;
+ struct lttng_event_extended *event_extended;
+
+ event = (lttng_event *) zmalloc(sizeof(*event));
+ if (!event) {
+ PERROR("Error allocating event structure");
+ goto end;
+ }
+
+ event_extended = (lttng_event_extended *) zmalloc(sizeof(*event_extended));
+ if (!event_extended) {
+ PERROR("Error allocating event extended structure");
+ goto error;
+ }
+ event->extended.ptr = event_extended;
+end:
+ return event;
+error:
+ free(event);
+ event = NULL;
+ goto end;
+}
+
+void lttng_event_destroy(struct lttng_event *event)
+{
+ struct lttng_event_extended *event_extended;
+
+ if (!event) {
+ return;
+ }
+
+ event_extended = (struct lttng_event_extended *) event->extended.ptr;
+
+ if (event_extended) {
+ if (event_extended->probe_location) {
+ lttng_userspace_probe_location_destroy(
+ event_extended->probe_location);
+ }
+ free(event_extended);
+ }
+ free(event);
+}
+
+int lttng_event_get_filter_expression(struct lttng_event *event,
+ const char **filter_expression)
+{
+ int ret = 0;
+ struct lttng_event_extended *event_extended;
+
+ if (!event || !filter_expression) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ event_extended = (struct lttng_event_extended *) event->extended.ptr;
+ if (!event_extended) {
+ /*
+ * This can happen since the lttng_event structure is
+ * used for other tasks where this pointer is never set.
+ */
+ *filter_expression = NULL;
+ goto end;
+ }
+
+ *filter_expression = event_extended->filter_expression;
+end:
+ return ret;
+}
+
+int lttng_event_get_exclusion_name_count(struct lttng_event *event)
+{
+ int ret = 0;
+ struct lttng_event_extended *event_extended;
+
+ if (!event) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ event_extended = (struct lttng_event_extended *) event->extended.ptr;
+ if (!event_extended) {
+ /*
+ * This can happen since the lttng_event structure is
+ * used for other tasks where this pointer is never set.
+ */
+ goto end;
+ }
+
+ if (event_extended->exclusions.count > INT_MAX) {
+ ret = -LTTNG_ERR_OVERFLOW;
+ goto end;
+ }
+ ret = (int) event_extended->exclusions.count;
+end:
+ return ret;
+}
+
+int lttng_event_get_exclusion_name(struct lttng_event *event,
+ size_t index, const char **exclusion_name)
+{
+ int ret = 0;
+ struct lttng_event_extended *event_extended;
+
+ if (!event || !exclusion_name) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ if (index > UINT_MAX) {
+ ret = -LTTNG_ERR_OVERFLOW;
+ goto end;
+ }
+
+ event_extended = (struct lttng_event_extended *) event->extended.ptr;
+ if (!event_extended) {
+ /*
+ * This can happen since the lttng_event structure is
+ * used for other tasks where this pointer is never set.
+ */
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ if (index >= event_extended->exclusions.count) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ *exclusion_name = event_extended->exclusions.strings +
+ (index * LTTNG_SYMBOL_NAME_LEN);
+end:
+ return ret;
+}
+
+const struct lttng_userspace_probe_location *
+lttng_event_get_userspace_probe_location(const struct lttng_event *event)
+{
+ struct lttng_userspace_probe_location *probe_location = NULL;
+ struct lttng_event_extended *event_extended;
+
+ if (!event) {
+ goto end;
+ }
+
+ event_extended = (struct lttng_event_extended *) event->extended.ptr;
+ if (!event_extended) {
+ goto end;
+ }
+ probe_location = event_extended->probe_location;
+end:
+ return probe_location;
+}
+
+int lttng_event_set_userspace_probe_location(struct lttng_event *event,
+ struct lttng_userspace_probe_location *probe_location)
+{
+ int ret = 0;
+ struct lttng_event_extended *event_extended;
+
+ if (!event || !probe_location) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ event_extended = (struct lttng_event_extended *) event->extended.ptr;
+ LTTNG_ASSERT(event_extended);
+ if (event_extended->probe_location) {
+ lttng_userspace_probe_location_destroy(
+ event_extended->probe_location);
+ }
+ event_extended->probe_location = probe_location;
+end:
+ return ret;
+}
+++ /dev/null
-/*
- * Copyright (C) 2014 David Goulet <dgoulet@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#define _LGPL_SOURCE
-#include <string.h>
-#include <limits.h>
-
-#include <lttng/lttng-error.h>
-#include <lttng/load.h>
-#include <lttng/load-internal.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <common/config/session-config.h>
-#include <common/uri.h>
-#include <common/macros.h>
-#include <common/compat/string.h>
-
-#include "lttng-ctl-helper.h"
-
-struct lttng_load_session_attr *lttng_load_session_attr_create(void)
-{
- return zmalloc(sizeof(struct lttng_load_session_attr));
-}
-
-static
-void reset_load_session_attr_urls(struct lttng_load_session_attr *attr)
-{
- free(attr->raw_override_url);
- free(attr->raw_override_path_url);
- free(attr->raw_override_ctrl_url);
- free(attr->raw_override_data_url);
- if (attr->override_attr) {
- free(attr->override_attr->path_url);
- free(attr->override_attr->ctrl_url);
- free(attr->override_attr->data_url);
- free(attr->override_attr->session_name);
- }
-}
-
-void lttng_load_session_attr_destroy(struct lttng_load_session_attr *attr)
-{
- if (attr) {
- reset_load_session_attr_urls(attr);
- free(attr->override_attr);
- free(attr);
- }
-}
-
-static int validate_attr(const struct lttng_load_session_attr *attr)
-{
- int ret = 0;
-
- if (!attr) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- if (!attr->override_attr) {
- goto end;
- }
-
- /*
- * Refuse override name if the objective is to load multiple session
- * since this operation is ambiguous while loading multiple session.
- */
- if (attr->override_attr->session_name
- && attr->session_name[0] == '\0') {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-end:
- return ret;
-}
-
-const char *lttng_load_session_attr_get_session_name(
- struct lttng_load_session_attr *attr)
-{
- const char *ret = NULL;
-
- if (attr && attr->session_name[0]) {
- ret = attr->session_name;
- }
-
- return ret;
-}
-
-const char *lttng_load_session_attr_get_input_url(
- struct lttng_load_session_attr *attr)
-{
- const char *ret = NULL;
-
- if (attr && attr->input_url[0]) {
- ret = attr->input_url;
- }
-
- return ret;
-}
-
-int lttng_load_session_attr_get_overwrite(
- struct lttng_load_session_attr *attr)
-{
- return attr ? attr->overwrite : -LTTNG_ERR_INVALID;
-}
-
-const char *lttng_load_session_attr_get_override_ctrl_url(
- struct lttng_load_session_attr *attr)
-{
- const char *ret = NULL;
-
- if (!attr || !attr->override_attr) {
- goto end;
- }
-
- ret = attr->raw_override_ctrl_url;
-end:
- return ret;
-}
-
-const char *lttng_load_session_attr_get_override_data_url(
- struct lttng_load_session_attr *attr)
-{
- const char *ret = NULL;
-
- if (!attr || !attr->override_attr) {
- goto end;
- }
-
- ret = attr->raw_override_data_url;
-end:
- return ret;
-}
-
-const char *lttng_load_session_attr_get_override_url(
- struct lttng_load_session_attr *attr)
-{
- const char *ret = NULL;
-
- if (!attr || !attr->override_attr) {
- goto end;
- }
-
- if ((attr->override_attr->path_url ||
- (attr->override_attr->ctrl_url &&
- attr->override_attr->data_url))) {
- ret = attr->raw_override_url;
- }
-end:
- return ret;
-}
-
-const char *lttng_load_session_attr_get_override_session_name(
- struct lttng_load_session_attr *attr)
-{
- const char *ret = NULL;
-
- if (!attr || !attr->override_attr) {
- goto end;
- }
-
- ret = attr->override_attr->session_name;
-end:
- return ret;
-}
-
-int lttng_load_session_attr_set_session_name(
- struct lttng_load_session_attr *attr, const char *session_name)
-{
- int ret = 0;
-
- if (!attr) {
- ret = -LTTNG_ERR_INVALID;
- goto error;
- }
-
- if (session_name) {
- size_t len;
-
- len = strlen(session_name);
- if (len >= LTTNG_NAME_MAX) {
- ret = -LTTNG_ERR_INVALID;
- goto error;
- }
-
- ret = lttng_strncpy(attr->session_name, session_name,
- sizeof(attr->session_name));
- if (ret) {
- ret = -LTTNG_ERR_INVALID;
- goto error;
- }
- } else {
- attr->session_name[0] = '\0';
- }
-error:
- return ret;
-}
-
-int lttng_load_session_attr_set_input_url(
- struct lttng_load_session_attr *attr, const char *url)
-{
- int ret = 0;
- size_t len;
- ssize_t size;
- struct lttng_uri *uris = NULL;
-
- if (!attr) {
- ret = -LTTNG_ERR_INVALID;
- goto error;
- }
-
- if (!url) {
- attr->input_url[0] = '\0';
- ret = 0;
- goto end;
- }
-
- len = strlen(url);
- if (len >= PATH_MAX) {
- ret = -LTTNG_ERR_INVALID;
- goto error;
- }
-
- size = uri_parse_str_urls(url, NULL, &uris);
- if (size <= 0 || uris[0].dtype != LTTNG_DST_PATH) {
- ret = -LTTNG_ERR_INVALID;
- goto error;
- }
-
- /* Copy string plus the NULL terminated byte. */
- ret = lttng_strncpy(attr->input_url, uris[0].dst.path,
- sizeof(attr->input_url));
- if (ret) {
- ret = -LTTNG_ERR_INVALID;
- goto error;
- }
-
-end:
-error:
- free(uris);
- return ret;
-}
-
-int lttng_load_session_attr_set_overwrite(
- struct lttng_load_session_attr *attr, int overwrite)
-{
- int ret = 0;
-
- if (!attr) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- attr->overwrite = !!overwrite;
-end:
- return ret;
-}
-
-int lttng_load_session_attr_set_override_ctrl_url(
- struct lttng_load_session_attr *attr, const char *url)
-{
- int ret = 0;
- ssize_t ret_size;
- struct lttng_uri *uri = NULL;
- char *url_str = NULL;
- char *raw_str = NULL;
-
- if (!attr) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- if (!attr->override_attr) {
- attr->override_attr = zmalloc(
- sizeof(struct config_load_session_override_attr));
- if (!attr->override_attr) {
- ret = -LTTNG_ERR_NOMEM;
- goto end;
- }
- }
-
- if (attr->override_attr->path_url) {
- /*
- * Setting a ctrl override after a path override makes no sense.
- */
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- /*
- * FIXME: uri_parse should be able to take as parameter the protocol
- * type to validate "url". For now only check the parsing goes through;
- * it will fail later on.
- */
- ret_size = uri_parse(url, &uri);
- if (ret_size < 0) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- if (uri[0].port == 0) {
- uri[0].port = DEFAULT_NETWORK_CONTROL_PORT;
- }
-
- url_str = zmalloc(PATH_MAX);
- if (!url_str) {
- /* FIXME: return valid error */
- ret = -LTTNG_ERR_NOMEM;
- goto end;
- }
-
- ret = uri_to_str_url(&uri[0], url_str, PATH_MAX);
- if (ret < 0) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
- ret = 0;
-
- raw_str = lttng_strndup(url, PATH_MAX);
- if (!raw_str) {
- ret = -LTTNG_ERR_NOMEM;
- goto end;
- }
-
- /* Squash old value if any */
- free(attr->override_attr->ctrl_url);
- free(attr->raw_override_ctrl_url);
-
- /* Populate the object */
- attr->override_attr->ctrl_url = url_str;
- attr->raw_override_ctrl_url = raw_str;
-
- /* Ownership passed to attr. */
- url_str = NULL;
- raw_str = NULL;
-
-end:
- free(raw_str);
- free(url_str);
- free(uri);
- return ret;
-}
-
-int lttng_load_session_attr_set_override_data_url(
- struct lttng_load_session_attr *attr, const char *url)
-{
- int ret = 0;
- ssize_t ret_size;
- struct lttng_uri *uri = NULL;
- char *url_str = NULL;
- char *raw_str = NULL;
-
- if (!attr) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- if (!attr->override_attr) {
- attr->override_attr = zmalloc(
- sizeof(struct config_load_session_override_attr));
- if (!attr->override_attr) {
- ret = -LTTNG_ERR_NOMEM;
- goto end;
- }
- }
-
- if (attr->override_attr->path_url) {
- /*
- * Setting a data override after a path override makes no sense.
- */
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- /*
- * FIXME: uri_parse should be able to take as parameter the protocol
- * type to validate "url". For now only check the parsing goes through;
- * it will fail later on.
- */
- ret_size = uri_parse(url, &uri);
- if (ret_size < 0) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- if (uri[0].port == 0) {
- uri[0].port = DEFAULT_NETWORK_DATA_PORT;
- }
-
- url_str = zmalloc(PATH_MAX);
- if (!url_str) {
- ret = -LTTNG_ERR_NOMEM;
- goto end;
- }
-
- ret = uri_to_str_url(&uri[0], url_str, PATH_MAX);
- if (ret < 0) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
- ret = 0;
-
- raw_str = lttng_strndup(url, PATH_MAX);
- if (!raw_str) {
- ret = -LTTNG_ERR_NOMEM;
- goto end;
- }
-
- /* Squash old value if any */
- free(attr->override_attr->data_url);
- free(attr->raw_override_data_url);
-
- /* Populate the object */
- attr->override_attr->data_url = url_str;
- attr->raw_override_data_url = raw_str;
-
- /* Ownership passed to attr. */
- url_str = NULL;
- raw_str = NULL;
-end:
- free(raw_str);
- free(url_str);
- free(uri);
- return ret;
-}
-
-int lttng_load_session_attr_set_override_url(
- struct lttng_load_session_attr *attr, const char *url)
-{
- int ret = 0;
- ssize_t ret_size;
- struct lttng_uri *uri = NULL;
- char *raw_url_str = NULL;
- char *raw_path_str = NULL;
- char *path_str = NULL;
- char *raw_ctrl_str = NULL;
- char *ctrl_str = NULL;
- char *raw_data_str = NULL;
- char *data_str = NULL;
- char buffer[PATH_MAX];
-
- if (!attr || !url || strlen(url) >= PATH_MAX) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- if (!attr->override_attr) {
- attr->override_attr = zmalloc(
- sizeof(struct config_load_session_override_attr));
- if (!attr->override_attr) {
- ret = -LTTNG_ERR_NOMEM;
- goto end;
- }
- }
-
- /*
- * FIXME: uri_parse should be able to take as parameter the protocol
- * type to validate "url". For now only check the parsing goes through;
- * it will fail later on.
- */
- ret_size = uri_parse_str_urls(url, NULL, &uri);
- if (ret_size < 0 || ret_size > 2) {
- /* Unexpected URL format. */
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- raw_url_str = lttng_strndup(url, PATH_MAX);
- if (!raw_url_str) {
- ret = -LTTNG_ERR_NOMEM;
- goto end;
- }
-
- /* Get path | ctrl && data string URL. */
- ret = uri_to_str_url(&uri[0], buffer, sizeof(buffer));
- if (ret < 0 || ret >= PATH_MAX) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
- ret = 0;
-
- switch (uri[0].dtype) {
- case LTTNG_DST_PATH:
- raw_path_str = lttng_strndup(buffer, PATH_MAX);
- if (!raw_path_str) {
- ret = -LTTNG_ERR_NOMEM;
- goto end;
- }
-
- path_str = lttng_strndup(raw_path_str, PATH_MAX);
- if (!path_str) {
- ret = -LTTNG_ERR_NOMEM;
- goto end;
- }
- break;
- case LTTNG_DST_IPV4:
- case LTTNG_DST_IPV6:
- if (ret_size != 2) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- raw_ctrl_str = lttng_strndup(buffer, PATH_MAX);
- if (!raw_ctrl_str) {
- ret = -LTTNG_ERR_NOMEM;
- goto end;
- }
-
- ctrl_str = lttng_strndup(raw_ctrl_str, PATH_MAX);
- if (!ctrl_str) {
- ret = -LTTNG_ERR_NOMEM;
- goto end;
- }
-
- /* Get the data uri. */
- ret = uri_to_str_url(&uri[1], buffer, sizeof(buffer));
- if (ret < 0) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
- ret = 0;
-
- raw_data_str = lttng_strndup(buffer, PATH_MAX);
- if (!raw_data_str) {
- ret = -LTTNG_ERR_NOMEM;
- goto end;
- }
-
- data_str = lttng_strndup(raw_data_str, PATH_MAX);
- if (!data_str) {
- ret = -LTTNG_ERR_NOMEM;
- goto end;
- }
-
- break;
- default:
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- reset_load_session_attr_urls(attr);
-
- attr->override_attr->path_url = path_str;
- attr->override_attr->ctrl_url = ctrl_str;
- attr->override_attr->data_url = data_str;
-
- attr->raw_override_url = raw_url_str;
- attr->raw_override_path_url = raw_path_str;
- attr->raw_override_ctrl_url = raw_ctrl_str;
- attr->raw_override_data_url = raw_data_str;
-
- /* Pass data ownership to attr. */
- raw_url_str = NULL;
- raw_path_str = NULL;
- path_str = NULL;
- raw_ctrl_str = NULL;
- ctrl_str = NULL;
- raw_data_str = NULL;
- data_str = NULL;
-
-end:
- free(raw_path_str);
- free(path_str);
- free(raw_ctrl_str);
- free(ctrl_str);
- free(raw_data_str);
- free(data_str);
- free(raw_url_str);
- free(uri);
- return ret;
-}
-
-int lttng_load_session_attr_set_override_session_name(
- struct lttng_load_session_attr *attr, const char *session_name)
-{
- int ret = 0;
- size_t len;
-
- if (!attr ||!session_name) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- if (!attr->override_attr) {
- attr->override_attr = zmalloc(
- sizeof(struct config_load_session_override_attr));
- if (!attr->override_attr) {
- ret = -LTTNG_ERR_NOMEM;
- goto end;
- }
- }
-
- len = strlen(session_name);
- if (len >= LTTNG_NAME_MAX) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- attr->override_attr->session_name = lttng_strndup(session_name,
- len);
- if (!attr->override_attr->session_name) {
- ret = -LTTNG_ERR_NOMEM;
- goto end;
- }
-end:
- return ret;
-}
-
-int lttng_load_session(struct lttng_load_session_attr *attr)
-{
- int ret;
- const char *url, *session_name;
-
- if (!attr) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- ret = validate_attr(attr);
- if (ret) {
- goto end;
- }
-
- url = attr->input_url[0] != '\0' ? attr->input_url : NULL;
- session_name = attr->session_name[0] != '\0' ?
- attr->session_name : NULL;
-
- ret = config_load_session(url, session_name, attr->overwrite, 0,
- attr->override_attr);
-
-end:
- return ret;
-}
--- /dev/null
+/*
+ * Copyright (C) 2014 David Goulet <dgoulet@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#define _LGPL_SOURCE
+#include <string.h>
+#include <limits.h>
+
+#include <lttng/lttng-error.h>
+#include <lttng/load.h>
+#include <lttng/load-internal.h>
+#include <common/sessiond-comm/sessiond-comm.h>
+#include <common/config/session-config.h>
+#include <common/uri.h>
+#include <common/macros.h>
+#include <common/compat/string.h>
+
+#include "lttng-ctl-helper.h"
+
+struct lttng_load_session_attr *lttng_load_session_attr_create(void)
+{
+ return (lttng_load_session_attr *) zmalloc(sizeof(struct lttng_load_session_attr));
+}
+
+static
+void reset_load_session_attr_urls(struct lttng_load_session_attr *attr)
+{
+ free(attr->raw_override_url);
+ free(attr->raw_override_path_url);
+ free(attr->raw_override_ctrl_url);
+ free(attr->raw_override_data_url);
+ if (attr->override_attr) {
+ free(attr->override_attr->path_url);
+ free(attr->override_attr->ctrl_url);
+ free(attr->override_attr->data_url);
+ free(attr->override_attr->session_name);
+ }
+}
+
+void lttng_load_session_attr_destroy(struct lttng_load_session_attr *attr)
+{
+ if (attr) {
+ reset_load_session_attr_urls(attr);
+ free(attr->override_attr);
+ free(attr);
+ }
+}
+
+static int validate_attr(const struct lttng_load_session_attr *attr)
+{
+ int ret = 0;
+
+ if (!attr) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ if (!attr->override_attr) {
+ goto end;
+ }
+
+ /*
+ * Refuse override name if the objective is to load multiple session
+ * since this operation is ambiguous while loading multiple session.
+ */
+ if (attr->override_attr->session_name
+ && attr->session_name[0] == '\0') {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+end:
+ return ret;
+}
+
+const char *lttng_load_session_attr_get_session_name(
+ struct lttng_load_session_attr *attr)
+{
+ const char *ret = NULL;
+
+ if (attr && attr->session_name[0]) {
+ ret = attr->session_name;
+ }
+
+ return ret;
+}
+
+const char *lttng_load_session_attr_get_input_url(
+ struct lttng_load_session_attr *attr)
+{
+ const char *ret = NULL;
+
+ if (attr && attr->input_url[0]) {
+ ret = attr->input_url;
+ }
+
+ return ret;
+}
+
+int lttng_load_session_attr_get_overwrite(
+ struct lttng_load_session_attr *attr)
+{
+ return attr ? attr->overwrite : -LTTNG_ERR_INVALID;
+}
+
+const char *lttng_load_session_attr_get_override_ctrl_url(
+ struct lttng_load_session_attr *attr)
+{
+ const char *ret = NULL;
+
+ if (!attr || !attr->override_attr) {
+ goto end;
+ }
+
+ ret = attr->raw_override_ctrl_url;
+end:
+ return ret;
+}
+
+const char *lttng_load_session_attr_get_override_data_url(
+ struct lttng_load_session_attr *attr)
+{
+ const char *ret = NULL;
+
+ if (!attr || !attr->override_attr) {
+ goto end;
+ }
+
+ ret = attr->raw_override_data_url;
+end:
+ return ret;
+}
+
+const char *lttng_load_session_attr_get_override_url(
+ struct lttng_load_session_attr *attr)
+{
+ const char *ret = NULL;
+
+ if (!attr || !attr->override_attr) {
+ goto end;
+ }
+
+ if ((attr->override_attr->path_url ||
+ (attr->override_attr->ctrl_url &&
+ attr->override_attr->data_url))) {
+ ret = attr->raw_override_url;
+ }
+end:
+ return ret;
+}
+
+const char *lttng_load_session_attr_get_override_session_name(
+ struct lttng_load_session_attr *attr)
+{
+ const char *ret = NULL;
+
+ if (!attr || !attr->override_attr) {
+ goto end;
+ }
+
+ ret = attr->override_attr->session_name;
+end:
+ return ret;
+}
+
+int lttng_load_session_attr_set_session_name(
+ struct lttng_load_session_attr *attr, const char *session_name)
+{
+ int ret = 0;
+
+ if (!attr) {
+ ret = -LTTNG_ERR_INVALID;
+ goto error;
+ }
+
+ if (session_name) {
+ size_t len;
+
+ len = strlen(session_name);
+ if (len >= LTTNG_NAME_MAX) {
+ ret = -LTTNG_ERR_INVALID;
+ goto error;
+ }
+
+ ret = lttng_strncpy(attr->session_name, session_name,
+ sizeof(attr->session_name));
+ if (ret) {
+ ret = -LTTNG_ERR_INVALID;
+ goto error;
+ }
+ } else {
+ attr->session_name[0] = '\0';
+ }
+error:
+ return ret;
+}
+
+int lttng_load_session_attr_set_input_url(
+ struct lttng_load_session_attr *attr, const char *url)
+{
+ int ret = 0;
+ size_t len;
+ ssize_t size;
+ struct lttng_uri *uris = NULL;
+
+ if (!attr) {
+ ret = -LTTNG_ERR_INVALID;
+ goto error;
+ }
+
+ if (!url) {
+ attr->input_url[0] = '\0';
+ ret = 0;
+ goto end;
+ }
+
+ len = strlen(url);
+ if (len >= PATH_MAX) {
+ ret = -LTTNG_ERR_INVALID;
+ goto error;
+ }
+
+ size = uri_parse_str_urls(url, NULL, &uris);
+ if (size <= 0 || uris[0].dtype != LTTNG_DST_PATH) {
+ ret = -LTTNG_ERR_INVALID;
+ goto error;
+ }
+
+ /* Copy string plus the NULL terminated byte. */
+ ret = lttng_strncpy(attr->input_url, uris[0].dst.path,
+ sizeof(attr->input_url));
+ if (ret) {
+ ret = -LTTNG_ERR_INVALID;
+ goto error;
+ }
+
+end:
+error:
+ free(uris);
+ return ret;
+}
+
+int lttng_load_session_attr_set_overwrite(
+ struct lttng_load_session_attr *attr, int overwrite)
+{
+ int ret = 0;
+
+ if (!attr) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ attr->overwrite = !!overwrite;
+end:
+ return ret;
+}
+
+int lttng_load_session_attr_set_override_ctrl_url(
+ struct lttng_load_session_attr *attr, const char *url)
+{
+ int ret = 0;
+ ssize_t ret_size;
+ struct lttng_uri *uri = NULL;
+ char *url_str = NULL;
+ char *raw_str = NULL;
+
+ if (!attr) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ if (!attr->override_attr) {
+ attr->override_attr = (config_load_session_override_attr *) zmalloc(
+ sizeof(struct config_load_session_override_attr));
+ if (!attr->override_attr) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto end;
+ }
+ }
+
+ if (attr->override_attr->path_url) {
+ /*
+ * Setting a ctrl override after a path override makes no sense.
+ */
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ /*
+ * FIXME: uri_parse should be able to take as parameter the protocol
+ * type to validate "url". For now only check the parsing goes through;
+ * it will fail later on.
+ */
+ ret_size = uri_parse(url, &uri);
+ if (ret_size < 0) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ if (uri[0].port == 0) {
+ uri[0].port = DEFAULT_NETWORK_CONTROL_PORT;
+ }
+
+ url_str = (char *) zmalloc(PATH_MAX);
+ if (!url_str) {
+ /* FIXME: return valid error */
+ ret = -LTTNG_ERR_NOMEM;
+ goto end;
+ }
+
+ ret = uri_to_str_url(&uri[0], url_str, PATH_MAX);
+ if (ret < 0) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+ ret = 0;
+
+ raw_str = lttng_strndup(url, PATH_MAX);
+ if (!raw_str) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto end;
+ }
+
+ /* Squash old value if any */
+ free(attr->override_attr->ctrl_url);
+ free(attr->raw_override_ctrl_url);
+
+ /* Populate the object */
+ attr->override_attr->ctrl_url = url_str;
+ attr->raw_override_ctrl_url = raw_str;
+
+ /* Ownership passed to attr. */
+ url_str = NULL;
+ raw_str = NULL;
+
+end:
+ free(raw_str);
+ free(url_str);
+ free(uri);
+ return ret;
+}
+
+int lttng_load_session_attr_set_override_data_url(
+ struct lttng_load_session_attr *attr, const char *url)
+{
+ int ret = 0;
+ ssize_t ret_size;
+ struct lttng_uri *uri = NULL;
+ char *url_str = NULL;
+ char *raw_str = NULL;
+
+ if (!attr) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ if (!attr->override_attr) {
+ attr->override_attr = (config_load_session_override_attr *) zmalloc(
+ sizeof(struct config_load_session_override_attr));
+ if (!attr->override_attr) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto end;
+ }
+ }
+
+ if (attr->override_attr->path_url) {
+ /*
+ * Setting a data override after a path override makes no sense.
+ */
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ /*
+ * FIXME: uri_parse should be able to take as parameter the protocol
+ * type to validate "url". For now only check the parsing goes through;
+ * it will fail later on.
+ */
+ ret_size = uri_parse(url, &uri);
+ if (ret_size < 0) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ if (uri[0].port == 0) {
+ uri[0].port = DEFAULT_NETWORK_DATA_PORT;
+ }
+
+ url_str = (char *) zmalloc(PATH_MAX);
+ if (!url_str) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto end;
+ }
+
+ ret = uri_to_str_url(&uri[0], url_str, PATH_MAX);
+ if (ret < 0) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+ ret = 0;
+
+ raw_str = lttng_strndup(url, PATH_MAX);
+ if (!raw_str) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto end;
+ }
+
+ /* Squash old value if any */
+ free(attr->override_attr->data_url);
+ free(attr->raw_override_data_url);
+
+ /* Populate the object */
+ attr->override_attr->data_url = url_str;
+ attr->raw_override_data_url = raw_str;
+
+ /* Ownership passed to attr. */
+ url_str = NULL;
+ raw_str = NULL;
+end:
+ free(raw_str);
+ free(url_str);
+ free(uri);
+ return ret;
+}
+
+int lttng_load_session_attr_set_override_url(
+ struct lttng_load_session_attr *attr, const char *url)
+{
+ int ret = 0;
+ ssize_t ret_size;
+ struct lttng_uri *uri = NULL;
+ char *raw_url_str = NULL;
+ char *raw_path_str = NULL;
+ char *path_str = NULL;
+ char *raw_ctrl_str = NULL;
+ char *ctrl_str = NULL;
+ char *raw_data_str = NULL;
+ char *data_str = NULL;
+ char buffer[PATH_MAX];
+
+ if (!attr || !url || strlen(url) >= PATH_MAX) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ if (!attr->override_attr) {
+ attr->override_attr = (config_load_session_override_attr *) zmalloc(
+ sizeof(struct config_load_session_override_attr));
+ if (!attr->override_attr) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto end;
+ }
+ }
+
+ /*
+ * FIXME: uri_parse should be able to take as parameter the protocol
+ * type to validate "url". For now only check the parsing goes through;
+ * it will fail later on.
+ */
+ ret_size = uri_parse_str_urls(url, NULL, &uri);
+ if (ret_size < 0 || ret_size > 2) {
+ /* Unexpected URL format. */
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ raw_url_str = lttng_strndup(url, PATH_MAX);
+ if (!raw_url_str) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto end;
+ }
+
+ /* Get path | ctrl && data string URL. */
+ ret = uri_to_str_url(&uri[0], buffer, sizeof(buffer));
+ if (ret < 0 || ret >= PATH_MAX) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+ ret = 0;
+
+ switch (uri[0].dtype) {
+ case LTTNG_DST_PATH:
+ raw_path_str = lttng_strndup(buffer, PATH_MAX);
+ if (!raw_path_str) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto end;
+ }
+
+ path_str = lttng_strndup(raw_path_str, PATH_MAX);
+ if (!path_str) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto end;
+ }
+ break;
+ case LTTNG_DST_IPV4:
+ case LTTNG_DST_IPV6:
+ if (ret_size != 2) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ raw_ctrl_str = lttng_strndup(buffer, PATH_MAX);
+ if (!raw_ctrl_str) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto end;
+ }
+
+ ctrl_str = lttng_strndup(raw_ctrl_str, PATH_MAX);
+ if (!ctrl_str) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto end;
+ }
+
+ /* Get the data uri. */
+ ret = uri_to_str_url(&uri[1], buffer, sizeof(buffer));
+ if (ret < 0) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+ ret = 0;
+
+ raw_data_str = lttng_strndup(buffer, PATH_MAX);
+ if (!raw_data_str) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto end;
+ }
+
+ data_str = lttng_strndup(raw_data_str, PATH_MAX);
+ if (!data_str) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto end;
+ }
+
+ break;
+ default:
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ reset_load_session_attr_urls(attr);
+
+ attr->override_attr->path_url = path_str;
+ attr->override_attr->ctrl_url = ctrl_str;
+ attr->override_attr->data_url = data_str;
+
+ attr->raw_override_url = raw_url_str;
+ attr->raw_override_path_url = raw_path_str;
+ attr->raw_override_ctrl_url = raw_ctrl_str;
+ attr->raw_override_data_url = raw_data_str;
+
+ /* Pass data ownership to attr. */
+ raw_url_str = NULL;
+ raw_path_str = NULL;
+ path_str = NULL;
+ raw_ctrl_str = NULL;
+ ctrl_str = NULL;
+ raw_data_str = NULL;
+ data_str = NULL;
+
+end:
+ free(raw_path_str);
+ free(path_str);
+ free(raw_ctrl_str);
+ free(ctrl_str);
+ free(raw_data_str);
+ free(data_str);
+ free(raw_url_str);
+ free(uri);
+ return ret;
+}
+
+int lttng_load_session_attr_set_override_session_name(
+ struct lttng_load_session_attr *attr, const char *session_name)
+{
+ int ret = 0;
+ size_t len;
+
+ if (!attr ||!session_name) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ if (!attr->override_attr) {
+ attr->override_attr = (config_load_session_override_attr *) zmalloc(
+ sizeof(struct config_load_session_override_attr));
+ if (!attr->override_attr) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto end;
+ }
+ }
+
+ len = strlen(session_name);
+ if (len >= LTTNG_NAME_MAX) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ attr->override_attr->session_name = lttng_strndup(session_name,
+ len);
+ if (!attr->override_attr->session_name) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto end;
+ }
+end:
+ return ret;
+}
+
+int lttng_load_session(struct lttng_load_session_attr *attr)
+{
+ int ret;
+ const char *url, *session_name;
+
+ if (!attr) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ ret = validate_attr(attr);
+ if (ret) {
+ goto end;
+ }
+
+ url = attr->input_url[0] != '\0' ? attr->input_url : NULL;
+ session_name = attr->session_name[0] != '\0' ?
+ attr->session_name : NULL;
+
+ ret = config_load_session(url, session_name, attr->overwrite, 0,
+ attr->override_attr);
+
+end:
+ return ret;
+}
+++ /dev/null
-/*
- * lttng-ctl-health.c
- *
- * Linux Trace Toolkit Health Control Library
- *
- * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
- * Copyright (C) 2013 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#define _LGPL_SOURCE
-#include <unistd.h>
-#include <sys/types.h>
-#include <stdint.h>
-#include <limits.h>
-#include <string.h>
-#include <lttng/health-internal.h>
-
-#include <bin/lttng-sessiond/health-sessiond.h>
-#include <bin/lttng-consumerd/health-consumerd.h>
-#include <bin/lttng-relayd/health-relayd.h>
-#include <common/defaults.h>
-#include <common/utils.h>
-#include <common/compat/errno.h>
-
-#include "lttng-ctl-helper.h"
-
-enum health_component {
- HEALTH_COMPONENT_SESSIOND,
- HEALTH_COMPONENT_CONSUMERD,
- HEALTH_COMPONENT_RELAYD,
-
- NR_HEALTH_COMPONENT,
-};
-
-struct lttng_health_thread {
- struct lttng_health *p;
- int state;
-};
-
-struct lttng_health {
- enum health_component component;
- uint64_t state;
- unsigned int nr_threads;
- char health_sock_path[PATH_MAX];
- /* For consumer health only */
- enum lttng_health_consumerd consumerd_type;
- struct lttng_health_thread thread[];
-};
-
-static
-const char *sessiond_thread_name[NR_HEALTH_SESSIOND_TYPES] = {
- [ HEALTH_SESSIOND_TYPE_CMD ] = "Session daemon command",
- [ HEALTH_SESSIOND_TYPE_APP_MANAGE ] = "Session daemon application manager",
- [ HEALTH_SESSIOND_TYPE_APP_REG ] = "Session daemon application registration",
- [ HEALTH_SESSIOND_TYPE_KERNEL ] = "Session daemon kernel",
- [ HEALTH_SESSIOND_TYPE_CONSUMER ] = "Session daemon consumer manager",
- [ HEALTH_SESSIOND_TYPE_HT_CLEANUP ] = "Session daemon hash table cleanup",
- [ HEALTH_SESSIOND_TYPE_APP_MANAGE_NOTIFY ] = "Session daemon application notification manager",
- [ HEALTH_SESSIOND_TYPE_APP_REG_DISPATCH ] = "Session daemon application registration dispatcher",
- [ HEALTH_SESSIOND_TYPE_ROTATION ] = "Session daemon rotation manager",
- [ HEALTH_SESSIOND_TYPE_TIMER ] = "Session daemon timer manager",
- [ HEALTH_SESSIOND_TYPE_ACTION_EXECUTOR ] = "Session daemon trigger action executor",
-};
-
-static
-const char *consumerd_thread_name[NR_HEALTH_CONSUMERD_TYPES] = {
- [ HEALTH_CONSUMERD_TYPE_CHANNEL ] = "Consumer daemon channel",
- [ HEALTH_CONSUMERD_TYPE_METADATA ] = "Consumer daemon metadata",
- [ HEALTH_CONSUMERD_TYPE_DATA ] = "Consumer daemon data",
- [ HEALTH_CONSUMERD_TYPE_SESSIOND ] = "Consumer daemon session daemon command manager",
- [ HEALTH_CONSUMERD_TYPE_METADATA_TIMER ] = "Consumer daemon metadata timer",
-};
-
-static
-const char *relayd_thread_name[NR_HEALTH_RELAYD_TYPES] = {
- [ HEALTH_RELAYD_TYPE_DISPATCHER ] = "Relay daemon dispatcher",
- [ HEALTH_RELAYD_TYPE_WORKER ] = "Relay daemon worker",
- [ HEALTH_RELAYD_TYPE_LISTENER ] = "Relay daemon listener",
- [ HEALTH_RELAYD_TYPE_LIVE_DISPATCHER ] = "Relay daemon live dispatcher",
- [ HEALTH_RELAYD_TYPE_LIVE_WORKER ] = "Relay daemon live worker",
- [ HEALTH_RELAYD_TYPE_LIVE_LISTENER ] = "Relay daemon live listener",
-};
-
-static
-const char **thread_name[NR_HEALTH_COMPONENT] = {
- [ HEALTH_COMPONENT_SESSIOND ] = sessiond_thread_name,
- [ HEALTH_COMPONENT_CONSUMERD] = consumerd_thread_name,
- [ HEALTH_COMPONENT_RELAYD ] = relayd_thread_name,
-};
-
-/*
- * Set health socket path.
- *
- * Returns 0 on success or a negative errno.
- */
-static
-int set_health_socket_path(struct lttng_health *lh,
- int tracing_group)
-{
- uid_t uid;
- const char *home;
- int ret;
- /* Global and home format strings */
- const char *global_str, *home_str;
-
- switch (lh->component) {
- case HEALTH_COMPONENT_SESSIOND:
- global_str = DEFAULT_GLOBAL_HEALTH_UNIX_SOCK;
- home_str = DEFAULT_HOME_HEALTH_UNIX_SOCK;
- break;
- case HEALTH_COMPONENT_CONSUMERD:
- switch (lh->consumerd_type) {
- case LTTNG_HEALTH_CONSUMERD_UST_32:
- global_str = DEFAULT_GLOBAL_USTCONSUMER32_HEALTH_UNIX_SOCK;
- home_str = DEFAULT_HOME_USTCONSUMER32_HEALTH_UNIX_SOCK;
- break;
- case LTTNG_HEALTH_CONSUMERD_UST_64:
- global_str = DEFAULT_GLOBAL_USTCONSUMER64_HEALTH_UNIX_SOCK;
- home_str = DEFAULT_HOME_USTCONSUMER64_HEALTH_UNIX_SOCK;
- break;
- case LTTNG_HEALTH_CONSUMERD_KERNEL:
- global_str = DEFAULT_GLOBAL_KCONSUMER_HEALTH_UNIX_SOCK;
- home_str = DEFAULT_HOME_KCONSUMER_HEALTH_UNIX_SOCK;
- break;
- default:
- return -EINVAL;
- }
- break;
- case HEALTH_COMPONENT_RELAYD:
- if (lh->health_sock_path[0] == '\0') {
- return -EINVAL;
- } else {
- return 0;
- }
- break; /* Unreached */
- default:
- return -EINVAL;
- }
-
- uid = getuid();
-
- if (uid == 0 || tracing_group) {
- ret = lttng_strncpy(lh->health_sock_path,
- global_str,
- sizeof(lh->health_sock_path));
- return ret == 0 ? 0 : -EINVAL;
- }
-
- /*
- * With GNU C < 2.1, snprintf returns -1 if the target buffer
- * is too small; With GNU C >= 2.1, snprintf returns the
- * required size (excluding closing null).
- */
- home = utils_get_home_dir();
- if (home == NULL) {
- /* Fallback in /tmp */
- home = "/tmp";
- }
-
- ret = snprintf(lh->health_sock_path, sizeof(lh->health_sock_path),
- home_str, home);
- if ((ret < 0) || (ret >= sizeof(lh->health_sock_path))) {
- return -ENOMEM;
- }
-
- return 0;
-}
-
-static
-struct lttng_health *lttng_health_create(enum health_component hc,
- unsigned int nr_threads)
-{
- struct lttng_health *lh;
- int i;
-
- lh = zmalloc(sizeof(*lh) + sizeof(lh->thread[0]) * nr_threads);
- if (!lh) {
- return NULL;
- }
-
- lh->component = hc;
- lh->state = UINT64_MAX; /* All bits in error initially */
- lh->nr_threads = nr_threads;
- for (i = 0; i < nr_threads; i++) {
- lh->thread[i].p = lh;
- }
- return lh;
-}
-
-struct lttng_health *lttng_health_create_sessiond(void)
-{
- struct lttng_health *lh;
-
- lh = lttng_health_create(HEALTH_COMPONENT_SESSIOND,
- NR_HEALTH_SESSIOND_TYPES);
- if (!lh) {
- return NULL;
- }
- return lh;
-}
-
-struct lttng_health *
- lttng_health_create_consumerd(enum lttng_health_consumerd consumerd)
-{
- struct lttng_health *lh;
-
- lh = lttng_health_create(HEALTH_COMPONENT_CONSUMERD,
- NR_HEALTH_CONSUMERD_TYPES);
- if (!lh) {
- return NULL;
- }
- lh->consumerd_type = consumerd;
- return lh;
-}
-
-struct lttng_health *lttng_health_create_relayd(const char *path)
-{
- int ret;
- struct lttng_health *lh = NULL;
-
- if (!path) {
- goto error;
- }
-
- lh = lttng_health_create(HEALTH_COMPONENT_RELAYD,
- NR_HEALTH_RELAYD_TYPES);
- if (!lh) {
- goto error;
- }
-
- ret = lttng_strncpy(lh->health_sock_path, path,
- sizeof(lh->health_sock_path));
- if (ret) {
- goto error;
- }
-
- return lh;
-
-error:
- free(lh);
- return NULL;
-}
-
-void lttng_health_destroy(struct lttng_health *lh)
-{
- free(lh);
-}
-
-int lttng_health_query(struct lttng_health *health)
-{
- int sock, ret, i, tracing_group;
- struct health_comm_msg msg;
- struct health_comm_reply reply;
-
- if (!health) {
- return -EINVAL;
- }
-
- tracing_group = lttng_check_tracing_group();
-retry:
- ret = set_health_socket_path(health, tracing_group);
- if (ret) {
- goto error;
- }
- /* Connect to component */
- sock = lttcomm_connect_unix_sock(health->health_sock_path);
- if (sock < 0) {
- if (tracing_group) {
- /* For tracing group, fallback to per-user */
- tracing_group = 0;
- goto retry;
- }
- ret = -1;
- goto error;
- }
-
- memset(&msg, 0, sizeof(msg));
- msg.cmd = HEALTH_CMD_CHECK;
-
- ret = lttcomm_send_unix_sock(sock, (void *)&msg, sizeof(msg));
- if (ret < 0) {
- ret = -1;
- goto close_error;
- }
-
- ret = lttcomm_recv_unix_sock(sock, (void *)&reply, sizeof(reply));
- if (ret < 0) {
- ret = -1;
- goto close_error;
- }
-
- health->state = reply.ret_code;
- for (i = 0; i < health->nr_threads; i++) {
- if (health->state & (1ULL << i)) {
- health->thread[i].state = -1;
- } else {
- health->thread[i].state = 0;
- }
- }
-
-close_error:
- {
- int closeret;
-
- closeret = close(sock);
- LTTNG_ASSERT(!closeret);
- }
-
-error:
- if (ret >= 0)
- ret = 0;
- return ret;
-}
-
-int lttng_health_state(const struct lttng_health *health)
-{
- if (!health) {
- return -EINVAL;
- }
-
- if (health->state == 0) {
- return 0;
- } else {
- return -1;
- }
-}
-
-int lttng_health_get_nr_threads(const struct lttng_health *health)
-{
- if (!health) {
- return -EINVAL;
- }
- return health->nr_threads;
-}
-
-const struct lttng_health_thread *
- lttng_health_get_thread(const struct lttng_health *health,
- unsigned int nth_thread)
-{
- if (!health || nth_thread >= health->nr_threads) {
- return NULL;
- }
- return &health->thread[nth_thread];
-}
-
-int lttng_health_thread_state(const struct lttng_health_thread *thread)
-{
- if (!thread) {
- return -EINVAL;
- }
- return thread->state;
-}
-
-const char *lttng_health_thread_name(const struct lttng_health_thread *thread)
-{
- unsigned int nr;
-
- if (!thread) {
- return NULL;
- }
- nr = thread - &thread->p->thread[0];
- return thread_name[thread->p->component][nr];
-}
--- /dev/null
+/*
+ * lttng-ctl-health.c
+ *
+ * Linux Trace Toolkit Health Control Library
+ *
+ * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ * Copyright (C) 2013 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#define _LGPL_SOURCE
+#include <unistd.h>
+#include <sys/types.h>
+#include <stdint.h>
+#include <limits.h>
+#include <string.h>
+#include <lttng/health-internal.h>
+
+#include <bin/lttng-sessiond/health-sessiond.h>
+#include <bin/lttng-consumerd/health-consumerd.h>
+#include <bin/lttng-relayd/health-relayd.h>
+#include <common/defaults.h>
+#include <common/utils.h>
+#include <common/compat/errno.h>
+
+#include "lttng-ctl-helper.h"
+
+enum health_component {
+ HEALTH_COMPONENT_SESSIOND,
+ HEALTH_COMPONENT_CONSUMERD,
+ HEALTH_COMPONENT_RELAYD,
+
+ NR_HEALTH_COMPONENT,
+};
+
+struct lttng_health_thread {
+ struct lttng_health *p;
+ int state;
+};
+
+struct lttng_health {
+ enum health_component component;
+ uint64_t state;
+ unsigned int nr_threads;
+ char health_sock_path[PATH_MAX];
+ /* For consumer health only */
+ enum lttng_health_consumerd consumerd_type;
+ struct lttng_health_thread thread[];
+};
+
+static
+const char *get_sessiond_thread_name(health_type_sessiond type) {
+ switch (type)
+ {
+ case HEALTH_SESSIOND_TYPE_CMD:
+ return "Session daemon command";
+ case HEALTH_SESSIOND_TYPE_APP_MANAGE:
+ return "Session daemon application manager";
+ case HEALTH_SESSIOND_TYPE_APP_REG:
+ return "Session daemon application registration";
+ case HEALTH_SESSIOND_TYPE_KERNEL:
+ return "Session daemon kernel";
+ case HEALTH_SESSIOND_TYPE_CONSUMER:
+ return "Session daemon consumer manager";
+ case HEALTH_SESSIOND_TYPE_HT_CLEANUP:
+ return "Session daemon hash table cleanup";
+ case HEALTH_SESSIOND_TYPE_APP_MANAGE_NOTIFY:
+ return "Session daemon application notification manager";
+ case HEALTH_SESSIOND_TYPE_APP_REG_DISPATCH:
+ return "Session daemon application registration dispatcher";
+ case HEALTH_SESSIOND_TYPE_NOTIFICATION:
+ return "Session daemon notification";
+ case HEALTH_SESSIOND_TYPE_ROTATION:
+ return "Session daemon rotation manager";
+ case HEALTH_SESSIOND_TYPE_TIMER:
+ return "Session daemon timer manager";
+ case HEALTH_SESSIOND_TYPE_ACTION_EXECUTOR:
+ return "Session daemon trigger action executor";
+ case NR_HEALTH_SESSIOND_TYPES:
+ abort();
+ }
+
+ abort();
+};
+
+static
+const char *get_consumerd_thread_name(health_type_consumerd type) {
+ switch (type) {
+ case HEALTH_CONSUMERD_TYPE_CHANNEL:
+ return "Consumer daemon channel";
+ case HEALTH_CONSUMERD_TYPE_METADATA:
+ return "Consumer daemon metadata";
+ case HEALTH_CONSUMERD_TYPE_DATA:
+ return "Consumer daemon data";
+ case HEALTH_CONSUMERD_TYPE_SESSIOND:
+ return "Consumer daemon session daemon command manager";
+ case HEALTH_CONSUMERD_TYPE_METADATA_TIMER:
+ return "Consumer daemon metadata timer";
+ case NR_HEALTH_CONSUMERD_TYPES:
+ abort();
+ }
+
+ abort();
+};
+
+static
+const char *get_relayd_thread_name(health_type_relayd type)
+{
+ switch (type) {
+ case HEALTH_RELAYD_TYPE_DISPATCHER:
+ return "Relay daemon dispatcher";
+ case HEALTH_RELAYD_TYPE_WORKER:
+ return "Relay daemon worker";
+ case HEALTH_RELAYD_TYPE_LISTENER:
+ return "Relay daemon listener";
+ case HEALTH_RELAYD_TYPE_LIVE_DISPATCHER:
+ return "Relay daemon live dispatcher";
+ case HEALTH_RELAYD_TYPE_LIVE_WORKER:
+ return "Relay daemon live worker";
+ case HEALTH_RELAYD_TYPE_LIVE_LISTENER:
+ return "Relay daemon live listener";
+ case NR_HEALTH_RELAYD_TYPES:
+ abort();
+ }
+
+ abort();
+}
+
+static
+const char *get_thread_name(int comp, int nr)
+{
+ switch (comp) {
+ case HEALTH_COMPONENT_SESSIOND:
+ return get_sessiond_thread_name((health_type_sessiond) nr);
+ case HEALTH_COMPONENT_CONSUMERD:
+ return get_consumerd_thread_name((health_type_consumerd) nr);
+ case HEALTH_COMPONENT_RELAYD:
+ return get_relayd_thread_name((health_type_relayd) nr);
+ case NR_HEALTH_COMPONENT:
+ abort();
+ }
+
+ abort();
+}
+
+/*
+ * Set health socket path.
+ *
+ * Returns 0 on success or a negative errno.
+ */
+static
+int set_health_socket_path(struct lttng_health *lh,
+ int tracing_group)
+{
+ uid_t uid;
+ const char *home;
+ int ret;
+ /* Global and home format strings */
+ const char *global_str, *home_str;
+
+ switch (lh->component) {
+ case HEALTH_COMPONENT_SESSIOND:
+ global_str = DEFAULT_GLOBAL_HEALTH_UNIX_SOCK;
+ home_str = DEFAULT_HOME_HEALTH_UNIX_SOCK;
+ break;
+ case HEALTH_COMPONENT_CONSUMERD:
+ switch (lh->consumerd_type) {
+ case LTTNG_HEALTH_CONSUMERD_UST_32:
+ global_str = DEFAULT_GLOBAL_USTCONSUMER32_HEALTH_UNIX_SOCK;
+ home_str = DEFAULT_HOME_USTCONSUMER32_HEALTH_UNIX_SOCK;
+ break;
+ case LTTNG_HEALTH_CONSUMERD_UST_64:
+ global_str = DEFAULT_GLOBAL_USTCONSUMER64_HEALTH_UNIX_SOCK;
+ home_str = DEFAULT_HOME_USTCONSUMER64_HEALTH_UNIX_SOCK;
+ break;
+ case LTTNG_HEALTH_CONSUMERD_KERNEL:
+ global_str = DEFAULT_GLOBAL_KCONSUMER_HEALTH_UNIX_SOCK;
+ home_str = DEFAULT_HOME_KCONSUMER_HEALTH_UNIX_SOCK;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ case HEALTH_COMPONENT_RELAYD:
+ if (lh->health_sock_path[0] == '\0') {
+ return -EINVAL;
+ } else {
+ return 0;
+ }
+ break; /* Unreached */
+ default:
+ return -EINVAL;
+ }
+
+ uid = getuid();
+
+ if (uid == 0 || tracing_group) {
+ ret = lttng_strncpy(lh->health_sock_path,
+ global_str,
+ sizeof(lh->health_sock_path));
+ return ret == 0 ? 0 : -EINVAL;
+ }
+
+ /*
+ * With GNU C < 2.1, snprintf returns -1 if the target buffer
+ * is too small; With GNU C >= 2.1, snprintf returns the
+ * required size (excluding closing null).
+ */
+ home = utils_get_home_dir();
+ if (home == NULL) {
+ /* Fallback in /tmp */
+ home = "/tmp";
+ }
+
+ ret = snprintf(lh->health_sock_path, sizeof(lh->health_sock_path),
+ home_str, home);
+ if ((ret < 0) || (ret >= sizeof(lh->health_sock_path))) {
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static
+struct lttng_health *lttng_health_create(enum health_component hc,
+ unsigned int nr_threads)
+{
+ struct lttng_health *lh;
+ int i;
+
+ lh = (lttng_health *) zmalloc(sizeof(*lh) + sizeof(lh->thread[0]) * nr_threads);
+ if (!lh) {
+ return NULL;
+ }
+
+ lh->component = hc;
+ lh->state = UINT64_MAX; /* All bits in error initially */
+ lh->nr_threads = nr_threads;
+ for (i = 0; i < nr_threads; i++) {
+ lh->thread[i].p = lh;
+ }
+ return lh;
+}
+
+struct lttng_health *lttng_health_create_sessiond(void)
+{
+ struct lttng_health *lh;
+
+ lh = lttng_health_create(HEALTH_COMPONENT_SESSIOND,
+ NR_HEALTH_SESSIOND_TYPES);
+ if (!lh) {
+ return NULL;
+ }
+ return lh;
+}
+
+struct lttng_health *
+ lttng_health_create_consumerd(enum lttng_health_consumerd consumerd)
+{
+ struct lttng_health *lh;
+
+ lh = lttng_health_create(HEALTH_COMPONENT_CONSUMERD,
+ NR_HEALTH_CONSUMERD_TYPES);
+ if (!lh) {
+ return NULL;
+ }
+ lh->consumerd_type = consumerd;
+ return lh;
+}
+
+struct lttng_health *lttng_health_create_relayd(const char *path)
+{
+ int ret;
+ struct lttng_health *lh = NULL;
+
+ if (!path) {
+ goto error;
+ }
+
+ lh = lttng_health_create(HEALTH_COMPONENT_RELAYD,
+ NR_HEALTH_RELAYD_TYPES);
+ if (!lh) {
+ goto error;
+ }
+
+ ret = lttng_strncpy(lh->health_sock_path, path,
+ sizeof(lh->health_sock_path));
+ if (ret) {
+ goto error;
+ }
+
+ return lh;
+
+error:
+ free(lh);
+ return NULL;
+}
+
+void lttng_health_destroy(struct lttng_health *lh)
+{
+ free(lh);
+}
+
+int lttng_health_query(struct lttng_health *health)
+{
+ int sock, ret, i, tracing_group;
+ struct health_comm_msg msg;
+ struct health_comm_reply reply;
+
+ if (!health) {
+ return -EINVAL;
+ }
+
+ tracing_group = lttng_check_tracing_group();
+retry:
+ ret = set_health_socket_path(health, tracing_group);
+ if (ret) {
+ goto error;
+ }
+ /* Connect to component */
+ sock = lttcomm_connect_unix_sock(health->health_sock_path);
+ if (sock < 0) {
+ if (tracing_group) {
+ /* For tracing group, fallback to per-user */
+ tracing_group = 0;
+ goto retry;
+ }
+ ret = -1;
+ goto error;
+ }
+
+ memset(&msg, 0, sizeof(msg));
+ msg.cmd = HEALTH_CMD_CHECK;
+
+ ret = lttcomm_send_unix_sock(sock, (void *)&msg, sizeof(msg));
+ if (ret < 0) {
+ ret = -1;
+ goto close_error;
+ }
+
+ ret = lttcomm_recv_unix_sock(sock, (void *)&reply, sizeof(reply));
+ if (ret < 0) {
+ ret = -1;
+ goto close_error;
+ }
+
+ health->state = reply.ret_code;
+ for (i = 0; i < health->nr_threads; i++) {
+ if (health->state & (1ULL << i)) {
+ health->thread[i].state = -1;
+ } else {
+ health->thread[i].state = 0;
+ }
+ }
+
+close_error:
+ {
+ int closeret;
+
+ closeret = close(sock);
+ LTTNG_ASSERT(!closeret);
+ }
+
+error:
+ if (ret >= 0)
+ ret = 0;
+ return ret;
+}
+
+int lttng_health_state(const struct lttng_health *health)
+{
+ if (!health) {
+ return -EINVAL;
+ }
+
+ if (health->state == 0) {
+ return 0;
+ } else {
+ return -1;
+ }
+}
+
+int lttng_health_get_nr_threads(const struct lttng_health *health)
+{
+ if (!health) {
+ return -EINVAL;
+ }
+ return health->nr_threads;
+}
+
+const struct lttng_health_thread *
+ lttng_health_get_thread(const struct lttng_health *health,
+ unsigned int nth_thread)
+{
+ if (!health || nth_thread >= health->nr_threads) {
+ return NULL;
+ }
+ return &health->thread[nth_thread];
+}
+
+int lttng_health_thread_state(const struct lttng_health_thread *thread)
+{
+ if (!thread) {
+ return -EINVAL;
+ }
+ return thread->state;
+}
+
+const char *lttng_health_thread_name(const struct lttng_health_thread *thread)
+{
+ unsigned int nr;
+
+ if (!thread) {
+ return NULL;
+ }
+ nr = thread - &thread->p->thread[0];
+ return get_thread_name (thread->p->component, nr);
+}
+++ /dev/null
-/*
- * lttng-ctl.c
- *
- * Linux Trace Toolkit Control Library
- *
- * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
- * Copyright (C) 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#define _LGPL_SOURCE
-#include <grp.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <common/bytecode/bytecode.h>
-#include <common/align.h>
-#include <common/common.h>
-#include <common/compat/errno.h>
-#include <common/compat/string.h>
-#include <common/defaults.h>
-#include <common/dynamic-array.h>
-#include <common/dynamic-buffer.h>
-#include <common/payload-view.h>
-#include <common/payload.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <common/tracker.h>
-#include <common/unix.h>
-#include <common/uri.h>
-#include <common/utils.h>
-#include <lttng/channel-internal.h>
-#include <lttng/destruction-handle.h>
-#include <lttng/endpoint.h>
-#include <lttng/error-query-internal.h>
-#include <lttng/event-internal.h>
-#include <lttng/health-internal.h>
-#include <lttng/lttng-error.h>
-#include <lttng/lttng.h>
-#include <lttng/session-descriptor-internal.h>
-#include <lttng/session-internal.h>
-#include <lttng/trigger/trigger-internal.h>
-#include <lttng/userspace-probe-internal.h>
-
-#include "lttng-ctl-helper.h"
-#include <common/filter/filter-ast.h>
-#include <common/filter/filter-parser.h>
-#include <common/filter/memstream.h>
-
-#define COPY_DOMAIN_PACKED(dst, src) \
-do { \
- struct lttng_domain _tmp_domain; \
- \
- lttng_ctl_copy_lttng_domain(&_tmp_domain, &src); \
- dst = _tmp_domain; \
-} while (0)
-
-/* Socket to session daemon for communication */
-static int sessiond_socket = -1;
-static char sessiond_sock_path[PATH_MAX];
-
-/* Variables */
-static char *tracing_group;
-static int connected;
-
-/* Global */
-
-/*
- * Those two variables are used by error.h to silent or control the verbosity of
- * error message. They are global to the library so application linking with it
- * are able to compile correctly and also control verbosity of the library.
- */
-int lttng_opt_quiet;
-int lttng_opt_verbose;
-int lttng_opt_mi;
-
-/*
- * Copy domain to lttcomm_session_msg domain.
- *
- * If domain is unknown, default domain will be the kernel.
- */
-void lttng_ctl_copy_lttng_domain(struct lttng_domain *dst,
- struct lttng_domain *src)
-{
- if (src && dst) {
- switch (src->type) {
- case LTTNG_DOMAIN_KERNEL:
- case LTTNG_DOMAIN_UST:
- case LTTNG_DOMAIN_JUL:
- case LTTNG_DOMAIN_LOG4J:
- case LTTNG_DOMAIN_PYTHON:
- memcpy(dst, src, sizeof(struct lttng_domain));
- break;
- default:
- memset(dst, 0, sizeof(struct lttng_domain));
- break;
- }
- }
-}
-
-/*
- * Send lttcomm_session_msg to the session daemon.
- *
- * On success, returns the number of bytes sent (>=0)
- * On error, returns -1
- */
-static int send_session_msg(struct lttcomm_session_msg *lsm)
-{
- int ret;
-
- if (!connected) {
- ret = -LTTNG_ERR_NO_SESSIOND;
- goto end;
- }
-
- DBG("LSM cmd type: '%s' (%d)", lttcomm_sessiond_command_str(lsm->cmd_type),
- lsm->cmd_type);
-
- ret = lttcomm_send_creds_unix_sock(sessiond_socket, lsm,
- sizeof(struct lttcomm_session_msg));
- if (ret < 0) {
- ret = -LTTNG_ERR_FATAL;
- }
-
-end:
- return ret;
-}
-
-/*
- * Send var len data to the session daemon.
- *
- * On success, returns the number of bytes sent (>=0)
- * On error, returns -1
- */
-static int send_session_varlen(const void *data, size_t len)
-{
- int ret;
-
- if (!connected) {
- ret = -LTTNG_ERR_NO_SESSIOND;
- goto end;
- }
-
- if (!data || !len) {
- ret = 0;
- goto end;
- }
-
- ret = lttcomm_send_unix_sock(sessiond_socket, data, len);
- if (ret < 0) {
- ret = -LTTNG_ERR_FATAL;
- }
-
-end:
- return ret;
-}
-
-/*
- * Send file descriptors to the session daemon.
- *
- * On success, returns the number of bytes sent (>=0)
- * On error, returns -1
- */
-static int send_session_fds(const int *fds, size_t nb_fd)
-{
- int ret;
-
- if (!connected) {
- ret = -LTTNG_ERR_NO_SESSIOND;
- goto end;
- }
-
- if (!fds || !nb_fd) {
- ret = 0;
- goto end;
- }
-
- ret = lttcomm_send_fds_unix_sock(sessiond_socket, fds, nb_fd);
- if (ret < 0) {
- ret = -LTTNG_ERR_FATAL;
- }
-
-end:
- return ret;
-}
-
-/*
- * Receive data from the sessiond socket.
- *
- * On success, returns the number of bytes received (>=0)
- * On error, returns a negative lttng_error_code.
- */
-static int recv_data_sessiond(void *buf, size_t len)
-{
- int ret;
-
- LTTNG_ASSERT(len > 0);
-
- if (!connected) {
- ret = -LTTNG_ERR_NO_SESSIOND;
- goto end;
- }
-
- ret = lttcomm_recv_unix_sock(sessiond_socket, buf, len);
- if (ret < 0) {
- ret = -LTTNG_ERR_FATAL;
- } else if (ret == 0) {
- ret = -LTTNG_ERR_NO_SESSIOND;
- }
-
-end:
- return ret;
-}
-
-/*
- * Receive a payload from the session daemon by appending to an existing
- * payload.
- * On success, returns the number of bytes received (>=0)
- * On error, returns a negative lttng_error_code.
- */
-static int recv_payload_sessiond(struct lttng_payload *payload, size_t len)
-{
- int ret;
- const size_t original_payload_size = payload->buffer.size;
-
- ret = lttng_dynamic_buffer_set_size(
- &payload->buffer, payload->buffer.size + len);
- if (ret) {
- ret = -LTTNG_ERR_NOMEM;
- goto end;
- }
-
- ret = recv_data_sessiond(
- payload->buffer.data + original_payload_size, len);
-end:
- return ret;
-}
-
-/*
- * Check if we are in the specified group.
- *
- * If yes return 1, else return -1.
- */
-int lttng_check_tracing_group(void)
-{
- gid_t *grp_list, tracing_gid;
- int grp_list_size, grp_id, i;
- int ret = -1;
- const char *grp_name = tracing_group;
-
- /* Get GID of group 'tracing' */
- if (utils_get_group_id(grp_name, false, &tracing_gid)) {
- /* If grp_tracing is NULL, the group does not exist. */
- goto end;
- }
-
- /* Get number of supplementary group IDs */
- grp_list_size = getgroups(0, NULL);
- if (grp_list_size < 0) {
- PERROR("getgroups");
- goto end;
- }
-
- /* Alloc group list of the right size */
- grp_list = zmalloc(grp_list_size * sizeof(gid_t));
- if (!grp_list) {
- PERROR("malloc");
- goto end;
- }
- grp_id = getgroups(grp_list_size, grp_list);
- if (grp_id < 0) {
- PERROR("getgroups");
- goto free_list;
- }
-
- for (i = 0; i < grp_list_size; i++) {
- if (grp_list[i] == tracing_gid) {
- ret = 1;
- break;
- }
- }
-
-free_list:
- free(grp_list);
-
-end:
- return ret;
-}
-
-static int check_enough_available_memory(size_t num_bytes_requested_per_cpu)
-{
- int ret;
- long num_cpu;
- size_t best_mem_info;
- size_t num_bytes_requested_total;
-
- /*
- * Get the number of CPU currently online to compute the amount of
- * memory needed to create a buffer for every CPU.
- */
- num_cpu = sysconf(_SC_NPROCESSORS_ONLN);
- if (num_cpu == -1) {
- goto error;
- }
-
- num_bytes_requested_total = num_bytes_requested_per_cpu * num_cpu;
-
- /*
- * Try to get the `MemAvail` field of `/proc/meminfo`. This is the most
- * reliable estimate we can get but it is only exposed by the kernel
- * since 3.14. (See Linux kernel commit:
- * 34e431b0ae398fc54ea69ff85ec700722c9da773)
- */
- ret = utils_get_memory_available(&best_mem_info);
- if (ret >= 0) {
- goto success;
- }
-
- /*
- * As a backup plan, use `MemTotal` field of `/proc/meminfo`. This
- * is a sanity check for obvious user error.
- */
- ret = utils_get_memory_total(&best_mem_info);
- if (ret >= 0) {
- goto success;
- }
-
-error:
- return -1;
-success:
- return best_mem_info >= num_bytes_requested_total;
-}
-
-/*
- * Try connect to session daemon with sock_path.
- *
- * Return 0 on success, else -1
- */
-static int try_connect_sessiond(const char *sock_path)
-{
- int ret;
-
- /* If socket exist, we check if the daemon listens for connect. */
- ret = access(sock_path, F_OK);
- if (ret < 0) {
- /* Not alive */
- goto error;
- }
-
- ret = lttcomm_connect_unix_sock(sock_path);
- if (ret < 0) {
- /* Not alive. */
- goto error;
- }
-
- ret = lttcomm_close_unix_sock(ret);
- if (ret < 0) {
- PERROR("lttcomm_close_unix_sock");
- }
-
- return 0;
-
-error:
- return -1;
-}
-
-/*
- * Set sessiond socket path by putting it in the global sessiond_sock_path
- * variable.
- *
- * Returns 0 on success, negative value on failure (the sessiond socket path
- * is somehow too long or ENOMEM).
- */
-static int set_session_daemon_path(void)
-{
- int in_tgroup = 0; /* In tracing group. */
- uid_t uid;
-
- uid = getuid();
-
- if (uid != 0) {
- /* Are we in the tracing group ? */
- in_tgroup = lttng_check_tracing_group();
- }
-
- if ((uid == 0) || in_tgroup == 1) {
- const int ret = lttng_strncpy(sessiond_sock_path,
- DEFAULT_GLOBAL_CLIENT_UNIX_SOCK,
- sizeof(sessiond_sock_path));
-
- if (ret) {
- goto error;
- }
- }
-
- if (uid != 0) {
- int ret;
-
- if (in_tgroup) {
- /* Tracing group. */
- ret = try_connect_sessiond(sessiond_sock_path);
- if (ret >= 0) {
- goto end;
- }
- /* Global session daemon not available... */
- }
- /* ...or not in tracing group (and not root), default */
-
- /*
- * With GNU C < 2.1, snprintf returns -1 if the target buffer
- * is too small;
- * With GNU C >= 2.1, snprintf returns the required size
- * (excluding closing null)
- */
- ret = snprintf(sessiond_sock_path, sizeof(sessiond_sock_path),
- DEFAULT_HOME_CLIENT_UNIX_SOCK, utils_get_home_dir());
- if ((ret < 0) || (ret >= sizeof(sessiond_sock_path))) {
- goto error;
- }
- }
-end:
- return 0;
-
-error:
- return -1;
-}
-
-/*
- * Connect to the LTTng session daemon.
- *
- * On success, return the socket's file descriptor. On error, return -1.
- */
-int connect_sessiond(void)
-{
- int ret;
-
- ret = set_session_daemon_path();
- if (ret < 0) {
- goto error;
- }
-
- /* Connect to the sesssion daemon. */
- ret = lttcomm_connect_unix_sock(sessiond_sock_path);
- if (ret < 0) {
- goto error;
- }
-
- return ret;
-
-error:
- return -1;
-}
-
-static void reset_global_sessiond_connection_state(void)
-{
- sessiond_socket = -1;
- connected = 0;
-}
-
-/*
- * Clean disconnect from the session daemon.
- *
- * On success, return 0. On error, return -1.
- */
-static int disconnect_sessiond(void)
-{
- int ret = 0;
-
- if (connected) {
- ret = lttcomm_close_unix_sock(sessiond_socket);
- reset_global_sessiond_connection_state();
- }
-
- return ret;
-}
-
-static int recv_sessiond_optional_data(size_t len, void **user_buf,
- size_t *user_len)
-{
- int ret = 0;
- void *buf = NULL;
-
- if (len) {
- if (!user_len) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- buf = zmalloc(len);
- if (!buf) {
- ret = -ENOMEM;
- goto end;
- }
-
- ret = recv_data_sessiond(buf, len);
- if (ret < 0) {
- goto end;
- }
-
- if (!user_buf) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- /* Move ownership of command header buffer to user. */
- *user_buf = buf;
- buf = NULL;
- *user_len = len;
- } else {
- /* No command header. */
- if (user_len) {
- *user_len = 0;
- }
-
- if (user_buf) {
- *user_buf = NULL;
- }
- }
-
-end:
- free(buf);
- return ret;
-}
-
-/*
- * Ask the session daemon a specific command and put the data into buf.
- * Takes extra var. len. data and file descriptors as input to send to the
- * session daemon.
- *
- * Return size of data (only payload, not header) or a negative error code.
- */
-int lttng_ctl_ask_sessiond_fds_varlen(struct lttcomm_session_msg *lsm,
- const int *fds, size_t nb_fd, const void *vardata,
- size_t vardata_len, void **user_payload_buf,
- void **user_cmd_header_buf, size_t *user_cmd_header_len)
-{
- int ret;
- size_t payload_len;
- struct lttcomm_lttng_msg llm;
-
- ret = connect_sessiond();
- if (ret < 0) {
- ret = -LTTNG_ERR_NO_SESSIOND;
- goto end;
- } else {
- sessiond_socket = ret;
- connected = 1;
- }
-
- ret = send_session_msg(lsm);
- if (ret < 0) {
- /* Ret value is a valid lttng error code. */
- goto end;
- }
- /* Send var len data */
- ret = send_session_varlen(vardata, vardata_len);
- if (ret < 0) {
- /* Ret value is a valid lttng error code. */
- goto end;
- }
-
- /* Send fds */
- ret = send_session_fds(fds, nb_fd);
- if (ret < 0) {
- /* Ret value is a valid lttng error code. */
- goto end;
- }
-
- /* Get header from data transmission */
- ret = recv_data_sessiond(&llm, sizeof(llm));
- if (ret < 0) {
- /* Ret value is a valid lttng error code. */
- goto end;
- }
-
- /* Check error code if OK */
- if (llm.ret_code != LTTNG_OK) {
- ret = -llm.ret_code;
- goto end;
- }
-
- /* Get command header from data transmission */
- ret = recv_sessiond_optional_data(llm.cmd_header_size,
- user_cmd_header_buf, user_cmd_header_len);
- if (ret < 0) {
- goto end;
- }
-
- /* Get payload from data transmission */
- ret = recv_sessiond_optional_data(llm.data_size, user_payload_buf,
- &payload_len);
- if (ret < 0) {
- goto end;
- }
-
- ret = llm.data_size;
-
-end:
- disconnect_sessiond();
- return ret;
-}
-
-int lttng_ctl_ask_sessiond_payload(struct lttng_payload_view *message,
- struct lttng_payload *reply)
-{
- int ret;
- struct lttcomm_lttng_msg llm;
- const int fd_count = lttng_payload_view_get_fd_handle_count(message);
-
- LTTNG_ASSERT(reply->buffer.size == 0);
- LTTNG_ASSERT(lttng_dynamic_pointer_array_get_count(&reply->_fd_handles) == 0);
-
- ret = connect_sessiond();
- if (ret < 0) {
- ret = -LTTNG_ERR_NO_SESSIOND;
- goto end;
- } else {
- sessiond_socket = ret;
- connected = 1;
- }
-
- /* Send command to session daemon */
- ret = lttcomm_send_creds_unix_sock(sessiond_socket, message->buffer.data,
- message->buffer.size);
- if (ret < 0) {
- ret = -LTTNG_ERR_FATAL;
- goto end;
- }
-
- if (fd_count > 0) {
- ret = lttcomm_send_payload_view_fds_unix_sock(sessiond_socket,
- message);
- if (ret < 0) {
- ret = -LTTNG_ERR_FATAL;
- goto end;
- }
- }
-
- /* Get header from data transmission */
- ret = recv_payload_sessiond(reply, sizeof(llm));
- if (ret < 0) {
- /* Ret value is a valid lttng error code. */
- goto end;
- }
-
- llm = *((typeof(llm) *) reply->buffer.data);
-
- /* Check error code if OK */
- if (llm.ret_code != LTTNG_OK) {
- if (llm.ret_code < LTTNG_OK || llm.ret_code >= LTTNG_ERR_NR) {
- /* Invalid error code received. */
- ret = -LTTNG_ERR_UNK;
- } else {
- ret = -llm.ret_code;
- }
- goto end;
- }
-
- if (llm.cmd_header_size > 0) {
- ret = recv_payload_sessiond(reply, llm.cmd_header_size);
- if (ret < 0) {
- goto end;
- }
- }
-
- /* Get command header from data transmission */
- if (llm.data_size > 0) {
- ret = recv_payload_sessiond(reply, llm.data_size);
- if (ret < 0) {
- goto end;
- }
- }
-
- if (llm.fd_count > 0) {
- ret = lttcomm_recv_payload_fds_unix_sock(
- sessiond_socket, llm.fd_count, reply);
- if (ret < 0) {
- goto end;
- }
- }
-
- /* Don't return the llm header to the caller. */
- memmove(reply->buffer.data, reply->buffer.data + sizeof(llm),
- reply->buffer.size - sizeof(llm));
- ret = lttng_dynamic_buffer_set_size(
- &reply->buffer, reply->buffer.size - sizeof(llm));
- if (ret) {
- /* Can't happen as size is reduced. */
- abort();
- }
-
- ret = reply->buffer.size;
-
-end:
- disconnect_sessiond();
- return ret;
-}
-
-/*
- * Create lttng handle and return pointer.
- *
- * The returned pointer will be NULL in case of malloc() error.
- */
-struct lttng_handle *lttng_create_handle(const char *session_name,
- struct lttng_domain *domain)
-{
- int ret;
- struct lttng_handle *handle = NULL;
-
- handle = zmalloc(sizeof(struct lttng_handle));
- if (handle == NULL) {
- PERROR("malloc handle");
- goto end;
- }
-
- /* Copy session name */
- ret = lttng_strncpy(handle->session_name, session_name ? : "",
- sizeof(handle->session_name));
- if (ret) {
- goto error;
- }
-
- /* Copy lttng domain or leave initialized to 0. */
- if (domain) {
- lttng_ctl_copy_lttng_domain(&handle->domain, domain);
- }
-
-end:
- return handle;
-error:
- free(handle);
- return NULL;
-}
-
-/*
- * Destroy handle by free(3) the pointer.
- */
-void lttng_destroy_handle(struct lttng_handle *handle)
-{
- free(handle);
-}
-
-/*
- * Register an outside consumer.
- *
- * Returns size of returned session payload data or a negative error code.
- */
-int lttng_register_consumer(struct lttng_handle *handle,
- const char *socket_path)
-{
- int ret;
- struct lttcomm_session_msg lsm;
-
- if (handle == NULL || socket_path == NULL) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- memset(&lsm, 0, sizeof(lsm));
- lsm.cmd_type = LTTNG_REGISTER_CONSUMER;
- ret = lttng_strncpy(lsm.session.name, handle->session_name,
- sizeof(lsm.session.name));
- if (ret) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- COPY_DOMAIN_PACKED(lsm.domain, handle->domain);
-
- ret = lttng_strncpy(lsm.u.reg.path, socket_path,
- sizeof(lsm.u.reg.path));
- if (ret) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- ret = lttng_ctl_ask_sessiond(&lsm, NULL);
-end:
- return ret;
-}
-
-/*
- * Start tracing for all traces of the session.
- *
- * Returns size of returned session payload data or a negative error code.
- */
-int lttng_start_tracing(const char *session_name)
-{
- int ret;
- struct lttcomm_session_msg lsm;
-
- if (session_name == NULL) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- memset(&lsm, 0, sizeof(lsm));
- lsm.cmd_type = LTTNG_START_TRACE;
-
- ret = lttng_strncpy(lsm.session.name, session_name,
- sizeof(lsm.session.name));
- if (ret) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- ret = lttng_ctl_ask_sessiond(&lsm, NULL);
-end:
- return ret;
-}
-
-/*
- * Stop tracing for all traces of the session.
- */
-static int _lttng_stop_tracing(const char *session_name, int wait)
-{
- int ret, data_ret;
- struct lttcomm_session_msg lsm;
-
- if (session_name == NULL) {
- ret = -LTTNG_ERR_INVALID;
- goto error;
- }
-
- memset(&lsm, 0, sizeof(lsm));
- lsm.cmd_type = LTTNG_STOP_TRACE;
-
- ret = lttng_strncpy(lsm.session.name, session_name,
- sizeof(lsm.session.name));
- if (ret) {
- ret = -LTTNG_ERR_INVALID;
- goto error;
- }
-
- ret = lttng_ctl_ask_sessiond(&lsm, NULL);
- if (ret < 0 && ret != -LTTNG_ERR_TRACE_ALREADY_STOPPED) {
- goto error;
- }
-
- if (!wait) {
- goto end;
- }
-
- /* Check for data availability */
- do {
- data_ret = lttng_data_pending(session_name);
- if (data_ret < 0) {
- /* Return the data available call error. */
- ret = data_ret;
- goto error;
- }
-
- /*
- * Data sleep time before retrying (in usec). Don't sleep if the
- * call returned value indicates availability.
- */
- if (data_ret) {
- usleep(DEFAULT_DATA_AVAILABILITY_WAIT_TIME_US);
- }
- } while (data_ret != 0);
-
-end:
-error:
- return ret;
-}
-
-/*
- * Stop tracing and wait for data availability.
- */
-int lttng_stop_tracing(const char *session_name)
-{
- return _lttng_stop_tracing(session_name, 1);
-}
-
-/*
- * Stop tracing but _don't_ wait for data availability.
- */
-int lttng_stop_tracing_no_wait(const char *session_name)
-{
- return _lttng_stop_tracing(session_name, 0);
-}
-
-/*
- * Add context to a channel.
- *
- * If the given channel is NULL, add the contexts to all channels.
- * The event_name param is ignored.
- *
- * Returns the size of the returned payload data or a negative error code.
- */
-int lttng_add_context(struct lttng_handle *handle,
- struct lttng_event_context *ctx, const char *event_name,
- const char *channel_name)
-{
- int ret;
- size_t len = 0;
- char *buf = NULL;
- struct lttcomm_session_msg lsm;
-
- /* Safety check. Both are mandatory. */
- if (handle == NULL || ctx == NULL) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- memset(&lsm, 0, sizeof(lsm));
- lsm.cmd_type = LTTNG_ADD_CONTEXT;
-
- /* If no channel name, send empty string. */
- ret = lttng_strncpy(lsm.u.context.channel_name, channel_name ?: "",
- sizeof(lsm.u.context.channel_name));
- if (ret) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- COPY_DOMAIN_PACKED(lsm.domain, handle->domain);
- ret = lttng_strncpy(lsm.session.name, handle->session_name,
- sizeof(lsm.session.name));
- if (ret) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- if (ctx->ctx == LTTNG_EVENT_CONTEXT_APP_CONTEXT) {
- size_t provider_len, ctx_len;
- const char *provider_name = ctx->u.app_ctx.provider_name;
- const char *ctx_name = ctx->u.app_ctx.ctx_name;
-
- if (!provider_name || !ctx_name) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- provider_len = strlen(provider_name);
- if (provider_len == 0) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
- lsm.u.context.provider_name_len = provider_len;
-
- ctx_len = strlen(ctx_name);
- if (ctx_len == 0) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
- lsm.u.context.context_name_len = ctx_len;
-
- len = provider_len + ctx_len;
- buf = zmalloc(len);
- if (!buf) {
- ret = -LTTNG_ERR_NOMEM;
- goto end;
- }
-
- memcpy(buf, provider_name, provider_len);
- memcpy(buf + provider_len, ctx_name, ctx_len);
- }
- memcpy(&lsm.u.context.ctx, ctx, sizeof(struct lttng_event_context));
-
- if (ctx->ctx == LTTNG_EVENT_CONTEXT_APP_CONTEXT) {
- /*
- * Don't leak application addresses to the sessiond.
- * This is only necessary when ctx is for an app ctx otherwise
- * the values inside the union (type & config) are overwritten.
- */
- lsm.u.context.ctx.u.app_ctx.provider_name = NULL;
- lsm.u.context.ctx.u.app_ctx.ctx_name = NULL;
- }
-
- ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header(&lsm, buf, len, NULL);
-end:
- free(buf);
- return ret;
-}
-
-/*
- * Enable event(s) for a channel.
- *
- * If no event name is specified, all events are enabled.
- * If no channel name is specified, the default 'channel0' is used.
- *
- * Returns size of returned session payload data or a negative error code.
- */
-int lttng_enable_event(struct lttng_handle *handle,
- struct lttng_event *ev, const char *channel_name)
-{
- return lttng_enable_event_with_exclusions(handle, ev, channel_name,
- NULL, 0, NULL);
-}
-
-/*
- * Create or enable an event with a filter expression.
- *
- * Return negative error value on error.
- * Return size of returned session payload data if OK.
- */
-int lttng_enable_event_with_filter(struct lttng_handle *handle,
- struct lttng_event *event, const char *channel_name,
- const char *filter_expression)
-{
- return lttng_enable_event_with_exclusions(handle, event, channel_name,
- filter_expression, 0, NULL);
-}
-
-/*
- * Depending on the event, return a newly allocated agent filter expression or
- * NULL if not applicable.
- *
- * An event with NO loglevel and the name is * will return NULL.
- */
-static char *set_agent_filter(const char *filter, struct lttng_event *ev)
-{
- int err;
- char *agent_filter = NULL;
-
- LTTNG_ASSERT(ev);
-
- /* Don't add filter for the '*' event. */
- if (strcmp(ev->name, "*") != 0) {
- if (filter) {
- err = asprintf(&agent_filter, "(%s) && (logger_name == \"%s\")", filter,
- ev->name);
- } else {
- err = asprintf(&agent_filter, "logger_name == \"%s\"", ev->name);
- }
- if (err < 0) {
- PERROR("asprintf");
- goto error;
- }
- }
-
- /* Add loglevel filtering if any for the JUL domain. */
- if (ev->loglevel_type != LTTNG_EVENT_LOGLEVEL_ALL) {
- const char *op;
-
- if (ev->loglevel_type == LTTNG_EVENT_LOGLEVEL_RANGE) {
- op = ">=";
- } else {
- op = "==";
- }
-
- if (filter || agent_filter) {
- char *new_filter;
-
- err = asprintf(&new_filter, "(%s) && (int_loglevel %s %d)",
- agent_filter ? agent_filter : filter, op,
- ev->loglevel);
- if (agent_filter) {
- free(agent_filter);
- }
- agent_filter = new_filter;
- } else {
- err = asprintf(&agent_filter, "int_loglevel %s %d", op,
- ev->loglevel);
- }
- if (err < 0) {
- PERROR("asprintf");
- goto error;
- }
- }
-
- return agent_filter;
-error:
- free(agent_filter);
- return NULL;
-}
-
-/*
- * Enable event(s) for a channel, possibly with exclusions and a filter.
- * If no event name is specified, all events are enabled.
- * If no channel name is specified, the default name is used.
- * If filter expression is not NULL, the filter is set for the event.
- * If exclusion count is not zero, the exclusions are set for the event.
- * Returns size of returned session payload data or a negative error code.
- */
-int lttng_enable_event_with_exclusions(struct lttng_handle *handle,
- struct lttng_event *ev, const char *channel_name,
- const char *original_filter_expression,
- int exclusion_count, char **exclusion_list)
-{
- struct lttcomm_session_msg lsm;
- struct lttng_payload payload;
- int ret = 0, i;
- unsigned int free_filter_expression = 0;
- struct filter_parser_ctx *ctx = NULL;
-
- /*
- * We have either a filter or some exclusions, so we need to set up
- * a variable-length payload from where to send the data.
- */
- lttng_payload_init(&payload);
-
- /*
- * Cast as non-const since we may replace the filter expression
- * by a dynamically allocated string. Otherwise, the original
- * string is not modified.
- */
- char *filter_expression = (char *) original_filter_expression;
-
- if (handle == NULL || ev == NULL) {
- ret = -LTTNG_ERR_INVALID;
- goto error;
- }
-
- /*
- * Empty filter string will always be rejected by the parser
- * anyway, so treat this corner-case early to eliminate
- * lttng_fmemopen error for 0-byte allocation.
- */
- if (filter_expression && filter_expression[0] == '\0') {
- ret = -LTTNG_ERR_INVALID;
- goto error;
- }
-
- memset(&lsm, 0, sizeof(lsm));
-
- /* If no channel name, send empty string. */
- ret = lttng_strncpy(lsm.u.enable.channel_name, channel_name ?: "",
- sizeof(lsm.u.enable.channel_name));
- if (ret) {
- ret = -LTTNG_ERR_INVALID;
- goto error;
- }
-
- lsm.cmd_type = LTTNG_ENABLE_EVENT;
- if (ev->name[0] == '\0') {
- /* Enable all events. */
- ret = lttng_strncpy(ev->name, "*", sizeof(ev->name));
- LTTNG_ASSERT(ret == 0);
- }
-
- COPY_DOMAIN_PACKED(lsm.domain, handle->domain);
- memcpy(&lsm.u.enable.event, ev, sizeof(lsm.u.enable.event));
-
- ret = lttng_strncpy(lsm.session.name, handle->session_name,
- sizeof(lsm.session.name));
- if (ret) {
- ret = -LTTNG_ERR_INVALID;
- goto error;
- }
-
- lsm.u.enable.exclusion_count = exclusion_count;
- lsm.u.enable.bytecode_len = 0;
-
- /* Parse filter expression. */
- if (filter_expression != NULL || handle->domain.type == LTTNG_DOMAIN_JUL
- || handle->domain.type == LTTNG_DOMAIN_LOG4J
- || handle->domain.type == LTTNG_DOMAIN_PYTHON) {
- if (handle->domain.type == LTTNG_DOMAIN_JUL ||
- handle->domain.type == LTTNG_DOMAIN_LOG4J ||
- handle->domain.type == LTTNG_DOMAIN_PYTHON) {
- char *agent_filter;
-
- /* Setup JUL filter if needed. */
- agent_filter = set_agent_filter(filter_expression, ev);
- if (!agent_filter) {
- if (!filter_expression) {
- /*
- * No JUL and no filter, just skip
- * everything below.
- */
- goto ask_sessiond;
- }
- } else {
- /*
- * With an agent filter, the original filter has
- * been added to it thus replace the filter
- * expression.
- */
- filter_expression = agent_filter;
- free_filter_expression = 1;
- }
- }
-
- ret = filter_parser_ctx_create_from_filter_expression(filter_expression, &ctx);
- if (ret) {
- goto filter_error;
- }
-
- lsm.u.enable.bytecode_len = sizeof(ctx->bytecode->b)
- + bytecode_get_len(&ctx->bytecode->b);
- lsm.u.enable.expression_len = strlen(filter_expression) + 1;
- }
-
- ret = lttng_dynamic_buffer_set_capacity(&payload.buffer,
- lsm.u.enable.bytecode_len +
- lsm.u.enable.expression_len +
- LTTNG_SYMBOL_NAME_LEN *
- exclusion_count);
- if (ret) {
- ret = -LTTNG_ERR_EXCLUSION_NOMEM;
- goto mem_error;
- }
-
- /* Put exclusion names first in the data. */
- for (i = 0; i < exclusion_count; i++) {
- size_t exclusion_len;
-
- exclusion_len = lttng_strnlen(exclusion_list[i],
- LTTNG_SYMBOL_NAME_LEN);
- if (exclusion_len == LTTNG_SYMBOL_NAME_LEN) {
- /* Exclusion is not NULL-terminated. */
- ret = -LTTNG_ERR_INVALID;
- goto mem_error;
- }
-
- ret = lttng_dynamic_buffer_append(&payload.buffer,
- exclusion_list[i], exclusion_len);
- if (ret) {
- goto mem_error;
- }
-
- /*
- * Padding the rest of the entry with zeros. Every exclusion
- * entries take LTTNG_SYMBOL_NAME_LEN bytes in the buffer.
- */
- ret = lttng_dynamic_buffer_set_size(&payload.buffer,
- LTTNG_SYMBOL_NAME_LEN * (i + 1));
- if (ret) {
- goto mem_error;
- }
- }
-
- /* Add filter expression next. */
- if (filter_expression) {
- ret = lttng_dynamic_buffer_append(&payload.buffer,
- filter_expression, lsm.u.enable.expression_len);
- if (ret) {
- goto mem_error;
- }
- }
- /* Add filter bytecode next. */
- if (ctx && lsm.u.enable.bytecode_len != 0) {
- ret = lttng_dynamic_buffer_append(&payload.buffer,
- &ctx->bytecode->b, lsm.u.enable.bytecode_len);
- if (ret) {
- goto mem_error;
- }
- }
- if (ev->extended.ptr) {
- struct lttng_event_extended *ev_ext =
- (struct lttng_event_extended *) ev->extended.ptr;
-
- if (ev_ext->probe_location) {
- /*
- * lttng_userspace_probe_location_serialize returns the
- * number of bytes that was appended to the buffer.
- */
- ret = lttng_userspace_probe_location_serialize(
- ev_ext->probe_location, &payload);
- if (ret < 0) {
- goto mem_error;
- }
-
- /*
- * Set the size of the userspace probe location element
- * of the buffer so that the receiving side knows where
- * to split it.
- */
- lsm.u.enable.userspace_probe_location_len = ret;
- }
- }
-
- {
- struct lttng_payload_view view = lttng_payload_view_from_payload(
- &payload, 0, -1);
- int fd_count = lttng_payload_view_get_fd_handle_count(&view);
- int fd_to_send;
-
- if (fd_count < 0) {
- goto mem_error;
- }
-
- LTTNG_ASSERT(fd_count == 0 || fd_count == 1);
- if (fd_count == 1) {
- struct fd_handle *h =
- lttng_payload_view_pop_fd_handle(&view);
-
- if (!h) {
- goto mem_error;
- }
-
- fd_to_send = fd_handle_get_fd(h);
- fd_handle_put(h);
- }
-
- ret = lttng_ctl_ask_sessiond_fds_varlen(&lsm,
- fd_count ? &fd_to_send : NULL, fd_count,
- view.buffer.size ? view.buffer.data : NULL,
- view.buffer.size, NULL, NULL, 0);
- }
-
-mem_error:
- if (filter_expression && ctx) {
- filter_bytecode_free(ctx);
- filter_ir_free(ctx);
- filter_parser_ctx_free(ctx);
- }
-filter_error:
- if (free_filter_expression) {
- /*
- * The filter expression has been replaced and must be freed as
- * it is not the original filter expression received as a
- * parameter.
- */
- free(filter_expression);
- }
-error:
- /*
- * Return directly to the caller and don't ask the sessiond since
- * something went wrong in the parsing of data above.
- */
- lttng_payload_reset(&payload);
- return ret;
-
-ask_sessiond:
- ret = lttng_ctl_ask_sessiond(&lsm, NULL);
- return ret;
-}
-
-int lttng_disable_event_ext(struct lttng_handle *handle,
- struct lttng_event *ev, const char *channel_name,
- const char *original_filter_expression)
-{
- struct lttcomm_session_msg lsm;
- char *varlen_data;
- int ret = 0;
- unsigned int free_filter_expression = 0;
- struct filter_parser_ctx *ctx = NULL;
- /*
- * Cast as non-const since we may replace the filter expression
- * by a dynamically allocated string. Otherwise, the original
- * string is not modified.
- */
- char *filter_expression = (char *) original_filter_expression;
-
- if (handle == NULL || ev == NULL) {
- ret = -LTTNG_ERR_INVALID;
- goto error;
- }
-
- /*
- * Empty filter string will always be rejected by the parser
- * anyway, so treat this corner-case early to eliminate
- * lttng_fmemopen error for 0-byte allocation.
- */
- if (filter_expression && filter_expression[0] == '\0') {
- ret = -LTTNG_ERR_INVALID;
- goto error;
- }
-
- memset(&lsm, 0, sizeof(lsm));
-
- /* If no channel name, send empty string. */
- ret = lttng_strncpy(lsm.u.disable.channel_name, channel_name ?: "",
- sizeof(lsm.u.disable.channel_name));
- if (ret) {
- ret = -LTTNG_ERR_INVALID;
- goto error;
- }
-
- lsm.cmd_type = LTTNG_DISABLE_EVENT;
-
- COPY_DOMAIN_PACKED(lsm.domain, handle->domain);
- memcpy(&lsm.u.disable.event, ev, sizeof(lsm.u.disable.event));
-
- ret = lttng_strncpy(lsm.session.name, handle->session_name,
- sizeof(lsm.session.name));
- if (ret) {
- ret = -LTTNG_ERR_INVALID;
- goto error;
- }
-
- lsm.u.disable.bytecode_len = 0;
-
- /*
- * For the JUL domain, a filter is enforced except for the
- * disable all event. This is done to avoid having the event in
- * all sessions thus filtering by logger name.
- */
- if (filter_expression == NULL &&
- (handle->domain.type != LTTNG_DOMAIN_JUL &&
- handle->domain.type != LTTNG_DOMAIN_LOG4J &&
- handle->domain.type != LTTNG_DOMAIN_PYTHON)) {
- goto ask_sessiond;
- }
-
- /*
- * We have a filter, so we need to set up a variable-length
- * memory block from where to send the data.
- */
-
- /* Parse filter expression */
- if (filter_expression != NULL || handle->domain.type == LTTNG_DOMAIN_JUL
- || handle->domain.type == LTTNG_DOMAIN_LOG4J
- || handle->domain.type == LTTNG_DOMAIN_PYTHON) {
- if (handle->domain.type == LTTNG_DOMAIN_JUL ||
- handle->domain.type == LTTNG_DOMAIN_LOG4J ||
- handle->domain.type == LTTNG_DOMAIN_PYTHON) {
- char *agent_filter;
-
- /* Setup JUL filter if needed. */
- agent_filter = set_agent_filter(filter_expression, ev);
- if (!agent_filter) {
- if (!filter_expression) {
- /*
- * No JUL and no filter, just skip
- * everything below.
- */
- goto ask_sessiond;
- }
- } else {
- /*
- * With a JUL filter, the original filter has
- * been added to it thus replace the filter
- * expression.
- */
- filter_expression = agent_filter;
- free_filter_expression = 1;
- }
- }
-
- ret = filter_parser_ctx_create_from_filter_expression(filter_expression, &ctx);
- if (ret) {
- goto filter_error;
- }
-
- lsm.u.enable.bytecode_len = sizeof(ctx->bytecode->b)
- + bytecode_get_len(&ctx->bytecode->b);
- lsm.u.enable.expression_len = strlen(filter_expression) + 1;
- }
-
- varlen_data = zmalloc(lsm.u.disable.bytecode_len
- + lsm.u.disable.expression_len);
- if (!varlen_data) {
- ret = -LTTNG_ERR_EXCLUSION_NOMEM;
- goto mem_error;
- }
-
- /* Add filter expression. */
- if (lsm.u.disable.expression_len != 0) {
- memcpy(varlen_data,
- filter_expression,
- lsm.u.disable.expression_len);
- }
- /* Add filter bytecode next. */
- if (ctx && lsm.u.disable.bytecode_len != 0) {
- memcpy(varlen_data
- + lsm.u.disable.expression_len,
- &ctx->bytecode->b,
- lsm.u.disable.bytecode_len);
- }
-
- ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header(&lsm, varlen_data,
- lsm.u.disable.bytecode_len + lsm.u.disable.expression_len, NULL);
- free(varlen_data);
-
-mem_error:
- if (filter_expression && ctx) {
- filter_bytecode_free(ctx);
- filter_ir_free(ctx);
- filter_parser_ctx_free(ctx);
- }
-filter_error:
- if (free_filter_expression) {
- /*
- * The filter expression has been replaced and must be freed as
- * it is not the original filter expression received as a
- * parameter.
- */
- free(filter_expression);
- }
-error:
- /*
- * Return directly to the caller and don't ask the sessiond since
- * something went wrong in the parsing of data above.
- */
- return ret;
-
-ask_sessiond:
- ret = lttng_ctl_ask_sessiond(&lsm, NULL);
- return ret;
-}
-
-/*
- * Disable event(s) of a channel and domain.
- * If no event name is specified, all events are disabled.
- * If no channel name is specified, the default 'channel0' is used.
- * Returns size of returned session payload data or a negative error code.
- */
-int lttng_disable_event(struct lttng_handle *handle, const char *name,
- const char *channel_name)
-{
- int ret;
- struct lttng_event ev;
-
- memset(&ev, 0, sizeof(ev));
- ev.loglevel = -1;
- ev.type = LTTNG_EVENT_ALL;
- ret = lttng_strncpy(ev.name, name ?: "", sizeof(ev.name));
- if (ret) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- ret = lttng_disable_event_ext(handle, &ev, channel_name, NULL);
-end:
- return ret;
-}
-
-struct lttng_channel *lttng_channel_create(struct lttng_domain *domain)
-{
- struct lttng_channel *channel = NULL;
- struct lttng_channel_extended *extended = NULL;
-
- if (!domain) {
- goto error;
- }
-
- /* Validate domain. */
- switch (domain->type) {
- case LTTNG_DOMAIN_UST:
- switch (domain->buf_type) {
- case LTTNG_BUFFER_PER_UID:
- case LTTNG_BUFFER_PER_PID:
- break;
- default:
- goto error;
- }
- break;
- case LTTNG_DOMAIN_KERNEL:
- if (domain->buf_type != LTTNG_BUFFER_GLOBAL) {
- goto error;
- }
- break;
- default:
- goto error;
- }
-
- channel = zmalloc(sizeof(*channel));
- if (!channel) {
- goto error;
- }
-
- extended = zmalloc(sizeof(*extended));
- if (!extended) {
- goto error;
- }
-
- channel->attr.extended.ptr = extended;
-
- lttng_channel_set_default_attr(domain, &channel->attr);
- return channel;
-error:
- free(channel);
- free(extended);
- return NULL;
-}
-
-void lttng_channel_destroy(struct lttng_channel *channel)
-{
- if (!channel) {
- return;
- }
-
- if (channel->attr.extended.ptr) {
- free(channel->attr.extended.ptr);
- }
- free(channel);
-}
-
-/*
- * Enable channel per domain
- * Returns size of returned session payload data or a negative error code.
- */
-int lttng_enable_channel(struct lttng_handle *handle,
- struct lttng_channel *in_chan)
-{
- int ret;
- struct lttcomm_session_msg lsm;
- size_t total_buffer_size_needed_per_cpu = 0;
-
- /* NULL arguments are forbidden. No default values. */
- if (handle == NULL || in_chan == NULL) {
- return -LTTNG_ERR_INVALID;
- }
-
- memset(&lsm, 0, sizeof(lsm));
- memcpy(&lsm.u.channel.chan, in_chan, sizeof(lsm.u.channel.chan));
- lsm.u.channel.chan.attr.extended.ptr = NULL;
-
- if (!in_chan->attr.extended.ptr) {
- struct lttng_channel *channel;
- struct lttng_channel_extended *extended;
-
- channel = lttng_channel_create(&handle->domain);
- if (!channel) {
- return -LTTNG_ERR_NOMEM;
- }
-
- /*
- * Create a new channel in order to use default extended
- * attribute values.
- */
- extended = (struct lttng_channel_extended *)
- channel->attr.extended.ptr;
- memcpy(&lsm.u.channel.extended, extended, sizeof(*extended));
- lttng_channel_destroy(channel);
- } else {
- struct lttng_channel_extended *extended;
-
- extended = (struct lttng_channel_extended *)
- in_chan->attr.extended.ptr;
- memcpy(&lsm.u.channel.extended, extended, sizeof(*extended));
- }
-
- /*
- * Verify that the amount of memory required to create the requested
- * buffer is available on the system at the moment.
- */
- total_buffer_size_needed_per_cpu = lsm.u.channel.chan.attr.num_subbuf *
- lsm.u.channel.chan.attr.subbuf_size;
- if (!check_enough_available_memory(total_buffer_size_needed_per_cpu)) {
- return -LTTNG_ERR_NOMEM;
- }
-
- lsm.cmd_type = LTTNG_ENABLE_CHANNEL;
- COPY_DOMAIN_PACKED(lsm.domain, handle->domain);
-
- ret = lttng_strncpy(lsm.session.name, handle->session_name,
- sizeof(lsm.session.name));
- if (ret) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- ret = lttng_ctl_ask_sessiond(&lsm, NULL);
-end:
- return ret;
-}
-
-/*
- * All tracing will be stopped for registered events of the channel.
- * Returns size of returned session payload data or a negative error code.
- */
-int lttng_disable_channel(struct lttng_handle *handle, const char *name)
-{
- int ret;
- struct lttcomm_session_msg lsm;
-
- /* Safety check. Both are mandatory. */
- if (handle == NULL || name == NULL) {
- return -LTTNG_ERR_INVALID;
- }
-
- memset(&lsm, 0, sizeof(lsm));
-
- lsm.cmd_type = LTTNG_DISABLE_CHANNEL;
-
- ret = lttng_strncpy(lsm.u.disable.channel_name, name,
- sizeof(lsm.u.disable.channel_name));
- if (ret) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- COPY_DOMAIN_PACKED(lsm.domain, handle->domain);
-
- ret = lttng_strncpy(lsm.session.name, handle->session_name,
- sizeof(lsm.session.name));
- if (ret) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- ret = lttng_ctl_ask_sessiond(&lsm, NULL);
-end:
- return ret;
-}
-
-/*
- * Lists all available tracepoints of domain.
- * Sets the contents of the events array.
- * Returns the number of lttng_event entries in events;
- * on error, returns a negative value.
- */
-int lttng_list_tracepoints(struct lttng_handle *handle,
- struct lttng_event **events)
-{
- int ret;
- struct lttcomm_session_msg lsm;
-
- if (handle == NULL) {
- return -LTTNG_ERR_INVALID;
- }
-
- memset(&lsm, 0, sizeof(lsm));
- lsm.cmd_type = LTTNG_LIST_TRACEPOINTS;
- COPY_DOMAIN_PACKED(lsm.domain, handle->domain);
-
- ret = lttng_ctl_ask_sessiond(&lsm, (void **) events);
- if (ret < 0) {
- return ret;
- }
-
- return ret / sizeof(struct lttng_event);
-}
-
-/*
- * Lists all available tracepoint fields of domain.
- * Sets the contents of the event field array.
- * Returns the number of lttng_event_field entries in events;
- * on error, returns a negative value.
- */
-int lttng_list_tracepoint_fields(struct lttng_handle *handle,
- struct lttng_event_field **fields)
-{
- int ret;
- struct lttcomm_session_msg lsm;
-
- if (handle == NULL) {
- return -LTTNG_ERR_INVALID;
- }
-
- memset(&lsm, 0, sizeof(lsm));
- lsm.cmd_type = LTTNG_LIST_TRACEPOINT_FIELDS;
- COPY_DOMAIN_PACKED(lsm.domain, handle->domain);
-
- ret = lttng_ctl_ask_sessiond(&lsm, (void **) fields);
- if (ret < 0) {
- return ret;
- }
-
- return ret / sizeof(struct lttng_event_field);
-}
-
-/*
- * Lists all available kernel system calls. Allocates and sets the contents of
- * the events array.
- *
- * Returns the number of lttng_event entries in events; on error, returns a
- * negative value.
- */
-int lttng_list_syscalls(struct lttng_event **events)
-{
- int ret;
- struct lttcomm_session_msg lsm;
-
- if (!events) {
- return -LTTNG_ERR_INVALID;
- }
-
- memset(&lsm, 0, sizeof(lsm));
- lsm.cmd_type = LTTNG_LIST_SYSCALLS;
- /* Force kernel domain for system calls. */
- lsm.domain.type = LTTNG_DOMAIN_KERNEL;
-
- ret = lttng_ctl_ask_sessiond(&lsm, (void **) events);
- if (ret < 0) {
- return ret;
- }
-
- return ret / sizeof(struct lttng_event);
-}
-
-/*
- * Returns a human readable string describing
- * the error code (a negative value).
- */
-const char *lttng_strerror(int code)
-{
- return error_get_str(code);
-}
-
-enum lttng_error_code lttng_create_session_ext(
- struct lttng_session_descriptor *session_descriptor)
-{
- enum lttng_error_code ret_code;
- struct lttcomm_session_msg lsm = {
- .cmd_type = LTTNG_CREATE_SESSION_EXT,
- };
- void *reply = NULL;
- struct lttng_buffer_view reply_view;
- int reply_ret;
- bool sessiond_must_generate_ouput;
- struct lttng_dynamic_buffer payload;
- int ret;
- size_t descriptor_size;
- struct lttng_session_descriptor *descriptor_reply = NULL;
-
- lttng_dynamic_buffer_init(&payload);
- if (!session_descriptor) {
- ret_code = LTTNG_ERR_INVALID;
- goto end;
- }
-
- sessiond_must_generate_ouput =
- !lttng_session_descriptor_is_output_destination_initialized(
- session_descriptor);
- if (sessiond_must_generate_ouput) {
- const char *home_dir = utils_get_home_dir();
- size_t home_dir_len = home_dir ? strlen(home_dir) + 1 : 0;
-
- if (!home_dir || home_dir_len > LTTNG_PATH_MAX) {
- ret_code = LTTNG_ERR_FATAL;
- goto end;
- }
-
- lsm.u.create_session.home_dir_size = (uint16_t) home_dir_len;
- ret = lttng_dynamic_buffer_append(&payload, home_dir,
- home_dir_len);
- if (ret) {
- ret_code = LTTNG_ERR_NOMEM;
- goto end;
- }
- }
-
- descriptor_size = payload.size;
- ret = lttng_session_descriptor_serialize(session_descriptor,
- &payload);
- if (ret) {
- ret_code = LTTNG_ERR_INVALID;
- goto end;
- }
- descriptor_size = payload.size - descriptor_size;
- lsm.u.create_session.session_descriptor_size = descriptor_size;
-
- /* Command returns a session descriptor on success. */
- reply_ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header(&lsm, payload.data,
- payload.size, &reply);
- if (reply_ret < 0) {
- ret_code = -reply_ret;
- goto end;
- } else if (reply_ret == 0) {
- /* Socket unexpectedly closed by the session daemon. */
- ret_code = LTTNG_ERR_FATAL;
- goto end;
- }
-
- reply_view = lttng_buffer_view_init(reply, 0, reply_ret);
- ret = lttng_session_descriptor_create_from_buffer(&reply_view,
- &descriptor_reply);
- if (ret < 0) {
- ret_code = LTTNG_ERR_FATAL;
- goto end;
- }
- ret_code = LTTNG_OK;
- lttng_session_descriptor_assign(session_descriptor, descriptor_reply);
-end:
- free(reply);
- lttng_dynamic_buffer_reset(&payload);
- lttng_session_descriptor_destroy(descriptor_reply);
- return ret_code;
-}
-
-/*
- * Create a new session using name and url for destination.
- *
- * Return 0 on success else a negative LTTng error code.
- */
-int lttng_create_session(const char *name, const char *url)
-{
- int ret;
- ssize_t size;
- struct lttng_uri *uris = NULL;
- struct lttng_session_descriptor *descriptor = NULL;
- enum lttng_error_code ret_code;
-
- if (!name) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- size = uri_parse_str_urls(url, NULL, &uris);
- if (size < 0) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
- switch (size) {
- case 0:
- descriptor = lttng_session_descriptor_create(name);
- break;
- case 1:
- if (uris[0].dtype != LTTNG_DST_PATH) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
- descriptor = lttng_session_descriptor_local_create(name,
- uris[0].dst.path);
- break;
- case 2:
- descriptor = lttng_session_descriptor_network_create(name, url,
- NULL);
- break;
- default:
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
- if (!descriptor) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
- ret_code = lttng_create_session_ext(descriptor);
- ret = ret_code == LTTNG_OK ? 0 : -ret_code;
-end:
- lttng_session_descriptor_destroy(descriptor);
- free(uris);
- return ret;
-}
-
-/*
- * Create a session exclusively used for snapshot.
- *
- * Return 0 on success else a negative LTTng error code.
- */
-int lttng_create_session_snapshot(const char *name, const char *snapshot_url)
-{
- int ret;
- enum lttng_error_code ret_code;
- ssize_t size;
- struct lttng_uri *uris = NULL;
- struct lttng_session_descriptor *descriptor = NULL;
-
- if (!name) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- size = uri_parse_str_urls(snapshot_url, NULL, &uris);
- if (size < 0) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
- /*
- * If the user does not specify a custom subdir, use the session name.
- */
- if (size > 0 && uris[0].dtype != LTTNG_DST_PATH &&
- strlen(uris[0].subdir) == 0) {
- ret = snprintf(uris[0].subdir, sizeof(uris[0].subdir), "%s",
- name);
- if (ret < 0) {
- PERROR("Failed to set session name as network destination sub-directory");
- ret = -LTTNG_ERR_FATAL;
- goto end;
- } else if (ret >= sizeof(uris[0].subdir)) {
- /* Truncated output. */
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
- }
-
- switch (size) {
- case 0:
- descriptor = lttng_session_descriptor_snapshot_create(name);
- break;
- case 1:
- if (uris[0].dtype != LTTNG_DST_PATH) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
- descriptor = lttng_session_descriptor_snapshot_local_create(
- name,
- uris[0].dst.path);
- break;
- case 2:
- descriptor = lttng_session_descriptor_snapshot_network_create(
- name,
- snapshot_url,
- NULL);
- break;
- default:
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
- if (!descriptor) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
- ret_code = lttng_create_session_ext(descriptor);
- ret = ret_code == LTTNG_OK ? 0 : -ret_code;
-end:
- lttng_session_descriptor_destroy(descriptor);
- free(uris);
- return ret;
-}
-
-/*
- * Create a session exclusively used for live.
- *
- * Return 0 on success else a negative LTTng error code.
- */
-int lttng_create_session_live(const char *name, const char *url,
- unsigned int timer_interval)
-{
- int ret;
- enum lttng_error_code ret_code;
- struct lttng_session_descriptor *descriptor = NULL;
-
- if (!name) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- if (url) {
- descriptor = lttng_session_descriptor_live_network_create(
- name, url, NULL, timer_interval);
- } else {
- descriptor = lttng_session_descriptor_live_create(
- name, timer_interval);
- }
- if (!descriptor) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
- ret_code = lttng_create_session_ext(descriptor);
- ret = ret_code == LTTNG_OK ? 0 : -ret_code;
-end:
- lttng_session_descriptor_destroy(descriptor);
- return ret;
-}
-
-/*
- * Stop the session and wait for the data before destroying it
- *
- * Return 0 on success else a negative LTTng error code.
- */
-int lttng_destroy_session(const char *session_name)
-{
- int ret;
- enum lttng_error_code ret_code;
- enum lttng_destruction_handle_status status;
- struct lttng_destruction_handle *handle = NULL;
-
- /*
- * Stop the tracing and wait for the data to be
- * consumed.
- */
- ret = _lttng_stop_tracing(session_name, 1);
- if (ret && ret != -LTTNG_ERR_TRACE_ALREADY_STOPPED) {
- goto end;
- }
-
- ret_code = lttng_destroy_session_ext(session_name, &handle);
- if (ret_code != LTTNG_OK) {
- ret = (int) -ret_code;
- goto end;
- }
- LTTNG_ASSERT(handle);
-
- /* Block until the completion of the destruction of the session. */
- status = lttng_destruction_handle_wait_for_completion(handle, -1);
- if (status != LTTNG_DESTRUCTION_HANDLE_STATUS_COMPLETED) {
- ret = -LTTNG_ERR_UNK;
- goto end;
- }
-
- status = lttng_destruction_handle_get_result(handle, &ret_code);
- if (status != LTTNG_DESTRUCTION_HANDLE_STATUS_OK) {
- ret = -LTTNG_ERR_UNK;
- goto end;
- }
- ret = ret_code == LTTNG_OK ? 0 : -ret_code;
-end:
- lttng_destruction_handle_destroy(handle);
- return ret;
-}
-
-/*
- * Destroy the session without waiting for the data.
- */
-int lttng_destroy_session_no_wait(const char *session_name)
-{
- enum lttng_error_code ret_code;
-
- ret_code = lttng_destroy_session_ext(session_name, NULL);
- return ret_code == LTTNG_OK ? 0 : -ret_code;
-}
-
-/*
- * Ask the session daemon for all available sessions.
- * Sets the contents of the sessions array.
- * Returns the number of lttng_session entries in sessions;
- * on error, returns a negative value.
- */
-int lttng_list_sessions(struct lttng_session **out_sessions)
-{
- int ret;
- struct lttcomm_session_msg lsm;
- const size_t session_size = sizeof(struct lttng_session) +
- sizeof(struct lttng_session_extended);
- size_t session_count, i;
- struct lttng_session_extended *sessions_extended_begin;
- struct lttng_session *sessions = NULL;
-
- memset(&lsm, 0, sizeof(lsm));
- lsm.cmd_type = LTTNG_LIST_SESSIONS;
- ret = lttng_ctl_ask_sessiond(&lsm, (void**) &sessions);
- if (ret <= 0) {
- goto end;
- }
- if (!sessions) {
- ret = -LTTNG_ERR_FATAL;
- goto end;
- }
-
- if (ret % session_size) {
- ret = -LTTNG_ERR_UNK;
- free(sessions);
- *out_sessions = NULL;
- goto end;
- }
- session_count = (size_t) ret / session_size;
- sessions_extended_begin = (struct lttng_session_extended *)
- (&sessions[session_count]);
-
- /* Set extended session info pointers. */
- for (i = 0; i < session_count; i++) {
- struct lttng_session *session = &sessions[i];
- struct lttng_session_extended *extended =
- &(sessions_extended_begin[i]);
-
- session->extended.ptr = extended;
- }
-
- ret = (int) session_count;
- *out_sessions = sessions;
-end:
- return ret;
-}
-
-enum lttng_error_code lttng_session_get_creation_time(
- const struct lttng_session *session, uint64_t *creation_time)
-{
- enum lttng_error_code ret = LTTNG_OK;
- struct lttng_session_extended *extended;
-
- if (!session || !creation_time || !session->extended.ptr) {
- ret = LTTNG_ERR_INVALID;
- goto end;
- }
-
- extended = session->extended.ptr;
- if (!extended->creation_time.is_set) {
- /* Not created on the session daemon yet. */
- ret = LTTNG_ERR_SESSION_NOT_EXIST;
- goto end;
- }
- *creation_time = extended->creation_time.value;
-end:
- return ret;
-}
-
-int lttng_set_session_shm_path(const char *session_name,
- const char *shm_path)
-{
- int ret;
- struct lttcomm_session_msg lsm;
-
- if (session_name == NULL) {
- return -LTTNG_ERR_INVALID;
- }
-
- memset(&lsm, 0, sizeof(lsm));
- lsm.cmd_type = LTTNG_SET_SESSION_SHM_PATH;
-
- ret = lttng_strncpy(lsm.session.name, session_name,
- sizeof(lsm.session.name));
- if (ret) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- ret = lttng_strncpy(lsm.u.set_shm_path.shm_path, shm_path ?: "",
- sizeof(lsm.u.set_shm_path.shm_path));
- if (ret) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- ret = lttng_ctl_ask_sessiond(&lsm, NULL);
-end:
- return ret;
-}
-
-/*
- * Ask the session daemon for all available domains of a session.
- * Sets the contents of the domains array.
- * Returns the number of lttng_domain entries in domains;
- * on error, returns a negative value.
- */
-int lttng_list_domains(const char *session_name,
- struct lttng_domain **domains)
-{
- int ret;
- struct lttcomm_session_msg lsm;
-
- if (session_name == NULL) {
- ret = -LTTNG_ERR_INVALID;
- goto error;
- }
-
- memset(&lsm, 0, sizeof(lsm));
- lsm.cmd_type = LTTNG_LIST_DOMAINS;
-
- ret = lttng_strncpy(lsm.session.name, session_name,
- sizeof(lsm.session.name));
- if (ret) {
- ret = -LTTNG_ERR_INVALID;
- goto error;
- }
-
- ret = lttng_ctl_ask_sessiond(&lsm, (void**) domains);
- if (ret < 0) {
- goto error;
- }
-
- return ret / sizeof(struct lttng_domain);
-error:
- return ret;
-}
-
-/*
- * Ask the session daemon for all available channels of a session.
- * Sets the contents of the channels array.
- * Returns the number of lttng_channel entries in channels;
- * on error, returns a negative value.
- */
-int lttng_list_channels(struct lttng_handle *handle,
- struct lttng_channel **channels)
-{
- int ret;
- size_t channel_count, i;
- const size_t channel_size = sizeof(struct lttng_channel) +
- sizeof(struct lttng_channel_extended);
- struct lttcomm_session_msg lsm;
- void *extended_at;
-
- if (handle == NULL) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- memset(&lsm, 0, sizeof(lsm));
- lsm.cmd_type = LTTNG_LIST_CHANNELS;
- ret = lttng_strncpy(lsm.session.name, handle->session_name,
- sizeof(lsm.session.name));
- if (ret) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- COPY_DOMAIN_PACKED(lsm.domain, handle->domain);
-
- ret = lttng_ctl_ask_sessiond(&lsm, (void**) channels);
- if (ret < 0) {
- goto end;
- }
-
- if (ret % channel_size) {
- ret = -LTTNG_ERR_UNK;
- free(*channels);
- *channels = NULL;
- goto end;
- }
- channel_count = (size_t) ret / channel_size;
-
- /* Set extended info pointers */
- extended_at = ((void *) *channels) +
- channel_count * sizeof(struct lttng_channel);
- for (i = 0; i < channel_count; i++) {
- struct lttng_channel *chan = &(*channels)[i];
-
- chan->attr.extended.ptr = extended_at;
- extended_at += sizeof(struct lttng_channel_extended);
- }
-
- ret = (int) channel_count;
-end:
- return ret;
-}
-
-/*
- * Ask the session daemon for all available events of a session channel.
- * Sets the contents of the events array.
- * Returns the number of lttng_event entries in events;
- * on error, returns a negative value.
- */
-int lttng_list_events(struct lttng_handle *handle,
- const char *channel_name, struct lttng_event **events)
-{
- int ret;
- struct lttcomm_session_msg lsm = {};
- const struct lttcomm_event_command_header *cmd_header = NULL;
- uint32_t nb_events, i;
- const void *comm_ext_at;
- struct lttng_dynamic_buffer listing;
- size_t storage_req;
- struct lttng_payload payload;
- struct lttng_payload payload_copy;
- struct lttng_payload_view lsm_view =
- lttng_payload_view_init_from_buffer(
- (const char *) &lsm, 0, sizeof(lsm));
- struct lttng_buffer_view cmd_header_view;
- struct lttng_buffer_view cmd_payload_view;
- struct lttng_buffer_view flat_events_view;
- struct lttng_buffer_view ext_view;
-
- /* Safety check. An handle and channel name are mandatory */
- if (handle == NULL || channel_name == NULL) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- lttng_payload_init(&payload);
- lttng_payload_init(&payload_copy);
-
- lsm.cmd_type = LTTNG_LIST_EVENTS;
- ret = lttng_strncpy(lsm.session.name, handle->session_name,
- sizeof(lsm.session.name));
- if (ret) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- ret = lttng_strncpy(lsm.u.list.channel_name, channel_name,
- sizeof(lsm.u.list.channel_name));
- if (ret) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- COPY_DOMAIN_PACKED(lsm.domain, handle->domain);
-
- ret = lttng_ctl_ask_sessiond_payload(&lsm_view, &payload);
- if (ret < 0) {
- goto end;
- }
-
- /*
- * A copy of the payload is performed since it will be
- * consumed twice. Consuming the same payload twice is invalid since
- * it will cause any received file descriptor to become "shared"
- * between different instances of the resulting objects.
- */
- ret = lttng_payload_copy(&payload, &payload_copy);
- if (ret) {
- ret = -LTTNG_ERR_NOMEM;
- goto end;
- }
-
- cmd_header_view = lttng_buffer_view_from_dynamic_buffer(
- &payload.buffer, 0, sizeof(*cmd_header));
- if (!lttng_buffer_view_is_valid(&cmd_header_view)) {
- ret = -LTTNG_ERR_INVALID_PROTOCOL;
- goto end;
- }
-
- cmd_header = (typeof(cmd_header)) cmd_header_view.data;
-
- /* Set number of events and free command header */
- nb_events = cmd_header->nb_events;
- if (nb_events > INT_MAX) {
- ret = -LTTNG_ERR_OVERFLOW;
- goto end;
- }
-
- cmd_payload_view = lttng_buffer_view_from_dynamic_buffer(
- &payload.buffer, sizeof(*cmd_header), -1);
-
- /*
- * The buffer that is returned must contain a "flat" version of
- * the events that are returned. In other words, all pointers
- * within an lttng_event must point to a location within the returned
- * buffer so that the user may free everything by simply calling free()
- * on the returned buffer. This is needed in order to maintain API
- * compatibility.
- *
- * A first pass is performed to compute the size of the buffer that
- * must be allocated. A second pass is then performed to setup
- * the returned events so that their members always point within the
- * buffer.
- *
- * The layout of the returned buffer is as follows:
- * - struct lttng_event[nb_events],
- * - nb_events times the following:
- * - struct lttng_event_extended,
- * - flattened version of userspace_probe_location
- * - filter_expression
- * - exclusions
- * - padding to align to 64-bits
- */
- ext_view = lttng_buffer_view_from_view(&cmd_payload_view,
- nb_events * sizeof(struct lttng_event), -1);
- comm_ext_at = ext_view.data;
- storage_req = nb_events * sizeof(struct lttng_event);
- {
- struct lttng_payload_view payload_view =
- lttng_payload_view_from_payload(&payload, 0, -1);
-
- for (i = 0; i < nb_events; i++) {
- const struct lttcomm_event_extended_header *ext_comm =
- (struct lttcomm_event_extended_header *)
- comm_ext_at;
- int probe_storage_req = 0;
-
- comm_ext_at += sizeof(*ext_comm);
- comm_ext_at += ext_comm->filter_len;
- comm_ext_at += ext_comm->nb_exclusions *
- LTTNG_SYMBOL_NAME_LEN;
-
- if (ext_comm->userspace_probe_location_len) {
- struct lttng_userspace_probe_location
- *probe_location = NULL;
- struct lttng_payload_view probe_location_view = lttng_payload_view_from_view(
- &payload_view,
- (const char *) comm_ext_at -
- payload_view.buffer.data,
- ext_comm->userspace_probe_location_len);
-
- if (!lttng_payload_view_is_valid(&probe_location_view)) {
- ret = -LTTNG_ERR_PROBE_LOCATION_INVAL;
- goto end;
- }
-
- /*
- * Create a temporary userspace probe location
- * to determine the size needed by a "flattened"
- * version of that same probe location.
- */
- ret = lttng_userspace_probe_location_create_from_payload(
- &probe_location_view,
- &probe_location);
- if (ret < 0) {
- ret = -LTTNG_ERR_PROBE_LOCATION_INVAL;
- goto end;
- }
-
- ret = lttng_userspace_probe_location_flatten(
- probe_location, NULL);
- lttng_userspace_probe_location_destroy(
- probe_location);
- if (ret < 0) {
- ret = -LTTNG_ERR_PROBE_LOCATION_INVAL;
- goto end;
- }
-
- probe_storage_req = ret;
- comm_ext_at += ext_comm->userspace_probe_location_len;
- }
-
- storage_req += sizeof(struct lttng_event_extended);
- storage_req += ext_comm->filter_len;
- storage_req += ext_comm->nb_exclusions *
- LTTNG_SYMBOL_NAME_LEN;
- /* Padding to ensure the flat probe is aligned. */
- storage_req = lttng_align_ceil(storage_req, sizeof(uint64_t));
- storage_req += probe_storage_req;
- }
- }
-
- lttng_dynamic_buffer_init(&listing);
- /*
- * We must ensure that "listing" is never resized so as to preserve
- * the validity of the flattened objects.
- */
- ret = lttng_dynamic_buffer_set_capacity(&listing, storage_req);
- if (ret) {
- ret = -LTTNG_ERR_NOMEM;
- goto end;
- }
-
- cmd_payload_view = lttng_buffer_view_from_dynamic_buffer(
- &payload_copy.buffer, sizeof(*cmd_header), -1);
- flat_events_view = lttng_buffer_view_from_view(&cmd_payload_view, 0,
- nb_events * sizeof(struct lttng_event));
- ret = lttng_dynamic_buffer_append_view(&listing, &flat_events_view);
- if (ret) {
- ret = -LTTNG_ERR_NOMEM;
- goto free_dynamic_buffer;
- }
-
- ext_view = lttng_buffer_view_from_view(&cmd_payload_view,
- nb_events * sizeof(struct lttng_event), -1);
- comm_ext_at = ext_view.data;
-
- {
- struct lttng_payload_view payload_copy_view =
- lttng_payload_view_from_payload(
- &payload_copy, 0, -1);
-
- for (i = 0; i < nb_events; i++) {
- struct lttng_event *event = (typeof(event))(
- listing.data +
- (sizeof(struct lttng_event) * i));
- const struct lttcomm_event_extended_header *ext_comm =
- (typeof(ext_comm)) comm_ext_at;
- struct lttng_event_extended *event_extended =
- (typeof(event_extended))(listing.data +
- listing.size);
-
- /* Insert struct lttng_event_extended. */
- ret = lttng_dynamic_buffer_set_size(&listing,
- listing.size + sizeof(*event_extended));
- if (ret) {
- ret = -LTTNG_ERR_NOMEM;
- goto free_dynamic_buffer;
- }
- event->extended.ptr = event_extended;
-
- comm_ext_at += sizeof(*ext_comm);
-
- /* Insert filter expression. */
- if (ext_comm->filter_len) {
- event_extended->filter_expression =
- listing.data + listing.size;
- ret = lttng_dynamic_buffer_append(&listing,
- comm_ext_at,
- ext_comm->filter_len);
- if (ret) {
- ret = -LTTNG_ERR_NOMEM;
- goto free_dynamic_buffer;
- }
- comm_ext_at += ext_comm->filter_len;
- }
-
- /* Insert exclusions. */
- if (ext_comm->nb_exclusions) {
- event_extended->exclusions.count =
- ext_comm->nb_exclusions;
- event_extended->exclusions.strings =
- listing.data + listing.size;
-
- ret = lttng_dynamic_buffer_append(&listing,
- comm_ext_at,
- ext_comm->nb_exclusions *
- LTTNG_SYMBOL_NAME_LEN);
- if (ret) {
- ret = -LTTNG_ERR_NOMEM;
- goto free_dynamic_buffer;
- }
- comm_ext_at += ext_comm->nb_exclusions *
- LTTNG_SYMBOL_NAME_LEN;
- }
-
- /* Insert padding to align to 64-bits. */
- ret = lttng_dynamic_buffer_set_size(&listing,
- lttng_align_ceil(listing.size,
- sizeof(uint64_t)));
- if (ret) {
- ret = -LTTNG_ERR_NOMEM;
- goto free_dynamic_buffer;
- }
-
- /* Insert flattened userspace probe location. */
- if (ext_comm->userspace_probe_location_len) {
- struct lttng_userspace_probe_location
- *probe_location = NULL;
- struct lttng_payload_view probe_location_view = lttng_payload_view_from_view(
- &payload_copy_view,
- (const char *) comm_ext_at -
- payload_copy_view.buffer.data,
- ext_comm->userspace_probe_location_len);
-
- if (!lttng_payload_view_is_valid(&probe_location_view)) {
- ret = -LTTNG_ERR_PROBE_LOCATION_INVAL;
- goto free_dynamic_buffer;
- }
-
- ret = lttng_userspace_probe_location_create_from_payload(
- &probe_location_view,
- &probe_location);
- if (ret < 0) {
- ret = -LTTNG_ERR_PROBE_LOCATION_INVAL;
- goto free_dynamic_buffer;
- }
-
- event_extended->probe_location = (struct lttng_userspace_probe_location
- *) (listing.data +
- listing.size);
- ret = lttng_userspace_probe_location_flatten(
- probe_location, &listing);
- lttng_userspace_probe_location_destroy(
- probe_location);
- if (ret < 0) {
- ret = -LTTNG_ERR_PROBE_LOCATION_INVAL;
- goto free_dynamic_buffer;
- }
-
- comm_ext_at += ext_comm->userspace_probe_location_len;
- }
- }
- }
-
- /* Don't reset listing buffer as we return its content. */
- *events = (struct lttng_event *) listing.data;
- lttng_dynamic_buffer_init(&listing);
- ret = (int) nb_events;
-free_dynamic_buffer:
- lttng_dynamic_buffer_reset(&listing);
-end:
- lttng_payload_reset(&payload);
- lttng_payload_reset(&payload_copy);
- return ret;
-}
-
-/*
- * Sets the tracing_group variable with name.
- * This function allocates memory pointed to by tracing_group.
- * On success, returns 0, on error, returns -1 (null name) or -ENOMEM.
- */
-int lttng_set_tracing_group(const char *name)
-{
- int ret = 0;
- char *new_group;
-
- if (name == NULL) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- new_group = strdup(name);
- if (!new_group) {
- ret = -LTTNG_ERR_FATAL;
- goto end;
- }
-
- free(tracing_group);
- tracing_group = new_group;
- new_group = NULL;
-
-end:
- return ret;
-}
-
-int lttng_calibrate(struct lttng_handle *handle,
- struct lttng_calibrate *calibrate)
-{
- /*
- * This command was removed in LTTng 2.9.
- */
- return -LTTNG_ERR_UND;
-}
-
-/*
- * Set default channel attributes.
- * If either or both of the arguments are null, attr content is zeroe'd.
- */
-void lttng_channel_set_default_attr(struct lttng_domain *domain,
- struct lttng_channel_attr *attr)
-{
- struct lttng_channel_extended *extended;
-
- /* Safety check */
- if (attr == NULL || domain == NULL) {
- return;
- }
-
- extended = (struct lttng_channel_extended *) attr->extended.ptr;
- memset(attr, 0, sizeof(struct lttng_channel_attr));
-
- /* Same for all domains. */
- attr->overwrite = DEFAULT_CHANNEL_OVERWRITE;
- attr->tracefile_size = DEFAULT_CHANNEL_TRACEFILE_SIZE;
- attr->tracefile_count = DEFAULT_CHANNEL_TRACEFILE_COUNT;
-
- switch (domain->type) {
- case LTTNG_DOMAIN_KERNEL:
- attr->switch_timer_interval =
- DEFAULT_KERNEL_CHANNEL_SWITCH_TIMER;
- attr->read_timer_interval = DEFAULT_KERNEL_CHANNEL_READ_TIMER;
- attr->subbuf_size = default_get_kernel_channel_subbuf_size();
- attr->num_subbuf = DEFAULT_KERNEL_CHANNEL_SUBBUF_NUM;
- attr->output = DEFAULT_KERNEL_CHANNEL_OUTPUT;
- if (extended) {
- extended->monitor_timer_interval =
- DEFAULT_KERNEL_CHANNEL_MONITOR_TIMER;
- extended->blocking_timeout =
- DEFAULT_KERNEL_CHANNEL_BLOCKING_TIMEOUT;
- }
- break;
- case LTTNG_DOMAIN_UST:
- switch (domain->buf_type) {
- case LTTNG_BUFFER_PER_UID:
- attr->subbuf_size = default_get_ust_uid_channel_subbuf_size();
- attr->num_subbuf = DEFAULT_UST_UID_CHANNEL_SUBBUF_NUM;
- attr->output = DEFAULT_UST_UID_CHANNEL_OUTPUT;
- attr->switch_timer_interval =
- DEFAULT_UST_UID_CHANNEL_SWITCH_TIMER;
- attr->read_timer_interval =
- DEFAULT_UST_UID_CHANNEL_READ_TIMER;
- if (extended) {
- extended->monitor_timer_interval =
- DEFAULT_UST_UID_CHANNEL_MONITOR_TIMER;
- extended->blocking_timeout =
- DEFAULT_UST_UID_CHANNEL_BLOCKING_TIMEOUT;
- }
- break;
- case LTTNG_BUFFER_PER_PID:
- default:
- attr->subbuf_size = default_get_ust_pid_channel_subbuf_size();
- attr->num_subbuf = DEFAULT_UST_PID_CHANNEL_SUBBUF_NUM;
- attr->output = DEFAULT_UST_PID_CHANNEL_OUTPUT;
- attr->switch_timer_interval =
- DEFAULT_UST_PID_CHANNEL_SWITCH_TIMER;
- attr->read_timer_interval =
- DEFAULT_UST_PID_CHANNEL_READ_TIMER;
- if (extended) {
- extended->monitor_timer_interval =
- DEFAULT_UST_PID_CHANNEL_MONITOR_TIMER;
- extended->blocking_timeout =
- DEFAULT_UST_PID_CHANNEL_BLOCKING_TIMEOUT;
- }
- break;
- }
- default:
- /* Default behavior: leave set to 0. */
- break;
- }
-
- attr->extended.ptr = extended;
-}
-
-int lttng_channel_get_discarded_event_count(struct lttng_channel *channel,
- uint64_t *discarded_events)
-{
- int ret = 0;
- struct lttng_channel_extended *chan_ext;
-
- if (!channel || !discarded_events) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- chan_ext = channel->attr.extended.ptr;
- if (!chan_ext) {
- /*
- * This can happen since the lttng_channel structure is
- * used for other tasks where this pointer is never set.
- */
- *discarded_events = 0;
- goto end;
- }
-
- *discarded_events = chan_ext->discarded_events;
-end:
- return ret;
-}
-
-int lttng_channel_get_lost_packet_count(struct lttng_channel *channel,
- uint64_t *lost_packets)
-{
- int ret = 0;
- struct lttng_channel_extended *chan_ext;
-
- if (!channel || !lost_packets) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- chan_ext = channel->attr.extended.ptr;
- if (!chan_ext) {
- /*
- * This can happen since the lttng_channel structure is
- * used for other tasks where this pointer is never set.
- */
- *lost_packets = 0;
- goto end;
- }
-
- *lost_packets = chan_ext->lost_packets;
-end:
- return ret;
-}
-
-int lttng_channel_get_monitor_timer_interval(struct lttng_channel *chan,
- uint64_t *monitor_timer_interval)
-{
- int ret = 0;
-
- if (!chan || !monitor_timer_interval) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- if (!chan->attr.extended.ptr) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- *monitor_timer_interval = ((struct lttng_channel_extended *)
- chan->attr.extended.ptr)->monitor_timer_interval;
-end:
- return ret;
-}
-
-int lttng_channel_set_monitor_timer_interval(struct lttng_channel *chan,
- uint64_t monitor_timer_interval)
-{
- int ret = 0;
-
- if (!chan || !chan->attr.extended.ptr) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- ((struct lttng_channel_extended *)
- chan->attr.extended.ptr)->monitor_timer_interval =
- monitor_timer_interval;
-end:
- return ret;
-}
-
-int lttng_channel_get_blocking_timeout(struct lttng_channel *chan,
- int64_t *blocking_timeout)
-{
- int ret = 0;
-
- if (!chan || !blocking_timeout) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- if (!chan->attr.extended.ptr) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- *blocking_timeout = ((struct lttng_channel_extended *)
- chan->attr.extended.ptr)->blocking_timeout;
-end:
- return ret;
-}
-
-int lttng_channel_set_blocking_timeout(struct lttng_channel *chan,
- int64_t blocking_timeout)
-{
- int ret = 0;
- int64_t msec_timeout;
-
- if (!chan || !chan->attr.extended.ptr) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- if (blocking_timeout < 0 && blocking_timeout != -1) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- /*
- * LTTng-ust's use of poll() to implement this timeout mechanism forces
- * us to accept a narrower range of values (msecs expressed as a signed
- * 32-bit integer).
- */
- msec_timeout = blocking_timeout / 1000;
- if (msec_timeout != (int32_t) msec_timeout) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- ((struct lttng_channel_extended *)
- chan->attr.extended.ptr)->blocking_timeout =
- blocking_timeout;
-end:
- return ret;
-}
-
-/*
- * Check if session daemon is alive.
- *
- * Return 1 if alive or 0 if not.
- * On error returns a negative value.
- */
-int lttng_session_daemon_alive(void)
-{
- int ret;
-
- ret = set_session_daemon_path();
- if (ret < 0) {
- /* Error. */
- return ret;
- }
-
- if (*sessiond_sock_path == '\0') {
- /*
- * No socket path set. Weird error which means the constructor
- * was not called.
- */
- abort();
- }
-
- ret = try_connect_sessiond(sessiond_sock_path);
- if (ret < 0) {
- /* Not alive. */
- return 0;
- }
-
- /* Is alive. */
- return 1;
-}
-
-/*
- * Set URL for a consumer for a session and domain.
- *
- * Return 0 on success, else a negative value.
- */
-int lttng_set_consumer_url(struct lttng_handle *handle,
- const char *control_url, const char *data_url)
-{
- int ret;
- ssize_t size;
- struct lttcomm_session_msg lsm;
- struct lttng_uri *uris = NULL;
-
- if (handle == NULL || (control_url == NULL && data_url == NULL)) {
- ret = -LTTNG_ERR_INVALID;
- goto error;
- }
-
- memset(&lsm, 0, sizeof(lsm));
-
- lsm.cmd_type = LTTNG_SET_CONSUMER_URI;
-
- ret = lttng_strncpy(lsm.session.name, handle->session_name,
- sizeof(lsm.session.name));
- if (ret) {
- ret = -LTTNG_ERR_INVALID;
- goto error;
- }
-
- COPY_DOMAIN_PACKED(lsm.domain, handle->domain);
-
- size = uri_parse_str_urls(control_url, data_url, &uris);
- if (size < 0) {
- ret = -LTTNG_ERR_INVALID;
- goto error;
- }
-
- lsm.u.uri.size = size;
-
- ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header(&lsm, uris,
- sizeof(struct lttng_uri) * size, NULL);
-
- free(uris);
-error:
- return ret;
-}
-
-/*
- * [OBSOLETE]
- */
-int lttng_enable_consumer(struct lttng_handle *handle);
-int lttng_enable_consumer(struct lttng_handle *handle)
-{
- return -ENOSYS;
-}
-
-/*
- * [OBSOLETE]
- */
-int lttng_disable_consumer(struct lttng_handle *handle);
-int lttng_disable_consumer(struct lttng_handle *handle)
-{
- return -ENOSYS;
-}
-
-/*
- * [OBSOLETE]
- */
-int _lttng_create_session_ext(const char *name, const char *url,
- const char *datetime);
-int _lttng_create_session_ext(const char *name, const char *url,
- const char *datetime)
-{
- return -ENOSYS;
-}
-
-/*
- * For a given session name, this call checks if the data is ready to be read
- * or is still being extracted by the consumer(s) hence not ready to be used by
- * any readers.
- */
-int lttng_data_pending(const char *session_name)
-{
- int ret;
- struct lttcomm_session_msg lsm;
- uint8_t *pending = NULL;
-
- if (session_name == NULL) {
- return -LTTNG_ERR_INVALID;
- }
-
- memset(&lsm, 0, sizeof(lsm));
- lsm.cmd_type = LTTNG_DATA_PENDING;
-
- ret = lttng_strncpy(lsm.session.name, session_name,
- sizeof(lsm.session.name));
- if (ret) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- ret = lttng_ctl_ask_sessiond(&lsm, (void **) &pending);
- if (ret < 0) {
- goto end;
- } else if (ret != 1) {
- /* Unexpected payload size */
- ret = -LTTNG_ERR_INVALID;
- goto end;
- } else if (!pending) {
- /* Internal error. */
- ret = -LTTNG_ERR_UNK;
- goto end;
- }
-
- ret = (int) *pending;
-end:
- free(pending);
- return ret;
-}
-
-/*
- * Regenerate the metadata for a session.
- * Return 0 on success, a negative error code on error.
- */
-int lttng_regenerate_metadata(const char *session_name)
-{
- int ret;
- struct lttcomm_session_msg lsm;
-
- if (!session_name) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- memset(&lsm, 0, sizeof(lsm));
- lsm.cmd_type = LTTNG_REGENERATE_METADATA;
-
- ret = lttng_strncpy(lsm.session.name, session_name,
- sizeof(lsm.session.name));
- if (ret) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- ret = lttng_ctl_ask_sessiond(&lsm, NULL);
- if (ret < 0) {
- goto end;
- }
-
- ret = 0;
-end:
- return ret;
-}
-
-/*
- * Deprecated, replaced by lttng_regenerate_metadata.
- */
-int lttng_metadata_regenerate(const char *session_name)
-{
- return lttng_regenerate_metadata(session_name);
-}
-
-/*
- * Regenerate the statedump of a session.
- * Return 0 on success, a negative error code on error.
- */
-int lttng_regenerate_statedump(const char *session_name)
-{
- int ret;
- struct lttcomm_session_msg lsm;
-
- if (!session_name) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- memset(&lsm, 0, sizeof(lsm));
- lsm.cmd_type = LTTNG_REGENERATE_STATEDUMP;
-
- ret = lttng_strncpy(lsm.session.name, session_name,
- sizeof(lsm.session.name));
- if (ret) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- ret = lttng_ctl_ask_sessiond(&lsm, NULL);
- if (ret < 0) {
- goto end;
- }
-
- ret = 0;
-end:
- return ret;
-}
-
-static
-int _lttng_register_trigger(struct lttng_trigger *trigger, const char *name,
- bool generate_name)
-{
- int ret;
- struct lttcomm_session_msg lsm = {
- .cmd_type = LTTNG_REGISTER_TRIGGER,
- .u.trigger.is_trigger_anonymous = !name && !generate_name,
- };
- struct lttcomm_session_msg *message_lsm;
- struct lttng_payload message;
- struct lttng_payload reply;
- struct lttng_trigger *reply_trigger = NULL;
- enum lttng_domain_type domain_type;
- const struct lttng_credentials user_creds = {
- .uid = LTTNG_OPTIONAL_INIT_VALUE(geteuid()),
- .gid = LTTNG_OPTIONAL_INIT_UNSET,
- };
- const char *unused_trigger_name = NULL;
- enum lttng_trigger_status trigger_status;
-
- lttng_payload_init(&message);
- lttng_payload_init(&reply);
-
- if (!trigger) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- trigger_status = lttng_trigger_get_name(trigger, &unused_trigger_name);
- if (trigger_status != LTTNG_TRIGGER_STATUS_UNSET) {
- /* Re-using already registered trigger. */
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- if (name) {
- trigger_status = lttng_trigger_set_name(trigger, name);
- if (trigger_status != LTTNG_TRIGGER_STATUS_OK) {
- ret = -LTTNG_ERR_NOMEM;
- goto end;
- }
- }
-
- if (!trigger->creds.uid.is_set) {
- /* Use the client's credentials as the trigger credentials. */
- lttng_trigger_set_credentials(trigger, &user_creds);
- } else {
- /*
- * Validate that either the current trigger credentials and the
- * client credentials are identical or that the current user is
- * root. The root user can register, unregister triggers for
- * himself and other users.
- *
- * This check is also present on the sessiond side, using the
- * credentials passed on the socket. These check are all
- * "safety" checks.
- */
- const struct lttng_credentials *trigger_creds =
- lttng_trigger_get_credentials(trigger);
-
- if (!lttng_credentials_is_equal_uid(trigger_creds, &user_creds)) {
- if (lttng_credentials_get_uid(&user_creds) != 0) {
- ret = -LTTNG_ERR_EPERM;
- goto end_unset_name;
- }
- }
- }
-
- if (!lttng_trigger_validate(trigger)) {
- ret = -LTTNG_ERR_INVALID_TRIGGER;
- goto end_unset_name;
- }
-
- domain_type = lttng_trigger_get_underlying_domain_type_restriction(
- trigger);
-
- lsm.domain.type = domain_type;
-
- ret = lttng_dynamic_buffer_append(&message.buffer, &lsm, sizeof(lsm));
- if (ret) {
- ret = -LTTNG_ERR_NOMEM;
- goto end_unset_name;
- }
-
- ret = lttng_trigger_serialize(trigger, &message);
- if (ret < 0) {
- ret = -LTTNG_ERR_UNK;
- goto end_unset_name;
- }
-
- /*
- * This is needed to populate the trigger object size for the command
- * header.
- */
- message_lsm = (struct lttcomm_session_msg *) message.buffer.data;
-
- message_lsm->u.trigger.length = (uint32_t) message.buffer.size - sizeof(lsm);
-
- {
- struct lttng_payload_view message_view =
- lttng_payload_view_from_payload(
- &message, 0, -1);
-
- message_lsm->fd_count = lttng_payload_view_get_fd_handle_count(
- &message_view);
- ret = lttng_ctl_ask_sessiond_payload(&message_view, &reply);
- if (ret < 0) {
- goto end_unset_name;
- }
- }
-
- {
- struct lttng_payload_view reply_view =
- lttng_payload_view_from_payload(
- &reply, 0, reply.buffer.size);
-
- ret = lttng_trigger_create_from_payload(
- &reply_view, &reply_trigger);
- if (ret < 0) {
- ret = -LTTNG_ERR_INVALID_PROTOCOL;
- goto end_unset_name;
- }
- }
-
- if (name || generate_name) {
- ret = lttng_trigger_assign_name(trigger, reply_trigger);
- if (ret < 0) {
- ret = -LTTNG_ERR_NOMEM;
- goto end;
- }
- }
-
- ret = 0;
- goto end;
-
-end_unset_name:
- trigger_status = lttng_trigger_set_name(trigger, NULL);
- if (trigger_status != LTTNG_TRIGGER_STATUS_OK) {
- ret = -LTTNG_ERR_UNK;
- }
-end:
- lttng_payload_reset(&message);
- lttng_payload_reset(&reply);
- lttng_trigger_destroy(reply_trigger);
- return ret;
-}
-
-int lttng_register_trigger(struct lttng_trigger *trigger)
-{
- /* Register an anonymous trigger. */
- return _lttng_register_trigger(trigger, NULL, false);
-}
-
-enum lttng_error_code lttng_register_trigger_with_name(
- struct lttng_trigger *trigger, const char *name)
-{
- const int ret = _lttng_register_trigger(trigger, name, false);
-
- return ret == 0 ? LTTNG_OK : (enum lttng_error_code) -ret;
-}
-
-enum lttng_error_code lttng_register_trigger_with_automatic_name(
- struct lttng_trigger *trigger)
-{
- const int ret = _lttng_register_trigger(trigger, false, true);
-
- return ret == 0 ? LTTNG_OK : (enum lttng_error_code) -ret;
-}
-
-enum lttng_error_code lttng_error_query_execute(
- const struct lttng_error_query *query,
- const struct lttng_endpoint *endpoint,
- struct lttng_error_query_results **results)
-{
- int ret;
- enum lttng_error_code ret_code;
- struct lttcomm_session_msg lsm = {
- .cmd_type = LTTNG_EXECUTE_ERROR_QUERY,
- };
- struct lttng_payload message;
- struct lttng_payload reply;
- struct lttcomm_session_msg *message_lsm;
-
- lttng_payload_init(&message);
- lttng_payload_init(&reply);
-
- if (!query || !results) {
- ret_code = LTTNG_ERR_INVALID;
- goto end;
- }
-
- if (endpoint != lttng_session_daemon_command_endpoint) {
- ret_code = LTTNG_ERR_INVALID_ERROR_QUERY_TARGET;
- goto end;
- }
-
- ret = lttng_dynamic_buffer_append(&message.buffer, &lsm, sizeof(lsm));
- if (ret) {
- ret_code = LTTNG_ERR_NOMEM;
- goto end;
- }
-
- ret = lttng_error_query_serialize(query, &message);
- if (ret) {
- ret_code = LTTNG_ERR_UNK;
- goto end;
- }
-
- message_lsm = (struct lttcomm_session_msg *) message.buffer.data;
- message_lsm->u.error_query.length =
- (uint32_t) message.buffer.size - sizeof(lsm);
-
- {
- struct lttng_payload_view message_view =
- lttng_payload_view_from_payload(
- &message, 0, -1);
-
- message_lsm->fd_count = lttng_payload_view_get_fd_handle_count(
- &message_view);
- ret = lttng_ctl_ask_sessiond_payload(&message_view, &reply);
- if (ret < 0) {
- ret_code = -ret;
- goto end;
- }
- }
-
- {
- ssize_t reply_create_ret;
- struct lttng_payload_view reply_view =
- lttng_payload_view_from_payload(
- &reply, 0, reply.buffer.size);
-
- reply_create_ret = lttng_error_query_results_create_from_payload(
- &reply_view, results);
- if (reply_create_ret < 0) {
- ret_code = LTTNG_ERR_INVALID_PROTOCOL;
- goto end;
- }
- }
-
- ret_code = LTTNG_OK;
-end:
- lttng_payload_reset(&message);
- lttng_payload_reset(&reply);
- return ret_code;
-}
-
-int lttng_unregister_trigger(const struct lttng_trigger *trigger)
-{
- int ret;
- struct lttcomm_session_msg lsm;
- struct lttcomm_session_msg *message_lsm;
- struct lttng_payload message;
- struct lttng_payload reply;
- struct lttng_trigger *copy = NULL;
- const struct lttng_credentials user_creds = {
- .uid = LTTNG_OPTIONAL_INIT_VALUE(geteuid()),
- .gid = LTTNG_OPTIONAL_INIT_UNSET,
- };
-
- lttng_payload_init(&message);
- lttng_payload_init(&reply);
-
- if (!trigger) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- copy = lttng_trigger_copy(trigger);
- if (!copy) {
- ret = -LTTNG_ERR_UNK;
- goto end;
- }
-
- if (!copy->creds.uid.is_set) {
- /* Use the client credentials as the trigger credentials */
- lttng_trigger_set_credentials(copy, &user_creds);
- } else {
- /*
- * Validate that either the current trigger credentials and the
- * client credentials are identical or that the current user is
- * root. The root user can register, unregister triggers for
- * himself and other users.
- *
- * This check is also present on the sessiond side, using the
- * credentials passed on the socket. These check are all
- * "safety" checks.
- */
- const struct lttng_credentials *trigger_creds =
- lttng_trigger_get_credentials(copy);
- if (!lttng_credentials_is_equal_uid(trigger_creds, &user_creds)) {
- if (lttng_credentials_get_uid(&user_creds) != 0) {
- ret = -LTTNG_ERR_EPERM;
- goto end;
- }
- }
- }
-
- if (!lttng_trigger_validate(copy)) {
- ret = -LTTNG_ERR_INVALID_TRIGGER;
- goto end;
- }
-
- memset(&lsm, 0, sizeof(lsm));
- lsm.cmd_type = LTTNG_UNREGISTER_TRIGGER;
-
- ret = lttng_dynamic_buffer_append(&message.buffer, &lsm, sizeof(lsm));
- if (ret) {
- ret = -LTTNG_ERR_NOMEM;
- goto end;
- }
-
- ret = lttng_trigger_serialize(copy, &message);
- if (ret < 0) {
- ret = -LTTNG_ERR_UNK;
- goto end;
- }
-
- /*
- * This is needed to populate the trigger object size for the command
- * header and number of fds sent.
- */
- message_lsm = (struct lttcomm_session_msg *) message.buffer.data;
-
- message_lsm->u.trigger.length = (uint32_t) message.buffer.size - sizeof(lsm);
-
- {
- struct lttng_payload_view message_view =
- lttng_payload_view_from_payload(
- &message, 0, -1);
-
- /*
- * Update the message header with the number of fd that will be
- * sent.
- */
- message_lsm->fd_count = lttng_payload_view_get_fd_handle_count(
- &message_view);
-
- ret = lttng_ctl_ask_sessiond_payload(&message_view, &reply);
- if (ret < 0) {
- goto end;
- }
- }
-
- ret = 0;
-end:
- lttng_trigger_destroy(copy);
- lttng_payload_reset(&message);
- lttng_payload_reset(&reply);
- return ret;
-}
-
-/*
- * Ask the session daemon for all registered triggers for the current user.
- *
- * Allocates and return an lttng_triggers set.
- * On error, returns a suitable lttng_error_code.
- */
-enum lttng_error_code lttng_list_triggers(struct lttng_triggers **triggers)
-{
- int ret;
- enum lttng_error_code ret_code = LTTNG_OK;
- struct lttcomm_session_msg lsm = { .cmd_type = LTTNG_LIST_TRIGGERS };
- struct lttng_triggers *local_triggers = NULL;
- struct lttng_payload reply;
- struct lttng_payload_view lsm_view =
- lttng_payload_view_init_from_buffer(
- (const char *) &lsm, 0, sizeof(lsm));
-
- lttng_payload_init(&reply);
-
- ret = lttng_ctl_ask_sessiond_payload(&lsm_view, &reply);
- if (ret < 0) {
- ret_code = (enum lttng_error_code) -ret;
- goto end;
- }
-
- {
- struct lttng_payload_view reply_view =
- lttng_payload_view_from_payload(
- &reply, 0, reply.buffer.size);
-
- ret = lttng_triggers_create_from_payload(
- &reply_view, &local_triggers);
- if (ret < 0) {
- ret_code = LTTNG_ERR_FATAL;
- goto end;
- }
- }
-
- *triggers = local_triggers;
- local_triggers = NULL;
-end:
- lttng_payload_reset(&reply);
- lttng_triggers_destroy(local_triggers);
- return ret_code;
-}
-
-/*
- * lib constructor.
- */
-static void __attribute__((constructor)) init(void)
-{
- /* Set default session group */
- lttng_set_tracing_group(DEFAULT_TRACING_GROUP);
-}
-
-/*
- * lib destructor.
- */
-static void __attribute__((destructor)) lttng_ctl_exit(void)
-{
- free(tracing_group);
-}
--- /dev/null
+/*
+ * lttng-ctl.c
+ *
+ * Linux Trace Toolkit Control Library
+ *
+ * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ * Copyright (C) 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#define _LGPL_SOURCE
+#include <grp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <common/bytecode/bytecode.h>
+#include <common/align.h>
+#include <common/common.h>
+#include <common/compat/errno.h>
+#include <common/compat/string.h>
+#include <common/defaults.h>
+#include <common/dynamic-array.h>
+#include <common/dynamic-buffer.h>
+#include <common/payload-view.h>
+#include <common/payload.h>
+#include <common/sessiond-comm/sessiond-comm.h>
+#include <common/tracker.h>
+#include <common/unix.h>
+#include <common/uri.h>
+#include <common/utils.h>
+#include <lttng/channel-internal.h>
+#include <lttng/destruction-handle.h>
+#include <lttng/endpoint.h>
+#include <lttng/error-query-internal.h>
+#include <lttng/event-internal.h>
+#include <lttng/health-internal.h>
+#include <lttng/lttng-error.h>
+#include <lttng/lttng.h>
+#include <lttng/session-descriptor-internal.h>
+#include <lttng/session-internal.h>
+#include <lttng/trigger/trigger-internal.h>
+#include <lttng/userspace-probe-internal.h>
+
+#include "lttng-ctl-helper.h"
+#include <common/filter/filter-ast.h>
+#include <common/filter/filter-parser.h>
+#include <common/filter/memstream.h>
+
+#define COPY_DOMAIN_PACKED(dst, src) \
+do { \
+ struct lttng_domain _tmp_domain; \
+ \
+ lttng_ctl_copy_lttng_domain(&_tmp_domain, &src); \
+ dst = _tmp_domain; \
+} while (0)
+
+/* Socket to session daemon for communication */
+static int sessiond_socket = -1;
+static char sessiond_sock_path[PATH_MAX];
+
+/* Variables */
+static char *tracing_group;
+static int connected;
+
+/* Global */
+
+/*
+ * Those two variables are used by error.h to silent or control the verbosity of
+ * error message. They are global to the library so application linking with it
+ * are able to compile correctly and also control verbosity of the library.
+ */
+LTTNG_EXPORT int lttng_opt_quiet;
+LTTNG_EXPORT int lttng_opt_verbose;
+LTTNG_EXPORT int lttng_opt_mi;
+
+/*
+ * Copy domain to lttcomm_session_msg domain.
+ *
+ * If domain is unknown, default domain will be the kernel.
+ */
+void lttng_ctl_copy_lttng_domain(struct lttng_domain *dst,
+ struct lttng_domain *src)
+{
+ if (src && dst) {
+ switch (src->type) {
+ case LTTNG_DOMAIN_KERNEL:
+ case LTTNG_DOMAIN_UST:
+ case LTTNG_DOMAIN_JUL:
+ case LTTNG_DOMAIN_LOG4J:
+ case LTTNG_DOMAIN_PYTHON:
+ memcpy(dst, src, sizeof(struct lttng_domain));
+ break;
+ default:
+ memset(dst, 0, sizeof(struct lttng_domain));
+ break;
+ }
+ }
+}
+
+/*
+ * Send lttcomm_session_msg to the session daemon.
+ *
+ * On success, returns the number of bytes sent (>=0)
+ * On error, returns -1
+ */
+static int send_session_msg(struct lttcomm_session_msg *lsm)
+{
+ int ret;
+
+ if (!connected) {
+ ret = -LTTNG_ERR_NO_SESSIOND;
+ goto end;
+ }
+
+ DBG("LSM cmd type: '%s' (%d)", lttcomm_sessiond_command_str((lttcomm_sessiond_command) lsm->cmd_type),
+ lsm->cmd_type);
+
+ ret = lttcomm_send_creds_unix_sock(sessiond_socket, lsm,
+ sizeof(struct lttcomm_session_msg));
+ if (ret < 0) {
+ ret = -LTTNG_ERR_FATAL;
+ }
+
+end:
+ return ret;
+}
+
+/*
+ * Send var len data to the session daemon.
+ *
+ * On success, returns the number of bytes sent (>=0)
+ * On error, returns -1
+ */
+static int send_session_varlen(const void *data, size_t len)
+{
+ int ret;
+
+ if (!connected) {
+ ret = -LTTNG_ERR_NO_SESSIOND;
+ goto end;
+ }
+
+ if (!data || !len) {
+ ret = 0;
+ goto end;
+ }
+
+ ret = lttcomm_send_unix_sock(sessiond_socket, data, len);
+ if (ret < 0) {
+ ret = -LTTNG_ERR_FATAL;
+ }
+
+end:
+ return ret;
+}
+
+/*
+ * Send file descriptors to the session daemon.
+ *
+ * On success, returns the number of bytes sent (>=0)
+ * On error, returns -1
+ */
+static int send_session_fds(const int *fds, size_t nb_fd)
+{
+ int ret;
+
+ if (!connected) {
+ ret = -LTTNG_ERR_NO_SESSIOND;
+ goto end;
+ }
+
+ if (!fds || !nb_fd) {
+ ret = 0;
+ goto end;
+ }
+
+ ret = lttcomm_send_fds_unix_sock(sessiond_socket, fds, nb_fd);
+ if (ret < 0) {
+ ret = -LTTNG_ERR_FATAL;
+ }
+
+end:
+ return ret;
+}
+
+/*
+ * Receive data from the sessiond socket.
+ *
+ * On success, returns the number of bytes received (>=0)
+ * On error, returns a negative lttng_error_code.
+ */
+static int recv_data_sessiond(void *buf, size_t len)
+{
+ int ret;
+
+ LTTNG_ASSERT(len > 0);
+
+ if (!connected) {
+ ret = -LTTNG_ERR_NO_SESSIOND;
+ goto end;
+ }
+
+ ret = lttcomm_recv_unix_sock(sessiond_socket, buf, len);
+ if (ret < 0) {
+ ret = -LTTNG_ERR_FATAL;
+ } else if (ret == 0) {
+ ret = -LTTNG_ERR_NO_SESSIOND;
+ }
+
+end:
+ return ret;
+}
+
+/*
+ * Receive a payload from the session daemon by appending to an existing
+ * payload.
+ * On success, returns the number of bytes received (>=0)
+ * On error, returns a negative lttng_error_code.
+ */
+static int recv_payload_sessiond(struct lttng_payload *payload, size_t len)
+{
+ int ret;
+ const size_t original_payload_size = payload->buffer.size;
+
+ ret = lttng_dynamic_buffer_set_size(
+ &payload->buffer, payload->buffer.size + len);
+ if (ret) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto end;
+ }
+
+ ret = recv_data_sessiond(
+ payload->buffer.data + original_payload_size, len);
+end:
+ return ret;
+}
+
+/*
+ * Check if we are in the specified group.
+ *
+ * If yes return 1, else return -1.
+ */
+int lttng_check_tracing_group(void)
+{
+ gid_t *grp_list, tracing_gid;
+ int grp_list_size, grp_id, i;
+ int ret = -1;
+ const char *grp_name = tracing_group;
+
+ /* Get GID of group 'tracing' */
+ if (utils_get_group_id(grp_name, false, &tracing_gid)) {
+ /* If grp_tracing is NULL, the group does not exist. */
+ goto end;
+ }
+
+ /* Get number of supplementary group IDs */
+ grp_list_size = getgroups(0, NULL);
+ if (grp_list_size < 0) {
+ PERROR("getgroups");
+ goto end;
+ }
+
+ /* Alloc group list of the right size */
+ grp_list = (gid_t *) zmalloc(grp_list_size * sizeof(gid_t));
+ if (!grp_list) {
+ PERROR("malloc");
+ goto end;
+ }
+ grp_id = getgroups(grp_list_size, grp_list);
+ if (grp_id < 0) {
+ PERROR("getgroups");
+ goto free_list;
+ }
+
+ for (i = 0; i < grp_list_size; i++) {
+ if (grp_list[i] == tracing_gid) {
+ ret = 1;
+ break;
+ }
+ }
+
+free_list:
+ free(grp_list);
+
+end:
+ return ret;
+}
+
+static int check_enough_available_memory(size_t num_bytes_requested_per_cpu)
+{
+ int ret;
+ long num_cpu;
+ size_t best_mem_info;
+ size_t num_bytes_requested_total;
+
+ /*
+ * Get the number of CPU currently online to compute the amount of
+ * memory needed to create a buffer for every CPU.
+ */
+ num_cpu = sysconf(_SC_NPROCESSORS_ONLN);
+ if (num_cpu == -1) {
+ goto error;
+ }
+
+ num_bytes_requested_total = num_bytes_requested_per_cpu * num_cpu;
+
+ /*
+ * Try to get the `MemAvail` field of `/proc/meminfo`. This is the most
+ * reliable estimate we can get but it is only exposed by the kernel
+ * since 3.14. (See Linux kernel commit:
+ * 34e431b0ae398fc54ea69ff85ec700722c9da773)
+ */
+ ret = utils_get_memory_available(&best_mem_info);
+ if (ret >= 0) {
+ goto success;
+ }
+
+ /*
+ * As a backup plan, use `MemTotal` field of `/proc/meminfo`. This
+ * is a sanity check for obvious user error.
+ */
+ ret = utils_get_memory_total(&best_mem_info);
+ if (ret >= 0) {
+ goto success;
+ }
+
+error:
+ return -1;
+success:
+ return best_mem_info >= num_bytes_requested_total;
+}
+
+/*
+ * Try connect to session daemon with sock_path.
+ *
+ * Return 0 on success, else -1
+ */
+static int try_connect_sessiond(const char *sock_path)
+{
+ int ret;
+
+ /* If socket exist, we check if the daemon listens for connect. */
+ ret = access(sock_path, F_OK);
+ if (ret < 0) {
+ /* Not alive */
+ goto error;
+ }
+
+ ret = lttcomm_connect_unix_sock(sock_path);
+ if (ret < 0) {
+ /* Not alive. */
+ goto error;
+ }
+
+ ret = lttcomm_close_unix_sock(ret);
+ if (ret < 0) {
+ PERROR("lttcomm_close_unix_sock");
+ }
+
+ return 0;
+
+error:
+ return -1;
+}
+
+/*
+ * Set sessiond socket path by putting it in the global sessiond_sock_path
+ * variable.
+ *
+ * Returns 0 on success, negative value on failure (the sessiond socket path
+ * is somehow too long or ENOMEM).
+ */
+static int set_session_daemon_path(void)
+{
+ int in_tgroup = 0; /* In tracing group. */
+ uid_t uid;
+
+ uid = getuid();
+
+ if (uid != 0) {
+ /* Are we in the tracing group ? */
+ in_tgroup = lttng_check_tracing_group();
+ }
+
+ if ((uid == 0) || in_tgroup == 1) {
+ const int ret = lttng_strncpy(sessiond_sock_path,
+ DEFAULT_GLOBAL_CLIENT_UNIX_SOCK,
+ sizeof(sessiond_sock_path));
+
+ if (ret) {
+ goto error;
+ }
+ }
+
+ if (uid != 0) {
+ int ret;
+
+ if (in_tgroup) {
+ /* Tracing group. */
+ ret = try_connect_sessiond(sessiond_sock_path);
+ if (ret >= 0) {
+ goto end;
+ }
+ /* Global session daemon not available... */
+ }
+ /* ...or not in tracing group (and not root), default */
+
+ /*
+ * With GNU C < 2.1, snprintf returns -1 if the target buffer
+ * is too small;
+ * With GNU C >= 2.1, snprintf returns the required size
+ * (excluding closing null)
+ */
+ ret = snprintf(sessiond_sock_path, sizeof(sessiond_sock_path),
+ DEFAULT_HOME_CLIENT_UNIX_SOCK, utils_get_home_dir());
+ if ((ret < 0) || (ret >= sizeof(sessiond_sock_path))) {
+ goto error;
+ }
+ }
+end:
+ return 0;
+
+error:
+ return -1;
+}
+
+/*
+ * Connect to the LTTng session daemon.
+ *
+ * On success, return the socket's file descriptor. On error, return -1.
+ */
+int connect_sessiond(void)
+{
+ int ret;
+
+ ret = set_session_daemon_path();
+ if (ret < 0) {
+ goto error;
+ }
+
+ /* Connect to the sesssion daemon. */
+ ret = lttcomm_connect_unix_sock(sessiond_sock_path);
+ if (ret < 0) {
+ goto error;
+ }
+
+ return ret;
+
+error:
+ return -1;
+}
+
+static void reset_global_sessiond_connection_state(void)
+{
+ sessiond_socket = -1;
+ connected = 0;
+}
+
+/*
+ * Clean disconnect from the session daemon.
+ *
+ * On success, return 0. On error, return -1.
+ */
+static int disconnect_sessiond(void)
+{
+ int ret = 0;
+
+ if (connected) {
+ ret = lttcomm_close_unix_sock(sessiond_socket);
+ reset_global_sessiond_connection_state();
+ }
+
+ return ret;
+}
+
+static int recv_sessiond_optional_data(size_t len, void **user_buf,
+ size_t *user_len)
+{
+ int ret = 0;
+ void *buf = NULL;
+
+ if (len) {
+ if (!user_len) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ buf = zmalloc(len);
+ if (!buf) {
+ ret = -ENOMEM;
+ goto end;
+ }
+
+ ret = recv_data_sessiond(buf, len);
+ if (ret < 0) {
+ goto end;
+ }
+
+ if (!user_buf) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ /* Move ownership of command header buffer to user. */
+ *user_buf = buf;
+ buf = NULL;
+ *user_len = len;
+ } else {
+ /* No command header. */
+ if (user_len) {
+ *user_len = 0;
+ }
+
+ if (user_buf) {
+ *user_buf = NULL;
+ }
+ }
+
+end:
+ free(buf);
+ return ret;
+}
+
+/*
+ * Ask the session daemon a specific command and put the data into buf.
+ * Takes extra var. len. data and file descriptors as input to send to the
+ * session daemon.
+ *
+ * Return size of data (only payload, not header) or a negative error code.
+ */
+int lttng_ctl_ask_sessiond_fds_varlen(struct lttcomm_session_msg *lsm,
+ const int *fds, size_t nb_fd, const void *vardata,
+ size_t vardata_len, void **user_payload_buf,
+ void **user_cmd_header_buf, size_t *user_cmd_header_len)
+{
+ int ret;
+ size_t payload_len;
+ struct lttcomm_lttng_msg llm;
+
+ ret = connect_sessiond();
+ if (ret < 0) {
+ ret = -LTTNG_ERR_NO_SESSIOND;
+ goto end;
+ } else {
+ sessiond_socket = ret;
+ connected = 1;
+ }
+
+ ret = send_session_msg(lsm);
+ if (ret < 0) {
+ /* Ret value is a valid lttng error code. */
+ goto end;
+ }
+ /* Send var len data */
+ ret = send_session_varlen(vardata, vardata_len);
+ if (ret < 0) {
+ /* Ret value is a valid lttng error code. */
+ goto end;
+ }
+
+ /* Send fds */
+ ret = send_session_fds(fds, nb_fd);
+ if (ret < 0) {
+ /* Ret value is a valid lttng error code. */
+ goto end;
+ }
+
+ /* Get header from data transmission */
+ ret = recv_data_sessiond(&llm, sizeof(llm));
+ if (ret < 0) {
+ /* Ret value is a valid lttng error code. */
+ goto end;
+ }
+
+ /* Check error code if OK */
+ if (llm.ret_code != LTTNG_OK) {
+ ret = -llm.ret_code;
+ goto end;
+ }
+
+ /* Get command header from data transmission */
+ ret = recv_sessiond_optional_data(llm.cmd_header_size,
+ user_cmd_header_buf, user_cmd_header_len);
+ if (ret < 0) {
+ goto end;
+ }
+
+ /* Get payload from data transmission */
+ ret = recv_sessiond_optional_data(llm.data_size, user_payload_buf,
+ &payload_len);
+ if (ret < 0) {
+ goto end;
+ }
+
+ ret = llm.data_size;
+
+end:
+ disconnect_sessiond();
+ return ret;
+}
+
+int lttng_ctl_ask_sessiond_payload(struct lttng_payload_view *message,
+ struct lttng_payload *reply)
+{
+ int ret;
+ struct lttcomm_lttng_msg llm;
+ const int fd_count = lttng_payload_view_get_fd_handle_count(message);
+
+ LTTNG_ASSERT(reply->buffer.size == 0);
+ LTTNG_ASSERT(lttng_dynamic_pointer_array_get_count(&reply->_fd_handles) == 0);
+
+ ret = connect_sessiond();
+ if (ret < 0) {
+ ret = -LTTNG_ERR_NO_SESSIOND;
+ goto end;
+ } else {
+ sessiond_socket = ret;
+ connected = 1;
+ }
+
+ /* Send command to session daemon */
+ ret = lttcomm_send_creds_unix_sock(sessiond_socket, message->buffer.data,
+ message->buffer.size);
+ if (ret < 0) {
+ ret = -LTTNG_ERR_FATAL;
+ goto end;
+ }
+
+ if (fd_count > 0) {
+ ret = lttcomm_send_payload_view_fds_unix_sock(sessiond_socket,
+ message);
+ if (ret < 0) {
+ ret = -LTTNG_ERR_FATAL;
+ goto end;
+ }
+ }
+
+ /* Get header from data transmission */
+ ret = recv_payload_sessiond(reply, sizeof(llm));
+ if (ret < 0) {
+ /* Ret value is a valid lttng error code. */
+ goto end;
+ }
+
+ llm = *((typeof(llm) *) reply->buffer.data);
+
+ /* Check error code if OK */
+ if (llm.ret_code != LTTNG_OK) {
+ if (llm.ret_code < LTTNG_OK || llm.ret_code >= LTTNG_ERR_NR) {
+ /* Invalid error code received. */
+ ret = -LTTNG_ERR_UNK;
+ } else {
+ ret = -llm.ret_code;
+ }
+ goto end;
+ }
+
+ if (llm.cmd_header_size > 0) {
+ ret = recv_payload_sessiond(reply, llm.cmd_header_size);
+ if (ret < 0) {
+ goto end;
+ }
+ }
+
+ /* Get command header from data transmission */
+ if (llm.data_size > 0) {
+ ret = recv_payload_sessiond(reply, llm.data_size);
+ if (ret < 0) {
+ goto end;
+ }
+ }
+
+ if (llm.fd_count > 0) {
+ ret = lttcomm_recv_payload_fds_unix_sock(
+ sessiond_socket, llm.fd_count, reply);
+ if (ret < 0) {
+ goto end;
+ }
+ }
+
+ /* Don't return the llm header to the caller. */
+ memmove(reply->buffer.data, reply->buffer.data + sizeof(llm),
+ reply->buffer.size - sizeof(llm));
+ ret = lttng_dynamic_buffer_set_size(
+ &reply->buffer, reply->buffer.size - sizeof(llm));
+ if (ret) {
+ /* Can't happen as size is reduced. */
+ abort();
+ }
+
+ ret = reply->buffer.size;
+
+end:
+ disconnect_sessiond();
+ return ret;
+}
+
+/*
+ * Create lttng handle and return pointer.
+ *
+ * The returned pointer will be NULL in case of malloc() error.
+ */
+struct lttng_handle *lttng_create_handle(const char *session_name,
+ struct lttng_domain *domain)
+{
+ int ret;
+ struct lttng_handle *handle = NULL;
+
+ handle = (lttng_handle *) zmalloc(sizeof(struct lttng_handle));
+ if (handle == NULL) {
+ PERROR("malloc handle");
+ goto end;
+ }
+
+ /* Copy session name */
+ ret = lttng_strncpy(handle->session_name, session_name ? : "",
+ sizeof(handle->session_name));
+ if (ret) {
+ goto error;
+ }
+
+ /* Copy lttng domain or leave initialized to 0. */
+ if (domain) {
+ lttng_ctl_copy_lttng_domain(&handle->domain, domain);
+ }
+
+end:
+ return handle;
+error:
+ free(handle);
+ return NULL;
+}
+
+/*
+ * Destroy handle by free(3) the pointer.
+ */
+void lttng_destroy_handle(struct lttng_handle *handle)
+{
+ free(handle);
+}
+
+/*
+ * Register an outside consumer.
+ *
+ * Returns size of returned session payload data or a negative error code.
+ */
+int lttng_register_consumer(struct lttng_handle *handle,
+ const char *socket_path)
+{
+ int ret;
+ struct lttcomm_session_msg lsm;
+
+ if (handle == NULL || socket_path == NULL) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ memset(&lsm, 0, sizeof(lsm));
+ lsm.cmd_type = LTTNG_REGISTER_CONSUMER;
+ ret = lttng_strncpy(lsm.session.name, handle->session_name,
+ sizeof(lsm.session.name));
+ if (ret) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ COPY_DOMAIN_PACKED(lsm.domain, handle->domain);
+
+ ret = lttng_strncpy(lsm.u.reg.path, socket_path,
+ sizeof(lsm.u.reg.path));
+ if (ret) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ ret = lttng_ctl_ask_sessiond(&lsm, NULL);
+end:
+ return ret;
+}
+
+/*
+ * Start tracing for all traces of the session.
+ *
+ * Returns size of returned session payload data or a negative error code.
+ */
+int lttng_start_tracing(const char *session_name)
+{
+ int ret;
+ struct lttcomm_session_msg lsm;
+
+ if (session_name == NULL) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ memset(&lsm, 0, sizeof(lsm));
+ lsm.cmd_type = LTTNG_START_TRACE;
+
+ ret = lttng_strncpy(lsm.session.name, session_name,
+ sizeof(lsm.session.name));
+ if (ret) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ ret = lttng_ctl_ask_sessiond(&lsm, NULL);
+end:
+ return ret;
+}
+
+/*
+ * Stop tracing for all traces of the session.
+ */
+static int _lttng_stop_tracing(const char *session_name, int wait)
+{
+ int ret, data_ret;
+ struct lttcomm_session_msg lsm;
+
+ if (session_name == NULL) {
+ ret = -LTTNG_ERR_INVALID;
+ goto error;
+ }
+
+ memset(&lsm, 0, sizeof(lsm));
+ lsm.cmd_type = LTTNG_STOP_TRACE;
+
+ ret = lttng_strncpy(lsm.session.name, session_name,
+ sizeof(lsm.session.name));
+ if (ret) {
+ ret = -LTTNG_ERR_INVALID;
+ goto error;
+ }
+
+ ret = lttng_ctl_ask_sessiond(&lsm, NULL);
+ if (ret < 0 && ret != -LTTNG_ERR_TRACE_ALREADY_STOPPED) {
+ goto error;
+ }
+
+ if (!wait) {
+ goto end;
+ }
+
+ /* Check for data availability */
+ do {
+ data_ret = lttng_data_pending(session_name);
+ if (data_ret < 0) {
+ /* Return the data available call error. */
+ ret = data_ret;
+ goto error;
+ }
+
+ /*
+ * Data sleep time before retrying (in usec). Don't sleep if the
+ * call returned value indicates availability.
+ */
+ if (data_ret) {
+ usleep(DEFAULT_DATA_AVAILABILITY_WAIT_TIME_US);
+ }
+ } while (data_ret != 0);
+
+end:
+error:
+ return ret;
+}
+
+/*
+ * Stop tracing and wait for data availability.
+ */
+int lttng_stop_tracing(const char *session_name)
+{
+ return _lttng_stop_tracing(session_name, 1);
+}
+
+/*
+ * Stop tracing but _don't_ wait for data availability.
+ */
+int lttng_stop_tracing_no_wait(const char *session_name)
+{
+ return _lttng_stop_tracing(session_name, 0);
+}
+
+/*
+ * Add context to a channel.
+ *
+ * If the given channel is NULL, add the contexts to all channels.
+ * The event_name param is ignored.
+ *
+ * Returns the size of the returned payload data or a negative error code.
+ */
+int lttng_add_context(struct lttng_handle *handle,
+ struct lttng_event_context *ctx, const char *event_name,
+ const char *channel_name)
+{
+ int ret;
+ size_t len = 0;
+ char *buf = NULL;
+ struct lttcomm_session_msg lsm;
+
+ /* Safety check. Both are mandatory. */
+ if (handle == NULL || ctx == NULL) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ memset(&lsm, 0, sizeof(lsm));
+ lsm.cmd_type = LTTNG_ADD_CONTEXT;
+
+ /* If no channel name, send empty string. */
+ ret = lttng_strncpy(lsm.u.context.channel_name, channel_name ?: "",
+ sizeof(lsm.u.context.channel_name));
+ if (ret) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ COPY_DOMAIN_PACKED(lsm.domain, handle->domain);
+ ret = lttng_strncpy(lsm.session.name, handle->session_name,
+ sizeof(lsm.session.name));
+ if (ret) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ if (ctx->ctx == LTTNG_EVENT_CONTEXT_APP_CONTEXT) {
+ size_t provider_len, ctx_len;
+ const char *provider_name = ctx->u.app_ctx.provider_name;
+ const char *ctx_name = ctx->u.app_ctx.ctx_name;
+
+ if (!provider_name || !ctx_name) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ provider_len = strlen(provider_name);
+ if (provider_len == 0) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+ lsm.u.context.provider_name_len = provider_len;
+
+ ctx_len = strlen(ctx_name);
+ if (ctx_len == 0) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+ lsm.u.context.context_name_len = ctx_len;
+
+ len = provider_len + ctx_len;
+ buf = (char *) zmalloc(len);
+ if (!buf) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto end;
+ }
+
+ memcpy(buf, provider_name, provider_len);
+ memcpy(buf + provider_len, ctx_name, ctx_len);
+ }
+ memcpy(&lsm.u.context.ctx, ctx, sizeof(struct lttng_event_context));
+
+ if (ctx->ctx == LTTNG_EVENT_CONTEXT_APP_CONTEXT) {
+ /*
+ * Don't leak application addresses to the sessiond.
+ * This is only necessary when ctx is for an app ctx otherwise
+ * the values inside the union (type & config) are overwritten.
+ */
+ lsm.u.context.ctx.u.app_ctx.provider_name = NULL;
+ lsm.u.context.ctx.u.app_ctx.ctx_name = NULL;
+ }
+
+ ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header(&lsm, buf, len, NULL);
+end:
+ free(buf);
+ return ret;
+}
+
+/*
+ * Enable event(s) for a channel.
+ *
+ * If no event name is specified, all events are enabled.
+ * If no channel name is specified, the default 'channel0' is used.
+ *
+ * Returns size of returned session payload data or a negative error code.
+ */
+int lttng_enable_event(struct lttng_handle *handle,
+ struct lttng_event *ev, const char *channel_name)
+{
+ return lttng_enable_event_with_exclusions(handle, ev, channel_name,
+ NULL, 0, NULL);
+}
+
+/*
+ * Create or enable an event with a filter expression.
+ *
+ * Return negative error value on error.
+ * Return size of returned session payload data if OK.
+ */
+int lttng_enable_event_with_filter(struct lttng_handle *handle,
+ struct lttng_event *event, const char *channel_name,
+ const char *filter_expression)
+{
+ return lttng_enable_event_with_exclusions(handle, event, channel_name,
+ filter_expression, 0, NULL);
+}
+
+/*
+ * Depending on the event, return a newly allocated agent filter expression or
+ * NULL if not applicable.
+ *
+ * An event with NO loglevel and the name is * will return NULL.
+ */
+static char *set_agent_filter(const char *filter, struct lttng_event *ev)
+{
+ int err;
+ char *agent_filter = NULL;
+
+ LTTNG_ASSERT(ev);
+
+ /* Don't add filter for the '*' event. */
+ if (strcmp(ev->name, "*") != 0) {
+ if (filter) {
+ err = asprintf(&agent_filter, "(%s) && (logger_name == \"%s\")", filter,
+ ev->name);
+ } else {
+ err = asprintf(&agent_filter, "logger_name == \"%s\"", ev->name);
+ }
+ if (err < 0) {
+ PERROR("asprintf");
+ goto error;
+ }
+ }
+
+ /* Add loglevel filtering if any for the JUL domain. */
+ if (ev->loglevel_type != LTTNG_EVENT_LOGLEVEL_ALL) {
+ const char *op;
+
+ if (ev->loglevel_type == LTTNG_EVENT_LOGLEVEL_RANGE) {
+ op = ">=";
+ } else {
+ op = "==";
+ }
+
+ if (filter || agent_filter) {
+ char *new_filter;
+
+ err = asprintf(&new_filter, "(%s) && (int_loglevel %s %d)",
+ agent_filter ? agent_filter : filter, op,
+ ev->loglevel);
+ if (agent_filter) {
+ free(agent_filter);
+ }
+ agent_filter = new_filter;
+ } else {
+ err = asprintf(&agent_filter, "int_loglevel %s %d", op,
+ ev->loglevel);
+ }
+ if (err < 0) {
+ PERROR("asprintf");
+ goto error;
+ }
+ }
+
+ return agent_filter;
+error:
+ free(agent_filter);
+ return NULL;
+}
+
+/*
+ * Enable event(s) for a channel, possibly with exclusions and a filter.
+ * If no event name is specified, all events are enabled.
+ * If no channel name is specified, the default name is used.
+ * If filter expression is not NULL, the filter is set for the event.
+ * If exclusion count is not zero, the exclusions are set for the event.
+ * Returns size of returned session payload data or a negative error code.
+ */
+int lttng_enable_event_with_exclusions(struct lttng_handle *handle,
+ struct lttng_event *ev, const char *channel_name,
+ const char *original_filter_expression,
+ int exclusion_count, char **exclusion_list)
+{
+ struct lttcomm_session_msg lsm;
+ struct lttng_payload payload;
+ int ret = 0, i;
+ unsigned int free_filter_expression = 0;
+ struct filter_parser_ctx *ctx = NULL;
+
+ /*
+ * We have either a filter or some exclusions, so we need to set up
+ * a variable-length payload from where to send the data.
+ */
+ lttng_payload_init(&payload);
+
+ /*
+ * Cast as non-const since we may replace the filter expression
+ * by a dynamically allocated string. Otherwise, the original
+ * string is not modified.
+ */
+ char *filter_expression = (char *) original_filter_expression;
+
+ if (handle == NULL || ev == NULL) {
+ ret = -LTTNG_ERR_INVALID;
+ goto error;
+ }
+
+ /*
+ * Empty filter string will always be rejected by the parser
+ * anyway, so treat this corner-case early to eliminate
+ * lttng_fmemopen error for 0-byte allocation.
+ */
+ if (filter_expression && filter_expression[0] == '\0') {
+ ret = -LTTNG_ERR_INVALID;
+ goto error;
+ }
+
+ memset(&lsm, 0, sizeof(lsm));
+
+ /* If no channel name, send empty string. */
+ ret = lttng_strncpy(lsm.u.enable.channel_name, channel_name ?: "",
+ sizeof(lsm.u.enable.channel_name));
+ if (ret) {
+ ret = -LTTNG_ERR_INVALID;
+ goto error;
+ }
+
+ lsm.cmd_type = LTTNG_ENABLE_EVENT;
+ if (ev->name[0] == '\0') {
+ /* Enable all events. */
+ ret = lttng_strncpy(ev->name, "*", sizeof(ev->name));
+ LTTNG_ASSERT(ret == 0);
+ }
+
+ COPY_DOMAIN_PACKED(lsm.domain, handle->domain);
+ memcpy(&lsm.u.enable.event, ev, sizeof(lsm.u.enable.event));
+
+ ret = lttng_strncpy(lsm.session.name, handle->session_name,
+ sizeof(lsm.session.name));
+ if (ret) {
+ ret = -LTTNG_ERR_INVALID;
+ goto error;
+ }
+
+ lsm.u.enable.exclusion_count = exclusion_count;
+ lsm.u.enable.bytecode_len = 0;
+
+ /* Parse filter expression. */
+ if (filter_expression != NULL || handle->domain.type == LTTNG_DOMAIN_JUL
+ || handle->domain.type == LTTNG_DOMAIN_LOG4J
+ || handle->domain.type == LTTNG_DOMAIN_PYTHON) {
+ if (handle->domain.type == LTTNG_DOMAIN_JUL ||
+ handle->domain.type == LTTNG_DOMAIN_LOG4J ||
+ handle->domain.type == LTTNG_DOMAIN_PYTHON) {
+ char *agent_filter;
+
+ /* Setup JUL filter if needed. */
+ agent_filter = set_agent_filter(filter_expression, ev);
+ if (!agent_filter) {
+ if (!filter_expression) {
+ /*
+ * No JUL and no filter, just skip
+ * everything below.
+ */
+ goto ask_sessiond;
+ }
+ } else {
+ /*
+ * With an agent filter, the original filter has
+ * been added to it thus replace the filter
+ * expression.
+ */
+ filter_expression = agent_filter;
+ free_filter_expression = 1;
+ }
+ }
+
+ ret = filter_parser_ctx_create_from_filter_expression(filter_expression, &ctx);
+ if (ret) {
+ goto filter_error;
+ }
+
+ lsm.u.enable.bytecode_len = sizeof(ctx->bytecode->b)
+ + bytecode_get_len(&ctx->bytecode->b);
+ lsm.u.enable.expression_len = strlen(filter_expression) + 1;
+ }
+
+ ret = lttng_dynamic_buffer_set_capacity(&payload.buffer,
+ lsm.u.enable.bytecode_len +
+ lsm.u.enable.expression_len +
+ LTTNG_SYMBOL_NAME_LEN *
+ exclusion_count);
+ if (ret) {
+ ret = -LTTNG_ERR_EXCLUSION_NOMEM;
+ goto mem_error;
+ }
+
+ /* Put exclusion names first in the data. */
+ for (i = 0; i < exclusion_count; i++) {
+ size_t exclusion_len;
+
+ exclusion_len = lttng_strnlen(exclusion_list[i],
+ LTTNG_SYMBOL_NAME_LEN);
+ if (exclusion_len == LTTNG_SYMBOL_NAME_LEN) {
+ /* Exclusion is not NULL-terminated. */
+ ret = -LTTNG_ERR_INVALID;
+ goto mem_error;
+ }
+
+ ret = lttng_dynamic_buffer_append(&payload.buffer,
+ exclusion_list[i], exclusion_len);
+ if (ret) {
+ goto mem_error;
+ }
+
+ /*
+ * Padding the rest of the entry with zeros. Every exclusion
+ * entries take LTTNG_SYMBOL_NAME_LEN bytes in the buffer.
+ */
+ ret = lttng_dynamic_buffer_set_size(&payload.buffer,
+ LTTNG_SYMBOL_NAME_LEN * (i + 1));
+ if (ret) {
+ goto mem_error;
+ }
+ }
+
+ /* Add filter expression next. */
+ if (filter_expression) {
+ ret = lttng_dynamic_buffer_append(&payload.buffer,
+ filter_expression, lsm.u.enable.expression_len);
+ if (ret) {
+ goto mem_error;
+ }
+ }
+ /* Add filter bytecode next. */
+ if (ctx && lsm.u.enable.bytecode_len != 0) {
+ ret = lttng_dynamic_buffer_append(&payload.buffer,
+ &ctx->bytecode->b, lsm.u.enable.bytecode_len);
+ if (ret) {
+ goto mem_error;
+ }
+ }
+ if (ev->extended.ptr) {
+ struct lttng_event_extended *ev_ext =
+ (struct lttng_event_extended *) ev->extended.ptr;
+
+ if (ev_ext->probe_location) {
+ /*
+ * lttng_userspace_probe_location_serialize returns the
+ * number of bytes that was appended to the buffer.
+ */
+ ret = lttng_userspace_probe_location_serialize(
+ ev_ext->probe_location, &payload);
+ if (ret < 0) {
+ goto mem_error;
+ }
+
+ /*
+ * Set the size of the userspace probe location element
+ * of the buffer so that the receiving side knows where
+ * to split it.
+ */
+ lsm.u.enable.userspace_probe_location_len = ret;
+ }
+ }
+
+ {
+ struct lttng_payload_view view = lttng_payload_view_from_payload(
+ &payload, 0, -1);
+ int fd_count = lttng_payload_view_get_fd_handle_count(&view);
+ int fd_to_send;
+
+ if (fd_count < 0) {
+ goto mem_error;
+ }
+
+ LTTNG_ASSERT(fd_count == 0 || fd_count == 1);
+ if (fd_count == 1) {
+ struct fd_handle *h =
+ lttng_payload_view_pop_fd_handle(&view);
+
+ if (!h) {
+ goto mem_error;
+ }
+
+ fd_to_send = fd_handle_get_fd(h);
+ fd_handle_put(h);
+ }
+
+ ret = lttng_ctl_ask_sessiond_fds_varlen(&lsm,
+ fd_count ? &fd_to_send : NULL, fd_count,
+ view.buffer.size ? view.buffer.data : NULL,
+ view.buffer.size, NULL, NULL, 0);
+ }
+
+mem_error:
+ if (filter_expression && ctx) {
+ filter_bytecode_free(ctx);
+ filter_ir_free(ctx);
+ filter_parser_ctx_free(ctx);
+ }
+filter_error:
+ if (free_filter_expression) {
+ /*
+ * The filter expression has been replaced and must be freed as
+ * it is not the original filter expression received as a
+ * parameter.
+ */
+ free(filter_expression);
+ }
+error:
+ /*
+ * Return directly to the caller and don't ask the sessiond since
+ * something went wrong in the parsing of data above.
+ */
+ lttng_payload_reset(&payload);
+ return ret;
+
+ask_sessiond:
+ ret = lttng_ctl_ask_sessiond(&lsm, NULL);
+ return ret;
+}
+
+int lttng_disable_event_ext(struct lttng_handle *handle,
+ struct lttng_event *ev, const char *channel_name,
+ const char *original_filter_expression)
+{
+ struct lttcomm_session_msg lsm;
+ char *varlen_data;
+ int ret = 0;
+ unsigned int free_filter_expression = 0;
+ struct filter_parser_ctx *ctx = NULL;
+ /*
+ * Cast as non-const since we may replace the filter expression
+ * by a dynamically allocated string. Otherwise, the original
+ * string is not modified.
+ */
+ char *filter_expression = (char *) original_filter_expression;
+
+ if (handle == NULL || ev == NULL) {
+ ret = -LTTNG_ERR_INVALID;
+ goto error;
+ }
+
+ /*
+ * Empty filter string will always be rejected by the parser
+ * anyway, so treat this corner-case early to eliminate
+ * lttng_fmemopen error for 0-byte allocation.
+ */
+ if (filter_expression && filter_expression[0] == '\0') {
+ ret = -LTTNG_ERR_INVALID;
+ goto error;
+ }
+
+ memset(&lsm, 0, sizeof(lsm));
+
+ /* If no channel name, send empty string. */
+ ret = lttng_strncpy(lsm.u.disable.channel_name, channel_name ?: "",
+ sizeof(lsm.u.disable.channel_name));
+ if (ret) {
+ ret = -LTTNG_ERR_INVALID;
+ goto error;
+ }
+
+ lsm.cmd_type = LTTNG_DISABLE_EVENT;
+
+ COPY_DOMAIN_PACKED(lsm.domain, handle->domain);
+ memcpy(&lsm.u.disable.event, ev, sizeof(lsm.u.disable.event));
+
+ ret = lttng_strncpy(lsm.session.name, handle->session_name,
+ sizeof(lsm.session.name));
+ if (ret) {
+ ret = -LTTNG_ERR_INVALID;
+ goto error;
+ }
+
+ lsm.u.disable.bytecode_len = 0;
+
+ /*
+ * For the JUL domain, a filter is enforced except for the
+ * disable all event. This is done to avoid having the event in
+ * all sessions thus filtering by logger name.
+ */
+ if (filter_expression == NULL &&
+ (handle->domain.type != LTTNG_DOMAIN_JUL &&
+ handle->domain.type != LTTNG_DOMAIN_LOG4J &&
+ handle->domain.type != LTTNG_DOMAIN_PYTHON)) {
+ goto ask_sessiond;
+ }
+
+ /*
+ * We have a filter, so we need to set up a variable-length
+ * memory block from where to send the data.
+ */
+
+ /* Parse filter expression */
+ if (filter_expression != NULL || handle->domain.type == LTTNG_DOMAIN_JUL
+ || handle->domain.type == LTTNG_DOMAIN_LOG4J
+ || handle->domain.type == LTTNG_DOMAIN_PYTHON) {
+ if (handle->domain.type == LTTNG_DOMAIN_JUL ||
+ handle->domain.type == LTTNG_DOMAIN_LOG4J ||
+ handle->domain.type == LTTNG_DOMAIN_PYTHON) {
+ char *agent_filter;
+
+ /* Setup JUL filter if needed. */
+ agent_filter = set_agent_filter(filter_expression, ev);
+ if (!agent_filter) {
+ if (!filter_expression) {
+ /*
+ * No JUL and no filter, just skip
+ * everything below.
+ */
+ goto ask_sessiond;
+ }
+ } else {
+ /*
+ * With a JUL filter, the original filter has
+ * been added to it thus replace the filter
+ * expression.
+ */
+ filter_expression = agent_filter;
+ free_filter_expression = 1;
+ }
+ }
+
+ ret = filter_parser_ctx_create_from_filter_expression(filter_expression, &ctx);
+ if (ret) {
+ goto filter_error;
+ }
+
+ lsm.u.enable.bytecode_len = sizeof(ctx->bytecode->b)
+ + bytecode_get_len(&ctx->bytecode->b);
+ lsm.u.enable.expression_len = strlen(filter_expression) + 1;
+ }
+
+ varlen_data = (char *) zmalloc(lsm.u.disable.bytecode_len
+ + lsm.u.disable.expression_len);
+ if (!varlen_data) {
+ ret = -LTTNG_ERR_EXCLUSION_NOMEM;
+ goto mem_error;
+ }
+
+ /* Add filter expression. */
+ if (lsm.u.disable.expression_len != 0) {
+ memcpy(varlen_data,
+ filter_expression,
+ lsm.u.disable.expression_len);
+ }
+ /* Add filter bytecode next. */
+ if (ctx && lsm.u.disable.bytecode_len != 0) {
+ memcpy(varlen_data
+ + lsm.u.disable.expression_len,
+ &ctx->bytecode->b,
+ lsm.u.disable.bytecode_len);
+ }
+
+ ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header(&lsm, varlen_data,
+ lsm.u.disable.bytecode_len + lsm.u.disable.expression_len, NULL);
+ free(varlen_data);
+
+mem_error:
+ if (filter_expression && ctx) {
+ filter_bytecode_free(ctx);
+ filter_ir_free(ctx);
+ filter_parser_ctx_free(ctx);
+ }
+filter_error:
+ if (free_filter_expression) {
+ /*
+ * The filter expression has been replaced and must be freed as
+ * it is not the original filter expression received as a
+ * parameter.
+ */
+ free(filter_expression);
+ }
+error:
+ /*
+ * Return directly to the caller and don't ask the sessiond since
+ * something went wrong in the parsing of data above.
+ */
+ return ret;
+
+ask_sessiond:
+ ret = lttng_ctl_ask_sessiond(&lsm, NULL);
+ return ret;
+}
+
+/*
+ * Disable event(s) of a channel and domain.
+ * If no event name is specified, all events are disabled.
+ * If no channel name is specified, the default 'channel0' is used.
+ * Returns size of returned session payload data or a negative error code.
+ */
+int lttng_disable_event(struct lttng_handle *handle, const char *name,
+ const char *channel_name)
+{
+ int ret;
+ struct lttng_event ev;
+
+ memset(&ev, 0, sizeof(ev));
+ ev.loglevel = -1;
+ ev.type = LTTNG_EVENT_ALL;
+ ret = lttng_strncpy(ev.name, name ?: "", sizeof(ev.name));
+ if (ret) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ ret = lttng_disable_event_ext(handle, &ev, channel_name, NULL);
+end:
+ return ret;
+}
+
+struct lttng_channel *lttng_channel_create(struct lttng_domain *domain)
+{
+ struct lttng_channel *channel = NULL;
+ struct lttng_channel_extended *extended = NULL;
+
+ if (!domain) {
+ goto error;
+ }
+
+ /* Validate domain. */
+ switch (domain->type) {
+ case LTTNG_DOMAIN_UST:
+ switch (domain->buf_type) {
+ case LTTNG_BUFFER_PER_UID:
+ case LTTNG_BUFFER_PER_PID:
+ break;
+ default:
+ goto error;
+ }
+ break;
+ case LTTNG_DOMAIN_KERNEL:
+ if (domain->buf_type != LTTNG_BUFFER_GLOBAL) {
+ goto error;
+ }
+ break;
+ default:
+ goto error;
+ }
+
+ channel = (lttng_channel *) zmalloc(sizeof(*channel));
+ if (!channel) {
+ goto error;
+ }
+
+ extended = (lttng_channel_extended *) zmalloc(sizeof(*extended));
+ if (!extended) {
+ goto error;
+ }
+
+ channel->attr.extended.ptr = extended;
+
+ lttng_channel_set_default_attr(domain, &channel->attr);
+ return channel;
+error:
+ free(channel);
+ free(extended);
+ return NULL;
+}
+
+void lttng_channel_destroy(struct lttng_channel *channel)
+{
+ if (!channel) {
+ return;
+ }
+
+ if (channel->attr.extended.ptr) {
+ free(channel->attr.extended.ptr);
+ }
+ free(channel);
+}
+
+/*
+ * Enable channel per domain
+ * Returns size of returned session payload data or a negative error code.
+ */
+int lttng_enable_channel(struct lttng_handle *handle,
+ struct lttng_channel *in_chan)
+{
+ int ret;
+ struct lttcomm_session_msg lsm;
+ size_t total_buffer_size_needed_per_cpu = 0;
+
+ /* NULL arguments are forbidden. No default values. */
+ if (handle == NULL || in_chan == NULL) {
+ return -LTTNG_ERR_INVALID;
+ }
+
+ memset(&lsm, 0, sizeof(lsm));
+ memcpy(&lsm.u.channel.chan, in_chan, sizeof(lsm.u.channel.chan));
+ lsm.u.channel.chan.attr.extended.ptr = NULL;
+
+ if (!in_chan->attr.extended.ptr) {
+ struct lttng_channel *channel;
+ struct lttng_channel_extended *extended;
+
+ channel = lttng_channel_create(&handle->domain);
+ if (!channel) {
+ return -LTTNG_ERR_NOMEM;
+ }
+
+ /*
+ * Create a new channel in order to use default extended
+ * attribute values.
+ */
+ extended = (struct lttng_channel_extended *)
+ channel->attr.extended.ptr;
+ memcpy(&lsm.u.channel.extended, extended, sizeof(*extended));
+ lttng_channel_destroy(channel);
+ } else {
+ struct lttng_channel_extended *extended;
+
+ extended = (struct lttng_channel_extended *)
+ in_chan->attr.extended.ptr;
+ memcpy(&lsm.u.channel.extended, extended, sizeof(*extended));
+ }
+
+ /*
+ * Verify that the amount of memory required to create the requested
+ * buffer is available on the system at the moment.
+ */
+ total_buffer_size_needed_per_cpu = lsm.u.channel.chan.attr.num_subbuf *
+ lsm.u.channel.chan.attr.subbuf_size;
+ if (!check_enough_available_memory(total_buffer_size_needed_per_cpu)) {
+ return -LTTNG_ERR_NOMEM;
+ }
+
+ lsm.cmd_type = LTTNG_ENABLE_CHANNEL;
+ COPY_DOMAIN_PACKED(lsm.domain, handle->domain);
+
+ ret = lttng_strncpy(lsm.session.name, handle->session_name,
+ sizeof(lsm.session.name));
+ if (ret) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ ret = lttng_ctl_ask_sessiond(&lsm, NULL);
+end:
+ return ret;
+}
+
+/*
+ * All tracing will be stopped for registered events of the channel.
+ * Returns size of returned session payload data or a negative error code.
+ */
+int lttng_disable_channel(struct lttng_handle *handle, const char *name)
+{
+ int ret;
+ struct lttcomm_session_msg lsm;
+
+ /* Safety check. Both are mandatory. */
+ if (handle == NULL || name == NULL) {
+ return -LTTNG_ERR_INVALID;
+ }
+
+ memset(&lsm, 0, sizeof(lsm));
+
+ lsm.cmd_type = LTTNG_DISABLE_CHANNEL;
+
+ ret = lttng_strncpy(lsm.u.disable.channel_name, name,
+ sizeof(lsm.u.disable.channel_name));
+ if (ret) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ COPY_DOMAIN_PACKED(lsm.domain, handle->domain);
+
+ ret = lttng_strncpy(lsm.session.name, handle->session_name,
+ sizeof(lsm.session.name));
+ if (ret) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ ret = lttng_ctl_ask_sessiond(&lsm, NULL);
+end:
+ return ret;
+}
+
+/*
+ * Lists all available tracepoints of domain.
+ * Sets the contents of the events array.
+ * Returns the number of lttng_event entries in events;
+ * on error, returns a negative value.
+ */
+int lttng_list_tracepoints(struct lttng_handle *handle,
+ struct lttng_event **events)
+{
+ int ret;
+ struct lttcomm_session_msg lsm;
+
+ if (handle == NULL) {
+ return -LTTNG_ERR_INVALID;
+ }
+
+ memset(&lsm, 0, sizeof(lsm));
+ lsm.cmd_type = LTTNG_LIST_TRACEPOINTS;
+ COPY_DOMAIN_PACKED(lsm.domain, handle->domain);
+
+ ret = lttng_ctl_ask_sessiond(&lsm, (void **) events);
+ if (ret < 0) {
+ return ret;
+ }
+
+ return ret / sizeof(struct lttng_event);
+}
+
+/*
+ * Lists all available tracepoint fields of domain.
+ * Sets the contents of the event field array.
+ * Returns the number of lttng_event_field entries in events;
+ * on error, returns a negative value.
+ */
+int lttng_list_tracepoint_fields(struct lttng_handle *handle,
+ struct lttng_event_field **fields)
+{
+ int ret;
+ struct lttcomm_session_msg lsm;
+
+ if (handle == NULL) {
+ return -LTTNG_ERR_INVALID;
+ }
+
+ memset(&lsm, 0, sizeof(lsm));
+ lsm.cmd_type = LTTNG_LIST_TRACEPOINT_FIELDS;
+ COPY_DOMAIN_PACKED(lsm.domain, handle->domain);
+
+ ret = lttng_ctl_ask_sessiond(&lsm, (void **) fields);
+ if (ret < 0) {
+ return ret;
+ }
+
+ return ret / sizeof(struct lttng_event_field);
+}
+
+/*
+ * Lists all available kernel system calls. Allocates and sets the contents of
+ * the events array.
+ *
+ * Returns the number of lttng_event entries in events; on error, returns a
+ * negative value.
+ */
+int lttng_list_syscalls(struct lttng_event **events)
+{
+ int ret;
+ struct lttcomm_session_msg lsm;
+
+ if (!events) {
+ return -LTTNG_ERR_INVALID;
+ }
+
+ memset(&lsm, 0, sizeof(lsm));
+ lsm.cmd_type = LTTNG_LIST_SYSCALLS;
+ /* Force kernel domain for system calls. */
+ lsm.domain.type = LTTNG_DOMAIN_KERNEL;
+
+ ret = lttng_ctl_ask_sessiond(&lsm, (void **) events);
+ if (ret < 0) {
+ return ret;
+ }
+
+ return ret / sizeof(struct lttng_event);
+}
+
+/*
+ * Returns a human readable string describing
+ * the error code (a negative value).
+ */
+const char *lttng_strerror(int code)
+{
+ return error_get_str(code);
+}
+
+enum lttng_error_code lttng_create_session_ext(
+ struct lttng_session_descriptor *session_descriptor)
+{
+ enum lttng_error_code ret_code;
+ struct lttcomm_session_msg lsm = {
+ .cmd_type = LTTNG_CREATE_SESSION_EXT,
+ };
+ void *reply = NULL;
+ struct lttng_buffer_view reply_view;
+ int reply_ret;
+ bool sessiond_must_generate_ouput;
+ struct lttng_dynamic_buffer payload;
+ int ret;
+ size_t descriptor_size;
+ struct lttng_session_descriptor *descriptor_reply = NULL;
+
+ lttng_dynamic_buffer_init(&payload);
+ if (!session_descriptor) {
+ ret_code = LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ sessiond_must_generate_ouput =
+ !lttng_session_descriptor_is_output_destination_initialized(
+ session_descriptor);
+ if (sessiond_must_generate_ouput) {
+ const char *home_dir = utils_get_home_dir();
+ size_t home_dir_len = home_dir ? strlen(home_dir) + 1 : 0;
+
+ if (!home_dir || home_dir_len > LTTNG_PATH_MAX) {
+ ret_code = LTTNG_ERR_FATAL;
+ goto end;
+ }
+
+ lsm.u.create_session.home_dir_size = (uint16_t) home_dir_len;
+ ret = lttng_dynamic_buffer_append(&payload, home_dir,
+ home_dir_len);
+ if (ret) {
+ ret_code = LTTNG_ERR_NOMEM;
+ goto end;
+ }
+ }
+
+ descriptor_size = payload.size;
+ ret = lttng_session_descriptor_serialize(session_descriptor,
+ &payload);
+ if (ret) {
+ ret_code = LTTNG_ERR_INVALID;
+ goto end;
+ }
+ descriptor_size = payload.size - descriptor_size;
+ lsm.u.create_session.session_descriptor_size = descriptor_size;
+
+ /* Command returns a session descriptor on success. */
+ reply_ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header(&lsm, payload.data,
+ payload.size, &reply);
+ if (reply_ret < 0) {
+ ret_code = (lttng_error_code) -reply_ret;
+ goto end;
+ } else if (reply_ret == 0) {
+ /* Socket unexpectedly closed by the session daemon. */
+ ret_code = LTTNG_ERR_FATAL;
+ goto end;
+ }
+
+ reply_view = lttng_buffer_view_init((const char *) reply, 0, reply_ret);
+ ret = lttng_session_descriptor_create_from_buffer(&reply_view,
+ &descriptor_reply);
+ if (ret < 0) {
+ ret_code = LTTNG_ERR_FATAL;
+ goto end;
+ }
+ ret_code = LTTNG_OK;
+ lttng_session_descriptor_assign(session_descriptor, descriptor_reply);
+end:
+ free(reply);
+ lttng_dynamic_buffer_reset(&payload);
+ lttng_session_descriptor_destroy(descriptor_reply);
+ return ret_code;
+}
+
+/*
+ * Create a new session using name and url for destination.
+ *
+ * Return 0 on success else a negative LTTng error code.
+ */
+int lttng_create_session(const char *name, const char *url)
+{
+ int ret;
+ ssize_t size;
+ struct lttng_uri *uris = NULL;
+ struct lttng_session_descriptor *descriptor = NULL;
+ enum lttng_error_code ret_code;
+
+ if (!name) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ size = uri_parse_str_urls(url, NULL, &uris);
+ if (size < 0) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+ switch (size) {
+ case 0:
+ descriptor = lttng_session_descriptor_create(name);
+ break;
+ case 1:
+ if (uris[0].dtype != LTTNG_DST_PATH) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+ descriptor = lttng_session_descriptor_local_create(name,
+ uris[0].dst.path);
+ break;
+ case 2:
+ descriptor = lttng_session_descriptor_network_create(name, url,
+ NULL);
+ break;
+ default:
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+ if (!descriptor) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+ ret_code = lttng_create_session_ext(descriptor);
+ ret = ret_code == LTTNG_OK ? 0 : -ret_code;
+end:
+ lttng_session_descriptor_destroy(descriptor);
+ free(uris);
+ return ret;
+}
+
+/*
+ * Create a session exclusively used for snapshot.
+ *
+ * Return 0 on success else a negative LTTng error code.
+ */
+int lttng_create_session_snapshot(const char *name, const char *snapshot_url)
+{
+ int ret;
+ enum lttng_error_code ret_code;
+ ssize_t size;
+ struct lttng_uri *uris = NULL;
+ struct lttng_session_descriptor *descriptor = NULL;
+
+ if (!name) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ size = uri_parse_str_urls(snapshot_url, NULL, &uris);
+ if (size < 0) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+ /*
+ * If the user does not specify a custom subdir, use the session name.
+ */
+ if (size > 0 && uris[0].dtype != LTTNG_DST_PATH &&
+ strlen(uris[0].subdir) == 0) {
+ ret = snprintf(uris[0].subdir, sizeof(uris[0].subdir), "%s",
+ name);
+ if (ret < 0) {
+ PERROR("Failed to set session name as network destination sub-directory");
+ ret = -LTTNG_ERR_FATAL;
+ goto end;
+ } else if (ret >= sizeof(uris[0].subdir)) {
+ /* Truncated output. */
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+ }
+
+ switch (size) {
+ case 0:
+ descriptor = lttng_session_descriptor_snapshot_create(name);
+ break;
+ case 1:
+ if (uris[0].dtype != LTTNG_DST_PATH) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+ descriptor = lttng_session_descriptor_snapshot_local_create(
+ name,
+ uris[0].dst.path);
+ break;
+ case 2:
+ descriptor = lttng_session_descriptor_snapshot_network_create(
+ name,
+ snapshot_url,
+ NULL);
+ break;
+ default:
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+ if (!descriptor) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+ ret_code = lttng_create_session_ext(descriptor);
+ ret = ret_code == LTTNG_OK ? 0 : -ret_code;
+end:
+ lttng_session_descriptor_destroy(descriptor);
+ free(uris);
+ return ret;
+}
+
+/*
+ * Create a session exclusively used for live.
+ *
+ * Return 0 on success else a negative LTTng error code.
+ */
+int lttng_create_session_live(const char *name, const char *url,
+ unsigned int timer_interval)
+{
+ int ret;
+ enum lttng_error_code ret_code;
+ struct lttng_session_descriptor *descriptor = NULL;
+
+ if (!name) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ if (url) {
+ descriptor = lttng_session_descriptor_live_network_create(
+ name, url, NULL, timer_interval);
+ } else {
+ descriptor = lttng_session_descriptor_live_create(
+ name, timer_interval);
+ }
+ if (!descriptor) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+ ret_code = lttng_create_session_ext(descriptor);
+ ret = ret_code == LTTNG_OK ? 0 : -ret_code;
+end:
+ lttng_session_descriptor_destroy(descriptor);
+ return ret;
+}
+
+/*
+ * Stop the session and wait for the data before destroying it
+ *
+ * Return 0 on success else a negative LTTng error code.
+ */
+int lttng_destroy_session(const char *session_name)
+{
+ int ret;
+ enum lttng_error_code ret_code;
+ enum lttng_destruction_handle_status status;
+ struct lttng_destruction_handle *handle = NULL;
+
+ /*
+ * Stop the tracing and wait for the data to be
+ * consumed.
+ */
+ ret = _lttng_stop_tracing(session_name, 1);
+ if (ret && ret != -LTTNG_ERR_TRACE_ALREADY_STOPPED) {
+ goto end;
+ }
+
+ ret_code = lttng_destroy_session_ext(session_name, &handle);
+ if (ret_code != LTTNG_OK) {
+ ret = (int) -ret_code;
+ goto end;
+ }
+ LTTNG_ASSERT(handle);
+
+ /* Block until the completion of the destruction of the session. */
+ status = lttng_destruction_handle_wait_for_completion(handle, -1);
+ if (status != LTTNG_DESTRUCTION_HANDLE_STATUS_COMPLETED) {
+ ret = -LTTNG_ERR_UNK;
+ goto end;
+ }
+
+ status = lttng_destruction_handle_get_result(handle, &ret_code);
+ if (status != LTTNG_DESTRUCTION_HANDLE_STATUS_OK) {
+ ret = -LTTNG_ERR_UNK;
+ goto end;
+ }
+ ret = ret_code == LTTNG_OK ? 0 : -ret_code;
+end:
+ lttng_destruction_handle_destroy(handle);
+ return ret;
+}
+
+/*
+ * Destroy the session without waiting for the data.
+ */
+int lttng_destroy_session_no_wait(const char *session_name)
+{
+ enum lttng_error_code ret_code;
+
+ ret_code = lttng_destroy_session_ext(session_name, NULL);
+ return ret_code == LTTNG_OK ? 0 : -ret_code;
+}
+
+/*
+ * Ask the session daemon for all available sessions.
+ * Sets the contents of the sessions array.
+ * Returns the number of lttng_session entries in sessions;
+ * on error, returns a negative value.
+ */
+int lttng_list_sessions(struct lttng_session **out_sessions)
+{
+ int ret;
+ struct lttcomm_session_msg lsm;
+ const size_t session_size = sizeof(struct lttng_session) +
+ sizeof(struct lttng_session_extended);
+ size_t session_count, i;
+ struct lttng_session_extended *sessions_extended_begin;
+ struct lttng_session *sessions = NULL;
+
+ memset(&lsm, 0, sizeof(lsm));
+ lsm.cmd_type = LTTNG_LIST_SESSIONS;
+ ret = lttng_ctl_ask_sessiond(&lsm, (void**) &sessions);
+ if (ret <= 0) {
+ goto end;
+ }
+ if (!sessions) {
+ ret = -LTTNG_ERR_FATAL;
+ goto end;
+ }
+
+ if (ret % session_size) {
+ ret = -LTTNG_ERR_UNK;
+ free(sessions);
+ *out_sessions = NULL;
+ goto end;
+ }
+ session_count = (size_t) ret / session_size;
+ sessions_extended_begin = (struct lttng_session_extended *)
+ (&sessions[session_count]);
+
+ /* Set extended session info pointers. */
+ for (i = 0; i < session_count; i++) {
+ struct lttng_session *session = &sessions[i];
+ struct lttng_session_extended *extended =
+ &(sessions_extended_begin[i]);
+
+ session->extended.ptr = extended;
+ }
+
+ ret = (int) session_count;
+ *out_sessions = sessions;
+end:
+ return ret;
+}
+
+enum lttng_error_code lttng_session_get_creation_time(
+ const struct lttng_session *session, uint64_t *creation_time)
+{
+ enum lttng_error_code ret = LTTNG_OK;
+ struct lttng_session_extended *extended;
+
+ if (!session || !creation_time || !session->extended.ptr) {
+ ret = LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ extended = (lttng_session_extended *) session->extended.ptr;
+ if (!extended->creation_time.is_set) {
+ /* Not created on the session daemon yet. */
+ ret = LTTNG_ERR_SESSION_NOT_EXIST;
+ goto end;
+ }
+ *creation_time = extended->creation_time.value;
+end:
+ return ret;
+}
+
+int lttng_set_session_shm_path(const char *session_name,
+ const char *shm_path)
+{
+ int ret;
+ struct lttcomm_session_msg lsm;
+
+ if (session_name == NULL) {
+ return -LTTNG_ERR_INVALID;
+ }
+
+ memset(&lsm, 0, sizeof(lsm));
+ lsm.cmd_type = LTTNG_SET_SESSION_SHM_PATH;
+
+ ret = lttng_strncpy(lsm.session.name, session_name,
+ sizeof(lsm.session.name));
+ if (ret) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ ret = lttng_strncpy(lsm.u.set_shm_path.shm_path, shm_path ?: "",
+ sizeof(lsm.u.set_shm_path.shm_path));
+ if (ret) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ ret = lttng_ctl_ask_sessiond(&lsm, NULL);
+end:
+ return ret;
+}
+
+/*
+ * Ask the session daemon for all available domains of a session.
+ * Sets the contents of the domains array.
+ * Returns the number of lttng_domain entries in domains;
+ * on error, returns a negative value.
+ */
+int lttng_list_domains(const char *session_name,
+ struct lttng_domain **domains)
+{
+ int ret;
+ struct lttcomm_session_msg lsm;
+
+ if (session_name == NULL) {
+ ret = -LTTNG_ERR_INVALID;
+ goto error;
+ }
+
+ memset(&lsm, 0, sizeof(lsm));
+ lsm.cmd_type = LTTNG_LIST_DOMAINS;
+
+ ret = lttng_strncpy(lsm.session.name, session_name,
+ sizeof(lsm.session.name));
+ if (ret) {
+ ret = -LTTNG_ERR_INVALID;
+ goto error;
+ }
+
+ ret = lttng_ctl_ask_sessiond(&lsm, (void**) domains);
+ if (ret < 0) {
+ goto error;
+ }
+
+ return ret / sizeof(struct lttng_domain);
+error:
+ return ret;
+}
+
+/*
+ * Ask the session daemon for all available channels of a session.
+ * Sets the contents of the channels array.
+ * Returns the number of lttng_channel entries in channels;
+ * on error, returns a negative value.
+ */
+int lttng_list_channels(struct lttng_handle *handle,
+ struct lttng_channel **channels)
+{
+ int ret;
+ size_t channel_count, i;
+ const size_t channel_size = sizeof(struct lttng_channel) +
+ sizeof(struct lttng_channel_extended);
+ struct lttcomm_session_msg lsm;
+ char *extended_at;
+
+ if (handle == NULL) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ memset(&lsm, 0, sizeof(lsm));
+ lsm.cmd_type = LTTNG_LIST_CHANNELS;
+ ret = lttng_strncpy(lsm.session.name, handle->session_name,
+ sizeof(lsm.session.name));
+ if (ret) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ COPY_DOMAIN_PACKED(lsm.domain, handle->domain);
+
+ ret = lttng_ctl_ask_sessiond(&lsm, (void**) channels);
+ if (ret < 0) {
+ goto end;
+ }
+
+ if (ret % channel_size) {
+ ret = -LTTNG_ERR_UNK;
+ free(*channels);
+ *channels = NULL;
+ goto end;
+ }
+ channel_count = (size_t) ret / channel_size;
+
+ /* Set extended info pointers */
+ extended_at = ((char *) *channels) +
+ channel_count * sizeof(struct lttng_channel);
+ for (i = 0; i < channel_count; i++) {
+ struct lttng_channel *chan = &(*channels)[i];
+
+ chan->attr.extended.ptr = extended_at;
+ extended_at += sizeof(struct lttng_channel_extended);
+ }
+
+ ret = (int) channel_count;
+end:
+ return ret;
+}
+
+/*
+ * Ask the session daemon for all available events of a session channel.
+ * Sets the contents of the events array.
+ * Returns the number of lttng_event entries in events;
+ * on error, returns a negative value.
+ */
+int lttng_list_events(struct lttng_handle *handle,
+ const char *channel_name, struct lttng_event **events)
+{
+ int ret;
+ struct lttcomm_session_msg lsm = {};
+ const struct lttcomm_event_command_header *cmd_header = NULL;
+ uint32_t nb_events, i;
+ const char *comm_ext_at;
+ struct lttng_dynamic_buffer listing;
+ size_t storage_req;
+ struct lttng_payload payload;
+ struct lttng_payload payload_copy;
+ struct lttng_payload_view lsm_view =
+ lttng_payload_view_init_from_buffer(
+ (const char *) &lsm, 0, sizeof(lsm));
+ struct lttng_buffer_view cmd_header_view;
+ struct lttng_buffer_view cmd_payload_view;
+ struct lttng_buffer_view flat_events_view;
+ struct lttng_buffer_view ext_view;
+
+ /* Safety check. An handle and channel name are mandatory */
+ if (handle == NULL || channel_name == NULL) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ lttng_payload_init(&payload);
+ lttng_payload_init(&payload_copy);
+
+ lsm.cmd_type = LTTNG_LIST_EVENTS;
+ ret = lttng_strncpy(lsm.session.name, handle->session_name,
+ sizeof(lsm.session.name));
+ if (ret) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ ret = lttng_strncpy(lsm.u.list.channel_name, channel_name,
+ sizeof(lsm.u.list.channel_name));
+ if (ret) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ COPY_DOMAIN_PACKED(lsm.domain, handle->domain);
+
+ ret = lttng_ctl_ask_sessiond_payload(&lsm_view, &payload);
+ if (ret < 0) {
+ goto end;
+ }
+
+ /*
+ * A copy of the payload is performed since it will be
+ * consumed twice. Consuming the same payload twice is invalid since
+ * it will cause any received file descriptor to become "shared"
+ * between different instances of the resulting objects.
+ */
+ ret = lttng_payload_copy(&payload, &payload_copy);
+ if (ret) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto end;
+ }
+
+ cmd_header_view = lttng_buffer_view_from_dynamic_buffer(
+ &payload.buffer, 0, sizeof(*cmd_header));
+ if (!lttng_buffer_view_is_valid(&cmd_header_view)) {
+ ret = -LTTNG_ERR_INVALID_PROTOCOL;
+ goto end;
+ }
+
+ cmd_header = (typeof(cmd_header)) cmd_header_view.data;
+
+ /* Set number of events and free command header */
+ nb_events = cmd_header->nb_events;
+ if (nb_events > INT_MAX) {
+ ret = -LTTNG_ERR_OVERFLOW;
+ goto end;
+ }
+
+ cmd_payload_view = lttng_buffer_view_from_dynamic_buffer(
+ &payload.buffer, sizeof(*cmd_header), -1);
+
+ /*
+ * The buffer that is returned must contain a "flat" version of
+ * the events that are returned. In other words, all pointers
+ * within an lttng_event must point to a location within the returned
+ * buffer so that the user may free everything by simply calling free()
+ * on the returned buffer. This is needed in order to maintain API
+ * compatibility.
+ *
+ * A first pass is performed to compute the size of the buffer that
+ * must be allocated. A second pass is then performed to setup
+ * the returned events so that their members always point within the
+ * buffer.
+ *
+ * The layout of the returned buffer is as follows:
+ * - struct lttng_event[nb_events],
+ * - nb_events times the following:
+ * - struct lttng_event_extended,
+ * - flattened version of userspace_probe_location
+ * - filter_expression
+ * - exclusions
+ * - padding to align to 64-bits
+ */
+ ext_view = lttng_buffer_view_from_view(&cmd_payload_view,
+ nb_events * sizeof(struct lttng_event), -1);
+ comm_ext_at = ext_view.data;
+ storage_req = nb_events * sizeof(struct lttng_event);
+ {
+ struct lttng_payload_view payload_view =
+ lttng_payload_view_from_payload(&payload, 0, -1);
+
+ for (i = 0; i < nb_events; i++) {
+ const struct lttcomm_event_extended_header *ext_comm =
+ (struct lttcomm_event_extended_header *)
+ comm_ext_at;
+ int probe_storage_req = 0;
+
+ comm_ext_at += sizeof(*ext_comm);
+ comm_ext_at += ext_comm->filter_len;
+ comm_ext_at += ext_comm->nb_exclusions *
+ LTTNG_SYMBOL_NAME_LEN;
+
+ if (ext_comm->userspace_probe_location_len) {
+ struct lttng_userspace_probe_location
+ *probe_location = NULL;
+ struct lttng_payload_view probe_location_view = lttng_payload_view_from_view(
+ &payload_view,
+ (const char *) comm_ext_at -
+ payload_view.buffer.data,
+ ext_comm->userspace_probe_location_len);
+
+ if (!lttng_payload_view_is_valid(&probe_location_view)) {
+ ret = -LTTNG_ERR_PROBE_LOCATION_INVAL;
+ goto end;
+ }
+
+ /*
+ * Create a temporary userspace probe location
+ * to determine the size needed by a "flattened"
+ * version of that same probe location.
+ */
+ ret = lttng_userspace_probe_location_create_from_payload(
+ &probe_location_view,
+ &probe_location);
+ if (ret < 0) {
+ ret = -LTTNG_ERR_PROBE_LOCATION_INVAL;
+ goto end;
+ }
+
+ ret = lttng_userspace_probe_location_flatten(
+ probe_location, NULL);
+ lttng_userspace_probe_location_destroy(
+ probe_location);
+ if (ret < 0) {
+ ret = -LTTNG_ERR_PROBE_LOCATION_INVAL;
+ goto end;
+ }
+
+ probe_storage_req = ret;
+ comm_ext_at += ext_comm->userspace_probe_location_len;
+ }
+
+ storage_req += sizeof(struct lttng_event_extended);
+ storage_req += ext_comm->filter_len;
+ storage_req += ext_comm->nb_exclusions *
+ LTTNG_SYMBOL_NAME_LEN;
+ /* Padding to ensure the flat probe is aligned. */
+ storage_req = lttng_align_ceil(storage_req, sizeof(uint64_t));
+ storage_req += probe_storage_req;
+ }
+ }
+
+ lttng_dynamic_buffer_init(&listing);
+ /*
+ * We must ensure that "listing" is never resized so as to preserve
+ * the validity of the flattened objects.
+ */
+ ret = lttng_dynamic_buffer_set_capacity(&listing, storage_req);
+ if (ret) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto end;
+ }
+
+ cmd_payload_view = lttng_buffer_view_from_dynamic_buffer(
+ &payload_copy.buffer, sizeof(*cmd_header), -1);
+ flat_events_view = lttng_buffer_view_from_view(&cmd_payload_view, 0,
+ nb_events * sizeof(struct lttng_event));
+ ret = lttng_dynamic_buffer_append_view(&listing, &flat_events_view);
+ if (ret) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto free_dynamic_buffer;
+ }
+
+ ext_view = lttng_buffer_view_from_view(&cmd_payload_view,
+ nb_events * sizeof(struct lttng_event), -1);
+ comm_ext_at = ext_view.data;
+
+ {
+ struct lttng_payload_view payload_copy_view =
+ lttng_payload_view_from_payload(
+ &payload_copy, 0, -1);
+
+ for (i = 0; i < nb_events; i++) {
+ struct lttng_event *event = (typeof(event))(
+ listing.data +
+ (sizeof(struct lttng_event) * i));
+ const struct lttcomm_event_extended_header *ext_comm =
+ (typeof(ext_comm)) comm_ext_at;
+ struct lttng_event_extended *event_extended =
+ (typeof(event_extended))(listing.data +
+ listing.size);
+
+ /* Insert struct lttng_event_extended. */
+ ret = lttng_dynamic_buffer_set_size(&listing,
+ listing.size + sizeof(*event_extended));
+ if (ret) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto free_dynamic_buffer;
+ }
+ event->extended.ptr = event_extended;
+
+ comm_ext_at += sizeof(*ext_comm);
+
+ /* Insert filter expression. */
+ if (ext_comm->filter_len) {
+ event_extended->filter_expression =
+ listing.data + listing.size;
+ ret = lttng_dynamic_buffer_append(&listing,
+ comm_ext_at,
+ ext_comm->filter_len);
+ if (ret) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto free_dynamic_buffer;
+ }
+ comm_ext_at += ext_comm->filter_len;
+ }
+
+ /* Insert exclusions. */
+ if (ext_comm->nb_exclusions) {
+ event_extended->exclusions.count =
+ ext_comm->nb_exclusions;
+ event_extended->exclusions.strings =
+ listing.data + listing.size;
+
+ ret = lttng_dynamic_buffer_append(&listing,
+ comm_ext_at,
+ ext_comm->nb_exclusions *
+ LTTNG_SYMBOL_NAME_LEN);
+ if (ret) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto free_dynamic_buffer;
+ }
+ comm_ext_at += ext_comm->nb_exclusions *
+ LTTNG_SYMBOL_NAME_LEN;
+ }
+
+ /* Insert padding to align to 64-bits. */
+ ret = lttng_dynamic_buffer_set_size(&listing,
+ lttng_align_ceil(listing.size,
+ sizeof(uint64_t)));
+ if (ret) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto free_dynamic_buffer;
+ }
+
+ /* Insert flattened userspace probe location. */
+ if (ext_comm->userspace_probe_location_len) {
+ struct lttng_userspace_probe_location
+ *probe_location = NULL;
+ struct lttng_payload_view probe_location_view = lttng_payload_view_from_view(
+ &payload_copy_view,
+ (const char *) comm_ext_at -
+ payload_copy_view.buffer.data,
+ ext_comm->userspace_probe_location_len);
+
+ if (!lttng_payload_view_is_valid(&probe_location_view)) {
+ ret = -LTTNG_ERR_PROBE_LOCATION_INVAL;
+ goto free_dynamic_buffer;
+ }
+
+ ret = lttng_userspace_probe_location_create_from_payload(
+ &probe_location_view,
+ &probe_location);
+ if (ret < 0) {
+ ret = -LTTNG_ERR_PROBE_LOCATION_INVAL;
+ goto free_dynamic_buffer;
+ }
+
+ event_extended->probe_location = (struct lttng_userspace_probe_location
+ *) (listing.data +
+ listing.size);
+ ret = lttng_userspace_probe_location_flatten(
+ probe_location, &listing);
+ lttng_userspace_probe_location_destroy(
+ probe_location);
+ if (ret < 0) {
+ ret = -LTTNG_ERR_PROBE_LOCATION_INVAL;
+ goto free_dynamic_buffer;
+ }
+
+ comm_ext_at += ext_comm->userspace_probe_location_len;
+ }
+ }
+ }
+
+ /* Don't reset listing buffer as we return its content. */
+ *events = (struct lttng_event *) listing.data;
+ lttng_dynamic_buffer_init(&listing);
+ ret = (int) nb_events;
+free_dynamic_buffer:
+ lttng_dynamic_buffer_reset(&listing);
+end:
+ lttng_payload_reset(&payload);
+ lttng_payload_reset(&payload_copy);
+ return ret;
+}
+
+/*
+ * Sets the tracing_group variable with name.
+ * This function allocates memory pointed to by tracing_group.
+ * On success, returns 0, on error, returns -1 (null name) or -ENOMEM.
+ */
+int lttng_set_tracing_group(const char *name)
+{
+ int ret = 0;
+ char *new_group;
+
+ if (name == NULL) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ new_group = strdup(name);
+ if (!new_group) {
+ ret = -LTTNG_ERR_FATAL;
+ goto end;
+ }
+
+ free(tracing_group);
+ tracing_group = new_group;
+ new_group = NULL;
+
+end:
+ return ret;
+}
+
+int lttng_calibrate(struct lttng_handle *handle,
+ struct lttng_calibrate *calibrate)
+{
+ /*
+ * This command was removed in LTTng 2.9.
+ */
+ return -LTTNG_ERR_UND;
+}
+
+/*
+ * Set default channel attributes.
+ * If either or both of the arguments are null, attr content is zeroe'd.
+ */
+void lttng_channel_set_default_attr(struct lttng_domain *domain,
+ struct lttng_channel_attr *attr)
+{
+ struct lttng_channel_extended *extended;
+
+ /* Safety check */
+ if (attr == NULL || domain == NULL) {
+ return;
+ }
+
+ extended = (struct lttng_channel_extended *) attr->extended.ptr;
+ memset(attr, 0, sizeof(struct lttng_channel_attr));
+
+ /* Same for all domains. */
+ attr->overwrite = DEFAULT_CHANNEL_OVERWRITE;
+ attr->tracefile_size = DEFAULT_CHANNEL_TRACEFILE_SIZE;
+ attr->tracefile_count = DEFAULT_CHANNEL_TRACEFILE_COUNT;
+
+ switch (domain->type) {
+ case LTTNG_DOMAIN_KERNEL:
+ attr->switch_timer_interval =
+ DEFAULT_KERNEL_CHANNEL_SWITCH_TIMER;
+ attr->read_timer_interval = DEFAULT_KERNEL_CHANNEL_READ_TIMER;
+ attr->subbuf_size = default_get_kernel_channel_subbuf_size();
+ attr->num_subbuf = DEFAULT_KERNEL_CHANNEL_SUBBUF_NUM;
+ attr->output = DEFAULT_KERNEL_CHANNEL_OUTPUT;
+ if (extended) {
+ extended->monitor_timer_interval =
+ DEFAULT_KERNEL_CHANNEL_MONITOR_TIMER;
+ extended->blocking_timeout =
+ DEFAULT_KERNEL_CHANNEL_BLOCKING_TIMEOUT;
+ }
+ break;
+ case LTTNG_DOMAIN_UST:
+ switch (domain->buf_type) {
+ case LTTNG_BUFFER_PER_UID:
+ attr->subbuf_size = default_get_ust_uid_channel_subbuf_size();
+ attr->num_subbuf = DEFAULT_UST_UID_CHANNEL_SUBBUF_NUM;
+ attr->output = DEFAULT_UST_UID_CHANNEL_OUTPUT;
+ attr->switch_timer_interval =
+ DEFAULT_UST_UID_CHANNEL_SWITCH_TIMER;
+ attr->read_timer_interval =
+ DEFAULT_UST_UID_CHANNEL_READ_TIMER;
+ if (extended) {
+ extended->monitor_timer_interval =
+ DEFAULT_UST_UID_CHANNEL_MONITOR_TIMER;
+ extended->blocking_timeout =
+ DEFAULT_UST_UID_CHANNEL_BLOCKING_TIMEOUT;
+ }
+ break;
+ case LTTNG_BUFFER_PER_PID:
+ default:
+ attr->subbuf_size = default_get_ust_pid_channel_subbuf_size();
+ attr->num_subbuf = DEFAULT_UST_PID_CHANNEL_SUBBUF_NUM;
+ attr->output = DEFAULT_UST_PID_CHANNEL_OUTPUT;
+ attr->switch_timer_interval =
+ DEFAULT_UST_PID_CHANNEL_SWITCH_TIMER;
+ attr->read_timer_interval =
+ DEFAULT_UST_PID_CHANNEL_READ_TIMER;
+ if (extended) {
+ extended->monitor_timer_interval =
+ DEFAULT_UST_PID_CHANNEL_MONITOR_TIMER;
+ extended->blocking_timeout =
+ DEFAULT_UST_PID_CHANNEL_BLOCKING_TIMEOUT;
+ }
+ break;
+ }
+ default:
+ /* Default behavior: leave set to 0. */
+ break;
+ }
+
+ attr->extended.ptr = extended;
+}
+
+int lttng_channel_get_discarded_event_count(struct lttng_channel *channel,
+ uint64_t *discarded_events)
+{
+ int ret = 0;
+ struct lttng_channel_extended *chan_ext;
+
+ if (!channel || !discarded_events) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ chan_ext = (lttng_channel_extended *) channel->attr.extended.ptr;
+ if (!chan_ext) {
+ /*
+ * This can happen since the lttng_channel structure is
+ * used for other tasks where this pointer is never set.
+ */
+ *discarded_events = 0;
+ goto end;
+ }
+
+ *discarded_events = chan_ext->discarded_events;
+end:
+ return ret;
+}
+
+int lttng_channel_get_lost_packet_count(struct lttng_channel *channel,
+ uint64_t *lost_packets)
+{
+ int ret = 0;
+ struct lttng_channel_extended *chan_ext;
+
+ if (!channel || !lost_packets) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ chan_ext = (lttng_channel_extended *) channel->attr.extended.ptr;
+ if (!chan_ext) {
+ /*
+ * This can happen since the lttng_channel structure is
+ * used for other tasks where this pointer is never set.
+ */
+ *lost_packets = 0;
+ goto end;
+ }
+
+ *lost_packets = chan_ext->lost_packets;
+end:
+ return ret;
+}
+
+int lttng_channel_get_monitor_timer_interval(struct lttng_channel *chan,
+ uint64_t *monitor_timer_interval)
+{
+ int ret = 0;
+
+ if (!chan || !monitor_timer_interval) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ if (!chan->attr.extended.ptr) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ *monitor_timer_interval = ((struct lttng_channel_extended *)
+ chan->attr.extended.ptr)->monitor_timer_interval;
+end:
+ return ret;
+}
+
+int lttng_channel_set_monitor_timer_interval(struct lttng_channel *chan,
+ uint64_t monitor_timer_interval)
+{
+ int ret = 0;
+
+ if (!chan || !chan->attr.extended.ptr) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ ((struct lttng_channel_extended *)
+ chan->attr.extended.ptr)->monitor_timer_interval =
+ monitor_timer_interval;
+end:
+ return ret;
+}
+
+int lttng_channel_get_blocking_timeout(struct lttng_channel *chan,
+ int64_t *blocking_timeout)
+{
+ int ret = 0;
+
+ if (!chan || !blocking_timeout) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ if (!chan->attr.extended.ptr) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ *blocking_timeout = ((struct lttng_channel_extended *)
+ chan->attr.extended.ptr)->blocking_timeout;
+end:
+ return ret;
+}
+
+int lttng_channel_set_blocking_timeout(struct lttng_channel *chan,
+ int64_t blocking_timeout)
+{
+ int ret = 0;
+ int64_t msec_timeout;
+
+ if (!chan || !chan->attr.extended.ptr) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ if (blocking_timeout < 0 && blocking_timeout != -1) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ /*
+ * LTTng-ust's use of poll() to implement this timeout mechanism forces
+ * us to accept a narrower range of values (msecs expressed as a signed
+ * 32-bit integer).
+ */
+ msec_timeout = blocking_timeout / 1000;
+ if (msec_timeout != (int32_t) msec_timeout) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ ((struct lttng_channel_extended *)
+ chan->attr.extended.ptr)->blocking_timeout =
+ blocking_timeout;
+end:
+ return ret;
+}
+
+/*
+ * Check if session daemon is alive.
+ *
+ * Return 1 if alive or 0 if not.
+ * On error returns a negative value.
+ */
+int lttng_session_daemon_alive(void)
+{
+ int ret;
+
+ ret = set_session_daemon_path();
+ if (ret < 0) {
+ /* Error. */
+ return ret;
+ }
+
+ if (*sessiond_sock_path == '\0') {
+ /*
+ * No socket path set. Weird error which means the constructor
+ * was not called.
+ */
+ abort();
+ }
+
+ ret = try_connect_sessiond(sessiond_sock_path);
+ if (ret < 0) {
+ /* Not alive. */
+ return 0;
+ }
+
+ /* Is alive. */
+ return 1;
+}
+
+/*
+ * Set URL for a consumer for a session and domain.
+ *
+ * Return 0 on success, else a negative value.
+ */
+int lttng_set_consumer_url(struct lttng_handle *handle,
+ const char *control_url, const char *data_url)
+{
+ int ret;
+ ssize_t size;
+ struct lttcomm_session_msg lsm;
+ struct lttng_uri *uris = NULL;
+
+ if (handle == NULL || (control_url == NULL && data_url == NULL)) {
+ ret = -LTTNG_ERR_INVALID;
+ goto error;
+ }
+
+ memset(&lsm, 0, sizeof(lsm));
+
+ lsm.cmd_type = LTTNG_SET_CONSUMER_URI;
+
+ ret = lttng_strncpy(lsm.session.name, handle->session_name,
+ sizeof(lsm.session.name));
+ if (ret) {
+ ret = -LTTNG_ERR_INVALID;
+ goto error;
+ }
+
+ COPY_DOMAIN_PACKED(lsm.domain, handle->domain);
+
+ size = uri_parse_str_urls(control_url, data_url, &uris);
+ if (size < 0) {
+ ret = -LTTNG_ERR_INVALID;
+ goto error;
+ }
+
+ lsm.u.uri.size = size;
+
+ ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header(&lsm, uris,
+ sizeof(struct lttng_uri) * size, NULL);
+
+ free(uris);
+error:
+ return ret;
+}
+
+/*
+ * [OBSOLETE]
+ */
+extern "C"
+LTTNG_EXPORT int lttng_enable_consumer(struct lttng_handle *handle);
+int lttng_enable_consumer(struct lttng_handle *handle)
+{
+ return -ENOSYS;
+}
+
+/*
+ * [OBSOLETE]
+ */
+extern "C"
+LTTNG_EXPORT int lttng_disable_consumer(struct lttng_handle *handle);
+int lttng_disable_consumer(struct lttng_handle *handle)
+{
+ return -ENOSYS;
+}
+
+/*
+ * [OBSOLETE]
+ */
+extern "C"
+LTTNG_EXPORT int _lttng_create_session_ext(const char *name, const char *url,
+ const char *datetime);
+int _lttng_create_session_ext(const char *name, const char *url,
+ const char *datetime)
+{
+ return -ENOSYS;
+}
+
+/*
+ * For a given session name, this call checks if the data is ready to be read
+ * or is still being extracted by the consumer(s) hence not ready to be used by
+ * any readers.
+ */
+int lttng_data_pending(const char *session_name)
+{
+ int ret;
+ struct lttcomm_session_msg lsm;
+ uint8_t *pending = NULL;
+
+ if (session_name == NULL) {
+ return -LTTNG_ERR_INVALID;
+ }
+
+ memset(&lsm, 0, sizeof(lsm));
+ lsm.cmd_type = LTTNG_DATA_PENDING;
+
+ ret = lttng_strncpy(lsm.session.name, session_name,
+ sizeof(lsm.session.name));
+ if (ret) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ ret = lttng_ctl_ask_sessiond(&lsm, (void **) &pending);
+ if (ret < 0) {
+ goto end;
+ } else if (ret != 1) {
+ /* Unexpected payload size */
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ } else if (!pending) {
+ /* Internal error. */
+ ret = -LTTNG_ERR_UNK;
+ goto end;
+ }
+
+ ret = (int) *pending;
+end:
+ free(pending);
+ return ret;
+}
+
+/*
+ * Regenerate the metadata for a session.
+ * Return 0 on success, a negative error code on error.
+ */
+int lttng_regenerate_metadata(const char *session_name)
+{
+ int ret;
+ struct lttcomm_session_msg lsm;
+
+ if (!session_name) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ memset(&lsm, 0, sizeof(lsm));
+ lsm.cmd_type = LTTNG_REGENERATE_METADATA;
+
+ ret = lttng_strncpy(lsm.session.name, session_name,
+ sizeof(lsm.session.name));
+ if (ret) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ ret = lttng_ctl_ask_sessiond(&lsm, NULL);
+ if (ret < 0) {
+ goto end;
+ }
+
+ ret = 0;
+end:
+ return ret;
+}
+
+/*
+ * Deprecated, replaced by lttng_regenerate_metadata.
+ */
+int lttng_metadata_regenerate(const char *session_name)
+{
+ return lttng_regenerate_metadata(session_name);
+}
+
+/*
+ * Regenerate the statedump of a session.
+ * Return 0 on success, a negative error code on error.
+ */
+int lttng_regenerate_statedump(const char *session_name)
+{
+ int ret;
+ struct lttcomm_session_msg lsm;
+
+ if (!session_name) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ memset(&lsm, 0, sizeof(lsm));
+ lsm.cmd_type = LTTNG_REGENERATE_STATEDUMP;
+
+ ret = lttng_strncpy(lsm.session.name, session_name,
+ sizeof(lsm.session.name));
+ if (ret) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ ret = lttng_ctl_ask_sessiond(&lsm, NULL);
+ if (ret < 0) {
+ goto end;
+ }
+
+ ret = 0;
+end:
+ return ret;
+}
+
+static
+int _lttng_register_trigger(struct lttng_trigger *trigger, const char *name,
+ bool generate_name)
+{
+ int ret;
+ struct lttcomm_session_msg lsm = {
+ .cmd_type = LTTNG_REGISTER_TRIGGER,
+ };
+ lsm.u.trigger.is_trigger_anonymous = !name && !generate_name;
+ struct lttcomm_session_msg *message_lsm;
+ struct lttng_payload message;
+ struct lttng_payload reply;
+ struct lttng_trigger *reply_trigger = NULL;
+ enum lttng_domain_type domain_type;
+ const struct lttng_credentials user_creds = {
+ .uid = LTTNG_OPTIONAL_INIT_VALUE(geteuid()),
+ .gid = LTTNG_OPTIONAL_INIT_UNSET,
+ };
+ const char *unused_trigger_name = NULL;
+ enum lttng_trigger_status trigger_status;
+
+ lttng_payload_init(&message);
+ lttng_payload_init(&reply);
+
+ if (!trigger) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ trigger_status = lttng_trigger_get_name(trigger, &unused_trigger_name);
+ if (trigger_status != LTTNG_TRIGGER_STATUS_UNSET) {
+ /* Re-using already registered trigger. */
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ if (name) {
+ trigger_status = lttng_trigger_set_name(trigger, name);
+ if (trigger_status != LTTNG_TRIGGER_STATUS_OK) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto end;
+ }
+ }
+
+ if (!trigger->creds.uid.is_set) {
+ /* Use the client's credentials as the trigger credentials. */
+ lttng_trigger_set_credentials(trigger, &user_creds);
+ } else {
+ /*
+ * Validate that either the current trigger credentials and the
+ * client credentials are identical or that the current user is
+ * root. The root user can register, unregister triggers for
+ * himself and other users.
+ *
+ * This check is also present on the sessiond side, using the
+ * credentials passed on the socket. These check are all
+ * "safety" checks.
+ */
+ const struct lttng_credentials *trigger_creds =
+ lttng_trigger_get_credentials(trigger);
+
+ if (!lttng_credentials_is_equal_uid(trigger_creds, &user_creds)) {
+ if (lttng_credentials_get_uid(&user_creds) != 0) {
+ ret = -LTTNG_ERR_EPERM;
+ goto end_unset_name;
+ }
+ }
+ }
+
+ if (!lttng_trigger_validate(trigger)) {
+ ret = -LTTNG_ERR_INVALID_TRIGGER;
+ goto end_unset_name;
+ }
+
+ domain_type = lttng_trigger_get_underlying_domain_type_restriction(
+ trigger);
+
+ lsm.domain.type = domain_type;
+
+ ret = lttng_dynamic_buffer_append(&message.buffer, &lsm, sizeof(lsm));
+ if (ret) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto end_unset_name;
+ }
+
+ ret = lttng_trigger_serialize(trigger, &message);
+ if (ret < 0) {
+ ret = -LTTNG_ERR_UNK;
+ goto end_unset_name;
+ }
+
+ /*
+ * This is needed to populate the trigger object size for the command
+ * header.
+ */
+ message_lsm = (struct lttcomm_session_msg *) message.buffer.data;
+
+ message_lsm->u.trigger.length = (uint32_t) message.buffer.size - sizeof(lsm);
+
+ {
+ struct lttng_payload_view message_view =
+ lttng_payload_view_from_payload(
+ &message, 0, -1);
+
+ message_lsm->fd_count = lttng_payload_view_get_fd_handle_count(
+ &message_view);
+ ret = lttng_ctl_ask_sessiond_payload(&message_view, &reply);
+ if (ret < 0) {
+ goto end_unset_name;
+ }
+ }
+
+ {
+ struct lttng_payload_view reply_view =
+ lttng_payload_view_from_payload(
+ &reply, 0, reply.buffer.size);
+
+ ret = lttng_trigger_create_from_payload(
+ &reply_view, &reply_trigger);
+ if (ret < 0) {
+ ret = -LTTNG_ERR_INVALID_PROTOCOL;
+ goto end_unset_name;
+ }
+ }
+
+ if (name || generate_name) {
+ ret = lttng_trigger_assign_name(trigger, reply_trigger);
+ if (ret < 0) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto end;
+ }
+ }
+
+ ret = 0;
+ goto end;
+
+end_unset_name:
+ trigger_status = lttng_trigger_set_name(trigger, NULL);
+ if (trigger_status != LTTNG_TRIGGER_STATUS_OK) {
+ ret = -LTTNG_ERR_UNK;
+ }
+end:
+ lttng_payload_reset(&message);
+ lttng_payload_reset(&reply);
+ lttng_trigger_destroy(reply_trigger);
+ return ret;
+}
+
+int lttng_register_trigger(struct lttng_trigger *trigger)
+{
+ /* Register an anonymous trigger. */
+ return _lttng_register_trigger(trigger, NULL, false);
+}
+
+enum lttng_error_code lttng_register_trigger_with_name(
+ struct lttng_trigger *trigger, const char *name)
+{
+ const int ret = _lttng_register_trigger(trigger, name, false);
+
+ return ret == 0 ? LTTNG_OK : (enum lttng_error_code) -ret;
+}
+
+enum lttng_error_code lttng_register_trigger_with_automatic_name(
+ struct lttng_trigger *trigger)
+{
+ const int ret = _lttng_register_trigger(trigger, nullptr, true);
+
+ return ret == 0 ? LTTNG_OK : (enum lttng_error_code) -ret;
+}
+
+enum lttng_error_code lttng_error_query_execute(
+ const struct lttng_error_query *query,
+ const struct lttng_endpoint *endpoint,
+ struct lttng_error_query_results **results)
+{
+ int ret;
+ enum lttng_error_code ret_code;
+ struct lttcomm_session_msg lsm = {
+ .cmd_type = LTTNG_EXECUTE_ERROR_QUERY,
+ };
+ struct lttng_payload message;
+ struct lttng_payload reply;
+ struct lttcomm_session_msg *message_lsm;
+
+ lttng_payload_init(&message);
+ lttng_payload_init(&reply);
+
+ if (!query || !results) {
+ ret_code = LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ if (endpoint != lttng_session_daemon_command_endpoint) {
+ ret_code = LTTNG_ERR_INVALID_ERROR_QUERY_TARGET;
+ goto end;
+ }
+
+ ret = lttng_dynamic_buffer_append(&message.buffer, &lsm, sizeof(lsm));
+ if (ret) {
+ ret_code = LTTNG_ERR_NOMEM;
+ goto end;
+ }
+
+ ret = lttng_error_query_serialize(query, &message);
+ if (ret) {
+ ret_code = LTTNG_ERR_UNK;
+ goto end;
+ }
+
+ message_lsm = (struct lttcomm_session_msg *) message.buffer.data;
+ message_lsm->u.error_query.length =
+ (uint32_t) message.buffer.size - sizeof(lsm);
+
+ {
+ struct lttng_payload_view message_view =
+ lttng_payload_view_from_payload(
+ &message, 0, -1);
+
+ message_lsm->fd_count = lttng_payload_view_get_fd_handle_count(
+ &message_view);
+ ret = lttng_ctl_ask_sessiond_payload(&message_view, &reply);
+ if (ret < 0) {
+ ret_code =(lttng_error_code) -ret;
+ goto end;
+ }
+ }
+
+ {
+ ssize_t reply_create_ret;
+ struct lttng_payload_view reply_view =
+ lttng_payload_view_from_payload(
+ &reply, 0, reply.buffer.size);
+
+ reply_create_ret = lttng_error_query_results_create_from_payload(
+ &reply_view, results);
+ if (reply_create_ret < 0) {
+ ret_code = LTTNG_ERR_INVALID_PROTOCOL;
+ goto end;
+ }
+ }
+
+ ret_code = LTTNG_OK;
+end:
+ lttng_payload_reset(&message);
+ lttng_payload_reset(&reply);
+ return ret_code;
+}
+
+int lttng_unregister_trigger(const struct lttng_trigger *trigger)
+{
+ int ret;
+ struct lttcomm_session_msg lsm;
+ struct lttcomm_session_msg *message_lsm;
+ struct lttng_payload message;
+ struct lttng_payload reply;
+ struct lttng_trigger *copy = NULL;
+ const struct lttng_credentials user_creds = {
+ .uid = LTTNG_OPTIONAL_INIT_VALUE(geteuid()),
+ .gid = LTTNG_OPTIONAL_INIT_UNSET,
+ };
+
+ lttng_payload_init(&message);
+ lttng_payload_init(&reply);
+
+ if (!trigger) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ copy = lttng_trigger_copy(trigger);
+ if (!copy) {
+ ret = -LTTNG_ERR_UNK;
+ goto end;
+ }
+
+ if (!copy->creds.uid.is_set) {
+ /* Use the client credentials as the trigger credentials */
+ lttng_trigger_set_credentials(copy, &user_creds);
+ } else {
+ /*
+ * Validate that either the current trigger credentials and the
+ * client credentials are identical or that the current user is
+ * root. The root user can register, unregister triggers for
+ * himself and other users.
+ *
+ * This check is also present on the sessiond side, using the
+ * credentials passed on the socket. These check are all
+ * "safety" checks.
+ */
+ const struct lttng_credentials *trigger_creds =
+ lttng_trigger_get_credentials(copy);
+ if (!lttng_credentials_is_equal_uid(trigger_creds, &user_creds)) {
+ if (lttng_credentials_get_uid(&user_creds) != 0) {
+ ret = -LTTNG_ERR_EPERM;
+ goto end;
+ }
+ }
+ }
+
+ if (!lttng_trigger_validate(copy)) {
+ ret = -LTTNG_ERR_INVALID_TRIGGER;
+ goto end;
+ }
+
+ memset(&lsm, 0, sizeof(lsm));
+ lsm.cmd_type = LTTNG_UNREGISTER_TRIGGER;
+
+ ret = lttng_dynamic_buffer_append(&message.buffer, &lsm, sizeof(lsm));
+ if (ret) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto end;
+ }
+
+ ret = lttng_trigger_serialize(copy, &message);
+ if (ret < 0) {
+ ret = -LTTNG_ERR_UNK;
+ goto end;
+ }
+
+ /*
+ * This is needed to populate the trigger object size for the command
+ * header and number of fds sent.
+ */
+ message_lsm = (struct lttcomm_session_msg *) message.buffer.data;
+
+ message_lsm->u.trigger.length = (uint32_t) message.buffer.size - sizeof(lsm);
+
+ {
+ struct lttng_payload_view message_view =
+ lttng_payload_view_from_payload(
+ &message, 0, -1);
+
+ /*
+ * Update the message header with the number of fd that will be
+ * sent.
+ */
+ message_lsm->fd_count = lttng_payload_view_get_fd_handle_count(
+ &message_view);
+
+ ret = lttng_ctl_ask_sessiond_payload(&message_view, &reply);
+ if (ret < 0) {
+ goto end;
+ }
+ }
+
+ ret = 0;
+end:
+ lttng_trigger_destroy(copy);
+ lttng_payload_reset(&message);
+ lttng_payload_reset(&reply);
+ return ret;
+}
+
+/*
+ * Ask the session daemon for all registered triggers for the current user.
+ *
+ * Allocates and return an lttng_triggers set.
+ * On error, returns a suitable lttng_error_code.
+ */
+enum lttng_error_code lttng_list_triggers(struct lttng_triggers **triggers)
+{
+ int ret;
+ enum lttng_error_code ret_code = LTTNG_OK;
+ struct lttcomm_session_msg lsm = { .cmd_type = LTTNG_LIST_TRIGGERS };
+ struct lttng_triggers *local_triggers = NULL;
+ struct lttng_payload reply;
+ struct lttng_payload_view lsm_view =
+ lttng_payload_view_init_from_buffer(
+ (const char *) &lsm, 0, sizeof(lsm));
+
+ lttng_payload_init(&reply);
+
+ ret = lttng_ctl_ask_sessiond_payload(&lsm_view, &reply);
+ if (ret < 0) {
+ ret_code = (enum lttng_error_code) -ret;
+ goto end;
+ }
+
+ {
+ struct lttng_payload_view reply_view =
+ lttng_payload_view_from_payload(
+ &reply, 0, reply.buffer.size);
+
+ ret = lttng_triggers_create_from_payload(
+ &reply_view, &local_triggers);
+ if (ret < 0) {
+ ret_code = LTTNG_ERR_FATAL;
+ goto end;
+ }
+ }
+
+ *triggers = local_triggers;
+ local_triggers = NULL;
+end:
+ lttng_payload_reset(&reply);
+ lttng_triggers_destroy(local_triggers);
+ return ret_code;
+}
+
+/*
+ * lib constructor.
+ */
+static void __attribute__((constructor)) init(void)
+{
+ /* Set default session group */
+ lttng_set_tracing_group(DEFAULT_TRACING_GROUP);
+}
+
+/*
+ * lib destructor.
+ */
+static void __attribute__((destructor)) lttng_ctl_exit(void)
+{
+ free(tracing_group);
+}
+++ /dev/null
-/*
- * Copyright (C) 2017 Julien Desfossez <jdesfossez@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#define _LGPL_SOURCE
-#include <string.h>
-
-#include <lttng/lttng-error.h>
-#include <lttng/rotation.h>
-#include <lttng/location-internal.h>
-#include <lttng/rotate-internal.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <common/macros.h>
-
-#include "lttng-ctl-helper.h"
-
-static
-enum lttng_rotation_status ask_rotation_info(
- struct lttng_rotation_handle *rotation_handle,
- struct lttng_rotation_get_info_return **info)
-{
- /* lsm.get_rotation_state.rotation_id */
- struct lttcomm_session_msg lsm;
- enum lttng_rotation_status status = LTTNG_ROTATION_STATUS_OK;
- int ret;
-
- if (!rotation_handle || !info) {
- status = LTTNG_ROTATION_STATUS_INVALID;
- goto end;
- }
-
- memset(&lsm, 0, sizeof(lsm));
- lsm.cmd_type = LTTNG_ROTATION_GET_INFO;
- lsm.u.get_rotation_info.rotation_id = rotation_handle->rotation_id;
-
- ret = lttng_strncpy(lsm.session.name, rotation_handle->session_name,
- sizeof(lsm.session.name));
- if (ret) {
- status = LTTNG_ROTATION_STATUS_INVALID;
- goto end;
- }
-
- ret = lttng_ctl_ask_sessiond(&lsm, (void **) info);
- if (ret < 0) {
- status = LTTNG_ROTATION_STATUS_ERROR;
- goto end;
- }
-end:
- return status;
-
-}
-
-static
-struct lttng_trace_archive_location *
-create_trace_archive_location_from_get_info(
- const struct lttng_rotation_get_info_return *info)
-{
- struct lttng_trace_archive_location *location;
-
- switch (info->location_type) {
- case LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_LOCAL:
- location = lttng_trace_archive_location_local_create(
- info->location.local.absolute_path);
- break;
- case LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_RELAY:
- location = lttng_trace_archive_location_relay_create(
- info->location.relay.host,
- info->location.relay.protocol,
- info->location.relay.ports.control,
- info->location.relay.ports.data,
- info->location.relay.relative_path);
- break;
- default:
- location = NULL;
- break;
- }
- return location;
-}
-
-enum lttng_rotation_status lttng_rotation_handle_get_state(
- struct lttng_rotation_handle *rotation_handle,
- enum lttng_rotation_state *state)
-{
- enum lttng_rotation_status status = LTTNG_ROTATION_STATUS_OK;
- struct lttng_rotation_get_info_return *info = NULL;
-
- if (!rotation_handle || !state) {
- status = LTTNG_ROTATION_STATUS_INVALID;
- goto end;
- }
-
- status = ask_rotation_info(rotation_handle, &info);
- if (status != LTTNG_ROTATION_STATUS_OK) {
- goto end;
- }
-
- *state = (enum lttng_rotation_state) info->status;
- if (rotation_handle->archive_location ||
- *state != LTTNG_ROTATION_STATE_COMPLETED) {
- /*
- * The path is only provided by the sessiond once
- * the session rotation is completed, but not expired.
- */
- goto end;
- }
-
- /*
- * Cache the location since the rotation may expire before the user
- * has a chance to query it.
- */
- rotation_handle->archive_location =
- create_trace_archive_location_from_get_info(info);
- if (!rotation_handle->archive_location) {
- status = LTTNG_ROTATION_STATUS_ERROR;
- goto end;
- }
-end:
- free(info);
- return status;
-}
-
-enum lttng_rotation_status lttng_rotation_handle_get_archive_location(
- struct lttng_rotation_handle *rotation_handle,
- const struct lttng_trace_archive_location **location)
-{
- enum lttng_rotation_status status = LTTNG_ROTATION_STATUS_OK;
- struct lttng_rotation_get_info_return *info = NULL;
-
- if (!rotation_handle || !location) {
- status = LTTNG_ROTATION_STATUS_INVALID;
- goto end;
- }
-
- /* Use the cached location we got from a previous query. */
- if (rotation_handle->archive_location) {
- *location = rotation_handle->archive_location;
- goto end;
- }
-
- status = ask_rotation_info(rotation_handle, &info);
- if (status != LTTNG_ROTATION_STATUS_OK) {
- goto end;
- }
-
- if ((enum lttng_rotation_state) info->status !=
- LTTNG_ROTATION_STATE_COMPLETED) {
- status = LTTNG_ROTATION_STATUS_UNAVAILABLE;
- goto end;
- }
-
- rotation_handle->archive_location =
- create_trace_archive_location_from_get_info(info);
- if (!rotation_handle->archive_location) {
- status = LTTNG_ROTATION_STATUS_ERROR;
- goto end;
- }
-end:
- free(info);
- return status;
-}
-
-void lttng_rotation_handle_destroy(
- struct lttng_rotation_handle *rotation_handle)
-{
- if (!rotation_handle) {
- return;
- }
- lttng_trace_archive_location_put(rotation_handle->archive_location);
- free(rotation_handle);
-}
-
-static
-int init_rotation_handle(struct lttng_rotation_handle *rotation_handle,
- const char *session_name,
- struct lttng_rotate_session_return *rotate_return)
-{
- int ret;
-
- ret = lttng_strncpy(rotation_handle->session_name, session_name,
- sizeof(rotation_handle->session_name));
- if (ret) {
- goto end;
- }
-
- rotation_handle->rotation_id = rotate_return->rotation_id;
-end:
- return ret;
-}
-
-/*
- * Rotate the output folder of the session.
- *
- * Return 0 on success else a negative LTTng error code.
- */
-int lttng_rotate_session(const char *session_name,
- struct lttng_rotation_immediate_descriptor *descriptor,
- struct lttng_rotation_handle **rotation_handle)
-{
- struct lttcomm_session_msg lsm;
- struct lttng_rotate_session_return *rotate_return = NULL;
- int ret;
- size_t session_name_len;
-
- if (!session_name) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- session_name_len = strlen(session_name);
- if (session_name_len >= sizeof(lsm.session.name) ||
- session_name_len >= member_sizeof(struct lttng_rotation_handle, session_name)) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- memset(&lsm, 0, sizeof(lsm));
- lsm.cmd_type = LTTNG_ROTATE_SESSION;
-
- ret = lttng_strncpy(lsm.session.name, session_name,
- sizeof(lsm.session.name));
- /* Source length already validated. */
- LTTNG_ASSERT(ret == 0);
-
- ret = lttng_ctl_ask_sessiond(&lsm, (void **) &rotate_return);
- if (ret <= 0) {
- *rotation_handle = NULL;
- goto end;
- }
-
- *rotation_handle = zmalloc(sizeof(struct lttng_rotation_handle));
- if (!*rotation_handle) {
- ret = -LTTNG_ERR_NOMEM;
- goto end;
- }
-
- init_rotation_handle(*rotation_handle, session_name, rotate_return);
-
- ret = 0;
-
-end:
- free(rotate_return);
- return ret;
-}
-
-/*
- * Update the automatic rotation parameters.
- * 'add' as true enables the provided schedule, false removes the shedule.
- *
- * The external API makes it appear as though arbitrary schedules can
- * be added or removed at will. However, the session daemon is
- * currently limited to one schedule per type (per session).
- *
- * The additional flexibility of the public API is offered for future
- * rotation schedules that could indicate more precise criteria than
- * size and time (e.g. a domain) where it could make sense to add
- * multiple schedules of a given type to a session.
- *
- * Hence, the exact schedule that the user wishes to remove (and not
- * just its type) must be passed so that the session daemon can
- * validate that is exists before clearing it.
- */
-static
-enum lttng_rotation_status lttng_rotation_update_schedule(
- const char *session_name,
- const struct lttng_rotation_schedule *schedule,
- bool add)
-{
- struct lttcomm_session_msg lsm;
- enum lttng_rotation_status status = LTTNG_ROTATION_STATUS_OK;
- int ret;
-
- if (!session_name || !schedule) {
- status = LTTNG_ROTATION_STATUS_INVALID;
- goto end;
- }
-
- if (strlen(session_name) >= sizeof(lsm.session.name)) {
- status = LTTNG_ROTATION_STATUS_INVALID;
- goto end;
- }
-
- memset(&lsm, 0, sizeof(lsm));
- lsm.cmd_type = LTTNG_ROTATION_SET_SCHEDULE;
- ret = lttng_strncpy(lsm.session.name, session_name,
- sizeof(lsm.session.name));
- /* Source length already validated. */
- LTTNG_ASSERT(ret == 0);
-
- lsm.u.rotation_set_schedule.type = (uint32_t) schedule->type;
- switch (schedule->type) {
- case LTTNG_ROTATION_SCHEDULE_TYPE_SIZE_THRESHOLD:
- {
- uint64_t threshold;
-
- status = lttng_rotation_schedule_size_threshold_get_threshold(
- schedule, &threshold);
- if (status != LTTNG_ROTATION_STATUS_OK) {
- if (status == LTTNG_ROTATION_STATUS_UNAVAILABLE) {
- status = LTTNG_ROTATION_STATUS_INVALID;
- }
- goto end;
- }
- lsm.u.rotation_set_schedule.value = threshold;
- lsm.u.rotation_set_schedule.set = !!add;
- break;
- }
- case LTTNG_ROTATION_SCHEDULE_TYPE_PERIODIC:
- {
- uint64_t period;
-
- status = lttng_rotation_schedule_periodic_get_period(
- schedule, &period);
- if (status != LTTNG_ROTATION_STATUS_OK) {
- if (status == LTTNG_ROTATION_STATUS_UNAVAILABLE) {
- status = LTTNG_ROTATION_STATUS_INVALID;
- }
- goto end;
- }
- lsm.u.rotation_set_schedule.value = period;
- lsm.u.rotation_set_schedule.set = !!add;
- break;
- }
- default:
- status = LTTNG_ROTATION_STATUS_INVALID;
- goto end;
- }
-
- ret = lttng_ctl_ask_sessiond(&lsm, NULL);
- if (ret >= 0) {
- goto end;
- }
-
- switch (-ret) {
- case LTTNG_ERR_ROTATION_SCHEDULE_SET:
- status = LTTNG_ROTATION_STATUS_SCHEDULE_ALREADY_SET;
- break;
- case LTTNG_ERR_ROTATION_SCHEDULE_NOT_SET:
- status = LTTNG_ROTATION_STATUS_INVALID;
- break;
- default:
- status = LTTNG_ROTATION_STATUS_ERROR;
- }
-end:
- return status;
-}
-
-static
-struct lttng_rotation_schedules *lttng_rotation_schedules_create(void)
-{
- return zmalloc(sizeof(struct lttng_rotation_schedules));
-}
-
-static
-void lttng_schedules_add(struct lttng_rotation_schedules *schedules,
- struct lttng_rotation_schedule *schedule)
-{
- schedules->schedules[schedules->count++] = schedule;
-}
-
-static
-int get_schedules(const char *session_name,
- struct lttng_rotation_schedules **_schedules)
-{
- int ret;
- struct lttcomm_session_msg lsm;
- struct lttng_session_list_schedules_return *schedules_comm = NULL;
- struct lttng_rotation_schedules *schedules = NULL;
- struct lttng_rotation_schedule *periodic = NULL, *size = NULL;
-
- if (!session_name) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- memset(&lsm, 0, sizeof(lsm));
- lsm.cmd_type = LTTNG_SESSION_LIST_ROTATION_SCHEDULES;
- ret = lttng_strncpy(lsm.session.name, session_name,
- sizeof(lsm.session.name));
- if (ret) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- ret = lttng_ctl_ask_sessiond(&lsm, (void **) &schedules_comm);
- if (ret < 0) {
- goto end;
- }
-
- schedules = lttng_rotation_schedules_create();
- if (!schedules) {
- ret = -LTTNG_ERR_NOMEM;
- goto end;
- }
-
- if (schedules_comm->periodic.set == 1) {
- enum lttng_rotation_status status;
-
- periodic = lttng_rotation_schedule_periodic_create();
- if (!periodic) {
- ret = -LTTNG_ERR_NOMEM;
- goto end;
- }
-
- status = lttng_rotation_schedule_periodic_set_period(
- periodic, schedules_comm->periodic.value);
- if (status != LTTNG_ROTATION_STATUS_OK) {
- /*
- * This would imply that the session daemon returned
- * an invalid periodic rotation schedule value.
- */
- ret = -LTTNG_ERR_UNK;
- goto end;
- }
-
- lttng_schedules_add(schedules, periodic);
- periodic = NULL;
- }
-
- if (schedules_comm->size.set == 1) {
- enum lttng_rotation_status status;
-
- size = lttng_rotation_schedule_size_threshold_create();
- if (!size) {
- ret = -LTTNG_ERR_NOMEM;
- goto end;
- }
-
- status = lttng_rotation_schedule_size_threshold_set_threshold(
- size, schedules_comm->size.value);
- if (status != LTTNG_ROTATION_STATUS_OK) {
- /*
- * This would imply that the session daemon returned
- * an invalid size threshold schedule value.
- */
- ret = -LTTNG_ERR_UNK;
- goto end;
- }
-
- lttng_schedules_add(schedules, size);
- size = NULL;
- }
-
- ret = LTTNG_OK;
-end:
- free(schedules_comm);
- free(periodic);
- free(size);
- *_schedules = schedules;
- return ret;
-}
-
-enum lttng_rotation_schedule_type lttng_rotation_schedule_get_type(
- const struct lttng_rotation_schedule *schedule)
-{
- return schedule ? schedule->type : LTTNG_ROTATION_SCHEDULE_TYPE_UNKNOWN;
-}
-
-struct lttng_rotation_schedule *
-lttng_rotation_schedule_size_threshold_create(void)
-{
- struct lttng_rotation_schedule_size_threshold *schedule;
-
- schedule = zmalloc(sizeof(*schedule));
- if (!schedule) {
- goto end;
- }
-
- schedule->parent.type = LTTNG_ROTATION_SCHEDULE_TYPE_SIZE_THRESHOLD;
-end:
- return &schedule->parent;
-}
-
-enum lttng_rotation_status
-lttng_rotation_schedule_size_threshold_get_threshold(
- const struct lttng_rotation_schedule *schedule,
- uint64_t *size_threshold_bytes)
-{
- enum lttng_rotation_status status = LTTNG_ROTATION_STATUS_OK;
- struct lttng_rotation_schedule_size_threshold *size_schedule;
-
- if (!schedule || !size_threshold_bytes ||
- schedule->type != LTTNG_ROTATION_SCHEDULE_TYPE_SIZE_THRESHOLD) {
- status = LTTNG_ROTATION_STATUS_INVALID;
- goto end;
- }
-
- size_schedule = container_of(schedule,
- struct lttng_rotation_schedule_size_threshold,
- parent);
- if (size_schedule->size.set) {
- *size_threshold_bytes = size_schedule->size.bytes;
- } else {
- status = LTTNG_ROTATION_STATUS_UNAVAILABLE;
- goto end;
- }
-end:
- return status;
-}
-
-enum lttng_rotation_status
-lttng_rotation_schedule_size_threshold_set_threshold(
- struct lttng_rotation_schedule *schedule,
- uint64_t size_threshold_bytes)
-{
- enum lttng_rotation_status status = LTTNG_ROTATION_STATUS_OK;
- struct lttng_rotation_schedule_size_threshold *size_schedule;
-
- if (!schedule || size_threshold_bytes == 0 ||
- size_threshold_bytes == -1ULL ||
- schedule->type != LTTNG_ROTATION_SCHEDULE_TYPE_SIZE_THRESHOLD) {
- status = LTTNG_ROTATION_STATUS_INVALID;
- goto end;
- }
-
- size_schedule = container_of(schedule,
- struct lttng_rotation_schedule_size_threshold,
- parent);
- size_schedule->size.bytes = size_threshold_bytes;
- size_schedule->size.set = true;
-end:
- return status;
-}
-
-struct lttng_rotation_schedule *
-lttng_rotation_schedule_periodic_create(void)
-{
- struct lttng_rotation_schedule_periodic *schedule;
-
- schedule = zmalloc(sizeof(*schedule));
- if (!schedule) {
- goto end;
- }
-
- schedule->parent.type = LTTNG_ROTATION_SCHEDULE_TYPE_PERIODIC;
-end:
- return &schedule->parent;
-}
-
-enum lttng_rotation_status
-lttng_rotation_schedule_periodic_get_period(
- const struct lttng_rotation_schedule *schedule,
- uint64_t *period_us)
-{
- enum lttng_rotation_status status = LTTNG_ROTATION_STATUS_OK;
- struct lttng_rotation_schedule_periodic *periodic_schedule;
-
- if (!schedule || !period_us ||
- schedule->type != LTTNG_ROTATION_SCHEDULE_TYPE_PERIODIC) {
- status = LTTNG_ROTATION_STATUS_INVALID;
- goto end;
- }
-
- periodic_schedule = container_of(schedule,
- struct lttng_rotation_schedule_periodic,
- parent);
- if (periodic_schedule->period.set) {
- *period_us = periodic_schedule->period.us;
- } else {
- status = LTTNG_ROTATION_STATUS_UNAVAILABLE;
- goto end;
- }
-end:
- return status;
-}
-
-enum lttng_rotation_status
-lttng_rotation_schedule_periodic_set_period(
- struct lttng_rotation_schedule *schedule,
- uint64_t period_us)
-{
- enum lttng_rotation_status status = LTTNG_ROTATION_STATUS_OK;
- struct lttng_rotation_schedule_periodic *periodic_schedule;
-
- if (!schedule || period_us == 0 || period_us == -1ULL ||
- schedule->type != LTTNG_ROTATION_SCHEDULE_TYPE_PERIODIC) {
- status = LTTNG_ROTATION_STATUS_INVALID;
- goto end;
- }
-
- periodic_schedule = container_of(schedule,
- struct lttng_rotation_schedule_periodic,
- parent);
- periodic_schedule->period.us = period_us;
- periodic_schedule->period.set = true;
-end:
- return status;
-}
-
-void lttng_rotation_schedule_destroy(struct lttng_rotation_schedule *schedule)
-{
- if (!schedule) {
- return;
- }
- free(schedule);
-}
-
-void lttng_rotation_schedules_destroy(
- struct lttng_rotation_schedules *schedules)
-{
- unsigned int i;
-
- if (!schedules) {
- return;
- }
-
- for (i = 0; i < schedules->count; i++) {
- lttng_rotation_schedule_destroy(schedules->schedules[i]);
- }
- free(schedules);
-}
-
-
-enum lttng_rotation_status lttng_rotation_schedules_get_count(
- const struct lttng_rotation_schedules *schedules,
- unsigned int *count)
-{
- enum lttng_rotation_status status = LTTNG_ROTATION_STATUS_OK;
-
- if (!schedules || !count) {
- status = LTTNG_ROTATION_STATUS_INVALID;
- goto end;
- }
-
- *count = schedules->count;
-end:
- return status;
-}
-
-const struct lttng_rotation_schedule *lttng_rotation_schedules_get_at_index(
- const struct lttng_rotation_schedules *schedules,
- unsigned int index)
-{
- const struct lttng_rotation_schedule *schedule = NULL;
-
- if (!schedules || index >= schedules->count) {
- goto end;
- }
-
- schedule = schedules->schedules[index];
-end:
- return schedule;
-}
-
-enum lttng_rotation_status lttng_session_add_rotation_schedule(
- const char *session_name,
- const struct lttng_rotation_schedule *schedule)
-{
- return lttng_rotation_update_schedule(session_name, schedule, true);
-}
-
-enum lttng_rotation_status lttng_session_remove_rotation_schedule(
- const char *session_name,
- const struct lttng_rotation_schedule *schedule)
-{
- return lttng_rotation_update_schedule(session_name, schedule, false);
-}
-
-int lttng_session_list_rotation_schedules(
- const char *session_name,
- struct lttng_rotation_schedules **schedules)
-{
- return get_schedules(session_name, schedules);
-}
--- /dev/null
+/*
+ * Copyright (C) 2017 Julien Desfossez <jdesfossez@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#define _LGPL_SOURCE
+#include <string.h>
+
+#include <lttng/lttng-error.h>
+#include <lttng/rotation.h>
+#include <lttng/location-internal.h>
+#include <lttng/rotate-internal.h>
+#include <common/sessiond-comm/sessiond-comm.h>
+#include <common/macros.h>
+
+#include "lttng-ctl-helper.h"
+
+static
+enum lttng_rotation_status ask_rotation_info(
+ struct lttng_rotation_handle *rotation_handle,
+ struct lttng_rotation_get_info_return **info)
+{
+ /* lsm.get_rotation_state.rotation_id */
+ struct lttcomm_session_msg lsm;
+ enum lttng_rotation_status status = LTTNG_ROTATION_STATUS_OK;
+ int ret;
+
+ if (!rotation_handle || !info) {
+ status = LTTNG_ROTATION_STATUS_INVALID;
+ goto end;
+ }
+
+ memset(&lsm, 0, sizeof(lsm));
+ lsm.cmd_type = LTTNG_ROTATION_GET_INFO;
+ lsm.u.get_rotation_info.rotation_id = rotation_handle->rotation_id;
+
+ ret = lttng_strncpy(lsm.session.name, rotation_handle->session_name,
+ sizeof(lsm.session.name));
+ if (ret) {
+ status = LTTNG_ROTATION_STATUS_INVALID;
+ goto end;
+ }
+
+ ret = lttng_ctl_ask_sessiond(&lsm, (void **) info);
+ if (ret < 0) {
+ status = LTTNG_ROTATION_STATUS_ERROR;
+ goto end;
+ }
+end:
+ return status;
+
+}
+
+static
+struct lttng_trace_archive_location *
+create_trace_archive_location_from_get_info(
+ const struct lttng_rotation_get_info_return *info)
+{
+ struct lttng_trace_archive_location *location;
+
+ switch (info->location_type) {
+ case LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_LOCAL:
+ location = lttng_trace_archive_location_local_create(
+ info->location.local.absolute_path);
+ break;
+ case LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_RELAY:
+ location = lttng_trace_archive_location_relay_create(
+ info->location.relay.host,
+ (lttng_trace_archive_location_relay_protocol_type) info->location.relay.protocol,
+ info->location.relay.ports.control,
+ info->location.relay.ports.data,
+ info->location.relay.relative_path);
+ break;
+ default:
+ location = NULL;
+ break;
+ }
+ return location;
+}
+
+enum lttng_rotation_status lttng_rotation_handle_get_state(
+ struct lttng_rotation_handle *rotation_handle,
+ enum lttng_rotation_state *state)
+{
+ enum lttng_rotation_status status = LTTNG_ROTATION_STATUS_OK;
+ struct lttng_rotation_get_info_return *info = NULL;
+
+ if (!rotation_handle || !state) {
+ status = LTTNG_ROTATION_STATUS_INVALID;
+ goto end;
+ }
+
+ status = ask_rotation_info(rotation_handle, &info);
+ if (status != LTTNG_ROTATION_STATUS_OK) {
+ goto end;
+ }
+
+ *state = (enum lttng_rotation_state) info->status;
+ if (rotation_handle->archive_location ||
+ *state != LTTNG_ROTATION_STATE_COMPLETED) {
+ /*
+ * The path is only provided by the sessiond once
+ * the session rotation is completed, but not expired.
+ */
+ goto end;
+ }
+
+ /*
+ * Cache the location since the rotation may expire before the user
+ * has a chance to query it.
+ */
+ rotation_handle->archive_location =
+ create_trace_archive_location_from_get_info(info);
+ if (!rotation_handle->archive_location) {
+ status = LTTNG_ROTATION_STATUS_ERROR;
+ goto end;
+ }
+end:
+ free(info);
+ return status;
+}
+
+enum lttng_rotation_status lttng_rotation_handle_get_archive_location(
+ struct lttng_rotation_handle *rotation_handle,
+ const struct lttng_trace_archive_location **location)
+{
+ enum lttng_rotation_status status = LTTNG_ROTATION_STATUS_OK;
+ struct lttng_rotation_get_info_return *info = NULL;
+
+ if (!rotation_handle || !location) {
+ status = LTTNG_ROTATION_STATUS_INVALID;
+ goto end;
+ }
+
+ /* Use the cached location we got from a previous query. */
+ if (rotation_handle->archive_location) {
+ *location = rotation_handle->archive_location;
+ goto end;
+ }
+
+ status = ask_rotation_info(rotation_handle, &info);
+ if (status != LTTNG_ROTATION_STATUS_OK) {
+ goto end;
+ }
+
+ if ((enum lttng_rotation_state) info->status !=
+ LTTNG_ROTATION_STATE_COMPLETED) {
+ status = LTTNG_ROTATION_STATUS_UNAVAILABLE;
+ goto end;
+ }
+
+ rotation_handle->archive_location =
+ create_trace_archive_location_from_get_info(info);
+ if (!rotation_handle->archive_location) {
+ status = LTTNG_ROTATION_STATUS_ERROR;
+ goto end;
+ }
+end:
+ free(info);
+ return status;
+}
+
+void lttng_rotation_handle_destroy(
+ struct lttng_rotation_handle *rotation_handle)
+{
+ if (!rotation_handle) {
+ return;
+ }
+ lttng_trace_archive_location_put(rotation_handle->archive_location);
+ free(rotation_handle);
+}
+
+static
+int init_rotation_handle(struct lttng_rotation_handle *rotation_handle,
+ const char *session_name,
+ struct lttng_rotate_session_return *rotate_return)
+{
+ int ret;
+
+ ret = lttng_strncpy(rotation_handle->session_name, session_name,
+ sizeof(rotation_handle->session_name));
+ if (ret) {
+ goto end;
+ }
+
+ rotation_handle->rotation_id = rotate_return->rotation_id;
+end:
+ return ret;
+}
+
+/*
+ * Rotate the output folder of the session.
+ *
+ * Return 0 on success else a negative LTTng error code.
+ */
+int lttng_rotate_session(const char *session_name,
+ struct lttng_rotation_immediate_descriptor *descriptor,
+ struct lttng_rotation_handle **rotation_handle)
+{
+ struct lttcomm_session_msg lsm;
+ struct lttng_rotate_session_return *rotate_return = NULL;
+ int ret;
+ size_t session_name_len;
+
+ if (!session_name) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ session_name_len = strlen(session_name);
+ if (session_name_len >= sizeof(lsm.session.name) ||
+ session_name_len >= member_sizeof(struct lttng_rotation_handle, session_name)) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ memset(&lsm, 0, sizeof(lsm));
+ lsm.cmd_type = LTTNG_ROTATE_SESSION;
+
+ ret = lttng_strncpy(lsm.session.name, session_name,
+ sizeof(lsm.session.name));
+ /* Source length already validated. */
+ LTTNG_ASSERT(ret == 0);
+
+ ret = lttng_ctl_ask_sessiond(&lsm, (void **) &rotate_return);
+ if (ret <= 0) {
+ *rotation_handle = NULL;
+ goto end;
+ }
+
+ *rotation_handle = (lttng_rotation_handle *) zmalloc(sizeof(struct lttng_rotation_handle));
+ if (!*rotation_handle) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto end;
+ }
+
+ init_rotation_handle(*rotation_handle, session_name, rotate_return);
+
+ ret = 0;
+
+end:
+ free(rotate_return);
+ return ret;
+}
+
+/*
+ * Update the automatic rotation parameters.
+ * 'add' as true enables the provided schedule, false removes the shedule.
+ *
+ * The external API makes it appear as though arbitrary schedules can
+ * be added or removed at will. However, the session daemon is
+ * currently limited to one schedule per type (per session).
+ *
+ * The additional flexibility of the public API is offered for future
+ * rotation schedules that could indicate more precise criteria than
+ * size and time (e.g. a domain) where it could make sense to add
+ * multiple schedules of a given type to a session.
+ *
+ * Hence, the exact schedule that the user wishes to remove (and not
+ * just its type) must be passed so that the session daemon can
+ * validate that is exists before clearing it.
+ */
+static
+enum lttng_rotation_status lttng_rotation_update_schedule(
+ const char *session_name,
+ const struct lttng_rotation_schedule *schedule,
+ bool add)
+{
+ struct lttcomm_session_msg lsm;
+ enum lttng_rotation_status status = LTTNG_ROTATION_STATUS_OK;
+ int ret;
+
+ if (!session_name || !schedule) {
+ status = LTTNG_ROTATION_STATUS_INVALID;
+ goto end;
+ }
+
+ if (strlen(session_name) >= sizeof(lsm.session.name)) {
+ status = LTTNG_ROTATION_STATUS_INVALID;
+ goto end;
+ }
+
+ memset(&lsm, 0, sizeof(lsm));
+ lsm.cmd_type = LTTNG_ROTATION_SET_SCHEDULE;
+ ret = lttng_strncpy(lsm.session.name, session_name,
+ sizeof(lsm.session.name));
+ /* Source length already validated. */
+ LTTNG_ASSERT(ret == 0);
+
+ lsm.u.rotation_set_schedule.type = (uint32_t) schedule->type;
+ switch (schedule->type) {
+ case LTTNG_ROTATION_SCHEDULE_TYPE_SIZE_THRESHOLD:
+ {
+ uint64_t threshold;
+
+ status = lttng_rotation_schedule_size_threshold_get_threshold(
+ schedule, &threshold);
+ if (status != LTTNG_ROTATION_STATUS_OK) {
+ if (status == LTTNG_ROTATION_STATUS_UNAVAILABLE) {
+ status = LTTNG_ROTATION_STATUS_INVALID;
+ }
+ goto end;
+ }
+ lsm.u.rotation_set_schedule.value = threshold;
+ lsm.u.rotation_set_schedule.set = !!add;
+ break;
+ }
+ case LTTNG_ROTATION_SCHEDULE_TYPE_PERIODIC:
+ {
+ uint64_t period;
+
+ status = lttng_rotation_schedule_periodic_get_period(
+ schedule, &period);
+ if (status != LTTNG_ROTATION_STATUS_OK) {
+ if (status == LTTNG_ROTATION_STATUS_UNAVAILABLE) {
+ status = LTTNG_ROTATION_STATUS_INVALID;
+ }
+ goto end;
+ }
+ lsm.u.rotation_set_schedule.value = period;
+ lsm.u.rotation_set_schedule.set = !!add;
+ break;
+ }
+ default:
+ status = LTTNG_ROTATION_STATUS_INVALID;
+ goto end;
+ }
+
+ ret = lttng_ctl_ask_sessiond(&lsm, NULL);
+ if (ret >= 0) {
+ goto end;
+ }
+
+ switch (-ret) {
+ case LTTNG_ERR_ROTATION_SCHEDULE_SET:
+ status = LTTNG_ROTATION_STATUS_SCHEDULE_ALREADY_SET;
+ break;
+ case LTTNG_ERR_ROTATION_SCHEDULE_NOT_SET:
+ status = LTTNG_ROTATION_STATUS_INVALID;
+ break;
+ default:
+ status = LTTNG_ROTATION_STATUS_ERROR;
+ }
+end:
+ return status;
+}
+
+static
+struct lttng_rotation_schedules *lttng_rotation_schedules_create(void)
+{
+ return (lttng_rotation_schedules *) zmalloc(sizeof(struct lttng_rotation_schedules));
+}
+
+static
+void lttng_schedules_add(struct lttng_rotation_schedules *schedules,
+ struct lttng_rotation_schedule *schedule)
+{
+ schedules->schedules[schedules->count++] = schedule;
+}
+
+static
+int get_schedules(const char *session_name,
+ struct lttng_rotation_schedules **_schedules)
+{
+ int ret;
+ struct lttcomm_session_msg lsm;
+ struct lttng_session_list_schedules_return *schedules_comm = NULL;
+ struct lttng_rotation_schedules *schedules = NULL;
+ struct lttng_rotation_schedule *periodic = NULL, *size = NULL;
+
+ if (!session_name) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ memset(&lsm, 0, sizeof(lsm));
+ lsm.cmd_type = LTTNG_SESSION_LIST_ROTATION_SCHEDULES;
+ ret = lttng_strncpy(lsm.session.name, session_name,
+ sizeof(lsm.session.name));
+ if (ret) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ ret = lttng_ctl_ask_sessiond(&lsm, (void **) &schedules_comm);
+ if (ret < 0) {
+ goto end;
+ }
+
+ schedules = lttng_rotation_schedules_create();
+ if (!schedules) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto end;
+ }
+
+ if (schedules_comm->periodic.set == 1) {
+ enum lttng_rotation_status status;
+
+ periodic = lttng_rotation_schedule_periodic_create();
+ if (!periodic) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto end;
+ }
+
+ status = lttng_rotation_schedule_periodic_set_period(
+ periodic, schedules_comm->periodic.value);
+ if (status != LTTNG_ROTATION_STATUS_OK) {
+ /*
+ * This would imply that the session daemon returned
+ * an invalid periodic rotation schedule value.
+ */
+ ret = -LTTNG_ERR_UNK;
+ goto end;
+ }
+
+ lttng_schedules_add(schedules, periodic);
+ periodic = NULL;
+ }
+
+ if (schedules_comm->size.set == 1) {
+ enum lttng_rotation_status status;
+
+ size = lttng_rotation_schedule_size_threshold_create();
+ if (!size) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto end;
+ }
+
+ status = lttng_rotation_schedule_size_threshold_set_threshold(
+ size, schedules_comm->size.value);
+ if (status != LTTNG_ROTATION_STATUS_OK) {
+ /*
+ * This would imply that the session daemon returned
+ * an invalid size threshold schedule value.
+ */
+ ret = -LTTNG_ERR_UNK;
+ goto end;
+ }
+
+ lttng_schedules_add(schedules, size);
+ size = NULL;
+ }
+
+ ret = LTTNG_OK;
+end:
+ free(schedules_comm);
+ free(periodic);
+ free(size);
+ *_schedules = schedules;
+ return ret;
+}
+
+enum lttng_rotation_schedule_type lttng_rotation_schedule_get_type(
+ const struct lttng_rotation_schedule *schedule)
+{
+ return schedule ? schedule->type : LTTNG_ROTATION_SCHEDULE_TYPE_UNKNOWN;
+}
+
+struct lttng_rotation_schedule *
+lttng_rotation_schedule_size_threshold_create(void)
+{
+ struct lttng_rotation_schedule_size_threshold *schedule;
+
+ schedule = (lttng_rotation_schedule_size_threshold *) zmalloc(sizeof(*schedule));
+ if (!schedule) {
+ goto end;
+ }
+
+ schedule->parent.type = LTTNG_ROTATION_SCHEDULE_TYPE_SIZE_THRESHOLD;
+end:
+ return &schedule->parent;
+}
+
+enum lttng_rotation_status
+lttng_rotation_schedule_size_threshold_get_threshold(
+ const struct lttng_rotation_schedule *schedule,
+ uint64_t *size_threshold_bytes)
+{
+ enum lttng_rotation_status status = LTTNG_ROTATION_STATUS_OK;
+ struct lttng_rotation_schedule_size_threshold *size_schedule;
+
+ if (!schedule || !size_threshold_bytes ||
+ schedule->type != LTTNG_ROTATION_SCHEDULE_TYPE_SIZE_THRESHOLD) {
+ status = LTTNG_ROTATION_STATUS_INVALID;
+ goto end;
+ }
+
+ size_schedule = container_of(schedule,
+ struct lttng_rotation_schedule_size_threshold,
+ parent);
+ if (size_schedule->size.set) {
+ *size_threshold_bytes = size_schedule->size.bytes;
+ } else {
+ status = LTTNG_ROTATION_STATUS_UNAVAILABLE;
+ goto end;
+ }
+end:
+ return status;
+}
+
+enum lttng_rotation_status
+lttng_rotation_schedule_size_threshold_set_threshold(
+ struct lttng_rotation_schedule *schedule,
+ uint64_t size_threshold_bytes)
+{
+ enum lttng_rotation_status status = LTTNG_ROTATION_STATUS_OK;
+ struct lttng_rotation_schedule_size_threshold *size_schedule;
+
+ if (!schedule || size_threshold_bytes == 0 ||
+ size_threshold_bytes == -1ULL ||
+ schedule->type != LTTNG_ROTATION_SCHEDULE_TYPE_SIZE_THRESHOLD) {
+ status = LTTNG_ROTATION_STATUS_INVALID;
+ goto end;
+ }
+
+ size_schedule = container_of(schedule,
+ struct lttng_rotation_schedule_size_threshold,
+ parent);
+ size_schedule->size.bytes = size_threshold_bytes;
+ size_schedule->size.set = true;
+end:
+ return status;
+}
+
+struct lttng_rotation_schedule *
+lttng_rotation_schedule_periodic_create(void)
+{
+ struct lttng_rotation_schedule_periodic *schedule;
+
+ schedule = (lttng_rotation_schedule_periodic *) zmalloc(sizeof(*schedule));
+ if (!schedule) {
+ goto end;
+ }
+
+ schedule->parent.type = LTTNG_ROTATION_SCHEDULE_TYPE_PERIODIC;
+end:
+ return &schedule->parent;
+}
+
+enum lttng_rotation_status
+lttng_rotation_schedule_periodic_get_period(
+ const struct lttng_rotation_schedule *schedule,
+ uint64_t *period_us)
+{
+ enum lttng_rotation_status status = LTTNG_ROTATION_STATUS_OK;
+ struct lttng_rotation_schedule_periodic *periodic_schedule;
+
+ if (!schedule || !period_us ||
+ schedule->type != LTTNG_ROTATION_SCHEDULE_TYPE_PERIODIC) {
+ status = LTTNG_ROTATION_STATUS_INVALID;
+ goto end;
+ }
+
+ periodic_schedule = container_of(schedule,
+ struct lttng_rotation_schedule_periodic,
+ parent);
+ if (periodic_schedule->period.set) {
+ *period_us = periodic_schedule->period.us;
+ } else {
+ status = LTTNG_ROTATION_STATUS_UNAVAILABLE;
+ goto end;
+ }
+end:
+ return status;
+}
+
+enum lttng_rotation_status
+lttng_rotation_schedule_periodic_set_period(
+ struct lttng_rotation_schedule *schedule,
+ uint64_t period_us)
+{
+ enum lttng_rotation_status status = LTTNG_ROTATION_STATUS_OK;
+ struct lttng_rotation_schedule_periodic *periodic_schedule;
+
+ if (!schedule || period_us == 0 || period_us == -1ULL ||
+ schedule->type != LTTNG_ROTATION_SCHEDULE_TYPE_PERIODIC) {
+ status = LTTNG_ROTATION_STATUS_INVALID;
+ goto end;
+ }
+
+ periodic_schedule = container_of(schedule,
+ struct lttng_rotation_schedule_periodic,
+ parent);
+ periodic_schedule->period.us = period_us;
+ periodic_schedule->period.set = true;
+end:
+ return status;
+}
+
+void lttng_rotation_schedule_destroy(struct lttng_rotation_schedule *schedule)
+{
+ if (!schedule) {
+ return;
+ }
+ free(schedule);
+}
+
+void lttng_rotation_schedules_destroy(
+ struct lttng_rotation_schedules *schedules)
+{
+ unsigned int i;
+
+ if (!schedules) {
+ return;
+ }
+
+ for (i = 0; i < schedules->count; i++) {
+ lttng_rotation_schedule_destroy(schedules->schedules[i]);
+ }
+ free(schedules);
+}
+
+
+enum lttng_rotation_status lttng_rotation_schedules_get_count(
+ const struct lttng_rotation_schedules *schedules,
+ unsigned int *count)
+{
+ enum lttng_rotation_status status = LTTNG_ROTATION_STATUS_OK;
+
+ if (!schedules || !count) {
+ status = LTTNG_ROTATION_STATUS_INVALID;
+ goto end;
+ }
+
+ *count = schedules->count;
+end:
+ return status;
+}
+
+const struct lttng_rotation_schedule *lttng_rotation_schedules_get_at_index(
+ const struct lttng_rotation_schedules *schedules,
+ unsigned int index)
+{
+ const struct lttng_rotation_schedule *schedule = NULL;
+
+ if (!schedules || index >= schedules->count) {
+ goto end;
+ }
+
+ schedule = schedules->schedules[index];
+end:
+ return schedule;
+}
+
+enum lttng_rotation_status lttng_session_add_rotation_schedule(
+ const char *session_name,
+ const struct lttng_rotation_schedule *schedule)
+{
+ return lttng_rotation_update_schedule(session_name, schedule, true);
+}
+
+enum lttng_rotation_status lttng_session_remove_rotation_schedule(
+ const char *session_name,
+ const struct lttng_rotation_schedule *schedule)
+{
+ return lttng_rotation_update_schedule(session_name, schedule, false);
+}
+
+int lttng_session_list_rotation_schedules(
+ const char *session_name,
+ struct lttng_rotation_schedules **schedules)
+{
+ return get_schedules(session_name, schedules);
+}
+++ /dev/null
-/*
- * Copyright (C) 2013 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#define _LGPL_SOURCE
-#include <string.h>
-
-#include <lttng/lttng-error.h>
-#include <lttng/save.h>
-#include <lttng/save-internal.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-
-#include "lttng-ctl-helper.h"
-
-struct lttng_save_session_attr *lttng_save_session_attr_create(void)
-{
- return zmalloc(sizeof(struct lttng_save_session_attr));
-}
-
-void lttng_save_session_attr_destroy(struct lttng_save_session_attr *output)
-{
- if (output) {
- free(output);
- }
-}
-
-const char *lttng_save_session_attr_get_session_name(
- struct lttng_save_session_attr *attr)
-{
- const char *ret = NULL;
-
- if (attr && attr->session_name[0]) {
- ret = attr->session_name;
- }
-
- return ret;
-}
-
-const char *lttng_save_session_attr_get_output_url(
- struct lttng_save_session_attr *attr)
-{
- const char *ret = NULL;
-
- if (attr && attr->configuration_url[0]) {
- ret = attr->configuration_url;
- }
-
- return ret;
-}
-
-int lttng_save_session_attr_get_overwrite(
- struct lttng_save_session_attr *attr)
-{
- return attr ? attr->overwrite : -LTTNG_ERR_INVALID;
-}
-
-int lttng_save_session_attr_get_omit_name(
- struct lttng_save_session_attr *attr)
-{
- return attr ? attr->omit_name : -LTTNG_ERR_INVALID;
-}
-
-int lttng_save_session_attr_get_omit_output(
- struct lttng_save_session_attr *attr)
-{
- return attr ? attr->omit_output : -LTTNG_ERR_INVALID;
-}
-
-int lttng_save_session_attr_set_session_name(
- struct lttng_save_session_attr *attr, const char *session_name)
-{
- int ret = 0;
-
- if (!attr) {
- ret = -LTTNG_ERR_INVALID;
- goto error;
- }
-
- if (session_name) {
- size_t len;
-
- len = strlen(session_name);
- if (len >= LTTNG_NAME_MAX) {
- ret = -LTTNG_ERR_INVALID;
- goto error;
- }
-
- ret = lttng_strncpy(attr->session_name, session_name,
- sizeof(attr->session_name));
- if (ret) {
- ret = -LTTNG_ERR_INVALID;
- goto error;
- }
- } else {
- attr->session_name[0] = '\0';
- }
-error:
- return ret;
-}
-
-int lttng_save_session_attr_set_output_url(
- struct lttng_save_session_attr *attr, const char *url)
-{
- int ret = 0;
- size_t len;
- ssize_t size;
- struct lttng_uri *uris = NULL;
-
- if (!attr) {
- ret = -LTTNG_ERR_INVALID;
- goto error;
- }
-
- if (!url) {
- attr->configuration_url[0] = '\0';
- ret = 0;
- goto end;
- }
-
- len = strlen(url);
- if (len >= PATH_MAX) {
- ret = -LTTNG_ERR_INVALID;
- goto error;
- }
-
- size = uri_parse_str_urls(url, NULL, &uris);
- if (size <= 0 || uris[0].dtype != LTTNG_DST_PATH) {
- ret = -LTTNG_ERR_INVALID;
- goto error;
- }
-
- /* Copy string plus the NULL terminated byte. */
- ret = lttng_strncpy(attr->configuration_url, uris[0].dst.path,
- sizeof(attr->configuration_url));
- if (ret) {
- ret = -LTTNG_ERR_INVALID;
- goto error;
- }
-
-end:
-error:
- free(uris);
- return ret;
-}
-
-int lttng_save_session_attr_set_overwrite(
- struct lttng_save_session_attr *attr, int overwrite)
-{
- int ret = 0;
-
- if (!attr) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- attr->overwrite = !!overwrite;
-end:
- return ret;
-}
-
-int lttng_save_session_attr_set_omit_name(
- struct lttng_save_session_attr *attr, int omit_name)
-{
- int ret = 0;
-
- if (!attr) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- attr->omit_name = !!omit_name;
-end:
- return ret;
-}
-
-int lttng_save_session_attr_set_omit_output(
- struct lttng_save_session_attr *attr, int omit_output)
-{
- int ret = 0;
-
- if (!attr) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- attr->omit_output = !!omit_output;
-end:
- return ret;
-}
-
-/*
- * The lttng-ctl API does not expose all the information needed to save the
- * session configurations. Thus, we must send a save command to the session
- * daemon which will, in turn, save its current session configuration.
- */
-int lttng_save_session(struct lttng_save_session_attr *attr)
-{
- struct lttcomm_session_msg lsm;
- int ret;
-
- if (!attr) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- memset(&lsm, 0, sizeof(lsm));
- lsm.cmd_type = LTTNG_SAVE_SESSION;
-
- memcpy(&lsm.u.save_session.attr, attr,
- sizeof(struct lttng_save_session_attr));
- ret = lttng_ctl_ask_sessiond(&lsm, NULL);
-end:
- return ret;
-}
--- /dev/null
+/*
+ * Copyright (C) 2013 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#define _LGPL_SOURCE
+#include <string.h>
+
+#include <lttng/lttng-error.h>
+#include <lttng/save.h>
+#include <lttng/save-internal.h>
+#include <common/sessiond-comm/sessiond-comm.h>
+
+#include "lttng-ctl-helper.h"
+
+struct lttng_save_session_attr *lttng_save_session_attr_create(void)
+{
+ return (lttng_save_session_attr *) zmalloc(sizeof(struct lttng_save_session_attr));
+}
+
+void lttng_save_session_attr_destroy(struct lttng_save_session_attr *output)
+{
+ if (output) {
+ free(output);
+ }
+}
+
+const char *lttng_save_session_attr_get_session_name(
+ struct lttng_save_session_attr *attr)
+{
+ const char *ret = NULL;
+
+ if (attr && attr->session_name[0]) {
+ ret = attr->session_name;
+ }
+
+ return ret;
+}
+
+const char *lttng_save_session_attr_get_output_url(
+ struct lttng_save_session_attr *attr)
+{
+ const char *ret = NULL;
+
+ if (attr && attr->configuration_url[0]) {
+ ret = attr->configuration_url;
+ }
+
+ return ret;
+}
+
+int lttng_save_session_attr_get_overwrite(
+ struct lttng_save_session_attr *attr)
+{
+ return attr ? attr->overwrite : -LTTNG_ERR_INVALID;
+}
+
+int lttng_save_session_attr_get_omit_name(
+ struct lttng_save_session_attr *attr)
+{
+ return attr ? attr->omit_name : -LTTNG_ERR_INVALID;
+}
+
+int lttng_save_session_attr_get_omit_output(
+ struct lttng_save_session_attr *attr)
+{
+ return attr ? attr->omit_output : -LTTNG_ERR_INVALID;
+}
+
+int lttng_save_session_attr_set_session_name(
+ struct lttng_save_session_attr *attr, const char *session_name)
+{
+ int ret = 0;
+
+ if (!attr) {
+ ret = -LTTNG_ERR_INVALID;
+ goto error;
+ }
+
+ if (session_name) {
+ size_t len;
+
+ len = strlen(session_name);
+ if (len >= LTTNG_NAME_MAX) {
+ ret = -LTTNG_ERR_INVALID;
+ goto error;
+ }
+
+ ret = lttng_strncpy(attr->session_name, session_name,
+ sizeof(attr->session_name));
+ if (ret) {
+ ret = -LTTNG_ERR_INVALID;
+ goto error;
+ }
+ } else {
+ attr->session_name[0] = '\0';
+ }
+error:
+ return ret;
+}
+
+int lttng_save_session_attr_set_output_url(
+ struct lttng_save_session_attr *attr, const char *url)
+{
+ int ret = 0;
+ size_t len;
+ ssize_t size;
+ struct lttng_uri *uris = NULL;
+
+ if (!attr) {
+ ret = -LTTNG_ERR_INVALID;
+ goto error;
+ }
+
+ if (!url) {
+ attr->configuration_url[0] = '\0';
+ ret = 0;
+ goto end;
+ }
+
+ len = strlen(url);
+ if (len >= PATH_MAX) {
+ ret = -LTTNG_ERR_INVALID;
+ goto error;
+ }
+
+ size = uri_parse_str_urls(url, NULL, &uris);
+ if (size <= 0 || uris[0].dtype != LTTNG_DST_PATH) {
+ ret = -LTTNG_ERR_INVALID;
+ goto error;
+ }
+
+ /* Copy string plus the NULL terminated byte. */
+ ret = lttng_strncpy(attr->configuration_url, uris[0].dst.path,
+ sizeof(attr->configuration_url));
+ if (ret) {
+ ret = -LTTNG_ERR_INVALID;
+ goto error;
+ }
+
+end:
+error:
+ free(uris);
+ return ret;
+}
+
+int lttng_save_session_attr_set_overwrite(
+ struct lttng_save_session_attr *attr, int overwrite)
+{
+ int ret = 0;
+
+ if (!attr) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ attr->overwrite = !!overwrite;
+end:
+ return ret;
+}
+
+int lttng_save_session_attr_set_omit_name(
+ struct lttng_save_session_attr *attr, int omit_name)
+{
+ int ret = 0;
+
+ if (!attr) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ attr->omit_name = !!omit_name;
+end:
+ return ret;
+}
+
+int lttng_save_session_attr_set_omit_output(
+ struct lttng_save_session_attr *attr, int omit_output)
+{
+ int ret = 0;
+
+ if (!attr) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ attr->omit_output = !!omit_output;
+end:
+ return ret;
+}
+
+/*
+ * The lttng-ctl API does not expose all the information needed to save the
+ * session configurations. Thus, we must send a save command to the session
+ * daemon which will, in turn, save its current session configuration.
+ */
+int lttng_save_session(struct lttng_save_session_attr *attr)
+{
+ struct lttcomm_session_msg lsm;
+ int ret;
+
+ if (!attr) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ memset(&lsm, 0, sizeof(lsm));
+ lsm.cmd_type = LTTNG_SAVE_SESSION;
+
+ memcpy(&lsm.u.save_session.attr, attr,
+ sizeof(struct lttng_save_session_attr));
+ ret = lttng_ctl_ask_sessiond(&lsm, NULL);
+end:
+ return ret;
+}
+++ /dev/null
-/*
- * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#define _LGPL_SOURCE
-#include <string.h>
-
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <lttng/lttng-error.h>
-#include <lttng/snapshot.h>
-#include <lttng/snapshot-internal.h>
-
-#include "lttng-ctl-helper.h"
-
-/*
- * Add an output object to a session identified by name.
- *
- * Return 0 on success or else a negative LTTNG_ERR code.
- */
-int lttng_snapshot_add_output(const char *session_name,
- struct lttng_snapshot_output *output)
-{
- int ret;
- struct lttcomm_session_msg lsm;
- struct lttcomm_lttng_output_id *reply;
-
- if (!session_name || !output) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- memset(&lsm, 0, sizeof(lsm));
- lsm.cmd_type = LTTNG_SNAPSHOT_ADD_OUTPUT;
-
- ret = lttng_strncpy(lsm.session.name, session_name,
- sizeof(lsm.session.name));
- if (ret) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- memcpy(&lsm.u.snapshot_output.output, output,
- sizeof(lsm.u.snapshot_output.output));
-
- ret = lttng_ctl_ask_sessiond(&lsm, (void **) &reply);
- if (ret < 0) {
- goto end;
- }
-
- output->id = reply->id;
- free(reply);
- ret = 0;
-end:
- return ret;
-}
-
-/*
- * Delete an output object to a session identified by name.
- *
- * Return 0 on success or else a negative LTTNG_ERR code.
- */
-int lttng_snapshot_del_output(const char *session_name,
- struct lttng_snapshot_output *output)
-{
- int ret;
- struct lttcomm_session_msg lsm;
-
- if (!session_name || !output) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- memset(&lsm, 0, sizeof(lsm));
- lsm.cmd_type = LTTNG_SNAPSHOT_DEL_OUTPUT;
-
- ret = lttng_strncpy(lsm.session.name, session_name,
- sizeof(lsm.session.name));
- if (ret) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- memcpy(&lsm.u.snapshot_output.output, output,
- sizeof(lsm.u.snapshot_output.output));
-
- ret = lttng_ctl_ask_sessiond(&lsm, NULL);
-end:
- return ret;
-}
-
-/*
- * List all snapshot output(s) of a session identified by name. The output list
- * object is populated and can be iterated over with the get_next call below.
- *
- * Return 0 on success or else a negative LTTNG_ERR code and the list pointer
- * is untouched.
- */
-int lttng_snapshot_list_output(const char *session_name,
- struct lttng_snapshot_output_list **list)
-{
- int ret;
- struct lttcomm_session_msg lsm;
- struct lttng_snapshot_output_list *new_list = NULL;
-
- if (!session_name || !list) {
- ret = -LTTNG_ERR_INVALID;
- goto error;
- }
-
- memset(&lsm, 0, sizeof(lsm));
- lsm.cmd_type = LTTNG_SNAPSHOT_LIST_OUTPUT;
-
- ret = lttng_strncpy(lsm.session.name, session_name,
- sizeof(lsm.session.name));
- if (ret) {
- ret = -LTTNG_ERR_INVALID;
- goto error;
- }
-
- new_list = zmalloc(sizeof(*new_list));
- if (!new_list) {
- ret = -LTTNG_ERR_NOMEM;
- goto error;
- }
-
- ret = lttng_ctl_ask_sessiond(&lsm, (void **) &new_list->array);
- if (ret < 0) {
- goto free_error;
- }
-
- new_list->count = ret / sizeof(struct lttng_snapshot_output);
- *list = new_list;
- return 0;
-
-free_error:
- free(new_list);
-error:
- return ret;
-}
-
-/*
- * Return the next available snapshot output object in the given list. A list
- * output command MUST have been done before.
- *
- * Return the next object on success or else NULL indicating the end of the
- * list.
- */
-struct lttng_snapshot_output *lttng_snapshot_output_list_get_next(
- struct lttng_snapshot_output_list *list)
-{
- struct lttng_snapshot_output *output = NULL;
-
- if (!list) {
- goto error;
- }
-
- /* We've reached the end. */
- if (list->index == list->count) {
- goto end;
- }
-
- output = &list->array[list->index];
- list->index++;
-
-end:
-error:
- return output;
-}
-
-/*
- * Free an output list object.
- */
-void lttng_snapshot_output_list_destroy(struct lttng_snapshot_output_list *list)
-{
- if (!list) {
- return;
- }
-
- free(list->array);
- free(list);
-}
-
-/*
- * Snapshot a trace for the given session.
- *
- * The output object can be NULL but an add output MUST be done prior to this
- * call. If it's not NULL, it will be used to snapshot a trace.
- *
- * The wait parameter is ignored for now. The snapshot record command will
- * ALWAYS wait for the snapshot to complete before returning meaning the
- * snapshot has been written on disk or streamed over the network to a relayd.
- *
- * Return 0 on success or else a negative LTTNG_ERR value.
- */
-int lttng_snapshot_record(const char *session_name,
- struct lttng_snapshot_output *output, int wait)
-{
- int ret;
- struct lttcomm_session_msg lsm;
-
- if (!session_name) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- memset(&lsm, 0, sizeof(lsm));
- lsm.cmd_type = LTTNG_SNAPSHOT_RECORD;
-
- ret = lttng_strncpy(lsm.session.name, session_name,
- sizeof(lsm.session.name));
- if (ret) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- /*
- * Not having an output object will use the default one of the session that
- * would need to be set by a call to add output prior to calling snapshot
- * record.
- */
- if (output) {
- memcpy(&lsm.u.snapshot_record.output, output,
- sizeof(lsm.u.snapshot_record.output));
- }
-
- /* The wait param is ignored. */
- ret = lttng_ctl_ask_sessiond(&lsm, NULL);
-end:
- return ret;
-}
-
-/*
- * Return an newly allocated snapshot output object or NULL on error.
- */
-struct lttng_snapshot_output *lttng_snapshot_output_create(void)
-{
- struct lttng_snapshot_output *output;
-
- output = zmalloc(sizeof(struct lttng_snapshot_output));
- if (!output) {
- goto error;
- }
-
- output->max_size = (uint64_t) -1ULL;
-
-error:
- return output;
-}
-
-/*
- * Free a given snapshot output object.
- */
-void lttng_snapshot_output_destroy(struct lttng_snapshot_output *obj)
-{
- if (obj) {
- free(obj);
- }
-}
-
-/*
- * Getter family functions of snapshot output.
- */
-
-uint32_t lttng_snapshot_output_get_id(const struct lttng_snapshot_output *output)
-{
- return output->id;
-}
-
-const char *lttng_snapshot_output_get_name(
- const struct lttng_snapshot_output *output)
-{
- return output->name;
-}
-
-const char *lttng_snapshot_output_get_data_url(const struct lttng_snapshot_output *output)
-{
- return output->data_url;
-}
-
-const char *lttng_snapshot_output_get_ctrl_url(const struct lttng_snapshot_output *output)
-{
- return output->ctrl_url;
-}
-
-uint64_t lttng_snapshot_output_get_maxsize(
- const struct lttng_snapshot_output *output)
-{
- return output->max_size;
-}
-
-/*
- * Setter family functions for snapshot output.
- */
-
-int lttng_snapshot_output_set_id(uint32_t id,
- struct lttng_snapshot_output *output)
-{
- if (!output || id == 0) {
- return -LTTNG_ERR_INVALID;
- }
-
- output->id = id;
- return 0;
-}
-
-int lttng_snapshot_output_set_size(uint64_t size,
- struct lttng_snapshot_output *output)
-{
- if (!output) {
- return -LTTNG_ERR_INVALID;
- }
-
- output->max_size = size;
- return 0;
-}
-
-int lttng_snapshot_output_set_name(const char *name,
- struct lttng_snapshot_output *output)
-{
- int ret;
-
- if (!output || !name) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- ret = lttng_strncpy(output->name, name, sizeof(output->name));
- if (ret) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
-end:
- return ret;
-}
-
-int lttng_snapshot_output_set_ctrl_url(const char *url,
- struct lttng_snapshot_output *output)
-{
- int ret;
-
- if (!output || !url) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- ret = lttng_strncpy(output->ctrl_url, url, sizeof(output->ctrl_url));
- if (ret) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
-end:
- return ret;
-}
-
-int lttng_snapshot_output_set_data_url(const char *url,
- struct lttng_snapshot_output *output)
-{
- int ret;
-
- if (!output || !url) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- ret = lttng_strncpy(output->data_url, url, sizeof(output->data_url));
- if (ret) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
-end:
- return ret;
-}
-
-int lttng_snapshot_output_set_local_path(const char *path,
- struct lttng_snapshot_output *output)
-{
- int ret;
- struct lttng_uri *uris = NULL;
- ssize_t num_uris;
-
- if (!path || !output) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- num_uris = uri_parse_str_urls(path, NULL, &uris);
- if (num_uris != 1) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- if (uris[0].dtype != LTTNG_DST_PATH) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- ret = lttng_strncpy(output->ctrl_url, path, sizeof(output->ctrl_url));
- if (ret != 0) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
-end:
- free(uris);
- return ret;
-}
-
-int lttng_snapshot_output_set_network_url(const char *url,
- struct lttng_snapshot_output *output)
-{
- int ret;
- struct lttng_uri *uris = NULL;
- ssize_t num_uris;
-
- if (!url || !output) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- num_uris = uri_parse_str_urls(url, NULL, &uris);
- if (num_uris != 2) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- if (uris[0].dtype != LTTNG_DST_IPV4 &&
- uris[0].dtype != LTTNG_DST_IPV6) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- if (uris[1].dtype != LTTNG_DST_IPV4 &&
- uris[1].dtype != LTTNG_DST_IPV6) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- ret = lttng_strncpy(output->ctrl_url, url, sizeof(output->ctrl_url));
- if (ret != 0) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
-end:
- free(uris);
- return ret;
-}
-
-int lttng_snapshot_output_set_network_urls(
- const char *ctrl_url, const char *data_url,
- struct lttng_snapshot_output *output)
-{
- int ret;
- struct lttng_uri *uris = NULL;
- ssize_t num_uris;
-
- if (!ctrl_url || !data_url || !output) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- num_uris = uri_parse_str_urls(ctrl_url, data_url, &uris);
- if (num_uris != 2) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- if (uris[0].dtype != LTTNG_DST_IPV4 &&
- uris[0].dtype != LTTNG_DST_IPV6) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- if (uris[1].dtype != LTTNG_DST_IPV4 &&
- uris[1].dtype != LTTNG_DST_IPV6) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- ret = lttng_strncpy(output->ctrl_url, ctrl_url, sizeof(output->ctrl_url));
- if (ret != 0) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- ret = lttng_strncpy(output->data_url, data_url, sizeof(output->data_url));
- if (ret != 0) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
-end:
- free(uris);
- return ret;
-}
--- /dev/null
+/*
+ * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#define _LGPL_SOURCE
+#include <string.h>
+
+#include <common/sessiond-comm/sessiond-comm.h>
+#include <lttng/lttng-error.h>
+#include <lttng/snapshot.h>
+#include <lttng/snapshot-internal.h>
+
+#include "lttng-ctl-helper.h"
+
+/*
+ * Add an output object to a session identified by name.
+ *
+ * Return 0 on success or else a negative LTTNG_ERR code.
+ */
+int lttng_snapshot_add_output(const char *session_name,
+ struct lttng_snapshot_output *output)
+{
+ int ret;
+ struct lttcomm_session_msg lsm;
+ struct lttcomm_lttng_output_id *reply;
+
+ if (!session_name || !output) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ memset(&lsm, 0, sizeof(lsm));
+ lsm.cmd_type = LTTNG_SNAPSHOT_ADD_OUTPUT;
+
+ ret = lttng_strncpy(lsm.session.name, session_name,
+ sizeof(lsm.session.name));
+ if (ret) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ memcpy(&lsm.u.snapshot_output.output, output,
+ sizeof(lsm.u.snapshot_output.output));
+
+ ret = lttng_ctl_ask_sessiond(&lsm, (void **) &reply);
+ if (ret < 0) {
+ goto end;
+ }
+
+ output->id = reply->id;
+ free(reply);
+ ret = 0;
+end:
+ return ret;
+}
+
+/*
+ * Delete an output object to a session identified by name.
+ *
+ * Return 0 on success or else a negative LTTNG_ERR code.
+ */
+int lttng_snapshot_del_output(const char *session_name,
+ struct lttng_snapshot_output *output)
+{
+ int ret;
+ struct lttcomm_session_msg lsm;
+
+ if (!session_name || !output) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ memset(&lsm, 0, sizeof(lsm));
+ lsm.cmd_type = LTTNG_SNAPSHOT_DEL_OUTPUT;
+
+ ret = lttng_strncpy(lsm.session.name, session_name,
+ sizeof(lsm.session.name));
+ if (ret) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ memcpy(&lsm.u.snapshot_output.output, output,
+ sizeof(lsm.u.snapshot_output.output));
+
+ ret = lttng_ctl_ask_sessiond(&lsm, NULL);
+end:
+ return ret;
+}
+
+/*
+ * List all snapshot output(s) of a session identified by name. The output list
+ * object is populated and can be iterated over with the get_next call below.
+ *
+ * Return 0 on success or else a negative LTTNG_ERR code and the list pointer
+ * is untouched.
+ */
+int lttng_snapshot_list_output(const char *session_name,
+ struct lttng_snapshot_output_list **list)
+{
+ int ret;
+ struct lttcomm_session_msg lsm;
+ struct lttng_snapshot_output_list *new_list = NULL;
+
+ if (!session_name || !list) {
+ ret = -LTTNG_ERR_INVALID;
+ goto error;
+ }
+
+ memset(&lsm, 0, sizeof(lsm));
+ lsm.cmd_type = LTTNG_SNAPSHOT_LIST_OUTPUT;
+
+ ret = lttng_strncpy(lsm.session.name, session_name,
+ sizeof(lsm.session.name));
+ if (ret) {
+ ret = -LTTNG_ERR_INVALID;
+ goto error;
+ }
+
+ new_list = (lttng_snapshot_output_list *) zmalloc(sizeof(*new_list));
+ if (!new_list) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto error;
+ }
+
+ ret = lttng_ctl_ask_sessiond(&lsm, (void **) &new_list->array);
+ if (ret < 0) {
+ goto free_error;
+ }
+
+ new_list->count = ret / sizeof(struct lttng_snapshot_output);
+ *list = new_list;
+ return 0;
+
+free_error:
+ free(new_list);
+error:
+ return ret;
+}
+
+/*
+ * Return the next available snapshot output object in the given list. A list
+ * output command MUST have been done before.
+ *
+ * Return the next object on success or else NULL indicating the end of the
+ * list.
+ */
+struct lttng_snapshot_output *lttng_snapshot_output_list_get_next(
+ struct lttng_snapshot_output_list *list)
+{
+ struct lttng_snapshot_output *output = NULL;
+
+ if (!list) {
+ goto error;
+ }
+
+ /* We've reached the end. */
+ if (list->index == list->count) {
+ goto end;
+ }
+
+ output = &list->array[list->index];
+ list->index++;
+
+end:
+error:
+ return output;
+}
+
+/*
+ * Free an output list object.
+ */
+void lttng_snapshot_output_list_destroy(struct lttng_snapshot_output_list *list)
+{
+ if (!list) {
+ return;
+ }
+
+ free(list->array);
+ free(list);
+}
+
+/*
+ * Snapshot a trace for the given session.
+ *
+ * The output object can be NULL but an add output MUST be done prior to this
+ * call. If it's not NULL, it will be used to snapshot a trace.
+ *
+ * The wait parameter is ignored for now. The snapshot record command will
+ * ALWAYS wait for the snapshot to complete before returning meaning the
+ * snapshot has been written on disk or streamed over the network to a relayd.
+ *
+ * Return 0 on success or else a negative LTTNG_ERR value.
+ */
+int lttng_snapshot_record(const char *session_name,
+ struct lttng_snapshot_output *output, int wait)
+{
+ int ret;
+ struct lttcomm_session_msg lsm;
+
+ if (!session_name) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ memset(&lsm, 0, sizeof(lsm));
+ lsm.cmd_type = LTTNG_SNAPSHOT_RECORD;
+
+ ret = lttng_strncpy(lsm.session.name, session_name,
+ sizeof(lsm.session.name));
+ if (ret) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ /*
+ * Not having an output object will use the default one of the session that
+ * would need to be set by a call to add output prior to calling snapshot
+ * record.
+ */
+ if (output) {
+ memcpy(&lsm.u.snapshot_record.output, output,
+ sizeof(lsm.u.snapshot_record.output));
+ }
+
+ /* The wait param is ignored. */
+ ret = lttng_ctl_ask_sessiond(&lsm, NULL);
+end:
+ return ret;
+}
+
+/*
+ * Return an newly allocated snapshot output object or NULL on error.
+ */
+struct lttng_snapshot_output *lttng_snapshot_output_create(void)
+{
+ struct lttng_snapshot_output *output;
+
+ output = (lttng_snapshot_output *) zmalloc(sizeof(struct lttng_snapshot_output));
+ if (!output) {
+ goto error;
+ }
+
+ output->max_size = (uint64_t) -1ULL;
+
+error:
+ return output;
+}
+
+/*
+ * Free a given snapshot output object.
+ */
+void lttng_snapshot_output_destroy(struct lttng_snapshot_output *obj)
+{
+ if (obj) {
+ free(obj);
+ }
+}
+
+/*
+ * Getter family functions of snapshot output.
+ */
+
+uint32_t lttng_snapshot_output_get_id(const struct lttng_snapshot_output *output)
+{
+ return output->id;
+}
+
+const char *lttng_snapshot_output_get_name(
+ const struct lttng_snapshot_output *output)
+{
+ return output->name;
+}
+
+const char *lttng_snapshot_output_get_data_url(const struct lttng_snapshot_output *output)
+{
+ return output->data_url;
+}
+
+const char *lttng_snapshot_output_get_ctrl_url(const struct lttng_snapshot_output *output)
+{
+ return output->ctrl_url;
+}
+
+uint64_t lttng_snapshot_output_get_maxsize(
+ const struct lttng_snapshot_output *output)
+{
+ return output->max_size;
+}
+
+/*
+ * Setter family functions for snapshot output.
+ */
+
+int lttng_snapshot_output_set_id(uint32_t id,
+ struct lttng_snapshot_output *output)
+{
+ if (!output || id == 0) {
+ return -LTTNG_ERR_INVALID;
+ }
+
+ output->id = id;
+ return 0;
+}
+
+int lttng_snapshot_output_set_size(uint64_t size,
+ struct lttng_snapshot_output *output)
+{
+ if (!output) {
+ return -LTTNG_ERR_INVALID;
+ }
+
+ output->max_size = size;
+ return 0;
+}
+
+int lttng_snapshot_output_set_name(const char *name,
+ struct lttng_snapshot_output *output)
+{
+ int ret;
+
+ if (!output || !name) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ ret = lttng_strncpy(output->name, name, sizeof(output->name));
+ if (ret) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+end:
+ return ret;
+}
+
+int lttng_snapshot_output_set_ctrl_url(const char *url,
+ struct lttng_snapshot_output *output)
+{
+ int ret;
+
+ if (!output || !url) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ ret = lttng_strncpy(output->ctrl_url, url, sizeof(output->ctrl_url));
+ if (ret) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+end:
+ return ret;
+}
+
+int lttng_snapshot_output_set_data_url(const char *url,
+ struct lttng_snapshot_output *output)
+{
+ int ret;
+
+ if (!output || !url) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ ret = lttng_strncpy(output->data_url, url, sizeof(output->data_url));
+ if (ret) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+end:
+ return ret;
+}
+
+int lttng_snapshot_output_set_local_path(const char *path,
+ struct lttng_snapshot_output *output)
+{
+ int ret;
+ struct lttng_uri *uris = NULL;
+ ssize_t num_uris;
+
+ if (!path || !output) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ num_uris = uri_parse_str_urls(path, NULL, &uris);
+ if (num_uris != 1) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ if (uris[0].dtype != LTTNG_DST_PATH) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ ret = lttng_strncpy(output->ctrl_url, path, sizeof(output->ctrl_url));
+ if (ret != 0) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+end:
+ free(uris);
+ return ret;
+}
+
+int lttng_snapshot_output_set_network_url(const char *url,
+ struct lttng_snapshot_output *output)
+{
+ int ret;
+ struct lttng_uri *uris = NULL;
+ ssize_t num_uris;
+
+ if (!url || !output) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ num_uris = uri_parse_str_urls(url, NULL, &uris);
+ if (num_uris != 2) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ if (uris[0].dtype != LTTNG_DST_IPV4 &&
+ uris[0].dtype != LTTNG_DST_IPV6) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ if (uris[1].dtype != LTTNG_DST_IPV4 &&
+ uris[1].dtype != LTTNG_DST_IPV6) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ ret = lttng_strncpy(output->ctrl_url, url, sizeof(output->ctrl_url));
+ if (ret != 0) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+end:
+ free(uris);
+ return ret;
+}
+
+int lttng_snapshot_output_set_network_urls(
+ const char *ctrl_url, const char *data_url,
+ struct lttng_snapshot_output *output)
+{
+ int ret;
+ struct lttng_uri *uris = NULL;
+ ssize_t num_uris;
+
+ if (!ctrl_url || !data_url || !output) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ num_uris = uri_parse_str_urls(ctrl_url, data_url, &uris);
+ if (num_uris != 2) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ if (uris[0].dtype != LTTNG_DST_IPV4 &&
+ uris[0].dtype != LTTNG_DST_IPV6) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ if (uris[1].dtype != LTTNG_DST_IPV4 &&
+ uris[1].dtype != LTTNG_DST_IPV6) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ ret = lttng_strncpy(output->ctrl_url, ctrl_url, sizeof(output->ctrl_url));
+ if (ret != 0) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ ret = lttng_strncpy(output->data_url, data_url, sizeof(output->data_url));
+ if (ret != 0) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+end:
+ free(uris);
+ return ret;
+}
+++ /dev/null
-/*
- * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#include "lttng-ctl-helper.h"
-#include "lttng/domain.h"
-#include "lttng/lttng-error.h"
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <common/tracker.h>
-#include <lttng/tracker.h>
-
-struct lttng_process_attr_tracker_handle {
- char *session_name;
- enum lttng_domain_type domain;
- enum lttng_process_attr process_attr;
- struct lttng_process_attr_values *inclusion_set;
-};
-
-void lttng_process_attr_tracker_handle_destroy(
- struct lttng_process_attr_tracker_handle *tracker)
-{
- if (!tracker) {
- return;
- }
-
- lttng_process_attr_values_destroy(tracker->inclusion_set);
- free(tracker->session_name);
- free(tracker);
-}
-
-enum lttng_error_code lttng_session_get_tracker_handle(const char *session_name,
- enum lttng_domain_type domain,
- enum lttng_process_attr process_attr,
- struct lttng_process_attr_tracker_handle **out_tracker_handle)
-{
- enum lttng_error_code ret_code = LTTNG_OK;
- struct lttng_process_attr_tracker_handle *handle = NULL;
- enum lttng_process_attr_tracker_handle_status status;
- enum lttng_tracking_policy policy;
-
- if (!session_name || !out_tracker_handle) {
- ret_code = LTTNG_ERR_INVALID;
- goto error;
- }
-
- if (domain != LTTNG_DOMAIN_KERNEL && domain != LTTNG_DOMAIN_UST) {
- ret_code = LTTNG_ERR_UNSUPPORTED_DOMAIN;
- goto error;
- }
-
- handle = zmalloc(sizeof(*handle));
- if (!handle) {
- ret_code = LTTNG_ERR_NOMEM;
- goto error;
- }
-
- handle->session_name = strdup(session_name);
- if (!handle->session_name) {
- ret_code = LTTNG_ERR_NOMEM;
- goto error;
- }
-
- handle->domain = domain;
- handle->process_attr = process_attr;
-
- /*
- * Use the `get_tracking_policy` command to validate the tracker's
- * existance.
- */
- status = lttng_process_attr_tracker_handle_get_tracking_policy(
- handle, &policy);
- switch (status) {
- case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK:
- break;
- case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_SESSION_DOES_NOT_EXIST:
- ret_code = LTTNG_ERR_SESSION_NOT_EXIST;
- goto error;
- default:
- ret_code = LTTNG_ERR_UNK;
- goto error;
- }
-
- *out_tracker_handle = handle;
- return ret_code;
-error:
- lttng_process_attr_tracker_handle_destroy(handle);
- return ret_code;
-}
-
-enum lttng_process_attr_tracker_handle_status
-lttng_process_attr_tracker_handle_get_tracking_policy(
- const struct lttng_process_attr_tracker_handle *tracker,
- enum lttng_tracking_policy *policy)
-{
- void *reply = NULL;
- int reply_ret, copy_ret;
- enum lttng_process_attr_tracker_handle_status status =
- LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK;
- struct lttcomm_session_msg lsm = {
- .cmd_type = LTTNG_PROCESS_ATTR_TRACKER_GET_POLICY,
- };
-
- if (!tracker || !policy) {
- status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID;
- goto end;
- }
-
- copy_ret = lttng_strncpy(lsm.session.name, tracker->session_name,
- sizeof(lsm.session.name));
- if (copy_ret) {
- status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID;
- goto end;
- }
-
- lsm.domain.type = tracker->domain;
- lsm.u.process_attr_tracker_get_tracking_policy.process_attr =
- (int32_t) tracker->process_attr;
-
- /* Command returns a session descriptor on success. */
- reply_ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header(
- &lsm, NULL, 0, &reply);
- if (reply_ret != sizeof(uint32_t)) {
- if (reply_ret == -LTTNG_ERR_SESSION_NOT_EXIST ||
- reply_ret == -LTTNG_ERR_SESS_NOT_FOUND) {
- status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_SESSION_DOES_NOT_EXIST;
- } else {
- status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_ERROR;
- }
- goto end;
- }
-
- *policy = (enum lttng_tracking_policy)(*((const uint32_t *) reply));
-end:
- free(reply);
- return status;
-}
-
-enum lttng_process_attr_tracker_handle_status
-lttng_process_attr_tracker_handle_set_tracking_policy(
- const struct lttng_process_attr_tracker_handle *tracker,
- enum lttng_tracking_policy policy)
-{
- int reply_ret, copy_ret;
- enum lttng_process_attr_tracker_handle_status status =
- LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK;
- struct lttcomm_session_msg lsm = {
- .cmd_type = LTTNG_PROCESS_ATTR_TRACKER_SET_POLICY,
- };
-
- if (!tracker) {
- status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID;
- goto end;
- }
-
- copy_ret = lttng_strncpy(lsm.session.name, tracker->session_name,
- sizeof(lsm.session.name));
- if (copy_ret) {
- status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID;
- goto end;
- }
-
- lsm.domain.type = tracker->domain;
- lsm.u.process_attr_tracker_set_tracking_policy.process_attr =
- (int32_t) tracker->process_attr;
- lsm.u.process_attr_tracker_set_tracking_policy.tracking_policy =
- (int32_t) policy;
-
- /* Command returns a session descriptor on success. */
- reply_ret = lttng_ctl_ask_sessiond(&lsm, NULL);
- if (reply_ret < 0) {
- if (reply_ret == -LTTNG_ERR_SESSION_NOT_EXIST) {
- status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_SESSION_DOES_NOT_EXIST;
- } else {
- status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_ERROR;
- }
- goto end;
- }
-end:
- return status;
-}
-
-#define DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(command_upper, \
- command_lower, process_attr_name, value_type_name, \
- value_type_c, value_type_enum) \
- enum lttng_process_attr_tracker_handle_status \
- lttng_process_attr_##process_attr_name##_tracker_handle_##command_lower##_##value_type_name( \
- const struct lttng_process_attr_tracker_handle \
- *tracker, \
- value_type_c value) \
- { \
- int ret; \
- enum lttng_process_attr_tracker_handle_status status = \
- LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK; \
- struct lttcomm_session_msg lsm = { \
- .cmd_type = LTTNG_PROCESS_ATTR_TRACKER_##command_upper##_INCLUDE_VALUE}; \
- \
- if (!tracker) { \
- status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID; \
- goto end; \
- } \
- \
- ret = lttng_strncpy(lsm.session.name, tracker->session_name, \
- sizeof(lsm.session.name)); \
- if (ret) { \
- status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID; \
- goto end; \
- } \
- \
- lsm.domain.type = tracker->domain; \
- lsm.u.process_attr_tracker_add_remove_include_value \
- .process_attr = \
- (int32_t) tracker->process_attr; \
- lsm.u.process_attr_tracker_add_remove_include_value \
- .value_type = (uint32_t) \
- LTTNG_PROCESS_ATTR_VALUE_TYPE_##value_type_enum; \
- \
- if (is_signed(value_type_c)) { \
- lsm.u.process_attr_tracker_add_remove_include_value \
- .integral_value.u._signed = value; \
- } else { \
- lsm.u.process_attr_tracker_add_remove_include_value \
- .integral_value.u._unsigned = value; \
- } \
- \
- ret = lttng_ctl_ask_sessiond(&lsm, NULL); \
- if (ret < 0) { \
- switch (-ret) { \
- case LTTNG_ERR_PROCESS_ATTR_EXISTS: \
- status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_EXISTS; \
- break; \
- case LTTNG_ERR_PROCESS_ATTR_MISSING: \
- status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_MISSING; \
- break; \
- case LTTNG_ERR_PROCESS_ATTR_TRACKER_INVALID_TRACKING_POLICY: \
- status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID_TRACKING_POLICY; \
- break; \
- default: \
- status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_ERROR; \
- } \
- } \
- end: \
- return status; \
- }
-
-#define DEFINE_TRACKER_ADD_REMOVE_STRING_VALUE_FUNC(command_upper, \
- command_lower, process_attr_name, value_type_name, \
- value_type_enum) \
- enum lttng_process_attr_tracker_handle_status \
- lttng_process_attr_##process_attr_name##_tracker_handle_##command_lower##_##value_type_name( \
- const struct lttng_process_attr_tracker_handle \
- *tracker, \
- const char *value) \
- { \
- int ret; \
- enum lttng_process_attr_tracker_handle_status status = \
- LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK; \
- struct lttcomm_session_msg lsm = { \
- .cmd_type = LTTNG_PROCESS_ATTR_TRACKER_##command_upper##_INCLUDE_VALUE}; \
- const size_t len = value ? strlen(value) + 1 : 0; \
- \
- if (!tracker || !value) { \
- status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID; \
- goto end; \
- } \
- \
- ret = lttng_strncpy(lsm.session.name, tracker->session_name, \
- sizeof(lsm.session.name)); \
- if (ret) { \
- status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID; \
- goto end; \
- } \
- \
- lsm.domain.type = tracker->domain; \
- lsm.u.process_attr_tracker_add_remove_include_value \
- .process_attr = \
- (int32_t) tracker->process_attr; \
- lsm.u.process_attr_tracker_add_remove_include_value.name_len = \
- (uint32_t) len; \
- lsm.u.process_attr_tracker_add_remove_include_value \
- .value_type = (uint32_t) \
- LTTNG_PROCESS_ATTR_VALUE_TYPE_##value_type_enum; \
- \
- ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header( \
- &lsm, value, len, NULL); \
- if (ret < 0) { \
- switch (-ret) { \
- case LTTNG_ERR_PROCESS_ATTR_EXISTS: \
- status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_EXISTS; \
- break; \
- case LTTNG_ERR_PROCESS_ATTR_MISSING: \
- status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_MISSING; \
- break; \
- case LTTNG_ERR_PROCESS_ATTR_TRACKER_INVALID_TRACKING_POLICY: \
- status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID_TRACKING_POLICY; \
- break; \
- case LTTNG_ERR_USER_NOT_FOUND: \
- status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_USER_NOT_FOUND; \
- break; \
- case LTTNG_ERR_GROUP_NOT_FOUND: \
- status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_GROUP_NOT_FOUND; \
- break; \
- default: \
- status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_ERROR; \
- } \
- } \
- end: \
- return status; \
- }
-
-/* PID */
-DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
- ADD, add, process_id, pid, pid_t, PID);
-DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
- REMOVE, remove, process_id, pid, pid_t, PID);
-
-/* VPID */
-DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
- ADD, add, virtual_process_id, pid, pid_t, PID);
-DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
- REMOVE, remove, virtual_process_id, pid, pid_t, PID);
-
-/* UID */
-DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
- ADD, add, user_id, uid, uid_t, UID);
-DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
- REMOVE, remove, user_id, uid, uid_t, UID);
-DEFINE_TRACKER_ADD_REMOVE_STRING_VALUE_FUNC(
- ADD, add, user_id, user_name, USER_NAME);
-DEFINE_TRACKER_ADD_REMOVE_STRING_VALUE_FUNC(
- REMOVE, remove, user_id, user_name, USER_NAME);
-
-/* VUID */
-DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
- ADD, add, virtual_user_id, uid, uid_t, UID);
-DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
- REMOVE, remove, virtual_user_id, uid, uid_t, UID);
-DEFINE_TRACKER_ADD_REMOVE_STRING_VALUE_FUNC(
- ADD, add, virtual_user_id, user_name, USER_NAME);
-DEFINE_TRACKER_ADD_REMOVE_STRING_VALUE_FUNC(
- REMOVE, remove, virtual_user_id, user_name, USER_NAME);
-
-/* GID */
-DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
- ADD, add, group_id, gid, gid_t, GID);
-DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
- REMOVE, remove, group_id, gid, gid_t, GID);
-DEFINE_TRACKER_ADD_REMOVE_STRING_VALUE_FUNC(
- ADD, add, group_id, group_name, GROUP_NAME);
-DEFINE_TRACKER_ADD_REMOVE_STRING_VALUE_FUNC(
- REMOVE, remove, group_id, group_name, GROUP_NAME);
-
-/* VGID */
-DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
- ADD, add, virtual_group_id, gid, gid_t, GID);
-DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
- REMOVE, remove, virtual_group_id, gid, gid_t, GID);
-DEFINE_TRACKER_ADD_REMOVE_STRING_VALUE_FUNC(
- ADD, add, virtual_group_id, group_name, GROUP_NAME);
-DEFINE_TRACKER_ADD_REMOVE_STRING_VALUE_FUNC(
- REMOVE, remove, virtual_group_id, group_name, GROUP_NAME);
-
-enum lttng_process_attr_tracker_handle_status
-lttng_process_attr_tracker_handle_get_inclusion_set(
- struct lttng_process_attr_tracker_handle *tracker,
- const struct lttng_process_attr_values **values)
-{
- void *reply = NULL;
- int reply_ret, copy_ret;
- enum lttng_process_attr_tracker_handle_status status =
- LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK;
- struct lttcomm_session_msg lsm = {
- .cmd_type = LTTNG_PROCESS_ATTR_TRACKER_GET_INCLUSION_SET,
- };
- struct lttng_buffer_view inclusion_set_view;
- ssize_t inclusion_set_ret;
-
- if (!tracker || !values) {
- status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID;
- goto end;
- }
-
- lttng_process_attr_values_destroy(tracker->inclusion_set);
- tracker->inclusion_set = NULL;
-
- copy_ret = lttng_strncpy(lsm.session.name, tracker->session_name,
- sizeof(lsm.session.name));
- if (copy_ret) {
- status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID;
- goto end;
- }
-
- lsm.domain.type = tracker->domain;
- lsm.u.process_attr_tracker_get_tracking_policy.process_attr =
- (int32_t) tracker->process_attr;
-
- /* Command returns a session descriptor on success. */
- reply_ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header(
- &lsm, NULL, 0, &reply);
- if (reply_ret < 0) {
- if (reply_ret == -LTTNG_ERR_SESSION_NOT_EXIST) {
- status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_SESSION_DOES_NOT_EXIST;
- } else if (reply_ret ==
- -LTTNG_ERR_PROCESS_ATTR_TRACKER_INVALID_TRACKING_POLICY) {
- status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID_TRACKING_POLICY;
- } else {
- status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_ERROR;
- }
- goto end;
- } else if (reply_ret == 0) {
- status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_COMMUNICATION_ERROR;
- goto end;
- }
-
- inclusion_set_view = lttng_buffer_view_init(reply, 0, reply_ret);
- if (!inclusion_set_view.data) {
- status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_COMMUNICATION_ERROR;
- goto end;
- }
-
- inclusion_set_ret = lttng_process_attr_values_create_from_buffer(
- tracker->domain, tracker->process_attr,
- &inclusion_set_view, &tracker->inclusion_set);
- if (inclusion_set_ret < 0) {
- status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_COMMUNICATION_ERROR;
- goto end;
- }
- *values = tracker->inclusion_set;
-end:
- free(reply);
- return status;
-}
-
-enum lttng_process_attr_values_status lttng_process_attr_values_get_count(
- const struct lttng_process_attr_values *values,
- unsigned int *count)
-{
- enum lttng_process_attr_values_status status =
- LTTNG_PROCESS_ATTR_VALUES_STATUS_OK;
-
- if (!values || !count) {
- status = LTTNG_PROCESS_ATTR_VALUES_STATUS_INVALID;
- goto end;
- }
-
- *count = _lttng_process_attr_values_get_count(values);
-end:
- return status;
-}
-
-enum lttng_process_attr_value_type lttng_process_attr_values_get_type_at_index(
- const struct lttng_process_attr_values *values,
- unsigned int index)
-{
- enum lttng_process_attr_value_type type;
- const struct process_attr_value *value;
-
- if (!values) {
- type = LTTNG_PROCESS_ATTR_VALUE_TYPE_INVALID;
- goto end;
- }
-
- if (_lttng_process_attr_values_get_count(values) <= index) {
- type = LTTNG_PROCESS_ATTR_VALUE_TYPE_INVALID;
- goto end;
- }
-
- value = lttng_process_attr_tracker_values_get_at_index(values, index);
- type = value->type;
-end:
- return type;
-}
-
-#define DEFINE_LTTNG_PROCESS_ATTR_VALUES_GETTER( \
- value_type_name, value_type, expected_value_type) \
- enum lttng_process_attr_values_status \
- lttng_process_attr_values_get_##value_type_name##_at_index( \
- const struct lttng_process_attr_values \
- *values, \
- unsigned int index, \
- value_type *out_value) \
- { \
- enum lttng_process_attr_values_status status = \
- LTTNG_PROCESS_ATTR_VALUES_STATUS_OK; \
- const struct process_attr_value *value; \
- \
- if (!values) { \
- status = LTTNG_PROCESS_ATTR_VALUES_STATUS_INVALID; \
- goto end; \
- } \
- \
- if (_lttng_process_attr_values_get_count(values) <= index) { \
- status = LTTNG_PROCESS_ATTR_VALUES_STATUS_INVALID; \
- goto end; \
- } \
- \
- value = lttng_process_attr_tracker_values_get_at_index( \
- values, index); \
- if (value->type != \
- LTTNG_PROCESS_ATTR_VALUE_TYPE_##expected_value_type) { \
- status = LTTNG_PROCESS_ATTR_VALUES_STATUS_INVALID_TYPE; \
- goto end; \
- } \
- *out_value = value->value.value_type_name; \
- end: \
- return status; \
- }
-
-DEFINE_LTTNG_PROCESS_ATTR_VALUES_GETTER(pid, pid_t, PID);
-DEFINE_LTTNG_PROCESS_ATTR_VALUES_GETTER(uid, uid_t, UID);
-DEFINE_LTTNG_PROCESS_ATTR_VALUES_GETTER(gid, gid_t, GID);
-DEFINE_LTTNG_PROCESS_ATTR_VALUES_GETTER(user_name, const char *, USER_NAME);
-DEFINE_LTTNG_PROCESS_ATTR_VALUES_GETTER(group_name, const char *, GROUP_NAME);
-
-static enum lttng_error_code handle_status_to_error_code(
- enum lttng_process_attr_tracker_handle_status handle_status)
-{
- switch (handle_status) {
- case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID_TRACKING_POLICY:
- return LTTNG_ERR_INVALID;
- case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_SESSION_DOES_NOT_EXIST:
- return LTTNG_ERR_SESSION_NOT_EXIST;
- case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_COMMUNICATION_ERROR:
- return LTTNG_ERR_INVALID_PROTOCOL;
- case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_EXISTS:
- return LTTNG_ERR_PID_TRACKED;
- case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_MISSING:
- return LTTNG_ERR_PID_NOT_TRACKED;
- case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK:
- return LTTNG_OK;
- case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_ERROR:
- default:
- /* fall-through. */
- return LTTNG_ERR_UNK;
- }
-}
-
-/*
- * Add PID to session tracker.
- * Return 0 on success else a negative LTTng error code.
- */
-int lttng_track_pid(struct lttng_handle *handle, int pid)
-{
- enum lttng_error_code ret_code;
- struct lttng_process_attr_tracker_handle *tracker_handle = NULL;
- enum lttng_process_attr_tracker_handle_status handle_status;
- enum lttng_tracking_policy policy;
- enum lttng_process_attr process_attr;
-
- if (!handle) {
- ret_code = LTTNG_ERR_INVALID;
- goto end;
- }
-
- process_attr = handle->domain.type == LTTNG_DOMAIN_KERNEL ?
- LTTNG_PROCESS_ATTR_PROCESS_ID :
- LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID;
-
- ret_code = lttng_session_get_tracker_handle(handle->session_name,
- handle->domain.type,
- process_attr, &tracker_handle);
- if (ret_code != LTTNG_OK) {
- goto end;
- }
-
- if (pid == -1) {
- handle_status = lttng_process_attr_tracker_handle_set_tracking_policy(
- tracker_handle,
- LTTNG_TRACKING_POLICY_INCLUDE_ALL);
- ret_code = handle_status_to_error_code(handle_status);
- goto end;
- }
-
- handle_status = lttng_process_attr_tracker_handle_get_tracking_policy(
- tracker_handle, &policy);
- if (handle_status != LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK) {
- ret_code = handle_status_to_error_code(handle_status);
- goto end;
- }
-
- if (policy != LTTNG_TRACKING_POLICY_INCLUDE_SET) {
- handle_status = lttng_process_attr_tracker_handle_set_tracking_policy(
- tracker_handle,
- LTTNG_TRACKING_POLICY_INCLUDE_SET);
- if (handle_status != LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK) {
- ret_code = handle_status_to_error_code(handle_status);
- goto end;
- }
- }
-
- handle_status = process_attr == LTTNG_PROCESS_ATTR_PROCESS_ID ?
- lttng_process_attr_process_id_tracker_handle_add_pid(
- tracker_handle,
- (pid_t) pid) :
- lttng_process_attr_virtual_process_id_tracker_handle_add_pid(
- tracker_handle,
- (pid_t) pid);
- ret_code = handle_status_to_error_code(handle_status);
-end:
- lttng_process_attr_tracker_handle_destroy(tracker_handle);
- return ret_code == LTTNG_OK ? 0 : -ret_code;
-}
-
-/*
- * Remove PID from session tracker.
- * Return 0 on success else a negative LTTng error code.
- */
-int lttng_untrack_pid(struct lttng_handle *handle, int pid)
-{
- enum lttng_error_code ret_code;
- struct lttng_process_attr_tracker_handle *tracker_handle = NULL;
- enum lttng_process_attr_tracker_handle_status handle_status;
- enum lttng_tracking_policy policy;
- enum lttng_process_attr process_attr;
-
- if (!handle) {
- ret_code = LTTNG_ERR_INVALID;
- goto end;
- }
-
- process_attr = handle->domain.type == LTTNG_DOMAIN_KERNEL ?
- LTTNG_PROCESS_ATTR_PROCESS_ID :
- LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID;
- ret_code = lttng_session_get_tracker_handle(handle->session_name,
- handle->domain.type, process_attr, &tracker_handle);
- if (ret_code != LTTNG_OK) {
- goto end;
- }
-
- if (pid == -1) {
- handle_status = lttng_process_attr_tracker_handle_set_tracking_policy(
- tracker_handle,
- LTTNG_TRACKING_POLICY_EXCLUDE_ALL);
- ret_code = handle_status_to_error_code(handle_status);
- goto end;
- }
-
- handle_status = lttng_process_attr_tracker_handle_get_tracking_policy(
- tracker_handle, &policy);
- if (handle_status != LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK) {
- ret_code = handle_status_to_error_code(handle_status);
- goto end;
- }
-
- if (policy == LTTNG_TRACKING_POLICY_EXCLUDE_ALL) {
- ret_code = LTTNG_ERR_PID_NOT_TRACKED;
- goto end;
- } else if (policy == LTTNG_TRACKING_POLICY_INCLUDE_ALL) {
- ret_code = LTTNG_ERR_INVALID;
- goto end;
- }
-
- handle_status = process_attr == LTTNG_PROCESS_ATTR_PROCESS_ID ?
- lttng_process_attr_process_id_tracker_handle_remove_pid(
- tracker_handle,
- (pid_t) pid) :
- lttng_process_attr_virtual_process_id_tracker_handle_remove_pid(
- tracker_handle,
- (pid_t) pid);
- if (handle_status == LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID_TRACKING_POLICY) {
- ret_code = LTTNG_ERR_PID_NOT_TRACKED;
- }
-end:
- lttng_process_attr_tracker_handle_destroy(tracker_handle);
- return ret_code == LTTNG_OK ? 0 : -ret_code;
-}
-
-/*
- * List PIDs in the tracker.
- *
- * enabled is set to whether the PID tracker is enabled.
- * pids is set to an allocated array of PIDs currently tracked. On
- * success, pids must be freed by the caller.
- * nr_pids is set to the number of entries contained by the pids array.
- *
- * Returns 0 on success, else a negative LTTng error code.
- */
-int lttng_list_tracker_pids(struct lttng_handle *handle,
- int *_enabled,
- int32_t **_pids,
- size_t *_nr_pids)
-{
- enum lttng_error_code ret_code;
- struct lttng_process_attr_tracker_handle *tracker_handle = NULL;
- enum lttng_process_attr_tracker_handle_status handle_status;
- const struct lttng_process_attr_values *values;
- enum lttng_tracking_policy policy;
- unsigned int pid_count, i;
- int32_t *pid_array = NULL;
-
- if (!handle || !_enabled || !_pids || !_nr_pids) {
- ret_code = LTTNG_ERR_INVALID;
- goto end;
- }
-
- ret_code = lttng_session_get_tracker_handle(handle->session_name,
- handle->domain.type,
- LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID, &tracker_handle);
- if (ret_code != LTTNG_OK) {
- goto end;
- }
-
- while (true) {
- handle_status = lttng_process_attr_tracker_handle_get_inclusion_set(
- tracker_handle, &values);
- if (handle_status ==
- LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK) {
- policy = LTTNG_TRACKING_POLICY_INCLUDE_SET;
- break;
- } else if (handle_status !=
- LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID_TRACKING_POLICY) {
- ret_code = handle_status_to_error_code(handle_status);
- goto end;
- }
-
- handle_status = lttng_process_attr_tracker_handle_get_tracking_policy(
- tracker_handle, &policy);
- if (handle_status !=
- LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK) {
- ret_code = handle_status_to_error_code(handle_status);
- goto end;
- }
-
- /* Tracking policy changed in the meantime, retry. */
- if (policy == LTTNG_TRACKING_POLICY_INCLUDE_SET) {
- continue;
- }
- break;
- }
-
- switch (policy) {
- case LTTNG_TRACKING_POLICY_INCLUDE_ALL:
- *_enabled = 0;
- goto end;
- case LTTNG_TRACKING_POLICY_EXCLUDE_ALL:
- *_enabled = 1;
- pid_count = 0;
- break;
- case LTTNG_TRACKING_POLICY_INCLUDE_SET:
- {
- const enum lttng_process_attr_values_status values_status =
- lttng_process_attr_values_get_count(
- values, &pid_count);
-
- if (values_status != LTTNG_PROCESS_ATTR_VALUES_STATUS_OK) {
- ret_code = LTTNG_ERR_UNK;
- goto end;
- }
- break;
- }
- default:
- ret_code = LTTNG_ERR_INVALID_PROTOCOL;
- goto end;
- }
-
- pid_array = zmalloc(pid_count * sizeof(int32_t));
- if (!pid_array) {
- ret_code = LTTNG_ERR_NOMEM;
- goto end;
- }
-
- /* Extract values to a raw array. */
- for (i = 0; i < pid_count; i++) {
- pid_t pid;
- const enum lttng_process_attr_values_status values_status =
- lttng_process_attr_values_get_pid_at_index(
- values, i, &pid);
-
- if (values_status != LTTNG_PROCESS_ATTR_VALUES_STATUS_OK) {
- ret_code = LTTNG_ERR_UNK;
- goto end;
- }
- pid_array[i] = (int32_t) pid;
- }
- *_nr_pids = (size_t) pid_count;
- *_pids = pid_array;
- pid_array = NULL;
-end:
- lttng_process_attr_tracker_handle_destroy(tracker_handle);
- free(pid_array);
- return ret_code == LTTNG_OK ? 0 : -ret_code;
-}
--- /dev/null
+/*
+ * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#include "lttng-ctl-helper.h"
+#include "lttng/domain.h"
+#include "lttng/lttng-error.h"
+#include <common/sessiond-comm/sessiond-comm.h>
+#include <common/tracker.h>
+#include <lttng/tracker.h>
+
+struct lttng_process_attr_tracker_handle {
+ char *session_name;
+ enum lttng_domain_type domain;
+ enum lttng_process_attr process_attr;
+ struct lttng_process_attr_values *inclusion_set;
+};
+
+void lttng_process_attr_tracker_handle_destroy(
+ struct lttng_process_attr_tracker_handle *tracker)
+{
+ if (!tracker) {
+ return;
+ }
+
+ lttng_process_attr_values_destroy(tracker->inclusion_set);
+ free(tracker->session_name);
+ free(tracker);
+}
+
+enum lttng_error_code lttng_session_get_tracker_handle(const char *session_name,
+ enum lttng_domain_type domain,
+ enum lttng_process_attr process_attr,
+ struct lttng_process_attr_tracker_handle **out_tracker_handle)
+{
+ enum lttng_error_code ret_code = LTTNG_OK;
+ struct lttng_process_attr_tracker_handle *handle = NULL;
+ enum lttng_process_attr_tracker_handle_status status;
+ enum lttng_tracking_policy policy;
+
+ if (!session_name || !out_tracker_handle) {
+ ret_code = LTTNG_ERR_INVALID;
+ goto error;
+ }
+
+ if (domain != LTTNG_DOMAIN_KERNEL && domain != LTTNG_DOMAIN_UST) {
+ ret_code = LTTNG_ERR_UNSUPPORTED_DOMAIN;
+ goto error;
+ }
+
+ handle = (lttng_process_attr_tracker_handle *) zmalloc(sizeof(*handle));
+ if (!handle) {
+ ret_code = LTTNG_ERR_NOMEM;
+ goto error;
+ }
+
+ handle->session_name = strdup(session_name);
+ if (!handle->session_name) {
+ ret_code = LTTNG_ERR_NOMEM;
+ goto error;
+ }
+
+ handle->domain = domain;
+ handle->process_attr = process_attr;
+
+ /*
+ * Use the `get_tracking_policy` command to validate the tracker's
+ * existance.
+ */
+ status = lttng_process_attr_tracker_handle_get_tracking_policy(
+ handle, &policy);
+ switch (status) {
+ case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK:
+ break;
+ case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_SESSION_DOES_NOT_EXIST:
+ ret_code = LTTNG_ERR_SESSION_NOT_EXIST;
+ goto error;
+ default:
+ ret_code = LTTNG_ERR_UNK;
+ goto error;
+ }
+
+ *out_tracker_handle = handle;
+ return ret_code;
+error:
+ lttng_process_attr_tracker_handle_destroy(handle);
+ return ret_code;
+}
+
+enum lttng_process_attr_tracker_handle_status
+lttng_process_attr_tracker_handle_get_tracking_policy(
+ const struct lttng_process_attr_tracker_handle *tracker,
+ enum lttng_tracking_policy *policy)
+{
+ void *reply = NULL;
+ int reply_ret, copy_ret;
+ enum lttng_process_attr_tracker_handle_status status =
+ LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK;
+ struct lttcomm_session_msg lsm = {
+ .cmd_type = LTTNG_PROCESS_ATTR_TRACKER_GET_POLICY,
+ };
+
+ if (!tracker || !policy) {
+ status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID;
+ goto end;
+ }
+
+ copy_ret = lttng_strncpy(lsm.session.name, tracker->session_name,
+ sizeof(lsm.session.name));
+ if (copy_ret) {
+ status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID;
+ goto end;
+ }
+
+ lsm.domain.type = tracker->domain;
+ lsm.u.process_attr_tracker_get_tracking_policy.process_attr =
+ (int32_t) tracker->process_attr;
+
+ /* Command returns a session descriptor on success. */
+ reply_ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header(
+ &lsm, NULL, 0, &reply);
+ if (reply_ret != sizeof(uint32_t)) {
+ if (reply_ret == -LTTNG_ERR_SESSION_NOT_EXIST ||
+ reply_ret == -LTTNG_ERR_SESS_NOT_FOUND) {
+ status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_SESSION_DOES_NOT_EXIST;
+ } else {
+ status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_ERROR;
+ }
+ goto end;
+ }
+
+ *policy = (enum lttng_tracking_policy)(*((const uint32_t *) reply));
+end:
+ free(reply);
+ return status;
+}
+
+enum lttng_process_attr_tracker_handle_status
+lttng_process_attr_tracker_handle_set_tracking_policy(
+ const struct lttng_process_attr_tracker_handle *tracker,
+ enum lttng_tracking_policy policy)
+{
+ int reply_ret, copy_ret;
+ enum lttng_process_attr_tracker_handle_status status =
+ LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK;
+ struct lttcomm_session_msg lsm = {
+ .cmd_type = LTTNG_PROCESS_ATTR_TRACKER_SET_POLICY,
+ };
+
+ if (!tracker) {
+ status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID;
+ goto end;
+ }
+
+ copy_ret = lttng_strncpy(lsm.session.name, tracker->session_name,
+ sizeof(lsm.session.name));
+ if (copy_ret) {
+ status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID;
+ goto end;
+ }
+
+ lsm.domain.type = tracker->domain;
+ lsm.u.process_attr_tracker_set_tracking_policy.process_attr =
+ (int32_t) tracker->process_attr;
+ lsm.u.process_attr_tracker_set_tracking_policy.tracking_policy =
+ (int32_t) policy;
+
+ /* Command returns a session descriptor on success. */
+ reply_ret = lttng_ctl_ask_sessiond(&lsm, NULL);
+ if (reply_ret < 0) {
+ if (reply_ret == -LTTNG_ERR_SESSION_NOT_EXIST) {
+ status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_SESSION_DOES_NOT_EXIST;
+ } else {
+ status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_ERROR;
+ }
+ goto end;
+ }
+end:
+ return status;
+}
+
+#define DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(command_upper, \
+ command_lower, process_attr_name, value_type_name, \
+ value_type_c, value_type_enum) \
+ enum lttng_process_attr_tracker_handle_status \
+ lttng_process_attr_##process_attr_name##_tracker_handle_##command_lower##_##value_type_name( \
+ const struct lttng_process_attr_tracker_handle \
+ *tracker, \
+ value_type_c value) \
+ { \
+ int ret; \
+ enum lttng_process_attr_tracker_handle_status status = \
+ LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK; \
+ struct lttcomm_session_msg lsm = { \
+ .cmd_type = LTTNG_PROCESS_ATTR_TRACKER_##command_upper##_INCLUDE_VALUE}; \
+ \
+ if (!tracker) { \
+ status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID; \
+ goto end; \
+ } \
+ \
+ ret = lttng_strncpy(lsm.session.name, tracker->session_name, \
+ sizeof(lsm.session.name)); \
+ if (ret) { \
+ status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID; \
+ goto end; \
+ } \
+ \
+ lsm.domain.type = tracker->domain; \
+ lsm.u.process_attr_tracker_add_remove_include_value \
+ .process_attr = \
+ (int32_t) tracker->process_attr; \
+ lsm.u.process_attr_tracker_add_remove_include_value \
+ .value_type = (uint32_t) \
+ LTTNG_PROCESS_ATTR_VALUE_TYPE_##value_type_enum; \
+ \
+ if (is_signed(value_type_c)) { \
+ lsm.u.process_attr_tracker_add_remove_include_value \
+ .integral_value.u._signed = value; \
+ } else { \
+ lsm.u.process_attr_tracker_add_remove_include_value \
+ .integral_value.u._unsigned = value; \
+ } \
+ \
+ ret = lttng_ctl_ask_sessiond(&lsm, NULL); \
+ if (ret < 0) { \
+ switch (-ret) { \
+ case LTTNG_ERR_PROCESS_ATTR_EXISTS: \
+ status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_EXISTS; \
+ break; \
+ case LTTNG_ERR_PROCESS_ATTR_MISSING: \
+ status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_MISSING; \
+ break; \
+ case LTTNG_ERR_PROCESS_ATTR_TRACKER_INVALID_TRACKING_POLICY: \
+ status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID_TRACKING_POLICY; \
+ break; \
+ default: \
+ status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_ERROR; \
+ } \
+ } \
+ end: \
+ return status; \
+ }
+
+#define DEFINE_TRACKER_ADD_REMOVE_STRING_VALUE_FUNC(command_upper, \
+ command_lower, process_attr_name, value_type_name, \
+ value_type_enum) \
+ enum lttng_process_attr_tracker_handle_status \
+ lttng_process_attr_##process_attr_name##_tracker_handle_##command_lower##_##value_type_name( \
+ const struct lttng_process_attr_tracker_handle \
+ *tracker, \
+ const char *value) \
+ { \
+ int ret; \
+ enum lttng_process_attr_tracker_handle_status status = \
+ LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK; \
+ struct lttcomm_session_msg lsm = { \
+ .cmd_type = LTTNG_PROCESS_ATTR_TRACKER_##command_upper##_INCLUDE_VALUE}; \
+ const size_t len = value ? strlen(value) + 1 : 0; \
+ \
+ if (!tracker || !value) { \
+ status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID; \
+ goto end; \
+ } \
+ \
+ ret = lttng_strncpy(lsm.session.name, tracker->session_name, \
+ sizeof(lsm.session.name)); \
+ if (ret) { \
+ status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID; \
+ goto end; \
+ } \
+ \
+ lsm.domain.type = tracker->domain; \
+ lsm.u.process_attr_tracker_add_remove_include_value \
+ .process_attr = \
+ (int32_t) tracker->process_attr; \
+ lsm.u.process_attr_tracker_add_remove_include_value.name_len = \
+ (uint32_t) len; \
+ lsm.u.process_attr_tracker_add_remove_include_value \
+ .value_type = (uint32_t) \
+ LTTNG_PROCESS_ATTR_VALUE_TYPE_##value_type_enum; \
+ \
+ ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header( \
+ &lsm, value, len, NULL); \
+ if (ret < 0) { \
+ switch (-ret) { \
+ case LTTNG_ERR_PROCESS_ATTR_EXISTS: \
+ status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_EXISTS; \
+ break; \
+ case LTTNG_ERR_PROCESS_ATTR_MISSING: \
+ status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_MISSING; \
+ break; \
+ case LTTNG_ERR_PROCESS_ATTR_TRACKER_INVALID_TRACKING_POLICY: \
+ status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID_TRACKING_POLICY; \
+ break; \
+ case LTTNG_ERR_USER_NOT_FOUND: \
+ status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_USER_NOT_FOUND; \
+ break; \
+ case LTTNG_ERR_GROUP_NOT_FOUND: \
+ status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_GROUP_NOT_FOUND; \
+ break; \
+ default: \
+ status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_ERROR; \
+ } \
+ } \
+ end: \
+ return status; \
+ }
+
+/* PID */
+DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
+ ADD, add, process_id, pid, pid_t, PID);
+DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
+ REMOVE, remove, process_id, pid, pid_t, PID);
+
+/* VPID */
+DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
+ ADD, add, virtual_process_id, pid, pid_t, PID);
+DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
+ REMOVE, remove, virtual_process_id, pid, pid_t, PID);
+
+/* UID */
+DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
+ ADD, add, user_id, uid, uid_t, UID);
+DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
+ REMOVE, remove, user_id, uid, uid_t, UID);
+DEFINE_TRACKER_ADD_REMOVE_STRING_VALUE_FUNC(
+ ADD, add, user_id, user_name, USER_NAME);
+DEFINE_TRACKER_ADD_REMOVE_STRING_VALUE_FUNC(
+ REMOVE, remove, user_id, user_name, USER_NAME);
+
+/* VUID */
+DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
+ ADD, add, virtual_user_id, uid, uid_t, UID);
+DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
+ REMOVE, remove, virtual_user_id, uid, uid_t, UID);
+DEFINE_TRACKER_ADD_REMOVE_STRING_VALUE_FUNC(
+ ADD, add, virtual_user_id, user_name, USER_NAME);
+DEFINE_TRACKER_ADD_REMOVE_STRING_VALUE_FUNC(
+ REMOVE, remove, virtual_user_id, user_name, USER_NAME);
+
+/* GID */
+DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
+ ADD, add, group_id, gid, gid_t, GID);
+DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
+ REMOVE, remove, group_id, gid, gid_t, GID);
+DEFINE_TRACKER_ADD_REMOVE_STRING_VALUE_FUNC(
+ ADD, add, group_id, group_name, GROUP_NAME);
+DEFINE_TRACKER_ADD_REMOVE_STRING_VALUE_FUNC(
+ REMOVE, remove, group_id, group_name, GROUP_NAME);
+
+/* VGID */
+DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
+ ADD, add, virtual_group_id, gid, gid_t, GID);
+DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
+ REMOVE, remove, virtual_group_id, gid, gid_t, GID);
+DEFINE_TRACKER_ADD_REMOVE_STRING_VALUE_FUNC(
+ ADD, add, virtual_group_id, group_name, GROUP_NAME);
+DEFINE_TRACKER_ADD_REMOVE_STRING_VALUE_FUNC(
+ REMOVE, remove, virtual_group_id, group_name, GROUP_NAME);
+
+enum lttng_process_attr_tracker_handle_status
+lttng_process_attr_tracker_handle_get_inclusion_set(
+ struct lttng_process_attr_tracker_handle *tracker,
+ const struct lttng_process_attr_values **values)
+{
+ char *reply = NULL;
+ int reply_ret, copy_ret;
+ enum lttng_process_attr_tracker_handle_status status =
+ LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK;
+ struct lttcomm_session_msg lsm = {
+ .cmd_type = LTTNG_PROCESS_ATTR_TRACKER_GET_INCLUSION_SET,
+ };
+ struct lttng_buffer_view inclusion_set_view;
+ ssize_t inclusion_set_ret;
+
+ if (!tracker || !values) {
+ status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID;
+ goto end;
+ }
+
+ lttng_process_attr_values_destroy(tracker->inclusion_set);
+ tracker->inclusion_set = NULL;
+
+ copy_ret = lttng_strncpy(lsm.session.name, tracker->session_name,
+ sizeof(lsm.session.name));
+ if (copy_ret) {
+ status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID;
+ goto end;
+ }
+
+ lsm.domain.type = tracker->domain;
+ lsm.u.process_attr_tracker_get_tracking_policy.process_attr =
+ (int32_t) tracker->process_attr;
+
+ /* Command returns a session descriptor on success. */
+ reply_ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header(
+ &lsm, NULL, 0, (void **) &reply);
+ if (reply_ret < 0) {
+ if (reply_ret == -LTTNG_ERR_SESSION_NOT_EXIST) {
+ status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_SESSION_DOES_NOT_EXIST;
+ } else if (reply_ret ==
+ -LTTNG_ERR_PROCESS_ATTR_TRACKER_INVALID_TRACKING_POLICY) {
+ status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID_TRACKING_POLICY;
+ } else {
+ status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_ERROR;
+ }
+ goto end;
+ } else if (reply_ret == 0) {
+ status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_COMMUNICATION_ERROR;
+ goto end;
+ }
+
+ inclusion_set_view = lttng_buffer_view_init(reply, 0, reply_ret);
+ if (!inclusion_set_view.data) {
+ status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_COMMUNICATION_ERROR;
+ goto end;
+ }
+
+ inclusion_set_ret = lttng_process_attr_values_create_from_buffer(
+ tracker->domain, tracker->process_attr,
+ &inclusion_set_view, &tracker->inclusion_set);
+ if (inclusion_set_ret < 0) {
+ status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_COMMUNICATION_ERROR;
+ goto end;
+ }
+ *values = tracker->inclusion_set;
+end:
+ free(reply);
+ return status;
+}
+
+enum lttng_process_attr_values_status lttng_process_attr_values_get_count(
+ const struct lttng_process_attr_values *values,
+ unsigned int *count)
+{
+ enum lttng_process_attr_values_status status =
+ LTTNG_PROCESS_ATTR_VALUES_STATUS_OK;
+
+ if (!values || !count) {
+ status = LTTNG_PROCESS_ATTR_VALUES_STATUS_INVALID;
+ goto end;
+ }
+
+ *count = _lttng_process_attr_values_get_count(values);
+end:
+ return status;
+}
+
+enum lttng_process_attr_value_type lttng_process_attr_values_get_type_at_index(
+ const struct lttng_process_attr_values *values,
+ unsigned int index)
+{
+ enum lttng_process_attr_value_type type;
+ const struct process_attr_value *value;
+
+ if (!values) {
+ type = LTTNG_PROCESS_ATTR_VALUE_TYPE_INVALID;
+ goto end;
+ }
+
+ if (_lttng_process_attr_values_get_count(values) <= index) {
+ type = LTTNG_PROCESS_ATTR_VALUE_TYPE_INVALID;
+ goto end;
+ }
+
+ value = lttng_process_attr_tracker_values_get_at_index(values, index);
+ type = value->type;
+end:
+ return type;
+}
+
+#define DEFINE_LTTNG_PROCESS_ATTR_VALUES_GETTER( \
+ value_type_name, value_type, expected_value_type) \
+ enum lttng_process_attr_values_status \
+ lttng_process_attr_values_get_##value_type_name##_at_index( \
+ const struct lttng_process_attr_values \
+ *values, \
+ unsigned int index, \
+ value_type *out_value) \
+ { \
+ enum lttng_process_attr_values_status status = \
+ LTTNG_PROCESS_ATTR_VALUES_STATUS_OK; \
+ const struct process_attr_value *value; \
+ \
+ if (!values) { \
+ status = LTTNG_PROCESS_ATTR_VALUES_STATUS_INVALID; \
+ goto end; \
+ } \
+ \
+ if (_lttng_process_attr_values_get_count(values) <= index) { \
+ status = LTTNG_PROCESS_ATTR_VALUES_STATUS_INVALID; \
+ goto end; \
+ } \
+ \
+ value = lttng_process_attr_tracker_values_get_at_index( \
+ values, index); \
+ if (value->type != \
+ LTTNG_PROCESS_ATTR_VALUE_TYPE_##expected_value_type) { \
+ status = LTTNG_PROCESS_ATTR_VALUES_STATUS_INVALID_TYPE; \
+ goto end; \
+ } \
+ *out_value = value->value.value_type_name; \
+ end: \
+ return status; \
+ }
+
+DEFINE_LTTNG_PROCESS_ATTR_VALUES_GETTER(pid, pid_t, PID);
+DEFINE_LTTNG_PROCESS_ATTR_VALUES_GETTER(uid, uid_t, UID);
+DEFINE_LTTNG_PROCESS_ATTR_VALUES_GETTER(gid, gid_t, GID);
+DEFINE_LTTNG_PROCESS_ATTR_VALUES_GETTER(user_name, const char *, USER_NAME);
+DEFINE_LTTNG_PROCESS_ATTR_VALUES_GETTER(group_name, const char *, GROUP_NAME);
+
+static enum lttng_error_code handle_status_to_error_code(
+ enum lttng_process_attr_tracker_handle_status handle_status)
+{
+ switch (handle_status) {
+ case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID_TRACKING_POLICY:
+ return LTTNG_ERR_INVALID;
+ case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_SESSION_DOES_NOT_EXIST:
+ return LTTNG_ERR_SESSION_NOT_EXIST;
+ case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_COMMUNICATION_ERROR:
+ return LTTNG_ERR_INVALID_PROTOCOL;
+ case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_EXISTS:
+ return LTTNG_ERR_PID_TRACKED;
+ case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_MISSING:
+ return LTTNG_ERR_PID_NOT_TRACKED;
+ case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK:
+ return LTTNG_OK;
+ case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_ERROR:
+ default:
+ /* fall-through. */
+ return LTTNG_ERR_UNK;
+ }
+}
+
+/*
+ * Add PID to session tracker.
+ * Return 0 on success else a negative LTTng error code.
+ */
+int lttng_track_pid(struct lttng_handle *handle, int pid)
+{
+ enum lttng_error_code ret_code;
+ struct lttng_process_attr_tracker_handle *tracker_handle = NULL;
+ enum lttng_process_attr_tracker_handle_status handle_status;
+ enum lttng_tracking_policy policy;
+ enum lttng_process_attr process_attr;
+
+ if (!handle) {
+ ret_code = LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ process_attr = handle->domain.type == LTTNG_DOMAIN_KERNEL ?
+ LTTNG_PROCESS_ATTR_PROCESS_ID :
+ LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID;
+
+ ret_code = lttng_session_get_tracker_handle(handle->session_name,
+ handle->domain.type,
+ process_attr, &tracker_handle);
+ if (ret_code != LTTNG_OK) {
+ goto end;
+ }
+
+ if (pid == -1) {
+ handle_status = lttng_process_attr_tracker_handle_set_tracking_policy(
+ tracker_handle,
+ LTTNG_TRACKING_POLICY_INCLUDE_ALL);
+ ret_code = handle_status_to_error_code(handle_status);
+ goto end;
+ }
+
+ handle_status = lttng_process_attr_tracker_handle_get_tracking_policy(
+ tracker_handle, &policy);
+ if (handle_status != LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK) {
+ ret_code = handle_status_to_error_code(handle_status);
+ goto end;
+ }
+
+ if (policy != LTTNG_TRACKING_POLICY_INCLUDE_SET) {
+ handle_status = lttng_process_attr_tracker_handle_set_tracking_policy(
+ tracker_handle,
+ LTTNG_TRACKING_POLICY_INCLUDE_SET);
+ if (handle_status != LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK) {
+ ret_code = handle_status_to_error_code(handle_status);
+ goto end;
+ }
+ }
+
+ handle_status = process_attr == LTTNG_PROCESS_ATTR_PROCESS_ID ?
+ lttng_process_attr_process_id_tracker_handle_add_pid(
+ tracker_handle,
+ (pid_t) pid) :
+ lttng_process_attr_virtual_process_id_tracker_handle_add_pid(
+ tracker_handle,
+ (pid_t) pid);
+ ret_code = handle_status_to_error_code(handle_status);
+end:
+ lttng_process_attr_tracker_handle_destroy(tracker_handle);
+ return ret_code == LTTNG_OK ? 0 : -ret_code;
+}
+
+/*
+ * Remove PID from session tracker.
+ * Return 0 on success else a negative LTTng error code.
+ */
+int lttng_untrack_pid(struct lttng_handle *handle, int pid)
+{
+ enum lttng_error_code ret_code;
+ struct lttng_process_attr_tracker_handle *tracker_handle = NULL;
+ enum lttng_process_attr_tracker_handle_status handle_status;
+ enum lttng_tracking_policy policy;
+ enum lttng_process_attr process_attr;
+
+ if (!handle) {
+ ret_code = LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ process_attr = handle->domain.type == LTTNG_DOMAIN_KERNEL ?
+ LTTNG_PROCESS_ATTR_PROCESS_ID :
+ LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID;
+ ret_code = lttng_session_get_tracker_handle(handle->session_name,
+ handle->domain.type, process_attr, &tracker_handle);
+ if (ret_code != LTTNG_OK) {
+ goto end;
+ }
+
+ if (pid == -1) {
+ handle_status = lttng_process_attr_tracker_handle_set_tracking_policy(
+ tracker_handle,
+ LTTNG_TRACKING_POLICY_EXCLUDE_ALL);
+ ret_code = handle_status_to_error_code(handle_status);
+ goto end;
+ }
+
+ handle_status = lttng_process_attr_tracker_handle_get_tracking_policy(
+ tracker_handle, &policy);
+ if (handle_status != LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK) {
+ ret_code = handle_status_to_error_code(handle_status);
+ goto end;
+ }
+
+ if (policy == LTTNG_TRACKING_POLICY_EXCLUDE_ALL) {
+ ret_code = LTTNG_ERR_PID_NOT_TRACKED;
+ goto end;
+ } else if (policy == LTTNG_TRACKING_POLICY_INCLUDE_ALL) {
+ ret_code = LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ handle_status = process_attr == LTTNG_PROCESS_ATTR_PROCESS_ID ?
+ lttng_process_attr_process_id_tracker_handle_remove_pid(
+ tracker_handle,
+ (pid_t) pid) :
+ lttng_process_attr_virtual_process_id_tracker_handle_remove_pid(
+ tracker_handle,
+ (pid_t) pid);
+ if (handle_status == LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID_TRACKING_POLICY) {
+ ret_code = LTTNG_ERR_PID_NOT_TRACKED;
+ }
+end:
+ lttng_process_attr_tracker_handle_destroy(tracker_handle);
+ return ret_code == LTTNG_OK ? 0 : -ret_code;
+}
+
+/*
+ * List PIDs in the tracker.
+ *
+ * enabled is set to whether the PID tracker is enabled.
+ * pids is set to an allocated array of PIDs currently tracked. On
+ * success, pids must be freed by the caller.
+ * nr_pids is set to the number of entries contained by the pids array.
+ *
+ * Returns 0 on success, else a negative LTTng error code.
+ */
+int lttng_list_tracker_pids(struct lttng_handle *handle,
+ int *_enabled,
+ int32_t **_pids,
+ size_t *_nr_pids)
+{
+ enum lttng_error_code ret_code;
+ struct lttng_process_attr_tracker_handle *tracker_handle = NULL;
+ enum lttng_process_attr_tracker_handle_status handle_status;
+ const struct lttng_process_attr_values *values;
+ enum lttng_tracking_policy policy;
+ unsigned int pid_count, i;
+ int32_t *pid_array = NULL;
+
+ if (!handle || !_enabled || !_pids || !_nr_pids) {
+ ret_code = LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ ret_code = lttng_session_get_tracker_handle(handle->session_name,
+ handle->domain.type,
+ LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID, &tracker_handle);
+ if (ret_code != LTTNG_OK) {
+ goto end;
+ }
+
+ while (true) {
+ handle_status = lttng_process_attr_tracker_handle_get_inclusion_set(
+ tracker_handle, &values);
+ if (handle_status ==
+ LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK) {
+ policy = LTTNG_TRACKING_POLICY_INCLUDE_SET;
+ break;
+ } else if (handle_status !=
+ LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID_TRACKING_POLICY) {
+ ret_code = handle_status_to_error_code(handle_status);
+ goto end;
+ }
+
+ handle_status = lttng_process_attr_tracker_handle_get_tracking_policy(
+ tracker_handle, &policy);
+ if (handle_status !=
+ LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK) {
+ ret_code = handle_status_to_error_code(handle_status);
+ goto end;
+ }
+
+ /* Tracking policy changed in the meantime, retry. */
+ if (policy == LTTNG_TRACKING_POLICY_INCLUDE_SET) {
+ continue;
+ }
+ break;
+ }
+
+ switch (policy) {
+ case LTTNG_TRACKING_POLICY_INCLUDE_ALL:
+ *_enabled = 0;
+ goto end;
+ case LTTNG_TRACKING_POLICY_EXCLUDE_ALL:
+ *_enabled = 1;
+ pid_count = 0;
+ break;
+ case LTTNG_TRACKING_POLICY_INCLUDE_SET:
+ {
+ const enum lttng_process_attr_values_status values_status =
+ lttng_process_attr_values_get_count(
+ values, &pid_count);
+
+ if (values_status != LTTNG_PROCESS_ATTR_VALUES_STATUS_OK) {
+ ret_code = LTTNG_ERR_UNK;
+ goto end;
+ }
+ break;
+ }
+ default:
+ ret_code = LTTNG_ERR_INVALID_PROTOCOL;
+ goto end;
+ }
+
+ pid_array = (int32_t *) zmalloc(pid_count * sizeof(int32_t));
+ if (!pid_array) {
+ ret_code = LTTNG_ERR_NOMEM;
+ goto end;
+ }
+
+ /* Extract values to a raw array. */
+ for (i = 0; i < pid_count; i++) {
+ pid_t pid;
+ const enum lttng_process_attr_values_status values_status =
+ lttng_process_attr_values_get_pid_at_index(
+ values, i, &pid);
+
+ if (values_status != LTTNG_PROCESS_ATTR_VALUES_STATUS_OK) {
+ ret_code = LTTNG_ERR_UNK;
+ goto end;
+ }
+ pid_array[i] = (int32_t) pid;
+ }
+ *_nr_pids = (size_t) pid_count;
+ *_pids = pid_array;
+ pid_array = NULL;
+end:
+ lttng_process_attr_tracker_handle_destroy(tracker_handle);
+ free(pid_array);
+ return ret_code == LTTNG_OK ? 0 : -ret_code;
+}
*
*/
+#include <lttng/lttng-export.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
/* Session daemon */
-int __testpoint_sessiond_thread_manage_clients(void);
+LTTNG_EXPORT int __testpoint_sessiond_thread_manage_clients(void);
int __testpoint_sessiond_thread_manage_clients(void)
{
const char *var = "LTTNG_SESSIOND_THREAD_MANAGE_CLIENTS_TP_FAIL";
return 0;
}
-int __testpoint_sessiond_thread_registration_apps(void);
+LTTNG_EXPORT int __testpoint_sessiond_thread_registration_apps(void);
int __testpoint_sessiond_thread_registration_apps(void)
{
const char *var = "LTTNG_SESSIOND_THREAD_REG_APPS_TP_FAIL";
return 0;
}
-int __testpoint_sessiond_thread_manage_apps(void);
+LTTNG_EXPORT int __testpoint_sessiond_thread_manage_apps(void);
int __testpoint_sessiond_thread_manage_apps(void)
{
const char *var = "LTTNG_SESSIOND_THREAD_MANAGE_APPS_TP_FAIL";
return 0;
}
-int __testpoint_sessiond_thread_manage_kernel(void);
+LTTNG_EXPORT int __testpoint_sessiond_thread_manage_kernel(void);
int __testpoint_sessiond_thread_manage_kernel(void)
{
const char *var = "LTTNG_SESSIOND_THREAD_MANAGE_KERNEL_TP_FAIL";
return 0;
}
-int __testpoint_sessiond_thread_manage_consumer(void);
+LTTNG_EXPORT int __testpoint_sessiond_thread_manage_consumer(void);
int __testpoint_sessiond_thread_manage_consumer(void)
{
const char *var = "LTTNG_SESSIOND_THREAD_MANAGE_CONSUMER_TP_FAIL";
return 0;
}
-int __testpoint_sessiond_thread_ht_cleanup(void);
+LTTNG_EXPORT int __testpoint_sessiond_thread_ht_cleanup(void);
int __testpoint_sessiond_thread_ht_cleanup(void)
{
const char *var = "LTTNG_SESSIOND_THREAD_HT_CLEANUP_TP_FAIL";
return 0;
}
-int __testpoint_sessiond_thread_app_manage_notify(void);
+LTTNG_EXPORT int __testpoint_sessiond_thread_app_manage_notify(void);
int __testpoint_sessiond_thread_app_manage_notify(void)
{
const char *var = "LTTNG_SESSIOND_THREAD_APP_MANAGE_NOTIFY_TP_FAIL";
return 0;
}
-int __testpoint_sessiond_thread_app_reg_dispatch(void);
+LTTNG_EXPORT int __testpoint_sessiond_thread_app_reg_dispatch(void);
int __testpoint_sessiond_thread_app_reg_dispatch(void)
{
const char *var = "LTTNG_SESSIOND_THREAD_APP_REG_DISPATCH_TP_FAIL";
/* Consumer daemon */
-int __testpoint_consumerd_thread_channel(void);
+LTTNG_EXPORT int __testpoint_consumerd_thread_channel(void);
int __testpoint_consumerd_thread_channel(void)
{
const char *var = "LTTNG_CONSUMERD_THREAD_CHANNEL_TP_FAIL";
return 0;
}
-int __testpoint_consumerd_thread_metadata(void);
+LTTNG_EXPORT int __testpoint_consumerd_thread_metadata(void);
int __testpoint_consumerd_thread_metadata(void)
{
const char *var = "LTTNG_CONSUMERD_THREAD_METADATA_TP_FAIL";
return 0;
}
-int __testpoint_consumerd_thread_data(void);
+LTTNG_EXPORT int __testpoint_consumerd_thread_data(void);
int __testpoint_consumerd_thread_data(void)
{
const char *var = "LTTNG_CONSUMERD_THREAD_DATA_TP_FAIL";
return 0;
}
-int __testpoint_consumerd_thread_sessiond(void);
+LTTNG_EXPORT int __testpoint_consumerd_thread_sessiond(void);
int __testpoint_consumerd_thread_sessiond(void)
{
const char *var = "LTTNG_CONSUMERD_THREAD_SESSIOND_TP_FAIL";
return 0;
}
-int __testpoint_consumerd_thread_metadata_timer(void);
+LTTNG_EXPORT int __testpoint_consumerd_thread_metadata_timer(void);
int __testpoint_consumerd_thread_metadata_timer(void)
{
const char *var = "LTTNG_CONSUMERD_THREAD_METADATA_TIMER_TP_FAIL";
/* Relay daemon */
-int __testpoint_relayd_thread_dispatcher(void);
+LTTNG_EXPORT int __testpoint_relayd_thread_dispatcher(void);
int __testpoint_relayd_thread_dispatcher(void)
{
const char *var = "LTTNG_RELAYD_THREAD_DISPATCHER_TP_FAIL";
return 0;
}
-int __testpoint_relayd_thread_worker(void);
+LTTNG_EXPORT int __testpoint_relayd_thread_worker(void);
int __testpoint_relayd_thread_worker(void)
{
const char *var = "LTTNG_RELAYD_THREAD_WORKER_TP_FAIL";
return 0;
}
-int __testpoint_relayd_thread_listener(void);
+LTTNG_EXPORT int __testpoint_relayd_thread_listener(void);
int __testpoint_relayd_thread_listener(void)
{
const char *var = "LTTNG_RELAYD_THREAD_LISTENER_TP_FAIL";
return 0;
}
-int __testpoint_relayd_thread_live_dispatcher(void);
+LTTNG_EXPORT int __testpoint_relayd_thread_live_dispatcher(void);
int __testpoint_relayd_thread_live_dispatcher(void)
{
const char *var = "LTTNG_RELAYD_THREAD_LIVE_DISPATCHER_TP_FAIL";
return 0;
}
-int __testpoint_relayd_thread_live_worker(void);
+LTTNG_EXPORT int __testpoint_relayd_thread_live_worker(void);
int __testpoint_relayd_thread_live_worker(void)
{
const char *var = "LTTNG_RELAYD_THREAD_LIVE_WORKER_TP_FAIL";
return 0;
}
-int __testpoint_relayd_thread_live_listener(void);
+LTTNG_EXPORT int __testpoint_relayd_thread_live_listener(void);
int __testpoint_relayd_thread_live_listener(void)
{
const char *var = "LTTNG_RELAYD_THREAD_LIVE_LISTENER_TP_FAIL";
*
*/
+#include <lttng/lttng-export.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
/* Session daemon */
-int __testpoint_sessiond_thread_manage_clients(void);
+LTTNG_EXPORT int __testpoint_sessiond_thread_manage_clients(void);
int __testpoint_sessiond_thread_manage_clients(void)
{
const char *var = "LTTNG_SESSIOND_THREAD_MANAGE_CLIENTS_STALL";
return 0;
}
-int __testpoint_sessiond_thread_registration_apps(void);
+LTTNG_EXPORT int __testpoint_sessiond_thread_registration_apps(void);
int __testpoint_sessiond_thread_registration_apps(void)
{
const char *var = "LTTNG_SESSIOND_THREAD_REG_APPS_STALL";
return 0;
}
-int __testpoint_sessiond_thread_manage_apps(void);
+LTTNG_EXPORT int __testpoint_sessiond_thread_manage_apps(void);
int __testpoint_sessiond_thread_manage_apps(void)
{
const char *var = "LTTNG_SESSIOND_THREAD_MANAGE_APPS_STALL";
return 0;
}
-int __testpoint_sessiond_thread_manage_kernel(void);
+LTTNG_EXPORT int __testpoint_sessiond_thread_manage_kernel(void);
int __testpoint_sessiond_thread_manage_kernel(void)
{
const char *var = "LTTNG_SESSIOND_THREAD_MANAGE_KERNEL_STALL";
return 0;
}
-int __testpoint_sessiond_thread_manage_consumer(void);
+LTTNG_EXPORT int __testpoint_sessiond_thread_manage_consumer(void);
int __testpoint_sessiond_thread_manage_consumer(void)
{
const char *var = "LTTNG_SESSIOND_THREAD_MANAGE_CONSUMER_STALL";
return 0;
}
-int __testpoint_sessiond_thread_ht_cleanup(void);
+LTTNG_EXPORT int __testpoint_sessiond_thread_ht_cleanup(void);
int __testpoint_sessiond_thread_ht_cleanup(void)
{
const char *var = "LTTNG_SESSIOND_THREAD_HT_CLEANUP_STALL";
return 0;
}
-int __testpoint_sessiond_thread_app_manage_notify(void);
+LTTNG_EXPORT int __testpoint_sessiond_thread_app_manage_notify(void);
int __testpoint_sessiond_thread_app_manage_notify(void)
{
const char *var = "LTTNG_SESSIOND_THREAD_APP_MANAGE_NOTIFY_STALL";
return 0;
}
-int __testpoint_sessiond_thread_app_reg_dispatch(void);
+LTTNG_EXPORT int __testpoint_sessiond_thread_app_reg_dispatch(void);
int __testpoint_sessiond_thread_app_reg_dispatch(void)
{
const char *var = "LTTNG_SESSIOND_THREAD_APP_REG_DISPATCH_STALL";
/* Consumer daemon */
-int __testpoint_consumerd_thread_channel(void);
+LTTNG_EXPORT int __testpoint_consumerd_thread_channel(void);
int __testpoint_consumerd_thread_channel(void)
{
const char *var = "LTTNG_CONSUMERD_THREAD_CHANNEL_STALL";
return 0;
}
-int __testpoint_consumerd_thread_metadata(void);
+LTTNG_EXPORT int __testpoint_consumerd_thread_metadata(void);
int __testpoint_consumerd_thread_metadata(void)
{
const char *var = "LTTNG_CONSUMERD_THREAD_METADATA_STALL";
return 0;
}
-int __testpoint_consumerd_thread_data(void);
+LTTNG_EXPORT int __testpoint_consumerd_thread_data(void);
int __testpoint_consumerd_thread_data(void)
{
const char *var = "LTTNG_CONSUMERD_THREAD_DATA_STALL";
return 0;
}
-int __testpoint_consumerd_thread_sessiond(void);
+LTTNG_EXPORT int __testpoint_consumerd_thread_sessiond(void);
int __testpoint_consumerd_thread_sessiond(void)
{
const char *var = "LTTNG_CONSUMERD_THREAD_SESSIOND_STALL";
return 0;
}
-int __testpoint_consumerd_thread_metadata_timer(void);
+LTTNG_EXPORT int __testpoint_consumerd_thread_metadata_timer(void);
int __testpoint_consumerd_thread_metadata_timer(void)
{
const char *var = "LTTNG_CONSUMERD_THREAD_METADATA_TIMER_STALL";
/* Relay daemon */
-int __testpoint_relayd_thread_dispatcher(void);
+LTTNG_EXPORT int __testpoint_relayd_thread_dispatcher(void);
int __testpoint_relayd_thread_dispatcher(void)
{
const char *var = "LTTNG_RELAYD_THREAD_DISPATCHER_STALL";
return 0;
}
-int __testpoint_relayd_thread_worker(void);
+LTTNG_EXPORT int __testpoint_relayd_thread_worker(void);
int __testpoint_relayd_thread_worker(void)
{
const char *var = "LTTNG_RELAYD_THREAD_WORKER_STALL";
return 0;
}
-int __testpoint_relayd_thread_listener(void);
+LTTNG_EXPORT int __testpoint_relayd_thread_listener(void);
int __testpoint_relayd_thread_listener(void)
{
const char *var = "LTTNG_RELAYD_THREAD_LISTENER_STALL";
return 0;
}
-int __testpoint_relayd_thread_live_dispatcher(void);
+LTTNG_EXPORT int __testpoint_relayd_thread_live_dispatcher(void);
int __testpoint_relayd_thread_live_dispatcher(void)
{
const char *var = "LTTNG_RELAYD_THREAD_LIVE_DISPATCHER_STALL";
return 0;
}
-int __testpoint_relayd_thread_live_worker(void);
+LTTNG_EXPORT int __testpoint_relayd_thread_live_worker(void);
int __testpoint_relayd_thread_live_worker(void)
{
const char *var = "LTTNG_RELAYD_THREAD_LIVE_WORKER_STALL";
return 0;
}
-int __testpoint_relayd_thread_live_listener(void);
+LTTNG_EXPORT int __testpoint_relayd_thread_live_listener(void);
int __testpoint_relayd_thread_live_listener(void)
{
const char *var = "LTTNG_RELAYD_THREAD_LIVE_LISTENER_STALL";
#define mmap_size 524288
#ifdef HAVE_LIBLTTNG_UST_CTL
+#include <lttng/lttng-export.h>
#include <lttng/ust-sigbus.h>
-DEFINE_LTTNG_UST_SIGBUS_STATE();
+LTTNG_EXPORT DEFINE_LTTNG_UST_SIGBUS_STATE();
#endif
static int control_sock;
#include <unistd.h>
#include <stdbool.h>
#include <lttng/constant.h>
+#include <lttng/lttng-export.h>
#include <fcntl.h>
#include <dlfcn.h>
#include <stdio.h>
* thread to create a named pipe/FIFO which a test application can use to either
* pause or resume the consumption of data.
*/
-int __testpoint_consumerd_thread_data(void);
+LTTNG_EXPORT int __testpoint_consumerd_thread_data(void);
int __testpoint_consumerd_thread_data(void)
{
int ret = 0;
return ret;
}
-int __testpoint_consumerd_thread_data_poll(void);
+LTTNG_EXPORT int __testpoint_consumerd_thread_data_poll(void);
int __testpoint_consumerd_thread_data_poll(void)
{
int ret = 0;
#include <unistd.h>
#include <stdbool.h>
#include <lttng/constant.h>
+#include <lttng/lttng-export.h>
#include <fcntl.h>
#include <dlfcn.h>
#include <stdio.h>
lttng_pipe_destroy(pause_pipe);
}
-int __testpoint_sessiond_thread_notification(void);
+LTTNG_EXPORT int __testpoint_sessiond_thread_notification(void);
int __testpoint_sessiond_thread_notification(void)
{
int ret = 0;
return ret;
}
-int __testpoint_sessiond_handle_notifier_event_pipe(void);
+LTTNG_EXPORT int __testpoint_sessiond_handle_notifier_event_pipe(void);
int __testpoint_sessiond_handle_notifier_event_pipe(void)
{
int ret = 0;
#include <common/compat/time.h>
#include <string.h>
#include <stdio.h>
+#include <lttng/lttng-export.h>
#include <lttng/ust-clock.h>
static
return "Freeze time with 1KHz for regression test";
}
-void lttng_ust_clock_plugin_init(void);
+LTTNG_EXPORT void lttng_ust_clock_plugin_init(void);
void lttng_ust_clock_plugin_init(void)
{
int ret;
#include <string.h>
#include <stdio.h>
#include <unistd.h>
+#include <lttng/lttng-export.h>
#include <lttng/ust-getcpu.h>
static long nprocessors;
return ret;
}
-void lttng_ust_getcpu_plugin_init(void);
+LTTNG_EXPORT void lttng_ust_getcpu_plugin_init(void);
void lttng_ust_getcpu_plugin_init(void)
{
int ret;
#ifndef CALLSITES_H
#define CALLSITES_H
-void call_tracepoint(void);
+
+#include <lttng/lttng-export.h>
+
+LTTNG_EXPORT void call_tracepoint(void);
+
#endif /* CALLSITES_H */
#ifndef _LIBBAR_H
#define _LIBBAR_H
-int bar(void);
+#include <lttng/lttng-export.h>
+
+LTTNG_EXPORT int bar(void);
#endif /* _LIBBAR_H */
#ifndef _LIBFOO_H
#define _LIBFOO_H
-int foo(void);
+#include <lttng/lttng-export.h>
+
+LTTNG_EXPORT int foo(void);
#endif /* _LIBFOO_H */
#define NUM_TESTS 11
#ifdef HAVE_LIBLTTNG_UST_CTL
+#include <lttng/lttng-export.h>
#include <lttng/ust-sigbus.h>
-DEFINE_LTTNG_UST_SIGBUS_STATE();
+LTTNG_EXPORT DEFINE_LTTNG_UST_SIGBUS_STATE();
#endif
static const char alphanum[] =
/* Number of TAP tests in this file */
#define NUM_TESTS 16
-DEFINE_LTTNG_UST_SIGBUS_STATE();
+LTTNG_EXPORT DEFINE_LTTNG_UST_SIGBUS_STATE();
static const char alphanum[] =
"0123456789"
*
*/
+#include <lttng/lttng-export.h>
#include <lttng/ust-sigbus.h>
-DEFINE_LTTNG_UST_SIGBUS_STATE();
+LTTNG_EXPORT DEFINE_LTTNG_UST_SIGBUS_STATE();
*
*/
-int dynamic_symbol(int a);
+#include <lttng/lttng-export.h>
+
+LTTNG_EXPORT int dynamic_symbol(int a);