From: Simon Marchi Date: Wed, 6 Oct 2021 16:15:33 +0000 (-0400) Subject: lib: compile liblttng-ctl as C++ X-Git-Url: https://git.lttng.org./?a=commitdiff_plain;h=4bd69c5f1161cd065f487da0f4c1aa03a73c47e4;p=lttng-tools.git lib: compile liblttng-ctl as C++ Same as the previous commits, but compile the liblttng-ctl library as C++ code (while still offering a C interface). Some exported global variables (for example in deprecated-symbols.cpp) have to be made non-const, otherwise we get: CXX deprecated-symbols.lo /home/simark/src/lttng-tools/src/lib/lttng-ctl/deprecated-symbols.cpp:21:33: error: ‘visibility’ attribute ignored [-Werror=attributes] 21 | LTTNG_EXPORT const char * const config_element_pid_tracker; | ^~~~~~~~~~~~~~~~~~~~~~~~~~ I think this is related to the fact that const global variables automatically have internal linkage in C++. Despite using -export-symbols in src/lib/lttng-ctl/Makefile.am, some new ELF symbols become exposed. It could be related to this, in the ld man page: --retain-symbols-file does not discard undefined symbols, or symbols needed for relocations. One new symbol I see, for example, is `_Z16connect_sessiondv`. Looking at liblttng-ctl.so, I indeed see a relocation for this symbol: 000000000010b778 0000053e00000007 R_X86_64_JUMP_SLOT 00000000000314a2 _Z16connect_sessiondv + 0 And that would explain why the linker keeps that symbol visible. This is related to the entry for this function in the procedure linkage table. I'm not entirely sure why these functions didn't generate a PLT entry in C, but do in C++. To avoid these new symbols, build everything with -fvisibility=hidden and -fvisibility-inlines-hidden, and tag functions we really want to export with LTTNG_EXPORT, a new macro defined to __attribute__((visibility("default"))). This macro is publicly visible, because it has to be used in distributed header files (although it's of no use for users of liblttng-ctl). Change-Id: Ie51bf0a2edfb87e5f46f9c39eed5309d9f8c41d6 Signed-off-by: Simon Marchi Signed-off-by: Jérémie Galarneau --- diff --git a/configure.ac b/configure.ac index e6b0d8e5a..abb61d27f 100644 --- a/configure.ac +++ b/configure.ac @@ -1085,10 +1085,10 @@ AM_CONDITIONAL([BUILD_LIB_SESSIOND_COMM], [test x$build_lib_sessiond_comm = xyes 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 += ...". diff --git a/include/Makefile.am b/include/Makefile.am index 12c5f883c..6fe724b3a 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -115,6 +115,7 @@ lttnginclude_HEADERS = \ 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 \ diff --git a/include/lttng/action/action.h b/include/lttng/action/action.h index cd3857d72..70237e43c 100644 --- a/include/lttng/action/action.h +++ b/include/lttng/action/action.h @@ -8,6 +8,8 @@ #ifndef LTTNG_ACTION_H #define LTTNG_ACTION_H +#include + struct lttng_action; #ifdef __cplusplus @@ -37,13 +39,13 @@ enum lttng_action_status { * * 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 } diff --git a/include/lttng/action/list.h b/include/lttng/action/list.h index ca871744d..9c23d60ca 100644 --- a/include/lttng/action/list.h +++ b/include/lttng/action/list.h @@ -8,6 +8,8 @@ #ifndef LTTNG_ACTION_LIST_H #define LTTNG_ACTION_LIST_H +#include + struct lttng_action; #ifdef __cplusplus @@ -20,7 +22,7 @@ extern "C" { * 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. @@ -31,13 +33,13 @@ extern struct lttng_action *lttng_action_list_create(void); * * 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); /* @@ -49,7 +51,7 @@ extern enum lttng_action_status lttng_action_list_get_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); diff --git a/include/lttng/action/notify.h b/include/lttng/action/notify.h index 08574753f..3aa55e09c 100644 --- a/include/lttng/action/notify.h +++ b/include/lttng/action/notify.h @@ -8,6 +8,8 @@ #ifndef LTTNG_ACTION_NOTIFY_H #define LTTNG_ACTION_NOTIFY_H +#include + struct lttng_action; struct lttng_rate_policy; @@ -28,7 +30,7 @@ extern "C" { * 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. @@ -37,7 +39,7 @@ extern struct lttng_action *lttng_action_notify_create(void); * 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); @@ -47,7 +49,7 @@ extern enum lttng_action_status lttng_action_notify_set_rate_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); diff --git a/include/lttng/action/path.h b/include/lttng/action/path.h index 507b4ab49..6ec91676b 100644 --- a/include/lttng/action/path.h +++ b/include/lttng/action/path.h @@ -8,6 +8,7 @@ #ifndef LTTNG_ACTION_PATH_H #define LTTNG_ACTION_PATH_H +#include #include #include @@ -44,19 +45,19 @@ enum lttng_action_path_status { * * 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); @@ -64,7 +65,7 @@ extern enum lttng_action_path_status lttng_action_path_get_index_at_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 } diff --git a/include/lttng/action/rate-policy.h b/include/lttng/action/rate-policy.h index a3a288a28..1cd0126e3 100644 --- a/include/lttng/action/rate-policy.h +++ b/include/lttng/action/rate-policy.h @@ -9,6 +9,7 @@ #define LTTNG_RATE_POLICY_H #include +#include #include struct lttng_rate_policy; @@ -36,7 +37,7 @@ enum lttng_rate_policy_type { /* * 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); /* @@ -49,7 +50,7 @@ extern enum lttng_rate_policy_type lttng_rate_policy_get_type( * 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); /* @@ -59,7 +60,7 @@ extern struct lttng_rate_policy *lttng_rate_policy_every_n_create( * 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); /* @@ -73,7 +74,7 @@ extern enum lttng_rate_policy_status lttng_rate_policy_every_n_get_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); /* @@ -83,14 +84,14 @@ extern struct lttng_rate_policy *lttng_rate_policy_once_after_n_create( * 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 } diff --git a/include/lttng/action/rotate-session.h b/include/lttng/action/rotate-session.h index 7fbcce98c..199b6f169 100644 --- a/include/lttng/action/rotate-session.h +++ b/include/lttng/action/rotate-session.h @@ -8,6 +8,8 @@ #ifndef LTTNG_ACTION_ROTATE_SESSION_H #define LTTNG_ACTION_ROTATE_SESSION_H +#include + struct lttng_action; struct lttng_rate_policy; @@ -25,20 +27,20 @@ extern "C" { * 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); /* @@ -48,7 +50,7 @@ extern enum lttng_action_status lttng_action_rotate_session_get_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); @@ -58,7 +60,7 @@ extern enum lttng_action_status lttng_action_rotate_session_set_rate_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); diff --git a/include/lttng/action/snapshot-session.h b/include/lttng/action/snapshot-session.h index faa9b9fab..859086200 100644 --- a/include/lttng/action/snapshot-session.h +++ b/include/lttng/action/snapshot-session.h @@ -8,6 +8,8 @@ #ifndef LTTNG_ACTION_SNAPSHOT_SESSION_H #define LTTNG_ACTION_SNAPSHOT_SESSION_H +#include + #ifdef __cplusplus extern "C" { #endif @@ -26,20 +28,20 @@ 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_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); /* @@ -50,14 +52,14 @@ extern enum lttng_action_status lttng_action_snapshot_session_get_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); @@ -68,7 +70,7 @@ extern enum lttng_action_status lttng_action_snapshot_session_get_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); @@ -78,7 +80,7 @@ extern enum lttng_action_status lttng_action_snapshot_session_set_rate_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); diff --git a/include/lttng/action/start-session.h b/include/lttng/action/start-session.h index c63a7d278..db5200032 100644 --- a/include/lttng/action/start-session.h +++ b/include/lttng/action/start-session.h @@ -8,6 +8,8 @@ #ifndef LTTNG_ACTION_START_SESSION_H #define LTTNG_ACTION_START_SESSION_H +#include + struct lttng_action; struct lttng_rate_policy; @@ -25,20 +27,20 @@ extern "C" { * 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); /* @@ -48,7 +50,7 @@ extern enum lttng_action_status lttng_action_start_session_get_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); @@ -58,7 +60,7 @@ extern enum lttng_action_status lttng_action_start_session_set_rate_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); diff --git a/include/lttng/action/stop-session.h b/include/lttng/action/stop-session.h index dbe6819e6..5b223ef23 100644 --- a/include/lttng/action/stop-session.h +++ b/include/lttng/action/stop-session.h @@ -8,6 +8,8 @@ #ifndef LTTNG_ACTION_STOP_SESSION_H #define LTTNG_ACTION_STOP_SESSION_H +#include + struct lttng_action; struct lttng_rate_policy; @@ -25,20 +27,20 @@ extern "C" { * 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); /* @@ -48,7 +50,7 @@ extern enum lttng_action_status lttng_action_stop_session_get_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); @@ -58,7 +60,7 @@ extern enum lttng_action_status lttng_action_stop_session_set_rate_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); diff --git a/include/lttng/channel.h b/include/lttng/channel.h index f3241ed30..62e202d26 100644 --- a/include/lttng/channel.h +++ b/include/lttng/channel.h @@ -10,6 +10,7 @@ #include #include +#include #include #ifdef __cplusplus @@ -60,11 +61,11 @@ struct lttng_channel { /* */ -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. @@ -74,7 +75,7 @@ extern void lttng_channel_destroy(struct lttng_channel *channel); * 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); /* @@ -84,7 +85,7 @@ extern int lttng_list_channels(struct lttng_handle *handle, * * 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); /* @@ -94,7 +95,7 @@ extern int lttng_enable_channel(struct lttng_handle *handle, * * 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); /* @@ -103,7 +104,7 @@ extern int lttng_disable_channel(struct lttng_handle *handle, * * 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); /* @@ -111,7 +112,7 @@ extern void lttng_channel_set_default_attr(struct lttng_domain *domain, * * 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); /* @@ -119,19 +120,19 @@ extern int lttng_channel_get_discarded_event_count(struct lttng_channel *chan, * * 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 diff --git a/include/lttng/clear-handle.h b/include/lttng/clear-handle.h index 4d952ce3d..e07e6c47f 100644 --- a/include/lttng/clear-handle.h +++ b/include/lttng/clear-handle.h @@ -10,6 +10,7 @@ #define LTTNG_CLEAR_HANDLE_H #include +#include #ifdef __cplusplus extern "C" { @@ -36,7 +37,7 @@ enum lttng_clear_handle_status { * 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. @@ -52,7 +53,7 @@ extern void lttng_clear_handle_destroy(struct lttng_clear_handle *handle); * 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); @@ -71,7 +72,7 @@ extern enum lttng_clear_handle_status * 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); diff --git a/include/lttng/clear.h b/include/lttng/clear.h index b656db9f4..5dfd5db58 100644 --- a/include/lttng/clear.h +++ b/include/lttng/clear.h @@ -10,6 +10,7 @@ #define LTTNG_CLEAR_H #include +#include #ifdef __cplusplus extern "C" { @@ -54,7 +55,7 @@ struct lttng_clear_handle; * 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 } diff --git a/include/lttng/condition/buffer-usage.h b/include/lttng/condition/buffer-usage.h index 0bcf4c7a6..dcdb7ca1f 100644 --- a/include/lttng/condition/buffer-usage.h +++ b/include/lttng/condition/buffer-usage.h @@ -12,6 +12,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { @@ -56,7 +57,7 @@ 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); /* @@ -72,7 +73,7 @@ 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); /* @@ -87,7 +88,7 @@ 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); @@ -103,7 +104,7 @@ lttng_condition_buffer_usage_get_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); @@ -119,7 +120,7 @@ lttng_condition_buffer_usage_set_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); @@ -133,7 +134,7 @@ lttng_condition_buffer_usage_get_threshold( * 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); @@ -150,7 +151,7 @@ lttng_condition_buffer_usage_set_threshold( * 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); @@ -163,7 +164,7 @@ lttng_condition_buffer_usage_get_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); @@ -180,7 +181,7 @@ lttng_condition_buffer_usage_set_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); @@ -193,7 +194,7 @@ lttng_condition_buffer_usage_get_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); @@ -206,7 +207,7 @@ lttng_condition_buffer_usage_set_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); @@ -217,7 +218,7 @@ lttng_condition_buffer_usage_get_domain_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); @@ -240,7 +241,7 @@ lttng_condition_buffer_usage_set_domain_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); @@ -251,7 +252,7 @@ lttng_evaluation_buffer_usage_get_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); diff --git a/include/lttng/condition/condition.h b/include/lttng/condition/condition.h index 7aff1469b..f0f5ffdd8 100644 --- a/include/lttng/condition/condition.h +++ b/include/lttng/condition/condition.h @@ -8,6 +8,8 @@ #ifndef LTTNG_CONDITION_H #define LTTNG_CONDITION_H +#include + #ifdef __cplusplus extern "C" { #endif @@ -39,13 +41,13 @@ enum lttng_condition_status { * 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 } diff --git a/include/lttng/condition/evaluation.h b/include/lttng/condition/evaluation.h index 4ae1c62d9..494cb9739 100644 --- a/include/lttng/condition/evaluation.h +++ b/include/lttng/condition/evaluation.h @@ -9,6 +9,7 @@ #define LTTNG_EVALUATION_H #include +#include #ifdef __cplusplus extern "C" { @@ -30,13 +31,13 @@ enum lttng_evaluation_status { * 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 } diff --git a/include/lttng/condition/event-rule-matches.h b/include/lttng/condition/event-rule-matches.h index 75d1c88af..b1bbe08f3 100644 --- a/include/lttng/condition/event-rule-matches.h +++ b/include/lttng/condition/event-rule-matches.h @@ -11,6 +11,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { @@ -42,7 +43,7 @@ enum lttng_evaluation_event_rule_matches_status { * 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); /* @@ -55,7 +56,7 @@ extern struct lttng_condition *lttng_condition_event_rule_matches_create( * 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); @@ -89,7 +90,7 @@ extern enum lttng_condition_status lttng_condition_event_rule_matches_get_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); @@ -122,7 +123,7 @@ lttng_evaluation_event_rule_matches_get_captured_values( * `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); @@ -142,7 +143,7 @@ lttng_condition_event_rule_matches_append_capture_descriptor( * `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); @@ -157,7 +158,7 @@ lttng_condition_event_rule_matches_get_capture_descriptor_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); diff --git a/include/lttng/condition/session-consumed-size.h b/include/lttng/condition/session-consumed-size.h index 24c9c5455..4d52cb689 100644 --- a/include/lttng/condition/session-consumed-size.h +++ b/include/lttng/condition/session-consumed-size.h @@ -10,6 +10,7 @@ #include #include +#include #include #ifdef __cplusplus @@ -42,7 +43,7 @@ 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_consumed_size_create(void); /* @@ -56,7 +57,7 @@ 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); @@ -69,7 +70,7 @@ lttng_condition_session_consumed_size_get_threshold( * 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); @@ -86,7 +87,7 @@ lttng_condition_session_consumed_size_set_threshold( * 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); @@ -99,7 +100,7 @@ lttng_condition_session_consumed_size_get_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); @@ -116,7 +117,7 @@ lttng_condition_session_consumed_size_set_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); diff --git a/include/lttng/condition/session-rotation.h b/include/lttng/condition/session-rotation.h index afd1bbf89..086fff915 100644 --- a/include/lttng/condition/session-rotation.h +++ b/include/lttng/condition/session-rotation.h @@ -13,6 +13,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { @@ -38,7 +39,7 @@ 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); /* @@ -53,7 +54,7 @@ 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); /* @@ -68,7 +69,7 @@ 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); @@ -81,7 +82,7 @@ lttng_condition_session_rotation_get_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); @@ -99,7 +100,7 @@ lttng_condition_session_rotation_set_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); @@ -118,7 +119,7 @@ lttng_evaluation_session_rotation_get_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); diff --git a/include/lttng/destruction-handle.h b/include/lttng/destruction-handle.h index 6757f213a..6fa4339ac 100644 --- a/include/lttng/destruction-handle.h +++ b/include/lttng/destruction-handle.h @@ -10,6 +10,7 @@ #include #include +#include #ifdef __cplusplus extern "C" { @@ -43,7 +44,7 @@ enum lttng_destruction_handle_status { * 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); /* @@ -60,7 +61,7 @@ extern void lttng_destruction_handle_destroy( * 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); @@ -79,7 +80,7 @@ lttng_destruction_handle_wait_for_completion( * 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); @@ -107,7 +108,7 @@ lttng_destruction_handle_get_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); @@ -131,7 +132,7 @@ lttng_destruction_handle_get_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); diff --git a/include/lttng/domain.h b/include/lttng/domain.h index ba62e0ec9..192c04bf2 100644 --- a/include/lttng/domain.h +++ b/include/lttng/domain.h @@ -13,6 +13,7 @@ extern "C" { #endif #include +#include /* * Domain types: the different possible tracers. @@ -58,7 +59,7 @@ struct lttng_domain { * 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 diff --git a/include/lttng/endpoint.h b/include/lttng/endpoint.h index 1db5e5108..e27ac3b01 100644 --- a/include/lttng/endpoint.h +++ b/include/lttng/endpoint.h @@ -8,6 +8,8 @@ #ifndef LTTNG_ENDPOINT_H #define LTTNG_ENDPOINT_H +#include + #ifdef __cplusplus extern "C" { #endif @@ -24,7 +26,7 @@ extern "C" { * - 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. @@ -38,7 +40,7 @@ extern struct lttng_endpoint *lttng_session_daemon_notification_endpoint; * - 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 } diff --git a/include/lttng/error-query.h b/include/lttng/error-query.h index ff0f0ae99..a7cbae421 100644 --- a/include/lttng/error-query.h +++ b/include/lttng/error-query.h @@ -11,6 +11,7 @@ #define LTTNG_ERROR_QUERY_H #include +#include #include #include @@ -58,11 +59,11 @@ enum lttng_error_query_results_status { }; /* 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); /* @@ -71,12 +72,12 @@ extern struct lttng_error_query *lttng_error_query_condition_create( * `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. @@ -84,45 +85,45 @@ extern void lttng_error_query_destroy(struct lttng_error_query *query); * 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); diff --git a/include/lttng/event-expr.h b/include/lttng/event-expr.h index 911648779..cab22c97e 100644 --- a/include/lttng/event-expr.h +++ b/include/lttng/event-expr.h @@ -8,6 +8,7 @@ #ifndef LTTNG_EVENT_EXPR_H #define LTTNG_EVENT_EXPR_H +#include #include struct lttng_event_expr; @@ -83,7 +84,7 @@ enum lttng_event_expr_status { * 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); /* @@ -95,7 +96,7 @@ extern enum lttng_event_expr_type lttng_event_expr_get_type( * * 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); /* @@ -106,7 +107,7 @@ extern struct lttng_event_expr *lttng_event_expr_event_payload_field_create( * * 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); /* @@ -118,7 +119,7 @@ extern const char *lttng_event_expr_event_payload_field_get_name( * * 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); /* @@ -129,7 +130,7 @@ 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); /* @@ -143,7 +144,7 @@ extern const char *lttng_event_expr_channel_context_field_get_name( * * `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); @@ -155,7 +156,7 @@ lttng_event_expr_app_specific_context_field_create( * * 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); @@ -167,7 +168,7 @@ lttng_event_expr_app_specific_context_field_get_provider_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_type_name( const struct lttng_event_expr *expr); @@ -187,7 +188,7 @@ lttng_event_expr_app_specific_context_field_get_type_name( * * `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); @@ -199,7 +200,7 @@ extern struct lttng_event_expr *lttng_event_expr_array_field_element_create( * * 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); @@ -218,7 +219,7 @@ lttng_event_expr_array_field_element_get_parent_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); @@ -228,13 +229,13 @@ lttng_event_expr_array_field_element_get_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 } diff --git a/include/lttng/event-field-value.h b/include/lttng/event-field-value.h index 7fa851a79..02d93c661 100644 --- a/include/lttng/event-field-value.h +++ b/include/lttng/event-field-value.h @@ -8,6 +8,7 @@ #ifndef LTTNG_EVENT_FIELD_VALUE_H #define LTTNG_EVENT_FIELD_VALUE_H +#include #include struct lttng_event_field_value; @@ -103,7 +104,7 @@ enum lttng_event_field_value_status { * `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); /* @@ -122,7 +123,7 @@ extern enum lttng_event_field_value_type lttng_event_field_value_get_type( * `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); @@ -142,7 +143,7 @@ lttng_event_field_value_unsigned_int_get_value( * `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); @@ -161,7 +162,7 @@ lttng_event_field_value_signed_int_get_value( * `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); @@ -177,7 +178,7 @@ lttng_event_field_value_real_get_value( * * 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); @@ -197,7 +198,7 @@ lttng_event_field_value_string_get_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); @@ -222,7 +223,7 @@ lttng_event_field_value_array_get_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, diff --git a/include/lttng/event-rule/event-rule.h b/include/lttng/event-rule/event-rule.h index a6dbb01a0..0c2453ccf 100644 --- a/include/lttng/event-rule/event-rule.h +++ b/include/lttng/event-rule/event-rule.h @@ -8,6 +8,8 @@ #ifndef LTTNG_EVENT_RULE_H #define LTTNG_EVENT_RULE_H +#include + #ifdef __cplusplus extern "C" { #endif @@ -46,13 +48,13 @@ enum lttng_event_rule_status { * 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 } diff --git a/include/lttng/event-rule/jul-logging.h b/include/lttng/event-rule/jul-logging.h index 943adde8a..833e6adff 100644 --- a/include/lttng/event-rule/jul-logging.h +++ b/include/lttng/event-rule/jul-logging.h @@ -10,6 +10,7 @@ #include #include +#include #include #ifdef __cplusplus @@ -24,7 +25,7 @@ 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_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. @@ -34,7 +35,7 @@ extern struct lttng_event_rule *lttng_event_rule_jul_logging_create(void); * 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); /* @@ -49,7 +50,7 @@ extern enum lttng_event_rule_status lttng_event_rule_jul_logging_set_name_patter * 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); /* @@ -60,7 +61,7 @@ extern enum lttng_event_rule_status lttng_event_rule_jul_logging_get_name_patter * 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); /* @@ -75,7 +76,7 @@ extern enum lttng_event_rule_status lttng_event_rule_jul_logging_set_filter( * 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); /* @@ -86,7 +87,7 @@ extern enum lttng_event_rule_status lttng_event_rule_jul_logging_get_filter( * 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); @@ -102,7 +103,7 @@ lttng_event_rule_jul_logging_set_log_level_rule(struct lttng_event_rule *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); diff --git a/include/lttng/event-rule/kernel-kprobe.h b/include/lttng/event-rule/kernel-kprobe.h index 95f0002a3..c970116af 100644 --- a/include/lttng/event-rule/kernel-kprobe.h +++ b/include/lttng/event-rule/kernel-kprobe.h @@ -9,6 +9,7 @@ #define LTTNG_EVENT_RULE_KERNEL_KPROBE_H #include +#include #ifdef __cplusplus extern "C" { @@ -24,7 +25,7 @@ struct lttng_kernel_probe_location; * 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); /* @@ -39,7 +40,7 @@ extern struct lttng_event_rule *lttng_event_rule_kernel_kprobe_create( * 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); @@ -51,7 +52,7 @@ extern enum lttng_event_rule_status lttng_event_rule_kernel_kprobe_get_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); /* @@ -65,7 +66,7 @@ extern enum lttng_event_rule_status lttng_event_rule_kernel_kprobe_set_event_nam * 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 diff --git a/include/lttng/event-rule/kernel-syscall.h b/include/lttng/event-rule/kernel-syscall.h index 1db691587..ce8be6a5d 100644 --- a/include/lttng/event-rule/kernel-syscall.h +++ b/include/lttng/event-rule/kernel-syscall.h @@ -9,6 +9,7 @@ #define LTTNG_EVENT_RULE_KERNEL_SYSCALL_H #include +#include #ifdef __cplusplus extern "C" { @@ -30,7 +31,7 @@ enum lttng_event_rule_kernel_syscall_emission_site { * 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); /* @@ -43,7 +44,7 @@ extern struct lttng_event_rule *lttng_event_rule_kernel_syscall_create(enum * 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); /* @@ -58,7 +59,7 @@ extern enum lttng_event_rule_status lttng_event_rule_kernel_syscall_set_name_pat * 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); /* @@ -69,7 +70,7 @@ extern enum lttng_event_rule_status lttng_event_rule_kernel_syscall_get_name_pat * 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); /* @@ -84,7 +85,7 @@ extern enum lttng_event_rule_status lttng_event_rule_kernel_syscall_set_filter( * 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); /* @@ -92,7 +93,7 @@ extern enum lttng_event_rule_status lttng_event_rule_kernel_syscall_get_filter( * * 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); diff --git a/include/lttng/event-rule/kernel-tracepoint.h b/include/lttng/event-rule/kernel-tracepoint.h index 84aa011e0..550a04ac4 100644 --- a/include/lttng/event-rule/kernel-tracepoint.h +++ b/include/lttng/event-rule/kernel-tracepoint.h @@ -10,6 +10,7 @@ #include #include +#include #ifdef __cplusplus extern "C" { @@ -23,7 +24,7 @@ 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. @@ -33,7 +34,7 @@ extern struct lttng_event_rule *lttng_event_rule_kernel_tracepoint_create(void); * 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); /* @@ -48,7 +49,7 @@ extern enum lttng_event_rule_status lttng_event_rule_kernel_tracepoint_set_name_ * 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); /* @@ -59,7 +60,7 @@ extern enum lttng_event_rule_status lttng_event_rule_kernel_tracepoint_get_name_ * 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); /* @@ -74,7 +75,7 @@ extern enum lttng_event_rule_status lttng_event_rule_kernel_tracepoint_set_filte * 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 diff --git a/include/lttng/event-rule/kernel-uprobe.h b/include/lttng/event-rule/kernel-uprobe.h index 06712df32..6b29b695d 100644 --- a/include/lttng/event-rule/kernel-uprobe.h +++ b/include/lttng/event-rule/kernel-uprobe.h @@ -9,6 +9,7 @@ #define LTTNG_EVENT_RULE_KERNEL_UPROBE_H #include +#include #include #ifdef __cplusplus @@ -23,7 +24,7 @@ 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_uprobe_create( +LTTNG_EXPORT extern struct lttng_event_rule *lttng_event_rule_kernel_uprobe_create( const struct lttng_userspace_probe_location *location); /* @@ -38,7 +39,7 @@ extern struct lttng_event_rule *lttng_event_rule_kernel_uprobe_create( * 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); @@ -50,7 +51,7 @@ extern enum lttng_event_rule_status lttng_event_rule_kernel_uprobe_get_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); /* @@ -64,7 +65,7 @@ extern enum lttng_event_rule_status lttng_event_rule_kernel_uprobe_set_event_nam * 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 diff --git a/include/lttng/event-rule/log4j-logging.h b/include/lttng/event-rule/log4j-logging.h index 1514a06f0..277e7d950 100644 --- a/include/lttng/event-rule/log4j-logging.h +++ b/include/lttng/event-rule/log4j-logging.h @@ -10,6 +10,7 @@ #include #include +#include #include #ifdef __cplusplus @@ -24,7 +25,7 @@ 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_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. @@ -34,7 +35,7 @@ extern struct lttng_event_rule *lttng_event_rule_log4j_logging_create(void); * 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); /* @@ -49,7 +50,7 @@ extern enum lttng_event_rule_status lttng_event_rule_log4j_logging_set_name_patt * 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); /* @@ -60,7 +61,7 @@ extern enum lttng_event_rule_status lttng_event_rule_log4j_logging_get_name_patt * 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); /* @@ -75,7 +76,7 @@ extern enum lttng_event_rule_status lttng_event_rule_log4j_logging_set_filter( * 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); /* @@ -86,7 +87,7 @@ extern enum lttng_event_rule_status lttng_event_rule_log4j_logging_get_filter( * 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); @@ -102,7 +103,7 @@ lttng_event_rule_log4j_logging_set_log_level_rule(struct lttng_event_rule *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); diff --git a/include/lttng/event-rule/python-logging.h b/include/lttng/event-rule/python-logging.h index cb1f7a985..d4a6ada47 100644 --- a/include/lttng/event-rule/python-logging.h +++ b/include/lttng/event-rule/python-logging.h @@ -10,6 +10,7 @@ #include #include +#include #include #ifdef __cplusplus @@ -24,7 +25,7 @@ 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_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. @@ -34,7 +35,7 @@ extern struct lttng_event_rule *lttng_event_rule_python_logging_create(void); * 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); /* @@ -49,7 +50,7 @@ extern enum lttng_event_rule_status lttng_event_rule_python_logging_set_name_pat * 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); /* @@ -60,7 +61,7 @@ extern enum lttng_event_rule_status lttng_event_rule_python_logging_get_name_pat * 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); /* @@ -75,7 +76,7 @@ extern enum lttng_event_rule_status lttng_event_rule_python_logging_set_filter( * 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); /* @@ -86,7 +87,7 @@ extern enum lttng_event_rule_status lttng_event_rule_python_logging_get_filter( * 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); @@ -102,7 +103,7 @@ lttng_event_rule_python_logging_set_log_level_rule(struct lttng_event_rule *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); diff --git a/include/lttng/event-rule/user-tracepoint.h b/include/lttng/event-rule/user-tracepoint.h index 8744d3594..7ee91ce79 100644 --- a/include/lttng/event-rule/user-tracepoint.h +++ b/include/lttng/event-rule/user-tracepoint.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #ifdef __cplusplus @@ -25,7 +26,7 @@ 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_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. @@ -35,7 +36,7 @@ extern struct lttng_event_rule *lttng_event_rule_user_tracepoint_create(void); * 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); /* @@ -50,7 +51,7 @@ extern enum lttng_event_rule_status lttng_event_rule_user_tracepoint_set_name_pa * 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); /* @@ -61,7 +62,7 @@ extern enum lttng_event_rule_status lttng_event_rule_user_tracepoint_get_name_pa * 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); /* @@ -76,7 +77,7 @@ extern enum lttng_event_rule_status lttng_event_rule_user_tracepoint_set_filter( * 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); /* @@ -87,7 +88,7 @@ extern enum lttng_event_rule_status lttng_event_rule_user_tracepoint_get_filter( * 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); @@ -103,7 +104,7 @@ lttng_event_rule_user_tracepoint_set_log_level_rule(struct lttng_event_rule *rul * 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); @@ -116,7 +117,7 @@ lttng_event_rule_user_tracepoint_get_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); @@ -127,7 +128,7 @@ extern enum lttng_event_rule_status lttng_event_rule_user_tracepoint_add_name_pa * 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); @@ -138,7 +139,7 @@ lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_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, diff --git a/include/lttng/event.h b/include/lttng/event.h index 12d0ecc68..5915db6d6 100644 --- a/include/lttng/event.h +++ b/include/lttng/event.h @@ -9,13 +9,14 @@ #ifndef LTTNG_EVENT_H #define LTTNG_EVENT_H +#include +#include +#include + #ifdef __cplusplus extern "C" { #endif -#include -#include - /* * Instrumentation type of tracing event. */ @@ -310,7 +311,7 @@ struct lttng_event_field { * 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); /* @@ -329,7 +330,7 @@ extern int lttng_list_events(struct lttng_handle *handle, * * 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. @@ -337,7 +338,7 @@ extern struct lttng_event *lttng_event_create(void); * 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. @@ -349,7 +350,7 @@ extern void lttng_event_destroy(struct lttng_event *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); /* @@ -358,7 +359,7 @@ extern int lttng_event_get_filter_expression(struct lttng_event *event, * 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. @@ -368,7 +369,7 @@ extern int lttng_event_get_exclusion_name_count(struct lttng_event *event); * * 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); /* @@ -377,7 +378,7 @@ extern int lttng_event_get_exclusion_name(struct lttng_event *event, * 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); /* @@ -391,7 +392,7 @@ 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); /* @@ -402,7 +403,7 @@ extern int lttng_event_set_userspace_probe_location(struct lttng_event *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_tracepoints(struct lttng_handle *handle, +LTTNG_EXPORT extern int lttng_list_tracepoints(struct lttng_handle *handle, struct lttng_event **events); /* @@ -414,7 +415,7 @@ extern int lttng_list_tracepoints(struct lttng_handle *handle, * 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); /* @@ -424,7 +425,7 @@ extern int lttng_list_tracepoint_fields(struct lttng_handle *handle, * 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). @@ -438,7 +439,7 @@ extern int lttng_list_syscalls(struct lttng_event **events); * * 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); @@ -453,7 +454,7 @@ extern int lttng_add_context(struct lttng_handle *handle, * * 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); /* @@ -469,7 +470,7 @@ extern int lttng_enable_event(struct lttng_handle *handle, * * 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); @@ -487,7 +488,7 @@ extern int lttng_enable_event_with_filter(struct lttng_handle *handle, * * 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); @@ -500,7 +501,7 @@ extern int lttng_enable_event_with_exclusions(struct lttng_handle *handle, * * 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); /* @@ -516,7 +517,7 @@ extern int lttng_disable_event(struct lttng_handle *handle, * * 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); diff --git a/include/lttng/handle.h b/include/lttng/handle.h index 10ec82c62..efc889f1d 100644 --- a/include/lttng/handle.h +++ b/include/lttng/handle.h @@ -9,6 +9,7 @@ #define LTTNG_HANDLE_H #include +#include #ifdef __cplusplus extern "C" { @@ -40,7 +41,7 @@ struct lttng_handle { * 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); /* @@ -48,7 +49,7 @@ extern struct lttng_handle *lttng_create_handle(const char *session_name, * * 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 diff --git a/include/lttng/health.h b/include/lttng/health.h index 0256cbea8..26e885705 100644 --- a/include/lttng/health.h +++ b/include/lttng/health.h @@ -9,6 +9,8 @@ * */ +#include + #ifdef __cplusplus extern "C" { #endif @@ -29,7 +31,7 @@ enum lttng_health_consumerd { * * 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 @@ -37,7 +39,7 @@ extern struct lttng_health *lttng_health_create_sessiond(void); * * 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); /** @@ -49,13 +51,13 @@ extern struct lttng_health * * * 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 @@ -65,7 +67,7 @@ extern void lttng_health_destroy(struct lttng_health *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 @@ -78,7 +80,7 @@ extern int lttng_health_query(struct lttng_health *health); * 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 @@ -87,7 +89,7 @@ extern int lttng_health_state(const struct lttng_health *health); * 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 @@ -98,7 +100,7 @@ extern int lttng_health_get_nr_threads(const struct lttng_health *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); @@ -108,7 +110,7 @@ extern const struct lttng_health_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 @@ -116,7 +118,7 @@ extern int lttng_health_thread_state(const struct lttng_health_thread *thread); * * 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 } diff --git a/include/lttng/kernel-probe.h b/include/lttng/kernel-probe.h index 4536fd5ef..cdd617dea 100644 --- a/include/lttng/kernel-probe.h +++ b/include/lttng/kernel-probe.h @@ -8,6 +8,7 @@ #ifndef LTTNG_KERNEL_PROBE_H #define LTTNG_KERNEL_PROBE_H +#include #include #ifdef __cplusplus @@ -33,34 +34,34 @@ enum lttng_kernel_probe_location_type { /* * 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); @@ -69,13 +70,13 @@ lttng_kernel_probe_location_symbol_get_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); diff --git a/include/lttng/load.h b/include/lttng/load.h index ea541e45b..0395bb414 100644 --- a/include/lttng/load.h +++ b/include/lttng/load.h @@ -9,6 +9,8 @@ #ifndef LTTNG_LOAD_H #define LTTNG_LOAD_H +#include + #ifdef __cplusplus extern "C" { #endif @@ -22,12 +24,12 @@ struct lttng_load_session_attr; /* * 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); /* @@ -35,14 +37,14 @@ 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); /* @@ -51,7 +53,7 @@ extern const char *lttng_load_session_attr_get_input_url( * 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); /* @@ -61,7 +63,7 @@ extern int lttng_load_session_attr_get_overwrite( * * 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); /* @@ -71,7 +73,7 @@ extern const char *lttng_load_session_attr_get_override_url( * * 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); /* @@ -81,7 +83,7 @@ extern const char *lttng_load_session_attr_get_override_ctrl_url( * * 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); /* @@ -92,7 +94,7 @@ extern const char *lttng_load_session_attr_get_override_data_url( * 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); /* @@ -106,7 +108,7 @@ extern const char *lttng_load_session_attr_get_override_session_name( * 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); /* @@ -115,7 +117,7 @@ extern int lttng_load_session_attr_set_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); /* @@ -123,7 +125,7 @@ extern int lttng_load_session_attr_set_input_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); /* @@ -143,7 +145,7 @@ extern int lttng_load_session_attr_set_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); /* @@ -156,7 +158,7 @@ extern int lttng_load_session_attr_set_override_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); /* @@ -169,7 +171,7 @@ extern int lttng_load_session_attr_set_override_ctrl_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); /* @@ -178,7 +180,7 @@ extern int lttng_load_session_attr_set_override_data_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); /* @@ -189,7 +191,7 @@ extern int lttng_load_session_attr_set_override_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 } diff --git a/include/lttng/location.h b/include/lttng/location.h index d875b2484..ce686315e 100644 --- a/include/lttng/location.h +++ b/include/lttng/location.h @@ -8,6 +8,7 @@ #ifndef LTTNG_LOCATION_H #define LTTNG_LOCATION_H +#include #include #ifdef __cplusplus @@ -38,7 +39,7 @@ struct lttng_trace_archive_location; /* * 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); @@ -47,7 +48,7 @@ lttng_trace_archive_location_get_type( * * 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); @@ -58,7 +59,7 @@ lttng_trace_archive_location_local_get_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); @@ -67,7 +68,7 @@ lttng_trace_archive_location_relay_get_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); @@ -76,7 +77,7 @@ lttng_trace_archive_location_relay_get_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); @@ -85,7 +86,7 @@ lttng_trace_archive_location_relay_get_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); @@ -95,7 +96,7 @@ lttng_trace_archive_location_relay_get_protocol_type( * * 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); diff --git a/include/lttng/log-level-rule.h b/include/lttng/log-level-rule.h index ea9045d56..ddb3501a1 100644 --- a/include/lttng/log-level-rule.h +++ b/include/lttng/log-level-rule.h @@ -8,6 +8,8 @@ #ifndef LTTNG_LOG_LEVEL_RULE_H #define LTTNG_LOG_LEVEL_RULE_H +#include + #ifdef __cplusplus extern "C" { #endif @@ -32,7 +34,7 @@ enum lttng_log_level_rule_status { * `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); /* @@ -46,7 +48,7 @@ extern enum lttng_log_level_rule_type lttng_log_level_rule_get_type( * 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); /* @@ -62,7 +64,7 @@ extern struct lttng_log_level_rule *lttng_log_level_rule_exactly_create( * * `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); /* @@ -76,7 +78,7 @@ extern enum lttng_log_level_rule_status lttng_log_level_rule_exactly_get_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); /* @@ -94,14 +96,14 @@ 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 diff --git a/include/lttng/lttng-error.h b/include/lttng/lttng-error.h index aadf2f45b..790a78a0b 100644 --- a/include/lttng/lttng-error.h +++ b/include/lttng/lttng-error.h @@ -15,6 +15,8 @@ #ifndef LTTNG_ERROR_H #define LTTNG_ERROR_H +#include + #ifdef __cplusplus extern "C" { #endif @@ -195,7 +197,7 @@ enum lttng_error_code { * * 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 } diff --git a/include/lttng/lttng-export.h b/include/lttng/lttng-export.h new file mode 100644 index 000000000..ae3990a29 --- /dev/null +++ b/include/lttng/lttng-export.h @@ -0,0 +1,14 @@ +/* + * Copyright (C) 2021 Simon Marchi + * + * 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 diff --git a/include/lttng/lttng.h b/include/lttng/lttng.h index efbd92f5d..825b6682b 100644 --- a/include/lttng/lttng.h +++ b/include/lttng/lttng.h @@ -58,6 +58,7 @@ #include #include #include +#include #include #include #include @@ -95,14 +96,14 @@ struct lttng_calibrate { * 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. @@ -114,7 +115,7 @@ extern int lttng_set_tracing_group(const char *name); * * 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); /* @@ -122,7 +123,7 @@ extern int lttng_register_consumer(struct lttng_handle *handle, * * 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. @@ -136,13 +137,13 @@ extern int lttng_start_tracing(const char *session_name); * * 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 @@ -150,7 +151,7 @@ extern int lttng_stop_tracing_no_wait(const char *session_name); */ #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 @@ -178,7 +179,7 @@ extern int lttng_calibrate(struct lttng_handle *handle, * * 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); /* @@ -191,13 +192,13 @@ extern int lttng_set_consumer_url(struct lttng_handle *handle, * 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. @@ -205,7 +206,7 @@ extern int lttng_metadata_regenerate(const char *session_name); * 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 @@ -214,7 +215,7 @@ extern int lttng_regenerate_metadata(const char *session_name); * * 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 } diff --git a/include/lttng/notification/channel.h b/include/lttng/notification/channel.h index 95a048fb9..030c88cbd 100644 --- a/include/lttng/notification/channel.h +++ b/include/lttng/notification/channel.h @@ -8,6 +8,7 @@ #ifndef LTTNG_NOTIFICATION_CHANNEL_H #define LTTNG_NOTIFICATION_CHANNEL_H +#include #include #ifdef __cplusplus @@ -57,7 +58,7 @@ enum lttng_notification_channel_status { * 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); /* @@ -81,7 +82,7 @@ extern struct lttng_notification_channel *lttng_notification_channel_create( * - 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); @@ -102,7 +103,7 @@ lttng_notification_channel_get_next_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); @@ -122,7 +123,7 @@ lttng_notification_channel_has_pending_notification( * 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); @@ -142,7 +143,7 @@ lttng_notification_channel_subscribe( * 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); @@ -150,7 +151,7 @@ lttng_notification_channel_unsubscribe( /* * 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 diff --git a/include/lttng/notification/notification.h b/include/lttng/notification/notification.h index 69e17d30c..d1c088fec 100644 --- a/include/lttng/notification/notification.h +++ b/include/lttng/notification/notification.h @@ -8,6 +8,8 @@ #ifndef LTTNG_NOTIFICATION_H #define LTTNG_NOTIFICATION_H +#include + #ifdef __cplusplus extern "C" { #endif @@ -28,7 +30,7 @@ struct lttng_notification; * * 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); /* @@ -43,7 +45,7 @@ extern const struct lttng_condition *lttng_notification_get_condition( * * 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); /* @@ -55,14 +57,14 @@ extern const struct lttng_evaluation *lttng_notification_get_evaluation( * * 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 } diff --git a/include/lttng/rotation.h b/include/lttng/rotation.h index 316f2cdb5..08f2a985b 100644 --- a/include/lttng/rotation.h +++ b/include/lttng/rotation.h @@ -11,6 +11,7 @@ #include #include +#include #ifdef __cplusplus extern "C" { @@ -101,7 +102,7 @@ struct lttng_rotation_handle; * 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); @@ -114,14 +115,14 @@ extern enum lttng_rotation_status lttng_rotation_handle_get_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); /* @@ -137,21 +138,21 @@ extern void lttng_rotation_handle_destroy( * 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); /* @@ -160,7 +161,7 @@ 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); @@ -168,7 +169,7 @@ lttng_rotation_schedule_size_threshold_get_threshold( /* * 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); @@ -177,7 +178,7 @@ lttng_rotation_schedule_size_threshold_set_threshold( * 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); /* @@ -186,34 +187,34 @@ 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); @@ -226,7 +227,7 @@ extern enum lttng_rotation_status lttng_rotation_schedules_get_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); @@ -241,7 +242,7 @@ lttng_rotation_schedules_get_at_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); @@ -252,7 +253,7 @@ extern enum lttng_rotation_status lttng_session_add_rotation_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); @@ -261,7 +262,7 @@ extern enum lttng_rotation_status lttng_session_remove_rotation_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); diff --git a/include/lttng/save.h b/include/lttng/save.h index 7dbe32698..d28fdffcd 100644 --- a/include/lttng/save.h +++ b/include/lttng/save.h @@ -8,6 +8,8 @@ #ifndef LTTNG_SAVE_H #define LTTNG_SAVE_H +#include + #ifdef __cplusplus extern "C" { #endif @@ -21,12 +23,12 @@ struct lttng_save_session_attr; /* * 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); /* @@ -34,32 +36,32 @@ extern void lttng_save_session_attr_destroy(struct lttng_save_session_attr *outp */ /* 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); /* @@ -73,32 +75,32 @@ extern int lttng_save_session_attr_get_omit_output( * 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); /* @@ -109,7 +111,7 @@ extern int lttng_save_session_attr_set_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 } diff --git a/include/lttng/session-descriptor.h b/include/lttng/session-descriptor.h index 3fb28a78e..5db04be7e 100644 --- a/include/lttng/session-descriptor.h +++ b/include/lttng/session-descriptor.h @@ -8,6 +8,8 @@ #ifndef LTTNG_SESSION_DESCRIPTOR_H #define LTTNG_SESSION_DESCRIPTOR_H +#include + #ifdef __cplusplus extern "C" { #endif @@ -103,7 +105,7 @@ enum lttng_session_descriptor_status { * * 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); /* @@ -116,7 +118,7 @@ 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); /* @@ -129,7 +131,7 @@ 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); @@ -140,7 +142,7 @@ lttng_session_descriptor_network_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_create(const char *name); /* @@ -153,7 +155,7 @@ 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); @@ -168,7 +170,7 @@ lttng_session_descriptor_snapshot_local_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_network_create(const char *name, const char *control_url, const char *data_url); @@ -185,7 +187,7 @@ lttng_session_descriptor_snapshot_network_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_live_create( const char *name, unsigned long long live_timer_interval_us); @@ -205,7 +207,7 @@ lttng_session_descriptor_live_create( * * 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, @@ -226,7 +228,7 @@ lttng_session_descriptor_live_network_create( * 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); @@ -237,7 +239,7 @@ lttng_session_descriptor_get_session_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 diff --git a/include/lttng/session.h b/include/lttng/session.h index f13f83916..153a37b03 100644 --- a/include/lttng/session.h +++ b/include/lttng/session.h @@ -14,6 +14,7 @@ extern "C" { #endif #include +#include struct lttng_handle; struct lttng_session_descriptor; @@ -86,7 +87,7 @@ struct lttng_session { * 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); /* @@ -97,7 +98,7 @@ extern enum lttng_error_code lttng_create_session_ext( * * 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 @@ -111,7 +112,7 @@ extern int lttng_create_session(const char *name, const char *url); * * 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); /* @@ -127,7 +128,7 @@ extern int lttng_create_session_snapshot(const char *name, * * 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); /* @@ -147,7 +148,7 @@ extern int lttng_create_session_live(const char *name, const char *url, * * 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. @@ -161,14 +162,14 @@ extern int lttng_destroy_session(const char *name); * 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. @@ -178,7 +179,7 @@ extern int lttng_destroy_session_no_wait(const char *name); * * 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. @@ -192,7 +193,7 @@ extern int lttng_list_sessions(struct lttng_session **sessions); * 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); /* @@ -204,7 +205,7 @@ extern enum lttng_error_code lttng_session_get_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 diff --git a/include/lttng/snapshot.h b/include/lttng/snapshot.h index bdbfb094f..b777e006b 100644 --- a/include/lttng/snapshot.h +++ b/include/lttng/snapshot.h @@ -9,6 +9,7 @@ #define LTTNG_SNAPSHOT_H #include +#include #include #include @@ -26,12 +27,12 @@ struct lttng_snapshot_output_list; /* * 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 @@ -39,15 +40,15 @@ extern void lttng_snapshot_output_destroy(struct lttng_snapshot_output *output); */ /* 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. @@ -57,13 +58,13 @@ extern const char *lttng_snapshot_output_get_data_url(const struct lttng_snapsho */ /* 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); /* @@ -73,7 +74,7 @@ extern int lttng_snapshot_output_set_name(const char *name, * * 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); /* @@ -84,7 +85,7 @@ extern int lttng_snapshot_output_set_local_path(const char *path, * * 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); /* @@ -97,15 +98,15 @@ extern int lttng_snapshot_output_set_network_url(const char *url, * * 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); /* @@ -113,7 +114,7 @@ extern int lttng_snapshot_output_set_data_url(const char *url, * * 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); /* @@ -121,7 +122,7 @@ extern int lttng_snapshot_add_output(const char *session_name, * * 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); /* @@ -131,7 +132,7 @@ extern int lttng_snapshot_del_output(const char *session_name, * 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); /* @@ -141,13 +142,13 @@ extern int lttng_snapshot_list_output(const char *session_name, * 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. @@ -161,7 +162,7 @@ extern void lttng_snapshot_output_list_destroy(struct lttng_snapshot_output_list * * 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 diff --git a/include/lttng/tracker.h b/include/lttng/tracker.h index fa91abab6..869f8a8f8 100644 --- a/include/lttng/tracker.h +++ b/include/lttng/tracker.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -115,7 +116,7 @@ struct lttng_process_attr_values; * 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, @@ -124,7 +125,7 @@ extern enum lttng_error_code lttng_session_get_tracker_handle( /* * 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); /* @@ -134,7 +135,7 @@ extern void lttng_process_attr_tracker_handle_destroy( * 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); @@ -147,7 +148,7 @@ lttng_process_attr_tracker_handle_get_tracking_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); @@ -162,7 +163,7 @@ lttng_process_attr_tracker_handle_set_tracking_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, @@ -177,7 +178,7 @@ lttng_process_attr_process_id_tracker_handle_add_pid( * 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, @@ -193,7 +194,7 @@ lttng_process_attr_process_id_tracker_handle_remove_pid( * 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, @@ -208,7 +209,7 @@ lttng_process_attr_virtual_process_id_tracker_handle_add_pid( * 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, @@ -223,7 +224,7 @@ lttng_process_attr_virtual_process_id_tracker_handle_remove_pid( * 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); @@ -237,7 +238,7 @@ lttng_process_attr_user_id_tracker_handle_add_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); @@ -254,7 +255,7 @@ lttng_process_attr_user_id_tracker_handle_remove_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); @@ -271,7 +272,7 @@ lttng_process_attr_user_id_tracker_handle_add_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); @@ -286,7 +287,7 @@ lttng_process_attr_user_id_tracker_handle_remove_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); @@ -300,7 +301,7 @@ lttng_process_attr_virtual_user_id_tracker_handle_add_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_virtual_user_id_tracker_handle_remove_uid( const struct lttng_process_attr_tracker_handle *user_id_tracker, uid_t vuid); @@ -318,7 +319,7 @@ lttng_process_attr_virtual_user_id_tracker_handle_remove_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_virtual_user_id_tracker_handle_add_user_name( const struct lttng_process_attr_tracker_handle *user_id_tracker, const char *virtual_user_name); @@ -335,7 +336,7 @@ lttng_process_attr_virtual_user_id_tracker_handle_add_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); @@ -349,7 +350,7 @@ lttng_process_attr_virtual_user_id_tracker_handle_remove_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); @@ -363,7 +364,7 @@ lttng_process_attr_group_id_tracker_handle_add_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); @@ -380,7 +381,7 @@ lttng_process_attr_group_id_tracker_handle_remove_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); @@ -397,7 +398,7 @@ lttng_process_attr_group_id_tracker_handle_add_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); @@ -412,7 +413,7 @@ lttng_process_attr_group_id_tracker_handle_remove_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); @@ -426,7 +427,7 @@ lttng_process_attr_virtual_group_id_tracker_handle_add_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_virtual_group_id_tracker_handle_remove_gid( const struct lttng_process_attr_tracker_handle *group_id_tracker, gid_t vgid); @@ -444,7 +445,7 @@ lttng_process_attr_virtual_group_id_tracker_handle_remove_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_virtual_group_id_tracker_handle_add_group_name( const struct lttng_process_attr_tracker_handle *group_id_tracker, const char *virtual_group_name); @@ -461,7 +462,7 @@ lttng_process_attr_virtual_group_id_tracker_handle_add_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); @@ -479,7 +480,7 @@ lttng_process_attr_virtual_group_id_tracker_handle_remove_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); @@ -490,7 +491,7 @@ lttng_process_attr_tracker_handle_get_inclusion_set( * 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); @@ -501,7 +502,7 @@ lttng_process_attr_values_get_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); @@ -513,7 +514,7 @@ lttng_process_attr_values_get_type_at_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, @@ -526,7 +527,7 @@ lttng_process_attr_values_get_pid_at_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, @@ -539,7 +540,7 @@ lttng_process_attr_values_get_uid_at_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, @@ -552,7 +553,7 @@ lttng_process_attr_values_get_user_name_at_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, @@ -565,7 +566,7 @@ lttng_process_attr_values_get_gid_at_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, @@ -588,7 +589,7 @@ lttng_process_attr_values_get_group_name_at_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); @@ -610,7 +611,7 @@ extern int lttng_list_tracker_pids(struct lttng_handle *handle, * * 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`. @@ -629,7 +630,7 @@ extern int lttng_track_pid(struct lttng_handle *handle, int 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 } diff --git a/include/lttng/trigger/trigger.h b/include/lttng/trigger/trigger.h index 842203ace..0a944a15a 100644 --- a/include/lttng/trigger/trigger.h +++ b/include/lttng/trigger/trigger.h @@ -12,6 +12,7 @@ #include #include #include +#include struct lttng_action; struct lttng_condition; @@ -62,7 +63,7 @@ enum lttng_trigger_status { * 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); /* @@ -74,7 +75,7 @@ extern struct lttng_trigger *lttng_trigger_create( * 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); /* @@ -84,7 +85,7 @@ extern enum lttng_trigger_status lttng_trigger_set_owner_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); /* @@ -94,10 +95,10 @@ extern enum lttng_trigger_status lttng_trigger_get_owner_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); /* @@ -107,10 +108,10 @@ extern const struct lttng_condition *lttng_trigger_get_const_condition( * * 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); /* @@ -124,13 +125,13 @@ extern const struct lttng_action *lttng_trigger_get_const_action( * 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. @@ -140,7 +141,7 @@ extern void lttng_trigger_destroy(struct lttng_trigger *trigger); * * 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); @@ -154,7 +155,7 @@ extern enum lttng_error_code lttng_register_trigger_with_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); /* @@ -164,7 +165,7 @@ extern enum lttng_error_code lttng_register_trigger_with_automatic_name( * * 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. @@ -176,7 +177,7 @@ extern int lttng_unregister_trigger(const struct lttng_trigger *trigger); * * 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); /* @@ -188,7 +189,7 @@ extern enum lttng_error_code lttng_list_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); /* @@ -197,13 +198,13 @@ extern const struct lttng_trigger *lttng_triggers_get_at_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 @@ -216,7 +217,7 @@ extern void lttng_triggers_destroy(struct lttng_triggers *triggers); * 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 } diff --git a/include/lttng/userspace-probe.h b/include/lttng/userspace-probe.h index 5a6fa51a0..b6fc13508 100644 --- a/include/lttng/userspace-probe.h +++ b/include/lttng/userspace-probe.h @@ -8,6 +8,8 @@ #ifndef LTTNG_USERSPACE_PROBE_H #define LTTNG_USERSPACE_PROBE_H +#include + #ifdef __cplusplus extern "C" { #endif @@ -28,28 +30,28 @@ enum lttng_userspace_probe_location_lookup_method_type { /* * 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); @@ -76,14 +78,14 @@ enum lttng_userspace_probe_location_type { /* * 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); @@ -101,7 +103,7 @@ enum lttng_userspace_probe_location_function_instrumentation_type { * 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); @@ -109,26 +111,26 @@ lttng_userspace_probe_location_function_create(const char *binary_path, /* * 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); @@ -141,7 +143,7 @@ lttng_userspace_probe_location_function_get_instrumentation_type( * 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); @@ -152,7 +154,7 @@ lttng_userspace_probe_location_function_set_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); @@ -165,7 +167,7 @@ lttng_userspace_probe_location_get_lookup_method( * 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); @@ -173,27 +175,27 @@ lttng_userspace_probe_location_tracepoint_create(const char *binary_path, /* * 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 diff --git a/src/bin/lttng-consumerd/lttng-consumerd.h b/src/bin/lttng-consumerd/lttng-consumerd.h index 7621877d3..354f7f3fa 100644 --- a/src/bin/lttng-consumerd/lttng-consumerd.h +++ b/src/bin/lttng-consumerd/lttng-consumerd.h @@ -16,9 +16,11 @@ extern int lttng_consumer_ready; 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 */ diff --git a/src/bin/lttng-sessiond/notification-thread.cpp b/src/bin/lttng-sessiond/notification-thread.cpp index e8a2adec9..867fc7c04 100644 --- a/src/bin/lttng-sessiond/notification-thread.cpp +++ b/src/bin/lttng-sessiond/notification-thread.cpp @@ -36,8 +36,13 @@ #include #include +/* + * 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. */ diff --git a/src/bin/lttng-sessiond/ust-sigbus.cpp b/src/bin/lttng-sessiond/ust-sigbus.cpp index 52a7ac270..93a974eb3 100644 --- a/src/bin/lttng-sessiond/ust-sigbus.cpp +++ b/src/bin/lttng-sessiond/ust-sigbus.cpp @@ -7,9 +7,10 @@ #include #include +#include #include "ust-sigbus.h" -DEFINE_LTTNG_UST_SIGBUS_STATE(); +LTTNG_EXPORT DEFINE_LTTNG_UST_SIGBUS_STATE(); void lttng_ust_handle_sigbus(void *address) { diff --git a/src/common/config/config-session-abi.h b/src/common/config/config-session-abi.h index 75ff303d4..6c903ef7a 100644 --- a/src/common/config/config-session-abi.h +++ b/src/common/config/config-session-abi.h @@ -8,23 +8,25 @@ #ifndef CONFIG_SESSION_INTERNAL_H #define CONFIG_SESSION_INTERNAL_H +#include + 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; @@ -36,49 +38,49 @@ extern const char * const config_element_userspace_probe_tracepoint_attributes; 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; @@ -99,50 +101,50 @@ extern const char * const config_element_rotation_timer_interval; 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; diff --git a/src/common/config/session-config.c b/src/common/config/session-config.c index cf785c8b5..08d66851b 100644 --- a/src/common/config/session-config.c +++ b/src/common/config/session-config.c @@ -52,17 +52,17 @@ struct session_config_validation_ctx { }; 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"; @@ -239,7 +239,7 @@ const char * const config_event_context_vegid = "VEGID"; 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, diff --git a/src/common/consumer/consumer.h b/src/common/consumer/consumer.h index 6f2aae31b..1b0ee000b 100644 --- a/src/common/consumer/consumer.h +++ b/src/common/consumer/consumer.h @@ -859,8 +859,12 @@ extern int consumer_quit; */ 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 diff --git a/src/common/error.h b/src/common/error.h index 6660cee6a..8bb0de15c 100644 --- a/src/common/error.h +++ b/src/common/error.h @@ -47,7 +47,7 @@ struct log_time { /* 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; diff --git a/src/common/filter/filter-lexer.l b/src/common/filter/filter-lexer.l index cdb099af7..9da4645e5 100644 --- a/src/common/filter/filter-lexer.l +++ b/src/common/filter/filter-lexer.l @@ -13,6 +13,7 @@ #include #include "filter-ast.h" #include "filter-parser.h" +#include static void yyunput (int c, register char * yy_bp , yyscan_t yyscanner) __attribute__((unused)); @@ -127,3 +128,215 @@ L\" BEGIN(string_lit); return STRING_LITERAL_START; [ \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); +} diff --git a/src/common/filter/filter-symbols.h b/src/common/filter/filter-symbols.h index 031776da0..27aaada54 100644 --- a/src/common/filter/filter-symbols.h +++ b/src/common/filter/filter-symbols.h @@ -12,34 +12,34 @@ * */ -#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 */ diff --git a/src/common/hashtable/hashtable.h b/src/common/hashtable/hashtable.h index e2dae968d..cefd43833 100644 --- a/src/common/hashtable/hashtable.h +++ b/src/common/hashtable/hashtable.h @@ -12,13 +12,14 @@ #include #include +#include #include #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; diff --git a/src/common/index-allocator.h b/src/common/index-allocator.h index 9dbd745e6..93ab5ddd5 100644 --- a/src/common/index-allocator.h +++ b/src/common/index-allocator.h @@ -9,6 +9,7 @@ #define _COMMON_INDEX_ALLOCATOR_H #include +#include #ifdef __cplusplus extern "C" { @@ -25,19 +26,19 @@ enum lttng_index_allocator_status { /* * 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); @@ -45,13 +46,13 @@ enum lttng_index_allocator_status lttng_index_allocator_alloc( * 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 } diff --git a/src/common/lttng-elf.h b/src/common/lttng-elf.h index 49b064ce5..524b87846 100644 --- a/src/common/lttng-elf.h +++ b/src/common/lttng-elf.h @@ -8,9 +8,11 @@ * */ -int lttng_elf_get_symbol_offset(int fd, char *symbol, uint64_t *offset); +#include -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 */ diff --git a/src/common/mi-lttng.c b/src/common/mi-lttng.c index b790f793a..1ff9f936c 100644 --- a/src/common/mi-lttng.c +++ b/src/common/mi-lttng.c @@ -435,14 +435,14 @@ const char *const mi_lttng_element_error_query_results = 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 diff --git a/src/common/mi-lttng.h b/src/common/mi-lttng.h index 2f27bf6cd..74ae502f5 100644 --- a/src/common/mi-lttng.h +++ b/src/common/mi-lttng.h @@ -62,147 +62,147 @@ struct mi_lttng_error_query_callbacks { }; /* 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; diff --git a/src/common/sessiond-comm/inet.h b/src/common/sessiond-comm/inet.h index 5c0828b2b..9aec36cf1 100644 --- a/src/common/sessiond-comm/inet.h +++ b/src/common/sessiond-comm/inet.h @@ -34,7 +34,7 @@ extern "C" { * 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; diff --git a/src/common/spawn-viewer.h b/src/common/spawn-viewer.h index 316fe1998..dc7b7bbcb 100644 --- a/src/common/spawn-viewer.h +++ b/src/common/spawn-viewer.h @@ -8,6 +8,7 @@ * */ +#include #include #if defined(__cplusplus) @@ -24,7 +25,7 @@ extern "C" { * 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) } diff --git a/src/common/ust-consumer/ust-consumer.c b/src/common/ust-consumer/ust-consumer.c index 31effcc23..310b670b1 100644 --- a/src/common/ust-consumer/ust-consumer.c +++ b/src/common/ust-consumer/ust-consumer.c @@ -47,7 +47,7 @@ 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 diff --git a/src/lib/lttng-ctl/Makefile.am b/src/lib/lttng-ctl/Makefile.am index e1ffd6a48..b31e5bd6f 100644 --- a/src/lib/lttng-ctl/Makefile.am +++ b/src/lib/lttng-ctl/Makefile.am @@ -6,10 +6,20 @@ AM_CPPFLAGS += -I$(srcdir) -I$(builddir) 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) \ diff --git a/src/lib/lttng-ctl/channel.c b/src/lib/lttng-ctl/channel.c deleted file mode 100644 index 17f9537ba..000000000 --- a/src/lib/lttng-ctl/channel.c +++ /dev/null @@ -1,735 +0,0 @@ -/* - * Copyright (C) 2017 Jérémie Galarneau - * - * SPDX-License-Identifier: LGPL-2.1-only - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "lttng-ctl-helper.h" -#include - -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); -} diff --git a/src/lib/lttng-ctl/channel.cpp b/src/lib/lttng-ctl/channel.cpp new file mode 100644 index 000000000..e7b044ac0 --- /dev/null +++ b/src/lib/lttng-ctl/channel.cpp @@ -0,0 +1,735 @@ +/* + * Copyright (C) 2017 Jérémie Galarneau + * + * SPDX-License-Identifier: LGPL-2.1-only + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "lttng-ctl-helper.h" +#include + +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); +} diff --git a/src/lib/lttng-ctl/clear.c b/src/lib/lttng-ctl/clear.c deleted file mode 100644 index 3face64de..000000000 --- a/src/lib/lttng-ctl/clear.c +++ /dev/null @@ -1,335 +0,0 @@ -/* - * Copyright (C) 2019 Jérémie Galarneau - * Copyright (C) 2019 Mathieu Desnoyers - * - * SPDX-License-Identifier: LGPL-2.1-only - * - */ - -#define _LGPL_SOURCE -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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; -} diff --git a/src/lib/lttng-ctl/clear.cpp b/src/lib/lttng-ctl/clear.cpp new file mode 100644 index 000000000..0eaf97364 --- /dev/null +++ b/src/lib/lttng-ctl/clear.cpp @@ -0,0 +1,336 @@ +/* + * Copyright (C) 2019 Jérémie Galarneau + * Copyright (C) 2019 Mathieu Desnoyers + * + * SPDX-License-Identifier: LGPL-2.1-only + * + */ + +#define _LGPL_SOURCE +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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; +} diff --git a/src/lib/lttng-ctl/deprecated-symbols.c b/src/lib/lttng-ctl/deprecated-symbols.c deleted file mode 100644 index 0ea802c5e..000000000 --- a/src/lib/lttng-ctl/deprecated-symbols.c +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2016 Jérémie Galarneau - * - * SPDX-License-Identifier: LGPL-2.1-only - * - */ - -#include - -/* - * 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; diff --git a/src/lib/lttng-ctl/deprecated-symbols.cpp b/src/lib/lttng-ctl/deprecated-symbols.cpp new file mode 100644 index 000000000..0eaf507c2 --- /dev/null +++ b/src/lib/lttng-ctl/deprecated-symbols.cpp @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2016 Jérémie Galarneau + * + * SPDX-License-Identifier: LGPL-2.1-only + * + */ + +#include +#include + +/* + * 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; diff --git a/src/lib/lttng-ctl/destruction-handle.c b/src/lib/lttng-ctl/destruction-handle.c deleted file mode 100644 index 26ae7d306..000000000 --- a/src/lib/lttng-ctl/destruction-handle.c +++ /dev/null @@ -1,446 +0,0 @@ -/* - * Copyright (C) 2019 Jérémie Galarneau - * - * SPDX-License-Identifier: LGPL-2.1-only - * - */ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "lttng-ctl-helper.h" - -#include - -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; -} diff --git a/src/lib/lttng-ctl/destruction-handle.cpp b/src/lib/lttng-ctl/destruction-handle.cpp new file mode 100644 index 000000000..35a1c3582 --- /dev/null +++ b/src/lib/lttng-ctl/destruction-handle.cpp @@ -0,0 +1,447 @@ +/* + * Copyright (C) 2019 Jérémie Galarneau + * + * SPDX-License-Identifier: LGPL-2.1-only + * + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "lttng-ctl-helper.h" + +#include +#include + +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; +} diff --git a/src/lib/lttng-ctl/event.c b/src/lib/lttng-ctl/event.c deleted file mode 100644 index c153b9187..000000000 --- a/src/lib/lttng-ctl/event.c +++ /dev/null @@ -1,197 +0,0 @@ -/* - * event.c - * - * Linux Trace Toolkit Control Library - * - * Copyright (C) 2017 Jérémie Galarneau - * - * SPDX-License-Identifier: LGPL-2.1-only - * - */ - -#define _LGPL_SOURCE -#include - -#include -#include -#include -#include -#include -#include - -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; -} diff --git a/src/lib/lttng-ctl/event.cpp b/src/lib/lttng-ctl/event.cpp new file mode 100644 index 000000000..3a6bf22b2 --- /dev/null +++ b/src/lib/lttng-ctl/event.cpp @@ -0,0 +1,197 @@ +/* + * event.c + * + * Linux Trace Toolkit Control Library + * + * Copyright (C) 2017 Jérémie Galarneau + * + * SPDX-License-Identifier: LGPL-2.1-only + * + */ + +#define _LGPL_SOURCE +#include + +#include +#include +#include +#include +#include +#include + +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; +} diff --git a/src/lib/lttng-ctl/load.c b/src/lib/lttng-ctl/load.c deleted file mode 100644 index 4af132675..000000000 --- a/src/lib/lttng-ctl/load.c +++ /dev/null @@ -1,634 +0,0 @@ -/* - * Copyright (C) 2014 David Goulet - * - * SPDX-License-Identifier: LGPL-2.1-only - * - */ - -#define _LGPL_SOURCE -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#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; -} diff --git a/src/lib/lttng-ctl/load.cpp b/src/lib/lttng-ctl/load.cpp new file mode 100644 index 000000000..0032df569 --- /dev/null +++ b/src/lib/lttng-ctl/load.cpp @@ -0,0 +1,634 @@ +/* + * Copyright (C) 2014 David Goulet + * + * SPDX-License-Identifier: LGPL-2.1-only + * + */ + +#define _LGPL_SOURCE +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#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; +} diff --git a/src/lib/lttng-ctl/lttng-ctl-health.c b/src/lib/lttng-ctl/lttng-ctl-health.c deleted file mode 100644 index 955b1fcd0..000000000 --- a/src/lib/lttng-ctl/lttng-ctl-health.c +++ /dev/null @@ -1,366 +0,0 @@ -/* - * lttng-ctl-health.c - * - * Linux Trace Toolkit Health Control Library - * - * Copyright (C) 2011 David Goulet - * Copyright (C) 2013 Mathieu Desnoyers - * - * SPDX-License-Identifier: LGPL-2.1-only - * - */ - -#define _LGPL_SOURCE -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#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]; -} diff --git a/src/lib/lttng-ctl/lttng-ctl-health.cpp b/src/lib/lttng-ctl/lttng-ctl-health.cpp new file mode 100644 index 000000000..2a992830d --- /dev/null +++ b/src/lib/lttng-ctl/lttng-ctl-health.cpp @@ -0,0 +1,420 @@ +/* + * lttng-ctl-health.c + * + * Linux Trace Toolkit Health Control Library + * + * Copyright (C) 2011 David Goulet + * Copyright (C) 2013 Mathieu Desnoyers + * + * SPDX-License-Identifier: LGPL-2.1-only + * + */ + +#define _LGPL_SOURCE +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#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); +} diff --git a/src/lib/lttng-ctl/lttng-ctl.c b/src/lib/lttng-ctl/lttng-ctl.c deleted file mode 100644 index 83a884c17..000000000 --- a/src/lib/lttng-ctl/lttng-ctl.c +++ /dev/null @@ -1,3516 +0,0 @@ -/* - * lttng-ctl.c - * - * Linux Trace Toolkit Control Library - * - * Copyright (C) 2011 David Goulet - * Copyright (C) 2016 Jérémie Galarneau - * - * SPDX-License-Identifier: LGPL-2.1-only - * - */ - -#define _LGPL_SOURCE -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "lttng-ctl-helper.h" -#include -#include -#include - -#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); -} diff --git a/src/lib/lttng-ctl/lttng-ctl.cpp b/src/lib/lttng-ctl/lttng-ctl.cpp new file mode 100644 index 000000000..362298718 --- /dev/null +++ b/src/lib/lttng-ctl/lttng-ctl.cpp @@ -0,0 +1,3519 @@ +/* + * lttng-ctl.c + * + * Linux Trace Toolkit Control Library + * + * Copyright (C) 2011 David Goulet + * Copyright (C) 2016 Jérémie Galarneau + * + * SPDX-License-Identifier: LGPL-2.1-only + * + */ + +#define _LGPL_SOURCE +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "lttng-ctl-helper.h" +#include +#include +#include + +#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); +} diff --git a/src/lib/lttng-ctl/rotate.c b/src/lib/lttng-ctl/rotate.c deleted file mode 100644 index d13194404..000000000 --- a/src/lib/lttng-ctl/rotate.c +++ /dev/null @@ -1,666 +0,0 @@ -/* - * Copyright (C) 2017 Julien Desfossez - * - * SPDX-License-Identifier: LGPL-2.1-only - * - */ - -#define _LGPL_SOURCE -#include - -#include -#include -#include -#include -#include -#include - -#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); -} diff --git a/src/lib/lttng-ctl/rotate.cpp b/src/lib/lttng-ctl/rotate.cpp new file mode 100644 index 000000000..6a003a18e --- /dev/null +++ b/src/lib/lttng-ctl/rotate.cpp @@ -0,0 +1,666 @@ +/* + * Copyright (C) 2017 Julien Desfossez + * + * SPDX-License-Identifier: LGPL-2.1-only + * + */ + +#define _LGPL_SOURCE +#include + +#include +#include +#include +#include +#include +#include + +#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); +} diff --git a/src/lib/lttng-ctl/save.c b/src/lib/lttng-ctl/save.c deleted file mode 100644 index c8d8ac9c2..000000000 --- a/src/lib/lttng-ctl/save.c +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright (C) 2013 Jérémie Galarneau - * - * SPDX-License-Identifier: LGPL-2.1-only - * - */ - -#define _LGPL_SOURCE -#include - -#include -#include -#include -#include - -#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; -} diff --git a/src/lib/lttng-ctl/save.cpp b/src/lib/lttng-ctl/save.cpp new file mode 100644 index 000000000..45894277a --- /dev/null +++ b/src/lib/lttng-ctl/save.cpp @@ -0,0 +1,217 @@ +/* + * Copyright (C) 2013 Jérémie Galarneau + * + * SPDX-License-Identifier: LGPL-2.1-only + * + */ + +#define _LGPL_SOURCE +#include + +#include +#include +#include +#include + +#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; +} diff --git a/src/lib/lttng-ctl/snapshot.c b/src/lib/lttng-ctl/snapshot.c deleted file mode 100644 index e90062352..000000000 --- a/src/lib/lttng-ctl/snapshot.c +++ /dev/null @@ -1,501 +0,0 @@ -/* - * Copyright (C) 2013 David Goulet - * - * SPDX-License-Identifier: LGPL-2.1-only - * - */ - -#define _LGPL_SOURCE -#include - -#include -#include -#include -#include - -#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; -} diff --git a/src/lib/lttng-ctl/snapshot.cpp b/src/lib/lttng-ctl/snapshot.cpp new file mode 100644 index 000000000..543861d67 --- /dev/null +++ b/src/lib/lttng-ctl/snapshot.cpp @@ -0,0 +1,501 @@ +/* + * Copyright (C) 2013 David Goulet + * + * SPDX-License-Identifier: LGPL-2.1-only + * + */ + +#define _LGPL_SOURCE +#include + +#include +#include +#include +#include + +#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; +} diff --git a/src/lib/lttng-ctl/tracker.c b/src/lib/lttng-ctl/tracker.c deleted file mode 100644 index 4eae95fc5..000000000 --- a/src/lib/lttng-ctl/tracker.c +++ /dev/null @@ -1,784 +0,0 @@ -/* - * Copyright (C) 2020 Jérémie Galarneau - * - * SPDX-License-Identifier: LGPL-2.1-only - * - */ - -#include "lttng-ctl-helper.h" -#include "lttng/domain.h" -#include "lttng/lttng-error.h" -#include -#include -#include - -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; -} diff --git a/src/lib/lttng-ctl/tracker.cpp b/src/lib/lttng-ctl/tracker.cpp new file mode 100644 index 000000000..1259729ea --- /dev/null +++ b/src/lib/lttng-ctl/tracker.cpp @@ -0,0 +1,784 @@ +/* + * Copyright (C) 2020 Jérémie Galarneau + * + * SPDX-License-Identifier: LGPL-2.1-only + * + */ + +#include "lttng-ctl-helper.h" +#include "lttng/domain.h" +#include "lttng/lttng-error.h" +#include +#include +#include + +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; +} diff --git a/tests/regression/tools/health/health_fail.c b/tests/regression/tools/health/health_fail.c index ca2bc3485..6a4c8f08a 100644 --- a/tests/regression/tools/health/health_fail.c +++ b/tests/regression/tools/health/health_fail.c @@ -6,6 +6,7 @@ * */ +#include #include #include #include @@ -30,7 +31,7 @@ int check_env_var(const char *env) /* 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"; @@ -42,7 +43,7 @@ int __testpoint_sessiond_thread_manage_clients(void) 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"; @@ -54,7 +55,7 @@ int __testpoint_sessiond_thread_registration_apps(void) 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"; @@ -66,7 +67,7 @@ int __testpoint_sessiond_thread_manage_apps(void) 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"; @@ -78,7 +79,7 @@ int __testpoint_sessiond_thread_manage_kernel(void) 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"; @@ -90,7 +91,7 @@ int __testpoint_sessiond_thread_manage_consumer(void) 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"; @@ -102,7 +103,7 @@ int __testpoint_sessiond_thread_ht_cleanup(void) 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"; @@ -114,7 +115,7 @@ int __testpoint_sessiond_thread_app_manage_notify(void) 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"; @@ -128,7 +129,7 @@ int __testpoint_sessiond_thread_app_reg_dispatch(void) /* 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"; @@ -140,7 +141,7 @@ int __testpoint_consumerd_thread_channel(void) 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"; @@ -152,7 +153,7 @@ int __testpoint_consumerd_thread_metadata(void) 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"; @@ -164,7 +165,7 @@ int __testpoint_consumerd_thread_data(void) 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"; @@ -176,7 +177,7 @@ int __testpoint_consumerd_thread_sessiond(void) 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"; @@ -190,7 +191,7 @@ int __testpoint_consumerd_thread_metadata_timer(void) /* 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"; @@ -202,7 +203,7 @@ int __testpoint_relayd_thread_dispatcher(void) 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"; @@ -214,7 +215,7 @@ int __testpoint_relayd_thread_worker(void) 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"; @@ -226,7 +227,7 @@ int __testpoint_relayd_thread_listener(void) 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"; @@ -238,7 +239,7 @@ int __testpoint_relayd_thread_live_dispatcher(void) 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"; @@ -250,7 +251,7 @@ int __testpoint_relayd_thread_live_worker(void) 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"; diff --git a/tests/regression/tools/health/health_stall.c b/tests/regression/tools/health/health_stall.c index 1c0d6dc77..e89966315 100644 --- a/tests/regression/tools/health/health_stall.c +++ b/tests/regression/tools/health/health_stall.c @@ -6,6 +6,7 @@ * */ +#include #include #include #include @@ -43,7 +44,7 @@ void do_stall(void) /* 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"; @@ -55,7 +56,7 @@ int __testpoint_sessiond_thread_manage_clients(void) 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"; @@ -67,7 +68,7 @@ int __testpoint_sessiond_thread_registration_apps(void) 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"; @@ -79,7 +80,7 @@ int __testpoint_sessiond_thread_manage_apps(void) 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"; @@ -91,7 +92,7 @@ int __testpoint_sessiond_thread_manage_kernel(void) 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"; @@ -103,7 +104,7 @@ int __testpoint_sessiond_thread_manage_consumer(void) 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"; @@ -115,7 +116,7 @@ int __testpoint_sessiond_thread_ht_cleanup(void) 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"; @@ -127,7 +128,7 @@ int __testpoint_sessiond_thread_app_manage_notify(void) 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"; @@ -141,7 +142,7 @@ int __testpoint_sessiond_thread_app_reg_dispatch(void) /* 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"; @@ -153,7 +154,7 @@ int __testpoint_consumerd_thread_channel(void) 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"; @@ -165,7 +166,7 @@ int __testpoint_consumerd_thread_metadata(void) 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"; @@ -177,7 +178,7 @@ int __testpoint_consumerd_thread_data(void) 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"; @@ -189,7 +190,7 @@ int __testpoint_consumerd_thread_sessiond(void) 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"; @@ -203,7 +204,7 @@ int __testpoint_consumerd_thread_metadata_timer(void) /* 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"; @@ -215,7 +216,7 @@ int __testpoint_relayd_thread_dispatcher(void) 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"; @@ -227,7 +228,7 @@ int __testpoint_relayd_thread_worker(void) 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"; @@ -239,7 +240,7 @@ int __testpoint_relayd_thread_listener(void) 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"; @@ -251,7 +252,7 @@ int __testpoint_relayd_thread_live_dispatcher(void) 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"; @@ -263,7 +264,7 @@ int __testpoint_relayd_thread_live_worker(void) 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"; diff --git a/tests/regression/tools/live/live_test.c b/tests/regression/tools/live/live_test.c index b428f1add..40d0f6270 100644 --- a/tests/regression/tools/live/live_test.c +++ b/tests/regression/tools/live/live_test.c @@ -41,8 +41,9 @@ #define mmap_size 524288 #ifdef HAVE_LIBLTTNG_UST_CTL +#include #include -DEFINE_LTTNG_UST_SIGBUS_STATE(); +LTTNG_EXPORT DEFINE_LTTNG_UST_SIGBUS_STATE(); #endif static int control_sock; diff --git a/tests/regression/tools/notification/consumer_testpoints.c b/tests/regression/tools/notification/consumer_testpoints.c index c4fc0a057..6294683f9 100644 --- a/tests/regression/tools/notification/consumer_testpoints.c +++ b/tests/regression/tools/notification/consumer_testpoints.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -46,7 +47,7 @@ void __attribute__((destructor)) pause_pipe_fini(void) * 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; @@ -106,7 +107,7 @@ end: 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; diff --git a/tests/regression/tools/notification/sessiond_testpoints.c b/tests/regression/tools/notification/sessiond_testpoints.c index 21f04cda7..2bfd7cab7 100644 --- a/tests/regression/tools/notification/sessiond_testpoints.c +++ b/tests/regression/tools/notification/sessiond_testpoints.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -42,7 +43,7 @@ void __attribute__((destructor)) pause_pipe_fini(void) 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; @@ -79,7 +80,7 @@ end: 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; diff --git a/tests/regression/ust/clock-override/lttng-ust-clock-override-test.c b/tests/regression/ust/clock-override/lttng-ust-clock-override-test.c index dace1d99c..a12a5b76b 100644 --- a/tests/regression/ust/clock-override/lttng-ust-clock-override-test.c +++ b/tests/regression/ust/clock-override/lttng-ust-clock-override-test.c @@ -14,6 +14,7 @@ #include #include #include +#include #include static @@ -49,7 +50,7 @@ const char *plugin_description(void) 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; diff --git a/tests/regression/ust/getcpu-override/lttng-ust-getcpu-override-test.c b/tests/regression/ust/getcpu-override/lttng-ust-getcpu-override-test.c index 976bcb231..dbe6c1d86 100644 --- a/tests/regression/ust/getcpu-override/lttng-ust-getcpu-override-test.c +++ b/tests/regression/ust/getcpu-override/lttng-ust-getcpu-override-test.c @@ -14,6 +14,7 @@ #include #include #include +#include #include static long nprocessors; @@ -58,7 +59,7 @@ int plugin_getcpu(void) 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; diff --git a/tests/regression/ust/multi-lib/callsites.h b/tests/regression/ust/multi-lib/callsites.h index 059d8f791..117aae8d3 100644 --- a/tests/regression/ust/multi-lib/callsites.h +++ b/tests/regression/ust/multi-lib/callsites.h @@ -7,5 +7,9 @@ #ifndef CALLSITES_H #define CALLSITES_H -void call_tracepoint(void); + +#include + +LTTNG_EXPORT void call_tracepoint(void); + #endif /* CALLSITES_H */ diff --git a/tests/regression/ust/ust-dl/libbar.h b/tests/regression/ust/ust-dl/libbar.h index a7f77458f..1f1a0bbfd 100644 --- a/tests/regression/ust/ust-dl/libbar.h +++ b/tests/regression/ust/ust-dl/libbar.h @@ -8,6 +8,8 @@ #ifndef _LIBBAR_H #define _LIBBAR_H -int bar(void); +#include + +LTTNG_EXPORT int bar(void); #endif /* _LIBBAR_H */ diff --git a/tests/regression/ust/ust-dl/libfoo.h b/tests/regression/ust/ust-dl/libfoo.h index f33442850..43ae5b9b8 100644 --- a/tests/regression/ust/ust-dl/libfoo.h +++ b/tests/regression/ust/ust-dl/libfoo.h @@ -8,6 +8,8 @@ #ifndef _LIBFOO_H #define _LIBFOO_H -int foo(void); +#include + +LTTNG_EXPORT int foo(void); #endif /* _LIBFOO_H */ diff --git a/tests/unit/test_kernel_data.cpp b/tests/unit/test_kernel_data.cpp index 79489e3d3..6f0ce872b 100644 --- a/tests/unit/test_kernel_data.cpp +++ b/tests/unit/test_kernel_data.cpp @@ -23,8 +23,9 @@ #define NUM_TESTS 11 #ifdef HAVE_LIBLTTNG_UST_CTL +#include #include -DEFINE_LTTNG_UST_SIGBUS_STATE(); +LTTNG_EXPORT DEFINE_LTTNG_UST_SIGBUS_STATE(); #endif static const char alphanum[] = diff --git a/tests/unit/test_ust_data.cpp b/tests/unit/test_ust_data.cpp index a6dfba429..f1b197ea9 100644 --- a/tests/unit/test_ust_data.cpp +++ b/tests/unit/test_ust_data.cpp @@ -32,7 +32,7 @@ /* 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" diff --git a/tests/unit/ust-sigbus.c b/tests/unit/ust-sigbus.c index 4dbdddefa..3b9dd771d 100644 --- a/tests/unit/ust-sigbus.c +++ b/tests/unit/ust-sigbus.c @@ -5,6 +5,7 @@ * */ +#include #include -DEFINE_LTTNG_UST_SIGBUS_STATE(); +LTTNG_EXPORT DEFINE_LTTNG_UST_SIGBUS_STATE(); diff --git a/tests/utils/testapp/userspace-probe-elf-binary/foo.h b/tests/utils/testapp/userspace-probe-elf-binary/foo.h index d1d79eeae..fb1f19de3 100644 --- a/tests/utils/testapp/userspace-probe-elf-binary/foo.h +++ b/tests/utils/testapp/userspace-probe-elf-binary/foo.h @@ -5,4 +5,6 @@ * */ -int dynamic_symbol(int a); +#include + +LTTNG_EXPORT int dynamic_symbol(int a);