Switch dump executable to libmgclient
Summary: Dump executable used to use C++ bolt api for connecting to the server. However, this is currently not efficient enough because it fetches entire data at once. We switched to C api libmgclient which supports streaming of data. Reviewers: teon.banek Reviewed By: teon.banek Subscribers: pullbot Differential Revision: https://phabricator.memgraph.io/D2129
This commit is contained in:
parent
804d123a6b
commit
7edf3e6935
@ -21,8 +21,8 @@ target_link_libraries(mg_client ${CLIENT_LIBS})
|
|||||||
|
|
||||||
# Memgraph Dump Target
|
# Memgraph Dump Target
|
||||||
add_executable(mg_dump mg_dump/main.cpp)
|
add_executable(mg_dump mg_dump/main.cpp)
|
||||||
target_link_libraries(mg_dump mg-communication mg-io)
|
target_include_directories(mg_dump PRIVATE ${MGCLIENT_INCLUDE_DIR})
|
||||||
|
target_link_libraries(mg_dump fmt gflags glog mgclient pthread)
|
||||||
|
|
||||||
# Strip the executable in release build.
|
# Strip the executable in release build.
|
||||||
string(TOLOWER ${CMAKE_BUILD_TYPE} lower_build_type)
|
string(TOLOWER ${CMAKE_BUILD_TYPE} lower_build_type)
|
||||||
@ -39,4 +39,4 @@ install(TARGETS mg_import_csv RUNTIME DESTINATION bin)
|
|||||||
install(TARGETS mg_client RUNTIME DESTINATION bin)
|
install(TARGETS mg_client RUNTIME DESTINATION bin)
|
||||||
|
|
||||||
# Target for building all the tool executables.
|
# Target for building all the tool executables.
|
||||||
add_custom_target(tools DEPENDS mg_import_csv mg_statsd mg_client)
|
add_custom_target(tools DEPENDS mg_import_csv mg_statsd mg_client mg_dump)
|
||||||
|
@ -1,17 +1,12 @@
|
|||||||
#include <exception>
|
#include <iostream>
|
||||||
#include <filesystem>
|
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
|
#include <fmt/format.h>
|
||||||
#include <gflags/gflags.h>
|
#include <gflags/gflags.h>
|
||||||
#include <glog/logging.h>
|
#include <glog/logging.h>
|
||||||
|
#include <mgclient.h>
|
||||||
|
|
||||||
#include "communication/bolt/client.hpp"
|
|
||||||
#include "io/network/endpoint.hpp"
|
|
||||||
#include "io/network/utils.hpp"
|
|
||||||
#include "version.hpp"
|
#include "version.hpp"
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
|
||||||
|
|
||||||
const char *kUsage =
|
const char *kUsage =
|
||||||
"Memgraph dump tool.\n"
|
"Memgraph dump tool.\n"
|
||||||
"A simple tool for dumping Memgraph database's data as list of openCypher "
|
"A simple tool for dumping Memgraph database's data as list of openCypher "
|
||||||
@ -26,51 +21,67 @@ DEFINE_bool(use_ssl, true, "Use SSL when connecting to the server");
|
|||||||
|
|
||||||
DECLARE_int32(min_log_level);
|
DECLARE_int32(min_log_level);
|
||||||
|
|
||||||
// NOLINTNEXTLINE(bugprone-exception-escape)
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
gflags::SetVersionString(version_string);
|
gflags::SetVersionString(version_string);
|
||||||
gflags::SetUsageMessage(kUsage);
|
gflags::SetUsageMessage(kUsage);
|
||||||
gflags::ParseCommandLineFlags(&argc, &argv, true);
|
gflags::ParseCommandLineFlags(&argc, &argv, true);
|
||||||
|
|
||||||
// TODO(tsabolcec): `FLAGS_min_log_level` is here to silent logs from
|
const std::string bolt_client_version =
|
||||||
// `communication::bolt::Client`. Remove this setting once we move to C
|
fmt::format("mg_dump/{}", gflags::VersionString());
|
||||||
// mg-bolt library which doesn't use glog.
|
|
||||||
FLAGS_min_log_level = google::ERROR;
|
|
||||||
google::InitGoogleLogging(argv[0]);
|
|
||||||
|
|
||||||
communication::Init();
|
// Setup session params
|
||||||
|
mg_session_params *params = mg_session_params_make();
|
||||||
|
if (!params) {
|
||||||
|
std::cerr << "Failed to allocate session params" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
mg_session_params_set_host(params, FLAGS_host.c_str());
|
||||||
|
mg_session_params_set_port(params, FLAGS_port);
|
||||||
|
if (!FLAGS_username.empty()) {
|
||||||
|
mg_session_params_set_username(params, FLAGS_username.c_str());
|
||||||
|
mg_session_params_set_password(params, FLAGS_password.c_str());
|
||||||
|
}
|
||||||
|
mg_session_params_set_client_name(params, bolt_client_version.c_str());
|
||||||
|
mg_session_params_set_sslmode(
|
||||||
|
params, FLAGS_use_ssl ? MG_SSLMODE_REQUIRE : MG_SSLMODE_DISABLE);
|
||||||
|
|
||||||
io::network::Endpoint endpoint(io::network::ResolveHostname(FLAGS_host),
|
// Establish connection
|
||||||
FLAGS_port);
|
mg_session *session = nullptr;
|
||||||
communication::ClientContext context(FLAGS_use_ssl);
|
int status = mg_connect(params, &session);
|
||||||
communication::bolt::Client client(&context);
|
mg_session_params_destroy(params);
|
||||||
|
if (status < 0) {
|
||||||
try {
|
std::cerr << "Connection failed: " << mg_session_error(session)
|
||||||
const std::string bolt_client_version =
|
<< std::endl;
|
||||||
fmt::format("mg_dump/{}", gflags::VersionString());
|
mg_session_destroy(session);
|
||||||
client.Connect(endpoint, FLAGS_username, FLAGS_password,
|
|
||||||
bolt_client_version);
|
|
||||||
} catch (const communication::bolt::ClientFatalException &e) {
|
|
||||||
std::cerr << "Connection failed: " << e.what() << std::endl;
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
if (mg_session_run(session, "DUMP DATABASE", nullptr, nullptr) < 0) {
|
||||||
auto ret = client.Execute("DUMP DATABASE", {});
|
std::cerr << "Execution failed: " << mg_session_error(session) << std::endl;
|
||||||
if (ret.fields.size() != 1) {
|
mg_session_destroy(session);
|
||||||
std::cerr << "Error: client received response in unexpected format"
|
|
||||||
<< std::endl;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const auto &row : ret.records) {
|
|
||||||
CHECK(row.size() == 1U) << "Unexpected number of columns in a row";
|
|
||||||
std::cout << row[0].ValueString() << std::endl;
|
|
||||||
}
|
|
||||||
} catch (const communication::bolt::ClientFatalException &e) {
|
|
||||||
std::cerr << "Client received exception: " << e.what() << std::endl;
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fetch results
|
||||||
|
mg_result *result;
|
||||||
|
while ((status = mg_session_pull(session, &result)) == 1) {
|
||||||
|
const mg_list *row = mg_result_row(result);
|
||||||
|
CHECK(mg_list_size(row) == 1)
|
||||||
|
<< "Error: dump client received data in unexpected format";
|
||||||
|
const mg_value *value = mg_list_at(row, 0);
|
||||||
|
CHECK(mg_value_get_type(value) == MG_VALUE_TYPE_STRING)
|
||||||
|
<< "Error: dump client received data in unexpected format";
|
||||||
|
const mg_string *str_value = mg_value_string(value);
|
||||||
|
std::cout.write(mg_string_data(str_value), mg_string_size(str_value));
|
||||||
|
std::cout << std::endl; // `std::endl` flushes
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status < 0) {
|
||||||
|
std::cerr << "Execution failed: " << mg_session_error(session) << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
mg_session_destroy(session);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user