| Line |
Branch |
Exec |
Source |
| 1 |
|
|
#include "ps/rdma/rdma_deployment.h" |
| 2 |
|
|
|
| 3 |
|
|
#include <algorithm> |
| 4 |
|
|
#include <iomanip> |
| 5 |
|
|
#include <sstream> |
| 6 |
|
|
#include <stdexcept> |
| 7 |
|
|
|
| 8 |
|
|
namespace recstore { |
| 9 |
|
|
|
| 10 |
|
|
namespace { |
| 11 |
|
|
|
| 12 |
|
12 |
std::string StableDigest(const json& value) { |
| 13 |
|
12 |
std::uint64_t hash = 14695981039346656037ULL; |
| 14 |
3/4
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 7 taken 5356 times.
✓ Branch 8 taken 12 times.
|
5368 |
for (unsigned char byte : value.dump()) { |
| 15 |
|
5356 |
hash ^= byte; |
| 16 |
|
5356 |
hash *= 1099511628211ULL; |
| 17 |
|
12 |
} |
| 18 |
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
|
12 |
std::ostringstream output; |
| 19 |
4/8
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 12 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 12 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 12 times.
✗ Branch 13 not taken.
|
12 |
output << std::hex << std::setfill('0') << std::setw(16) << hash; |
| 20 |
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
|
24 |
return output.str(); |
| 21 |
|
12 |
} |
| 22 |
|
|
|
| 23 |
|
6 |
json CanonicalDeploymentConfig(const json& distributed_client, |
| 24 |
|
|
const json& rdma_deployment) { |
| 25 |
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 |
json canonical_client = distributed_client; |
| 26 |
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 |
auto& servers = canonical_client["servers"]; |
| 27 |
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 |
std::sort( |
| 28 |
|
6 |
servers.begin(), servers.end(), [](const json& lhs, const json& rhs) { |
| 29 |
|
8 |
return lhs.at("shard").get<int>() < rhs.at("shard").get<int>(); |
| 30 |
|
|
}); |
| 31 |
|
|
|
| 32 |
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 |
json canonical_rdma = rdma_deployment; |
| 33 |
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 |
auto& nodes = canonical_rdma["nodes"]; |
| 34 |
1/2
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
|
6 |
std::sort(nodes.begin(), nodes.end(), [](const json& lhs, const json& rhs) { |
| 35 |
|
20 |
return lhs.at("node_id").get<int>() < rhs.at("node_id").get<int>(); |
| 36 |
|
|
}); |
| 37 |
|
|
return { |
| 38 |
|
6 |
{"distributed_client", std::move(canonical_client)}, |
| 39 |
|
6 |
{"rdma_deployment", std::move(canonical_rdma)}, |
| 40 |
11/22
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 6 times.
✗ Branch 9 not taken.
✓ Branch 12 taken 6 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 6 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 12 times.
✓ Branch 18 taken 6 times.
✓ Branch 20 taken 12 times.
✓ Branch 21 taken 6 times.
✓ Branch 23 taken 12 times.
✓ Branch 24 taken 6 times.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
|
60 |
}; |
| 41 |
|
6 |
} |
| 42 |
|
|
|
| 43 |
|
|
} // namespace |
| 44 |
|
|
|
| 45 |
|
|
ResolvedRdmaDeployment |
| 46 |
|
72 |
ParseResolvedRdmaDeployment(const json& distributed_client) { |
| 47 |
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 72 times.
|
72 |
if (!distributed_client.is_object()) { |
| 48 |
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
✗ |
throw std::invalid_argument("RDMA distributed_client must be an object"); |
| 49 |
|
|
} |
| 50 |
5/6
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 70 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 70 times.
|
142 |
if (!distributed_client.contains("num_shards") || |
| 51 |
2/4
✓ Branch 1 taken 70 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 70 times.
|
70 |
!distributed_client["num_shards"].is_number_integer()) { |
| 52 |
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 |
throw std::invalid_argument("RDMA distributed_client.num_shards must be an " |
| 53 |
|
4 |
"explicit positive integer"); |
| 54 |
|
|
} |
| 55 |
2/4
✓ Branch 1 taken 70 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 70 times.
✗ Branch 5 not taken.
|
70 |
const int num_shards = distributed_client["num_shards"].get<int>(); |
| 56 |
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 66 times.
|
70 |
if (num_shards <= 0) { |
| 57 |
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 |
throw std::invalid_argument("RDMA distributed_client.num_shards must be an " |
| 58 |
|
8 |
"explicit positive integer"); |
| 59 |
|
|
} |
| 60 |
5/6
✓ Branch 1 taken 66 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 64 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 64 times.
|
130 |
if (!distributed_client.contains("hash_method") || |
| 61 |
2/4
✓ Branch 1 taken 64 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 64 times.
|
64 |
!distributed_client["hash_method"].is_string()) { |
| 62 |
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 |
throw std::invalid_argument( |
| 63 |
|
4 |
"RDMA distributed_client.hash_method must be explicit"); |
| 64 |
|
|
} |
| 65 |
|
|
const std::string hash_method = |
| 66 |
2/4
✓ Branch 1 taken 64 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 64 times.
✗ Branch 5 not taken.
|
64 |
distributed_client["hash_method"].get<std::string>(); |
| 67 |
8/10
✓ Branch 1 taken 64 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 60 times.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✓ Branch 9 taken 2 times.
✓ Branch 10 taken 2 times.
✓ Branch 11 taken 62 times.
|
64 |
if (hash_method != "city_hash" && hash_method != "simple_mod") { |
| 68 |
2/4
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
|
2 |
throw std::invalid_argument("unsupported RDMA hash method: " + hash_method); |
| 69 |
|
|
} |
| 70 |
1/2
✓ Branch 1 taken 62 times.
✗ Branch 2 not taken.
|
62 |
if (!distributed_client.contains("max_keys_per_request") || |
| 71 |
6/8
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 2 times.
✓ Branch 3 taken 60 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 60 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 6 times.
✓ Branch 9 taken 56 times.
|
122 |
!distributed_client["max_keys_per_request"].is_number_integer() || |
| 72 |
4/6
✓ Branch 1 taken 60 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 60 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 56 times.
|
60 |
distributed_client["max_keys_per_request"].get<int>() <= 0) { |
| 73 |
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 |
throw std::invalid_argument("RDMA distributed_client.max_keys_per_request " |
| 74 |
|
12 |
"must be explicit and positive"); |
| 75 |
|
|
} |
| 76 |
1/2
✓ Branch 1 taken 56 times.
✗ Branch 2 not taken.
|
56 |
if (!distributed_client.contains("servers") || |
| 77 |
6/8
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 2 times.
✓ Branch 3 taken 54 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 54 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 6 times.
✓ Branch 9 taken 50 times.
|
110 |
!distributed_client["servers"].is_array() || |
| 78 |
1/2
✓ Branch 1 taken 54 times.
✗ Branch 2 not taken.
|
54 |
distributed_client["servers"].size() != |
| 79 |
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 50 times.
|
54 |
static_cast<std::size_t>(num_shards)) { |
| 80 |
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 |
throw std::invalid_argument("RDMA distributed_client.servers must be an " |
| 81 |
|
12 |
"array with one entry per shard"); |
| 82 |
|
|
} |
| 83 |
|
|
|
| 84 |
|
50 |
ResolvedRdmaDeployment deployment; |
| 85 |
|
50 |
deployment.num_shards = num_shards; |
| 86 |
1/2
✓ Branch 1 taken 50 times.
✗ Branch 2 not taken.
|
50 |
deployment.hash_method = hash_method; |
| 87 |
|
50 |
deployment.max_keys_per_request = |
| 88 |
2/4
✓ Branch 1 taken 50 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 50 times.
✗ Branch 5 not taken.
|
50 |
distributed_client["max_keys_per_request"].get<int>(); |
| 89 |
2/4
✓ Branch 1 taken 50 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 50 times.
✗ Branch 6 not taken.
|
50 |
deployment.endpoints.reserve(distributed_client["servers"].size()); |
| 90 |
1/2
✓ Branch 2 taken 50 times.
✗ Branch 3 not taken.
|
50 |
std::vector<bool> seen_shards(static_cast<std::size_t>(num_shards), false); |
| 91 |
6/10
✓ Branch 1 taken 50 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 90 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 76 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 126 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 90 times.
✓ Branch 15 taken 36 times.
|
126 |
for (const auto& server : distributed_client["servers"]) { |
| 92 |
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 88 times.
|
90 |
if (!server.is_object()) { |
| 93 |
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 |
throw std::invalid_argument( |
| 94 |
|
4 |
"RDMA distributed_client.servers entries must be objects"); |
| 95 |
|
|
} |
| 96 |
6/10
✓ Branch 1 taken 88 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 88 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 88 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 88 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 2 times.
✓ Branch 12 taken 86 times.
|
176 |
if (!server.contains("host") || !server["host"].is_string() || |
| 97 |
5/10
✓ Branch 1 taken 88 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 88 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 88 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2 times.
✓ Branch 11 taken 86 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
|
176 |
server["host"].get<std::string>().empty()) { |
| 98 |
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 |
throw std::invalid_argument( |
| 99 |
|
4 |
"RDMA distributed_client.servers[].host must be a non-empty string"); |
| 100 |
|
|
} |
| 101 |
5/10
✓ Branch 1 taken 86 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 86 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 86 times.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 86 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 86 times.
|
86 |
if (!server.contains("port") || !server["port"].is_number_integer()) { |
| 102 |
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
✗ |
throw std::invalid_argument( |
| 103 |
|
✗ |
"RDMA distributed_client.servers[].port must be explicit"); |
| 104 |
|
|
} |
| 105 |
2/4
✓ Branch 1 taken 86 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 86 times.
✗ Branch 5 not taken.
|
86 |
const int port = server["port"].get<int>(); |
| 106 |
4/4
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 82 times.
|
86 |
if (port < 1 || port > 65535) { |
| 107 |
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 |
throw std::invalid_argument( |
| 108 |
|
8 |
"RDMA distributed_client.servers[].port must be in [1, 65535]"); |
| 109 |
|
|
} |
| 110 |
7/10
✓ Branch 1 taken 82 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 80 times.
✓ Branch 4 taken 2 times.
✓ Branch 6 taken 80 times.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 80 times.
✓ Branch 11 taken 2 times.
✓ Branch 12 taken 80 times.
|
82 |
if (!server.contains("shard") || !server["shard"].is_number_integer()) { |
| 111 |
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 |
throw std::invalid_argument( |
| 112 |
|
4 |
"RDMA distributed_client.servers[].shard must be explicit"); |
| 113 |
|
|
} |
| 114 |
2/4
✓ Branch 1 taken 80 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 80 times.
✗ Branch 5 not taken.
|
80 |
const int shard = server["shard"].get<int>(); |
| 115 |
3/4
✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 78 times.
|
80 |
if (shard < 0 || shard >= num_shards) { |
| 116 |
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 |
throw std::invalid_argument( |
| 117 |
|
4 |
"RDMA distributed_client.servers[].shard is out of range"); |
| 118 |
|
|
} |
| 119 |
3/4
✓ Branch 1 taken 78 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 76 times.
|
78 |
if (seen_shards[static_cast<std::size_t>(shard)]) { |
| 120 |
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 |
throw std::invalid_argument( |
| 121 |
|
4 |
"RDMA distributed_client.servers contains duplicate shard"); |
| 122 |
|
|
} |
| 123 |
2/4
✓ Branch 1 taken 76 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 76 times.
✗ Branch 5 not taken.
|
76 |
const std::string host = server["host"].get<std::string>(); |
| 124 |
|
76 |
const int endpoint_index = static_cast<int>(deployment.endpoints.size()); |
| 125 |
2/4
✓ Branch 1 taken 76 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 76 times.
✗ Branch 5 not taken.
|
76 |
deployment.endpoints.push_back({host, port, shard}); |
| 126 |
1/2
✓ Branch 1 taken 76 times.
✗ Branch 2 not taken.
|
76 |
deployment.shard_to_endpoint_index.emplace(shard, endpoint_index); |
| 127 |
1/2
✓ Branch 1 taken 76 times.
✗ Branch 2 not taken.
|
76 |
seen_shards[static_cast<std::size_t>(shard)] = true; |
| 128 |
|
76 |
} |
| 129 |
2/2
✓ Branch 6 taken 70 times.
✓ Branch 7 taken 36 times.
|
106 |
for (bool seen : seen_shards) { |
| 130 |
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 70 times.
|
70 |
if (!seen) { |
| 131 |
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
✗ |
throw std::invalid_argument( |
| 132 |
|
✗ |
"RDMA distributed_client.servers must cover every shard"); |
| 133 |
|
|
} |
| 134 |
|
|
} |
| 135 |
|
72 |
return deployment; |
| 136 |
|
92 |
} |
| 137 |
|
|
|
| 138 |
|
|
namespace { |
| 139 |
|
36 |
RdmaFabricMode ParseMode(const json& node) { |
| 140 |
1/2
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
|
36 |
const auto mode = node.value("mode", std::string()); |
| 141 |
2/2
✓ Branch 1 taken 28 times.
✓ Branch 2 taken 8 times.
|
36 |
if (mode == "ib") |
| 142 |
|
28 |
return RdmaFabricMode::kIb; |
| 143 |
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
|
8 |
if (mode == "rocev1") |
| 144 |
|
✗ |
return RdmaFabricMode::kRocEv1; |
| 145 |
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 |
if (mode == "rocev2") |
| 146 |
|
8 |
return RdmaFabricMode::kRocEv2; |
| 147 |
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
✗ |
throw std::invalid_argument("RDMA fabric mode must be ib, rocev1, or rocev2"); |
| 148 |
|
36 |
} |
| 149 |
|
|
} // namespace |
| 150 |
|
|
|
| 151 |
|
30 |
ResolvedRdmaDeployment ParseResolvedRdmaDeploymentConfig(const json& config) { |
| 152 |
3/6
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 30 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 30 times.
|
60 |
if (!config.contains("distributed_client") || |
| 153 |
2/4
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 30 times.
|
30 |
!config.contains("rdma_deployment")) { |
| 154 |
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
✗ |
throw std::invalid_argument("RDMA config requires rdma_deployment"); |
| 155 |
|
|
} |
| 156 |
|
|
auto deployment = |
| 157 |
2/4
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 30 times.
✗ Branch 5 not taken.
|
30 |
ParseResolvedRdmaDeployment(config.at("distributed_client")); |
| 158 |
1/2
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
|
30 |
const auto& rdma = config.at("rdma_deployment"); |
| 159 |
|
118 |
if (!rdma.contains("deployment_id") || |
| 160 |
6/10
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 28 times.
✓ Branch 4 taken 2 times.
✓ Branch 6 taken 28 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 28 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 28 times.
|
58 |
!rdma.at("deployment_id").is_string() || |
| 161 |
6/10
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 28 times.
✓ Branch 8 taken 2 times.
✓ Branch 10 taken 2 times.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
|
58 |
rdma.at("deployment_id").get<std::string>().empty()) { |
| 162 |
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 |
throw std::invalid_argument( |
| 163 |
|
4 |
"rdma_deployment.deployment_id must be explicit and non-empty"); |
| 164 |
|
|
} |
| 165 |
7/10
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 26 times.
✓ Branch 4 taken 2 times.
✓ Branch 6 taken 26 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 26 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 2 times.
✓ Branch 12 taken 26 times.
|
54 |
if (!rdma.contains("epoch") || !rdma.at("epoch").is_number_integer() || |
| 166 |
3/6
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 26 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 26 times.
|
26 |
rdma.at("epoch").get<std::int64_t>() <= 0) { |
| 167 |
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 |
throw std::invalid_argument( |
| 168 |
|
4 |
"rdma_deployment.epoch must be explicit and positive"); |
| 169 |
|
|
} |
| 170 |
1/2
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
|
26 |
if (!rdma.contains("protocol_version") || |
| 171 |
6/8
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 2 times.
✓ Branch 3 taken 24 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 24 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✓ Branch 9 taken 24 times.
|
50 |
!rdma.at("protocol_version").is_number_integer() || |
| 172 |
3/6
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 24 times.
|
24 |
rdma.at("protocol_version").get<std::int64_t>() <= 0) { |
| 173 |
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 |
throw std::invalid_argument( |
| 174 |
|
4 |
"rdma_deployment.protocol_version must be explicit and positive"); |
| 175 |
|
|
} |
| 176 |
2/4
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
|
24 |
deployment.deployment_id = rdma.at("deployment_id").get<std::string>(); |
| 177 |
2/4
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
|
24 |
deployment.epoch = rdma.at("epoch").get<std::uint64_t>(); |
| 178 |
|
24 |
deployment.protocol_version = |
| 179 |
2/4
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
|
24 |
rdma.at("protocol_version").get<std::uint32_t>(); |
| 180 |
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 22 times.
|
24 |
if (deployment.protocol_version != kRdmaDeploymentProtocolVersion) { |
| 181 |
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 |
throw std::invalid_argument("unsupported RDMA deployment protocol_version"); |
| 182 |
|
|
} |
| 183 |
1/2
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
|
22 |
if (!rdma.contains("num_clients") || |
| 184 |
4/8
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 22 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 22 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 22 times.
|
44 |
!rdma.at("num_clients").is_number_integer() || |
| 185 |
3/6
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 22 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 22 times.
|
22 |
rdma.at("num_clients").get<int>() <= 0) |
| 186 |
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
✗ |
throw std::invalid_argument( |
| 187 |
|
✗ |
"rdma_deployment.num_clients must be explicit and positive"); |
| 188 |
2/4
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 22 times.
✗ Branch 5 not taken.
|
22 |
deployment.num_clients = rdma.at("num_clients").get<int>(); |
| 189 |
9/12
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 22 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 22 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 20 times.
✓ Branch 10 taken 2 times.
✓ Branch 11 taken 2 times.
✓ Branch 12 taken 18 times.
✓ Branch 13 taken 4 times.
✓ Branch 14 taken 18 times.
|
42 |
if (!rdma.contains("nodes") || !rdma.at("nodes").is_array() || |
| 190 |
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 |
rdma.at("nodes").empty()) { |
| 191 |
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 |
throw std::invalid_argument( |
| 192 |
|
8 |
"rdma_deployment.nodes must be a non-empty array"); |
| 193 |
|
|
} |
| 194 |
1/2
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
|
18 |
const auto& nodes = rdma.at("nodes"); |
| 195 |
5/8
✓ Branch 3 taken 42 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 34 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 52 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 42 times.
✓ Branch 12 taken 10 times.
|
52 |
for (const auto& node : nodes) { |
| 196 |
2/4
✓ Branch 2 taken 42 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 42 times.
✗ Branch 5 not taken.
|
84 |
if (!node.is_object() || !node.contains("node_id") || |
| 197 |
4/8
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 42 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 42 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 42 times.
✗ Branch 9 not taken.
|
42 |
!node.contains("role") || !node.contains("device") || |
| 198 |
6/12
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 42 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 42 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 42 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 42 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 42 times.
|
84 |
!node.contains("port") || !node.contains("gid_index")) { |
| 199 |
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
✗ |
throw std::invalid_argument( |
| 200 |
|
✗ |
"fabric node requires node_id, role, device, port, gid_index"); |
| 201 |
|
|
} |
| 202 |
1/2
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
|
42 |
if (!node.at("node_id").is_number_integer() || |
| 203 |
4/8
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 42 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 42 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 42 times.
✗ Branch 11 not taken.
|
42 |
!node.at("role").is_string() || !node.at("device").is_string() || |
| 204 |
4/8
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 42 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 42 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 42 times.
|
126 |
!node.at("port").is_number_integer() || |
| 205 |
2/4
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 42 times.
|
42 |
!node.at("gid_index").is_number_integer()) { |
| 206 |
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
✗ |
throw std::invalid_argument("RDMA fabric node fields have invalid types"); |
| 207 |
|
|
} |
| 208 |
2/4
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 42 times.
✗ Branch 5 not taken.
|
42 |
const int id = node.at("node_id").get<int>(); |
| 209 |
3/4
✓ Branch 5 taken 42 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 2 times.
✓ Branch 9 taken 40 times.
|
42 |
if (!deployment.fabrics.emplace(id, ResolvedRdmaFabric{}).second) { |
| 210 |
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 |
throw std::invalid_argument("duplicate RDMA fabric node_id"); |
| 211 |
|
|
} |
| 212 |
1/2
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
|
40 |
auto& fabric = deployment.fabrics.at(id); |
| 213 |
1/2
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
|
40 |
fabric.deployment_id = deployment.deployment_id; |
| 214 |
|
40 |
fabric.deployment_epoch = deployment.epoch; |
| 215 |
|
40 |
fabric.protocol_version = deployment.protocol_version; |
| 216 |
2/4
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 40 times.
✗ Branch 5 not taken.
|
40 |
const auto role = node.at("role").get<std::string>(); |
| 217 |
6/10
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
✓ Branch 4 taken 30 times.
✓ Branch 6 taken 10 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 10 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 40 times.
|
40 |
if (role != "server" && role != "client") { |
| 218 |
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
✗ |
throw std::invalid_argument("RDMA fabric role must be server or client"); |
| 219 |
|
|
} |
| 220 |
|
40 |
const bool server = role == "server"; |
| 221 |
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 10 times.
|
40 |
fabric.role = server ? RdmaNodeRole::kServer : RdmaNodeRole::kClient; |
| 222 |
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 10 times.
|
40 |
fabric.logical_id = server ? id : id - deployment.num_shards; |
| 223 |
5/6
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 28 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
|
40 |
if ((server && (id >= deployment.num_shards || fabric.logical_id < 0)) || |
| 224 |
5/6
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 28 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
|
38 |
(!server && (id < deployment.num_shards || fabric.logical_id < 0 || |
| 225 |
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 |
fabric.logical_id >= deployment.num_clients))) |
| 226 |
1/2
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 |
throw std::invalid_argument("RDMA fabric node_id/role is inconsistent"); |
| 227 |
1/2
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
|
36 |
fabric.mode = ParseMode(node); |
| 228 |
2/4
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 36 times.
✗ Branch 5 not taken.
|
36 |
fabric.device = node.at("device").get<std::string>(); |
| 229 |
2/4
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 36 times.
✗ Branch 5 not taken.
|
36 |
fabric.port = node.at("port").get<int>(); |
| 230 |
2/4
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 36 times.
✗ Branch 5 not taken.
|
36 |
fabric.gid_index = node.at("gid_index").get<int>(); |
| 231 |
2/4
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 36 times.
✗ Branch 4 not taken.
|
72 |
if (fabric.device.empty() || fabric.port < 1 || fabric.port > 255 || |
| 232 |
4/8
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 36 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 36 times.
|
72 |
fabric.gid_index < 0 || id < 0) { |
| 233 |
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
✗ |
throw std::invalid_argument("RDMA fabric device/port/gid_index invalid"); |
| 234 |
|
|
} |
| 235 |
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 28 times.
|
36 |
if (fabric.mode == RdmaFabricMode::kRocEv2) { |
| 236 |
7/10
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 2 times.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 6 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✓ Branch 11 taken 6 times.
|
14 |
if (!node.contains("hop_limit") || !node.contains("traffic_class") || |
| 237 |
2/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
|
6 |
!node.contains("flow_label")) { |
| 238 |
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 |
throw std::invalid_argument( |
| 239 |
|
4 |
"RoCE v2 requires hop_limit, traffic_class, flow_label"); |
| 240 |
|
|
} |
| 241 |
2/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
|
6 |
fabric.hop_limit = node.at("hop_limit").get<int>(); |
| 242 |
2/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
|
6 |
fabric.traffic_class = node.at("traffic_class").get<int>(); |
| 243 |
2/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
|
6 |
fabric.flow_label = node.at("flow_label").get<std::uint32_t>(); |
| 244 |
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
|
6 |
if (fabric.hop_limit < 1 || fabric.hop_limit > 255 || |
| 245 |
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
|
6 |
fabric.traffic_class < 0 || fabric.traffic_class > 255 || |
| 246 |
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 |
fabric.flow_label > 0xfffff) { |
| 247 |
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
✗ |
throw std::invalid_argument("RoCE v2 network fields are out of range"); |
| 248 |
|
|
} |
| 249 |
|
|
} |
| 250 |
|
40 |
} |
| 251 |
|
10 |
if (deployment.fabrics.size() != |
| 252 |
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 6 times.
|
10 |
static_cast<std::size_t>(deployment.num_shards + deployment.num_clients)) |
| 253 |
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 |
throw std::invalid_argument( |
| 254 |
|
8 |
"RDMA fabric nodes must cover every server and client"); |
| 255 |
|
|
const json canonical = |
| 256 |
2/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
|
6 |
CanonicalDeploymentConfig(config.at("distributed_client"), rdma); |
| 257 |
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 |
deployment.configuration_digest = StableDigest(canonical); |
| 258 |
|
|
deployment.fabric_digest = |
| 259 |
3/6
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 6 times.
✗ Branch 8 not taken.
|
6 |
StableDigest(canonical.at("rdma_deployment").at("nodes")); |
| 260 |
2/2
✓ Branch 7 taken 18 times.
✓ Branch 8 taken 6 times.
|
24 |
for (auto& [node_id, fabric] : deployment.fabrics) { |
| 261 |
|
|
(void)node_id; |
| 262 |
1/2
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
|
18 |
fabric.configuration_digest = deployment.configuration_digest; |
| 263 |
1/2
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
|
18 |
fabric.fabric_digest = deployment.fabric_digest; |
| 264 |
|
|
} |
| 265 |
|
12 |
return deployment; |
| 266 |
|
30 |
} |
| 267 |
|
|
|
| 268 |
|
|
const ResolvedRdmaFabric& |
| 269 |
|
✗ |
LocalRdmaFabric(const ResolvedRdmaDeployment& deployment, int node_id) { |
| 270 |
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
✗ |
const auto it = deployment.fabrics.find(node_id); |
| 271 |
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
✗ |
if (it == deployment.fabrics.end()) { |
| 272 |
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
✗ |
throw std::invalid_argument( |
| 273 |
0/4
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
✗ |
"missing RDMA fabric for local node_id=" + std::to_string(node_id)); |
| 274 |
|
|
} |
| 275 |
|
✗ |
return it->second; |
| 276 |
|
|
} |
| 277 |
|
|
|
| 278 |
|
|
} // namespace recstore |
| 279 |
|
|
|