#include <common/sessiond-comm/sessiond-comm.h>
#include <common/macros.h>
#include <lttng/condition/condition.h>
-#include <lttng/action/action.h>
+#include <lttng/action/action-internal.h>
#include <lttng/notification/notification-internal.h>
#include <lttng/condition/condition-internal.h>
#include <lttng/condition/buffer-usage-internal.h>
#define CLIENT_POLL_MASK_IN_OUT (CLIENT_POLL_MASK_IN | LPOLLOUT)
struct lttng_trigger_list_element {
- struct lttng_trigger *trigger;
+ /* No ownership of the trigger object is assumed. */
+ const struct lttng_trigger *trigger;
struct cds_list_head node;
};
uint64_t latest_session_consumed_total,
struct channel_info *channel_info);
static
-int send_evaluation_to_clients(struct lttng_trigger *trigger,
- struct lttng_evaluation *evaluation,
+int send_evaluation_to_clients(const struct lttng_trigger *trigger,
+ const struct lttng_evaluation *evaluation,
struct notification_client_list *client_list,
struct notification_thread_state *state,
uid_t channel_uid, gid_t channel_gid);
static
unsigned long lttng_condition_buffer_usage_hash(
- struct lttng_condition *_condition)
+ const struct lttng_condition *_condition)
{
- unsigned long hash = 0;
+ unsigned long hash;
+ unsigned long condition_type;
struct lttng_condition_buffer_usage *condition;
condition = container_of(_condition,
struct lttng_condition_buffer_usage, parent);
+ condition_type = (unsigned long) condition->parent.type;
+ hash = hash_key_ulong((void *) condition_type, lttng_ht_seed);
if (condition->session_name) {
hash ^= hash_key_str(condition->session_name, lttng_ht_seed);
}
static
unsigned long lttng_condition_session_consumed_size_hash(
- struct lttng_condition *_condition)
+ const struct lttng_condition *_condition)
{
- unsigned long hash = 0;
+ unsigned long hash;
+ unsigned long condition_type =
+ (unsigned long) LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE;
struct lttng_condition_session_consumed_size *condition;
uint64_t val;
condition = container_of(_condition,
struct lttng_condition_session_consumed_size, parent);
+ hash = hash_key_ulong((void *) condition_type, lttng_ht_seed);
if (condition->session_name) {
hash ^= hash_key_str(condition->session_name, lttng_ht_seed);
}
return hash;
}
+
/*
* The lttng_condition hashing code is kept in this file (rather than
* condition.c) since it makes use of GPLv2 code (hashtable utils), which we
* don't want to link in liblttng-ctl.
*/
static
-unsigned long lttng_condition_hash(struct lttng_condition *condition)
+unsigned long lttng_condition_hash(const struct lttng_condition *condition)
{
switch (condition->type) {
case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
struct lttng_trigger_list_element *element;
cds_list_for_each_entry(element, &channel_trigger_list->list, node) {
- struct lttng_condition *current_condition =
- lttng_trigger_get_condition(
+ const struct lttng_condition *current_condition =
+ lttng_trigger_get_const_condition(
element->trigger);
assert(current_condition);
client, state)) {
WARN("[notification-thread] Evaluation of a condition on client subscription failed, aborting.");
ret = -1;
+ free(client_list_element);
goto end_unlock;
}
name, uid, gid);
goto end;
}
+
+ cds_lfht_add(state->sessions_ht, hash_key_str(name, lttng_ht_seed),
+ &session->sessions_ht_node);
end:
rcu_read_unlock();
return session;
cds_list_for_each_entry_safe(trigger_element, tmp,
&trigger_list->list, node) {
- struct lttng_condition *current_condition =
- lttng_trigger_get_condition(
+ const struct lttng_condition *current_condition =
+ lttng_trigger_get_const_condition(
trigger_element->trigger);
assert(current_condition);
break;
case LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE:
*evaluation = lttng_evaluation_session_consumed_size_create(
- condition_type,
latest_session_consumed_total);
break;
default:
}
static
-int send_evaluation_to_clients(struct lttng_trigger *trigger,
- struct lttng_evaluation *evaluation,
+int send_evaluation_to_clients(const struct lttng_trigger *trigger,
+ const struct lttng_evaluation *evaluation,
struct notification_client_list* client_list,
struct notification_thread_state *state,
uid_t channel_uid, gid_t channel_gid)
int ret = 0;
struct lttng_dynamic_buffer msg_buffer;
struct notification_client_list_element *client_list_element, *tmp;
- struct lttng_notification *notification;
- struct lttng_condition *condition;
- ssize_t expected_notification_size, notification_size;
- struct lttng_notification_channel_message msg;
+ const struct lttng_notification notification = {
+ .condition = (struct lttng_condition *) lttng_trigger_get_const_condition(trigger),
+ .evaluation = (struct lttng_evaluation *) evaluation,
+ };
+ struct lttng_notification_channel_message msg_header = {
+ .type = (int8_t) LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_NOTIFICATION,
+ };
lttng_dynamic_buffer_init(&msg_buffer);
- condition = lttng_trigger_get_condition(trigger);
- assert(condition);
-
- notification = lttng_notification_create(condition, evaluation);
- if (!notification) {
- ret = -1;
- goto end;
- }
-
- expected_notification_size = lttng_notification_serialize(notification,
- NULL);
- if (expected_notification_size < 0) {
- ERR("[notification-thread] Failed to get size of serialized notification");
- ret = -1;
- goto end;
- }
-
- msg.type = (int8_t) LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_NOTIFICATION;
- msg.size = (uint32_t) expected_notification_size;
- ret = lttng_dynamic_buffer_append(&msg_buffer, &msg, sizeof(msg));
+ ret = lttng_dynamic_buffer_append(&msg_buffer, &msg_header,
+ sizeof(msg_header));
if (ret) {
goto end;
}
- ret = lttng_dynamic_buffer_set_size(&msg_buffer,
- msg_buffer.size + expected_notification_size);
+ ret = lttng_notification_serialize(¬ification, &msg_buffer);
if (ret) {
- goto end;
- }
-
- notification_size = lttng_notification_serialize(notification,
- msg_buffer.data + sizeof(msg));
- if (notification_size != expected_notification_size) {
ERR("[notification-thread] Failed to serialize notification");
ret = -1;
goto end;
}
+ /* Update payload size. */
+ ((struct lttng_notification_channel_message * ) msg_buffer.data)->size =
+ (uint32_t) (msg_buffer.size - sizeof(msg_header));
+
cds_list_for_each_entry_safe(client_list_element, tmp,
&client_list->list, node) {
struct notification_client *client =
}
ret = 0;
end:
- lttng_notification_destroy(notification);
lttng_dynamic_buffer_reset(&msg_buffer);
return ret;
}
channel_triggers_ht_node);
cds_list_for_each_entry(trigger_list_element, &trigger_list->list,
node) {
- struct lttng_condition *condition;
- struct lttng_action *action;
- struct lttng_trigger *trigger;
+ const struct lttng_condition *condition;
+ const struct lttng_action *action;
+ const struct lttng_trigger *trigger;
struct notification_client_list *client_list;
struct lttng_evaluation *evaluation = NULL;
trigger = trigger_list_element->trigger;
- condition = lttng_trigger_get_condition(trigger);
+ condition = lttng_trigger_get_const_condition(trigger);
assert(condition);
- action = lttng_trigger_get_action(trigger);
+ action = lttng_trigger_get_const_action(trigger);
/* Notify actions are the only type currently supported. */
- assert(lttng_action_get_type(action) ==
+ assert(lttng_action_get_type_const(action) ==
LTTNG_ACTION_TYPE_NOTIFY);
/*