@@ -412,10 +412,17 @@ CacheManager::CacheManager(std::shared_ptr<MetricsRegistry> metrics_registry,
412412
413413CacheManager::~CacheManager () {
414414 if (cache_garbage_collector_) {
415- cache_garbage_collector_->Stop ();
416- cache_garbage_collector_.reset ();
415+ // Close intent admission before detaching callbacks. A liveness thread
416+ // may already have copied a callback, so the callback itself also uses
417+ // a weak GC reference and will either observe stopped admission or an
418+ // expired collector.
419+ cache_garbage_collector_->RequestStop ();
417420 }
418421 ClearEventCleanupCallbacks ();
422+ if (cache_garbage_collector_) {
423+ cache_garbage_collector_->Join ();
424+ cache_garbage_collector_.reset ();
425+ }
419426 StopRecoverRetryLoop ();
420427 DeactivateEventCleanupCallbacks ();
421428 if (write_location_manager_) {
@@ -2584,54 +2591,6 @@ class ValidatedEventLocationSpecs {
25842591 std::vector<ValidatedEventLocationSpec> many_;
25852592};
25862593
2587- bool IsSnapshotLocationStale (const EventReportBackend *event_backend,
2588- const std::string &instance_id,
2589- const CacheLocation &location,
2590- bool preserve_in_flight = false ) {
2591- if (!event_backend) {
2592- return false ;
2593- }
2594-
2595- std::string medium;
2596- std::string reporter_host;
2597- if (!event_backend->ParseLocationId (location.id (), medium, reporter_host)) {
2598- return false ;
2599- }
2600-
2601- const ReporterSnapshotKey reporter_key{instance_id, reporter_host};
2602- std::string committed_version;
2603- std::string in_flight_version;
2604- event_backend->GetSnapshotVersionTokens (reporter_key, committed_version, in_flight_version);
2605- if (location.location_specs ().empty ()) {
2606- return true ;
2607- }
2608- bool contains_committed = false ;
2609- bool contains_in_flight = false ;
2610- for (const auto &spec : location.location_specs ()) {
2611- const size_t version_param_count =
2612- SnapshotUriUtils::CountUriParam (spec.uri (), SnapshotUriUtils::kSnapshotVersionParam );
2613- if (version_param_count == 0 ) {
2614- // Legacy metadata is a stale reconciliation component, but a
2615- // current delta spec in the same stable location still protects
2616- // the location from coarse-grained cleanup.
2617- continue ;
2618- }
2619- SnapshotUriInfo info;
2620- if (version_param_count != 1 || !SnapshotUriUtils::ParseSnapshotUriInfo (spec.uri (), info)) {
2621- return true ;
2622- }
2623- contains_committed = contains_committed || (!committed_version.empty () && info.version == committed_version);
2624- contains_in_flight = contains_in_flight ||
2625- (preserve_in_flight && !in_flight_version.empty () && info.version == in_flight_version);
2626- }
2627- // Delta merge is spec-granular and can temporarily leave multiple
2628- // generations in one stable location. Cleanup is location-granular, so it
2629- // must preserve the whole location when any current/in-flight spec is
2630- // present; deleting stale sibling specs is deferred to a later complete
2631- // snapshot rather than risking a false negative for a successful delta.
2632- return !contains_committed && !contains_in_flight;
2633- }
2634-
26352594bool IsEventReportLocationReadable (const CacheLocation &location,
26362595 bool strict_query_visibility,
26372596 const std::string &committed_version) {
@@ -2777,7 +2736,7 @@ ErrorCode CacheManager::ReportEvent(RequestContext *request_context,
27772736 const std::string &cleanup_instance,
27782737 const std::string &down_host,
27792738 uint64_t generation) {
2780- if (auto backend = weak_backend.lock ()) {
2739+ if (auto backend = weak_backend.lock (); backend ) {
27812740 auto gc = weak_gc.lock ();
27822741 if (gc && !gc->RegisterHostCleanupIntent (
27832742 cleanup_instance, requested_type, down_host, generation, backend)) {
@@ -3671,7 +3630,8 @@ ErrorCode CacheManager::ReportEvent(RequestContext *request_context,
36713630 }
36723631 if (!has_host_down && event_backend->IsNodeRegistered (instance_id, host_ip_port) && cache_garbage_collector_ &&
36733632 cache_garbage_collector_->IsEventReportCleanupEnabled()) {
3674- cache_garbage_collector_->CancelHostCleanupIntent (instance_id, requested_type, host_ip_port);
3633+ cache_garbage_collector_->CancelHostCleanupIntent (
3634+ instance_id, requested_type, host_ip_port, event_backend->GetNodeGeneration (instance_id, host_ip_port));
36753635 }
36763636
36773637 // MetaSearcher calls this once after the fused target-location read and
@@ -3906,6 +3866,14 @@ ErrorCode CacheManager::ReportEvent(RequestContext *request_context,
39063866 if (cache_garbage_collector_ && cache_garbage_collector_->IsEventReportCleanupEnabled ()) {
39073867 cleanup_dispatched = cache_garbage_collector_->RegisterHostCleanupIntent (
39083868 instance_id, requested_type, host_ip_port, gen_at_trigger, event_backend);
3869+ if (!cleanup_dispatched) {
3870+ KVCM_LOG_WARN (" trace_id [%s] | HOST_DOWN: failed to register GC cleanup intent for host [%s], "
3871+ " instance [%s], gen=%" PRIu64,
3872+ trace_id.c_str (),
3873+ host_ip_port.c_str (),
3874+ instance_id.c_str (),
3875+ gen_at_trigger);
3876+ }
39093877 } else {
39103878 const auto cleanup_state = event_cleanup_callback_state_;
39113879 uint64_t cleanup_epoch = 0 ;
0 commit comments