Add global and method parsing logic

reviewable/pr18586/r2
Yash Tibrewal 6 years ago
parent c871a0bb32
commit 9bfd2354ec
  1. 150
      src/core/ext/filters/client_channel/service_config.cc
  2. 53
      src/core/ext/filters/client_channel/service_config.h

@ -35,7 +35,7 @@ namespace grpc_core {
int ServiceConfig::registered_parsers_count = 0; int ServiceConfig::registered_parsers_count = 0;
UniquePtr<ServiceConfigParser> UniquePtr<ServiceConfigParser>
ServiceConfig::registered_parsers[ServiceConfig::kMaxParsers]; ServiceConfig::registered_parsers[ServiceConfigParser::kMaxParsers];
RefCountedPtr<ServiceConfig> ServiceConfig::Create(const char* json) { RefCountedPtr<ServiceConfig> ServiceConfig::Create(const char* json) {
UniquePtr<char> service_config_json(gpr_strdup(json)); UniquePtr<char> service_config_json(gpr_strdup(json));
@ -45,15 +45,155 @@ RefCountedPtr<ServiceConfig> ServiceConfig::Create(const char* json) {
gpr_log(GPR_INFO, "failed to parse JSON for service config"); gpr_log(GPR_INFO, "failed to parse JSON for service config");
return nullptr; return nullptr;
} }
return MakeRefCounted<ServiceConfig>(std::move(service_config_json), bool success;
std::move(json_string), json_tree); auto return_value = MakeRefCounted<ServiceConfig>(
std::move(service_config_json), std::move(json_string), json_tree,
&success);
// return return_value;
return success ? return_value : nullptr;
} }
ServiceConfig::ServiceConfig(UniquePtr<char> service_config_json, ServiceConfig::ServiceConfig(UniquePtr<char> service_config_json,
UniquePtr<char> json_string, grpc_json* json_tree) UniquePtr<char> json_string, grpc_json* json_tree,
bool* success)
: service_config_json_(std::move(service_config_json)), : service_config_json_(std::move(service_config_json)),
json_string_(std::move(json_string)), json_string_(std::move(json_string)),
json_tree_(json_tree) {} json_tree_(json_tree) {
GPR_DEBUG_ASSERT(success != nullptr);
if (json_tree->type != GRPC_JSON_OBJECT || json_tree->key != nullptr) {
gpr_log(GPR_ERROR, "error");
*success = false;
return;
}
ParseGlobalParams(json_tree, success);
if (!*success) {
gpr_log(GPR_ERROR, "global error");
return;
}
ParsePerMethodParams(json_tree, success);
if (!*success) {
gpr_log(GPR_ERROR, "local error");
return;
}
}
void ServiceConfig::ParseGlobalParams(const grpc_json* json_tree,
bool* success) {
GPR_DEBUG_ASSERT(success != nullptr);
GPR_DEBUG_ASSERT(json_tree_->type == GRPC_JSON_OBJECT);
GPR_DEBUG_ASSERT(json_tree_->key == nullptr);
for (auto i = 0; i < registered_parsers_count; i++) {
auto parsed_obj =
registered_parsers[i]->ParseGlobalParams(json_tree, success);
if (!*success) {
return;
}
parsed_global_service_config_objects.push_back(parsed_obj);
}
*success = true;
}
bool ServiceConfig::ParseJsonMethodConfigToServiceConfigObjectsTable(
const grpc_json* json,
SliceHashTable<RefCountedPtr<ServiceConfigObjectsVector>>::Entry* entries,
size_t* idx) {
auto objs_vector = MakeRefCounted<ServiceConfigObjectsVector>();
for (auto i = 0; i < registered_parsers_count; i++) {
bool success;
auto parsed_obj =
registered_parsers[i]->ParsePerMethodParams(json, &success);
if (!success) {
return false;
}
objs_vector->vector.push_back(parsed_obj);
}
// Construct list of paths.
InlinedVector<UniquePtr<char>, 10> paths;
for (grpc_json* child = json->child; child != nullptr; child = child->next) {
if (child->key == nullptr) continue;
if (strcmp(child->key, "name") == 0) {
if (child->type != GRPC_JSON_ARRAY) return false;
for (grpc_json* name = child->child; name != nullptr; name = name->next) {
UniquePtr<char> path = ParseJsonMethodName(name);
if (path == nullptr) return false;
paths.push_back(std::move(path));
}
}
}
if (paths.size() == 0) return false; // No names specified.
// Add entry for each path.
for (size_t i = 0; i < paths.size(); ++i) {
entries[*idx].key = grpc_slice_from_copied_string(paths[i].get());
entries[*idx].value = objs_vector; // Takes a new ref.
++*idx;
}
return true;
}
void ServiceConfig::ParsePerMethodParams(const grpc_json* json_tree,
bool* success) {
GPR_DEBUG_ASSERT(success != nullptr);
GPR_DEBUG_ASSERT(json_tree_->type == GRPC_JSON_OBJECT);
GPR_DEBUG_ASSERT(json_tree_->key == nullptr);
SliceHashTable<RefCountedPtr<ServiceConfigObjectsVector>>::Entry* entries =
nullptr;
size_t num_entries = 0;
for (grpc_json* field = json_tree->child; field != nullptr;
field = field->next) {
if (field->key == nullptr) {
*success = false;
return;
}
if (strcmp(field->key, "methodConfig") == 0) {
if (entries != nullptr) {
GPR_ASSERT(false);
}
if (field->type != GRPC_JSON_ARRAY) {
*success = false;
return;
}
for (grpc_json* method = field->child; method != nullptr;
method = method->next) {
int count = CountNamesInMethodConfig(method);
if (count <= 0) {
*success = false;
return;
}
num_entries += static_cast<size_t>(count);
}
entries = static_cast<
SliceHashTable<RefCountedPtr<ServiceConfigObjectsVector>>::Entry*>(
gpr_zalloc(
num_entries *
sizeof(SliceHashTable<
RefCountedPtr<ServiceConfigObjectsVector>>::Entry)));
size_t idx = 0;
for (grpc_json* method = field->child; method != nullptr;
method = method->next) {
if (!ParseJsonMethodConfigToServiceConfigObjectsTable(method, entries,
&idx)) {
for (size_t i = 0; i < idx; ++i) {
grpc_slice_unref_internal(entries[i].key);
entries[i].value.reset();
}
gpr_free(entries);
*success = false;
return;
}
}
GPR_DEBUG_ASSERT(idx == num_entries);
break;
}
}
if (entries != nullptr) {
parsed_method_service_config_objects_table =
SliceHashTable<RefCountedPtr<ServiceConfigObjectsVector>>::Create(
num_entries, entries, nullptr);
gpr_free(entries);
}
*success = true;
}
ServiceConfig::~ServiceConfig() { grpc_json_destroy(json_tree_); } ServiceConfig::~ServiceConfig() { grpc_json_destroy(json_tree_); }

