Merge remote-tracking branch 'upstream/master' into security_connector_refactor_new

pull/16963/head
Yihua Zhang 6 years ago
commit f5ad6f0ee3
  1. 34
      src/core/lib/channel/channelz_registry.cc
  2. 4
      src/core/lib/channel/channelz_registry.h
  3. 173
      test/core/channel/channelz_test.cc

@ -79,12 +79,13 @@ void ChannelzRegistry::MaybePerformCompactionLocked() {
}
}
int ChannelzRegistry::FindByUuidLocked(intptr_t target_uuid) {
size_t left = 0;
size_t right = entities_.size() - 1;
int ChannelzRegistry::FindByUuidLocked(intptr_t target_uuid,
bool direct_hit_needed) {
int left = 0;
int right = int(entities_.size() - 1);
while (left <= right) {
size_t true_middle = left + (right - left) / 2;
size_t first_non_null = true_middle;
int true_middle = left + (right - left) / 2;
int first_non_null = true_middle;
while (first_non_null < right && entities_[first_non_null] == nullptr) {
first_non_null++;
}
@ -102,14 +103,14 @@ int ChannelzRegistry::FindByUuidLocked(intptr_t target_uuid) {
right = true_middle - 1;
}
}
return -1;
return direct_hit_needed ? -1 : left;
}
void ChannelzRegistry::InternalUnregister(intptr_t uuid) {
GPR_ASSERT(uuid >= 1);
MutexLock lock(&mu_);
GPR_ASSERT(uuid <= uuid_generator_);
int idx = FindByUuidLocked(uuid);
int idx = FindByUuidLocked(uuid, true);
GPR_ASSERT(idx >= 0);
entities_[idx] = nullptr;
num_empty_slots_++;
@ -121,7 +122,7 @@ BaseNode* ChannelzRegistry::InternalGet(intptr_t uuid) {
if (uuid < 1 || uuid > uuid_generator_) {
return nullptr;
}
int idx = FindByUuidLocked(uuid);
int idx = FindByUuidLocked(uuid, true);
return idx < 0 ? nullptr : entities_[idx];
}
@ -131,16 +132,13 @@ char* ChannelzRegistry::InternalGetTopChannels(intptr_t start_channel_id) {
grpc_json* json = top_level_json;
grpc_json* json_iterator = nullptr;
InlinedVector<BaseNode*, 10> top_level_channels;
// uuids index into entities one-off (idx 0 is really uuid 1, since 0 is
// reserved). However, we want to support requests coming in with
// start_channel_id=0, which signifies "give me everything." Hence this
// funky looking line below.
size_t start_idx = start_channel_id == 0 ? 0 : start_channel_id - 1;
bool reached_pagination_limit = false;
int start_idx = GPR_MAX(FindByUuidLocked(start_channel_id, false), 0);
for (size_t i = start_idx; i < entities_.size(); ++i) {
if (entities_[i] != nullptr &&
entities_[i]->type() ==
grpc_core::channelz::BaseNode::EntityType::kTopLevelChannel) {
grpc_core::channelz::BaseNode::EntityType::kTopLevelChannel &&
entities_[i]->uuid() >= start_channel_id) {
// check if we are over pagination limit to determine if we need to set
// the "end" element. If we don't go through this block, we know that
// when the loop terminates, we have <= to kPaginationLimit.
@ -176,15 +174,13 @@ char* ChannelzRegistry::InternalGetServers(intptr_t start_server_id) {
grpc_json* json = top_level_json;
grpc_json* json_iterator = nullptr;
InlinedVector<BaseNode*, 10> servers;
// uuids index into entities one-off (idx 0 is really uuid 1, since 0 is
// reserved). However, we want to support requests coming in with
// start_server_id=0, which signifies "give me everything."
size_t start_idx = start_server_id == 0 ? 0 : start_server_id - 1;
bool reached_pagination_limit = false;
int start_idx = GPR_MAX(FindByUuidLocked(start_server_id, false), 0);
for (size_t i = start_idx; i < entities_.size(); ++i) {
if (entities_[i] != nullptr &&
entities_[i]->type() ==
grpc_core::channelz::BaseNode::EntityType::kServer) {
grpc_core::channelz::BaseNode::EntityType::kServer &&
entities_[i]->uuid() >= start_server_id) {
// check if we are over pagination limit to determine if we need to set
// the "end" element. If we don't go through this block, we know that
// when the loop terminates, we have <= to kPaginationLimit.

@ -92,7 +92,9 @@ class ChannelzRegistry {
void MaybePerformCompactionLocked();
// Performs binary search on entities_ to find the index with that uuid.
int FindByUuidLocked(intptr_t uuid);
// If direct_hit_needed, then will return -1 in case of absence.
// Else, will return idx of the first uuid higher than the target.
int FindByUuidLocked(intptr_t uuid, bool direct_hit_needed);
// protects members
gpr_mu mu_;

@ -85,6 +85,19 @@ void ValidateJsonArraySize(grpc_json* json, const char* key,
EXPECT_EQ(count, expected_size);
}
std::vector<intptr_t> GetUuidListFromArray(grpc_json* arr) {
EXPECT_EQ(arr->type, GRPC_JSON_ARRAY);
std::vector<intptr_t> uuids;
for (grpc_json* child = arr->child; child != nullptr; child = child->next) {
grpc_json* it = GetJsonChild(child, "ref");
EXPECT_NE(it, nullptr);
it = GetJsonChild(it, "channelId");
EXPECT_NE(it, nullptr);
uuids.push_back(atoi(it->value));
}
return uuids;
}
void ValidateGetTopChannels(size_t expected_channels) {
char* json_str = ChannelzRegistry::GetTopChannels(0);
grpc::testing::ValidateGetTopChannelsResponseProtoJsonTranslation(json_str);
@ -226,19 +239,7 @@ void ChannelzSleep(int64_t sleep_us) {
} // anonymous namespace
class ChannelzChannelTest : public ::testing::TestWithParam<size_t> {
protected:
// ensure we always have a fresh registry for tests.
void SetUp() override {
ChannelzRegistry::Shutdown();
ChannelzRegistry::Init();
}
void TearDown() override {
ChannelzRegistry::Shutdown();
ChannelzRegistry::Init();
}
};
class ChannelzChannelTest : public ::testing::TestWithParam<size_t> {};
TEST_P(ChannelzChannelTest, BasicChannel) {
grpc_core::ExecCtx exec_ctx;
@ -307,25 +308,39 @@ TEST_P(ChannelzChannelTest, LastCallStartedMillis) {
EXPECT_NE(millis1, millis4);
}
TEST(ChannelzGetTopChannelsTest, BasicGetTopChannelsTest) {
class ChannelzRegistryBasedTest : public ::testing::TestWithParam<size_t> {
protected:
// ensure we always have a fresh registry for tests.
void SetUp() override {
ChannelzRegistry::Shutdown();
ChannelzRegistry::Init();
}
void TearDown() override {
ChannelzRegistry::Shutdown();
ChannelzRegistry::Init();
}
};
TEST_F(ChannelzRegistryBasedTest, BasicGetTopChannelsTest) {
grpc_core::ExecCtx exec_ctx;
ChannelFixture channel;
ValidateGetTopChannels(1);
}
TEST(ChannelzGetTopChannelsTest, NoChannelsTest) {
TEST_F(ChannelzRegistryBasedTest, NoChannelsTest) {
grpc_core::ExecCtx exec_ctx;
ValidateGetTopChannels(0);
}
TEST(ChannelzGetTopChannelsTest, ManyChannelsTest) {
TEST_F(ChannelzRegistryBasedTest, ManyChannelsTest) {
grpc_core::ExecCtx exec_ctx;
ChannelFixture channels[10];
(void)channels; // suppress unused variable error
ValidateGetTopChannels(10);
}
TEST(ChannelzGetTopChannelsTest, GetTopChannelsPagination) {
TEST_F(ChannelzRegistryBasedTest, GetTopChannelsPagination) {
grpc_core::ExecCtx exec_ctx;
// this is over the pagination limit.
ChannelFixture channels[150];
@ -351,7 +366,116 @@ TEST(ChannelzGetTopChannelsTest, GetTopChannelsPagination) {
gpr_free(json_str);
}
TEST(ChannelzGetTopChannelsTest, InternalChannelTest) {
TEST_F(ChannelzRegistryBasedTest, GetTopChannelsUuidCheck) {
const intptr_t kNumChannels = 50;
grpc_core::ExecCtx exec_ctx;
ChannelFixture channels[kNumChannels];
(void)channels; // suppress unused variable error
char* json_str = ChannelzRegistry::GetTopChannels(0);
grpc_json* parsed_json = grpc_json_parse_string(json_str);
ValidateJsonArraySize(parsed_json, "channel", kNumChannels);
grpc_json* json_channels = GetJsonChild(parsed_json, "channel");
std::vector<intptr_t> uuids = GetUuidListFromArray(json_channels);
for (int i = 0; i < kNumChannels; ++i) {
EXPECT_EQ(i + 1, uuids[i]);
}
grpc_json_destroy(parsed_json);
gpr_free(json_str);
}
TEST_F(ChannelzRegistryBasedTest, GetTopChannelsMiddleUuidCheck) {
const intptr_t kNumChannels = 50;
const intptr_t kMidQuery = 40;
grpc_core::ExecCtx exec_ctx;
ChannelFixture channels[kNumChannels];
(void)channels; // suppress unused variable error
// only query for the end of the channels
char* json_str = ChannelzRegistry::GetTopChannels(kMidQuery);
grpc_json* parsed_json = grpc_json_parse_string(json_str);
ValidateJsonArraySize(parsed_json, "channel", kNumChannels - kMidQuery + 1);
grpc_json* json_channels = GetJsonChild(parsed_json, "channel");
std::vector<intptr_t> uuids = GetUuidListFromArray(json_channels);
for (size_t i = 0; i < uuids.size(); ++i) {
EXPECT_EQ(static_cast<intptr_t>(kMidQuery + i), uuids[i]);
}
grpc_json_destroy(parsed_json);
gpr_free(json_str);
}
TEST_F(ChannelzRegistryBasedTest, GetTopChannelsNoHitUuid) {
grpc_core::ExecCtx exec_ctx;
ChannelFixture pre_channels[40]; // will take uuid[1, 40]
(void)pre_channels; // suppress unused variable error
ServerFixture servers[10]; // will take uuid[41, 50]
(void)servers; // suppress unused variable error
ChannelFixture channels[10]; // will take uuid[51, 60]
(void)channels; // suppress unused variable error
// query in the middle of the server channels
char* json_str = ChannelzRegistry::GetTopChannels(45);
grpc_json* parsed_json = grpc_json_parse_string(json_str);
ValidateJsonArraySize(parsed_json, "channel", 10);
grpc_json* json_channels = GetJsonChild(parsed_json, "channel");
std::vector<intptr_t> uuids = GetUuidListFromArray(json_channels);
for (size_t i = 0; i < uuids.size(); ++i) {
EXPECT_EQ(static_cast<intptr_t>(51 + i), uuids[i]);
}
grpc_json_destroy(parsed_json);
gpr_free(json_str);
}
TEST_F(ChannelzRegistryBasedTest, GetTopChannelsMoreGaps) {
grpc_core::ExecCtx exec_ctx;
ChannelFixture channel_with_uuid1;
{ ServerFixture channel_with_uuid2; }
ChannelFixture channel_with_uuid3;
{ ServerFixture server_with_uuid4; }
ChannelFixture channel_with_uuid5;
// Current state of list: [1, NULL, 3, NULL, 5]
char* json_str = ChannelzRegistry::GetTopChannels(2);
grpc_json* parsed_json = grpc_json_parse_string(json_str);
ValidateJsonArraySize(parsed_json, "channel", 2);
grpc_json* json_channels = GetJsonChild(parsed_json, "channel");
std::vector<intptr_t> uuids = GetUuidListFromArray(json_channels);
EXPECT_EQ(static_cast<intptr_t>(3), uuids[0]);
EXPECT_EQ(static_cast<intptr_t>(5), uuids[1]);
grpc_json_destroy(parsed_json);
gpr_free(json_str);
json_str = ChannelzRegistry::GetTopChannels(4);
parsed_json = grpc_json_parse_string(json_str);
ValidateJsonArraySize(parsed_json, "channel", 1);
json_channels = GetJsonChild(parsed_json, "channel");
uuids = GetUuidListFromArray(json_channels);
EXPECT_EQ(static_cast<intptr_t>(5), uuids[0]);
grpc_json_destroy(parsed_json);
gpr_free(json_str);
}
TEST_F(ChannelzRegistryBasedTest, GetTopChannelsUuidAfterCompaction) {
const intptr_t kLoopIterations = 50;
grpc_core::ExecCtx exec_ctx;
std::vector<UniquePtr<ChannelFixture>> even_channels;
{
// these will delete and unregister themselves after this block.
std::vector<UniquePtr<ChannelFixture>> odd_channels;
for (int i = 0; i < kLoopIterations; i++) {
odd_channels.push_back(MakeUnique<ChannelFixture>());
even_channels.push_back(MakeUnique<ChannelFixture>());
}
}
char* json_str = ChannelzRegistry::GetTopChannels(0);
grpc_json* parsed_json = grpc_json_parse_string(json_str);
ValidateJsonArraySize(parsed_json, "channel", kLoopIterations);
grpc_json* json_channels = GetJsonChild(parsed_json, "channel");
std::vector<intptr_t> uuids = GetUuidListFromArray(json_channels);
for (int i = 0; i < kLoopIterations; ++i) {
// only the even uuids will still be present.
EXPECT_EQ((i + 1) * 2, uuids[i]);
}
grpc_json_destroy(parsed_json);
gpr_free(json_str);
}
TEST_F(ChannelzRegistryBasedTest, InternalChannelTest) {
grpc_core::ExecCtx exec_ctx;
ChannelFixture channels[10];
(void)channels; // suppress unused variable error
@ -369,9 +493,7 @@ TEST(ChannelzGetTopChannelsTest, InternalChannelTest) {
grpc_channel_destroy(internal_channel);
}
class ChannelzServerTest : public ::testing::TestWithParam<size_t> {};
TEST_P(ChannelzServerTest, BasicServerAPIFunctionality) {
TEST(ChannelzServerTest, BasicServerAPIFunctionality) {
grpc_core::ExecCtx exec_ctx;
ServerFixture server(10);
ServerNode* channelz_server = grpc_server_get_channelz_node(server.server());
@ -388,18 +510,18 @@ TEST_P(ChannelzServerTest, BasicServerAPIFunctionality) {
ValidateServer(channelz_server, {3, 3, 3});
}
TEST(ChannelzGetServersTest, BasicGetServersTest) {
TEST_F(ChannelzRegistryBasedTest, BasicGetServersTest) {
grpc_core::ExecCtx exec_ctx;
ServerFixture server;
ValidateGetServers(1);
}
TEST(ChannelzGetServersTest, NoServersTest) {
TEST_F(ChannelzRegistryBasedTest, NoServersTest) {
grpc_core::ExecCtx exec_ctx;
ValidateGetServers(0);
}
TEST(ChannelzGetServersTest, ManyServersTest) {
TEST_F(ChannelzRegistryBasedTest, ManyServersTest) {
grpc_core::ExecCtx exec_ctx;
ServerFixture servers[10];
(void)servers; // suppress unused variable error
@ -409,9 +531,6 @@ TEST(ChannelzGetServersTest, ManyServersTest) {
INSTANTIATE_TEST_CASE_P(ChannelzChannelTestSweep, ChannelzChannelTest,
::testing::Values(0, 8, 64, 1024, 1024 * 1024));
INSTANTIATE_TEST_CASE_P(ChannelzServerTestSweep, ChannelzServerTest,
::testing::Values(0, 8, 64, 1024, 1024 * 1024));
} // namespace testing
} // namespace channelz
} // namespace grpc_core

Loading…
Cancel
Save