#define _LGPL_SOURCE
#include <inttypes.h>
-#include <common/common.h>
-#include <common/hashtable/utils.h>
+#include <common/common.hpp>
+#include <common/hashtable/utils.hpp>
+#include <common/exception.hpp>
#include <lttng/lttng.h>
-#include "ust-registry.h"
-#include "ust-app.h"
-#include "ust-field-utils.h"
-#include "utils.h"
-#include "lttng-sessiond.h"
-#include "notification-thread-commands.h"
-
+#include "ust-registry.hpp"
+#include "ust-app.hpp"
+#include "ust-field-utils.hpp"
+#include "utils.hpp"
+#include "lttng-sessiond.hpp"
+#include "notification-thread-commands.hpp"
/*
* Hash table match function for event in the registry.
{
const struct ust_registry_event *key;
struct ust_registry_event *event;
- int i;
LTTNG_ASSERT(node);
LTTNG_ASSERT(_key);
goto no_match;
}
- /* Compare the number of fields. */
- if (event->nr_fields != key->nr_fields) {
+ /* Compare the arrays of fields. */
+ if (!match_lttng_ust_ctl_field_array(event->fields, event->nr_fields,
+ key->fields, key->nr_fields)) {
goto no_match;
}
- /* Compare each field individually. */
- for (i = 0; i < event->nr_fields; i++) {
- if (!match_lttng_ust_ctl_field(&event->fields[i], &key->fields[i])) {
- goto no_match;
- }
- }
-
/* Compare model URI. */
if (event->model_emf_uri != NULL && key->model_emf_uri == NULL) {
goto no_match;
return NULL;
}
- event = (ust_registry_event *) zmalloc(sizeof(*event));
+ event = zmalloc<ust_registry_event>();
if (!event) {
PERROR("zmalloc ust registry event");
goto error;
/*
* Free event data structure. This does NOT delete it from any hash table. It's
- * safe to pass a NULL pointer. This shoudl be called inside a call RCU if the
+ * safe to pass a NULL pointer. This should be called inside a call RCU if the
* event is previously deleted from a rcu hash table.
*/
static void destroy_event(struct ust_registry_event *event)
LTTNG_ASSERT(chan);
LTTNG_ASSERT(name);
LTTNG_ASSERT(sig);
+ ASSERT_RCU_READ_LOCKED();
/* Setup key for the match function. */
strncpy(key.name, name, sizeof(key.name));
key.name[sizeof(key.name) - 1] = '\0';
key.signature = sig;
- cds_lfht_lookup(chan->ht->ht, chan->ht->hash_fct(&key, lttng_ht_seed),
- chan->ht->match_fct, &key, &iter.iter);
+ cds_lfht_lookup(chan->events->ht, chan->events->hash_fct(&key, lttng_ht_seed),
+ chan->events->match_fct, &key, &iter.iter);
node = lttng_ht_iter_get_node_u64(&iter);
if (!node) {
goto end;
*
* Should be called with session registry mutex held.
*/
-int ust_registry_create_event(struct ust_registry_session *session,
+int ust_registry_create_event(ust_registry_session *session,
uint64_t chan_key, int session_objd, int channel_objd, char *name,
char *sig, size_t nr_fields, struct lttng_ust_ctl_field *fields,
int loglevel_value, char *model_emf_uri, int buffer_type,
* This is an add unique with a custom match function for event. The node
* are matched using the event name and signature.
*/
- nptr = cds_lfht_add_unique(chan->ht->ht, chan->ht->hash_fct(event,
- lttng_ht_seed), chan->ht->match_fct, event, &event->node.node);
+ nptr = cds_lfht_add_unique(chan->events->ht, chan->events->hash_fct(event,
+ lttng_ht_seed), chan->events->match_fct, event, &event->node.node);
if (nptr != &event->node.node) {
if (buffer_type == LTTNG_BUFFER_PER_UID) {
/*
LTTNG_ASSERT(chan);
LTTNG_ASSERT(event);
+ ASSERT_RCU_READ_LOCKED();
/* Delete the node first. */
iter.iter.node = &event->node.node;
- ret = lttng_ht_del(chan->ht, &iter);
+ ret = lttng_ht_del(chan->events, &iter);
LTTNG_ASSERT(!ret);
call_rcu(&event->node.head, destroy_event_rcu);
* Needs to be called from RCU read-side critical section.
*/
static struct ust_registry_enum *ust_registry_lookup_enum(
- struct ust_registry_session *session,
+ ust_registry_session *session,
const struct ust_registry_enum *reg_enum_lookup)
{
struct ust_registry_enum *reg_enum = NULL;
struct lttng_ht_node_str *node;
struct lttng_ht_iter iter;
- cds_lfht_lookup(session->enums->ht,
+ ASSERT_RCU_READ_LOCKED();
+
+ cds_lfht_lookup(session->_enums->ht,
ht_hash_enum((void *) reg_enum_lookup, lttng_ht_seed),
ht_match_enum, reg_enum_lookup, &iter.iter);
node = lttng_ht_iter_get_node_str(&iter);
* Needs to be called from RCU read-side critical section.
*/
struct ust_registry_enum *
- ust_registry_lookup_enum_by_id(struct ust_registry_session *session,
+ ust_registry_lookup_enum_by_id(ust_registry_session *session,
const char *enum_name, uint64_t enum_id)
{
struct ust_registry_enum *reg_enum = NULL;
struct lttng_ht_iter iter;
struct ust_registry_enum reg_enum_lookup;
+ ASSERT_RCU_READ_LOCKED();
+
memset(®_enum_lookup, 0, sizeof(reg_enum_lookup));
strncpy(reg_enum_lookup.name, enum_name, LTTNG_UST_ABI_SYM_NAME_LEN);
reg_enum_lookup.name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
reg_enum_lookup.id = enum_id;
- cds_lfht_lookup(session->enums->ht,
+ cds_lfht_lookup(session->_enums->ht,
ht_hash_enum((void *) ®_enum_lookup, lttng_ht_seed),
ht_match_enum_id, ®_enum_lookup, &iter.iter);
node = lttng_ht_iter_get_node_str(&iter);
*
* We receive ownership of entries.
*/
-int ust_registry_create_or_find_enum(struct ust_registry_session *session,
+int ust_registry_create_or_find_enum(ust_registry_session *session,
int session_objd, char *enum_name,
struct lttng_ust_ctl_enum_entry *entries, size_t nr_entries,
uint64_t *enum_id)
}
/* Check if the enumeration was already dumped */
- reg_enum = (ust_registry_enum *) zmalloc(sizeof(*reg_enum));
+ reg_enum = zmalloc<ust_registry_enum>();
if (!reg_enum) {
PERROR("zmalloc ust registry enumeration");
ret = -ENOMEM;
} else {
DBG("UST registry creating enum: %s, sess_objd: %u",
enum_name, session_objd);
- if (session->next_enum_id == -1ULL) {
+ if (session->_next_enum_id == -1ULL) {
ret = -EOVERFLOW;
destroy_enum(reg_enum);
goto end;
}
- reg_enum->id = session->next_enum_id++;
+ reg_enum->id = session->_next_enum_id++;
cds_lfht_node_init(®_enum->node.node);
- nodep = cds_lfht_add_unique(session->enums->ht,
+ nodep = cds_lfht_add_unique(session->_enums->ht,
ht_hash_enum(reg_enum, lttng_ht_seed),
ht_match_enum_id, reg_enum,
®_enum->node.node);
* the enumeration.
* This MUST be called within a RCU read side lock section.
*/
-static void ust_registry_destroy_enum(struct ust_registry_session *reg_session,
+void ust_registry_destroy_enum(ust_registry_session *reg_session,
struct ust_registry_enum *reg_enum)
{
int ret;
LTTNG_ASSERT(reg_session);
LTTNG_ASSERT(reg_enum);
+ ASSERT_RCU_READ_LOCKED();
/* Delete the node first. */
iter.iter.node = ®_enum->node.node;
- ret = lttng_ht_del(reg_session->enums, &iter);
+ ret = lttng_ht_del(reg_session->_enums.get(), &iter);
LTTNG_ASSERT(!ret);
call_rcu(®_enum->rcu_head, destroy_enum_rcu);
}
-/*
- * We need to execute ht_destroy outside of RCU read-side critical
- * section and outside of call_rcu thread, so we postpone its execution
- * using ht_cleanup_push. It is simpler than to change the semantic of
- * the many callers of delete_ust_app_session().
- */
static
void destroy_channel_rcu(struct rcu_head *head)
{
struct ust_registry_channel *chan =
caa_container_of(head, struct ust_registry_channel, rcu_head);
- if (chan->ht) {
- ht_cleanup_push(chan->ht);
+ if (chan->events) {
+ lttng_ht_destroy(chan->events);
}
+
free(chan->ctx_fields);
free(chan);
}
* free the registry pointer since it might not have been allocated before so
* it's the caller responsability.
*/
-static void destroy_channel(struct ust_registry_channel *chan, bool notif)
+void ust_registry_channel_destroy(struct ust_registry_channel *chan, bool notify)
{
struct lttng_ht_iter iter;
struct ust_registry_event *event;
LTTNG_ASSERT(chan);
- if (notif) {
+ if (notify) {
cmd_ret = notification_thread_command_remove_channel(
the_notification_thread_handle,
chan->consumer_key, LTTNG_DOMAIN_UST);
}
}
- if (chan->ht) {
+ if (chan->events) {
rcu_read_lock();
/* Destroy all event associated with this registry. */
cds_lfht_for_each_entry(
- chan->ht->ht, &iter.iter, event, node.node) {
+ chan->events->ht, &iter.iter, event, node.node) {
/* Delete the node from the ht and free it. */
ust_registry_destroy_event(chan, event);
}
/*
* Initialize registry with default values.
*/
-int ust_registry_channel_add(struct ust_registry_session *session,
+int ust_registry_channel_add(ust_registry_session *session,
uint64_t key)
{
int ret = 0;
LTTNG_ASSERT(session);
- chan = (ust_registry_channel *) zmalloc(sizeof(*chan));
+ chan = zmalloc<ust_registry_channel>();
if (!chan) {
PERROR("zmalloc ust registry channel");
ret = -ENOMEM;
goto error_alloc;
}
- chan->ht = lttng_ht_new(0, LTTNG_HT_TYPE_STRING);
- if (!chan->ht) {
+ chan->events = lttng_ht_new(0, LTTNG_HT_TYPE_STRING);
+ if (!chan->events) {
ret = -ENOMEM;
goto error;
}
/* Set custom match function. */
- chan->ht->match_fct = ht_match_event;
- chan->ht->hash_fct = ht_hash_event;
+ chan->events->match_fct = ht_match_event;
+ chan->events->hash_fct = ht_hash_event;
/*
* Assign a channel ID right now since the event notification comes
* *before* the channel notify so the ID needs to be set at this point so
* the metadata can be dumped for that event.
*/
- if (ust_registry_is_max_id(session->used_channel_id)) {
+ if (ust_registry_is_max_id(session->_used_channel_id)) {
ret = -1;
goto error;
}
rcu_read_lock();
lttng_ht_node_init_u64(&chan->node, key);
- lttng_ht_add_unique_u64(session->channels, &chan->node);
+ lttng_ht_add_unique_u64(session->_channels.get(), &chan->node);
rcu_read_unlock();
return 0;
error:
- destroy_channel(chan, false);
+ ust_registry_channel_destroy(chan, false);
error_alloc:
return ret;
}
* On success, the pointer is returned else NULL.
*/
struct ust_registry_channel *ust_registry_channel_find(
- struct ust_registry_session *session, uint64_t key)
+ ust_registry_session *session, uint64_t key)
{
struct lttng_ht_node_u64 *node;
struct lttng_ht_iter iter;
struct ust_registry_channel *chan = NULL;
LTTNG_ASSERT(session);
- LTTNG_ASSERT(session->channels);
+ LTTNG_ASSERT(session->_channels);
+ ASSERT_RCU_READ_LOCKED();
DBG3("UST registry channel finding key %" PRIu64, key);
- lttng_ht_lookup(session->channels, &key, &iter);
+ lttng_ht_lookup(session->_channels.get(), &key, &iter);
node = lttng_ht_iter_get_node_u64(&iter);
if (!node) {
goto end;
/*
* Remove channel using key from registry and free memory.
*/
-void ust_registry_channel_del_free(struct ust_registry_session *session,
+void ust_registry_channel_del_free(ust_registry_session *session,
uint64_t key, bool notif)
{
struct lttng_ht_iter iter;
}
iter.iter.node = &chan->node.node;
- ret = lttng_ht_del(session->channels, &iter);
+ ret = lttng_ht_del(session->_channels.get(), &iter);
LTTNG_ASSERT(!ret);
rcu_read_unlock();
- destroy_channel(chan, notif);
+ ust_registry_channel_destroy(chan, notif);
end:
return;
}
-/*
- * Initialize registry with default values and set the newly allocated session
- * pointer to sessionp.
- *
- * Return 0 on success and sessionp is set or else return -1 and sessionp is
- * kept untouched.
- */
-int ust_registry_session_init(struct ust_registry_session **sessionp,
- struct ust_app *app,
- uint32_t bits_per_long,
+ust_registry_session *ust_registry_session_per_uid_create(uint32_t bits_per_long,
uint32_t uint8_t_alignment,
uint32_t uint16_t_alignment,
uint32_t uint32_t_alignment,
uint64_t tracing_id,
uid_t tracing_uid)
{
- int ret;
- struct ust_registry_session *session;
-
- LTTNG_ASSERT(sessionp);
-
- session = (ust_registry_session *) zmalloc(sizeof(*session));
- if (!session) {
- PERROR("zmalloc ust registry session");
- goto error_alloc;
- }
-
- pthread_mutex_init(&session->lock, NULL);
- session->bits_per_long = bits_per_long;
- session->uint8_t_alignment = uint8_t_alignment;
- session->uint16_t_alignment = uint16_t_alignment;
- session->uint32_t_alignment = uint32_t_alignment;
- session->uint64_t_alignment = uint64_t_alignment;
- session->long_alignment = long_alignment;
- session->byte_order = byte_order;
- session->metadata_fd = -1;
- session->uid = euid;
- session->gid = egid;
- session->next_enum_id = 0;
- session->major = major;
- session->minor = minor;
- strncpy(session->root_shm_path, root_shm_path,
- sizeof(session->root_shm_path));
- session->root_shm_path[sizeof(session->root_shm_path) - 1] = '\0';
- if (shm_path[0]) {
- strncpy(session->shm_path, shm_path,
- sizeof(session->shm_path));
- session->shm_path[sizeof(session->shm_path) - 1] = '\0';
- strncpy(session->metadata_path, shm_path,
- sizeof(session->metadata_path));
- session->metadata_path[sizeof(session->metadata_path) - 1] = '\0';
- strncat(session->metadata_path, "/metadata",
- sizeof(session->metadata_path)
- - strlen(session->metadata_path) - 1);
- }
- if (session->shm_path[0]) {
- ret = run_as_mkdir_recursive(session->shm_path,
- S_IRWXU | S_IRWXG,
- euid, egid);
- if (ret) {
- PERROR("run_as_mkdir_recursive");
- goto error;
- }
- }
- if (session->metadata_path[0]) {
- /* Create metadata file */
- ret = run_as_open(session->metadata_path,
- O_WRONLY | O_CREAT | O_EXCL,
- S_IRUSR | S_IWUSR, euid, egid);
- if (ret < 0) {
- PERROR("Opening metadata file");
- goto error;
- }
- session->metadata_fd = ret;
+ try {
+ return new ust_registry_session_per_uid(bits_per_long, uint8_t_alignment,
+ uint16_t_alignment, uint32_t_alignment, uint64_t_alignment,
+ long_alignment, byte_order, major, minor, root_shm_path, shm_path,
+ euid, egid, tracing_id, tracing_uid);
+ } catch (const std::exception &ex) {
+ ERR("Failed to create per-uid registry session: %s", ex.what());
+ return nullptr;
}
+}
- session->enums = lttng_ht_new(0, LTTNG_HT_TYPE_STRING);
- if (!session->enums) {
- ERR("Failed to create enums hash table");
- goto error;
- }
- /* hash/match functions are specified at call site. */
- session->enums->match_fct = NULL;
- session->enums->hash_fct = NULL;
-
- session->channels = lttng_ht_new(0, LTTNG_HT_TYPE_U64);
- if (!session->channels) {
- goto error;
- }
-
- ret = lttng_uuid_generate(session->uuid);
- if (ret) {
- ERR("Failed to generate UST uuid (errno = %d)", ret);
- goto error;
- }
-
- session->tracing_id = tracing_id;
- session->tracing_uid = tracing_uid;
-
- pthread_mutex_lock(&session->lock);
- ret = ust_metadata_session_statedump(session, app, major, minor);
- pthread_mutex_unlock(&session->lock);
- if (ret) {
- ERR("Failed to generate session metadata (errno = %d)", ret);
- goto error;
+ust_registry_session *ust_registry_session_per_pid_create(struct ust_app *app,
+ uint32_t bits_per_long,
+ uint32_t uint8_t_alignment,
+ uint32_t uint16_t_alignment,
+ uint32_t uint32_t_alignment,
+ uint32_t uint64_t_alignment,
+ uint32_t long_alignment,
+ int byte_order,
+ uint32_t major,
+ uint32_t minor,
+ const char *root_shm_path,
+ const char *shm_path,
+ uid_t euid,
+ gid_t egid,
+ uint64_t tracing_id)
+{
+ try {
+ return new ust_registry_session_per_pid(*app, bits_per_long, uint8_t_alignment,
+ uint16_t_alignment, uint32_t_alignment, uint64_t_alignment,
+ long_alignment, byte_order, major, minor, root_shm_path, shm_path,
+ euid, egid, tracing_id);
+ } catch (const std::exception &ex) {
+ ERR("Failed to create per-pid registry session: %s", ex.what());
+ return nullptr;
}
-
- *sessionp = session;
-
- return 0;
-
-error:
- ust_registry_session_destroy(session);
- free(session);
-error_alloc:
- return -1;
}
/*
* Destroy session registry. This does NOT free the given pointer since it
* might get passed as a reference. The registry lock should NOT be acquired.
*/
-void ust_registry_session_destroy(struct ust_registry_session *reg)
+void ust_registry_session_destroy(ust_registry_session *reg)
{
- int ret;
- struct lttng_ht_iter iter;
- struct ust_registry_channel *chan;
- struct ust_registry_enum *reg_enum;
-
- if (!reg) {
- return;
- }
-
- /* On error, EBUSY can be returned if lock. Code flow error. */
- ret = pthread_mutex_destroy(®->lock);
- LTTNG_ASSERT(!ret);
-
- if (reg->channels) {
- rcu_read_lock();
- /* Destroy all event associated with this registry. */
- cds_lfht_for_each_entry(reg->channels->ht, &iter.iter, chan,
- node.node) {
- /* Delete the node from the ht and free it. */
- ret = lttng_ht_del(reg->channels, &iter);
- LTTNG_ASSERT(!ret);
- destroy_channel(chan, true);
- }
- rcu_read_unlock();
- ht_cleanup_push(reg->channels);
- }
-
- free(reg->metadata);
- if (reg->metadata_fd >= 0) {
- ret = close(reg->metadata_fd);
- if (ret) {
- PERROR("close");
- }
- ret = run_as_unlink(reg->metadata_path,
- reg->uid, reg->gid);
- if (ret) {
- PERROR("unlink");
- }
- }
- if (reg->root_shm_path[0]) {
- /*
- * Try deleting the directory hierarchy.
- */
- (void) run_as_rmdir_recursive(reg->root_shm_path,
- reg->uid, reg->gid,
- LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG);
- }
- /* Destroy the enum hash table */
- if (reg->enums) {
- rcu_read_lock();
- /* Destroy all enum entries associated with this registry. */
- cds_lfht_for_each_entry(reg->enums->ht, &iter.iter, reg_enum,
- node.node) {
- ust_registry_destroy_enum(reg, reg_enum);
- }
- rcu_read_unlock();
- ht_cleanup_push(reg->enums);
- }
+ delete reg;
}