Skip to content
Snippets Groups Projects
Commit 7f4e6580 authored by Sherman The Tank's avatar Sherman The Tank
Browse files

First commit

parent 6807ba2e
No related branches found
No related tags found
No related merge requests found
cmake_minimum_required(VERSION 3.0.0)
project("vGraph" CXX)
set(CMAKE_SKIP_RPATH TRUE)
set(CMAKE_VERBOSE_MAKEFILE TRUE)
if (!CMAKE_CXX_COMPILER)
message(FATAL_ERROR "No C++ compiler found")
endif()
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_EXE_LINKER_FLAGS "-static-libstdc++")
# Possible values are Debug, Release, RelWithDebInfo, MinSizeRel
set(CMAKE_BUILD_TYPE "RelWithDebInfo")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "_build")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "_build")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "_build")
# Set the project home dir
set(VGRAPH_HOME ${CMAKE_CURRENT_SOURCE_DIR})
# To include customized FindXXX.cmake modules
set(CMAKE_MODULE_PATH "${VGRAPH_HOME}/cmake" ${CMAKE_MODULE_PATH})
find_package(Boost)
find_package(OpenSSL)
find_package(Krb5 REQUIRED gssapi)
find_package(PCHSupport)
add_compile_options(-Winvalid-pch)
include_directories(SYSTEM ${VGRAPH_HOME}/third-party/_build/include)
include_directories(SYSTEM ${Boost_INCLUDE_DIRS})
include_directories(SYSTEM ${OPENSSL_INCLUDE_DIR})
include_directories(SYSTEM ${KRB5_INCLUDE_DIRS})
include_directories(AFTER common)
include_directories(AFTER interface)
include_directories(AFTER ${VGRAPH_HOME})
link_directories(third-party/_build/lib ${Boost_LIBRARY_DIRS} ${KRB5_LIBRARY_DIRS})
# All thrift libraries
set(THRIFT_LIBRARIES
thriftcpp2
thrift
thriftprotocol
server
async
protocol
transport
concurrency
security
thriftfrozen2
thrift-core
)
# All compression libraries
set(COMPRESSION_LIBRARIES bz2 snappy zstd z)
add_subdirectory(third-party)
add_subdirectory(interface)
add_subdirectory(common)
add_subdirectory(dataman)
add_subdirectory(client)
#add_subdirectory(storage)
add_subdirectory(server)
add_subdirectory(console)
add_subdirectory(consensus)
add_dependencies(common third-party)
#add_dependencies(storage_engines common)
add_custom_target(
clean-build
COMMAND ${CMAKE_MAKE_PROGRAM} clean
DEPENDS clean-interface clean-pch
)
add_custom_target(
clean-all
COMMAND ${CMAKE_MAKE_PROGRAM} clean
DEPENDS clean-interface clean-pch clean-third-party
)
add_custom_target(
distclean
COMMAND "find" "." "-name" "CMakeFiles" "|" "xargs" "rm" "-fr"
COMMAND "find" "." "-name" "CMakeCache.txt" "|" "xargs" "rm" "-f"
COMMAND "find" "." "-name" "cmake_install.cmake" "|" "xargs" "rm" "-f"
COMMAND "find" "." "-name" "Makefile" "|" "xargs" "rm" "-f"
DEPENDS clean-all
)
add_library(console_obj OBJECT CliManager.cpp CmdProcessor.cpp)
add_dependencies(console_obj common)
add_executable(
vgraph
GraphDbConsole.cpp
$<TARGET_OBJECTS:console_obj>
$<TARGET_OBJECTS:client_cpp_obj>
$<TARGET_OBJECTS:dataman_obj>
$<TARGET_OBJECTS:base_obj>
$<TARGET_OBJECTS:vgraph_thrift_obj>
$<TARGET_OBJECTS:time_obj>
)
target_link_libraries(
vgraph
thriftcpp2
thrift
thrift-core
thriftprotocol
async
protocol
transport
concurrency
security
thriftfrozen2
wangle
folly
boost_system
boost_context
${OPENSSL_LIBRARIES}
${KRB5_LIBRARIES}
event
bz2
snappy
zstd
z
glog
gflags
resolv
double-conversion
dl
-pthread
)
#add_subdirectory(test)
/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
*
* This source code is licensed under Apache 2.0 License
* (found in the LICENSE.Apache file in the root directory)
*/
#include "console/CliManager.h"
#include "client/cpp/GraphDbClient.h"
DEFINE_string(prompt, "vGraph >",
"Default prompt for the command line interface");
namespace vesoft {
namespace vgraph {
const int32_t kMaxAuthInfoRetries = 3;
const int32_t kMaxUsernameLen = 16;
const int32_t kMaxPasswordLen = 24;
const int32_t kMaxCommandLineLen = 1024;
bool CliManager::connect(const std::string& addr,
uint16_t port,
const std::string& username,
const std::string& password) {
char user[kMaxUsernameLen + 1];
char pass[kMaxPasswordLen + 1];
strncpy(user, username.c_str(), kMaxUsernameLen);
user[kMaxUsernameLen] = '\0';
strncpy(pass, password.c_str(), kMaxPasswordLen);
pass[kMaxPasswordLen] = '\0';
// Make sure username is not empty
for (int32_t i = 0; i < kMaxAuthInfoRetries && !strlen(user); i++) {
// Need to interactively get the username
std::cout << "Username: ";
std::cin.getline(user, kMaxUsernameLen);
user[kMaxUsernameLen] = '\0';
}
if (!strlen(user)) {
std::cout << "Authentication failed: "
"Need a valid username to authenticate\n\n";
return false;
}
// Make sure password is not empty
for (int32_t i = 0; i < kMaxAuthInfoRetries && !strlen(pass); i++) {
// Need to interactively get the password
std::cout << "Password: ";
std::cin.getline(pass, kMaxPasswordLen);
pass[kMaxPasswordLen] = '\0';
}
if (!strlen(pass)) {
std::cout << "Authentication failed: "
"Need a valid password\n\n";
return false;
}
addr_ = addr;
port_ = port;
username_ = user;
auto client = std::make_unique<GraphDbClient>(addr_, port_);
int32_t err = client->connect(user, pass);
if (!err) {
std::cerr << "\nWelcome to vGraph (Version 0.1)\n\n";
cmdProcessor_ = std::make_unique<CmdProcessor>(std::move(client));
return true;
} else {
// There is an error
std::cout << "Authentication failed: " << client->getErrorStr() << "\n";
return false;
}
}
void CliManager::batch(const std::string& filename) {
}
void CliManager::loop() {
char cmd[kMaxCommandLineLen + 1];
while (true) {
// Print out prompt
std::cout << FLAGS_prompt << " ";
std::cin.getline(cmd, kMaxCommandLineLen);
cmd[kMaxCommandLineLen] = '\0';
auto trimmedCmd = folly::trimWhitespace(cmd);
if (!trimmedCmd.empty() && !cmdProcessor_->process(trimmedCmd)) {
break;
}
}
std::cout << "\nBye!\n\n";
}
} // namespace vgraph
} // namespace vesoft
/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
*
* This source code is licensed under Apache 2.0 License
* (found in the LICENSE.Apache file in the root directory)
*/
#ifndef CONSOLE_CLIMANAGER_H_
#define CONSOLE_CLIMANAGER_H_
#include "base/Base.h"
#include "console/CmdProcessor.h"
namespace vesoft {
namespace vgraph {
class CliManager final {
public:
CliManager() = default;
~CliManager() = default;
bool connect(const std::string& addr,
uint16_t port,
const std::string& username,
const std::string& password);
void batch(const std::string& filename);
void loop();
private:
std::string addr_;
uint16_t port_;
std::string username_;
std::unique_ptr<CmdProcessor> cmdProcessor_;
};
} // namespace vgraph
} // namespace vesoft
#endif // CONSOLE_CLIMANAGER_H_
/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
*
* This source code is licensed under Apache 2.0 License
* (found in the LICENSE.Apache file in the root directory)
*/
#include "console/CmdProcessor.h"
#include "time/Duration.h"
#include "dataman/RowSetReader.h"
#include "dataman/RowReader.h"
namespace vesoft {
namespace vgraph {
#define GET_VALUE_WIDTH(VT, FN, FMT) \
VT val; \
if (fieldIt->get ## FN (val) == ResultType::SUCCEEDED) { \
int32_t len = folly::stringPrintf(FMT, val).size(); \
if (widths[fieldIdx] < len) { \
widths[fieldIdx] = len; \
} \
}
std::vector<int16_t> CmdProcessor::calColumnWidths(
const RowSetReader* dataReader) const {
std::vector<int16_t> widths;
// Check column names first
auto* schema = dataReader->schema();
for (int i = 0; i < schema->getNumFields(0); i++) {
widths.emplace_back(strlen(schema->getFieldName(i, 0)));
}
// TODO Then check data width
auto rowIt = dataReader->begin();
while (bool(rowIt)) {
int32_t fieldIdx = 0;
auto fieldIt = rowIt->begin();
while (bool(fieldIt)) {
switch (schema->getFieldType(fieldIdx, 0)->get_type()) {
case cpp2::SupportedType::BOOL: {
// Enough to hold "false"
if (widths[fieldIdx] < 5) {
widths[fieldIdx] = 5;
}
break;
}
case cpp2::SupportedType::INT: {
GET_VALUE_WIDTH(int64_t, Int, "%d")
break;
}
case cpp2::SupportedType::FLOAT: {
GET_VALUE_WIDTH(float, Float, "%f")
break;
}
case cpp2::SupportedType::DOUBLE: {
GET_VALUE_WIDTH(double, Double, "%f")
break;
}
case cpp2::SupportedType::STRING: {
folly::StringPiece val;
if (fieldIt->getString(val) == ResultType::SUCCEEDED) {
if (widths[fieldIdx] < val.size()) {
widths[fieldIdx] = val.size();
}
}
break;
}
case cpp2::SupportedType::VID: {
// Enough to hold "0x{16 letters}"
if (widths[fieldIdx] < 18) {
widths[fieldIdx] = 18;
}
break;
}
default: {
}
}
++fieldIt;
++fieldIdx;
}
++rowIt;
}
return std::move(widths);
}
#undef GET_VALUE_WIDTH
int32_t CmdProcessor::printResult(const RowSetReader* dataReader) const {
std::vector<int16_t> widths = calColumnWidths(dataReader);
int32_t sum = 0;
for (auto w : widths) {
sum += w;
}
std::string headerLine(sum + 3 * widths.size() + 1, '=');
std::string rowLine(sum + 3 * widths.size() + 1, '-');
std::cout << headerLine << "\n|";
std::vector<std::string> formats = printHeader(dataReader, widths);
std::cout << headerLine << "\n";
int32_t numRows = printData(dataReader, rowLine, formats);
return numRows;
}
std::vector<std::string> CmdProcessor::printHeader(
const RowSetReader* dataReader,
const std::vector<int16_t>& widths) const {
std::vector<std::string> formats;
auto* schema = dataReader->schema();
for (int i = 0; i < schema->getNumFields(0); i++) {
std::string fmt = folly::stringPrintf(" %%%ds |", widths[i]);
std::cout << folly::stringPrintf(fmt.c_str(), schema->getFieldName(i, 0));
switch (schema->getFieldType(i, 0)->get_type()) {
case cpp2::SupportedType::BOOL: {
formats.emplace_back(folly::stringPrintf(" %%%ds |", widths[i]));
break;
}
case cpp2::SupportedType::INT: {
formats.emplace_back(folly::stringPrintf(" %%%dld |", widths[i]));
break;
}
case cpp2::SupportedType::FLOAT: {
formats.emplace_back(folly::stringPrintf(" %%%df |", widths[i]));
break;
}
case cpp2::SupportedType::DOUBLE: {
formats.emplace_back(folly::stringPrintf(" %%%df |", widths[i]));
break;
}
case cpp2::SupportedType::STRING: {
formats.emplace_back(folly::stringPrintf(" %%%ds |", widths[i]));
break;
}
case cpp2::SupportedType::VID: {
formats.emplace_back(folly::stringPrintf(" %%%sX |", widths[i]));
break;
}
default: {
formats.emplace_back(" *ERROR* |");
}
}
}
std::cout << "\n";
return std::move(formats);
}
#define PRINT_FIELD_VALUE(VT, FN, VAL) \
VT val; \
if (fIt->get ## FN (val) == ResultType::SUCCEEDED) { \
std::cout << folly::stringPrintf(formats[fIdx].c_str(), (VAL)); \
} else { \
std::cout << " *BAD* |"; \
}
int32_t CmdProcessor::printData(const RowSetReader* dataReader,
const std::string& rowLine,
const std::vector<std::string>& formats) const {
int32_t numRows = 0;
auto* schema = dataReader->schema();
auto rowIt = dataReader->begin();
while (bool(rowIt)) {
int32_t fIdx = 0;
auto fIt = rowIt->begin();
std::cout << "|";
while (bool(fIt)) {
switch (schema->getFieldType(fIdx, 0)->get_type()) {
case cpp2::SupportedType::BOOL: {
PRINT_FIELD_VALUE(bool, Bool, (val ? "true" : "false"))
break;
}
case cpp2::SupportedType::INT: {
PRINT_FIELD_VALUE(int64_t, Int, val)
break;
}
case cpp2::SupportedType::FLOAT: {
PRINT_FIELD_VALUE(float, Float, val)
break;
}
case cpp2::SupportedType::DOUBLE: {
PRINT_FIELD_VALUE(double, Double, val)
break;
}
case cpp2::SupportedType::STRING: {
PRINT_FIELD_VALUE(folly::StringPiece, String, val.toString().c_str())
break;
}
case cpp2::SupportedType::VID: {
PRINT_FIELD_VALUE(int64_t, Vid, val)
break;
}
default: {
std::cout << " *ERROR* |";
}
}
++fIt;
++fIdx;
}
std::cout << "\n" << rowLine << "\n";
++numRows;
++rowIt;
}
return numRows;
}
#undef PRINT_FIELD_VALUE
bool CmdProcessor::processClientCmd(folly::StringPiece cmd,
bool& readyToExit) {
if (cmd == "exit") {
readyToExit = true;
return true;
} else {
readyToExit = false;
}
// TODO(sye) Check for all client commands
return false;
}
void CmdProcessor::processServerCmd(folly::StringPiece cmd) {
time::Duration dur;
std::unique_ptr<RowSetReader> dataReader;
int32_t res = client_->execute(cmd, dataReader);
if (!res) {
// Succeeded
auto* schema = dataReader->schema();
int32_t numRows = 0;
if (dataReader->schema()) {
// Only print when the schema is no empty
numRows = printResult(dataReader.get());
}
std::cout << "Got " << numRows << " rows (Time spent: "
<< client_->getServerLatency() << "/"
<< dur.elapsedInMSec() << " ms)\n";
} else {
std::cout << "[ERROR (" << res << ")] "
<< client_->getErrorStr() << "\n";
}
}
bool CmdProcessor::process(folly::StringPiece cmd) {
bool exit;
if (processClientCmd(cmd, exit)) {
return !exit;
}
processServerCmd(cmd);
return true;
}
} // namespace vgraph
} // namespace vesoft
/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
*
* This source code is licensed under Apache 2.0 License
* (found in the LICENSE.Apache file in the root directory)
*/
#ifndef CONSOLE_CMDPROCESSOR_H_
#define CONSOLE_CMDPROCESSOR_H_
#include "base/Base.h"
#include "client/cpp/GraphDbClient.h"
namespace vesoft {
namespace vgraph {
class CmdProcessor final {
public:
explicit CmdProcessor(std::unique_ptr<GraphDbClient> client)
: client_(std::move(client)) {}
~CmdProcessor() = default;
// Process the given command
//
// The method returns false when it's ready to exit, otherwise
// the method returns true
bool process(folly::StringPiece cmd);
private:
std::unique_ptr<GraphDbClient> client_;
// The method returns true if the given command is a client command
// and has been processed. Otherwise, the method returns false
bool processClientCmd(folly::StringPiece cmd, bool& readyToExit);
void processServerCmd(folly::StringPiece cmd);
std::vector<int16_t> calColumnWidths(const RowSetReader* dataReader) const;
int32_t printResult(const RowSetReader* dataReader) const;
std::vector<std::string> printHeader(const RowSetReader* dataReader,
const std::vector<int16_t>& widths) const;
// The method returns the total number of rows
int32_t printData(const RowSetReader* dataReader,
const std::string& rowLine,
const std::vector<std::string>& formats) const;
};
} // namespace vgraph
} // namespace vesoft
#endif // CONSOLE_CMDPROCESSOR_H_
/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
*
* This source code is licensed under Apache 2.0 License
* (found in the LICENSE.Apache file in the root directory)
*/
#include "base/Base.h"
#include "console/CliManager.h"
DEFINE_string(addr, "127.0.0.1", "GraphDB daemon IP address");
DEFINE_int32(port, 34500, "GraphDB daemon listening port");
DEFINE_string(username, "", "Username used to authenticate");
DEFINE_string(password, "", "Password used to authenticate");
int main(int argc, char *argv[]) {
folly::init(&argc, &argv, true);
using namespace vesoft::vgraph;
CliManager cli;
if (!cli.connect(FLAGS_addr, FLAGS_port, FLAGS_username, FLAGS_password)) {
exit(1);
}
cli.loop();
}
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment