};
struct notification_client {
+ notification_client_id id;
int socket;
/* Client protocol version. */
uint8_t major, minor;
*/
struct cds_list_head condition_list;
struct cds_lfht_node client_socket_ht_node;
+ struct cds_lfht_node client_id_ht_node;
struct {
+ /*
+ * If a client's communication is inactive, it means a fatal
+ * error (either a protocol error or the socket API returned
+ * a fatal error). No further communication should be attempted;
+ * the client is queued for clean-up.
+ */
+ bool active;
struct {
/*
* During the reception of a message, the reception
static
-int match_client(struct cds_lfht_node *node, const void *key)
+int match_client_socket(struct cds_lfht_node *node, const void *key)
{
/* This double-cast is intended to supress pointer-to-cast warning. */
- int socket = (int) (intptr_t) key;
- struct notification_client *client;
+ const int socket = (int) (intptr_t) key;
+ const struct notification_client *client = caa_container_of(node,
+ struct notification_client, client_socket_ht_node);
- client = caa_container_of(node, struct notification_client,
- client_socket_ht_node);
+ return client->socket == socket;
+}
- return !!(client->socket == socket);
+static
+int match_client_id(struct cds_lfht_node *node, const void *key)
+{
+ /* This double-cast is intended to supress pointer-to-cast warning. */
+ const notification_client_id id = *((notification_client_id *) key);
+ const struct notification_client *client = caa_container_of(
+ node, struct notification_client, client_id_ht_node);
+
+ return client->id == id;
}
static
return key_hash ^ domain_hash;
}
+static
+unsigned long hash_client_socket(int socket)
+{
+ return hash_key_ulong((void *) (unsigned long) socket, lttng_ht_seed);
+}
+
+static
+unsigned long hash_client_id(notification_client_id id)
+{
+ return hash_key_u64(&id, lttng_ht_seed);
+}
+
/*
* Get the type of object to which a given condition applies. Bindings let
* the notification system evaluate a trigger's condition when a given
if (client->socket >= 0) {
(void) lttcomm_close_unix_sock(client->socket);
+ client->socket = -1;
}
lttng_dynamic_buffer_reset(&client->communication.inbound.buffer);
lttng_dynamic_buffer_reset(&client->communication.outbound.buffer);
struct notification_client *client = NULL;
cds_lfht_lookup(state->client_socket_ht,
- hash_key_ulong((void *) (unsigned long) socket, lttng_ht_seed),
- match_client,
+ hash_client_socket(socket),
+ match_client_socket,
(void *) (unsigned long) socket,
&iter);
node = cds_lfht_iter_get_node(&iter);
return client;
}
+/*
+ * Call with rcu_read_lock held (and hold for the lifetime of the returned
+ * client pointer).
+ */
+static
+struct notification_client *get_client_from_id(notification_client_id id,
+ struct notification_thread_state *state)
+{
+ struct cds_lfht_iter iter;
+ struct cds_lfht_node *node;
+ struct notification_client *client = NULL;
+
+ cds_lfht_lookup(state->client_id_ht,
+ hash_client_id(id),
+ match_client_id,
+ &id,
+ &iter);
+ node = cds_lfht_iter_get_node(&iter);
+ if (!node) {
+ goto end;
+ }
+
+ client = caa_container_of(node, struct notification_client,
+ client_id_ht_node);
+end:
+ return client;
+}
+
static
bool buffer_usage_condition_applies_to_channel(
const struct lttng_condition *condition,
return -1;
}
-static
-unsigned long hash_client_socket(int socket)
-{
- return hash_key_ulong((void *) (unsigned long) socket, lttng_ht_seed);
-}
-
static
int socket_set_non_blocking(int socket)
{
ret = -1;
goto error;
}
+ client->id = state->next_notification_client_id++;
CDS_INIT_LIST_HEAD(&client->condition_list);
lttng_dynamic_buffer_init(&client->communication.inbound.buffer);
lttng_dynamic_buffer_init(&client->communication.outbound.buffer);
cds_lfht_add(state->client_socket_ht,
hash_client_socket(client->socket),
&client->client_socket_ht_node);
+ cds_lfht_add(state->client_id_ht,
+ hash_client_id(client->id),
+ &client->client_id_ht_node);
rcu_read_unlock();
return ret;
}
cds_lfht_del(state->client_socket_ht,
&client->client_socket_ht_node);
+ cds_lfht_del(state->client_id_ht,
+ &client->client_id_ht_node);
notification_client_destroy(client, state);
end:
rcu_read_unlock();
goto end;
}
client->validated = true;
+ client->communication.active = true;
break;
}
case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_SUBSCRIBE: