--- /dev/null
+/*
+ * Copyright (C) 2018 - Francis Deslauriers <francis.deslauriers@efficios.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License, version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdbool.h>
+#include <string.h>
+
+#include "ust-field-utils.h"
+
+/*
+ * The ustctl_field is made of a combination of C basic types
+ * ustctl_basic_type and _ustctl_basic_type.
+ *
+ * ustctl_basic_type contains an enumeration describing the abstract type.
+ * _ustctl_basic_type does _NOT_ contain an enumeration describing the
+ * abstract type.
+ *
+ * A layer is needed to use the same code for both structures.
+ * When dealing with _ustctl_basic_type, we need to use the abstract type of
+ * the ustctl_type struct.
+ */
+
+/*
+ * Compare two ustctl_integer_type fields.
+ * Returns 1 if both are identical.
+ */
+static bool match_ustctl_field_integer(const struct ustctl_integer_type *first,
+ const struct ustctl_integer_type *second)
+{
+ if (first->size != second->size) {
+ goto no_match;
+ }
+ if (first->alignment != second->alignment) {
+ goto no_match;
+ }
+ if (first->signedness != second->signedness) {
+ goto no_match;
+ }
+ if (first->encoding != second->encoding) {
+ goto no_match;
+ }
+ if (first->base != second->base) {
+ goto no_match;
+ }
+ if (first->reverse_byte_order != second->reverse_byte_order) {
+ goto no_match;
+ }
+
+ return true;
+
+no_match:
+ return false;
+}
+
+/*
+ * Compare two _ustctl_basic_type fields known to be of type integer.
+ * Returns 1 if both are identical.
+ */
+static bool match_ustctl_field_integer_from_raw_basic_type(
+ const union _ustctl_basic_type *first,
+ const union _ustctl_basic_type *second)
+{
+ return match_ustctl_field_integer(&first->integer, &second->integer);
+}
+
+/*
+ * Compare two _ustctl_basic_type fields known to be of type enum.
+ * Returns 1 if both are identical.
+ */
+static bool match_ustctl_field_enum_from_raw_basic_type(
+ const union _ustctl_basic_type *first,
+ const union _ustctl_basic_type *second)
+{
+ /*
+ * Compare enumeration ID. Enumeration ID is provided to the application by
+ * the session daemon before event registration.
+ */
+ if (first->enumeration.id != second->enumeration.id) {
+ goto no_match;
+ }
+
+ /*
+ * Sanity check of the name and container type. Those were already checked
+ * during enum registration.
+ */
+ if (strncmp(first->enumeration.name, second->enumeration.name,
+ LTTNG_UST_SYM_NAME_LEN)) {
+ goto no_match;
+ }
+ if (!match_ustctl_field_integer(&first->enumeration.container_type,
+ &second->enumeration.container_type)) {
+ goto no_match;
+ }
+
+ return true;
+
+no_match:
+ return false;
+}
+
+/*
+ * Compare two _ustctl_basic_type fields known to be of type string.
+ * Returns 1 if both are identical.
+ */
+static bool match_ustctl_field_string_from_raw_basic_type(
+ const union _ustctl_basic_type *first,
+ const union _ustctl_basic_type *second)
+{
+ return first->string.encoding == second->string.encoding;
+}
+
+/*
+ * Compare two _ustctl_basic_type fields known to be of type float.
+ * Returns 1 if both are identical.
+ */
+static bool match_ustctl_field_float_from_raw_basic_type(
+ const union _ustctl_basic_type *first,
+ const union _ustctl_basic_type *second)
+{
+ if (first->_float.exp_dig != second->_float.exp_dig) {
+ goto no_match;
+ }
+
+ if (first->_float.mant_dig != second->_float.mant_dig) {
+ goto no_match;
+ }
+
+ if (first->_float.reverse_byte_order !=
+ second->_float.reverse_byte_order) {
+ goto no_match;
+ }
+
+ if (first->_float.alignment != second->_float.alignment) {
+ goto no_match;
+ }
+
+ return true;
+
+no_match:
+ return false;
+}
+
+/*
+ * Compare two _ustctl_basic_type fields given their respective abstract types.
+ * Returns 1 if both are identical.
+ */
+static bool match_ustctl_field_raw_basic_type(
+ enum ustctl_abstract_types first_atype,
+ const union _ustctl_basic_type *first,
+ enum ustctl_abstract_types second_atype,
+ const union _ustctl_basic_type *second)
+{
+ if (first_atype != second_atype) {
+ goto no_match;
+ }
+
+ switch (first_atype) {
+ case ustctl_atype_integer:
+ if (!match_ustctl_field_integer_from_raw_basic_type(first, second)) {
+ goto no_match;
+ }
+ break;
+ case ustctl_atype_enum:
+ if (!match_ustctl_field_enum_from_raw_basic_type(first, second)) {
+ goto no_match;
+ }
+ break;
+ case ustctl_atype_string:
+ if (!match_ustctl_field_string_from_raw_basic_type(first, second)) {
+ goto no_match;
+ }
+ break;
+ case ustctl_atype_float:
+ if (!match_ustctl_field_float_from_raw_basic_type(first, second)) {
+ goto no_match;
+ }
+ break;
+ default:
+ goto no_match;
+ }
+
+ return true;
+
+no_match:
+ return false;
+}
+
+/*
+ * Compatibility layer between the ustctl_basic_type struct and
+ * _ustctl_basic_type union.
+ */
+static bool match_ustctl_field_basic_type(const struct ustctl_basic_type *first,
+ const struct ustctl_basic_type *second)
+{
+ return match_ustctl_field_raw_basic_type(first->atype, &first->u.basic,
+ second->atype, &second->u.basic);
+}
+
+int match_ustctl_field(const struct ustctl_field *first,
+ const struct ustctl_field *second)
+{
+ /* Check the name of the field is identical. */
+ if (strncmp(first->name, second->name, LTTNG_UST_SYM_NAME_LEN)) {
+ goto no_match;
+ }
+
+ /* Check the field type is identical. */
+ if (first->type.atype != second->type.atype) {
+ goto no_match;
+ }
+
+ /* Check the field layout. */
+ switch (first->type.atype) {
+ case ustctl_atype_integer:
+ case ustctl_atype_enum:
+ case ustctl_atype_string:
+ case ustctl_atype_float:
+ if (!match_ustctl_field_raw_basic_type(first->type.atype,
+ &first->type.u.basic, second->type.atype,
+ &second->type.u.basic)) {
+ goto no_match;
+ }
+ break;
+ case ustctl_atype_sequence:
+ /* Match element type of the sequence. */
+ if (!match_ustctl_field_basic_type(&first->type.u.sequence.elem_type,
+ &second->type.u.sequence.elem_type)) {
+ goto no_match;
+ }
+
+ /* Match length type of the sequence. */
+ if (!match_ustctl_field_basic_type(&first->type.u.sequence.length_type,
+ &second->type.u.sequence.length_type)) {
+ goto no_match;
+ }
+ break;
+ case ustctl_atype_array:
+ /* Match element type of the array. */
+ if (!match_ustctl_field_basic_type(&first->type.u.array.elem_type,
+ &second->type.u.array.elem_type)) {
+ goto no_match;
+ }
+
+ /* Match length of the array. */
+ if (first->type.u.array.length != second->type.u.array.length) {
+ goto no_match;
+ }
+ break;
+ case ustctl_atype_variant:
+ /* Compare number of choice of the variants. */
+ if (first->type.u.variant.nr_choices !=
+ second->type.u.variant.nr_choices) {
+ goto no_match;
+ }
+
+ /* Compare tag name of the variants. */
+ if (strncmp(first->type.u.variant.tag_name,
+ second->type.u.variant.tag_name,
+ LTTNG_UST_SYM_NAME_LEN)) {
+ goto no_match;
+ }
+ break;
+ case ustctl_atype_struct:
+ /* Compare number of fields of the structs. */
+ if (first->type.u._struct.nr_fields != second->type.u._struct.nr_fields) {
+ goto no_match;
+ }
+ break;
+ default:
+ goto no_match;
+ }
+
+ return true;
+
+no_match:
+ return false;
+}
#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"
+
/*
* Hash table match function for event in the registry.
*/
static int ht_match_event(struct cds_lfht_node *node, const void *_key)
{
- struct ust_registry_event *event;
const struct ust_registry_event *key;
+ struct ust_registry_event *event;
+ int i;
assert(node);
assert(_key);
assert(event);
key = _key;
- /* It has to be a perfect match. */
+ /* It has to be a perfect match. First, compare the event names. */
if (strncmp(event->name, key->name, sizeof(event->name))) {
goto no_match;
}
- /* It has to be a perfect match. */
- if (strncmp(event->signature, key->signature,
- strlen(event->signature))) {
+ /* Compare log levels. */
+ if (event->loglevel_value != key->loglevel_value) {
+ goto no_match;
+ }
+
+ /* Compare the number of fields. */
+ if (event->nr_fields != key->nr_fields) {
+ goto no_match;
+ }
+
+ /* Compare each field individually. */
+ for (i = 0; i < event->nr_fields; i++) {
+ if (!match_ustctl_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;
+ } else if(event->model_emf_uri == NULL && key->model_emf_uri != NULL) {
goto no_match;
+ } else if (event->model_emf_uri != NULL && key->model_emf_uri != NULL) {
+ if (strcmp(event->model_emf_uri, key->model_emf_uri)) {
+ goto no_match;
+ }
}
/* Match */
static unsigned long ht_hash_event(const void *_key, unsigned long seed)
{
- uint64_t xored_key;
+ uint64_t hashed_key;
const struct ust_registry_event *key = _key;
assert(key);
- xored_key = (uint64_t) (hash_key_str(key->name, seed) ^
- hash_key_str(key->signature, seed));
+ hashed_key = (uint64_t) hash_key_str(key->name, seed);
- return hash_key_u64(&xored_key, seed);
+ return hash_key_u64(&hashed_key, seed);
}
static int compare_enums(const struct ust_registry_enum *reg_enum_a,