|
1 | 1 | /* |
2 | | - * Copyright 2025, Datadog, Inc. |
| 2 | + * Copyright 2025, 2026, Datadog, Inc. |
3 | 3 | * SPDX-License-Identifier: Apache-2.0 |
4 | 4 | */ |
5 | 5 |
|
@@ -451,15 +451,34 @@ void CallTraceHashTable::putWithExistingId(CallTrace* source_trace, u64 weight) |
451 | 451 |
|
452 | 452 | u64 hash = calcHash(source_trace->num_frames, source_trace->frames, source_trace->truncated); |
453 | 453 |
|
454 | | - // First check if trace already exists in any table in the chain. |
| 454 | + // First check if this exact trace ID already exists in any table in the |
| 455 | + // chain. Different storage generations can assign different IDs to the same |
| 456 | + // stack. Both entries must survive preservation because recorded events |
| 457 | + // reference the ID, not the stack hash. |
455 | 458 | // Use ACQUIRE to match the RELEASE store in clearTableOnly(); putWithExistingId() |
456 | 459 | // is only called on scratch/standby tables with no concurrent writers, so the |
457 | 460 | // load is safe, but consistent ordering prevents latent issues if callers change. |
458 | 461 | for (LongHashTable *search_table = __atomic_load_n(&_table, __ATOMIC_ACQUIRE); |
459 | 462 | search_table != nullptr; search_table = search_table->prev()) { |
460 | | - CallTrace *existing_trace = findCallTrace(search_table, hash); |
461 | | - if (existing_trace != nullptr) { |
462 | | - return; |
| 463 | + u64 *search_keys = search_table->keys(); |
| 464 | + HashProbe search_probe(hash, search_table->capacity()); |
| 465 | + u32 search_slot = search_probe.slot(); |
| 466 | + while (true) { |
| 467 | + u64 key = __atomic_load_n(&search_keys[search_slot], __ATOMIC_RELAXED); |
| 468 | + if (key == 0) { |
| 469 | + break; |
| 470 | + } |
| 471 | + if (key == hash) { |
| 472 | + CallTrace *existing_trace = search_table->values()[search_slot].acquireTrace(); |
| 473 | + if (existing_trace != nullptr && existing_trace != CallTraceSample::PREPARING && |
| 474 | + existing_trace->trace_id == source_trace->trace_id) { |
| 475 | + return; |
| 476 | + } |
| 477 | + } |
| 478 | + if (!search_probe.hasNext()) { |
| 479 | + break; |
| 480 | + } |
| 481 | + search_slot = search_probe.next(); |
463 | 482 | } |
464 | 483 | } |
465 | 484 |
|
|
0 commit comments