From 0e7e84b9953e5bf815900d4d750a46997cf1a6e5 Mon Sep 17 00:00:00 2001 From: dutor <440396+dutor@users.noreply.github.com> Date: Sun, 16 Dec 2018 21:23:28 +0800 Subject: [PATCH] Refactor the source tree (#41) --- CMakeLists.txt | 151 ++++++------- CONTRIBUTING.md | 168 -------------- conf/CMakeLists.txt | 1 + conf/nebula-graphd.conf.default | 28 +++ src/CMakeLists.txt | 11 + src/README.md | 1 + src/console/CMakeLists.txt | 10 +- src/console/CliManager.cpp | 15 +- src/console/CliManager.h | 8 +- src/console/CmdProcessor.cpp | 8 +- src/console/CmdProcessor.h | 14 +- .../{GraphDbConsole.cpp => NebulaConsole.cpp} | 6 +- src/console/README.md | 1 + src/daemons/CMakeLists.txt | 33 +++ src/daemons/GraphDaemon.cpp | 123 ++++++++++ src/daemons/README.md | 1 + src/executor/AlterEdgeExecutor.cpp | 31 +++ src/executor/AlterEdgeExecutor.h | 35 +++ src/executor/AlterTagExecutor.cpp | 31 +++ src/executor/AlterTagExecutor.h | 36 +++ src/executor/Authenticator.h | 26 +++ src/executor/CMakeLists.txt | 33 +++ src/executor/ClientSession.cpp | 33 +++ src/executor/ClientSession.h | 69 ++++++ src/executor/CompoundExecutor.cpp | 74 ++++++ src/executor/CompoundExecutor.h | 41 ++++ src/executor/DefineEdgeExecutor.cpp | 36 +++ src/executor/DefineEdgeExecutor.h | 35 +++ src/executor/DefineTagExecutor.cpp | 34 +++ src/executor/DefineTagExecutor.h | 36 +++ src/executor/DescribeEdgeExecutor.cpp | 75 +++++++ src/executor/DescribeEdgeExecutor.h | 38 ++++ src/executor/DescribeTagExecutor.cpp | 59 +++++ src/executor/DescribeTagExecutor.h | 39 ++++ src/executor/ExecutionContext.cpp | 15 ++ src/executor/ExecutionContext.h | 56 +++++ src/executor/ExecutionEngine.cpp | 36 +++ src/executor/ExecutionEngine.h | 42 ++++ src/executor/ExecutionPlan.cpp | 78 +++++++ src/executor/ExecutionPlan.h | 62 +++++ src/executor/Executor.cpp | 75 +++++++ src/executor/Executor.h | 85 +++++++ src/executor/GoExecutor.cpp | 212 ++++++++++++++++++ src/executor/GoExecutor.h | 66 ++++++ src/executor/GraphFlags.cpp | 21 ++ src/executor/GraphFlags.h | 26 +++ src/executor/GraphService.cpp | 104 +++++++++ src/executor/GraphService.h | 43 ++++ src/executor/InsertEdgeExecutor.cpp | 55 +++++ src/executor/InsertEdgeExecutor.h | 42 ++++ src/executor/InsertVertexExecutor.cpp | 50 +++++ src/executor/InsertVertexExecutor.h | 40 ++++ src/executor/PipeExecutor.cpp | 112 +++++++++ src/executor/PipeExecutor.h | 50 +++++ src/executor/README.md | 1 + src/executor/RequestContext.h | 95 ++++++++ src/executor/SessionManager.cpp | 105 +++++++++ src/executor/SessionManager.h | 60 +++++ src/executor/SimpleAuthenticator.h | 32 +++ src/executor/TraverseExecutor.cpp | 37 +++ src/executor/TraverseExecutor.h | 97 ++++++++ src/executor/UseExecutor.cpp | 34 +++ src/executor/UseExecutor.h | 36 +++ src/executor/mock/EdgeSchema.cpp | 32 +++ src/executor/mock/EdgeSchema.h | 89 ++++++++ src/executor/mock/PropertiesSchema.cpp | 55 +++++ src/executor/mock/PropertiesSchema.h | 42 ++++ src/executor/mock/SchemaManager.cpp | 70 ++++++ src/executor/mock/SchemaManager.h | 43 ++++ src/executor/mock/StorageService.cpp | 107 +++++++++ src/executor/mock/StorageService.h | 86 +++++++ src/executor/mock/TagSchema.cpp | 34 +++ src/executor/mock/TagSchema.h | 51 +++++ src/executor/test/CMakeLists.txt | 71 ++++++ src/executor/test/DefineSchemaTest.cpp | 122 ++++++++++ src/executor/test/SessionManagerTest.cpp | 82 +++++++ src/executor/test/TestBase.cpp | 21 ++ src/executor/test/TestBase.h | 204 +++++++++++++++++ src/executor/test/TestEnv.cpp | 69 ++++++ src/executor/test/TestEnv.h | 51 +++++ src/executor/test/TestMain.cpp | 21 ++ src/parser/.gitignore | 6 +- src/parser/CMakeLists.txt | 6 +- src/parser/Clauses.cpp | 4 +- src/parser/Clauses.h | 2 +- src/parser/CompoundSentence.cpp | 4 +- src/parser/CompoundSentence.h | 8 +- src/parser/Expressions.cpp | 4 +- src/parser/Expressions.h | 4 +- src/parser/GQLParser.cpp | 4 +- src/parser/GQLParser.h | 12 +- .../{VGraphScanner.h => GraphScanner.h} | 24 +- src/parser/MaintainSentences.cpp | 4 +- src/parser/MaintainSentences.h | 4 +- src/parser/MutateSentences.cpp | 4 +- src/parser/MutateSentences.h | 4 +- src/parser/README.md | 1 + src/parser/Sentence.h | 4 +- src/parser/TraverseSentences.cpp | 4 +- src/parser/TraverseSentences.h | 4 +- src/parser/parser.yy | 72 +++--- src/parser/scanner.lex | 8 +- src/parser/test/ParserTest.cpp | 4 +- src/parser/test/ScannerTest.cpp | 18 +- 104 files changed, 4189 insertions(+), 377 deletions(-) delete mode 100644 CONTRIBUTING.md create mode 100644 conf/CMakeLists.txt create mode 100644 conf/nebula-graphd.conf.default create mode 100644 src/CMakeLists.txt create mode 100644 src/README.md rename src/console/{GraphDbConsole.cpp => NebulaConsole.cpp} (78%) create mode 100644 src/console/README.md create mode 100644 src/daemons/CMakeLists.txt create mode 100644 src/daemons/GraphDaemon.cpp create mode 100644 src/daemons/README.md create mode 100644 src/executor/AlterEdgeExecutor.cpp create mode 100644 src/executor/AlterEdgeExecutor.h create mode 100644 src/executor/AlterTagExecutor.cpp create mode 100644 src/executor/AlterTagExecutor.h create mode 100644 src/executor/Authenticator.h create mode 100644 src/executor/CMakeLists.txt create mode 100644 src/executor/ClientSession.cpp create mode 100644 src/executor/ClientSession.h create mode 100644 src/executor/CompoundExecutor.cpp create mode 100644 src/executor/CompoundExecutor.h create mode 100644 src/executor/DefineEdgeExecutor.cpp create mode 100644 src/executor/DefineEdgeExecutor.h create mode 100644 src/executor/DefineTagExecutor.cpp create mode 100644 src/executor/DefineTagExecutor.h create mode 100644 src/executor/DescribeEdgeExecutor.cpp create mode 100644 src/executor/DescribeEdgeExecutor.h create mode 100644 src/executor/DescribeTagExecutor.cpp create mode 100644 src/executor/DescribeTagExecutor.h create mode 100644 src/executor/ExecutionContext.cpp create mode 100644 src/executor/ExecutionContext.h create mode 100644 src/executor/ExecutionEngine.cpp create mode 100644 src/executor/ExecutionEngine.h create mode 100644 src/executor/ExecutionPlan.cpp create mode 100644 src/executor/ExecutionPlan.h create mode 100644 src/executor/Executor.cpp create mode 100644 src/executor/Executor.h create mode 100644 src/executor/GoExecutor.cpp create mode 100644 src/executor/GoExecutor.h create mode 100644 src/executor/GraphFlags.cpp create mode 100644 src/executor/GraphFlags.h create mode 100644 src/executor/GraphService.cpp create mode 100644 src/executor/GraphService.h create mode 100644 src/executor/InsertEdgeExecutor.cpp create mode 100644 src/executor/InsertEdgeExecutor.h create mode 100644 src/executor/InsertVertexExecutor.cpp create mode 100644 src/executor/InsertVertexExecutor.h create mode 100644 src/executor/PipeExecutor.cpp create mode 100644 src/executor/PipeExecutor.h create mode 100644 src/executor/README.md create mode 100644 src/executor/RequestContext.h create mode 100644 src/executor/SessionManager.cpp create mode 100644 src/executor/SessionManager.h create mode 100644 src/executor/SimpleAuthenticator.h create mode 100644 src/executor/TraverseExecutor.cpp create mode 100644 src/executor/TraverseExecutor.h create mode 100644 src/executor/UseExecutor.cpp create mode 100644 src/executor/UseExecutor.h create mode 100644 src/executor/mock/EdgeSchema.cpp create mode 100644 src/executor/mock/EdgeSchema.h create mode 100644 src/executor/mock/PropertiesSchema.cpp create mode 100644 src/executor/mock/PropertiesSchema.h create mode 100644 src/executor/mock/SchemaManager.cpp create mode 100644 src/executor/mock/SchemaManager.h create mode 100644 src/executor/mock/StorageService.cpp create mode 100644 src/executor/mock/StorageService.h create mode 100644 src/executor/mock/TagSchema.cpp create mode 100644 src/executor/mock/TagSchema.h create mode 100644 src/executor/test/CMakeLists.txt create mode 100644 src/executor/test/DefineSchemaTest.cpp create mode 100644 src/executor/test/SessionManagerTest.cpp create mode 100644 src/executor/test/TestBase.cpp create mode 100644 src/executor/test/TestBase.h create mode 100644 src/executor/test/TestEnv.cpp create mode 100644 src/executor/test/TestEnv.h create mode 100644 src/executor/test/TestMain.cpp rename src/parser/{VGraphScanner.h => GraphScanner.h} (53%) create mode 100644 src/parser/README.md diff --git a/CMakeLists.txt b/CMakeLists.txt index 24cdcc0b..159990dd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,17 +9,17 @@ # CMAKE_C_COMPILER -- Specify the compiler for C language # CMAKE_CXX_COMPILER -- Specify the compiler for C++ language # FLEX_EXECUTABLE -- Specify the full path of flex executable -# VGRAPH_GPERF_BIN_DIR -- Specify the full path to the directory +# NEBULA_GPERF_BIN_DIR -- Specify the full path to the directory # containing gperf binary # -# VGRAPH_KRB5_ROOT -- Specify the root directory for KRB5 -# VGRAPH_LIBUNWIND_ROOT -- Specify the root directory for libunwind -# VGRAPH_OPENSSL_ROOT -- Specify the root directory for openssl -# VGRAPH_BOOST_ROOT -- Specify the root directory for boost +# NEBULA_KRB5_ROOT -- Specify the root directory for KRB5 +# NEBULA_LIBUNWIND_ROOT -- Specify the root directory for libunwind +# NEBULA_OPENSSL_ROOT -- Specify the root directory for openssl +# NEBULA_BOOST_ROOT -- Specify the root directory for boost # cmake_minimum_required(VERSION 3.0.0) -project("vGraph" C CXX) +project("Nebula Graph" C CXX) set(CMAKE_SKIP_RPATH TRUE) @@ -35,6 +35,10 @@ set(CMAKE_CXX_STANDARD 14) set(CMAKE_EXE_LINKER_FLAGS "-static-libstdc++") +if (NOT THIRD_PARTY_JOBS) + set(THIRD_PARTY_JOBS 2) +endif(NOT THIRD_PARTY_JOBS) + # Possible values are Debug, Release, RelWithDebInfo, MinSizeRel if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "Debug") @@ -46,39 +50,39 @@ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "_build") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "_build") # Set the project home dir -set(VGRAPH_HOME ${CMAKE_CURRENT_SOURCE_DIR}) +set(NEBULA_HOME ${CMAKE_CURRENT_SOURCE_DIR}) # To include customized FindXXX.cmake modules -set(CMAKE_MODULE_PATH "${VGRAPH_HOME}/cmake" ${CMAKE_MODULE_PATH}) +set(CMAKE_MODULE_PATH "${NEBULA_HOME}/cmake" ${CMAKE_MODULE_PATH}) -if(NOT ${VGRAPH_KRB5_ROOT} STREQUAL "") - message(STATUS "Specified VGRAPH_KRB5_ROOT: " ${VGRAPH_KRB5_ROOT}) - list(APPEND CMAKE_INCLUDE_PATH ${VGRAPH_KRB5_ROOT}/include) - list(APPEND CMAKE_LIBRARY_PATH ${VGRAPH_KRB5_ROOT}/lib) - list(APPEND CMAKE_PROGRAM_PATH ${VGRAPH_KRB5_ROOT}/bin) +if(NOT ${NEBULA_KRB5_ROOT} STREQUAL "") + message(STATUS "Specified NEBULA_KRB5_ROOT: " ${NEBULA_KRB5_ROOT}) + list(APPEND CMAKE_INCLUDE_PATH ${NEBULA_KRB5_ROOT}/include) + list(APPEND CMAKE_LIBRARY_PATH ${NEBULA_KRB5_ROOT}/lib) + list(APPEND CMAKE_PROGRAM_PATH ${NEBULA_KRB5_ROOT}/bin) endif() -if(NOT ${VGRAPH_LIBUNWIND_ROOT} STREQUAL "") - message(STATUS "Specified VGRAPH_LIBUNWIND_ROOT: " ${VGRAPH_LIBUNWIND_ROOT}) - list(APPEND CMAKE_INCLUDE_PATH ${VGRAPH_LIBUNWIND_ROOT}/include) - list(APPEND CMAKE_LIBRARY_PATH ${VGRAPH_LIBUNWIND_ROOT}/lib) +if(NOT ${NEBULA_LIBUNWIND_ROOT} STREQUAL "") + message(STATUS "Specified NEBULA_LIBUNWIND_ROOT: " ${NEBULA_LIBUNWIND_ROOT}) + list(APPEND CMAKE_INCLUDE_PATH ${NEBULA_LIBUNWIND_ROOT}/include) + list(APPEND CMAKE_LIBRARY_PATH ${NEBULA_LIBUNWIND_ROOT}/lib) endif() -if(NOT ${VGRAPH_OPENSSL_ROOT} STREQUAL "") - message(STATUS "Specified VGRAPH_OPENSSL_ROOT: " ${VGRAPH_OPENSSL_ROOT}) - list(APPEND CMAKE_INCLUDE_PATH ${VGRAPH_OPENSSL_ROOT}/include) - list(APPEND CMAKE_LIBRARY_PATH ${VGRAPH_OPENSSL_ROOT}/lib) +if(NOT ${NEBULA_OPENSSL_ROOT} STREQUAL "") + message(STATUS "Specified NEBULA_OPENSSL_ROOT: " ${NEBULA_OPENSSL_ROOT}) + list(APPEND CMAKE_INCLUDE_PATH ${NEBULA_OPENSSL_ROOT}/include) + list(APPEND CMAKE_LIBRARY_PATH ${NEBULA_OPENSSL_ROOT}/lib) endif() -if(NOT ${VGRAPH_BOOST_ROOT} STREQUAL "") - message(STATUS "Specified VGRAPH_BOOST_ROOT: " ${VGRAPH_BOOST_ROOT}) - list(APPEND CMAKE_INCLUDE_PATH ${VGRAPH_BOOST_ROOT}/include) - list(APPEND CMAKE_LIBRARY_PATH ${VGRAPH_BOOST_ROOT}/lib) +if(NOT ${NEBULA_BOOST_ROOT} STREQUAL "") + message(STATUS "Specified NEBULA_BOOST_ROOT: " ${NEBULA_BOOST_ROOT}) + list(APPEND CMAKE_INCLUDE_PATH ${NEBULA_BOOST_ROOT}/include) + list(APPEND CMAKE_LIBRARY_PATH ${NEBULA_BOOST_ROOT}/lib) endif() -if(NOT ${VGRAPH_GPERF_BIN_DIR} STREQUAL "") - message(STATUS "Specified VGRAPH_GPERF_BIN_DIR: " ${VGRAPH_GPERF_BIN_DIR}) - list(APPEND CMAKE_PROGRAM_PATH ${VGRAPH_GPERF_BIN_DIR}) +if(NOT ${NEBULA_GPERF_BIN_DIR} STREQUAL "") + message(STATUS "Specified NEBULA_GPERF_BIN_DIR: " ${NEBULA_GPERF_BIN_DIR}) + list(APPEND CMAKE_PROGRAM_PATH ${NEBULA_GPERF_BIN_DIR}) endif() message(STATUS "CMAKE_INCLUDE_PATH: " ${CMAKE_INCLUDE_PATH}) @@ -98,53 +102,53 @@ find_package(Readline REQUIRED) add_compile_options(-Winvalid-pch) add_compile_options(-Wall) add_compile_options(-Werror) -add_compile_options(-Wno-error=sign-compare) +add_compile_options(-Wunused-parameter) add_compile_options(-Wshadow) -include_directories(SYSTEM ${VGRAPH_HOME}/third-party/bzip2/_install/include) -include_directories(SYSTEM ${VGRAPH_HOME}/third-party/double-conversion/_install/include) -include_directories(SYSTEM ${VGRAPH_HOME}/third-party/fatal/_install/include) -include_directories(SYSTEM ${VGRAPH_HOME}/third-party/fbthrift/_install/include) -include_directories(SYSTEM ${VGRAPH_HOME}/third-party/folly/_install/include) -include_directories(SYSTEM ${VGRAPH_HOME}/third-party/gflags/_install/include) -include_directories(SYSTEM ${VGRAPH_HOME}/third-party/glog/_install/include) -include_directories(SYSTEM ${VGRAPH_HOME}/third-party/googletest/_install/include) -include_directories(SYSTEM ${VGRAPH_HOME}/third-party/jemalloc/_install/include) -include_directories(SYSTEM ${VGRAPH_HOME}/third-party/libevent/_install/include) -include_directories(SYSTEM ${VGRAPH_HOME}/third-party/mstch/_install/include) -include_directories(SYSTEM ${VGRAPH_HOME}/third-party/proxygen/_install/include) -include_directories(SYSTEM ${VGRAPH_HOME}/third-party/rocksdb/_install/include) -include_directories(SYSTEM ${VGRAPH_HOME}/third-party/snappy/_install/include) -include_directories(SYSTEM ${VGRAPH_HOME}/third-party/wangle/_install/include) -include_directories(SYSTEM ${VGRAPH_HOME}/third-party/zlib/_install/include) -include_directories(SYSTEM ${VGRAPH_HOME}/third-party/zstd/_install/include) +include_directories(SYSTEM ${NEBULA_HOME}/third-party/bzip2/_install/include) +include_directories(SYSTEM ${NEBULA_HOME}/third-party/double-conversion/_install/include) +include_directories(SYSTEM ${NEBULA_HOME}/third-party/fatal/_install/include) +include_directories(SYSTEM ${NEBULA_HOME}/third-party/fbthrift/_install/include) +include_directories(SYSTEM ${NEBULA_HOME}/third-party/folly/_install/include) +include_directories(SYSTEM ${NEBULA_HOME}/third-party/gflags/_install/include) +include_directories(SYSTEM ${NEBULA_HOME}/third-party/glog/_install/include) +include_directories(SYSTEM ${NEBULA_HOME}/third-party/googletest/_install/include) +include_directories(SYSTEM ${NEBULA_HOME}/third-party/jemalloc/_install/include) +include_directories(SYSTEM ${NEBULA_HOME}/third-party/libevent/_install/include) +include_directories(SYSTEM ${NEBULA_HOME}/third-party/mstch/_install/include) +include_directories(SYSTEM ${NEBULA_HOME}/third-party/proxygen/_install/include) +include_directories(SYSTEM ${NEBULA_HOME}/third-party/rocksdb/_install/include) +include_directories(SYSTEM ${NEBULA_HOME}/third-party/snappy/_install/include) +include_directories(SYSTEM ${NEBULA_HOME}/third-party/wangle/_install/include) +include_directories(SYSTEM ${NEBULA_HOME}/third-party/zlib/_install/include) +include_directories(SYSTEM ${NEBULA_HOME}/third-party/zstd/_install/include) include_directories(SYSTEM ${Boost_INCLUDE_DIRS}) include_directories(SYSTEM ${OPENSSL_INCLUDE_DIR}) include_directories(SYSTEM ${KRB5_INCLUDE_DIRS}) include_directories(SYSTEM ${FLEX_INCLUDE_DIRS}) include_directories(SYSTEM ${Readline_INCLUDE_DIR}) -include_directories(AFTER common) -include_directories(AFTER interface) -include_directories(AFTER ${VGRAPH_HOME}) +include_directories(AFTER ${NEBULA_HOME}/src) +include_directories(AFTER src/common) +include_directories(AFTER src/interface) link_directories( - ${VGRAPH_HOME}/third-party/bzip2/_install/lib - ${VGRAPH_HOME}/third-party/double-conversion/_install/lib - ${VGRAPH_HOME}/third-party/fatal/_install/lib - ${VGRAPH_HOME}/third-party/fbthrift/_install/lib - ${VGRAPH_HOME}/third-party/folly/_install/lib - ${VGRAPH_HOME}/third-party/gflags/_install/lib - ${VGRAPH_HOME}/third-party/glog/_install/lib - ${VGRAPH_HOME}/third-party/googletest/_install/lib - ${VGRAPH_HOME}/third-party/jemalloc/_install/lib - ${VGRAPH_HOME}/third-party/libevent/_install/lib - ${VGRAPH_HOME}/third-party/mstch/_install/lib - ${VGRAPH_HOME}/third-party/proxygen/_install/lib - ${VGRAPH_HOME}/third-party/rocksdb/_install/lib64 - ${VGRAPH_HOME}/third-party/snappy/_install/lib - ${VGRAPH_HOME}/third-party/wangle/_install/lib - ${VGRAPH_HOME}/third-party/zlib/_install/lib - ${VGRAPH_HOME}/third-party/zstd/_install/lib + ${NEBULA_HOME}/third-party/bzip2/_install/lib + ${NEBULA_HOME}/third-party/double-conversion/_install/lib + ${NEBULA_HOME}/third-party/fatal/_install/lib + ${NEBULA_HOME}/third-party/fbthrift/_install/lib + ${NEBULA_HOME}/third-party/folly/_install/lib + ${NEBULA_HOME}/third-party/gflags/_install/lib + ${NEBULA_HOME}/third-party/glog/_install/lib + ${NEBULA_HOME}/third-party/googletest/_install/lib + ${NEBULA_HOME}/third-party/jemalloc/_install/lib + ${NEBULA_HOME}/third-party/libevent/_install/lib + ${NEBULA_HOME}/third-party/mstch/_install/lib + ${NEBULA_HOME}/third-party/proxygen/_install/lib + ${NEBULA_HOME}/third-party/rocksdb/_install/lib64 + ${NEBULA_HOME}/third-party/snappy/_install/lib + ${NEBULA_HOME}/third-party/wangle/_install/lib + ${NEBULA_HOME}/third-party/zlib/_install/lib + ${NEBULA_HOME}/third-party/zstd/_install/lib ${Boost_LIBRARY_DIRS} ${KRB5_LIBRARY_DIRS} ) @@ -163,22 +167,15 @@ set(THRIFT_LIBRARIES thrift-core ) -set(ROCKSDB_LIBRARIES ${VGRAPH_HOME}/third-party/rocksdb/_install/lib64/librocksdb.a) +set(ROCKSDB_LIBRARIES ${NEBULA_HOME}/third-party/rocksdb/_install/lib64/librocksdb.a) # All compression libraries set(COMPRESSION_LIBRARIES bz2 snappy zstd z) add_subdirectory(third-party) -add_subdirectory(interface) -add_subdirectory(common) -add_subdirectory(meta) -add_subdirectory(dataman) -add_subdirectory(client) -add_subdirectory(vgraphd) -add_subdirectory(console) -add_subdirectory(raftex) -add_subdirectory(storage) -add_subdirectory(parser) +add_subdirectory(src) +add_subdirectory(etc) +add_subdirectory(scripts) add_dependencies(common third-party) #add_dependencies(storage_engines common) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 28e15eac..00000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,168 +0,0 @@ -## Workflow - -### Step 1: Fork in the cloud - -1. Visit https://github.com/vesoft-inc/vgraph -2. Click `Fork` button (top right) to establish a cloud-based fork. - -### Step 2: Clone fork to local storage - -Define a local working directory: - -```sh -# Define your working directory -working_dir=$HOME/Workspace -``` - -Set `user` to match your github profile name: - -```sh -user={your github profile name} -``` - -Create your clone: - -```sh -mkdir -p $working_dir -cd $working_dir -git clone https://github.com/$user/vgraph.git -# the following is recommended -# or: git clone git@github.com:$user/vgraph.git - -cd $working_dir/vgraph -git remote add upstream https://github.com/vesoft-inc/vgraph.git -# or: git remote add upstream git@github.com:vesoft-inc/vgraph.git - -# Never push to upstream master since you do not have write access. -git remote set-url --push upstream no_push - -# Confirm that your remotes make sense: -# It should look like: -# origin git@github.com:$(user)/vgraph.git (fetch) -# origin git@github.com:$(user)/vgraph.git (push) -# upstream https://github.com/vesoft-inc/vgraph (fetch) -# upstream no_push (push) -git remote -v -``` - -#### Define a pre-commit hook - -Please link the vGraph pre-commit hook into your `.git` directory. - -This hook checks your commits for formatting, building, doc generation, etc. - -```sh -cd $working_dir/vgraph/.git/hooks -ln -s ../../hooks/pre-commit . -``` -Sometime, pre-commit hook can not be executable. In such case, you have to make it executable manually. - -```sh -cd $working_dir/vgraph/.git/hooks -chmod +x pre-commit -``` - -### Step 3: Branch - -Get your local master up to date: - -```sh -cd $working_dir/vgraph -git fetch upstream -git checkout master -git rebase upstream/master -``` - -Branch from master: - -```sh -git checkout -b myfeature -``` -**NOTE**: Because your PR often consists of several commits, which might be squashed while being merged into upstream, -we strongly suggest you open a separate topic branch to make your changes on. After merged, -this topic branch could be just abandoned, thus you could synchronize your master branch with -upstream easily with a rebase like above. Otherwise, if you commit your changes directly into master, -maybe you must use a hard reset on the master branch, like: - -```sh -git fetch upstream -git checkout master -git reset --hard upstream/master -git push --force origin master -``` - -### Step 4: Develop - -#### Edit the code - -You can now edit the code on the `myfeature` branch. Please follow the coding style guidance [here](docs/cpp-coding-style.md) - -#### Run stand-alone mode - -If you want to reproduce and investigate an issue, you may need -to run vGraph in stand-alone mode. - -```sh -# Build the binary. -make server - -# Run in stand-alone mode. -vgraphd -``` - -Then you can connect the vGraph console to your local server -```sh -vgraph -``` - -#### Run Test - -```sh -# Run unit test to make sure all test passed. -``` - -### Step 5: Keep your branch in sync - -```sh -# While on your myfeature branch. -git fetch upstream -git rebase upstream/master -``` - -### Step 6: Commit - -Commit your changes. - -```sh -git commit -``` - -Likely you'll go back and edit/build/test some more than `commit --amend` -in a few cycles. - -### Step 7: Push - -When ready to review (or just to establish an offsite backup or your work), -push your branch to your fork on `github.com`: - -```sh -git push -f origin myfeature -``` - -### Step 8: Create a pull request - -1. Visit your fork at https://github.com/$user/vgraph (replace `$user` obviously). -2. Click the `Compare & pull request` button next to your `myfeature` branch. - -### Step 9: Get a code review - -Once your pull request has been opened, it will be assigned to at least one -reviewers. Those reviewers will do a thorough code review, looking for -correctness, bugs, opportunities for improvement, documentation and comments, -and style. - -Commit changes made in response to review comments to the same branch on your -fork. - -Very small PRs are easy to review. Very large PRs are very difficult to -review. diff --git a/conf/CMakeLists.txt b/conf/CMakeLists.txt new file mode 100644 index 00000000..4e7e2cbe --- /dev/null +++ b/conf/CMakeLists.txt @@ -0,0 +1 @@ +install(FILES nebula-graphd.conf.default DESTINATION etc) diff --git a/conf/nebula-graphd.conf.default b/conf/nebula-graphd.conf.default new file mode 100644 index 00000000..9edf937d --- /dev/null +++ b/conf/nebula-graphd.conf.default @@ -0,0 +1,28 @@ +########## logging ########## +--log_dir=/tmp/nebula-graphd +# 0, 1, 2, 3 for INFO, WARNING, ERROR, FATAL respectively +--minloglevel=0 +# verbose loging level, 1, 2, 3, 4, the higher of the level, the more verbose of the logging +--v=4 +# maximum seconds to buffer the log messages +--logbufsecs=0 +# Whether to redirect stdout and stderr to separate output files +--redirect_stdout=true +# Destination filename of stdout and stderr, which will also reside in log_dir. +--stdout_log_file=stdout.log +--stderr_log_file=stderr.log + +########## networking ########## +--port=3699 +# seconds before we close the idle connections, 0 for infinite +--client_idle_timeout_secs=0 +# seconds before we expire the idle sessions, 0 for inifnite +--session_idle_timeout_secs=60000 +# number of threads to accept incoming connections +--num_accept_threads=1 +# number of networking IO threads, 0 for number of physical CPU cores +--num_netio_threads=0 +# turn on SO_REUSEPORT or not +--reuse_port=false +# Backlog of the listen socket, adjust this together with net.core.somaxconn +--listen_backlog=1024 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 00000000..60f73183 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,11 @@ +add_subdirectory(common) +add_subdirectory(interface) +add_subdirectory(client) +add_subdirectory(meta) +add_subdirectory(console) +add_subdirectory(raftex) +add_subdirectory(storage) +add_subdirectory(parser) +add_subdirectory(dataman) +add_subdirectory(graph) +add_subdirectory(daemons) diff --git a/src/README.md b/src/README.md new file mode 100644 index 00000000..07dd0c5c --- /dev/null +++ b/src/README.md @@ -0,0 +1 @@ +# Overview diff --git a/src/console/CMakeLists.txt b/src/console/CMakeLists.txt index a35963b3..43177149 100644 --- a/src/console/CMakeLists.txt +++ b/src/console/CMakeLists.txt @@ -2,17 +2,17 @@ add_library(console_obj OBJECT CliManager.cpp CmdProcessor.cpp) add_dependencies(console_obj common) add_executable( - vgraph - GraphDbConsole.cpp + nebula + NebulaConsole.cpp $<TARGET_OBJECTS:console_obj> $<TARGET_OBJECTS:client_cpp_obj> $<TARGET_OBJECTS:base_obj> - $<TARGET_OBJECTS:vgraph_thrift_obj> + $<TARGET_OBJECTS:graph_thrift_obj> $<TARGET_OBJECTS:time_obj> $<TARGET_OBJECTS:thread_obj> ) target_link_libraries( - vgraph + nebula thriftcpp2 thrift thrift-core @@ -44,5 +44,7 @@ target_link_libraries( -pthread ) +install(TARGETS nebula DESTINATION bin) + #add_subdirectory(test) diff --git a/src/console/CliManager.cpp b/src/console/CliManager.cpp index bebc3038..9afde2af 100644 --- a/src/console/CliManager.cpp +++ b/src/console/CliManager.cpp @@ -8,10 +8,10 @@ #include <readline/readline.h> #include <readline/history.h> #include "console/CliManager.h" -#include "client/cpp/GraphDbClient.h" +#include "client/cpp/GraphClient.h" -namespace vesoft { -namespace vgraph { +namespace nebula { +namespace graph { const int32_t kMaxAuthInfoRetries = 3; const int32_t kMaxUsernameLen = 16; @@ -61,10 +61,10 @@ bool CliManager::connect(const std::string& addr, port_ = port; username_ = user; - auto client = std::make_unique<GraphDbClient>(addr_, port_); + auto client = std::make_unique<GraphClient>(addr_, port_); cpp2::ErrorCode res = client->connect(user, pass); if (res == cpp2::ErrorCode::SUCCEEDED) { - std::cerr << "\nWelcome to vGraph (Version 0.1)\n\n"; + std::cerr << "\nWelcome to Nebula Graph (Version 0.1)\n\n"; cmdProcessor_ = std::make_unique<CmdProcessor>(std::move(client)); return true; } else { @@ -76,6 +76,7 @@ bool CliManager::connect(const std::string& addr, void CliManager::batch(const std::string& filename) { + UNUSED(filename); } @@ -190,5 +191,5 @@ void CliManager::loadHistory() { ::fclose(file); } -} // namespace vgraph -} // namespace vesoft +} // namespace graph +} // namespace nebula diff --git a/src/console/CliManager.h b/src/console/CliManager.h index dc48f865..fac2b8bc 100644 --- a/src/console/CliManager.h +++ b/src/console/CliManager.h @@ -10,8 +10,8 @@ #include "base/Base.h" #include "console/CmdProcessor.h" -namespace vesoft { -namespace vgraph { +namespace nebula { +namespace graph { class CliManager final { public: @@ -43,6 +43,6 @@ private: std::unique_ptr<CmdProcessor> cmdProcessor_; }; -} // namespace vgraph -} // namespace vesoft +} // namespace graph +} // namespace nebula #endif // CONSOLE_CLIMANAGER_H_ diff --git a/src/console/CmdProcessor.cpp b/src/console/CmdProcessor.cpp index 4afa6f3a..79c5250b 100644 --- a/src/console/CmdProcessor.cpp +++ b/src/console/CmdProcessor.cpp @@ -8,8 +8,8 @@ #include "console/CmdProcessor.h" #include "time/Duration.h" -namespace vesoft { -namespace vgraph { +namespace nebula { +namespace graph { #define GET_VALUE_WIDTH(VT, FN, FMT) \ VT val = col.get_ ## FN(); \ @@ -377,6 +377,6 @@ bool CmdProcessor::process(folly::StringPiece cmd) { return true; } -} // namespace vgraph -} // namespace vesoft +} // namespace graph +} // namespace nebula diff --git a/src/console/CmdProcessor.h b/src/console/CmdProcessor.h index 8de95f7c..7bff6829 100644 --- a/src/console/CmdProcessor.h +++ b/src/console/CmdProcessor.h @@ -8,14 +8,14 @@ #define CONSOLE_CMDPROCESSOR_H_ #include "base/Base.h" -#include "client/cpp/GraphDbClient.h" +#include "client/cpp/GraphClient.h" -namespace vesoft { -namespace vgraph { +namespace nebula { +namespace graph { class CmdProcessor final { public: - explicit CmdProcessor(std::unique_ptr<GraphDbClient> client) + explicit CmdProcessor(std::unique_ptr<GraphClient> client) : client_(std::move(client)) {} ~CmdProcessor() = default; @@ -26,7 +26,7 @@ public: bool process(folly::StringPiece cmd); private: - std::unique_ptr<GraphDbClient> client_; + std::unique_ptr<GraphClient> client_; // The method returns true if the given command is a client command // and has been processed. Otherwise, the method returns false @@ -47,6 +47,6 @@ private: const std::vector<std::string>& formats) const; }; -} // namespace vgraph -} // namespace vesoft +} // namespace graph +} // namespace nebula #endif // CONSOLE_CMDPROCESSOR_H_ diff --git a/src/console/GraphDbConsole.cpp b/src/console/NebulaConsole.cpp similarity index 78% rename from src/console/GraphDbConsole.cpp rename to src/console/NebulaConsole.cpp index 2d5ab9ef..30f68c05 100644 --- a/src/console/GraphDbConsole.cpp +++ b/src/console/NebulaConsole.cpp @@ -7,8 +7,8 @@ #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(addr, "127.0.0.1", "Nebula daemon IP address"); +DEFINE_int32(port, 34500, "Nebula daemon listening port"); DEFINE_string(username, "", "Username used to authenticate"); DEFINE_string(password, "", "Password used to authenticate"); @@ -16,7 +16,7 @@ DEFINE_string(password, "", "Password used to authenticate"); int main(int argc, char *argv[]) { folly::init(&argc, &argv, true); - using namespace vesoft::vgraph; + using namespace nebula::graph; CliManager cli; if (!cli.connect(FLAGS_addr, FLAGS_port, FLAGS_username, FLAGS_password)) { diff --git a/src/console/README.md b/src/console/README.md new file mode 100644 index 00000000..07dd0c5c --- /dev/null +++ b/src/console/README.md @@ -0,0 +1 @@ +# Overview diff --git a/src/daemons/CMakeLists.txt b/src/daemons/CMakeLists.txt new file mode 100644 index 00000000..835f9932 --- /dev/null +++ b/src/daemons/CMakeLists.txt @@ -0,0 +1,33 @@ + +add_executable( + nebula-graphd + GraphDaemon.cpp + $<TARGET_OBJECTS:graph_obj> + $<TARGET_OBJECTS:base_obj> + $<TARGET_OBJECTS:graph_thrift_obj> + $<TARGET_OBJECTS:time_obj> + $<TARGET_OBJECTS:fs_obj> + $<TARGET_OBJECTS:thread_obj> + $<TARGET_OBJECTS:parser_obj> +) + +target_link_libraries( + nebula-graphd + ${THRIFT_LIBRARIES} + wangle + folly + boost_system + boost_context + ${OPENSSL_LIBRARIES} + ${KRB5_LIBRARIES} + glog + gflags + event + ${COMPRESSION_LIBRARIES} + resolv + double-conversion + dl + -pthread +) + +install(TARGETS nebula-graphd DESTINATION bin) diff --git a/src/daemons/GraphDaemon.cpp b/src/daemons/GraphDaemon.cpp new file mode 100644 index 00000000..1846ce38 --- /dev/null +++ b/src/daemons/GraphDaemon.cpp @@ -0,0 +1,123 @@ +/* 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 <signal.h> +#include "base/Base.h" +#include "base/Status.h" +#include "fs/FileUtils.h" +#include <thrift/lib/cpp2/server/ThriftServer.h> +#include "graph/GraphService.h" +#include "graph/GraphFlags.h" + +using namespace nebula; +using namespace nebula::graph; +using namespace nebula::fs; + +static std::unique_ptr<apache::thrift::ThriftServer> gServer; + +static void signalHandler(int sig); +static Status setupSignalHandler(); +static Status setupLogging(); + +int main(int argc, char *argv[]) { + folly::init(&argc, &argv, true); + + auto status = setupLogging(); + if (!status.ok()) { + LOG(ERROR) << status; + return EXIT_FAILURE; + } + + status = setupSignalHandler(); + if (!status.ok()) { + LOG(ERROR) << status; + return EXIT_FAILURE; + } + + auto interface = std::make_shared<GraphService>(); + gServer = std::make_unique<apache::thrift::ThriftServer>(); + + gServer->setInterface(interface); + gServer->setPort(FLAGS_port); + gServer->setReusePort(FLAGS_reuse_port); + gServer->setIdleTimeout(std::chrono::seconds(FLAGS_client_idle_timeout_secs)); + + // TODO(dutor) This only take effects on NORMAL priority threads + gServer->setNumCPUWorkerThreads(1); + + gServer->setCPUWorkerThreadName("executor"); + gServer->setNumAcceptThreads(FLAGS_num_accept_threads); + gServer->setListenBacklog(FLAGS_listen_backlog); + gServer->setThreadStackSizeMB(5); + if (FLAGS_num_netio_threads != 0) { + gServer->setNumIOWorkerThreads(FLAGS_num_netio_threads); + } + + FLOG_INFO("Starting nebula-graphd on port %d\n", FLAGS_port); + try { + gServer->serve(); // Blocking wait until shut down via gServer->stop() + } catch (const std::exception &e) { + FLOG_ERROR("Exception thrown while starting the RPC server: %s", e.what()); + return EXIT_FAILURE; + } + + FLOG_INFO("nebula-graphd on port %d has been stopped", FLAGS_port); + + return EXIT_SUCCESS; +} + + +Status setupSignalHandler() { + ::signal(SIGPIPE, SIG_IGN); + ::signal(SIGINT, signalHandler); + ::signal(SIGTERM, signalHandler); + return Status::OK(); +} + + +void signalHandler(int sig) { + switch (sig) { + case SIGINT: + case SIGTERM: + FLOG_INFO("Signal %d(%s) received, stopping this server", sig, ::strsignal(sig)); + gServer->stop(); + break; + default: + FLOG_ERROR("Signal %d(%s) received but ignored", sig, ::strsignal(sig)); + } +} + + +Status setupLogging() { + auto dup = [] (const std::string &filename, FILE *stream) -> Status { + auto path = FLAGS_log_dir + "/" + filename; + auto fd = ::open(path.c_str(), O_WRONLY | O_APPEND | O_CREAT, 0644); + if (fd == -1) { + return Status::Error("Failed to create or open `%s': %s", + path.c_str(), ::strerror(errno)); + } + if (::dup2(fd, ::fileno(stream)) == -1) { + return Status::Error("Failed to ::dup2 from `%s' to stdout: %s", + path.c_str(), ::strerror(errno)); + } + ::close(fd); + return Status::OK(); + }; + + Status status = Status::OK(); + do { + status = dup(FLAGS_stdout_log_file, stdout); + if (!status.ok()) { + break; + } + status = dup(FLAGS_stderr_log_file, stderr); + if (!status.ok()) { + break; + } + } while (false); + + return status; +} diff --git a/src/daemons/README.md b/src/daemons/README.md new file mode 100644 index 00000000..07dd0c5c --- /dev/null +++ b/src/daemons/README.md @@ -0,0 +1 @@ +# Overview diff --git a/src/executor/AlterEdgeExecutor.cpp b/src/executor/AlterEdgeExecutor.cpp new file mode 100644 index 00000000..dec97e6e --- /dev/null +++ b/src/executor/AlterEdgeExecutor.cpp @@ -0,0 +1,31 @@ +/* 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 "graph/AlterEdgeExecutor.h" + +namespace nebula { +namespace graph { + +AlterEdgeExecutor::AlterEdgeExecutor(Sentence *sentence, + ExecutionContext *ectx) : Executor(ectx) { + sentence_ = static_cast<AlterEdgeSentence*>(sentence); +} + + +Status AlterEdgeExecutor::prepare() { + return Status::OK(); +} + + +void AlterEdgeExecutor::execute() { + if (onFinish_) { + onFinish_(); + } +} + +} // namespace graph +} // namespace nebula diff --git a/src/executor/AlterEdgeExecutor.h b/src/executor/AlterEdgeExecutor.h new file mode 100644 index 00000000..fb9dd9b0 --- /dev/null +++ b/src/executor/AlterEdgeExecutor.h @@ -0,0 +1,35 @@ +/* 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 GRAPH_ALTEREDGEEXECUTOR_H_ +#define GRAPH_ALTEREDGEEXECUTOR_H_ + +#include "base/Base.h" +#include "graph/Executor.h" + +namespace nebula { +namespace graph { + +class AlterEdgeExecutor final : public Executor { +public: + AlterEdgeExecutor(Sentence *sentence, ExecutionContext *ectx); + + const char* name() const override { + return "AlterEdgeExecutor"; + } + + Status VE_MUST_USE_RESULT prepare() override; + + void execute() override; + +private: + AlterEdgeSentence *sentence_{nullptr}; +}; + +} // namespace graph +} // namespace nebula + +#endif // GRAPH_ALTEREDGEEXECUTOR_H_ diff --git a/src/executor/AlterTagExecutor.cpp b/src/executor/AlterTagExecutor.cpp new file mode 100644 index 00000000..ea53610a --- /dev/null +++ b/src/executor/AlterTagExecutor.cpp @@ -0,0 +1,31 @@ +/* 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 "graph/AlterTagExecutor.h" + +namespace nebula { +namespace graph { + +AlterTagExecutor::AlterTagExecutor(Sentence *sentence, + ExecutionContext *ectx) : Executor(ectx) { + sentence_ = static_cast<AlterTagSentence*>(sentence); +} + + +Status AlterTagExecutor::prepare() { + return Status::OK(); +} + + +void AlterTagExecutor::execute() { + if (onFinish_) { + onFinish_(); + } +} + +} // namespace graph +} // namespace nebula diff --git a/src/executor/AlterTagExecutor.h b/src/executor/AlterTagExecutor.h new file mode 100644 index 00000000..4c4cbbca --- /dev/null +++ b/src/executor/AlterTagExecutor.h @@ -0,0 +1,36 @@ +/* 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 GRAPH_ALTERTAGEXECUTOR_H_ +#define GRAPH_ALTERTAGEXECUTOR_H_ + +#include "base/Base.h" +#include "graph/Executor.h" + +namespace nebula { +namespace graph { + +class AlterTagExecutor final : public Executor { +public: + AlterTagExecutor(Sentence *sentence, ExecutionContext *ectx); + + const char* name() const override { + return "AlterTagExecutor"; + } + + Status VE_MUST_USE_RESULT prepare() override; + + void execute() override; + +private: + AlterTagSentence *sentence_{nullptr}; +}; + +} // namespace graph +} // namespace nebula + + +#endif // GRAPH_ALTERTAGEXECUTOR_H_ diff --git a/src/executor/Authenticator.h b/src/executor/Authenticator.h new file mode 100644 index 00000000..3ee24c60 --- /dev/null +++ b/src/executor/Authenticator.h @@ -0,0 +1,26 @@ +/* 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 GRAPH_AUTHENTICATOR_H_ +#define GRAPH_AUTHENTICATOR_H_ + +#include "base/Base.h" + +namespace nebula { +namespace graph { + +class Authenticator { +public: + virtual ~Authenticator() {}; + + virtual bool VE_MUST_USE_RESULT auth(const std::string &user, + const std::string &password) = 0; +}; + +} // namespace graph +} // namespace nebula + +#endif // GRAPH_AUTHENTICATOR_H_ diff --git a/src/executor/CMakeLists.txt b/src/executor/CMakeLists.txt new file mode 100644 index 00000000..76712f32 --- /dev/null +++ b/src/executor/CMakeLists.txt @@ -0,0 +1,33 @@ +add_library( + graph_obj + OBJECT + GraphFlags.cpp + GraphService.cpp + ClientSession.cpp + SessionManager.cpp + ExecutionEngine.cpp + ExecutionContext.cpp + ExecutionPlan.cpp + Executor.cpp + TraverseExecutor.cpp + CompoundExecutor.cpp + UseExecutor.cpp + GoExecutor.cpp + PipeExecutor.cpp + DefineEdgeExecutor.cpp + DefineTagExecutor.cpp + AlterEdgeExecutor.cpp + AlterTagExecutor.cpp + DescribeTagExecutor.cpp + DescribeEdgeExecutor.cpp + InsertVertexExecutor.cpp + InsertEdgeExecutor.cpp + mock/PropertiesSchema.cpp + mock/EdgeSchema.cpp + mock/TagSchema.cpp + mock/SchemaManager.cpp + mock/StorageService.cpp +) +add_dependencies(graph_obj common parser_obj graph_thrift_obj) + +add_subdirectory(test) diff --git a/src/executor/ClientSession.cpp b/src/executor/ClientSession.cpp new file mode 100644 index 00000000..b17c5634 --- /dev/null +++ b/src/executor/ClientSession.cpp @@ -0,0 +1,33 @@ +/* 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 "graph/ClientSession.h" + + +namespace nebula { +namespace graph { + +ClientSession::ClientSession(int64_t id) { + id_ = id; +} + +std::shared_ptr<ClientSession> ClientSession::create(int64_t id) { + // return std::make_shared<ClientSession>(id); + // `std::make_shared' cannot access ClientSession's construtor + return std::shared_ptr<ClientSession>(new ClientSession(id)); +} + +void ClientSession::charge() { + idleDuration_.reset(); +} + +uint64_t ClientSession::idleSeconds() const { + return idleDuration_.elapsedInSec(); +} + +} // namespace graph +} // namespace nebula diff --git a/src/executor/ClientSession.h b/src/executor/ClientSession.h new file mode 100644 index 00000000..24610991 --- /dev/null +++ b/src/executor/ClientSession.h @@ -0,0 +1,69 @@ +/* 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 GRAPH_CLIENTSESSION_H_ +#define GRAPH_CLIENTSESSION_H_ + +#include "base/Base.h" +#include "time/Duration.h" + +/** + * A ClientSession holds the context informations of a session opened by a client. + */ + +namespace nebula { +namespace graph { + +class ClientSession final { +public: + int64_t id() const { + return id_; + } + + void setId(int64_t id) { + id_ = id; + } + + const std::string& space() const { + return space_; + } + + void setSpace(std::string space) { + space_ = std::move(space); + } + + uint64_t idleSeconds() const; + + const std::string& user() const { + return user_; + } + + void setUser(std::string user) { + user_ = std::move(user); + } + + void charge(); + +private: + // ClientSession could only be created via SessionManager + friend class SessionManager; + ClientSession() = default; + explicit ClientSession(int64_t id); + + static std::shared_ptr<ClientSession> create(int64_t id); + + +private: + int64_t id_{0}; + time::Duration idleDuration_; + std::string space_; + std::string user_; +}; + +} // namespace graph +} // namespace nebula + +#endif // GRAPH_CLIENTSESSION_H_ diff --git a/src/executor/CompoundExecutor.cpp b/src/executor/CompoundExecutor.cpp new file mode 100644 index 00000000..860c57db --- /dev/null +++ b/src/executor/CompoundExecutor.cpp @@ -0,0 +1,74 @@ +/* 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 "graph/CompoundExecutor.h" +#include "graph/GoExecutor.h" +#include "graph/PipeExecutor.h" +#include "graph/UseExecutor.h" + +namespace nebula { +namespace graph { + +CompoundExecutor::CompoundExecutor(CompoundSentence *compound, + ExecutionContext *ectx) : Executor(ectx) { + compound_ = compound; +} + + +Status CompoundExecutor::prepare() { + for (auto i = 0U; i < compound_->sentences_.size(); i++) { + auto *sentence = compound_->sentences_[i].get(); + auto executor = makeExecutor(sentence); + DCHECK(executor != nullptr); + auto status = executor->prepare(); + if (!status.ok()) { + FLOG_ERROR("Prepare executor `%s' failed: %s", + executor->name(), status.toString().c_str()); + return status; + } + executors_.emplace_back(std::move(executor)); + } + /** + * For the time being, we execute sentences one by one. We may allow concurrent + * or out of order execution in the future. + */ + // For an executor except the last one, it executes the next one on finished. + // If any fails, the whole execution would abort. + auto onError = [this] (Status status) { + DCHECK(onError_); + onError_(std::move(status)); + }; + for (auto i = 0U; i < executors_.size() - 1; i++) { + auto onFinish = [this, next = i + 1] () { + executors_[next]->execute(); + }; + executors_[i]->setOnFinish(onFinish); + executors_[i]->setOnError(onError); + } + // The whole execution is done upon the last executor finishes. + auto onFinish = [this] () { + DCHECK(onFinish_); + onFinish_(); + }; + executors_.back()->setOnFinish(onFinish); + executors_.back()->setOnError(onError); + + return Status::OK(); +} + + +void CompoundExecutor::execute() { + executors_.front()->execute(); +} + + +void CompoundExecutor::setupResponse(cpp2::ExecutionResponse &resp) { + executors_.back()->setupResponse(resp); +} + +} // namespace graph +} // namespace nebula diff --git a/src/executor/CompoundExecutor.h b/src/executor/CompoundExecutor.h new file mode 100644 index 00000000..259e5e53 --- /dev/null +++ b/src/executor/CompoundExecutor.h @@ -0,0 +1,41 @@ +/* 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 GRAPH_COMPOUNDEXECUTOR_H_ +#define GRAPH_COMPOUNDEXECUTOR_H_ + +#include "base/Base.h" +#include "graph/Executor.h" + + +namespace nebula { +namespace graph { + +class CompoundExecutor final : public Executor { +public: + CompoundExecutor(CompoundSentence *compound, ExecutionContext *ectx); + + const char* name() const override { + return "CompoundExecutor"; + } + + Status VE_MUST_USE_RESULT prepare() override; + + void execute() override; + + void setupResponse(cpp2::ExecutionResponse &resp) override; + +private: + CompoundSentence *compound_{nullptr}; + std::vector<std::unique_ptr<Executor>> executors_; +}; + + +} // namespace graph +} // namespace nebula + + +#endif // GRAPH_COMPOUNDEXECUTOR_H_ diff --git a/src/executor/DefineEdgeExecutor.cpp b/src/executor/DefineEdgeExecutor.cpp new file mode 100644 index 00000000..d574c4d5 --- /dev/null +++ b/src/executor/DefineEdgeExecutor.cpp @@ -0,0 +1,36 @@ +/* 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 "graph/DefineEdgeExecutor.h" + +namespace nebula { +namespace graph { + +DefineEdgeExecutor::DefineEdgeExecutor(Sentence *sentence, + ExecutionContext *ectx) : Executor(ectx) { + sentence_ = static_cast<DefineEdgeSentence*>(sentence); +} + + +Status DefineEdgeExecutor::prepare() { + return Status::OK(); +} + + +void DefineEdgeExecutor::execute() { + auto *sm = ectx()->schemaManager(); + auto *name = sentence_->name(); + auto *src = sentence_->src(); + auto *dst = sentence_->dst(); + auto specs = sentence_->columnSpecs(); + sm->addEdgeSchema(*name, *src, *dst, specs); + DCHECK(onFinish_); + onFinish_(); +} + +} // namespace graph +} // namespace nebula diff --git a/src/executor/DefineEdgeExecutor.h b/src/executor/DefineEdgeExecutor.h new file mode 100644 index 00000000..ec983bc5 --- /dev/null +++ b/src/executor/DefineEdgeExecutor.h @@ -0,0 +1,35 @@ +/* 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 GRAPH_DEFINEEDGEEXECUTOR_H_ +#define GRAPH_DEFINEEDGEEXECUTOR_H_ + +#include "base/Base.h" +#include "graph/Executor.h" + +namespace nebula { +namespace graph { + +class DefineEdgeExecutor final : public Executor { +public: + DefineEdgeExecutor(Sentence *sentence, ExecutionContext *ectx); + + const char* name() const override { + return "DefineEdgeExecutor"; + } + + Status VE_MUST_USE_RESULT prepare() override; + + void execute() override; + +private: + DefineEdgeSentence *sentence_{nullptr}; +}; + +} // namespace graph +} // namespace nebula + +#endif // GRAPH_DEFINEEDGEEXECUTOR_H_ diff --git a/src/executor/DefineTagExecutor.cpp b/src/executor/DefineTagExecutor.cpp new file mode 100644 index 00000000..cd2b2427 --- /dev/null +++ b/src/executor/DefineTagExecutor.cpp @@ -0,0 +1,34 @@ +/* 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 "graph/DefineTagExecutor.h" + +namespace nebula { +namespace graph { + +DefineTagExecutor::DefineTagExecutor(Sentence *sentence, + ExecutionContext *ectx) : Executor(ectx) { + sentence_ = static_cast<DefineTagSentence*>(sentence); +} + + +Status DefineTagExecutor::prepare() { + return Status::OK(); +} + + +void DefineTagExecutor::execute() { + auto *sm = ectx()->schemaManager(); + auto *name = sentence_->name(); + auto specs = sentence_->columnSpecs(); + sm->addTagSchema(*name, specs); + DCHECK(onFinish_); + onFinish_(); +} + +} // namespace graph +} // namespace nebula diff --git a/src/executor/DefineTagExecutor.h b/src/executor/DefineTagExecutor.h new file mode 100644 index 00000000..e92fb3f2 --- /dev/null +++ b/src/executor/DefineTagExecutor.h @@ -0,0 +1,36 @@ +/* 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 GRAPH_DEFINETAGEXECUTOR_H_ +#define GRAPH_DEFINETAGEXECUTOR_H_ + +#include "base/Base.h" +#include "graph/Executor.h" + +namespace nebula { +namespace graph { + +class DefineTagExecutor final : public Executor { +public: + DefineTagExecutor(Sentence *sentence, ExecutionContext *ectx); + + const char* name() const override { + return "DefineTagExecutor"; + } + + Status VE_MUST_USE_RESULT prepare() override; + + void execute() override; + +private: + DefineTagSentence *sentence_{nullptr}; +}; + +} // namespace graph +} // namespace nebula + + +#endif // GRAPH_DEFINETAGEXECUTOR_H_ diff --git a/src/executor/DescribeEdgeExecutor.cpp b/src/executor/DescribeEdgeExecutor.cpp new file mode 100644 index 00000000..a2d2331a --- /dev/null +++ b/src/executor/DescribeEdgeExecutor.cpp @@ -0,0 +1,75 @@ +/* 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 "graph/DescribeEdgeExecutor.h" + +namespace nebula { +namespace graph { + +DescribeEdgeExecutor::DescribeEdgeExecutor(Sentence *sentence, + ExecutionContext *ectx) : Executor(ectx) { + sentence_ = static_cast<DescribeEdgeSentence*>(sentence); +} + + +Status DescribeEdgeExecutor::prepare() { + return Status::OK(); +} + + +void DescribeEdgeExecutor::execute() { + auto *sm = ectx()->schemaManager(); + auto *name = sentence_->name(); + auto *schema = sm->getEdgeSchema(*name); + resp_ = std::make_unique<cpp2::ExecutionResponse>(); + + do { + if (schema == nullptr) { + onError_(Status::Error("Schema not found for edge `%s'", name->c_str())); + return; + } + std::vector<std::string> header{"SrcTag", "DstTag", "Column", "Type"}; + auto &src = schema->srcTag(); + auto &dst = schema->dstTag(); + auto &items = schema->getPropertiesSchema()->getItems(); + std::vector<cpp2::RowValue> rows; + for (auto &item : items) { + std::vector<cpp2::ColumnValue> row; + row.resize(4); + row[0].set_str(src); + row[1].set_str(dst); + row[2].set_str(item.name_); + row[3].set_str(columnTypeToString(item.type_)); + rows.emplace_back(); + rows.back().set_columns(std::move(row)); + } + if (!rows.empty()) { + resp_->set_column_names(std::move(header)); + } else { // no columns + header.resize(header.size() - 2); + resp_->set_column_names(std::move(header)); + std::vector<cpp2::ColumnValue> row; + row.resize(2); + row[0].set_str(src); + row[1].set_str(dst); + rows.resize(1); + rows[0].set_columns(std::move(row)); + } + resp_->set_rows(std::move(rows)); + } while (false); + + DCHECK(onFinish_); + onFinish_(); +} + + +void DescribeEdgeExecutor::setupResponse(cpp2::ExecutionResponse &resp) { + resp = std::move(*resp_); +} + +} // namespace graph +} // namespace nebula diff --git a/src/executor/DescribeEdgeExecutor.h b/src/executor/DescribeEdgeExecutor.h new file mode 100644 index 00000000..2f084628 --- /dev/null +++ b/src/executor/DescribeEdgeExecutor.h @@ -0,0 +1,38 @@ +/* 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 GRAPH_DESCRIBEEDGEEXECUTOR_H_ +#define GRAPH_DESCRIBEEDGEEXECUTOR_H_ + +#include "base/Base.h" +#include "graph/Executor.h" + +namespace nebula { +namespace graph { + +class DescribeEdgeExecutor final : public Executor { +public: + DescribeEdgeExecutor(Sentence *sentence, ExecutionContext *ectx); + + const char* name() const override { + return "DescribeEdgeExecutor"; + } + + Status VE_MUST_USE_RESULT prepare() override; + + void execute() override; + + void setupResponse(cpp2::ExecutionResponse &resp) override; + +private: + DescribeEdgeSentence *sentence_{nullptr}; + std::unique_ptr<cpp2::ExecutionResponse> resp_; +}; + +} // namespace graph +} // namespace nebula + +#endif // GRAPH_DESCRIBEEDGEEXECUTOR_H_ diff --git a/src/executor/DescribeTagExecutor.cpp b/src/executor/DescribeTagExecutor.cpp new file mode 100644 index 00000000..d332aa69 --- /dev/null +++ b/src/executor/DescribeTagExecutor.cpp @@ -0,0 +1,59 @@ +/* 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 "graph/DescribeTagExecutor.h" + +namespace nebula { +namespace graph { + +DescribeTagExecutor::DescribeTagExecutor(Sentence *sentence, + ExecutionContext *ectx) : Executor(ectx) { + sentence_ = static_cast<DescribeTagSentence*>(sentence); +} + + +Status DescribeTagExecutor::prepare() { + return Status::OK(); +} + + +void DescribeTagExecutor::execute() { + auto *sm = ectx()->schemaManager(); + auto *name = sentence_->name(); + resp_ = std::make_unique<cpp2::ExecutionResponse>(); + auto *schema = sm->getTagSchema(*name); + do { + if (schema == nullptr) { + onError_(Status::Error("Schema not found for tag `%s'", name->c_str())); + return; + } + std::vector<std::string> header{"Column", "Type"}; + resp_->set_column_names(std::move(header)); + auto &items = schema->getPropertiesSchema()->getItems(); + std::vector<cpp2::RowValue> rows; + for (auto &item : items) { + std::vector<cpp2::ColumnValue> row; + row.resize(2); + row[0].set_str(item.name_); + row[1].set_str(columnTypeToString(item.type_)); + rows.emplace_back(); + rows.back().set_columns(std::move(row)); + } + resp_->set_rows(std::move(rows)); + } while (false); + + DCHECK(onFinish_); + onFinish_(); +} + + +void DescribeTagExecutor::setupResponse(cpp2::ExecutionResponse &resp) { + resp = std::move(*resp_); +} + +} // namespace graph +} // namespace nebula diff --git a/src/executor/DescribeTagExecutor.h b/src/executor/DescribeTagExecutor.h new file mode 100644 index 00000000..2c865aa5 --- /dev/null +++ b/src/executor/DescribeTagExecutor.h @@ -0,0 +1,39 @@ +/* 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 GRAPH_DESCRIBETAGEXECUTOR_H_ +#define GRAPH_DESCRIBETAGEXECUTOR_H_ + +#include "base/Base.h" +#include "graph/Executor.h" + +namespace nebula { +namespace graph { + +class DescribeTagExecutor final : public Executor { +public: + DescribeTagExecutor(Sentence *sentence, ExecutionContext *ectx); + + const char* name() const override { + return "DescribeTagExecutor"; + } + + Status VE_MUST_USE_RESULT prepare() override; + + void execute() override; + + void setupResponse(cpp2::ExecutionResponse &resp) override; + +private: + DescribeTagSentence *sentence_{nullptr}; + std::string *tag_{nullptr}; + std::unique_ptr<cpp2::ExecutionResponse> resp_; +}; + +} // namespace graph +} // namespace nebula + +#endif // GRAPH_DESCRIBETAGEXECUTOR_H_ diff --git a/src/executor/ExecutionContext.cpp b/src/executor/ExecutionContext.cpp new file mode 100644 index 00000000..279fee13 --- /dev/null +++ b/src/executor/ExecutionContext.cpp @@ -0,0 +1,15 @@ +/* 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 "graph/ExecutionContext.h" + +namespace nebula { +namespace graph { + + +} // namespace graph +} // namespace nebula diff --git a/src/executor/ExecutionContext.h b/src/executor/ExecutionContext.h new file mode 100644 index 00000000..65d02bd0 --- /dev/null +++ b/src/executor/ExecutionContext.h @@ -0,0 +1,56 @@ +/* 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 GRAPH_EXECUTIONCONTEXT_H_ +#define GRAPH_EXECUTIONCONTEXT_H_ + +#include "base/Base.h" +#include "cpp/helpers.h" +#include "graph/RequestContext.h" +#include "parser/CompoundSentence.h" +#include "graph/mock/SchemaManager.h" +#include "graph/mock/StorageService.h" + +/** + * ExecutionContext holds context infos in the execution process, e.g. clients of storage or meta services. + */ + +namespace nebula { +namespace graph { + +class ExecutionContext final : public cpp::NonCopyable, public cpp::NonMovable { +public: + using RequestContextPtr = std::unique_ptr<RequestContext<cpp2::ExecutionResponse>>; + ExecutionContext(RequestContextPtr rctx, SchemaManager *sm, StorageService *storage) { + rctx_ = std::move(rctx); + sm_ = sm; + storage_ = storage; + } + + ~ExecutionContext() = default; + + RequestContext<cpp2::ExecutionResponse>* rctx() const { + return rctx_.get(); + } + + SchemaManager* schemaManager() const { + return sm_; + } + + StorageService* storage() const { + return storage_; + } + +private: + RequestContextPtr rctx_; + SchemaManager *sm_{nullptr}; + StorageService *storage_{nullptr}; +}; + +} // namespace graph +} // namespace graph + +#endif // GRAPH_EXECUTIONCONTEXT_H_ diff --git a/src/executor/ExecutionEngine.cpp b/src/executor/ExecutionEngine.cpp new file mode 100644 index 00000000..7acd8647 --- /dev/null +++ b/src/executor/ExecutionEngine.cpp @@ -0,0 +1,36 @@ +/* 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 "graph/ExecutionEngine.h" +#include "graph/ExecutionContext.h" +#include "graph/ExecutionPlan.h" + +namespace nebula { +namespace graph { + +ExecutionEngine::ExecutionEngine() { + schemaManager_ = std::make_unique<SchemaManager>(); + storage_ = std::make_unique<StorageService>(schemaManager_.get()); +} + + +ExecutionEngine::~ExecutionEngine() { +} + + +void ExecutionEngine::execute(RequestContextPtr rctx) { + auto ectx = std::make_unique<ExecutionContext>(std::move(rctx), + schemaManager_.get(), + storage_.get()); + // TODO(dutor) add support to execution plan + auto plan = new ExecutionPlan(std::move(ectx)); + + plan->execute(); +} + +} // namespace graph +} // namespace nebula diff --git a/src/executor/ExecutionEngine.h b/src/executor/ExecutionEngine.h new file mode 100644 index 00000000..a515d7f0 --- /dev/null +++ b/src/executor/ExecutionEngine.h @@ -0,0 +1,42 @@ +/* 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 GRAPH_EXECUTION_ENGINE_H_ +#define GRAPH_EXECUTION_ENGINE_H_ + +#include "base/Base.h" +#include "cpp/helpers.h" +#include "graph/RequestContext.h" +#include "gen-cpp2/GraphService.h" +#include "graph/mock/SchemaManager.h" +#include "graph/mock/StorageService.h" + +/** + * ExecutinoEngine is responsible to create and manage ExecutionPlan. + * For the time being, we don't have the execution plan cache support, + * instead we create a plan for each query, and destroy it upon finish. + */ + +namespace nebula { +namespace graph { + +class ExecutionEngine final : public cpp::NonCopyable, public cpp::NonMovable { +public: + ExecutionEngine(); + ~ExecutionEngine(); + + using RequestContextPtr = std::unique_ptr<RequestContext<cpp2::ExecutionResponse>>; + void execute(RequestContextPtr rctx); + +private: + std::unique_ptr<SchemaManager> schemaManager_; + std::unique_ptr<StorageService> storage_; +}; + +} // namespace graph +} // namespace nebula + +#endif // GRAPH_EXECUTION_ENGINE_H_ diff --git a/src/executor/ExecutionPlan.cpp b/src/executor/ExecutionPlan.cpp new file mode 100644 index 00000000..f0bea9be --- /dev/null +++ b/src/executor/ExecutionPlan.cpp @@ -0,0 +1,78 @@ +/* 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 "graph/ExecutionPlan.h" + +namespace nebula { +namespace graph { + +void ExecutionPlan::execute() { + auto *rctx = ectx()->rctx(); + FLOG_INFO("Parsing query: %s", rctx->query().c_str()); + + Status status; + do { + auto result = GQLParser().parse(rctx->query()); + if (!result.ok()) { + status = std::move(result).status(); + break; + } + + compound_ = std::move(result).value(); + executor_ = std::make_unique<CompoundExecutor>(compound_.get(), ectx()); + status = executor_->prepare(); + if (!status.ok()) { + break; + } + } while (false); + + // Prepare failed + if (!status.ok()) { + onError(std::move(status)); + return; + } + + // Prepared + auto onFinish = [this] () { + this->onFinish(); + }; + auto onError = [this] (Status s) { + this->onError(std::move(s)); + }; + executor_->setOnFinish(std::move(onFinish)); + executor_->setOnError(std::move(onError)); + + executor_->execute(); +} + + +void ExecutionPlan::onFinish() { + executor_->setupResponse(ectx()->rctx()->resp()); + ectx()->rctx()->finish(); + + // The `ExecutionPlan' is the root node holding all resources during the execution. + // When the whole query process is done, it's safe to release this object, as long as + // no other contexts have chances to access these resources later on, + // e.g. previously launched uncompleted async sub-tasks, EVEN on failures. + delete this; +} + + +void ExecutionPlan::onError(Status status) { + auto *rctx = ectx()->rctx(); + if (status.isSyntaxError()) { + rctx->resp().set_error_code(cpp2::ErrorCode::E_SYNTAX_ERROR); + } else { + rctx->resp().set_error_code(cpp2::ErrorCode::E_EXECUTION_ERROR); + } + rctx->resp().set_error_msg(status.toString()); + rctx->finish(); + delete this; +} + +} // namespace graph +} // namespace nebula diff --git a/src/executor/ExecutionPlan.h b/src/executor/ExecutionPlan.h new file mode 100644 index 00000000..888f4111 --- /dev/null +++ b/src/executor/ExecutionPlan.h @@ -0,0 +1,62 @@ +/* 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 GRAPH_EXECUTIONPLAN_H_ +#define GRAPH_EXECUTIONPLAN_H_ + +#include "base/Base.h" +#include "base/Status.h" +#include "cpp/helpers.h" +#include "parser/GQLParser.h" +#include "graph/ExecutionContext.h" +#include "graph/CompoundExecutor.h" + +/** + * ExecutionPlan coordinates the execution process, + * i.e. parse a query into a parsing tree, analyze the tree, + * initiate and finalize the execution. + */ + +namespace nebula { +namespace graph { + +class ExecutionPlan final : public cpp::NonCopyable, public cpp::NonMovable { +public: + explicit ExecutionPlan(std::unique_ptr<ExecutionContext> ectx) { + ectx_ = std::move(ectx); + } + + ~ExecutionPlan() = default; + + void execute(); + + /** + * If the whole execution was done, `onFinish' would be invoked. + * All `onFinish' should do is to ask `executor_' to fill the `ectx()->rctx()->resp()', + * which in turn asks the last sub-executor to do the actual job. + */ + void onFinish(); + + /** + * If any error occurred during the execution, `onError' should + * be invoked with a status to indicate the reason. + */ + void onError(Status); + + ExecutionContext* ectx() const { + return ectx_.get(); + } + +private: + std::unique_ptr<CompoundSentence> compound_; + std::unique_ptr<ExecutionContext> ectx_; + std::unique_ptr<CompoundExecutor> executor_; +}; + +} // namespace graph +} // namespace nebula + +#endif // GRAPH_EXECUTIONPLAN_H_ diff --git a/src/executor/Executor.cpp b/src/executor/Executor.cpp new file mode 100644 index 00000000..e4184e45 --- /dev/null +++ b/src/executor/Executor.cpp @@ -0,0 +1,75 @@ +/* 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 "graph/Executor.h" +#include "parser/TraverseSentences.h" +#include "parser/MutateSentences.h" +#include "parser/MaintainSentences.h" +#include "graph/GoExecutor.h" +#include "graph/UseExecutor.h" +#include "graph/PipeExecutor.h" +#include "graph/DefineTagExecutor.h" +#include "graph/DefineEdgeExecutor.h" +#include "graph/AlterTagExecutor.h" +#include "graph/AlterEdgeExecutor.h" +#include "graph/DescribeTagExecutor.h" +#include "graph/DescribeEdgeExecutor.h" +#include "graph/InsertVertexExecutor.h" +#include "graph/InsertEdgeExecutor.h" + +namespace nebula { +namespace graph { + +std::unique_ptr<Executor> Executor::makeExecutor(Sentence *sentence) { + auto kind = sentence->kind(); + std::unique_ptr<Executor> executor; + switch (kind) { + case Sentence::Kind::kGo: + executor = std::make_unique<GoExecutor>(sentence, ectx()); + break; + case Sentence::Kind::kUse: + executor = std::make_unique<UseExecutor>(sentence, ectx()); + break; + case Sentence::Kind::kPipe: + executor = std::make_unique<PipeExecutor>(sentence, ectx()); + break; + case Sentence::Kind::kDefineTag: + executor = std::make_unique<DefineTagExecutor>(sentence, ectx()); + break; + case Sentence::Kind::kDefineEdge: + executor = std::make_unique<DefineEdgeExecutor>(sentence, ectx()); + break; + case Sentence::Kind::kAlterTag: + executor = std::make_unique<AlterTagExecutor>(sentence, ectx()); + break; + case Sentence::Kind::kAlterEdge: + executor = std::make_unique<AlterEdgeExecutor>(sentence, ectx()); + break; + case Sentence::Kind::kDescribeTag: + executor = std::make_unique<DescribeTagExecutor>(sentence, ectx()); + break; + case Sentence::Kind::kDescribeEdge: + executor = std::make_unique<DescribeEdgeExecutor>(sentence, ectx()); + break; + case Sentence::Kind::kInsertVertex: + executor = std::make_unique<InsertVertexExecutor>(sentence, ectx()); + break; + case Sentence::Kind::kInsertEdge: + executor = std::make_unique<InsertEdgeExecutor>(sentence, ectx()); + break; + case Sentence::Kind::kUnknown: + LOG(FATAL) << "Sentence kind unknown"; + break; + default: + LOG(FATAL) << "Sentence kind illegal: " << kind; + break; + } + return executor; +} + +} // namespace graph +} // namespace nebula diff --git a/src/executor/Executor.h b/src/executor/Executor.h new file mode 100644 index 00000000..f4b14701 --- /dev/null +++ b/src/executor/Executor.h @@ -0,0 +1,85 @@ +/* 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 GRAPH_EXECUTOR_H_ +#define GRAPH_EXECUTOR_H_ + +#include "base/Base.h" +#include "base/Status.h" +#include "cpp/helpers.h" +#include "graph/ExecutionContext.h" + + +/** + * Executor is the interface of kinds of specific executors that do the actual execution. + */ + +namespace nebula { +namespace graph { + +class Executor : public cpp::NonCopyable, public cpp::NonMovable { +public: + explicit Executor(ExecutionContext *ectx) { + ectx_ = ectx; + } + + virtual ~Executor() {} + + /** + * Do some preparatory works, such as sanitize checking, dependency setup, etc. + * + * `prepare' succeeds only if all its sub-executors are prepared. + * `prepare' works in a synchronous way, once the executor is prepared, it will + * be executed. + */ + virtual Status VE_MUST_USE_RESULT prepare() = 0; + + virtual void execute() = 0; + + virtual const char* name() const = 0; + + /** + * Set callback to be invoked when this executor is finished(normally). + */ + void setOnFinish(std::function<void()> onFinish) { + onFinish_ = onFinish; + } + /** + * When some error happens during an executor's execution, it should invoke its + * `onError_' with a Status that indicates the reason. + * + * An executor terminates its execution via invoking either `onFinish_' or `onError_', + * but should never call them both. + */ + void setOnError(std::function<void(Status)> onError) { + onError_ = onError; + } + /** + * Upon finished successfully, `setupResponse' would be invoked on the last executor. + * Any Executor implementation, which wants to send its meaningful result to the client, + * should override this method. + */ + virtual void setupResponse(cpp2::ExecutionResponse &resp) { + resp.set_error_code(cpp2::ErrorCode::SUCCEEDED); + } + + ExecutionContext* ectx() const { + return ectx_; + } + +protected: + std::unique_ptr<Executor> makeExecutor(Sentence *sentence); + +protected: + ExecutionContext *ectx_; + std::function<void()> onFinish_; + std::function<void(Status)> onError_; +}; + +} // namespace graph +} // namespace nebula + +#endif // GRAPH_EXECUTOR_H_ diff --git a/src/executor/GoExecutor.cpp b/src/executor/GoExecutor.cpp new file mode 100644 index 00000000..0062e2e9 --- /dev/null +++ b/src/executor/GoExecutor.cpp @@ -0,0 +1,212 @@ +/* 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 "graph/GoExecutor.h" + + +namespace nebula { +namespace graph { + +GoExecutor::GoExecutor(Sentence *sentence, ExecutionContext *ectx) : TraverseExecutor(ectx) { + // The RTTI is guaranteed by Sentence::Kind, + // so we use `static_cast' instead of `dynamic_cast' for the sake of efficiency. + sentence_ = static_cast<GoSentence*>(sentence); +} + + +Status GoExecutor::prepare() { + DCHECK(sentence_ != nullptr); + Status status; + expctx_ = std::make_unique<ExpressionContext>(); + do { + status = prepareStep(); + if (!status.ok()) { + break; + } + status = prepareFrom(); + if (!status.ok()) { + break; + } + status = prepareOver(); + if (!status.ok()) { + break; + } + status = prepareWhere(); + if (!status.ok()) { + break; + } + status = prepareYield(); + if (!status.ok()) { + break; + } + status = prepareResultSchema(); + if (!status.ok()) { + break; + } + status = prepareNeededProps(); + if (!status.ok()) { + break; + } + } while (false); + + if (!status.ok()) { + return status; + } + + expctx_->print(); + + if (!onResult_) { + onResult_ = [this] (TraverseRecords records) { + this->cacheResult(std::move(records)); + }; + } + + return status; +} + + +void GoExecutor::execute() { + FLOG_INFO("Executing Go: %s", sentence_->toString().c_str()); + using Result = StatusOr<storage::cpp2::QueryResponse>; + auto eprops = expctx_->edgePropNames(); + auto vprops = expctx_->srcNodePropNames(); + auto *edge = edges_[0]->edge(); + auto future = ectx()->storage()->getOutBound(starts_, edge, eprops, vprops); + auto *runner = ectx()->rctx()->runner(); + std::move(future).via(runner).then([this] (Result result) { + if (!result.ok()) { + auto &resp = ectx()->rctx()->resp(); + auto status = result.status(); + resp.set_error_code(cpp2::ErrorCode::E_EXECUTION_ERROR); + resp.set_error_msg(status.toString()); + } + if (onFinish_) { + onFinish_(); + } + }); +} + + +void GoExecutor::feedResult(TraverseRecords records) { + inputs_.reserve(records.size()); + for (auto &record : records) { + inputs_.push_back(std::move(record)); + } +} + + +Status GoExecutor::prepareResultSchema() { + resultSchema_ = std::make_unique<ResultSchema>(); + for (auto *column : yields_) { + resultSchema_->addColumn(*column->alias()); + } + return Status::OK(); +} + + +Status GoExecutor::prepareStep() { + auto *clause = sentence_->stepClause(); + if (clause != nullptr) { + steps_ = clause->steps(); + upto_ = clause->isUpto(); + } + return Status::OK(); +} + + +Status GoExecutor::prepareFrom() { + Status status = Status::OK(); + auto *clause = sentence_->fromClause(); + do { + if (clause == nullptr) { + break; + } + auto *alias = clause->alias(); + if (alias == nullptr) { + break; + } + expctx_->addAlias(*alias, AliasKind::SourceNode); + starts_ = clause->srcNodeList()->nodeIds(); + } while (false); + return status; +} + + +Status GoExecutor::prepareOver() { + Status status = Status::OK(); + auto *clause = sentence_->overClause(); + do { + if (clause == nullptr) { + break; + } + edges_ = clause->edges(); + reversely_ = clause->isReversely(); + if (edges_.empty()) { + break; + } + for (auto *item : edges_) { + expctx_->addAlias(*item->alias(), AliasKind::Edge, *item->edge()); + + } + } while (false); + return status; +} + + +Status GoExecutor::prepareWhere() { + auto *clause = sentence_->whereClause(); + if (clause != nullptr) { + filter_ = clause->filter(); + } + return Status::OK(); +} + + +Status GoExecutor::prepareYield() { + auto *clause = sentence_->yieldClause(); + if (clause != nullptr) { + yields_ = clause->columns(); + } + return Status::OK(); +} + + +Status GoExecutor::prepareNeededProps() { + auto status = Status::OK(); + do { + if (filter_ != nullptr) { + status = filter_->prepare(expctx_.get()); + if (!status.ok()) { + break; + } + } + if (yields_.empty()) { + break; + } + for (auto *col : yields_) { + status = col->expr()->prepare(expctx_.get()); + if (!status.ok()) { + break; + } + } + } while (false); + + return status; +} + + +void GoExecutor::cacheResult(TraverseRecords records) { + UNUSED(records); +} + + +void GoExecutor::setupResponse(cpp2::ExecutionResponse &resp) { + UNUSED(resp); +} + +} // namespace graph +} // namespace nebula diff --git a/src/executor/GoExecutor.h b/src/executor/GoExecutor.h new file mode 100644 index 00000000..31c3ea6a --- /dev/null +++ b/src/executor/GoExecutor.h @@ -0,0 +1,66 @@ +/* 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 GRAPH_GOEXECUTOR_H_ +#define GRAPH_GOEXECUTOR_H_ + +#include "base/Base.h" +#include "graph/TraverseExecutor.h" + +namespace nebula { +namespace graph { + +class GoExecutor final : public TraverseExecutor { +public: + GoExecutor(Sentence *sentence, ExecutionContext *ectx); + + const char* name() const override { + return "GoExecutor"; + } + + Status VE_MUST_USE_RESULT prepare() override; + + void execute() override; + + void feedResult(TraverseRecords records) override; + + void setupResponse(cpp2::ExecutionResponse &resp) override; + +private: + Status prepareResultSchema(); + + Status prepareStep(); + + Status prepareFrom(); + + Status prepareOver(); + + Status prepareWhere(); + + Status prepareYield(); + + Status prepareNeededProps(); + + void cacheResult(TraverseRecords records); + +private: + GoSentence *sentence_{nullptr}; + uint32_t steps_{1}; + bool upto_{false}; + bool reversely_{false}; + std::vector<EdgeItem*> edges_; + Expression *filter_{nullptr}; + std::vector<YieldColumn*> yields_; + TraverseRecords inputs_; + std::unique_ptr<ExpressionContext> expctx_; + std::vector<int64_t> starts_; +}; + +} // namespace graph +} // namespace nebula + + +#endif // GRAPH_GOEXECUTOR_H_ diff --git a/src/executor/GraphFlags.cpp b/src/executor/GraphFlags.cpp new file mode 100644 index 00000000..c4ca13e6 --- /dev/null +++ b/src/executor/GraphFlags.cpp @@ -0,0 +1,21 @@ +/* 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 "graph/GraphFlags.h" + +DEFINE_int32(port, 34500, "Nebula Graph daemon's listen port"); +DEFINE_int32(client_idle_timeout_secs, 0, "Seconds before we close the idle connections, 0 for infinite"); +DEFINE_int32(session_idle_timeout_secs, 600, "Seconds before we expire the idle sessions, 0 for infinite"); +DEFINE_int32(session_reclaim_interval_secs, 10, "Period we try to reclaim expired sessions"); +DEFINE_int32(num_netio_threads, 0, "Number of networking threads, 0 for number of physical CPU cores"); +DEFINE_int32(num_accept_threads, 1, "Number of threads to accept incoming connections"); +DEFINE_bool(reuse_port, true, "Whether to turn on the SO_REUSEPORT option"); +DEFINE_int32(listen_backlog, 1024, "Backlog of the listen socket"); + +DEFINE_bool(redirect_stdout, true, "Whether to redirect stdout and stderr to separate files"); +DEFINE_string(stdout_log_file, "graphd-stdout.log", "Destination filename of stdout"); +DEFINE_string(stderr_log_file, "graphd-stderr.log", "Destination filename of stderr"); diff --git a/src/executor/GraphFlags.h b/src/executor/GraphFlags.h new file mode 100644 index 00000000..445a1a97 --- /dev/null +++ b/src/executor/GraphFlags.h @@ -0,0 +1,26 @@ +/* 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 GRAPH_GRAPHFLAGS_H_ +#define GRAPH_GRAPHFLAGS_H_ + +#include "base/Base.h" + +DECLARE_int32(port); +DECLARE_int32(client_idle_timeout_secs); +DECLARE_int32(session_idle_timeout_secs); +DECLARE_int32(session_reclaim_interval_secs); +DECLARE_int32(num_netio_threads); +DECLARE_int32(num_accept_threads); +DECLARE_bool(reuse_port); +DECLARE_int32(listen_backlog); + +DECLARE_bool(redirect_stdout); +DECLARE_string(stdout_log_file); +DECLARE_string(stderr_log_file); + + +#endif // GRAPH_GRAPHFLAGS_H_ diff --git a/src/executor/GraphService.cpp b/src/executor/GraphService.cpp new file mode 100644 index 00000000..b06e8a26 --- /dev/null +++ b/src/executor/GraphService.cpp @@ -0,0 +1,104 @@ +/* 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 "graph/GraphService.h" +#include "time/Duration.h" +#include "graph/RequestContext.h" +#include "graph/SimpleAuthenticator.h" + +namespace nebula { +namespace graph { + +GraphService::GraphService() { + sessionManager_ = std::make_unique<SessionManager>(); + executionEngine_ = std::make_unique<ExecutionEngine>(); + authenticator_ = std::make_unique<SimpleAuthenticator>(); +} + +GraphService::~GraphService() { +} + +folly::Future<cpp2::AuthResponse> GraphService::future_authenticate( + const std::string& username, + const std::string& password) { + auto *peer = getConnectionContext()->getPeerAddress(); + FVLOG2("Authenticating user %s from %s", username.c_str(), peer->describe().c_str()); + + RequestContext<cpp2::AuthResponse> ctx; + auto session = sessionManager_->createSession(); + session->setUser(username); + ctx.setSession(std::move(session)); + + if (authenticator_->auth(username, password)) { + ctx.resp().set_error_code(cpp2::ErrorCode::SUCCEEDED); + ctx.resp().set_session_id(ctx.session()->id()); + } else { + sessionManager_->removeSession(ctx.session()->id()); + ctx.resp().set_error_code(cpp2::ErrorCode::E_BAD_USERNAME_PASSWORD); + ctx.resp().set_error_msg(getErrorStr(cpp2::ErrorCode::E_BAD_USERNAME_PASSWORD)); + } + + ctx.finish(); + return ctx.future(); +} + + +void GraphService::signout(int64_t sessionId) { + VLOG(2) << "Sign out session " << sessionId; + sessionManager_->removeSession(sessionId); +} + + +folly::Future<cpp2::ExecutionResponse> +GraphService::future_execute(int64_t sessionId, const std::string& query) { + auto ctx = std::make_unique<RequestContext<cpp2::ExecutionResponse>>(); + ctx->setQuery(query); + ctx->setRunner(getThreadManager()); + auto future = ctx->future(); + { + auto result = sessionManager_->findSession(sessionId); + if (!result.ok()) { + FLOG_ERROR("Session not found, id[%ld]", sessionId); + ctx->resp().set_error_code(cpp2::ErrorCode::E_SESSION_INVALID); + ctx->resp().set_error_msg(result.status().toString()); + ctx->finish(); + return future; + } + ctx->setSession(std::move(result).value()); + } + executionEngine_->execute(std::move(ctx)); + + return future; +} + + +const char* GraphService::getErrorStr(cpp2::ErrorCode result) { + switch (result) { + case cpp2::ErrorCode::SUCCEEDED: + return "Succeeded"; + /********************** + * Server side errors + **********************/ + case cpp2::ErrorCode::E_BAD_USERNAME_PASSWORD: + return "Bad username/password"; + case cpp2::ErrorCode::E_SESSION_INVALID: + return "The session is invalid"; + case cpp2::ErrorCode::E_SESSION_TIMEOUT: + return "The session timed out"; + case cpp2::ErrorCode::E_SYNTAX_ERROR: + return "Syntax error"; + /********************** + * Unknown error + **********************/ + default: + return "Unknown error"; + } +} + +} // namespace graph +} // namespace nebula + diff --git a/src/executor/GraphService.h b/src/executor/GraphService.h new file mode 100644 index 00000000..13c12611 --- /dev/null +++ b/src/executor/GraphService.h @@ -0,0 +1,43 @@ +/* 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 GRAPH_GRAPHSERVICE_H_ +#define GRAPH_GRAPHSERVICE_H_ + +#include "base/Base.h" +#include "gen-cpp2/GraphService.h" +#include "graph/SessionManager.h" +#include "graph/ExecutionEngine.h" +#include "graph/Authenticator.h" + +namespace nebula { +namespace graph { + +class GraphService final : public cpp2::GraphServiceSvIf { +public: + GraphService(); + ~GraphService(); + folly::Future<cpp2::AuthResponse> future_authenticate( + const std::string& username, + const std::string& password) override; + + void signout(int64_t /*sessionId*/) override; + + folly::Future<cpp2::ExecutionResponse> future_execute( + int64_t sessionId, + const std::string& stmt) override; + + const char* getErrorStr(cpp2::ErrorCode result); + +private: + std::unique_ptr<SessionManager> sessionManager_; + std::unique_ptr<ExecutionEngine> executionEngine_; + std::unique_ptr<Authenticator> authenticator_; +}; + +} // namespace graph +} // namespace nebula +#endif // GRAPH_GRAPHSERVICE_H_ diff --git a/src/executor/InsertEdgeExecutor.cpp b/src/executor/InsertEdgeExecutor.cpp new file mode 100644 index 00000000..73303859 --- /dev/null +++ b/src/executor/InsertEdgeExecutor.cpp @@ -0,0 +1,55 @@ +/* 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 "graph/InsertEdgeExecutor.h" + +namespace nebula { +namespace graph { + +InsertEdgeExecutor::InsertEdgeExecutor(Sentence *sentence, + ExecutionContext *ectx) : Executor(ectx) { + sentence_ = static_cast<InsertEdgeSentence*>(sentence); +} + + +Status InsertEdgeExecutor::prepare() { + overwritable_ = sentence_->overwritable(); + srcid_ = sentence_->srcid(); + dstid_ = sentence_->dstid(); + edge_ = sentence_->edge(); + rank_ = sentence_->rank(); + properties_ = sentence_->properties(); + values_ = sentence_->values(); + // TODO(dutor) check on property names and types + if (properties_.size() != values_.size()) { + return Status::Error("Number of property names and values not match"); + } + return Status::OK(); +} + + +void InsertEdgeExecutor::execute() { + std::vector<VariantType> values; + values.resize(values_.size()); + auto eval = [] (auto *expr) { return expr->eval(); }; + std::transform(values_.begin(), values_.end(), values.begin(), eval); + + auto future = ectx()->storage()->addEdge(edge_, srcid_, dstid_, properties_, values); + auto *runner = ectx()->rctx()->runner(); + std::move(future).via(runner).then([this] (Status status) { + if (!status.ok()) { + auto &resp = ectx()->rctx()->resp(); + resp.set_error_code(cpp2::ErrorCode::E_EXECUTION_ERROR); + resp.set_error_msg(status.toString()); + } + DCHECK(onFinish_); + onFinish_(); + }); +} + +} // namespace graph +} // namespace nebula diff --git a/src/executor/InsertEdgeExecutor.h b/src/executor/InsertEdgeExecutor.h new file mode 100644 index 00000000..b5560148 --- /dev/null +++ b/src/executor/InsertEdgeExecutor.h @@ -0,0 +1,42 @@ +/* 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 GRAPH_INSERTEDGEEXECUTOR_H_ +#define GRAPH_INSERTEDGEEXECUTOR_H_ + +#include "base/Base.h" +#include "graph/Executor.h" + +namespace nebula { +namespace graph { + +class InsertEdgeExecutor final : public Executor { +public: + InsertEdgeExecutor(Sentence *sentence, ExecutionContext *ectx); + + const char* name() const override { + return "InsertEdgeExecutor"; + } + + Status VE_MUST_USE_RESULT prepare() override; + + void execute() override; + +private: + InsertEdgeSentence *sentence_{nullptr}; + bool overwritable_{true}; + int64_t srcid_{0}; + int64_t dstid_{0}; + int64_t rank_{0}; + std::string *edge_{nullptr}; + std::vector<std::string*> properties_; + std::vector<Expression*> values_; +}; + +} // namespace graph +} // namespace nebula + +#endif // GRAPH_INSERTEDGEEXECUTOR_H_ diff --git a/src/executor/InsertVertexExecutor.cpp b/src/executor/InsertVertexExecutor.cpp new file mode 100644 index 00000000..3542b036 --- /dev/null +++ b/src/executor/InsertVertexExecutor.cpp @@ -0,0 +1,50 @@ +/* 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 "graph/InsertVertexExecutor.h" + +namespace nebula { +namespace graph { + +InsertVertexExecutor::InsertVertexExecutor(Sentence *sentence, + ExecutionContext *ectx) : Executor(ectx) { + sentence_ = static_cast<InsertVertexSentence*>(sentence); +} + + +Status InsertVertexExecutor::prepare() { + overwritable_ = sentence_->overwritable(); + id_ = sentence_->id(); + vertex_ = sentence_->vertex(); + properties_ = sentence_->properties(); + values_ = sentence_->values(); + // TODO(dutor) check on property names and types + if (properties_.size() != values_.size()) { + return Status::Error("Number of property names and values not match"); + } + return Status::OK(); +} + + +void InsertVertexExecutor::execute() { + std::vector<VariantType> values; + values.resize(values_.size()); + auto eval = [] (auto *expr) { return expr->eval(); }; + std::transform(values_.begin(), values_.end(), values.begin(), eval); + + auto future = ectx()->storage()->addTag(vertex_, id_, properties_, values); + auto *runner = ectx()->rctx()->runner(); + std::move(future).via(runner).then([this] (Status status) { + // TODO(dutor) error handling + UNUSED(status); + DCHECK(onFinish_); + onFinish_(); + }); +} + +} // namespace graph +} // namespace nebula diff --git a/src/executor/InsertVertexExecutor.h b/src/executor/InsertVertexExecutor.h new file mode 100644 index 00000000..9092adf1 --- /dev/null +++ b/src/executor/InsertVertexExecutor.h @@ -0,0 +1,40 @@ +/* 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 GRAPH_INSERTVERTEXEXECUTOR_H_ +#define GRAPH_INSERTVERTEXEXECUTOR_H_ + +#include "base/Base.h" +#include "graph/Executor.h" + +namespace nebula { +namespace graph { + +class InsertVertexExecutor final : public Executor { +public: + InsertVertexExecutor(Sentence *sentence, ExecutionContext *ectx); + + const char* name() const override { + return "InsertVertexExecutor"; + } + + Status VE_MUST_USE_RESULT prepare() override; + + void execute() override; + +private: + InsertVertexSentence *sentence_{nullptr}; + bool overwritable_{true}; + int64_t id_{0}; + std::string *vertex_{nullptr}; + std::vector<std::string*> properties_; + std::vector<Expression*> values_; +}; + +} // namespace graph +} // namespace nebula + +#endif // GRAPH_INSERTVERTEXEXECUTOR_H_ diff --git a/src/executor/PipeExecutor.cpp b/src/executor/PipeExecutor.cpp new file mode 100644 index 00000000..25cfa16c --- /dev/null +++ b/src/executor/PipeExecutor.cpp @@ -0,0 +1,112 @@ +/* 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 "graph/PipeExecutor.h" + +namespace nebula { +namespace graph { + +PipeExecutor::PipeExecutor(Sentence *sentence, + ExecutionContext *ectx) : TraverseExecutor(ectx) { + sentence_ = static_cast<PipedSentence*>(sentence); +} + + +Status PipeExecutor::prepare() { + left_ = makeTraverseExecutor(sentence_->left()); + right_ = makeTraverseExecutor(sentence_->right()); + DCHECK(left_ != nullptr); + DCHECK(right_ != nullptr); + + auto status = left_->prepare(); + if (!status.ok()) { + FLOG_ERROR("Prepare executor `%s' failed: %s", + left_->name(), status.toString().c_str()); + return status; + } + + right_->setInputResultSchema(left_->resultSchema()); + + status = right_->prepare(); + if (!status.ok()) { + FLOG_ERROR("Prepare executor `%s' failed: %s", + right_->name(), status.toString().c_str()); + return status; + } + + auto onError = [this] (Status s) { + /** + * TODO(dutor) + * If we allow concurrent execution of both sides, we must wait for all their + * internal on-fly async-requests' to arrive before call `onError_'. + * For the sake of simplicity, we don't allow the pipeline way for now. + */ + onError_(std::move(s)); + }; + + // Setup dependencies + { + auto onFinish = [this] () { + // Start executing `right_' when `left_' is finished. + right_->execute(); + }; + left_->setOnFinish(onFinish); + + auto onResult = [this] (TraverseRecords records) { + // Feed results from `left_' to `right_' + right_->feedResult(std::move(records)); + }; + left_->setOnResult(onResult); + + left_->setOnError(onError); + } + { + auto onFinish = [this] () { + // This executor is done when `right_' finishes. + DCHECK(onFinish_); + onFinish_(); + }; + right_->setOnFinish(onFinish); + + if (onResult_) { + auto onResult = [this] (TraverseRecords records) { + // This executor takes results of `right_' as results. + onResult_(std::move(records)); + }; + right_->setOnResult(onResult); + } else { + // `right_' is the right most part of the pipeline + } + + right_->setOnError(onError); + } + + return Status::OK(); +} + + +void PipeExecutor::execute() { + left_->execute(); +} + + +void PipeExecutor::feedResult(TraverseRecords records) { + left_->feedResult(std::move(records)); +} + + +void PipeExecutor::setupResponse(cpp2::ExecutionResponse &resp) { + /** + * `setupResponse()' could be invoked if and only if this executor + * is the right most one, i.e. `onResult_' wasn't set. + */ + DCHECK(!onResult_); + right_->setupResponse(resp); +} + +} // namespace graph +} // namespace nebula diff --git a/src/executor/PipeExecutor.h b/src/executor/PipeExecutor.h new file mode 100644 index 00000000..89443540 --- /dev/null +++ b/src/executor/PipeExecutor.h @@ -0,0 +1,50 @@ +/* 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 GRAPH_PIPEEXECUTOR_H_ +#define GRAPH_PIPEEXECUTOR_H_ + +#include "base/Base.h" +#include "graph/TraverseExecutor.h" + +namespace nebula { +namespace graph { + +class PipeExecutor final : public TraverseExecutor { +public: + PipeExecutor(Sentence *sentence, ExecutionContext *ectx); + + const char* name() const override { + return "PipeExecutor"; + } + + Status VE_MUST_USE_RESULT prepare() override; + + void execute() override; + + void feedResult(TraverseRecords records) override; + + void setupResponse(cpp2::ExecutionResponse &resp) override; + + ResultSchema* resultSchema() const override { + return right_->resultSchema(); + } + + void setInputResultSchema(ResultSchema *schema) override { + left_->setInputResultSchema(schema); + } + +private: + PipedSentence *sentence_{nullptr}; + std::unique_ptr<TraverseExecutor> left_; + std::unique_ptr<TraverseExecutor> right_; +}; + +} // namespace graph +} // namespace nebula + + +#endif // GRAPH_PIPEEXECUTOR_H_ diff --git a/src/executor/README.md b/src/executor/README.md new file mode 100644 index 00000000..07dd0c5c --- /dev/null +++ b/src/executor/README.md @@ -0,0 +1 @@ +# Overview diff --git a/src/executor/RequestContext.h b/src/executor/RequestContext.h new file mode 100644 index 00000000..13e0397d --- /dev/null +++ b/src/executor/RequestContext.h @@ -0,0 +1,95 @@ +/* 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 GRAPH_REQUESTCONTEXT_H_ +#define GRAPH_REQUESTCONTEXT_H_ + +#include "base/Base.h" +#include "gen-cpp2/GraphService.h" +#include "cpp/helpers.h" +#include "time/Duration.h" +#include "graph/ClientSession.h" + +/** + * RequestContext holds context infos of a specific request from a client. + * The typical use is: + * 1. Create a RequestContext, with statement, session, etc. + * 2. Obtain a Future from the context, which is to be returned back to the Thrift framework. + * 3. Prepare the Response when the request is complished. + * 4. Call `finish' to send the response to the client. + */ + +namespace nebula { +namespace graph { + +template <typename Response> +class RequestContext final : public cpp::NonCopyable, public cpp::NonMovable { +public: + RequestContext() = default; + ~RequestContext() { + if (session_ != nullptr) { + // keep the session active + session_->charge(); + } + } + + void setQuery(std::string query) { + query_ = std::move(query); + } + + const std::string& query() const { + return query_; + } + + Response& resp() { + return resp_; + } + + folly::Future<Response> future() { + return promise_.getFuture(); + } + + void setSession(std::shared_ptr<ClientSession> session) { + session_ = std::move(session); + if (session_ != nullptr) { + // keep the session active + session_->charge(); + } + } + + ClientSession* session() const { + return session_.get(); + } + + folly::Executor* runner() const { + return runner_; + } + + void setRunner(folly::Executor *runner) { + runner_ = runner; + } + + const time::Duration& duration() const { + return duration_; + } + + void finish() { + promise_.setValue(std::move(resp_)); + } + +private: + time::Duration duration_; + std::string query_; + Response resp_; + folly::Promise<Response> promise_; + std::shared_ptr<ClientSession> session_; + folly::Executor *runner_{nullptr}; +}; + +} // namespace graph +} // namespace nebula + +#endif // GRAPH_REQUESTCONTEXT_H_ diff --git a/src/executor/SessionManager.cpp b/src/executor/SessionManager.cpp new file mode 100644 index 00000000..6f3ddf3c --- /dev/null +++ b/src/executor/SessionManager.cpp @@ -0,0 +1,105 @@ +/* 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 "graph/SessionManager.h" +#include "graph/GraphFlags.h" + +namespace nebula { +namespace graph { + +SessionManager::SessionManager() { + scavenger_ = std::make_unique<thread::GenericWorker>(); + auto ok = scavenger_->start("session-manager"); + DCHECK(ok); + auto bound = std::bind(&SessionManager::reclaimExpiredSessions, this); + scavenger_->addRepeatTask(FLAGS_session_reclaim_interval_secs * 1000, std::move(bound)); +} + + +SessionManager::~SessionManager() { + if (scavenger_ != nullptr) { + scavenger_->stop(); + scavenger_->wait(); + scavenger_.reset(); + } +} + + +StatusOr<std::shared_ptr<ClientSession>> +SessionManager::findSession(int64_t id) { + folly::RWSpinLock::ReadHolder holder(rwlock_); + auto iter = activeSessions_.find(id); + if (iter == activeSessions_.end()) { + return Status::Error("Session `%ld' has expired", id); + } + return iter->second; +} + + +std::shared_ptr<ClientSession> SessionManager::createSession() { + folly::RWSpinLock::WriteHolder holder(rwlock_); + auto sid = newSessionId(); + while (true) { + if (activeSessions_.count(sid) == 0UL) { + break; + } + // This ID is in use already, try another one + sid = newSessionId(); + } + DCHECK(sid != 0L); + auto session = ClientSession::create(sid); + activeSessions_[sid] = session; + session->charge(); + return session; +} + + +std::shared_ptr<ClientSession> SessionManager::removeSession(int64_t id) { + folly::RWSpinLock::WriteHolder holder(rwlock_); + auto iter = activeSessions_.find(id); + if (iter == activeSessions_.end()) { + return nullptr; + } + auto session = std::move(iter->second); + activeSessions_.erase(iter); + return session; +} + + +int64_t SessionManager::newSessionId() { + int64_t id = ++nextId_; + if (id == 0) { + id = ++nextId_; + } + return id; +} + + +// TODO(dutor) Now we do a brute-force scanning, of course we could make it more efficient. +void SessionManager::reclaimExpiredSessions() { + folly::RWSpinLock::WriteHolder holder(rwlock_); + if (activeSessions_.empty()) { + return; + } + + FVLOG3("Try to reclaim expired sessions out of %lu ones", activeSessions_.size()); + auto iter = activeSessions_.begin(); + auto end = activeSessions_.end(); + while (iter != end) { + auto *session = iter->second.get(); + int32_t idleSecs = session->idleSeconds(); + if (idleSecs < FLAGS_session_idle_timeout_secs) { + ++iter; + continue; + } + FLOG_INFO("Session %ld has expired", session->id()); + iter = activeSessions_.erase(iter); + } +} + +} // namespace graph +} // namespace nebula diff --git a/src/executor/SessionManager.h b/src/executor/SessionManager.h new file mode 100644 index 00000000..4fb3d11a --- /dev/null +++ b/src/executor/SessionManager.h @@ -0,0 +1,60 @@ +/* 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 GRAPH_SESSIONMANAGER_H_ +#define GRAPH_SESSIONMANAGER_H_ + +#include "base/Base.h" +#include "base/StatusOr.h" +#include "graph/ClientSession.h" +#include "thread/GenericWorker.h" + +/** + * SessionManager manages the client sessions, e.g. create new, find existing and drop expired. + */ + +namespace nebula { +namespace graph { + +class SessionManager final { +public: + SessionManager(); + ~SessionManager(); + + using SessionPtr = std::shared_ptr<ClientSession>; + /** + * Find an existing session + */ + StatusOr<SessionPtr> findSession(int64_t id); + /** + * Create a new session + */ + SessionPtr createSession(); + /** + * Remove a session + */ + SessionPtr removeSession(int64_t id); + +private: + /** + * Generate a non-zero number + */ + int64_t newSessionId(); + + void reclaimExpiredSessions(); + +private: + std::atomic<int64_t> nextId_{0}; + folly::RWSpinLock rwlock_; // TODO(dutor) writer might starve + std::unordered_map<int64_t, SessionPtr> activeSessions_; + std::unique_ptr<thread::GenericWorker> scavenger_; +}; + +} // namespace graph +} // namespace nebula + + +#endif // GRAPH_SESSIONMANAGER_H_ diff --git a/src/executor/SimpleAuthenticator.h b/src/executor/SimpleAuthenticator.h new file mode 100644 index 00000000..475e726f --- /dev/null +++ b/src/executor/SimpleAuthenticator.h @@ -0,0 +1,32 @@ +/* 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 GRAPH_SIMPLEAUTHENTICATOR_H_ +#define GRAPH_SIMPLEAUTHENTICATOR_H_ + +#include "base/Base.h" +#include "graph/Authenticator.h" + +namespace nebula { +namespace graph { + +class SimpleAuthenticator final : public Authenticator { +public: + bool VE_MUST_USE_RESULT auth(const std::string &user, + const std::string &password) override { + if (user == "user" && password == "password") { + return true; + } + return false; + } + +private: +}; + +} // namespace graph +} // namespace nebula + +#endif // GRAPH_SIMPLEAUTHENTICATOR_H_ diff --git a/src/executor/TraverseExecutor.cpp b/src/executor/TraverseExecutor.cpp new file mode 100644 index 00000000..cf4e84c7 --- /dev/null +++ b/src/executor/TraverseExecutor.cpp @@ -0,0 +1,37 @@ +/* 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 "graph/TraverseExecutor.h" +#include "parser/TraverseSentences.h" +#include "graph/GoExecutor.h" +#include "graph/PipeExecutor.h" + +namespace nebula { +namespace graph { + +std::unique_ptr<TraverseExecutor> TraverseExecutor::makeTraverseExecutor(Sentence *sentence) { + auto kind = sentence->kind(); + std::unique_ptr<TraverseExecutor> executor; + switch (kind) { + case Sentence::Kind::kGo: + executor = std::make_unique<GoExecutor>(sentence, ectx()); + break; + case Sentence::Kind::kPipe: + executor = std::make_unique<PipeExecutor>(sentence, ectx()); + break; + case Sentence::Kind::kUnknown: + LOG(FATAL) << "Sentence kind unknown"; + break; + default: + LOG(FATAL) << "Sentence kind illegal: " << kind; + break; + } + return executor; +} + +} // namespace graph +} // namespace nebula diff --git a/src/executor/TraverseExecutor.h b/src/executor/TraverseExecutor.h new file mode 100644 index 00000000..dbbfb3dc --- /dev/null +++ b/src/executor/TraverseExecutor.h @@ -0,0 +1,97 @@ +/* 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 GRAPH_TRAVERSEEXECUTOR_H_ +#define GRAPH_TRAVERSEEXECUTOR_H_ + +#include "base/Base.h" +#include "graph/Executor.h" + +namespace nebula { +namespace graph { + +class ResultSchema final { +public: + struct Column { + std::string name_; + // TODO(dutor) type + }; + + void addColumn(std::string name) { + columns_.emplace_back(); + columns_.back().name_ = std::move(name); + + } + + std::string toString() const { + std::string buf; + buf.reserve(256); + for (auto &column : columns_) { + if (column.name_.empty()) { + buf += "NULL"; + } else { + buf += column.name_; + } + buf += "\t"; + } + if (!buf.empty()) { + buf.resize(buf.size() - 1); + } + return buf; + } + +private: + std::vector<Column> columns_; +}; + + +class TraverseExecutor : public Executor { +public: + TraverseExecutor(ExecutionContext *ectx) : Executor(ectx) { + } + + using TraverseRecord = std::vector<VariantType>; + using TraverseRecords = std::vector<TraverseRecord>; + using OnResult = std::function<void(TraverseRecords)>; + + virtual void feedResult(TraverseRecords records) = 0; + + /** + * `onResult_' must be set except for the right most executor + * inside the chain of pipeline. + * + * For any TraverseExecutor, if `onResult_' is set, it means that + * some other executor depends on its execution result. Otherwise, + * it means that this executor is the right most one, whose results must + * be cached during its execution and are to be used to fill `ExecutionResponse' + * upon `setupResponse()'s invoke. + */ + void setOnResult(OnResult onResult) { + onResult_ = std::move(onResult); + } + + virtual ResultSchema* resultSchema() const { + return resultSchema_.get(); + } + + virtual void setInputResultSchema(ResultSchema *schema) { + inputResultSchema_ = schema; + } + +protected: + std::unique_ptr<TraverseExecutor> makeTraverseExecutor(Sentence *sentence); + +protected: + OnResult onResult_; + std::unique_ptr<ResultSchema> resultSchema_; + ResultSchema *inputResultSchema_{nullptr}; +}; + +} // namespace graph +} // namespace nebula + + +#endif // GRAPH_TRAVERSEEXECUTOR_H_ diff --git a/src/executor/UseExecutor.cpp b/src/executor/UseExecutor.cpp new file mode 100644 index 00000000..4dc41a24 --- /dev/null +++ b/src/executor/UseExecutor.cpp @@ -0,0 +1,34 @@ +/* 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 "graph/UseExecutor.h" + +namespace nebula { +namespace graph { + +UseExecutor::UseExecutor(Sentence *sentence, ExecutionContext *ectx) : Executor(ectx) { + sentence_ = static_cast<UseSentence*>(sentence); +} + + +Status UseExecutor::prepare() { + return Status::OK(); +} + + +void UseExecutor::execute() { + auto *session = ectx()->rctx()->session(); + + // TODO(dutor) Check space's validness and map to type of integer + session->setSpace(sentence_->space()); + FLOG_INFO("Graph space switched to `%s'", sentence_->space().c_str()); + + onFinish_(); +} + +} // namespace graph +} // namespace nebula diff --git a/src/executor/UseExecutor.h b/src/executor/UseExecutor.h new file mode 100644 index 00000000..05d637c3 --- /dev/null +++ b/src/executor/UseExecutor.h @@ -0,0 +1,36 @@ +/* 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 GRAPH_USEEXECUTOR_H_ +#define GRAPH_USEEXECUTOR_H_ + +#include "base/Base.h" +#include "graph/Executor.h" + +namespace nebula { +namespace graph { + +class UseExecutor final : public Executor { +public: + UseExecutor(Sentence *sentence, ExecutionContext *ectx); + + const char* name() const override { + return "UseExecutor"; + } + + Status VE_MUST_USE_RESULT prepare() override; + + void execute() override; + +private: + UseSentence *sentence_{nullptr}; +}; + +} // namespace graph +} // namespace nebula + + +#endif // GRAPH_USEEXECUTOR_H_ diff --git a/src/executor/mock/EdgeSchema.cpp b/src/executor/mock/EdgeSchema.cpp new file mode 100644 index 00000000..e85e65ed --- /dev/null +++ b/src/executor/mock/EdgeSchema.cpp @@ -0,0 +1,32 @@ +/* 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 "graph/mock/EdgeSchema.h" + +namespace nebula { +namespace graph { + +void EdgeSchema::addProperty(std::string name, ColumnType type) { + properties_.addProperty(std::move(name), type); +} + + +const PropertyItem* EdgeSchema::getProperty(const std::string &name) { + return properties_.getProperty(name); +} + + +std::string EdgeSchema::toString() const { + return folly::stringPrintf("%s[%u] %s[%u]->%s[%u] %s", + name_.c_str(), id_, + srcTag_.c_str(), srcId_, + dstTag_.c_str(), dstId_, + properties_.toString().c_str()); +} + +} // namespace graph +} // namespace nebula diff --git a/src/executor/mock/EdgeSchema.h b/src/executor/mock/EdgeSchema.h new file mode 100644 index 00000000..7cd1f850 --- /dev/null +++ b/src/executor/mock/EdgeSchema.h @@ -0,0 +1,89 @@ +/* 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 GRAPH_EDGESCHEMA_H_ +#define GRAPH_EDGESCHEMA_H_ + +#include "base/Base.h" +#include "graph/mock/PropertiesSchema.h" + +namespace nebula { +namespace graph { + +class EdgeSchema final { +public: + uint32_t id() const { + return id_; + } + + void setId(uint32_t id) { + id_ = id; + } + + const std::string& name() const { + return name_; + } + + void setName(std::string name) { + name_ = std::move(name); + } + + const std::string& srcTag() const { + return srcTag_; + } + + void setSrcTag(std::string tag) { + srcTag_ = tag; + } + + const std::string& dstTag() const { + return dstTag_; + } + + void setDstTag(std::string tag) { + dstTag_ = tag; + } + + uint32_t srcId() const { + return srcId_; + } + + void setSrcId(uint32_t id) { + srcId_ = id; + } + + uint32_t dstId() const { + return dstId_; + } + + void setDstId(uint32_t id) { + dstId_ = id; + } + + void addProperty(std::string name, ColumnType type); + + const PropertyItem* getProperty(const std::string &name); + + const PropertiesSchema* getPropertiesSchema() const { + return &properties_; + } + + std::string toString() const; + +private: + uint32_t id_{0}; + uint32_t srcId_{0}; + uint32_t dstId_{0}; + std::string name_; + std::string srcTag_; + std::string dstTag_; + PropertiesSchema properties_; +}; + +} // namespace graph +} // namespace nebula + +#endif // GRAPH_EDGESCHEMA_H_ diff --git a/src/executor/mock/PropertiesSchema.cpp b/src/executor/mock/PropertiesSchema.cpp new file mode 100644 index 00000000..3d8f477c --- /dev/null +++ b/src/executor/mock/PropertiesSchema.cpp @@ -0,0 +1,55 @@ +/* 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 "graph/mock/PropertiesSchema.h" + +namespace nebula { +namespace graph { + +void PropertiesSchema::addProperty(std::string name, ColumnType type) { + auto index = properties_.size(); + properties_.emplace_back(); + auto &item = properties_.back(); + item.index_ = index; + item.name_ = std::move(name); + item.type_ = type; + mapping_[name] = &item; +} + + +const PropertyItem* PropertiesSchema::getProperty(const std::string &name) const { + auto iter = mapping_.find(name); + if (iter != mapping_.end()) { + return nullptr; + } + return iter->second; +} + + +const std::vector<PropertyItem>& PropertiesSchema::getItems() const { + return properties_; +} + + +std::string PropertiesSchema::toString() const { + std::string buf; + for (auto &item : properties_) { + buf += item.name_; + buf += "["; + buf += std::to_string(item.index_); + buf += "] "; + buf += columnTypeToString(item.type_); + buf += ","; + } + if (!buf.empty()) { + buf.resize(buf.size() - 1); + } + return buf; +} + +} // namespace graph +} // namespace nebula diff --git a/src/executor/mock/PropertiesSchema.h b/src/executor/mock/PropertiesSchema.h new file mode 100644 index 00000000..643e01c7 --- /dev/null +++ b/src/executor/mock/PropertiesSchema.h @@ -0,0 +1,42 @@ +/* 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 GRAPH_PROPERTIESSCHEMA_H_ +#define GRAPH_PROPERTIESSCHEMA_H_ + +#include "base/Base.h" +#include "parser/Expressions.h" + +namespace nebula { +namespace graph { + +struct PropertyItem { + uint32_t index_{0}; + std::string name_; + ColumnType type_; +}; + + +class PropertiesSchema final { +public: + void addProperty(std::string name, ColumnType type); + + const PropertyItem* getProperty(const std::string &name) const; + + const std::vector<PropertyItem>& getItems() const; + + std::string toString() const; + +private: + using MappingType = std::unordered_map<std::string, const PropertyItem*>; + std::vector<PropertyItem> properties_; + MappingType mapping_; +}; + +} // namespace graph +} // namespace nebula + +#endif // GRAPH_PROPERTIESSCHEMA_H_ diff --git a/src/executor/mock/SchemaManager.cpp b/src/executor/mock/SchemaManager.cpp new file mode 100644 index 00000000..823b627c --- /dev/null +++ b/src/executor/mock/SchemaManager.cpp @@ -0,0 +1,70 @@ +/* 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 "graph/mock/SchemaManager.h" + +namespace nebula { +namespace graph { + +void SchemaManager::addEdgeSchema(const std::string &name, + const std::string &src, + const std::string &dst, + const std::vector<ColumnSpecification*> &specs) { + // TODO(dutor) check existence of src & dst tag + auto &schema = edges_[name]; + schema.setId(nextEdgeId_++); + schema.setName(name); + schema.setSrcTag(src); + schema.setDstTag(dst); + schema.setSrcId(tags_[src].id()); + schema.setDstId(tags_[dst].id()); + for (auto *spec : specs) { + schema.addProperty(*spec->name(), spec->type()); + } +} + + +void SchemaManager::addTagSchema(const std::string &name, + const std::vector<ColumnSpecification*> &specs) { + auto &schema = tags_[name]; + schema.setId(nextTagId_++); + schema.setName(name); + for (auto *spec : specs) { + schema.addProperty(*spec->name(), spec->type()); + } +} + + +const EdgeSchema* SchemaManager::getEdgeSchema(const std::string &name) { + auto iter = edges_.find(name); + if (iter == edges_.end()) { + return nullptr; + } + return &iter->second; +} + + +const TagSchema* SchemaManager::getTagSchema(const std::string &name) { + auto iter = tags_.find(name); + if (iter == tags_.end()) { + return nullptr; + } + return &iter->second; +} + + +void SchemaManager::print() const { + for (auto &entry : edges_) { + FLOG_INFO("Edge `%s': \n%s", entry.first.c_str(), entry.second.toString().c_str()); + } + for (auto &entry : tags_) { + FLOG_INFO("Tag `%s': \n%s", entry.first.c_str(), entry.second.toString().c_str()); + } +} + +} // namespace graph +} // namespace nebula diff --git a/src/executor/mock/SchemaManager.h b/src/executor/mock/SchemaManager.h new file mode 100644 index 00000000..bc88f270 --- /dev/null +++ b/src/executor/mock/SchemaManager.h @@ -0,0 +1,43 @@ +/* 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 GRAPH_SCHEMAMANAGER_H_ +#define GRAPH_SCHEMAMANAGER_H_ + +#include "base/Base.h" +#include "graph/mock/EdgeSchema.h" +#include "graph/mock/TagSchema.h" +#include "parser/MaintainSentences.h" + +namespace nebula { +namespace graph { + +class SchemaManager final { +public: + void addEdgeSchema(const std::string &name, + const std::string &src, + const std::string &dst, + const std::vector<ColumnSpecification*> &specs); + void addTagSchema(const std::string &name, + const std::vector<ColumnSpecification*> &specs); + + const EdgeSchema* getEdgeSchema(const std::string &name); + + const TagSchema* getTagSchema(const std::string &name); + + void print() const; + +private: + uint32_t nextEdgeId_{0}; + uint32_t nextTagId_{0}; + std::unordered_map<std::string, EdgeSchema> edges_; + std::unordered_map<std::string, TagSchema> tags_; +}; + +} // namespace graph +} // namespace nebula + +#endif // GRAPH_SCHEMAMANAGER_H_ diff --git a/src/executor/mock/StorageService.cpp b/src/executor/mock/StorageService.cpp new file mode 100644 index 00000000..555aaa42 --- /dev/null +++ b/src/executor/mock/StorageService.cpp @@ -0,0 +1,107 @@ +/* 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 "graph/mock/StorageService.h" + +namespace nebula { +namespace graph { + +StorageService::StorageService(SchemaManager *sm) { + pool_ = std::make_unique<thread::GenericThreadPool>(); + pool_->start(4, "storage-svc"); + sm_ = sm; +} + + +folly::SemiFuture<Status> +StorageService::addTag(const std::string *tag, + int64_t id, + const std::vector<std::string*> &names, + const std::vector<VariantType> &values) { + auto task = [this, tag, id, names, values] () -> Status { + auto *schema = sm_->getTagSchema(*tag); + if (schema == nullptr) { + return Status::Error("Tag `%s' not defined", tag->c_str()); + } + TagKey key; + key.id_ = id; + key.type_ = schema->id(); + auto &props = tags_[key]; + for (auto i = 0u; i < names.size(); i++) { + props[*names[i]] = values[i]; + } + return Status::OK(); + }; + return pool_->addTask(std::move(task)); +} + + +folly::SemiFuture<Status> +StorageService::addEdge(const std::string *edge, + int64_t srcid, int64_t dstid, + const std::vector<std::string*> &names, + const std::vector<VariantType> &values) { + auto task = [this, edge, srcid, dstid, names, values] () -> Status { + auto *schema = sm_->getEdgeSchema(*edge); + if (schema == nullptr) { + return Status::Error("Edge `%s' not defined", edge->c_str()); + } + EdgeKey key; + key.srcid_ = srcid; + key.dstid_ = dstid; + key.type_ = schema->id(); + auto &props = edges_[key]; + for (auto i = 0u; i < names.size(); i++) { + props[*names[i]] = values[i]; + } + return Status::OK(); + }; + + return pool_->addTask(std::move(task)); +} + +folly::SemiFuture<StorageService::OutBoundResult> +StorageService::getOutBound(const std::vector<int64_t> &ids, + const std::string *edge, + const std::vector<std::string> &eprops, + const std::vector<std::string> &vprops) { + auto task = [this, ids, edge, eprops, vprops] () -> OutBoundResult { + OutBoundResult result; + auto *schema = sm_->getEdgeSchema(*edge); + if (schema == nullptr) { + return Status::Error("Edge `%s' not defined", edge->c_str()); + } + //storage::cpp2::QueryResponse resp; + for (auto id : ids) { + EdgeKey start, end; + start.srcid_ = id; + start.type_ = schema->id(); + start.dstid_ = -1; + end.srcid_ = id; + end.type_ = start.type_ + 1; + end.dstid_ = -1; + auto left = edges_.lower_bound(start); + auto right = edges_.lower_bound(end); + for (auto iter = left; iter != right; ++iter) { + if (iter->first.srcid_ != id) { + break; + } + if (iter->first.type_ != start.type_) { + break; + } + //auto &properties = iter->second; + FLOG_INFO("%ld -%s-> %ld", id, edge->c_str(), iter->first.dstid_); + } + } + return result; + }; + + return pool_->addTask(std::move(task)); +} + +} // namespace graph +} // namespace nebula diff --git a/src/executor/mock/StorageService.h b/src/executor/mock/StorageService.h new file mode 100644 index 00000000..632d90c8 --- /dev/null +++ b/src/executor/mock/StorageService.h @@ -0,0 +1,86 @@ +/* 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 GRAPH_MOCK_STORAGESERVICE_H_ +#define GRAPH_MOCK_STORAGESERVICE_H_ + +#include "base/Base.h" +#include "base/Status.h" +#include "base/StatusOr.h" +#include "gen-cpp2/StorageService.h" +#include "thread/GenericThreadPool.h" +#include "graph/mock/SchemaManager.h" + +namespace nebula { +namespace graph { + +class StorageService { +public: + StorageService(SchemaManager *sm); + + folly::SemiFuture<Status> addTag(const std::string *tag, + int64_t id, + const std::vector<std::string*> &names, + const std::vector<VariantType> &values); + + folly::SemiFuture<Status> addEdge(const std::string *edge, + int64_t srcid, int64_t dstid, + const std::vector<std::string*> &names, + const std::vector<VariantType> &values); + using OutBoundResult = StatusOr<storage::cpp2::QueryResponse>; + folly::SemiFuture<OutBoundResult> getOutBound(const std::vector<int64_t> &ids, + const std::string *edge, + const std::vector<std::string> &eprops, + const std::vector<std::string> &vprops); + +private: + struct TagKey { + int64_t id_{0}; + int64_t type_{0}; + }; + + struct EdgeKey { + int64_t srcid_{0}; + int64_t dstid_{0}; + int32_t type_{0}; + }; + + struct TagLess { + bool operator()(const TagKey &lhs, const TagKey &rhs) const { + if (lhs.id_ != rhs.id_) { + return lhs.id_ < rhs.id_; + } + return lhs.type_ < rhs.type_; + } + }; + + struct EdgeLess { + bool operator()(const EdgeKey &lhs, const EdgeKey &rhs) const { + if (lhs.srcid_ != rhs.srcid_) { + return lhs.srcid_ < rhs.dstid_; + } + if (lhs.type_ != rhs.type_) { + return lhs.type_ < rhs.type_; + } + return lhs.dstid_ < rhs.dstid_; + } + }; + + using PropertiesType = std::unordered_map<std::string, VariantType>; + using TagsType = std::map<TagKey, PropertiesType, TagLess>; + using EdgesType = std::map<EdgeKey, PropertiesType, EdgeLess>; + +private: + TagsType tags_; + EdgesType edges_; + std::unique_ptr<thread::GenericThreadPool> pool_; + SchemaManager *sm_; +}; + +} // namespace graph +} // namespace nebula + +#endif diff --git a/src/executor/mock/TagSchema.cpp b/src/executor/mock/TagSchema.cpp new file mode 100644 index 00000000..d4649b3a --- /dev/null +++ b/src/executor/mock/TagSchema.cpp @@ -0,0 +1,34 @@ +/* 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 "graph/mock/TagSchema.h" + +namespace nebula { +namespace graph { + +void TagSchema::addProperty(std::string name, ColumnType type) { + properties_.addProperty(std::move(name), type); +} + + +const PropertyItem* TagSchema::getProperty(const std::string &name) const { + return properties_.getProperty(name); +} + + +std::string TagSchema::toString() const { + return folly::stringPrintf("%s[%u] %s", + name_.c_str(), id_, properties_.toString().c_str()); +} + + +const PropertiesSchema* TagSchema::getPropertiesSchema() const { + return &properties_; +} + +} // namespace graph +} // namespace nebula diff --git a/src/executor/mock/TagSchema.h b/src/executor/mock/TagSchema.h new file mode 100644 index 00000000..7e979928 --- /dev/null +++ b/src/executor/mock/TagSchema.h @@ -0,0 +1,51 @@ +/* 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 GRAPH_TAGSCHEMA_H_ +#define GRAPH_TAGSCHEMA_H_ + +#include "base/Base.h" +#include "graph/mock/PropertiesSchema.h" + +namespace nebula { +namespace graph { + +class TagSchema final { +public: + uint32_t id() const { + return id_; + } + + void setId(uint32_t id) { + id_ = id; + } + + const std::string &name() const { + return name_; + } + + void setName(std::string name) { + name_ = std::move(name); + } + + void addProperty(std::string name, ColumnType type); + + const PropertyItem* getProperty(const std::string &name) const; + + const PropertiesSchema* getPropertiesSchema() const; + + std::string toString() const; + +private: + uint32_t id_{0}; + std::string name_; + PropertiesSchema properties_; +}; + +} // namespace graph +} // namespace nebula + +#endif // GRAPH_TAGSCHEMA_H_ diff --git a/src/executor/test/CMakeLists.txt b/src/executor/test/CMakeLists.txt new file mode 100644 index 00000000..b277b297 --- /dev/null +++ b/src/executor/test/CMakeLists.txt @@ -0,0 +1,71 @@ +add_executable( + session_manager_test + SessionManagerTest.cpp + $<TARGET_OBJECTS:graph_obj> + $<TARGET_OBJECTS:base_obj> + $<TARGET_OBJECTS:graph_thrift_obj> + $<TARGET_OBJECTS:time_obj> + $<TARGET_OBJECTS:fs_obj> + $<TARGET_OBJECTS:thread_obj> + $<TARGET_OBJECTS:parser_obj> +) +target_link_libraries( + session_manager_test + ${THRIFT_LIBRARIES} + wangle + folly + boost_system + boost_context + ${OPENSSL_LIBRARIES} + ${KRB5_LIBRARIES} + gtest + gtest_main + glog + gflags + event + ${COMPRESSION_LIBRARIES} + resolv + double-conversion + dl + -pthread +) + +add_test(NAME session_manager_test COMMAND session_manager_test) + + +add_executable( + query_engine_test + TestMain.cpp + TestEnv.cpp + TestBase.cpp + DefineSchemaTest.cpp + $<TARGET_OBJECTS:graph_obj> + $<TARGET_OBJECTS:client_cpp_obj> + $<TARGET_OBJECTS:base_obj> + $<TARGET_OBJECTS:graph_thrift_obj> + $<TARGET_OBJECTS:time_obj> + $<TARGET_OBJECTS:fs_obj> + $<TARGET_OBJECTS:thread_obj> + $<TARGET_OBJECTS:parser_obj> +) +target_link_libraries( + query_engine_test + ${THRIFT_LIBRARIES} + wangle + folly + boost_system + boost_context + ${OPENSSL_LIBRARIES} + ${KRB5_LIBRARIES} + gtest + gtest_main + glog + gflags + event + ${COMPRESSION_LIBRARIES} + resolv + double-conversion + dl + -pthread +) +add_test(NAME query_engine_test COMMAND query_engine_test) diff --git a/src/executor/test/DefineSchemaTest.cpp b/src/executor/test/DefineSchemaTest.cpp new file mode 100644 index 00000000..09cffe7b --- /dev/null +++ b/src/executor/test/DefineSchemaTest.cpp @@ -0,0 +1,122 @@ +/* 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 "graph/test/TestEnv.h" +#include "graph/test/TestBase.h" + + +namespace nebula { +namespace graph { + +class DefineSchemaTest : public TestBase { +protected: + void SetUp() override { + TestBase::SetUp(); + // ... + } + + void TearDown() override { + // ... + TestBase::TearDown(); + } + +}; + + +TEST_F(DefineSchemaTest, Simple) { + auto client = gEnv->getClient(); + ASSERT_NE(nullptr, client); + { + cpp2::ExecutionResponse resp; + std::string query = "DEFINE TAG person(name string, email string, age int16, gender string)"; + auto code = client->execute(query, resp); + ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); + } + { + cpp2::ExecutionResponse resp; + std::string query = "DESCRIBE TAG person"; + client->execute(query, resp); + std::vector<uniform_tuple_t<std::string, 2>> expected{ + {"email", "string"}, + {"name", "string"}, + {"age", "int16"}, + {"gender", "string"}, + }; + ASSERT_TRUE(verifyResult(resp, expected)); + } + { + cpp2::ExecutionResponse resp; + std::string query = "DEFINE TAG account(id int64, balance double)"; + auto code = client->execute(query, resp); + ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); + } + { + cpp2::ExecutionResponse resp; + std::string query = "DESCRIBE TAG account"; + client->execute(query, resp); + std::vector<uniform_tuple_t<std::string, 2>> expected{ + {"id", "int64"}, + {"balance", "double"}, + }; + ASSERT_TRUE(verifyResult(resp, expected)); + } + { + cpp2::ExecutionResponse resp; + std::string query = "DEFINE EDGE friend_of person -> person()"; + auto code = client->execute(query, resp); + ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); + } + { + cpp2::ExecutionResponse resp; + std::string query = "DESCRIBE EDGE friend_of"; + client->execute(query, resp); + std::vector<uniform_tuple_t<std::string, 2>> expected{ + {"person", "person"}, + }; + ASSERT_TRUE(verifyResult(resp, expected)); + } + { + cpp2::ExecutionResponse resp; + std::string query = "DEFINE EDGE transfer " + "account -> account(amount double, time int64)"; + auto code = client->execute(query, resp); + ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); + } + { + cpp2::ExecutionResponse resp; + std::string query = "DESCRIBE EDGE transfer"; + client->execute(query, resp); + std::vector<uniform_tuple_t<std::string, 4>> expected{ + {"account", "account", "amount", "double"}, + {"account", "account", "time", "int64"}, + }; + ASSERT_TRUE(verifyResult(resp, expected)); + } + // compound sentences + { + cpp2::ExecutionResponse resp; + std::string query = "DESCRIBE EDGE friend_of; DESCRIBE EDGE transfer"; + client->execute(query, resp); + std::vector<uniform_tuple_t<std::string, 4>> expected{ + {"account", "account", "amount", "double"}, + {"account", "account", "time", "int64"}, + }; + ASSERT_TRUE(verifyResult(resp, expected)); + } + { + cpp2::ExecutionResponse resp; + std::string query = "DESCRIBE EDGE transfer; DESCRIBE EDGE friend_of"; + client->execute(query, resp); + std::vector<uniform_tuple_t<std::string, 2>> expected{ + {"person", "person"}, + }; + ASSERT_TRUE(verifyResult(resp, expected)); + } +} + +} // namespace graph +} // namespace nebula diff --git a/src/executor/test/SessionManagerTest.cpp b/src/executor/test/SessionManagerTest.cpp new file mode 100644 index 00000000..5de7ae8a --- /dev/null +++ b/src/executor/test/SessionManagerTest.cpp @@ -0,0 +1,82 @@ +/* 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 <gtest/gtest.h> +#include "graph/SessionManager.h" +#include "graph/GraphFlags.h" +#include "thread/GenericWorker.h" + +using nebula::thread::GenericWorker; + +namespace nebula { +namespace graph { + +TEST(SessionManager, Basic) { + auto sm = std::make_shared<SessionManager>(); + + auto session = sm->createSession(); + ASSERT_NE(nullptr, session); + ASSERT_NE(0, session->id()); + + auto result = sm->findSession(session->id()); + ASSERT_TRUE(result.ok()); + ASSERT_EQ(session.get(), result.value().get()); +} + +TEST(SessionManager, ExpiredSession) { + FLAGS_session_idle_timeout_secs = 3; + FLAGS_session_reclaim_interval_secs = 1; + + auto sm = std::make_shared<SessionManager>(); + + auto worker = std::make_shared<GenericWorker>(); + ASSERT_TRUE(worker->start()); + + auto idle = sm->createSession(); + auto active = sm->createSession(); + ASSERT_NE(nullptr, idle); + ASSERT_NE(nullptr, active); + ASSERT_NE(idle.get(), active.get()); + ASSERT_NE(idle->id(), active->id()); + + // keep `active' active + auto charger = [&] () { + active->charge(); + }; + worker->addRepeatTask(1000/*ms*/, charger); + + // assert `idle' not expired + auto check_not_expired = [&] () { + auto result = sm->findSession(idle->id()); + ASSERT_TRUE(result.ok()); + ASSERT_NE(nullptr, result.value()); + }; + + // assert `idle' has expired + auto check_already_expired = [&] () { + auto result = sm->findSession(idle->id()); + ASSERT_FALSE(result.ok()); + }; + + auto timeout = FLAGS_session_idle_timeout_secs; + auto future1 = worker->addDelayTask((timeout - 1) * 1000 - 50/*ms*/, check_not_expired); + auto future2 = worker->addDelayTask((timeout + 1) * 1000 + 50/*ms*/, check_already_expired); + + std::move(future1).get(); + std::move(future2).get(); + + auto result = sm->findSession(active->id()); + ASSERT_TRUE(result.ok()); + ASSERT_NE(nullptr, result.value()); + ASSERT_EQ(active.get(), result.value().get()); + + worker->stop(); + worker->wait(); +} + +} // namespace graph +} // namespace nebula diff --git a/src/executor/test/TestBase.cpp b/src/executor/test/TestBase.cpp new file mode 100644 index 00000000..6c8d02a3 --- /dev/null +++ b/src/executor/test/TestBase.cpp @@ -0,0 +1,21 @@ +/* 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 "graph/test/TestBase.h" + +namespace nebula { +namespace graph { + +void TestBase::SetUp() { +} + + +void TestBase::TearDown() { +} + +} // namespace graph +} // namespace nebula diff --git a/src/executor/test/TestBase.h b/src/executor/test/TestBase.h new file mode 100644 index 00000000..97d514dd --- /dev/null +++ b/src/executor/test/TestBase.h @@ -0,0 +1,204 @@ +/* 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 GRAPH_TEST_TESTBASE_H_ +#define GRAPH_TEST_TESTBASE_H_ + +#include "base/Base.h" +#include <gtest/gtest.h> +#include "gen-cpp2/GraphService.h" + +/** + * According to the ADL(Argument-dependent Lookup) rules, + * we have to define operator<< for `std::tuple<...>' in the global scope or `std' + */ +namespace std { + +template <typename Tuple, size_t...Is> +void printTupleImpl(std::ostream &os, const Tuple &tuple, std::index_sequence<Is...>) { + auto flags = os.flags(); + os << std::boolalpha; + + using DumyType = int[]; + (void)DumyType{(void(os << (Is == 0 ? "" : ", ") << std::get<Is>(tuple)), 0)...}; + + os.flags(flags); +} + + +template <typename Tuple> +void printTuple(std::ostream &os, const Tuple &tuple) { + printTupleImpl(os, tuple, std::make_index_sequence<std::tuple_size<Tuple>::value>()); +} + + +template <typename...Args> +std::ostream& operator<<(std::ostream &os, const std::tuple<Args...> &tuple) { + os << "["; + printTuple(os, tuple); + os << "]"; + return os; +} + +} // namespace std + + +namespace nebula { +namespace graph { + +class TestBase : public ::testing::Test { +protected: + void SetUp() override; + + void TearDown() override; + + using AssertionResult = ::testing::AssertionResult; + using ColumnType = cpp2::ColumnValue::Type; + using Row = std::vector<cpp2::ColumnValue>; + using Rows = std::vector<Row>; + + template <typename, typename> + struct uniform_tuple_impl; + template <typename T, size_t...Is> + struct uniform_tuple_impl<T, std::index_sequence<Is...>> { + template <size_t> + using IndexedType = T; + using type = std::tuple<IndexedType<Is>...>; + }; + + template <typename T, size_t N> + struct uniform_tuple { + using type = typename uniform_tuple_impl<T, std::make_index_sequence<N>>::type; + }; + + template <typename T, size_t N> + using uniform_tuple_t = typename uniform_tuple<T, N>::type; + + Rows respToRecords(const cpp2::ExecutionResponse &resp) { + CHECK(resp.get_rows() != nullptr); + Rows result; + for (auto &row : *resp.get_rows()) { + auto &columns = row.get_columns(); + result.emplace_back(); + result.back().assign(columns.begin(), columns.end()); + } + return result; + } + + /** + * Convert `ColumnValue' to its cooresponding type + */ + template <typename T> + std::enable_if_t<std::is_integral<T>::value, T> + convert(const cpp2::ColumnValue &v) { + switch (v.getType()) { + case ColumnType::integer: + return v.get_integer(); + case ColumnType::timestamp: + return v.get_timestamp(); + case ColumnType::id: + return v.get_id(); + case ColumnType::boolean: + return v.get_boolean(); + default: + throw TestError() << "Cannot convert unknown dynamic column type to integer: " + << static_cast<int32_t>(v.getType()); + } + return T(); // suppress the no-return waring + } + + template <typename T> + std::enable_if_t<std::is_same<T, std::string>::value, T> + convert(const cpp2::ColumnValue &v) { + switch (v.getType()) { + case ColumnType::str: + return v.get_str(); + default: + throw TestError() << "Cannot convert unknown dynamic column type to string: " + << static_cast<int32_t>(v.getType()); + } + return T(); // suppress the no-return warning + } + + /** + * Transform rows of dynamic type to tuples of static type + */ + template <typename Tuple, size_t...Is> + auto rowToTupleImpl(const Row &row, std::index_sequence<Is...>) { + return std::make_tuple(convert<std::tuple_element_t<Is, Tuple>>(row[Is])...); + } + + template <typename Tuple> + auto rowToTuple(const Row &row) { + constexpr auto tupleSize = std::tuple_size<Tuple>::value; + return rowToTupleImpl<Tuple>(row, std::make_index_sequence<tupleSize>()); + } + + template <typename Tuple> + auto rowsToTuples(const Rows &rows) { + std::vector<Tuple> result; + if (rows.empty()) { + return result; + } + if (rows.back().size() != std::tuple_size<Tuple>::value) { + throw TestError() << "Column count not match: " + << rows.back().size() << " vs. " + << std::tuple_size<Tuple>::value; + } + for (auto &row : rows) { + result.emplace_back(rowToTuple<Tuple>(row)); + } + return result; + } + + template <typename Tuple> + AssertionResult verifyResult(const cpp2::ExecutionResponse &resp, + std::vector<Tuple> &expected) { + if (resp.get_error_code() != cpp2::ErrorCode::SUCCEEDED) { + auto *errmsg = resp.get_error_msg(); + return TestError() << "Query failed with `" + << static_cast<int32_t>(resp.get_error_code()) + << (errmsg == nullptr ? "'" : "': " + *errmsg); + } + + std::vector<Tuple> rows; + try { + rows = rowsToTuples<Tuple>(respToRecords(resp)); + } catch (const AssertionResult &e) { + return e; + } catch (const std::exception &e) { + return TestError() << "Unknown exception thrown: " << e.what(); + } + + if (expected.size() != rows.size()) { + return TestError() << "Rows' count not match: " + << rows.size() << " vs. " << expected.size(); + } + + if (expected.empty()) { + return TestOK(); + } + + std::sort(rows.begin(), rows.end()); + std::sort(expected.begin(), expected.end()); + + for (auto i = 0u; i < rows.size(); i++) { + if (rows[i] != expected[i]) { + return TestError() << rows[i] << " vs. " << expected[i]; + } + } + return TestOK(); + } + +protected: + std::function<AssertionResult()> TestOK = [] { return ::testing::AssertionSuccess(); }; + std::function<AssertionResult()> TestError = [] { return ::testing::AssertionFailure(); }; +}; + +} // namespace graph +} // namespace nebula + +#endif // GRAPH_TEST_TESTBASE_H_ diff --git a/src/executor/test/TestEnv.cpp b/src/executor/test/TestEnv.cpp new file mode 100644 index 00000000..647503ae --- /dev/null +++ b/src/executor/test/TestEnv.cpp @@ -0,0 +1,69 @@ +/* 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 "graph/test/TestEnv.h" + +namespace nebula { +namespace graph { + + +TestEnv *gEnv = nullptr; + +TestEnv::TestEnv() { +} + + +TestEnv::~TestEnv() { +} + + +void TestEnv::SetUp() { + auto interface = std::make_shared<GraphService>(); + using ThriftServer = apache::thrift::ThriftServer; + server_ = std::make_unique<ThriftServer>(); + server_->setInterface(std::move(interface)); + server_->setPort(0); // Let the system choose an available port for us + + auto serve = [this] { + server_->serve(); + }; + + thread_ = std::make_unique<thread::NamedThread>("", serve); + // busy waiting for `thread_' to enter the loop + while (!server_->getServeEventBase() || !server_->getServeEventBase()->isRunning()) { + ; + } +} + + +void TestEnv::TearDown() { + if (server_ != nullptr) { + server_->stop(); + } + if (thread_ != nullptr) { + thread_->join(); + } + server_ = nullptr; + thread_ = nullptr; +} + + +uint16_t TestEnv::serverPort() const { + return server_->getAddress().getPort(); +} + + +std::unique_ptr<GraphClient> TestEnv::getClient() const { + auto client = std::make_unique<GraphClient>("127.0.0.1", serverPort()); + if (cpp2::ErrorCode::SUCCEEDED != client->connect("user", "password")) { + return nullptr; + } + return client; +} + +} // namespace graph +} // namespace nebula diff --git a/src/executor/test/TestEnv.h b/src/executor/test/TestEnv.h new file mode 100644 index 00000000..52727aa4 --- /dev/null +++ b/src/executor/test/TestEnv.h @@ -0,0 +1,51 @@ +/* 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 GRAPH_TEST_TESTENV_H_ +#define GRAPH_TEST_TESTENV_H_ + +#include "base/Base.h" +#include <gtest/gtest.h> +#include "thread/NamedThread.h" +#include <thrift/lib/cpp2/server/ThriftServer.h> +#include "graph/GraphService.h" +#include "client/cpp/GraphClient.h" + +namespace apache { +namespace thrift { +class ThriftServer; +} +} + +namespace nebula { +namespace graph { + +class GraphClient; +class TestEnv : public ::testing::Environment { +public: + TestEnv(); + virtual ~TestEnv(); + + void SetUp() override; + + void TearDown() override; + // Obtain the system assigned listening port + uint16_t serverPort() const; + + std::unique_ptr<GraphClient> getClient() const; + +private: + std::unique_ptr<apache::thrift::ThriftServer> server_; + std::unique_ptr<thread::NamedThread> thread_; +}; + + +extern TestEnv *gEnv; + +} // namespace graph +} // namespace nebula + +#endif // GRAPH_TEST_TESTENV_H_ diff --git a/src/executor/test/TestMain.cpp b/src/executor/test/TestMain.cpp new file mode 100644 index 00000000..082415bf --- /dev/null +++ b/src/executor/test/TestMain.cpp @@ -0,0 +1,21 @@ +/* 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 <gtest/gtest.h> +#include "graph/test/TestEnv.h" + +using namespace nebula::graph; + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + folly::init(&argc, &argv, true); + + gEnv = new TestEnv(); // gtest will delete this env object for us + ::testing::AddGlobalTestEnvironment(gEnv); + + return RUN_ALL_TESTS(); +} diff --git a/src/parser/.gitignore b/src/parser/.gitignore index 8ca6e678..11b3d6df 100644 --- a/src/parser/.gitignore +++ b/src/parser/.gitignore @@ -1,6 +1,6 @@ -VGraphParser.cpp -VGraphParser.hpp -VGraphScanner.cpp +GraphParser.cpp +GraphParser.hpp +GraphScanner.cpp location.hh position.hh stack.hh diff --git a/src/parser/CMakeLists.txt b/src/parser/CMakeLists.txt index d1b72c97..ab231294 100644 --- a/src/parser/CMakeLists.txt +++ b/src/parser/CMakeLists.txt @@ -1,11 +1,13 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}) include_directories(${CMAKE_CURRENT_BINARY_DIR}) -bison_target(Parser parser.yy ${CMAKE_CURRENT_BINARY_DIR}/VGraphParser.cpp COMPILE_FLAGS "-Werror") -flex_target(Scanner scanner.lex ${CMAKE_CURRENT_BINARY_DIR}/VGraphScanner.cpp) +bison_target(Parser parser.yy ${CMAKE_CURRENT_BINARY_DIR}/GraphParser.cpp COMPILE_FLAGS "-Werror") +flex_target(Scanner scanner.lex ${CMAKE_CURRENT_BINARY_DIR}/GraphScanner.cpp) add_flex_bison_dependency(Scanner Parser) +add_compile_options(-Wno-error=sign-compare) + add_library( parser_obj OBJECT diff --git a/src/parser/Clauses.cpp b/src/parser/Clauses.cpp index b50e7467..7330d18b 100644 --- a/src/parser/Clauses.cpp +++ b/src/parser/Clauses.cpp @@ -7,7 +7,7 @@ #include "base/Base.h" #include "parser/Clauses.h" -namespace vesoft { +namespace nebula { std::string StepClause::toString() const { @@ -110,4 +110,4 @@ std::string YieldClause::toString() const { return buf; } -} // namespace vesoft +} // namespace nebula diff --git a/src/parser/Clauses.h b/src/parser/Clauses.h index 78322653..24f7562e 100644 --- a/src/parser/Clauses.h +++ b/src/parser/Clauses.h @@ -9,7 +9,7 @@ #include "base/Base.h" #include "parser/Expressions.h" -namespace vesoft { +namespace nebula { class StepClause final { public: diff --git a/src/parser/CompoundSentence.cpp b/src/parser/CompoundSentence.cpp index cc161da3..b1ad2c42 100644 --- a/src/parser/CompoundSentence.cpp +++ b/src/parser/CompoundSentence.cpp @@ -7,7 +7,7 @@ #include "base/Base.h" #include "parser/CompoundSentence.h" -namespace vesoft { +namespace nebula { std::string CompoundSentence::toString() const { std::string buf; @@ -21,4 +21,4 @@ std::string CompoundSentence::toString() const { return buf; } -} // namespace vesoft +} // namespace nebula diff --git a/src/parser/CompoundSentence.h b/src/parser/CompoundSentence.h index 8b8e82da..01f277ee 100644 --- a/src/parser/CompoundSentence.h +++ b/src/parser/CompoundSentence.h @@ -11,9 +11,9 @@ #include "parser/TraverseSentences.h" #include "parser/MutateSentences.h" -namespace vesoft { +namespace nebula { -namespace vgraph { +namespace graph { class CompoundExecutor; } @@ -30,11 +30,11 @@ public: std::string toString() const; private: - friend class vesoft::vgraph::CompoundExecutor; + friend class nebula::graph::CompoundExecutor; std::vector<std::unique_ptr<Sentence>> sentences_; }; -} // namespace vesoft +} // namespace nebula #endif // PARSER_COMPOUNDSENTENCE_H_ diff --git a/src/parser/Expressions.cpp b/src/parser/Expressions.cpp index 3dec79a3..fe48344c 100644 --- a/src/parser/Expressions.cpp +++ b/src/parser/Expressions.cpp @@ -7,7 +7,7 @@ #include "base/Base.h" #include "parser/Expressions.h" -namespace vesoft { +namespace nebula { void ExpressionContext::print() const { for (auto &entry : aliasInfo_) { @@ -899,4 +899,4 @@ Status LogicalExpression::prepare(ExpressionContext *context) { return Status::OK(); } -} // namespace vesoft +} // namespace nebula diff --git a/src/parser/Expressions.h b/src/parser/Expressions.h index 5bbefdf3..a52457e6 100644 --- a/src/parser/Expressions.h +++ b/src/parser/Expressions.h @@ -10,7 +10,7 @@ #include "base/Status.h" #include <boost/variant.hpp> -namespace vesoft { +namespace nebula { enum ColumnType { INT8, INT16, INT32, INT64, @@ -767,6 +767,6 @@ private: std::unique_ptr<Expression> right_; }; -} // namespace vesoft +} // namespace nebula #endif // PARSER_EXPRESSIONS_H_ diff --git a/src/parser/GQLParser.cpp b/src/parser/GQLParser.cpp index f1f17641..bb291d2b 100644 --- a/src/parser/GQLParser.cpp +++ b/src/parser/GQLParser.cpp @@ -7,6 +7,6 @@ #include "base/Base.h" #include "GQLParser.h" -namespace vesoft { -} // namespace vesoft +namespace nebula { +} // namespace nebula diff --git a/src/parser/GQLParser.h b/src/parser/GQLParser.h index 9be210f1..a75472d0 100644 --- a/src/parser/GQLParser.h +++ b/src/parser/GQLParser.h @@ -8,10 +8,10 @@ #include "base/Base.h" #include "base/StatusOr.h" -#include "VGraphParser.hpp" -#include "VGraphScanner.h" +#include "GraphParser.hpp" +#include "GraphScanner.h" -namespace vesoft { +namespace nebula { class GQLParser { public: @@ -37,12 +37,12 @@ public: } private: - vesoft::VGraphScanner scanner_; - vesoft::VGraphParser parser_; + nebula::GraphScanner scanner_; + nebula::GraphParser parser_; std::string error_; CompoundSentence *compound_ = nullptr; }; -} // namespace vesoft +} // namespace nebula #endif // PARSER_GQLPARSER_H_ diff --git a/src/parser/VGraphScanner.h b/src/parser/GraphScanner.h similarity index 53% rename from src/parser/VGraphScanner.h rename to src/parser/GraphScanner.h index bbd7e510..1b3774be 100644 --- a/src/parser/VGraphScanner.h +++ b/src/parser/GraphScanner.h @@ -3,8 +3,8 @@ * This source code is licensed under Apache 2.0 License * (found in the LICENSE.Apache file in the root directory) */ -#ifndef PARSER_VGRAPHSCANNER_H_ -#define PARSER_VGRAPHSCANNER_H_ +#ifndef PARSER_GRAPHSCANNER_H_ +#define PARSER_GRAPHSCANNER_H_ #include "base/Base.h" @@ -15,16 +15,16 @@ // Override the interface for yylex since we namespaced it #undef YY_DECL -#define YY_DECL int vesoft::VGraphScanner::yylex() +#define YY_DECL int nebula::GraphScanner::yylex() -#include "VGraphParser.hpp" +#include "GraphParser.hpp" -namespace vesoft { +namespace nebula { -class VGraphScanner : public yyFlexLexer { +class GraphScanner : public yyFlexLexer { public: - int yylex(vesoft::VGraphParser::semantic_type * lval, - vesoft::VGraphParser::location_type *loc) { + int yylex(nebula::GraphParser::semantic_type * lval, + nebula::GraphParser::location_type *loc) { yylval = lval; yylloc = loc; return yylex(); @@ -35,10 +35,10 @@ private: friend class Scanner_Basic_Test; int yylex(); - vesoft::VGraphParser::semantic_type * yylval{nullptr}; - vesoft::VGraphParser::location_type * yylloc{nullptr}; + nebula::GraphParser::semantic_type * yylval{nullptr}; + nebula::GraphParser::location_type * yylloc{nullptr}; }; -} // namespace vesoft +} // namespace nebula -#endif // PARSER_VGRAPHSCANNER_H_ +#endif // PARSER_GRAPHSCANNER_H_ diff --git a/src/parser/MaintainSentences.cpp b/src/parser/MaintainSentences.cpp index 8f287410..ad26a639 100644 --- a/src/parser/MaintainSentences.cpp +++ b/src/parser/MaintainSentences.cpp @@ -7,7 +7,7 @@ #include "base/Base.h" #include "parser/MaintainSentences.h" -namespace vesoft { +namespace nebula { std::string DefineTagSentence::toString() const { std::string buf; @@ -110,4 +110,4 @@ std::string DescribeEdgeSentence::toString() const { return buf; } -} // namespace vesoft +} // namespace nebula diff --git a/src/parser/MaintainSentences.h b/src/parser/MaintainSentences.h index eae4aaa5..cf4c5e29 100644 --- a/src/parser/MaintainSentences.h +++ b/src/parser/MaintainSentences.h @@ -10,7 +10,7 @@ #include "parser/Clauses.h" #include "parser/Sentence.h" -namespace vesoft { +namespace nebula { class ColumnSpecification final { public: @@ -216,6 +216,6 @@ private: std::unique_ptr<std::string> name_; }; -} // namespace vesoft +} // namespace nebula #endif // PARSER_MAINTAINSENTENCES_H_ diff --git a/src/parser/MutateSentences.cpp b/src/parser/MutateSentences.cpp index 8914310a..1bd3a55c 100644 --- a/src/parser/MutateSentences.cpp +++ b/src/parser/MutateSentences.cpp @@ -7,7 +7,7 @@ #include "base/Base.h" #include "parser/MutateSentences.h" -namespace vesoft { +namespace nebula { std::string PropertyList::toString() const { std::string buf; @@ -139,4 +139,4 @@ std::string UpdateEdgeSentence::toString() const { return buf; } -} // namespace vesoft +} // namespace nebula diff --git a/src/parser/MutateSentences.h b/src/parser/MutateSentences.h index 95c5dc70..c92dfa14 100644 --- a/src/parser/MutateSentences.h +++ b/src/parser/MutateSentences.h @@ -10,7 +10,7 @@ #include "parser/Clauses.h" #include "parser/Sentence.h" -namespace vesoft { +namespace nebula { class PropertyList final { public: @@ -267,6 +267,6 @@ private: std::unique_ptr<YieldClause> yieldClause_; }; -} // namespace vesoft +} // namespace nebula #endif // PARSER_MUTATESENTENCES_H_ diff --git a/src/parser/README.md b/src/parser/README.md new file mode 100644 index 00000000..07dd0c5c --- /dev/null +++ b/src/parser/README.md @@ -0,0 +1 @@ +# Overview diff --git a/src/parser/Sentence.h b/src/parser/Sentence.h index 06a838d5..50a38ab2 100644 --- a/src/parser/Sentence.h +++ b/src/parser/Sentence.h @@ -9,7 +9,7 @@ #include "base/Base.h" #include "parser/Expressions.h" -namespace vesoft { +namespace nebula { class Sentence { public: @@ -46,6 +46,6 @@ inline std::ostream& operator<<(std::ostream &os, Sentence::Kind kind) { return os << static_cast<uint32_t>(kind); } -} // namespace vesoft +} // namespace nebula #endif // PARSER_SENTENCE_H_ diff --git a/src/parser/TraverseSentences.cpp b/src/parser/TraverseSentences.cpp index 0c6e7e44..671a29e8 100644 --- a/src/parser/TraverseSentences.cpp +++ b/src/parser/TraverseSentences.cpp @@ -7,7 +7,7 @@ #include "base/Base.h" #include "parser/TraverseSentences.h" -namespace vesoft { +namespace nebula { std::string GoSentence::toString() const { std::string buf; @@ -84,4 +84,4 @@ std::string AssignmentSentence::toString() const { return buf; } -} // namespace vesoft +} // namespace nebula diff --git a/src/parser/TraverseSentences.h b/src/parser/TraverseSentences.h index c86f4aec..772fb353 100644 --- a/src/parser/TraverseSentences.h +++ b/src/parser/TraverseSentences.h @@ -10,7 +10,7 @@ #include "parser/Sentence.h" #include "parser/Clauses.h" -namespace vesoft { +namespace nebula { class GoSentence final : public Sentence { public: @@ -159,6 +159,6 @@ private: }; -} // namespace vesoft +} // namespace nebula #endif // PARSER_TRAVERSESENTENCES_H_ diff --git a/src/parser/parser.yy b/src/parser/parser.yy index ecad4072..ef61efb1 100644 --- a/src/parser/parser.yy +++ b/src/parser/parser.yy @@ -2,12 +2,12 @@ %skeleton "lalr1.cc" %no-lines %locations -%define api.namespace { vesoft } -%define parser_class_name { VGraphParser } -%lex-param { vesoft::VGraphScanner& scanner } -%parse-param { vesoft::VGraphScanner& scanner } +%define api.namespace { nebula } +%define parser_class_name { GraphParser } +%lex-param { nebula::GraphScanner& scanner } +%parse-param { nebula::GraphScanner& scanner } %parse-param { std::string &errmsg } -%parse-param { vesoft::CompoundSentence** compound } +%parse-param { nebula::CompoundSentence** compound } %code requires { #include <iostream> @@ -15,18 +15,18 @@ #include <string> #include "parser/CompoundSentence.h" -namespace vesoft { +namespace nebula { -class VGraphScanner; +class GraphScanner; } } %code { - static int yylex(vesoft::VGraphParser::semantic_type* yylval, - vesoft::VGraphParser::location_type *yylloc, - vesoft::VGraphScanner& scanner); + static int yylex(nebula::GraphParser::semantic_type* yylval, + nebula::GraphParser::location_type *yylloc, + nebula::GraphScanner& scanner); } %union { @@ -34,26 +34,26 @@ class VGraphScanner; uint64_t intval; double doubleval; std::string *strval; - vesoft::Expression *expr; - vesoft::Sentence *sentence; - vesoft::CompoundSentence *compound; - vesoft::ColumnSpecification *colspec; - vesoft::ColumnSpecificationList *colspeclist; - vesoft::ColumnType type; - vesoft::StepClause *step_clause; - vesoft::FromClause *from_clause; - vesoft::SourceNodeList *src_node_list; - vesoft::OverClause *over_clause; - vesoft::EdgeList *edge_list; - vesoft::EdgeItem *edge_item; - vesoft::WhereClause *where_clause; - vesoft::YieldClause *yield_clause; - vesoft::YieldColumns *yield_columns; - vesoft::YieldColumn *yield_column; - vesoft::PropertyList *prop_list; - vesoft::ValueList *value_list; - vesoft::UpdateList *update_list; - vesoft::UpdateItem *update_item; + nebula::Expression *expr; + nebula::Sentence *sentence; + nebula::CompoundSentence *compound; + nebula::ColumnSpecification *colspec; + nebula::ColumnSpecificationList *colspeclist; + nebula::ColumnType type; + nebula::StepClause *step_clause; + nebula::FromClause *from_clause; + nebula::SourceNodeList *src_node_list; + nebula::OverClause *over_clause; + nebula::EdgeList *edge_list; + nebula::EdgeItem *edge_item; + nebula::WhereClause *where_clause; + nebula::YieldClause *yield_clause; + nebula::YieldColumns *yield_columns; + nebula::YieldColumn *yield_column; + nebula::PropertyList *prop_list; + nebula::ValueList *value_list; + nebula::UpdateList *update_list; + nebula::UpdateItem *update_item; } /* keywords */ %token KW_GO KW_AS KW_TO KW_OR KW_USE KW_SET KW_FROM KW_WHERE KW_ALTER @@ -770,17 +770,17 @@ compound %% -void vesoft::VGraphParser::error(const vesoft::VGraphParser::location_type& loc, - const std::string &msg) { +void nebula::GraphParser::error(const nebula::GraphParser::location_type& loc, + const std::string &msg) { std::ostringstream os; os << msg << " at " << loc; errmsg = os.str(); } -#include "VGraphScanner.h" -static int yylex(vesoft::VGraphParser::semantic_type* yylval, - vesoft::VGraphParser::location_type *yylloc, - vesoft::VGraphScanner& scanner) { +#include "GraphScanner.h" +static int yylex(nebula::GraphParser::semantic_type* yylval, + nebula::GraphParser::location_type *yylloc, + nebula::GraphScanner& scanner) { return scanner.yylex(yylval, yylloc); } diff --git a/src/parser/scanner.lex b/src/parser/scanner.lex index 97c21826..d7c00001 100644 --- a/src/parser/scanner.lex +++ b/src/parser/scanner.lex @@ -1,17 +1,17 @@ %option c++ -%option yyclass="VGraphScanner" +%option yyclass="GraphScanner" %option nodefault noyywrap %option never-interactive %option yylineno %{ #include "parser/GQLParser.h" -#include "parser/VGraphScanner.h" -#include "VGraphParser.hpp" +#include "parser/GraphScanner.h" +#include "GraphParser.hpp" #define YY_USER_ACTION yylloc->columns(yyleng); -using TokenType = vesoft::VGraphParser::token; +using TokenType = nebula::GraphParser::token; static constexpr size_t MAX_STRING = 4096; diff --git a/src/parser/test/ParserTest.cpp b/src/parser/test/ParserTest.cpp index 548a8b20..ccb77b4a 100644 --- a/src/parser/test/ParserTest.cpp +++ b/src/parser/test/ParserTest.cpp @@ -10,7 +10,7 @@ // TODO(dutor) Inspect the internal structures to check on the syntax and semantics -namespace vesoft { +namespace nebula { TEST(Parser, Go) { { @@ -272,4 +272,4 @@ TEST(Parser, UpdateEdge) { } } -} // namespace vesoft +} // namespace nebula diff --git a/src/parser/test/ScannerTest.cpp b/src/parser/test/ScannerTest.cpp index 3b4f2b99..9ff9fa0b 100644 --- a/src/parser/test/ScannerTest.cpp +++ b/src/parser/test/ScannerTest.cpp @@ -9,15 +9,15 @@ #include <sstream> #include <vector> #include <utility> -#include "parser/VGraphParser.hpp" -#include "parser/VGraphScanner.h" +#include "parser/GraphParser.hpp" +#include "parser/GraphScanner.h" using namespace ::testing; // TODO(dutor) Check on the sematic value of tokens -namespace vesoft { +namespace nebula { -using semantic_type = vesoft::VGraphParser::semantic_type; +using semantic_type = nebula::GraphParser::semantic_type; static auto checkSemanticValue(const char *expected, semantic_type *sv) { auto &actual = *sv->strval; if (expected != actual) { @@ -67,11 +67,11 @@ checkSemanticValue(T expected, semantic_type *sv) { TEST(Scanner, Basic) { - using TokenType = vesoft::VGraphParser::token_type; + using TokenType = nebula::GraphParser::token_type; using Validator = std::function<::testing::AssertionResult()>; - vesoft::VGraphParser::semantic_type yylval; - vesoft::VGraphParser::location_type yyloc; - VGraphScanner scanner; + nebula::GraphParser::semantic_type yylval; + nebula::GraphParser::location_type yyloc; + GraphScanner scanner; std::string stream; #define CHECK_SEMANTIC_TYPE(STR, TYPE) \ @@ -239,4 +239,4 @@ TEST(Scanner, Basic) { } } -} // namespace vesoft +} // namespace nebula -- GitLab