Skip to content
This repository has been archived by the owner on Jun 23, 2022. It is now read-only.

Commit

Permalink
feat(dup): support HTTP API to inspect duplication state (#401)
Browse files Browse the repository at this point in the history
  • Loading branch information
Wu Tao authored Mar 11, 2020
1 parent a685758 commit e2a945b
Show file tree
Hide file tree
Showing 15 changed files with 586 additions and 382 deletions.
5 changes: 4 additions & 1 deletion include/dsn/dist/replication/duplication_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,12 @@ extern const char *get_current_cluster_name();
/// The returned cluster id of get_duplication_cluster_id("wuhan-mi-srv-ad") is 3.
extern error_with<uint8_t> get_duplication_cluster_id(const std::string &cluster_name);

/// Returns a displayable string for this duplication_entry.
/// Returns a json string.
extern std::string duplication_entry_to_string(const duplication_entry &dup);

/// Returns a json string.
extern std::string duplication_query_response_to_string(const duplication_query_response &);

/// Returns a mapping from cluster_name to cluster_id.
extern const std::map<std::string, uint8_t> &get_duplication_group();

Expand Down
19 changes: 17 additions & 2 deletions include/dsn/dist/replication/replication_types.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 17 additions & 11 deletions src/dist/http/http_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,23 +127,29 @@ void http_server::add_service(http_service *service)
unresolved_query = decoded_unresolved_query.get_value();
}

// remove tailing '\0'
if (!unresolved_path.empty() && *unresolved_path.crbegin() == '\0') {
unresolved_path.pop_back();
}
std::vector<std::string> args;
boost::split(args, unresolved_path, boost::is_any_of("/"));
std::vector<string_view> real_args;
for (string_view arg : args) {
if (!arg.empty() && strlen(arg.data()) != 0) {
real_args.emplace_back(string_view(arg.data()));
std::vector<std::string> real_args;
for (std::string &arg : args) {
if (!arg.empty()) {
real_args.emplace_back(std::move(arg));
}
}
if (real_args.size() > 2) {
return error_s::make(ERR_INVALID_PARAMETERS);
}
if (real_args.size() == 1) {
ret.service_method = {std::string(real_args[0]), ""};
} else if (real_args.size() == 0) {
if (real_args.size() == 0) {
ret.service_method = {"", ""};
} else if (real_args.size() == 1) {
ret.service_method = {std::move(real_args[0]), ""};
} else {
ret.service_method = {std::string(real_args[0]), std::string(real_args[1])};
std::string method = std::move(real_args[1]);
for (int i = 2; i < real_args.size(); i++) {
method += '/';
method += real_args[i];
}
ret.service_method = {std::move(real_args[0]), std::move(method)};
}

// find if there are method args (<ip>:<port>/<service>/<method>?<arg>=<val>&<arg>=<val>)
Expand Down
3 changes: 2 additions & 1 deletion src/dist/http/test/http_server_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ TEST(http_server, parse_url)
{"http://127.0.0.1:34601/threads/", ERR_OK, {"threads", ""}},
{"http://127.0.0.1:34601//pprof/heap/", ERR_OK, {"pprof", "heap"}},
{"http://127.0.0.1:34601//pprof///heap", ERR_OK, {"pprof", "heap"}},
{"http://127.0.0.1:34601/pprof/heap/arg/", ERR_INVALID_PARAMETERS, {}},
{"http://127.0.0.1:34601/pprof/heap/arg/", ERR_OK, {"pprof", "heap/arg"}},
{"http://127.0.0.1:34601/pprof///heap///arg/", ERR_OK, {"pprof", "heap/arg"}},
};

for (auto tt : tests) {
Expand Down
67 changes: 41 additions & 26 deletions src/dist/replication/common/duplication_common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,8 @@
#include <dsn/dist/replication/duplication_common.h>
#include <dsn/dist/fmt_logging.h>
#include <dsn/utility/singleton.h>
#include <rapidjson/document.h>
#include <rapidjson/stringbuffer.h>
#include <rapidjson/prettywriter.h>
#include <dsn/utility/time_utils.h>
#include <nlohmann/json.hpp>

namespace dsn {
namespace replication {
Expand Down Expand Up @@ -114,32 +113,48 @@ class duplication_group_registry : public utils::singleton<duplication_group_reg

// TODO(wutao1): implement our C++ version of `TSimpleJSONProtocol` if there're
// more cases for converting thrift to JSON
/*extern*/ std::string duplication_entry_to_string(const duplication_entry &dup)
static nlohmann::json duplication_entry_to_json(const duplication_entry &ent)
{
rapidjson::Document doc;
doc.SetObject();
auto &alloc = doc.GetAllocator();

doc.AddMember("dupid", dup.dupid, alloc);
doc.AddMember("status", rapidjson::StringRef(duplication_status_to_string(dup.status)), alloc);
doc.AddMember("remote", rapidjson::StringRef(dup.remote.data(), dup.remote.length()), alloc);
doc.AddMember("create_ts", dup.create_ts, alloc);

doc.AddMember("progress", rapidjson::Value(), alloc);
auto &p = doc["progress"];
p.SetArray();
for (const auto &kv : dup.progress) {
rapidjson::Value part;
part.SetObject();
part.AddMember("pid", kv.first, alloc);
part.AddMember("confirmed", kv.second, alloc);
p.PushBack(std::move(part), alloc);
char ts_buf[30];
utils::time_ms_to_date_time(static_cast<uint64_t>(ent.create_ts), ts_buf, sizeof(ts_buf));
nlohmann::json json{
{"dupid", ent.dupid},
{"create_ts", ts_buf},
{"remote", ent.remote},
{"status", duplication_status_to_string(ent.status)},
};
if (ent.__isset.not_confirmed) {
nlohmann::json sub_json;
for (const auto &p : ent.not_confirmed) {
sub_json[std::to_string(p.first)] = p.second;
}
json["not_confirmed_mutations_num"] = sub_json;
}
if (ent.__isset.progress) {
nlohmann::json sub_json;
for (const auto &p : ent.progress) {
sub_json[std::to_string(p.first)] = p.second;
}
json["progress"] = sub_json;
}
return json;
}

rapidjson::StringBuffer sb;
rapidjson::Writer<rapidjson::StringBuffer> writer(sb);
doc.Accept(writer);
return sb.GetString();
/*extern*/ std::string duplication_entry_to_string(const duplication_entry &ent)
{
return duplication_entry_to_json(ent).dump();
}

/*extern*/ std::string duplication_query_response_to_string(const duplication_query_response &resp)
{
nlohmann::json json;
int i = 1;
for (const auto &ent : resp.entry_list) {
json["appid"] = resp.appid;
json[std::to_string(i)] = duplication_entry_to_json(ent);
i++;
}
return json.dump();
}

/*extern*/ const std::map<std::string, uint8_t> &get_duplication_group()
Expand Down
Loading

0 comments on commit e2a945b

Please sign in to comment.