diff --git a/db/view/view.cc b/db/view/view.cc index 4d3e5a2345..34000c47a7 100644 --- a/db/view/view.cc +++ b/db/view/view.cc @@ -1536,6 +1536,14 @@ bool needs_static_row(const mutation_partition& mp, const std::vectorget_token_metadata_ptr()->get_topology(); auto my_address = topology.my_address(); auto my_datacenter = topology.get_datacenter(); @@ -1562,20 +1571,26 @@ get_view_natural_endpoint( } for (auto&& view_endpoint : view_erm->get_natural_endpoints(view_token)) { - // If this base replica is also one of the view replicas, we use - // ourselves as the view replica. - if (view_endpoint == my_address) { - return view_endpoint; - } - // We have to remove any endpoint which is shared between the base - // and the view, as it will select itself and throw off the counts - // otherwise. - auto it = std::find(base_endpoints.begin(), base_endpoints.end(), - view_endpoint); - if (it != base_endpoints.end()) { - base_endpoints.erase(it); - } else if (!network_topology || topology.get_datacenter(view_endpoint) == my_datacenter) { - view_endpoints.push_back(view_endpoint); + if (use_legacy_self_pairing) { + // If this base replica is also one of the view replicas, we use + // ourselves as the view replica. + if (view_endpoint == my_address) { + return view_endpoint; + } + // We have to remove any endpoint which is shared between the base + // and the view, as it will select itself and throw off the counts + // otherwise. + auto it = std::find(base_endpoints.begin(), base_endpoints.end(), + view_endpoint); + if (it != base_endpoints.end()) { + base_endpoints.erase(it); + } else if (!network_topology || topology.get_datacenter(view_endpoint) == my_datacenter) { + view_endpoints.push_back(view_endpoint); + } + } else { + if (!network_topology || topology.get_datacenter(view_endpoint) == my_datacenter) { + view_endpoints.push_back(view_endpoint); + } } } @@ -1583,6 +1598,8 @@ get_view_natural_endpoint( auto base_it = std::find(base_endpoints.begin(), base_endpoints.end(), my_address); if (base_it == base_endpoints.end()) { // This node is not a base replica of this key, so we return empty + // FIXME: This case shouldn't happen, and if it happens, a view update + // would be lost. We should reported or count this case. return {}; } return view_endpoints[base_it - base_endpoints.begin()]; @@ -1638,7 +1655,13 @@ future<> view_update_generator::mutate_MV( auto view_ermp = mut.s->table().get_effective_replication_map(); auto& ks = _proxy.local().local_db().find_keyspace(mut.s->ks_name()); bool network_topology = dynamic_cast(&ks.get_replication_strategy()); - auto target_endpoint = get_view_natural_endpoint(base_ermp, view_ermp, network_topology, base_token, view_token); + // We set legacy self-pairing for old vnode-based tables (for backward + // compatibility), and unset it for tablets - where range movements + // are more frequent and backward compatibility is less important. + // TODO: Maybe allow users to set use_legacy_self_pairing explicitly + // on a view, like we have the synchronous_updates_flag. + bool use_legacy_self_pairing = !ks.get_replication_strategy().uses_tablets(); + auto target_endpoint = get_view_natural_endpoint(base_ermp, view_ermp, network_topology, base_token, view_token, use_legacy_self_pairing); auto remote_endpoints = view_ermp->get_pending_endpoints(view_token); auto sem_units = pending_view_updates.split(mut.fm.representation().size());