Skip to content

Commit e0fe0ad

Browse files
committed
[manager/meta] support V6D and subscriber reporting for multi-engine instances
1 parent 6e3d187 commit e0fe0ad

4 files changed

Lines changed: 373 additions & 10 deletions

File tree

kv_cache_manager/manager/cache_manager.cc

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <algorithm>
44
#include <array>
55
#include <cassert>
6+
#include <charconv>
67
#include <chrono>
78
#include <cinttypes>
89
#include <limits>
@@ -89,6 +90,39 @@ namespace kv_cache_manager {
8990
} while (0)
9091

9192
namespace {
93+
struct ReporterIdentityView {
94+
std::string_view base_host;
95+
std::optional<uint64_t> engine_rank;
96+
};
97+
98+
bool ParseReporterIdentity(std::string_view host_ip_port, ReporterIdentityView &out) {
99+
out = {};
100+
if (host_ip_port.empty()) {
101+
return false;
102+
}
103+
const size_t separator = host_ip_port.find('@');
104+
if (separator == std::string_view::npos) {
105+
out.base_host = host_ip_port;
106+
return true;
107+
}
108+
if (separator == 0 || separator + 1 >= host_ip_port.size() ||
109+
host_ip_port.find('@', separator + 1) != std::string_view::npos) {
110+
return false;
111+
}
112+
const std::string_view rank_text = host_ip_port.substr(separator + 1);
113+
if (rank_text.size() > 1 && rank_text.front() == '0') {
114+
return false;
115+
}
116+
uint64_t rank = 0;
117+
const auto [end, ec] = std::from_chars(rank_text.data(), rank_text.data() + rank_text.size(), rank);
118+
if (ec != std::errc{} || end != rank_text.data() + rank_text.size()) {
119+
return false;
120+
}
121+
out.base_host = host_ip_port.substr(0, separator);
122+
out.engine_rank = rank;
123+
return true;
124+
}
125+
92126
CacheManager::KeyVector GenKeyVector(const CacheManager::TokenIdsVector &tokens, int64_t block_size) {
93127
std::vector<int64_t> block_keys;
94128
size_t total_blocks = tokens.size() / block_size;
@@ -2668,7 +2702,9 @@ ErrorCode CacheManager::ReportEvent(RequestContext *request_context,
26682702
const std::string &host_ip_port = request->host_ip_port();
26692703
auto *response_status = response->mutable_header()->mutable_status();
26702704

2671-
if (instance_id.empty() || !SnapshotUriUtils::IsValidLocationIdComponent(host_ip_port)) {
2705+
ReporterIdentityView reporter_identity;
2706+
if (instance_id.empty() || !SnapshotUriUtils::IsValidLocationIdComponent(host_ip_port) ||
2707+
!ParseReporterIdentity(host_ip_port, reporter_identity)) {
26722708
KVCM_LOG_WARN("trace_id [%s] | ReportEvent: invalid instance_id or host_ip_port", trace_id.c_str());
26732709
response_status->set_code(proto::meta::INVALID_ARGUMENT);
26742710
response_status->set_message("invalid instance_id or host_ip_port");
@@ -4596,6 +4632,7 @@ CacheManager::GetHostCacheStateCheckLocDataExistFunc(const std::string &instance
45964632
struct EventVisibilitySnapshot {
45974633
std::shared_ptr<EventReportBackend> backend;
45984634
EventReportBackend::QueryVisibilitySnapshot reporters;
4635+
std::map<std::string, std::vector<std::string>, std::less<>> logical_hosts_by_reporter;
45994636
};
46004637
struct EventVisibilitySnapshots {
46014638
std::once_flag initialize_once;
@@ -4627,6 +4664,42 @@ CacheManager::GetHostCacheStateCheckLocDataExistFunc(const std::string &instance
46274664
snapshot.backend->GetQueryVisibilitySnapshot(instance_id, snapshot.reporters);
46284665
event_snapshots->by_storage_type.emplace(storage_type, std::move(snapshot));
46294666
}
4667+
4668+
std::map<std::string, std::vector<std::string>, std::less<>> ranked_hosts_by_base;
4669+
const auto l1p5_it = event_snapshots->by_storage_type.find(
4670+
DataStorageType::DATA_STORAGE_TYPE_EVENT_REPORT_L1P5);
4671+
if (l1p5_it != event_snapshots->by_storage_type.end()) {
4672+
for (const auto &[reporter, state] : l1p5_it->second.reporters) {
4673+
(void)state;
4674+
ReporterIdentityView identity;
4675+
if (ParseReporterIdentity(reporter, identity) && identity.engine_rank.has_value()) {
4676+
ranked_hosts_by_base[std::string(identity.base_host)].push_back(reporter);
4677+
}
4678+
}
4679+
}
4680+
for (auto &[base, ranked_hosts] : ranked_hosts_by_base) {
4681+
(void)base;
4682+
std::sort(ranked_hosts.begin(), ranked_hosts.end());
4683+
ranked_hosts.erase(std::unique(ranked_hosts.begin(), ranked_hosts.end()), ranked_hosts.end());
4684+
}
4685+
for (auto &[storage_type, snapshot] : event_snapshots->by_storage_type) {
4686+
for (const auto &[reporter, state] : snapshot.reporters) {
4687+
(void)state;
4688+
auto &logical_hosts = snapshot.logical_hosts_by_reporter[reporter];
4689+
ReporterIdentityView identity;
4690+
const bool parsed = ParseReporterIdentity(reporter, identity);
4691+
if (parsed && storage_type == DataStorageType::DATA_STORAGE_TYPE_EVENT_REPORT_L2 &&
4692+
!identity.engine_rank.has_value()) {
4693+
const auto ranked_it = ranked_hosts_by_base.find(identity.base_host);
4694+
if (ranked_it != ranked_hosts_by_base.end()) {
4695+
logical_hosts = ranked_it->second;
4696+
}
4697+
}
4698+
if (logical_hosts.empty()) {
4699+
logical_hosts.push_back(reporter);
4700+
}
4701+
}
4702+
}
46304703
};
46314704

46324705
return [fallback = std::move(fallback),
@@ -4661,6 +4734,10 @@ CacheManager::GetHostCacheStateCheckLocDataExistFunc(const std::string &instance
46614734
out_info.has_reporter_identity = true;
46624735
out_info.reporter_medium = reporter_medium;
46634736
out_info.reporter_host = reporter_host;
4737+
const auto logical_hosts_it = snapshot_it->second.logical_hosts_by_reporter.find(reporter_host);
4738+
if (logical_hosts_it != snapshot_it->second.logical_hosts_by_reporter.end()) {
4739+
out_info.logical_hosts = &logical_hosts_it->second;
4740+
}
46644741
return true;
46654742
};
46664743
}

kv_cache_manager/manager/meta_searcher.cc

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -481,14 +481,26 @@ void VisitHostSpecsForOneKey(const LocationRange &locations,
481481
// applying the reporter generation fence. Reuse that result.
482482
const bool specs_already_validated =
483483
request_check_location != nullptr && is_event_report && location_info.has_reporter_identity;
484+
const auto visit_logical_hosts = [&](std::string_view spec_name) {
485+
if (location_info.logical_hosts && !location_info.logical_hosts->empty()) {
486+
for (const auto &logical_host : *location_info.logical_hosts) {
487+
visitor(std::string_view(logical_host),
488+
spec_name,
489+
is_vineyard,
490+
location_info.reporter_host);
491+
}
492+
return;
493+
}
494+
visitor(location_info.reporter_host, spec_name, is_vineyard, location_info.reporter_host);
495+
};
484496
if (!visit_spec_names) {
485497
if (specs_already_validated) {
486-
visitor(location_info.reporter_host, std::string_view{}, is_vineyard);
498+
visit_logical_hosts(std::string_view{});
487499
continue;
488500
}
489501
for (const auto &spec : loc->location_specs()) {
490502
if (StandardUri(spec.uri()).Valid()) {
491-
visitor(location_info.reporter_host, std::string_view{}, is_vineyard);
503+
visit_logical_hosts(std::string_view{});
492504
break;
493505
}
494506
}
@@ -498,7 +510,7 @@ void VisitHostSpecsForOneKey(const LocationRange &locations,
498510
if (!specs_already_validated && !StandardUri(spec.uri()).Valid()) {
499511
continue;
500512
}
501-
visitor(location_info.reporter_host, std::string_view(spec.name()), is_vineyard);
513+
visit_logical_hosts(std::string_view(spec.name()));
502514
}
503515
continue;
504516
}
@@ -510,7 +522,7 @@ void VisitHostSpecsForOneKey(const LocationRange &locations,
510522
}
511523
const std::string host = uri.GetHostPort();
512524
if (!host.empty()) {
513-
visitor(std::string_view(host), std::string_view(spec.name()), false);
525+
visitor(std::string_view(host), std::string_view(spec.name()), false, std::string_view(host));
514526
}
515527
}
516528
}
@@ -527,7 +539,9 @@ void BuildHostsForOneKey(const LocationRange &locations,
527539
request_check_location,
528540
medium_set,
529541
false,
530-
[&hosts](std::string_view host, std::string_view, bool) { hosts.emplace_back(host); });
542+
[&hosts](std::string_view host, std::string_view, bool, std::string_view) {
543+
hosts.emplace_back(host);
544+
});
531545
std::sort(hosts.begin(), hosts.end());
532546
hosts.erase(std::unique(hosts.begin(), hosts.end()), hosts.end());
533547
}
@@ -544,7 +558,8 @@ void BuildCandidatePresenceForOneKey(const LocationRange &locations,
544558
request_check_location,
545559
medium_set,
546560
false,
547-
[&candidate_hosts, presence_words](std::string_view host, std::string_view, bool) {
561+
[&candidate_hosts, presence_words](
562+
std::string_view host, std::string_view, bool, std::string_view) {
548563
const auto it =
549564
std::lower_bound(candidate_hosts.begin(),
550565
candidate_hosts.end(),
@@ -601,11 +616,17 @@ void BuildHostSpecNamesForOneKey(const LocationRange &locations,
601616
request_check_location,
602617
medium_set,
603618
true,
604-
[&host_specs, &vineyard_host_specs](std::string_view host, std::string_view spec_name, bool is_vineyard) {
619+
[&host_specs, &vineyard_host_specs](std::string_view host,
620+
std::string_view spec_name,
621+
bool is_vineyard,
622+
std::string_view physical_reporter) {
605623
auto &local_names = host_specs[std::string(host)];
606624
local_names.emplace(spec_name);
607625
if (is_vineyard) {
608-
vineyard_host_specs[std::string(host)].emplace(spec_name);
626+
// Keep one P2P candidate per physical EventReport reporter.
627+
// A shared L2 reporter may project onto several logical ranks,
628+
// but must not become several Vineyard peers.
629+
vineyard_host_specs[std::string(physical_reporter)].emplace(spec_name);
609630
}
610631
});
611632
}
@@ -1114,7 +1135,7 @@ ErrorCode PrefixMatchWithMambaByHostWithoutP2P(MetaIndexer *meta_indexer,
11141135
medium_set,
11151136
true,
11161137
[&candidate_hosts, &required_spec_names, &seen_words, &host_present, spec_word_count](
1117-
std::string_view host, std::string_view spec_name, bool) {
1138+
std::string_view host, std::string_view spec_name, bool, std::string_view) {
11181139
const auto host_it = std::lower_bound(candidate_hosts.begin(),
11191140
candidate_hosts.end(),
11201141
host,

kv_cache_manager/manager/meta_searcher.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@ class MetaSearcher {
6565
// never retained in output.
6666
std::string_view reporter_medium;
6767
std::string_view reporter_host;
68+
// Optional request-owned projection of one physical reporter onto one
69+
// or more schedulable engine identities. Shared L2 reporters use this
70+
// to contribute their specs to every active ranked L1P5 engine without
71+
// duplicating the stored CacheLocation or its physical Vineyard URI.
72+
const std::vector<std::string> *logical_hosts = nullptr;
6873
};
6974
using CheckHostCacheLocationFunc =
7075
std::function<bool(const CacheLocation &location, HostCacheLocationInfo &out_info)>;

0 commit comments

Comments
 (0)