@ -56,7 +56,7 @@ namespace grpc_core {
/// This is the base class that all service config parsers MUST use to store /// This is the base class that all service config parsers MUST use to store
/// parsed service config data. /// parsed service config data.
class ServiceConfigParsedObject { class ServiceConfigParsedObject : public RefCounted<ServiceConfigParsedObject> {
public: public:
virtual ~ServiceConfigParsedObject() = default; virtual ~ServiceConfigParsedObject() = default;
@ -68,19 +68,35 @@ class ServiceConfigParser {
public: public:
virtual ~ServiceConfigParser() = default; virtual ~ServiceConfigParser() = default;
virtual UniquePtr<ServiceConfigParsedObject> ParseGlobalParams( virtual RefCountedPtr<ServiceConfigParsedObject> ParseGlobalParams(
const grpc_json* json) { const grpc_json* json, bool* success) {
if (success != nullptr) {
*success = true;
}
return nullptr; return nullptr;
} }
virtual UniquePtr<ServiceConfigParsedObject> ParsePerMethodParams( virtual RefCountedPtr<ServiceConfigParsedObject> ParsePerMethodParams(
const grpc_json* json) { const grpc_json* json, bool* success) {
if (success != nullptr) {
*success = true;
}
return nullptr; return nullptr;
} }
static constexpr int kMaxParsers = 32;
GRPC_ABSTRACT_BASE_CLASS; GRPC_ABSTRACT_BASE_CLASS;
}; };
class ServiceConfigObjectsVector
: public RefCounted<ServiceConfigObjectsVector> {
public:
grpc_core::InlinedVector<RefCountedPtr<ServiceConfigParsedObject>,
ServiceConfigParser::kMaxParsers>
vector;
};
class ServiceConfig : public RefCounted<ServiceConfig> { class ServiceConfig : public RefCounted<ServiceConfig> {
public: public:
/// Creates a new service config from parsing \a json_string. /// Creates a new service config from parsing \a json_string.
@ -129,12 +145,9 @@ class ServiceConfig : public RefCounted<ServiceConfig> {
return parsed_global_service_config_objects[index].get(); return parsed_global_service_config_objects[index].get();
} }
static constexpr int kMaxParsers = 32;
/// Retrieves the vector of method service config objects for a given path \a /// Retrieves the vector of method service config objects for a given path \a
/// path. /// path.
const grpc_core::InlinedVector<UniquePtr<ServiceConfigParsedObject>, const RefCountedPtr<ServiceConfigObjectsVector>*
kMaxParsers>*
GetMethodServiceConfigObjectsVector(const grpc_slice& path) { GetMethodServiceConfigObjectsVector(const grpc_slice& path) {
const auto* value = parsed_method_service_config_objects_table->Get(path); const auto* value = parsed_method_service_config_objects_table->Get(path);
// If we didn't find a match for the path, try looking for a wildcard // If we didn't find a match for the path, try looking for a wildcard
@ -169,7 +182,7 @@ class ServiceConfig : public RefCounted<ServiceConfig> {
} }
static void ResetServiceConfigParsers() { static void ResetServiceConfigParsers() {
for (auto i = 0; i < kMaxParsers; i++) { for (auto i = 0; i < ServiceConfigParser::kMaxParsers; i++) {
registered_parsers[i].reset(nullptr); registered_parsers[i].reset(nullptr);
} }
registered_parsers_count = 0; registered_parsers_count = 0;
@ -182,7 +195,11 @@ class ServiceConfig : public RefCounted<ServiceConfig> {
// Takes ownership of \a json_tree. // Takes ownership of \a json_tree.
ServiceConfig(UniquePtr<char> service_config_json, ServiceConfig(UniquePtr<char> service_config_json,
UniquePtr<char> json_string, grpc_json* json_tree); UniquePtr<char> json_string, grpc_json* json_tree,
bool* success);
void ParseGlobalParams(const grpc_json* json_tree, bool* success);
void ParsePerMethodParams(const grpc_json* json_tree, bool* success);
// Returns the number of names specified in the method config \a json. // Returns the number of names specified in the method config \a json.
static int CountNamesInMethodConfig(grpc_json* json); static int CountNamesInMethodConfig(grpc_json* json);
@ -199,17 +216,23 @@ class ServiceConfig : public RefCounted<ServiceConfig> {
grpc_json* json, CreateValue<T> create_value, grpc_json* json, CreateValue<T> create_value,
typename SliceHashTable<RefCountedPtr<T>>::Entry* entries, size_t* idx); typename SliceHashTable<RefCountedPtr<T>>::Entry* entries, size_t* idx);
static bool ParseJsonMethodConfigToServiceConfigObjectsTable(
const grpc_json* json,
SliceHashTable<RefCountedPtr<ServiceConfigObjectsVector>>::Entry* entries,
size_t* idx);
static int registered_parsers_count; static int registered_parsers_count;
static UniquePtr<ServiceConfigParser> registered_parsers[kMaxParsers]; static UniquePtr<ServiceConfigParser>
registered_parsers[ServiceConfigParser::kMaxParsers];
UniquePtr<char> service_config_json_; UniquePtr<char> service_config_json_;
UniquePtr<char> json_string_; // Underlying storage for json_tree. UniquePtr<char> json_string_; // Underlying storage for json_tree.
grpc_json* json_tree_; grpc_json* json_tree_;
InlinedVector<UniquePtr<ServiceConfigParsedObject>, kMaxParsers> InlinedVector<RefCountedPtr<ServiceConfigParsedObject>,
ServiceConfigParser::kMaxParsers>
parsed_global_service_config_objects; parsed_global_service_config_objects;
RefCountedPtr<SliceHashTable< RefCountedPtr<SliceHashTable<RefCountedPtr<ServiceConfigObjectsVector>>>
InlinedVector<UniquePtr<ServiceConfigParsedObject>, kMaxParsers>>>
parsed_method_service_config_objects_table; parsed_method_service_config_objects_table;
}; };

Loading…
Cancel
Save