diff --git a/CHANGELOGS.md b/CHANGELOGS.md index d9ef3d4c36..bbe0d9fc60 100644 --- a/CHANGELOGS.md +++ b/CHANGELOGS.md @@ -17,3 +17,4 @@ Please mark all change in change log and use the ticket from JIRA. - MS-1 - Add CHANGELOG.md - MS-161 - Add CI / CD Module to Milvus Project - MS-202 - Add Milvus Jenkins project email notification +- MS-215 - Add Milvus cluster CI/CD groovy file diff --git a/ci/jenkinsfile/milvus_build.groovy b/ci/jenkinsfile/milvus_build.groovy index 99892c90ef..016acfdefa 100644 --- a/ci/jenkinsfile/milvus_build.groovy +++ b/ci/jenkinsfile/milvus_build.groovy @@ -1,5 +1,5 @@ container('milvus-build-env') { - timeout(time: 20, unit: 'MINUTES') { + timeout(time: 30, unit: 'MINUTES') { gitlabCommitStatus(name: 'Build Engine') { dir ("milvus_engine") { try { @@ -17,4 +17,3 @@ container('milvus-build-env') { } } } - diff --git a/ci/jenkinsfile/milvus_build_no_ut.groovy b/ci/jenkinsfile/milvus_build_no_ut.groovy index 6c30ce491c..f4e243f1cc 100644 --- a/ci/jenkinsfile/milvus_build_no_ut.groovy +++ b/ci/jenkinsfile/milvus_build_no_ut.groovy @@ -1,5 +1,5 @@ container('milvus-build-env') { - timeout(time: 20, unit: 'MINUTES') { + timeout(time: 30, unit: 'MINUTES') { gitlabCommitStatus(name: 'Build Engine') { dir ("milvus_engine") { try { @@ -17,4 +17,3 @@ container('milvus-build-env') { } } } - diff --git a/ci/main_jenkinsfile b/ci/main_jenkinsfile index 9577837bfd..d4132e9ff1 100644 --- a/ci/main_jenkinsfile +++ b/ci/main_jenkinsfile @@ -35,7 +35,7 @@ pipeline { defaultContainer 'jnlp' containerTemplate { name 'milvus-build-env' - image 'registry.zilliz.com/milvus/milvus-build-env:v0.10' + image 'registry.zilliz.com/milvus/milvus-build-env:v0.11' ttyEnabled true command 'cat' } diff --git a/ci/main_jenkinsfile_no_ut b/ci/main_jenkinsfile_no_ut index 082433650c..0b2f90fd63 100644 --- a/ci/main_jenkinsfile_no_ut +++ b/ci/main_jenkinsfile_no_ut @@ -35,7 +35,7 @@ pipeline { defaultContainer 'jnlp' containerTemplate { name 'milvus-build-env' - image 'registry.zilliz.com/milvus/milvus-build-env:v0.10' + image 'registry.zilliz.com/milvus/milvus-build-env:v0.11' ttyEnabled true command 'cat' } diff --git a/ci/nightly_main_jenkinsfile b/ci/nightly_main_jenkinsfile index 7f59561f82..5458cf7632 100644 --- a/ci/nightly_main_jenkinsfile +++ b/ci/nightly_main_jenkinsfile @@ -35,7 +35,7 @@ pipeline { defaultContainer 'jnlp' containerTemplate { name 'milvus-build-env' - image 'registry.zilliz.com/milvus/milvus-build-env:v0.10' + image 'registry.zilliz.com/milvus/milvus-build-env:v0.11' ttyEnabled true command 'cat' } diff --git a/cpp/CHANGELOG.md b/cpp/CHANGELOG.md index 7e7f88a2e9..fd0d2dfae9 100644 --- a/cpp/CHANGELOG.md +++ b/cpp/CHANGELOG.md @@ -9,9 +9,17 @@ Please mark all change in change log and use the ticket from JIRA. - MS-148 - Disable cleanup if mode is read only - MS-149 - Fixed searching only one index file issue in distributed mode -- MS-153 - fix c_str error when connecting to MySQL -- MS-157 - fix changelog -- MS-190 - use env variable to switch mem manager and fix cmake +- MS-153 - Fix c_str error when connecting to MySQL +- MS-157 - Fix changelog +- MS-190 - Use env variable to switch mem manager and fix cmake +- MS-217 - Fix SQ8 row count bug +- MS-224 - Return AlreadyExist status in MySQLMetaImpl::CreateTable if table already exists +- MS-232 - Add MySQLMetaImpl::UpdateTableFilesToIndex and set maximum_memory to default if config value = 0 +- MS-233 - Remove mem manager log +- MS-230 - Change parameter name: Maximum_memory to insert_buffer_size +- MS-234 - Some case cause background merge thread stop +- MS-235 - Some test cases random fail +- MS-236 - Add MySQLMetaImpl::HasNonIndexFiles ## Improvement - MS-156 - Add unittest for merge result functions @@ -20,12 +28,13 @@ Please mark all change in change log and use the ticket from JIRA. - MS-206 - Support SQ8 index type - MS-208 - Add buildinde interface for C++ SDK - MS-212 - Support Inner product metric type - -## New Feature -- MS-195 - Add nlist and use_blas_threshold conf +- MS-241 - Build Faiss with MKL if using Intel CPU; else build with OpenBlas +- MS-242 - Clean up cmake and change MAKE_BUILD_ARGS to be user defined variable +- MS-245 - Improve search result transfer performance ## New Feature - MS-180 - Add new mem manager +- MS-195 - Add nlist and use_blas_threshold conf ## Task diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index 3a0e8900a6..07b4719790 100644 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -116,6 +116,11 @@ set(MILVUS_ENGINE_SRC ${PROJECT_SOURCE_DIR}/src) add_compile_definitions(PROFILER=${PROFILER}) +message("MILVUS_ENABLE_PROFILING = ${MILVUS_ENABLE_PROFILING}") +if (MILVUS_ENABLE_PROFILING STREQUAL "ON") + ADD_DEFINITIONS(-DMILVUS_ENABLE_PROFILING) +endif() + include_directories(${MILVUS_ENGINE_INCLUDE}) include_directories(${MILVUS_ENGINE_SRC}) diff --git a/cpp/README.md b/cpp/README.md index 1b2f507db2..b46515a1cf 100644 --- a/cpp/README.md +++ b/cpp/README.md @@ -1,13 +1,13 @@ ### Compilation #### Step 1: install necessery tools - Install MySQL - centos7 : - yum install gfortran qt4 flex bison mysql-devel + yum install gfortran qt4 flex bison mysql-devel mysql ubuntu16.04 : - sudo apt-get install gfortran qt4-qmake flex bison libmysqlclient-dev + sudo apt-get install gfortran qt4-qmake flex bison libmysqlclient-dev mysql-client + + cd scripts && sudo ./requirements.sh If `libmysqlclient_r.so` does not exist after installing MySQL Development Files, you need to create a symbolic link: diff --git a/cpp/build.sh b/cpp/build.sh index 80be1d7ddb..52ac97d22a 100755 --- a/cpp/build.sh +++ b/cpp/build.sh @@ -7,8 +7,9 @@ INSTALL_PREFIX=$(pwd)/milvus MAKE_CLEAN="OFF" BUILD_COVERAGE="OFF" DB_PATH="/opt/milvus" +PROFILING="OFF" -while getopts "p:d:t:uhlrc" arg +while getopts "p:d:t:uhlrcg" arg do case $arg in t) @@ -36,6 +37,9 @@ do c) BUILD_COVERAGE="ON" ;; + g) + PROFILING="ON" + ;; h) # help echo " @@ -47,6 +51,7 @@ parameter: -l: build license version(default: OFF) -r: remove previous build directory(default: OFF) -c: code coverage(default: OFF) +-g: profiling(default: OFF) usage: ./build.sh -t \${BUILD_TYPE} [-u] [-h] [-g] [-r] [-c] @@ -77,6 +82,7 @@ if [[ ${MAKE_CLEAN} == "ON" ]]; then -DCMAKE_LICENSE_CHECK=${LICENSE_CHECK} \ -DBUILD_COVERAGE=${BUILD_COVERAGE} \ -DMILVUS_DB_PATH=${DB_PATH} \ + -DMILVUS_ENABLE_PROFILING=${PROFILING} \ $@ ../" echo ${CMAKE_CMD} diff --git a/cpp/cmake/DefineOptions.cmake b/cpp/cmake/DefineOptions.cmake index 147663d0db..cc9792391d 100644 --- a/cpp/cmake/DefineOptions.cmake +++ b/cpp/cmake/DefineOptions.cmake @@ -57,8 +57,6 @@ define_option(MILVUS_VERBOSE_THIRDPARTY_BUILD define_option(MILVUS_WITH_ARROW "Build with ARROW" OFF) -define_option(MILVUS_BOOST_USE_SHARED "Rely on boost shared libraries where relevant" OFF) - define_option(MILVUS_BOOST_VENDORED "Use vendored Boost instead of existing Boost. \ Note that this requires linking Boost statically" ON) @@ -111,6 +109,11 @@ define_option(MILVUS_WITH_ZSTD "Build with zstd compression" ${MILVUS_WITH_ZSTD_ define_option(MILVUS_WITH_AWS "Build with AWS SDK" ON) +if (MILVUS_ENABLE_PROFILING STREQUAL "ON") + define_option(MILVUS_WITH_LIBUNWIND "Build with libunwind" ON) + define_option(MILVUS_WITH_GPERFTOOLS "Build with gperftools" ON) +endif() + #---------------------------------------------------------------------- if(MSVC) set_option_category("MSVC") diff --git a/cpp/cmake/ThirdPartyPackages.cmake b/cpp/cmake/ThirdPartyPackages.cmake index 9e19b037f8..20292cdd32 100644 --- a/cpp/cmake/ThirdPartyPackages.cmake +++ b/cpp/cmake/ThirdPartyPackages.cmake @@ -5,7 +5,6 @@ # to you 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, @@ -37,7 +36,9 @@ set(MILVUS_THIRDPARTY_DEPENDENCIES yaml-cpp ZLIB ZSTD - AWS) + AWS + libunwind + gperftools) message(STATUS "Using ${MILVUS_DEPENDENCY_SOURCE} approach to find dependencies") @@ -89,6 +90,10 @@ macro(build_dependency DEPENDENCY_NAME) build_zstd() elseif("${DEPENDENCY_NAME}" STREQUAL "AWS") build_aws() + elseif("${DEPENDENCY_NAME}" STREQUAL "libunwind") + build_libunwind() + elseif("${DEPENDENCY_NAME}" STREQUAL "gperftools") + build_gperftools() else() message(FATAL_ERROR "Unknown thirdparty dependency to build: ${DEPENDENCY_NAME}") endif () @@ -96,12 +101,8 @@ endmacro() macro(resolve_dependency DEPENDENCY_NAME) if (${DEPENDENCY_NAME}_SOURCE STREQUAL "AUTO") - #message(STATUS "Finding ${DEPENDENCY_NAME} package") -# find_package(${DEPENDENCY_NAME} QUIET) -# if (NOT ${DEPENDENCY_NAME}_FOUND) - #message(STATUS "${DEPENDENCY_NAME} package not found") + #disable find_package for now build_dependency(${DEPENDENCY_NAME}) -# endif () elseif (${DEPENDENCY_NAME}_SOURCE STREQUAL "BUNDLED") build_dependency(${DEPENDENCY_NAME}) elseif (${DEPENDENCY_NAME}_SOURCE STREQUAL "SYSTEM") @@ -117,11 +118,9 @@ string(TOUPPER ${CMAKE_BUILD_TYPE} UPPERCASE_BUILD_TYPE) set(EP_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${UPPERCASE_BUILD_TYPE}}") set(EP_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${UPPERCASE_BUILD_TYPE}}") -if(NOT MSVC) - # Set -fPIC on all external projects - set(EP_CXX_FLAGS "${EP_CXX_FLAGS} -fPIC") - set(EP_C_FLAGS "${EP_C_FLAGS} -fPIC") -endif() +# Set -fPIC on all external projects +set(EP_CXX_FLAGS "${EP_CXX_FLAGS} -fPIC") +set(EP_C_FLAGS "${EP_C_FLAGS} -fPIC") # CC/CXX environment variables are captured on the first invocation of the # builder (e.g make or ninja) instead of when CMake is invoked into to build @@ -159,20 +158,13 @@ endif() # Ensure that a default make is set if("${MAKE}" STREQUAL "") - if(NOT MSVC) - find_program(MAKE make) - endif() + find_program(MAKE make) endif() -set(MAKE_BUILD_ARGS "-j2") - -## Using make -j in sub-make is fragile -#if(${CMAKE_GENERATOR} MATCHES "Makefiles") -# set(MAKE_BUILD_ARGS "") -#else() -# # limit the maximum number of jobs for ninja -# set(MAKE_BUILD_ARGS "-j4") -#endif() +if (NOT DEFINED MAKE_BUILD_ARGS) + set(MAKE_BUILD_ARGS "-j8") +endif() +message(STATUS "Third Party MAKE_BUILD_ARGS = ${MAKE_BUILD_ARGS}") # ---------------------------------------------------------------------- # Find pthreads @@ -285,7 +277,6 @@ if (DEFINED ENV{MILVUS_PROMETHEUS_URL}) set(PROMETHEUS_SOURCE_URL "$ENV{PROMETHEUS_OPENBLAS_URL}") else () set(PROMETHEUS_SOURCE_URL - #"https://github.com/JinHai-CN/prometheus-cpp/archive/${PROMETHEUS_VERSION}.tar.gz" https://github.com/jupp0r/prometheus-cpp.git) endif() @@ -347,6 +338,21 @@ if(DEFINED ENV{MILVUS_AWS_URL}) else() set(AWS_SOURCE_URL "https://github.com/aws/aws-sdk-cpp/archive/${AWS_VERSION}.tar.gz") endif() + +if(DEFINED ENV{MILVUS_LIBUNWIND_URL}) + set(LIBUNWIND_SOURCE_URL "$ENV{MILVUS_LIBUNWIND_URL}") +else() + set(LIBUNWIND_SOURCE_URL + "https://github.com/libunwind/libunwind/releases/download/v${LIBUNWIND_VERSION}/libunwind-${LIBUNWIND_VERSION}.tar.gz") +endif() + +if(DEFINED ENV{MILVUS_GPERFTOOLS_URL}) + set(GPERFTOOLS_SOURCE_URL "$ENV{MILVUS_GPERFTOOLS_URL}") +else() + set(GPERFTOOLS_SOURCE_URL + "https://github.com/gperftools/gperftools/releases/download/gperftools-${GPERFTOOLS_VERSION}/gperftools-${GPERFTOOLS_VERSION}.tar.gz") +endif() + # ---------------------------------------------------------------------- # ARROW @@ -354,19 +360,13 @@ macro(build_arrow) message(STATUS "Building Apache ARROW-${ARROW_VERSION} from source") set(ARROW_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/arrow_ep-prefix/src/arrow_ep/cpp") set(ARROW_STATIC_LIB_NAME arrow) -# set(ARROW_CUDA_STATIC_LIB_NAME arrow_cuda) + set(ARROW_STATIC_LIB "${ARROW_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}${ARROW_STATIC_LIB_NAME}${CMAKE_STATIC_LIBRARY_SUFFIX}" ) -# set(ARROW_CUDA_STATIC_LIB -# "${ARROW_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}${ARROW_CUDA_STATIC_LIB_NAME}${CMAKE_STATIC_LIBRARY_SUFFIX}" -# ) set(ARROW_INCLUDE_DIR "${ARROW_PREFIX}/include") - set(ARROW_CMAKE_ARGS ${EP_COMMON_CMAKE_ARGS} -# "-DARROW_THRIFT_URL=${THRIFT_SOURCE_URL}" - #"env ARROW_THRIFT_URL=${THRIFT_SOURCE_URL}" -DARROW_BUILD_STATIC=ON -DARROW_BUILD_SHARED=OFF -DARROW_PARQUET=ON @@ -375,8 +375,6 @@ macro(build_arrow) "-DCMAKE_LIBRARY_PATH=${CUDA_TOOLKIT_ROOT_DIR}/lib64/stubs" -DCMAKE_BUILD_TYPE=Release) -# set($ENV{ARROW_THRIFT_URL} ${THRIFT_SOURCE_URL}) - externalproject_add(arrow_ep GIT_REPOSITORY ${ARROW_SOURCE_URL} @@ -384,14 +382,8 @@ macro(build_arrow) ${ARROW_VERSION} GIT_SHALLOW TRUE -# SOURCE_DIR -# ${ARROW_PREFIX} -# BINARY_DIR -# ${ARROW_PREFIX} SOURCE_SUBDIR cpp -# COMMAND -# "export \"ARROW_THRIFT_URL=${THRIFT_SOURCE_URL}\"" ${EP_LOG_OPTIONS} CMAKE_ARGS ${ARROW_CMAKE_ARGS} @@ -400,21 +392,16 @@ macro(build_arrow) ${MAKE_BUILD_ARGS} INSTALL_COMMAND ${MAKE} install -# BUILD_IN_SOURCE -# 1 BUILD_BYPRODUCTS "${ARROW_STATIC_LIB}" -# "${ARROW_CUDA_STATIC_LIB}" ) -# ExternalProject_Add_StepDependencies(arrow_ep build thrift_ep) - file(MAKE_DIRECTORY "${ARROW_PREFIX}/include") add_library(arrow STATIC IMPORTED) set_target_properties(arrow PROPERTIES IMPORTED_LOCATION "${ARROW_STATIC_LIB}" INTERFACE_INCLUDE_DIRECTORIES "${ARROW_INCLUDE_DIR}") -# INTERFACE_LINK_LIBRARIES thrift) + add_dependencies(arrow arrow_ep) set(JEMALLOC_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/arrow_ep-prefix/src/arrow_ep-build/jemalloc_ep-prefix/src/jemalloc_ep") @@ -438,9 +425,6 @@ endif() # Add Boost dependencies (code adapted from Apache Kudu (incubating)) set(Boost_USE_MULTITHREADED ON) -if(MSVC AND MILVUS_USE_STATIC_CRT) - set(Boost_USE_STATIC_RUNTIME ON) -endif() set(Boost_ADDITIONAL_VERSIONS "1.70.0" "1.70" @@ -530,59 +514,8 @@ if(MILVUS_BOOST_VENDORED) add_dependencies(boost_filesystem_static boost_ep) add_dependencies(boost_serialization_static boost_ep) -else() - if(MSVC) - # disable autolinking in boost - add_definitions(-DBOOST_ALL_NO_LIB) - endif() - -# if(DEFINED ENV{BOOST_ROOT} OR DEFINED BOOST_ROOT) -# # In older versions of CMake (such as 3.2), the system paths for Boost will -# # be looked in first even if we set $BOOST_ROOT or pass -DBOOST_ROOT -# set(Boost_NO_SYSTEM_PATHS ON) -# endif() - - if(MILVUS_BOOST_USE_SHARED) - # Find shared Boost libraries. - set(Boost_USE_STATIC_LIBS OFF) - set(BUILD_SHARED_LIBS_KEEP ${BUILD_SHARED_LIBS}) - set(BUILD_SHARED_LIBS ON) - - if(MSVC) - # force all boost libraries to dynamic link - add_definitions(-DBOOST_ALL_DYN_LINK) - endif() - - if(MILVUS_BOOST_HEADER_ONLY) - find_package(Boost REQUIRED) - else() - find_package(Boost COMPONENTS serialization system filesystem REQUIRED) - set(BOOST_SYSTEM_LIBRARY Boost::system) - set(BOOST_FILESYSTEM_LIBRARY Boost::filesystem) - set(BOOST_SERIALIZATION_LIBRARY Boost::serialization) - set(MILVUS_BOOST_LIBS ${BOOST_SYSTEM_LIBRARY} ${BOOST_FILESYSTEM_LIBRARY}) - endif() - set(BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS_KEEP}) - unset(BUILD_SHARED_LIBS_KEEP) - else() - # Find static boost headers and libs - # TODO Differentiate here between release and debug builds - set(Boost_USE_STATIC_LIBS ON) - if(MILVUS_BOOST_HEADER_ONLY) - find_package(Boost REQUIRED) - else() - find_package(Boost COMPONENTS serialization system filesystem REQUIRED) - set(BOOST_SYSTEM_LIBRARY Boost::system) - set(BOOST_FILESYSTEM_LIBRARY Boost::filesystem) - set(BOOST_SERIALIZATION_LIBRARY Boost::serialization) - set(MILVUS_BOOST_LIBS ${BOOST_SYSTEM_LIBRARY} ${BOOST_FILESYSTEM_LIBRARY}) - endif() - endif() endif() -#message(STATUS "Boost include dir: " ${Boost_INCLUDE_DIR}) -#message(STATUS "Boost libraries: " ${Boost_LIBRARIES}) - include_directories(SYSTEM ${Boost_INCLUDE_DIR}) link_directories(SYSTEM ${BOOST_LIB_DIR}) @@ -726,13 +659,6 @@ macro(build_openblas) add_dependencies(openblas openblas_ep) endmacro() -#if(MILVUS_WITH_OPENBLAS) -# resolve_dependency(OpenBLAS) -# -# get_target_property(OPENBLAS_INCLUDE_DIR openblas INTERFACE_INCLUDE_DIRECTORIES) -# include_directories(SYSTEM "${OPENBLAS_INCLUDE_DIR}") -#endif() - # ---------------------------------------------------------------------- # LAPACK @@ -770,16 +696,23 @@ macro(build_lapack) add_dependencies(lapack lapack_ep) endmacro() -#if(MILVUS_WITH_LAPACK) -# resolve_dependency(LAPACK) -# -# get_target_property(LAPACK_INCLUDE_DIR lapack INTERFACE_INCLUDE_DIRECTORIES) -# include_directories(SYSTEM "${LAPACK_INCLUDE_DIR}") -#endif() - # ---------------------------------------------------------------------- # FAISS +set(BUILD_FAISS_WITH_MKL false) + +if(EXISTS "/proc/cpuinfo") + FILE(READ /proc/cpuinfo PROC_CPUINFO) + + SET(VENDOR_ID_RX "vendor_id[ \t]*:[ \t]*([a-zA-Z]+)\n") + STRING(REGEX MATCH "${VENDOR_ID_RX}" VENDOR_ID "${PROC_CPUINFO}") + STRING(REGEX REPLACE "${VENDOR_ID_RX}" "\\1" VENDOR_ID "${VENDOR_ID}") + + if(${VENDOR_ID} STREQUAL "GenuineIntel") + set(BUILD_FAISS_WITH_MKL true) + endif() +endif() + macro(build_faiss) message(STATUS "Building FAISS-${FAISS_VERSION} from source") set(FAISS_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/faiss_ep-prefix/src/faiss_ep") @@ -787,33 +720,36 @@ macro(build_faiss) set(FAISS_STATIC_LIB "${FAISS_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}faiss${CMAKE_STATIC_LIBRARY_SUFFIX}") -# add_custom_target(faiss_dependencies) -# add_dependencies(faiss_dependencies openblas_ep) -# add_dependencies(faiss_dependencies openblas) -# get_target_property(FAISS_OPENBLAS_LIB_DIR openblas IMPORTED_LOCATION) -# get_filename_component(FAISS_OPENBLAS_LIB "${FAISS_OPENBLAS_LIB_DIR}" DIRECTORY) - set(FAISS_CONFIGURE_ARGS "--prefix=${FAISS_PREFIX}" "CFLAGS=${EP_C_FLAGS}" "CXXFLAGS=${EP_CXX_FLAGS}" - "LDFLAGS=-L${OPENBLAS_PREFIX}/lib -L${LAPACK_PREFIX}/lib -lopenblas -llapack" --without-python) -# if(OPENBLAS_STATIC_LIB) -# set(OPENBLAS_LIBRARY ${OPENBLAS_STATIC_LIB}) -# else() -# set(OPENBLAS_LIBRARY ${OPENBLAS_SHARED_LIB}) -# endif() -# set(FAISS_DEPENDENCIES ${FAISS_DEPENDENCIES} ${OPENBLAS_LIBRARY}) + set(FAISS_CFLAGS ${EP_C_FLAGS}) + set(FAISS_CXXFLAGS ${EP_CXX_FLAGS}) + + if(${BUILD_FAISS_WITH_MKL} STREQUAL "true") + message(STATUS "Build Faiss with MKL") + if(NOT DEFINED MKL_LIB_PATH) + set(MKL_LIB_PATH "/opt/intel/compilers_and_libraries_${MKL_VERSION}/linux/mkl/lib/intel64") + message(STATUS "MKL_LIB_PATH = ${MKL_LIB_PATH}") + endif() + + set(FAISS_CONFIGURE_ARGS ${FAISS_CONFIGURE_ARGS} + "CPPFLAGS=-DFINTEGER=long -DMKL_ILP64 -m64 -I${MKL_LIB_PATH}/../../include" + "LDFLAGS=-L${MKL_LIB_PATH}" + "LIBS=-Wl,--start-group ${MKL_LIB_PATH}/libmkl_intel_ilp64.a ${MKL_LIB_PATH}/libmkl_gnu_thread.a ${MKL_LIB_PATH}/libmkl_core.a -Wl,--end-group -lgomp -lpthread -lm -ldl") + + else() + message(STATUS "Build Faiss with OpenBlas/LAPACK") + set(FAISS_CONFIGURE_ARGS ${FAISS_CONFIGURE_ARGS} + "LDFLAGS=-L${OPENBLAS_PREFIX}/lib -L${LAPACK_PREFIX}/lib") + endif() if(${MILVUS_WITH_FAISS_GPU_VERSION} STREQUAL "ON") set(FAISS_CONFIGURE_ARGS ${FAISS_CONFIGURE_ARGS} "--with-cuda=${CUDA_TOOLKIT_ROOT_DIR}" -# "with_cuda_arch=\"-gencode=arch=compute_35,code=compute_35 \\ -# -gencode=arch=compute_52,code=compute_52 \\ -# -gencode=arch=compute_60,code=compute_60 \\ -# -gencode=arch=compute_61,code=compute_61\"" "--with-cuda-arch=\"-gencode=arch=compute_35,code=compute_35\"" "--with-cuda-arch=\"-gencode=arch=compute_52,code=compute_52\"" "--with-cuda-arch=\"-gencode=arch=compute_60,code=compute_60\"" @@ -830,58 +766,66 @@ macro(build_faiss) CONFIGURE_COMMAND "./configure" ${FAISS_CONFIGURE_ARGS} -# BINARY_DIR -# ${FAISS_PREFIX} -# INSTALL_DIR -# ${FAISS_PREFIX} -# BUILD_COMMAND -# ${MAKE} ${MAKE_BUILD_ARGS} BUILD_COMMAND ${MAKE} ${MAKE_BUILD_ARGS} all COMMAND cd gpu && ${MAKE} ${MAKE_BUILD_ARGS} BUILD_IN_SOURCE 1 -# INSTALL_DIR -# ${FAISS_PREFIX} INSTALL_COMMAND ${MAKE} install COMMAND ln -s faiss_ep ../faiss BUILD_BYPRODUCTS ${FAISS_STATIC_LIB}) -# DEPENDS -# ${faiss_dependencies}) - - ExternalProject_Add_StepDependencies(faiss_ep build openblas_ep lapack_ep) + + if(${BUILD_FAISS_WITH_MKL} STREQUAL "false") + ExternalProject_Add_StepDependencies(faiss_ep build openblas_ep lapack_ep) + endif() file(MAKE_DIRECTORY "${FAISS_INCLUDE_DIR}") - add_library(faiss STATIC IMPORTED) - set_target_properties( - faiss - PROPERTIES IMPORTED_LOCATION "${FAISS_STATIC_LIB}" - INTERFACE_INCLUDE_DIRECTORIES "${FAISS_INCLUDE_DIR}" - INTERFACE_LINK_LIBRARIES "openblas;lapack" ) + add_library(faiss SHARED IMPORTED) + if(${BUILD_FAISS_WITH_MKL} STREQUAL "true") + set(MKL_LIBS ${MKL_LIB_PATH}/libmkl_intel_ilp64.a + ${MKL_LIB_PATH}/libmkl_gnu_thread.a + ${MKL_LIB_PATH}/libmkl_core.a) + + set_target_properties( + faiss + PROPERTIES IMPORTED_LOCATION "${FAISS_STATIC_LIB}" + INTERFACE_INCLUDE_DIRECTORIES "${FAISS_INCLUDE_DIR}" + INTERFACE_LINK_LIBRARIES "${MKL_LIBS}" ) + else() + set_target_properties( + faiss + PROPERTIES IMPORTED_LOCATION "${FAISS_STATIC_LIB}" + INTERFACE_INCLUDE_DIRECTORIES "${FAISS_INCLUDE_DIR}" + INTERFACE_LINK_LIBRARIES "openblas;lapack" ) + endif() + add_dependencies(faiss faiss_ep) - #add_dependencies(faiss openblas_ep) - #add_dependencies(faiss lapack_ep) - #target_link_libraries(faiss ${OPENBLAS_PREFIX}/lib) - #target_link_libraries(faiss ${LAPACK_PREFIX}/lib) + + if(${BUILD_FAISS_WITH_MKL} STREQUAL "false") + add_dependencies(faiss openblas_ep) + add_dependencies(faiss lapack_ep) + endif() endmacro() if(MILVUS_WITH_FAISS) - resolve_dependency(OpenBLAS) - get_target_property(OPENBLAS_INCLUDE_DIR openblas INTERFACE_INCLUDE_DIRECTORIES) - include_directories(SYSTEM "${OPENBLAS_INCLUDE_DIR}") - link_directories(SYSTEM ${OPENBLAS_PREFIX}/lib) + if(${BUILD_FAISS_WITH_MKL} STREQUAL "false") + resolve_dependency(OpenBLAS) + get_target_property(OPENBLAS_INCLUDE_DIR openblas INTERFACE_INCLUDE_DIRECTORIES) + include_directories(SYSTEM "${OPENBLAS_INCLUDE_DIR}") + link_directories(SYSTEM ${OPENBLAS_PREFIX}/lib) - resolve_dependency(LAPACK) - get_target_property(LAPACK_INCLUDE_DIR lapack INTERFACE_INCLUDE_DIRECTORIES) - include_directories(SYSTEM "${LAPACK_INCLUDE_DIR}") - link_directories(SYSTEM "${LAPACK_PREFIX}/lib") + resolve_dependency(LAPACK) + get_target_property(LAPACK_INCLUDE_DIR lapack INTERFACE_INCLUDE_DIRECTORIES) + include_directories(SYSTEM "${LAPACK_INCLUDE_DIR}") + link_directories(SYSTEM "${LAPACK_PREFIX}/lib") + endif() resolve_dependency(FAISS) get_target_property(FAISS_INCLUDE_DIR faiss INTERFACE_INCLUDE_DIRECTORIES) @@ -926,8 +870,6 @@ macro(build_gtest) set(GMOCK_STATIC_LIB "${GTEST_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}gmock${CMAKE_STATIC_LIBRARY_SUFFIX}" ) - - ExternalProject_Add(googletest_ep URL ${GTEST_SOURCE_URL} @@ -967,13 +909,11 @@ macro(build_gtest) endmacro() if (MILVUS_BUILD_TESTS) - #message(STATUS "Resolving gtest dependency") resolve_dependency(GTest) if(NOT GTEST_VENDORED) endif() - - # TODO: Don't use global includes but rather target_include_directories + get_target_property(GTEST_INCLUDE_DIR gtest INTERFACE_INCLUDE_DIRECTORIES) link_directories(SYSTEM "${GTEST_PREFIX}/lib") include_directories(SYSTEM ${GTEST_INCLUDE_DIR}) @@ -1011,32 +951,8 @@ macro(build_lz4) set(LZ4_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/lz4_ep-prefix/src/lz4_ep") set(LZ4_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/lz4_ep-prefix/") - if(MSVC) - if(MILVUS_USE_STATIC_CRT) - if(${UPPERCASE_BUILD_TYPE} STREQUAL "DEBUG") - set(LZ4_RUNTIME_LIBRARY_LINKAGE "/p:RuntimeLibrary=MultiThreadedDebug") - else() - set(LZ4_RUNTIME_LIBRARY_LINKAGE "/p:RuntimeLibrary=MultiThreaded") - endif() - endif() - set(LZ4_STATIC_LIB - "${LZ4_BUILD_DIR}/visual/VS2010/bin/x64_${CMAKE_BUILD_TYPE}/liblz4_static.lib") - set(LZ4_BUILD_COMMAND - BUILD_COMMAND - msbuild.exe - /m - /p:Configuration=${CMAKE_BUILD_TYPE} - /p:Platform=x64 - /p:PlatformToolset=v140 - ${LZ4_RUNTIME_LIBRARY_LINKAGE} - /t:Build - ${LZ4_BUILD_DIR}/visual/VS2010/lz4.sln) - else() - set(LZ4_STATIC_LIB "${LZ4_BUILD_DIR}/lib/liblz4.a") - #set(LZ4_BUILD_COMMAND BUILD_COMMAND ${CMAKE_SOURCE_DIR}/build-support/build-lz4-lib.sh - # "AR=${CMAKE_AR}") - set(LZ4_BUILD_COMMAND BUILD_COMMAND ${MAKE} ${MAKE_BUILD_ARGS} CFLAGS=${EP_C_FLAGS}) - endif() + set(LZ4_STATIC_LIB "${LZ4_BUILD_DIR}/lib/liblz4.a") + set(LZ4_BUILD_COMMAND BUILD_COMMAND ${MAKE} ${MAKE_BUILD_ARGS} CFLAGS=${EP_C_FLAGS}) # We need to copy the header in lib to directory outside of the build externalproject_add(lz4_ep @@ -1071,7 +987,6 @@ endmacro() if(MILVUS_WITH_LZ4) resolve_dependency(Lz4) - # TODO: Don't use global includes but rather target_include_directories get_target_property(LZ4_INCLUDE_DIR lz4 INTERFACE_INCLUDE_DIRECTORIES) link_directories(SYSTEM ${LZ4_BUILD_DIR}/lib/) include_directories(SYSTEM ${LZ4_INCLUDE_DIR}) @@ -1097,16 +1012,8 @@ macro(build_mysqlpp) externalproject_add(mysqlpp_ep URL ${MYSQLPP_SOURCE_URL} -# GIT_REPOSITORY -# ${MYSQLPP_SOURCE_URL} -# GIT_TAG -# ${MYSQLPP_VERSION} -# GIT_SHALLOW -# TRUE ${EP_LOG_OPTIONS} CONFIGURE_COMMAND -# "./bootstrap" -# COMMAND "./configure" ${MYSQLPP_CONFIGURE_ARGS} BUILD_COMMAND @@ -1167,10 +1074,6 @@ macro(build_prometheus) ${PROMETHEUS_VERSION} GIT_SHALLOW TRUE -# GIT_CONFIG -# recurse-submodules=true -# URL -# ${PROMETHEUS_SOURCE_URL} ${EP_LOG_OPTIONS} CMAKE_ARGS ${PROMETHEUS_CMAKE_ARGS} @@ -1214,21 +1117,15 @@ if(MILVUS_WITH_PROMETHEUS) resolve_dependency(Prometheus) - # TODO: Don't use global includes but rather target_include_directories - #get_target_property(PROMETHEUS-core_INCLUDE_DIRS prometheus-core INTERFACE_INCLUDE_DIRECTORIES) - - #get_target_property(PROMETHEUS_PUSH_INCLUDE_DIRS prometheus_push INTERFACE_INCLUDE_DIRECTORIES) link_directories(SYSTEM ${PROMETHEUS_PREFIX}/push/) include_directories(SYSTEM ${PROMETHEUS_PREFIX}/push/include) - #get_target_property(PROMETHEUS_PULL_INCLUDE_DIRS prometheus_pull INTERFACE_INCLUDE_DIRECTORIES) link_directories(SYSTEM ${PROMETHEUS_PREFIX}/pull/) include_directories(SYSTEM ${PROMETHEUS_PREFIX}/pull/include) link_directories(SYSTEM ${PROMETHEUS_PREFIX}/core/) include_directories(SYSTEM ${PROMETHEUS_PREFIX}/core/include) - #link_directories(${PROMETHEUS_PREFIX}/civetweb_ep-prefix/src/civetweb_ep) endif() # ---------------------------------------------------------------------- @@ -1276,8 +1173,6 @@ if(MILVUS_WITH_ROCKSDB) resolve_dependency(RocksDB) - # TODO: Don't use global includes but rather target_include_directories -# get_target_property(ROCKSDB_INCLUDE_DIRS rocksdb INTERFACE_INCLUDE_DIRECTORIES) link_directories(SYSTEM ${ROCKSDB_PREFIX}/lib/lib/) include_directories(SYSTEM ${ROCKSDB_INCLUDE_DIRS}) endif() @@ -1326,34 +1221,9 @@ macro(build_snappy) endmacro() if(MILVUS_WITH_SNAPPY) -# if(Snappy_SOURCE STREQUAL "AUTO") -# # Normally *Config.cmake files reside in /usr/lib/cmake but Snappy -# # errornously places them in ${CMAKE_ROOT}/Modules/ -# # This is fixed in 1.1.7 but fedora (30) still installs into the wrong -# # location. -# # https://bugzilla.redhat.com/show_bug.cgi?id=1679727 -# # https://src.fedoraproject.org/rpms/snappy/pull-request/1 -# find_package(Snappy QUIET HINTS "${CMAKE_ROOT}/Modules/") -# if(NOT Snappy_FOUND) -# find_package(SnappyAlt) -# endif() -# if(NOT Snappy_FOUND AND NOT SnappyAlt_FOUND) -# build_snappy() -# endif() -# elseif(Snappy_SOURCE STREQUAL "BUNDLED") -# build_snappy() -# elseif(Snappy_SOURCE STREQUAL "SYSTEM") -# # SnappyConfig.cmake is not installed on Ubuntu/Debian -# # TODO: Make a bug report upstream -# find_package(Snappy HINTS "${CMAKE_ROOT}/Modules/") -# if(NOT Snappy_FOUND) -# find_package(SnappyAlt REQUIRED) -# endif() -# endif() resolve_dependency(Snappy) - - # TODO: Don't use global includes but rather target_include_directories + get_target_property(SNAPPY_INCLUDE_DIRS snappy INTERFACE_INCLUDE_DIRECTORIES) link_directories(SYSTEM ${SNAPPY_PREFIX}/lib/) include_directories(SYSTEM ${SNAPPY_INCLUDE_DIRS}) @@ -1425,75 +1295,11 @@ macro(build_sqlite_orm) endif () - #set(SQLITE_ORM_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/sqlite_orm_ep-prefix/src/sqlite_orm_ep") - #set(SQLITE_ORM_INCLUDE_DIR "${SQLITE_ORM_PREFIX}/include/sqlite_orm") - -# set(SQLITE_ORM_STATIC_LIB -# "${SQLITE_ORM_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}sqlite_orm${CMAKE_STATIC_LIBRARY_SUFFIX}") -# -# set(SQLITE_ORM_CMAKE_CXX_FLAGS "${EP_CXX_FLAGS} -std=c++14") -# set(SQLITE_ORM_CMAKE_CXX_FLAGS_DEBUG "${EP_CXX_FLAGS} -std=c++14") -# -# set(SQLITE_ORM_CMAKE_ARGS -# ${EP_COMMON_CMAKE_ARGS} -# "-DCMAKE_INSTALL_PREFIX=${SQLITE_ORM_PREFIX}" -# #"LDFLAGS=-L${SQLITE_PREFIX}" -# #"-DCMAKE_PREFIX_PATH=${SQLITE_PREFIX}/include" -# "-DCMAKE_INCLUDE_PATH=${SQLITE_PREFIX}/include" -# "-DCMAKE_CXX_FLAGS=${SQLITE_ORM_CMAKE_CXX_FLAGS}" -# "-DCMAKE_CXX_FLAGS_DEBUG=${SQLITE_ORM_CMAKE_CXX_FLAGS}" -# -DSqliteOrm_BuildTests=off -# -DBUILD_TESTING=off) -# message(STATUS "SQLITE_INCLUDE: ${SQLITE_ORM_CMAKE_ARGS}") -# -# message(STATUS "SQLITE_ORM_CMAKE_CXX_FLAGS: ${SQLITE_ORM_CMAKE_CXX_FLAGS}") - -# externalproject_add(sqlite_orm_ep -# URL -# ${SQLITE_ORM_SOURCE_URL} -# PREFIX ${CMAKE_CURRENT_BINARY_DIR}/sqlite_orm_ep-prefix -# CONFIGURE_COMMAND -# "" -# BUILD_COMMAND -# "" -# INSTALL_COMMAND -# "" - #${EP_LOG_OPTIONS} - #${EP_LOG_OPTIONS} -# CMAKE_ARGS -# ${SQLITE_ORM_CMAKE_ARGS} -# BUILD_COMMAND -# ${MAKE} -# ${MAKE_BUILD_ARGS} -# #"LDFLAGS=-L${SQLITE_PREFIX}" -# BUILD_IN_SOURCE -# 1 -# BUILD_BYPRODUCTS -# "${SQLITE_ORM_STATIC_LIB}" -# ) -# ExternalProject_Add_StepDependencies(sqlite_orm_ep build sqlite_ep) - - #set(SQLITE_ORM_SQLITE_HEADER ${SQLITE_INCLUDE_DIR}/sqlite3.h) -# file(MAKE_DIRECTORY "${SQLITE_ORM_INCLUDE_DIR}") -# add_library(sqlite_orm STATIC IMPORTED) -## message(STATUS "SQLITE_INCLUDE_DIR: ${SQLITE_INCLUDE_DIR}") -# set_target_properties( -# sqlite_orm -# PROPERTIES -# IMPORTED_LOCATION "${SQLITE_ORM_STATIC_LIB}" -# INTERFACE_INCLUDE_DIRECTORIES "${SQLITE_ORM_INCLUDE_DIR};${SQLITE_INCLUDE_DIR}") -# target_include_directories(sqlite_orm INTERFACE ${SQLITE_PREFIX} ${SQLITE_INCLUDE_DIR}) -# target_link_libraries(sqlite_orm INTERFACE sqlite) -# -# add_dependencies(sqlite_orm sqlite_orm_ep) endmacro() if(MILVUS_WITH_SQLITE_ORM) resolve_dependency(SQLite_ORM) -# ExternalProject_Get_Property(sqlite_orm_ep source_dir) -# set(SQLITE_ORM_INCLUDE_DIR ${source_dir}/sqlite_orm_ep) include_directories(SYSTEM "${SQLITE_ORM_INCLUDE_DIR}") - #message(STATUS "SQLITE_ORM_INCLUDE_DIR: ${SQLITE_ORM_INCLUDE_DIR}") endif() # ---------------------------------------------------------------------- @@ -1533,18 +1339,7 @@ macro(build_thrift) endif() set(THRIFT_STATIC_LIB_NAME "${CMAKE_STATIC_LIBRARY_PREFIX}thrift") - if(MSVC) - if(MILVUS_USE_STATIC_CRT) - set(THRIFT_STATIC_LIB_NAME "${THRIFT_STATIC_LIB_NAME}") - set(THRIFT_CMAKE_ARGS ${THRIFT_CMAKE_ARGS} "-DWITH_MT=ON") - else() - set(THRIFT_STATIC_LIB_NAME "${THRIFT_STATIC_LIB_NAME}") - set(THRIFT_CMAKE_ARGS ${THRIFT_CMAKE_ARGS} "-DWITH_MT=OFF") - endif() - endif() - if(${UPPERCASE_BUILD_TYPE} STREQUAL "DEBUG") - set(THRIFT_STATIC_LIB_NAME "${THRIFT_STATIC_LIB_NAME}") - endif() + set(THRIFT_STATIC_LIB "${THRIFT_PREFIX}/lib/${THRIFT_STATIC_LIB_NAME}${CMAKE_STATIC_LIBRARY_SUFFIX}") @@ -1555,60 +1350,6 @@ macro(build_thrift) endif() set(THRIFT_DEPENDENCIES ${THRIFT_DEPENDENCIES} ${ZLIB_LIBRARY}) - if(MSVC) - set(WINFLEXBISON_VERSION 2.4.9) - set(WINFLEXBISON_PREFIX - "${CMAKE_CURRENT_BINARY_DIR}/winflexbison_ep/src/winflexbison_ep-install") - externalproject_add( - winflexbison_ep - URL - https://github.com/lexxmark/winflexbison/releases/download/v.${WINFLEXBISON_VERSION}/win_flex_bison-${WINFLEXBISON_VERSION}.zip - URL_HASH - MD5=a2e979ea9928fbf8567e995e9c0df765 - SOURCE_DIR - ${WINFLEXBISON_PREFIX} - CONFIGURE_COMMAND - "" - BUILD_COMMAND - "" - INSTALL_COMMAND - "" - ${EP_LOG_OPTIONS}) - set(THRIFT_DEPENDENCIES ${THRIFT_DEPENDENCIES} winflexbison_ep) - - set(THRIFT_CMAKE_ARGS - "-DFLEX_EXECUTABLE=${WINFLEXBISON_PREFIX}/win_flex.exe" - "-DBISON_EXECUTABLE=${WINFLEXBISON_PREFIX}/win_bison.exe" - "-DZLIB_INCLUDE_DIR=${ZLIB_INCLUDE_DIR}" - "-DWITH_SHARED_LIB=OFF" - "-DWITH_PLUGIN=OFF" - ${THRIFT_CMAKE_ARGS}) - elseif(APPLE) - # Some other process always resets BISON_EXECUTABLE to the system default, - # thus we use our own variable here. - if(NOT DEFINED THRIFT_BISON_EXECUTABLE) - find_package(BISON 2.5.1) - - # In the case where we cannot find a system-wide installation, look for - # homebrew and ask for its bison installation. - if(NOT BISON_FOUND) - find_program(BREW_BIN brew) - if(BREW_BIN) - execute_process(COMMAND ${BREW_BIN} --prefix bison - OUTPUT_VARIABLE BISON_PREFIX - OUTPUT_STRIP_TRAILING_WHITESPACE) - set(BISON_EXECUTABLE "${BISON_PREFIX}/bin/bison") - find_package(BISON 2.5.1) - set(THRIFT_BISON_EXECUTABLE "${BISON_EXECUTABLE}") - endif() - else() - set(THRIFT_BISON_EXECUTABLE "${BISON_EXECUTABLE}") - endif() - endif() - set(THRIFT_CMAKE_ARGS "-DBISON_EXECUTABLE=${THRIFT_BISON_EXECUTABLE}" - ${THRIFT_CMAKE_ARGS}) - endif() - externalproject_add(thrift_ep URL ${THRIFT_SOURCE_URL} @@ -1637,8 +1378,7 @@ endmacro() if(MILVUS_WITH_THRIFT) resolve_dependency(Thrift) - # TODO: Don't use global includes but rather target_include_directories -# MESSAGE(STATUS ${THRIFT_PREFIX}/lib/) + link_directories(SYSTEM ${THRIFT_PREFIX}/lib/) link_directories(SYSTEM ${CMAKE_CURRENT_BINARY_DIR}/thrift_ep-prefix/src/thrift_ep-build/lib) include_directories(SYSTEM ${THRIFT_INCLUDE_DIR}) @@ -1684,8 +1424,7 @@ endmacro() if(MILVUS_WITH_YAMLCPP) resolve_dependency(yaml-cpp) - - # TODO: Don't use global includes but rather target_include_directories + get_target_property(YAMLCPP_INCLUDE_DIR yaml-cpp INTERFACE_INCLUDE_DIRECTORIES) link_directories(SYSTEM ${YAMLCPP_PREFIX}/lib/) include_directories(SYSTEM ${YAMLCPP_INCLUDE_DIR}) @@ -1697,15 +1436,7 @@ endif() macro(build_zlib) message(STATUS "Building ZLIB-${ZLIB_VERSION} from source") set(ZLIB_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/zlib_ep-prefix/src/zlib_ep") - if(MSVC) - if(${UPPERCASE_BUILD_TYPE} STREQUAL "DEBUG") - set(ZLIB_STATIC_LIB_NAME zlibstaticd.lib) - else() - set(ZLIB_STATIC_LIB_NAME zlibstatic.lib) - endif() - else() - set(ZLIB_STATIC_LIB_NAME libz.a) - endif() + set(ZLIB_STATIC_LIB_NAME libz.a) set(ZLIB_STATIC_LIB "${ZLIB_PREFIX}/lib/${ZLIB_STATIC_LIB_NAME}") set(ZLIB_CMAKE_ARGS ${EP_COMMON_CMAKE_ARGS} "-DCMAKE_INSTALL_PREFIX=${ZLIB_PREFIX}" -DBUILD_SHARED_LIBS=OFF) @@ -1734,8 +1465,7 @@ endmacro() if(MILVUS_WITH_ZLIB) resolve_dependency(ZLIB) - - # TODO: Don't use global includes but rather target_include_directories + get_target_property(ZLIB_INCLUDE_DIR zlib INTERFACE_INCLUDE_DIRECTORIES) include_directories(SYSTEM ${ZLIB_INCLUDE_DIR}) endif() @@ -1757,22 +1487,15 @@ macro(build_zstd) -DZSTD_BUILD_STATIC=on -DZSTD_MULTITHREAD_SUPPORT=off) - if(MSVC) - set(ZSTD_STATIC_LIB "${ZSTD_PREFIX}/lib/zstd_static.lib") - if(MILVUS_USE_STATIC_CRT) - set(ZSTD_CMAKE_ARGS ${ZSTD_CMAKE_ARGS} "-DZSTD_USE_STATIC_RUNTIME=on") - endif() - else() - set(ZSTD_STATIC_LIB "${ZSTD_PREFIX}/lib/libzstd.a") - # Only pass our C flags on Unix as on MSVC it leads to a - # "incompatible command-line options" error - set(ZSTD_CMAKE_ARGS - ${ZSTD_CMAKE_ARGS} - -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} - -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} - -DCMAKE_C_FLAGS=${EP_C_FLAGS} - -DCMAKE_CXX_FLAGS=${EP_CXX_FLAGS}) - endif() + + set(ZSTD_STATIC_LIB "${ZSTD_PREFIX}/lib/libzstd.a") + + set(ZSTD_CMAKE_ARGS + ${ZSTD_CMAKE_ARGS} + -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} + -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} + -DCMAKE_C_FLAGS=${EP_C_FLAGS} + -DCMAKE_CXX_FLAGS=${EP_CXX_FLAGS}) if(CMAKE_VERSION VERSION_LESS 3.7) message(FATAL_ERROR "Building zstd using ExternalProject requires at least CMake 3.7") @@ -1806,8 +1529,7 @@ endmacro() if(MILVUS_WITH_ZSTD) resolve_dependency(ZSTD) - - # TODO: Don't use global includes but rather target_include_directories + get_target_property(ZSTD_INCLUDE_DIR zstd INTERFACE_INCLUDE_DIRECTORIES) link_directories(SYSTEM ${ZSTD_PREFIX}/lib) include_directories(SYSTEM ${ZSTD_INCLUDE_DIR}) @@ -1823,7 +1545,7 @@ macro(build_aws) ${EP_COMMON_TOOLCHAIN} "-DCMAKE_INSTALL_PREFIX=${AWS_PREFIX}" -DCMAKE_BUILD_TYPE=Release - -DCMAKE_INSTALL_LIBDIR=lib #${CMAKE_INSTALL_LIBDIR} + -DCMAKE_INSTALL_LIBDIR=lib -DBUILD_ONLY=s3 -DBUILD_SHARED_LIBS=off -DENABLE_TESTING=off @@ -1834,8 +1556,7 @@ macro(build_aws) "${AWS_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}aws-cpp-sdk-core${CMAKE_STATIC_LIBRARY_SUFFIX}") set(AWS_CPP_SDK_S3_STATIC_LIB "${AWS_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}aws-cpp-sdk-s3${CMAKE_STATIC_LIBRARY_SUFFIX}") - # Only pass our C flags on Unix as on MSVC it leads to a - # "incompatible command-line options" error + set(AWS_CMAKE_ARGS ${AWS_CMAKE_ARGS} -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} @@ -1843,10 +1564,6 @@ macro(build_aws) -DCMAKE_C_FLAGS=${EP_C_FLAGS} -DCMAKE_CXX_FLAGS=${EP_CXX_FLAGS}) - if(CMAKE_VERSION VERSION_LESS 3.7) - message(FATAL_ERROR "Building AWS using ExternalProject requires at least CMake 3.7") - endif() - externalproject_add(aws_ep ${EP_LOG_OPTIONS} CMAKE_ARGS @@ -1861,8 +1578,6 @@ macro(build_aws) BUILD_BYPRODUCTS "${AWS_CPP_SDK_S3_STATIC_LIB}" "${AWS_CPP_SDK_CORE_STATIC_LIB}") - - file(MAKE_DIRECTORY "${AWS_PREFIX}/include") add_library(aws-cpp-sdk-s3 STATIC IMPORTED) @@ -1885,8 +1600,7 @@ endmacro() if(MILVUS_WITH_AWS) resolve_dependency(AWS) - - # TODO: Don't use global includes but rather target_include_directories + link_directories(SYSTEM ${AWS_PREFIX}/lib) get_target_property(AWS_CPP_SDK_S3_INCLUDE_DIR aws-cpp-sdk-s3 INTERFACE_INCLUDE_DIRECTORIES) @@ -1896,3 +1610,91 @@ if(MILVUS_WITH_AWS) include_directories(SYSTEM ${AWS_CPP_SDK_CORE_INCLUDE_DIR}) endif() + +# ---------------------------------------------------------------------- +# libunwind + +macro(build_libunwind) + message(STATUS "Building libunwind-${LIBUNWIND_VERSION} from source") + set(LIBUNWIND_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/libunwind_ep-prefix/src/libunwind_ep/install") + set(LIBUNWIND_INCLUDE_DIR "${LIBUNWIND_PREFIX}/include") + set(LIBUNWIND_SHARED_LIB "${LIBUNWIND_PREFIX}/lib/libunwind${CMAKE_SHARED_LIBRARY_SUFFIX}") + set(LIBUNWIND_CONFIGURE_ARGS "--prefix=${LIBUNWIND_PREFIX}") + + externalproject_add(libunwind_ep + URL + ${LIBUNWIND_SOURCE_URL} + ${EP_LOG_OPTIONS} + CONFIGURE_COMMAND + "./configure" + ${LIBUNWIND_CONFIGURE_ARGS} + BUILD_COMMAND + ${MAKE} ${MAKE_BUILD_ARGS} + BUILD_IN_SOURCE + 1 + INSTALL_COMMAND + ${MAKE} install + BUILD_BYPRODUCTS + ${LIBUNWIND_SHARED_LIB}) + + file(MAKE_DIRECTORY "${LIBUNWIND_INCLUDE_DIR}") + + add_library(libunwind SHARED IMPORTED) + set_target_properties(libunwind + PROPERTIES IMPORTED_LOCATION "${LIBUNWIND_SHARED_LIB}" + INTERFACE_INCLUDE_DIRECTORIES "${LIBUNWIND_INCLUDE_DIR}") + + add_dependencies(libunwind libunwind_ep) +endmacro() + +if(MILVUS_WITH_LIBUNWIND) + resolve_dependency(libunwind) + + # TODO: Don't use global includes but rather target_include_directories + get_target_property(LIBUNWIND_INCLUDE_DIR libunwind INTERFACE_INCLUDE_DIRECTORIES) + include_directories(SYSTEM ${LIBUNWIND_INCLUDE_DIR}) +endif() + +# ---------------------------------------------------------------------- +# gperftools + +macro(build_gperftools) + message(STATUS "Building gperftools-${GPERFTOOLS_VERSION} from source") + set(GPERFTOOLS_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/gperftools_ep-prefix/src/gperftools_ep") + set(GPERFTOOLS_INCLUDE_DIR "${GPERFTOOLS_PREFIX}/include") + set(GPERFTOOLS_STATIC_LIB "${GPERFTOOLS_PREFIX}/lib/libprofiler${CMAKE_STATIC_LIBRARY_SUFFIX}") + set(GPERFTOOLS_CONFIGURE_ARGS "--prefix=${GPERFTOOLS_PREFIX}") + + externalproject_add(gperftools_ep + URL + ${GPERFTOOLS_SOURCE_URL} + ${EP_LOG_OPTIONS} + CONFIGURE_COMMAND + "./configure" + ${GPERFTOOLS_CONFIGURE_ARGS} + BUILD_COMMAND + ${MAKE} ${MAKE_BUILD_ARGS} + BUILD_IN_SOURCE + 1 + INSTALL_COMMAND + ${MAKE} install + BUILD_BYPRODUCTS + ${GPERFTOOLS_STATIC_LIB}) + + file(MAKE_DIRECTORY "${GPERFTOOLS_INCLUDE_DIR}") + + add_library(gperftools SHARED IMPORTED) + set_target_properties(gperftools + PROPERTIES IMPORTED_LOCATION "${GPERFTOOLS_STATIC_LIB}" + INTERFACE_INCLUDE_DIRECTORIES "${GPERFTOOLS_INCLUDE_DIR}") + + add_dependencies(gperftools gperftools_ep) +endmacro() + +if(MILVUS_WITH_GPERFTOOLS) + resolve_dependency(gperftools) + + # TODO: Don't use global includes but rather target_include_directories + get_target_property(GPERFTOOLS_INCLUDE_DIR gperftools INTERFACE_INCLUDE_DIRECTORIES) + include_directories(SYSTEM ${GPERFTOOLS_INCLUDE_DIR}) +endif() diff --git a/cpp/conf/server_config.template b/cpp/conf/server_config.template index 17d5bcadef..2dd8daa0f1 100644 --- a/cpp/conf/server_config.template +++ b/cpp/conf/server_config.template @@ -14,10 +14,10 @@ db_config: db_backend_url: sqlite://:@:/ index_building_threshold: 1024 # index building trigger threshold, default: 1024, unit: MB - archive_disk_threshold: 512 # triger archive action if storage size exceed this value, unit: GB - archive_days_threshold: 30 # files older than x days will be archived, unit: day - maximum_memory: 4 # maximum memory allowed, default: 4, unit: GB, should be at least 1 GB. - # the sum of maximum_memory and cpu_cache_capacity should be less than total memory + archive_disk_threshold: 0 # triger archive action if storage size exceed this value, 0 means no limit, unit: GB + archive_days_threshold: 0 # files older than x days will be archived, 0 means no limit, unit: day + insert_buffer_size: 4 # maximum insert buffer size allowed, default: 4, unit: GB, should be at least 1 GB. + # the sum of insert_buffer_size and cpu_cache_capacity should be less than total memory metric_config: is_startup: off # if monitoring start: on, off @@ -39,4 +39,4 @@ engine_config: nprobe: 10 nlist: 16384 use_blas_threshold: 20 - metric_type: L2 #L2 or Inner Product + metric_type: L2 # compare vectors by euclidean distance(L2) or inner product(IP), optional: L2 or IP diff --git a/cpp/scripts/requirements.sh b/cpp/scripts/requirements.sh new file mode 100755 index 0000000000..5f8b74ad2c --- /dev/null +++ b/cpp/scripts/requirements.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +wget -P /tmp https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS-2019.PUB +apt-key add /tmp/GPG-PUB-KEY-INTEL-SW-PRODUCTS-2019.PUB + +sh -c 'echo deb https://apt.repos.intel.com/mkl all main > /etc/apt/sources.list.d/intel-mkl.list' +apt -y update && apt-get -y install intel-mkl-gnu-2019.4-243 intel-mkl-core-2019.4-243 + +#sh -c 'echo export LD_LIBRARY_PATH=/opt/intel/compilers_and_libraries_2019.4.243/linux/mkl/lib/intel64:\$LD_LIBRARY_PATH > /etc/profile.d/mkl.sh' +#source /etc/profile diff --git a/cpp/src/CMakeLists.txt b/cpp/src/CMakeLists.txt index d0029d5175..64edf5b91e 100644 --- a/cpp/src/CMakeLists.txt +++ b/cpp/src/CMakeLists.txt @@ -48,7 +48,6 @@ set(engine_files ${db_files} ${db_scheduler_files} ${wrapper_files} -# metrics/Metrics.cpp ${metrics_files} ) @@ -64,6 +63,10 @@ include_directories("${CUDA_TOOLKIT_ROOT_DIR}/include") include_directories(thrift/gen-cpp) include_directories(/usr/include/mysql) +if (MILVUS_ENABLE_PROFILING STREQUAL "ON") + SET(PROFILER_LIB profiler) +endif() + set(third_party_libs easyloggingpp sqlite @@ -71,8 +74,6 @@ set(third_party_libs yaml-cpp libgpufaiss.a faiss - lapack - openblas prometheus-cpp-push prometheus-cpp-pull prometheus-cpp-core @@ -85,11 +86,22 @@ set(third_party_libs zlib zstd mysqlpp + ${PROFILER_LIB} ${CUDA_TOOLKIT_ROOT_DIR}/lib64/stubs/libnvidia-ml.so ) + if (MEGASEARCH_WITH_ARROW STREQUAL "ON") set(third_party_libs ${third_party_libs} arrow) -endif() +endif() +if(${BUILD_FAISS_WITH_MKL} STREQUAL "true") + set(third_party_libs ${third_party_libs} + ${MKL_LIBS} + ${MKL_LIBS}) +else() + set(third_party_libs ${third_party_libs} + lapack + openblas) +endif() if (GPU_VERSION STREQUAL "ON") link_directories("${CUDA_TOOLKIT_ROOT_DIR}/lib64") @@ -187,6 +199,6 @@ install(FILES ${CMAKE_BINARY_DIR}/mysqlpp_ep-prefix/src/mysqlpp_ep/lib/${CMAKE_SHARED_LIBRARY_PREFIX}mysqlpp${CMAKE_SHARED_LIBRARY_SUFFIX} ${CMAKE_BINARY_DIR}/mysqlpp_ep-prefix/src/mysqlpp_ep/lib/${CMAKE_SHARED_LIBRARY_PREFIX}mysqlpp${CMAKE_SHARED_LIBRARY_SUFFIX}.3 ${CMAKE_BINARY_DIR}/mysqlpp_ep-prefix/src/mysqlpp_ep/lib/${CMAKE_SHARED_LIBRARY_PREFIX}mysqlpp${CMAKE_SHARED_LIBRARY_SUFFIX}.3.2.4 - DESTINATION lib) #need to copy libmysqlpp.so + DESTINATION lib) -#add_subdirectory(sdk) +add_subdirectory(sdk) diff --git a/cpp/src/cache/DataObj.h b/cpp/src/cache/DataObj.h index 1dff04027e..995711c6ab 100644 --- a/cpp/src/cache/DataObj.h +++ b/cpp/src/cache/DataObj.h @@ -20,6 +20,11 @@ public: : index_(index) {} + DataObj(const engine::Index_ptr& index, int64_t size) + : index_(index), + size_(size) + {} + engine::Index_ptr data() { return index_; } const engine::Index_ptr& data() const { return index_; } @@ -28,11 +33,16 @@ public: return 0; } + if(size_ > 0) { + return size_; + } + return index_->ntotal*(index_->dim*4); } private: engine::Index_ptr index_ = nullptr; + int64_t size_ = 0; }; using DataObjPtr = std::shared_ptr; diff --git a/cpp/src/db/DBImpl.cpp b/cpp/src/db/DBImpl.cpp index dca0f2a2ed..863f3db639 100644 --- a/cpp/src/db/DBImpl.cpp +++ b/cpp/src/db/DBImpl.cpp @@ -89,6 +89,7 @@ DBImpl::DBImpl(const Options& options) meta_ptr_ = DBMetaImplFactory::Build(options.meta, options.mode); mem_mgr_ = MemManagerFactory::Build(meta_ptr_, options_); if (options.mode != Options::MODE::READ_ONLY) { + ENGINE_LOG_INFO << "StartTimerTasks"; StartTimerTasks(); } } @@ -169,7 +170,10 @@ Status DBImpl::Query(const std::string& table_id, uint64_t k, uint64_t nq, } } - return QueryAsync(table_id, file_id_array, k, nq, vectors, dates, results); + cache::CpuCacheMgr::GetInstance()->PrintInfo(); //print cache info before query + status = QueryAsync(table_id, file_id_array, k, nq, vectors, dates, results); + cache::CpuCacheMgr::GetInstance()->PrintInfo(); //print cache info after query + return status; } Status DBImpl::Query(const std::string& table_id, const std::vector& file_ids, @@ -194,7 +198,10 @@ Status DBImpl::Query(const std::string& table_id, const std::vector return Status::Error("Invalid file id"); } - return QueryAsync(table_id, files_array, k, nq, vectors, dates, results); + cache::CpuCacheMgr::GetInstance()->PrintInfo(); //print cache info before query + status = QueryAsync(table_id, files_array, k, nq, vectors, dates, results); + cache::CpuCacheMgr::GetInstance()->PrintInfo(); //print cache info after query + return status; } Status DBImpl::QueryAsync(const std::string& table_id, const meta::TableFilesSchema& files, @@ -229,7 +236,6 @@ void DBImpl::BackgroundTimerTask() { Status status; server::SystemInfo::GetInstance().Init(); while (true) { - if (!bg_error_.ok()) break; if (shutting_down_.load(std::memory_order_acquire)){ for(auto& iter : compact_thread_results_) { iter.wait(); @@ -384,15 +390,11 @@ Status DBImpl::BackgroundMergeFiles(const std::string& table_id) { } void DBImpl::BackgroundCompaction(std::set table_ids) { -// static int b_count = 0; -// b_count++; -// std::cout << "BackgroundCompaction: " << b_count << std::endl; - Status status; for (auto& table_id : table_ids) { status = BackgroundMergeFiles(table_id); if (!status.ok()) { - bg_error_ = status; + ENGINE_LOG_ERROR << "Merge files for table " << table_id << " failed: " << status.ToString(); return; } } @@ -402,7 +404,6 @@ void DBImpl::BackgroundCompaction(std::set table_ids) { int ttl = 1; if (options_.mode == Options::MODE::CLUSTER) { ttl = meta::D_SEC; -// ENGINE_LOG_DEBUG << "Server mode is cluster. Clean up files with ttl = " << std::to_string(ttl) << "seconds."; } meta_ptr_->CleanUpFilesWithTTL(ttl); } @@ -486,7 +487,7 @@ Status DBImpl::BuildIndex(const meta::TableFileSchema& file) { //step 6: update meta table_file.file_type_ = meta::TableFileSchema::INDEX; - table_file.size_ = index->PhysicalSize(); + table_file.size_ = index->Size(); auto to_remove = file; to_remove.file_type_ = meta::TableFileSchema::TO_DELETE; @@ -535,10 +536,9 @@ void DBImpl::BackgroundBuildIndex() { meta_ptr_->FilesToIndex(to_index_files); Status status; for (auto& file : to_index_files) { - /* ENGINE_LOG_DEBUG << "Buiding index for " << file.location; */ status = BuildIndex(file); if (!status.ok()) { - bg_error_ = status; + ENGINE_LOG_ERROR << "Building index for " << file.id_ << " failed: " << status.ToString(); return; } @@ -546,7 +546,6 @@ void DBImpl::BackgroundBuildIndex() { break; } } - /* ENGINE_LOG_DEBUG << "All Buiding index Done"; */ } Status DBImpl::DropAll() { diff --git a/cpp/src/db/DBImpl.h b/cpp/src/db/DBImpl.h index 1309154a3c..73d28779b7 100644 --- a/cpp/src/db/DBImpl.h +++ b/cpp/src/db/DBImpl.h @@ -118,10 +118,8 @@ class DBImpl : public DB { BuildIndex(const meta::TableFileSchema &); private: - const Options options_; - Status bg_error_; std::atomic shutting_down_; std::thread bg_timer_thread_; diff --git a/cpp/src/db/DBMetaImpl.cpp b/cpp/src/db/DBMetaImpl.cpp index fc67c6b360..48e0fa46cd 100644 --- a/cpp/src/db/DBMetaImpl.cpp +++ b/cpp/src/db/DBMetaImpl.cpp @@ -291,6 +291,8 @@ Status DBMetaImpl::HasNonIndexFiles(const std::string& table_id, bool& has) { try { auto selected = ConnectorPtr->select(columns(&TableFileSchema::id_), where((c(&TableFileSchema::file_type_) == (int) TableFileSchema::RAW + or + c(&TableFileSchema::file_type_) == (int) TableFileSchema::NEW or c(&TableFileSchema::file_type_) == (int) TableFileSchema::TO_INDEX) and c(&TableFileSchema::table_id_) == table_id @@ -674,16 +676,22 @@ Status DBMetaImpl::Archive() { Status DBMetaImpl::Size(uint64_t &result) { result = 0; try { - auto selected = ConnectorPtr->select(columns(sum(&TableFileSchema::size_)), - where( - c(&TableFileSchema::file_type_) != (int) TableFileSchema::TO_DELETE - )); + auto files = ConnectorPtr->select(columns(&TableFileSchema::size_, + &TableFileSchema::file_type_, + &TableFileSchema::engine_type_), + where( + c(&TableFileSchema::file_type_) != (int) TableFileSchema::TO_DELETE + )); - for (auto &sub_query : selected) { - if (!std::get<0>(sub_query)) { - continue; + for (auto &file : files) { + auto file_size = std::get<0>(file); + auto file_type = std::get<1>(file); + auto engine_type = std::get<2>(file); + if(file_type == (int)TableFileSchema::INDEX && engine_type == (int)EngineType::FAISS_IVFSQ8) { + result += (uint64_t)file_size/4;//hardcode for sq8 + } else { + result += (uint64_t)file_size; } - result += (uint64_t) (*std::get<0>(sub_query)); } } catch (std::exception &e) { return HandleException("Encounter exception when calculte db size", e); diff --git a/cpp/src/db/ExecutionEngine.h b/cpp/src/db/ExecutionEngine.h index 4503e55650..cd9e071b9c 100644 --- a/cpp/src/db/ExecutionEngine.h +++ b/cpp/src/db/ExecutionEngine.h @@ -19,6 +19,7 @@ enum class EngineType { FAISS_IDMAP = 1, FAISS_IVFFLAT, FAISS_IVFSQ8, + MAX_VALUE = FAISS_IVFSQ8, }; class ExecutionEngine { diff --git a/cpp/src/db/FaissExecutionEngine.cpp b/cpp/src/db/FaissExecutionEngine.cpp index d2cb835364..e32363dd1d 100644 --- a/cpp/src/db/FaissExecutionEngine.cpp +++ b/cpp/src/db/FaissExecutionEngine.cpp @@ -110,7 +110,7 @@ Status FaissExecutionEngine::Merge(const std::string& location) { if (location == location_) { return Status::Error("Cannot Merge Self"); } - ENGINE_LOG_DEBUG << "Merge index file: " << location << " to: " << location_; + ENGINE_LOG_DEBUG << "Merge raw file: " << location << " to: " << location_; auto to_merge = zilliz::milvus::cache::CpuCacheMgr::GetInstance()->GetIndex(location); if (!to_merge) { @@ -165,8 +165,9 @@ Status FaissExecutionEngine::Search(long n, } Status FaissExecutionEngine::Cache() { - zilliz::milvus::cache::CpuCacheMgr::GetInstance( - )->InsertItem(location_, std::make_shared(pIndex_)); + auto index = std::make_shared(pIndex_); + cache::DataObjPtr data_obj = std::make_shared(index, PhysicalSize()); + zilliz::milvus::cache::CpuCacheMgr::GetInstance()->InsertItem(location_, data_obj); return Status::OK(); } diff --git a/cpp/src/db/MemManager.cpp b/cpp/src/db/MemManager.cpp index dbf0703173..366188b547 100644 --- a/cpp/src/db/MemManager.cpp +++ b/cpp/src/db/MemManager.cpp @@ -125,9 +125,6 @@ Status MemManager::InsertVectors(const std::string &table_id_, const float *vectors_, IDNumbers &vector_ids_) { - LOG(DEBUG) << "MemManager::InsertVectors: mutable mem = " << GetCurrentMutableMem() << - ", immutable mem = " << GetCurrentImmutableMem() << ", total mem = " << GetCurrentMem(); - std::unique_lock lock(mutex_); return InsertVectorsNoLock(table_id_, n_, vectors_, vector_ids_); diff --git a/cpp/src/db/MySQLMetaImpl.cpp b/cpp/src/db/MySQLMetaImpl.cpp index bd82e7e6a1..fa055feb3e 100644 --- a/cpp/src/db/MySQLMetaImpl.cpp +++ b/cpp/src/db/MySQLMetaImpl.cpp @@ -24,228 +24,895 @@ #include "mysql++/mysql++.h" + namespace zilliz { namespace milvus { namespace engine { namespace meta { - using namespace mysqlpp; +using namespace mysqlpp; + + -// static std::unique_ptr connectionPtr(new Connection()); -// std::recursive_mutex mysql_mutex; // -// std::unique_ptr& MySQLMetaImpl::getConnectionPtr() { -//// static std::recursive_mutex connectionMutex_; -// std::lock_guard lock(connectionMutex_); -// return connectionPtr; -// } - namespace { +// - Status HandleException(const std::string& desc, std::exception &e) { - ENGINE_LOG_ERROR << desc << ": " << e.what(); - return Status::DBTransactionError(desc, e.what()); + + + +namespace { + +Status HandleException(const std::string &desc, std::exception &e) { + ENGINE_LOG_ERROR << desc << ": " << e.what(); + return Status::DBTransactionError(desc, e.what()); +} + +class MetricCollector { + public: + MetricCollector() { + server::Metrics::GetInstance().MetaAccessTotalIncrement(); + start_time_ = METRICS_NOW_TIME; + } + + ~MetricCollector() { + auto end_time = METRICS_NOW_TIME; + auto total_time = METRICS_MICROSECONDS(start_time_, end_time); + server::Metrics::GetInstance().MetaAccessDurationSecondsHistogramObserve(total_time); + } + + private: + using TIME_POINT = std::chrono::system_clock::time_point; + TIME_POINT start_time_; +}; + +} + +Status MySQLMetaImpl::NextTableId(std::string &table_id) { + std::stringstream ss; + SimpleIDGenerator g; + ss << g.GetNextIDNumber(); + table_id = ss.str(); + return Status::OK(); +} + +Status MySQLMetaImpl::NextFileId(std::string &file_id) { + std::stringstream ss; + SimpleIDGenerator g; + ss << g.GetNextIDNumber(); + file_id = ss.str(); + return Status::OK(); +} + +MySQLMetaImpl::MySQLMetaImpl(const DBMetaOptions &options_, const int &mode) + : options_(options_), + mode_(mode) { + Initialize(); +} + +Status MySQLMetaImpl::Initialize() { + + + if (!boost::filesystem::is_directory(options_.path)) { + auto ret = boost::filesystem::create_directory(options_.path); + if (!ret) { + ENGINE_LOG_ERROR << "Failed to create db directory " << options_.path; + return Status::DBTransactionError("Failed to create db directory", options_.path); } - - class MetricCollector { - public: - MetricCollector() { - server::Metrics::GetInstance().MetaAccessTotalIncrement(); - start_time_ = METRICS_NOW_TIME; - } - - ~MetricCollector() { - auto end_time = METRICS_NOW_TIME; - auto total_time = METRICS_MICROSECONDS(start_time_, end_time); - server::Metrics::GetInstance().MetaAccessDurationSecondsHistogramObserve(total_time); - } - - private: - using TIME_POINT = std::chrono::system_clock::time_point; - TIME_POINT start_time_; - }; - } - Status MySQLMetaImpl::NextTableId(std::string &table_id) { - std::stringstream ss; - SimpleIDGenerator g; - ss << g.GetNextIDNumber(); - table_id = ss.str(); - return Status::OK(); - } + std::string uri = options_.backend_uri; - Status MySQLMetaImpl::NextFileId(std::string &file_id) { - std::stringstream ss; - SimpleIDGenerator g; - ss << g.GetNextIDNumber(); - file_id = ss.str(); - return Status::OK(); - } + std::string dialectRegex = "(.*)"; + std::string usernameRegex = "(.*)"; + std::string passwordRegex = "(.*)"; + std::string hostRegex = "(.*)"; + std::string portRegex = "(.*)"; + std::string dbNameRegex = "(.*)"; + std::string uriRegexStr = dialectRegex + "\\:\\/\\/" + + usernameRegex + "\\:" + + passwordRegex + "\\@" + + hostRegex + "\\:" + + portRegex + "\\/" + + dbNameRegex; + std::regex uriRegex(uriRegexStr); + std::smatch pieces_match; - MySQLMetaImpl::MySQLMetaImpl(const DBMetaOptions &options_, const int& mode) - : options_(options_), - mode_(mode) { - Initialize(); - } - - Status MySQLMetaImpl::Initialize() { - -// std::lock_guard lock(mysql_mutex); - - if (!boost::filesystem::is_directory(options_.path)) { - auto ret = boost::filesystem::create_directory(options_.path); - if (!ret) { - ENGINE_LOG_ERROR << "Failed to create db directory " << options_.path; - return Status::DBTransactionError("Failed to create db directory", options_.path); - } + if (std::regex_match(uri, pieces_match, uriRegex)) { + std::string dialect = pieces_match[1].str(); + std::transform(dialect.begin(), dialect.end(), dialect.begin(), ::tolower); + if (dialect.find("mysql") == std::string::npos) { + return Status::Error("URI's dialect is not MySQL"); } + std::string username = pieces_match[2].str(); + std::string password = pieces_match[3].str(); + std::string serverAddress = pieces_match[4].str(); + unsigned int port = 0; + if (!pieces_match[5].str().empty()) { + port = std::stoi(pieces_match[5].str()); + } + std::string dbName = pieces_match[6].str(); - std::string uri = options_.backend_uri; - std::string dialectRegex = "(.*)"; - std::string usernameRegex = "(.*)"; - std::string passwordRegex = "(.*)"; - std::string hostRegex = "(.*)"; - std::string portRegex = "(.*)"; - std::string dbNameRegex = "(.*)"; - std::string uriRegexStr = dialectRegex + "\\:\\/\\/" + - usernameRegex + "\\:" + - passwordRegex + "\\@" + - hostRegex + "\\:" + - portRegex + "\\/" + - dbNameRegex; - std::regex uriRegex(uriRegexStr); - std::smatch pieces_match; + int threadHint = std::thread::hardware_concurrency(); + int maxPoolSize = threadHint == 0 ? 8 : threadHint; + mysql_connection_pool_ = + std::make_shared(dbName, username, password, serverAddress, port, maxPoolSize); - if (std::regex_match(uri, pieces_match, uriRegex)) { - std::string dialect = pieces_match[1].str(); - std::transform(dialect.begin(), dialect.end(), dialect.begin(), ::tolower); - if (dialect.find("mysql") == std::string::npos) { - return Status::Error("URI's dialect is not MySQL"); + ENGINE_LOG_DEBUG << "MySQL connection pool: maximum pool size = " << std::to_string(maxPoolSize); + try { + + if (mode_ != Options::MODE::READ_ONLY) { + CleanUp(); } - std::string username = pieces_match[2].str(); - std::string password = pieces_match[3].str(); - std::string serverAddress = pieces_match[4].str(); - unsigned int port = 0; - if (!pieces_match[5].str().empty()) { - port = std::stoi(pieces_match[5].str()); - } - std::string dbName = pieces_match[6].str(); -// std::cout << dbName << " " << serverAddress << " " << username << " " << password << " " << port << std::endl; -// connectionPtr->set_option(new MultiStatementsOption(true)); -// connectionPtr->set_option(new mysqlpp::ReconnectOption(true)); - int threadHint = std::thread::hardware_concurrency(); - int maxPoolSize = threadHint == 0 ? 8 : threadHint; - mysql_connection_pool_ = std::make_shared(dbName, username, password, serverAddress, port, maxPoolSize); -// std::cout << "MySQL++ thread aware:" << std::to_string(connectionPtr->thread_aware()) << std::endl; - ENGINE_LOG_DEBUG << "MySQL connection pool: maximum pool size = " << std::to_string(maxPoolSize); - try { - if (mode_ != Options::MODE::READ_ONLY) { - CleanUp(); + { + ScopedConnection connectionPtr(*mysql_connection_pool_, safe_grab); + + if (connectionPtr == nullptr) { + return Status::Error("Failed to connect to database server"); } - { - ScopedConnection connectionPtr(*mysql_connection_pool_, safe_grab); - if (connectionPtr == nullptr) { - return Status::Error("Failed to connect to database server"); - } + if (!connectionPtr->thread_aware()) { + ENGINE_LOG_ERROR << "MySQL++ wasn't built with thread awareness! Can't run without it."; + return Status::Error("MySQL++ wasn't built with thread awareness! Can't run without it."); + } + Query InitializeQuery = connectionPtr->query(); -// ENGINE_LOG_DEBUG << "MySQLMetaImpl::Initialize: connections in use = " << mysql_connection_pool_->getConnectionsInUse(); -// if (!connectionPtr->connect(dbName, serverAddress, username, password, port)) { -// return Status::Error("DB connection failed: ", connectionPtr->error()); -// } - if (!connectionPtr->thread_aware()) { - ENGINE_LOG_ERROR << "MySQL++ wasn't built with thread awareness! Can't run without it."; - return Status::Error("MySQL++ wasn't built with thread awareness! Can't run without it."); - } - Query InitializeQuery = connectionPtr->query(); -// InitializeQuery << "SET max_allowed_packet=67108864;"; -// if (!InitializeQuery.exec()) { -// return Status::DBTransactionError("Initialization Error", InitializeQuery.error()); -// } + InitializeQuery << "CREATE TABLE IF NOT EXISTS Tables (" << + "id BIGINT PRIMARY KEY AUTO_INCREMENT, " << + "table_id VARCHAR(255) UNIQUE NOT NULL, " << + "state INT NOT NULL, " << + "dimension SMALLINT NOT NULL, " << + "created_on BIGINT NOT NULL, " << + "files_cnt BIGINT DEFAULT 0 NOT NULL, " << + "engine_type INT DEFAULT 1 NOT NULL, " << + "store_raw_data BOOL DEFAULT false NOT NULL);"; -// InitializeQuery << "DROP TABLE IF EXISTS Tables, TableFiles;"; - InitializeQuery << "CREATE TABLE IF NOT EXISTS Tables (" << - "id BIGINT PRIMARY KEY AUTO_INCREMENT, " << - "table_id VARCHAR(255) UNIQUE NOT NULL, " << - "state INT NOT NULL, " << - "dimension SMALLINT NOT NULL, " << - "created_on BIGINT NOT NULL, " << - "files_cnt BIGINT DEFAULT 0 NOT NULL, " << - "engine_type INT DEFAULT 1 NOT NULL, " << - "store_raw_data BOOL DEFAULT false NOT NULL);"; + ENGINE_LOG_DEBUG << "MySQLMetaImpl::Initialize: " << InitializeQuery.str(); - ENGINE_LOG_DEBUG << "MySQLMetaImpl::Initialize: " << InitializeQuery.str(); + if (!InitializeQuery.exec()) { + return Status::DBTransactionError("Initialization Error", InitializeQuery.error()); + } - if (!InitializeQuery.exec()) { - return Status::DBTransactionError("Initialization Error", InitializeQuery.error()); - } + InitializeQuery << "CREATE TABLE IF NOT EXISTS TableFiles (" << + "id BIGINT PRIMARY KEY AUTO_INCREMENT, " << + "table_id VARCHAR(255) NOT NULL, " << + "engine_type INT DEFAULT 1 NOT NULL, " << + "file_id VARCHAR(255) NOT NULL, " << + "file_type INT DEFAULT 0 NOT NULL, " << + "size BIGINT DEFAULT 0 NOT NULL, " << + "updated_time BIGINT NOT NULL, " << + "created_on BIGINT NOT NULL, " << + "date INT DEFAULT -1 NOT NULL);"; - InitializeQuery << "CREATE TABLE IF NOT EXISTS TableFiles (" << - "id BIGINT PRIMARY KEY AUTO_INCREMENT, " << - "table_id VARCHAR(255) NOT NULL, " << - "engine_type INT DEFAULT 1 NOT NULL, " << - "file_id VARCHAR(255) NOT NULL, " << - "file_type INT DEFAULT 0 NOT NULL, " << - "size BIGINT DEFAULT 0 NOT NULL, " << - "updated_time BIGINT NOT NULL, " << - "created_on BIGINT NOT NULL, " << - "date INT DEFAULT -1 NOT NULL);"; + ENGINE_LOG_DEBUG << "MySQLMetaImpl::Initialize: " << InitializeQuery.str(); - ENGINE_LOG_DEBUG << "MySQLMetaImpl::Initialize: " << InitializeQuery.str(); + if (!InitializeQuery.exec()) { + return Status::DBTransactionError("Initialization Error", InitializeQuery.error()); + } + } //Scoped Connection - if (!InitializeQuery.exec()) { - return Status::DBTransactionError("Initialization Error", InitializeQuery.error()); - } - } //Scoped Connection -// //Consume all results to avoid "Commands out of sync" error -// while (InitializeQuery.more_results()) { -// InitializeQuery.store_next(); -// } - return Status::OK(); -// if (InitializeQuery.exec()) { -// std::cout << "XXXXXXXXXXXXXXXXXXXXXXXXX" << std::endl; -// while (InitializeQuery.more_results()) { -// InitializeQuery.store_next(); -// } -// return Status::OK(); -// } else { -// return Status::DBTransactionError("Initialization Error", InitializeQuery.error()); -// } - } catch (const BadQuery& er) { - // Handle any query errors - ENGINE_LOG_ERROR << "QUERY ERROR DURING INITIALIZATION" << ": " << er.what(); - return Status::DBTransactionError("QUERY ERROR DURING INITIALIZATION", er.what()); - } catch (const Exception& er) { - // Catch-all for any other MySQL++ exceptions - ENGINE_LOG_ERROR << "GENERAL ERROR DURING INITIALIZATION" << ": " << er.what(); - return Status::DBTransactionError("GENERAL ERROR DURING INITIALIZATION", er.what()); - } catch (std::exception &e) { - return HandleException("Encounter exception during initialization", e); - } - } - else { - ENGINE_LOG_ERROR << "Wrong URI format. URI = " << uri; - return Status::Error("Wrong URI format"); + + + return Status::OK(); + + + } catch (const BadQuery &er) { + // Handle any query errors + ENGINE_LOG_ERROR << "QUERY ERROR DURING INITIALIZATION" << ": " << er.what(); + return Status::DBTransactionError("QUERY ERROR DURING INITIALIZATION", er.what()); + } catch (const Exception &er) { + // Catch-all for any other MySQL++ exceptions + ENGINE_LOG_ERROR << "GENERAL ERROR DURING INITIALIZATION" << ": " << er.what(); + return Status::DBTransactionError("GENERAL ERROR DURING INITIALIZATION", er.what()); + } catch (std::exception &e) { + return HandleException("Encounter exception during initialization", e); } + } else { + ENGINE_LOG_ERROR << "Wrong URI format. URI = " << uri; + return Status::Error("Wrong URI format"); } +} // PXU TODO: Temp solution. Will fix later - Status MySQLMetaImpl::DropPartitionsByDates(const std::string &table_id, - const DatesT &dates) { +Status MySQLMetaImpl::DropPartitionsByDates(const std::string &table_id, + const DatesT &dates) { -// std::lock_guard lock(mysql_mutex); - if (dates.empty()) { - return Status::OK(); + if (dates.empty()) { + return Status::OK(); + } + + TableSchema table_schema; + table_schema.table_id_ = table_id; + auto status = DescribeTable(table_schema); + if (!status.ok()) { + return status; + } + + try { + + auto yesterday = GetDateWithDelta(-1); + + for (auto &date : dates) { + if (date >= yesterday) { + return Status::Error("Could not delete partitions within 2 days"); + } } + std::stringstream dateListSS; + for (auto &date : dates) { + dateListSS << std::to_string(date) << ", "; + } + std::string dateListStr = dateListSS.str(); + dateListStr = dateListStr.substr(0, dateListStr.size() - 2); //remove the last ", " + + { + ScopedConnection connectionPtr(*mysql_connection_pool_, safe_grab); + + if (connectionPtr == nullptr) { + return Status::Error("Failed to connect to database server"); + } + + + Query dropPartitionsByDatesQuery = connectionPtr->query(); + + dropPartitionsByDatesQuery << "UPDATE TableFiles " << + "SET file_type = " << std::to_string(TableFileSchema::TO_DELETE) << " " << + "WHERE table_id = " << quote << table_id << " AND " << + "date in (" << dateListStr << ");"; + + ENGINE_LOG_DEBUG << "MySQLMetaImpl::DropPartitionsByDates: " << dropPartitionsByDatesQuery.str(); + + if (!dropPartitionsByDatesQuery.exec()) { + ENGINE_LOG_ERROR << "QUERY ERROR WHEN DROPPING PARTITIONS BY DATES"; + return Status::DBTransactionError("QUERY ERROR WHEN DROPPING PARTITIONS BY DATES", + dropPartitionsByDatesQuery.error()); + } + } //Scoped Connection + } catch (const BadQuery &er) { + // Handle any query errors + ENGINE_LOG_ERROR << "QUERY ERROR WHEN DROPPING PARTITIONS BY DATES" << ": " << er.what(); + return Status::DBTransactionError("QUERY ERROR WHEN DROPPING PARTITIONS BY DATES", er.what()); + } catch (const Exception &er) { + // Catch-all for any other MySQL++ exceptions + ENGINE_LOG_ERROR << "GENERAL ERROR WHEN DROPPING PARTITIONS BY DATES" << ": " << er.what(); + return Status::DBTransactionError("GENERAL ERROR WHEN DROPPING PARTITIONS BY DATES", er.what()); + } + return Status::OK(); +} + +Status MySQLMetaImpl::CreateTable(TableSchema &table_schema) { + + + try { + + MetricCollector metric; + + { + ScopedConnection connectionPtr(*mysql_connection_pool_, safe_grab); + + if (connectionPtr == nullptr) { + return Status::Error("Failed to connect to database server"); + } + + + Query createTableQuery = connectionPtr->query(); + + if (table_schema.table_id_.empty()) { + NextTableId(table_schema.table_id_); + } else { + createTableQuery << "SELECT state FROM Tables " << + "WHERE table_id = " << quote << table_schema.table_id_ << ";"; + + + ENGINE_LOG_DEBUG << "MySQLMetaImpl::CreateTable: " << createTableQuery.str(); + + StoreQueryResult res = createTableQuery.store(); + + if (res.num_rows() == 1) { + int state = res[0]["state"]; + if (TableSchema::TO_DELETE == state) { + return Status::Error("Table already exists and it is in delete state, please wait a second"); + } else { + return Status::AlreadyExist("Table already exists"); + } + } + } + + + table_schema.files_cnt_ = 0; + table_schema.id_ = -1; + table_schema.created_on_ = utils::GetMicroSecTimeStamp(); + + + std::string id = "NULL"; //auto-increment + std::string table_id = table_schema.table_id_; + std::string state = std::to_string(table_schema.state_); + std::string dimension = std::to_string(table_schema.dimension_); + std::string created_on = std::to_string(table_schema.created_on_); + std::string files_cnt = "0"; + std::string engine_type = std::to_string(table_schema.engine_type_); + std::string store_raw_data = table_schema.store_raw_data_ ? "true" : "false"; + + createTableQuery << "INSERT INTO Tables VALUES" << + "(" << id << ", " << quote << table_id << ", " << state << ", " << dimension << ", " << + created_on << ", " << files_cnt << ", " << engine_type << ", " << store_raw_data << ");"; + + + ENGINE_LOG_DEBUG << "MySQLMetaImpl::CreateTable: " << createTableQuery.str(); + + if (SimpleResult res = createTableQuery.execute()) { + table_schema.id_ = res.insert_id(); //Might need to use SELECT LAST_INSERT_ID()? + + //Consume all results to avoid "Commands out of sync" error + + + + } else { + ENGINE_LOG_ERROR << "Add Table Error"; + return Status::DBTransactionError("Add Table Error", createTableQuery.error()); + } + } //Scoped Connection + + + + + + return utils::CreateTablePath(options_, table_schema.table_id_); + + } catch (const BadQuery &er) { + // Handle any query errors + ENGINE_LOG_ERROR << "QUERY ERROR WHEN ADDING TABLE" << ": " << er.what(); + return Status::DBTransactionError("QUERY ERROR WHEN ADDING TABLE", er.what()); + } catch (const Exception &er) { + // Catch-all for any other MySQL++ exceptions + ENGINE_LOG_ERROR << "GENERAL ERROR WHEN ADDING TABLE" << ": " << er.what(); + return Status::DBTransactionError("GENERAL ERROR WHEN ADDING TABLE", er.what()); + } catch (std::exception &e) { + return HandleException("Encounter exception when create table", e); + } + + return Status::OK(); +} + +Status MySQLMetaImpl::HasNonIndexFiles(const std::string &table_id, bool &has) { + + has = false; + + try { + + StoreQueryResult res; + + { + ScopedConnection connectionPtr(*mysql_connection_pool_, safe_grab); + + if (connectionPtr == nullptr) { + return Status::Error("Failed to connect to database server"); + } + + + Query hasNonIndexFilesQuery = connectionPtr->query(); + //since table_id is a unique column we just need to check whether it exists or not + hasNonIndexFilesQuery << "SELECT EXISTS " << + "(SELECT 1 FROM TableFiles " << + "WHERE table_id = " << quote << table_id << " AND " << + "(file_type = " << std::to_string(TableFileSchema::RAW) << " OR " << + "file_type = " << std::to_string(TableFileSchema::NEW) << " OR " << + "file_type = " << std::to_string(TableFileSchema::TO_INDEX) << ")) " << + "AS " << quote << "check" << ";"; + + ENGINE_LOG_DEBUG << "MySQLMetaImpl::HasNonIndexFiles: " << hasNonIndexFilesQuery.str(); + + res = hasNonIndexFilesQuery.store(); + } //Scoped Connection + + int check = res[0]["check"]; + has = (check == 1); + + } catch (const BadQuery &er) { + // Handle any query errors + ENGINE_LOG_ERROR << "QUERY ERROR WHEN CHECKING IF NON INDEX FILES EXISTS" << ": " << er.what(); + return Status::DBTransactionError("QUERY ERROR WHEN CHECKING IF NON INDEX FILES EXISTS", er.what()); + } catch (const Exception &er) { + // Catch-all for any other MySQL++ exceptions + ENGINE_LOG_ERROR << "GENERAL ERROR WHEN CHECKING IF NON INDEX FILES EXISTS" << ": " << er.what(); + return Status::DBTransactionError("GENERAL ERROR WHEN CHECKING IF NON INDEX FILES EXISTS", er.what()); + } + + return Status::OK(); +} + +Status MySQLMetaImpl::DeleteTable(const std::string &table_id) { + + + try { + + MetricCollector metric; + + { + ScopedConnection connectionPtr(*mysql_connection_pool_, safe_grab); + + if (connectionPtr == nullptr) { + return Status::Error("Failed to connect to database server"); + } + + + + + + //soft delete table + Query deleteTableQuery = connectionPtr->query(); +// + deleteTableQuery << "UPDATE Tables " << + "SET state = " << std::to_string(TableSchema::TO_DELETE) << " " << + "WHERE table_id = " << quote << table_id << ";"; + + ENGINE_LOG_DEBUG << "MySQLMetaImpl::DeleteTable: " << deleteTableQuery.str(); + + if (!deleteTableQuery.exec()) { + ENGINE_LOG_ERROR << "QUERY ERROR WHEN DELETING TABLE"; + return Status::DBTransactionError("QUERY ERROR WHEN DELETING TABLE", deleteTableQuery.error()); + } + + } //Scoped Connection + + + if (mode_ == Options::MODE::CLUSTER) { + DeleteTableFiles(table_id); + } + + } catch (const BadQuery &er) { + // Handle any query errors + ENGINE_LOG_ERROR << "GENERAL ERROR WHEN DELETING TABLE" << ": " << er.what(); + return Status::DBTransactionError("QUERY ERROR WHEN DELETING TABLE", er.what()); + } catch (const Exception &er) { + // Catch-all for any other MySQL++ exceptions + ENGINE_LOG_ERROR << "GENERAL ERROR WHEN DELETING TABLE" << ": " << er.what(); + return Status::DBTransactionError("GENERAL ERROR WHEN DELETING TABLE", er.what()); + } + + return Status::OK(); +} + +Status MySQLMetaImpl::DeleteTableFiles(const std::string &table_id) { + try { + MetricCollector metric; + + { + ScopedConnection connectionPtr(*mysql_connection_pool_, safe_grab); + + if (connectionPtr == nullptr) { + return Status::Error("Failed to connect to database server"); + } + + + + + + //soft delete table files + Query deleteTableFilesQuery = connectionPtr->query(); + // + deleteTableFilesQuery << "UPDATE TableFiles " << + "SET file_type = " << std::to_string(TableFileSchema::TO_DELETE) << ", " << + "updated_time = " << std::to_string(utils::GetMicroSecTimeStamp()) << " " << + "WHERE table_id = " << quote << table_id << " AND " << + "file_type <> " << std::to_string(TableFileSchema::TO_DELETE) << ";"; + + ENGINE_LOG_DEBUG << "MySQLMetaImpl::DeleteTableFiles: " << deleteTableFilesQuery.str(); + + if (!deleteTableFilesQuery.exec()) { + ENGINE_LOG_ERROR << "QUERY ERROR WHEN DELETING TABLE FILES"; + return Status::DBTransactionError("QUERY ERROR WHEN DELETING TABLE", deleteTableFilesQuery.error()); + } + } //Scoped Connection + } catch (const BadQuery &er) { + // Handle any query errors + ENGINE_LOG_ERROR << "QUERY ERROR WHEN DELETING TABLE FILES" << ": " << er.what(); + return Status::DBTransactionError("QUERY ERROR WHEN DELETING TABLE FILES", er.what()); + } catch (const Exception &er) { + // Catch-all for any other MySQL++ exceptions + ENGINE_LOG_ERROR << "GENERAL ERROR WHEN DELETING TABLE FILES" << ": " << er.what(); + return Status::DBTransactionError("GENERAL ERROR WHEN DELETING TABLE FILES", er.what()); + } + + return Status::OK(); +} + +Status MySQLMetaImpl::DescribeTable(TableSchema &table_schema) { + + + try { + + MetricCollector metric; + + StoreQueryResult res; + + { + ScopedConnection connectionPtr(*mysql_connection_pool_, safe_grab); + + if (connectionPtr == nullptr) { + return Status::Error("Failed to connect to database server"); + } + + + Query describeTableQuery = connectionPtr->query(); + describeTableQuery << "SELECT id, dimension, files_cnt, engine_type, store_raw_data " << + "FROM Tables " << + "WHERE table_id = " << quote << table_schema.table_id_ << " " << + "AND state <> " << std::to_string(TableSchema::TO_DELETE) << ";"; + + ENGINE_LOG_DEBUG << "MySQLMetaImpl::DescribeTable: " << describeTableQuery.str(); + + res = describeTableQuery.store(); + } //Scoped Connection + + if (res.num_rows() == 1) { + const Row &resRow = res[0]; + + table_schema.id_ = resRow["id"]; //implicit conversion + + table_schema.dimension_ = resRow["dimension"]; + + table_schema.files_cnt_ = resRow["files_cnt"]; + + table_schema.engine_type_ = resRow["engine_type"]; + + int store_raw_data = resRow["store_raw_data"]; + table_schema.store_raw_data_ = (store_raw_data == 1); + } else { + return Status::NotFound("Table " + table_schema.table_id_ + " not found"); + } + + } catch (const BadQuery &er) { + // Handle any query errors + ENGINE_LOG_ERROR << "QUERY ERROR WHEN DESCRIBING TABLE" << ": " << er.what(); + return Status::DBTransactionError("QUERY ERROR WHEN DESCRIBING TABLE", er.what()); + } catch (const Exception &er) { + // Catch-all for any other MySQL++ exceptions + ENGINE_LOG_ERROR << "GENERAL ERROR WHEN DESCRIBING TABLE" << ": " << er.what(); + return Status::DBTransactionError("GENERAL ERROR WHEN DESCRIBING TABLE", er.what()); + } + + return Status::OK(); +} + +Status MySQLMetaImpl::HasTable(const std::string &table_id, bool &has_or_not) { + + + try { + + MetricCollector metric; + + StoreQueryResult res; + + { + ScopedConnection connectionPtr(*mysql_connection_pool_, safe_grab); + + if (connectionPtr == nullptr) { + return Status::Error("Failed to connect to database server"); + } + + + Query hasTableQuery = connectionPtr->query(); + //since table_id is a unique column we just need to check whether it exists or not + hasTableQuery << "SELECT EXISTS " << + "(SELECT 1 FROM Tables " << + "WHERE table_id = " << quote << table_id << " " << + "AND state <> " << std::to_string(TableSchema::TO_DELETE) << ") " << + "AS " << quote << "check" << ";"; + + ENGINE_LOG_DEBUG << "MySQLMetaImpl::HasTable: " << hasTableQuery.str(); + + res = hasTableQuery.store(); + } //Scoped Connection + + int check = res[0]["check"]; + has_or_not = (check == 1); + + } catch (const BadQuery &er) { + // Handle any query errors + ENGINE_LOG_ERROR << "QUERY ERROR WHEN CHECKING IF TABLE EXISTS" << ": " << er.what(); + return Status::DBTransactionError("QUERY ERROR WHEN CHECKING IF TABLE EXISTS", er.what()); + } catch (const Exception &er) { + // Catch-all for any other MySQL++ exceptions + ENGINE_LOG_ERROR << "GENERAL ERROR WHEN CHECKING IF TABLE EXISTS" << ": " << er.what(); + return Status::DBTransactionError("GENERAL ERROR WHEN CHECKING IF TABLE EXISTS", er.what()); + } + + return Status::OK(); +} + +Status MySQLMetaImpl::AllTables(std::vector &table_schema_array) { + + + try { + + MetricCollector metric; + + StoreQueryResult res; + + { + ScopedConnection connectionPtr(*mysql_connection_pool_, safe_grab); + + if (connectionPtr == nullptr) { + return Status::Error("Failed to connect to database server"); + } + + + Query allTablesQuery = connectionPtr->query(); + allTablesQuery << "SELECT id, table_id, dimension, files_cnt, engine_type, store_raw_data " << + "FROM Tables " << + "WHERE state <> " << std::to_string(TableSchema::TO_DELETE) << ";"; + + ENGINE_LOG_DEBUG << "MySQLMetaImpl::AllTables: " << allTablesQuery.str(); + + res = allTablesQuery.store(); + } //Scoped Connection + + for (auto &resRow : res) { + TableSchema table_schema; + + table_schema.id_ = resRow["id"]; //implicit conversion + + std::string table_id; + resRow["table_id"].to_string(table_id); + table_schema.table_id_ = table_id; + + table_schema.dimension_ = resRow["dimension"]; + + table_schema.files_cnt_ = resRow["files_cnt"]; + + table_schema.engine_type_ = resRow["engine_type"]; + + int store_raw_data = resRow["store_raw_data"]; + table_schema.store_raw_data_ = (store_raw_data == 1); + + table_schema_array.emplace_back(table_schema); + } + } catch (const BadQuery &er) { + // Handle any query errors + ENGINE_LOG_ERROR << "QUERY ERROR WHEN DESCRIBING ALL TABLES" << ": " << er.what(); + return Status::DBTransactionError("QUERY ERROR WHEN DESCRIBING ALL TABLES", er.what()); + } catch (const Exception &er) { + // Catch-all for any other MySQL++ exceptions + ENGINE_LOG_ERROR << "GENERAL ERROR WHEN DESCRIBING ALL TABLES" << ": " << er.what(); + return Status::DBTransactionError("GENERAL ERROR WHEN DESCRIBING ALL TABLES", er.what()); + } + + return Status::OK(); +} + +Status MySQLMetaImpl::CreateTableFile(TableFileSchema &file_schema) { + + + if (file_schema.date_ == EmptyDate) { + file_schema.date_ = Meta::GetDate(); + } + TableSchema table_schema; + table_schema.table_id_ = file_schema.table_id_; + auto status = DescribeTable(table_schema); + if (!status.ok()) { + return status; + } + + try { + + MetricCollector metric; + + NextFileId(file_schema.file_id_); + file_schema.file_type_ = TableFileSchema::NEW; + file_schema.dimension_ = table_schema.dimension_; + file_schema.size_ = 0; + file_schema.created_on_ = utils::GetMicroSecTimeStamp(); + file_schema.updated_time_ = file_schema.created_on_; + file_schema.engine_type_ = table_schema.engine_type_; + utils::GetTableFilePath(options_, file_schema); + + std::string id = "NULL"; //auto-increment + std::string table_id = file_schema.table_id_; + std::string engine_type = std::to_string(file_schema.engine_type_); + std::string file_id = file_schema.file_id_; + std::string file_type = std::to_string(file_schema.file_type_); + std::string size = std::to_string(file_schema.size_); + std::string updated_time = std::to_string(file_schema.updated_time_); + std::string created_on = std::to_string(file_schema.created_on_); + std::string date = std::to_string(file_schema.date_); + + { + ScopedConnection connectionPtr(*mysql_connection_pool_, safe_grab); + + if (connectionPtr == nullptr) { + return Status::Error("Failed to connect to database server"); + } + + + Query createTableFileQuery = connectionPtr->query(); + + createTableFileQuery << "INSERT INTO TableFiles VALUES" << + "(" << id << ", " << quote << table_id << ", " << engine_type << ", " << + quote << file_id << ", " << file_type << ", " << size << ", " << + updated_time << ", " << created_on << ", " << date << ");"; + + ENGINE_LOG_DEBUG << "MySQLMetaImpl::CreateTableFile: " << createTableFileQuery.str(); + + if (SimpleResult res = createTableFileQuery.execute()) { + file_schema.id_ = res.insert_id(); //Might need to use SELECT LAST_INSERT_ID()? + + //Consume all results to avoid "Commands out of sync" error + + + + } else { + ENGINE_LOG_ERROR << "QUERY ERROR WHEN ADDING TABLE FILE"; + return Status::DBTransactionError("Add file Error", createTableFileQuery.error()); + } + } // Scoped Connection + + return utils::CreateTableFilePath(options_, file_schema); + + } catch (const BadQuery &er) { + // Handle any query errors + ENGINE_LOG_ERROR << "QUERY ERROR WHEN ADDING TABLE FILE" << ": " << er.what(); + return Status::DBTransactionError("QUERY ERROR WHEN ADDING TABLE FILE", er.what()); + } catch (const Exception &er) { + // Catch-all for any other MySQL++ exceptions + ENGINE_LOG_ERROR << "GENERAL ERROR WHEN ADDING TABLE FILE" << ": " << er.what(); + return Status::DBTransactionError("GENERAL ERROR WHEN ADDING TABLE FILE", er.what()); + } catch (std::exception &ex) { + return HandleException("Encounter exception when create table file", ex); + } + + return Status::OK(); +} + +Status MySQLMetaImpl::FilesToIndex(TableFilesSchema &files) { + + + files.clear(); + + try { + + MetricCollector metric; + + StoreQueryResult res; + + { + ScopedConnection connectionPtr(*mysql_connection_pool_, safe_grab); + + if (connectionPtr == nullptr) { + return Status::Error("Failed to connect to database server"); + } + + + Query filesToIndexQuery = connectionPtr->query(); + filesToIndexQuery << "SELECT id, table_id, engine_type, file_id, file_type, size, date " << + "FROM TableFiles " << + "WHERE file_type = " << std::to_string(TableFileSchema::TO_INDEX) << ";"; + + ENGINE_LOG_DEBUG << "MySQLMetaImpl::FilesToIndex: " << filesToIndexQuery.str(); + + res = filesToIndexQuery.store(); + } //Scoped Connection + + std::map groups; + TableFileSchema table_file; + for (auto &resRow : res) { + + table_file.id_ = resRow["id"]; //implicit conversion + + std::string table_id; + resRow["table_id"].to_string(table_id); + table_file.table_id_ = table_id; + + table_file.engine_type_ = resRow["engine_type"]; + + std::string file_id; + resRow["file_id"].to_string(file_id); + table_file.file_id_ = file_id; + + table_file.file_type_ = resRow["file_type"]; + + table_file.size_ = resRow["size"]; + + table_file.date_ = resRow["date"]; + + auto groupItr = groups.find(table_file.table_id_); + if (groupItr == groups.end()) { + TableSchema table_schema; + table_schema.table_id_ = table_file.table_id_; + auto status = DescribeTable(table_schema); + if (!status.ok()) { + return status; + } + groups[table_file.table_id_] = table_schema; + + } + table_file.dimension_ = groups[table_file.table_id_].dimension_; + + utils::GetTableFilePath(options_, table_file); + + files.push_back(table_file); + } + } catch (const BadQuery &er) { + // Handle any query errors + ENGINE_LOG_ERROR << "QUERY ERROR WHEN FINDING TABLE FILES TO INDEX" << ": " << er.what(); + return Status::DBTransactionError("QUERY ERROR WHEN FINDING TABLE FILES TO INDEX", er.what()); + } catch (const Exception &er) { + // Catch-all for any other MySQL++ exceptions + ENGINE_LOG_ERROR << "GENERAL ERROR WHEN FINDING TABLE FILES TO INDEX" << ": " << er.what(); + return Status::DBTransactionError("GENERAL ERROR WHEN FINDING TABLE FILES TO INDEX", er.what()); + } + + return Status::OK(); +} + +Status MySQLMetaImpl::FilesToSearch(const std::string &table_id, + const DatesT &partition, + DatePartionedTableFilesSchema &files) { + + + files.clear(); + + try { + + MetricCollector metric; + + StoreQueryResult res; + + { + ScopedConnection connectionPtr(*mysql_connection_pool_, safe_grab); + + if (connectionPtr == nullptr) { + return Status::Error("Failed to connect to database server"); + } + + + if (partition.empty()) { + + Query filesToSearchQuery = connectionPtr->query(); + filesToSearchQuery << "SELECT id, table_id, engine_type, file_id, file_type, size, date " << + "FROM TableFiles " << + "WHERE table_id = " << quote << table_id << " AND " << + "(file_type = " << std::to_string(TableFileSchema::RAW) << " OR " << + "file_type = " << std::to_string(TableFileSchema::TO_INDEX) << " OR " << + "file_type = " << std::to_string(TableFileSchema::INDEX) << ");"; + + ENGINE_LOG_DEBUG << "MySQLMetaImpl::FilesToSearch: " << filesToSearchQuery.str(); + + res = filesToSearchQuery.store(); + + } else { + + Query filesToSearchQuery = connectionPtr->query(); + + std::stringstream partitionListSS; + for (auto &date : partition) { + partitionListSS << std::to_string(date) << ", "; + } + std::string partitionListStr = partitionListSS.str(); + partitionListStr = partitionListStr.substr(0, partitionListStr.size() - 2); //remove the last ", " + + filesToSearchQuery << "SELECT id, table_id, engine_type, file_id, file_type, size, date " << + "FROM TableFiles " << + "WHERE table_id = " << quote << table_id << " AND " << + "date IN (" << partitionListStr << ") AND " << + "(file_type = " << std::to_string(TableFileSchema::RAW) << " OR " << + "file_type = " << std::to_string(TableFileSchema::TO_INDEX) << " OR " << + "file_type = " << std::to_string(TableFileSchema::INDEX) << ");"; + + ENGINE_LOG_DEBUG << "MySQLMetaImpl::FilesToSearch: " << filesToSearchQuery.str(); + + res = filesToSearchQuery.store(); + + } + } //Scoped Connection + TableSchema table_schema; table_schema.table_id_ = table_id; auto status = DescribeTable(table_schema); @@ -253,469 +920,450 @@ namespace meta { return status; } - try { + TableFileSchema table_file; + for (auto &resRow : res) { - auto yesterday = GetDateWithDelta(-1); + table_file.id_ = resRow["id"]; //implicit conversion - for (auto &date : dates) { - if (date >= yesterday) { - return Status::Error("Could not delete partitions within 2 days"); - } + std::string table_id_str; + resRow["table_id"].to_string(table_id_str); + table_file.table_id_ = table_id_str; + + table_file.engine_type_ = resRow["engine_type"]; + + std::string file_id; + resRow["file_id"].to_string(file_id); + table_file.file_id_ = file_id; + + table_file.file_type_ = resRow["file_type"]; + + table_file.size_ = resRow["size"]; + + table_file.date_ = resRow["date"]; + + table_file.dimension_ = table_schema.dimension_; + + utils::GetTableFilePath(options_, table_file); + + auto dateItr = files.find(table_file.date_); + if (dateItr == files.end()) { + files[table_file.date_] = TableFilesSchema(); } - std::stringstream dateListSS; - for (auto &date : dates) { - dateListSS << std::to_string(date) << ", "; - } - std::string dateListStr = dateListSS.str(); - dateListStr = dateListStr.substr(0, dateListStr.size() - 2); //remove the last ", " - - { - ScopedConnection connectionPtr(*mysql_connection_pool_, safe_grab); - - if (connectionPtr == nullptr) { - return Status::Error("Failed to connect to database server"); - } - -// if (mysql_connection_pool_->getConnectionsInUse() <= 0) { -// ENGINE_LOG_WARNING << "MySQLMetaImpl::DropPartitionsByDates connection in use = " << mysql_connection_pool_->getConnectionsInUse(); -// } - - Query dropPartitionsByDatesQuery = connectionPtr->query(); - - dropPartitionsByDatesQuery << "UPDATE TableFiles " << - "SET file_type = " << std::to_string(TableFileSchema::TO_DELETE) << " " << - "WHERE table_id = " << quote << table_id << " AND " << - "date in (" << dateListStr << ");"; - - ENGINE_LOG_DEBUG << "MySQLMetaImpl::DropPartitionsByDates: " << dropPartitionsByDatesQuery.str(); - - if (!dropPartitionsByDatesQuery.exec()) { - ENGINE_LOG_ERROR << "QUERY ERROR WHEN DROPPING PARTITIONS BY DATES"; - return Status::DBTransactionError("QUERY ERROR WHEN DROPPING PARTITIONS BY DATES", - dropPartitionsByDatesQuery.error()); - } - } //Scoped Connection - } catch (const BadQuery& er) { - // Handle any query errors - ENGINE_LOG_ERROR << "QUERY ERROR WHEN DROPPING PARTITIONS BY DATES" << ": " << er.what(); - return Status::DBTransactionError("QUERY ERROR WHEN DROPPING PARTITIONS BY DATES", er.what()); - } catch (const Exception& er) { - // Catch-all for any other MySQL++ exceptions - ENGINE_LOG_ERROR << "GENERAL ERROR WHEN DROPPING PARTITIONS BY DATES" << ": " << er.what(); - return Status::DBTransactionError("GENERAL ERROR WHEN DROPPING PARTITIONS BY DATES", er.what()); + files[table_file.date_].push_back(table_file); } - return Status::OK(); + } catch (const BadQuery &er) { + // Handle any query errors + ENGINE_LOG_ERROR << "QUERY ERROR WHEN FINDING TABLE FILES TO SEARCH" << ": " << er.what(); + return Status::DBTransactionError("QUERY ERROR WHEN FINDING TABLE FILES TO SEARCH", er.what()); + } catch (const Exception &er) { + // Catch-all for any other MySQL++ exceptions + ENGINE_LOG_ERROR << "GENERAL ERROR WHEN FINDING TABLE FILES TO SEARCH" << ": " << er.what(); + return Status::DBTransactionError("GENERAL ERROR WHEN FINDING TABLE FILES TO SEARCH", er.what()); } - Status MySQLMetaImpl::CreateTable(TableSchema &table_schema) { + return Status::OK(); +} -// std::lock_guard lock(mysql_mutex); - -// server::Metrics::GetInstance().MetaAccessTotalIncrement(); - try { - - MetricCollector metric; - - { - ScopedConnection connectionPtr(*mysql_connection_pool_, safe_grab); - - if (connectionPtr == nullptr) { - return Status::Error("Failed to connect to database server"); - } - -// if (mysql_connection_pool_->getConnectionsInUse() <= 0) { -// ENGINE_LOG_WARNING << "MySQLMetaImpl::CreateTable connection in use = " << mysql_connection_pool_->getConnectionsInUse(); -// } - - Query createTableQuery = connectionPtr->query(); -// ENGINE_LOG_DEBUG << "Create Table in"; - if (table_schema.table_id_.empty()) { - NextTableId(table_schema.table_id_); - } else { - createTableQuery << "SELECT state FROM Tables " << - "WHERE table_id = " << quote << table_schema.table_id_ << ";"; -// ENGINE_LOG_DEBUG << "Create Table : " << createTableQuery.str(); - - ENGINE_LOG_DEBUG << "MySQLMetaImpl::CreateTable: " << createTableQuery.str(); - - StoreQueryResult res = createTableQuery.store(); - - if (res.num_rows() == 1) { - int state = res[0]["state"]; - if (TableSchema::TO_DELETE == state) { - return Status::Error("Table already exists and it is in delete state, please wait a second"); - } - else { - return Status::OK();//table already exists, no error - } - } - } -// ENGINE_LOG_DEBUG << "Create Table start"; - - table_schema.files_cnt_ = 0; - table_schema.id_ = -1; - table_schema.created_on_ = utils::GetMicroSecTimeStamp(); - -// auto start_time = METRICS_NOW_TIME; - - std::string id = "NULL"; //auto-increment - std::string table_id = table_schema.table_id_; - std::string state = std::to_string(table_schema.state_); - std::string dimension = std::to_string(table_schema.dimension_); - std::string created_on = std::to_string(table_schema.created_on_); - std::string files_cnt = "0"; - std::string engine_type = std::to_string(table_schema.engine_type_); - std::string store_raw_data = table_schema.store_raw_data_ ? "true" : "false"; - - createTableQuery << "INSERT INTO Tables VALUES" << - "(" << id << ", " << quote << table_id << ", " << state << ", " << dimension << ", " << - created_on << ", " << files_cnt << ", " << engine_type << ", " << store_raw_data << ");"; -// ENGINE_LOG_DEBUG << "Create Table : " << createTableQuery.str(); - - ENGINE_LOG_DEBUG << "MySQLMetaImpl::CreateTable: " << createTableQuery.str(); - - if (SimpleResult res = createTableQuery.execute()) { - table_schema.id_ = res.insert_id(); //Might need to use SELECT LAST_INSERT_ID()? -// std::cout << table_schema.id_ << std::endl; - //Consume all results to avoid "Commands out of sync" error -// while (createTableQuery.more_results()) { -// createTableQuery.store_next(); -// } - } else { - ENGINE_LOG_ERROR << "Add Table Error"; - return Status::DBTransactionError("Add Table Error", createTableQuery.error()); - } - } //Scoped Connection - -// auto end_time = METRICS_NOW_TIME; -// auto total_time = METRICS_MICROSECONDS(start_time, end_time); -// server::Metrics::GetInstance().MetaAccessDurationSecondsHistogramObserve(total_time); - - return utils::CreateTablePath(options_, table_schema.table_id_); - - } catch (const BadQuery& er) { - // Handle any query errors - ENGINE_LOG_ERROR << "QUERY ERROR WHEN ADDING TABLE" << ": " << er.what(); - return Status::DBTransactionError("QUERY ERROR WHEN ADDING TABLE", er.what()); - } catch (const Exception& er) { - // Catch-all for any other MySQL++ exceptions - ENGINE_LOG_ERROR << "GENERAL ERROR WHEN ADDING TABLE" << ": " << er.what(); - return Status::DBTransactionError("GENERAL ERROR WHEN ADDING TABLE", er.what()); - } catch (std::exception &e) { - return HandleException("Encounter exception when create table", e); - } - - return Status::OK(); - } - - Status MySQLMetaImpl::HasNonIndexFiles(const std::string& table_id, bool& has) { - // TODO - return Status::OK(); - } - - Status MySQLMetaImpl::DeleteTable(const std::string& table_id) { - -// std::lock_guard lock(mysql_mutex); - - try { - - MetricCollector metric; - - { - ScopedConnection connectionPtr(*mysql_connection_pool_, safe_grab); - - if (connectionPtr == nullptr) { - return Status::Error("Failed to connect to database server"); - } - -// if (mysql_connection_pool_->getConnectionsInUse() <= 0) { -// ENGINE_LOG_WARNING << "MySQLMetaImpl::DeleteTable connection in use = " << mysql_connection_pool_->getConnectionsInUse(); -// } - - //soft delete table - Query deleteTableQuery = connectionPtr->query(); -// - deleteTableQuery << "UPDATE Tables " << - "SET state = " << std::to_string(TableSchema::TO_DELETE) << " " << - "WHERE table_id = " << quote << table_id << ";"; - - ENGINE_LOG_DEBUG << "MySQLMetaImpl::DeleteTable: " << deleteTableQuery.str(); - - if (!deleteTableQuery.exec()) { - ENGINE_LOG_ERROR << "QUERY ERROR WHEN DELETING TABLE"; - return Status::DBTransactionError("QUERY ERROR WHEN DELETING TABLE", deleteTableQuery.error()); - } - - } //Scoped Connection +Status MySQLMetaImpl::FilesToMerge(const std::string &table_id, + DatePartionedTableFilesSchema &files) { - if (mode_ == Options::MODE::CLUSTER) { - DeleteTableFiles(table_id); + files.clear(); + + try { + MetricCollector metric; + + StoreQueryResult res; + + { + ScopedConnection connectionPtr(*mysql_connection_pool_, safe_grab); + + if (connectionPtr == nullptr) { + return Status::Error("Failed to connect to database server"); } - } catch (const BadQuery& er) { - // Handle any query errors - ENGINE_LOG_ERROR << "GENERAL ERROR WHEN DELETING TABLE" << ": " << er.what(); - return Status::DBTransactionError("QUERY ERROR WHEN DELETING TABLE", er.what()); - } catch (const Exception& er) { - // Catch-all for any other MySQL++ exceptions - ENGINE_LOG_ERROR << "GENERAL ERROR WHEN DELETING TABLE" << ": " << er.what(); - return Status::DBTransactionError("GENERAL ERROR WHEN DELETING TABLE", er.what()); - } - return Status::OK(); - } + Query filesToMergeQuery = connectionPtr->query(); + filesToMergeQuery << "SELECT id, table_id, file_id, file_type, size, date " << + "FROM TableFiles " << + "WHERE table_id = " << quote << table_id << " AND " << + "file_type = " << std::to_string(TableFileSchema::RAW) << " " << + "ORDER BY size DESC" << ";"; - Status MySQLMetaImpl::DeleteTableFiles(const std::string& table_id) { - try { - MetricCollector metric; + ENGINE_LOG_DEBUG << "MySQLMetaImpl::FilesToMerge: " << filesToMergeQuery.str(); - { - ScopedConnection connectionPtr(*mysql_connection_pool_, safe_grab); + res = filesToMergeQuery.store(); + } //Scoped Connection - if (connectionPtr == nullptr) { - return Status::Error("Failed to connect to database server"); - } - -// if (mysql_connection_pool_->getConnectionsInUse() <= 0) { -// ENGINE_LOG_WARNING << "MySQLMetaImpl::DeleteTableFiles connection in use = " << mysql_connection_pool_->getConnectionsInUse(); -// } - - //soft delete table files - Query deleteTableFilesQuery = connectionPtr->query(); - // - deleteTableFilesQuery << "UPDATE TableFiles " << - "SET file_type = " << std::to_string(TableFileSchema::TO_DELETE) << ", " << - "updated_time = " << std::to_string(utils::GetMicroSecTimeStamp()) << " " << - "WHERE table_id = " << quote << table_id << " AND " << - "file_type <> " << std::to_string(TableFileSchema::TO_DELETE) << ";"; - - ENGINE_LOG_DEBUG << "MySQLMetaImpl::DeleteTableFiles: " << deleteTableFilesQuery.str(); - - if (!deleteTableFilesQuery.exec()) { - ENGINE_LOG_ERROR << "QUERY ERROR WHEN DELETING TABLE FILES"; - return Status::DBTransactionError("QUERY ERROR WHEN DELETING TABLE", deleteTableFilesQuery.error()); - } - } //Scoped Connection - } catch (const BadQuery& er) { - // Handle any query errors - ENGINE_LOG_ERROR << "QUERY ERROR WHEN DELETING TABLE FILES" << ": " << er.what(); - return Status::DBTransactionError("QUERY ERROR WHEN DELETING TABLE FILES", er.what()); - } catch (const Exception& er) { - // Catch-all for any other MySQL++ exceptions - ENGINE_LOG_ERROR << "GENERAL ERROR WHEN DELETING TABLE FILES" << ": " << er.what(); - return Status::DBTransactionError("GENERAL ERROR WHEN DELETING TABLE FILES", er.what()); - } - - return Status::OK(); - } - - Status MySQLMetaImpl::DescribeTable(TableSchema &table_schema) { - -// std::lock_guard lock(mysql_mutex); - - try { - - MetricCollector metric; - - StoreQueryResult res; - - { - ScopedConnection connectionPtr(*mysql_connection_pool_, safe_grab); - - if (connectionPtr == nullptr) { - return Status::Error("Failed to connect to database server"); - } - -// if (mysql_connection_pool_->getConnectionsInUse() <= 0) { -// ENGINE_LOG_WARNING << "MySQLMetaImpl::DescribeTable connection in use = " << mysql_connection_pool_->getConnectionsInUse(); -// } - - Query describeTableQuery = connectionPtr->query(); - describeTableQuery << "SELECT id, dimension, files_cnt, engine_type, store_raw_data " << - "FROM Tables " << - "WHERE table_id = " << quote << table_schema.table_id_ << " " << - "AND state <> " << std::to_string(TableSchema::TO_DELETE) << ";"; - - ENGINE_LOG_DEBUG << "MySQLMetaImpl::DescribeTable: " << describeTableQuery.str(); - - res = describeTableQuery.store(); - } //Scoped Connection - - if (res.num_rows() == 1) { - const Row& resRow = res[0]; - - table_schema.id_ = resRow["id"]; //implicit conversion - - table_schema.dimension_ = resRow["dimension"]; - - table_schema.files_cnt_ = resRow["files_cnt"]; - - table_schema.engine_type_ = resRow["engine_type"]; - - int store_raw_data = resRow["store_raw_data"]; - table_schema.store_raw_data_ = (store_raw_data == 1); - } - else { - return Status::NotFound("Table " + table_schema.table_id_ + " not found"); - } - - } catch (const BadQuery& er) { - // Handle any query errors - ENGINE_LOG_ERROR << "QUERY ERROR WHEN DESCRIBING TABLE" << ": " << er.what(); - return Status::DBTransactionError("QUERY ERROR WHEN DESCRIBING TABLE", er.what()); - } catch (const Exception& er) { - // Catch-all for any other MySQL++ exceptions - ENGINE_LOG_ERROR << "GENERAL ERROR WHEN DESCRIBING TABLE" << ": " << er.what(); - return Status::DBTransactionError("GENERAL ERROR WHEN DESCRIBING TABLE", er.what()); - } - - return Status::OK(); - } - - Status MySQLMetaImpl::HasTable(const std::string &table_id, bool &has_or_not) { - -// std::lock_guard lock(mysql_mutex); - - try { - - MetricCollector metric; - - StoreQueryResult res; - - { - ScopedConnection connectionPtr(*mysql_connection_pool_, safe_grab); - - if (connectionPtr == nullptr) { - return Status::Error("Failed to connect to database server"); - } - -// if (mysql_connection_pool_->getConnectionsInUse() <= 0) { -// ENGINE_LOG_WARNING << "MySQLMetaImpl::HasTable connection in use = " << mysql_connection_pool_->getConnectionsInUse(); -// } - - Query hasTableQuery = connectionPtr->query(); - //since table_id is a unique column we just need to check whether it exists or not - hasTableQuery << "SELECT EXISTS " << - "(SELECT 1 FROM Tables " << - "WHERE table_id = " << quote << table_id << " " << - "AND state <> " << std::to_string(TableSchema::TO_DELETE) << ") " << - "AS " << quote << "check" << ";"; - - ENGINE_LOG_DEBUG << "MySQLMetaImpl::HasTable: " << hasTableQuery.str(); - - res = hasTableQuery.store(); - } //Scoped Connection - - int check = res[0]["check"]; - has_or_not = (check == 1); - - } catch (const BadQuery& er) { - // Handle any query errors - ENGINE_LOG_ERROR << "QUERY ERROR WHEN CHECKING IF TABLE EXISTS" << ": " << er.what(); - return Status::DBTransactionError("QUERY ERROR WHEN CHECKING IF TABLE EXISTS", er.what()); - } catch (const Exception& er) { - // Catch-all for any other MySQL++ exceptions - ENGINE_LOG_ERROR << "GENERAL ERROR WHEN CHECKING IF TABLE EXISTS" << ": " << er.what(); - return Status::DBTransactionError("GENERAL ERROR WHEN CHECKING IF TABLE EXISTS", er.what()); - } - - return Status::OK(); - } - - Status MySQLMetaImpl::AllTables(std::vector& table_schema_array) { - -// std::lock_guard lock(mysql_mutex); - - try { - - MetricCollector metric; - - StoreQueryResult res; - - { - ScopedConnection connectionPtr(*mysql_connection_pool_, safe_grab); - - if (connectionPtr == nullptr) { - return Status::Error("Failed to connect to database server"); - } - -// if (mysql_connection_pool_->getConnectionsInUse() <= 0) { -// ENGINE_LOG_WARNING << "MySQLMetaImpl::AllTables connection in use = " << mysql_connection_pool_->getConnectionsInUse(); -// } - - Query allTablesQuery = connectionPtr->query(); - allTablesQuery << "SELECT id, table_id, dimension, files_cnt, engine_type, store_raw_data " << - "FROM Tables " << - "WHERE state <> " << std::to_string(TableSchema::TO_DELETE) << ";"; - - ENGINE_LOG_DEBUG << "MySQLMetaImpl::AllTables: " << allTablesQuery.str(); - - res = allTablesQuery.store(); - } //Scoped Connection - - for (auto& resRow : res) { - TableSchema table_schema; - - table_schema.id_ = resRow["id"]; //implicit conversion - - std::string table_id; - resRow["table_id"].to_string(table_id); - table_schema.table_id_ = table_id; - - table_schema.dimension_ = resRow["dimension"]; - - table_schema.files_cnt_ = resRow["files_cnt"]; - - table_schema.engine_type_ = resRow["engine_type"]; - - int store_raw_data = resRow["store_raw_data"]; - table_schema.store_raw_data_ = (store_raw_data == 1); - - table_schema_array.emplace_back(table_schema); - } - } catch (const BadQuery& er) { - // Handle any query errors - ENGINE_LOG_ERROR << "QUERY ERROR WHEN DESCRIBING ALL TABLES" << ": " << er.what(); - return Status::DBTransactionError("QUERY ERROR WHEN DESCRIBING ALL TABLES", er.what()); - } catch (const Exception& er) { - // Catch-all for any other MySQL++ exceptions - ENGINE_LOG_ERROR << "GENERAL ERROR WHEN DESCRIBING ALL TABLES" << ": " << er.what(); - return Status::DBTransactionError("GENERAL ERROR WHEN DESCRIBING ALL TABLES", er.what()); - } - - return Status::OK(); - } - - Status MySQLMetaImpl::CreateTableFile(TableFileSchema &file_schema) { - -// std::lock_guard lock(mysql_mutex); - - if (file_schema.date_ == EmptyDate) { - file_schema.date_ = Meta::GetDate(); - } TableSchema table_schema; - table_schema.table_id_ = file_schema.table_id_; + table_schema.table_id_ = table_id; + auto status = DescribeTable(table_schema); + + if (!status.ok()) { + return status; + } + + TableFileSchema table_file; + for (auto &resRow : res) { + + table_file.id_ = resRow["id"]; //implicit conversion + + std::string table_id_str; + resRow["table_id"].to_string(table_id_str); + table_file.table_id_ = table_id_str; + + std::string file_id; + resRow["file_id"].to_string(file_id); + table_file.file_id_ = file_id; + + table_file.file_type_ = resRow["file_type"]; + + table_file.size_ = resRow["size"]; + + table_file.date_ = resRow["date"]; + + table_file.dimension_ = table_schema.dimension_; + + utils::GetTableFilePath(options_, table_file); + + auto dateItr = files.find(table_file.date_); + if (dateItr == files.end()) { + files[table_file.date_] = TableFilesSchema(); + } + + files[table_file.date_].push_back(table_file); + } + + } catch (const BadQuery &er) { + // Handle any query errors + ENGINE_LOG_ERROR << "QUERY ERROR WHEN FINDING TABLE FILES TO MERGE" << ": " << er.what(); + return Status::DBTransactionError("QUERY ERROR WHEN FINDING TABLE FILES TO MERGE", er.what()); + } catch (const Exception &er) { + // Catch-all for any other MySQL++ exceptions + ENGINE_LOG_ERROR << "GENERAL ERROR WHEN FINDING TABLE FILES TO MERGE" << ": " << er.what(); + return Status::DBTransactionError("GENERAL ERROR WHEN FINDING TABLE FILES TO MERGE", er.what()); + } + + return Status::OK(); +} + +Status MySQLMetaImpl::GetTableFiles(const std::string &table_id, + const std::vector &ids, + TableFilesSchema &table_files) { + + + if (ids.empty()) { + return Status::OK(); + } + + std::stringstream idSS; + for (auto &id : ids) { + idSS << "id = " << std::to_string(id) << " OR "; + } + std::string idStr = idSS.str(); + idStr = idStr.substr(0, idStr.size() - 4); //remove the last " OR " + + try { + + StoreQueryResult res; + + { + ScopedConnection connectionPtr(*mysql_connection_pool_, safe_grab); + + if (connectionPtr == nullptr) { + return Status::Error("Failed to connect to database server"); + } + + + Query getTableFileQuery = connectionPtr->query(); + getTableFileQuery << "SELECT id, engine_type, file_id, file_type, size, date " << + "FROM TableFiles " << + "WHERE table_id = " << quote << table_id << " AND " << + "(" << idStr << ");"; + + ENGINE_LOG_DEBUG << "MySQLMetaImpl::GetTableFiles: " << getTableFileQuery.str(); + + res = getTableFileQuery.store(); + } //Scoped Connection + + TableSchema table_schema; + table_schema.table_id_ = table_id; auto status = DescribeTable(table_schema); if (!status.ok()) { return status; } - try { + for (auto &resRow : res) { - MetricCollector metric; + TableFileSchema file_schema; + + file_schema.id_ = resRow["id"]; + + file_schema.table_id_ = table_id; + + file_schema.engine_type_ = resRow["engine_type"]; + + std::string file_id; + resRow["file_id"].to_string(file_id); + file_schema.file_id_ = file_id; + + file_schema.file_type_ = resRow["file_type"]; + + file_schema.size_ = resRow["size"]; + + file_schema.date_ = resRow["date"]; - NextFileId(file_schema.file_id_); - file_schema.file_type_ = TableFileSchema::NEW; file_schema.dimension_ = table_schema.dimension_; - file_schema.size_ = 0; - file_schema.created_on_ = utils::GetMicroSecTimeStamp(); - file_schema.updated_time_ = file_schema.created_on_; - file_schema.engine_type_ = table_schema.engine_type_; + utils::GetTableFilePath(options_, file_schema); - std::string id = "NULL"; //auto-increment + table_files.emplace_back(file_schema); + } + } catch (const BadQuery &er) { + // Handle any query errors + ENGINE_LOG_ERROR << "QUERY ERROR WHEN RETRIEVING TABLE FILES" << ": " << er.what(); + return Status::DBTransactionError("QUERY ERROR WHEN RETRIEVING TABLE FILES", er.what()); + } catch (const Exception &er) { + // Catch-all for any other MySQL++ exceptions + ENGINE_LOG_ERROR << "GENERAL ERROR WHEN RETRIEVING TABLE FILES" << ": " << er.what(); + return Status::DBTransactionError("GENERAL ERROR WHEN RETRIEVING TABLE FILES", er.what()); + } + + return Status::OK(); +} + +// PXU TODO: Support Swap +Status MySQLMetaImpl::Archive() { + + + auto &criterias = options_.archive_conf.GetCriterias(); + if (criterias.empty()) { + return Status::OK(); + } + + for (auto &kv : criterias) { + auto &criteria = kv.first; + auto &limit = kv.second; + if (criteria == "days") { + size_t usecs = limit * D_SEC * US_PS; + long now = utils::GetMicroSecTimeStamp(); + + try { + + ScopedConnection connectionPtr(*mysql_connection_pool_, safe_grab); + + if (connectionPtr == nullptr) { + return Status::Error("Failed to connect to database server"); + } + + + Query archiveQuery = connectionPtr->query(); + archiveQuery << "UPDATE TableFiles " << + "SET file_type = " << std::to_string(TableFileSchema::TO_DELETE) << " " << + "WHERE created_on < " << std::to_string(now - usecs) << " AND " << + "file_type <> " << std::to_string(TableFileSchema::TO_DELETE) << ";"; + + ENGINE_LOG_DEBUG << "MySQLMetaImpl::Archive: " << archiveQuery.str(); + + if (!archiveQuery.exec()) { + return Status::DBTransactionError("QUERY ERROR DURING ARCHIVE", archiveQuery.error()); + } + + } catch (const BadQuery &er) { + // Handle any query errors + ENGINE_LOG_ERROR << "QUERY ERROR WHEN DURING ARCHIVE" << ": " << er.what(); + return Status::DBTransactionError("QUERY ERROR WHEN DURING ARCHIVE", er.what()); + } catch (const Exception &er) { + // Catch-all for any other MySQL++ exceptions + ENGINE_LOG_ERROR << "GENERAL ERROR WHEN DURING ARCHIVE" << ": " << er.what(); + return Status::DBTransactionError("GENERAL ERROR WHEN DURING ARCHIVE", er.what()); + } + } + if (criteria == "disk") { + uint64_t sum = 0; + Size(sum); + + auto to_delete = (sum - limit * G); + DiscardFiles(to_delete); + } + } + + return Status::OK(); +} + +Status MySQLMetaImpl::Size(uint64_t &result) { + + + result = 0; + try { + + StoreQueryResult res; + + { + ScopedConnection connectionPtr(*mysql_connection_pool_, safe_grab); + + if (connectionPtr == nullptr) { + return Status::Error("Failed to connect to database server"); + } + + + Query getSizeQuery = connectionPtr->query(); + getSizeQuery << "SELECT IFNULL(SUM(size),0) AS sum " << + "FROM TableFiles " << + "WHERE file_type <> " << std::to_string(TableFileSchema::TO_DELETE) << ";"; + + ENGINE_LOG_DEBUG << "MySQLMetaImpl::Size: " << getSizeQuery.str(); + + res = getSizeQuery.store(); + } //Scoped Connection + + +// + + + if (res.empty()) { + result = 0; + + } else { + result = res[0]["sum"]; + + } + + } catch (const BadQuery &er) { + // Handle any query errors + ENGINE_LOG_ERROR << "QUERY ERROR WHEN RETRIEVING SIZE" << ": " << er.what(); + return Status::DBTransactionError("QUERY ERROR WHEN RETRIEVING SIZE", er.what()); + } catch (const Exception &er) { + // Catch-all for any other MySQL++ exceptions + ENGINE_LOG_ERROR << "GENERAL ERROR WHEN RETRIEVING SIZE" << ": " << er.what(); + return Status::DBTransactionError("GENERAL ERROR WHEN RETRIEVING SIZE", er.what()); + } + + return Status::OK(); +} + +Status MySQLMetaImpl::DiscardFiles(long long to_discard_size) { + + + if (to_discard_size <= 0) { + + return Status::OK(); + } + ENGINE_LOG_DEBUG << "About to discard size=" << to_discard_size; + + try { + + MetricCollector metric; + + bool status; + + { + ScopedConnection connectionPtr(*mysql_connection_pool_, safe_grab); + + if (connectionPtr == nullptr) { + return Status::Error("Failed to connect to database server"); + } + + + Query discardFilesQuery = connectionPtr->query(); + discardFilesQuery << "SELECT id, size " << + "FROM TableFiles " << + "WHERE file_type <> " << std::to_string(TableFileSchema::TO_DELETE) << " " << + "ORDER BY id ASC " << + "LIMIT 10;"; + + ENGINE_LOG_DEBUG << "MySQLMetaImpl::DiscardFiles: " << discardFilesQuery.str(); + + + StoreQueryResult res = discardFilesQuery.store(); + + if (res.num_rows() == 0) { + return Status::OK(); + } + + TableFileSchema table_file; + std::stringstream idsToDiscardSS; + for (auto &resRow : res) { + if (to_discard_size <= 0) { + break; + } + table_file.id_ = resRow["id"]; + table_file.size_ = resRow["size"]; + idsToDiscardSS << "id = " << std::to_string(table_file.id_) << " OR "; + ENGINE_LOG_DEBUG << "Discard table_file.id=" << table_file.file_id_ + << " table_file.size=" << table_file.size_; + to_discard_size -= table_file.size_; + } + + std::string idsToDiscardStr = idsToDiscardSS.str(); + idsToDiscardStr = idsToDiscardStr.substr(0, idsToDiscardStr.size() - 4); //remove the last " OR " + + discardFilesQuery << "UPDATE TableFiles " << + "SET file_type = " << std::to_string(TableFileSchema::TO_DELETE) << ", " << + "updated_time = " << std::to_string(utils::GetMicroSecTimeStamp()) << " " << + "WHERE " << idsToDiscardStr << ";"; + + ENGINE_LOG_DEBUG << "MySQLMetaImpl::DiscardFiles: " << discardFilesQuery.str(); + + status = discardFilesQuery.exec(); + if (!status) { + ENGINE_LOG_ERROR << "QUERY ERROR WHEN DISCARDING FILES"; + return Status::DBTransactionError("QUERY ERROR WHEN DISCARDING FILES", discardFilesQuery.error()); + } + } //Scoped Connection + + return DiscardFiles(to_discard_size); + + } catch (const BadQuery &er) { + // Handle any query errors + ENGINE_LOG_ERROR << "QUERY ERROR WHEN DISCARDING FILES" << ": " << er.what(); + return Status::DBTransactionError("QUERY ERROR WHEN DISCARDING FILES", er.what()); + } catch (const Exception &er) { + // Catch-all for any other MySQL++ exceptions + ENGINE_LOG_ERROR << "GENERAL ERROR WHEN DISCARDING FILES" << ": " << er.what(); + return Status::DBTransactionError("GENERAL ERROR WHEN DISCARDING FILES", er.what()); + } +} + +//ZR: this function assumes all fields in file_schema have value +Status MySQLMetaImpl::UpdateTableFile(TableFileSchema &file_schema) { + + + file_schema.updated_time_ = utils::GetMicroSecTimeStamp(); + try { + + MetricCollector metric; + + { + ScopedConnection connectionPtr(*mysql_connection_pool_, safe_grab); + + if (connectionPtr == nullptr) { + return Status::Error("Failed to connect to database server"); + } + + + Query updateTableFileQuery = connectionPtr->query(); + + //if the table has been deleted, just mark the table file as TO_DELETE + //clean thread will delete the file later + updateTableFileQuery << "SELECT state FROM Tables " << + "WHERE table_id = " << quote << file_schema.table_id_ << ";"; + + ENGINE_LOG_DEBUG << "MySQLMetaImpl::UpdateTableFile: " << updateTableFileQuery.str(); + + StoreQueryResult res = updateTableFileQuery.store(); + + if (res.num_rows() == 1) { + int state = res[0]["state"]; + if (state == TableSchema::TO_DELETE) { + file_schema.file_type_ = TableFileSchema::TO_DELETE; + } + } else { + file_schema.file_type_ = TableFileSchema::TO_DELETE; + } + + std::string id = std::to_string(file_schema.id_); std::string table_id = file_schema.table_id_; std::string engine_type = std::to_string(file_schema.engine_type_); std::string file_id = file_schema.file_id_; @@ -725,679 +1373,121 @@ namespace meta { std::string created_on = std::to_string(file_schema.created_on_); std::string date = std::to_string(file_schema.date_); - { - ScopedConnection connectionPtr(*mysql_connection_pool_, safe_grab); + updateTableFileQuery << "UPDATE TableFiles " << + "SET table_id = " << quote << table_id << ", " << + "engine_type = " << engine_type << ", " << + "file_id = " << quote << file_id << ", " << + "file_type = " << file_type << ", " << + "size = " << size << ", " << + "updated_time = " << updated_time << ", " << + "created_on = " << created_on << ", " << + "date = " << date << " " << + "WHERE id = " << id << ";"; - if (connectionPtr == nullptr) { - return Status::Error("Failed to connect to database server"); - } + ENGINE_LOG_DEBUG << "MySQLMetaImpl::UpdateTableFile: " << updateTableFileQuery.str(); -// if (mysql_connection_pool_->getConnectionsInUse() <= 0) { -// ENGINE_LOG_WARNING << "MySQLMetaImpl::CreateTableFile connection in use = " << mysql_connection_pool_->getConnectionsInUse(); -// } - Query createTableFileQuery = connectionPtr->query(); + if (!updateTableFileQuery.exec()) { + ENGINE_LOG_DEBUG << "table_id= " << file_schema.table_id_ << " file_id=" << file_schema.file_id_; + ENGINE_LOG_ERROR << "QUERY ERROR WHEN UPDATING TABLE FILE"; + return Status::DBTransactionError("QUERY ERROR WHEN UPDATING TABLE FILE", + updateTableFileQuery.error()); + } + } //Scoped Connection - createTableFileQuery << "INSERT INTO TableFiles VALUES" << - "(" << id << ", " << quote << table_id << ", " << engine_type << ", " << - quote << file_id << ", " << file_type << ", " << size << ", " << - updated_time << ", " << created_on << ", " << date << ");"; + } catch (const BadQuery &er) { + // Handle any query errors + ENGINE_LOG_DEBUG << "table_id= " << file_schema.table_id_ << " file_id=" << file_schema.file_id_; + ENGINE_LOG_ERROR << "QUERY ERROR WHEN UPDATING TABLE FILE" << ": " << er.what(); + return Status::DBTransactionError("QUERY ERROR WHEN UPDATING TABLE FILE", er.what()); + } catch (const Exception &er) { + // Catch-all for any other MySQL++ exceptions + ENGINE_LOG_DEBUG << "table_id= " << file_schema.table_id_ << " file_id=" << file_schema.file_id_; + ENGINE_LOG_ERROR << "GENERAL ERROR WHEN UPDATING TABLE FILE" << ": " << er.what(); + return Status::DBTransactionError("GENERAL ERROR WHEN UPDATING TABLE FILE", er.what()); + } + return Status::OK(); +} - ENGINE_LOG_DEBUG << "MySQLMetaImpl::CreateTableFile: " << createTableFileQuery.str(); +Status MySQLMetaImpl::UpdateTableFilesToIndex(const std::string &table_id) { + try { + ScopedConnection connectionPtr(*mysql_connection_pool_, safe_grab); - if (SimpleResult res = createTableFileQuery.execute()) { - file_schema.id_ = res.insert_id(); //Might need to use SELECT LAST_INSERT_ID()? - - //Consume all results to avoid "Commands out of sync" error -// while (createTableFileQuery.more_results()) { -// createTableFileQuery.store_next(); -// } - } else { - ENGINE_LOG_ERROR << "QUERY ERROR WHEN ADDING TABLE FILE"; - return Status::DBTransactionError("Add file Error", createTableFileQuery.error()); - } - } // Scoped Connection - - return utils::CreateTableFilePath(options_, file_schema); - - } catch (const BadQuery& er) { - // Handle any query errors - ENGINE_LOG_ERROR << "QUERY ERROR WHEN ADDING TABLE FILE" << ": " << er.what(); - return Status::DBTransactionError("QUERY ERROR WHEN ADDING TABLE FILE", er.what()); - } catch (const Exception& er) { - // Catch-all for any other MySQL++ exceptions - ENGINE_LOG_ERROR << "GENERAL ERROR WHEN ADDING TABLE FILE" << ": " << er.what(); - return Status::DBTransactionError("GENERAL ERROR WHEN ADDING TABLE FILE", er.what()); - } catch (std::exception& ex) { - return HandleException("Encounter exception when create table file", ex); + if (connectionPtr == nullptr) { + return Status::Error("Failed to connect to database server"); } - return Status::OK(); + Query updateTableFilesToIndexQuery = connectionPtr->query(); + + updateTableFilesToIndexQuery << "UPDATE TableFiles " << + "SET file_type = " << std::to_string(TableFileSchema::TO_INDEX) << " " << + "WHERE table_id = " << quote << table_id << " AND " << + "file_type = " << std::to_string(TableFileSchema::RAW) << ";"; + + ENGINE_LOG_DEBUG << "MySQLMetaImpl::UpdateTableFilesToIndex: " << updateTableFilesToIndexQuery.str(); + + if (!updateTableFilesToIndexQuery.exec()) { + ENGINE_LOG_ERROR << "QUERY ERROR WHEN UPDATING TABLE FILE"; + return Status::DBTransactionError("QUERY ERROR WHEN UPDATING TABLE FILE", + updateTableFilesToIndexQuery.error()); + } + + } catch (const BadQuery &er) { + // Handle any query errors + ENGINE_LOG_ERROR << "QUERY ERROR WHEN UPDATING TABLE FILES TO INDEX" << ": " << er.what(); + return Status::DBTransactionError("QUERY ERROR WHEN UPDATING TABLE FILES TO INDEX", er.what()); + } catch (const Exception &er) { + // Catch-all for any other MySQL++ exceptions + ENGINE_LOG_ERROR << "GENERAL ERROR WHEN UPDATING TABLE FILES TO INDEX" << ": " << er.what(); + return Status::DBTransactionError("GENERAL ERROR WHEN UPDATING TABLE FILES TO INDEX", er.what()); } - Status MySQLMetaImpl::FilesToIndex(TableFilesSchema &files) { + return Status::OK(); +} -// std::lock_guard lock(mysql_mutex); +Status MySQLMetaImpl::UpdateTableFiles(TableFilesSchema &files) { - files.clear(); - try { + try { + MetricCollector metric; - MetricCollector metric; + { + ScopedConnection connectionPtr(*mysql_connection_pool_, safe_grab); - StoreQueryResult res; - - { - ScopedConnection connectionPtr(*mysql_connection_pool_, safe_grab); - - if (connectionPtr == nullptr) { - return Status::Error("Failed to connect to database server"); - } - -// if (mysql_connection_pool_->getConnectionsInUse() <= 0) { -// ENGINE_LOG_WARNING << "MySQLMetaImpl::FilesToIndex connection in use = " << mysql_connection_pool_->getConnectionsInUse(); -// } - - Query filesToIndexQuery = connectionPtr->query(); - filesToIndexQuery << "SELECT id, table_id, engine_type, file_id, file_type, size, date " << - "FROM TableFiles " << - "WHERE file_type = " << std::to_string(TableFileSchema::TO_INDEX) << ";"; - - ENGINE_LOG_DEBUG << "MySQLMetaImpl::FilesToIndex: " << filesToIndexQuery.str(); - - res = filesToIndexQuery.store(); - } //Scoped Connection - - std::map groups; - TableFileSchema table_file; - for (auto& resRow : res) { - - table_file.id_ = resRow["id"]; //implicit conversion - - std::string table_id; - resRow["table_id"].to_string(table_id); - table_file.table_id_ = table_id; - - table_file.engine_type_ = resRow["engine_type"]; - - std::string file_id; - resRow["file_id"].to_string(file_id); - table_file.file_id_ = file_id; - - table_file.file_type_ = resRow["file_type"]; - - table_file.size_ = resRow["size"]; - - table_file.date_ = resRow["date"]; - - auto groupItr = groups.find(table_file.table_id_); - if (groupItr == groups.end()) { - TableSchema table_schema; - table_schema.table_id_ = table_file.table_id_; - auto status = DescribeTable(table_schema); - if (!status.ok()) { - return status; - } - groups[table_file.table_id_] = table_schema; -// std::cout << table_schema.dimension_ << std::endl; - } - table_file.dimension_ = groups[table_file.table_id_].dimension_; - - utils::GetTableFilePath(options_, table_file); - - files.push_back(table_file); - } - } catch (const BadQuery& er) { - // Handle any query errors - ENGINE_LOG_ERROR << "QUERY ERROR WHEN FINDING TABLE FILES TO INDEX" << ": " << er.what(); - return Status::DBTransactionError("QUERY ERROR WHEN FINDING TABLE FILES TO INDEX", er.what()); - } catch (const Exception& er) { - // Catch-all for any other MySQL++ exceptions - ENGINE_LOG_ERROR << "GENERAL ERROR WHEN FINDING TABLE FILES TO INDEX" << ": " << er.what(); - return Status::DBTransactionError("GENERAL ERROR WHEN FINDING TABLE FILES TO INDEX", er.what()); - } - - return Status::OK(); - } - - Status MySQLMetaImpl::FilesToSearch(const std::string &table_id, - const DatesT &partition, - DatePartionedTableFilesSchema &files) { - -// std::lock_guard lock(mysql_mutex); - - files.clear(); - - try { - - MetricCollector metric; - - StoreQueryResult res; - - { - ScopedConnection connectionPtr(*mysql_connection_pool_, safe_grab); - - if (connectionPtr == nullptr) { - return Status::Error("Failed to connect to database server"); - } -// if (mysql_connection_pool_->getConnectionsInUse() <= 0) { -// ENGINE_LOG_WARNING << "MySQLMetaImpl::FilesToSearch connection in use = " << mysql_connection_pool_->getConnectionsInUse(); -// } - - if (partition.empty()) { - - Query filesToSearchQuery = connectionPtr->query(); - filesToSearchQuery << "SELECT id, table_id, engine_type, file_id, file_type, size, date " << - "FROM TableFiles " << - "WHERE table_id = " << quote << table_id << " AND " << - "(file_type = " << std::to_string(TableFileSchema::RAW) << " OR " << - "file_type = " << std::to_string(TableFileSchema::TO_INDEX) << " OR " << - "file_type = " << std::to_string(TableFileSchema::INDEX) << ");"; - - ENGINE_LOG_DEBUG << "MySQLMetaImpl::FilesToSearch: " << filesToSearchQuery.str(); - - res = filesToSearchQuery.store(); - - } else { - - Query filesToSearchQuery = connectionPtr->query(); - - std::stringstream partitionListSS; - for (auto &date : partition) { - partitionListSS << std::to_string(date) << ", "; - } - std::string partitionListStr = partitionListSS.str(); - partitionListStr = partitionListStr.substr(0, partitionListStr.size() - 2); //remove the last ", " - - filesToSearchQuery << "SELECT id, table_id, engine_type, file_id, file_type, size, date " << - "FROM TableFiles " << - "WHERE table_id = " << quote << table_id << " AND " << - "date IN (" << partitionListStr << ") AND " << - "(file_type = " << std::to_string(TableFileSchema::RAW) << " OR " << - "file_type = " << std::to_string(TableFileSchema::TO_INDEX) << " OR " << - "file_type = " << std::to_string(TableFileSchema::INDEX) << ");"; - - ENGINE_LOG_DEBUG << "MySQLMetaImpl::FilesToSearch: " << filesToSearchQuery.str(); - - res = filesToSearchQuery.store(); - - } - } //Scoped Connection - - TableSchema table_schema; - table_schema.table_id_ = table_id; - auto status = DescribeTable(table_schema); - if (!status.ok()) { - return status; + if (connectionPtr == nullptr) { + return Status::Error("Failed to connect to database server"); } - TableFileSchema table_file; - for (auto& resRow : res) { - table_file.id_ = resRow["id"]; //implicit conversion + Query updateTableFilesQuery = connectionPtr->query(); - std::string table_id_str; - resRow["table_id"].to_string(table_id_str); - table_file.table_id_ = table_id_str; + std::map has_tables; + for (auto &file_schema : files) { - table_file.engine_type_ = resRow["engine_type"]; - - std::string file_id; - resRow["file_id"].to_string(file_id); - table_file.file_id_ = file_id; - - table_file.file_type_ = resRow["file_type"]; - - table_file.size_ = resRow["size"]; - - table_file.date_ = resRow["date"]; - - table_file.dimension_ = table_schema.dimension_; - - utils::GetTableFilePath(options_, table_file); - - auto dateItr = files.find(table_file.date_); - if (dateItr == files.end()) { - files[table_file.date_] = TableFilesSchema(); + if (has_tables.find(file_schema.table_id_) != has_tables.end()) { + continue; } - files[table_file.date_].push_back(table_file); - } - } catch (const BadQuery& er) { - // Handle any query errors - ENGINE_LOG_ERROR << "QUERY ERROR WHEN FINDING TABLE FILES TO SEARCH" << ": " << er.what(); - return Status::DBTransactionError("QUERY ERROR WHEN FINDING TABLE FILES TO SEARCH", er.what()); - } catch (const Exception& er) { - // Catch-all for any other MySQL++ exceptions - ENGINE_LOG_ERROR << "GENERAL ERROR WHEN FINDING TABLE FILES TO SEARCH" << ": " << er.what(); - return Status::DBTransactionError("GENERAL ERROR WHEN FINDING TABLE FILES TO SEARCH", er.what()); - } + updateTableFilesQuery << "SELECT EXISTS " << + "(SELECT 1 FROM Tables " << + "WHERE table_id = " << quote << file_schema.table_id_ << " " << + "AND state <> " << std::to_string(TableSchema::TO_DELETE) << ") " << + "AS " << quote << "check" << ";"; - return Status::OK(); - } + ENGINE_LOG_DEBUG << "MySQLMetaImpl::UpdateTableFiles: " << updateTableFilesQuery.str(); - Status MySQLMetaImpl::FilesToMerge(const std::string &table_id, - DatePartionedTableFilesSchema &files) { + StoreQueryResult res = updateTableFilesQuery.store(); -// std::lock_guard lock(mysql_mutex); - - files.clear(); - - try { - MetricCollector metric; - - StoreQueryResult res; - - { - ScopedConnection connectionPtr(*mysql_connection_pool_, safe_grab); - - if (connectionPtr == nullptr) { - return Status::Error("Failed to connect to database server"); - } - -// if (mysql_connection_pool_->getConnectionsInUse() <= 0) { -// ENGINE_LOG_WARNING << "MySQLMetaImpl::FilesToMerge connection in use = " << mysql_connection_pool_->getConnectionsInUse(); -// } - - Query filesToMergeQuery = connectionPtr->query(); - filesToMergeQuery << "SELECT id, table_id, file_id, file_type, size, date " << - "FROM TableFiles " << - "WHERE table_id = " << quote << table_id << " AND " << - "file_type = " << std::to_string(TableFileSchema::RAW) << " " << - "ORDER BY size DESC" << ";"; - - ENGINE_LOG_DEBUG << "MySQLMetaImpl::FilesToMerge: " << filesToMergeQuery.str(); - - res = filesToMergeQuery.store(); - } //Scoped Connection - - TableSchema table_schema; - table_schema.table_id_ = table_id; - auto status = DescribeTable(table_schema); - - if (!status.ok()) { - return status; + int check = res[0]["check"]; + has_tables[file_schema.table_id_] = (check == 1); } - TableFileSchema table_file; - for (auto& resRow : res) { + for (auto &file_schema : files) { - table_file.id_ = resRow["id"]; //implicit conversion - - std::string table_id_str; - resRow["table_id"].to_string(table_id_str); - table_file.table_id_ = table_id_str; - - std::string file_id; - resRow["file_id"].to_string(file_id); - table_file.file_id_ = file_id; - - table_file.file_type_ = resRow["file_type"]; - - table_file.size_ = resRow["size"]; - - table_file.date_ = resRow["date"]; - - table_file.dimension_ = table_schema.dimension_; - - utils::GetTableFilePath(options_, table_file); - - auto dateItr = files.find(table_file.date_); - if (dateItr == files.end()) { - files[table_file.date_] = TableFilesSchema(); - } - - files[table_file.date_].push_back(table_file); - } - - } catch (const BadQuery& er) { - // Handle any query errors - ENGINE_LOG_ERROR << "QUERY ERROR WHEN FINDING TABLE FILES TO MERGE" << ": " << er.what(); - return Status::DBTransactionError("QUERY ERROR WHEN FINDING TABLE FILES TO MERGE", er.what()); - } catch (const Exception& er) { - // Catch-all for any other MySQL++ exceptions - ENGINE_LOG_ERROR << "GENERAL ERROR WHEN FINDING TABLE FILES TO MERGE" << ": " << er.what(); - return Status::DBTransactionError("GENERAL ERROR WHEN FINDING TABLE FILES TO MERGE", er.what()); - } - - return Status::OK(); - } - - Status MySQLMetaImpl::GetTableFiles(const std::string& table_id, - const std::vector& ids, - TableFilesSchema& table_files) { - -// std::lock_guard lock(mysql_mutex); - - if (ids.empty()) { - return Status::OK(); - } - - std::stringstream idSS; - for (auto& id : ids) { - idSS << "id = " << std::to_string(id) << " OR "; - } - std::string idStr = idSS.str(); - idStr = idStr.substr(0, idStr.size() - 4); //remove the last " OR " - - try { - - StoreQueryResult res; - - { - ScopedConnection connectionPtr(*mysql_connection_pool_, safe_grab); - - if (connectionPtr == nullptr) { - return Status::Error("Failed to connect to database server"); - } - -// if (mysql_connection_pool_->getConnectionsInUse() <= 0) { -// ENGINE_LOG_WARNING << "MySQLMetaImpl::GetTableFiles connection in use = " << mysql_connection_pool_->getConnectionsInUse(); -// } - - Query getTableFileQuery = connectionPtr->query(); - getTableFileQuery << "SELECT id, engine_type, file_id, file_type, size, date " << - "FROM TableFiles " << - "WHERE table_id = " << quote << table_id << " AND " << - "(" << idStr << ");"; - - ENGINE_LOG_DEBUG << "MySQLMetaImpl::GetTableFiles: " << getTableFileQuery.str(); - - res = getTableFileQuery.store(); - } //Scoped Connection - - TableSchema table_schema; - table_schema.table_id_ = table_id; - auto status = DescribeTable(table_schema); - if (!status.ok()) { - return status; - } - - for (auto& resRow : res) { - - TableFileSchema file_schema; - - file_schema.id_ = resRow["id"]; - - file_schema.table_id_ = table_id; - - file_schema.engine_type_ = resRow["engine_type"]; - - std::string file_id; - resRow["file_id"].to_string(file_id); - file_schema.file_id_ = file_id; - - file_schema.file_type_ = resRow["file_type"]; - - file_schema.size_ = resRow["size"]; - - file_schema.date_ = resRow["date"]; - - file_schema.dimension_ = table_schema.dimension_; - - utils::GetTableFilePath(options_, file_schema); - - table_files.emplace_back(file_schema); - } - } catch (const BadQuery& er) { - // Handle any query errors - ENGINE_LOG_ERROR << "QUERY ERROR WHEN RETRIEVING TABLE FILES" << ": " << er.what(); - return Status::DBTransactionError("QUERY ERROR WHEN RETRIEVING TABLE FILES", er.what()); - } catch (const Exception& er) { - // Catch-all for any other MySQL++ exceptions - ENGINE_LOG_ERROR << "GENERAL ERROR WHEN RETRIEVING TABLE FILES" << ": " << er.what(); - return Status::DBTransactionError("GENERAL ERROR WHEN RETRIEVING TABLE FILES", er.what()); - } - - return Status::OK(); - } - -// PXU TODO: Support Swap - Status MySQLMetaImpl::Archive() { - -// std::lock_guard lock(mysql_mutex); - - auto &criterias = options_.archive_conf.GetCriterias(); - if (criterias.empty()) { - return Status::OK(); - } - - for (auto& kv : criterias) { - auto &criteria = kv.first; - auto &limit = kv.second; - if (criteria == "days") { - size_t usecs = limit * D_SEC * US_PS; - long now = utils::GetMicroSecTimeStamp(); - - try { - - ScopedConnection connectionPtr(*mysql_connection_pool_, safe_grab); - - if (connectionPtr == nullptr) { - return Status::Error("Failed to connect to database server"); - } - -// if (mysql_connection_pool_->getConnectionsInUse() <= 0) { -// ENGINE_LOG_WARNING << "MySQLMetaImpl::Archive connection in use = " << mysql_connection_pool_->getConnectionsInUse(); -// } - - Query archiveQuery = connectionPtr->query(); - archiveQuery << "UPDATE TableFiles " << - "SET file_type = " << std::to_string(TableFileSchema::TO_DELETE) << " " << - "WHERE created_on < " << std::to_string(now - usecs) << " AND " << - "file_type <> " << std::to_string(TableFileSchema::TO_DELETE) << ";"; - - ENGINE_LOG_DEBUG << "MySQLMetaImpl::Archive: " << archiveQuery.str(); - - if (!archiveQuery.exec()) { - return Status::DBTransactionError("QUERY ERROR DURING ARCHIVE", archiveQuery.error()); - } - - } catch (const BadQuery& er) { - // Handle any query errors - ENGINE_LOG_ERROR << "QUERY ERROR WHEN DURING ARCHIVE" << ": " << er.what(); - return Status::DBTransactionError("QUERY ERROR WHEN DURING ARCHIVE", er.what()); - } catch (const Exception& er) { - // Catch-all for any other MySQL++ exceptions - ENGINE_LOG_ERROR << "GENERAL ERROR WHEN DURING ARCHIVE" << ": " << er.what(); - return Status::DBTransactionError("GENERAL ERROR WHEN DURING ARCHIVE", er.what()); - } - } - if (criteria == "disk") { - uint64_t sum = 0; - Size(sum); - - auto to_delete = (sum - limit * G); - DiscardFiles(to_delete); - } - } - - return Status::OK(); - } - - Status MySQLMetaImpl::Size(uint64_t &result) { - -// std::lock_guard lock(mysql_mutex); - - result = 0; - try { - - StoreQueryResult res; - - { - ScopedConnection connectionPtr(*mysql_connection_pool_, safe_grab); - - if (connectionPtr == nullptr) { - return Status::Error("Failed to connect to database server"); - } - -// if (mysql_connection_pool_->getConnectionsInUse() <= 0) { -// ENGINE_LOG_WARNING << "MySQLMetaImpl::Size connection in use = " << mysql_connection_pool_->getConnectionsInUse(); -// } - - Query getSizeQuery = connectionPtr->query(); - getSizeQuery << "SELECT IFNULL(SUM(size),0) AS sum " << - "FROM TableFiles " << - "WHERE file_type <> " << std::to_string(TableFileSchema::TO_DELETE) << ";"; - - ENGINE_LOG_DEBUG << "MySQLMetaImpl::Size: " << getSizeQuery.str(); - - res = getSizeQuery.store(); - } //Scoped Connection - -// if (!res) { -//// std::cout << "result is NULL" << std::endl; -// return Status::DBTransactionError("QUERY ERROR WHEN RETRIEVING SIZE", getSizeQuery.error()); -// } - if (res.empty()) { - result = 0; -// std::cout << "result = 0" << std::endl; - } - else { - result = res[0]["sum"]; -// std::cout << "result = " << std::to_string(result) << std::endl; - } - - } catch (const BadQuery& er) { - // Handle any query errors - ENGINE_LOG_ERROR << "QUERY ERROR WHEN RETRIEVING SIZE" << ": " << er.what(); - return Status::DBTransactionError("QUERY ERROR WHEN RETRIEVING SIZE", er.what()); - } catch (const Exception& er) { - // Catch-all for any other MySQL++ exceptions - ENGINE_LOG_ERROR << "GENERAL ERROR WHEN RETRIEVING SIZE" << ": " << er.what(); - return Status::DBTransactionError("GENERAL ERROR WHEN RETRIEVING SIZE", er.what()); - } - - return Status::OK(); - } - - Status MySQLMetaImpl::DiscardFiles(long long to_discard_size) { - -// std::lock_guard lock(mysql_mutex); - - if (to_discard_size <= 0) { -// std::cout << "in" << std::endl; - return Status::OK(); - } - ENGINE_LOG_DEBUG << "About to discard size=" << to_discard_size; - - try { - - MetricCollector metric; - - bool status; - - { - ScopedConnection connectionPtr(*mysql_connection_pool_, safe_grab); - - if (connectionPtr == nullptr) { - return Status::Error("Failed to connect to database server"); - } - -// if (mysql_connection_pool_->getConnectionsInUse() <= 0) { -// ENGINE_LOG_WARNING << "MySQLMetaImpl::DiscardFiles connection in use = " << mysql_connection_pool_->getConnectionsInUse(); -// } - - Query discardFilesQuery = connectionPtr->query(); - discardFilesQuery << "SELECT id, size " << - "FROM TableFiles " << - "WHERE file_type <> " << std::to_string(TableFileSchema::TO_DELETE) << " " << - "ORDER BY id ASC " << - "LIMIT 10;"; - - ENGINE_LOG_DEBUG << "MySQLMetaImpl::DiscardFiles: " << discardFilesQuery.str(); - - // std::cout << discardFilesQuery.str() << std::endl; - StoreQueryResult res = discardFilesQuery.store(); - - if (res.num_rows() == 0) { - return Status::OK(); - } - - TableFileSchema table_file; - std::stringstream idsToDiscardSS; - for (auto &resRow : res) { - if (to_discard_size <= 0) { - break; - } - table_file.id_ = resRow["id"]; - table_file.size_ = resRow["size"]; - idsToDiscardSS << "id = " << std::to_string(table_file.id_) << " OR "; - ENGINE_LOG_DEBUG << "Discard table_file.id=" << table_file.file_id_ - << " table_file.size=" << table_file.size_; - to_discard_size -= table_file.size_; - } - - std::string idsToDiscardStr = idsToDiscardSS.str(); - idsToDiscardStr = idsToDiscardStr.substr(0, idsToDiscardStr.size() - 4); //remove the last " OR " - - discardFilesQuery << "UPDATE TableFiles " << - "SET file_type = " << std::to_string(TableFileSchema::TO_DELETE) << ", " << - "updated_time = " << std::to_string(utils::GetMicroSecTimeStamp()) << " " << - "WHERE " << idsToDiscardStr << ";"; - - ENGINE_LOG_DEBUG << "MySQLMetaImpl::DiscardFiles: " << discardFilesQuery.str(); - - status = discardFilesQuery.exec(); - if (!status) { - ENGINE_LOG_ERROR << "QUERY ERROR WHEN DISCARDING FILES"; - return Status::DBTransactionError("QUERY ERROR WHEN DISCARDING FILES", discardFilesQuery.error()); - } - } //Scoped Connection - - return DiscardFiles(to_discard_size); - - } catch (const BadQuery& er) { - // Handle any query errors - ENGINE_LOG_ERROR << "QUERY ERROR WHEN DISCARDING FILES" << ": " << er.what(); - return Status::DBTransactionError("QUERY ERROR WHEN DISCARDING FILES", er.what()); - } catch (const Exception& er) { - // Catch-all for any other MySQL++ exceptions - ENGINE_LOG_ERROR << "GENERAL ERROR WHEN DISCARDING FILES" << ": " << er.what(); - return Status::DBTransactionError("GENERAL ERROR WHEN DISCARDING FILES", er.what()); - } - } - - //ZR: this function assumes all fields in file_schema have value - Status MySQLMetaImpl::UpdateTableFile(TableFileSchema &file_schema) { - -// std::lock_guard lock(mysql_mutex); - - file_schema.updated_time_ = utils::GetMicroSecTimeStamp(); - try { - - MetricCollector metric; - - { - ScopedConnection connectionPtr(*mysql_connection_pool_, safe_grab); - - if (connectionPtr == nullptr) { - return Status::Error("Failed to connect to database server"); - } - -// if (mysql_connection_pool_->getConnectionsInUse() <= 0) { -// ENGINE_LOG_WARNING << "MySQLMetaImpl::UpdateTableFile connection in use = " << mysql_connection_pool_->getConnectionsInUse(); -// } - - Query updateTableFileQuery = connectionPtr->query(); - - //if the table has been deleted, just mark the table file as TO_DELETE - //clean thread will delete the file later - updateTableFileQuery << "SELECT state FROM Tables " << - "WHERE table_id = " << quote << file_schema.table_id_ << ";"; - - ENGINE_LOG_DEBUG << "MySQLMetaImpl::UpdateTableFile: " << updateTableFileQuery.str(); - - StoreQueryResult res = updateTableFileQuery.store(); - - if (res.num_rows() == 1) { - int state = res[0]["state"]; - if (state == TableSchema::TO_DELETE) { - file_schema.file_type_ = TableFileSchema::TO_DELETE; - } - } else { + if (!has_tables[file_schema.table_id_]) { file_schema.file_type_ = TableFileSchema::TO_DELETE; } + file_schema.updated_time_ = utils::GetMicroSecTimeStamp(); std::string id = std::to_string(file_schema.id_); std::string table_id = file_schema.table_id_; @@ -1409,467 +1499,341 @@ namespace meta { std::string created_on = std::to_string(file_schema.created_on_); std::string date = std::to_string(file_schema.date_); - updateTableFileQuery << "UPDATE TableFiles " << - "SET table_id = " << quote << table_id << ", " << - "engine_type = " << engine_type << ", " << - "file_id = " << quote << file_id << ", " << - "file_type = " << file_type << ", " << - "size = " << size << ", " << - "updated_time = " << updated_time << ", " << - "created_on = " << created_on << ", " << - "date = " << date << " " << - "WHERE id = " << id << ";"; + updateTableFilesQuery << "UPDATE TableFiles " << + "SET table_id = " << quote << table_id << ", " << + "engine_type = " << engine_type << ", " << + "file_id = " << quote << file_id << ", " << + "file_type = " << file_type << ", " << + "size = " << size << ", " << + "updated_time = " << updated_time << ", " << + "created_on = " << created_on << ", " << + "date = " << date << " " << + "WHERE id = " << id << ";"; - ENGINE_LOG_DEBUG << "MySQLMetaImpl::UpdateTableFile: " << updateTableFileQuery.str(); + ENGINE_LOG_DEBUG << "MySQLMetaImpl::UpdateTableFiles: " << updateTableFilesQuery.str(); - // std::cout << updateTableFileQuery.str() << std::endl; - - if (!updateTableFileQuery.exec()) { - ENGINE_LOG_DEBUG << "table_id= " << file_schema.table_id_ << " file_id=" << file_schema.file_id_; - ENGINE_LOG_ERROR << "QUERY ERROR WHEN UPDATING TABLE FILE"; - return Status::DBTransactionError("QUERY ERROR WHEN UPDATING TABLE FILE", - updateTableFileQuery.error()); + if (!updateTableFilesQuery.exec()) { + ENGINE_LOG_ERROR << "QUERY ERROR WHEN UPDATING TABLE FILES"; + return Status::DBTransactionError("QUERY ERROR WHEN UPDATING TABLE FILES", + updateTableFilesQuery.error()); } - } //Scoped Connection + } + } //Scoped Connection - } catch (const BadQuery& er) { - // Handle any query errors - ENGINE_LOG_DEBUG << "table_id= " << file_schema.table_id_ << " file_id=" << file_schema.file_id_; - ENGINE_LOG_ERROR << "QUERY ERROR WHEN UPDATING TABLE FILE" << ": " << er.what(); - return Status::DBTransactionError("QUERY ERROR WHEN UPDATING TABLE FILE", er.what()); - } catch (const Exception& er) { - // Catch-all for any other MySQL++ exceptions - ENGINE_LOG_DEBUG << "table_id= " << file_schema.table_id_ << " file_id=" << file_schema.file_id_; - ENGINE_LOG_ERROR << "GENERAL ERROR WHEN UPDATING TABLE FILE" << ": " << er.what(); - return Status::DBTransactionError("GENERAL ERROR WHEN UPDATING TABLE FILE", er.what()); - } - return Status::OK(); + } catch (const BadQuery &er) { + // Handle any query errors + ENGINE_LOG_ERROR << "QUERY ERROR WHEN UPDATING TABLE FILES" << ": " << er.what(); + return Status::DBTransactionError("QUERY ERROR WHEN UPDATING TABLE FILES", er.what()); + } catch (const Exception &er) { + // Catch-all for any other MySQL++ exceptions + ENGINE_LOG_ERROR << "GENERAL ERROR WHEN UPDATING TABLE FILES" << ": " << er.what(); + return Status::DBTransactionError("GENERAL ERROR WHEN UPDATING TABLE FILES", er.what()); } + return Status::OK(); +} - Status MySQLMetaImpl::UpdateTableFilesToIndex(const std::string& table_id) { - // TODO - return Status::OK(); - } +Status MySQLMetaImpl::CleanUpFilesWithTTL(uint16_t seconds) { - Status MySQLMetaImpl::UpdateTableFiles(TableFilesSchema &files) { -// std::lock_guard lock(mysql_mutex); + auto now = utils::GetMicroSecTimeStamp(); + try { + MetricCollector metric; - try { - MetricCollector metric; + { - { - ScopedConnection connectionPtr(*mysql_connection_pool_, safe_grab); - if (connectionPtr == nullptr) { - return Status::Error("Failed to connect to database server"); - } - -// if (mysql_connection_pool_->getConnectionsInUse() <= 0) { -// ENGINE_LOG_WARNING << "MySQLMetaImpl::UpdateTableFiles connection in use = " << mysql_connection_pool_->getConnectionsInUse(); -// } - - Query updateTableFilesQuery = connectionPtr->query(); - - std::map has_tables; - for (auto &file_schema : files) { - - if (has_tables.find(file_schema.table_id_) != has_tables.end()) { - continue; - } - - updateTableFilesQuery << "SELECT EXISTS " << - "(SELECT 1 FROM Tables " << - "WHERE table_id = " << quote << file_schema.table_id_ << " " << - "AND state <> " << std::to_string(TableSchema::TO_DELETE) << ") " << - "AS " << quote << "check" << ";"; - - ENGINE_LOG_DEBUG << "MySQLMetaImpl::UpdateTableFiles: " << updateTableFilesQuery.str(); - - StoreQueryResult res = updateTableFilesQuery.store(); - - int check = res[0]["check"]; - has_tables[file_schema.table_id_] = (check == 1); - } - - for (auto &file_schema : files) { - - if (!has_tables[file_schema.table_id_]) { - file_schema.file_type_ = TableFileSchema::TO_DELETE; - } - file_schema.updated_time_ = utils::GetMicroSecTimeStamp(); - - std::string id = std::to_string(file_schema.id_); - std::string table_id = file_schema.table_id_; - std::string engine_type = std::to_string(file_schema.engine_type_); - std::string file_id = file_schema.file_id_; - std::string file_type = std::to_string(file_schema.file_type_); - std::string size = std::to_string(file_schema.size_); - std::string updated_time = std::to_string(file_schema.updated_time_); - std::string created_on = std::to_string(file_schema.created_on_); - std::string date = std::to_string(file_schema.date_); - - updateTableFilesQuery << "UPDATE TableFiles " << - "SET table_id = " << quote << table_id << ", " << - "engine_type = " << engine_type << ", " << - "file_id = " << quote << file_id << ", " << - "file_type = " << file_type << ", " << - "size = " << size << ", " << - "updated_time = " << updated_time << ", " << - "created_on = " << created_on << ", " << - "date = " << date << " " << - "WHERE id = " << id << ";"; - - ENGINE_LOG_DEBUG << "MySQLMetaImpl::UpdateTableFiles: " << updateTableFilesQuery.str(); - - if (!updateTableFilesQuery.exec()) { - ENGINE_LOG_ERROR << "QUERY ERROR WHEN UPDATING TABLE FILES"; - return Status::DBTransactionError("QUERY ERROR WHEN UPDATING TABLE FILES", - updateTableFilesQuery.error()); - } - } - } //Scoped Connection - - } catch (const BadQuery& er) { - // Handle any query errors - ENGINE_LOG_ERROR << "QUERY ERROR WHEN UPDATING TABLE FILES" << ": " << er.what(); - return Status::DBTransactionError("QUERY ERROR WHEN UPDATING TABLE FILES", er.what()); - } catch (const Exception& er) { - // Catch-all for any other MySQL++ exceptions - ENGINE_LOG_ERROR << "GENERAL ERROR WHEN UPDATING TABLE FILES" << ": " << er.what(); - return Status::DBTransactionError("GENERAL ERROR WHEN UPDATING TABLE FILES", er.what()); - } - return Status::OK(); - } - - Status MySQLMetaImpl::CleanUpFilesWithTTL(uint16_t seconds) { -// static int b_count = 0; -// b_count++; -// std::cout << "CleanUpFilesWithTTL: " << b_count << std::endl; -// std::lock_guard lock(mysql_mutex); - - auto now = utils::GetMicroSecTimeStamp(); - try { - MetricCollector metric; - - { - -// ENGINE_LOG_WARNING << "MySQLMetaImpl::CleanUpFilesWithTTL: clean table files: connection in use before creating ScopedConnection = " -// << mysql_connection_pool_->getConnectionsInUse(); - - ScopedConnection connectionPtr(*mysql_connection_pool_, safe_grab); - - if (connectionPtr == nullptr) { - return Status::Error("Failed to connect to database server"); - } - -// if (mysql_connection_pool_->getConnectionsInUse() <= 0) { -// ENGINE_LOG_WARNING << "MySQLMetaImpl::CleanUpFilesWithTTL: clean table files: connection in use after creating ScopedConnection = " -// << mysql_connection_pool_->getConnectionsInUse(); -// } - - Query cleanUpFilesWithTTLQuery = connectionPtr->query(); - cleanUpFilesWithTTLQuery << "SELECT id, table_id, file_id, date " << - "FROM TableFiles " << - "WHERE file_type = " << std::to_string(TableFileSchema::TO_DELETE) << " AND " << - "updated_time < " << std::to_string(now - seconds * US_PS) << ";"; - - ENGINE_LOG_DEBUG << "MySQLMetaImpl::CleanUpFilesWithTTL: " << cleanUpFilesWithTTLQuery.str(); - - StoreQueryResult res = cleanUpFilesWithTTLQuery.store(); - - TableFileSchema table_file; - std::vector idsToDelete; - - for (auto &resRow : res) { - - table_file.id_ = resRow["id"]; //implicit conversion - - std::string table_id; - resRow["table_id"].to_string(table_id); - table_file.table_id_ = table_id; - - std::string file_id; - resRow["file_id"].to_string(file_id); - table_file.file_id_ = file_id; - - table_file.date_ = resRow["date"]; - - utils::DeleteTableFilePath(options_, table_file); - - ENGINE_LOG_DEBUG << "Removing deleted id =" << table_file.id_ << " location = " - << table_file.location_ << std::endl; - - idsToDelete.emplace_back(std::to_string(table_file.id_)); - } - - if (!idsToDelete.empty()) { - - std::stringstream idsToDeleteSS; - for (auto &id : idsToDelete) { - idsToDeleteSS << "id = " << id << " OR "; - } - - std::string idsToDeleteStr = idsToDeleteSS.str(); - idsToDeleteStr = idsToDeleteStr.substr(0, idsToDeleteStr.size() - 4); //remove the last " OR " - cleanUpFilesWithTTLQuery << "DELETE FROM TableFiles WHERE " << - idsToDeleteStr << ";"; - - ENGINE_LOG_DEBUG << "MySQLMetaImpl::CleanUpFilesWithTTL: " << cleanUpFilesWithTTLQuery.str(); - - if (!cleanUpFilesWithTTLQuery.exec()) { - ENGINE_LOG_ERROR << "QUERY ERROR WHEN CLEANING UP FILES WITH TTL"; - return Status::DBTransactionError("CleanUpFilesWithTTL Error", - cleanUpFilesWithTTLQuery.error()); - } - } - } //Scoped Connection - - } catch (const BadQuery& er) { - // Handle any query errors - ENGINE_LOG_ERROR << "QUERY ERROR WHEN CLEANING UP FILES WITH TTL" << ": " << er.what(); - return Status::DBTransactionError("QUERY ERROR WHEN CLEANING UP FILES WITH TTL", er.what()); - } catch (const Exception& er) { - // Catch-all for any other MySQL++ exceptions - ENGINE_LOG_ERROR << "GENERAL ERROR WHEN CLEANING UP FILES WITH TTL" << ": " << er.what(); - return Status::DBTransactionError("GENERAL ERROR WHEN CLEANING UP FILES WITH TTL", er.what()); - } - - try { - MetricCollector metric; - - { -// ENGINE_LOG_WARNING << "MySQLMetaImpl::CleanUpFilesWithTTL: clean tables: connection in use before creating ScopedConnection = " -// << mysql_connection_pool_->getConnectionsInUse(); - - ScopedConnection connectionPtr(*mysql_connection_pool_, safe_grab); - - if (connectionPtr == nullptr) { - return Status::Error("Failed to connect to database server"); - } - -// if (mysql_connection_pool_->getConnectionsInUse() <= 0) { -// ENGINE_LOG_WARNING << "MySQLMetaImpl::CleanUpFilesWithTTL: clean tables: connection in use after creating ScopedConnection = " -// << mysql_connection_pool_->getConnectionsInUse(); -// } - - Query cleanUpFilesWithTTLQuery = connectionPtr->query(); - cleanUpFilesWithTTLQuery << "SELECT id, table_id " << - "FROM Tables " << - "WHERE state = " << std::to_string(TableSchema::TO_DELETE) << ";"; - - ENGINE_LOG_DEBUG << "MySQLMetaImpl::CleanUpFilesWithTTL: " << cleanUpFilesWithTTLQuery.str(); - - StoreQueryResult res = cleanUpFilesWithTTLQuery.store(); -// std::cout << res.num_rows() << std::endl; - - if (!res.empty()) { - - std::stringstream idsToDeleteSS; - for (auto &resRow : res) { - size_t id = resRow["id"]; - std::string table_id; - resRow["table_id"].to_string(table_id); - - utils::DeleteTablePath(options_, table_id); - - idsToDeleteSS << "id = " << std::to_string(id) << " OR "; - } - std::string idsToDeleteStr = idsToDeleteSS.str(); - idsToDeleteStr = idsToDeleteStr.substr(0, idsToDeleteStr.size() - 4); //remove the last " OR " - cleanUpFilesWithTTLQuery << "DELETE FROM Tables WHERE " << - idsToDeleteStr << ";"; - - ENGINE_LOG_DEBUG << "MySQLMetaImpl::CleanUpFilesWithTTL: " << cleanUpFilesWithTTLQuery.str(); - - if (!cleanUpFilesWithTTLQuery.exec()) { - ENGINE_LOG_ERROR << "QUERY ERROR WHEN CLEANING UP FILES WITH TTL"; - return Status::DBTransactionError("QUERY ERROR WHEN CLEANING UP FILES WITH TTL", - cleanUpFilesWithTTLQuery.error()); - } - } - } //Scoped Connection - - } catch (const BadQuery& er) { - // Handle any query errors - ENGINE_LOG_ERROR << "QUERY ERROR WHEN CLEANING UP FILES WITH TTL" << ": " << er.what(); - return Status::DBTransactionError("QUERY ERROR WHEN CLEANING UP FILES WITH TTL", er.what()); - } catch (const Exception& er) { - // Catch-all for any other MySQL++ exceptions - ENGINE_LOG_ERROR << "GENERAL ERROR WHEN CLEANING UP FILES WITH TTL" << ": " << er.what(); - return Status::DBTransactionError("GENERAL ERROR WHEN CLEANING UP FILES WITH TTL", er.what()); - } - - return Status::OK(); - } - - Status MySQLMetaImpl::CleanUp() { - -// std::lock_guard lock(mysql_mutex); - - try { ScopedConnection connectionPtr(*mysql_connection_pool_, safe_grab); if (connectionPtr == nullptr) { return Status::Error("Failed to connect to database server"); } -// if (mysql_connection_pool_->getConnectionsInUse() <= 0) { -// ENGINE_LOG_WARNING << "MySQLMetaImpl::CleanUp: connection in use = " << mysql_connection_pool_->getConnectionsInUse(); -// } - Query cleanUpQuery = connectionPtr->query(); - cleanUpQuery << "SELECT table_name " << - "FROM information_schema.tables " << - "WHERE table_schema = " << quote << mysql_connection_pool_->getDB() << " " << - "AND table_name = " << quote << "TableFiles" << ";"; + Query cleanUpFilesWithTTLQuery = connectionPtr->query(); + cleanUpFilesWithTTLQuery << "SELECT id, table_id, file_id, date " << + "FROM TableFiles " << + "WHERE file_type = " << std::to_string(TableFileSchema::TO_DELETE) << " AND " << + "updated_time < " << std::to_string(now - seconds * US_PS) << ";"; + + ENGINE_LOG_DEBUG << "MySQLMetaImpl::CleanUpFilesWithTTL: " << cleanUpFilesWithTTLQuery.str(); + + StoreQueryResult res = cleanUpFilesWithTTLQuery.store(); + + TableFileSchema table_file; + std::vector idsToDelete; + + for (auto &resRow : res) { + + table_file.id_ = resRow["id"]; //implicit conversion + + std::string table_id; + resRow["table_id"].to_string(table_id); + table_file.table_id_ = table_id; + + std::string file_id; + resRow["file_id"].to_string(file_id); + table_file.file_id_ = file_id; + + table_file.date_ = resRow["date"]; + + utils::DeleteTableFilePath(options_, table_file); + + ENGINE_LOG_DEBUG << "Removing deleted id =" << table_file.id_ << " location = " + << table_file.location_ << std::endl; + + idsToDelete.emplace_back(std::to_string(table_file.id_)); + } + + if (!idsToDelete.empty()) { + + std::stringstream idsToDeleteSS; + for (auto &id : idsToDelete) { + idsToDeleteSS << "id = " << id << " OR "; + } + + std::string idsToDeleteStr = idsToDeleteSS.str(); + idsToDeleteStr = idsToDeleteStr.substr(0, idsToDeleteStr.size() - 4); //remove the last " OR " + cleanUpFilesWithTTLQuery << "DELETE FROM TableFiles WHERE " << + idsToDeleteStr << ";"; + + ENGINE_LOG_DEBUG << "MySQLMetaImpl::CleanUpFilesWithTTL: " << cleanUpFilesWithTTLQuery.str(); + + if (!cleanUpFilesWithTTLQuery.exec()) { + ENGINE_LOG_ERROR << "QUERY ERROR WHEN CLEANING UP FILES WITH TTL"; + return Status::DBTransactionError("CleanUpFilesWithTTL Error", + cleanUpFilesWithTTLQuery.error()); + } + } + } //Scoped Connection + + } catch (const BadQuery &er) { + // Handle any query errors + ENGINE_LOG_ERROR << "QUERY ERROR WHEN CLEANING UP FILES WITH TTL" << ": " << er.what(); + return Status::DBTransactionError("QUERY ERROR WHEN CLEANING UP FILES WITH TTL", er.what()); + } catch (const Exception &er) { + // Catch-all for any other MySQL++ exceptions + ENGINE_LOG_ERROR << "GENERAL ERROR WHEN CLEANING UP FILES WITH TTL" << ": " << er.what(); + return Status::DBTransactionError("GENERAL ERROR WHEN CLEANING UP FILES WITH TTL", er.what()); + } + + try { + MetricCollector metric; + + { + + + ScopedConnection connectionPtr(*mysql_connection_pool_, safe_grab); + + if (connectionPtr == nullptr) { + return Status::Error("Failed to connect to database server"); + } + + + Query cleanUpFilesWithTTLQuery = connectionPtr->query(); + cleanUpFilesWithTTLQuery << "SELECT id, table_id " << + "FROM Tables " << + "WHERE state = " << std::to_string(TableSchema::TO_DELETE) << ";"; + + ENGINE_LOG_DEBUG << "MySQLMetaImpl::CleanUpFilesWithTTL: " << cleanUpFilesWithTTLQuery.str(); + + StoreQueryResult res = cleanUpFilesWithTTLQuery.store(); + + + if (!res.empty()) { + + std::stringstream idsToDeleteSS; + for (auto &resRow : res) { + size_t id = resRow["id"]; + std::string table_id; + resRow["table_id"].to_string(table_id); + + utils::DeleteTablePath(options_, table_id); + + idsToDeleteSS << "id = " << std::to_string(id) << " OR "; + } + std::string idsToDeleteStr = idsToDeleteSS.str(); + idsToDeleteStr = idsToDeleteStr.substr(0, idsToDeleteStr.size() - 4); //remove the last " OR " + cleanUpFilesWithTTLQuery << "DELETE FROM Tables WHERE " << + idsToDeleteStr << ";"; + + ENGINE_LOG_DEBUG << "MySQLMetaImpl::CleanUpFilesWithTTL: " << cleanUpFilesWithTTLQuery.str(); + + if (!cleanUpFilesWithTTLQuery.exec()) { + ENGINE_LOG_ERROR << "QUERY ERROR WHEN CLEANING UP FILES WITH TTL"; + return Status::DBTransactionError("QUERY ERROR WHEN CLEANING UP FILES WITH TTL", + cleanUpFilesWithTTLQuery.error()); + } + } + } //Scoped Connection + + } catch (const BadQuery &er) { + // Handle any query errors + ENGINE_LOG_ERROR << "QUERY ERROR WHEN CLEANING UP FILES WITH TTL" << ": " << er.what(); + return Status::DBTransactionError("QUERY ERROR WHEN CLEANING UP FILES WITH TTL", er.what()); + } catch (const Exception &er) { + // Catch-all for any other MySQL++ exceptions + ENGINE_LOG_ERROR << "GENERAL ERROR WHEN CLEANING UP FILES WITH TTL" << ": " << er.what(); + return Status::DBTransactionError("GENERAL ERROR WHEN CLEANING UP FILES WITH TTL", er.what()); + } + + return Status::OK(); +} + +Status MySQLMetaImpl::CleanUp() { + + + try { + ScopedConnection connectionPtr(*mysql_connection_pool_, safe_grab); + + if (connectionPtr == nullptr) { + return Status::Error("Failed to connect to database server"); + } + + + Query cleanUpQuery = connectionPtr->query(); + cleanUpQuery << "SELECT table_name " << + "FROM information_schema.tables " << + "WHERE table_schema = " << quote << mysql_connection_pool_->getDB() << " " << + "AND table_name = " << quote << "TableFiles" << ";"; + + ENGINE_LOG_DEBUG << "MySQLMetaImpl::CleanUp: " << cleanUpQuery.str(); + + StoreQueryResult res = cleanUpQuery.store(); + + if (!res.empty()) { + ENGINE_LOG_DEBUG << "Remove table file type as NEW"; + cleanUpQuery << "DELETE FROM TableFiles WHERE file_type = " << std::to_string(TableFileSchema::NEW) << ";"; ENGINE_LOG_DEBUG << "MySQLMetaImpl::CleanUp: " << cleanUpQuery.str(); - StoreQueryResult res = cleanUpQuery.store(); - - if (!res.empty()) { - ENGINE_LOG_DEBUG << "Remove table file type as NEW"; - cleanUpQuery << "DELETE FROM TableFiles WHERE file_type = " << std::to_string(TableFileSchema::NEW) << ";"; - - ENGINE_LOG_DEBUG << "MySQLMetaImpl::CleanUp: " << cleanUpQuery.str(); - - if (!cleanUpQuery.exec()) { - ENGINE_LOG_ERROR << "QUERY ERROR WHEN CLEANING UP FILES"; - return Status::DBTransactionError("Clean up Error", cleanUpQuery.error()); - } + if (!cleanUpQuery.exec()) { + ENGINE_LOG_ERROR << "QUERY ERROR WHEN CLEANING UP FILES"; + return Status::DBTransactionError("Clean up Error", cleanUpQuery.error()); } - - } catch (const BadQuery& er) { - // Handle any query errors - ENGINE_LOG_ERROR << "QUERY ERROR WHEN CLEANING UP FILES" << ": " << er.what(); - return Status::DBTransactionError("QUERY ERROR WHEN CLEANING UP FILES", er.what()); - } catch (const Exception& er) { - // Catch-all for any other MySQL++ exceptions - ENGINE_LOG_ERROR << "GENERAL ERROR WHEN CLEANING UP FILES" << ": " << er.what(); - return Status::DBTransactionError("GENERAL ERROR WHEN CLEANING UP FILES", er.what()); } - return Status::OK(); + } catch (const BadQuery &er) { + // Handle any query errors + ENGINE_LOG_ERROR << "QUERY ERROR WHEN CLEANING UP FILES" << ": " << er.what(); + return Status::DBTransactionError("QUERY ERROR WHEN CLEANING UP FILES", er.what()); + } catch (const Exception &er) { + // Catch-all for any other MySQL++ exceptions + ENGINE_LOG_ERROR << "GENERAL ERROR WHEN CLEANING UP FILES" << ": " << er.what(); + return Status::DBTransactionError("GENERAL ERROR WHEN CLEANING UP FILES", er.what()); } - Status MySQLMetaImpl::Count(const std::string &table_id, uint64_t &result) { + return Status::OK(); +} -// std::lock_guard lock(mysql_mutex); +Status MySQLMetaImpl::Count(const std::string &table_id, uint64_t &result) { - try { - MetricCollector metric; - TableSchema table_schema; - table_schema.table_id_ = table_id; - auto status = DescribeTable(table_schema); + try { + MetricCollector metric; - if (!status.ok()) { - return status; - } + TableSchema table_schema; + table_schema.table_id_ = table_id; + auto status = DescribeTable(table_schema); - StoreQueryResult res; - - { - ScopedConnection connectionPtr(*mysql_connection_pool_, safe_grab); - - if (connectionPtr == nullptr) { - return Status::Error("Failed to connect to database server"); - } - -// if (mysql_connection_pool_->getConnectionsInUse() <= 0) { -// ENGINE_LOG_WARNING << "MySQLMetaImpl::Count: connection in use = " << mysql_connection_pool_->getConnectionsInUse(); -// } - - Query countQuery = connectionPtr->query(); - countQuery << "SELECT size " << - "FROM TableFiles " << - "WHERE table_id = " << quote << table_id << " AND " << - "(file_type = " << std::to_string(TableFileSchema::RAW) << " OR " << - "file_type = " << std::to_string(TableFileSchema::TO_INDEX) << " OR " << - "file_type = " << std::to_string(TableFileSchema::INDEX) << ");"; - - ENGINE_LOG_DEBUG << "MySQLMetaImpl::Count: " << countQuery.str(); - - res = countQuery.store(); - } //Scoped Connection - - result = 0; - for (auto &resRow : res) { - size_t size = resRow["size"]; - result += size; - } - - if (table_schema.dimension_ <= 0) { - std::stringstream errorMsg; - errorMsg << "MySQLMetaImpl::Count: " << "table dimension = " << std::to_string(table_schema.dimension_) << ", table_id = " << table_id; - ENGINE_LOG_ERROR << errorMsg.str(); - return Status::Error(errorMsg.str()); - } - result /= table_schema.dimension_; - result /= sizeof(float); - - } catch (const BadQuery& er) { - // Handle any query errors - ENGINE_LOG_ERROR << "QUERY ERROR WHEN RETRIEVING COUNT" << ": " << er.what(); - return Status::DBTransactionError("QUERY ERROR WHEN RETRIEVING COUNT", er.what()); - } catch (const Exception& er) { - // Catch-all for any other MySQL++ exceptions - ENGINE_LOG_ERROR << "GENERAL ERROR WHEN RETRIEVING COUNT" << ": " << er.what(); - return Status::DBTransactionError("GENERAL ERROR WHEN RETRIEVING COUNT", er.what()); + if (!status.ok()) { + return status; } - return Status::OK(); - } - Status MySQLMetaImpl::DropAll() { - -// std::lock_guard lock(mysql_mutex); - - if (boost::filesystem::is_directory(options_.path)) { - boost::filesystem::remove_all(options_.path); - } - try { + StoreQueryResult res; + { ScopedConnection connectionPtr(*mysql_connection_pool_, safe_grab); if (connectionPtr == nullptr) { return Status::Error("Failed to connect to database server"); } -// if (mysql_connection_pool_->getConnectionsInUse() <= 0) { -// ENGINE_LOG_WARNING << "MySQLMetaImpl::DropAll: connection in use = " << mysql_connection_pool_->getConnectionsInUse(); -// } - Query dropTableQuery = connectionPtr->query(); - dropTableQuery << "DROP TABLE IF EXISTS Tables, TableFiles;"; + Query countQuery = connectionPtr->query(); + countQuery << "SELECT size " << + "FROM TableFiles " << + "WHERE table_id = " << quote << table_id << " AND " << + "(file_type = " << std::to_string(TableFileSchema::RAW) << " OR " << + "file_type = " << std::to_string(TableFileSchema::TO_INDEX) << " OR " << + "file_type = " << std::to_string(TableFileSchema::INDEX) << ");"; - ENGINE_LOG_DEBUG << "MySQLMetaImpl::DropAll: " << dropTableQuery.str(); + ENGINE_LOG_DEBUG << "MySQLMetaImpl::Count: " << countQuery.str(); - if (dropTableQuery.exec()) { - return Status::OK(); - } - else { - ENGINE_LOG_ERROR << "QUERY ERROR WHEN DROPPING TABLE"; - return Status::DBTransactionError("DROP TABLE ERROR", dropTableQuery.error()); - } - } catch (const BadQuery& er) { - // Handle any query errors - ENGINE_LOG_ERROR << "QUERY ERROR WHEN DROPPING TABLE" << ": " << er.what(); - return Status::DBTransactionError("QUERY ERROR WHEN DROPPING TABLE", er.what()); - } catch (const Exception& er) { - // Catch-all for any other MySQL++ exceptions - ENGINE_LOG_ERROR << "GENERAL ERROR WHEN DROPPING TABLE" << ": " << er.what(); - return Status::DBTransactionError("GENERAL ERROR WHEN DROPPING TABLE", er.what()); + res = countQuery.store(); + } //Scoped Connection + + result = 0; + for (auto &resRow : res) { + size_t size = resRow["size"]; + result += size; } - return Status::OK(); - } - MySQLMetaImpl::~MySQLMetaImpl() { -// std::lock_guard lock(mysql_mutex); - if (mode_ != Options::MODE::READ_ONLY) { - CleanUp(); + if (table_schema.dimension_ <= 0) { + std::stringstream errorMsg; + errorMsg << "MySQLMetaImpl::Count: " << "table dimension = " << std::to_string(table_schema.dimension_) + << ", table_id = " << table_id; + ENGINE_LOG_ERROR << errorMsg.str(); + return Status::Error(errorMsg.str()); } + result /= table_schema.dimension_; + result /= sizeof(float); + + } catch (const BadQuery &er) { + // Handle any query errors + ENGINE_LOG_ERROR << "QUERY ERROR WHEN RETRIEVING COUNT" << ": " << er.what(); + return Status::DBTransactionError("QUERY ERROR WHEN RETRIEVING COUNT", er.what()); + } catch (const Exception &er) { + // Catch-all for any other MySQL++ exceptions + ENGINE_LOG_ERROR << "GENERAL ERROR WHEN RETRIEVING COUNT" << ": " << er.what(); + return Status::DBTransactionError("GENERAL ERROR WHEN RETRIEVING COUNT", er.what()); } + return Status::OK(); +} + +Status MySQLMetaImpl::DropAll() { + + + if (boost::filesystem::is_directory(options_.path)) { + boost::filesystem::remove_all(options_.path); + } + try { + + ScopedConnection connectionPtr(*mysql_connection_pool_, safe_grab); + + if (connectionPtr == nullptr) { + return Status::Error("Failed to connect to database server"); + } + + + Query dropTableQuery = connectionPtr->query(); + dropTableQuery << "DROP TABLE IF EXISTS Tables, TableFiles;"; + + ENGINE_LOG_DEBUG << "MySQLMetaImpl::DropAll: " << dropTableQuery.str(); + + if (dropTableQuery.exec()) { + return Status::OK(); + } else { + ENGINE_LOG_ERROR << "QUERY ERROR WHEN DROPPING TABLE"; + return Status::DBTransactionError("DROP TABLE ERROR", dropTableQuery.error()); + } + } catch (const BadQuery &er) { + // Handle any query errors + ENGINE_LOG_ERROR << "QUERY ERROR WHEN DROPPING TABLE" << ": " << er.what(); + return Status::DBTransactionError("QUERY ERROR WHEN DROPPING TABLE", er.what()); + } catch (const Exception &er) { + // Catch-all for any other MySQL++ exceptions + ENGINE_LOG_ERROR << "GENERAL ERROR WHEN DROPPING TABLE" << ": " << er.what(); + return Status::DBTransactionError("GENERAL ERROR WHEN DROPPING TABLE", er.what()); + } + return Status::OK(); +} + +MySQLMetaImpl::~MySQLMetaImpl() { + + if (mode_ != Options::MODE::READ_ONLY) { + CleanUp(); + } +} } // namespace meta } // namespace engine diff --git a/cpp/src/db/NewMemManager.cpp b/cpp/src/db/NewMemManager.cpp index e4903d75a9..c7291354ad 100644 --- a/cpp/src/db/NewMemManager.cpp +++ b/cpp/src/db/NewMemManager.cpp @@ -25,13 +25,10 @@ Status NewMemManager::InsertVectors(const std::string &table_id_, const float *vectors_, IDNumbers &vector_ids_) { - while (GetCurrentMem() > options_.maximum_memory) { + while (GetCurrentMem() > options_.insert_buffer_size) { std::this_thread::sleep_for(std::chrono::milliseconds(1)); } - LOG(DEBUG) << "NewMemManager::InsertVectors: mutable mem = " << GetCurrentMutableMem() << - ", immutable mem = " << GetCurrentImmutableMem() << ", total mem = " << GetCurrentMem(); - std::unique_lock lock(mutex_); return InsertVectorsNoLock(table_id_, n_, vectors_, vector_ids_); diff --git a/cpp/src/db/Options.cpp b/cpp/src/db/Options.cpp index 5f591dcb0f..81f97978ea 100644 --- a/cpp/src/db/Options.cpp +++ b/cpp/src/db/Options.cpp @@ -41,6 +41,10 @@ void ArchiveConf::ParseCritirias(const std::string& criterias) { } for (auto& token : tokens) { + if(token.empty()) { + continue; + } + std::vector kv; boost::algorithm::split(kv, token, boost::is_any_of(":")); if (kv.size() != 2) { diff --git a/cpp/src/db/Options.h b/cpp/src/db/Options.h index 515a84d663..efc5ee3604 100644 --- a/cpp/src/db/Options.h +++ b/cpp/src/db/Options.h @@ -22,7 +22,7 @@ static constexpr uint64_t ONE_GB = ONE_KB*ONE_MB; static const std::string ARCHIVE_CONF_DISK = "disk"; static const std::string ARCHIVE_CONF_DAYS = "days"; -static const std::string ARCHIVE_CONF_DEFAULT = ARCHIVE_CONF_DISK + ":512"; +static const std::string ARCHIVE_CONF_DEFAULT = ""; struct ArchiveConf { using CriteriaT = std::map; @@ -63,7 +63,7 @@ struct Options { size_t index_trigger_size = ONE_GB; //unit: byte DBMetaOptions meta; int mode = MODE::SINGLE; - float maximum_memory = 4 * ONE_GB; + size_t insert_buffer_size = 4 * ONE_GB; }; // Options diff --git a/cpp/src/db/scheduler/task/SearchTask.cpp b/cpp/src/db/scheduler/task/SearchTask.cpp index 8036cf986d..5606ba2c84 100644 --- a/cpp/src/db/scheduler/task/SearchTask.cpp +++ b/cpp/src/db/scheduler/task/SearchTask.cpp @@ -107,7 +107,7 @@ Status SearchTask::ClusterResult(const std::vector &output_ids, uint64_t nq, uint64_t topk, SearchContext::ResultSet &result_set) { - if(output_ids.size() != nq*topk || output_distence.size() != nq*topk) { + if(output_ids.size() < nq*topk || output_distence.size() < nq*topk) { std::string msg = "Invalid id array size: " + std::to_string(output_ids.size()) + " distance array size: " + std::to_string(output_distence.size()); SERVER_LOG_ERROR << msg; diff --git a/cpp/src/sdk/examples/simple/src/ClientTest.cpp b/cpp/src/sdk/examples/simple/src/ClientTest.cpp index 495e6ae861..a17e4e5703 100644 --- a/cpp/src/sdk/examples/simple/src/ClientTest.cpp +++ b/cpp/src/sdk/examples/simple/src/ClientTest.cpp @@ -23,6 +23,7 @@ namespace { static constexpr int64_t TOP_K = 10; static constexpr int64_t SEARCH_TARGET = 5000; //change this value, result is different static constexpr int64_t ADD_VECTOR_LOOP = 10; + static constexpr int64_t SECONDS_EACH_HOUR = 3600; #define BLOCK_SPLITER std::cout << "===========================================" << std::endl; @@ -59,7 +60,7 @@ namespace { std::string CurrentTime() { time_t tt; time( &tt ); - tt = tt + 8*3600; + tt = tt + 8*SECONDS_EACH_HOUR; tm* t= gmtime( &tt ); std::string str = std::to_string(t->tm_year + 1900) + "_" + std::to_string(t->tm_mon + 1) @@ -69,10 +70,11 @@ namespace { return str; } - std::string CurrentTmDate() { + std::string CurrentTmDate(int64_t offset_day = 0) { time_t tt; time( &tt ); - tt = tt + 8*3600; + tt = tt + 8*SECONDS_EACH_HOUR; + tt = tt + 24*SECONDS_EACH_HOUR*offset_day; tm* t= gmtime( &tt ); std::string str = std::to_string(t->tm_year + 1900) + "-" + std::to_string(t->tm_mon + 1) @@ -148,7 +150,7 @@ namespace { std::cout << "The top 1 result is wrong: " << result_id << " vs. " << search_id << std::endl; } else { - std::cout << "Check result sucessfully" << std::endl; + std::cout << "No." << index-1 << " Check result successfully" << std::endl; } } BLOCK_SPLITER @@ -160,7 +162,7 @@ namespace { std::vector query_range_array; Range rg; rg.start_value = CurrentTmDate(); - rg.end_value = CurrentTmDate(); + rg.end_value = CurrentTmDate(1); query_range_array.emplace_back(rg); std::vector record_array; @@ -234,6 +236,7 @@ ClientTest::Test(const std::string& address, const std::string& port) { std::vector> search_record_array; {//add vectors for (int i = 0; i < ADD_VECTOR_LOOP; i++) {//add vectors + TimeRecorder recorder("Add vector No." + std::to_string(i)); std::vector record_array; int64_t begin_index = i * BATCH_ROW_COUNT; BuildVectors(begin_index, begin_index + BATCH_ROW_COUNT, record_array); @@ -255,6 +258,7 @@ ClientTest::Test(const std::string& address, const std::string& port) { } {//wait unit build index finish + TimeRecorder recorder("Build index"); std::cout << "Wait until build all index done" << std::endl; Status stat = conn->BuildIndex(TABLE_NAME); std::cout << "BuildIndex function call status: " << stat.ToString() << std::endl; diff --git a/cpp/src/sdk/src/client/ClientProxy.cpp b/cpp/src/sdk/src/client/ClientProxy.cpp index 81dc8d28e4..115795c2f3 100644 --- a/cpp/src/sdk/src/client/ClientProxy.cpp +++ b/cpp/src/sdk/src/client/ClientProxy.cpp @@ -209,17 +209,25 @@ ClientProxy::SearchVector(const std::string &table_name, } //step 3: search vectors - std::vector result_array; - ClientPtr()->interface()->SearchVector(result_array, table_name, thrift_records, thrift_ranges, topk); + std::vector result_array; + ClientPtr()->interface()->SearchVector2(result_array, table_name, thrift_records, thrift_ranges, topk); //step 4: convert result array for(auto& thrift_topk_result : result_array) { TopKQueryResult result; - for(auto& thrift_query_result : thrift_topk_result.query_result_arrays) { + size_t id_count = thrift_topk_result.id_array.size()/sizeof(int64_t); + size_t dist_count = thrift_topk_result.distance_array.size()/ sizeof(double); + if(id_count != dist_count) { + return Status(StatusCode::UnknownError, "illegal result"); + } + + int64_t* id_ptr = (int64_t*)thrift_topk_result.id_array.data(); + double* dist_ptr = (double*)thrift_topk_result.distance_array.data(); + for(size_t i = 0; i < id_count; i++) { QueryResult query_result; - query_result.id = thrift_query_result.id; - query_result.distance = thrift_query_result.distance; + query_result.id = id_ptr[i]; + query_result.distance = dist_ptr[i]; result.query_result_arrays.emplace_back(query_result); } diff --git a/cpp/src/server/DBWrapper.cpp b/cpp/src/server/DBWrapper.cpp index 66a1d83479..6c67176571 100644 --- a/cpp/src/server/DBWrapper.cpp +++ b/cpp/src/server/DBWrapper.cpp @@ -28,12 +28,12 @@ DBWrapper::DBWrapper() { if(index_size > 0) {//ensure larger than zero, unit is MB opt.index_trigger_size = (size_t)index_size * engine::ONE_MB; } - float maximum_memory = config.GetFloatValue(CONFIG_MAXMIMUM_MEMORY); - if (maximum_memory > 1.0) { - opt.maximum_memory = maximum_memory * engine::ONE_GB; + int64_t insert_buffer_size = config.GetInt64Value(CONFIG_DB_INSERT_BUFFER_SIZE, 4); + if (insert_buffer_size >= 1) { + opt.insert_buffer_size = insert_buffer_size * engine::ONE_GB; } else { - std::cout << "ERROR: maximum_memory should be at least 1 GB" << std::endl; + std::cout << "ERROR: insert_buffer_size should be at least 1 GB" << std::endl; kill(0, SIGUSR1); } diff --git a/cpp/src/server/MilvusServer.cpp b/cpp/src/server/MilvusServer.cpp index 92e06d0ccd..2f68c4b189 100644 --- a/cpp/src/server/MilvusServer.cpp +++ b/cpp/src/server/MilvusServer.cpp @@ -76,7 +76,7 @@ MilvusServer::StartService() { return; } - stdcxx::shared_ptr threadManager(ThreadManager::newSimpleThreadManager()); + stdcxx::shared_ptr threadManager(ThreadManager::newSimpleThreadManager(16)); stdcxx::shared_ptr threadFactory(new PosixThreadFactory()); threadManager->threadFactory(threadFactory); threadManager->start(); diff --git a/cpp/src/server/RequestHandler.cpp b/cpp/src/server/RequestHandler.cpp index 5ff6b1784a..5074043148 100644 --- a/cpp/src/server/RequestHandler.cpp +++ b/cpp/src/server/RequestHandler.cpp @@ -60,11 +60,22 @@ RequestHandler::SearchVector(std::vector &_return, const std::vector &query_range_array, const int64_t topk) { // SERVER_LOG_DEBUG << "Entering RequestHandler::SearchVector"; - BaseTaskPtr task_ptr = SearchVectorTask::Create(table_name, std::vector(), query_record_array, + BaseTaskPtr task_ptr = SearchVectorTask1::Create(table_name, std::vector(), query_record_array, query_range_array, topk, _return); RequestScheduler::ExecTask(task_ptr); } +void +RequestHandler::SearchVector2(std::vector & _return, + const std::string& table_name, + const std::vector & query_record_array, + const std::vector & query_range_array, + const int64_t topk) { + BaseTaskPtr task_ptr = SearchVectorTask2::Create(table_name, std::vector(), query_record_array, + query_range_array, topk, _return); + RequestScheduler::ExecTask(task_ptr); +} + void RequestHandler::SearchVectorInFiles(std::vector<::milvus::thrift::TopKQueryResult> &_return, const std::string& table_name, @@ -73,7 +84,7 @@ RequestHandler::SearchVectorInFiles(std::vector<::milvus::thrift::TopKQueryResul const std::vector<::milvus::thrift::Range> &query_range_array, const int64_t topk) { // SERVER_LOG_DEBUG << "Entering RequestHandler::SearchVectorInFiles. file_id_array size = " << std::to_string(file_id_array.size()); - BaseTaskPtr task_ptr = SearchVectorTask::Create(table_name, file_id_array, query_record_array, + BaseTaskPtr task_ptr = SearchVectorTask1::Create(table_name, file_id_array, query_record_array, query_range_array, topk, _return); RequestScheduler::ExecTask(task_ptr); } diff --git a/cpp/src/server/RequestHandler.h b/cpp/src/server/RequestHandler.h index aeda4e5ed6..a79830b512 100644 --- a/cpp/src/server/RequestHandler.h +++ b/cpp/src/server/RequestHandler.h @@ -106,6 +106,29 @@ public: const std::vector<::milvus::thrift::Range> & query_range_array, const int64_t topk); + /** + * @brief Query vector + * + * This method is used to query vector in table. + * + * @param table_name, table_name is queried. + * @param query_record_array, all vector are going to be queried. + * @param query_range_array, optional ranges for conditional search. If not specified, search whole table + * @param topk, how many similarity vectors will be searched. + * + * @return query binary result array. + * + * @param table_name + * @param query_record_array + * @param query_range_array + * @param topk + */ + void SearchVector2(std::vector<::milvus::thrift::TopKQueryBinResult> & _return, + const std::string& table_name, + const std::vector<::milvus::thrift::RowRecord> & query_record_array, + const std::vector<::milvus::thrift::Range> & query_range_array, + const int64_t topk); + /** * @brief Internal use query interface * diff --git a/cpp/src/server/RequestTask.cpp b/cpp/src/server/RequestTask.cpp index d4051eba66..c6a3455600 100644 --- a/cpp/src/server/RequestTask.cpp +++ b/cpp/src/server/RequestTask.cpp @@ -12,6 +12,10 @@ #include "DBWrapper.h" #include "version.h" +#ifdef MILVUS_ENABLE_PROFILING +#include "gperftools/profiler.h" +#endif + namespace zilliz { namespace milvus { namespace server { @@ -127,6 +131,18 @@ namespace { } } } + + std::string + GetCurrTimeStr() { + char tm_buf[20] = {0}; + time_t tt; + time(&tt); + tt = tt + 8 * 60 * 60; + tm* t = gmtime(&tt); + sprintf(tm_buf, "%4d%02d%02d_%02d%02d%02d", (t->tm_year+1900), (t->tm_mon+1), (t->tm_mday), + (t->tm_hour), (t->tm_min), (t->tm_sec)); + return tm_buf; + } } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -148,17 +164,17 @@ ServerError CreateTableTask::OnExecute() { ServerError res = SERVER_SUCCESS; res = ValidateTableName(schema_.table_name); if(res != SERVER_SUCCESS) { - return res; + return SetError(res, "Invalid table name: " + schema_.table_name); } res = ValidateTableDimension(schema_.dimension); if(res != SERVER_SUCCESS) { - return res; + return SetError(res, "Invalid table dimension: " + std::to_string(schema_.dimension)); } res = ValidateTableIndexType(schema_.index_type); if(res != SERVER_SUCCESS) { - return res; + return SetError(res, "Invalid index type: " + std::to_string(schema_.index_type)); } //step 2: construct table schema @@ -203,7 +219,7 @@ ServerError DescribeTableTask::OnExecute() { ServerError res = SERVER_SUCCESS; res = ValidateTableName(table_name_); if(res != SERVER_SUCCESS) { - return res; + return SetError(res, "Invalid table name: " + table_name_); } //step 2: get table info @@ -243,12 +259,20 @@ ServerError BuildIndexTask::OnExecute() { TimeRecorder rc("BuildIndexTask"); //step 1: check arguments - if(table_name_.empty()) { - return SetError(SERVER_INVALID_TABLE_NAME, "Empty table name"); + ServerError res = SERVER_SUCCESS; + res = ValidateTableName(table_name_); + if(res != SERVER_SUCCESS) { + return SetError(res, "Invalid table name: " + table_name_); + } + + bool has_table = false; + engine::Status stat = DBWrapper::DB()->HasTable(table_name_, has_table); + if(!has_table) { + return SetError(SERVER_TABLE_NOT_EXIST, "Table " + table_name_ + " not exists"); } //step 2: check table existence - engine::Status stat = DBWrapper::DB()->BuildIndex(table_name_); + stat = DBWrapper::DB()->BuildIndex(table_name_); if(!stat.ok()) { return SetError(SERVER_BUILD_INDEX_ERROR, "Engine failed: " + stat.ToString()); } @@ -281,8 +305,9 @@ ServerError HasTableTask::OnExecute() { ServerError res = SERVER_SUCCESS; res = ValidateTableName(table_name_); if(res != SERVER_SUCCESS) { - return res; + return SetError(res, "Invalid table name: " + table_name_); } + //step 2: check table existence engine::Status stat = DBWrapper::DB()->HasTable(table_name_, has_table_); if(!stat.ok()) { @@ -316,7 +341,7 @@ ServerError DeleteTableTask::OnExecute() { ServerError res = SERVER_SUCCESS; res = ValidateTableName(table_name_); if(res != SERVER_SUCCESS) { - return res; + return SetError(res, "Invalid table name: " + table_name_); } //step 2: check table existence @@ -400,7 +425,7 @@ ServerError AddVectorTask::OnExecute() { ServerError res = SERVER_SUCCESS; res = ValidateTableName(table_name_); if(res != SERVER_SUCCESS) { - return res; + return SetError(res, "Invalid table name: " + table_name_); } if(record_array_.empty()) { @@ -421,6 +446,12 @@ ServerError AddVectorTask::OnExecute() { rc.Record("check validation"); +#ifdef MILVUS_ENABLE_PROFILING + std::string fname = "/tmp/insert_" + std::to_string(this->record_array_.size()) + + "_" + GetCurrTimeStr() + ".profiling"; + ProfilerStart(fname.c_str()); +#endif + //step 3: prepare float data std::vector vec_f; ServerError error_code = SERVER_SUCCESS; @@ -446,6 +477,10 @@ ServerError AddVectorTask::OnExecute() { return SetError(SERVER_ILLEGAL_VECTOR_ID, msg); } +#ifdef MILVUS_ENABLE_PROFILING + ProfilerStop(); +#endif + rc.Record("do insert"); rc.Elapse("total cost"); @@ -457,33 +492,21 @@ ServerError AddVectorTask::OnExecute() { } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -SearchVectorTask::SearchVectorTask(const std::string &table_name, - const std::vector& file_id_array, - const std::vector &query_record_array, - const std::vector &query_range_array, - const int64_t top_k, - std::vector &result_array) +SearchVectorTaskBase::SearchVectorTaskBase(const std::string &table_name, + const std::vector& file_id_array, + const std::vector &query_record_array, + const std::vector &query_range_array, + const int64_t top_k) : BaseTask(DQL_TASK_GROUP), table_name_(table_name), file_id_array_(file_id_array), record_array_(query_record_array), range_array_(query_range_array), - top_k_(top_k), - result_array_(result_array) { + top_k_(top_k) { } -BaseTaskPtr SearchVectorTask::Create(const std::string& table_name, - const std::vector& file_id_array, - const std::vector & query_record_array, - const std::vector & query_range_array, - const int64_t top_k, - std::vector& result_array) { - return std::shared_ptr(new SearchVectorTask(table_name, file_id_array, - query_record_array, query_range_array, top_k, result_array)); -} - -ServerError SearchVectorTask::OnExecute() { +ServerError SearchVectorTaskBase::OnExecute() { try { TimeRecorder rc("SearchVectorTask"); @@ -491,7 +514,7 @@ ServerError SearchVectorTask::OnExecute() { ServerError res = SERVER_SUCCESS; res = ValidateTableName(table_name_); if(res != SERVER_SUCCESS) { - return res; + return SetError(res, "Invalid table name: " + table_name_); } if(top_k_ <= 0) { @@ -524,6 +547,13 @@ ServerError SearchVectorTask::OnExecute() { rc.Record("check validation"); +#ifdef MILVUS_ENABLE_PROFILING + std::string fname = "/tmp/search_nq_" + std::to_string(this->record_array_.size()) + + "_top_" + std::to_string(this->top_k_) + "_" + + GetCurrTimeStr() + ".profiling"; + ProfilerStart(fname.c_str()); +#endif + //step 3: prepare float data std::vector vec_f; ConvertRowRecordToFloatArray(record_array_, table_info.dimension_, vec_f, error_code, error_msg); @@ -561,21 +591,12 @@ ServerError SearchVectorTask::OnExecute() { rc.Record("do search"); //step 5: construct result array - for(uint64_t i = 0; i < record_count; i++) { - auto& result = results[i]; - const auto& record = record_array_[i]; + ConstructResult(results); - thrift::TopKQueryResult thrift_topk_result; - for(auto& pair : result) { - thrift::QueryResult thrift_result; - thrift_result.__set_id(pair.first); - thrift_result.__set_distance(pair.second); +#ifdef MILVUS_ENABLE_PROFILING + ProfilerStop(); +#endif - thrift_topk_result.query_result_arrays.emplace_back(thrift_result); - } - - result_array_.emplace_back(thrift_topk_result); - } rc.Record("construct result"); rc.Elapse("total cost"); @@ -586,6 +607,100 @@ ServerError SearchVectorTask::OnExecute() { return SERVER_SUCCESS; } +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +SearchVectorTask1::SearchVectorTask1(const std::string &table_name, + const std::vector& file_id_array, + const std::vector &query_record_array, + const std::vector &query_range_array, + const int64_t top_k, + std::vector &result_array) + : SearchVectorTaskBase(table_name, file_id_array, query_record_array, query_range_array, top_k), + result_array_(result_array) { + +} + +BaseTaskPtr SearchVectorTask1::Create(const std::string& table_name, + const std::vector& file_id_array, + const std::vector & query_record_array, + const std::vector & query_range_array, + const int64_t top_k, + std::vector& result_array) { + return std::shared_ptr(new SearchVectorTask1(table_name, file_id_array, + query_record_array, query_range_array, top_k, result_array)); +} + +ServerError SearchVectorTask1::ConstructResult(engine::QueryResults& results) { + for(uint64_t i = 0; i < results.size(); i++) { + auto& result = results[i]; + const auto& record = record_array_[i]; + + thrift::TopKQueryResult thrift_topk_result; + for(auto& pair : result) { + thrift::QueryResult thrift_result; + thrift_result.__set_id(pair.first); + thrift_result.__set_distance(pair.second); + + thrift_topk_result.query_result_arrays.emplace_back(thrift_result); + } + + result_array_.emplace_back(thrift_topk_result); + } + + return SERVER_SUCCESS; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +SearchVectorTask2::SearchVectorTask2(const std::string &table_name, + const std::vector& file_id_array, + const std::vector &query_record_array, + const std::vector &query_range_array, + const int64_t top_k, + std::vector &result_array) + : SearchVectorTaskBase(table_name, file_id_array, query_record_array, query_range_array, top_k), + result_array_(result_array) { + +} + +BaseTaskPtr SearchVectorTask2::Create(const std::string& table_name, + const std::vector& file_id_array, + const std::vector & query_record_array, + const std::vector & query_range_array, + const int64_t top_k, + std::vector& result_array) { + return std::shared_ptr(new SearchVectorTask2(table_name, file_id_array, + query_record_array, query_range_array, top_k, result_array)); +} + +ServerError SearchVectorTask2::ConstructResult(engine::QueryResults& results) { + for(size_t i = 0; i < results.size(); i++) { + auto& result = results[i]; + + thrift::TopKQueryBinResult thrift_topk_result; + if(result.empty()) { + result_array_.emplace_back(thrift_topk_result); + continue; + } + + std::string str_ids, str_distances; + str_ids.resize(sizeof(engine::IDNumber)*result.size()); + str_distances.resize(sizeof(double)*result.size()); + + engine::IDNumber* ids_ptr = (engine::IDNumber*)str_ids.data(); + double* distance_ptr = (double*)str_distances.data(); + for(size_t k = 0; k < results.size(); k++) { + auto& pair = result[k]; + ids_ptr[k] = pair.first; + distance_ptr[k] = pair.second; + } + + thrift_topk_result.__set_id_array(str_ids); + thrift_topk_result.__set_distance_array(str_distances); + result_array_.emplace_back(thrift_topk_result); + } + + return SERVER_SUCCESS; +} + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// GetTableRowCountTask::GetTableRowCountTask(const std::string& table_name, int64_t& row_count) : BaseTask(DDL_DML_TASK_GROUP), @@ -606,7 +721,7 @@ ServerError GetTableRowCountTask::OnExecute() { ServerError res = SERVER_SUCCESS; res = ValidateTableName(table_name_); if(res != SERVER_SUCCESS) { - return res; + return SetError(res, "Invalid table name: " + table_name_); } //step 2: get row count diff --git a/cpp/src/server/RequestTask.h b/cpp/src/server/RequestTask.h index 37c04272fa..4a95ef5b61 100644 --- a/cpp/src/server/RequestTask.h +++ b/cpp/src/server/RequestTask.h @@ -129,7 +129,28 @@ private: }; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -class SearchVectorTask : public BaseTask { +class SearchVectorTaskBase : public BaseTask { +protected: + SearchVectorTaskBase(const std::string& table_name, + const std::vector& file_id_array, + const std::vector<::milvus::thrift::RowRecord> & query_record_array, + const std::vector<::milvus::thrift::Range> & query_range_array, + const int64_t top_k); + + ServerError OnExecute() override; + + virtual ServerError ConstructResult(engine::QueryResults& results) = 0; + +protected: + std::string table_name_; + std::vector file_id_array_; + int64_t top_k_; + const std::vector<::milvus::thrift::RowRecord>& record_array_; + const std::vector<::milvus::thrift::Range>& range_array_; +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class SearchVectorTask1 : public SearchVectorTaskBase { public: static BaseTaskPtr Create(const std::string& table_name, const std::vector& file_id_array, @@ -139,24 +160,43 @@ public: std::vector<::milvus::thrift::TopKQueryResult>& result_array); protected: - SearchVectorTask(const std::string& table_name, - const std::vector& file_id_array, - const std::vector<::milvus::thrift::RowRecord> & query_record_array, - const std::vector<::milvus::thrift::Range> & query_range_array, - const int64_t top_k, + SearchVectorTask1(const std::string& table_name, + const std::vector& file_id_array, + const std::vector<::milvus::thrift::RowRecord> & query_record_array, + const std::vector<::milvus::thrift::Range> & query_range_array, + const int64_t top_k, std::vector<::milvus::thrift::TopKQueryResult>& result_array); - ServerError OnExecute() override; + ServerError ConstructResult(engine::QueryResults& results) override; private: - std::string table_name_; - std::vector file_id_array_; - int64_t top_k_; - const std::vector<::milvus::thrift::RowRecord>& record_array_; - const std::vector<::milvus::thrift::Range>& range_array_; std::vector<::milvus::thrift::TopKQueryResult>& result_array_; }; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class SearchVectorTask2 : public SearchVectorTaskBase { +public: + static BaseTaskPtr Create(const std::string& table_name, + const std::vector& file_id_array, + const std::vector<::milvus::thrift::RowRecord> & query_record_array, + const std::vector<::milvus::thrift::Range> & query_range_array, + const int64_t top_k, + std::vector<::milvus::thrift::TopKQueryBinResult>& result_array); + +protected: + SearchVectorTask2(const std::string& table_name, + const std::vector& file_id_array, + const std::vector<::milvus::thrift::RowRecord> & query_record_array, + const std::vector<::milvus::thrift::Range> & query_range_array, + const int64_t top_k, + std::vector<::milvus::thrift::TopKQueryBinResult>& result_array); + + ServerError ConstructResult(engine::QueryResults& results) override; + +private: + std::vector<::milvus::thrift::TopKQueryBinResult>& result_array_; +}; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// class GetTableRowCountTask : public BaseTask { public: diff --git a/cpp/src/server/ServerConfig.h b/cpp/src/server/ServerConfig.h index d3fb77a8cb..bc202adcf6 100644 --- a/cpp/src/server/ServerConfig.h +++ b/cpp/src/server/ServerConfig.h @@ -27,7 +27,7 @@ static const std::string CONFIG_DB_SLAVE_PATH = "db_slave_path"; static const std::string CONFIG_DB_INDEX_TRIGGER_SIZE = "index_building_threshold"; static const std::string CONFIG_DB_ARCHIVE_DISK = "archive_disk_threshold"; static const std::string CONFIG_DB_ARCHIVE_DAYS = "archive_days_threshold"; -static const std::string CONFIG_MAXMIMUM_MEMORY = "maximum_memory"; +static const std::string CONFIG_DB_INSERT_BUFFER_SIZE = "insert_buffer_size"; static const std::string CONFIG_LOG = "log_config"; diff --git a/cpp/src/thrift/gen-cpp/MilvusService.cpp b/cpp/src/thrift/gen-cpp/MilvusService.cpp index fb66b0ecbe..3420b92b5d 100644 --- a/cpp/src/thrift/gen-cpp/MilvusService.cpp +++ b/cpp/src/thrift/gen-cpp/MilvusService.cpp @@ -814,14 +814,14 @@ uint32_t MilvusService_AddVector_args::read(::apache::thrift::protocol::TProtoco if (ftype == ::apache::thrift::protocol::T_LIST) { { this->record_array.clear(); - uint32_t _size19; - ::apache::thrift::protocol::TType _etype22; - xfer += iprot->readListBegin(_etype22, _size19); - this->record_array.resize(_size19); - uint32_t _i23; - for (_i23 = 0; _i23 < _size19; ++_i23) + uint32_t _size21; + ::apache::thrift::protocol::TType _etype24; + xfer += iprot->readListBegin(_etype24, _size21); + this->record_array.resize(_size21); + uint32_t _i25; + for (_i25 = 0; _i25 < _size21; ++_i25) { - xfer += this->record_array[_i23].read(iprot); + xfer += this->record_array[_i25].read(iprot); } xfer += iprot->readListEnd(); } @@ -854,10 +854,10 @@ uint32_t MilvusService_AddVector_args::write(::apache::thrift::protocol::TProtoc xfer += oprot->writeFieldBegin("record_array", ::apache::thrift::protocol::T_LIST, 3); { xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRUCT, static_cast(this->record_array.size())); - std::vector ::const_iterator _iter24; - for (_iter24 = this->record_array.begin(); _iter24 != this->record_array.end(); ++_iter24) + std::vector ::const_iterator _iter26; + for (_iter26 = this->record_array.begin(); _iter26 != this->record_array.end(); ++_iter26) { - xfer += (*_iter24).write(oprot); + xfer += (*_iter26).write(oprot); } xfer += oprot->writeListEnd(); } @@ -885,10 +885,10 @@ uint32_t MilvusService_AddVector_pargs::write(::apache::thrift::protocol::TProto xfer += oprot->writeFieldBegin("record_array", ::apache::thrift::protocol::T_LIST, 3); { xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRUCT, static_cast((*(this->record_array)).size())); - std::vector ::const_iterator _iter25; - for (_iter25 = (*(this->record_array)).begin(); _iter25 != (*(this->record_array)).end(); ++_iter25) + std::vector ::const_iterator _iter27; + for (_iter27 = (*(this->record_array)).begin(); _iter27 != (*(this->record_array)).end(); ++_iter27) { - xfer += (*_iter25).write(oprot); + xfer += (*_iter27).write(oprot); } xfer += oprot->writeListEnd(); } @@ -929,14 +929,14 @@ uint32_t MilvusService_AddVector_result::read(::apache::thrift::protocol::TProto if (ftype == ::apache::thrift::protocol::T_LIST) { { this->success.clear(); - uint32_t _size26; - ::apache::thrift::protocol::TType _etype29; - xfer += iprot->readListBegin(_etype29, _size26); - this->success.resize(_size26); - uint32_t _i30; - for (_i30 = 0; _i30 < _size26; ++_i30) + uint32_t _size28; + ::apache::thrift::protocol::TType _etype31; + xfer += iprot->readListBegin(_etype31, _size28); + this->success.resize(_size28); + uint32_t _i32; + for (_i32 = 0; _i32 < _size28; ++_i32) { - xfer += iprot->readI64(this->success[_i30]); + xfer += iprot->readI64(this->success[_i32]); } xfer += iprot->readListEnd(); } @@ -975,10 +975,10 @@ uint32_t MilvusService_AddVector_result::write(::apache::thrift::protocol::TProt xfer += oprot->writeFieldBegin("success", ::apache::thrift::protocol::T_LIST, 0); { xfer += oprot->writeListBegin(::apache::thrift::protocol::T_I64, static_cast(this->success.size())); - std::vector ::const_iterator _iter31; - for (_iter31 = this->success.begin(); _iter31 != this->success.end(); ++_iter31) + std::vector ::const_iterator _iter33; + for (_iter33 = this->success.begin(); _iter33 != this->success.end(); ++_iter33) { - xfer += oprot->writeI64((*_iter31)); + xfer += oprot->writeI64((*_iter33)); } xfer += oprot->writeListEnd(); } @@ -1023,14 +1023,14 @@ uint32_t MilvusService_AddVector_presult::read(::apache::thrift::protocol::TProt if (ftype == ::apache::thrift::protocol::T_LIST) { { (*(this->success)).clear(); - uint32_t _size32; - ::apache::thrift::protocol::TType _etype35; - xfer += iprot->readListBegin(_etype35, _size32); - (*(this->success)).resize(_size32); - uint32_t _i36; - for (_i36 = 0; _i36 < _size32; ++_i36) + uint32_t _size34; + ::apache::thrift::protocol::TType _etype37; + xfer += iprot->readListBegin(_etype37, _size34); + (*(this->success)).resize(_size34); + uint32_t _i38; + for (_i38 = 0; _i38 < _size34; ++_i38) { - xfer += iprot->readI64((*(this->success))[_i36]); + xfer += iprot->readI64((*(this->success))[_i38]); } xfer += iprot->readListEnd(); } @@ -1097,14 +1097,14 @@ uint32_t MilvusService_SearchVector_args::read(::apache::thrift::protocol::TProt if (ftype == ::apache::thrift::protocol::T_LIST) { { this->query_record_array.clear(); - uint32_t _size37; - ::apache::thrift::protocol::TType _etype40; - xfer += iprot->readListBegin(_etype40, _size37); - this->query_record_array.resize(_size37); - uint32_t _i41; - for (_i41 = 0; _i41 < _size37; ++_i41) + uint32_t _size39; + ::apache::thrift::protocol::TType _etype42; + xfer += iprot->readListBegin(_etype42, _size39); + this->query_record_array.resize(_size39); + uint32_t _i43; + for (_i43 = 0; _i43 < _size39; ++_i43) { - xfer += this->query_record_array[_i41].read(iprot); + xfer += this->query_record_array[_i43].read(iprot); } xfer += iprot->readListEnd(); } @@ -1117,14 +1117,14 @@ uint32_t MilvusService_SearchVector_args::read(::apache::thrift::protocol::TProt if (ftype == ::apache::thrift::protocol::T_LIST) { { this->query_range_array.clear(); - uint32_t _size42; - ::apache::thrift::protocol::TType _etype45; - xfer += iprot->readListBegin(_etype45, _size42); - this->query_range_array.resize(_size42); - uint32_t _i46; - for (_i46 = 0; _i46 < _size42; ++_i46) + uint32_t _size44; + ::apache::thrift::protocol::TType _etype47; + xfer += iprot->readListBegin(_etype47, _size44); + this->query_range_array.resize(_size44); + uint32_t _i48; + for (_i48 = 0; _i48 < _size44; ++_i48) { - xfer += this->query_range_array[_i46].read(iprot); + xfer += this->query_range_array[_i48].read(iprot); } xfer += iprot->readListEnd(); } @@ -1165,10 +1165,10 @@ uint32_t MilvusService_SearchVector_args::write(::apache::thrift::protocol::TPro xfer += oprot->writeFieldBegin("query_record_array", ::apache::thrift::protocol::T_LIST, 3); { xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRUCT, static_cast(this->query_record_array.size())); - std::vector ::const_iterator _iter47; - for (_iter47 = this->query_record_array.begin(); _iter47 != this->query_record_array.end(); ++_iter47) + std::vector ::const_iterator _iter49; + for (_iter49 = this->query_record_array.begin(); _iter49 != this->query_record_array.end(); ++_iter49) { - xfer += (*_iter47).write(oprot); + xfer += (*_iter49).write(oprot); } xfer += oprot->writeListEnd(); } @@ -1177,10 +1177,10 @@ uint32_t MilvusService_SearchVector_args::write(::apache::thrift::protocol::TPro xfer += oprot->writeFieldBegin("query_range_array", ::apache::thrift::protocol::T_LIST, 4); { xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRUCT, static_cast(this->query_range_array.size())); - std::vector ::const_iterator _iter48; - for (_iter48 = this->query_range_array.begin(); _iter48 != this->query_range_array.end(); ++_iter48) + std::vector ::const_iterator _iter50; + for (_iter50 = this->query_range_array.begin(); _iter50 != this->query_range_array.end(); ++_iter50) { - xfer += (*_iter48).write(oprot); + xfer += (*_iter50).write(oprot); } xfer += oprot->writeListEnd(); } @@ -1212,10 +1212,10 @@ uint32_t MilvusService_SearchVector_pargs::write(::apache::thrift::protocol::TPr xfer += oprot->writeFieldBegin("query_record_array", ::apache::thrift::protocol::T_LIST, 3); { xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRUCT, static_cast((*(this->query_record_array)).size())); - std::vector ::const_iterator _iter49; - for (_iter49 = (*(this->query_record_array)).begin(); _iter49 != (*(this->query_record_array)).end(); ++_iter49) + std::vector ::const_iterator _iter51; + for (_iter51 = (*(this->query_record_array)).begin(); _iter51 != (*(this->query_record_array)).end(); ++_iter51) { - xfer += (*_iter49).write(oprot); + xfer += (*_iter51).write(oprot); } xfer += oprot->writeListEnd(); } @@ -1224,10 +1224,10 @@ uint32_t MilvusService_SearchVector_pargs::write(::apache::thrift::protocol::TPr xfer += oprot->writeFieldBegin("query_range_array", ::apache::thrift::protocol::T_LIST, 4); { xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRUCT, static_cast((*(this->query_range_array)).size())); - std::vector ::const_iterator _iter50; - for (_iter50 = (*(this->query_range_array)).begin(); _iter50 != (*(this->query_range_array)).end(); ++_iter50) + std::vector ::const_iterator _iter52; + for (_iter52 = (*(this->query_range_array)).begin(); _iter52 != (*(this->query_range_array)).end(); ++_iter52) { - xfer += (*_iter50).write(oprot); + xfer += (*_iter52).write(oprot); } xfer += oprot->writeListEnd(); } @@ -1272,14 +1272,14 @@ uint32_t MilvusService_SearchVector_result::read(::apache::thrift::protocol::TPr if (ftype == ::apache::thrift::protocol::T_LIST) { { this->success.clear(); - uint32_t _size51; - ::apache::thrift::protocol::TType _etype54; - xfer += iprot->readListBegin(_etype54, _size51); - this->success.resize(_size51); - uint32_t _i55; - for (_i55 = 0; _i55 < _size51; ++_i55) + uint32_t _size53; + ::apache::thrift::protocol::TType _etype56; + xfer += iprot->readListBegin(_etype56, _size53); + this->success.resize(_size53); + uint32_t _i57; + for (_i57 = 0; _i57 < _size53; ++_i57) { - xfer += this->success[_i55].read(iprot); + xfer += this->success[_i57].read(iprot); } xfer += iprot->readListEnd(); } @@ -1318,10 +1318,10 @@ uint32_t MilvusService_SearchVector_result::write(::apache::thrift::protocol::TP xfer += oprot->writeFieldBegin("success", ::apache::thrift::protocol::T_LIST, 0); { xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRUCT, static_cast(this->success.size())); - std::vector ::const_iterator _iter56; - for (_iter56 = this->success.begin(); _iter56 != this->success.end(); ++_iter56) + std::vector ::const_iterator _iter58; + for (_iter58 = this->success.begin(); _iter58 != this->success.end(); ++_iter58) { - xfer += (*_iter56).write(oprot); + xfer += (*_iter58).write(oprot); } xfer += oprot->writeListEnd(); } @@ -1366,14 +1366,357 @@ uint32_t MilvusService_SearchVector_presult::read(::apache::thrift::protocol::TP if (ftype == ::apache::thrift::protocol::T_LIST) { { (*(this->success)).clear(); - uint32_t _size57; - ::apache::thrift::protocol::TType _etype60; - xfer += iprot->readListBegin(_etype60, _size57); - (*(this->success)).resize(_size57); - uint32_t _i61; - for (_i61 = 0; _i61 < _size57; ++_i61) + uint32_t _size59; + ::apache::thrift::protocol::TType _etype62; + xfer += iprot->readListBegin(_etype62, _size59); + (*(this->success)).resize(_size59); + uint32_t _i63; + for (_i63 = 0; _i63 < _size59; ++_i63) { - xfer += (*(this->success))[_i61].read(iprot); + xfer += (*(this->success))[_i63].read(iprot); + } + xfer += iprot->readListEnd(); + } + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 1: + if (ftype == ::apache::thrift::protocol::T_STRUCT) { + xfer += this->e.read(iprot); + this->__isset.e = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + + +MilvusService_SearchVector2_args::~MilvusService_SearchVector2_args() throw() { +} + + +uint32_t MilvusService_SearchVector2_args::read(::apache::thrift::protocol::TProtocol* iprot) { + + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 2: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->table_name); + this->__isset.table_name = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 3: + if (ftype == ::apache::thrift::protocol::T_LIST) { + { + this->query_record_array.clear(); + uint32_t _size64; + ::apache::thrift::protocol::TType _etype67; + xfer += iprot->readListBegin(_etype67, _size64); + this->query_record_array.resize(_size64); + uint32_t _i68; + for (_i68 = 0; _i68 < _size64; ++_i68) + { + xfer += this->query_record_array[_i68].read(iprot); + } + xfer += iprot->readListEnd(); + } + this->__isset.query_record_array = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 4: + if (ftype == ::apache::thrift::protocol::T_LIST) { + { + this->query_range_array.clear(); + uint32_t _size69; + ::apache::thrift::protocol::TType _etype72; + xfer += iprot->readListBegin(_etype72, _size69); + this->query_range_array.resize(_size69); + uint32_t _i73; + for (_i73 = 0; _i73 < _size69; ++_i73) + { + xfer += this->query_range_array[_i73].read(iprot); + } + xfer += iprot->readListEnd(); + } + this->__isset.query_range_array = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 5: + if (ftype == ::apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->topk); + this->__isset.topk = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t MilvusService_SearchVector2_args::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + xfer += oprot->writeStructBegin("MilvusService_SearchVector2_args"); + + xfer += oprot->writeFieldBegin("table_name", ::apache::thrift::protocol::T_STRING, 2); + xfer += oprot->writeString(this->table_name); + xfer += oprot->writeFieldEnd(); + + xfer += oprot->writeFieldBegin("query_record_array", ::apache::thrift::protocol::T_LIST, 3); + { + xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRUCT, static_cast(this->query_record_array.size())); + std::vector ::const_iterator _iter74; + for (_iter74 = this->query_record_array.begin(); _iter74 != this->query_record_array.end(); ++_iter74) + { + xfer += (*_iter74).write(oprot); + } + xfer += oprot->writeListEnd(); + } + xfer += oprot->writeFieldEnd(); + + xfer += oprot->writeFieldBegin("query_range_array", ::apache::thrift::protocol::T_LIST, 4); + { + xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRUCT, static_cast(this->query_range_array.size())); + std::vector ::const_iterator _iter75; + for (_iter75 = this->query_range_array.begin(); _iter75 != this->query_range_array.end(); ++_iter75) + { + xfer += (*_iter75).write(oprot); + } + xfer += oprot->writeListEnd(); + } + xfer += oprot->writeFieldEnd(); + + xfer += oprot->writeFieldBegin("topk", ::apache::thrift::protocol::T_I64, 5); + xfer += oprot->writeI64(this->topk); + xfer += oprot->writeFieldEnd(); + + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + + +MilvusService_SearchVector2_pargs::~MilvusService_SearchVector2_pargs() throw() { +} + + +uint32_t MilvusService_SearchVector2_pargs::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + xfer += oprot->writeStructBegin("MilvusService_SearchVector2_pargs"); + + xfer += oprot->writeFieldBegin("table_name", ::apache::thrift::protocol::T_STRING, 2); + xfer += oprot->writeString((*(this->table_name))); + xfer += oprot->writeFieldEnd(); + + xfer += oprot->writeFieldBegin("query_record_array", ::apache::thrift::protocol::T_LIST, 3); + { + xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRUCT, static_cast((*(this->query_record_array)).size())); + std::vector ::const_iterator _iter76; + for (_iter76 = (*(this->query_record_array)).begin(); _iter76 != (*(this->query_record_array)).end(); ++_iter76) + { + xfer += (*_iter76).write(oprot); + } + xfer += oprot->writeListEnd(); + } + xfer += oprot->writeFieldEnd(); + + xfer += oprot->writeFieldBegin("query_range_array", ::apache::thrift::protocol::T_LIST, 4); + { + xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRUCT, static_cast((*(this->query_range_array)).size())); + std::vector ::const_iterator _iter77; + for (_iter77 = (*(this->query_range_array)).begin(); _iter77 != (*(this->query_range_array)).end(); ++_iter77) + { + xfer += (*_iter77).write(oprot); + } + xfer += oprot->writeListEnd(); + } + xfer += oprot->writeFieldEnd(); + + xfer += oprot->writeFieldBegin("topk", ::apache::thrift::protocol::T_I64, 5); + xfer += oprot->writeI64((*(this->topk))); + xfer += oprot->writeFieldEnd(); + + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + + +MilvusService_SearchVector2_result::~MilvusService_SearchVector2_result() throw() { +} + + +uint32_t MilvusService_SearchVector2_result::read(::apache::thrift::protocol::TProtocol* iprot) { + + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == ::apache::thrift::protocol::T_LIST) { + { + this->success.clear(); + uint32_t _size78; + ::apache::thrift::protocol::TType _etype81; + xfer += iprot->readListBegin(_etype81, _size78); + this->success.resize(_size78); + uint32_t _i82; + for (_i82 = 0; _i82 < _size78; ++_i82) + { + xfer += this->success[_i82].read(iprot); + } + xfer += iprot->readListEnd(); + } + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 1: + if (ftype == ::apache::thrift::protocol::T_STRUCT) { + xfer += this->e.read(iprot); + this->__isset.e = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t MilvusService_SearchVector2_result::write(::apache::thrift::protocol::TProtocol* oprot) const { + + uint32_t xfer = 0; + + xfer += oprot->writeStructBegin("MilvusService_SearchVector2_result"); + + if (this->__isset.success) { + xfer += oprot->writeFieldBegin("success", ::apache::thrift::protocol::T_LIST, 0); + { + xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRUCT, static_cast(this->success.size())); + std::vector ::const_iterator _iter83; + for (_iter83 = this->success.begin(); _iter83 != this->success.end(); ++_iter83) + { + xfer += (*_iter83).write(oprot); + } + xfer += oprot->writeListEnd(); + } + xfer += oprot->writeFieldEnd(); + } else if (this->__isset.e) { + xfer += oprot->writeFieldBegin("e", ::apache::thrift::protocol::T_STRUCT, 1); + xfer += this->e.write(oprot); + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + + +MilvusService_SearchVector2_presult::~MilvusService_SearchVector2_presult() throw() { +} + + +uint32_t MilvusService_SearchVector2_presult::read(::apache::thrift::protocol::TProtocol* iprot) { + + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == ::apache::thrift::protocol::T_LIST) { + { + (*(this->success)).clear(); + uint32_t _size84; + ::apache::thrift::protocol::TType _etype87; + xfer += iprot->readListBegin(_etype87, _size84); + (*(this->success)).resize(_size84); + uint32_t _i88; + for (_i88 = 0; _i88 < _size84; ++_i88) + { + xfer += (*(this->success))[_i88].read(iprot); } xfer += iprot->readListEnd(); } @@ -1440,14 +1783,14 @@ uint32_t MilvusService_SearchVectorInFiles_args::read(::apache::thrift::protocol if (ftype == ::apache::thrift::protocol::T_LIST) { { this->file_id_array.clear(); - uint32_t _size62; - ::apache::thrift::protocol::TType _etype65; - xfer += iprot->readListBegin(_etype65, _size62); - this->file_id_array.resize(_size62); - uint32_t _i66; - for (_i66 = 0; _i66 < _size62; ++_i66) + uint32_t _size89; + ::apache::thrift::protocol::TType _etype92; + xfer += iprot->readListBegin(_etype92, _size89); + this->file_id_array.resize(_size89); + uint32_t _i93; + for (_i93 = 0; _i93 < _size89; ++_i93) { - xfer += iprot->readString(this->file_id_array[_i66]); + xfer += iprot->readString(this->file_id_array[_i93]); } xfer += iprot->readListEnd(); } @@ -1460,14 +1803,14 @@ uint32_t MilvusService_SearchVectorInFiles_args::read(::apache::thrift::protocol if (ftype == ::apache::thrift::protocol::T_LIST) { { this->query_record_array.clear(); - uint32_t _size67; - ::apache::thrift::protocol::TType _etype70; - xfer += iprot->readListBegin(_etype70, _size67); - this->query_record_array.resize(_size67); - uint32_t _i71; - for (_i71 = 0; _i71 < _size67; ++_i71) + uint32_t _size94; + ::apache::thrift::protocol::TType _etype97; + xfer += iprot->readListBegin(_etype97, _size94); + this->query_record_array.resize(_size94); + uint32_t _i98; + for (_i98 = 0; _i98 < _size94; ++_i98) { - xfer += this->query_record_array[_i71].read(iprot); + xfer += this->query_record_array[_i98].read(iprot); } xfer += iprot->readListEnd(); } @@ -1480,14 +1823,14 @@ uint32_t MilvusService_SearchVectorInFiles_args::read(::apache::thrift::protocol if (ftype == ::apache::thrift::protocol::T_LIST) { { this->query_range_array.clear(); - uint32_t _size72; - ::apache::thrift::protocol::TType _etype75; - xfer += iprot->readListBegin(_etype75, _size72); - this->query_range_array.resize(_size72); - uint32_t _i76; - for (_i76 = 0; _i76 < _size72; ++_i76) + uint32_t _size99; + ::apache::thrift::protocol::TType _etype102; + xfer += iprot->readListBegin(_etype102, _size99); + this->query_range_array.resize(_size99); + uint32_t _i103; + for (_i103 = 0; _i103 < _size99; ++_i103) { - xfer += this->query_range_array[_i76].read(iprot); + xfer += this->query_range_array[_i103].read(iprot); } xfer += iprot->readListEnd(); } @@ -1528,10 +1871,10 @@ uint32_t MilvusService_SearchVectorInFiles_args::write(::apache::thrift::protoco xfer += oprot->writeFieldBegin("file_id_array", ::apache::thrift::protocol::T_LIST, 3); { xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRING, static_cast(this->file_id_array.size())); - std::vector ::const_iterator _iter77; - for (_iter77 = this->file_id_array.begin(); _iter77 != this->file_id_array.end(); ++_iter77) + std::vector ::const_iterator _iter104; + for (_iter104 = this->file_id_array.begin(); _iter104 != this->file_id_array.end(); ++_iter104) { - xfer += oprot->writeString((*_iter77)); + xfer += oprot->writeString((*_iter104)); } xfer += oprot->writeListEnd(); } @@ -1540,10 +1883,10 @@ uint32_t MilvusService_SearchVectorInFiles_args::write(::apache::thrift::protoco xfer += oprot->writeFieldBegin("query_record_array", ::apache::thrift::protocol::T_LIST, 4); { xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRUCT, static_cast(this->query_record_array.size())); - std::vector ::const_iterator _iter78; - for (_iter78 = this->query_record_array.begin(); _iter78 != this->query_record_array.end(); ++_iter78) + std::vector ::const_iterator _iter105; + for (_iter105 = this->query_record_array.begin(); _iter105 != this->query_record_array.end(); ++_iter105) { - xfer += (*_iter78).write(oprot); + xfer += (*_iter105).write(oprot); } xfer += oprot->writeListEnd(); } @@ -1552,10 +1895,10 @@ uint32_t MilvusService_SearchVectorInFiles_args::write(::apache::thrift::protoco xfer += oprot->writeFieldBegin("query_range_array", ::apache::thrift::protocol::T_LIST, 5); { xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRUCT, static_cast(this->query_range_array.size())); - std::vector ::const_iterator _iter79; - for (_iter79 = this->query_range_array.begin(); _iter79 != this->query_range_array.end(); ++_iter79) + std::vector ::const_iterator _iter106; + for (_iter106 = this->query_range_array.begin(); _iter106 != this->query_range_array.end(); ++_iter106) { - xfer += (*_iter79).write(oprot); + xfer += (*_iter106).write(oprot); } xfer += oprot->writeListEnd(); } @@ -1587,10 +1930,10 @@ uint32_t MilvusService_SearchVectorInFiles_pargs::write(::apache::thrift::protoc xfer += oprot->writeFieldBegin("file_id_array", ::apache::thrift::protocol::T_LIST, 3); { xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRING, static_cast((*(this->file_id_array)).size())); - std::vector ::const_iterator _iter80; - for (_iter80 = (*(this->file_id_array)).begin(); _iter80 != (*(this->file_id_array)).end(); ++_iter80) + std::vector ::const_iterator _iter107; + for (_iter107 = (*(this->file_id_array)).begin(); _iter107 != (*(this->file_id_array)).end(); ++_iter107) { - xfer += oprot->writeString((*_iter80)); + xfer += oprot->writeString((*_iter107)); } xfer += oprot->writeListEnd(); } @@ -1599,10 +1942,10 @@ uint32_t MilvusService_SearchVectorInFiles_pargs::write(::apache::thrift::protoc xfer += oprot->writeFieldBegin("query_record_array", ::apache::thrift::protocol::T_LIST, 4); { xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRUCT, static_cast((*(this->query_record_array)).size())); - std::vector ::const_iterator _iter81; - for (_iter81 = (*(this->query_record_array)).begin(); _iter81 != (*(this->query_record_array)).end(); ++_iter81) + std::vector ::const_iterator _iter108; + for (_iter108 = (*(this->query_record_array)).begin(); _iter108 != (*(this->query_record_array)).end(); ++_iter108) { - xfer += (*_iter81).write(oprot); + xfer += (*_iter108).write(oprot); } xfer += oprot->writeListEnd(); } @@ -1611,10 +1954,10 @@ uint32_t MilvusService_SearchVectorInFiles_pargs::write(::apache::thrift::protoc xfer += oprot->writeFieldBegin("query_range_array", ::apache::thrift::protocol::T_LIST, 5); { xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRUCT, static_cast((*(this->query_range_array)).size())); - std::vector ::const_iterator _iter82; - for (_iter82 = (*(this->query_range_array)).begin(); _iter82 != (*(this->query_range_array)).end(); ++_iter82) + std::vector ::const_iterator _iter109; + for (_iter109 = (*(this->query_range_array)).begin(); _iter109 != (*(this->query_range_array)).end(); ++_iter109) { - xfer += (*_iter82).write(oprot); + xfer += (*_iter109).write(oprot); } xfer += oprot->writeListEnd(); } @@ -1659,14 +2002,14 @@ uint32_t MilvusService_SearchVectorInFiles_result::read(::apache::thrift::protoc if (ftype == ::apache::thrift::protocol::T_LIST) { { this->success.clear(); - uint32_t _size83; - ::apache::thrift::protocol::TType _etype86; - xfer += iprot->readListBegin(_etype86, _size83); - this->success.resize(_size83); - uint32_t _i87; - for (_i87 = 0; _i87 < _size83; ++_i87) + uint32_t _size110; + ::apache::thrift::protocol::TType _etype113; + xfer += iprot->readListBegin(_etype113, _size110); + this->success.resize(_size110); + uint32_t _i114; + for (_i114 = 0; _i114 < _size110; ++_i114) { - xfer += this->success[_i87].read(iprot); + xfer += this->success[_i114].read(iprot); } xfer += iprot->readListEnd(); } @@ -1705,10 +2048,10 @@ uint32_t MilvusService_SearchVectorInFiles_result::write(::apache::thrift::proto xfer += oprot->writeFieldBegin("success", ::apache::thrift::protocol::T_LIST, 0); { xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRUCT, static_cast(this->success.size())); - std::vector ::const_iterator _iter88; - for (_iter88 = this->success.begin(); _iter88 != this->success.end(); ++_iter88) + std::vector ::const_iterator _iter115; + for (_iter115 = this->success.begin(); _iter115 != this->success.end(); ++_iter115) { - xfer += (*_iter88).write(oprot); + xfer += (*_iter115).write(oprot); } xfer += oprot->writeListEnd(); } @@ -1753,14 +2096,14 @@ uint32_t MilvusService_SearchVectorInFiles_presult::read(::apache::thrift::proto if (ftype == ::apache::thrift::protocol::T_LIST) { { (*(this->success)).clear(); - uint32_t _size89; - ::apache::thrift::protocol::TType _etype92; - xfer += iprot->readListBegin(_etype92, _size89); - (*(this->success)).resize(_size89); - uint32_t _i93; - for (_i93 = 0; _i93 < _size89; ++_i93) + uint32_t _size116; + ::apache::thrift::protocol::TType _etype119; + xfer += iprot->readListBegin(_etype119, _size116); + (*(this->success)).resize(_size116); + uint32_t _i120; + for (_i120 = 0; _i120 < _size116; ++_i120) { - xfer += (*(this->success))[_i93].read(iprot); + xfer += (*(this->success))[_i120].read(iprot); } xfer += iprot->readListEnd(); } @@ -2291,14 +2634,14 @@ uint32_t MilvusService_ShowTables_result::read(::apache::thrift::protocol::TProt if (ftype == ::apache::thrift::protocol::T_LIST) { { this->success.clear(); - uint32_t _size94; - ::apache::thrift::protocol::TType _etype97; - xfer += iprot->readListBegin(_etype97, _size94); - this->success.resize(_size94); - uint32_t _i98; - for (_i98 = 0; _i98 < _size94; ++_i98) + uint32_t _size121; + ::apache::thrift::protocol::TType _etype124; + xfer += iprot->readListBegin(_etype124, _size121); + this->success.resize(_size121); + uint32_t _i125; + for (_i125 = 0; _i125 < _size121; ++_i125) { - xfer += iprot->readString(this->success[_i98]); + xfer += iprot->readString(this->success[_i125]); } xfer += iprot->readListEnd(); } @@ -2337,10 +2680,10 @@ uint32_t MilvusService_ShowTables_result::write(::apache::thrift::protocol::TPro xfer += oprot->writeFieldBegin("success", ::apache::thrift::protocol::T_LIST, 0); { xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRING, static_cast(this->success.size())); - std::vector ::const_iterator _iter99; - for (_iter99 = this->success.begin(); _iter99 != this->success.end(); ++_iter99) + std::vector ::const_iterator _iter126; + for (_iter126 = this->success.begin(); _iter126 != this->success.end(); ++_iter126) { - xfer += oprot->writeString((*_iter99)); + xfer += oprot->writeString((*_iter126)); } xfer += oprot->writeListEnd(); } @@ -2385,14 +2728,14 @@ uint32_t MilvusService_ShowTables_presult::read(::apache::thrift::protocol::TPro if (ftype == ::apache::thrift::protocol::T_LIST) { { (*(this->success)).clear(); - uint32_t _size100; - ::apache::thrift::protocol::TType _etype103; - xfer += iprot->readListBegin(_etype103, _size100); - (*(this->success)).resize(_size100); - uint32_t _i104; - for (_i104 = 0; _i104 < _size100; ++_i104) + uint32_t _size127; + ::apache::thrift::protocol::TType _etype130; + xfer += iprot->readListBegin(_etype130, _size127); + (*(this->success)).resize(_size127); + uint32_t _i131; + for (_i131 = 0; _i131 < _size127; ++_i131) { - xfer += iprot->readString((*(this->success))[_i104]); + xfer += iprot->readString((*(this->success))[_i131]); } xfer += iprot->readListEnd(); } @@ -2983,6 +3326,70 @@ void MilvusServiceClient::recv_SearchVector(std::vector & _retu throw ::apache::thrift::TApplicationException(::apache::thrift::TApplicationException::MISSING_RESULT, "SearchVector failed: unknown result"); } +void MilvusServiceClient::SearchVector2(std::vector & _return, const std::string& table_name, const std::vector & query_record_array, const std::vector & query_range_array, const int64_t topk) +{ + send_SearchVector2(table_name, query_record_array, query_range_array, topk); + recv_SearchVector2(_return); +} + +void MilvusServiceClient::send_SearchVector2(const std::string& table_name, const std::vector & query_record_array, const std::vector & query_range_array, const int64_t topk) +{ + int32_t cseqid = 0; + oprot_->writeMessageBegin("SearchVector2", ::apache::thrift::protocol::T_CALL, cseqid); + + MilvusService_SearchVector2_pargs args; + args.table_name = &table_name; + args.query_record_array = &query_record_array; + args.query_range_array = &query_range_array; + args.topk = &topk; + args.write(oprot_); + + oprot_->writeMessageEnd(); + oprot_->getTransport()->writeEnd(); + oprot_->getTransport()->flush(); +} + +void MilvusServiceClient::recv_SearchVector2(std::vector & _return) +{ + + int32_t rseqid = 0; + std::string fname; + ::apache::thrift::protocol::TMessageType mtype; + + iprot_->readMessageBegin(fname, mtype, rseqid); + if (mtype == ::apache::thrift::protocol::T_EXCEPTION) { + ::apache::thrift::TApplicationException x; + x.read(iprot_); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw x; + } + if (mtype != ::apache::thrift::protocol::T_REPLY) { + iprot_->skip(::apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + } + if (fname.compare("SearchVector2") != 0) { + iprot_->skip(::apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + } + MilvusService_SearchVector2_presult result; + result.success = &_return; + result.read(iprot_); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + + if (result.__isset.success) { + // _return pointer has now been filled + return; + } + if (result.__isset.e) { + throw result.e; + } + throw ::apache::thrift::TApplicationException(::apache::thrift::TApplicationException::MISSING_RESULT, "SearchVector2 failed: unknown result"); +} + void MilvusServiceClient::SearchVectorInFiles(std::vector & _return, const std::string& table_name, const std::vector & file_id_array, const std::vector & query_record_array, const std::vector & query_range_array, const int64_t topk) { send_SearchVectorInFiles(table_name, file_id_array, query_record_array, query_range_array, topk); @@ -3649,6 +4056,63 @@ void MilvusServiceProcessor::process_SearchVector(int32_t seqid, ::apache::thrif } } +void MilvusServiceProcessor::process_SearchVector2(int32_t seqid, ::apache::thrift::protocol::TProtocol* iprot, ::apache::thrift::protocol::TProtocol* oprot, void* callContext) +{ + void* ctx = NULL; + if (this->eventHandler_.get() != NULL) { + ctx = this->eventHandler_->getContext("MilvusService.SearchVector2", callContext); + } + ::apache::thrift::TProcessorContextFreer freer(this->eventHandler_.get(), ctx, "MilvusService.SearchVector2"); + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->preRead(ctx, "MilvusService.SearchVector2"); + } + + MilvusService_SearchVector2_args args; + args.read(iprot); + iprot->readMessageEnd(); + uint32_t bytes = iprot->getTransport()->readEnd(); + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->postRead(ctx, "MilvusService.SearchVector2", bytes); + } + + MilvusService_SearchVector2_result result; + try { + iface_->SearchVector2(result.success, args.table_name, args.query_record_array, args.query_range_array, args.topk); + result.__isset.success = true; + } catch (Exception &e) { + result.e = e; + result.__isset.e = true; + } catch (const std::exception& e) { + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->handlerError(ctx, "MilvusService.SearchVector2"); + } + + ::apache::thrift::TApplicationException x(e.what()); + oprot->writeMessageBegin("SearchVector2", ::apache::thrift::protocol::T_EXCEPTION, seqid); + x.write(oprot); + oprot->writeMessageEnd(); + oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + return; + } + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->preWrite(ctx, "MilvusService.SearchVector2"); + } + + oprot->writeMessageBegin("SearchVector2", ::apache::thrift::protocol::T_REPLY, seqid); + result.write(oprot); + oprot->writeMessageEnd(); + bytes = oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->postWrite(ctx, "MilvusService.SearchVector2", bytes); + } +} + void MilvusServiceProcessor::process_SearchVectorInFiles(int32_t seqid, ::apache::thrift::protocol::TProtocol* iprot, ::apache::thrift::protocol::TProtocol* oprot, void* callContext) { void* ctx = NULL; @@ -4455,6 +4919,97 @@ void MilvusServiceConcurrentClient::recv_SearchVector(std::vector & _return, const std::string& table_name, const std::vector & query_record_array, const std::vector & query_range_array, const int64_t topk) +{ + int32_t seqid = send_SearchVector2(table_name, query_record_array, query_range_array, topk); + recv_SearchVector2(_return, seqid); +} + +int32_t MilvusServiceConcurrentClient::send_SearchVector2(const std::string& table_name, const std::vector & query_record_array, const std::vector & query_range_array, const int64_t topk) +{ + int32_t cseqid = this->sync_.generateSeqId(); + ::apache::thrift::async::TConcurrentSendSentry sentry(&this->sync_); + oprot_->writeMessageBegin("SearchVector2", ::apache::thrift::protocol::T_CALL, cseqid); + + MilvusService_SearchVector2_pargs args; + args.table_name = &table_name; + args.query_record_array = &query_record_array; + args.query_range_array = &query_range_array; + args.topk = &topk; + args.write(oprot_); + + oprot_->writeMessageEnd(); + oprot_->getTransport()->writeEnd(); + oprot_->getTransport()->flush(); + + sentry.commit(); + return cseqid; +} + +void MilvusServiceConcurrentClient::recv_SearchVector2(std::vector & _return, const int32_t seqid) +{ + + int32_t rseqid = 0; + std::string fname; + ::apache::thrift::protocol::TMessageType mtype; + + // the read mutex gets dropped and reacquired as part of waitForWork() + // The destructor of this sentry wakes up other clients + ::apache::thrift::async::TConcurrentRecvSentry sentry(&this->sync_, seqid); + + while(true) { + if(!this->sync_.getPending(fname, mtype, rseqid)) { + iprot_->readMessageBegin(fname, mtype, rseqid); + } + if(seqid == rseqid) { + if (mtype == ::apache::thrift::protocol::T_EXCEPTION) { + ::apache::thrift::TApplicationException x; + x.read(iprot_); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + sentry.commit(); + throw x; + } + if (mtype != ::apache::thrift::protocol::T_REPLY) { + iprot_->skip(::apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + } + if (fname.compare("SearchVector2") != 0) { + iprot_->skip(::apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + + // in a bad state, don't commit + using ::apache::thrift::protocol::TProtocolException; + throw TProtocolException(TProtocolException::INVALID_DATA); + } + MilvusService_SearchVector2_presult result; + result.success = &_return; + result.read(iprot_); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + + if (result.__isset.success) { + // _return pointer has now been filled + sentry.commit(); + return; + } + if (result.__isset.e) { + sentry.commit(); + throw result.e; + } + // in a bad state, don't commit + throw ::apache::thrift::TApplicationException(::apache::thrift::TApplicationException::MISSING_RESULT, "SearchVector2 failed: unknown result"); + } + // seqid != rseqid + this->sync_.updatePending(fname, mtype, rseqid); + + // this will temporarily unlock the readMutex, and let other clients get work done + this->sync_.waitForWork(seqid); + } // end while(true) +} + void MilvusServiceConcurrentClient::SearchVectorInFiles(std::vector & _return, const std::string& table_name, const std::vector & file_id_array, const std::vector & query_record_array, const std::vector & query_range_array, const int64_t topk) { int32_t seqid = send_SearchVectorInFiles(table_name, file_id_array, query_record_array, query_range_array, topk); diff --git a/cpp/src/thrift/gen-cpp/MilvusService.h b/cpp/src/thrift/gen-cpp/MilvusService.h index 5b4204e6b8..c18a33009a 100644 --- a/cpp/src/thrift/gen-cpp/MilvusService.h +++ b/cpp/src/thrift/gen-cpp/MilvusService.h @@ -104,6 +104,25 @@ class MilvusServiceIf { */ virtual void SearchVector(std::vector & _return, const std::string& table_name, const std::vector & query_record_array, const std::vector & query_range_array, const int64_t topk) = 0; + /** + * @brief Query vector + * + * This method is used to query vector in table. + * + * @param table_name, table_name is queried. + * @param query_record_array, all vector are going to be queried. + * @param query_range_array, optional ranges for conditional search. If not specified, search whole table + * @param topk, how many similarity vectors will be searched. + * + * @return query binary result array. + * + * @param table_name + * @param query_record_array + * @param query_range_array + * @param topk + */ + virtual void SearchVector2(std::vector & _return, const std::string& table_name, const std::vector & query_record_array, const std::vector & query_range_array, const int64_t topk) = 0; + /** * @brief Internal use query interface * @@ -218,6 +237,9 @@ class MilvusServiceNull : virtual public MilvusServiceIf { void SearchVector(std::vector & /* _return */, const std::string& /* table_name */, const std::vector & /* query_record_array */, const std::vector & /* query_range_array */, const int64_t /* topk */) { return; } + void SearchVector2(std::vector & /* _return */, const std::string& /* table_name */, const std::vector & /* query_record_array */, const std::vector & /* query_range_array */, const int64_t /* topk */) { + return; + } void SearchVectorInFiles(std::vector & /* _return */, const std::string& /* table_name */, const std::vector & /* file_id_array */, const std::vector & /* query_record_array */, const std::vector & /* query_range_array */, const int64_t /* topk */) { return; } @@ -912,6 +934,139 @@ class MilvusService_SearchVector_presult { }; +typedef struct _MilvusService_SearchVector2_args__isset { + _MilvusService_SearchVector2_args__isset() : table_name(false), query_record_array(false), query_range_array(false), topk(false) {} + bool table_name :1; + bool query_record_array :1; + bool query_range_array :1; + bool topk :1; +} _MilvusService_SearchVector2_args__isset; + +class MilvusService_SearchVector2_args { + public: + + MilvusService_SearchVector2_args(const MilvusService_SearchVector2_args&); + MilvusService_SearchVector2_args& operator=(const MilvusService_SearchVector2_args&); + MilvusService_SearchVector2_args() : table_name(), topk(0) { + } + + virtual ~MilvusService_SearchVector2_args() throw(); + std::string table_name; + std::vector query_record_array; + std::vector query_range_array; + int64_t topk; + + _MilvusService_SearchVector2_args__isset __isset; + + void __set_table_name(const std::string& val); + + void __set_query_record_array(const std::vector & val); + + void __set_query_range_array(const std::vector & val); + + void __set_topk(const int64_t val); + + bool operator == (const MilvusService_SearchVector2_args & rhs) const + { + if (!(table_name == rhs.table_name)) + return false; + if (!(query_record_array == rhs.query_record_array)) + return false; + if (!(query_range_array == rhs.query_range_array)) + return false; + if (!(topk == rhs.topk)) + return false; + return true; + } + bool operator != (const MilvusService_SearchVector2_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const MilvusService_SearchVector2_args & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + + +class MilvusService_SearchVector2_pargs { + public: + + + virtual ~MilvusService_SearchVector2_pargs() throw(); + const std::string* table_name; + const std::vector * query_record_array; + const std::vector * query_range_array; + const int64_t* topk; + + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _MilvusService_SearchVector2_result__isset { + _MilvusService_SearchVector2_result__isset() : success(false), e(false) {} + bool success :1; + bool e :1; +} _MilvusService_SearchVector2_result__isset; + +class MilvusService_SearchVector2_result { + public: + + MilvusService_SearchVector2_result(const MilvusService_SearchVector2_result&); + MilvusService_SearchVector2_result& operator=(const MilvusService_SearchVector2_result&); + MilvusService_SearchVector2_result() { + } + + virtual ~MilvusService_SearchVector2_result() throw(); + std::vector success; + Exception e; + + _MilvusService_SearchVector2_result__isset __isset; + + void __set_success(const std::vector & val); + + void __set_e(const Exception& val); + + bool operator == (const MilvusService_SearchVector2_result & rhs) const + { + if (!(success == rhs.success)) + return false; + if (!(e == rhs.e)) + return false; + return true; + } + bool operator != (const MilvusService_SearchVector2_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const MilvusService_SearchVector2_result & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _MilvusService_SearchVector2_presult__isset { + _MilvusService_SearchVector2_presult__isset() : success(false), e(false) {} + bool success :1; + bool e :1; +} _MilvusService_SearchVector2_presult__isset; + +class MilvusService_SearchVector2_presult { + public: + + + virtual ~MilvusService_SearchVector2_presult() throw(); + std::vector * success; + Exception e; + + _MilvusService_SearchVector2_presult__isset __isset; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + +}; + typedef struct _MilvusService_SearchVectorInFiles_args__isset { _MilvusService_SearchVectorInFiles_args__isset() : table_name(false), file_id_array(false), query_record_array(false), query_range_array(false), topk(false) {} bool table_name :1; @@ -1531,6 +1686,9 @@ class MilvusServiceClient : virtual public MilvusServiceIf { void SearchVector(std::vector & _return, const std::string& table_name, const std::vector & query_record_array, const std::vector & query_range_array, const int64_t topk); void send_SearchVector(const std::string& table_name, const std::vector & query_record_array, const std::vector & query_range_array, const int64_t topk); void recv_SearchVector(std::vector & _return); + void SearchVector2(std::vector & _return, const std::string& table_name, const std::vector & query_record_array, const std::vector & query_range_array, const int64_t topk); + void send_SearchVector2(const std::string& table_name, const std::vector & query_record_array, const std::vector & query_range_array, const int64_t topk); + void recv_SearchVector2(std::vector & _return); void SearchVectorInFiles(std::vector & _return, const std::string& table_name, const std::vector & file_id_array, const std::vector & query_record_array, const std::vector & query_range_array, const int64_t topk); void send_SearchVectorInFiles(const std::string& table_name, const std::vector & file_id_array, const std::vector & query_record_array, const std::vector & query_range_array, const int64_t topk); void recv_SearchVectorInFiles(std::vector & _return); @@ -1567,6 +1725,7 @@ class MilvusServiceProcessor : public ::apache::thrift::TDispatchProcessor { void process_BuildIndex(int32_t seqid, ::apache::thrift::protocol::TProtocol* iprot, ::apache::thrift::protocol::TProtocol* oprot, void* callContext); void process_AddVector(int32_t seqid, ::apache::thrift::protocol::TProtocol* iprot, ::apache::thrift::protocol::TProtocol* oprot, void* callContext); void process_SearchVector(int32_t seqid, ::apache::thrift::protocol::TProtocol* iprot, ::apache::thrift::protocol::TProtocol* oprot, void* callContext); + void process_SearchVector2(int32_t seqid, ::apache::thrift::protocol::TProtocol* iprot, ::apache::thrift::protocol::TProtocol* oprot, void* callContext); void process_SearchVectorInFiles(int32_t seqid, ::apache::thrift::protocol::TProtocol* iprot, ::apache::thrift::protocol::TProtocol* oprot, void* callContext); void process_DescribeTable(int32_t seqid, ::apache::thrift::protocol::TProtocol* iprot, ::apache::thrift::protocol::TProtocol* oprot, void* callContext); void process_GetTableRowCount(int32_t seqid, ::apache::thrift::protocol::TProtocol* iprot, ::apache::thrift::protocol::TProtocol* oprot, void* callContext); @@ -1581,6 +1740,7 @@ class MilvusServiceProcessor : public ::apache::thrift::TDispatchProcessor { processMap_["BuildIndex"] = &MilvusServiceProcessor::process_BuildIndex; processMap_["AddVector"] = &MilvusServiceProcessor::process_AddVector; processMap_["SearchVector"] = &MilvusServiceProcessor::process_SearchVector; + processMap_["SearchVector2"] = &MilvusServiceProcessor::process_SearchVector2; processMap_["SearchVectorInFiles"] = &MilvusServiceProcessor::process_SearchVectorInFiles; processMap_["DescribeTable"] = &MilvusServiceProcessor::process_DescribeTable; processMap_["GetTableRowCount"] = &MilvusServiceProcessor::process_GetTableRowCount; @@ -1670,6 +1830,16 @@ class MilvusServiceMultiface : virtual public MilvusServiceIf { return; } + void SearchVector2(std::vector & _return, const std::string& table_name, const std::vector & query_record_array, const std::vector & query_range_array, const int64_t topk) { + size_t sz = ifaces_.size(); + size_t i = 0; + for (; i < (sz - 1); ++i) { + ifaces_[i]->SearchVector2(_return, table_name, query_record_array, query_range_array, topk); + } + ifaces_[i]->SearchVector2(_return, table_name, query_record_array, query_range_array, topk); + return; + } + void SearchVectorInFiles(std::vector & _return, const std::string& table_name, const std::vector & file_id_array, const std::vector & query_record_array, const std::vector & query_range_array, const int64_t topk) { size_t sz = ifaces_.size(); size_t i = 0; @@ -1767,6 +1937,9 @@ class MilvusServiceConcurrentClient : virtual public MilvusServiceIf { void SearchVector(std::vector & _return, const std::string& table_name, const std::vector & query_record_array, const std::vector & query_range_array, const int64_t topk); int32_t send_SearchVector(const std::string& table_name, const std::vector & query_record_array, const std::vector & query_range_array, const int64_t topk); void recv_SearchVector(std::vector & _return, const int32_t seqid); + void SearchVector2(std::vector & _return, const std::string& table_name, const std::vector & query_record_array, const std::vector & query_range_array, const int64_t topk); + int32_t send_SearchVector2(const std::string& table_name, const std::vector & query_record_array, const std::vector & query_range_array, const int64_t topk); + void recv_SearchVector2(std::vector & _return, const int32_t seqid); void SearchVectorInFiles(std::vector & _return, const std::string& table_name, const std::vector & file_id_array, const std::vector & query_record_array, const std::vector & query_range_array, const int64_t topk); int32_t send_SearchVectorInFiles(const std::string& table_name, const std::vector & file_id_array, const std::vector & query_record_array, const std::vector & query_range_array, const int64_t topk); void recv_SearchVectorInFiles(std::vector & _return, const int32_t seqid); diff --git a/cpp/src/thrift/gen-cpp/MilvusService_server.skeleton.cpp b/cpp/src/thrift/gen-cpp/MilvusService_server.skeleton.cpp index f22cfc2894..efa8e95034 100644 --- a/cpp/src/thrift/gen-cpp/MilvusService_server.skeleton.cpp +++ b/cpp/src/thrift/gen-cpp/MilvusService_server.skeleton.cpp @@ -120,6 +120,28 @@ class MilvusServiceHandler : virtual public MilvusServiceIf { printf("SearchVector\n"); } + /** + * @brief Query vector + * + * This method is used to query vector in table. + * + * @param table_name, table_name is queried. + * @param query_record_array, all vector are going to be queried. + * @param query_range_array, optional ranges for conditional search. If not specified, search whole table + * @param topk, how many similarity vectors will be searched. + * + * @return query binary result array. + * + * @param table_name + * @param query_record_array + * @param query_range_array + * @param topk + */ + void SearchVector2(std::vector & _return, const std::string& table_name, const std::vector & query_record_array, const std::vector & query_range_array, const int64_t topk) { + // Your implementation goes here + printf("SearchVector2\n"); + } + /** * @brief Internal use query interface * diff --git a/cpp/src/thrift/gen-cpp/milvus_types.cpp b/cpp/src/thrift/gen-cpp/milvus_types.cpp index 06923c3a1a..a1ef24de52 100644 --- a/cpp/src/thrift/gen-cpp/milvus_types.cpp +++ b/cpp/src/thrift/gen-cpp/milvus_types.cpp @@ -781,4 +781,119 @@ void TopKQueryResult::printTo(std::ostream& out) const { out << ")"; } + +TopKQueryBinResult::~TopKQueryBinResult() throw() { +} + + +void TopKQueryBinResult::__set_id_array(const std::string& val) { + this->id_array = val; +} + +void TopKQueryBinResult::__set_distance_array(const std::string& val) { + this->distance_array = val; +} +std::ostream& operator<<(std::ostream& out, const TopKQueryBinResult& obj) +{ + obj.printTo(out); + return out; +} + + +uint32_t TopKQueryBinResult::read(::apache::thrift::protocol::TProtocol* iprot) { + + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + bool isset_id_array = false; + bool isset_distance_array = false; + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readBinary(this->id_array); + isset_id_array = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readBinary(this->distance_array); + isset_distance_array = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + if (!isset_id_array) + throw TProtocolException(TProtocolException::INVALID_DATA); + if (!isset_distance_array) + throw TProtocolException(TProtocolException::INVALID_DATA); + return xfer; +} + +uint32_t TopKQueryBinResult::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + xfer += oprot->writeStructBegin("TopKQueryBinResult"); + + xfer += oprot->writeFieldBegin("id_array", ::apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeBinary(this->id_array); + xfer += oprot->writeFieldEnd(); + + xfer += oprot->writeFieldBegin("distance_array", ::apache::thrift::protocol::T_STRING, 2); + xfer += oprot->writeBinary(this->distance_array); + xfer += oprot->writeFieldEnd(); + + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +void swap(TopKQueryBinResult &a, TopKQueryBinResult &b) { + using ::std::swap; + swap(a.id_array, b.id_array); + swap(a.distance_array, b.distance_array); +} + +TopKQueryBinResult::TopKQueryBinResult(const TopKQueryBinResult& other19) { + id_array = other19.id_array; + distance_array = other19.distance_array; +} +TopKQueryBinResult& TopKQueryBinResult::operator=(const TopKQueryBinResult& other20) { + id_array = other20.id_array; + distance_array = other20.distance_array; + return *this; +} +void TopKQueryBinResult::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "TopKQueryBinResult("; + out << "id_array=" << to_string(id_array); + out << ", " << "distance_array=" << to_string(distance_array); + out << ")"; +} + }} // namespace diff --git a/cpp/src/thrift/gen-cpp/milvus_types.h b/cpp/src/thrift/gen-cpp/milvus_types.h index 63e313d197..a75d883074 100644 --- a/cpp/src/thrift/gen-cpp/milvus_types.h +++ b/cpp/src/thrift/gen-cpp/milvus_types.h @@ -63,6 +63,8 @@ class QueryResult; class TopKQueryResult; +class TopKQueryBinResult; + typedef struct _Exception__isset { _Exception__isset() : code(false), reason(false) {} bool code :1; @@ -346,6 +348,47 @@ void swap(TopKQueryResult &a, TopKQueryResult &b); std::ostream& operator<<(std::ostream& out, const TopKQueryResult& obj); + +class TopKQueryBinResult : public virtual ::apache::thrift::TBase { + public: + + TopKQueryBinResult(const TopKQueryBinResult&); + TopKQueryBinResult& operator=(const TopKQueryBinResult&); + TopKQueryBinResult() : id_array(), distance_array() { + } + + virtual ~TopKQueryBinResult() throw(); + std::string id_array; + std::string distance_array; + + void __set_id_array(const std::string& val); + + void __set_distance_array(const std::string& val); + + bool operator == (const TopKQueryBinResult & rhs) const + { + if (!(id_array == rhs.id_array)) + return false; + if (!(distance_array == rhs.distance_array)) + return false; + return true; + } + bool operator != (const TopKQueryBinResult &rhs) const { + return !(*this == rhs); + } + + bool operator < (const TopKQueryBinResult & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + + virtual void printTo(std::ostream& out) const; +}; + +void swap(TopKQueryBinResult &a, TopKQueryBinResult &b); + +std::ostream& operator<<(std::ostream& out, const TopKQueryBinResult& obj); + }} // namespace #endif diff --git a/cpp/src/thrift/milvus.thrift b/cpp/src/thrift/milvus.thrift index 001b27b04b..64f25ae387 100644 --- a/cpp/src/thrift/milvus.thrift +++ b/cpp/src/thrift/milvus.thrift @@ -84,6 +84,14 @@ struct TopKQueryResult { 1: list query_result_arrays; ///< TopK query result } +/** + * @brief TopK query binary result + */ +struct TopKQueryBinResult { + 1: required binary id_array; ///< id array, interger array + 2: required binary distance_array; ///< distance array, double array +} + service MilvusService { /** * @brief Create table method @@ -158,6 +166,23 @@ service MilvusService { 4: list query_range_array, 5: i64 topk) throws(1: Exception e); + /** + * @brief Query vector + * + * This method is used to query vector in table. + * + * @param table_name, table_name is queried. + * @param query_record_array, all vector are going to be queried. + * @param query_range_array, optional ranges for conditional search. If not specified, search whole table + * @param topk, how many similarity vectors will be searched. + * + * @return query binary result array. + */ + list SearchVector2(2: string table_name, + 3: list query_record_array, + 4: list query_range_array, + 5: i64 topk) throws(1: Exception e); + /** * @brief Internal use query interface * diff --git a/cpp/src/utils/ValidationUtil.cpp b/cpp/src/utils/ValidationUtil.cpp index 65cd81e670..53f00a4fc7 100644 --- a/cpp/src/utils/ValidationUtil.cpp +++ b/cpp/src/utils/ValidationUtil.cpp @@ -56,17 +56,13 @@ ValidateTableDimension(int64_t dimension) { ServerError ValidateTableIndexType(int32_t index_type) { - auto engine_type = engine::EngineType(index_type); - switch (engine_type) { - case engine::EngineType::FAISS_IDMAP: - case engine::EngineType::FAISS_IVFFLAT: { - SERVER_LOG_DEBUG << "Index type: " << index_type; - return SERVER_SUCCESS; - } - default: { - return SERVER_INVALID_INDEX_TYPE; - } + int engine_type = (int)engine::EngineType(index_type); + if(engine_type <= 0 || engine_type > (int)engine::EngineType::MAX_VALUE) { + return SERVER_INVALID_INDEX_TYPE; } + + SERVER_LOG_DEBUG << "Index type: " << index_type; + return SERVER_SUCCESS; } } diff --git a/cpp/src/wrapper/Operand.cpp b/cpp/src/wrapper/Operand.cpp index 62a863ae0e..49d007ba2a 100644 --- a/cpp/src/wrapper/Operand.cpp +++ b/cpp/src/wrapper/Operand.cpp @@ -28,6 +28,15 @@ IndexType resolveIndexType(const string &index_type) { return IndexType::Invalid_Option; } +int CalcBacketCount(int nb, size_t nlist) { + int backet_count = int(nb / 1000000.0 * nlist); + if(backet_count == 0) { + backet_count = 1; //avoid faiss rash + } + + return backet_count; +} + // nb at least 100 string Operand::get_index_type(const int &nb) { if (!index_str.empty()) { return index_str; } @@ -45,7 +54,7 @@ string Operand::get_index_type(const int &nb) { size_t nlist = engine_config.GetInt32Value(CONFIG_NLIST, 16384); index_str += (ncent != 0 ? index_type + std::to_string(ncent) : - index_type + std::to_string(int(nb / 1000000.0 * nlist))); + index_type + std::to_string(CalcBacketCount(nb, nlist))); // std::cout<<"nlist = "<BuildIndex(TABLE_NAME); // wait until build index finish - engine::QueryResults results; - stat = db_->Query(TABLE_NAME, k, nq, xq.data(), results); - ASSERT_STATS(stat); + { + engine::QueryResults results; + stat = db_->Query(TABLE_NAME, k, nq, xq.data(), results); + ASSERT_STATS(stat); + } + + {//search by specify index file + engine::meta::DatesT dates; + std::vector file_ids = {"1", "2", "3", "4"}; + engine::QueryResults results; + stat = db_->Query(TABLE_NAME, file_ids, k, nq, xq.data(), dates, results); + ASSERT_STATS(stat); + } // TODO(linxj): add groundTruth assert }; diff --git a/cpp/unittest/db/mem_test.cpp b/cpp/unittest/db/mem_test.cpp index 2f6952c79d..17d87030cd 100644 --- a/cpp/unittest/db/mem_test.cpp +++ b/cpp/unittest/db/mem_test.cpp @@ -273,7 +273,7 @@ TEST_F(NewMemManagerTest, INSERT_TEST) { int insert_loop = 20; for (int i = 0; i < insert_loop; ++i) { - int64_t nb = 409600; + int64_t nb = 40960; std::vector xb; BuildVectors(nb, xb); engine::IDNumbers vector_ids; @@ -308,7 +308,7 @@ TEST_F(NewMemManagerTest, CONCURRENT_INSERT_SEARCH_TEST) { engine::IDNumbers vector_ids; engine::IDNumbers target_ids; - int64_t nb = 409600; + int64_t nb = 40960; std::vector xb; BuildVectors(nb, xb); diff --git a/cpp/unittest/db/misc_test.cpp b/cpp/unittest/db/misc_test.cpp index 4356746fc2..9dd07fac8d 100644 --- a/cpp/unittest/db/misc_test.cpp +++ b/cpp/unittest/db/misc_test.cpp @@ -14,6 +14,7 @@ #include "db/Options.h" #include "db/DBMetaImpl.h" #include "db/EngineFactory.h" +#include "db/Utils.h" #include @@ -134,4 +135,32 @@ TEST(DBMiscTest, META_TEST) { int delta = 10; engine::meta::DateT dt = impl.GetDate(tt, delta); ASSERT_GT(dt, 0); +} + +TEST(DBMiscTest, UTILS_TEST) { + engine::DBMetaOptions options; + options.path = "/tmp/milvus_test/main"; + options.slave_paths.push_back("/tmp/milvus_test/slave_1"); + options.slave_paths.push_back("/tmp/milvus_test/slave_2"); + + const std::string TABLE_NAME = "test_tbl"; + auto status = engine::utils::CreateTablePath(options, TABLE_NAME); + ASSERT_TRUE(status.ok()); + ASSERT_TRUE(boost::filesystem::exists(options.path)); + for(auto& path : options.slave_paths) { + ASSERT_TRUE(boost::filesystem::exists(path)); + } + + engine::meta::TableFileSchema file; + file.id_ = 50; + file.table_id_ = TABLE_NAME; + file.file_type_ = 3; + file.date_ = 155000; + status = engine::utils::GetTableFilePath(options, file); + ASSERT_FALSE(status.ok()); + ASSERT_TRUE(file.location_.empty()); + + status = engine::utils::DeleteTablePath(options, TABLE_NAME); + ASSERT_TRUE(status.ok()); + } \ No newline at end of file diff --git a/cpp/unittest/faiss_wrapper/CMakeLists.txt b/cpp/unittest/faiss_wrapper/CMakeLists.txt index ff2535e3fd..c439250544 100644 --- a/cpp/unittest/faiss_wrapper/CMakeLists.txt +++ b/cpp/unittest/faiss_wrapper/CMakeLists.txt @@ -35,6 +35,10 @@ set(wrapper_libs zstd lz4 ) +if(${BUILD_FAISS_WITH_MKL} STREQUAL "true") + set(wrapper_libs ${wrapper_libs} ${MKL_LIBS} ${MKL_LIBS}) +endif() + target_link_libraries(wrapper_test ${wrapper_libs} ${unittest_libs}) set(topk_test_src diff --git a/cpp/unittest/metrics/CMakeLists.txt b/cpp/unittest/metrics/CMakeLists.txt index 513b37b8c2..418544d0ca 100644 --- a/cpp/unittest/metrics/CMakeLists.txt +++ b/cpp/unittest/metrics/CMakeLists.txt @@ -10,8 +10,6 @@ include_directories(../../src) - - aux_source_directory(../../src/db db_srcs) aux_source_directory(../../src/config config_files) aux_source_directory(../../src/cache cache_srcs) @@ -33,21 +31,10 @@ include_directories(../../third_party/build/include) link_directories(../../third_party/build/lib) include_directories(/usr/local/cuda/include) link_directories("/usr/local/cuda/lib64") -#include_directories(../db/utils.h) include_directories(../../src/metrics) include_directories(/usr/include/mysql) -#set(metrics_src_files -# ../../src/metrics/Metrics.cpp -# ../../src/metrics/Metrics.h -# ../../src/metrics/PrometheusMetrics.cpp -# ../../src/metrics/MetricBase.h -# ../../src/server/ServerConfig.cpp -# ../../src/utils/CommonUtil.cpp -# ../../src/utils/TimeRecorder.cpp -# ) - set(count_test_src ${config_files} ${cache_srcs} @@ -77,5 +64,8 @@ target_link_libraries(metrics_test mysqlpp ${unittest_libs} ) +if(${BUILD_FAISS_WITH_MKL} STREQUAL "true") + target_link_libraries(metrics_test ${MKL_LIBS} ${MKL_LIBS}) +endif() install(TARGETS metrics_test DESTINATION bin) \ No newline at end of file diff --git a/cpp/unittest/server/CMakeLists.txt b/cpp/unittest/server/CMakeLists.txt index e49aed500c..40f5b10128 100644 --- a/cpp/unittest/server/CMakeLists.txt +++ b/cpp/unittest/server/CMakeLists.txt @@ -48,6 +48,10 @@ set(require_libs pthread ) +if(${BUILD_FAISS_WITH_MKL} STREQUAL "true") + set(require_libs ${require_libs} ${MKL_LIBS} ${MKL_LIBS}) +endif() + target_link_libraries(server_test ${require_libs} ${cuda_library} diff --git a/cpp/unittest/utils/ValidationUtilTest.cpp b/cpp/unittest/utils/ValidationUtilTest.cpp index 095614e325..38fc63a10d 100644 --- a/cpp/unittest/utils/ValidationUtilTest.cpp +++ b/cpp/unittest/utils/ValidationUtilTest.cpp @@ -7,9 +7,11 @@ #include "utils/ValidationUtil.h" #include "utils/Error.h" +#include "db/ExecutionEngine.h" #include +using namespace zilliz::milvus; using namespace zilliz::milvus::server; TEST(ValidationUtilTest, TableNameTest) { @@ -53,9 +55,9 @@ TEST(ValidationUtilTest, TableDimensionTest) { } TEST(ValidationUtilTest, TableIndexTypeTest) { - ASSERT_EQ(ValidateTableIndexType(0), SERVER_INVALID_INDEX_TYPE); - ASSERT_EQ(ValidateTableIndexType(1), SERVER_SUCCESS); - ASSERT_EQ(ValidateTableIndexType(2), SERVER_SUCCESS); - ASSERT_EQ(ValidateTableIndexType(3), SERVER_INVALID_INDEX_TYPE); - ASSERT_EQ(ValidateTableIndexType(4), SERVER_INVALID_INDEX_TYPE); + ASSERT_EQ(ValidateTableIndexType((int)engine::EngineType::INVALID), SERVER_INVALID_INDEX_TYPE); + for(int i = 1; i <= (int)engine::EngineType::MAX_VALUE; i++) { + ASSERT_EQ(ValidateTableIndexType(i), SERVER_SUCCESS); + } + ASSERT_EQ(ValidateTableIndexType((int)engine::EngineType::MAX_VALUE + 1), SERVER_INVALID_INDEX_TYPE); }