diff --git a/.github/workflows/flex.yml b/.github/workflows/flex.yml index 297c63a01748..3dcc04a06099 100644 --- a/.github/workflows/flex.yml +++ b/.github/workflows/flex.yml @@ -46,4 +46,13 @@ jobs: run: | cd ${GITHUB_WORKSPACE}/flex mkdir build && cd build - cmake .. && sudo make -j$(nproc) \ No newline at end of file + cmake .. && sudo make -j$(nproc) + + - name: GRIN on mutable csr test + run: | + git submodule update --init + cd flex/engines/graph_db/grin + mkdir build && cd build + cmake .. && sudo make -j$(nproc) + export FLEX_DATA_DIR=../../../../storages/rt_mutable_graph/modern_graph/ + ./run_grin_test diff --git a/.gitmodules b/.gitmodules index f038d8b178ac..dabe493f60bd 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,7 @@ [submodule "learning_engine/graph-learn"] path = learning_engine/graph-learn url = https://github.com/alibaba/graph-learn.git + +[submodule "flex/grin"] + path = flex/grin + url = https://github.com/GraphScope/GRIN.git diff --git a/flex/engines/graph_db/database/transaction_utils.h b/flex/engines/graph_db/database/transaction_utils.h index 68aa215bca64..f219414f15ec 100644 --- a/flex/engines/graph_db/database/transaction_utils.h +++ b/flex/engines/graph_db/database/transaction_utils.h @@ -39,6 +39,9 @@ inline void serialize_field(grape::InArchive& arc, const Any& prop) { case PropertyType::kInt64: arc << prop.value.l; break; + case PropertyType::kDouble: + arc << prop.value.db; + break; default: LOG(FATAL) << "Unexpected property type"; } @@ -60,6 +63,9 @@ inline void deserialize_field(grape::OutArchive& arc, Any& prop) { case PropertyType::kInt64: arc >> prop.value.l; break; + case PropertyType::kDouble: + arc >> prop.value.db; + break; default: LOG(FATAL) << "Unexpected property type"; } diff --git a/flex/engines/graph_db/grin/CMakeLists.txt b/flex/engines/graph_db/grin/CMakeLists.txt new file mode 100644 index 000000000000..3a066292b992 --- /dev/null +++ b/flex/engines/graph_db/grin/CMakeLists.txt @@ -0,0 +1,69 @@ +cmake_minimum_required(VERSION 3.1) + +set(GRIN_READER_MAJOR_VERSION 0) +set(GRIN_READER_MINOR_VERSION 1) +set(GRIN_READER_VERSION ${GRIN_READER_MAJOR_VERSION}.${GRIN_READER_MINOR_VERSION}) + +project(grin_reader LANGUAGES C CXX VERSION ${GRIN_READER_VERSION}) + +# Set flags +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99") + +# ------------------------------------------------------------------------------ +# find_libraries +# ------------------------------------------------------------------------------ + +find_package(libgrapelite REQUIRED) +include_directories(${LIBGRAPELITE_INCLUDE_DIRS}) + +include("../../../../flex/cmake/FindGFlags.cmake") +if (GFLAGS_FOUND) + include_directories(SYSTEM ${GFLAGS_INCLUDE_DIRS}) +else () + message(FATAL_ERROR "gflags not found") +endif () + +include("../../../../flex/cmake/FindGlog.cmake") +include_directories(SYSTEM ${GLOG_INCLUDE_DIRS}) +if (GLOG_FOUND) + set(CMAKE_REQUIRED_INCLUDES "${GLOG_INCLUDE_DIRS}") + set(CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES} ${GLOG_LIBRARIES}") +endif () + +find_package(yaml-cpp REQUIRED) +include_directories(SYSTEM ${yaml-cpp_INCLUDE_DIRS}) + +#set(yaml-cpp_INCLUDE_DIRS "/usr/local/Cellar/yaml-cpp/0.7.0/include") +#include_directories(SYSTEM ${yaml-cpp_INCLUDE_DIRS}) +#set(YAML_CPP_LIBRARIES "/usr/local/Cellar/yaml-cpp/0.7.0/lib/libyaml-cpp.0.7.0.dylib") + + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../..) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../..) +message(STATUS "${CMAKE_CURRENT_SOURCE_DIR}") +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../storages/rt_mutable_graph) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../utils/property) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) + +file(GLOB_RECURSE FILES_NEED_FORMAT "src/*.cc") + +add_custom_target(grin_clformat + COMMAND clang-format --style=file -i ${FILES_NEED_FORMAT} + COMMENT "Running clang-format." + VERBATIM) + +file(GLOB SOURCES "src/*.cc" "src/topology/*.cc" "src/property/*.cc" "src/index/*.cc" "src/common/*.cc" "../../../utils/property/*.cc" "../../../storages/rt_mutable_graph/*.cc") +add_library(flex_grin SHARED ${SOURCES}) +target_link_libraries(flex_grin ${LIBGRAPELITE_LIBRARIES} ${GFLAGS_LIBRARIES} ${CMAKE_DL_LIBS} ${YAML_CPP_LIBRARIES}) + + +add_executable(run_grin_test test/test.c) + +target_include_directories(run_grin_test PRIVATE ${LIBGRAPELITE_INCLUDE_DIRS}/grape/analytical_apps fragment) +target_link_libraries(run_grin_test flex_grin ${LIBGRAPELITE_LIBRARIES} ${GFLAGS_LIBRARIES} ${CMAKE_DL_LIBS}) +target_link_libraries(run_grin_test) diff --git a/flex/engines/graph_db/grin/predefine.h b/flex/engines/graph_db/grin/predefine.h new file mode 100644 index 000000000000..85578a8c4a8c --- /dev/null +++ b/flex/engines/graph_db/grin/predefine.h @@ -0,0 +1,296 @@ +/** Copyright 2020 Alibaba Group Holding Limited. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +/** + * @file predefine.h + * @brief This template file consists of four parts: + * 1. The predefined enumerate types of GRIN, which should NOT be modified. + * 2. The supported macros which should be specified by storage implementors + * based on storage features. + * 3. The typedefs of the enabled handles. This should be specified by storage. + * 4. The corresponding null values of the enabled handles. This should be + * specified by storage. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +/* 1. Predefined enumerate types of GRIN */ +/// Enumerates the directions of edges with respect to a certain vertex +typedef enum { + IN = 0, ///< incoming + OUT = 1, ///< outgoing + BOTH = 2, ///< incoming & outgoing +} GRIN_DIRECTION; + +/// Enumerates the datatype supported in the storage +typedef enum { + Undefined = 0, ///< other unknown types + Int32 = 1, ///< int + UInt32 = 2, ///< unsigned int + Int64 = 3, ///< long int + UInt64 = 4, ///< unsigned long int + Float = 5, ///< float + Double = 6, ///< double + String = 7, ///< string + Date32 = 8, ///< date + Time32 = 9, ///< Time32 + Timestamp64 = 10, ///< Timestamp +} GRIN_DATATYPE; + +/// Enumerates the error codes of grin +typedef enum { + NO_ERROR = 0, ///< success + UNKNOWN_ERROR = 1, ///< unknown error + INVALID_VALUE = 2, ///< invalid value + UNKNOWN_DATATYPE = 3, ///< unknown datatype +} GRIN_ERROR_CODE; + +/* 2. Define supported macros based on storage features */ +// Topology +#define GRIN_ASSUME_HAS_DIRECTED_GRAPH +#define GRIN_ASSUME_HAS_UNDIRECTED_GRAPH +#define GRIN_ASSUME_HAS_MULTI_EDGE_GRAPH +// #define GRIN_WITH_VERTEX_DATA +#define GRIN_WITH_EDGE_DATA +#define GRIN_ENABLE_VERTEX_LIST +// #define GRIN_ENABLE_VERTEX_LIST_ARRAY +#define GRIN_ENABLE_VERTEX_LIST_ITERATOR +#define GRIN_ENABLE_EDGE_LIST +// #define GRIN_ENABLE_EDGE_LIST_ARRAY +#define GRIN_ENABLE_EDGE_LIST_ITERATOR +#define GRIN_ENABLE_ADJACENT_LIST +// #define GRIN_ENABLE_ADJACENT_LIST_ARRAY +#define GRIN_ENABLE_ADJACENT_LIST_ITERATOR + +// Partition +/** +#define GRIN_ENABLE_GRAPH_PARTITION +#define GRIN_TRAIT_NATURAL_ID_FOR_PARTITION +#define GRIN_ENABLE_VERTEX_REF +#define GRIN_TRAIT_FAST_VERTEX_REF +#define GRIN_ENABLE_EDGE_REF +#define GRIN_ASSUME_ALL_REPLICATE_PARTITION +#define GRIN_ASSUME_EDGE_CUT_PARTITION +#define GRIN_ASSUME_EDGE_CUT_FOLLOW_SRC_PARTITION +#define GRIN_ASSUME_EDGE_CUT_FOLLOW_DST_PARTITION +#define GRIN_ASSUME_VERTEX_CUT_PARTITION +#define GRIN_ASSUME_MASTER_ONLY_PARTITION_FOR_VERTEX_DATA +#define GRIN_ASSUME_REPLICATE_MASTER_MIRROR_PARTITION_FOR_VERTEX_DATA +#define GRIN_ASSUME_MASTER_ONLY_PARTITION_FOR_EDGE_DATA +#define GRIN_ASSUME_REPLICATE_MASTER_MIRROR_PARTITION_FOR_EDGE_DATA +#define GRIN_TRAIT_MASTER_VERTEX_MIRROR_PARTITION_LIST +#define GRIN_TRAIT_MIRROR_VERTEX_MIRROR_PARTITION_LIST +#define GRIN_TRAIT_MASTER_EDGE_MIRROR_PARTITION_LIST +#define GRIN_TRAIT_MIRROR_EDGE_MIRROR_PARTITION_LIST +#define GRIN_TRAIT_SELECT_MASTER_FOR_VERTEX_LIST +#define GRIN_TRAIT_SELECT_PARTITION_FOR_VERTEX_LIST +#define GRIN_TRAIT_SELECT_MASTER_FOR_EDGE_LIST +#define GRIN_TRAIT_SELECT_PARTITION_FOR_EDGE_LIST +#define GRIN_TRAIT_SELECT_MASTER_NEIGHBOR_FOR_ADJACENT_LIST +#define GRIN_TRAIT_SELECT_NEIGHBOR_PARTITION_FOR_ADJACENT_LIST +*/ + +// Property +#define GRIN_ENABLE_ROW +#define GRIN_TRAIT_CONST_VALUE_PTR +#define GRIN_WITH_VERTEX_PROPERTY +#define GRIN_WITH_VERTEX_PROPERTY_NAME +#define GRIN_WITH_VERTEX_TYPE_NAME +#define GRIN_TRAIT_NATURAL_ID_FOR_VERTEX_TYPE +#define GRIN_ENABLE_VERTEX_PRIMARY_KEYS +#define GRIN_TRAIT_NATURAL_ID_FOR_VERTEX_PROPERTY +#define GRIN_WITH_EDGE_PROPERTY +// #define GRIN_WITH_EDGE_PROPERTY_NAME +#define GRIN_WITH_EDGE_TYPE_NAME +#define GRIN_TRAIT_NATURAL_ID_FOR_EDGE_TYPE +// #define GRIN_ENABLE_EDGE_PRIMARY_KEYS +// #define GRIN_TRAIT_NATURAL_ID_FOR_EDGE_PROPERTY +// #define GRIN_TRAIT_SPECIFIC_VEV_RELATION +// #define GRIN_ASSUME_MASTER_ONLY_PARTITION_FOR_VERTEX_PROPERTY +// #define GRIN_ASSUME_REPLICATE_MASTER_MIRROR_PARTITION_FOR_VERTEX_PROPERTY +// #define GRIN_ASSUME_SPLIT_MASTER_MIRROR_PARTITION_FOR_VERTEX_PROPERTY +// #define GRIN_ASSUME_MASTER_ONLY_PARTITION_FOR_EDGE_PROPERTY +// #define GRIN_ASSUME_REPLICATE_MASTER_MIRROR_PARTITION_FOR_EDGE_PROPERTY +// #define GRIN_ASSUME_SPLIT_MASTER_MIRROR_PARTITION_FOR_EDGE_PROPERTY +// Index +#define GRIN_WITH_VERTEX_LABEL +#define GRIN_WITH_EDGE_LABEL +/// #define GRIN_ASSUME_ALL_VERTEX_LIST_SORTED +#define GRIN_ENABLE_VERTEX_INTERNAL_ID_INDEX +#define GRIN_ENABLE_VERTEX_PK_INDEX +// #define GRIN_ENABLE_EDGE_PK_INDEX + +/* 3. Define the handles using typedef */ +typedef void* GRIN_GRAPH; +// label: 8, vid: 32 +typedef uint64_t GRIN_VERTEX; +typedef void* GRIN_EDGE; + +#ifdef GRIN_WITH_VERTEX_DATA +typedef void* GRIN_VERTEX_DATA; +#endif + +#ifdef GRIN_WITH_VERTEX_PROPERTY +typedef unsigned GRIN_VERTEX_TYPE; +typedef void* GRIN_VERTEX_TYPE_LIST; +// datatype: 8, vertex label: 8, property index:8 +typedef uint32_t GRIN_VERTEX_PROPERTY; + +typedef void* GRIN_VERTEX_PROPERTY_LIST; +#endif + +#ifdef GRIN_ENABLE_VERTEX_LIST +typedef struct GRIN_VERTEX_LIST { + size_t vertex_num; + GRIN_VERTEX_TYPE label; +} GRIN_VERTEX_LIST; +#endif + +#ifdef GRIN_ENABLE_VERTEX_LIST_ITERATOR +typedef struct GRIN_VERTEX_LIST_ITERATOR { + uint32_t* cur_vid; + GRIN_VERTEX_LIST vertex_list; +} GRIN_VERTEX_LIST_ITERATOR; +#endif + +#ifdef GRIN_WITH_EDGE_DATA +typedef void* GRIN_EDGE_DATA; +#endif + +#ifdef GRIN_ENABLE_EDGE_LIST +typedef void* GRIN_EDGE_LIST; +#endif + +#ifdef GRIN_ENABLE_EDGE_LIST_ITERATOR +typedef void* GRIN_EDGE_LIST_ITERATOR; +#endif + +/** +#ifdef GRIN_ENABLE_GRAPH_PARTITION +typedef void* GRIN_PARTITIONED_GRAPH; +typedef void* GRIN_PARTITION; +typedef void* GRIN_PARTITION_LIST; +#endif + +#ifdef GRIN_TRAIT_NATURAL_ID_FOR_PARTITION +typedef unsigned GRIN_PARTITION_ID; +#endif +*/ + +#ifdef GRIN_ENABLE_VERTEX_REF +typedef void* GRIN_VERTEX_REF; +#endif + +#ifdef GRIN_ENABLE_EDGE_REF +typedef void* GRIN_EDGE_REF; +#endif + +#ifdef GRIN_TRAIT_NATURAL_ID_FOR_VERTEX_TYPE +typedef unsigned GRIN_VERTEX_TYPE_ID; +#endif + +#ifdef GRIN_TRAIT_NATURAL_ID_FOR_VERTEX_PROPERTY +typedef unsigned GRIN_VERTEX_PROPERTY_ID; +#endif + +#ifdef GRIN_WITH_EDGE_PROPERTY +// src_label: 8, dst_label: 8, edge_label: 8 +typedef unsigned GRIN_EDGE_TYPE; +typedef void* GRIN_EDGE_TYPE_LIST; +// index: 8, src_label: 8, dst_label: 8, edge_label: 8 +typedef unsigned GRIN_EDGE_PROPERTY; +typedef void* GRIN_EDGE_PROPERTY_LIST; +#endif + +#ifdef GRIN_TRAIT_NATURAL_ID_FOR_EDGE_TYPE +typedef unsigned GRIN_EDGE_TYPE_ID; +#endif + +#ifdef GRIN_ENABLE_ADJACENT_LIST +typedef struct GRIN_ADJACENT_LIST { + GRIN_VERTEX v; + GRIN_DIRECTION dir; + GRIN_EDGE_TYPE edge_label; +} GRIN_ADJACENT_LIST; +#endif + +#ifdef GRIN_ENABLE_ADJACENT_LIST_ITERATOR +typedef struct GRIN_ADJACENT_LIST_ITERATOR { + // gs::MutableCsrConstEdgeIterBase* + void* edge_iter; + GRIN_ADJACENT_LIST adj_list; +} GRIN_ADJACENT_LIST_ITERATOR; +#endif + +#ifdef GRIN_TRAIT_NATURAL_ID_FOR_EDGE_PROPERTY +typedef unsigned GRIN_EDGE_PROPERTY_ID; +#endif + +#ifdef GRIN_ENABLE_ROW +typedef void* GRIN_ROW; +#endif + +#if defined(GRIN_WITH_VERTEX_LABEL) || defined(GRIN_WITH_EDGE_LABEL) +typedef void* GRIN_LABEL; +typedef void* GRIN_LABEL_LIST; +#endif + +/* 4. Define invalid values for returns of handles */ +#define GRIN_NULL_GRAPH NULL +#define GRIN_NULL_VERTEX (unsigned long long) ~0 +#define GRIN_NULL_EDGE NULL +#define GRIN_NULL_VERTEX_DATA NULL +#define GRIN_NULL_VERTEX_LIST NULL +#define GRIN_NULL_VERTEX_LIST_ITERATOR NULL +#define GRIN_NULL_ADJACENT_LIST NULL +#define GRIN_NULL_ADJACENT_LIST_ITERATOR NULL +#define GRIN_NULL_EDGE_DATA NULL +#define GRIN_NULL_EDGE_LIST NULL +#define GRIN_NULL_EDGE_LIST_ITERATOR NULL +#define GRIN_NULL_PARTITIONED_GRAPH NULL +#define GRIN_NULL_PARTITION NULL +#define GRIN_NULL_PARTITION_LIST NULL +#define GRIN_NULL_PARTITION_ID (unsigned) ~0 +#define GRIN_NULL_VERTEX_REF NULL +#define GRIN_NULL_EDGE_REF NULL +#define GRIN_NULL_VERTEX_TYPE (unsigned) ~0 +#define GRIN_NULL_VERTEX_TYPE_LIST NULL +#define GRIN_NULL_VERTEX_PROPERTY (unsigned) ~0 +#define GRIN_NULL_VERTEX_PROPERTY_LIST NULL +#define GRIN_NULL_VERTEX_TYPE_ID (unsigned) ~0 +#define GRIN_NULL_VERTEX_PROPERTY_ID (unsigned) ~0 +#define GRIN_NULL_EDGE_TYPE (unsigned) ~0 +#define GRIN_NULL_EDGE_TYPE_LIST NULL +#define GRIN_NULL_VEV_TYPE NULL +#define GRIN_NULL_VEV_TYPE_LIST NULL +#define GRIN_NULL_EDGE_PROPERTY NULL +#define GRIN_NULL_EDGE_PROPERTY_LIST NULL +#define GRIN_NULL_EDGE_TYPE_ID (unsigned) ~0 +#define GRIN_NULL_EDGE_PROPERTY_ID (unsigned) ~0 +#define GRIN_NULL_ROW NULL +#define GRIN_NULL_LABEL NULL +#define GRIN_NULL_LABEL_LIST NULL +#define GRIN_NULL_SIZE (unsigned) ~0 +#define GRIN_NULL_NAME NULL + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/flex/engines/graph_db/grin/src/common/error.cc b/flex/engines/graph_db/grin/src/common/error.cc new file mode 100644 index 000000000000..d910f0b74892 --- /dev/null +++ b/flex/engines/graph_db/grin/src/common/error.cc @@ -0,0 +1,24 @@ +/** Copyright 2020 Alibaba Group Holding Limited. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +/** + @file error.h + @brief Define the error code related APIs +*/ + +#include "grin/src/predefine.h" + +#include "grin/include/common/error.h" + +__thread GRIN_ERROR_CODE grin_error_code = GRIN_ERROR_CODE::NO_ERROR; + +GRIN_ERROR_CODE grin_get_last_error_code() { return grin_error_code; } \ No newline at end of file diff --git a/flex/engines/graph_db/grin/src/index/internal_id.cc b/flex/engines/graph_db/grin/src/index/internal_id.cc new file mode 100644 index 000000000000..923f5692d988 --- /dev/null +++ b/flex/engines/graph_db/grin/src/index/internal_id.cc @@ -0,0 +1,101 @@ +/** Copyright 2020 Alibaba Group Holding Limited. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include "grin/src/predefine.h" + +#include "grin/include/index/internal_id.h" + +#if defined(GRIN_ENABLE_VERTEX_INTERNAL_ID_INDEX) && \ + !defined(GRIN_WITH_VERTEX_PROPERTY) +/** + * @brief Get the int64 internal id of a vertex + * @param GRIN_GRAPH The graph + * @param GRIN_VERTEX The vertex + * @return The int64 internal id of the vertex + */ +long long int grin_get_vertex_internal_id(GRIN_GRAPH, GRIN_VERTEX); + +/** + * @brief Get the vertex by internal id. + * Different from pk_of_int64, the internal id is unique over all vertex types. + * @param GRIN_GRAPH The graph + * @param id The internal id of the vertex + * @return The vertex + */ +GRIN_VERTEX grin_get_vertex_by_internal_id(GRIN_GRAPH, long long int id); + +/** + * @brief Get the upper bound of internal id. + * @param GRIN_GRAPH The graph + * @return The upper bound + */ +long long int grin_get_vertex_internal_id_upper_bound(GRIN_GRAPH); + +/** + * @brief Get the lower bound of internal id. + * @param GRIN_GRAPH The graph + * @return The lower bound + */ +long long int grin_get_vertex_internal_id_lower_bound(GRIN_GRAPH); +#endif + +#if defined(GRIN_ENABLE_VERTEX_INTERNAL_ID_INDEX) && \ + defined(GRIN_WITH_VERTEX_PROPERTY) +/** + * @brief Get the int64 internal id of a vertex + * @param GRIN_GRAPH The graph + * @param GRIN_VERTEX The vertex + * @return The int64 internal id of the vertex + */ +long long int grin_get_vertex_internal_id_by_type(GRIN_GRAPH g, + GRIN_VERTEX_TYPE vt, + GRIN_VERTEX v) { + return v & (0xffffffff); +} + +/** + * @brief Get the vertex by internal id under type + * @param GRIN_GRAPH The graph + * @param GRIN_VERTEX_TYPE The vertex type + * @param id The internal id of the vertex under type + * @return The vertex + */ +GRIN_VERTEX grin_get_vertex_by_internal_id_by_type(GRIN_GRAPH g, + GRIN_VERTEX_TYPE vt, + long long int id) { + auto v = static_cast(vt); + return (v << 32) + id; +} + +/** + * @brief Get the upper bound of internal id under type. + * @param GRIN_GRAPH The graph + * @param GRIN_VERTEX_TYPE The vertex type + * @return The upper bound of internal id under type + */ +long long int grin_get_vertex_internal_id_upper_bound_by_type( + GRIN_GRAPH g, GRIN_VERTEX_TYPE vt) { + auto _g = static_cast(g); + return _g->g.vertex_num(vt); +} + +/** + * @brief Get the lower bound internal id under type. + * @param GRIN_GRAPH The graph + * @param GRIN_VERTEX_TYPE The vertex type + * @return The lower bound internal id under type + */ +long long int grin_get_vertex_internal_id_lower_bound_by_type( + GRIN_GRAPH g, GRIN_VERTEX_TYPE vt) { + return 0; +} +#endif \ No newline at end of file diff --git a/flex/engines/graph_db/grin/src/index/pk.cc b/flex/engines/graph_db/grin/src/index/pk.cc new file mode 100644 index 000000000000..6227edd46482 --- /dev/null +++ b/flex/engines/graph_db/grin/src/index/pk.cc @@ -0,0 +1,43 @@ +/** Copyright 2020 Alibaba Group Holding Limited. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include "grin/src/predefine.h" + +#include "grin/include/index/pk.h" + +#if defined(GRIN_ENABLE_VERTEX_PK_INDEX) && \ + defined(GRIN_ENABLE_VERTEX_PRIMARY_KEYS) +/** + * @brief Get the vertex by primary keys row. + * The values in the row must be in the same order as the primary keys + * properties, which can be obtained by + * ``grin_get_primary_keys_by_vertex_type``. + * @param GRIN_GRAPH The graph. + * @param GRIN_VERTEX_TYPE The vertex type. + * @param GRIN_ROW The values row of primary keys properties. + * @return The vertex. + */ +GRIN_VERTEX grin_get_vertex_by_primary_keys_row(GRIN_GRAPH g, + GRIN_VERTEX_TYPE label, + GRIN_ROW r) { + auto _r = static_cast(r); + auto _g = static_cast(g); + auto oid = *static_cast((*_r)[0]); + uint32_t vid; + + if (!_g->g.get_lid(label, oid, vid)) { + return GRIN_NULL_VERTEX; + } + uint64_t v = ((label * 1ull) << 32) + vid; + return v; +} +#endif \ No newline at end of file diff --git a/flex/engines/graph_db/grin/src/predefine.cc b/flex/engines/graph_db/grin/src/predefine.cc new file mode 100644 index 000000000000..75ee84d8e3b0 --- /dev/null +++ b/flex/engines/graph_db/grin/src/predefine.cc @@ -0,0 +1,53 @@ +#include "grin/src/predefine.h" + +GRIN_DATATYPE _get_data_type(const gs::PropertyType& type) { + if (type == gs::PropertyType::kInt32) { + return GRIN_DATATYPE::Int32; + } else if (type == gs::PropertyType::kInt64) { + return GRIN_DATATYPE::Int64; + } else if (type == gs::PropertyType::kString) { + return GRIN_DATATYPE::String; + } else if (type == gs::PropertyType::kDate) { + return GRIN_DATATYPE::Timestamp64; + } else if (type == gs::PropertyType::kDouble) { + return GRIN_DATATYPE::Double; + } else { + return GRIN_DATATYPE::Undefined; + } +} + +void init_cache(GRIN_GRAPH_T* g) { + auto v_label_num = g->g.vertex_label_num_; + for (size_t i = 0; i < v_label_num; ++i) { + std::vector tmp; + const auto& vec = g->g.schema().get_vertex_properties(i); + const auto& table = g->g.get_vertex_table(i); + for (size_t idx = 0; idx < vec.size(); ++idx) { + const auto& type = vec[idx]; + if (type == gs::PropertyType::kInt32) { + tmp.emplace_back(std::dynamic_pointer_cast( + table.get_column_by_id(idx)) + .get()); + } else if (type == gs::PropertyType::kInt64) { + tmp.emplace_back(std::dynamic_pointer_cast( + table.get_column_by_id(idx)) + .get()); + } else if (type == gs::PropertyType::kString) { + tmp.emplace_back(std::dynamic_pointer_cast( + table.get_column_by_id(idx)) + .get()); + } else if (type == gs::PropertyType::kDate) { + tmp.emplace_back(std::dynamic_pointer_cast( + table.get_column_by_id(idx)) + .get()); + } else if (type == gs::PropertyType::kDouble) { + tmp.emplace_back(std::dynamic_pointer_cast( + table.get_column_by_id(idx)) + .get()); + } else { + tmp.emplace_back((const void*) NULL); + } + } + g->vproperties.emplace_back(tmp); + } +} \ No newline at end of file diff --git a/flex/engines/graph_db/grin/src/predefine.h b/flex/engines/graph_db/grin/src/predefine.h new file mode 100644 index 000000000000..a04ccf186565 --- /dev/null +++ b/flex/engines/graph_db/grin/src/predefine.h @@ -0,0 +1,38 @@ +#include + +#include "grin/predefine.h" +#include "storages/rt_mutable_graph/mutable_property_fragment.h" + +typedef gs::oid_t GRIN_OID_T; +typedef gs::vid_t GRIN_VID_T; + +typedef struct GRIN_GRAPH_T { + gs::MutablePropertyFragment g; + std::vector> vproperties; + // std::vector> eproperties; +} GRIN_GRAPH_T; + +typedef struct GRIN_EDGE_T { + GRIN_VERTEX dst; + GRIN_VERTEX src; + GRIN_DIRECTION dir; + gs::label_t label; + gs::Any data; +} GRIN_EDGE_T; + +#ifdef GRIN_WITH_VERTEX_PROPERTY +typedef std::vector GRIN_VERTEX_TYPE_LIST_T; +typedef std::vector GRIN_VERTEX_PROPERTY_LIST_T; +#endif + +#if defined(GRIN_WITH_VERTEX_PROPERTY) || defined(GRIN_WITH_EDGE_PROPERTY) +typedef std::vector GRIN_ROW_T; +#endif + +#ifdef GRIN_WITH_EDGE_PROPERTY +typedef std::vector GRIN_EDGE_TYPE_LIST_T; +typedef std::vector GRIN_EDGE_PROPERTY_LIST_T; +#endif + +GRIN_DATATYPE _get_data_type(const gs::PropertyType& type); +void init_cache(GRIN_GRAPH_T* g); \ No newline at end of file diff --git a/flex/engines/graph_db/grin/src/property/primarykey.cc b/flex/engines/graph_db/grin/src/property/primarykey.cc new file mode 100644 index 000000000000..878fa0b2b32f --- /dev/null +++ b/flex/engines/graph_db/grin/src/property/primarykey.cc @@ -0,0 +1,57 @@ +#include "grin/src/predefine.h" + +#include "grin/include/common/error.h" +#include "grin/include/property/primarykey.h" +#ifdef GRIN_ENABLE_VERTEX_PRIMARY_KEYS +/** + * @brief Get the vertex types that have primary keys + * In some graph, not every vertex type has primary keys. + * @param GRIN_GRAPH The graph + * @return The vertex type list of types that have primary keys + */ +GRIN_VERTEX_TYPE_LIST grin_get_vertex_types_with_primary_keys(GRIN_GRAPH g) { + auto _g = static_cast(g); + GRIN_VERTEX_TYPE_LIST_T* vtl = new GRIN_VERTEX_TYPE_LIST_T(); + for (size_t idx = 0; idx < _g->g.vertex_label_num_; ++idx) { + vtl->push_back(idx); + } + return vtl; +} + +/** + * @brief Get the primary keys properties of a vertex type + * The primary keys properties are the properties that can be used to identify a + * vertex. They are a subset of the properties of a vertex type. + * @param GRIN_GRAPH The graph + * @param GRIN_VERTEX_TYPE The vertex type + * @return The primary keys properties list + */ +GRIN_VERTEX_PROPERTY_LIST grin_get_primary_keys_by_vertex_type( + GRIN_GRAPH, GRIN_VERTEX_TYPE label) { + GRIN_VERTEX_PROPERTY_LIST_T* vpl = new GRIN_VERTEX_PROPERTY_LIST_T(); + GRIN_VERTEX_PROPERTY vp; + vp = 0; + vp += (label * 1u) << 8; + vp += (GRIN_DATATYPE::Int64 * 1u) << 16; + vpl->emplace_back(vp); + return vpl; +} + +/** + * @brief Get the primary keys values row of a vertex + * The values in the row are in the same order as the primary keys properties. + * @param GRIN_GRAPH The graph + * @param GRIN_VERTEX The vertex + * @return The primary keys values row + */ +GRIN_ROW grin_get_vertex_primary_keys_row(GRIN_GRAPH g, GRIN_VERTEX v) { + GRIN_ROW_T* row = new GRIN_ROW_T(); + auto _g = static_cast(g); + auto vid = v & (0xffffffff); + auto label = v >> 32; + auto oid = _g->g.get_oid(label, vid); + auto p = new gs::oid_t(oid); + row->emplace_back(p); + return row; +} +#endif diff --git a/flex/engines/graph_db/grin/src/property/property.cc b/flex/engines/graph_db/grin/src/property/property.cc new file mode 100644 index 000000000000..0a5c2d2f4262 --- /dev/null +++ b/flex/engines/graph_db/grin/src/property/property.cc @@ -0,0 +1,447 @@ +/** Copyright 2020 Alibaba Group Holding Limited. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include "grin/src/predefine.h" + +#include "grin/include/common/error.h" +#include "grin/include/property/property.h" + +void grin_destroy_string_value(GRIN_GRAPH g, const char* value) { + delete value; +} + +#ifdef GRIN_WITH_VERTEX_PROPERTY_NAME +const char* grin_get_vertex_property_name(GRIN_GRAPH g, GRIN_VERTEX_TYPE vt, + GRIN_VERTEX_PROPERTY vp) { + auto _g = static_cast(g); + auto& table = _g->g.get_vertex_table(vt); + + const auto& name = table.column_name(vp & (0xff)); + auto len = name.length() + 1; + char* out = new char[len]; + snprintf(out, len, "%s", name.c_str()); + return out; +} + +GRIN_VERTEX_PROPERTY grin_get_vertex_property_by_name(GRIN_GRAPH g, + GRIN_VERTEX_TYPE vt, + const char* name) { + auto _g = static_cast(g); + auto& table = _g->g.get_vertex_table(vt); + auto col = table.get_column(name); + if (col == nullptr) { + return GRIN_NULL_VERTEX_PROPERTY; + } + GRIN_VERTEX_PROPERTY vp; + vp = table.get_column_id_by_name(name); + vp += (vt * 1u) << 8; + vp += (_get_data_type(col->type()) * 1u) << 16; + return vp; +} + +GRIN_VERTEX_PROPERTY_LIST grin_get_vertex_properties_by_name(GRIN_GRAPH g, + const char* name) { + auto _g = static_cast(g); + std::string prop_name(name); + auto vps = new GRIN_VERTEX_PROPERTY_LIST_T(); + std::string _name = std::string(name); + for (auto idx = 0; idx < _g->g.vertex_label_num_; idx++) { + auto& table = _g->g.get_vertex_table(static_cast(idx)); + + auto col = table.get_column(name); + + if (col != nullptr) { + GRIN_VERTEX_PROPERTY vp; + vp = table.get_column_id_by_name(name); + vp += (idx * 1u) << 8; + vp += (_get_data_type(col->type()) * 1u) << 16; + vps->emplace_back(vp); + } + } + if (vps->size() == 0) { + delete vps; + return GRIN_NULL_VERTEX_PROPERTY_LIST; + } + return vps; +} +#endif + +#ifdef GRIN_WITH_VERTEX_PROPERTY +bool grin_equal_vertex_property(GRIN_GRAPH g, GRIN_VERTEX_PROPERTY vp1, + GRIN_VERTEX_PROPERTY vp2) { + return vp1 == vp2; +} + +void grin_destroy_vertex_property(GRIN_GRAPH g, GRIN_VERTEX_PROPERTY vp) {} + +/** + * @TODO add type for GRIN_VERTEX_PROPERTY_T + */ +GRIN_DATATYPE grin_get_vertex_property_datatype(GRIN_GRAPH g, + GRIN_VERTEX_PROPERTY vp) { + return (GRIN_DATATYPE) (vp >> 16); +} + +int grin_get_vertex_property_value_of_int32(GRIN_GRAPH g, GRIN_VERTEX v, + GRIN_VERTEX_PROPERTY vp) { + auto _g = static_cast(g); + auto label = v >> 32; + auto vid = v & (0xffffffff); + auto plabel = (vp >> 8) & (0xff); + auto pdt = (vp >> 16); + auto pid = vp & (0xff); + if (label != plabel || pdt != GRIN_DATATYPE::Int32) { + grin_error_code = INVALID_VALUE; + return 0; + } + if (label >= _g->g.vertex_label_num_ || + pid >= _g->vproperties[label].size()) { + grin_error_code = INVALID_VALUE; + return 0; + } + auto pcol = _g->vproperties[label][pid]; + if (pcol == NULL) { + grin_error_code = INVALID_VALUE; + return 0; + } + auto col = static_cast(pcol); + return col->get_view(vid); +} + +unsigned int grin_get_vertex_property_value_of_uint32(GRIN_GRAPH g, + GRIN_VERTEX v, + GRIN_VERTEX_PROPERTY vp) { + grin_error_code = INVALID_VALUE; + return 0; +} + +long long int grin_get_vertex_property_value_of_int64(GRIN_GRAPH g, + GRIN_VERTEX v, + GRIN_VERTEX_PROPERTY vp) { + auto _g = static_cast(g); + auto label = v >> 32; + auto vid = v & (0xffffffff); + auto plabel = (vp >> 8) & (0xff); + auto pdt = (vp >> 16); + auto pid = vp & (0xff); + + if (label != plabel || pdt != GRIN_DATATYPE::Int64) { + grin_error_code = INVALID_VALUE; + return 0; + } + + if (label >= _g->g.vertex_label_num_ || + pid >= _g->vproperties[label].size()) { + grin_error_code = INVALID_VALUE; + return 0; + } + auto pcol = _g->vproperties[label][pid]; + if (pcol == NULL) { + grin_error_code = INVALID_VALUE; + return 0.0f; + } + auto col = static_cast(pcol); + return col->get_view(vid); +} + +unsigned long long int grin_get_vertex_property_value_of_uint64( + GRIN_GRAPH g, GRIN_VERTEX v, GRIN_VERTEX_PROPERTY vp) { + grin_error_code = INVALID_VALUE; + return 0; +} + +float grin_get_vertex_property_value_of_float(GRIN_GRAPH g, GRIN_VERTEX v, + GRIN_VERTEX_PROPERTY vp) { + grin_error_code = INVALID_VALUE; + return 0.0f; +} + +double grin_get_vertex_property_value_of_double(GRIN_GRAPH g, GRIN_VERTEX v, + GRIN_VERTEX_PROPERTY vp) { + auto _g = static_cast(g); + auto label = v >> 32; + auto vid = v & (0xffffffff); + auto plabel = (vp >> 8) & (0xff); + auto pdt = (vp >> 16); + auto pid = vp & (0xff); + + if (label != plabel || pdt != GRIN_DATATYPE::Double) { + grin_error_code = INVALID_VALUE; + return 0.0; + } + + if (label >= _g->g.vertex_label_num_ || + pid >= _g->vproperties[label].size()) { + grin_error_code = INVALID_VALUE; + return 0.0; + } + auto pcol = _g->vproperties[label][pid]; + if (pcol == NULL) { + grin_error_code = INVALID_VALUE; + return 0; + } + auto col = static_cast(pcol); + return col->get_view(vid); +} + +const char* grin_get_vertex_property_value_of_string(GRIN_GRAPH g, + GRIN_VERTEX v, + GRIN_VERTEX_PROPERTY vp) { + auto _g = static_cast(g); + auto label = v >> 32; + auto vid = v & (0xffffffff); + auto plabel = (vp >> 8) & (0xff); + auto pdt = (vp >> 16); + auto pid = vp & (0xff); + + if (label != plabel || pdt != GRIN_DATATYPE::String) { + grin_error_code = INVALID_VALUE; + return NULL; + } + + if (label >= _g->g.vertex_label_num_ || + pid >= _g->vproperties[label].size()) { + grin_error_code = INVALID_VALUE; + return ""; + } + auto pcol = _g->vproperties[label][pid]; + if (pcol == NULL) { + grin_error_code = INVALID_VALUE; + return ""; + } + auto col = static_cast(pcol); + + auto s = col->get_view(vid); + auto len = s.size() + 1; + char* out = new char[len]; + snprintf(out, len, "%s", s.data()); + return out; +} + +int grin_get_vertex_property_value_of_date32(GRIN_GRAPH g, GRIN_VERTEX v, + GRIN_VERTEX_PROPERTY vp) { + grin_error_code = INVALID_VALUE; + return 0; +} + +int grin_get_vertex_property_value_of_time32(GRIN_GRAPH g, GRIN_VERTEX v, + GRIN_VERTEX_PROPERTY vp) { + grin_error_code = INVALID_VALUE; + return 0; +} + +long long int grin_get_vertex_property_value_of_timestamp64( + GRIN_GRAPH g, GRIN_VERTEX v, GRIN_VERTEX_PROPERTY vp) { + auto _g = static_cast(g); + auto label = v >> 32; + auto vid = v & (0xffffffff); + auto plabel = (vp >> 8) & (0xff); + auto pdt = (vp >> 16); + auto pid = vp & (0xff); + + if (label != plabel || pdt != GRIN_DATATYPE::Timestamp64) { + grin_error_code = INVALID_VALUE; + return 0; + } + + if (label >= _g->g.vertex_label_num_ || + pid >= _g->vproperties[label].size()) { + grin_error_code = INVALID_VALUE; + return 0; + } + auto pcol = _g->vproperties[label][pid]; + if (pcol == NULL) { + grin_error_code = INVALID_VALUE; + return 0; + } + auto col = static_cast(pcol); + return col->get_view(vid).milli_second; +} + +GRIN_VERTEX_TYPE grin_get_vertex_type_from_property(GRIN_GRAPH g, + GRIN_VERTEX_PROPERTY vp) { + return (vp >> 8) & (0xff); +} +#endif + +#if defined(GRIN_WITH_VERTEX_PROPERTY) && defined(GRIN_TRAIT_CONST_VALUE_PTR) +const void* grin_get_vertex_property_value(GRIN_GRAPH g, GRIN_VERTEX v, + GRIN_VERTEX_PROPERTY vp) { + auto plabel = (vp >> 8) & (0xff); + auto type = (vp >> 16); + auto pid = vp & (0xff); + + auto _g = static_cast(g); + + if (plabel >= _g->g.vertex_label_num_ || + pid >= _g->vproperties[plabel].size()) { + grin_error_code = INVALID_VALUE; + return 0; + } + auto col = _g->vproperties[plabel][pid]; + if (col == NULL) { + grin_error_code = UNKNOWN_DATATYPE; + return 0; + } + + auto vid = v & (0xffffffff); + + switch (type) { + case GRIN_DATATYPE::Int32: { + auto _col = static_cast(col); + return _col->buffer().data() + vid; + } + case GRIN_DATATYPE::Int64: { + auto _col = static_cast(col); + return _col->buffer().data() + vid; + } + case GRIN_DATATYPE::String: { + auto _col = static_cast(col); + return _col->buffer()[vid].data(); + } + case GRIN_DATATYPE::Timestamp64: { + auto _col = static_cast(col); + return _col->buffer().data() + vid; + } + case GRIN_DATATYPE::Double: { + auto _col = static_cast(col); + return _col->buffer().data() + vid; + } + default: + grin_error_code = UNKNOWN_DATATYPE; + return NULL; + } +} +#endif + +#ifdef GRIN_WITH_EDGE_PROPERTY +bool grin_equal_edge_property(GRIN_GRAPH g, GRIN_EDGE_PROPERTY ep1, + GRIN_EDGE_PROPERTY ep2) { + return ep1 == ep2; +} + +void grin_destroy_edge_property(GRIN_GRAPH g, GRIN_EDGE_PROPERTY ep) {} + +GRIN_DATATYPE grin_get_edge_property_datatype(GRIN_GRAPH g, + GRIN_EDGE_PROPERTY ep) { + auto _g = static_cast(g); + auto src_label_i = (ep >> 16) & 0xff; + const auto& src_label = _g->g.schema().get_vertex_label_name(src_label_i); + auto dst_label_i = (ep >> 8) & 0xff; + const auto& dst_label = _g->g.schema().get_vertex_label_name(dst_label_i); + auto edge_label_i = ep & 0xff; + const auto& edge_label = _g->g.schema().get_edge_label_name(edge_label_i); + const auto& type = + _g->g.schema().get_edge_properties(src_label, dst_label, edge_label); + auto idx = ep >> 24; + return _get_data_type(type[idx]); +} + +int grin_get_edge_property_value_of_int32(GRIN_GRAPH g, GRIN_EDGE e, + GRIN_EDGE_PROPERTY ep) { + auto _e = static_cast(e); + auto idx = ep >> 24; + if (idx > 0 || _get_data_type(_e->data.type) != GRIN_DATATYPE::Int32) { + grin_error_code = INVALID_VALUE; + return 0; + } + return _e->data.value.i; +} + +unsigned int grin_get_edge_property_value_of_uint32(GRIN_GRAPH g, GRIN_EDGE e, + GRIN_EDGE_PROPERTY ep) { + grin_error_code = INVALID_VALUE; + return 0; +} + +long long int grin_get_edge_property_value_of_int64(GRIN_GRAPH g, GRIN_EDGE e, + GRIN_EDGE_PROPERTY ep) { + auto _e = static_cast(e); + auto idx = ep >> 24; + if (idx > 0 || _get_data_type(_e->data.type) != GRIN_DATATYPE::Int64) { + grin_error_code = INVALID_VALUE; + return 0; + } + return _e->data.value.l; +} + +unsigned long long int grin_get_edge_property_value_of_uint64( + GRIN_GRAPH g, GRIN_EDGE e, GRIN_EDGE_PROPERTY ep) { + grin_error_code = INVALID_VALUE; + return 0; +} + +float grin_get_edge_property_value_of_float(GRIN_GRAPH g, GRIN_EDGE e, + GRIN_EDGE_PROPERTY ep) { + grin_error_code = INVALID_VALUE; + return 0.0; +} +double grin_get_edge_property_value_of_double(GRIN_GRAPH g, GRIN_EDGE e, + GRIN_EDGE_PROPERTY ep) { + auto _e = static_cast(e); + auto idx = ep >> 24; + if (idx > 0 || _get_data_type(_e->data.type) != GRIN_DATATYPE::Double) { + grin_error_code = INVALID_VALUE; + return 0.0; + } + return _e->data.value.db; +} + +const char* grin_get_edge_property_value_of_string(GRIN_GRAPH g, GRIN_EDGE e, + GRIN_EDGE_PROPERTY ep) { + auto _e = static_cast(e); + auto idx = ep >> 24; + if (idx > 0 || _get_data_type(_e->data.type) != GRIN_DATATYPE::String) { + grin_error_code = INVALID_VALUE; + return NULL; + } + auto s = _e->data.value.s; + auto len = s.size() + 1; + char* out = new char[len]; + snprintf(out, len, "%s", s.data()); + return out; +} + +int grin_get_edge_property_value_of_date32(GRIN_GRAPH g, GRIN_EDGE e, + GRIN_EDGE_PROPERTY ep) { + grin_error_code = INVALID_VALUE; + return 0; +} +int grin_get_edge_property_value_of_time32(GRIN_GRAPH g, GRIN_EDGE e, + GRIN_EDGE_PROPERTY ep) { + grin_error_code = INVALID_VALUE; + return 0; +} + +long long int grin_get_edge_property_value_of_timestamp64( + GRIN_GRAPH g, GRIN_EDGE e, GRIN_EDGE_PROPERTY ep) { + auto _e = static_cast(e); + auto idx = ep >> 24; + if (idx > 0 || _get_data_type(_e->data.type) != GRIN_DATATYPE::Timestamp64) { + grin_error_code = INVALID_VALUE; + return 0; + } + return _e->data.value.d.milli_second; +} + +GRIN_EDGE_TYPE grin_get_edge_type_from_property(GRIN_GRAPH g, + GRIN_EDGE_PROPERTY ep) { + return ep & (~0xff000000); +} +#endif + +#if defined(GRIN_WITH_EDGE_PROPERTY) && defined(GRIN_TRAIT_CONST_VALUE_PTR) +const void* grin_get_edge_property_value(GRIN_GRAPH g, GRIN_EDGE e, + GRIN_EDGE_PROPERTY ep) { + return NULL; +} +#endif \ No newline at end of file diff --git a/flex/engines/graph_db/grin/src/property/propertylist.cc b/flex/engines/graph_db/grin/src/property/propertylist.cc new file mode 100644 index 000000000000..a52639f105c9 --- /dev/null +++ b/flex/engines/graph_db/grin/src/property/propertylist.cc @@ -0,0 +1,147 @@ +/** Copyright 2020 Alibaba Group Holding Limited. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include "grin/src/predefine.h" + +#include "grin/include/property/propertylist.h" + +#ifdef GRIN_WITH_VERTEX_PROPERTY +GRIN_VERTEX_PROPERTY_LIST grin_get_vertex_property_list_by_type( + GRIN_GRAPH g, GRIN_VERTEX_TYPE vt) { + auto _g = static_cast(g); + auto& table = _g->g.get_vertex_table(vt); + + auto vertex_prop_num = table.col_num(); + GRIN_VERTEX_PROPERTY_LIST_T* vpl = new GRIN_VERTEX_PROPERTY_LIST_T(); + const auto& prop_types = table.column_types(); + for (size_t i = 0; i < vertex_prop_num; ++i) { + GRIN_VERTEX_PROPERTY vp; + vp = i; + vp += (vt * 1u) << 8; + vp += (_get_data_type(prop_types[i]) * 1u) << 16; + vpl->emplace_back(vp); + } + return vpl; +} + +size_t grin_get_vertex_property_list_size(GRIN_GRAPH g, + GRIN_VERTEX_PROPERTY_LIST vpl) { + auto _vpl = static_cast(vpl); + return _vpl->size(); +} + +GRIN_VERTEX_PROPERTY grin_get_vertex_property_from_list( + GRIN_GRAPH g, GRIN_VERTEX_PROPERTY_LIST vpl, size_t idx) { + auto _vpl = static_cast(vpl); + return (*_vpl)[idx]; +} + +GRIN_VERTEX_PROPERTY_LIST grin_create_vertex_property_list(GRIN_GRAPH g) { + return new GRIN_VERTEX_PROPERTY_LIST_T(); +} + +void grin_destroy_vertex_property_list(GRIN_GRAPH g, + GRIN_VERTEX_PROPERTY_LIST vpl) { + auto _vpl = static_cast(vpl); + delete _vpl; +} + +bool grin_insert_vertex_property_to_list(GRIN_GRAPH g, + GRIN_VERTEX_PROPERTY_LIST vpl, + GRIN_VERTEX_PROPERTY vp) { + auto _vpl = static_cast(vpl); + _vpl->push_back(vp); + return true; +} +#endif + +#ifdef GRIN_TRAIT_NATURAL_ID_FOR_VERTEX_PROPERTY +GRIN_VERTEX_PROPERTY grin_get_vertex_property_by_id( + GRIN_GRAPH g, GRIN_VERTEX_TYPE vt, GRIN_VERTEX_PROPERTY_ID pid) { + auto _g = static_cast(g); + + auto& table = _g->g.get_vertex_table(vt); + auto vertex_prop_num = table.col_num(); + + if (pid >= vertex_prop_num) { + return GRIN_NULL_VERTEX_PROPERTY; + } + const auto& prop_types = table.column_types(); + GRIN_VERTEX_PROPERTY vp; + vp = pid; + vp += (vt * 1u) << 8; + vp += (_get_data_type(prop_types[pid]) * 1u) << 16; + return vp; +} + +GRIN_VERTEX_PROPERTY_ID grin_get_vertex_property_id(GRIN_GRAPH g, + GRIN_VERTEX_TYPE vt, + GRIN_VERTEX_PROPERTY vp) { + return vp & (0xff); +} +#endif + +#ifdef GRIN_WITH_EDGE_PROPERTY +GRIN_EDGE_PROPERTY_LIST grin_get_edge_property_list_by_type(GRIN_GRAPH g, + GRIN_EDGE_TYPE et) { + GRIN_EDGE_PROPERTY_LIST_T* p = new GRIN_EDGE_PROPERTY_LIST_T(); + + auto _g = static_cast(g); + auto src_label_i = et >> 16; + auto src_label = _g->g.schema().get_vertex_label_name(src_label_i); + auto dst_label_i = (et >> 8) & (0xff); + auto dst_label = _g->g.schema().get_vertex_label_name(dst_label_i); + auto edge_label_i = et & 0xff; + auto edge_label = _g->g.schema().get_edge_label_name(edge_label_i); + auto sz = _g->g.schema() + .get_edge_properties(src_label, dst_label, edge_label) + .size(); + for (size_t i = 0; i < sz; ++i) { + p->emplace_back(et + (i << 24)); + } + return p; +} + +size_t grin_get_edge_property_list_size(GRIN_GRAPH g, + GRIN_EDGE_PROPERTY_LIST epl) { + auto _epl = static_cast(epl); + return _epl->size(); +} + +GRIN_EDGE_PROPERTY grin_get_edge_property_from_list(GRIN_GRAPH g, + GRIN_EDGE_PROPERTY_LIST epl, + size_t idx) { + auto _epl = static_cast(epl); + if (_epl->size() <= idx) { + return GRIN_NULL_EDGE_PROPERTY; + } + return (*_epl)[idx]; +} + +GRIN_EDGE_PROPERTY_LIST grin_create_edge_property_list(GRIN_GRAPH g) { + return new GRIN_EDGE_PROPERTY_LIST_T(); +} + +void grin_destroy_edge_property_list(GRIN_GRAPH g, + GRIN_EDGE_PROPERTY_LIST epl) { + auto _epl = static_cast(epl); + delete _epl; +} + +bool grin_insert_edge_property_to_list(GRIN_GRAPH g, + GRIN_EDGE_PROPERTY_LIST epl, + GRIN_EDGE_PROPERTY ep) { + auto _epl = static_cast(epl); + _epl->emplace_back(ep); + return true; +} +#endif diff --git a/flex/engines/graph_db/grin/src/property/row.cc b/flex/engines/graph_db/grin/src/property/row.cc new file mode 100644 index 000000000000..c81af3f08099 --- /dev/null +++ b/flex/engines/graph_db/grin/src/property/row.cc @@ -0,0 +1,268 @@ +/** Copyright 2020 Alibaba Group Holding Limited. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include "grin/src/predefine.h" + +#include "grin/include/property/row.h" + +#ifdef GRIN_ENABLE_ROW +void grin_destroy_row(GRIN_GRAPH g, GRIN_ROW r) { + auto _r = static_cast(r); + delete _r; +} + +int grin_get_int32_from_row(GRIN_GRAPH g, GRIN_ROW r, size_t idx) { + auto _r = static_cast(r); + return *static_cast((*_r)[idx]); +} + +unsigned int grin_get_uint32_from_row(GRIN_GRAPH g, GRIN_ROW r, size_t idx) { + auto _r = static_cast(r); + return *static_cast((*_r)[idx]); +} + +long long int grin_get_int64_from_row(GRIN_GRAPH g, GRIN_ROW r, size_t idx) { + auto _r = static_cast(r); + return *static_cast((*_r)[idx]); +} + +unsigned long long int grin_get_uint64_from_row(GRIN_GRAPH g, GRIN_ROW r, + size_t idx) { + auto _r = static_cast(r); + return *static_cast((*_r)[idx]); +} + +float grin_get_float_from_row(GRIN_GRAPH g, GRIN_ROW r, size_t idx) { + auto _r = static_cast(r); + return *static_cast((*_r)[idx]); +} + +double grin_get_double_from_row(GRIN_GRAPH g, GRIN_ROW r, size_t idx) { + auto _r = static_cast(r); + return *static_cast((*_r)[idx]); +} + +const char* grin_get_string_from_row(GRIN_GRAPH g, GRIN_ROW r, size_t idx) { + auto _r = static_cast(r); + auto s = static_cast((*_r)[idx]); + return s; +} + +int grin_get_date32_from_row(GRIN_GRAPH g, GRIN_ROW r, size_t idx) { + auto _r = static_cast(r); + return *static_cast((*_r)[idx]); +} + +int grin_get_time32_from_row(GRIN_GRAPH g, GRIN_ROW r, size_t idx) { + auto _r = static_cast(r); + return *static_cast((*_r)[idx]); +} + +long long int grin_get_timestamp64_from_row(GRIN_GRAPH g, GRIN_ROW r, + size_t idx) { + auto _r = static_cast(r); + return (*static_cast((*_r)[idx])); +} + +GRIN_ROW grin_create_row(GRIN_GRAPH g) { + auto r = new GRIN_ROW_T(); + return r; +} + +bool grin_insert_int32_to_row(GRIN_GRAPH g, GRIN_ROW r, int value) { + auto _r = static_cast(r); + _r->push_back(new int32_t(value)); + return true; +} + +bool grin_insert_uint32_to_row(GRIN_GRAPH g, GRIN_ROW r, unsigned int value) { + auto _r = static_cast(r); + _r->push_back(new uint32_t(value)); + return true; +} + +bool grin_insert_int64_to_row(GRIN_GRAPH g, GRIN_ROW r, long long int value) { + auto _r = static_cast(r); + _r->push_back(new int64_t(value)); + return true; +} + +bool grin_insert_uint64_to_row(GRIN_GRAPH g, GRIN_ROW r, + unsigned long long int value) { + auto _r = static_cast(r); + _r->push_back(new uint64_t(value)); + return true; +} + +bool grin_insert_float_to_row(GRIN_GRAPH g, GRIN_ROW r, float value) { + auto _r = static_cast(r); + _r->push_back(new float(value)); + return true; +} + +bool grin_insert_double_to_row(GRIN_GRAPH g, GRIN_ROW r, double value) { + auto _r = static_cast(r); + _r->push_back(new double(value)); + return true; +} + +bool grin_insert_string_to_row(GRIN_GRAPH g, GRIN_ROW r, const char* value) { + auto _r = static_cast(r); + _r->push_back(value); + return true; +} + +bool grin_insert_date32_to_row(GRIN_GRAPH g, GRIN_ROW r, int value) { + auto _r = static_cast(r); + _r->push_back(new int32_t(value)); + return true; +} + +bool grin_insert_time32_to_row(GRIN_GRAPH g, GRIN_ROW r, int value) { + auto _r = static_cast(r); + _r->push_back(new int32_t(value)); + return true; +} + +bool grin_insert_timestamp64_to_row(GRIN_GRAPH g, GRIN_ROW r, + long long int value) { + auto _r = static_cast(r); + _r->push_back(new int64_t(value)); + return true; +} +#endif + +#if defined(GRIN_ENABLE_ROW) && defined(GRIN_TRAIT_CONST_VALUE_PTR) +/** @brief the value of a property from row by its position in row */ +const void* grin_get_value_from_row(GRIN_GRAPH g, GRIN_ROW r, GRIN_DATATYPE dt, + size_t idx) { + auto _r = static_cast(r); + switch (dt) { + case GRIN_DATATYPE::Int32: + return static_cast((*_r)[idx]); + case GRIN_DATATYPE::UInt32: + return static_cast((*_r)[idx]); + case GRIN_DATATYPE::Int64: + return static_cast((*_r)[idx]); + case GRIN_DATATYPE::UInt64: + return static_cast((*_r)[idx]); + case GRIN_DATATYPE::Float: + return static_cast((*_r)[idx]); + case GRIN_DATATYPE::Double: + return static_cast((*_r)[idx]); + case GRIN_DATATYPE::String: + return static_cast((*_r)[idx]); + case GRIN_DATATYPE::Date32: + return static_cast((*_r)[idx]); + case GRIN_DATATYPE::Time32: + return static_cast((*_r)[idx]); + case GRIN_DATATYPE::Timestamp64: + return static_cast((*_r)[idx]); + default: + return NULL; + } + return NULL; +} +#endif +///@} + +#if defined(GRIN_WITH_VERTEX_PROPERTY) && defined(GRIN_ENABLE_ROW) +GRIN_ROW grin_get_vertex_row(GRIN_GRAPH g, GRIN_VERTEX v) { + auto _g = static_cast(g); + auto vid = v & (0xffffffff); + auto label = v >> 32; + + if (label >= _g->g.vertex_label_num_) { + return NULL; + } + auto& table = _g->g.get_vertex_table(label); + auto prop_size = table.col_num(); + const auto& types = table.column_types(); + auto r = new GRIN_ROW_T(); + for (size_t prop_id = 0; prop_id < prop_size; prop_id++) { + auto col = _g->vproperties[label][prop_id]; + auto type = _get_data_type(types[prop_id]); + switch (type) { + case GRIN_DATATYPE::Int32: { + auto _col = static_cast(col); + r->emplace_back(_col->buffer().data() + vid); + break; + } + case GRIN_DATATYPE::Int64: { + auto _col = static_cast(col); + r->emplace_back(_col->buffer().data() + vid); + break; + } + case GRIN_DATATYPE::String: { + auto _col = static_cast(col); + auto s = _col->get_view(vid); + auto len = s.size() + 1; + char* out = new char[len]; + snprintf(out, len, "%s", s.data()); + r->emplace_back(out); + break; + } + case GRIN_DATATYPE::Timestamp64: { + auto _col = static_cast(col); + r->emplace_back(_col->buffer().data() + vid); + break; + } + case GRIN_DATATYPE::Double: { + auto _col = static_cast(col); + r->emplace_back(_col->buffer().data() + vid); + break; + } + default: + r->emplace_back(static_cast(NULL)); + } + } + return r; +} +#endif + +#if defined(GRIN_WITH_EDGE_PROPERTY) && defined(GRIN_ENABLE_ROW) +GRIN_ROW grin_get_edge_row(GRIN_GRAPH g, GRIN_EDGE e) { + auto _e = static_cast(e); + auto type = _get_data_type(_e->data.type); + GRIN_ROW_T* r = new GRIN_ROW_T(); + switch (type) { + case GRIN_DATATYPE::Int32: { + r->emplace_back(new int(_e->data.value.i)); + break; + } + case GRIN_DATATYPE::Int64: { + r->emplace_back(new int64_t(_e->data.value.l)); + break; + } + case GRIN_DATATYPE::String: { + auto s = _e->data.value.s; + auto len = s.size() + 1; + char* out = new char[len]; + snprintf(out, len, "%s", s.data()); + + r->emplace_back(out); + break; + } + case GRIN_DATATYPE::Timestamp64: { + r->emplace_back(new int64_t(_e->data.value.d.milli_second)); + break; + } + case GRIN_DATATYPE::Double: { + r->emplace_back(new double(_e->data.value.db)); + break; + } + default: + r->emplace_back(static_cast(NULL)); + } + return r; +} +#endif \ No newline at end of file diff --git a/flex/engines/graph_db/grin/src/property/topology.cc b/flex/engines/graph_db/grin/src/property/topology.cc new file mode 100644 index 000000000000..5a58e07ecb03 --- /dev/null +++ b/flex/engines/graph_db/grin/src/property/topology.cc @@ -0,0 +1,75 @@ +/** Copyright 2020 Alibaba Group Holding Limited. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include "grin/src/predefine.h" + +#include "grin/include/property/topology.h" + +#ifdef GRIN_WITH_VERTEX_PROPERTY +size_t grin_get_vertex_num_by_type(GRIN_GRAPH g, GRIN_VERTEX_TYPE vt) { + auto _g = static_cast(g); + return _g->g.vertex_num(vt); +} +#endif + +#ifdef GRIN_WITH_EDGE_PROPERTY +size_t grin_get_edge_num_by_type(GRIN_GRAPH g, GRIN_EDGE_TYPE et) { + auto src_label = et >> 16; + auto dst_label = (et >> 8) & (0xff); + auto edge_label = et & (0xff); + auto _g = static_cast(g); + + auto oe = _g->g.get_oe_csr(src_label, dst_label, edge_label); + auto vertex_num = _g->g.vertex_num(src_label); + size_t edge_num = 0; + for (size_t i = 0; i < vertex_num; ++i) { + edge_num += oe->edge_iter(i)->size(); + } + if (edge_num != 0) { + return edge_num; + } + auto ie = _g->g.get_ie_csr(dst_label, src_label, edge_label); + vertex_num = _g->g.vertex_num(dst_label); + for (size_t i = 0; i < vertex_num; ++i) { + edge_num += ie->edge_iter(i)->size(); + } + return edge_num; +} +#endif + +#if defined(GRIN_ENABLE_VERTEX_LIST) && defined(GRIN_WITH_VERTEX_PROPERTY) +GRIN_VERTEX_LIST grin_get_vertex_list_by_type(GRIN_GRAPH g, + GRIN_VERTEX_TYPE vt) { + GRIN_VERTEX_LIST vl; + vl.label = vt; + auto _g = static_cast(g); + vl.vertex_num = _g->g.vertex_num(vt); + return vl; +} +#endif + +#if defined(GRIN_ENABLE_EDGE_LIST) && defined(GRIN_WITH_EDGE_PROPERTY) +GRIN_EDGE_LIST grin_get_edge_list_by_type(GRIN_GRAPH, GRIN_EDGE_TYPE); +#endif + +#if defined(GRIN_ENABLE_ADJACENT_LIST) && defined(GRIN_WITH_EDGE_PROPERTY) +GRIN_ADJACENT_LIST grin_get_adjacent_list_by_edge_type(GRIN_GRAPH g, + GRIN_DIRECTION dir, + GRIN_VERTEX v, + GRIN_EDGE_TYPE et) { + GRIN_ADJACENT_LIST adj_list; + adj_list.v = v; + adj_list.dir = dir; + adj_list.edge_label = et; + return adj_list; +} +#endif \ No newline at end of file diff --git a/flex/engines/graph_db/grin/src/property/type.cc b/flex/engines/graph_db/grin/src/property/type.cc new file mode 100644 index 000000000000..ea40c524b980 --- /dev/null +++ b/flex/engines/graph_db/grin/src/property/type.cc @@ -0,0 +1,275 @@ +/** Copyright 2020 Alibaba Group Holding Limited. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include "grin/src/predefine.h" + +#include "grin/include/property/type.h" + +#ifdef GRIN_WITH_VERTEX_PROPERTY +// Vertex type +bool grin_equal_vertex_type(GRIN_GRAPH g, GRIN_VERTEX_TYPE vt1, + GRIN_VERTEX_TYPE vt2) { + return (vt1 == vt2); +} + +GRIN_VERTEX_TYPE grin_get_vertex_type(GRIN_GRAPH g, GRIN_VERTEX v) { + return v >> 32; +} + +void grin_destroy_vertex_type(GRIN_GRAPH g, GRIN_VERTEX_TYPE vt) {} + +// Vertex type list +GRIN_VERTEX_TYPE_LIST grin_get_vertex_type_list(GRIN_GRAPH g) { + auto _g = static_cast(g); + auto vtl = new GRIN_VERTEX_TYPE_LIST_T(); + auto vertex_label_num = _g->g.schema().vertex_label_num(); + for (size_t idx = 0; idx < vertex_label_num; ++idx) { + vtl->push_back(idx); + } + return vtl; +} + +void grin_destroy_vertex_type_list(GRIN_GRAPH g, GRIN_VERTEX_TYPE_LIST vtl) { + auto _vtl = static_cast(vtl); + delete _vtl; +} + +GRIN_VERTEX_TYPE_LIST grin_create_vertex_type_list(GRIN_GRAPH g) { + auto vtl = new GRIN_VERTEX_TYPE_LIST_T(); + return vtl; +} + +bool grin_insert_vertex_type_to_list(GRIN_GRAPH g, GRIN_VERTEX_TYPE_LIST vtl, + GRIN_VERTEX_TYPE vt) { + auto _vtl = static_cast(vtl); + _vtl->push_back(vt); + return true; +} + +size_t grin_get_vertex_type_list_size(GRIN_GRAPH g, GRIN_VERTEX_TYPE_LIST vtl) { + auto _vtl = static_cast(vtl); + return _vtl->size(); +} + +GRIN_VERTEX_TYPE grin_get_vertex_type_from_list(GRIN_GRAPH g, + GRIN_VERTEX_TYPE_LIST vtl, + size_t idx) { + auto _vtl = static_cast(vtl); + return (*_vtl)[idx]; +} +#endif + +#ifdef GRIN_WITH_VERTEX_TYPE_NAME +const char* grin_get_vertex_type_name(GRIN_GRAPH g, GRIN_VERTEX_TYPE vt) { + auto _g = static_cast(g); + std::string type_name = _g->g.schema().get_vertex_label_name(vt); + auto len = type_name.length() + 1; + char* out = new char[len]; + snprintf(out, len, "%s", type_name.c_str()); + return out; +} + +GRIN_VERTEX_TYPE grin_get_vertex_type_by_name(GRIN_GRAPH g, const char* name) { + auto _g = static_cast(g); + std::string type_name(name); + if ((!_g->g.schema().contains_vertex_label(type_name))) { + return GRIN_NULL_VERTEX_TYPE; + } + auto type = _g->g.schema().get_vertex_label_id(type_name); + return type; +} +#endif + +#ifdef GRIN_TRAIT_NATURAL_ID_FOR_VERTEX_TYPE +GRIN_VERTEX_TYPE_ID grin_get_vertex_type_id(GRIN_GRAPH g, GRIN_VERTEX_TYPE vt) { + return vt; +} + +GRIN_VERTEX_TYPE grin_get_vertex_type_by_id(GRIN_GRAPH g, + GRIN_VERTEX_TYPE_ID tid) { + return tid; +} +#endif + +#ifdef GRIN_WITH_EDGE_PROPERTY +// Edge type +bool grin_equal_edge_type(GRIN_GRAPH g, GRIN_EDGE_TYPE et1, + GRIN_EDGE_TYPE et2) { + return (et1 == et2); +} + +GRIN_EDGE_TYPE grin_get_edge_type(GRIN_GRAPH g, GRIN_EDGE e) { + auto _e = static_cast(e); + auto src_label = _e->src >> 32; + auto dst_label = _e->dst >> 32; + return _e->label + (src_label << 16) + (dst_label << 8); +} + +void grin_destroy_edge_type(GRIN_GRAPH g, GRIN_EDGE_TYPE et) { + // do nothing +} + +// Edge type list +GRIN_EDGE_TYPE_LIST grin_get_edge_type_list(GRIN_GRAPH g) { + auto _g = static_cast(g); + auto etl = new GRIN_EDGE_TYPE_LIST_T(); + auto edge_label_num = _g->g.edge_label_num_; + auto vertex_label_num = _g->g.vertex_label_num_; + for (size_t src_label_i = 0; src_label_i < vertex_label_num; ++src_label_i) { + const auto& src_label = _g->g.schema().get_vertex_label_name(src_label_i); + for (size_t dst_label_i = 0; dst_label_i < vertex_label_num; + ++dst_label_i) { + const auto& dst_label = _g->g.schema().get_vertex_label_name(dst_label_i); + for (size_t edge_label_i = 0; edge_label_i < edge_label_num; + ++edge_label_i) { + const auto& edge_label = + _g->g.schema().get_edge_label_name(edge_label_i); + if (_g->g.schema().exist(src_label, dst_label, edge_label)) { + auto label = (src_label_i << 16) + (dst_label_i << 8) + edge_label_i; + etl->push_back(label); + } + } + } + } + return etl; +} + +void grin_destroy_edge_type_list(GRIN_GRAPH g, GRIN_EDGE_TYPE_LIST etl) { + auto _etl = static_cast(etl); + delete _etl; +} + +GRIN_EDGE_TYPE_LIST grin_create_edge_type_list(GRIN_GRAPH g) { + auto etl = new GRIN_EDGE_TYPE_LIST_T(); + return etl; +} + +bool grin_insert_edge_type_to_list(GRIN_GRAPH g, GRIN_EDGE_TYPE_LIST etl, + GRIN_EDGE_TYPE et) { + auto _etl = static_cast(etl); + _etl->push_back(et); + return true; +} + +size_t grin_get_edge_type_list_size(GRIN_GRAPH g, GRIN_EDGE_TYPE_LIST etl) { + auto _etl = static_cast(etl); + return _etl->size(); +} + +GRIN_EDGE_TYPE grin_get_edge_type_from_list(GRIN_GRAPH g, + GRIN_EDGE_TYPE_LIST etl, + size_t idx) { + auto _etl = static_cast(etl); + return (*_etl)[idx]; +} +#endif + +#ifdef GRIN_WITH_EDGE_TYPE_NAME +const char* grin_get_edge_type_name(GRIN_GRAPH g, GRIN_EDGE_TYPE et) { + auto _g = static_cast(g); + const auto& schema = _g->g.schema(); + auto edge_label_i = et & 0xff; + auto src_label_i = et >> 16; + auto dst_label_i = (et >> 8) & 0xff; + const auto& edge_label = schema.get_edge_label_name(edge_label_i); + const auto& src_label = schema.get_vertex_label_name(src_label_i); + const auto& dst_label = schema.get_vertex_label_name(dst_label_i); + auto label = src_label + "#" + dst_label + "#" + edge_label; + auto len = label.length() + 1; + char* out = new char[len]; + snprintf(out, len, "%s", label.c_str()); + return out; +} + +GRIN_EDGE_TYPE grin_get_edge_type_by_name(GRIN_GRAPH g, const char* name) { + auto _g = static_cast(g); + + const auto& schema = _g->g.schema(); + std::vector vec; + size_t len = strlen(name); + std::string ss{}; + for (size_t i = 0; i <= len; ++i) { + if (name[i] == '#' || name[i] == '\0') { + vec.emplace_back(ss); + ss = ""; + } else { + ss += name[i]; + } + } + + if (vec.size() != 3) { + return GRIN_NULL_EDGE_TYPE; + } + if ((!schema.contains_vertex_label(vec[0])) || + (!schema.contains_vertex_label(vec[1])) || + (!schema.contains_edge_label(vec[2]))) { + return GRIN_NULL_EDGE_TYPE; + } + auto src_label = schema.get_vertex_label_id(vec[0]); + auto dst_label = schema.get_vertex_label_id(vec[1]); + auto edge_label = schema.get_edge_label_id(vec[2]); + return (src_label << 16) + (dst_label << 8) + edge_label; +} +#endif + +#ifdef GRIN_TRAIT_NATURAL_ID_FOR_EDGE_TYPE +GRIN_EDGE_TYPE_ID grin_get_edge_type_id(GRIN_GRAPH g, GRIN_EDGE_TYPE et) { + return et; +} + +GRIN_EDGE_TYPE grin_get_edge_type_by_id(GRIN_GRAPH g, GRIN_EDGE_TYPE_ID etid) { + return etid; +} +#endif + +#if defined(GRIN_WITH_VERTEX_PROPERTY) && defined(GRIN_WITH_EDGE_PROPERTY) +/** @brief the src vertex type list */ +GRIN_VERTEX_TYPE_LIST grin_get_src_types_by_edge_type(GRIN_GRAPH g, + GRIN_EDGE_TYPE et) { + auto vtl = new GRIN_VERTEX_TYPE_LIST_T(); + vtl->emplace_back(et >> 16); + return vtl; +} + +/** @brief get the dst vertex type list */ +GRIN_VERTEX_TYPE_LIST grin_get_dst_types_by_edge_type(GRIN_GRAPH g, + GRIN_EDGE_TYPE et) { + auto vtl = new GRIN_VERTEX_TYPE_LIST_T(); + vtl->emplace_back((et >> 8) & (0xff)); + return vtl; +} + +/** @brief get the edge type list related to a given pair of vertex types */ +GRIN_EDGE_TYPE_LIST grin_get_edge_types_by_vertex_type_pair( + GRIN_GRAPH g, GRIN_VERTEX_TYPE vt1, GRIN_VERTEX_TYPE vt2) { + auto _g = static_cast(g); + + auto vtl = new GRIN_VERTEX_TYPE_LIST_T(); + const auto& schema = _g->g.schema(); + auto edge_label_num = _g->g.edge_label_num_; + std::string src_label = + schema.get_vertex_label_name(static_cast(vt1)); + std::string dst_label = + schema.get_vertex_label_name(static_cast(vt2)); + auto label = (vt1 << 16) + (vt2 << 8); + for (size_t edge_label_i = 0; edge_label_i != edge_label_num; + ++edge_label_i) { + std::string edge_label = + schema.get_vertex_label_name(static_cast(edge_label_i)); + if (schema.exist(src_label, dst_label, edge_label)) { + vtl->push_back(label + edge_label_i); + } + } + return vtl; +} +#endif +///@} diff --git a/flex/engines/graph_db/grin/src/topology/adjacentlist.cc b/flex/engines/graph_db/grin/src/topology/adjacentlist.cc new file mode 100644 index 000000000000..112da2e552d3 --- /dev/null +++ b/flex/engines/graph_db/grin/src/topology/adjacentlist.cc @@ -0,0 +1,125 @@ +/** Copyright 2020 Alibaba Group Holding Limited. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include "grin/src/predefine.h" + +#include "grin/include/topology/adjacentlist.h" + +#if defined(GRIN_ENABLE_ADJACENT_LIST) && !defined(GRIN_ENABLE_EDGE_PROPERTY) +GRIN_ADJACENT_LIST grin_get_adjacent_list(GRIN_GRAPH g, GRIN_DIRECTION dir, + GRIN_VERTEX v) { + GRIN_ADJACENT_LIST alt; + alt.dir = dir; + alt.v = v; + return alt; +} +#endif + +#ifdef GRIN_ENABLE_ADJACENT_LIST +void grin_destroy_adjacent_list(GRIN_GRAPH g, GRIN_ADJACENT_LIST adj_list) {} +#endif + +#ifdef GRIN_ENABLE_ADJACENT_LIST_ITERATOR +GRIN_ADJACENT_LIST_ITERATOR grin_get_adjacent_list_begin( + GRIN_GRAPH g, GRIN_ADJACENT_LIST adj_list) { + auto _g = static_cast(g); + GRIN_ADJACENT_LIST_ITERATOR iter; + auto& v = adj_list.v; + iter.adj_list = adj_list; + auto label = adj_list.edge_label; + auto src_label = label >> 16; + auto dst_label = (label >> 8) & 0xff; + auto edge_label = label & 0xff; + auto v_label = v >> 32; + auto vid = v & (0xffffffff); + if (adj_list.dir == GRIN_DIRECTION::OUT) { + if (src_label == v_label) { + iter.edge_iter = + _g->g.get_outgoing_edges_raw(src_label, vid, dst_label, edge_label); + + } else { + iter.edge_iter = nullptr; + } + } else { + if (dst_label == v_label) { + iter.edge_iter = + _g->g.get_incoming_edges_raw(dst_label, vid, src_label, edge_label); + } else { + iter.edge_iter = nullptr; + } + } + return iter; +} + +void grin_destroy_adjacent_list_iter(GRIN_GRAPH g, + GRIN_ADJACENT_LIST_ITERATOR iter) { + if (iter.edge_iter != nullptr) { + auto edge_iter = + static_cast(iter.edge_iter); + delete edge_iter; + } +} + +void grin_get_next_adjacent_list_iter(GRIN_GRAPH g, + GRIN_ADJACENT_LIST_ITERATOR iter) { + auto edge_iter = + static_cast(iter.edge_iter); + edge_iter->next(); +} + +bool grin_is_adjacent_list_end(GRIN_GRAPH g, GRIN_ADJACENT_LIST_ITERATOR iter) { + if (iter.edge_iter == nullptr) { + return true; + } + auto edge_iter = + static_cast(iter.edge_iter); + return !edge_iter->is_valid(); +} + +GRIN_VERTEX grin_get_neighbor_from_adjacent_list_iter( + GRIN_GRAPH g, GRIN_ADJACENT_LIST_ITERATOR iter) { + auto edge_iter = + static_cast(iter.edge_iter); + auto vid = edge_iter->get_neighbor(); + auto label = iter.adj_list.edge_label; + + if (iter.adj_list.dir == GRIN_DIRECTION::OUT) { + label = (label >> 8) & 0xff; + } else { + label = label >> 16; + } + return ((label * 1ull) << 32) + vid; +} + +GRIN_EDGE grin_get_edge_from_adjacent_list_iter( + GRIN_GRAPH g, GRIN_ADJACENT_LIST_ITERATOR iter) { + auto edge_iter = + static_cast(iter.edge_iter); + GRIN_EDGE_T* edge = new GRIN_EDGE_T(); + auto nbr = grin_get_neighbor_from_adjacent_list_iter(g, iter); + if (iter.adj_list.dir == GRIN_DIRECTION::IN) { + edge->src = nbr; + edge->dst = iter.adj_list.v; + } else { + edge->src = iter.adj_list.v; + edge->dst = nbr; + } + edge->dir = iter.adj_list.dir; + edge->data = edge_iter->get_data(); + auto label = iter.adj_list.edge_label; + edge->label = label & 0xff; + return edge; +} +#endif \ No newline at end of file diff --git a/flex/engines/graph_db/grin/src/topology/structure.cc b/flex/engines/graph_db/grin/src/topology/structure.cc new file mode 100644 index 000000000000..469cfa672c33 --- /dev/null +++ b/flex/engines/graph_db/grin/src/topology/structure.cc @@ -0,0 +1,146 @@ +/** Copyright 2020 Alibaba Group Holding Limited. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include "grin/src/predefine.h" + +#include "grin/include/topology/structure.h" + +/** + * @brief Get a (non-partitioned) graph from storage + * @param uri The URI of the graph. + * Current URI format: + * flex://{path_to_yaml} + * @return A graph handle. + */ +GRIN_GRAPH grin_get_graph_from_storage(const char* uri) { + std::string _uri(uri); + std::string::size_type pos = _uri.find("://"); + if (pos == std::string::npos) { + return GRIN_NULL_GRAPH; + } + auto protocol = _uri.substr(0, pos); + if (protocol != "flex") { + return GRIN_NULL_GRAPH; + } + _uri = _uri.substr(pos + 3); + std::string graph_schema_path = _uri + "/modern_graph.yaml"; + std::string data_path = uri; + std::string bulk_load_config_path = _uri + "/bulk_load.yaml"; + if (!std::filesystem::exists(graph_schema_path) || + !(std::filesystem::exists(bulk_load_config_path))) { + return GRIN_NULL_GRAPH; + } + auto ret = gs::Schema::LoadFromYaml(graph_schema_path, bulk_load_config_path); + const auto& schema = std::get<0>(ret); + auto& vertex_files = std::get<1>(ret); + + auto& edge_files = std::get<2>(ret); + + GRIN_GRAPH_T* g = new GRIN_GRAPH_T(); + g->g.Init(schema, vertex_files, edge_files); + init_cache(g); + return g; +} + +void grin_destroy_graph(GRIN_GRAPH g) { + auto _g = static_cast(g); + delete _g; +} + +// Graph +#if defined(GRIN_ASSUME_HAS_DIRECTED_GRAPH) && \ + defined(GRIN_ASSUME_HAS_UNDIRECTED_GRAPH) +bool grin_is_directed(GRIN_GRAPH g) { return true; } +#endif + +#ifdef GRIN_ASSUME_HAS_MULTI_EDGE_GRAPH +bool grin_is_multigraph(GRIN_GRAPH) { return true; } +#endif + +#ifndef GRIN_WITH_VERTEX_PROPERTY +size_t grin_get_vertex_num(GRIN_GRAPH); +#endif + +#ifndef GRIN_WITH_EDGE_PROPERTY +size_t grin_get_edge_num(GRIN_GRAPH); +#endif + +// Vertex +void grin_destroy_vertex(GRIN_GRAPH, GRIN_VERTEX v) {} + +bool grin_equal_vertex(GRIN_GRAPH g, GRIN_VERTEX v1, GRIN_VERTEX v2) { + return v1 == v2; +} + +// Data +#ifdef GRIN_WITH_VERTEX_DATA +GRIN_DATATYPE grin_get_vertex_data_datatype(GRIN_GRAPH, GRIN_VERTEX); + +const void* grin_get_vertex_data_value(GRIN_GRAPH, GRIN_VERTEX); +#endif + +// Edge +void grin_destroy_edge(GRIN_GRAPH, GRIN_EDGE e) { + auto _e = static_cast(e); + delete _e; +} + +GRIN_VERTEX grin_get_src_vertex_from_edge(GRIN_GRAPH, GRIN_EDGE e) { + auto _e = static_cast(e); + auto v = _e->src; + return v; +} + +GRIN_VERTEX grin_get_dst_vertex_from_edge(GRIN_GRAPH, GRIN_EDGE e) { + auto _e = static_cast(e); + auto v = _e->dst; + return v; +} + +#ifdef GRIN_WITH_EDGE_DATA +GRIN_DATATYPE grin_get_edge_data_datatype(GRIN_GRAPH, GRIN_EDGE e) { + auto _e = static_cast(e); + auto type = _e->data.type; + return _get_data_type(type); +} + +const void* grin_get_edge_data_value(GRIN_GRAPH, GRIN_EDGE e) { + auto _e = static_cast(e); + auto type = _e->data.type; + switch (_get_data_type(type)) { + case GRIN_DATATYPE::Int32: { + return new int32_t(_e->data.value.i); + } + case GRIN_DATATYPE::Int64: { + return new int64_t(_e->data.value.l); + } + case GRIN_DATATYPE::Double: { + return new double(_e->data.value.db); + } + case GRIN_DATATYPE::String: { + auto s = _e->data.value.s; + auto len = s.size() + 1; + char* out = new char[len]; + snprintf(out, len, "%s", s.data()); + return out; + } + case GRIN_DATATYPE::Timestamp64: { + return new int64_t(_e->data.value.d.milli_second); + } + default: + return GRIN_NULL_EDGE_DATA; + } +} +#endif \ No newline at end of file diff --git a/flex/engines/graph_db/grin/src/topology/vertexlist.cc b/flex/engines/graph_db/grin/src/topology/vertexlist.cc new file mode 100644 index 000000000000..413525e24980 --- /dev/null +++ b/flex/engines/graph_db/grin/src/topology/vertexlist.cc @@ -0,0 +1,58 @@ +/** Copyright 2020 Alibaba Group Holding Limited. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include "grin/src/predefine.h" + +#include "grin/include/topology/vertexlist.h" + +#if defined(GRIN_ENABLE_VERTEX_LIST) && !defined(GRIN_WITH_VERTEX_PROPERTY) +GRIN_VERTEX_LIST grin_get_vertex_list(GRIN_GRAPH g) {} +#endif + +#ifdef GRIN_ENABLE_VERTEX_LIST +void grin_destroy_vertex_list(GRIN_GRAPH g, GRIN_VERTEX_LIST vl) {} +#endif + +#ifdef GRIN_ENABLE_VERTEX_LIST_ITERATOR +GRIN_VERTEX_LIST_ITERATOR grin_get_vertex_list_begin(GRIN_GRAPH g, + GRIN_VERTEX_LIST vl) { + GRIN_VERTEX_LIST_ITERATOR vlt; + vlt.cur_vid = new uint32_t(0); + vlt.vertex_list = vl; + return vlt; +} + +void grin_destroy_vertex_list_iter(GRIN_GRAPH g, + GRIN_VERTEX_LIST_ITERATOR iter) { + delete iter.cur_vid; +} + +void grin_get_next_vertex_list_iter(GRIN_GRAPH g, + GRIN_VERTEX_LIST_ITERATOR iter) { + if (*iter.cur_vid < iter.vertex_list.vertex_num) + ++(*iter.cur_vid); +} + +bool grin_is_vertex_list_end(GRIN_GRAPH g, GRIN_VERTEX_LIST_ITERATOR iter) { + return *iter.cur_vid == iter.vertex_list.vertex_num; +} + +GRIN_VERTEX grin_get_vertex_from_iter(GRIN_GRAPH g, + GRIN_VERTEX_LIST_ITERATOR iter) { + auto label = iter.vertex_list.label; + auto vid = *iter.cur_vid; + return ((label * 1ull) << 32) + vid; +} +#endif \ No newline at end of file diff --git a/flex/engines/graph_db/grin/test/test.c b/flex/engines/graph_db/grin/test/test.c new file mode 100644 index 000000000000..4612d041885b --- /dev/null +++ b/flex/engines/graph_db/grin/test/test.c @@ -0,0 +1,1065 @@ +#include +#include +#include +#include +#include + +#include "grin/predefine.h" + +#include "grin/include/common/error.h" +#include "grin/include/index/internal_id.h" +#include "grin/include/index/label.h" +#include "grin/include/index/order.h" +#include "grin/include/index/pk.h" +#include "grin/include/partition/partition.h" +#include "grin/include/partition/reference.h" +#include "grin/include/partition/topology.h" +#include "grin/include/property/partition.h" +#include "grin/include/property/primarykey.h" +#include "grin/include/property/property.h" +#include "grin/include/property/propertylist.h" +#include "grin/include/property/row.h" +#include "grin/include/property/topology.h" +#include "grin/include/property/type.h" +#include "grin/include/topology/adjacentlist.h" +#include "grin/include/topology/edgelist.h" +#include "grin/include/topology/structure.h" +#include "grin/include/topology/vertexlist.h" + +#define eps (1e-8) +#define FOR_VERTEX_BEGIN(g, vl, v) \ + GRIN_VERTEX_LIST_ITERATOR __vli = grin_get_vertex_list_begin(g, vl); \ + unsigned __vcnt = 0; \ + while (!grin_is_vertex_list_end(g, __vli)) { \ + GRIN_VERTEX v = grin_get_vertex_from_iter(g, __vli); + +#ifdef GRIN_WITH_VERTEX_PROPERTY +#define FOR_VERTEX_END(g, vl, v) \ + grin_destroy_vertex(g, v); \ + __vcnt++; \ + grin_get_next_vertex_list_iter(g, __vli); \ + } \ + printf("vertex type %s, checked: %u\n", vt_names[__vtl_i], __vcnt); + +#define FOR_VERTEX_LIST_BEGIN(g, vl) \ + { \ + GRIN_VERTEX_TYPE_LIST __vtl = grin_get_vertex_type_list(g); \ + size_t __vtl_sz = grin_get_vertex_type_list_size(g, __vtl); \ + for (size_t __vtl_i = 0; __vtl_i < __vtl_sz; ++__vtl_i) { \ + GRIN_VERTEX_TYPE __vt = \ + grin_get_vertex_type_from_list(g, __vtl, __vtl_i); \ + GRIN_VERTEX_LIST vl = grin_get_vertex_list_by_type(g, __vt); \ + grin_destroy_vertex_type(g, __vt); + +#define FOR_VERTEX_LIST_SELECT_MASTER_BEGIN(g, vl) \ + { \ + GRIN_VERTEX_TYPE_LIST __vtl = grin_get_vertex_type_list(g); \ + size_t __vtl_sz = grin_get_vertex_type_list_size(g, __vtl); \ + for (size_t __vtl_i = 0; __vtl_i < __vtl_sz; ++__vtl_i) { \ + GRIN_VERTEX_TYPE __vt = \ + grin_get_vertex_type_from_list(g, __vtl, __vtl_i); \ + GRIN_VERTEX_LIST vl = \ + grin_get_vertex_list_by_type_select_master(g, __vt); \ + grin_destroy_vertex_type(g, __vt); + +#define FOR_VERTEX_LIST_SELECT_MIRROR_BEGIN(g, vl) \ + { \ + GRIN_VERTEX_TYPE_LIST __vtl = grin_get_vertex_type_list(g); \ + size_t __vtl_sz = grin_get_vertex_type_list_size(g, __vtl); \ + for (size_t __vtl_i = 0; __vtl_i < __vtl_sz; ++__vtl_i) { \ + GRIN_VERTEX_TYPE __vt = \ + grin_get_vertex_type_from_list(g, __vtl, __vtl_i); \ + GRIN_VERTEX_LIST vl = \ + grin_get_vertex_list_by_type_select_mirror(g, __vt); \ + grin_destroy_vertex_type(g, __vt); + +#define FOR_VERTEX_LIST_END(g, vl) \ + grin_destroy_vertex_list(g, vl); \ + } \ + grin_destroy_vertex_type_list(g, __vtl); \ + } +#else +#define FOR_VERTEX_END(g, vl) \ + grin_destroy_vertex(g, v); \ + __vcnt++; \ + grin_get_next_vertex_list_iter(g, __vli); \ + } \ + printf("vertex checked: %u\n", __vcnt); + +#define FOR_VERTEX_LIST_BEGIN(g, vl) \ + GRIN_VERTEX_LIST vl = grin_get_vertex_list(g); + +#define FOR_VERTEX_LIST_SELECT_MASTER_BEGIN(g, vl) \ + GRIN_VERTEX_LIST vl = grin_get_vertex_list_select_master(g); + +#define FOR_VERTEX_LIST_SELECT_MIRROR_BEGIN(g, vl) \ + GRIN_VERTEX_LIST vl = grin_get_vertex_list_select_mirror(g); + +#define FOR_VERTEX_LIST_END(g, vl) grin_destroy_vertex_list(g, vl); +#endif + +#ifdef GRIN_WITH_EDGE_PROPERTY +#define FOR_ADJ_LIST_BEGIN(g, dir, v, al) \ + { \ + GRIN_EDGE_TYPE_LIST __etl = grin_get_edge_type_list(g); \ + size_t __etl_size = grin_get_edge_type_list_size(g, __etl); \ + for (size_t __etl_i = 0; __etl_i < __etl_size; ++__etl_i) { \ + GRIN_EDGE_TYPE __et = grin_get_edge_type_from_list(g, __etl, __etl_i); \ + GRIN_ADJACENT_LIST al = \ + grin_get_adjacent_list_by_edge_type(g, dir, v, __et); \ + grin_destroy_edge_type(g, __et); +#define FOR_ADJ_LIST_END(g, al) \ + grin_destroy_adjacent_list(g, al); \ + } \ + grin_destroy_edge_type_list(g, __etl); \ + } +#else +#define FOR_ADJ_LIST_BEGIN(g, dir, v, al) \ + GRIN_ADJACENT_LIST al = grin_get_adjacent_list(g, dir, v); +#define FOR_ADJ_LIST_END(g, al) grin_destroy_adjacent_list(g, al); +#endif + +const char* vt_names[] = {"person", "software"}; +const char* et_names[] = {"knows", "created"}; + +const char* v_names[][4] = {{"josh", "vadas", "peter", "marko"}, + {"lop", "ripple", "wrong", + "wrong"}}; // TODO align with order in local graph + +GRIN_GRAPH get_graph(const char* uri_str, int p) { +#ifdef GRIN_ENABLE_GRAPH_PARTITION + GRIN_PARTITIONED_GRAPH pg = grin_get_partitioned_graph_from_storage(argv[1]); + GRIN_PARTITION_LIST local_partitions = grin_get_local_partition_list(pg); + assert(p < grin_get_partition_list_size(pg, local_partitions)); + GRIN_PARTITION partition = + grin_get_partition_from_list(pg, local_partitions, p); + GRIN_PARTITION_ID partition_id = grin_get_partition_id(pg, partition); + GRIN_PARTITION p1 = grin_get_partition_by_id(pg, partition_id); + if (!grin_equal_partition(pg, partition, p1)) { + printf("partition not match\n"); + } + grin_destroy_partition(pg, p1); + GRIN_GRAPH g = grin_get_local_graph_by_partition(pg, partition); + grin_destroy_partition(pg, partition); + grin_destroy_partition_list(pg, local_partitions); + grin_destroy_partitioned_graph(pg); +#else + GRIN_GRAPH g = grin_get_graph_from_storage(uri_str); +#endif + return g; +} + +#ifdef GRIN_ENABLE_GRAPH_PARTITION +GRIN_VERTEX get_one_master_person(GRIN_GRAPH g) { + GRIN_VERTEX_TYPE vt = grin_get_vertex_type_by_name(g, "person"); + GRIN_VERTEX_LIST vl = grin_get_vertex_list_by_type_select_master(g, vt); + grin_destroy_vertex_type(g, vt); + GRIN_VERTEX_LIST_ITERATOR vli = grin_get_vertex_list_begin(g, vl); + GRIN_VERTEX v = grin_get_vertex_from_iter(g, vli); + grin_destroy_vertex_list_iter(g, vli); + grin_destroy_vertex_list(g, vl); +#ifdef GRIN_ENABLE_VERTEX_INTERNAL_ID_INDEX + printf("Got vertex %s\n", + v_names[vt][grin_get_vertex_internal_id_by_type(g, vt, v)]); +#endif + return v; +} +#endif + +GRIN_VERTEX get_one_person(GRIN_GRAPH g) { + GRIN_VERTEX_TYPE vt = grin_get_vertex_type_by_name(g, "person"); + GRIN_VERTEX_LIST vl = grin_get_vertex_list_by_type(g, vt); + grin_destroy_vertex_type(g, vt); + GRIN_VERTEX_LIST_ITERATOR vli = grin_get_vertex_list_begin(g, vl); + GRIN_VERTEX v = grin_get_vertex_from_iter(g, vli); + grin_destroy_vertex_list_iter(g, vli); + grin_destroy_vertex_list(g, vl); +#ifdef GRIN_ENABLE_VERTEX_INTERNAL_ID_INDEX + printf("Got vertex %s\n", + v_names[vt][grin_get_vertex_internal_id_by_type(g, vt, v)]); +#endif + return v; +} + +void test_property_type(const char* uri_str) { + printf("+++++++++++++++++++++ Test property/type +++++++++++++++++++++\n"); + + GRIN_GRAPH g = get_graph(uri_str, 0); + + printf("------------ Vertex Type ------------\n"); + GRIN_VERTEX_TYPE_LIST vtl = grin_get_vertex_type_list(g); + size_t vtl_size = grin_get_vertex_type_list_size(g, vtl); + printf("vertex type list size: %zu\n", vtl_size); + + for (size_t i = 0; i < vtl_size; ++i) { + printf("------------ Iterate the %zu-th vertex type ------------\n", i); + GRIN_VERTEX_TYPE vt = grin_get_vertex_type_from_list(g, vtl, i); +#ifdef GRIN_WITH_VERTEX_TYPE_NAME + const char* vt_name = grin_get_vertex_type_name(g, vt); + printf("vertex type name: %s\n", vt_name); + GRIN_VERTEX_TYPE vt0 = grin_get_vertex_type_by_name(g, vt_name); + if (!grin_equal_vertex_type(g, vt, vt0)) { + printf("vertex type name not match\n"); + } + grin_destroy_vertex_type(g, vt0); +#endif +#ifdef GRIN_TRAIT_NATURAL_ID_FOR_VERTEX_TYPE + printf("vertex type id: %u\n", grin_get_vertex_type_id(g, vt)); + GRIN_VERTEX_TYPE vt1 = + grin_get_vertex_type_by_id(g, grin_get_vertex_type_id(g, vt)); + if (!grin_equal_vertex_type(g, vt, vt1)) { + printf("vertex type id not match\n"); + } + grin_destroy_vertex_type(g, vt1); +#endif + } + grin_destroy_vertex_type_list(g, vtl); + + printf( + "------------ Create a vertex type list of one type \"person\" " + "------------\n"); + GRIN_VERTEX_TYPE_LIST vtl2 = grin_create_vertex_type_list(g); +#ifdef GRIN_WITH_VERTEX_TYPE_NAME + GRIN_VERTEX_TYPE vt2_w = grin_get_vertex_type_by_name(g, "knows"); + if (vt2_w == GRIN_NULL_VERTEX_TYPE) { + printf("(Correct) vertex type of knows does not exists\n"); + } + + GRIN_VERTEX_TYPE vt2 = grin_get_vertex_type_by_name(g, "person"); + if (vt2 == GRIN_NULL_VERTEX_TYPE) { + printf("(Wrong) vertex type of person can not be found\n"); + } else { + const char* vt2_name = grin_get_vertex_type_name(g, vt2); + printf("vertex type name: %s\n", vt2_name); + } +#else + GRIN_VERTEX_TYPE vt2 = get_one_vertex_type(g); +#endif + grin_insert_vertex_type_to_list(g, vtl2, vt2); + size_t vtl2_size = grin_get_vertex_type_list_size(g, vtl2); + printf("created vertex type list size: %zu\n", vtl2_size); + GRIN_VERTEX_TYPE vt3 = grin_get_vertex_type_from_list(g, vtl2, 0); + if (!grin_equal_vertex_type(g, vt2, vt3)) { + printf("vertex type not match\n"); + } + grin_destroy_vertex_type(g, vt2); + grin_destroy_vertex_type(g, vt3); + grin_destroy_vertex_type_list(g, vtl2); + + // edge + printf("------------ Edge Type ------------\n"); + GRIN_EDGE_TYPE_LIST etl = grin_get_edge_type_list(g); + size_t etl_size = grin_get_edge_type_list_size(g, etl); + printf("edge type list size: %zu\n", etl_size); + + for (size_t i = 0; i < etl_size; ++i) { + printf("------------ Iterate the %zu-th edge type ------------\n", i); + GRIN_EDGE_TYPE et = grin_get_edge_type_from_list(g, etl, i); +#ifdef GRIN_WITH_EDGE_TYPE_NAME + const char* et_name = grin_get_edge_type_name(g, et); + printf("edge type name: %s\n", et_name); + GRIN_EDGE_TYPE et0 = grin_get_edge_type_by_name(g, et_name); + if (!grin_equal_edge_type(g, et, et0)) { + printf("edge type name not match\n"); + } + grin_destroy_edge_type(g, et0); +#endif +#ifdef GRIN_TRAIT_NATURAL_ID_FOR_EDGE_TYPE + printf("edge type id: %u\n", grin_get_edge_type_id(g, et)); + GRIN_EDGE_TYPE et1 = + grin_get_edge_type_by_id(g, grin_get_edge_type_id(g, et)); + if (!grin_equal_edge_type(g, et, et1)) { + printf("edge type id not match\n"); + } + grin_destroy_edge_type(g, et1); +#endif + // relation + GRIN_VERTEX_TYPE_LIST src_vtl = grin_get_src_types_by_edge_type(g, et); + size_t src_vtl_size = grin_get_vertex_type_list_size(g, src_vtl); + printf("source vertex type list size: %zu\n", src_vtl_size); + + GRIN_VERTEX_TYPE_LIST dst_vtl = grin_get_dst_types_by_edge_type(g, et); + + size_t dst_vtl_size = grin_get_vertex_type_list_size(g, dst_vtl); + printf("destination vertex type list size: %zu\n", dst_vtl_size); + + if (src_vtl_size != dst_vtl_size) { + printf("source and destination vertex type list size not match\n"); + } + for (size_t j = 0; j < src_vtl_size; ++j) { + GRIN_VERTEX_TYPE src_vt = grin_get_vertex_type_from_list(g, src_vtl, j); + GRIN_VERTEX_TYPE dst_vt = grin_get_vertex_type_from_list(g, dst_vtl, j); + const char* src_vt_name = grin_get_vertex_type_name(g, src_vt); + const char* dst_vt_name = grin_get_vertex_type_name(g, dst_vt); + const char* et_name = grin_get_edge_type_name(g, et); + printf("edge type name: %s-%s-%s\n", src_vt_name, et_name, dst_vt_name); + grin_destroy_vertex_type(g, src_vt); + grin_destroy_vertex_type(g, dst_vt); + } + grin_destroy_vertex_type_list(g, src_vtl); + grin_destroy_vertex_type_list(g, dst_vtl); + } + grin_destroy_edge_type_list(g, etl); + + printf( + "------------ Create an edge type list of one type \"created\" " + "------------\n"); + GRIN_EDGE_TYPE_LIST etl2 = grin_create_edge_type_list(g); +#ifdef GRIN_WITH_EDGE_TYPE_NAME + GRIN_EDGE_TYPE et2_w = grin_get_edge_type_by_name(g, "person"); + if (et2_w == GRIN_NULL_EDGE_TYPE) { + printf("(Correct) edge type of person does not exists\n"); + } + GRIN_EDGE_TYPE et2 = grin_get_edge_type_by_name(g, "created"); + if (et2 == GRIN_NULL_EDGE_TYPE) { + printf("(Wrong) edge type of created can not be found\n"); + } else { + const char* et2_name = grin_get_edge_type_name(g, et2); + printf("edge type name: %s\n", et2_name); + } +#else + GRIN_EDGE_TYPE et2 = get_one_edge_type(g); +#endif + grin_insert_edge_type_to_list(g, etl2, et2); + size_t etl2_size = grin_get_edge_type_list_size(g, etl2); + printf("created edge type list size: %zu\n", etl2_size); + GRIN_EDGE_TYPE et3 = grin_get_edge_type_from_list(g, etl2, 0); + if (!grin_equal_edge_type(g, et2, et3)) { + printf("edge type not match\n"); + } + grin_destroy_edge_type(g, et2); + grin_destroy_edge_type(g, et3); + grin_destroy_edge_type_list(g, etl2); + + grin_destroy_graph(g); +} + +void test_property_vertex_property_value(const char* uri_str) { + printf("------------ Test Vertex property value ------------\n"); + GRIN_GRAPH g = get_graph(uri_str, 0); + + // value check + printf("------ check value ------\n"); + FOR_VERTEX_LIST_BEGIN(g, vl) + GRIN_VERTEX_PROPERTY_LIST vpl = + grin_get_vertex_property_list_by_type(g, __vt); + size_t vpl_size = grin_get_vertex_property_list_size(g, vpl); + FOR_VERTEX_BEGIN(g, vl, v) +#ifdef GRIN_ENABLE_VERTEX_INTERNAL_ID_INDEX + long long int vid = grin_get_vertex_internal_id_by_type(g, __vt, v); +#else + long long int vid = __vcnt; +#endif +#ifdef GRIN_ENABLE_ROW + GRIN_ROW row = grin_get_vertex_row(g, v); +#endif + for (size_t j = 0; j < vpl_size; ++j) { + GRIN_VERTEX_PROPERTY vp = grin_get_vertex_property_from_list(g, vpl, j); + GRIN_DATATYPE dt = grin_get_vertex_property_datatype(g, vp); + if (dt == Int64) { + long long int pv = grin_get_vertex_property_value_of_int64(g, v, vp); + assert(grin_get_last_error_code() == NO_ERROR); +#ifdef GRIN_ENABLE_ROW + long long int rv = grin_get_int64_from_row(g, row, j); + assert(pv == rv); +#endif +#ifdef GRIN_WITH_VERTEX_PROPERTY_NAME + printf("%s %s: %lld\n", v_names[__vt][vid], + grin_get_vertex_property_name(g, __vt, vp), pv); +#else + printf("%s %zu: %lld\n", v_names[__vt][vid], j, pv); +#endif + } else if (dt == String) { + const char* pv = grin_get_vertex_property_value_of_string(g, v, vp); + assert(grin_get_last_error_code() == NO_ERROR); +#ifdef GRIN_ENABLE_ROW + const char* rv = grin_get_string_from_row(g, row, j); + assert(strcmp(pv, rv) == 0); +#endif +#ifdef GRIN_WITH_VERTEX_PROPERTY_NAME + printf("%s %s: %s\n", v_names[__vt][vid], + grin_get_vertex_property_name(g, __vt, vp), pv); +#else + printf("%s %zu: %s\n", v_names[__vt][vid], j, pv); +#endif + grin_destroy_string_value(g, pv); + grin_destroy_string_value(g, rv); + } + grin_destroy_vertex_property(g, vp); + } +#ifdef GRIN_ENABLE_ROW + grin_destroy_row(g, row); +#endif + FOR_VERTEX_END(g, vl, v) + grin_destroy_vertex_property_list(g, vpl); + FOR_VERTEX_LIST_END(g, vl) + + // check schema + printf("------ check schema ------\n"); + GRIN_VERTEX_TYPE_LIST vtl = grin_get_vertex_type_list(g); + size_t vtl_size = grin_get_vertex_type_list_size(g, vtl); + for (size_t i = 0; i < vtl_size; ++i) { + GRIN_VERTEX_TYPE vt = grin_get_vertex_type_from_list(g, vtl, i); + GRIN_VERTEX_PROPERTY_LIST vpl = + grin_get_vertex_property_list_by_type(g, vt); + size_t vpl_size = grin_get_vertex_property_list_size(g, vpl); + for (size_t j = 0; j < vpl_size; ++j) { + GRIN_VERTEX_PROPERTY vp = grin_get_vertex_property_from_list(g, vpl, j); + GRIN_VERTEX_TYPE vt1 = grin_get_vertex_type_from_property(g, vp); + assert(grin_equal_vertex_type(g, vt, vt1)); + grin_destroy_vertex_type(g, vt1); + +#ifdef GRIN_TRAIT_NATURAL_ID_FOR_VERTEX_PROPERTY + unsigned int id = grin_get_vertex_property_id(g, vt, vp); + GRIN_VERTEX_PROPERTY vp1 = grin_get_vertex_property_by_id(g, vt, id); + assert(grin_equal_vertex_property(g, vp, vp1)); + grin_destroy_vertex_property(g, vp1); +#else + unsigned int id = i; +#endif + +#ifdef GRIN_WITH_VERTEX_PROPERTY_NAME + const char* vp_name = grin_get_vertex_property_name(g, vt, vp); + GRIN_VERTEX_PROPERTY vp2 = + grin_get_vertex_property_by_name(g, vt, vp_name); + assert(grin_equal_vertex_property(g, vp, vp2)); +#else + const char* vp_name = "unknown"; +#endif + printf("%s %u %s checked\n", vt_names[i], id, vp_name); + } + grin_destroy_vertex_property_list(g, vpl); + + // corner case +#ifdef GRIN_TRAIT_NATURAL_ID_FOR_VERTEX_PROPERTY + GRIN_VERTEX_PROPERTY vp3 = grin_get_vertex_property_by_id(g, vt, vpl_size); + assert(vp3 == GRIN_NULL_VERTEX_PROPERTY); +#endif + +#ifdef GRIN_WITH_VERTEX_PROPERTY_NAME + GRIN_VERTEX_PROPERTY vp4 = + grin_get_vertex_property_by_name(g, vt, "unknown"); + assert(vp4 == GRIN_NULL_VERTEX_PROPERTY); +#endif + grin_destroy_vertex_type(g, vt); + } + grin_destroy_vertex_type_list(g, vtl); + + // corner case +#ifdef GRIN_WITH_VERTEX_PROPERTY_NAME + GRIN_VERTEX_PROPERTY_LIST vpl1 = + grin_get_vertex_properties_by_name(g, "unknown"); + assert(vpl1 == GRIN_NULL_VERTEX_PROPERTY_LIST); + + GRIN_VERTEX_PROPERTY_LIST vpl2 = + grin_get_vertex_properties_by_name(g, "name"); + assert(vpl2 != GRIN_NULL_VERTEX_PROPERTY_LIST); + + size_t vpl2_size = grin_get_vertex_property_list_size(g, vpl2); + for (size_t i = 0; i < vpl2_size; ++i) { + GRIN_VERTEX_PROPERTY vp5 = grin_get_vertex_property_from_list(g, vpl2, i); + GRIN_VERTEX_TYPE vt5 = grin_get_vertex_type_from_property(g, vp5); + const char* vp5_name = grin_get_vertex_property_name(g, vt5, vp5); + assert(strcmp(vp5_name, "name") == 0); + } + grin_destroy_vertex_property_list(g, vpl2); +#endif + + grin_destroy_graph(g); +} + +void test_property_edge_property_value(const char* uri_str, + GRIN_DIRECTION dir) { + printf("------------ Test Edge property value ------------\n"); + GRIN_GRAPH g = get_graph(uri_str, 0); + + // value check + printf("------ check value ------\n"); + FOR_VERTEX_LIST_BEGIN(g, vl) + FOR_VERTEX_BEGIN(g, vl, v) + FOR_ADJ_LIST_BEGIN(g, dir, v, al) + GRIN_EDGE_PROPERTY_LIST epl = grin_get_edge_property_list_by_type(g, __et); + size_t epl_size = grin_get_edge_property_list_size(g, epl); + GRIN_ADJACENT_LIST_ITERATOR ali = grin_get_adjacent_list_begin(g, al); + size_t acnt = 0; + while (!grin_is_adjacent_list_end(g, ali)) { + GRIN_EDGE e = grin_get_edge_from_adjacent_list_iter(g, ali); + GRIN_VERTEX u = grin_get_neighbor_from_adjacent_list_iter(g, ali); +#ifdef GRIN_ENABLE_VERTEX_INTERNAL_ID_INDEX + GRIN_VERTEX_TYPE ut = grin_get_vertex_type(g, u); + long long int vid = grin_get_vertex_internal_id_by_type(g, __vt, v); + long long int uid = grin_get_vertex_internal_id_by_type(g, ut, u); + grin_destroy_vertex_type(g, ut); +#else + long long int vid = __vcnt; + long long int uid = acnt; +#endif +#ifdef GRIN_ENABLE_ROW + GRIN_ROW row = grin_get_edge_row(g, e); + +#endif + for (size_t j = 0; j < epl_size; ++j) { + GRIN_EDGE_PROPERTY ep = grin_get_edge_property_from_list(g, epl, j); + GRIN_DATATYPE dt = grin_get_edge_property_datatype(g, ep); + if (dt == Int64) { + long long int pv = grin_get_edge_property_value_of_int64(g, e, ep); + assert(grin_get_last_error_code() == NO_ERROR); +#ifdef GRIN_ENABLE_ROW + long long int rv = grin_get_int64_from_row(g, row, j); + assert(pv == rv); +#endif +#ifdef GRIN_WITH_EDGE_PROPERTY_NAME + printf("%s %s %s: %lld\n", v_names[__vt][vid], v_names[ut][uid], + grin_get_edge_property_name(g, __et, ep), pv); +#else + printf("%s %zu %lld: %lld\n", v_names[__vt][vid], j, uid, pv); +#endif + } else if (dt == Double) { + double pv = grin_get_edge_property_value_of_double(g, e, ep); + assert(grin_get_last_error_code() == NO_ERROR); +#ifdef GRIN_ENABLE_ROW + double rv = grin_get_double_from_row(g, row, j); + assert(fabs(pv - rv) < eps); +#endif +#ifdef GRIN_WITH_EDGE_PROPERTY_NAME + printf("%s %s %s: %lf\n", v_names[__vt][vid], v_names[ut][uid], + grin_get_edge_property_name(g, __et, ep), pv); +#else + printf("%s %zu %lld: %lf\n", v_names[__vt][vid], j, uid, pv); +#endif + } else if (dt == String) { + const char* pv = grin_get_edge_property_value_of_string(g, e, ep); + assert(grin_get_last_error_code() == NO_ERROR); +#ifdef GRIN_ENABLE_ROW + const char* rv = grin_get_string_from_row(g, row, j); + assert(strcmp(pv, rv) == 0); +#endif +#ifdef GRIN_WITH_EDGE_PROPERTY_NAME + printf("%s %s %s: %s\n", v_names[__vt][vid], v_names[ut][uid], + grin_get_edge_property_name(g, __et, ep), pv); +#else + printf("%s %zu %lld: %s\n", v_names[__vt][vid], j, uid, pv); +#endif + } + } +#ifdef GRIN_ENABLE_ROW + grin_destroy_row(g, row); +#endif + grin_destroy_edge(g, e); + grin_destroy_vertex(g, u); + acnt++; + grin_get_next_adjacent_list_iter(g, ali); + } + grin_destroy_adjacent_list_iter(g, ali); + grin_destroy_edge_property_list(g, epl); + FOR_ADJ_LIST_END(g, al) + FOR_VERTEX_END(g, vl, v) + FOR_VERTEX_LIST_END(g, vl) + + // check schema + printf("------ check schema ------\n"); + GRIN_EDGE_TYPE_LIST etl = grin_get_edge_type_list(g); + size_t etl_size = grin_get_edge_type_list_size(g, etl); + for (size_t i = 0; i < etl_size; ++i) { + GRIN_EDGE_TYPE et = grin_get_edge_type_from_list(g, etl, i); + GRIN_EDGE_PROPERTY_LIST epl = grin_get_edge_property_list_by_type(g, et); + size_t epl_size = grin_get_edge_property_list_size(g, epl); + for (size_t j = 0; j < epl_size; ++j) { + GRIN_EDGE_PROPERTY ep = grin_get_edge_property_from_list(g, epl, j); + GRIN_EDGE_TYPE et1 = grin_get_edge_type_from_property(g, ep); + assert(grin_equal_edge_type(g, et, et1)); + grin_destroy_edge_type(g, et1); + +#ifdef GRIN_TRAIT_NATURAL_ID_FOR_EDGE_PROPERTY + unsigned int id = grin_get_edge_property_id(g, et, ep); + GRIN_EDGE_PROPERTY ep1 = grin_get_edge_property_by_id(g, et, id); + assert(grin_equal_edge_property(g, ep, ep1)); + grin_destroy_edge_property(g, ep1); +#else + unsigned int id = i; +#endif + +#ifdef GRIN_WITH_EDGE_PROPERTY_NAME + const char* ep_name = grin_get_edge_property_name(g, et, ep); + GRIN_EDGE_PROPERTY ep2 = grin_get_edge_property_by_name(g, et, ep_name); + assert(grin_equal_edge_property(g, ep, ep2)); +#else + const char* ep_name = "unknown"; +#endif + printf("%s %u %s checked\n", et_names[i], id, ep_name); + } + grin_destroy_edge_property_list(g, epl); + + // corner case +#ifdef GRIN_TRAIT_NATURAL_ID_FOR_EDGE_PROPERTY + GRIN_EDGE_PROPERTY ep3 = grin_get_edge_property_by_id(g, et, epl_size); + assert(ep3 == GRIN_NULL_EDGE_PROPERTY); +#endif + +#ifdef GRIN_WITH_EDGE_PROPERTY_NAME + GRIN_EDGE_PROPERTY ep4 = grin_get_edge_property_by_name(g, et, "unknown"); + assert(ep4 == GRIN_NULL_EDGE_PROPERTY); +#endif + grin_destroy_edge_type(g, et); + } + grin_destroy_edge_type_list(g, etl); + + // corner case +#ifdef GRIN_WITH_EDGE_PROPERTY_NAME + GRIN_EDGE_PROPERTY_LIST epl1 = grin_get_edge_properties_by_name(g, "unknown"); + assert(epl1 == GRIN_NULL_EDGE_PROPERTY_LIST); + + GRIN_EDGE_PROPERTY_LIST epl2 = grin_get_edge_properties_by_name(g, "weight"); + assert(epl2 != GRIN_NULL_EDGE_PROPERTY_LIST); + + size_t epl2_size = grin_get_edge_property_list_size(g, epl2); + for (size_t i = 0; i < epl2_size; ++i) { + GRIN_EDGE_PROPERTY ep5 = grin_get_edge_property_from_list(g, epl2, i); + GRIN_EDGE_TYPE et5 = grin_get_edge_type_from_property(g, ep5); + const char* ep5_name = grin_get_edge_property_name(g, et5, ep5); + assert(strcmp(ep5_name, "weight") == 0); + } + grin_destroy_edge_property_list(g, epl2); +#endif + + grin_destroy_graph(g); +} + +#ifdef GRIN_ENABLE_VERTEX_PRIMARY_KEYS +void test_property_primary_key(const char* uri_str) { + printf( + "+++++++++++++++++++++ Test property/primary key " + "+++++++++++++++++++++\n"); + GRIN_GRAPH g = get_graph(uri_str, 0); + GRIN_VERTEX_TYPE_LIST vtl = grin_get_vertex_types_with_primary_keys(g); + size_t vtl_size = grin_get_vertex_type_list_size(g, vtl); + printf("vertex type num with primary key: %zu\n", vtl_size); + + unsigned id_type[7] = {(~0), 0, 0, 1, 0, 1, 0}; + + for (size_t i = 0; i < vtl_size; ++i) { + GRIN_VERTEX_TYPE vt = grin_get_vertex_type_from_list(g, vtl, i); + const char* vt_name = grin_get_vertex_type_name(g, vt); + printf("vertex type name: %s\n", vt_name); + + GRIN_VERTEX_PROPERTY_LIST vpl = grin_get_primary_keys_by_vertex_type(g, vt); + size_t vpl_size = grin_get_vertex_property_list_size(g, vpl); + assert(vpl_size == 1); + + for (size_t j = 0; j < vpl_size; ++j) { + GRIN_VERTEX_PROPERTY vp = grin_get_vertex_property_from_list(g, vpl, j); + const char* vp_name = grin_get_vertex_property_name(g, vt, vp); + printf("primary key name: %s\n", vp_name); + grin_destroy_vertex_property(g, vp); + } + + GRIN_VERTEX_PROPERTY vp = grin_get_vertex_property_from_list(g, vpl, 0); + GRIN_DATATYPE dt = grin_get_vertex_property_datatype(g, vp); + + for (size_t j = 1; j <= 6; ++j) { + GRIN_ROW r = grin_create_row(g); + assert(dt == Int64); + grin_insert_int64_to_row(g, r, j); +#ifdef GRIN_ENABLE_VERTEX_PK_INDEX + GRIN_VERTEX v = grin_get_vertex_by_primary_keys_row(g, vt, r); + if (v != GRIN_NULL_VERTEX && id_type[j] == i) { + GRIN_ROW nr = grin_get_vertex_primary_keys_row(g, v); + long long int k = grin_get_int64_from_row(g, nr, 0); + assert(k == j); + grin_destroy_row(g, nr); + grin_destroy_vertex(g, v); + } +#endif + grin_destroy_row(g, r); + } + + grin_destroy_vertex_property(g, vp); + grin_destroy_vertex_property_list(g, vpl); + grin_destroy_vertex_type(g, vt); + } + + grin_destroy_vertex_type_list(g, vtl); + grin_destroy_graph(g); +} +#endif + +void test_error_code(const char* uri_str) { + printf("+++++++++++++++++++++ Test error code +++++++++++++++++++++\n"); + GRIN_GRAPH g = get_graph(uri_str, 0); + + GRIN_VERTEX_TYPE vt1 = grin_get_vertex_type_by_name(g, "person"); + GRIN_VERTEX_TYPE vt2 = grin_get_vertex_type_by_name(g, "software"); + GRIN_VERTEX_PROPERTY vp = grin_get_vertex_property_by_name(g, vt2, "lang"); +#ifdef GRIN_ENABLE_GRAPH_PARTITION + GRIN_VERTEX v = get_one_master_person(g); +#else + GRIN_VERTEX v = get_one_person(g); +#endif + + const char* value = grin_get_vertex_property_value_of_string(g, v, vp); + assert(grin_get_last_error_code() == INVALID_VALUE); +} + +void test_property(const char* uri_str) { + test_property_type(uri_str); + test_property_vertex_property_value(uri_str); + test_property_edge_property_value(uri_str, OUT); + test_property_edge_property_value(uri_str, IN); +#ifdef GRIN_ENABLE_VERTEX_PRIMARY_KEYS + test_property_primary_key(uri_str); +#endif +#ifdef GRIN_WITH_VERTEX_PROPERTY_NAME + test_error_code(uri_str); +#endif +} +/** +void test_partition_reference(const char* uri_str) { + printf("+++++++++++++++++++++ Test partition/reference ++++++++++++++++++++++\n"); +GRIN_PARTITIONED_GRAPH pg = +grin_get_partitioned_graph_from_storage(argv[1]); +GRIN_PARTITION_LIST +local_partitions = grin_get_local_partition_list(pg); + assert(grin_get_partition_list_size(pg, local_partitions) >= 2); + + GRIN_PARTITION p0 = grin_get_partition_from_list(pg, local_partitions, 0); + GRIN_PARTITION p1 = grin_get_partition_from_list(pg, local_partitions, 1); + GRIN_GRAPH g0 = grin_get_local_graph_by_partition(pg, p0); + GRIN_GRAPH g1 = grin_get_local_graph_by_partition(pg, p1); + +FOR_VERTEX_LIST_BEGIN(g0, vl0) + size_t mcnt = 0; + FOR_VERTEX_BEGIN(g0, vl0, v0) + GRIN_VERTEX_REF vref0 = grin_get_vertex_ref_by_vertex(g0, v0); + if (grin_is_master_vertex(g0, v0)) { + mcnt++; +#ifdef GRIN_TRAIT_FAST_VERTEX_REF + long long int sref = grin_serialize_vertex_ref_as_int64(g0, vref0); + GRIN_VERTEX_REF vref1 = grin_deserialize_int64_to_vertex_ref(g0, sref); +#else + const char* sref = grin_serialize_vertex_ref(g0, vref0); + GRIN_VERTEX_REF vref1 = grin_deserialize_vertex_ref(g0, sref); + grin_destroy_string_value(g0, sref); +#endif + GRIN_VERTEX v1 = grin_get_vertex_from_vertex_ref(g0, vref1); + if (!grin_equal_vertex(g0, v0, v1)) { + printf("vertex not match after deserialize\n"); + } + GRIN_PARTITION p = grin_get_master_partition_from_vertex_ref(g0, vref0); + if (!grin_equal_partition(g0, p, p0)) { + printf("(Wrong) partition not match in vertex ref\n"); + } + grin_destroy_partition(pg, p); + grin_destroy_vertex(g0, v1); + grin_destroy_vertex_ref(g0, vref1); + } else if (grin_is_mirror_vertex(g0, v0)) { +#ifdef GRIN_TRAIT_FAST_VERTEX_REF + long long int sref = grin_serialize_vertex_ref_as_int64(g0, vref0); + GRIN_VERTEX_REF vref1 = grin_deserialize_int64_to_vertex_ref(g1, sref); +#else + const char* sref = grin_serialize_vertex_ref(g0, vref0); + GRIN_VERTEX_REF vref1 = grin_deserialize_vertex_ref(g1, sref); + grin_destroy_string_value(g0, sref); +#endif + GRIN_VERTEX v1 = grin_get_vertex_from_vertex_ref(g1, vref1); + if (!grin_is_master_vertex(g1, v1)) { + printf("(Wrong) vertex not master after deserialize\n"); + } + GRIN_PARTITION p = grin_get_master_partition_from_vertex_ref(g0, vref0); + if (!grin_equal_partition(g0, p, p1)) { + printf("(Wrong) partition not match in vertex ref\n"); + } + grin_destroy_partition(pg, p); + grin_destroy_vertex(g1, v1); + grin_destroy_vertex_ref(g1, vref1); + } else { + printf("(Wrong) vertex other than master or mirror\n"); + } + grin_destroy_vertex_ref(g0, vref0); + FOR_VERTEX_END(g0, vl0, v0) + printf("master checked: %zu\n", mcnt); +FOR_VERTEX_LIST_END(g0, vl0) + + grin_destroy_partition(pg, p0); + grin_destroy_partition(pg, p1); + grin_destroy_graph(g0); + grin_destroy_graph(g1); + grin_destroy_partition_list(pg, local_partitions); + grin_destroy_partitioned_graph(pg); +} + + +void test_partition_topology(const char* uri_str) { + printf("+++++++++++++++++++++ Test partition/topology ++++++++++++++++++++++\n"); GRIN_GRAPH g = get_graph(uri_str, 0); + + printf("----- check master ----- \n"); +FOR_VERTEX_LIST_SELECT_MASTER_BEGIN(g, vl) + FOR_VERTEX_BEGIN(g, vl, v) + #ifdef GRIN_ENABLE_VERTEX_LIST_ARRAY + GRIN_VERTEX v1 = grin_get_vertex_from_list(g, vl, __vcnt); + assert(grin_equal_vertex(g, v, v1)); + grin_destroy_vertex(g, v1); + #endif + assert(grin_is_master_vertex(g, v)); + FOR_VERTEX_END(g, vl, v) +FOR_VERTEX_LIST_END(g, vl) + + printf("----- check mirror ----- \n"); +FOR_VERTEX_LIST_SELECT_MIRROR_BEGIN(g, vl) + FOR_VERTEX_BEGIN(g, vl, v) + #ifdef GRIN_ENABLE_VERTEX_LIST_ARRAY + GRIN_VERTEX v1 = grin_get_vertex_from_list(g, vl, __vcnt); + assert(grin_equal_vertex(g, v, v1)); + grin_destroy_vertex(g, v1); + #endif + assert(grin_is_mirror_vertex(g, v)); + FOR_VERTEX_END(g, vl, v) +FOR_VERTEX_LIST_END(g, vl) + + grin_destroy_graph(g); +} + +void test_partition(const char* uri_str) { +#ifdef GRIN_ENABLE_GRAPH_PARTITION + test_partition_reference(uri_str); + test_partition_topology(uri_str); +#endif +} +*/ +void test_topology_structure(const char* uri_str) { + printf( + "+++++++++++++++++++++ Test topology/structure +++++++++++++++++++++\n"); + GRIN_GRAPH g = get_graph(uri_str, 0); +#ifndef GRIN_WITH_VERTEX_PROPERTY + printf("vertex num: %zu\n", grin_get_vertex_num(g)); +#endif + +#ifndef GRIN_WITH_EDGE_PROPERTY + printf("edge num: %zu\n", grin_get_edge_num(g)); +#endif + grin_destroy_graph(g); +} + +void test_topology_vertex_list(const char* uri_str) { + printf( + "+++++++++++++++++++++ Test topology/vertex_list " + "+++++++++++++++++++++\n"); + GRIN_GRAPH g = get_graph(uri_str, 0); + + FOR_VERTEX_LIST_BEGIN(g, vl) + FOR_VERTEX_BEGIN(g, vl, v) +#ifdef GRIN_ENABLE_VERTEX_LIST_ARRAY + GRIN_VERTEX v1 = grin_get_vertex_from_list(g, vl, __vcnt); + assert(grin_equal_vertex(g, v, v1)); + grin_destroy_vertex(g, v1); +#endif + FOR_VERTEX_END(g, vl, v) + FOR_VERTEX_LIST_END(g, vl) + + grin_destroy_graph(g); +} + +void test_topology_adjacent_list(const char* uri_str, GRIN_DIRECTION dir) { + if (dir == IN) { + printf( + "+++++++++++++++++++++ Test topology/adjacent_list IN " + "+++++++++++++++++++++\n"); + } else { + printf( + "+++++++++++++++++++++ Test topology/adjacent_list OUT " + "+++++++++++++++++++++\n"); + } + + GRIN_GRAPH g = get_graph(uri_str, 0); + + FOR_VERTEX_LIST_BEGIN(g, vl) + FOR_VERTEX_BEGIN(g, vl, v) +#ifdef GRIN_ENABLE_VERTEX_INTERNAL_ID_INDEX + long long int vid = grin_get_vertex_internal_id_by_type(g, __vt, v); +#else + long long int vid = __vcnt; +#endif +#ifdef GRIN_ENABLE_GRAPH_PARTITION + if (!grin_is_master_vertex(g, v)) { + grin_destroy_vertex(g, v); + grin_get_next_vertex_list_iter(g, __vli); + continue; + } +#endif + FOR_ADJ_LIST_BEGIN(g, dir, v, al) + GRIN_ADJACENT_LIST_ITERATOR ali = grin_get_adjacent_list_begin(g, al); + size_t acnt = 0; + while (!grin_is_adjacent_list_end(g, ali)) { + GRIN_EDGE e = grin_get_edge_from_adjacent_list_iter(g, ali); + GRIN_VERTEX v1 = grin_get_src_vertex_from_edge(g, e); + GRIN_VERTEX v2 = grin_get_dst_vertex_from_edge(g, e); + GRIN_VERTEX u = grin_get_neighbor_from_adjacent_list_iter(g, ali); + +#ifdef GRIN_ENABLE_ADJACENT_LIST_ARRAY + GRIN_EDGE e1 = grin_get_edge_from_adjacent_list(g, al, acnt); + GRIN_VERTEX e1v1 = grin_get_src_vertex_from_edge(g, e1); + GRIN_VERTEX e1v2 = grin_get_dst_vertex_from_edge(g, e1); + assert(grin_equal_vertex(g, v1, e1v1)); + assert(grin_equal_vertex(g, v2, e1v2)); + grin_destroy_edge(g, e1); + grin_destroy_vertex(g, e1v1); + grin_destroy_vertex(g, e1v2); +#endif + + if (dir == OUT) { + assert(grin_equal_vertex(g, v, v1)); + assert(grin_equal_vertex(g, v2, u)); + } else { + assert(grin_equal_vertex(g, v, v2)); + assert(grin_equal_vertex(g, v1, u)); + } + grin_destroy_vertex(g, v1); + grin_destroy_vertex(g, v2); + grin_destroy_vertex(g, u); + grin_destroy_edge(g, e); + + acnt++; + grin_get_next_adjacent_list_iter(g, ali); + } +#ifdef GRIN_ENABLE_ADJAECENT_LIST_ARRAY + assert(acnt == grin_get_adjacent_list_size(g, al)); +#endif + grin_destroy_adjacent_list_iter(g, ali); +#ifdef GRIN_WITH_EDGE_PROPERTY + printf("vertex %s adjlist, edgetype: %s, checked num: %zu\n", + v_names[__vt][vid], et_names[__etl_i], acnt); +#else + printf("vertex %s adjlist, checked num: %zu\n", v_names[__vt][vid], acnt); +#endif + FOR_ADJ_LIST_END(g, al) + FOR_VERTEX_END(g, vl, v) + FOR_VERTEX_LIST_END(g, vl) + grin_destroy_graph(g); +} + +void test_topology(const char* uri_str) { + test_topology_structure(uri_str); + test_topology_vertex_list(uri_str); + test_topology_adjacent_list(uri_str, OUT); + test_topology_adjacent_list(uri_str, IN); +} + +#if defined(GRIN_ASSUME_ALL_VERTEX_LIST_SORTED) && \ + defined(GRIN_ENABLE_VERTEX_LIST_ARRAY) +void test_index_order(const char* uri_str) { + printf("+++++++++++++++++++++ Test index order +++++++++++++++++++++\n"); + GRIN_GRAPH g = get_graph(uri_str, 0); + + FOR_VERTEX_LIST_BEGIN(g, vl) + FOR_VERTEX_BEGIN(g, vl, v) + size_t pos = grin_get_position_of_vertex_from_sorted_list(g, vl, v); + assert(pos == __vcnt); + FOR_VERTEX_END(g, vl, v) +#ifdef GRIN_ENABLE_GRAPH_PARTITION + { + GRIN_VERTEX_LIST mvlist = + grin_get_vertex_list_by_type_select_master(g, __vt); + size_t mvlist_sz = grin_get_vertex_list_size(g, mvlist); + for (size_t i = 0; i < mvlist_sz; ++i) { + GRIN_VERTEX v = grin_get_vertex_from_list(g, mvlist, i); + size_t pos = grin_get_position_of_vertex_from_sorted_list(g, mvlist, v); + assert(pos == i); + size_t pos1 = grin_get_position_of_vertex_from_sorted_list(g, vl, v); + GRIN_VERTEX v1 = grin_get_vertex_from_list(g, vl, pos1); + assert(grin_equal_vertex(g, v, v1)); + grin_destroy_vertex(g, v1); + grin_destroy_vertex(g, v); + } + grin_destroy_vertex_list(g, mvlist); + } + { + GRIN_VERTEX_LIST mvlist = + grin_get_vertex_list_by_type_select_mirror(g, __vt); + size_t mvlist_sz = grin_get_vertex_list_size(g, mvlist); + for (size_t i = 0; i < mvlist_sz; ++i) { + GRIN_VERTEX v = grin_get_vertex_from_list(g, mvlist, i); + size_t pos = grin_get_position_of_vertex_from_sorted_list(g, mvlist, v); + assert(pos == i); + size_t pos1 = grin_get_position_of_vertex_from_sorted_list(g, vl, v); + GRIN_VERTEX v1 = grin_get_vertex_from_list(g, vl, pos1); + assert(grin_equal_vertex(g, v, v1)); + grin_destroy_vertex(g, v1); + grin_destroy_vertex(g, v); + } + grin_destroy_vertex_list(g, mvlist); + } +#endif + FOR_VERTEX_LIST_END(g, vl) + + grin_destroy_graph(g); +} +#endif + +void test_index_internal_id(const char* uri_str) { + printf( + "+++++++++++++++++++++ Test index internal id +++++++++++++++++++++\n"); + GRIN_GRAPH g = get_graph(uri_str, 0); + + FOR_VERTEX_LIST_BEGIN(g, vl) + long long int min = grin_get_vertex_internal_id_lower_bound_by_type(g, __vt); + long long int max = grin_get_vertex_internal_id_upper_bound_by_type(g, __vt); + FOR_VERTEX_BEGIN(g, vl, v) +#ifdef GRIN_ENABLE_VERTEX_INTERNAL_ID_INDEX + long long int oid = grin_get_vertex_internal_id_by_type(g, __vt, v); + assert(oid >= min && oid < max); + GRIN_VERTEX v1 = grin_get_vertex_by_internal_id_by_type(g, __vt, oid); + assert(grin_equal_vertex(g, v, v1)); + grin_destroy_vertex(g, v1); +#endif + FOR_VERTEX_END(g, vl, v) + FOR_VERTEX_LIST_END(g, vl) + + grin_destroy_graph(g); +} + +void test_index(const char* uri_str) { +#if defined(GRIN_ASSUME_ALL_VERTEX_LIST_SORTED) && \ + defined(GRIN_ENABLE_VERTEX_LIST_ARRAY) + test_index_order(uri_str); +#endif +#ifdef GRIN_ENABLE_VERTEX_INTERNAL_ID_INDEX + test_index_internal_id(uri_str); +#endif +} + +void test_vertex_property_value(const char* uri_str) { + GRIN_GRAPH g = get_graph(uri_str, 0); + GRIN_VERTEX_TYPE vt = grin_get_vertex_type_by_name(g, "person"); + GRIN_VERTEX_PROPERTY vp = grin_get_vertex_property_by_name(g, vt, "age"); + GRIN_VERTEX v = get_one_person(g); + + struct timeval t1, t2; + gettimeofday(&t1, NULL); + for (int i = 0; i < 1000000; ++i) { + long long int age = grin_get_vertex_property_value_of_int32(g, v, vp); + } + gettimeofday(&t2, NULL); + double elapsedTime = (t2.tv_sec - t1.tv_sec) * 1000.0; + elapsedTime += (t2.tv_usec - t1.tv_usec) / 1000.0; + printf("%f ms.\n", elapsedTime); + grin_destroy_vertex(g, v); + grin_destroy_vertex_property(g, vp); + grin_destroy_vertex_type(g, vt); + grin_destroy_graph(g); +} + +void test_perf(const char* uri_str) { test_vertex_property_value(uri_str); } + +int main(int argc, char** argv) { + const char* uri_str = + "flex://" + "../../../../storages/rt_mutable_graph/modern_graph/"; + + test_index(uri_str); + test_property(uri_str); + // test_partition(uri_str); + test_topology(uri_str); + test_perf(uri_str); + return 0; +} diff --git a/flex/grin b/flex/grin new file mode 160000 index 000000000000..bcafca761f7a --- /dev/null +++ b/flex/grin @@ -0,0 +1 @@ +Subproject commit bcafca761f7ac44f2fb20f599d8ce7c13daae3d9 diff --git a/flex/scripts/install_dependencies.sh b/flex/scripts/install_dependencies.sh index 43268ccc1110..1d72c6f9e860 100644 --- a/flex/scripts/install_dependencies.sh +++ b/flex/scripts/install_dependencies.sh @@ -10,7 +10,7 @@ apt install -y xfslibs-dev libgnutls28-dev liblz4-dev maven openssl pkg-config \ git clone https://github.com/alibaba/libgrape-lite.git cd libgrape-lite -git checkout 976544ef7a9777ed93088459638ff87154e2109d +git checkout v0.3.2 mkdir build && cd build && cmake .. make -j && make install cp /usr/local/lib/libgrape-lite.so /usr/lib/libgrape-lite.so diff --git a/flex/storages/rt_mutable_graph/modern_graph/person_created_software.csv b/flex/storages/rt_mutable_graph/modern_graph/person_created_software.csv index 2b1d262322b5..248331e15956 100644 --- a/flex/storages/rt_mutable_graph/modern_graph/person_created_software.csv +++ b/flex/storages/rt_mutable_graph/modern_graph/person_created_software.csv @@ -2,4 +2,4 @@ person.id|software.id|weight 1|3|0.4 4|3|0.4 6|3|0.2 -4|5|1.0 \ No newline at end of file +2|5|1.0 \ No newline at end of file diff --git a/flex/storages/rt_mutable_graph/mutable_csr.cc b/flex/storages/rt_mutable_graph/mutable_csr.cc index c499453eb5db..8b84f9fd4461 100644 --- a/flex/storages/rt_mutable_graph/mutable_csr.cc +++ b/flex/storages/rt_mutable_graph/mutable_csr.cc @@ -170,4 +170,7 @@ template class MutableCsr; template class SingleMutableCsr; template class MutableCsr; +template class SingleMutableCsr; +template class MutableCsr; + } // namespace gs diff --git a/flex/storages/rt_mutable_graph/mutable_csr.h b/flex/storages/rt_mutable_graph/mutable_csr.h index 3b172824742b..5fa6b245103a 100644 --- a/flex/storages/rt_mutable_graph/mutable_csr.h +++ b/flex/storages/rt_mutable_graph/mutable_csr.h @@ -34,7 +34,9 @@ template struct MutableNbr { MutableNbr() = default; MutableNbr(const MutableNbr& rhs) - : neighbor(rhs.neighbor), timestamp(rhs.timestamp.load()), data(data) {} + : neighbor(rhs.neighbor), + timestamp(rhs.timestamp.load()), + data(rhs.data) {} ~MutableNbr() = default; vid_t neighbor; @@ -317,6 +319,8 @@ class MutableCsrBase { virtual std::shared_ptr edge_iter( vid_t v) const = 0; + virtual MutableCsrConstEdgeIterBase* edge_iter_raw(vid_t v) const = 0; + virtual std::shared_ptr edge_iter_mut(vid_t v) = 0; }; @@ -472,6 +476,9 @@ class MutableCsr : public TypedMutableCsrBase { get_edges(v)); } + MutableCsrConstEdgeIterBase* edge_iter_raw(vid_t v) const override { + return new TypedMutableCsrConstEdgeIter(get_edges(v)); + } std::shared_ptr edge_iter_mut(vid_t v) override { return std::make_shared>(get_edges_mut(v)); } @@ -576,6 +583,10 @@ class MutableCsr : public TypedMutableCsrBase { get_edges(v)); } + MutableCsrConstEdgeIterBase* edge_iter_raw(vid_t v) const override { + return new TypedMutableCsrConstEdgeIter(get_edges(v)); + } + std::shared_ptr edge_iter_mut(vid_t v) override { return std::make_shared>( get_edges_mut(v)); @@ -680,6 +691,10 @@ class SingleMutableCsr : public TypedMutableCsrBase { get_edges(v)); } + MutableCsrConstEdgeIterBase* edge_iter_raw(vid_t v) const override { + return new TypedMutableCsrConstEdgeIter(get_edges(v)); + } + std::shared_ptr edge_iter_mut(vid_t v) override { return std::make_shared>(get_edges_mut(v)); } diff --git a/flex/storages/rt_mutable_graph/mutable_property_fragment.cc b/flex/storages/rt_mutable_graph/mutable_property_fragment.cc index 5b4a1350365e..ca716c2802d5 100644 --- a/flex/storages/rt_mutable_graph/mutable_property_fragment.cc +++ b/flex/storages/rt_mutable_graph/mutable_property_fragment.cc @@ -46,6 +46,7 @@ void MutablePropertyFragment::initVertices( auto& table = vertex_data_[v_label_i]; auto& property_types = schema_.get_vertex_properties(v_label_name); size_t col_num = property_types.size(); + std::vector col_names; for (size_t col_i = 0; col_i < col_num; ++col_i) { col_names.push_back("col_" + std::to_string(col_i)); @@ -96,7 +97,10 @@ class EmptyCsr : public TypedMutableCsrBase { return std::make_shared>( MutableNbrSlice::empty()); } - + MutableCsrConstEdgeIterBase* edge_iter_raw(vid_t v) const override { + return new TypedMutableCsrConstEdgeIter( + MutableNbrSlice::empty()); + } std::shared_ptr edge_iter_mut(vid_t v) override { return std::make_shared>( MutableNbrSliceMut::empty()); @@ -272,6 +276,17 @@ void MutablePropertyFragment::initEdges( } else { LOG(FATAL) << "Unsupported edge property type."; } + } else if (property_types[0] == PropertyType::kDouble) { + if (filenames.empty()) { + std::tie(ie_[index], oe_[index]) = + construct_empty_csr(ie_strtagy, oe_strtagy); + } else { + std::tie(ie_[index], oe_[index]) = construct_csr( + filenames, property_types, ie_strtagy, oe_strtagy, + lf_indexers_[src_label_i], lf_indexers_[dst_label_i]); + + // LOG(FATAL) << "Unsupported edge property type."; + } } else { LOG(FATAL) << "Unsupported edge property type."; } @@ -575,6 +590,20 @@ MutablePropertyFragment::get_incoming_edges(label_t label, vid_t u, return ie_[index]->edge_iter(u); } +MutableCsrConstEdgeIterBase* MutablePropertyFragment::get_outgoing_edges_raw( + label_t label, vid_t u, label_t neighbor_label, label_t edge_label) const { + size_t index = label * vertex_label_num_ * edge_label_num_ + + neighbor_label * edge_label_num_ + edge_label; + return oe_[index]->edge_iter_raw(u); +} + +MutableCsrConstEdgeIterBase* MutablePropertyFragment::get_incoming_edges_raw( + label_t label, vid_t u, label_t neighbor_label, label_t edge_label) const { + size_t index = neighbor_label * vertex_label_num_ * edge_label_num_ + + label * edge_label_num_ + edge_label; + return ie_[index]->edge_iter_raw(u); +} + std::shared_ptr MutablePropertyFragment::get_outgoing_edges_mut(label_t label, vid_t u, label_t neighbor_label, diff --git a/flex/storages/rt_mutable_graph/mutable_property_fragment.h b/flex/storages/rt_mutable_graph/mutable_property_fragment.h index b275c301d6fb..3b3454b97c97 100644 --- a/flex/storages/rt_mutable_graph/mutable_property_fragment.h +++ b/flex/storages/rt_mutable_graph/mutable_property_fragment.h @@ -65,7 +65,6 @@ class MutablePropertyFragment { oid_t get_oid(label_t label, vid_t lid) const; vid_t add_vertex(label_t label, oid_t id); - std::shared_ptr get_outgoing_edges( label_t label, vid_t u, label_t neighbor_label, label_t edge_label) const; @@ -78,6 +77,14 @@ class MutablePropertyFragment { std::shared_ptr get_incoming_edges_mut( label_t label, vid_t u, label_t neighbor_label, label_t edge_label); + MutableCsrConstEdgeIterBase* get_outgoing_edges_raw(label_t label, vid_t u, + label_t neighbor_label, + label_t edge_label) const; + + MutableCsrConstEdgeIterBase* get_incoming_edges_raw(label_t label, vid_t u, + label_t neighbor_label, + label_t edge_label) const; + MutableCsrBase* get_oe_csr(label_t label, label_t neighbor_label, label_t edge_label); diff --git a/flex/storages/rt_mutable_graph/schema.cc b/flex/storages/rt_mutable_graph/schema.cc index be8b4f0473dd..c17c78f5d50d 100644 --- a/flex/storages/rt_mutable_graph/schema.cc +++ b/flex/storages/rt_mutable_graph/schema.cc @@ -359,6 +359,8 @@ static PropertyType StringToPropertyType(const std::string& str) { return PropertyType::kEmpty; } else if (str == "int64") { return PropertyType::kInt64; + } else if (str == "double") { + return PropertyType::kDouble; } else { return PropertyType::kEmpty; } @@ -543,6 +545,29 @@ static bool parse_edges_schema(YAML::Node node, Schema& schema) { return true; } +static bool access_file(std::string& file_path) { + if (file_path.size() == 0) { + return false; + } + if (file_path[0] == '/') { + std::filesystem::path path(file_path); + return std::filesystem::exists(path); + } + char* flex_data_dir = std::getenv("FLEX_DATA_DIR"); + if (flex_data_dir != NULL) { + auto temp = std::string(flex_data_dir) + "/" + file_path; + std::filesystem::path path(temp); + if (std::filesystem::exists(path)) { + file_path = temp; + return true; + } + } + file_path = + std::filesystem::current_path().generic_string() + "/" + file_path; + std::filesystem::path path(file_path); + return std::filesystem::exists(path); +} + static bool parse_vertex_files( YAML::Node node, std::vector>& files) { std::string label_name; @@ -569,10 +594,10 @@ static bool parse_vertex_files( if (!get_scalar(files_node[i], "path", file_path)) { return false; } - std::filesystem::path path(file_path); - if (!std::filesystem::exists(path)) { + if (!access_file(file_path)) { LOG(ERROR) << "vertex file - " << file_path << " file not found..."; } + std::filesystem::path path(file_path); files.emplace_back(label_name, std::filesystem::canonical(path)); } return true; @@ -630,10 +655,10 @@ static bool parse_edge_files( if (!get_scalar(files_node[i], "path", file_path)) { return false; } - std::filesystem::path path(file_path); - if (!std::filesystem::exists(path)) { + if (!access_file(file_path)) { LOG(ERROR) << "edge file - " << file_path << " file not found..."; } + std::filesystem::path path(file_path); files.emplace_back(src_label, dst_label, edge_label, std::filesystem::canonical(path)); } diff --git a/flex/utils/property/column.h b/flex/utils/property/column.h index ec2661360d9b..b79356e5f576 100644 --- a/flex/utils/property/column.h +++ b/flex/utils/property/column.h @@ -96,6 +96,7 @@ using IntColumn = TypedColumn; using LongColumn = TypedColumn; using DateColumn = TypedColumn; using StringColumn = TypedColumn; +using DoubleColumn = TypedColumn; std::shared_ptr CreateColumn( PropertyType type, StorageStrategy strategy = StorageStrategy::kMem); diff --git a/flex/utils/property/table.cc b/flex/utils/property/table.cc index 2833717f77e2..2c53de48db1c 100644 --- a/flex/utils/property/table.cc +++ b/flex/utils/property/table.cc @@ -60,6 +60,22 @@ std::vector Table::column_names() const { return names; } +std::string Table::column_name(size_t index) const { + size_t col_num = col_id_indexer_.size(); + CHECK(index < col_num); + std::string name{}; + CHECK(col_id_indexer_.get_key(index, name)); + return name; +} + +int Table::get_column_id_by_name(const std::string& name) const { + int col_id; + if (col_id_indexer_.get_index(name, col_id)) { + return col_id; + } + return -1; +} + std::vector Table::column_types() const { size_t col_num = col_id_indexer_.size(); std::vector types(col_num); diff --git a/flex/utils/property/table.h b/flex/utils/property/table.h index 0b4e5fcbdc42..4fa2110ffab4 100644 --- a/flex/utils/property/table.h +++ b/flex/utils/property/table.h @@ -41,6 +41,10 @@ class Table { std::vector column_names() const; + std::string column_name(size_t index) const; + + int get_column_id_by_name(const std::string& name) const; + std::vector column_types() const; std::shared_ptr get_column(const std::string& name); diff --git a/flex/utils/property/types.cc b/flex/utils/property/types.cc index cfcdaaa56a63..f1e93c687802 100644 --- a/flex/utils/property/types.cc +++ b/flex/utils/property/types.cc @@ -40,6 +40,10 @@ inline void ParseString(const std::string_view& str, std::string_view& val) { val = str; } +inline void ParseDouble(const std::string_view& str, double& val) { + sscanf(str.data(), "%lf", &val); +} + void ParseRecord(const char* line, std::vector& rec) { const char* cur = line; for (auto& item : rec) { @@ -56,6 +60,8 @@ void ParseRecord(const char* line, std::vector& rec) { ParseDate(sv, item.value.d); } else if (item.type == PropertyType::kString) { ParseString(sv, item.value.s); + } else if (item.type == PropertyType::kDouble) { + ParseDouble(sv, item.value.db); } cur = ptr + 1; } @@ -102,9 +108,17 @@ void ParseRecordX(const char* line, int64_t& src, int64_t& dst, #endif } -// parseRecordX for edge with int64 property +void ParseRecordX(const char* line, int64_t& src, int64_t& dst, double& prop) { +#ifdef __APPLE__ + sscanf(line, "%lld|%lld|%lf", &src, &dst, &prop); +#else + sscanf(line, "%" SCNd64 "|%" SCNd64 "|%lf", &src, &dst, &prop); +#endif +} + void ParseRecordX(const char* line, int64_t& src, int64_t& dst, int64_t& prop) { #ifdef __APPLE__ + // parseRecordX for edge with int64 property sscanf(line, "%lld|%lld|%lld", &src, &dst, &prop); #else sscanf(line, "%" SCNd64 "|%" SCNd64 "|%" SCNd64 "", &src, &dst, &prop); @@ -125,6 +139,9 @@ grape::InArchive& operator<<(grape::InArchive& in_archive, const Any& value) { case PropertyType::kString: in_archive << value.type << value.value.s; break; + case PropertyType::kDouble: + in_archive << value.type << value.value.db; + break; default: in_archive << PropertyType::kEmpty; break; @@ -148,6 +165,9 @@ grape::OutArchive& operator>>(grape::OutArchive& out_archive, Any& value) { case PropertyType::kString: out_archive >> value.value.s; break; + case PropertyType::kDouble: + out_archive >> value.value.db; + break; default: break; } diff --git a/flex/utils/property/types.h b/flex/utils/property/types.h index 054d6a845202..8dc83aa468a1 100644 --- a/flex/utils/property/types.h +++ b/flex/utils/property/types.h @@ -38,15 +38,16 @@ enum class PropertyType { kString, kEmpty, kInt64, + kDouble, }; struct Date { Date() = default; ~Date() = default; Date(int64_t x); - Date(const char *str); + Date(const char* str); - void reset(const char *str); + void reset(const char* str); std::string to_string() const; int64_t milli_second; @@ -60,9 +61,11 @@ union AnyValue { int64_t l; Date d; std::string_view s; + double db; }; -template struct AnyConverter; +template +struct AnyConverter; struct Any { Any() : type(PropertyType::kEmpty) {} @@ -97,6 +100,11 @@ struct Any { value.s = v; } + void set_double(double db) { + type = PropertyType::kDouble; + value.db = db; + } + std::string to_string() const { if (type == PropertyType::kInt32) { return std::to_string(value.i); @@ -109,6 +117,8 @@ struct Any { return value.d.to_string(); } else if (type == PropertyType::kEmpty) { return "NULL"; + } else if (type == PropertyType::kDouble) { + return std::to_string(value.db); } else { LOG(FATAL) << "Unexpected property type: " << static_cast(type); return ""; @@ -125,17 +135,23 @@ struct Any { return value.l; } - const std::string_view &AsStringView() const { + double AsDouble() const { + assert(type == PropertyType::kDouble); + return value.db; + } + + const std::string_view& AsStringView() const { assert(type == PropertyType::kString); return value.s; } - const Date &AsDate() const { + const Date& AsDate() const { assert(type == PropertyType::kDate); return value.d; } - template static Any From(const T &value) { + template + static Any From(const T& value) { return AnyConverter::to_any(value); } @@ -143,222 +159,271 @@ struct Any { AnyValue value; }; -template struct ConvertAny { - static void to(const Any &value, T &out) { +template +struct ConvertAny { + static void to(const Any& value, T& out) { LOG(FATAL) << "Unexpected convert type..."; } }; -template <> struct ConvertAny { - static void to(const Any &value, int &out) { +template <> +struct ConvertAny { + static void to(const Any& value, int& out) { CHECK(value.type == PropertyType::kInt32); out = value.value.i; } }; -template <> struct ConvertAny { - static void to(const Any &value, int64_t &out) { +template <> +struct ConvertAny { + static void to(const Any& value, int64_t& out) { CHECK(value.type == PropertyType::kInt64); out = value.value.l; } }; -template <> struct ConvertAny { - static void to(const Any &value, Date &out) { +template <> +struct ConvertAny { + static void to(const Any& value, Date& out) { CHECK(value.type == PropertyType::kDate); out = value.value.d; } }; -template <> struct ConvertAny { - static void to(const Any &value, grape::EmptyType &out) { +template <> +struct ConvertAny { + static void to(const Any& value, grape::EmptyType& out) { CHECK(value.type == PropertyType::kEmpty); } }; -template <> struct ConvertAny { - static void to(const Any &value, std::string &out) { +template <> +struct ConvertAny { + static void to(const Any& value, std::string& out) { CHECK(value.type == PropertyType::kString); out = std::string(value.value.s); } }; -template struct AnyConverter {}; +template <> +struct ConvertAny { + static void to(const Any& value, double& out) { + CHECK(value.type == PropertyType::kDouble); + out = value.value.db; + } +}; -template <> struct AnyConverter { +template +struct AnyConverter {}; + +template <> +struct AnyConverter { static constexpr PropertyType type = PropertyType::kInt32; - static Any to_any(const int &value) { + static Any to_any(const int& value) { Any ret; ret.set_integer(value); return ret; } - static AnyValue to_any_value(const int &value) { + static AnyValue to_any_value(const int& value) { AnyValue ret; ret.i = value; return ret; } - static const int &from_any(const Any &value) { + static const int& from_any(const Any& value) { CHECK(value.type == PropertyType::kInt32); return value.value.i; } - static const int &from_any_value(const AnyValue &value) { return value.i; } + static const int& from_any_value(const AnyValue& value) { return value.i; } }; -template <> struct AnyConverter { +template <> +struct AnyConverter { static constexpr PropertyType type = PropertyType::kInt64; - static Any to_any(const int64_t &value) { + static Any to_any(const int64_t& value) { Any ret; ret.set_long(value); return ret; } - static AnyValue to_any_value(const int64_t &value) { + static AnyValue to_any_value(const int64_t& value) { AnyValue ret; ret.l = value; return ret; } - static const int64_t &from_any(const Any &value) { + static const int64_t& from_any(const Any& value) { CHECK(value.type == PropertyType::kInt64); return value.value.l; } - static const int64_t &from_any_value(const AnyValue &value) { + static const int64_t& from_any_value(const AnyValue& value) { return value.l; } }; -template <> struct AnyConverter { +template <> +struct AnyConverter { static constexpr PropertyType type = PropertyType::kDate; - static Any to_any(const Date &value) { + static Any to_any(const Date& value) { Any ret; ret.set_date(value); return ret; } - static AnyValue to_any_value(const Date &value) { + static AnyValue to_any_value(const Date& value) { AnyValue ret; ret.d = value; return ret; } - static const Date &from_any(const Any &value) { + static const Date& from_any(const Any& value) { CHECK(value.type == PropertyType::kDate); return value.value.d; } - static const Date &from_any_value(const AnyValue &value) { return value.d; } + static const Date& from_any_value(const AnyValue& value) { return value.d; } }; -template <> struct AnyConverter { +template <> +struct AnyConverter { static constexpr PropertyType type = PropertyType::kString; - static Any to_any(const std::string_view &value) { + static Any to_any(const std::string_view& value) { Any ret; ret.set_string(value); return ret; } - static AnyValue to_any_value(const std::string_view &value) { + static AnyValue to_any_value(const std::string_view& value) { AnyValue ret; ret.s = value; return ret; } - static const std::string_view &from_any(const Any &value) { + static const std::string_view& from_any(const Any& value) { CHECK(value.type == PropertyType::kString); return value.value.s; } - static const std::string_view &from_any_value(const AnyValue &value) { + static const std::string_view& from_any_value(const AnyValue& value) { return value.s; } }; -template <> struct AnyConverter { +template <> +struct AnyConverter { static constexpr PropertyType type = PropertyType::kString; - static Any to_any(const std::string &value) { + static Any to_any(const std::string& value) { Any ret; ret.set_string(value); return ret; } - static AnyValue to_any_value(const std::string &value) { + static AnyValue to_any_value(const std::string& value) { AnyValue ret; ret.s = value; return ret; } - static std::string from_any(const Any &value) { + static std::string from_any(const Any& value) { CHECK(value.type == PropertyType::kString); return std::string(value.value.s); } - static std::string from_any_value(const AnyValue &value) { + static std::string from_any_value(const AnyValue& value) { return std::string(value.s); } }; -template <> struct AnyConverter { +template <> +struct AnyConverter { static constexpr PropertyType type = PropertyType::kEmpty; - static Any to_any(const grape::EmptyType &value) { + static Any to_any(const grape::EmptyType& value) { Any ret; return ret; } - static AnyValue to_any_value(const grape::EmptyType &value) { + static AnyValue to_any_value(const grape::EmptyType& value) { AnyValue ret; return ret; } - static grape::EmptyType from_any(const Any &value) { + static grape::EmptyType from_any(const Any& value) { CHECK(value.type == PropertyType::kEmpty); return grape::EmptyType(); } - static grape::EmptyType from_any_value(const AnyValue &value) { + static grape::EmptyType from_any_value(const AnyValue& value) { return grape::EmptyType(); } }; -void ParseRecord(const char *line, std::vector &rec); +template <> +struct AnyConverter { + static constexpr PropertyType type = PropertyType::kDouble; + + static Any to_any(const double& value) { + Any ret; + ret.set_double(value); + return ret; + } + + static AnyValue to_any_value(const double& value) { + AnyValue ret; + ret.db = value; + return ret; + } + + static const double& from_any(const Any& value) { + CHECK(value.type == PropertyType::kDouble); + return value.value.db; + } + + static const double& from_any_value(const AnyValue& value) { + return value.db; + } +}; + +void ParseRecord(const char* line, std::vector& rec); -void ParseRecord(const char *line, int64_t &id, std::vector &rec); +void ParseRecord(const char* line, int64_t& id, std::vector& rec); -void ParseRecordX(const char *line, int64_t &src, int64_t &dst, int &prop); +void ParseRecordX(const char* line, int64_t& src, int64_t& dst, int& prop); -void ParseRecordX(const char *line, int64_t &src, int64_t &dst, Date &prop); +void ParseRecordX(const char* line, int64_t& src, int64_t& dst, Date& prop); -void ParseRecordX(const char *line, int64_t &src, int64_t &dst, - grape::EmptyType &prop); +void ParseRecordX(const char* line, int64_t& src, int64_t& dst, + grape::EmptyType& prop); +void ParseRecordX(const char* line, int64_t& src, int64_t& dst, double& prop); -void ParseRecordX(const char *line, int64_t &src, int64_t &dst, - int64_t &prop); +void ParseRecordX(const char* line, int64_t& src, int64_t& dst, int64_t& prop); -grape::InArchive &operator<<(grape::InArchive &in_archive, const Any &value); -grape::OutArchive &operator>>(grape::OutArchive &out_archive, Any &value); +grape::InArchive& operator<<(grape::InArchive& in_archive, const Any& value); +grape::OutArchive& operator>>(grape::OutArchive& out_archive, Any& value); -grape::InArchive &operator<<(grape::InArchive &in_archive, const std::string_view &value); -grape::OutArchive &operator>>(grape::OutArchive &out_archive, std::string_view &value); +grape::InArchive& operator<<(grape::InArchive& in_archive, + const std::string_view& value); +grape::OutArchive& operator>>(grape::OutArchive& out_archive, + std::string_view& value); -} // namespace gs +} // namespace gs namespace std { -inline ostream &operator<<(ostream &os, const gs::Date &dt) { +inline ostream& operator<<(ostream& os, const gs::Date& dt) { os << dt.to_string(); return os; } -inline ostream &operator<<(ostream &os, gs::PropertyType pt) { +inline ostream& operator<<(ostream& os, gs::PropertyType pt) { switch (pt) { case gs::PropertyType::kInt32: os << "int32"; @@ -375,6 +440,9 @@ inline ostream &operator<<(ostream &os, gs::PropertyType pt) { case gs::PropertyType::kEmpty: os << "Empty"; break; + case gs::PropertyType::kDouble: + os << "double"; + break; default: os << "Unknown"; break; @@ -382,6 +450,6 @@ inline ostream &operator<<(ostream &os, gs::PropertyType pt) { return os; } -} // namespace std +} // namespace std -#endif // GRAPHSCOPE_TYPES_H_ +#endif // GRAPHSCOPE_TYPES_H_