Commit | Line | Data |
---|---|---|
0c1b0f77 | 1 | /* |
ab5be9fa | 2 | * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com> |
0c1b0f77 | 3 | * |
ab5be9fa | 4 | * SPDX-License-Identifier: GPL-2.0-only |
0c1b0f77 | 5 | * |
0c1b0f77 JG |
6 | */ |
7 | ||
c9e313bc | 8 | #include "sessiond-trace-chunks.hpp" |
28ab034a | 9 | |
c9e313bc SM |
10 | #include <common/defaults.hpp> |
11 | #include <common/error.hpp> | |
28ab034a JG |
12 | #include <common/hashtable/hashtable.hpp> |
13 | #include <common/hashtable/utils.hpp> | |
14 | #include <common/macros.hpp> | |
c9e313bc | 15 | #include <common/string-utils/format.hpp> |
28ab034a JG |
16 | #include <common/trace-chunk-registry.hpp> |
17 | ||
0c1b0f77 | 18 | #include <inttypes.h> |
28ab034a JG |
19 | #include <stdio.h> |
20 | #include <urcu.h> | |
21 | #include <urcu/rculfhash.h> | |
22 | #include <urcu/ref.h> | |
0c1b0f77 JG |
23 | |
24 | /* | |
25 | * Lifetime of trace chunks within the relay daemon. | |
26 | * | |
27 | * Trace chunks are shared accross connections initiated from a given | |
28 | * session daemon. When a session is created by a consumer daemon, the | |
29 | * UUID of its associated session daemon is transmitted (in the case of | |
30 | * 2.11+ consumer daemons). | |
31 | * | |
32 | * The sessiond_trace_chunk_registry_new_session() and | |
33 | * sessiond_trace_chunk_registry_session_closed() methods create and | |
34 | * manage the reference count of lttng_trace_chunk_registry objects | |
35 | * associated to the various sessiond instances served by the relay daemon. | |
36 | * | |
37 | * When all sessions associated with a given sessiond instance are | |
38 | * destroyed, its registry is destroyed. | |
39 | * | |
40 | * lttng_trace_chunk objects are uniquely identified by the | |
41 | * (sessiond_uuid, sessiond_session_id, chunk_id) tuple. If a trace chunk | |
42 | * matching that tuple already exists, a new reference to the trace chunk | |
43 | * is acquired and it is returned to the caller. Otherwise, a new trace | |
44 | * chunk is created. This is how trace chunks are de-duplicated across | |
45 | * multiple consumer daemons managed by the same session daemon. | |
46 | * | |
47 | * Note that trace chunks are always added to their matching | |
48 | * lttng_trace_chunk_registry. They are automatically removed from the | |
49 | * trace chunk registry when their reference count reaches zero. | |
50 | */ | |
51 | ||
52 | /* | |
53 | * It is assumed that the sessiond_trace_chunk_registry is created and | |
54 | * destroyed by the same thread. | |
55 | */ | |
56 | struct sessiond_trace_chunk_registry { | |
57 | /* Maps an lttng_uuid to an lttng_trace_chunk_registry. */ | |
58 | struct cds_lfht *ht; | |
59 | }; | |
60 | ||
f1494934 | 61 | namespace { |
0c1b0f77 JG |
62 | struct trace_chunk_registry_ht_key { |
63 | lttng_uuid sessiond_uuid; | |
64 | }; | |
65 | ||
66 | struct trace_chunk_registry_ht_element { | |
67 | struct trace_chunk_registry_ht_key key; | |
68 | struct urcu_ref ref; | |
69 | /* Node into the sessiond_trace_chunk_registry's hash table. */ | |
70 | struct cds_lfht_node ht_node; | |
71 | /* Used for defered call_rcu reclaim. */ | |
72 | struct rcu_head rcu_node; | |
73 | struct lttng_trace_chunk_registry *trace_chunk_registry; | |
74 | struct sessiond_trace_chunk_registry *sessiond_trace_chunk_registry; | |
75 | }; | |
f1494934 | 76 | } /* namespace */ |
0c1b0f77 | 77 | |
28ab034a | 78 | static unsigned long trace_chunk_registry_ht_key_hash(const struct trace_chunk_registry_ht_key *key) |
0c1b0f77 | 79 | { |
328c2fe7 JG |
80 | const uint64_t uuid_h1 = *reinterpret_cast<const uint64_t *>(&key->sessiond_uuid[0]); |
81 | const uint64_t uuid_h2 = *reinterpret_cast<const uint64_t *>(&key->sessiond_uuid[1]); | |
0c1b0f77 | 82 | |
28ab034a | 83 | return hash_key_u64(&uuid_h1, lttng_ht_seed) ^ hash_key_u64(&uuid_h2, lttng_ht_seed); |
0c1b0f77 JG |
84 | } |
85 | ||
86 | /* cds_lfht match function */ | |
28ab034a | 87 | static int trace_chunk_registry_ht_key_match(struct cds_lfht_node *node, const void *_key) |
0c1b0f77 | 88 | { |
28ab034a | 89 | const struct trace_chunk_registry_ht_key *key = (struct trace_chunk_registry_ht_key *) _key; |
0c1b0f77 JG |
90 | struct trace_chunk_registry_ht_element *registry; |
91 | ||
0114db0e | 92 | registry = lttng::utils::container_of(node, &trace_chunk_registry_ht_element::ht_node); |
328c2fe7 | 93 | return key->sessiond_uuid == registry->key.sessiond_uuid; |
0c1b0f77 JG |
94 | } |
95 | ||
28ab034a | 96 | static void trace_chunk_registry_ht_element_free(struct rcu_head *node) |
0c1b0f77 | 97 | { |
28ab034a JG |
98 | struct trace_chunk_registry_ht_element *element = |
99 | lttng::utils::container_of(node, &trace_chunk_registry_ht_element::rcu_node); | |
0c1b0f77 | 100 | |
0c1b0f77 JG |
101 | free(element); |
102 | } | |
103 | ||
28ab034a | 104 | static void trace_chunk_registry_ht_element_release(struct urcu_ref *ref) |
0c1b0f77 JG |
105 | { |
106 | struct trace_chunk_registry_ht_element *element = | |
28ab034a | 107 | lttng::utils::container_of(ref, &trace_chunk_registry_ht_element::ref); |
c70636a7 | 108 | char uuid_str[LTTNG_UUID_STR_LEN]; |
0c1b0f77 JG |
109 | |
110 | lttng_uuid_to_str(element->key.sessiond_uuid, uuid_str); | |
111 | ||
28ab034a | 112 | DBG("Destroying trace chunk registry associated to sessiond {%s}", uuid_str); |
0c1b0f77 JG |
113 | if (element->sessiond_trace_chunk_registry) { |
114 | /* Unpublish. */ | |
115 | rcu_read_lock(); | |
28ab034a | 116 | cds_lfht_del(element->sessiond_trace_chunk_registry->ht, &element->ht_node); |
0c1b0f77 | 117 | rcu_read_unlock(); |
cd9adb8b | 118 | element->sessiond_trace_chunk_registry = nullptr; |
0c1b0f77 JG |
119 | } |
120 | ||
c35f9726 | 121 | lttng_trace_chunk_registry_destroy(element->trace_chunk_registry); |
0c1b0f77 JG |
122 | /* Defered reclaim of the object */ |
123 | call_rcu(&element->rcu_node, trace_chunk_registry_ht_element_free); | |
124 | } | |
125 | ||
28ab034a | 126 | static bool trace_chunk_registry_ht_element_get(struct trace_chunk_registry_ht_element *element) |
0c1b0f77 JG |
127 | { |
128 | return urcu_ref_get_unless_zero(&element->ref); | |
129 | } | |
130 | ||
28ab034a | 131 | static void trace_chunk_registry_ht_element_put(struct trace_chunk_registry_ht_element *element) |
0c1b0f77 | 132 | { |
cd65fb86 FD |
133 | if (!element) { |
134 | return; | |
135 | } | |
136 | ||
0c1b0f77 JG |
137 | urcu_ref_put(&element->ref, trace_chunk_registry_ht_element_release); |
138 | } | |
139 | ||
140 | /* Acquires a reference to the returned element on behalf of the caller. */ | |
28ab034a JG |
141 | static struct trace_chunk_registry_ht_element * |
142 | trace_chunk_registry_ht_element_find(struct sessiond_trace_chunk_registry *sessiond_registry, | |
143 | const struct trace_chunk_registry_ht_key *key) | |
0c1b0f77 | 144 | { |
cd9adb8b | 145 | struct trace_chunk_registry_ht_element *element = nullptr; |
0c1b0f77 JG |
146 | struct cds_lfht_node *node; |
147 | struct cds_lfht_iter iter; | |
148 | ||
149 | rcu_read_lock(); | |
150 | cds_lfht_lookup(sessiond_registry->ht, | |
151 | trace_chunk_registry_ht_key_hash(key), | |
152 | trace_chunk_registry_ht_key_match, | |
153 | key, | |
154 | &iter); | |
155 | node = cds_lfht_iter_get_node(&iter); | |
156 | if (node) { | |
28ab034a JG |
157 | element = |
158 | lttng::utils::container_of(node, &trace_chunk_registry_ht_element::ht_node); | |
0c1b0f77 JG |
159 | /* |
160 | * Only consider the look-up as successful if a reference | |
161 | * could be acquired. | |
162 | */ | |
163 | if (!trace_chunk_registry_ht_element_get(element)) { | |
cd9adb8b | 164 | element = nullptr; |
0c1b0f77 JG |
165 | } |
166 | } | |
167 | rcu_read_unlock(); | |
168 | return element; | |
169 | } | |
170 | ||
28ab034a JG |
171 | static int |
172 | trace_chunk_registry_ht_element_create(struct sessiond_trace_chunk_registry *sessiond_registry, | |
173 | const struct trace_chunk_registry_ht_key *key) | |
0c1b0f77 JG |
174 | { |
175 | int ret = 0; | |
176 | struct trace_chunk_registry_ht_element *new_element; | |
177 | struct lttng_trace_chunk_registry *trace_chunk_registry; | |
c70636a7 | 178 | char uuid_str[LTTNG_UUID_STR_LEN]; |
0c1b0f77 JG |
179 | |
180 | lttng_uuid_to_str(key->sessiond_uuid, uuid_str); | |
181 | ||
182 | trace_chunk_registry = lttng_trace_chunk_registry_create(); | |
183 | if (!trace_chunk_registry) { | |
184 | ret = -1; | |
185 | goto end; | |
186 | } | |
187 | ||
64803277 | 188 | new_element = zmalloc<trace_chunk_registry_ht_element>(); |
0c1b0f77 JG |
189 | if (!new_element) { |
190 | ret = -1; | |
191 | goto end; | |
192 | } | |
193 | ||
194 | memcpy(&new_element->key, key, sizeof(new_element->key)); | |
195 | urcu_ref_init(&new_element->ref); | |
196 | cds_lfht_node_init(&new_element->ht_node); | |
197 | new_element->trace_chunk_registry = trace_chunk_registry; | |
cd9adb8b | 198 | trace_chunk_registry = nullptr; |
0c1b0f77 JG |
199 | |
200 | /* Attempt to publish the new element. */ | |
201 | rcu_read_lock(); | |
cd9adb8b | 202 | while (true) { |
0c1b0f77 JG |
203 | struct cds_lfht_node *published_node; |
204 | struct trace_chunk_registry_ht_element *published_element; | |
205 | ||
28ab034a JG |
206 | published_node = |
207 | cds_lfht_add_unique(sessiond_registry->ht, | |
208 | trace_chunk_registry_ht_key_hash(&new_element->key), | |
209 | trace_chunk_registry_ht_key_match, | |
210 | &new_element->key, | |
211 | &new_element->ht_node); | |
0c1b0f77 JG |
212 | if (published_node == &new_element->ht_node) { |
213 | /* New element published successfully. */ | |
28ab034a JG |
214 | DBG("Created trace chunk registry for sessiond {%s}", uuid_str); |
215 | new_element->sessiond_trace_chunk_registry = sessiond_registry; | |
0c1b0f77 JG |
216 | break; |
217 | } | |
218 | ||
219 | /* | |
220 | * An equivalent element was published during the creation of | |
221 | * this element. Attempt to acquire a reference to the one that | |
222 | * was already published and release the reference to the copy | |
223 | * we created if successful. | |
224 | */ | |
28ab034a JG |
225 | published_element = lttng::utils::container_of( |
226 | published_node, &trace_chunk_registry_ht_element::ht_node); | |
0c1b0f77 JG |
227 | if (trace_chunk_registry_ht_element_get(published_element)) { |
228 | DBG("Acquired reference to trace chunk registry of sessiond {%s}", | |
28ab034a | 229 | uuid_str); |
0c1b0f77 | 230 | trace_chunk_registry_ht_element_put(new_element); |
cd9adb8b | 231 | new_element = nullptr; |
0c1b0f77 JG |
232 | break; |
233 | } | |
234 | /* | |
235 | * A reference to the previously published element could not | |
236 | * be acquired. Hence, retry to publish our copy of the | |
237 | * element. | |
238 | */ | |
239 | } | |
240 | rcu_read_unlock(); | |
241 | end: | |
242 | if (ret < 0) { | |
28ab034a | 243 | ERR("Failed to create trace chunk registry for session daemon {%s}", uuid_str); |
0c1b0f77 | 244 | } |
e441f4e9 | 245 | lttng_trace_chunk_registry_destroy(trace_chunk_registry); |
0c1b0f77 JG |
246 | return ret; |
247 | } | |
248 | ||
cd9adb8b | 249 | struct sessiond_trace_chunk_registry *sessiond_trace_chunk_registry_create() |
0c1b0f77 JG |
250 | { |
251 | struct sessiond_trace_chunk_registry *sessiond_registry = | |
28ab034a | 252 | zmalloc<sessiond_trace_chunk_registry>(); |
0c1b0f77 JG |
253 | |
254 | if (!sessiond_registry) { | |
255 | goto end; | |
256 | } | |
257 | ||
28ab034a | 258 | sessiond_registry->ht = cds_lfht_new( |
cd9adb8b | 259 | DEFAULT_HT_SIZE, 1, 0, CDS_LFHT_AUTO_RESIZE | CDS_LFHT_ACCOUNTING, nullptr); |
0c1b0f77 JG |
260 | if (!sessiond_registry->ht) { |
261 | goto error; | |
262 | } | |
263 | ||
264 | end: | |
265 | return sessiond_registry; | |
266 | error: | |
267 | sessiond_trace_chunk_registry_destroy(sessiond_registry); | |
cd9adb8b | 268 | return nullptr; |
0c1b0f77 JG |
269 | } |
270 | ||
28ab034a | 271 | void sessiond_trace_chunk_registry_destroy(struct sessiond_trace_chunk_registry *sessiond_registry) |
0c1b0f77 | 272 | { |
cd9adb8b | 273 | int ret = cds_lfht_destroy(sessiond_registry->ht, nullptr); |
0c1b0f77 | 274 | |
a0377dfe | 275 | LTTNG_ASSERT(!ret); |
0c1b0f77 JG |
276 | free(sessiond_registry); |
277 | } | |
278 | ||
279 | int sessiond_trace_chunk_registry_session_created( | |
28ab034a | 280 | struct sessiond_trace_chunk_registry *sessiond_registry, const lttng_uuid& sessiond_uuid) |
0c1b0f77 JG |
281 | { |
282 | int ret = 0; | |
283 | struct trace_chunk_registry_ht_key key; | |
284 | struct trace_chunk_registry_ht_element *element; | |
285 | ||
328c2fe7 | 286 | key.sessiond_uuid = sessiond_uuid; |
0c1b0f77 JG |
287 | |
288 | element = trace_chunk_registry_ht_element_find(sessiond_registry, &key); | |
289 | if (element) { | |
c70636a7 | 290 | char uuid_str[LTTNG_UUID_STR_LEN]; |
0c1b0f77 JG |
291 | |
292 | lttng_uuid_to_str(sessiond_uuid, uuid_str); | |
28ab034a | 293 | DBG("Acquired reference to trace chunk registry of sessiond {%s}", uuid_str); |
0c1b0f77 JG |
294 | goto end; |
295 | } else { | |
28ab034a | 296 | ret = trace_chunk_registry_ht_element_create(sessiond_registry, &key); |
0c1b0f77 JG |
297 | } |
298 | end: | |
299 | return ret; | |
300 | } | |
301 | ||
302 | int sessiond_trace_chunk_registry_session_destroyed( | |
28ab034a | 303 | struct sessiond_trace_chunk_registry *sessiond_registry, const lttng_uuid& sessiond_uuid) |
0c1b0f77 JG |
304 | { |
305 | int ret = 0; | |
306 | struct trace_chunk_registry_ht_key key; | |
307 | struct trace_chunk_registry_ht_element *element; | |
c70636a7 | 308 | char uuid_str[LTTNG_UUID_STR_LEN]; |
0c1b0f77 JG |
309 | |
310 | lttng_uuid_to_str(sessiond_uuid, uuid_str); | |
328c2fe7 | 311 | key.sessiond_uuid = sessiond_uuid; |
0c1b0f77 JG |
312 | |
313 | element = trace_chunk_registry_ht_element_find(sessiond_registry, &key); | |
314 | if (element) { | |
28ab034a | 315 | DBG("Releasing reference to trace chunk registry of sessiond {%s}", uuid_str); |
0c1b0f77 JG |
316 | /* |
317 | * Release the reference held by the session and the reference | |
318 | * acquired through the "find" operation. | |
319 | */ | |
320 | trace_chunk_registry_ht_element_put(element); | |
321 | trace_chunk_registry_ht_element_put(element); | |
322 | } else { | |
28ab034a | 323 | ERR("Failed to find trace chunk registry of sessiond {%s}", uuid_str); |
0c1b0f77 JG |
324 | ret = -1; |
325 | } | |
326 | return ret; | |
327 | } | |
328 | ||
28ab034a JG |
329 | struct lttng_trace_chunk * |
330 | sessiond_trace_chunk_registry_publish_chunk(struct sessiond_trace_chunk_registry *sessiond_registry, | |
331 | const lttng_uuid& sessiond_uuid, | |
332 | uint64_t session_id, | |
333 | struct lttng_trace_chunk *new_chunk) | |
0c1b0f77 JG |
334 | { |
335 | enum lttng_trace_chunk_status status; | |
336 | uint64_t chunk_id; | |
337 | bool is_anonymous_chunk; | |
338 | struct trace_chunk_registry_ht_key key; | |
cd9adb8b | 339 | struct trace_chunk_registry_ht_element *element = nullptr; |
c70636a7 | 340 | char uuid_str[LTTNG_UUID_STR_LEN]; |
0c1b0f77 | 341 | char chunk_id_str[MAX_INT_DEC_LEN(typeof(chunk_id))] = "-1"; |
cd9adb8b | 342 | struct lttng_trace_chunk *published_chunk = nullptr; |
c5c79321 | 343 | bool trace_chunk_already_published; |
0c1b0f77 JG |
344 | |
345 | lttng_uuid_to_str(sessiond_uuid, uuid_str); | |
328c2fe7 | 346 | key.sessiond_uuid = sessiond_uuid; |
0c1b0f77 JG |
347 | |
348 | status = lttng_trace_chunk_get_id(new_chunk, &chunk_id); | |
22df7435 | 349 | if (status == LTTNG_TRACE_CHUNK_STATUS_OK) { |
0c1b0f77 JG |
350 | int ret; |
351 | ||
28ab034a | 352 | ret = snprintf(chunk_id_str, sizeof(chunk_id_str), "%" PRIu64, chunk_id); |
0c1b0f77 JG |
353 | if (ret < 0) { |
354 | lttng_strncpy(chunk_id_str, "-1", sizeof(chunk_id_str)); | |
355 | WARN("Failed to format trace chunk id"); | |
356 | } | |
357 | is_anonymous_chunk = false; | |
22df7435 | 358 | } else if (status == LTTNG_TRACE_CHUNK_STATUS_NONE) { |
0c1b0f77 JG |
359 | is_anonymous_chunk = true; |
360 | } else { | |
361 | ERR("Failed to get trace chunk id"); | |
362 | goto end; | |
363 | } | |
364 | ||
22df7435 | 365 | DBG("Attempting to publish trace chunk: sessiond {%s}, session_id = " |
28ab034a JG |
366 | "%" PRIu64 ", chunk_id = %s", |
367 | uuid_str, | |
368 | session_id, | |
369 | is_anonymous_chunk ? "anonymous" : chunk_id_str); | |
0c1b0f77 | 370 | |
22df7435 | 371 | element = trace_chunk_registry_ht_element_find(sessiond_registry, &key); |
0c1b0f77 JG |
372 | if (!element) { |
373 | ERR("Failed to find registry of sessiond {%s}", uuid_str); | |
374 | goto end; | |
375 | } | |
376 | ||
28ab034a JG |
377 | published_chunk = lttng_trace_chunk_registry_publish_chunk(element->trace_chunk_registry, |
378 | session_id, | |
379 | new_chunk, | |
380 | &trace_chunk_already_published); | |
c35f9726 | 381 | /* |
c5c79321 JG |
382 | * When the trace chunk is first published, two references to the |
383 | * published chunks exist. One is taken by the registry while the other | |
384 | * is being returned to the caller. In the use case of the relay daemon, | |
385 | * the reference held by the registry itself is undesirable. | |
c35f9726 JG |
386 | * |
387 | * We want the trace chunk to be removed from the registry as soon | |
388 | * as it is not being used by the relay daemon (through a session | |
389 | * or a stream). This differs from the behaviour of the consumer | |
390 | * daemon which relies on an explicit command from the session | |
391 | * daemon to release the registry's reference. | |
c5c79321 JG |
392 | * |
393 | * In cases where the trace chunk had already been published, | |
394 | * the reference belonging to the sessiond trace chunk | |
395 | * registry instance has already been 'put'. We simply return | |
396 | * the published trace chunk with a reference taken on behalf of the | |
397 | * caller. | |
c35f9726 | 398 | */ |
c5c79321 JG |
399 | if (!trace_chunk_already_published) { |
400 | lttng_trace_chunk_put(published_chunk); | |
401 | } | |
0c1b0f77 JG |
402 | end: |
403 | trace_chunk_registry_ht_element_put(element); | |
404 | return published_chunk; | |
405 | } | |
406 | ||
28ab034a JG |
407 | struct lttng_trace_chunk *sessiond_trace_chunk_registry_get_anonymous_chunk( |
408 | struct sessiond_trace_chunk_registry *sessiond_registry, | |
409 | const lttng_uuid& sessiond_uuid, | |
410 | uint64_t session_id) | |
0c1b0f77 | 411 | { |
cd9adb8b | 412 | struct lttng_trace_chunk *chunk = nullptr; |
0c1b0f77 JG |
413 | struct trace_chunk_registry_ht_element *element; |
414 | struct trace_chunk_registry_ht_key key; | |
c70636a7 | 415 | char uuid_str[LTTNG_UUID_STR_LEN]; |
0c1b0f77 JG |
416 | |
417 | lttng_uuid_to_str(sessiond_uuid, uuid_str); | |
418 | ||
328c2fe7 | 419 | key.sessiond_uuid = sessiond_uuid; |
0c1b0f77 JG |
420 | element = trace_chunk_registry_ht_element_find(sessiond_registry, &key); |
421 | if (!element) { | |
28ab034a | 422 | ERR("Failed to find trace chunk registry of sessiond {%s}", uuid_str); |
0c1b0f77 JG |
423 | goto end; |
424 | } | |
425 | ||
28ab034a JG |
426 | chunk = lttng_trace_chunk_registry_find_anonymous_chunk(element->trace_chunk_registry, |
427 | session_id); | |
0c1b0f77 JG |
428 | trace_chunk_registry_ht_element_put(element); |
429 | end: | |
430 | return chunk; | |
431 | } | |
432 | ||
433 | struct lttng_trace_chunk * | |
28ab034a JG |
434 | sessiond_trace_chunk_registry_get_chunk(struct sessiond_trace_chunk_registry *sessiond_registry, |
435 | const lttng_uuid& sessiond_uuid, | |
436 | uint64_t session_id, | |
437 | uint64_t chunk_id) | |
0c1b0f77 | 438 | { |
cd9adb8b | 439 | struct lttng_trace_chunk *chunk = nullptr; |
0c1b0f77 JG |
440 | struct trace_chunk_registry_ht_element *element; |
441 | struct trace_chunk_registry_ht_key key; | |
c70636a7 | 442 | char uuid_str[LTTNG_UUID_STR_LEN]; |
0c1b0f77 JG |
443 | |
444 | lttng_uuid_to_str(sessiond_uuid, uuid_str); | |
445 | ||
328c2fe7 | 446 | key.sessiond_uuid = sessiond_uuid; |
0c1b0f77 JG |
447 | element = trace_chunk_registry_ht_element_find(sessiond_registry, &key); |
448 | if (!element) { | |
28ab034a | 449 | ERR("Failed to find trace chunk registry of sessiond {%s}", uuid_str); |
0c1b0f77 JG |
450 | goto end; |
451 | } | |
452 | ||
453 | chunk = lttng_trace_chunk_registry_find_chunk( | |
28ab034a | 454 | element->trace_chunk_registry, session_id, chunk_id); |
0c1b0f77 JG |
455 | trace_chunk_registry_ht_element_put(element); |
456 | end: | |
457 | return chunk; | |
458 | } | |
6b584c2e JG |
459 | |
460 | int sessiond_trace_chunk_registry_chunk_exists( | |
28ab034a JG |
461 | struct sessiond_trace_chunk_registry *sessiond_registry, |
462 | const lttng_uuid& sessiond_uuid, | |
463 | uint64_t session_id, | |
464 | uint64_t chunk_id, | |
465 | bool *chunk_exists) | |
6b584c2e JG |
466 | { |
467 | int ret; | |
468 | struct trace_chunk_registry_ht_element *element; | |
469 | struct trace_chunk_registry_ht_key key; | |
470 | ||
328c2fe7 | 471 | key.sessiond_uuid = sessiond_uuid; |
6b584c2e JG |
472 | element = trace_chunk_registry_ht_element_find(sessiond_registry, &key); |
473 | if (!element) { | |
c70636a7 | 474 | char uuid_str[LTTNG_UUID_STR_LEN]; |
6b584c2e JG |
475 | |
476 | lttng_uuid_to_str(sessiond_uuid, uuid_str); | |
477 | /* | |
478 | * While this certainly means that the chunk does not exist, | |
479 | * it is unexpected for a chunk existence query to target a | |
480 | * session daemon that does not have an active | |
481 | * connection/registry. This would indicate a protocol | |
482 | * (or internal) error. | |
483 | */ | |
28ab034a | 484 | ERR("Failed to find trace chunk registry of sessiond {%s}", uuid_str); |
6b584c2e JG |
485 | ret = -1; |
486 | goto end; | |
487 | } | |
488 | ||
489 | ret = lttng_trace_chunk_registry_chunk_exists( | |
28ab034a | 490 | element->trace_chunk_registry, session_id, chunk_id, chunk_exists); |
6b584c2e JG |
491 | trace_chunk_registry_ht_element_put(element); |
492 | end: | |
493 | return ret; | |
494 | } |