├── tests ├── cmake │ ├── pmreorder.conf │ └── run_default.cmake ├── true.cmake ├── compatibility │ ├── README.md │ ├── CMakeLists.txt │ └── cmap.sh ├── engine_scenarios │ ├── pmemobj │ │ ├── mock_tx_alloc.h │ │ ├── error_handling_defrag.cc │ │ ├── put_get_std_map_defrag.cc │ │ ├── error_handling_tx_path.cc │ │ ├── mock_tx_alloc.cc │ │ ├── error_handling_tx_oid.cc │ │ ├── put_get_std_map_oid.cc │ │ ├── error_handling_tx.hpp │ │ ├── create_or_error_if_exists.cc │ │ └── error_handling_tx_oom.cc │ ├── transaction │ │ ├── not_supported.cc │ │ └── put_pmreorder.cc │ ├── all │ │ ├── put_get_std_map.cc │ │ ├── iterator_not_supported.cc │ │ ├── error_handling_oom.cc │ │ ├── put_get_remove_long_key.cc │ │ ├── put_get_remove_params.cc │ │ ├── open.cc │ │ └── iterate.cc │ ├── persistent │ │ ├── put_get_std_map_multiple_reopen.cc │ │ ├── not_found_verify.cc │ │ ├── put_verify_desc_params.cc │ │ ├── put_verify_asc_params.cc │ │ ├── put_remove_verify.cc │ │ ├── overwrite_verify.cc │ │ └── put_verify.cc │ ├── pmreorder │ │ ├── recover.cc │ │ ├── insert.cc │ │ └── erase.cc │ ├── put_get_std_map.hpp │ ├── iterator.hpp │ └── concurrent │ │ └── put_get_remove_single_op_params.cc ├── engines │ ├── pmemobj_based │ │ ├── pmreorder │ │ │ ├── pmreorder.conf │ │ │ ├── erase.cmake │ │ │ ├── insert.cmake │ │ │ ├── iterator.cmake │ │ │ └── recover.cmake │ │ ├── pmemobj │ │ │ ├── error_handling_create.cmake │ │ │ ├── create_if_missing.cmake │ │ │ ├── put_get_std_map_create_or_error_if_exists.cmake │ │ │ ├── error_handling_tx_oid.cmake │ │ │ ├── put_get_std_map_oid.cmake │ │ │ └── error_handling_tx_path.cmake │ │ ├── helpers.cmake │ │ ├── default.cmake │ │ ├── default_no_config.cmake │ │ └── persistent │ │ │ └── insert_check.cmake │ ├── dram │ │ └── default.cmake │ ├── blackhole │ │ └── default.cmake │ └── memkind_based │ │ ├── memkind │ │ └── error_handling.cmake │ │ ├── default_no_config.cmake │ │ └── default.cmake ├── memcheck-stdcpp.supp ├── common │ ├── test_backtrace.h │ └── check_is_pmem.cpp ├── drd.supp ├── memcheck-libunwind.supp ├── memcheck-ndctl.supp ├── ld.supp ├── config │ ├── deprecated_config.cc │ └── deprecated_config.c ├── error_msg_test.cc ├── comparator │ ├── basic_persistent.c │ ├── basic.c │ ├── default_reopen.cc │ └── default_reopen.c ├── README.md └── wrong_engine_name_test.cc ├── .gitattributes ├── doc ├── architecture.png ├── ENGINES-testing.md ├── RELEASE_STEPS.md └── libpmemkv_json_config.3.md ├── .gitignore ├── src ├── valgrind │ └── README ├── libpmemkv_json_config.map ├── engines │ ├── vcmap.cc │ ├── vcmap.h │ └── blackhole.h ├── engines-testing │ ├── dram_vcmap.cc │ └── dram_vcmap.h ├── libpmemkv_json_config.h ├── out.h ├── out.cc ├── comparator │ ├── volatile_comparator.h │ ├── pmemobj_comparator.h │ └── comparator.h ├── README.md ├── fast_hash.h ├── iterator.cc ├── exceptions.h ├── iterator.h ├── transaction.h ├── fast_hash.cc └── libpmemkv.map ├── examples ├── example.poolset ├── pmemkv_basic_c │ └── CMakeLists.txt ├── pmemkv_fill_cpp │ └── CMakeLists.txt ├── pmemkv_basic_cpp │ └── CMakeLists.txt ├── pmemkv_open_cpp │ └── CMakeLists.txt ├── pmemkv_comparator_c │ └── CMakeLists.txt ├── pmemkv_iterator_c │ └── CMakeLists.txt ├── pmemkv_comparator_cpp │ ├── CMakeLists.txt │ └── pmemkv_comparator.cpp ├── pmemkv_transaction_c │ └── CMakeLists.txt ├── pmemkv_iterator_cpp │ └── CMakeLists.txt ├── pmemkv_transaction_cpp │ ├── CMakeLists.txt │ └── pmemkv_transaction.cpp ├── pmemkv_pmemobj_cpp │ └── CMakeLists.txt └── pmemkv_config_c │ ├── CMakeLists.txt │ └── pmemkv_basic_config.c ├── utils ├── check_license │ └── file-exceptions.sh ├── jenkins │ └── scripts │ │ └── removeNamespaces.sh ├── docker │ ├── images │ │ ├── install-rapidjson.sh │ │ ├── install-memkind.sh │ │ ├── download-scripts.sh │ │ ├── install-valgrind.sh │ │ ├── README.md │ │ ├── build-image.sh │ │ ├── install-pmdk.sh │ │ ├── install-libndctl.sh │ │ ├── install-libpmemobj-cpp.sh │ │ ├── 0001-fix-generating-gcov-files-and-turn-off-verbose-log.patch │ │ ├── push-image.sh │ │ ├── Dockerfile.fedora-rawhide │ │ ├── Dockerfile.ubuntu-20.04_bindings │ │ ├── Dockerfile.ubuntu-devel │ │ ├── Dockerfile.debian-latest │ │ ├── Dockerfile.debian-testing │ │ ├── Dockerfile.debian-unstable │ │ ├── Dockerfile.ubuntu-21.04 │ │ ├── Dockerfile.fedora-33 │ │ └── Dockerfile.fedora-34 │ ├── 0001-travis-fix-travisci_build_coverity_scan.sh.patch │ ├── run-coverity.sh │ └── run-compatibility.sh ├── md2man │ ├── default.man │ └── md2man.sh └── cppstyle ├── codecov.yml ├── libpmemkv.pc.in ├── .github ├── ISSUE_TEMPLATE │ ├── feature.md │ ├── question.md │ └── bug_report.md └── workflows │ ├── coverity.yml │ ├── weekly.yml │ └── nightly.yml ├── libpmemkv_json_config.pc.in ├── cmake ├── libpmemobj++.cmake ├── FindLIBPMEM.cmake ├── FindLIBPMEMOBJ.cmake ├── rapidjson.cmake ├── cmake_uninstall.cmake.in ├── memkind.cmake ├── tbb.cmake └── packages.cmake ├── .clang-format └── LICENSE /tests/cmake/pmreorder.conf: -------------------------------------------------------------------------------- 1 | { 2 | "no_reorder" : "NoReorderNoCheck" 3 | } 4 | 5 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | *.jpg binary 3 | *.png binary 4 | *.gif binary 5 | -------------------------------------------------------------------------------- /doc/architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pmem/pmemkv/HEAD/doc/architecture.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .* 2 | !.gitignore 3 | !.gitattributes 4 | !.github/ 5 | !.clang-format 6 | *.d 7 | build/ 8 | *~ 9 | -------------------------------------------------------------------------------- /src/valgrind/README: -------------------------------------------------------------------------------- 1 | Files in this directory were imported from Valgrind 3.14: 2 | https://github.com/pmem/valgrind 3 | -------------------------------------------------------------------------------- /examples/example.poolset: -------------------------------------------------------------------------------- 1 | PMEMPOOLSET 2 | 100M /dev/shm/pmemkv_open_ex_pool.part0 3 | 100M /dev/shm/pmemkv_open_ex_pool.part1 4 | -------------------------------------------------------------------------------- /tests/true.cmake: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2020, Intel Corporation 3 | 4 | # true.cmake - cmake script which always succeeds 5 | 6 | return() 7 | -------------------------------------------------------------------------------- /tests/compatibility/README.md: -------------------------------------------------------------------------------- 1 | This folder contains tests which can be used to test compatibility between different 2 | pmemkv versions. For usage, see ../../utils/docker/run-compatibility.sh 3 | -------------------------------------------------------------------------------- /tests/engine_scenarios/pmemobj/mock_tx_alloc.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2017-2020, Intel Corporation */ 3 | 4 | #pragma once 5 | 6 | extern thread_local bool tx_alloc_should_fail; 7 | -------------------------------------------------------------------------------- /tests/engines/pmemobj_based/pmreorder/pmreorder.conf: -------------------------------------------------------------------------------- 1 | { 2 | "pmemobj_open" : "NoReorderNoCheck", 3 | "pmemobj_close" : "NoReorderNoCheck", 4 | "pmemobj_alloc" : "NoReorderNoCheck", 5 | "pmemobj_xalloc" : "NoReorderNoCheck" 6 | } 7 | -------------------------------------------------------------------------------- /tests/cmake/run_default.cmake: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2019-2020, Intel Corporation 3 | 4 | include(${PARENT_SRC_DIR}/helpers.cmake) 5 | 6 | setup() 7 | 8 | execute(${TEST_EXECUTABLE} ${DIR}/testfile) 9 | 10 | finish() 11 | -------------------------------------------------------------------------------- /utils/check_license/file-exceptions.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | # Copyright 2016-2021, Intel Corporation 4 | # 5 | 6 | # file-exceptions.sh - filter out files not checked for copyright and license 7 | 8 | grep -v -E -e 'src/valgrind|src/fast_hash.*' 9 | -------------------------------------------------------------------------------- /tests/engines/dram/default.cmake: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2021, Intel Corporation 3 | 4 | include(${PARENT_SRC_DIR}/helpers.cmake) 5 | 6 | setup() 7 | 8 | make_config({}) 9 | execute(${TEST_EXECUTABLE} ${ENGINE} ${CONFIG} ${PARAMS}) 10 | 11 | finish() 12 | -------------------------------------------------------------------------------- /tests/engines/blackhole/default.cmake: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2021, Intel Corporation 3 | 4 | include(${PARENT_SRC_DIR}/helpers.cmake) 5 | 6 | setup() 7 | 8 | make_config({}) 9 | execute(${TEST_EXECUTABLE} ${ENGINE} ${CONFIG} ${PARAMS}) 10 | 11 | finish() 12 | -------------------------------------------------------------------------------- /tests/engines/memkind_based/memkind/error_handling.cmake: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2020-2021, Intel Corporation 3 | 4 | include(${PARENT_SRC_DIR}/helpers.cmake) 5 | 6 | setup() 7 | 8 | execute(${TEST_EXECUTABLE} ${ENGINE} ${DIR}/nope/nope ${DIR} ${PARAMS}) 9 | 10 | finish() 11 | -------------------------------------------------------------------------------- /tests/engines/pmemobj_based/pmemobj/error_handling_create.cmake: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2020, Intel Corporation 3 | 4 | include(${PARENT_SRC_DIR}/helpers.cmake) 5 | 6 | setup() 7 | 8 | execute(${TEST_EXECUTABLE} ${ENGINE} ${DIR}/testfile ${DIR}/nope/nope) 9 | 10 | finish() 11 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | coverage: 2 | status: 3 | project: 4 | default: 5 | threshold: 0.2 6 | 7 | ignore: 8 | - doc/ 9 | - examples/ 10 | - utils/ 11 | - src/valgrind/ 12 | - tests/ 13 | 14 | comment: 15 | layout: "diff, files" 16 | behavior: default 17 | require_changes: yes 18 | -------------------------------------------------------------------------------- /tests/engines/memkind_based/default_no_config.cmake: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2020-2021, Intel Corporation 3 | 4 | include(${PARENT_SRC_DIR}/helpers.cmake) 5 | 6 | setup() 7 | 8 | set(PATH "${DIR}") 9 | execute(${TEST_EXECUTABLE} ${ENGINE} ${PATH} ${DB_SIZE} ${PARAMS}) 10 | 11 | finish() 12 | -------------------------------------------------------------------------------- /tests/engines/memkind_based/default.cmake: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2020, Intel Corporation 3 | 4 | include(${PARENT_SRC_DIR}/helpers.cmake) 5 | 6 | setup() 7 | 8 | make_config({"path":"${DIR}","size":${DB_SIZE}}) 9 | execute(${TEST_EXECUTABLE} ${ENGINE} ${CONFIG} ${PARAMS}) 10 | 11 | finish() 12 | -------------------------------------------------------------------------------- /src/libpmemkv_json_config.map: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2019, Intel Corporation 3 | # 4 | # 5 | # src/libpmemkv_json_config.map -- linker map file for libpmemkv_json_config 6 | # 7 | LIBPMEMKV_JSON_CONFIG_1.0 { 8 | global: 9 | pmemkv_config_from_json; 10 | pmemkv_config_from_json_errormsg; 11 | local: 12 | *; 13 | }; 14 | -------------------------------------------------------------------------------- /tests/engines/pmemobj_based/helpers.cmake: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2020, Intel Corporation 3 | 4 | # 5 | # helpers.cmake - helper functions for tests' (cmake) scripts (pmemobj_based engines only) 6 | # 7 | 8 | set(LAYOUT "pmemkv") 9 | if (NOT ${ENGINE} STREQUAL "cmap") 10 | string(CONCAT LAYOUT "pmemkv_" ${ENGINE}) 11 | endif() 12 | -------------------------------------------------------------------------------- /tests/memcheck-stdcpp.supp: -------------------------------------------------------------------------------- 1 | { 2 | https://bugs.kde.org/show_bug.cgi?id=345307, https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65434, https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64535 3 | Memcheck:Leak 4 | match-leak-kinds: reachable 5 | fun:malloc 6 | obj:*/libstdc++.so.* 7 | fun:call_init.part.0 8 | ... 9 | fun:_dl_init 10 | obj:*/ld-*.so 11 | } 12 | -------------------------------------------------------------------------------- /tests/engines/pmemobj_based/pmemobj/create_if_missing.cmake: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2020-2021, Intel Corporation 3 | 4 | include(${PARENT_SRC_DIR}/helpers.cmake) 5 | 6 | setup() 7 | 8 | make_config({"path":"${DIR}/testfile","create_if_missing":1,"size":83886080}) #80MB 9 | execute(${TEST_EXECUTABLE} ${ENGINE} ${CONFIG} ${PARAMS}) 10 | 11 | finish() 12 | -------------------------------------------------------------------------------- /tests/engines/pmemobj_based/pmemobj/put_get_std_map_create_or_error_if_exists.cmake: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2020-2021, Intel Corporation 3 | 4 | include(${PARENT_SRC_DIR}/helpers.cmake) 5 | 6 | setup() 7 | 8 | make_config({"path":"${DIR}/testfile","create_or_error_if_exists":1,"size":838860800}) #80MB 9 | execute(${TEST_EXECUTABLE} ${ENGINE} ${CONFIG} ${PARAMS}) 10 | 11 | finish() 12 | -------------------------------------------------------------------------------- /tests/common/test_backtrace.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2015-2020, Intel Corporation */ 3 | 4 | #ifndef TEST_BACKTRACE_H 5 | #define TEST_BACKTRACE_H 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | void test_dump_backtrace(void); 12 | void test_sighandler(int sig); 13 | void test_register_sighandlers(void); 14 | 15 | #ifdef __cplusplus 16 | } 17 | #endif 18 | #endif 19 | -------------------------------------------------------------------------------- /tests/engines/pmemobj_based/pmemobj/error_handling_tx_oid.cmake: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2020, Intel Corporation 3 | 4 | include(${PARENT_SRC_DIR}/helpers.cmake) 5 | include(${PARENT_SRC_DIR}/engines/pmemobj_based/helpers.cmake) 6 | 7 | setup() 8 | 9 | pmempool_execute(create -l ${LAYOUT} -s 100M obj ${DIR}/testfile) 10 | execute(${TEST_EXECUTABLE} ${ENGINE} ${DIR}/testfile) 11 | 12 | finish() 13 | -------------------------------------------------------------------------------- /tests/engines/pmemobj_based/pmemobj/put_get_std_map_oid.cmake: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2020, Intel Corporation 3 | 4 | include(${PARENT_SRC_DIR}/helpers.cmake) 5 | include(${PARENT_SRC_DIR}/engines/pmemobj_based/helpers.cmake) 6 | 7 | setup() 8 | 9 | pmempool_execute(create -l ${LAYOUT} -s ${DB_SIZE} obj ${DIR}/testfile) 10 | execute(${TEST_EXECUTABLE} ${ENGINE} ${DIR}/testfile ${PARAMS}) 11 | 12 | finish() 13 | -------------------------------------------------------------------------------- /libpmemkv.pc.in: -------------------------------------------------------------------------------- 1 | version=@VERSION@ 2 | prefix=@CMAKE_INSTALL_PREFIX@ 3 | libdir=@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@ 4 | includedir=@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_INCLUDEDIR@ 5 | 6 | Name: libpmemkv 7 | Description: libpmemkv - Key/Value Datastore for Persistent Memory 8 | Version: ${version} 9 | URL: https://github.com/pmem/pmemkv 10 | Requires.private: @PKG_CONFIG_REQUIRES@ 11 | Libs: -L${libdir} -lpmemkv 12 | Cflags: -I${includedir} 13 | -------------------------------------------------------------------------------- /src/engines/vcmap.cc: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2017-2021, Intel Corporation */ 3 | 4 | #include "vcmap.h" 5 | 6 | namespace pmem 7 | { 8 | namespace kv 9 | { 10 | 11 | template <> 12 | std::string vcmap::name() 13 | { 14 | return "vcmap"; 15 | } 16 | 17 | static factory_registerer 18 | register_vcmap(std::unique_ptr(new vcmap_factory)); 19 | 20 | } // namespace kv 21 | } // namespace pmem 22 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature 3 | about: Request a feature 4 | labels: "Type: Feature" 5 | --- 6 | # FEAT: 7 | 8 | ## Rationale 9 | 10 | 11 | 12 | ## Description 13 | 14 | 15 | 16 | ## API Changes 17 | 18 | 19 | 20 | ## Implementation details 21 | 22 | 23 | 24 | ## Meta 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/engines-testing/dram_vcmap.cc: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2021, Intel Corporation */ 3 | 4 | #include "dram_vcmap.h" 5 | 6 | namespace pmem 7 | { 8 | namespace kv 9 | { 10 | 11 | template<> 12 | std::string dram_vcmap::name() { 13 | return "dram_vcmap"; 14 | } 15 | 16 | static factory_registerer register_dram_vcmap( 17 | std::unique_ptr(new dram_vcmap_factory)); 18 | 19 | } // namespace kv 20 | } // namespace pmem 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/question.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Question 3 | about: Do you have question regarding pmemkv? Don't hesitate to ask. 4 | labels: "Type: Question" 5 | --- 6 | # QUESTION: 7 | 8 | ## Details 9 | 10 | 11 | 12 | 16 | -------------------------------------------------------------------------------- /libpmemkv_json_config.pc.in: -------------------------------------------------------------------------------- 1 | version=@VERSION@ 2 | prefix=@CMAKE_INSTALL_PREFIX@ 3 | libdir=@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@ 4 | includedir=@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_INCLUDEDIR@ 5 | 6 | Name: libpmemkv_json_config 7 | Description: libpmemkv_json_config - helper library for pmemkv 8 | Version: ${version} 9 | URL: https://github.com/pmem/pmemkv 10 | Requires: libpmemkv 11 | Requires.private: RapidJSON 12 | Libs: -L${libdir} -lpmemkv_json_config 13 | Cflags: -I${includedir} 14 | -------------------------------------------------------------------------------- /examples/pmemkv_basic_c/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2019-2020, Intel Corporation 3 | 4 | cmake_minimum_required(VERSION 3.3) 5 | project(pmemkv_basic C) 6 | 7 | find_package(PkgConfig REQUIRED) 8 | pkg_check_modules(LIBPMEMKV REQUIRED libpmemkv) 9 | 10 | include_directories(${LIBPMEMKV_INCLUDE_DIRS}) 11 | link_directories(${LIBPMEMKV_LIBRARY_DIRS}) 12 | add_executable(pmemkv_basic_c pmemkv_basic.c) 13 | target_link_libraries(pmemkv_basic_c ${LIBPMEMKV_LIBRARIES}) 14 | -------------------------------------------------------------------------------- /examples/pmemkv_fill_cpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2021, Intel Corporation 3 | 4 | cmake_minimum_required(VERSION 3.3) 5 | project(pmemkv_basic CXX) 6 | 7 | find_package(PkgConfig REQUIRED) 8 | pkg_check_modules(LIBPMEMKV REQUIRED libpmemkv) 9 | 10 | include_directories(${LIBPMEMKV_INCLUDE_DIRS}) 11 | link_directories(${LIBPMEMKV_LIBRARY_DIRS}) 12 | add_executable(pmemkv_fill_cpp pmemkv_fill.cpp) 13 | target_link_libraries(pmemkv_fill_cpp ${LIBPMEMKV_LIBRARIES}) 14 | -------------------------------------------------------------------------------- /examples/pmemkv_basic_cpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2019-2020, Intel Corporation 3 | 4 | cmake_minimum_required(VERSION 3.3) 5 | project(pmemkv_basic CXX) 6 | 7 | find_package(PkgConfig REQUIRED) 8 | pkg_check_modules(LIBPMEMKV REQUIRED libpmemkv) 9 | 10 | include_directories(${LIBPMEMKV_INCLUDE_DIRS}) 11 | link_directories(${LIBPMEMKV_LIBRARY_DIRS}) 12 | add_executable(pmemkv_basic_cpp pmemkv_basic.cpp) 13 | target_link_libraries(pmemkv_basic_cpp ${LIBPMEMKV_LIBRARIES}) 14 | -------------------------------------------------------------------------------- /examples/pmemkv_open_cpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2019-2020, Intel Corporation 3 | 4 | cmake_minimum_required(VERSION 3.3) 5 | project(pmemkv_open_cpp CXX) 6 | 7 | find_package(PkgConfig REQUIRED) 8 | pkg_check_modules(LIBPMEMKV REQUIRED libpmemkv) 9 | 10 | include_directories(${LIBPMEMKV_INCLUDE_DIRS}) 11 | link_directories(${LIBPMEMKV_LIBRARY_DIRS}) 12 | add_executable(pmemkv_open_cpp pmemkv_open.cpp) 13 | target_link_libraries(pmemkv_open_cpp ${LIBPMEMKV_LIBRARIES}) 14 | -------------------------------------------------------------------------------- /src/libpmemkv_json_config.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2019, Intel Corporation */ 3 | 4 | #ifndef LIBPMEMKV_JSON_H 5 | #define LIBPMEMKV_JSON_H 6 | 7 | #include "libpmemkv.h" 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | int pmemkv_config_from_json(pmemkv_config *config, const char *jsonconfig); 14 | const char *pmemkv_config_from_json_errormsg(void); 15 | 16 | #ifdef __cplusplus 17 | } /* end extern "C" */ 18 | #endif 19 | 20 | #endif /* LIBPMEMKV_JSON_H */ 21 | -------------------------------------------------------------------------------- /examples/pmemkv_comparator_c/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2020, Intel Corporation 3 | 4 | cmake_minimum_required(VERSION 3.3) 5 | project(pmemkv_basic C) 6 | 7 | find_package(PkgConfig REQUIRED) 8 | pkg_check_modules(LIBPMEMKV REQUIRED libpmemkv) 9 | 10 | include_directories(${LIBPMEMKV_INCLUDE_DIRS}) 11 | link_directories(${LIBPMEMKV_LIBRARY_DIRS}) 12 | add_executable(pmemkv_comparator_c pmemkv_comparator.c) 13 | target_link_libraries(pmemkv_comparator_c ${LIBPMEMKV_LIBRARIES}) 14 | -------------------------------------------------------------------------------- /examples/pmemkv_iterator_c/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2020, Intel Corporation 3 | 4 | cmake_minimum_required(VERSION 3.3) 5 | project(pmemkv_iterator_c C) 6 | 7 | find_package(PkgConfig REQUIRED) 8 | pkg_check_modules(LIBPMEMKV REQUIRED libpmemkv) 9 | 10 | include_directories(${LIBPMEMKV_INCLUDE_DIRS}) 11 | link_directories(${LIBPMEMKV_LIBRARY_DIRS}) 12 | add_executable(pmemkv_iterator_c pmemkv_iterator.c) 13 | target_link_libraries(pmemkv_iterator_c ${LIBPMEMKV_LIBRARIES}) 14 | -------------------------------------------------------------------------------- /cmake/libpmemobj++.cmake: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2017-2019, Intel Corporation 3 | 4 | if(PKG_CONFIG_FOUND) 5 | pkg_check_modules(LIBPMEMOBJ++ REQUIRED libpmemobj++>=${LIBPMEMOBJ_CPP_REQUIRED_VERSION}) 6 | else() 7 | find_package(LIBPMEMOBJ++ ${LIBPMEMOBJ_CPP_REQUIRED_VERSION} REQUIRED libpmemobj++) 8 | message(STATUS "libpmemobj++ found the old way (w/o pkg-config)") 9 | endif() 10 | 11 | include_directories(${LIBPMEMOBJ++_INCLUDE_DIRS}) 12 | link_directories(${LIBPMEMOBJ++_LIBRARY_DIRS}) 13 | -------------------------------------------------------------------------------- /examples/pmemkv_comparator_cpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2020, Intel Corporation 3 | 4 | cmake_minimum_required(VERSION 3.3) 5 | project(pmemkv_basic CXX) 6 | 7 | find_package(PkgConfig REQUIRED) 8 | pkg_check_modules(LIBPMEMKV REQUIRED libpmemkv) 9 | 10 | include_directories(${LIBPMEMKV_INCLUDE_DIRS}) 11 | link_directories(${LIBPMEMKV_LIBRARY_DIRS}) 12 | add_executable(pmemkv_comparator_cpp pmemkv_comparator.cpp) 13 | target_link_libraries(pmemkv_comparator_cpp ${LIBPMEMKV_LIBRARIES}) 14 | -------------------------------------------------------------------------------- /examples/pmemkv_transaction_c/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2020, Intel Corporation 3 | 4 | cmake_minimum_required(VERSION 3.3) 5 | project(pmemkv_transaction_c C) 6 | 7 | find_package(PkgConfig REQUIRED) 8 | pkg_check_modules(LIBPMEMKV REQUIRED libpmemkv) 9 | 10 | include_directories(${LIBPMEMKV_INCLUDE_DIRS}) 11 | link_directories(${LIBPMEMKV_LIBRARY_DIRS}) 12 | add_executable(pmemkv_transaction_c pmemkv_transaction.c) 13 | target_link_libraries(pmemkv_transaction_c ${LIBPMEMKV_LIBRARIES}) 14 | -------------------------------------------------------------------------------- /examples/pmemkv_iterator_cpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2020-2021, Intel Corporation 3 | 4 | cmake_minimum_required(VERSION 3.3) 5 | project(pmemkv_iterator_cpp CXX) 6 | 7 | find_package(PkgConfig REQUIRED) 8 | pkg_check_modules(LIBPMEMKV REQUIRED libpmemkv) 9 | 10 | include_directories(${LIBPMEMKV_INCLUDE_DIRS}) 11 | link_directories(${LIBPMEMKV_LIBRARY_DIRS}) 12 | add_executable(pmemkv_iterator_cpp pmemkv_iterator.cpp) 13 | target_link_libraries(pmemkv_iterator_cpp ${LIBPMEMKV_LIBRARIES} pthread) 14 | -------------------------------------------------------------------------------- /examples/pmemkv_transaction_cpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2020, Intel Corporation 3 | 4 | cmake_minimum_required(VERSION 3.3) 5 | project(pmemkv_transaction_cpp CXX) 6 | 7 | find_package(PkgConfig REQUIRED) 8 | pkg_check_modules(LIBPMEMKV REQUIRED libpmemkv) 9 | 10 | include_directories(${LIBPMEMKV_INCLUDE_DIRS}) 11 | link_directories(${LIBPMEMKV_LIBRARY_DIRS}) 12 | add_executable(pmemkv_transaction_cpp pmemkv_transaction.cpp) 13 | target_link_libraries(pmemkv_transaction_cpp ${LIBPMEMKV_LIBRARIES}) 14 | -------------------------------------------------------------------------------- /tests/drd.supp: -------------------------------------------------------------------------------- 1 | { 2 | Conditional variable destruction false-positive 3 | drd:CondErr 4 | ... 5 | fun:pthread_cond_destroy@* 6 | ... 7 | } 8 | { 9 | Pthread mutex lock false positive 10 | Drd:Race 11 | ... 12 | fun:pthread_mutex_*lock* 13 | ... 14 | } 15 | { 16 | Pthread rwlock lock false positive 17 | Drd:Race 18 | ... 19 | fun:pthread_rwlock_*lock* 20 | ... 21 | } 22 | { 23 | Dl lookup 24 | drd:ConflictingAccess 25 | fun:_dl_lookup_symbol_x 26 | fun:_dl_fixup 27 | fun:_dl_runtime_resolve_xsave 28 | } 29 | -------------------------------------------------------------------------------- /tests/engines/pmemobj_based/pmemobj/error_handling_tx_path.cmake: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2020, Intel Corporation 3 | 4 | include(${PARENT_SRC_DIR}/helpers.cmake) 5 | include(${PARENT_SRC_DIR}/engines/pmemobj_based/helpers.cmake) 6 | 7 | setup() 8 | 9 | pmempool_execute(create -l ${LAYOUT} -s 100M obj ${DIR}/testfile) 10 | pmempool_execute(create -l ${LAYOUT} -s 100M obj ${DIR}/testfile2) 11 | 12 | make_config({"path":"${DIR}/testfile"}) 13 | execute(${TEST_EXECUTABLE} ${ENGINE} ${CONFIG} ${DIR}/testfile2) 14 | 15 | finish() 16 | -------------------------------------------------------------------------------- /utils/jenkins/scripts/removeNamespaces.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | # Copyright 2019-2021, Intel Corporation 4 | 5 | # removeNamespaces.sh - clear all existing namespaces. 6 | set -e 7 | 8 | MOUNT_POINT="/mnt/pmem*" 9 | 10 | # Clearing all existing namespaces 11 | 12 | sudo umount $MOUNT_POINT || true 13 | 14 | namespace_names=$(ndctl list -X | jq -r '.[].dev') 15 | 16 | for n in $namespace_names 17 | do 18 | sudo ndctl clear-errors $n -v 19 | done 20 | sudo ndctl disable-namespace all || true 21 | sudo ndctl destroy-namespace all || true 22 | -------------------------------------------------------------------------------- /doc/ENGINES-testing.md: -------------------------------------------------------------------------------- 1 | # Testing Storage Engines for pmemkv 2 | 3 | - [dram_vcmap](#dram_vcmap) 4 | 5 | # dram_vcmap 6 | 7 | A volatile concurrent engine backed by std::allocator. Data written using this engine is stored entierly in DRAM and lost after the database is closed. 8 | 9 | This engine is variant of vcmap, which uses std::allocator to allocate memory. That means it is built on top of tbb::concurrent\_hash\_map data structure; std::basic\_string is used as a type of a key and a value. 10 | TBB package is required. 11 | 12 | This engine do not require any config parameters 13 | 14 | -------------------------------------------------------------------------------- /tests/engines/pmemobj_based/default.cmake: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2020, Intel Corporation 3 | 4 | include(${PARENT_SRC_DIR}/helpers.cmake) 5 | include(${PARENT_SRC_DIR}/engines/pmemobj_based/helpers.cmake) 6 | 7 | setup() 8 | 9 | if ((${TRACER} STREQUAL "drd") OR (${TRACER} STREQUAL "helgrind")) 10 | check_is_pmem(${DIR}/testfile) 11 | endif() 12 | 13 | pmempool_execute(create -l ${LAYOUT} -s ${DB_SIZE} obj ${DIR}/testfile) 14 | 15 | make_config({"path":"${DIR}/testfile"}) 16 | execute(${TEST_EXECUTABLE} ${ENGINE} ${CONFIG} ${PARAMS}) 17 | 18 | finish() 19 | -------------------------------------------------------------------------------- /utils/docker/images/install-rapidjson.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | # Copyright 2020, Intel Corporation 4 | 5 | # 6 | # install-rapidjson.sh - installs rapidjson from sources 7 | # 8 | 9 | set -e 10 | 11 | git clone https://github.com/Tencent/rapidjson 12 | cd rapidjson 13 | # master: Merge pull request #1760 from escherstair/fix_ce6_support, 07.08.2020 14 | git checkout "ce81bc9edfe773667a7a4454ba81dac72ed4364c" 15 | 16 | mkdir build 17 | cd build 18 | cmake .. 19 | make -j$(nproc) 20 | sudo make -j$(nproc) install 21 | 22 | cd ../.. 23 | rm -r rapidjson 24 | -------------------------------------------------------------------------------- /tests/engines/pmemobj_based/default_no_config.cmake: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2020-2021, Intel Corporation 3 | 4 | include(${PARENT_SRC_DIR}/helpers.cmake) 5 | include(${PARENT_SRC_DIR}/engines/pmemobj_based/helpers.cmake) 6 | 7 | setup() 8 | 9 | if ((${TRACER} STREQUAL "drd") OR (${TRACER} STREQUAL "helgrind")) 10 | check_is_pmem(${DIR}/testfile) 11 | endif() 12 | 13 | set(TEST_PATH "${DIR}/testfile") 14 | pmempool_execute(create -l ${LAYOUT} -s ${DB_SIZE} obj ${TEST_PATH}) 15 | 16 | execute(${TEST_EXECUTABLE} ${ENGINE} ${TEST_PATH} ${DB_SIZE} ${PARAMS}) 17 | 18 | finish() 19 | -------------------------------------------------------------------------------- /cmake/FindLIBPMEM.cmake: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2019-2020, Intel Corporation 3 | 4 | find_path(LIBPMEM_INCLUDE_DIR libpmem.h) 5 | find_library(LIBPMEM_LIBRARY NAMES pmem libpmem) 6 | 7 | set(LIBPMEM_LIBRARIES ${LIBPMEM_LIBRARY}) 8 | set(LIBPMEM_INCLUDE_DIRS ${LIBPMEM_INCLUDE_DIR}) 9 | 10 | set(MSG_NOT_FOUND "libpmem NOT found (set CMAKE_PREFIX_PATH to point the location)") 11 | if(NOT (LIBPMEM_INCLUDE_DIR AND LIBPMEM_LIBRARY)) 12 | if(LIBPMEM_FIND_REQUIRED) 13 | message(FATAL_ERROR ${MSG_NOT_FOUND}) 14 | else() 15 | message(WARNING ${MSG_NOT_FOUND}) 16 | endif() 17 | endif() 18 | 19 | mark_as_advanced(LIBPMEM_LIBRARY LIBPMEM_INCLUDE_DIR) 20 | -------------------------------------------------------------------------------- /tests/engines/pmemobj_based/persistent/insert_check.cmake: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2020, Intel Corporation 3 | 4 | include(${PARENT_SRC_DIR}/helpers.cmake) 5 | include(${PARENT_SRC_DIR}/engines/pmemobj_based/helpers.cmake) 6 | 7 | setup() 8 | 9 | if ((${TRACER} STREQUAL "drd") OR (${TRACER} STREQUAL "helgrind")) 10 | check_is_pmem(${DIR}/testfile) 11 | endif() 12 | 13 | pmempool_execute(create -l ${LAYOUT} -s ${DB_SIZE} obj ${DIR}/testfile) 14 | 15 | make_config({"path":"${DIR}/testfile"}) 16 | execute(${TEST_EXECUTABLE} ${ENGINE} ${CONFIG} insert ${PARAMS}) 17 | execute(${TEST_EXECUTABLE} ${ENGINE} ${CONFIG} check ${PARAMS}) 18 | 19 | finish() 20 | -------------------------------------------------------------------------------- /examples/pmemkv_pmemobj_cpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2019-2020, Intel Corporation 3 | 4 | cmake_minimum_required(VERSION 3.3) 5 | project(pmemkv_pmemobj CXX) 6 | 7 | set(LIBPMEMOBJ_CPP_REQUIRED_VERSION 1.9) 8 | 9 | find_package(PkgConfig REQUIRED) 10 | pkg_check_modules(LIBPMEMKV REQUIRED libpmemkv) 11 | pkg_check_modules(LIBPMEMOBJ++ REQUIRED libpmemobj++>=${LIBPMEMOBJ_CPP_REQUIRED_VERSION}) 12 | 13 | include_directories(${LIBPMEMKV_INCLUDE_DIRS}) 14 | link_directories(${LIBPMEMKV_LIBRARY_DIRS}) 15 | add_executable(pmemkv_pmemobj_cpp pmemkv_pmemobj.cpp) 16 | target_link_libraries(pmemkv_pmemobj_cpp ${LIBPMEMKV_LIBRARIES} ${LIBPMEMOBJ++_LIBRARIES}) 17 | -------------------------------------------------------------------------------- /tests/compatibility/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2019-2020, Intel Corporation 3 | 4 | project(pmemkv_compatibility_test) 5 | 6 | cmake_minimum_required(VERSION 3.13) 7 | 8 | include(../ctest_helpers.cmake) 9 | 10 | find_package(PkgConfig REQUIRED) 11 | 12 | enable_testing() 13 | 14 | pkg_check_modules(LIBPMEMKV REQUIRED libpmemkv) 15 | 16 | function(build_binary name) 17 | add_executable(${name} ${ARGN}) 18 | 19 | target_include_directories(${name} PRIVATE ${LIBPMEMKV_INCLUDE_DIRS}) 20 | target_link_directories(${name} PRIVATE ${LIBPMEMKV_LIBRARY_DIRS}) 21 | target_link_libraries(${name} pmemkv) 22 | endfunction() 23 | 24 | build_binary(cmap_compatibility cmap.cc) 25 | -------------------------------------------------------------------------------- /tests/memcheck-libunwind.supp: -------------------------------------------------------------------------------- 1 | { 2 | generic libunwind suppression 3 | Memcheck:Param 4 | msync(start) 5 | ... 6 | obj:*libunwind* 7 | ... 8 | } 9 | { 10 | generic libunwind suppression 11 | Memcheck:Param 12 | rt_sigprocmask(set) 13 | ... 14 | obj:*libunwind* 15 | ... 16 | } 17 | { 18 | generic libunwind suppression 19 | Memcheck:Addr8 20 | ... 21 | obj:*libunwind* 22 | ... 23 | } 24 | { 25 | libunwind exception suppresion 26 | Memcheck:Param 27 | write(buf) 28 | ... 29 | obj:*libunwind* 30 | ... 31 | } 32 | { 33 | libunwind calls glibc's setcontext on some architectures, e.g. ppc 34 | Memcheck:Addr8 35 | fun:setcontext* 36 | ... 37 | } 38 | -------------------------------------------------------------------------------- /cmake/FindLIBPMEMOBJ.cmake: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2018-2020, Intel Corporation 3 | 4 | find_path(LIBPMEMOBJ_INCLUDE_DIR libpmemobj.h) 5 | find_library(LIBPMEMOBJ_LIBRARY NAMES pmemobj libpmemobj) 6 | 7 | set(LIBPMEMOBJ_LIBRARIES ${LIBPMEMOBJ_LIBRARY}) 8 | set(LIBPMEMOBJ_INCLUDE_DIRS ${LIBPMEMOBJ_INCLUDE_DIR}) 9 | 10 | set(MSG_NOT_FOUND "libpmemobj NOT found (set CMAKE_PREFIX_PATH to point the location)") 11 | if(NOT (LIBPMEMOBJ_INCLUDE_DIR AND LIBPMEMOBJ_LIBRARY)) 12 | if(LIBPMEMOBJ_FIND_REQUIRED) 13 | message(FATAL_ERROR ${MSG_NOT_FOUND}) 14 | else() 15 | message(WARNING ${MSG_NOT_FOUND}) 16 | endif() 17 | endif() 18 | 19 | mark_as_advanced(LIBPMEMOBJ_LIBRARY LIBPMEMOBJ_INCLUDE_DIR) 20 | -------------------------------------------------------------------------------- /tests/engine_scenarios/transaction/not_supported.cc: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2021, Intel Corporation */ 3 | 4 | #include "unittest.hpp" 5 | 6 | using namespace pmem::kv; 7 | 8 | static void test_tx_status(pmem::kv::db &kv) 9 | { 10 | auto tx = kv.tx_begin(); 11 | UT_ASSERT(!tx.is_ok()); 12 | 13 | auto s = tx.get_status(); 14 | ASSERT_STATUS(s, status::NOT_SUPPORTED); 15 | } 16 | 17 | static void test(int argc, char *argv[]) 18 | { 19 | if (argc < 3) 20 | UT_FATAL("usage: %s engine json_config", argv[0]); 21 | 22 | run_engine_tests(argv[1], argv[2], {test_tx_status}); 23 | } 24 | 25 | int main(int argc, char *argv[]) 26 | { 27 | return run_test([&] { test(argc, argv); }); 28 | } 29 | -------------------------------------------------------------------------------- /tests/memcheck-ndctl.supp: -------------------------------------------------------------------------------- 1 | { 2 | ndctl suppression 3 | Memcheck:Leak 4 | match-leak-kinds: definite 5 | fun:realloc 6 | ... 7 | fun:ndctl_pfn_get_first 8 | fun:ndctl_namespace_get_pfn 9 | ... 10 | } 11 | { 12 | ndctl suppression 13 | Memcheck:Leak 14 | match-leak-kinds: definite 15 | fun:realloc 16 | ... 17 | fun:ndctl_dax_get_first 18 | ... 19 | } 20 | { 21 | memory leak in ndctl 63 22 | Memcheck:Leak 23 | match-leak-kinds: reachable 24 | fun:malloc 25 | ... 26 | fun:ndctl_namespace_get_first_badblock 27 | ... 28 | } 29 | { 30 | cond jump in libkmod 31 | Memcheck:Cond 32 | ... 33 | fun:kmod_module_new_from_lookup 34 | ... 35 | fun:ndctl_region_get_first 36 | ... 37 | } 38 | -------------------------------------------------------------------------------- /src/out.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2019-2021, Intel Corporation */ 3 | 4 | #ifndef LIBPMEMKV_OUT_H 5 | #define LIBPMEMKV_OUT_H 6 | 7 | #include 8 | 9 | std::ostream &out_err_stream(const char *func); 10 | 11 | #define DO_LOG 0 12 | #define LOG(msg) \ 13 | do { \ 14 | if (DO_LOG) \ 15 | std::cout << "[" << name() << "] " << msg << "\n"; \ 16 | } while (0) 17 | 18 | #define ERR() out_err_stream(__func__) 19 | 20 | const char *out_get_errormsg(void); 21 | void set_last_status(int status); 22 | 23 | #endif /* LIBPMEMKV_OUT_H */ 24 | -------------------------------------------------------------------------------- /utils/md2man/default.man: -------------------------------------------------------------------------------- 1 | $if(has-tables)$ 2 | .\"t 3 | $endif$ 4 | $if(pandoc-version)$ 5 | .\" Automatically generated by Pandoc $pandoc-version$ 6 | .\" 7 | $endif$ 8 | $if(adjusting)$ 9 | .ad $adjusting$ 10 | $endif$ 11 | .TH "$title$" "$section$" "$date$" "PMEMKV - $secondary_title$ version $version$" "PMEMKV Programmer's Manual" 12 | $if(hyphenate)$ 13 | .hy 14 | $else$ 15 | .nh \" Turn off hyphenation by default. 16 | $endif$ 17 | $for(header-includes)$ 18 | $header-includes$ 19 | $endfor$ 20 | .\" SPDX-License-Identifier: BSD-3-Clause 21 | .\" Copyright 2019-$year$, Intel Corporation 22 | $for(include-before)$ 23 | $include-before$ 24 | $endfor$ 25 | $body$ 26 | $for(include-after)$ 27 | $include-after$ 28 | $endfor$ 29 | $if(author)$ 30 | .SH AUTHORS 31 | $for(author)$$author$$sep$; $endfor$. 32 | $endif$ 33 | -------------------------------------------------------------------------------- /examples/pmemkv_config_c/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2019-2021, Intel Corporation 3 | 4 | cmake_minimum_required(VERSION 3.3) 5 | project(pmemkv_config C) 6 | 7 | find_package(PkgConfig REQUIRED) 8 | pkg_check_modules(LIBPMEMKV REQUIRED libpmemkv libpmemkv_json_config) 9 | 10 | include_directories(${LIBPMEMKV_INCLUDE_DIRS}) 11 | link_directories(${LIBPMEMKV_LIBRARY_DIRS}) 12 | 13 | add_executable(pmemkv_config_c pmemkv_config.c) 14 | target_link_libraries(pmemkv_config_c ${LIBPMEMKV_LIBRARIES}) 15 | 16 | # Additional executable for basic example not using json helper library. 17 | # It links directly with 'pmemkv' library (not what pkg-config found). 18 | add_executable(pmemkv_basic_config_c pmemkv_basic_config.c) 19 | target_link_libraries(pmemkv_basic_config_c pmemkv) 20 | -------------------------------------------------------------------------------- /tests/engine_scenarios/pmemobj/error_handling_defrag.cc: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2020, Intel Corporation */ 3 | 4 | #include "unittest.hpp" 5 | 6 | static void DefragInvalidArgument(pmem::kv::db &kv) 7 | { 8 | ASSERT_STATUS(kv.defrag(50, 100), pmem::kv::status::INVALID_ARGUMENT); 9 | ASSERT_STATUS(kv.defrag(0, 101), pmem::kv::status::INVALID_ARGUMENT); 10 | ASSERT_STATUS(kv.defrag(101, 0), pmem::kv::status::INVALID_ARGUMENT); 11 | } 12 | 13 | static void test(int argc, char *argv[]) 14 | { 15 | if (argc < 3) 16 | UT_FATAL("usage: %s engine json_config", argv[0]); 17 | 18 | auto kv = INITIALIZE_KV(argv[1], CONFIG_FROM_JSON(argv[2])); 19 | 20 | DefragInvalidArgument(kv); 21 | } 22 | 23 | int main(int argc, char *argv[]) 24 | { 25 | return run_test([&] { test(argc, argv); }); 26 | } 27 | -------------------------------------------------------------------------------- /tests/engine_scenarios/all/put_get_std_map.cc: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2020, Intel Corporation */ 3 | 4 | #include "../put_get_std_map.hpp" 5 | 6 | static void test(int argc, char *argv[]) 7 | { 8 | using namespace std::placeholders; 9 | 10 | if (argc < 6) 11 | UT_FATAL("usage: %s engine json_config n_inserts key_length value_length", 12 | argv[0]); 13 | 14 | auto n_inserts = std::stoull(argv[3]); 15 | auto key_length = std::stoull(argv[4]); 16 | auto value_length = std::stoull(argv[5]); 17 | 18 | auto kv = INITIALIZE_KV(argv[1], CONFIG_FROM_JSON(argv[2])); 19 | 20 | auto proto = PutToMapTest(n_inserts, key_length, value_length, kv); 21 | VerifyKv(proto, kv); 22 | 23 | kv.close(); 24 | } 25 | 26 | int main(int argc, char *argv[]) 27 | { 28 | return run_test([&] { test(argc, argv); }); 29 | } 30 | -------------------------------------------------------------------------------- /src/out.cc: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2019-2021, Intel Corporation */ 3 | 4 | #include "out.h" 5 | #include "libpmemkv.h" 6 | 7 | #include "libpmemkv.h" 8 | 9 | #include 10 | #include 11 | 12 | static thread_local std::stringstream error_stream; 13 | static thread_local std::string str; 14 | static thread_local int last_status; 15 | 16 | std::ostream &out_err_stream(const char *func) 17 | { 18 | error_stream.str(std::string()); 19 | 20 | error_stream << "[" << func << "] "; 21 | 22 | return error_stream; 23 | } 24 | 25 | void set_last_status(int s) 26 | { 27 | last_status = s; 28 | } 29 | 30 | const char *out_get_errormsg(void) 31 | { 32 | if (last_status == PMEMKV_STATUS_NOT_FOUND || 33 | last_status == PMEMKV_STATUS_STOPPED_BY_CB) 34 | return ""; 35 | str = error_stream.str(); 36 | return str.c_str(); 37 | } 38 | -------------------------------------------------------------------------------- /tests/engines/pmemobj_based/pmreorder/erase.cmake: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2020, Intel Corporation 3 | 4 | include(${PARENT_SRC_DIR}/helpers.cmake) 5 | include(${PARENT_SRC_DIR}/engines/pmemobj_based/helpers.cmake) 6 | 7 | setup() 8 | 9 | if ((${TRACER} STREQUAL "drd") OR (${TRACER} STREQUAL "helgrind")) 10 | check_is_pmem(${DIR}/testfile) 11 | endif() 12 | 13 | pmempool_execute(create -l ${LAYOUT} -s ${DB_SIZE} obj ${DIR}/testfile) 14 | 15 | make_config({"path":"${DIR}/testfile"}) 16 | 17 | execute(${TEST_EXECUTABLE} ${ENGINE} ${CONFIG} create ${PARAMS}) 18 | pmreorder_create_store_log(${DIR}/testfile ${TEST_EXECUTABLE} ${ENGINE} ${CONFIG} erase ${PARAMS}) 19 | pmreorder_execute(true ReorderAccumulative ${PARENT_SRC_DIR}/engines/pmemobj_based/pmreorder/pmreorder.conf ${TEST_EXECUTABLE} ${ENGINE} ${CONFIG} open ${PARAMS}) 20 | 21 | finish() 22 | -------------------------------------------------------------------------------- /tests/engines/pmemobj_based/pmreorder/insert.cmake: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2020, Intel Corporation 3 | 4 | include(${PARENT_SRC_DIR}/helpers.cmake) 5 | include(${PARENT_SRC_DIR}/engines/pmemobj_based/helpers.cmake) 6 | 7 | setup() 8 | 9 | if ((${TRACER} STREQUAL "drd") OR (${TRACER} STREQUAL "helgrind")) 10 | check_is_pmem(${DIR}/testfile) 11 | endif() 12 | 13 | pmempool_execute(create -l ${LAYOUT} -s ${DB_SIZE} obj ${DIR}/testfile) 14 | 15 | make_config({"path":"${DIR}/testfile"}) 16 | 17 | execute(${TEST_EXECUTABLE} ${ENGINE} ${CONFIG} create ${PARAMS}) 18 | pmreorder_create_store_log(${DIR}/testfile ${TEST_EXECUTABLE} ${ENGINE} ${CONFIG} insert ${PARAMS}) 19 | pmreorder_execute(true ReorderAccumulative ${PARENT_SRC_DIR}/engines/pmemobj_based/pmreorder/pmreorder.conf ${TEST_EXECUTABLE} ${ENGINE} ${CONFIG} open ${PARAMS}) 20 | 21 | finish() 22 | -------------------------------------------------------------------------------- /tests/engines/pmemobj_based/pmreorder/iterator.cmake: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2020, Intel Corporation 3 | 4 | include(${PARENT_SRC_DIR}/helpers.cmake) 5 | include(${PARENT_SRC_DIR}/engines/pmemobj_based/helpers.cmake) 6 | 7 | setup() 8 | 9 | if ((${TRACER} STREQUAL "drd") OR (${TRACER} STREQUAL "helgrind")) 10 | check_is_pmem(${DIR}/testfile) 11 | endif() 12 | 13 | pmempool_execute(create -l ${LAYOUT} -s ${DB_SIZE} obj ${DIR}/testfile) 14 | 15 | make_config({"path":"${DIR}/testfile"}) 16 | 17 | execute(${TEST_EXECUTABLE} ${ENGINE} ${CONFIG} create ${PARAMS}) 18 | pmreorder_create_store_log(${DIR}/testfile ${TEST_EXECUTABLE} ${ENGINE} ${CONFIG} write ${PARAMS}) 19 | pmreorder_execute(true ReorderAccumulative ${PARENT_SRC_DIR}/engines/pmemobj_based/pmreorder/pmreorder.conf ${TEST_EXECUTABLE} ${ENGINE} ${CONFIG} open ${PARAMS}) 20 | 21 | finish() 22 | -------------------------------------------------------------------------------- /utils/docker/images/install-memkind.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | # Copyright 2019-2021, Intel Corporation 4 | 5 | # 6 | # install-memkind.sh - installs memkind from sources; depends on 7 | # the system it uses proper installation parameters 8 | # 9 | 10 | set -e 11 | 12 | # memkind v1.13.0 13 | MEMKIND_VERSION=a8c54e4920a4859e9e00073280363ca7281dde10 14 | 15 | WORKDIR=$(pwd) 16 | 17 | git clone https://github.com/memkind/memkind 18 | cd ${WORKDIR}/memkind 19 | git checkout ${MEMKIND_VERSION} 20 | 21 | echo "set OS-specific configure options" 22 | OS_SPECIFIC="" 23 | case $(echo ${OS} | cut -d'-' -f1) in 24 | centos|opensuse) 25 | OS_SPECIFIC="--libdir=/usr/lib64" 26 | ;; 27 | esac 28 | 29 | ./autogen.sh 30 | ./configure --prefix=/usr ${OS_SPECIFIC} 31 | make -j$(nproc) 32 | make -j$(nproc) install 33 | 34 | echo "cleanup:" 35 | cd ${WORKDIR} 36 | rm -r memkind 37 | -------------------------------------------------------------------------------- /tests/engines/pmemobj_based/pmreorder/recover.cmake: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2021, Intel Corporation 3 | 4 | include(${PARENT_SRC_DIR}/helpers.cmake) 5 | include(${PARENT_SRC_DIR}/engines/pmemobj_based/helpers.cmake) 6 | 7 | setup() 8 | 9 | if ((${TRACER} STREQUAL "drd") OR (${TRACER} STREQUAL "helgrind")) 10 | check_is_pmem(${DIR}/testfile) 11 | endif() 12 | 13 | if (${ENGINE} STREQUAL "robinhood") 14 | set(ENV{PMEMKV_ROBINHOOD_SHARDS_NUMBER} 64) 15 | endif() 16 | 17 | pmempool_execute(create -l ${LAYOUT} -s ${DB_SIZE} obj ${DIR}/testfile) 18 | 19 | make_config({"path":"${DIR}/testfile"}) 20 | 21 | pmreorder_create_store_log(${DIR}/testfile ${TEST_EXECUTABLE} ${ENGINE} ${CONFIG} create ${PARAMS}) 22 | pmreorder_execute(true ReorderPartial ${PARENT_SRC_DIR}/engines/pmemobj_based/pmreorder/pmreorder.conf ${TEST_EXECUTABLE} ${ENGINE} ${CONFIG} open ${PARAMS}) 23 | 24 | finish() 25 | -------------------------------------------------------------------------------- /tests/ld.supp: -------------------------------------------------------------------------------- 1 | { 2 | 3 | Memcheck:Cond 4 | fun:index 5 | fun:expand_dynamic_string_token 6 | fun:_dl_map_object 7 | fun:map_doit 8 | fun:_dl_catch_error 9 | fun:do_preload 10 | fun:dl_main 11 | fun:_dl_sysdep_start 12 | fun:_dl_start 13 | obj:/lib/x86_64-linux-gnu/ld-2.*.so 14 | obj:* 15 | obj:* 16 | } 17 | { 18 | 19 | Memcheck:Cond 20 | fun:index 21 | fun:expand_dynamic_string_token 22 | fun:_dl_map_object 23 | fun:map_doit 24 | fun:_dl_catch_error 25 | fun:do_preload 26 | fun:handle_ld_preload 27 | fun:dl_main 28 | fun:_dl_sysdep_start 29 | fun:_dl_start 30 | obj:/lib/x86_64-linux-gnu/ld-2.*.so 31 | obj:* 32 | } 33 | { 34 | 35 | Memcheck:Leak 36 | ... 37 | fun:_dl_init 38 | fun:dl_open_worker 39 | fun:_dl_catch_error 40 | ... 41 | } 42 | -------------------------------------------------------------------------------- /src/comparator/volatile_comparator.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2020, Intel Corporation */ 3 | 4 | #ifndef LIBPMEMKV_VOLATILE_COMPARATOR_H 5 | #define LIBPMEMKV_VOLATILE_COMPARATOR_H 6 | 7 | #include "../exceptions.h" 8 | #include "comparator.h" 9 | 10 | namespace pmem 11 | { 12 | namespace kv 13 | { 14 | namespace internal 15 | { 16 | 17 | class volatile_compare { 18 | public: 19 | using is_transparent = void; 20 | 21 | volatile_compare(const comparator *cmp) : cmp(cmp) 22 | { 23 | } 24 | 25 | template 26 | bool operator()(const T &lhs, const U &rhs) const 27 | { 28 | auto key1 = make_string_view(lhs); 29 | auto key2 = make_string_view(rhs); 30 | 31 | return (cmp->compare(key1, key2) < 0); 32 | } 33 | 34 | private: 35 | const comparator *cmp; 36 | }; 37 | 38 | } /* namespace internal */ 39 | } /* namespace kv */ 40 | } /* namespace pmem */ 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /tests/config/deprecated_config.cc: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2019-2021, Intel Corporation */ 3 | 4 | #include "unittest.hpp" 5 | 6 | /** 7 | * Tests deprecated config methods using C++ API 8 | */ 9 | 10 | using namespace pmem::kv; 11 | 12 | static void deprecated_funcs_test() 13 | { 14 | /** 15 | * TEST: add and read data from config, using deprecated methods. 16 | */ 17 | config cfg; 18 | 19 | status s = cfg.put_force_create(true); 20 | ASSERT_STATUS(s, status::OK); 21 | 22 | uint64_t int_us; 23 | s = cfg.get_uint64("create_or_error_if_exists", int_us); 24 | ASSERT_STATUS(s, status::OK); 25 | UT_ASSERTeq(int_us, 1); 26 | 27 | /* Check if not-deprecated function sets the same config field */ 28 | s = cfg.put_create_or_error_if_exists(false); 29 | UT_ASSERTne(s, status::OK); 30 | } 31 | 32 | int main(int argc, char *argv[]) 33 | { 34 | return run_test([&] { deprecated_funcs_test(); }); 35 | } 36 | -------------------------------------------------------------------------------- /tests/engine_scenarios/pmemobj/put_get_std_map_defrag.cc: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2020, Intel Corporation */ 3 | 4 | #include "../put_get_std_map.hpp" 5 | 6 | static void test(int argc, char *argv[]) 7 | { 8 | using namespace std::placeholders; 9 | 10 | if (argc < 6) 11 | UT_FATAL("usage: %s engine json_config n_inserts key_length value_length", 12 | argv[0]); 13 | 14 | auto n_inserts = std::stoull(argv[3]); 15 | auto key_length = std::stoull(argv[4]); 16 | auto value_length = std::stoull(argv[5]); 17 | 18 | auto kv = INITIALIZE_KV(argv[1], CONFIG_FROM_JSON(argv[2])); 19 | 20 | auto proto = PutToMapTest(n_inserts, key_length, value_length, kv); 21 | 22 | auto s = kv.defrag(0, 100); 23 | ASSERT_STATUS(s, pmem::kv::status::OK); 24 | 25 | VerifyKv(proto, kv); 26 | 27 | kv.close(); 28 | } 29 | 30 | int main(int argc, char *argv[]) 31 | { 32 | return run_test([&] { test(argc, argv); }); 33 | } 34 | -------------------------------------------------------------------------------- /utils/docker/images/download-scripts.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | # Copyright 2020, Intel Corporation 4 | 5 | # 6 | # download-scripts.sh - downloads specific version of 7 | # codecov's bash script to generate and upload reports. 8 | # It's useful, since they may break our coverage. 9 | # 10 | 11 | set -e 12 | 13 | # master: Merge pull request #342 from codecov/revert-proj-name-..., 18.08.2020 14 | CODECOV_VERSION="e877c1280cc6e902101fb5df2981ed1c962da7f0" 15 | 16 | if [ "${SKIP_SCRIPTS_DOWNLOAD}" ]; then 17 | echo "Variable 'SKIP_SCRIPTS_DOWNLOAD' is set; skipping scripts' download" 18 | exit 19 | fi 20 | 21 | mkdir -p /opt/scripts 22 | 23 | git clone https://github.com/codecov/codecov-bash 24 | cd codecov-bash 25 | git checkout $CODECOV_VERSION 26 | 27 | git apply ../0001-fix-generating-gcov-files-and-turn-off-verbose-log.patch 28 | mv -v codecov /opt/scripts/codecov 29 | 30 | cd .. 31 | rm -rf codecov-bash 32 | -------------------------------------------------------------------------------- /utils/docker/images/install-valgrind.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | # Copyright 2016-2022, Intel Corporation 4 | 5 | # 6 | # install-valgrind.sh - installs valgrind with pmemcheck 7 | # 8 | 9 | set -e 10 | 11 | if [ "${SKIP_VALGRIND_BUILD}" ]; then 12 | echo "Variable 'SKIP_VALGRIND_BUILD' is set; skipping building valgrind (pmem's fork)" 13 | exit 14 | fi 15 | 16 | OS=${1} 17 | 18 | git clone https://github.com/pmem/valgrind.git 19 | cd valgrind 20 | # pmem-3.18: memcheck: fix test addressable err exp; 21.01.2022 21 | git checkout 06f15d69237501852dd29883940e18da4179830a 22 | 23 | # set OS-specific configure options 24 | OS_SPECIFIC="" 25 | case $(echo ${OS} | cut -d'-' -f1) in 26 | centos|opensuse) 27 | OS_SPECIFIC="--libdir=/usr/lib64" 28 | ;; 29 | esac 30 | 31 | ./autogen.sh 32 | ./configure --prefix=/usr ${OS_SPECIFIC} 33 | make -j$(nproc) 34 | sudo make -j$(nproc) install 35 | cd .. 36 | rm -r valgrind 37 | -------------------------------------------------------------------------------- /tests/error_msg_test.cc: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2021, Intel Corporation */ 3 | 4 | #include 5 | 6 | #include "unittest.hpp" 7 | 8 | static void errormsg_cleared() 9 | { 10 | pmem::kv::db kv; 11 | auto s = kv.open("non-existing name"); 12 | ASSERT_STATUS(s, pmem::kv::status::WRONG_ENGINE_NAME); 13 | 14 | auto err = pmem::kv::errormsg(); 15 | UT_ASSERT(err.size() > 0); 16 | 17 | s = kv.open("blackhole"); 18 | ASSERT_STATUS(s, pmem::kv::status::OK); 19 | 20 | std::string value; 21 | s = kv.get("Nonexisting key:", &value); 22 | ASSERT_STATUS(s, pmem::kv::status::NOT_FOUND); 23 | err = pmem::kv::errormsg(); 24 | UT_ASSERT(err == ""); 25 | UT_ASSERTeq(err.size(), 0); 26 | 27 | s = kv.open("non-existing name"); 28 | ASSERT_STATUS(s, pmem::kv::status::WRONG_ENGINE_NAME); 29 | err = pmem::kv::errormsg(); 30 | UT_ASSERT(err.size() > 0); 31 | } 32 | 33 | int main() 34 | { 35 | errormsg_cleared(); 36 | 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /cmake/rapidjson.cmake: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2017-2021, Intel Corporation 3 | 4 | message(STATUS "Checking for module 'RapidJSON'") 5 | 6 | if(PKG_CONFIG_FOUND) 7 | pkg_check_modules(RapidJSON QUIET RapidJSON>=${RAPIDJSON_REQUIRED_VERSION}) 8 | endif() 9 | 10 | if(NOT RapidJSON_FOUND) 11 | # find_package (run after pkg-config) without unsetting this var is not working correctly 12 | unset(RapidJSON_FOUND CACHE) 13 | 14 | find_package(RapidJSON ${RAPIDJSON_REQUIRED_VERSION} QUIET REQUIRED) 15 | 16 | set(RapidJSON_LIBRARIES ${RapidJSON_LIBRARY}) 17 | set(RapidJSON_INCLUDE_DIRS ${RapidJSON_INCLUDE_DIR}) 18 | message(STATUS " Found in dir '${RapidJSON_DIR}' using CMake's find_package (ver: ${RapidJSON_VERSION})") 19 | else() 20 | message(STATUS " Found in dir '${RapidJSON_INCLUDEDIR}' using pkg-config (ver: ${RapidJSON_VERSION})") 21 | endif() 22 | 23 | include_directories(${RapidJSON_INCLUDE_DIRS}) 24 | link_directories(${RapidJSON_LIBRARY_DIRS}) 25 | -------------------------------------------------------------------------------- /tests/comparator/basic_persistent.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2020, Intel Corporation */ 3 | 4 | #include 5 | 6 | #include "unittest.h" 7 | 8 | #include 9 | 10 | static int ARG_VALUE = 0xABC; 11 | 12 | static int reverse_three_way_compare(const char *key1, size_t keybytes1, const char *key2, 13 | size_t keybytes2, void *arg) 14 | { 15 | UT_ASSERT(*((int *)arg) == ARG_VALUE); 16 | 17 | /* Compare just first bytes */ 18 | return key2[0] - key1[0]; 19 | } 20 | 21 | static void test_nullptr_name(const char *engine, pmemkv_config *cfg) 22 | { 23 | pmemkv_comparator *cmp = 24 | pmemkv_comparator_new(&reverse_three_way_compare, NULL, &ARG_VALUE); 25 | UT_ASSERTeq(cmp, NULL); 26 | 27 | pmemkv_config_delete(cfg); 28 | } 29 | 30 | int main(int argc, char *argv[]) 31 | { 32 | START(); 33 | 34 | if (argc < 3) 35 | UT_FATAL("usage %s: engine config", argv[0]); 36 | 37 | test_nullptr_name(argv[1], C_CONFIG_FROM_JSON(argv[2])); 38 | 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /tests/engine_scenarios/persistent/put_get_std_map_multiple_reopen.cc: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2020, Intel Corporation */ 3 | 4 | #include "../put_get_std_map.hpp" 5 | 6 | const int N_ITERS = 50; 7 | 8 | static void test(int argc, char *argv[]) 9 | { 10 | using namespace std::placeholders; 11 | 12 | if (argc < 6) 13 | UT_FATAL("usage: %s engine json_config n_inserts key_length value_length", 14 | argv[0]); 15 | 16 | auto n_inserts = std::stoull(argv[3]); 17 | auto key_length = std::stoull(argv[4]); 18 | auto value_length = std::stoull(argv[5]); 19 | 20 | auto kv = INITIALIZE_KV(argv[1], CONFIG_FROM_JSON(argv[2])); 21 | 22 | auto proto = PutToMapTest(n_inserts, key_length, value_length, kv); 23 | 24 | for (int i = 0; i < N_ITERS; i++) { 25 | kv.close(); 26 | kv = INITIALIZE_KV(argv[1], CONFIG_FROM_JSON(argv[2])); 27 | VerifyKv(proto, kv); 28 | } 29 | 30 | kv.close(); 31 | } 32 | 33 | int main(int argc, char *argv[]) 34 | { 35 | return run_test([&] { test(argc, argv); }); 36 | } 37 | -------------------------------------------------------------------------------- /tests/engine_scenarios/pmemobj/error_handling_tx_path.cc: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2020, Intel Corporation */ 3 | 4 | #include "error_handling_tx.hpp" 5 | 6 | static void test(int argc, char *argv[]) 7 | { 8 | using namespace std::placeholders; 9 | 10 | if (argc < 4) 11 | UT_FATAL("usage: %s engine json_config obj_path", argv[0]); 12 | 13 | auto pmemobj_pool_path = std::string(argv[3]); 14 | pmem::obj::pool_base pmemobj_pool; 15 | 16 | auto layout = std::string("pmemkv"); 17 | auto engine = std::string(argv[1]); 18 | if (engine != "cmap") 19 | layout = "pmemkv_" + engine; 20 | 21 | try { 22 | pmemobj_pool = pmem::obj::pool_base::open(pmemobj_pool_path, layout); 23 | } catch (std::exception &e) { 24 | UT_FATALexc(e); 25 | } 26 | 27 | auto kv = INITIALIZE_KV(engine, CONFIG_FROM_JSON(argv[2])); 28 | 29 | TransactionTest(pmemobj_pool, kv); 30 | 31 | pmemobj_pool.close(); 32 | } 33 | 34 | int main(int argc, char *argv[]) 35 | { 36 | return run_test([&] { test(argc, argv); }); 37 | } 38 | -------------------------------------------------------------------------------- /tests/compatibility/cmap.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | # Copyright 2020, Intel Corporation 4 | 5 | # 6 | # cmap.sh -- runs cmap compatibility test 7 | # 8 | 9 | set -e 10 | 11 | binary1=${1} 12 | binary2=${2} 13 | testfile=${3} 14 | 15 | echo "## cmap.sh" 16 | echo "1st binary: ${binary1}" 17 | echo "2nd binary: ${binary2}" 18 | echo "testfile: ${testfile}" 19 | echo 20 | 21 | echo "Test: binary1 create; binary2 open" 22 | rm -f ${testfile} 23 | ${binary1} ${testfile} create 24 | ${binary2} ${testfile} open 25 | 26 | echo "Test: binary1 create_ungraceful; binary2 open" 27 | rm -f ${testfile} 28 | ${binary1} ${testfile} create_ungraceful 29 | ${binary2} ${testfile} open 30 | 31 | echo "Test: binary2 create; binary1 open" 32 | rm -f ${testfile} 33 | ${binary2} ${testfile} create 34 | ${binary1} ${testfile} open 35 | 36 | echo "Test: binary2 create_ungraceful; binary1 open" 37 | rm -f ${testfile} 38 | ${binary2} ${testfile} create_ungraceful 39 | ${binary1} ${testfile} open 40 | 41 | rm -f ${testfile} 42 | -------------------------------------------------------------------------------- /tests/engine_scenarios/all/iterator_not_supported.cc: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2021, Intel Corporation */ 3 | 4 | #include "unittest.hpp" 5 | 6 | using namespace pmem::kv; 7 | 8 | static void read_iterator_not_supported(pmem::kv::db &kv) 9 | { 10 | auto res = kv.new_read_iterator(); 11 | UT_ASSERT(!res.is_ok()); 12 | 13 | auto s = res.get_status(); 14 | ASSERT_STATUS(s, status::NOT_SUPPORTED); 15 | } 16 | 17 | static void write_iterator_not_supported(pmem::kv::db &kv) 18 | { 19 | auto res = kv.new_write_iterator(); 20 | UT_ASSERT(!res.is_ok()); 21 | 22 | auto s = res.get_status(); 23 | ASSERT_STATUS(s, status::NOT_SUPPORTED); 24 | } 25 | 26 | static void test(int argc, char *argv[]) 27 | { 28 | if (argc < 3) 29 | UT_FATAL("usage: %s engine json_config", argv[0]); 30 | 31 | run_engine_tests(argv[1], argv[2], 32 | { 33 | write_iterator_not_supported, 34 | read_iterator_not_supported, 35 | }); 36 | } 37 | 38 | int main(int argc, char *argv[]) 39 | { 40 | return run_test([&] { test(argc, argv); }); 41 | } 42 | -------------------------------------------------------------------------------- /utils/cppstyle: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | # Copyright 2017, Intel Corporation 4 | 5 | use strict; 6 | use Text::Diff; 7 | 8 | my $clangfmt = shift or die; 9 | my $mode = shift or die; 10 | 11 | sub check { 12 | my ($file) = @_; 13 | my $original; 14 | my $formatted; 15 | 16 | $formatted = `$clangfmt -style=file "$file"`; 17 | 18 | if ($mode eq 'check') { 19 | local $/=undef; 20 | open FILE, "$file" or die "Couldn't open file: $file"; 21 | binmode FILE; 22 | $original = ; 23 | close FILE; 24 | 25 | my $diff = diff \$original, \$formatted; 26 | 27 | if ($diff ne "") { 28 | print "Style check using $clangfmt for file $file failed\n"; 29 | print $diff; 30 | die "Style check using $clangfmt for file $file failed\n"; 31 | } 32 | } elsif ($mode eq 'format') { 33 | local $/=undef; 34 | open FILE, '>', "$file" or die "Couldn't open file: $file"; 35 | print FILE "$formatted"; 36 | close FILE; 37 | } else { 38 | die 'unknown mode'; 39 | } 40 | } 41 | 42 | foreach(@ARGV) { 43 | check($_) 44 | } 45 | -------------------------------------------------------------------------------- /src/README.md: -------------------------------------------------------------------------------- 1 | pmemkv {#mainpage} 2 | =========================== 3 | 4 | Key/Value Datastore for Persistent Memory 5 | 6 | All general information about (lib)pmemkv can be found on the webstie: 7 | https://pmem.io/pmemkv 8 | 9 | Main code repository location: 10 | https://github.com/pmem/pmemkv 11 | (it contains full sources of all examples' snippets from this documentation) 12 | 13 | Here user can found description of C++ API. 14 | 15 | ### Important classes/functions ### 16 | 17 | * class pmem::kv::db, with its functions: 18 | * pmem::kv::db::open() to create/open file with data 19 | * pmem::kv::db::put() to insert data into database 20 | * pmem::kv::db::get() to read data back 21 | * pmem::kv::db::remove() to get rid of selected key (ant its value) 22 | * class pmem::kv::config to setup parameters to open/create database 23 | * class pmem::kv::tx for grouping operations into a single atomic action 24 | * class pmem::kv::db::iterator to iterate over records in db 25 | * enum class pmem::kv::status containing all possible statuses returned by 26 | most of public functions 27 | -------------------------------------------------------------------------------- /utils/docker/0001-travis-fix-travisci_build_coverity_scan.sh.patch: -------------------------------------------------------------------------------- 1 | From b5179dc4822eaab192361da05aa95d98f523960f Mon Sep 17 00:00:00 2001 2 | From: Lukasz Dorau 3 | Date: Mon, 7 May 2018 12:05:40 +0200 4 | Subject: [PATCH] travis: fix travisci_build_coverity_scan.sh 5 | 6 | --- 7 | travisci_build_coverity_scan.sh | 4 ++-- 8 | 1 file changed, 2 insertions(+), 2 deletions(-) 9 | 10 | diff --git a/travisci_build_coverity_scan.sh b/travisci_build_coverity_scan.sh 11 | index ad9d4afcf..562b08bcc 100644 12 | --- a/travisci_build_coverity_scan.sh 13 | +++ b/travisci_build_coverity_scan.sh 14 | @@ -92,8 +92,8 @@ response=$(curl \ 15 | --form description="Travis CI build" \ 16 | $UPLOAD_URL) 17 | status_code=$(echo "$response" | sed -n '$p') 18 | -if [ "$status_code" != "201" ]; then 19 | +if [ "$status_code" != "200" ]; then 20 | TEXT=$(echo "$response" | sed '$d') 21 | - echo -e "\033[33;1mCoverity Scan upload failed: $TEXT.\033[0m" 22 | + echo -e "\033[33;1mCoverity Scan upload failed: $response.\033[0m" 23 | exit 1 24 | fi 25 | -- 26 | 2.13.6 27 | 28 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | AccessModifierOffset: -8 2 | AlignOperands: false 3 | AllowShortBlocksOnASingleLine: false 4 | AllowShortFunctionsOnASingleLine: false 5 | AllowShortIfStatementsOnASingleLine: false 6 | AlwaysBreakAfterDefinitionReturnType: false 7 | AlwaysBreakTemplateDeclarations: true 8 | BasedOnStyle: LLVM 9 | BraceWrapping: 10 | AfterClass: false 11 | AfterControlStatement: false 12 | AfterEnum: false 13 | AfterFunction: true 14 | AfterNamespace: true 15 | AfterObjCDeclaration: false 16 | AfterStruct: false 17 | AfterUnion: false 18 | BeforeCatch: false 19 | BeforeElse: false 20 | IndentBraces: false 21 | BreakBeforeBraces: Custom 22 | BreakStringLiterals: false 23 | ColumnLimit: 90 24 | ConstructorInitializerAllOnOneLineOrOnePerLine: true 25 | ContinuationIndentWidth: 8 26 | FixNamespaceComments: false 27 | IndentCaseLabels: true 28 | IndentWidth: 8 29 | PointerAlignment: Right 30 | SpaceBeforeParens: ControlStatements 31 | SpacesBeforeTrailingComments: 1 32 | SpacesInContainerLiterals: false 33 | SpacesInCStyleCastParentheses: false 34 | UseTab: Always 35 | -------------------------------------------------------------------------------- /tests/engine_scenarios/all/error_handling_oom.cc: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2020-2021, Intel Corporation */ 3 | 4 | #include "unittest.hpp" 5 | 6 | static void OOM(pmem::kv::db &kv) 7 | { 8 | size_t cnt = 0; 9 | while (1) { 10 | auto s = kv.put(entry_from_number(cnt), 11 | entry_from_string(std::string(cnt + 1, 'a'))); 12 | if (s == pmem::kv::status::OUT_OF_MEMORY) 13 | break; 14 | 15 | ASSERT_STATUS(s, pmem::kv::status::OK); 16 | 17 | cnt++; 18 | } 19 | 20 | /* At least one iteration */ 21 | UT_ASSERT(cnt > 0); 22 | 23 | /* Start freeing elements from the smallest one */ 24 | for (size_t i = 0; i < cnt; i++) { 25 | auto s = kv.remove(entry_from_number(i)); 26 | ASSERT_STATUS(s, pmem::kv::status::OK); 27 | } 28 | 29 | ASSERT_SIZE(kv, 0); 30 | } 31 | 32 | static void test(int argc, char *argv[]) 33 | { 34 | if (argc < 3) 35 | UT_FATAL("usage: %s engine json_config", argv[0]); 36 | 37 | run_engine_tests(argv[1], argv[2], {OOM}); 38 | } 39 | 40 | int main(int argc, char *argv[]) 41 | { 42 | return run_test([&] { test(argc, argv); }); 43 | } 44 | -------------------------------------------------------------------------------- /utils/docker/images/README.md: -------------------------------------------------------------------------------- 1 | # Content 2 | 3 | Dockerfiles and scripts placed in this directory are intended to be used as 4 | development process vehicles and part of continuous integration process. 5 | 6 | Images built out of those recipes may by used with Docker or podman as 7 | development environment. 8 | Only those used on Travis are fully tested on a daily basis. 9 | In case of any problem, patches and github issues are welcome. 10 | 11 | # How to build docker image 12 | 13 | ```sh 14 | docker build --build-arg https_proxy=http://proxy.com:port --build-arg http_proxy=http://proxy.com:port -t pmemkv:debian-unstable -f ./Dockerfile.debian-unstable . 15 | ``` 16 | 17 | # How to use docker image 18 | 19 | To run build and tests on local machine on Docker: 20 | 21 | ```sh 22 | docker run --network=bridge --shm-size=4G -v /your/workspace/path/:/opt/workspace:z -w /opt/workspace/ -e CC=clang -e CXX=clang++ -e PKG_CONFIG_PATH=/opt/pmdk/lib/pkgconfig -it pmemkv:debian-unstable /bin/bash 23 | ``` 24 | 25 | To get strace working, add to Docker commandline 26 | 27 | ```sh 28 | --cap-add SYS_PTRACE 29 | ``` 30 | -------------------------------------------------------------------------------- /src/engines-testing/dram_vcmap.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2021, Intel Corporation */ 3 | 4 | #pragma once 5 | 6 | #include "../engines/basic_vcmap.h" 7 | 8 | namespace pmem 9 | { 10 | namespace kv 11 | { 12 | namespace internal 13 | { 14 | 15 | class std_allocator_factory { 16 | public: 17 | template 18 | using allocator_type = std::allocator; 19 | 20 | template 21 | static allocator_type create(internal::config& cfg) { 22 | return allocator_type(); 23 | } 24 | }; 25 | } /* namespace internal */ 26 | 27 | using dram_vcmap = basic_vcmap; 28 | 29 | class dram_vcmap_factory : public engine_base::factory_base { 30 | public: 31 | std::unique_ptr create(std::unique_ptr cfg) override 32 | { 33 | check_config_null(get_name(), cfg); 34 | return std::unique_ptr(new dram_vcmap(std::move(cfg))); 35 | }; 36 | std::string get_name() override 37 | { 38 | return "dram_vcmap"; 39 | }; 40 | }; 41 | 42 | } /* namespace kv */ 43 | } /* namespace pmem */ 44 | -------------------------------------------------------------------------------- /tests/config/deprecated_config.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2019-2021, Intel Corporation */ 3 | 4 | #include "unittest.h" 5 | 6 | /** 7 | * Tests deprecated config methods using C API 8 | */ 9 | 10 | static void deprecated_funcs_test() 11 | { 12 | /** 13 | * TEST: add and read data from config, using deprecated functions 14 | */ 15 | pmemkv_config *config = pmemkv_config_new(); 16 | UT_ASSERT(config != NULL); 17 | 18 | int ret = pmemkv_config_put_force_create(config, true); 19 | UT_ASSERTeq(ret, PMEMKV_STATUS_OK); 20 | 21 | uint64_t value_uint; 22 | ret = pmemkv_config_get_uint64(config, "create_or_error_if_exists", &value_uint); 23 | UT_ASSERTeq(ret, PMEMKV_STATUS_OK); 24 | UT_ASSERTeq(value_uint, 1); 25 | 26 | /* Check if not-deprecated function sets the same config field */ 27 | ret = pmemkv_config_put_create_or_error_if_exists(config, false); 28 | UT_ASSERTne(ret, PMEMKV_STATUS_OK); 29 | 30 | pmemkv_config_delete(config); 31 | config = NULL; 32 | } 33 | 34 | int main(int argc, char *argv[]) 35 | { 36 | START(); 37 | 38 | deprecated_funcs_test(); 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /tests/engine_scenarios/pmemobj/mock_tx_alloc.cc: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2017-2019, Intel Corporation */ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "mock_tx_alloc.h" 10 | 11 | thread_local bool tx_alloc_should_fail; 12 | 13 | extern "C" PMEMoid pmemobj_tx_alloc(size_t size, uint64_t type_num); 14 | 15 | PMEMoid pmemobj_tx_alloc(size_t size, uint64_t type_num) 16 | { 17 | static auto real = 18 | (decltype(pmemobj_tx_alloc) *)dlsym(RTLD_NEXT, "pmemobj_tx_alloc"); 19 | 20 | if (real == nullptr) 21 | abort(); 22 | 23 | if (tx_alloc_should_fail) { 24 | errno = ENOMEM; 25 | return OID_NULL; 26 | } 27 | 28 | return real(size, type_num); 29 | } 30 | 31 | PMEMoid pmemobj_tx_xalloc(size_t size, uint64_t type_num, uint64_t flags) 32 | { 33 | static auto real = 34 | (decltype(pmemobj_tx_xalloc) *)dlsym(RTLD_NEXT, "pmemobj_tx_xalloc"); 35 | 36 | if (real == nullptr) 37 | abort(); 38 | 39 | if (tx_alloc_should_fail) { 40 | errno = ENOMEM; 41 | return OID_NULL; 42 | } 43 | 44 | return real(size, type_num, flags); 45 | } 46 | -------------------------------------------------------------------------------- /cmake/cmake_uninstall.cmake.in: -------------------------------------------------------------------------------- 1 | # From: https://gitlab.kitware.com/cmake/community/wikis/FAQ 2 | 3 | if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") 4 | message(FATAL_ERROR "Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") 5 | endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") 6 | 7 | file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) 8 | string(REGEX REPLACE "\n" ";" files "${files}") 9 | foreach(file ${files}) 10 | message(STATUS "Uninstalling $ENV{DESTDIR}${file}") 11 | if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") 12 | exec_program("@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" 13 | OUTPUT_VARIABLE rm_out 14 | RETURN_VALUE rm_retval 15 | ) 16 | if(NOT "${rm_retval}" STREQUAL 0) 17 | message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}") 18 | endif(NOT "${rm_retval}" STREQUAL 0) 19 | else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") 20 | message(STATUS "File $ENV{DESTDIR}${file} does not exist.") 21 | endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") 22 | endforeach(file) 23 | -------------------------------------------------------------------------------- /tests/common/check_is_pmem.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2019-2020, Intel Corporation */ 3 | 4 | /* 5 | * check_is_pmem.cpp -- check if path points to a directory on pmem. 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | /* 13 | * return value is: 14 | * - 0 when path points to pmem 15 | * - 1 when path points to non-pmem 16 | * - 2 when error occurred 17 | */ 18 | int main(int argc, char *argv[]) 19 | { 20 | if (argc != 2) { 21 | std::cerr << "usage: " << argv[0] << " filepath\n"; 22 | return 2; 23 | } 24 | 25 | auto path = argv[1]; 26 | 27 | int is_pmem; 28 | size_t size; 29 | int flags = PMEM_FILE_CREATE; 30 | 31 | #ifdef _WIN32 32 | void *addr = pmem_map_fileU(path, 4096, flags, 0, &size, &is_pmem); 33 | #else 34 | void *addr = pmem_map_file(path, 4096, flags, 0, &size, &is_pmem); 35 | #endif 36 | if (addr == nullptr) { 37 | perror("pmem_map_file failed"); 38 | return 2; 39 | } 40 | 41 | pmem_unmap(addr, size); 42 | if (remove(path) != 0) { 43 | perror("remove(path) failed"); 44 | return 2; 45 | } 46 | 47 | if (is_pmem) 48 | return 0; 49 | else 50 | return 1; 51 | } 52 | -------------------------------------------------------------------------------- /tests/engine_scenarios/persistent/not_found_verify.cc: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2020-2021, Intel Corporation */ 3 | 4 | #include "unittest.hpp" 5 | 6 | using namespace pmem::kv; 7 | 8 | static void insert(pmem::kv::db &kv) 9 | { 10 | ASSERT_STATUS(kv.put(entry_from_string("tmpkey"), entry_from_string("tmpval1")), 11 | status::OK); 12 | } 13 | 14 | static void check(pmem::kv::db &kv) 15 | { 16 | std::string key = entry_from_string("tmpkey"); 17 | ASSERT_STATUS(kv.remove(key), status::OK); 18 | std::string value; 19 | ASSERT_STATUS(kv.get(key, &value), status::NOT_FOUND); 20 | } 21 | 22 | static void test(int argc, char *argv[]) 23 | { 24 | if (argc < 4) 25 | UT_FATAL("usage: %s engine json_config insert/check", argv[0]); 26 | 27 | std::string mode = argv[3]; 28 | if (mode != "insert" && mode != "check") 29 | UT_FATAL("usage: %s engine json_config insert/check", argv[0]); 30 | 31 | auto kv = INITIALIZE_KV(argv[1], CONFIG_FROM_JSON(argv[2])); 32 | 33 | if (mode == "insert") { 34 | insert(kv); 35 | } else { 36 | check(kv); 37 | } 38 | 39 | kv.close(); 40 | } 41 | 42 | int main(int argc, char *argv[]) 43 | { 44 | return run_test([&] { test(argc, argv); }); 45 | } 46 | -------------------------------------------------------------------------------- /.github/workflows/coverity.yml: -------------------------------------------------------------------------------- 1 | 2 | name: pmemkv-coverity 3 | # It runs static analysis build - Coverity. It requires special token (set in CI's secret). 4 | 5 | # Run this job at 00:00 UTC once a month; but also allow manual trigger. 6 | on: 7 | workflow_dispatch: 8 | schedule: 9 | - cron: '0 0 1 * *' 10 | 11 | env: 12 | REPO: pmemkv 13 | GITHUB_REPO: pmem/pmemkv 14 | CONTAINER_REG: ghcr.io/pmem/pmemkv 15 | HOST_WORKDIR: ${{ github.workspace }} 16 | WORKDIR: utils/docker 17 | IMG_VER: latest 18 | COVERITY_SCAN_NOTIFICATION_EMAIL: ${{ secrets.COVERITY_SCAN_NOTIFICATION_EMAIL }} 19 | COVERITY_SCAN_TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }} 20 | 21 | jobs: 22 | linux: 23 | name: Linux-coverity 24 | runs-on: ubuntu-latest 25 | strategy: 26 | matrix: 27 | CONFIG: ["TYPE=coverity OS=ubuntu OS_VER=20.04"] 28 | steps: 29 | - name: Clone the git repo 30 | uses: actions/checkout@v2 31 | 32 | # coverity workflow should just reuse (pull) the most recent, available image 33 | - name: Pull the image 34 | run: cd $WORKDIR && ${{ matrix.CONFIG }} ./pull-or-rebuild-image.sh pull 35 | 36 | - name: Run the build 37 | run: cd $WORKDIR && ${{ matrix.CONFIG }} ./build.sh 38 | -------------------------------------------------------------------------------- /tests/engine_scenarios/pmemobj/error_handling_tx_oid.cc: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2020, Intel Corporation */ 3 | 4 | #include "error_handling_tx.hpp" 5 | 6 | #include 7 | #include 8 | 9 | struct Root { 10 | PMEMoid oid; 11 | }; 12 | 13 | static void test(int argc, char *argv[]) 14 | { 15 | using namespace std::placeholders; 16 | 17 | if (argc < 3) 18 | UT_FATAL("usage: %s engine path", argv[0]); 19 | 20 | auto pmemobj_pool_path = std::string(argv[2]); 21 | pmem::obj::pool pmemobj_pool; 22 | 23 | auto layout = std::string("pmemkv"); 24 | auto engine = std::string(argv[1]); 25 | if (engine != "cmap") 26 | layout = "pmemkv_" + engine; 27 | 28 | try { 29 | pmemobj_pool = pmem::obj::pool::open(pmemobj_pool_path, layout); 30 | } catch (std::exception &e) { 31 | UT_FATALexc(e); 32 | } 33 | 34 | pmem::kv::config cfg; 35 | auto s = cfg.put_oid(&(pmemobj_pool.root()->oid)); 36 | 37 | ASSERT_STATUS(s, status::OK); 38 | 39 | { 40 | auto kv = INITIALIZE_KV(engine, std::move(cfg)); 41 | 42 | TransactionTest(pmemobj_pool, kv); 43 | } 44 | 45 | pmemobj_pool.close(); 46 | } 47 | 48 | int main(int argc, char *argv[]) 49 | { 50 | return run_test([&] { test(argc, argv); }); 51 | } 52 | -------------------------------------------------------------------------------- /utils/docker/images/build-image.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | # Copyright 2016-2021, Intel Corporation 4 | # 5 | # build-image.sh - prepares a Docker image with -based environment for 6 | # testing (or dev) purpose, tagged with ${CONTAINER_REG}:${OS}-${OS_VER}-${IMG_VER}, 7 | # according to the Dockerfile.${OS}-${OS_VER} file located in the same directory. 8 | # IMG_VER is a version of docker image (it usually relates to project's release tag) 9 | # and it defaults to "devel". 10 | # 11 | 12 | set -e 13 | IMG_VER=${IMG_VER:-devel} 14 | TAG="${OS}-${OS_VER}-${IMG_VER}" 15 | 16 | if [[ -z "${OS}" || -z "${OS_VER}" ]]; then 17 | echo "ERROR: The variables OS and OS_VER have to be set " \ 18 | "(e.g. OS=fedora, OS_VER=32)." 19 | exit 1 20 | fi 21 | 22 | if [[ -z "${CONTAINER_REG}" ]]; then 23 | echo "ERROR: CONTAINER_REG environment variable is not set " \ 24 | "(e.g. \"//\")." 25 | exit 1 26 | fi 27 | 28 | echo "Check if the file Dockerfile.${OS}-${OS_VER} exists" 29 | if [[ ! -f "Dockerfile.${OS}-${OS_VER}" ]]; then 30 | echo "Error: Dockerfile.${OS}-${OS_VER} does not exist." 31 | exit 1 32 | fi 33 | 34 | echo "Build a Docker image tagged with: ${CONTAINER_REG}:${TAG}" 35 | docker build -t ${CONTAINER_REG}:${TAG} \ 36 | --build-arg http_proxy=$http_proxy \ 37 | --build-arg https_proxy=$https_proxy \ 38 | -f Dockerfile.${OS}-${OS_VER} . 39 | -------------------------------------------------------------------------------- /utils/docker/images/install-pmdk.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | # Copyright 2019-2022, Intel Corporation 4 | 5 | # 6 | # install-pmdk.sh [package_type] - installs PMDK 7 | # from DEB/RPM packages if possible. 8 | # 9 | 10 | set -e 11 | 12 | if [ "${SKIP_PMDK_BUILD}" ]; then 13 | echo "Variable 'SKIP_PMDK_BUILD' is set; skipping building PMDK" 14 | exit 15 | fi 16 | 17 | PACKAGE_TYPE=${1} 18 | PREFIX=${2:-/usr} 19 | 20 | # master: Merge pull request #5399 from kilobyte/codespell, 24.01.2022 21 | # It contains fix for recognizing AlmaLinux as proper distro 22 | PMDK_VERSION="43aa506db217c7dd2d98090a525306c3ab45f9cf" 23 | 24 | git clone https://github.com/pmem/pmdk 25 | cd pmdk 26 | git checkout ${PMDK_VERSION} 27 | 28 | if [ "${PACKAGE_TYPE}" = "" ]; then 29 | make DOC=n -j$(nproc) install prefix=${PREFIX} 30 | else 31 | make -j$(nproc) BUILD_PACKAGE_CHECK=n ${PACKAGE_TYPE} 32 | if [ "${PACKAGE_TYPE}" = "dpkg" ]; then 33 | sudo dpkg -i dpkg/libpmem_*.deb dpkg/libpmem-dev_*.deb \ 34 | dpkg/libpmemobj_*.deb dpkg/libpmemobj-dev_*.deb \ 35 | dpkg/pmreorder_*.deb dpkg/libpmempool_*.deb dpkg/libpmempool-dev_*.deb \ 36 | dpkg/libpmemblk_*.deb dpkg/libpmemlog_*.deb dpkg/pmempool_*.deb 37 | elif [ "${PACKAGE_TYPE}" = "rpm" ]; then 38 | sudo rpm -i rpm/*/pmdk-debuginfo-*.rpm \ 39 | rpm/*/libpmem*-*.rpm \ 40 | rpm/*/pmreorder-*.rpm \ 41 | rpm/*/pmempool-*.rpm 42 | fi 43 | fi 44 | 45 | cd .. 46 | rm -r pmdk 47 | -------------------------------------------------------------------------------- /tests/README.md: -------------------------------------------------------------------------------- 1 | # Content 2 | 3 | This directory contains tests for pmemkv. They are grouped into directories: 4 | 5 | - **c_api** - most of pmemkv's tests use C++ API, these tests use only C API 6 | - **compatibility** - compatibility checks between different pmemkv versions 7 | - **config** - tests for all functions in config's API 8 | - **engine_scenarios** - test scenarios parameterized with at least engine name; 9 | they are grouped into sub-sections related to specific group of engines' capabilities 10 | - **engines** - tests and scripts related to pmemkv's engines 11 | - **engines-experimental** - tests and scripts related to experimental engines 12 | - and additional test(s) in main directory 13 | 14 | # Tests execution 15 | 16 | Before executing tests it's required to build pmemkv's sources and tests. 17 | See [INSTALLING.md](../INSTALLING.md) for details. There are CMake's options related 18 | to tests - see all options in top-level CMakeLists.txt with prefix `TESTS_`. 19 | One of them - `TESTS_USE_FORCED_PMEM=ON` speeds up tests execution on emulated pmem. 20 | It's useful for long (e.g. concurrent) tests. 21 | 22 | To run all tests execute: 23 | 24 | ```sh 25 | make test 26 | ``` 27 | 28 | or, if you want to see an output/logs of failed tests, run: 29 | 30 | ```sh 31 | ctest --output-on-failure 32 | ``` 33 | 34 | There are other parameters to use in `ctest` command. 35 | To see the full list read [ctest(1) manpage](https://cmake.org/cmake/help/latest/manual/ctest.1.html). 36 | -------------------------------------------------------------------------------- /src/fast_hash.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The fast-hash algorithm is covered by the MIT License: 3 | * 4 | * Copyright (C) 2012 Zilong Tan (eric.zltan@gmail.com) 5 | * 6 | * Permission is hereby granted, free of charge, to any person 7 | * obtaining a copy of this software and associated documentation 8 | * files (the "Software"), to deal in the Software without 9 | * restriction, including without limitation the rights to use, copy, 10 | * modify, merge, publish, distribute, sublicense, and/or sell copies 11 | * of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be 15 | * included in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 21 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 22 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #ifndef FAST_HASH_H 28 | #define FAST_HASH_H 29 | 30 | #include 31 | #include 32 | uint64_t fast_hash(size_t key_size, const char *key); 33 | 34 | #endif /* FAST_HASH_H */ 35 | -------------------------------------------------------------------------------- /src/engines/vcmap.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2017-2021, Intel Corporation */ 3 | 4 | #ifndef LIBPMEMKV_VCMAP_H 5 | #define LIBPMEMKV_VCMAP_H 6 | 7 | #include "basic_vcmap.h" 8 | #include "memkind_allocator_wrapper.h" 9 | 10 | namespace pmem 11 | { 12 | namespace kv 13 | { 14 | namespace internal 15 | { 16 | 17 | class memkind_allocator_factory { 18 | public: 19 | template 20 | using allocator_type = internal::memkind_allocator_wrapper; 21 | 22 | template 23 | using wrapped_type = typename allocator_type::allocator_type; 24 | 25 | template 26 | static allocator_type create(internal::config &cfg) 27 | { 28 | auto *allocator_ptr = new wrapped_type(cfg.get_path(), cfg.get_size()); 29 | 30 | cfg.put_object("allocator", allocator_ptr, [](void *arg) { 31 | delete reinterpret_cast *>(arg); 32 | }); 33 | 34 | return allocator_type(allocator_ptr); 35 | } 36 | }; 37 | } 38 | 39 | using vcmap = basic_vcmap; 40 | 41 | class vcmap_factory : public engine_base::factory_base { 42 | public: 43 | virtual std::unique_ptr create(std::unique_ptr cfg) 44 | { 45 | check_config_null(get_name(), cfg); 46 | return std::unique_ptr(new vcmap(std::move(cfg))); 47 | }; 48 | virtual std::string get_name() 49 | { 50 | return "vcmap"; 51 | }; 52 | }; 53 | 54 | } /* namespace kv */ 55 | } /* namespace pmem */ 56 | 57 | #endif /* LIBPMEMKV_VCMAP_H */ 58 | -------------------------------------------------------------------------------- /utils/md2man/md2man.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | # Copyright 2016-2021, Intel Corporation 4 | # 5 | 6 | # 7 | # md2man.sh -- convert markdown to groff man pages 8 | # 9 | # usage: md2man.sh file template outfile 10 | # 11 | # This script converts markdown file into groff man page using pandoc. 12 | # It performs some pre- and post-processing for better results: 13 | # - parse input file for YAML metadata block and read man page title, 14 | # section and version 15 | # - cut-off metadata block and license 16 | # - unindent code blocks 17 | # 18 | 19 | set -e 20 | set -o pipefail 21 | 22 | filename=$1 23 | template=$2 24 | outfile=$3 25 | version=$4 26 | title=`sed -n 's/^title:\ _MP(*\([A-Za-z_-]*\).*$/\1/p' $filename` 27 | section=`sed -n 's/^title:.*\([0-9]\))$/\1/p' $filename` 28 | secondary_title=`sed -n 's/^secondary_title:\ *\(.*\)$/\1/p' $filename` 29 | 30 | dt="$(date --utc --date="@${SOURCE_DATE_EPOCH:-$(date +%s)}" +%F)" 31 | year="$(date --utc --date="@${SOURCE_DATE_EPOCH:-$(date +%s)}" +%Y)" 32 | # since generated docs are not kept in the repo the output dir may not exist 33 | out_dir=`echo $outfile | sed 's/\(.*\)\/.*/\1/'` 34 | mkdir -p $out_dir 35 | 36 | cat $filename | sed -n -e '/# NAME #/,$p' |\ 37 | pandoc -s -t man -o $outfile --template=$template \ 38 | -V title=$title -V section=$section \ 39 | -V date="$dt" -V version="$version" \ 40 | -V year="$year" -V secondary_title="$secondary_title" | 41 | sed '/^\.IP/{ 42 | N 43 | /\n\.nf/{ 44 | s/IP/PP/ 45 | } 46 | }' 47 | -------------------------------------------------------------------------------- /tests/engine_scenarios/pmemobj/put_get_std_map_oid.cc: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2020, Intel Corporation */ 3 | 4 | #include "../put_get_std_map.hpp" 5 | 6 | #include 7 | #include 8 | 9 | struct Root { 10 | PMEMoid oid; 11 | }; 12 | 13 | static void test(int argc, char *argv[]) 14 | { 15 | using namespace std::placeholders; 16 | 17 | if (argc < 6) 18 | UT_FATAL("usage: %s engine path n_inserts key_length value_length", 19 | argv[0]); 20 | 21 | auto n_inserts = std::stoull(argv[3]); 22 | auto key_length = std::stoull(argv[4]); 23 | auto value_length = std::stoull(argv[5]); 24 | 25 | auto pmemobj_pool_path = std::string(argv[2]); 26 | pmem::obj::pool pmemobj_pool; 27 | 28 | auto layout = std::string("pmemkv"); 29 | auto engine = std::string(argv[1]); 30 | if (engine != "cmap") 31 | layout = "pmemkv_" + engine; 32 | 33 | try { 34 | pmemobj_pool = pmem::obj::pool::open(pmemobj_pool_path, layout); 35 | } catch (std::exception &e) { 36 | UT_FATALexc(e); 37 | } 38 | 39 | pmem::kv::config cfg; 40 | auto s = cfg.put_oid(&pmemobj_pool.root()->oid); 41 | ASSERT_STATUS(s, status::OK); 42 | 43 | auto kv = INITIALIZE_KV(engine, std::move(cfg)); 44 | 45 | auto proto = PutToMapTest(n_inserts, key_length, value_length, kv); 46 | VerifyKv(proto, kv); 47 | 48 | kv.close(); 49 | 50 | pmemobj_pool.close(); 51 | } 52 | 53 | int main(int argc, char *argv[]) 54 | { 55 | return run_test([&] { test(argc, argv); }); 56 | } 57 | -------------------------------------------------------------------------------- /src/iterator.cc: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2020, Intel Corporation */ 3 | 4 | #include "iterator.h" 5 | 6 | namespace pmem 7 | { 8 | namespace kv 9 | { 10 | namespace internal 11 | { 12 | 13 | status iterator_base::seek_lower(string_view key) 14 | { 15 | return status::NOT_SUPPORTED; 16 | } 17 | 18 | status iterator_base::seek_lower_eq(string_view key) 19 | { 20 | return status::NOT_SUPPORTED; 21 | } 22 | 23 | status iterator_base::seek_higher(string_view key) 24 | { 25 | return status::NOT_SUPPORTED; 26 | } 27 | 28 | status iterator_base::seek_higher_eq(string_view key) 29 | { 30 | return status::NOT_SUPPORTED; 31 | } 32 | 33 | status iterator_base::seek_to_first() 34 | { 35 | return status::NOT_SUPPORTED; 36 | } 37 | 38 | status iterator_base::seek_to_last() 39 | { 40 | return status::NOT_SUPPORTED; 41 | } 42 | 43 | status iterator_base::is_next() 44 | { 45 | return status::NOT_SUPPORTED; 46 | } 47 | 48 | status iterator_base::next() 49 | { 50 | return status::NOT_SUPPORTED; 51 | } 52 | 53 | status iterator_base::prev() 54 | { 55 | return status::NOT_SUPPORTED; 56 | } 57 | 58 | result> iterator_base::write_range(size_t pos, size_t n) 59 | { 60 | return {status::NOT_SUPPORTED}; 61 | } 62 | 63 | status iterator_base::commit() 64 | { 65 | return status::NOT_SUPPORTED; 66 | } 67 | 68 | void iterator_base::abort() 69 | { 70 | /* by default NOT_SUPPORTED */ 71 | } 72 | 73 | void iterator_base::init_seek() 74 | { 75 | abort(); 76 | } 77 | 78 | } /* namespace internal */ 79 | } /* namespace kv */ 80 | } /* namespace pmem */ 81 | -------------------------------------------------------------------------------- /utils/docker/images/install-libndctl.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | # Copyright 2018-2021, Intel Corporation 4 | 5 | # 6 | # install-libndctl.sh - installs libndctl 7 | # 8 | 9 | set -e 10 | 11 | OS=$1 12 | 13 | echo "==== clone ndctl repo ====" 14 | git clone https://github.com/pmem/ndctl.git 15 | cd ndctl 16 | git checkout v69 17 | 18 | if [ "$OS" = "fedora" ]; then 19 | echo "==== setup rpmbuild tree ====" 20 | rpmdev-setuptree 21 | 22 | RPMDIR=$HOME/rpmbuild/ 23 | VERSION=$(./git-version) 24 | SPEC=./rhel/ndctl.spec 25 | 26 | echo "==== create source tarball =====" 27 | git archive --format=tar --prefix="ndctl-${VERSION}/" HEAD | gzip > "$RPMDIR/SOURCES/ndctl-${VERSION}.tar.gz" 28 | 29 | echo "==== build ndctl ====" 30 | ./autogen.sh 31 | ./configure --disable-docs 32 | make -j$(nproc) 33 | 34 | echo "==== build ndctl packages ====" 35 | rpmbuild -ba $SPEC 36 | 37 | echo "==== install ndctl packages ====" 38 | rpm -i $RPMDIR/RPMS/x86_64/*.rpm 39 | 40 | echo "==== cleanup ====" 41 | rm -rf $RPMDIR 42 | else 43 | echo "==== set OS-specific options ====" 44 | OS_SPECIFIC="" 45 | LIBDIR=/usr/lib 46 | case $(echo $OS | cut -d'-' -f1) in 47 | centos|opensuse) 48 | LIBDIR=/usr/lib64 49 | ;; 50 | archlinux) 51 | OS_SPECIFIC="--disable-dependency-tracking" 52 | ;; 53 | esac 54 | 55 | echo "==== build ndctl ====" 56 | ./autogen.sh 57 | ./configure --libdir=$LIBDIR --disable-docs $OS_SPECIFIC 58 | make -j$(nproc) 59 | 60 | echo "==== install ndctl ====" 61 | make -j$(nproc) install 62 | 63 | echo "==== cleanup ====" 64 | fi 65 | 66 | cd .. 67 | rm -rf ndctl 68 | -------------------------------------------------------------------------------- /utils/docker/images/install-libpmemobj-cpp.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | # Copyright 2019-2022, Intel Corporation 4 | 5 | # 6 | # install-libpmemobj-cpp.sh [package_type] 7 | # - installs PMDK C++ bindings (libpmemobj-cpp) 8 | # 9 | 10 | set -e 11 | 12 | if [ "${SKIP_LIBPMEMOBJCPP_BUILD}" ]; then 13 | echo "Variable 'SKIP_LIBPMEMOBJCPP_BUILD' is set; skipping building libpmemobj-cpp" 14 | exit 15 | fi 16 | 17 | PREFIX="/usr" 18 | PACKAGE_TYPE=${1^^} #To uppercase 19 | echo "PACKAGE_TYPE: ${PACKAGE_TYPE}" 20 | 21 | # master: Merge pull request #1242 from lukaszstolarczuk/docs-update, 28.01.2022 22 | # It contains fix for gcc-12 in radix_tree 23 | LIBPMEMOBJ_CPP_VERSION="7e59f08f65d6d67cd893f4c6b7c1141a04f28ac3" 24 | echo "LIBPMEMOBJ_CPP_VERSION: ${LIBPMEMOBJ_CPP_VERSION}" 25 | 26 | build_dir=$(mktemp -d -t libpmemobj-cpp-XXX) 27 | 28 | git clone https://github.com/pmem/libpmemobj-cpp --shallow-since=2020-06-01 ${build_dir} 29 | 30 | pushd ${build_dir} 31 | git checkout ${LIBPMEMOBJ_CPP_VERSION} 32 | 33 | mkdir build 34 | cd build 35 | 36 | # turn off all redundant components 37 | cmake .. -DCPACK_GENERATOR="${PACKAGE_TYPE}" -DCMAKE_INSTALL_PREFIX=${PREFIX} \ 38 | -DBUILD_EXAMPLES=OFF -DBUILD_TESTS=OFF -DBUILD_DOC=OFF -DBUILD_BENCHMARKS=OFF \ 39 | -DTESTS_USE_VALGRIND=OFF 40 | 41 | if [ "${PACKAGE_TYPE}" = "" ]; then 42 | make -j$(nproc) install 43 | else 44 | make -j$(nproc) package 45 | if [ "${PACKAGE_TYPE}" = "DEB" ]; then 46 | sudo dpkg -i libpmemobj++*.deb 47 | elif [ "${PACKAGE_TYPE}" = "RPM" ]; then 48 | sudo rpm -iv libpmemobj++*.rpm 49 | fi 50 | fi 51 | 52 | popd 53 | rm -r ${build_dir} 54 | -------------------------------------------------------------------------------- /tests/engine_scenarios/pmreorder/recover.cc: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2021, Intel Corporation */ 3 | 4 | /* 5 | * recover.cc -- recover pmreorder test 6 | */ 7 | 8 | #include "unittest.hpp" 9 | 10 | static void check_consistency(std::string engine, std::string config) 11 | { 12 | auto kv = INITIALIZE_KV(engine, CONFIG_FROM_JSON(config)); 13 | ASSERT_SIZE(kv, 0); 14 | 15 | const size_t elements_cnt = 100; 16 | for (size_t i = 0; i < elements_cnt; ++i) 17 | ASSERT_STATUS(kv.put(entry_from_number(i, "", "key"), 18 | entry_from_number(i, "", "val")), 19 | pmem::kv::status::OK); 20 | 21 | ASSERT_SIZE(kv, elements_cnt); 22 | 23 | for (size_t i = 0; i < elements_cnt; ++i) { 24 | std::string val; 25 | ASSERT_STATUS(kv.get(entry_from_number(i, "", "key"), &val), 26 | pmem::kv::status::OK); 27 | UT_ASSERT(val == entry_from_number(i, "", "val")); 28 | 29 | ASSERT_STATUS(kv.remove(entry_from_number(i, "", "key")), 30 | pmem::kv::status::OK); 31 | } 32 | 33 | ASSERT_SIZE(kv, 0); 34 | kv.close(); 35 | } 36 | 37 | static void test(int argc, char *argv[]) 38 | { 39 | if (argc < 4) 40 | UT_FATAL("usage: %s engine json_config ", argv[0]); 41 | 42 | std::string mode = argv[3]; 43 | if (mode != "open" && mode != "create") 44 | UT_FATAL("usage: %s engine json_config ", argv[0]); 45 | 46 | if (mode == "open") { 47 | check_consistency(argv[1], argv[2]); 48 | } else if (mode == "create") { 49 | INITIALIZE_KV(argv[1], CONFIG_FROM_JSON(argv[2])); 50 | } 51 | } 52 | 53 | int main(int argc, char *argv[]) 54 | { 55 | return run_test([&] { test(argc, argv); }); 56 | } 57 | -------------------------------------------------------------------------------- /src/exceptions.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2019-2020, Intel Corporation */ 3 | 4 | #ifndef LIBPMEMKV_EXCEPTIONS_H 5 | #define LIBPMEMKV_EXCEPTIONS_H 6 | 7 | #include 8 | 9 | #include "libpmemkv.h" 10 | 11 | namespace pmem 12 | { 13 | namespace kv 14 | { 15 | namespace internal 16 | { 17 | 18 | struct error : std::runtime_error { 19 | error(const std::string &msg, int status_code = PMEMKV_STATUS_UNKNOWN_ERROR) 20 | : std::runtime_error(msg), status_code(status_code) 21 | { 22 | } 23 | int status_code; 24 | }; 25 | 26 | struct not_supported : error { 27 | not_supported(const std::string &msg) : error(msg, PMEMKV_STATUS_NOT_SUPPORTED) 28 | { 29 | } 30 | }; 31 | 32 | struct invalid_argument : error { 33 | invalid_argument(const std::string &msg) 34 | : error(msg, PMEMKV_STATUS_INVALID_ARGUMENT) 35 | { 36 | } 37 | }; 38 | 39 | struct config_parsing_error : error { 40 | config_parsing_error(const std::string &msg) 41 | : error(msg, PMEMKV_STATUS_CONFIG_PARSING_ERROR) 42 | { 43 | } 44 | }; 45 | 46 | struct config_type_error : error { 47 | config_type_error(const std::string &msg) 48 | : error(msg, PMEMKV_STATUS_CONFIG_TYPE_ERROR) 49 | { 50 | } 51 | }; 52 | 53 | struct wrong_engine_name : error { 54 | wrong_engine_name(const std::string &msg) 55 | : error(msg, PMEMKV_STATUS_WRONG_ENGINE_NAME) 56 | { 57 | } 58 | }; 59 | 60 | struct comparator_mismatch : error { 61 | comparator_mismatch(const std::string &msg) 62 | : error(msg, PMEMKV_STATUS_COMPARATOR_MISMATCH) 63 | { 64 | } 65 | }; 66 | 67 | } /* namespace internal */ 68 | } /* namespace kv */ 69 | } /* namespace pmem */ 70 | 71 | #endif /* LIBPMEMKV_EXCEPTIONS_H */ 72 | -------------------------------------------------------------------------------- /tests/engine_scenarios/persistent/put_verify_desc_params.cc: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2020-2021, Intel Corporation */ 3 | 4 | #include "unittest.hpp" 5 | 6 | using namespace pmem::kv; 7 | 8 | static void insert(const size_t iterations, pmem::kv::db &kv) 9 | { 10 | for (size_t i = iterations; i >= 1; i--) { 11 | auto key = entry_from_number(i); 12 | auto expected_value = entry_from_number(i, "ABC"); 13 | ASSERT_STATUS(kv.put(key, expected_value), status::OK); 14 | std::string value; 15 | ASSERT_STATUS(kv.get(key, &value), status::OK); 16 | UT_ASSERT(value == expected_value); 17 | } 18 | } 19 | static void check(const size_t iterations, pmem::kv::db &kv) 20 | { 21 | for (size_t i = iterations; i >= 1; i--) { 22 | auto key = entry_from_number(i); 23 | auto expected_value = entry_from_number(i, "ABC"); 24 | std::string value; 25 | ASSERT_STATUS(kv.get(key, &value), status::OK); 26 | UT_ASSERT(value == expected_value); 27 | } 28 | ASSERT_SIZE(kv, iterations); 29 | } 30 | 31 | static void test(int argc, char *argv[]) 32 | { 33 | if (argc < 5) 34 | UT_FATAL("usage: %s engine json_config insert/check iterations", argv[0]); 35 | 36 | std::string mode = argv[3]; 37 | if (mode != "insert" && mode != "check") 38 | UT_FATAL("usage: %s engine json_config insert/check iterations", argv[0]); 39 | 40 | auto iterations = std::stoull(argv[4]); 41 | 42 | auto kv = INITIALIZE_KV(argv[1], CONFIG_FROM_JSON(argv[2])); 43 | 44 | if (mode == "insert") { 45 | insert(iterations, kv); 46 | } else { 47 | check(iterations, kv); 48 | } 49 | 50 | kv.close(); 51 | } 52 | 53 | int main(int argc, char *argv[]) 54 | { 55 | return run_test([&] { test(argc, argv); }); 56 | } 57 | -------------------------------------------------------------------------------- /tests/engine_scenarios/all/put_get_remove_long_key.cc: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2017-2021, Intel Corporation */ 3 | 4 | #include "unittest.hpp" 5 | 6 | using namespace pmem::kv; 7 | 8 | static void PutKeysOfDifferentSizesTest(pmem::kv::db &kv) 9 | { 10 | std::string value; 11 | ASSERT_STATUS(kv.put("123456789ABCDE", "A"), status::OK); 12 | ASSERT_SIZE(kv, 1); 13 | ASSERT_STATUS(kv.get("123456789ABCDE", &value), status::OK); 14 | UT_ASSERT(value == "A"); 15 | 16 | std::string value2; 17 | ASSERT_STATUS(kv.put("123456789ABCDEF", "B"), status::OK); 18 | ASSERT_SIZE(kv, 2); 19 | ASSERT_STATUS(kv.get("123456789ABCDEF", &value2), status::OK); 20 | UT_ASSERT(value2 == "B"); 21 | 22 | std::string value3; 23 | ASSERT_STATUS(kv.put("12345678ABCDEFG", "C"), status::OK); 24 | ASSERT_SIZE(kv, 3); 25 | ASSERT_STATUS(kv.get("12345678ABCDEFG", &value3), status::OK); 26 | UT_ASSERT(value3 == "C"); 27 | 28 | std::string value4; 29 | ASSERT_STATUS(kv.put("123456789", "D"), status::OK); 30 | ASSERT_SIZE(kv, 4); 31 | ASSERT_STATUS(kv.get("123456789", &value4), status::OK); 32 | UT_ASSERT(value4 == "D"); 33 | 34 | std::string value5; 35 | ASSERT_STATUS(kv.put("123456789ABCDEFGHI", "E"), status::OK); 36 | ASSERT_SIZE(kv, 5); 37 | ASSERT_STATUS(kv.get("123456789ABCDEFGHI", &value5), status::OK); 38 | UT_ASSERT(value5 == "E"); 39 | } 40 | 41 | static void test(int argc, char *argv[]) 42 | { 43 | if (argc < 3) 44 | UT_FATAL("usage: %s engine json_config", argv[0]); 45 | 46 | run_engine_tests(argv[1], argv[2], 47 | { 48 | PutKeysOfDifferentSizesTest, 49 | }); 50 | } 51 | 52 | int main(int argc, char *argv[]) 53 | { 54 | return run_test([&] { test(argc, argv); }); 55 | } 56 | -------------------------------------------------------------------------------- /tests/engine_scenarios/put_get_std_map.hpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2020-2021, Intel Corporation */ 3 | 4 | #include "unittest.hpp" 5 | 6 | #include 7 | #include 8 | 9 | using namespace pmem::kv; 10 | 11 | template 12 | std::map PutToMapTest(size_t n_inserts, size_t key_length, 13 | size_t value_length, Inserter &kv) 14 | { 15 | /** 16 | * Test: Put data into db and get it back 17 | */ 18 | std::map proto_dictionary; 19 | for (size_t i = 0; i < n_inserts; i++) { 20 | std::string key = std::to_string(i); 21 | if (key_length > key.length()) 22 | key += std::string(key_length - key.length(), '0'); 23 | 24 | std::string val = std::to_string(i); 25 | if (value_length > val.length()) 26 | val += std::string(value_length - val.length(), '0'); 27 | 28 | proto_dictionary[key] = val; 29 | } 30 | 31 | /* Put data into db */ 32 | for (const auto &record : proto_dictionary) { 33 | const auto &key = record.first; 34 | const auto &val = record.second; 35 | 36 | auto s = kv.put(key, val); 37 | ASSERT_STATUS(s, status::OK); 38 | } 39 | 40 | return proto_dictionary; 41 | } 42 | 43 | void VerifyKv(const std::map &prototype, pmem::kv::db &kv) 44 | { 45 | ASSERT_SIZE(kv, prototype.size()); 46 | 47 | /* Retrieve data from db and compare with prototype */ 48 | for (const auto &record : prototype) { 49 | const auto &key = record.first; 50 | const auto &val = record.second; 51 | 52 | auto s = kv.get(key, [&](string_view value) { 53 | UT_ASSERTeq(value.compare(val), 0); 54 | }); 55 | ASSERT_STATUS(s, status::OK); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /tests/engine_scenarios/persistent/put_verify_asc_params.cc: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2020-2021, Intel Corporation */ 3 | 4 | #include "unittest.hpp" 5 | 6 | using namespace pmem::kv; 7 | 8 | static void insert(const size_t iterations, pmem::kv::db &kv) 9 | { 10 | for (size_t i = 1; i <= iterations; i++) { 11 | auto key = entry_from_number(i); 12 | auto expected_value = entry_from_number(i, "", "!"); 13 | ASSERT_STATUS(kv.put(key, expected_value), status::OK); 14 | std::string value; 15 | ASSERT_STATUS(kv.get(key, &value), status::OK); 16 | UT_ASSERT(value == expected_value); 17 | } 18 | } 19 | 20 | static void check(const size_t iterations, pmem::kv::db &kv) 21 | { 22 | for (size_t i = 1; i <= iterations; i++) { 23 | auto key = entry_from_number(i); 24 | auto expected_value = entry_from_number(i, "", "!"); 25 | std::string value; 26 | ASSERT_STATUS(kv.get(key, &value), status::OK); 27 | UT_ASSERT(value == expected_value); 28 | } 29 | ASSERT_SIZE(kv, iterations); 30 | } 31 | 32 | static void test(int argc, char *argv[]) 33 | { 34 | if (argc < 5) 35 | UT_FATAL("usage: %s engine json_config insert/check iterations", argv[0]); 36 | 37 | std::string mode = argv[3]; 38 | if (mode != "insert" && mode != "check") 39 | UT_FATAL("usage: %s engine json_config insert/check iterations", argv[0]); 40 | 41 | auto iterations = std::stoull(argv[4]); 42 | 43 | auto kv = INITIALIZE_KV(argv[1], CONFIG_FROM_JSON(argv[2])); 44 | 45 | if (mode == "insert") { 46 | insert(iterations, kv); 47 | } else { 48 | check(iterations, kv); 49 | } 50 | 51 | kv.close(); 52 | } 53 | 54 | int main(int argc, char *argv[]) 55 | { 56 | return run_test([&] { test(argc, argv); }); 57 | } 58 | -------------------------------------------------------------------------------- /utils/docker/images/0001-fix-generating-gcov-files-and-turn-off-verbose-log.patch: -------------------------------------------------------------------------------- 1 | From d633d3b0a5f03be280efb80a69b9d5ed4e9c4d56 Mon Sep 17 00:00:00 2001 2 | From: =?UTF-8?q?=C5=81ukasz=20Stolarczuk?= 3 | Date: Tue, 14 Jul 2020 13:58:34 +0200 4 | Subject: [PATCH] fix generating gcov files and turn-off verbose log 5 | 6 | --- 7 | codecov | 6 +++--- 8 | 1 file changed, 3 insertions(+), 3 deletions(-) 9 | 10 | diff --git a/codecov b/codecov 11 | index e702ecd..0a2f4d8 100755 12 | --- a/codecov 13 | +++ b/codecov 14 | @@ -1108,9 +1108,9 @@ then 15 | if [ "$ft_gcovout" = "0" ]; 16 | then 17 | # suppress gcov output 18 | - bash -c "find $proj_root -type f -name '*.gcno' $gcov_include $gcov_ignore -exec $gcov_exe -pb $gcov_arg {} +" >/dev/null 2>&1 || true 19 | + bash -c "find $proj_root -type f -name '*.gcno' $gcov_include $gcov_ignore -execdir $gcov_exe -pb $gcov_arg {} \;" >/dev/null 2>&1 || true 20 | else 21 | - bash -c "find $proj_root -type f -name '*.gcno' $gcov_include $gcov_ignore -exec $gcov_exe -pb $gcov_arg {} +" || true 22 | + bash -c "find $proj_root -type f -name '*.gcno' $gcov_include $gcov_ignore -execdir $gcov_exe -pb $gcov_arg {} \;" || true 23 | fi 24 | else 25 | say "${e}==>${x} gcov disabled" 26 | @@ -1425,7 +1425,7 @@ do 27 | report_len=$(wc -c < "$file") 28 | if [ "$report_len" -ne 0 ]; 29 | then 30 | - say " ${g}+${x} $file ${e}bytes=$(echo "$report_len" | tr -d ' ')${x}" 31 | + #say " ${g}+${x} $file ${e}bytes=$(echo "$report_len" | tr -d ' ')${x}" 32 | # append to to upload 33 | _filename=$(basename "$file") 34 | if [ "${_filename##*.}" = 'gcov' ]; 35 | -- 36 | 2.25.1 37 | 38 | -------------------------------------------------------------------------------- /.github/workflows/weekly.yml: -------------------------------------------------------------------------------- 1 | 2 | name: pmemkv-weekly 3 | # It runs non-day-to-day checks; "unusual" jobs required to be checked only once in a while. 4 | 5 | # instead of running it every week, it's now run only on-demand 6 | on: 7 | workflow_dispatch: 8 | 9 | env: 10 | REPO: pmemkv 11 | GITHUB_REPO: pmem/pmemkv 12 | CONTAINER_REG: ghcr.io/pmem/pmemkv 13 | HOST_WORKDIR: ${{ github.workspace }} 14 | WORKDIR: utils/docker 15 | TEST_TIMEOUT: 900 16 | IMG_VER: latest 17 | PUSH_IMAGE: 0 18 | 19 | jobs: 20 | linux: 21 | name: Linux-weekly 22 | runs-on: ubuntu-latest 23 | strategy: 24 | fail-fast: false 25 | matrix: 26 | CONFIG: ["TYPE=debug OS=ubuntu OS_VER=devel TESTS_ASAN=1 TESTS_PMREORDER=0", 27 | "TYPE=debug OS=ubuntu OS_VER=devel TESTS_UBSAN=1 TESTS_PMREORDER=0", 28 | "TYPE=debug OS=fedora OS_VER=34 TESTS_ASAN=1 TESTS_PMREORDER=0", 29 | "TYPE=debug OS=fedora OS_VER=34 TESTS_UBSAN=1 TESTS_PMREORDER=0", 30 | "TYPE=valgrind OS=fedora OS_VER=rawhide TESTS_PMREORDER=0", 31 | "TYPE=memcheck_drd OS=fedora OS_VER=rawhide TESTS_PMREORDER=0", 32 | "TYPE=building OS=fedora OS_VER=rawhide", 33 | "TYPE=building OS=ubuntu OS_VER=devel"] 34 | steps: 35 | - name: Clone the git repo 36 | uses: actions/checkout@v2 37 | 38 | # It rebuilds images every time (push is not neccessary; they are pushed in other workflows) 39 | - name: Rebuild the image 40 | run: cd $WORKDIR && ${{ matrix.CONFIG }} ./pull-or-rebuild-image.sh rebuild 41 | 42 | - name: Run the build 43 | run: cd $WORKDIR && ${{ matrix.CONFIG }} ./build.sh 44 | -------------------------------------------------------------------------------- /utils/docker/images/push-image.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | # Copyright 2016-2021, Intel Corporation 4 | 5 | # 6 | # push-image.sh - pushes the Docker image tagged as described in 7 | # ./build-image.sh, to the ${CONTAINER_REG}. 8 | # 9 | # The script utilizes ${CONTAINER_REG_USER} and ${CONTAINER_REG_PASS} variables to 10 | # log in to the ${CONTAINER_REG}. The variables can be set in the CI's configuration 11 | # for automated builds. 12 | # 13 | 14 | set -e 15 | IMG_VER=${IMG_VER:-devel} 16 | TAG="${OS}-${OS_VER}-${IMG_VER}" 17 | 18 | if [[ -z "${OS}" ]]; then 19 | echo "OS environment variable is not set" 20 | exit 1 21 | fi 22 | 23 | if [[ -z "${OS_VER}" ]]; then 24 | echo "OS_VER environment variable is not set" 25 | exit 1 26 | fi 27 | 28 | if [[ -z "${CONTAINER_REG}" ]]; then 29 | echo "CONTAINER_REG environment variable is not set" 30 | exit 1 31 | fi 32 | 33 | if [[ -z "${CONTAINER_REG_USER}" || -z "${CONTAINER_REG_PASS}" ]]; then 34 | echo "ERROR: variables CONTAINER_REG_USER=\"${CONTAINER_REG_USER}\" and CONTAINER_REG_PASS=\"${CONTAINER_REG_PASS}\"" \ 35 | "have to be set properly to allow login to the Container Registry." 36 | exit 1 37 | fi 38 | 39 | # Check if the image tagged with ${CONTAINER_REG}:${TAG} exists locally 40 | if [[ ! $(docker images -a | awk -v pattern="^${CONTAINER_REG}:${TAG}\$" \ 41 | '$1":"$2 ~ pattern') ]] 42 | then 43 | echo "ERROR: Docker image tagged ${CONTAINER_REG}:${TAG} does not exists locally." 44 | exit 1 45 | fi 46 | 47 | echo "Log in to the container registry: ${CONTAINER_REG}" 48 | echo "${CONTAINER_REG_PASS}" | docker login ghcr.io -u="${CONTAINER_REG_USER}" --password-stdin 49 | 50 | echo "Push the image to the repository" 51 | docker push ${CONTAINER_REG}:${TAG} 52 | -------------------------------------------------------------------------------- /tests/engine_scenarios/pmemobj/error_handling_tx.hpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2020-2021, Intel Corporation */ 3 | 4 | #include "unittest.hpp" 5 | 6 | #include 7 | 8 | using namespace pmem::kv; 9 | 10 | // XXX should this be per engine or implemented in some generic way, e.g. 11 | // UT_ASSERT(kv.some_func() == NOT_SUPPORTED 12 | // || kv.some_func() == TRANSACTION_SCOPE_ERROR); ? 13 | static void TransactionTest(pmem::obj::pool_base &pmemobj_pool, pmem::kv::db &kv) 14 | { 15 | 16 | std::string value; 17 | ASSERT_STATUS(kv.get(entry_from_string("key1"), &value), status::NOT_FOUND); 18 | 19 | pmem::obj::transaction::run(pmemobj_pool, [&] { 20 | ASSERT_STATUS( 21 | kv.put(entry_from_string("key1"), entry_from_string("value1")), 22 | status::TRANSACTION_SCOPE_ERROR); 23 | }); 24 | 25 | pmem::obj::transaction::run(pmemobj_pool, [&] { 26 | ASSERT_STATUS(kv.get(entry_from_string("key1"), &value), 27 | status::TRANSACTION_SCOPE_ERROR); 28 | }); 29 | 30 | pmem::obj::transaction::run(pmemobj_pool, [&] { 31 | ASSERT_STATUS(kv.remove(entry_from_string("key1")), 32 | status::TRANSACTION_SCOPE_ERROR); 33 | }); 34 | 35 | pmem::obj::transaction::run(pmemobj_pool, [&] { 36 | ASSERT_STATUS(kv.exists(entry_from_string("key1")), 37 | status::TRANSACTION_SCOPE_ERROR); 38 | }); 39 | 40 | pmem::obj::transaction::run(pmemobj_pool, [&] { 41 | ASSERT_STATUS(kv.get_all([&](pmem::kv::string_view key, 42 | pmem::kv::string_view value) { return 0; }), 43 | status::TRANSACTION_SCOPE_ERROR); 44 | }); 45 | 46 | pmem::obj::transaction::run(pmemobj_pool, [&] { 47 | size_t cnt; 48 | ASSERT_STATUS(kv.count_all(cnt), status::TRANSACTION_SCOPE_ERROR); 49 | }); 50 | } 51 | -------------------------------------------------------------------------------- /cmake/memkind.cmake: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2017-2020, Intel Corporation 3 | 4 | if(PKG_CONFIG_FOUND) 5 | pkg_check_modules(MEMKIND memkind>=${MEMKIND_REQUIRED_VERSION}) 6 | endif() 7 | 8 | if(NOT MEMKIND_FOUND) 9 | unset(MEMKIND_LIBRARY CACHE) 10 | unset(MEMKIND_INCLUDEDIR CACHE) 11 | 12 | # try old method 13 | include(FindPackageHandleStandardArgs) 14 | find_path(MEMKIND_INCLUDEDIR pmem_allocator.h) 15 | find_library(MEMKIND_LIBRARY NAMES memkind libmemkind) 16 | mark_as_advanced(MEMKIND_LIBRARY MEMKIND_INCLUDEDIR) 17 | find_package_handle_standard_args(MEMKIND DEFAULT_MSG MEMKIND_INCLUDEDIR MEMKIND_LIBRARY) 18 | 19 | if(MEMKIND_FOUND) 20 | set(MEMKIND_LIBRARIES ${MEMKIND_LIBRARY}) 21 | set(MEMKIND_INCLUDE_DIRS ${MEMKIND_INCLUDEDIR}) 22 | message(STATUS "Memkind library found the old way (w/o pkg-config)") 23 | else() 24 | message(FATAL_ERROR "Memkind library (>=${MEMKIND_REQUIRED_VERSION}) not found") 25 | endif() 26 | endif() 27 | 28 | link_directories(${MEMKIND_LIBRARY_DIRS}) 29 | include_directories(${MEMKIND_INCLUDE_DIRS}) 30 | 31 | # XXX To be removed when memkind updated to ver. >= 1.10 32 | # Check if libmemkind namespace is available, if not 33 | # the old namespace will be used for 'pmem::allocator'. 34 | # ref: https://github.com/pmem/pmemkv/issues/429 35 | set(SAVED_CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES}) 36 | set(CMAKE_REQUIRED_INCLUDES ${MEMKIND_INCLUDE_DIRS}) 37 | CHECK_CXX_SOURCE_COMPILES( 38 | "#include 39 | #include \"pmem_allocator.h\" 40 | int main(void) { 41 | libmemkind::pmem::allocator *alc = nullptr; 42 | (void)alc; 43 | }" 44 | LIBMEMKIND_NAMESPACE_PRESENT) 45 | set(CMAKE_REQUIRED_INCLUDES ${SAVED_CMAKE_REQUIRED_INCLUDES}) 46 | 47 | if(LIBMEMKIND_NAMESPACE_PRESENT) 48 | add_definitions(-DUSE_LIBMEMKIND_NAMESPACE) 49 | endif() 50 | -------------------------------------------------------------------------------- /cmake/tbb.cmake: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2017-2021, Intel Corporation 3 | 4 | set(TBB_DIR "" CACHE PATH "dir with TBBConfig.cmake, to be set if using custom TBB installation") 5 | message(STATUS "Checking for module 'tbb'") 6 | 7 | # TBB was found without pkg-config, warning must be printed 8 | # and global variable with tbb libs has to be set. 9 | function(handle_tbb_found_no_pkgconf) 10 | set(TBB_LIBRARIES ${TBB_IMPORTED_TARGETS} PARENT_SCOPE) 11 | 12 | message(STATUS " Found in dir '${TBB_DIR}' using CMake's find_package (ver: ${TBB_VERSION})") 13 | message(WARNING "TBB package was found without pkg-config. If you'll compile a " 14 | "standalone application and link with this libpmemkv, TBB may not be properly linked!") 15 | endfunction() 16 | 17 | # CMake param TBB_DIR is priortized. This is the best to use 18 | # while developing/testing pmemkv with custom TBB installation. 19 | if(TBB_DIR) 20 | message(STATUS " CMake param TBB_DIR is set, look ONLY in there (${TBB_DIR})!") 21 | find_package(TBB QUIET NAMES TBB tbb NO_DEFAULT_PATH) 22 | if(TBB_FOUND) 23 | handle_tbb_found_no_pkgconf() 24 | else() 25 | message(FATAL_ERROR "TBB_DIR is set, but does not contain a path to TBB. " 26 | "Either set this var to a dir with TBBConfig.cmake (or tbb-config.cmake), " 27 | "or unset it and let CMake find TBB in the system (using e.g. pkg-config).") 28 | endif() 29 | else() 30 | if(PKG_CONFIG_FOUND) 31 | pkg_check_modules(TBB QUIET tbb) 32 | if(TBB_FOUND) 33 | message(STATUS " Found in dir '${TBB_LIBDIR}' using pkg-config (ver: ${TBB_VERSION})") 34 | return() 35 | endif() 36 | endif() 37 | 38 | # find_package (run after pkg-config) without unsetting this var is not working correctly 39 | unset(TBB_FOUND CACHE) 40 | 41 | find_package(TBB REQUIRED tbb) 42 | handle_tbb_found_no_pkgconf() 43 | endif() 44 | -------------------------------------------------------------------------------- /tests/engine_scenarios/persistent/put_remove_verify.cc: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2020-2021, Intel Corporation */ 3 | 4 | #include "unittest.hpp" 5 | 6 | using namespace pmem::kv; 7 | 8 | static void insert(pmem::kv::db &kv) 9 | { 10 | 11 | ASSERT_STATUS(kv.put(entry_from_string("key1"), entry_from_string("value1")), 12 | status::OK); 13 | ASSERT_STATUS(kv.put(entry_from_string("key2"), entry_from_string("value2")), 14 | status::OK); 15 | ASSERT_STATUS(kv.put(entry_from_string("key3"), entry_from_string("value3")), 16 | status::OK); 17 | ASSERT_STATUS(kv.remove(entry_from_string("key2")), status::OK); 18 | ASSERT_STATUS(kv.put(entry_from_string("key3"), entry_from_string("VALUE3")), 19 | status::OK); 20 | } 21 | 22 | static void check(pmem::kv::db &kv) 23 | { 24 | 25 | std::string value1; 26 | ASSERT_STATUS(kv.get(entry_from_string("key1"), &value1), status::OK); 27 | UT_ASSERT(value1 == entry_from_string("value1")); 28 | std::string value2; 29 | ASSERT_STATUS(kv.get(entry_from_string("key2"), &value2), status::NOT_FOUND); 30 | std::string value3; 31 | ASSERT_STATUS(kv.get(entry_from_string("key3"), &value3), status::OK); 32 | UT_ASSERT(value3 == entry_from_string("VALUE3")); 33 | } 34 | 35 | static void test(int argc, char *argv[]) 36 | { 37 | if (argc < 4) 38 | UT_FATAL("usage: %s engine json_config insert/check", argv[0]); 39 | 40 | std::string mode = argv[3]; 41 | if (mode != "insert" && mode != "check") 42 | UT_FATAL("usage: %s engine json_config insert/check", argv[0]); 43 | 44 | auto kv = INITIALIZE_KV(argv[1], CONFIG_FROM_JSON(argv[2])); 45 | 46 | if (mode == "insert") { 47 | insert(kv); 48 | } else { 49 | check(kv); 50 | } 51 | 52 | kv.close(); 53 | } 54 | 55 | int main(int argc, char *argv[]) 56 | { 57 | return run_test([&] { test(argc, argv); }); 58 | } 59 | -------------------------------------------------------------------------------- /doc/RELEASE_STEPS.md: -------------------------------------------------------------------------------- 1 | ## pmemkv release steps 2 | 3 | This document contains all the steps required to make a new release of pmemkv. 4 | 5 | \#define $VERSION = current full version (e.g. 1.0.2); $VER = major+minor only version (e.g. 1.0) 6 | 7 | Make a release locally: 8 | - add an entry to ChangeLog, remember to change the day of the week in the release date 9 | - for major/minor releases mention compatibility with the previous release 10 | - echo $VERSION > VERSION 11 | - git add VERSION 12 | - git commit -a -S -m "$VERSION release" 13 | - git tag -a -s -m "Version $VERSION" $VERSION 14 | 15 | Undo temporary release changes: 16 | - git rm VERSION 17 | - git commit -m "Remove VERSION file" 18 | - for major/minor release: 19 | - create stable-$VER branch now: git checkout -b stable-$VER 20 | 21 | Publish changes: 22 | - for major/minor release: 23 | - git push upstream HEAD:master $VERSION 24 | - create and push to upstream stable-$VER branch 25 | - for patch release: 26 | - git push upstream HEAD:stable-$VER $VERSION 27 | - create PR from stable-$VER to next stable (or master, if release is from most recent stable branch) 28 | 29 | Publish package and make it official: 30 | - go to [GitHub's releases tab](https://github.com/pmem/pmemkv/releases/new): 31 | - tag version: $VERSION, release title: pmemkv version $VERSION, description: copy entry from ChangeLog and format it with no tabs and no characters limit in line 32 | - announce the release on pmem group and on pmem slack channel(s) 33 | 34 | Later, for major/minor release: 35 | - add new version in compatibility test in run-compatibility.sh, on stable-$VER branch 36 | 37 | 38 | - once 'docs' branch contains new documentation: 39 | - add there (in index.md) new links to manpages and Doxygen docs 40 | - update there "Releases' support status" table (update any other release's status if needed) 41 | -------------------------------------------------------------------------------- /src/comparator/pmemobj_comparator.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2020, Intel Corporation */ 3 | 4 | #ifndef LIBPMEMKV_PMEMOBJ_COMPARATOR_H 5 | #define LIBPMEMKV_PMEMOBJ_COMPARATOR_H 6 | 7 | #include "../exceptions.h" 8 | #include "comparator.h" 9 | 10 | #include "../valgrind/pmemcheck.h" 11 | 12 | #include 13 | 14 | namespace pmem 15 | { 16 | namespace kv 17 | { 18 | namespace internal 19 | { 20 | 21 | class pmemobj_compare { 22 | public: 23 | using is_transparent = void; 24 | 25 | pmemobj_compare() : name() 26 | { 27 | } 28 | 29 | void initialize(const comparator *cmp) 30 | { 31 | /* initialize should be called only once */ 32 | assert(this->name.size() == 0); 33 | 34 | if (cmp->name().size() == 0) 35 | throw internal::invalid_argument( 36 | "Comparator does not have a valid name"); 37 | 38 | this->cmp = cmp; 39 | 40 | auto pop = pmem::obj::pool_base(pmemobj_pool_by_ptr(this)); 41 | pop.persist(&this->cmp, sizeof(this->cmp)); 42 | 43 | this->name = cmp->name(); 44 | } 45 | 46 | void runtime_initialize(const comparator *cmp) 47 | { 48 | if (this->name != cmp->name()) 49 | throw internal::comparator_mismatch( 50 | "Comparator with name: \"" + 51 | std::string(this->name.c_str()) + "\" expected"); 52 | 53 | this->cmp = cmp; 54 | 55 | auto pop = pmem::obj::pool_base(pmemobj_pool_by_ptr(this)); 56 | pop.persist(&this->cmp, sizeof(this->cmp)); 57 | } 58 | 59 | template 60 | bool operator()(const T &lhs, const U &rhs) const 61 | { 62 | auto key1 = make_string_view(lhs); 63 | auto key2 = make_string_view(rhs); 64 | 65 | return (cmp->compare(key1, key2) < 0); 66 | } 67 | 68 | private: 69 | pmem::obj::string name; 70 | const comparator *cmp = nullptr; 71 | }; 72 | 73 | static_assert(sizeof(pmemobj_compare) == 40, "wrong pmemobj_compare size"); 74 | 75 | } /* namespace internal */ 76 | } /* namespace kv */ 77 | } /* namespace pmem */ 78 | 79 | #endif 80 | -------------------------------------------------------------------------------- /tests/engine_scenarios/pmemobj/create_or_error_if_exists.cc: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2021, Intel Corporation */ 3 | 4 | #include "unittest.hpp" 5 | 6 | /* 7 | * Tests for config flag create_or_error_if_exists with existing pool. 8 | */ 9 | 10 | static void FailsToOpenExisting(std::string path, std::string engine, std::size_t size) 11 | { 12 | /** 13 | * TEST: create_or_error_if_exists set to **true** should not work with existing 14 | * pool. 15 | */ 16 | 17 | pmem::kv::config config; 18 | auto s = config.put_path(path); 19 | ASSERT_STATUS(s, pmem::kv::status::OK); 20 | s = config.put_size(size); 21 | ASSERT_STATUS(s, pmem::kv::status::OK); 22 | s = config.put_create_or_error_if_exists(true); 23 | ASSERT_STATUS(s, pmem::kv::status::OK); 24 | 25 | pmem::kv::db kv; 26 | s = kv.open(engine, std::move(config)); 27 | 28 | /* It should err with "Failed creating pool - already exists" */ 29 | ASSERT_STATUS(s, pmem::kv::status::INVALID_ARGUMENT); 30 | } 31 | 32 | static void OpenExisting(std::string path, std::string engine, std::size_t size) 33 | { 34 | /** 35 | * TEST: create_or_error_if_exists set to **false** should work with existing 36 | * pool. 37 | */ 38 | 39 | pmem::kv::config config; 40 | auto s = config.put_path(path); 41 | ASSERT_STATUS(s, pmem::kv::status::OK); 42 | s = config.put_size(size); 43 | ASSERT_STATUS(s, pmem::kv::status::OK); 44 | s = config.put_create_or_error_if_exists(false); 45 | ASSERT_STATUS(s, pmem::kv::status::OK); 46 | 47 | pmem::kv::db kv; 48 | s = kv.open(engine, std::move(config)); 49 | 50 | ASSERT_STATUS(s, pmem::kv::status::OK); 51 | } 52 | 53 | static void test(int argc, char *argv[]) 54 | { 55 | if (argc < 4) 56 | UT_FATAL("usage: %s engine path size", argv[0]); 57 | 58 | auto engine = argv[1]; 59 | auto path = argv[2]; 60 | size_t size = std::stoul(argv[3]); 61 | 62 | FailsToOpenExisting(path, engine, size); 63 | OpenExisting(path, engine, size); 64 | } 65 | 66 | int main(int argc, char *argv[]) 67 | { 68 | return run_test([&] { test(argc, argv); }); 69 | } 70 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | SPDX-License-Identifier: BSD-3-Clause 2 | Copyright 2017-2021, Intel Corporation 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions 6 | are met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | * Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in 13 | the documentation and/or other materials provided with the 14 | distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived 18 | from this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | 32 | 33 | Everything in this source tree is covered by the previous license 34 | with the following exceptions: 35 | 36 | * src/valgrind/valgrind.h, src/valgrind/memcheck.h, 37 | src/valgrind/helgrind.h, src/valgrind/drd.h are covered by 38 | another similar BSD license variant, contained in those files. 39 | 40 | * src/fast_hash.h and src/fast_hash.cc are covered by MIT license, 41 | contained in those files. 42 | -------------------------------------------------------------------------------- /src/comparator/comparator.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2020, Intel Corporation */ 3 | 4 | #ifndef LIBPMEMKV_COMPARATOR_H 5 | #define LIBPMEMKV_COMPARATOR_H 6 | 7 | #include "../config.h" 8 | #include "../exceptions.h" 9 | #include "../libpmemkv.h" 10 | #include "../libpmemkv.hpp" 11 | #include "../out.h" 12 | 13 | namespace pmem 14 | { 15 | namespace kv 16 | { 17 | namespace internal 18 | { 19 | 20 | class comparator { 21 | public: 22 | comparator(pmemkv_compare_function *cmp, std::string name, void *arg) 23 | : cmp(cmp), name_(name), arg(arg) 24 | { 25 | } 26 | 27 | int compare(string_view key1, string_view key2) const 28 | { 29 | return (*cmp)(key1.data(), key1.size(), key2.data(), key2.size(), arg); 30 | } 31 | 32 | std::string name() const 33 | { 34 | return name_; 35 | } 36 | 37 | private: 38 | pmemkv_compare_function *cmp; 39 | std::string name_; 40 | void *arg; 41 | }; 42 | 43 | static inline int binary_compare(const char *key1, size_t kb1, const char *key2, 44 | size_t kb2, void *arg) 45 | { 46 | (void)arg; 47 | return string_view(key1, kb1).compare(string_view(key2, kb2)); 48 | } 49 | 50 | static inline const comparator &binary_comparator() 51 | { 52 | static const comparator cmp(binary_compare, "__pmemkv_binary_comparator", 53 | nullptr); 54 | return cmp; 55 | } 56 | 57 | template ().c_str())>::value>::type> 60 | static inline string_view make_string_view(const T &str) 61 | { 62 | return string_view(str.c_str(), str.size()); 63 | } 64 | 65 | static inline string_view make_string_view(string_view v) 66 | { 67 | return v; 68 | } 69 | 70 | static inline const comparator *extract_comparator(internal::config &cfg) 71 | { 72 | comparator *cmp; 73 | 74 | if (!cfg.get_object("comparator", (void **)&cmp)) 75 | return &internal::binary_comparator(); 76 | else 77 | return cmp; 78 | } 79 | 80 | } /* namespace internal */ 81 | } /* namespace kv */ 82 | } /* namespace pmem */ 83 | 84 | #endif 85 | -------------------------------------------------------------------------------- /tests/engine_scenarios/persistent/overwrite_verify.cc: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2020-2021, Intel Corporation */ 3 | 4 | #include "unittest.hpp" 5 | 6 | using namespace pmem::kv; 7 | 8 | static void insert(pmem::kv::db &kv) 9 | { 10 | std::string key = entry_from_string("key1"); 11 | 12 | std::string expected_value = entry_from_string("value1"); 13 | std::string value; 14 | ASSERT_STATUS(kv.put(key, expected_value), status::OK); 15 | ASSERT_STATUS(kv.get(key, &value), status::OK); 16 | UT_ASSERT(value == expected_value); 17 | 18 | expected_value = entry_from_string("VALUE1"); 19 | std::string new_value; 20 | ASSERT_STATUS(kv.put(key, expected_value), status::OK); // same size 21 | ASSERT_STATUS(kv.get(key, &new_value), status::OK); 22 | UT_ASSERT(new_value == expected_value); 23 | 24 | kv.close(); 25 | } 26 | 27 | static void check(pmem::kv::db &kv) 28 | { 29 | std::string key = entry_from_string("key1"); 30 | 31 | std::string expected_value = entry_from_string("new_val"); // longer size 32 | std::string new_value2; 33 | ASSERT_STATUS(kv.put(key, expected_value), status::OK); 34 | ASSERT_STATUS(kv.get(key, &new_value2), status::OK); 35 | UT_ASSERT(new_value2 == expected_value); 36 | 37 | expected_value = entry_from_string("?"); // shorter size 38 | std::string new_value3; 39 | ASSERT_STATUS(kv.put(key, expected_value), status::OK); 40 | ASSERT_STATUS(kv.get(key, &new_value3), status::OK); 41 | UT_ASSERT(new_value3 == expected_value); 42 | } 43 | 44 | static void test(int argc, char *argv[]) 45 | { 46 | if (argc < 4) 47 | UT_FATAL("usage: %s engine json_config insert/check", argv[0]); 48 | 49 | std::string mode = argv[3]; 50 | if (mode != "insert" && mode != "check") 51 | UT_FATAL("usage: %s engine json_config insert/check", argv[0]); 52 | 53 | auto kv = INITIALIZE_KV(argv[1], CONFIG_FROM_JSON(argv[2])); 54 | 55 | if (mode == "insert") { 56 | insert(kv); 57 | } else { 58 | check(kv); 59 | } 60 | 61 | kv.close(); 62 | } 63 | 64 | int main(int argc, char *argv[]) 65 | { 66 | return run_test([&] { test(argc, argv); }); 67 | } 68 | -------------------------------------------------------------------------------- /tests/engine_scenarios/all/put_get_remove_params.cc: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2020-2021, Intel Corporation */ 3 | 4 | #include "unittest.hpp" 5 | 6 | using namespace pmem::kv; 7 | 8 | static void LargeAscendingTest(const size_t iterations, pmem::kv::db &kv) 9 | { 10 | for (size_t i = 1; i <= iterations; i++) { 11 | std::string istr = entry_from_number(i); 12 | ASSERT_STATUS(kv.put(istr, entry_from_number(i, "", "!")), status::OK); 13 | std::string value; 14 | ASSERT_STATUS(kv.get(istr, &value), status::OK); 15 | UT_ASSERT(value == entry_from_number(i, "", "!")); 16 | } 17 | for (size_t i = 1; i <= iterations; i++) { 18 | std::string istr = entry_from_number(i); 19 | std::string value; 20 | ASSERT_STATUS(kv.get(istr, &value), status::OK); 21 | UT_ASSERT(value == entry_from_number(i, "", "!")); 22 | } 23 | ASSERT_SIZE(kv, iterations); 24 | } 25 | 26 | static void LargeDescendingTest(const size_t iterations, pmem::kv::db &kv) 27 | { 28 | for (size_t i = iterations; i >= 1; i--) { 29 | std::string istr = entry_from_number(i); 30 | ASSERT_STATUS(kv.put(istr, entry_from_number(i, "ABC")), status::OK); 31 | std::string value; 32 | ASSERT_STATUS(kv.get(istr, &value), status::OK); 33 | UT_ASSERT(value == entry_from_number(i, "ABC")); 34 | } 35 | for (size_t i = iterations; i >= 1; i--) { 36 | std::string istr = entry_from_number(i); 37 | std::string value; 38 | ASSERT_STATUS(kv.get(istr, &value), status::OK); 39 | UT_ASSERT(value == entry_from_number(i, "ABC")); 40 | } 41 | ASSERT_SIZE(kv, iterations); 42 | } 43 | 44 | static void test(int argc, char *argv[]) 45 | { 46 | using namespace std::placeholders; 47 | 48 | if (argc < 4) 49 | UT_FATAL("usage: %s engine json_config iterations", argv[0]); 50 | 51 | auto iterations = std::stoull(argv[3]); 52 | 53 | run_engine_tests(argv[1], argv[2], 54 | { 55 | std::bind(LargeAscendingTest, iterations, _1), 56 | std::bind(LargeDescendingTest, iterations, _1), 57 | }); 58 | } 59 | 60 | int main(int argc, char *argv[]) 61 | { 62 | return run_test([&] { test(argc, argv); }); 63 | } 64 | -------------------------------------------------------------------------------- /.github/workflows/nightly.yml: -------------------------------------------------------------------------------- 1 | 2 | name: pmemkv-nightly 3 | # It runs non-deafult OSes, listed below with basic set of compilers and tests. 4 | 5 | # instead of running it every night, it's now run only on-demand 6 | on: 7 | workflow_dispatch: 8 | inputs: 9 | build_type: 10 | description: 'Build type (as defined in build.sh)' 11 | required: true 12 | default: 'debug' 13 | 14 | env: 15 | REPO: pmemkv 16 | GITHUB_REPO: pmem/pmemkv 17 | CONTAINER_REG: ghcr.io/pmem/pmemkv 18 | HOST_WORKDIR: ${{ github.workspace }} 19 | WORKDIR: utils/docker 20 | TEST_TIMEOUT: 900 21 | IMG_VER: latest 22 | TYPE: ${{ github.event.inputs.build_type }} 23 | PUSH_IMAGE: 1 24 | # use org's Private Access Token to log in to GitHub Container Registry 25 | CONTAINER_REG_USER: ${{ secrets.GH_CR_USER }} 26 | CONTAINER_REG_PASS: ${{ secrets.GH_CR_PAT }} 27 | 28 | jobs: 29 | linux: 30 | name: Linux-nightly 31 | runs-on: ubuntu-latest 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | CONFIG: ["OS=almalinux OS_VER=8", 36 | "OS=archlinux-base OS_VER=latest", 37 | "OS=debian OS_VER=testing", 38 | "OS=debian OS_VER=unstable", 39 | "OS=debian OS_VER=latest", 40 | "OS=fedora OS_VER=33", 41 | "OS=fedora OS_VER=34", 42 | "OS=fedora OS_VER=rawhide", 43 | "OS=opensuse-leap OS_VER=latest", 44 | "OS=opensuse-tumbleweed OS_VER=latest", 45 | "OS=ubuntu OS_VER=18.04", 46 | "OS=ubuntu OS_VER=21.04", 47 | "OS=ubuntu OS_VER=devel"] 48 | steps: 49 | - name: Clone the git repo 50 | uses: actions/checkout@v2 51 | 52 | # It rebuilds images every time and pushes them to the container registry 53 | - name: Rebuild and push the image 54 | run: cd $WORKDIR && ${{ matrix.CONFIG }} ./pull-or-rebuild-image.sh rebuild 55 | 56 | - name: Run the build 57 | run: cd $WORKDIR && ${{ matrix.CONFIG }} ./build.sh 58 | -------------------------------------------------------------------------------- /src/iterator.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2020-2021, Intel Corporation */ 3 | 4 | #ifndef LIBPMEMKV_ITERATOR_H 5 | #define LIBPMEMKV_ITERATOR_H 6 | 7 | #include "libpmemkv.hpp" 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | namespace pmem 14 | { 15 | namespace kv 16 | { 17 | namespace internal 18 | { 19 | class iterator_base { 20 | public: 21 | virtual ~iterator_base() = default; 22 | 23 | virtual status seek(string_view key) = 0; 24 | virtual status seek_lower(string_view key); 25 | virtual status seek_lower_eq(string_view key); 26 | virtual status seek_higher(string_view key); 27 | virtual status seek_higher_eq(string_view key); 28 | 29 | virtual status seek_to_first(); 30 | virtual status seek_to_last(); 31 | 32 | virtual status is_next(); 33 | virtual status next(); 34 | virtual status prev(); 35 | 36 | virtual result key() = 0; 37 | virtual result> read_range(size_t pos, 38 | size_t n) = 0; 39 | 40 | virtual result> write_range(size_t pos, size_t n); 41 | 42 | virtual status commit(); 43 | virtual void abort(); 44 | 45 | protected: 46 | virtual void init_seek(); 47 | }; 48 | 49 | template 50 | std::size_t distance(It first, It last) 51 | { 52 | auto dist = std::distance(first, last); 53 | assert(dist >= 0); 54 | return static_cast(dist); 55 | } 56 | 57 | /** 58 | * Helper function to iterate between specified range and execute 59 | * callback on every item. 60 | */ 61 | template 62 | status iterate_through_pairs(It first, It last, get_kv_callback *callback, void *arg) 63 | { 64 | for (auto it = first; it != last; ++it) { 65 | auto ret = callback(it->first.c_str(), it->first.size(), 66 | it->second.c_str(), it->second.size(), arg); 67 | if (ret != 0) 68 | return status::STOPPED_BY_CB; 69 | } 70 | return status::OK; 71 | } 72 | 73 | } /* namespace internal */ 74 | } /* namespace kv */ 75 | } /* namespace pmem */ 76 | 77 | #endif /* LIBPMEMKV_ITERATOR_H */ 78 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Did you find a bug in pmemkv? Please let us know. 4 | labels: "Type: Bug" 5 | --- 6 | 13 | 14 | # ISSUE: 15 | 16 | ## Environment Information 17 | 18 | | Name | Version | 19 | | :--------------------------- | :-------------------------: | 20 | | pmemkv version(s) | | 21 | | libpmemobj-cpp version(s) | | 22 | | PMDK (libpmem/libpmemobj) version(s) | | 23 | | OS(es) version(s) | | 24 | | kernel version(s) | | 25 | | compiler, libraries, packaging and other related tools version(s) | | 26 | 27 | and if applicable: 28 | | Name | Version | 29 | | :-------------------------- | :---------: | 30 | | TBB version(s): | | 31 | | memkind version(s): | | 32 | | ndctl version(s): | | 33 | 34 | 35 | 36 | ## Please provide a reproduction of the bug: 37 | 38 | 39 | 40 | ## How often bug is revealed: 41 | 42 | (always, often, rare) 43 | 44 | 45 | ## Actual behavior: 46 | 47 | 48 | 49 | ## Expected behavior: 50 | 51 | 52 | 53 | ## Details 54 | 55 | 56 | 57 | ## Additional information about Priority and Help Requested: 58 | 59 | | Question | Answer | 60 | | :------- | :----: | 61 | | Are you willing to submit a pull request with a proposed change? | Yes/No | 62 | | Requested priority | Showstopper/High/Medium/Low | 63 | 64 | -------------------------------------------------------------------------------- /tests/engine_scenarios/iterator.hpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2020, Intel Corporation */ 3 | 4 | /* 5 | * Helper functions to test iterators. 6 | */ 7 | 8 | #include "../common/unittest.hpp" 9 | 10 | template 11 | using iterator = typename std::conditional::type; 13 | 14 | using pair = std::pair; 15 | 16 | using key_result = std::pair; 17 | 18 | static std::vector keys{{"aaa", "1"}, {"bbb", "2"}, {"ccc", "3"}, {"rrr", "4"}, 19 | {"sss", "5"}, {"ttt", "6"}, {"yyy", "记!"}}; 20 | 21 | void insert_keys(pmem::kv::db &kv) 22 | { 23 | std::for_each(keys.begin(), keys.end(), [&](pair p) { 24 | ASSERT_STATUS(kv.put(p.first, p.second), pmem::kv::status::OK); 25 | }); 26 | } 27 | 28 | template 29 | void verify_key(iterator &it, pmem::kv::string_view expected) 30 | { 31 | auto result = it.key(); 32 | UT_ASSERT(result.is_ok()); 33 | UT_ASSERTeq(expected.compare(result.get_value()), 0); 34 | } 35 | 36 | template 37 | void verify_value(iterator &it, pmem::kv::string_view expected) 38 | { 39 | auto result = it.read_range(); 40 | UT_ASSERT(result.is_ok()); 41 | UT_ASSERTeq(expected.compare(result.get_value()), 0); 42 | } 43 | 44 | template 45 | typename std::enable_if>::type new_iterator(pmem::kv::db &kv) 46 | { 47 | auto res = kv.new_read_iterator(); 48 | UT_ASSERT(res.is_ok()); 49 | return std::move(res.get_value()); 50 | } 51 | 52 | template 53 | typename std::enable_if>::type new_iterator(pmem::kv::db &kv) 54 | { 55 | auto res = kv.new_write_iterator(); 56 | UT_ASSERT(res.is_ok()); 57 | return std::move(res.get_value()); 58 | } 59 | 60 | template 61 | static void verify_keys(iterator &it) 62 | { 63 | std::for_each(keys.begin(), keys.end(), [&](pair p) { 64 | ASSERT_STATUS(it.seek(p.first), pmem::kv::status::OK); 65 | verify_key(it, p.first); 66 | verify_value(it, p.second); 67 | }); 68 | } 69 | -------------------------------------------------------------------------------- /src/transaction.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2020, Intel Corporation */ 3 | 4 | #ifndef LIBPMEMKV_TRANSACTION_H 5 | #define LIBPMEMKV_TRANSACTION_H 6 | 7 | #include "libpmemkv.hpp" 8 | 9 | #include 10 | 11 | namespace pmem 12 | { 13 | 14 | namespace kv 15 | { 16 | 17 | namespace internal 18 | { 19 | 20 | class transaction { 21 | public: 22 | transaction() 23 | { 24 | } 25 | 26 | virtual ~transaction() 27 | { 28 | } 29 | 30 | virtual status put(string_view key, string_view value) = 0; 31 | virtual status commit() = 0; 32 | virtual void abort() = 0; 33 | 34 | virtual status remove(string_view key) 35 | { 36 | return status::NOT_SUPPORTED; 37 | } 38 | }; 39 | 40 | class dram_log { 41 | public: 42 | using element_type = std::pair; 43 | 44 | void insert(string_view key, string_view value) 45 | { 46 | op_type.emplace_back(operation::insert); 47 | log.emplace_back(std::piecewise_construct, 48 | std::forward_as_tuple(key.data(), key.size()), 49 | std::forward_as_tuple(value.data(), value.size())); 50 | } 51 | 52 | void remove(string_view key) 53 | { 54 | op_type.emplace_back(operation::remove); 55 | log.emplace_back(std::piecewise_construct, 56 | std::forward_as_tuple(key.data(), key.size()), 57 | std::forward_as_tuple()); 58 | } 59 | 60 | template 61 | void foreach (F1 &&insert_cb, F2 && remove_cb) 62 | { 63 | assert(op_type.size() == log.size()); 64 | 65 | for (size_t i = 0; i < log.size(); i++) { 66 | switch (op_type[i]) { 67 | case operation::insert: 68 | insert_cb(log[i]); 69 | break; 70 | case operation::remove: 71 | remove_cb(log[i]); 72 | break; 73 | default: 74 | assert(false); 75 | break; 76 | } 77 | } 78 | } 79 | 80 | void clear() 81 | { 82 | op_type.clear(); 83 | log.clear(); 84 | } 85 | 86 | private: 87 | enum class operation { insert, remove }; 88 | 89 | std::vector op_type; 90 | std::vector log; 91 | }; 92 | 93 | } /* namespace internal */ 94 | } /* namespace kv */ 95 | } /* namespace pmem */ 96 | 97 | #endif /* LIBPMEMKV_TRANSACTION_H */ 98 | -------------------------------------------------------------------------------- /tests/engine_scenarios/persistent/put_verify.cc: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2020-2021, Intel Corporation */ 3 | 4 | #include "unittest.hpp" 5 | 6 | using namespace pmem::kv; 7 | 8 | static void insert(pmem::kv::db &kv) 9 | { 10 | ASSERT_STATUS(kv.put(entry_from_string("abc"), entry_from_string("A1")), 11 | status::OK); 12 | ASSERT_STATUS(kv.put(entry_from_string("def"), entry_from_string("B2")), 13 | status::OK); 14 | ASSERT_STATUS(kv.put(entry_from_string("hij"), entry_from_string("C3")), 15 | status::OK); 16 | } 17 | 18 | static void check(pmem::kv::db &kv) 19 | { 20 | ASSERT_STATUS(kv.put(entry_from_string("jkl"), entry_from_string("D4")), 21 | status::OK); 22 | ASSERT_STATUS(kv.put(entry_from_string("mno"), entry_from_string("E5")), 23 | status::OK); 24 | std::string value1; 25 | ASSERT_STATUS(kv.get(entry_from_string("abc"), &value1), status::OK); 26 | UT_ASSERT(value1 == entry_from_string("A1")); 27 | std::string value2; 28 | ASSERT_STATUS(kv.get(entry_from_string("def"), &value2), status::OK); 29 | UT_ASSERT(value2 == entry_from_string("B2")); 30 | std::string value3; 31 | ASSERT_STATUS(kv.get(entry_from_string("hij"), &value3), status::OK); 32 | UT_ASSERT(value3 == entry_from_string("C3")); 33 | std::string value4; 34 | ASSERT_STATUS(kv.get(entry_from_string("jkl"), &value4), status::OK); 35 | UT_ASSERT(value4 == entry_from_string("D4")); 36 | std::string value5; 37 | ASSERT_STATUS(kv.get(entry_from_string("mno"), &value5), status::OK); 38 | UT_ASSERT(value5 == entry_from_string("E5")); 39 | } 40 | 41 | static void test(int argc, char *argv[]) 42 | { 43 | if (argc < 4) 44 | UT_FATAL("usage: %s engine json_config insert/check", argv[0]); 45 | 46 | std::string mode = argv[3]; 47 | if (mode != "insert" && mode != "check") 48 | UT_FATAL("usage: %s engine json_config insert/check", argv[0]); 49 | 50 | auto kv = INITIALIZE_KV(argv[1], CONFIG_FROM_JSON(argv[2])); 51 | 52 | if (mode == "insert") { 53 | insert(kv); 54 | } else { 55 | check(kv); 56 | } 57 | 58 | kv.close(); 59 | } 60 | 61 | int main(int argc, char *argv[]) 62 | { 63 | return run_test([&] { test(argc, argv); }); 64 | } 65 | -------------------------------------------------------------------------------- /tests/engine_scenarios/transaction/put_pmreorder.cc: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2020-2021, Intel Corporation */ 3 | 4 | /* 5 | * insert.cc -- insert pmreorder test 6 | */ 7 | 8 | #include "unittest.hpp" 9 | 10 | static std::vector init_elements = {"0", "1"}; 11 | static std::vector elements = {"A", "B", "C"}; 12 | 13 | static void test_put_commit(pmem::kv::db &kv) 14 | { 15 | auto tx = kv.tx_begin().get_value(); 16 | for (auto &e : elements) 17 | ASSERT_STATUS(tx.put(e, e), pmem::kv::status::OK); 18 | 19 | ASSERT_STATUS(tx.commit(), pmem::kv::status::OK); 20 | } 21 | 22 | static void test_init(pmem::kv::db &kv) 23 | { 24 | for (auto &e : init_elements) 25 | ASSERT_STATUS(kv.put(e, e), pmem::kv::status::OK); 26 | } 27 | 28 | static void check_consistency(pmem::kv::db &kv) 29 | { 30 | std::size_t size; 31 | ASSERT_STATUS(kv.count_all(size), pmem::kv::status::OK); 32 | 33 | for (auto &e : init_elements) 34 | ASSERT_STATUS(kv.exists(e), pmem::kv::status::OK); 35 | 36 | if (size > init_elements.size()) { 37 | UT_ASSERTeq(size, init_elements.size() + elements.size()); 38 | for (auto &e : elements) 39 | ASSERT_STATUS(kv.exists(e), pmem::kv::status::OK); 40 | } else { 41 | UT_ASSERTeq(size, init_elements.size()); 42 | } 43 | } 44 | 45 | static void test(int argc, char *argv[]) 46 | { 47 | std::cout << "ARGC: " << argc << std::endl; 48 | for (int i = 0; i < argc; ++i) { 49 | std::cout << "ARGV " << i << " : " << argv[i] << std::endl; 50 | } 51 | if (argc < 4) 52 | UT_FATAL("usage: %s engine json_config ", argv[0]); 53 | 54 | std::string mode = argv[3]; 55 | if (mode != "create" && mode != "open" && mode != "insert") 56 | UT_FATAL("usage: %s engine json_config ", argv[0]); 57 | 58 | auto kv = INITIALIZE_KV(argv[1], CONFIG_FROM_JSON(argv[2])); 59 | 60 | if (mode == "create") { 61 | test_init(kv); 62 | } else if (mode == "open") { 63 | check_consistency(kv); 64 | } else if (mode == "insert") { 65 | test_put_commit(kv); 66 | } 67 | 68 | kv.close(); 69 | } 70 | 71 | int main(int argc, char *argv[]) 72 | { 73 | return run_test([&] { test(argc, argv); }); 74 | } 75 | -------------------------------------------------------------------------------- /src/fast_hash.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * The fast-hash algorithm is covered by the MIT License: 3 | * 4 | * Copyright (C) 2012 Zilong Tan (eric.zltan@gmail.com) 5 | * 6 | * Permission is hereby granted, free of charge, to any person 7 | * obtaining a copy of this software and associated documentation 8 | * files (the "Software"), to deal in the Software without 9 | * restriction, including without limitation the rights to use, copy, 10 | * modify, merge, publish, distribute, sublicense, and/or sell copies 11 | * of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be 15 | * included in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 21 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 22 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include "fast_hash.h" 28 | #include 29 | 30 | /* 31 | * mix -- (internal) helper for the fast-hash mixing step 32 | */ 33 | static inline uint64_t mix(uint64_t h) 34 | { 35 | h ^= h >> 23; 36 | h *= 0x2127599bf4325c37ULL; 37 | return h ^ h >> 47; 38 | } 39 | 40 | /* 41 | * hash -- calculate the hash of a piece of memory 42 | */ 43 | uint64_t fast_hash(size_t key_size, const char *key) 44 | { 45 | /* fast-hash, by Zilong Tan */ 46 | const uint64_t m = 0x880355f21e6d1965ULL; 47 | const uint64_t *pos = (const uint64_t *)key; 48 | const uint64_t *end = pos + (key_size / 8); 49 | uint64_t h = key_size * m; 50 | 51 | while (pos != end) 52 | h = (h ^ mix(*pos++)) * m; 53 | 54 | if (key_size & 7) { 55 | uint64_t shift = (key_size & 7) * 8; 56 | uint64_t mask = (1ULL << shift) - 1; 57 | uint64_t v = htole64(*pos) & mask; 58 | h = (h ^ mix(v)) * m; 59 | } 60 | 61 | return mix(h); 62 | } 63 | -------------------------------------------------------------------------------- /src/libpmemkv.map: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2019-2021, Intel Corporation 3 | # 4 | # 5 | # src/libpmemkv.map -- linker map file for libpmemkv 6 | # 7 | LIBPMEMKV_1.0 { 8 | global: 9 | pmemkv_close; 10 | pmemkv_config_delete; 11 | pmemkv_config_get_data; 12 | pmemkv_config_get_int64; 13 | pmemkv_config_get_object; 14 | pmemkv_config_get_string; 15 | pmemkv_config_get_uint64; 16 | pmemkv_config_new; 17 | pmemkv_config_put_data; 18 | pmemkv_config_put_int64; 19 | pmemkv_config_put_object; 20 | pmemkv_config_put_object_cb; 21 | pmemkv_config_put_string; 22 | pmemkv_config_put_uint64; 23 | pmemkv_config_put_size; 24 | pmemkv_config_put_path; 25 | pmemkv_config_put_oid; 26 | pmemkv_config_put_comparator; 27 | pmemkv_config_put_create_if_missing; 28 | pmemkv_config_put_create_or_error_if_exists; 29 | pmemkv_config_put_force_create; 30 | pmemkv_comparator_new; 31 | pmemkv_comparator_delete; 32 | pmemkv_count_above; 33 | pmemkv_count_all; 34 | pmemkv_count_below; 35 | pmemkv_count_between; 36 | pmemkv_count_equal_above; 37 | pmemkv_count_equal_below; 38 | pmemkv_defrag; 39 | pmemkv_errormsg; 40 | pmemkv_exists; 41 | pmemkv_get; 42 | pmemkv_get_above; 43 | pmemkv_get_all; 44 | pmemkv_get_below; 45 | pmemkv_get_between; 46 | pmemkv_get_copy; 47 | pmemkv_get_equal_above; 48 | pmemkv_get_equal_below; 49 | pmemkv_iterator_delete; 50 | pmemkv_iterator_is_next; 51 | pmemkv_iterator_key; 52 | pmemkv_iterator_new; 53 | pmemkv_iterator_next; 54 | pmemkv_iterator_prev; 55 | pmemkv_iterator_read_range; 56 | pmemkv_iterator_seek; 57 | pmemkv_iterator_seek_higher; 58 | pmemkv_iterator_seek_higher_eq; 59 | pmemkv_iterator_seek_lower; 60 | pmemkv_iterator_seek_lower_eq; 61 | pmemkv_iterator_seek_to_first; 62 | pmemkv_iterator_seek_to_last; 63 | pmemkv_open; 64 | pmemkv_put; 65 | pmemkv_remove; 66 | pmemkv_tx_abort; 67 | pmemkv_tx_begin; 68 | pmemkv_tx_commit; 69 | pmemkv_tx_end; 70 | pmemkv_tx_put; 71 | pmemkv_tx_remove; 72 | pmemkv_write_iterator_abort; 73 | pmemkv_write_iterator_commit; 74 | pmemkv_write_iterator_delete; 75 | pmemkv_write_iterator_new; 76 | pmemkv_write_iterator_write_range; 77 | local: 78 | *; 79 | }; 80 | -------------------------------------------------------------------------------- /tests/wrong_engine_name_test.cc: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2019-2021, Intel Corporation */ 3 | 4 | #include 5 | 6 | #include "unittest.hpp" 7 | 8 | /** 9 | * Tests if open() returns WRONG_ENGINE_NAME if wrong engine's name is passed. 10 | */ 11 | 12 | static bool wrong_engine_name_test(std::string name) 13 | { 14 | /** 15 | * TEST: if engine is not switched on (in CMake) it should not open 16 | */ 17 | pmem::kv::db db; 18 | return db.open(name) == pmem::kv::status::WRONG_ENGINE_NAME; 19 | } 20 | 21 | static void errormsg_test() 22 | { 23 | /** 24 | * TEST: using WRONG_ENGINE_NAME status, we check if errormsg is properly set 25 | */ 26 | pmem::kv::db kv; 27 | auto s = kv.open("non-existing name"); 28 | ASSERT_STATUS(s, pmem::kv::status::WRONG_ENGINE_NAME); 29 | 30 | auto err = pmem::kv::errormsg(); 31 | UT_ASSERT(err.size() > 0); 32 | 33 | s = kv.open("non-existing name"); 34 | ASSERT_STATUS(s, pmem::kv::status::WRONG_ENGINE_NAME); 35 | s = kv.open("non-existing name"); 36 | ASSERT_STATUS(s, pmem::kv::status::WRONG_ENGINE_NAME); 37 | 38 | /* Test whether errormsg is cleared correctly after each error */ 39 | UT_ASSERT(pmem::kv::errormsg() == err); 40 | 41 | /* Test if instance of db reports the same error */ 42 | UT_ASSERT(kv.errormsg() == err); 43 | 44 | kv.close(); 45 | } 46 | 47 | int main() 48 | { 49 | UT_ASSERT(wrong_engine_name_test("non_existent_name")); 50 | 51 | #ifndef ENGINE_CMAP 52 | UT_ASSERT(wrong_engine_name_test("cmap")); 53 | #endif 54 | 55 | #ifndef ENGINE_VSMAP 56 | UT_ASSERT(wrong_engine_name_test("vsmap")); 57 | #endif 58 | 59 | #ifndef ENGINE_VCMAP 60 | UT_ASSERT(wrong_engine_name_test("vcmap")); 61 | #endif 62 | 63 | #ifndef ENGINE_CSMAP 64 | UT_ASSERT(wrong_engine_name_test("csmap")); 65 | #endif 66 | 67 | #ifndef ENGINE_TREE3 68 | UT_ASSERT(wrong_engine_name_test("tree3")); 69 | #endif 70 | 71 | #ifndef ENGINE_STREE 72 | UT_ASSERT(wrong_engine_name_test("stree")); 73 | #endif 74 | 75 | #ifndef ENGINE_RADIX 76 | UT_ASSERT(wrong_engine_name_test("radix")); 77 | #endif 78 | 79 | #ifndef ENGINE_ROBINHOOD 80 | UT_ASSERT(wrong_engine_name_test("robinhood")); 81 | #endif 82 | #ifndef ENGINE_DRAM_VCMAP 83 | UT_ASSERT(wrong_engine_name_test("dram_vcmap")); 84 | #endif 85 | 86 | errormsg_test(); 87 | 88 | return 0; 89 | } 90 | -------------------------------------------------------------------------------- /tests/engine_scenarios/all/open.cc: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2021, Intel Corporation */ 3 | 4 | #include "unittest.hpp" 5 | 6 | /* 7 | * Tests for config flags. 8 | * Setting create_if_missing to control kv.open() or unsetting both flags 9 | * should not fail in any engine. 10 | * If engine supports these flags the scenarios below, should just open the pool. 11 | * Engines with no support for these flags should just not read them. 12 | */ 13 | 14 | static void OpenWithCreateIfMissing(std::string path, std::string engine, size_t size, 15 | bool flag_value) 16 | { 17 | /** 18 | * TEST: create_if_missing should work fine with either setting, on existing pool. 19 | */ 20 | 21 | pmem::kv::config config; 22 | auto s = config.put_path(path); 23 | ASSERT_STATUS(s, pmem::kv::status::OK); 24 | s = config.put_size(size); 25 | ASSERT_STATUS(s, pmem::kv::status::OK); 26 | s = config.put_create_if_missing(flag_value); 27 | ASSERT_STATUS(s, pmem::kv::status::OK); 28 | 29 | pmem::kv::db kv; 30 | s = kv.open(engine, std::move(config)); 31 | ASSERT_STATUS(s, pmem::kv::status::OK); 32 | } 33 | 34 | static void OpenWithBothFlagsFalse(std::string path, std::string engine, size_t size) 35 | { 36 | /** 37 | * TEST: both flags set to false, it should just open pool. 38 | */ 39 | 40 | pmem::kv::config config; 41 | auto s = config.put_path(path); 42 | ASSERT_STATUS(s, pmem::kv::status::OK); 43 | s = config.put_size(size); 44 | ASSERT_STATUS(s, pmem::kv::status::OK); 45 | s = config.put_create_or_error_if_exists(false); 46 | ASSERT_STATUS(s, pmem::kv::status::OK); 47 | s = config.put_create_if_missing(false); 48 | ASSERT_STATUS(s, pmem::kv::status::OK); 49 | 50 | pmem::kv::db kv; 51 | s = kv.open(engine, std::move(config)); 52 | ASSERT_STATUS(s, pmem::kv::status::OK); 53 | } 54 | 55 | static void test(int argc, char *argv[]) 56 | { 57 | if (argc < 4) 58 | UT_FATAL("usage: %s engine path size", argv[0]); 59 | 60 | auto engine = argv[1]; 61 | auto path = argv[2]; 62 | size_t size = std::stoul(argv[3]); 63 | 64 | OpenWithBothFlagsFalse(path, engine, size); 65 | 66 | for (auto flag : {true, false}) { 67 | OpenWithCreateIfMissing(path, engine, size, flag); 68 | } 69 | } 70 | 71 | int main(int argc, char *argv[]) 72 | { 73 | return run_test([&] { test(argc, argv); }); 74 | } 75 | -------------------------------------------------------------------------------- /tests/comparator/basic.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2020, Intel Corporation */ 3 | 4 | #include 5 | 6 | #include "unittest.h" 7 | 8 | #include 9 | 10 | static int ARG_VALUE = 0xABC; 11 | 12 | static int reverse_three_way_compare(const char *key1, size_t keybytes1, const char *key2, 13 | size_t keybytes2, void *arg) 14 | { 15 | UT_ASSERT(*((int *)arg) == ARG_VALUE); 16 | 17 | /* Compare just first bytes */ 18 | return key2[0] - key1[0]; 19 | } 20 | 21 | static const char *keys[3]; 22 | static int keys_count = 0; 23 | 24 | static int get_callback(const char *key, size_t kb, const char *value, size_t vb, 25 | void *arg) 26 | { 27 | char *key_copy = malloc(kb); 28 | memcpy(key_copy, key, kb); 29 | 30 | keys[keys_count++] = key_copy; 31 | 32 | return 0; 33 | } 34 | 35 | static void test_valid_comparator(const char *engine, pmemkv_config *cfg) 36 | { 37 | pmemkv_comparator *cmp = pmemkv_comparator_new(&reverse_three_way_compare, 38 | "single_byte_compare", &ARG_VALUE); 39 | UT_ASSERTne(cmp, NULL); 40 | 41 | int s = pmemkv_config_put_comparator(cfg, cmp); 42 | UT_ASSERTeq(s, PMEMKV_STATUS_OK); 43 | 44 | pmemkv_db *db; 45 | 46 | s = pmemkv_open(engine, cfg, &db); 47 | UT_ASSERTeq(s, PMEMKV_STATUS_OK); 48 | 49 | s = pmemkv_put(db, "123", 3, "1", 1); 50 | UT_ASSERTeq(s, PMEMKV_STATUS_OK); 51 | 52 | s = pmemkv_put(db, "333", 3, "1", 1); 53 | UT_ASSERTeq(s, PMEMKV_STATUS_OK); 54 | 55 | s = pmemkv_put(db, "223", 3, "1", 1); 56 | UT_ASSERTeq(s, PMEMKV_STATUS_OK); 57 | 58 | pmemkv_get_all(db, &get_callback, NULL); 59 | 60 | UT_ASSERTeq(keys_count, 3); 61 | UT_ASSERTeq(memcmp(keys[0], "333", 3), 0); 62 | UT_ASSERTeq(memcmp(keys[1], "223", 3), 0); 63 | UT_ASSERTeq(memcmp(keys[2], "123", 3), 0); 64 | 65 | pmemkv_close(db); 66 | } 67 | 68 | static void test_nullptr_function(const char *engine, pmemkv_config *cfg) 69 | { 70 | pmemkv_comparator *cmp = pmemkv_comparator_new(NULL, "name", &ARG_VALUE); 71 | UT_ASSERTeq(cmp, NULL); 72 | 73 | pmemkv_config_delete(cfg); 74 | } 75 | 76 | int main(int argc, char *argv[]) 77 | { 78 | START(); 79 | 80 | if (argc < 3) 81 | UT_FATAL("usage %s: engine config", argv[0]); 82 | 83 | test_valid_comparator(argv[1], C_CONFIG_FROM_JSON(argv[2])); 84 | test_nullptr_function(argv[1], C_CONFIG_FROM_JSON(argv[2])); 85 | 86 | return 0; 87 | } 88 | -------------------------------------------------------------------------------- /utils/docker/images/Dockerfile.fedora-rawhide: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2016-2021, Intel Corporation 3 | 4 | # 5 | # Dockerfile - a 'recipe' for Docker to build an image of Fedora-based 6 | # environment prepared for running pmemkv build and tests. 7 | # PMDK (libpmem & libpmemobj) and Valgrind are installed from dnf repo. 8 | # 9 | 10 | # Pull base image 11 | FROM registry.fedoraproject.org/fedora:rawhide 12 | MAINTAINER igor.chorazewicz@intel.com 13 | 14 | # Set required environment variables 15 | ENV OS fedora 16 | ENV OS_VER rawhide 17 | ENV PACKAGE_MANAGER rpm 18 | ENV NOTTY 1 19 | 20 | # Additional parameters to build docker without building components 21 | ARG SKIP_VALGRIND_BUILD 22 | ARG SKIP_PMDK_BUILD 23 | ARG SKIP_LIBPMEMOBJCPP_BUILD 24 | 25 | # Base development packages 26 | ARG BASE_DEPS="\ 27 | cmake \ 28 | gcc \ 29 | gcc-c++ \ 30 | git \ 31 | make" 32 | 33 | # Dependencies for compiling pmemkv project 34 | ARG PMEMKV_DEPS="\ 35 | memkind-devel \ 36 | rapidjson-devel \ 37 | tbb-devel" 38 | 39 | # libpmemobj-cpp's dependencies (optional; libpmemobj++-devel package may be used instead) 40 | ARG LIBPMEMOBJ_CPP_DEPS="\ 41 | libatomic \ 42 | libpmemobj-devel \ 43 | rpm-build \ 44 | tbb-devel" 45 | 46 | # Examples (optional) 47 | ARG EXAMPLES_DEPS="\ 48 | ncurses-devel \ 49 | SFML-devel" 50 | 51 | # Documentation (optional) 52 | ARG DOC_DEPS="\ 53 | doxygen \ 54 | graphviz" 55 | 56 | # Tests (optional) 57 | # NOTE: glibc is installed as a separate command; see below 58 | ARG TESTS_DEPS="\ 59 | gdb \ 60 | libpmem-devel \ 61 | libunwind-devel \ 62 | pmempool \ 63 | valgrind-devel" 64 | 65 | # Misc for our builds/CI (optional) 66 | ARG MISC_DEPS="\ 67 | clang \ 68 | perl-Text-Diff \ 69 | pkgconf \ 70 | sudo" 71 | 72 | # Update packages and install basic tools 73 | RUN dnf update -y \ 74 | && dnf install -y \ 75 | ${BASE_DEPS} \ 76 | ${PMEMKV_DEPS} \ 77 | ${LIBPMEMOBJ_CPP_DEPS} \ 78 | ${EXAMPLES_DEPS} \ 79 | ${DOC_DEPS} \ 80 | ${TESTS_DEPS} \ 81 | ${MISC_DEPS} \ 82 | && dnf debuginfo-install -y glibc \ 83 | && dnf clean all 84 | 85 | # Install pmdk c++ bindings 86 | COPY install-libpmemobj-cpp.sh install-libpmemobj-cpp.sh 87 | RUN ./install-libpmemobj-cpp.sh RPM 88 | 89 | # Add user 90 | ENV USER user 91 | ENV USERPASS pass 92 | RUN useradd -m $USER \ 93 | && echo "$USER:$USERPASS" | chpasswd \ 94 | && gpasswd wheel -a $USER 95 | USER $USER 96 | -------------------------------------------------------------------------------- /utils/docker/run-coverity.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | # Copyright 2018-2021, Intel Corporation 4 | 5 | # 6 | # run-coverity.sh - runs the Coverity scan build 7 | # 8 | 9 | set -e 10 | 11 | if [[ "${CI_REPO_SLUG}" != "${GITHUB_REPO}" \ 12 | && ( "${COVERITY_SCAN_NOTIFICATION_EMAIL}" == "" \ 13 | || "${COVERITY_SCAN_TOKEN}" == "" ) ]]; then 14 | echo 15 | echo "Skipping Coverity build:"\ 16 | "COVERITY_SCAN_TOKEN=\"${COVERITY_SCAN_TOKEN}\" or"\ 17 | "COVERITY_SCAN_NOTIFICATION_EMAIL="\ 18 | "\"${COVERITY_SCAN_NOTIFICATION_EMAIL}\" is not set" 19 | exit 0 20 | fi 21 | 22 | # Prepare build environment 23 | source `dirname ${0}`/prepare-for-build.sh 24 | 25 | CERT_FILE=/etc/ssl/certs/ca-certificates.crt 26 | TEMP_CF=$(mktemp) 27 | cp ${CERT_FILE} ${TEMP_CF} 28 | 29 | # Download Coverity certificate 30 | echo -n | openssl s_client -connect scan.coverity.com:443 | \ 31 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | \ 32 | tee -a ${TEMP_CF} 33 | 34 | sudo_password mv ${TEMP_CF} ${CERT_FILE} 35 | 36 | cd ${WORKDIR} 37 | mkdir build 38 | cd build 39 | cmake .. -DCMAKE_BUILD_TYPE=Debug 40 | 41 | export COVERITY_SCAN_PROJECT_NAME="${CI_REPO_SLUG}" 42 | export COVERITY_SCAN_BRANCH_PATTERN="master" 43 | export COVERITY_SCAN_BUILD_COMMAND="make -j$(nproc)" 44 | 45 | # 46 | # Run the Coverity scan 47 | # 48 | 49 | # The 'travisci_build_coverity_scan.sh' script requires the following 50 | # environment variables to be set: 51 | # - TRAVIS_BRANCH - has to contain the name of the current branch 52 | # - TRAVIS_PULL_REQUEST - has to be set to 'true' in case of pull requests 53 | # 54 | export TRAVIS_BRANCH=${CI_BRANCH} 55 | [ "${CI_EVENT_TYPE}" == "pull_request" ] && export TRAVIS_PULL_REQUEST="true" 56 | 57 | # XXX: Patch the Coverity script. 58 | # Recently, this script regularly exits with an error, even though 59 | # the build is successfully submitted. Probably because the status code 60 | # is missing in response, or it's not 201. 61 | # Changes: 62 | # 1) change the expected status code to 200 and 63 | # 2) print the full response string. 64 | # 65 | # This change should be reverted when the Coverity script is fixed. 66 | # 67 | # The previous version was: 68 | # curl -s https://scan.coverity.com/scripts/travisci_build_coverity_scan.sh | bash 69 | 70 | wget https://scan.coverity.com/scripts/travisci_build_coverity_scan.sh 71 | patch < ../utils/docker/0001-travis-fix-travisci_build_coverity_scan.sh.patch 72 | bash ./travisci_build_coverity_scan.sh 73 | -------------------------------------------------------------------------------- /tests/engine_scenarios/pmreorder/insert.cc: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2020-2021, Intel Corporation */ 3 | 4 | /* 5 | * insert.cc -- insert pmreorder test 6 | */ 7 | 8 | #include "unittest.hpp" 9 | 10 | static constexpr size_t len_elements = 10; 11 | 12 | static void check_exist(pmem::kv::db &kv, const std::string &element, 13 | pmem::kv::status exists) 14 | { 15 | std::string value; 16 | UT_ASSERT(kv.get(element, &value) == exists); 17 | 18 | if (exists == pmem::kv::status::OK) { 19 | UT_ASSERT(element == value); 20 | } 21 | } 22 | 23 | static void test_init(pmem::kv::db &kv) 24 | { 25 | for (size_t i = 0; i < len_elements; i++) { 26 | std::string element = entry_from_number(i); 27 | ASSERT_STATUS(kv.put(element, element), pmem::kv::status::OK); 28 | check_exist(kv, element, pmem::kv::status::OK); 29 | } 30 | } 31 | 32 | static void test_insert(pmem::kv::db &kv) 33 | { 34 | ASSERT_SIZE(kv, len_elements); 35 | 36 | std::string element = entry_from_number(len_elements); 37 | ASSERT_STATUS(kv.put(element, element), pmem::kv::status::OK); 38 | check_exist(kv, element, pmem::kv::status::OK); 39 | } 40 | 41 | static void check_consistency(pmem::kv::db &kv) 42 | { 43 | std::size_t size; 44 | ASSERT_STATUS(kv.count_all(size), pmem::kv::status::OK); 45 | std::size_t count = 0; 46 | 47 | for (size_t i = 0; i <= len_elements; i++) { 48 | std::string element = entry_from_number(i); 49 | if (kv.exists(element) == pmem::kv::status::OK) { 50 | ++count; 51 | check_exist(kv, element, pmem::kv::status::OK); 52 | } else { 53 | check_exist(kv, element, pmem::kv::status::NOT_FOUND); 54 | } 55 | } 56 | 57 | UT_ASSERTeq(count, size); 58 | } 59 | 60 | static void test(int argc, char *argv[]) 61 | { 62 | std::cout << "ARGC: " << argc << std::endl; 63 | for (int i = 0; i < argc; ++i) { 64 | std::cout << "ARGV " << i << " : " << argv[i] << std::endl; 65 | } 66 | if (argc < 4) 67 | UT_FATAL("usage: %s engine json_config ", argv[0]); 68 | 69 | std::string mode = argv[3]; 70 | if (mode != "create" && mode != "open" && mode != "insert") 71 | UT_FATAL("usage: %s engine json_config ", argv[0]); 72 | 73 | auto kv = INITIALIZE_KV(argv[1], CONFIG_FROM_JSON(argv[2])); 74 | 75 | if (mode == "create") { 76 | test_init(kv); 77 | } else if (mode == "open") { 78 | check_consistency(kv); 79 | } else if (mode == "insert") { 80 | test_insert(kv); 81 | } 82 | 83 | kv.close(); 84 | } 85 | 86 | int main(int argc, char *argv[]) 87 | { 88 | return run_test([&] { test(argc, argv); }); 89 | } 90 | -------------------------------------------------------------------------------- /src/engines/blackhole.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2017-2021, Intel Corporation */ 3 | 4 | #ifndef LIBPMEMKV_BLACKHOLE_H 5 | #define LIBPMEMKV_BLACKHOLE_H 6 | 7 | #include "../engine.h" 8 | 9 | namespace pmem 10 | { 11 | namespace kv 12 | { 13 | 14 | class blackhole : public engine_base { 15 | class blackhole_iterator; 16 | 17 | public: 18 | blackhole(std::unique_ptr cfg); 19 | ~blackhole(); 20 | 21 | std::string name() final; 22 | 23 | status count_all(std::size_t &cnt) final; 24 | status count_above(string_view key, std::size_t &cnt) final; 25 | status count_equal_above(string_view key, std::size_t &cnt) final; 26 | status count_equal_below(string_view key, std::size_t &cnt) final; 27 | status count_below(string_view key, std::size_t &cnt) final; 28 | status count_between(string_view key1, string_view key2, std::size_t &cnt) final; 29 | 30 | status get_all(get_kv_callback *callback, void *arg) final; 31 | status get_above(string_view key, get_kv_callback *callback, void *arg) final; 32 | status get_equal_above(string_view key, get_kv_callback *callback, 33 | void *arg) final; 34 | status get_equal_below(string_view key, get_kv_callback *callback, 35 | void *arg) final; 36 | status get_below(string_view key, get_kv_callback *callback, void *arg) final; 37 | status get_between(string_view key1, string_view key2, get_kv_callback *callback, 38 | void *arg) final; 39 | 40 | status exists(string_view key) final; 41 | 42 | status get(string_view key, get_v_callback *callback, void *arg) final; 43 | 44 | status put(string_view key, string_view value) final; 45 | 46 | status remove(string_view key) final; 47 | 48 | internal::iterator_base *new_iterator() final; 49 | internal::iterator_base *new_const_iterator() final; 50 | }; 51 | 52 | class blackhole::blackhole_iterator : public internal::iterator_base { 53 | public: 54 | status seek(string_view key) final; 55 | 56 | result key() final; 57 | 58 | result> read_range(size_t pos, size_t n) final; 59 | 60 | private: 61 | std::string name(); 62 | }; 63 | 64 | class blackhole_factory : public engine_base::factory_base { 65 | public: 66 | std::unique_ptr 67 | create(std::unique_ptr cfg) override 68 | { 69 | return std::unique_ptr(new blackhole(std::move(cfg))); 70 | }; 71 | std::string get_name() override 72 | { 73 | return "blackhole"; 74 | }; 75 | }; 76 | 77 | } /* namespace kv */ 78 | } /* namespace pmem */ 79 | 80 | #endif /* LIBPMEMKV_BLACKHOLE_H */ 81 | -------------------------------------------------------------------------------- /tests/comparator/default_reopen.cc: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2020, Intel Corporation */ 3 | 4 | #include "unittest.hpp" 5 | 6 | #include 7 | 8 | using namespace pmem::kv; 9 | 10 | static const char *EXPECTED_ERR_MSG = 11 | "[pmemkv_open] Comparator with name: \"__pmemkv_binary_comparator\" expected"; 12 | 13 | class invalid_comparator { 14 | public: 15 | int compare(string_view k1, string_view k2) 16 | { 17 | return k2.compare(k1); 18 | } 19 | 20 | std::string name() 21 | { 22 | return "invalid_cmp"; 23 | } 24 | }; 25 | 26 | static void insert(std::string name, pmem::kv::config &&cfg) 27 | { 28 | pmem::kv::db kv; 29 | auto s = kv.open(name, std::move(cfg)); 30 | ASSERT_STATUS(s, status::OK); 31 | 32 | s = kv.put("A", "A"); 33 | ASSERT_STATUS(s, status::OK); 34 | s = kv.put("B", "B"); 35 | ASSERT_STATUS(s, status::OK); 36 | s = kv.put("C", "C"); 37 | ASSERT_STATUS(s, status::OK); 38 | s = kv.put("D", "D"); 39 | ASSERT_STATUS(s, status::OK); 40 | 41 | kv.close(); 42 | } 43 | 44 | static void check_valid(std::string name, pmem::kv::config &&cfg) 45 | { 46 | pmem::kv::db kv; 47 | auto s = kv.open(name, std::move(cfg)); 48 | ASSERT_STATUS(s, status::OK); 49 | 50 | size_t cnt = std::numeric_limits::max(); 51 | s = kv.count_above("B", cnt); 52 | ASSERT_STATUS(s, status::OK); 53 | UT_ASSERTeq(cnt, 2); 54 | 55 | cnt = std::numeric_limits::max(); 56 | s = kv.count_below("B", cnt); 57 | ASSERT_STATUS(s, status::OK); 58 | UT_ASSERTeq(cnt, 1); 59 | kv.close(); 60 | } 61 | 62 | static void check_invalid(std::string name, pmem::kv::config &&cfg) 63 | { 64 | auto s = cfg.put_comparator(invalid_comparator{}); 65 | ASSERT_STATUS(s, status::OK); 66 | 67 | pmem::kv::db kv; 68 | s = kv.open(name, std::move(cfg)); 69 | ASSERT_STATUS(s, status::COMPARATOR_MISMATCH); 70 | 71 | UT_ASSERT(pmem::kv::errormsg() == EXPECTED_ERR_MSG); 72 | } 73 | 74 | static void test(int argc, char *argv[]) 75 | { 76 | if (argc < 4) 77 | UT_FATAL("usage: %s engine json_config insert/check", argv[0]); 78 | 79 | std::string engine = argv[1]; 80 | std::string json_config = argv[2]; 81 | std::string mode = argv[3]; 82 | if (mode != "insert" && mode != "check") 83 | UT_FATAL("usage: %s engine json_config insert/check", argv[0]); 84 | 85 | if (mode == "insert") { 86 | insert(engine, CONFIG_FROM_JSON(json_config)); 87 | } else { 88 | check_valid(engine, CONFIG_FROM_JSON(json_config)); 89 | check_invalid(engine, CONFIG_FROM_JSON(json_config)); 90 | } 91 | } 92 | 93 | int main(int argc, char *argv[]) 94 | { 95 | return run_test([&] { test(argc, argv); }); 96 | } 97 | -------------------------------------------------------------------------------- /utils/docker/run-compatibility.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | # Copyright 2020-2021, Intel Corporation 4 | 5 | # 6 | # run-compatibility.sh - verify compatibility between versions 7 | # 8 | 9 | set -e 10 | 11 | TEST_DIR=${PMEMKV_TEST_DIR:-${DEFAULT_TEST_DIR}} 12 | 13 | INSTALL_PREFIX=/opt 14 | 15 | source `dirname ${0}`/prepare-for-build.sh 16 | 17 | function build_and_install_pmemkv() { 18 | version=${1} 19 | git checkout ${version} 20 | 21 | mkdir ${WORKDIR}/build 22 | cd ${WORKDIR}/build 23 | 24 | cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo \ 25 | -DBUILD_TESTS=OFF \ 26 | -DCMAKE_INSTALL_PREFIX=${INSTALL_PREFIX}/pmemkv-${version} 27 | make -j$(nproc) 28 | sudo_password -S make -j$(nproc) install 29 | 30 | workspace_cleanup 31 | } 32 | 33 | function verify_compatibility() { 34 | version=${1} 35 | 36 | echo 37 | echo "##################################################################" 38 | echo "### Verifying compatibility with ${version}" 39 | echo "##################################################################" 40 | 41 | mkdir ${WORKDIR}/build 42 | cd ${WORKDIR}/build 43 | 44 | mkdir pmemkv-HEAD 45 | cd pmemkv-HEAD 46 | PKG_CONFIG_PATH=${INSTALL_PREFIX}/pmemkv-HEAD/lib64/pkgconfig cmake ../../tests/compatibility 47 | make -j$(nproc) 48 | cd .. 49 | 50 | mkdir pmemkv-${version} 51 | cd pmemkv-${version} 52 | PKG_CONFIG_PATH=${INSTALL_PREFIX}/pmemkv-${version}/lib64/pkgconfig cmake ../../tests/compatibility 53 | make -j$(nproc) 54 | cd ../.. 55 | 56 | PMEM_IS_PMEM_FORCE=1 ${WORKDIR}/tests/compatibility/cmap.sh ${WORKDIR}/build/pmemkv-HEAD/cmap_compatibility ${WORKDIR}/build/pmemkv-${version}/cmap_compatibility ${TEST_DIR}/testfile 57 | 58 | workspace_cleanup 59 | } 60 | 61 | ## Main: 62 | # Fetch git history if clone is shallow 63 | [ -f ${WORKDIR}/.git/shallow ] && git fetch --unshallow --tags 64 | 65 | current_version=$(git describe --all) 66 | echo "Current pmemkv version: ${current_version}" 67 | 68 | echo "Build and install current pmemkv's version - 'HEAD'" 69 | build_and_install_pmemkv "HEAD" 70 | 71 | echo "Build and install older pmemkv's versions" 72 | build_and_install_pmemkv "1.0.2" 73 | build_and_install_pmemkv "1.1" 74 | build_and_install_pmemkv "1.2" 75 | build_and_install_pmemkv "1.3" 76 | build_and_install_pmemkv "1.4" 77 | 78 | # checkout HEAD/current version again 79 | git checkout ${current_version} 80 | 81 | echo "Test compatibility of previous versions with current one" 82 | verify_compatibility "1.0.2" 83 | verify_compatibility "1.1" 84 | verify_compatibility "1.2" 85 | verify_compatibility "1.3" 86 | verify_compatibility "1.4" 87 | -------------------------------------------------------------------------------- /tests/engine_scenarios/pmemobj/error_handling_tx_oom.cc: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2020, Intel Corporation */ 3 | 4 | #include "mock_tx_alloc.h" 5 | #include "unittest.hpp" 6 | 7 | const std::string LONGSTR = 8 | "123456789A123456789A123456789A123456789A123456789A123456789A123456789A"; 9 | 10 | const int init_iterations = 50000; 11 | 12 | void validate(pmem::kv::db &kv) 13 | { 14 | for (size_t i = 0; i < init_iterations; i++) { 15 | std::string istr = std::to_string(i); 16 | auto s = kv.get(istr, [&](pmem::kv::string_view val) { 17 | UT_ASSERT(val.compare(istr + "!") == 0); 18 | }); 19 | ASSERT_STATUS(s, pmem::kv::status::OK); 20 | } 21 | } 22 | 23 | void populate(pmem::kv::db &kv) 24 | { 25 | for (size_t i = 0; i < init_iterations; i++) { 26 | std::string istr = std::to_string(i); 27 | ASSERT_STATUS(kv.put(istr, (istr + "!")), pmem::kv::status::OK); 28 | } 29 | } 30 | 31 | void LongStringTest(pmem::kv::db &kv) 32 | { 33 | populate(kv); 34 | 35 | ASSERT_STATUS(kv.remove("100"), pmem::kv::status::OK); 36 | tx_alloc_should_fail = true; 37 | ASSERT_STATUS(kv.put("100", LONGSTR), pmem::kv::status::OUT_OF_MEMORY); 38 | tx_alloc_should_fail = false; 39 | ASSERT_STATUS(kv.put("100", "100!"), pmem::kv::status::OK); 40 | 41 | validate(kv); 42 | } 43 | 44 | void ShortKeyTest(pmem::kv::db &kv) 45 | { 46 | populate(kv); 47 | 48 | tx_alloc_should_fail = true; 49 | for (int i = 0; i <= 99999; i++) { 50 | ASSERT_STATUS(kv.put("123456", LONGSTR), pmem::kv::status::OUT_OF_MEMORY); 51 | } 52 | tx_alloc_should_fail = false; 53 | ASSERT_STATUS(kv.remove("4567"), pmem::kv::status::OK); 54 | ASSERT_STATUS(kv.put("4567", "4567!"), pmem::kv::status::OK); 55 | 56 | validate(kv); 57 | } 58 | 59 | void LongKeyTest(pmem::kv::db &kv) 60 | { 61 | populate(kv); 62 | 63 | tx_alloc_should_fail = true; 64 | for (int i = 0; i <= 99999; i++) { 65 | ASSERT_STATUS(kv.put(LONGSTR, "1"), pmem::kv::status::OUT_OF_MEMORY); 66 | ASSERT_STATUS(kv.put(LONGSTR, LONGSTR), pmem::kv::status::OUT_OF_MEMORY); 67 | } 68 | tx_alloc_should_fail = false; 69 | ASSERT_STATUS(kv.remove("34567"), pmem::kv::status::OK); 70 | ASSERT_STATUS(kv.put("34567", "34567!"), pmem::kv::status::OK); 71 | 72 | validate(kv); 73 | } 74 | 75 | static void test(int argc, char *argv[]) 76 | { 77 | using namespace std::placeholders; 78 | 79 | if (argc < 3) 80 | UT_FATAL("usage: %s engine json_config", argv[0]); 81 | 82 | run_engine_tests(argv[1], argv[2], 83 | { 84 | LongStringTest, 85 | ShortKeyTest, 86 | LongKeyTest, 87 | }); 88 | } 89 | 90 | int main(int argc, char *argv[]) 91 | { 92 | return run_test([&] { test(argc, argv); }); 93 | } 94 | -------------------------------------------------------------------------------- /tests/engine_scenarios/pmreorder/erase.cc: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2020-2021, Intel Corporation */ 3 | 4 | /* 5 | * erase.cc -- erase pmreorder test 6 | */ 7 | 8 | #include "unittest.hpp" 9 | 10 | static constexpr size_t len_elements = 10; 11 | 12 | static void check_exist(pmem::kv::db &kv, const std::string &element, 13 | pmem::kv::status exists) 14 | { 15 | std::string value; 16 | UT_ASSERT(kv.get(element, &value) == exists); 17 | 18 | if (exists == pmem::kv::status::OK) { 19 | UT_ASSERT(element == value); 20 | } 21 | } 22 | 23 | static void test_init(pmem::kv::db &kv) 24 | { 25 | for (size_t i = 0; i < len_elements; i++) { 26 | std::string element = entry_from_number(i); 27 | ASSERT_STATUS(kv.put(element, element), pmem::kv::status::OK); 28 | check_exist(kv, element, pmem::kv::status::OK); 29 | } 30 | } 31 | 32 | static void test_erase(pmem::kv::db &kv) 33 | { 34 | ASSERT_SIZE(kv, len_elements); 35 | 36 | std::string element = entry_from_number(1); /* remove this element */ 37 | check_exist(kv, element, pmem::kv::status::OK); 38 | 39 | ASSERT_STATUS(kv.remove(element), pmem::kv::status::OK); 40 | check_exist(kv, element, pmem::kv::status::NOT_FOUND); 41 | 42 | ASSERT_SIZE(kv, len_elements - 1); 43 | } 44 | 45 | static void check_consistency(pmem::kv::db &kv) 46 | { 47 | std::size_t size; 48 | ASSERT_STATUS(kv.count_all(size), pmem::kv::status::OK); 49 | std::size_t count = 0; 50 | 51 | for (size_t i = 0; i < len_elements; i++) { 52 | std::string element = entry_from_number(i); 53 | if (kv.exists(element) == pmem::kv::status::OK) { 54 | ++count; 55 | check_exist(kv, element, pmem::kv::status::OK); 56 | } else { 57 | check_exist(kv, element, pmem::kv::status::NOT_FOUND); 58 | } 59 | } 60 | 61 | UT_ASSERTeq(count, size); 62 | } 63 | 64 | static void test(int argc, char *argv[]) 65 | { 66 | std::cout << "ARGC: " << argc << std::endl; 67 | for (int i = 0; i < argc; ++i) { 68 | std::cout << "ARGV " << i << " : " << argv[i] << std::endl; 69 | } 70 | if (argc < 4) 71 | UT_FATAL("usage: %s engine json_config ", argv[0]); 72 | 73 | std::string mode = argv[3]; 74 | if (mode != "create" && mode != "open" && mode != "erase") 75 | UT_FATAL("usage: %s engine json_config ", argv[0]); 76 | 77 | auto kv = INITIALIZE_KV(argv[1], CONFIG_FROM_JSON(argv[2])); 78 | 79 | if (mode == "create") { 80 | test_init(kv); 81 | } else if (mode == "open") { 82 | check_consistency(kv); 83 | } else if (mode == "erase") { 84 | test_erase(kv); 85 | } 86 | 87 | kv.close(); 88 | } 89 | 90 | int main(int argc, char *argv[]) 91 | { 92 | return run_test([&] { test(argc, argv); }); 93 | } 94 | -------------------------------------------------------------------------------- /examples/pmemkv_comparator_cpp/pmemkv_comparator.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2020-2021, Intel Corporation */ 3 | 4 | /* 5 | * pmemkv_comparator.cpp -- example usage of pmemkv with custom comparator. 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #define ASSERT(expr) \ 15 | do { \ 16 | if (!(expr)) \ 17 | std::cout << pmemkv_errormsg() << std::endl; \ 18 | assert(expr); \ 19 | } while (0) 20 | #define LOG(msg) std::cout << msg << std::endl 21 | 22 | using namespace pmem::kv; 23 | 24 | const uint64_t SIZE = 1024UL * 1024UL * 1024UL; 25 | 26 | //! [custom-comparator] 27 | class lexicographical_comparator { 28 | public: 29 | int compare(string_view k1, string_view k2) 30 | { 31 | if (k1.compare(k2) == 0) 32 | return 0; 33 | else if (std::lexicographical_compare(k1.data(), k1.data() + k1.size(), 34 | k2.data(), k2.data() + k2.size())) 35 | return -1; 36 | else 37 | return 1; 38 | } 39 | 40 | std::string name() 41 | { 42 | return "lexicographical_comparator"; 43 | } 44 | }; 45 | //! [custom-comparator] 46 | 47 | int main(int argc, char *argv[]) 48 | { 49 | if (argc < 2) { 50 | std::cerr << "Usage: " << argv[0] << " file\n"; 51 | exit(1); 52 | } 53 | 54 | /* See libpmemkv_config(3) for more detailed example of config creation */ 55 | LOG("Creating config"); 56 | 57 | //! [comparator-usage] 58 | config cfg; 59 | 60 | status s = cfg.put_path(argv[1]); 61 | ASSERT(s == status::OK); 62 | s = cfg.put_size(SIZE); 63 | ASSERT(s == status::OK); 64 | s = cfg.put_create_if_missing(true); 65 | ASSERT(s == status::OK); 66 | s = cfg.put_comparator(lexicographical_comparator{}); 67 | ASSERT(s == status::OK); 68 | 69 | LOG("Opening pmemkv database with 'csmap' engine"); 70 | db kv; 71 | s = kv.open("csmap", std::move(cfg)); 72 | ASSERT(s == status::OK); 73 | 74 | LOG("Putting new keys"); 75 | s = kv.put("key1", "value1"); 76 | ASSERT(s == status::OK); 77 | s = kv.put("key2", "value2"); 78 | ASSERT(s == status::OK); 79 | s = kv.put("key3", "value3"); 80 | ASSERT(s == status::OK); 81 | 82 | LOG("Iterating over existing keys in order specified by the comparator"); 83 | kv.get_all([](string_view k, string_view v) { 84 | LOG(" visited: " << k.data()); 85 | return 0; 86 | }); 87 | //! [comparator-usage] 88 | 89 | LOG("Closing database"); 90 | return 0; 91 | } 92 | -------------------------------------------------------------------------------- /tests/engine_scenarios/all/iterate.cc: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2017-2021, Intel Corporation */ 3 | 4 | #include "unittest.hpp" 5 | 6 | #include 7 | #include 8 | 9 | /** 10 | * Tests get_all and count_all methods for unsorted engines. 11 | * Since we cannot assume any order, custom sort is applied to results before comparing. 12 | */ 13 | 14 | /* XXX: are we missing check for unsorted engines, if get/count_* methods are not 15 | * supported...? */ 16 | /* XXX: this test should be extended with more data and some removal */ 17 | 18 | using namespace pmem::kv; 19 | 20 | using test_kv = std::pair; 21 | using test_kv_list = std::vector; 22 | 23 | static test_kv_list sort(test_kv_list list) 24 | { 25 | std::sort(list.begin(), list.end(), [](const test_kv &lhs, const test_kv &rhs) { 26 | return lhs.first < rhs.first; 27 | }); 28 | 29 | return list; 30 | } 31 | 32 | static void GetAllTest(pmem::kv::db &kv) 33 | { 34 | /** 35 | * TEST: get_all should return all elements in db and count_all should count them 36 | * properly 37 | */ 38 | 39 | auto entries = test_kv_list{ 40 | {entry_from_string("1"), entry_from_string("one")}, 41 | {entry_from_string("2"), entry_from_string("two")}, 42 | {entry_from_string("记!"), entry_from_string("RR")}, 43 | }; 44 | for (size_t i = 0; i < entries.size(); i++) { 45 | auto e = entries[i]; 46 | ASSERT_STATUS(kv.put(e.first, e.second), status::OK); 47 | ASSERT_SIZE(kv, i + 1); 48 | } 49 | 50 | test_kv_list result; 51 | /* get_all using string_view */ 52 | auto s = kv.get_all([&](string_view k, string_view v) { 53 | result.emplace_back(std::string(k.data(), k.size()), 54 | std::string(v.data(), v.size())); 55 | return 0; 56 | }); 57 | ASSERT_STATUS(s, status::OK); 58 | UT_ASSERT((sort(result) == sort(entries))); 59 | 60 | /* get_all with non-zero exit status from callback*/ 61 | s = kv.get_all([&](string_view k, string_view v) { return 1; }); 62 | ASSERT_STATUS(s, status::STOPPED_BY_CB); 63 | 64 | result = {}; 65 | /* get_all with C-like API */ 66 | s = kv.get_all( 67 | [](const char *k, size_t kb, const char *v, size_t vb, void *arg) { 68 | const auto c = ((test_kv_list *)arg); 69 | c->emplace_back(std::string(k, kb), std::string(v, vb)); 70 | return 0; 71 | }, 72 | &result); 73 | ASSERT_STATUS(s, status::OK); 74 | UT_ASSERT((sort(result) == sort(entries))); 75 | } 76 | 77 | static void test(int argc, char *argv[]) 78 | { 79 | if (argc < 3) 80 | UT_FATAL("usage: %s engine json_config", argv[0]); 81 | 82 | run_engine_tests(argv[1], argv[2], {GetAllTest}); 83 | } 84 | 85 | int main(int argc, char *argv[]) 86 | { 87 | return run_test([&] { test(argc, argv); }); 88 | } 89 | -------------------------------------------------------------------------------- /doc/libpmemkv_json_config.3.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: manual 3 | Content-Style: 'text/css' 4 | title: _MP(PMEMKV_JSON_CONFIG, 3) 5 | collection: libpmemkv 6 | header: PMEMKV_JSON_CONFIG 7 | secondary_title: pmemkv_json_config 8 | ... 9 | 10 | [comment]: <> (SPDX-License-Identifier: BSD-3-Clause) 11 | [comment]: <> (Copyright 2019-2021, Intel Corporation) 12 | 13 | [comment]: <> (libpmemkv_json_config.3 -- man page for libpmemkv_json_config configuration API) 14 | 15 | [NAME](#name)
16 | [SYNOPSIS](#synopsis)
17 | [DESCRIPTION](#description)
18 | [ERRORS](#errors)
19 | [EXAMPLE](#example)
20 | [SEE ALSO](#see-also)
21 | 22 | 23 | # NAME # 24 | 25 | **pmemkv_json_config** - helper configuration API for libpmemkv 26 | 27 | # SYNOPSIS # 28 | 29 | ```c 30 | #include 31 | 32 | int pmemkv_config_from_json(pmemkv_config *config, const char *jsonconfig); 33 | const char *pmemkv_config_from_json_errormsg(void); 34 | ``` 35 | 36 | For general description of pmemkv and available engines see **libpmemkv**(7). 37 | For description of pmemkv core API see **libpmemkv**(3). 38 | For description of configuration API for libpmemkv see **libpmemkv_config**(3). 39 | 40 | # DESCRIPTION # 41 | 42 | pmemkv_json_config is a helper library that provides two functions: 43 | 44 | `int pmemkv_config_from_json(pmemkv_config *config, const char *jsonconfig);` 45 | 46 | : Parses JSON string and puts all items found in JSON into `config`. Allowed types 47 | in JSON strings and their corresponding types in pmemkv_config are: 48 | + **number** -- int64 or uint64 49 | + **string** -- const char * 50 | + **object** -- (another JSON string) -> pointer to pmemkv_config (can be obtained using pmemkv_config_get_object) 51 | + **True**, **False** -- int64 52 | 53 | `const char *pmemkv_config_from_json_errormsg(void);` 54 | 55 | : Returns a human readable string describing the last error. 56 | 57 | The `pmemkv_config_from_json` function depends on RapidJSON library 58 | what is the direct cause of the creation of this small library. 59 | 60 | The building of this library is enabled by default. 61 | It can be disabled by setting the **BUILD_JSON_CONFIG** CMake variable to OFF: 62 | 63 | ```sh 64 | cmake .. -DBUILD_JSON_CONFIG=OFF 65 | ``` 66 | 67 | ## ERRORS ## 68 | 69 | The `pmemkv_config_from_json()` function returns status. Possible return values are: 70 | 71 | + **PMEMKV_STATUS_OK** -- no error 72 | + **PMEMKV_STATUS_UNKNOWN_ERROR** -- unknown error 73 | + **PMEMKV_STATUS_CONFIG_PARSING_ERROR** -- parsing config data failed 74 | 75 | # EXAMPLE # 76 | 77 | An example using this API can be found in **libpmemkv_config**(3). 78 | 79 | # SEE ALSO # 80 | 81 | **libpmemkv**(7), **libpmemkv**(3), **libpmemkv_config**(3) and **** 82 | -------------------------------------------------------------------------------- /cmake/packages.cmake: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2019-2021, Intel Corporation 3 | 4 | # 5 | # packages.cmake - CPack configuration for rpm and deb generation 6 | # 7 | 8 | string(TOUPPER "${CPACK_GENERATOR}" CPACK_GENERATOR) 9 | 10 | if(NOT ("${CPACK_GENERATOR}" STREQUAL "DEB" OR 11 | "${CPACK_GENERATOR}" STREQUAL "RPM")) 12 | message(FATAL_ERROR "Wrong CPACK_GENERATOR value, valid generators are: DEB, RPM") 13 | endif() 14 | 15 | set(CPACK_PACKAGING_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") 16 | set(CMAKE_INSTALL_TMPDIR /tmp CACHE PATH "Output dir for temporary package") 17 | set(CPACK_COMPONENTS_ALL_IN_ONE) 18 | 19 | # Filter out some of directories from %dir section, which are expected 20 | # to exist in filesystem. Leaving them might lead to conflicts with other 21 | # packages (for example with 'filesystem' package on fedora which specify 22 | # /usr, /usr/local, etc.) 23 | set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION 24 | ${CPACK_PACKAGING_INSTALL_PREFIX} 25 | ${CPACK_PACKAGING_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR} 26 | ${CPACK_PACKAGING_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/pkgconfig 27 | ${CPACK_PACKAGING_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR} 28 | ${CPACK_PACKAGING_INSTALL_PREFIX}/share 29 | ${CPACK_PACKAGING_INSTALL_PREFIX}/share/doc 30 | ${CPACK_PACKAGING_INSTALL_PREFIX}/share/man 31 | ${CPACK_PACKAGING_INSTALL_PREFIX}/share/man/man3 32 | ${CPACK_PACKAGING_INSTALL_PREFIX}/share/man/man7) 33 | 34 | set(CPACK_PACKAGE_NAME "libpmemkv") 35 | set(CPACK_PACKAGE_VERSION ${VERSION}) 36 | set(CPACK_PACKAGE_VERSION_MAJOR ${VERSION_MAJOR}) 37 | set(CPACK_PACKAGE_VERSION_MINOR ${VERSION_MINOR}) 38 | set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Key/Value Datastore for Persistent Memory") 39 | set(CPACK_PACKAGE_VENDOR "Intel") 40 | 41 | set(CPACK_RPM_PACKAGE_NAME "libpmemkv-devel") 42 | set(CPACK_RPM_PACKAGE_GROUP "Development/Libraries") 43 | set(CPACK_RPM_PACKAGE_LICENSE "BSD") 44 | set(CPACK_RPM_PACKAGE_ARCHITECTURE x86_64) 45 | set(CPACK_RPM_PACKAGE_AUTOREQ "no") 46 | set(CPACK_RPM_PACKAGE_REQUIRES ${RPM_PACKAGE_REQUIRES}) 47 | #set(CPACK_RPM_CHANGELOG_FILE ${PMEMKV_ROOT_DIR}/ChangeLog) 48 | 49 | set(CPACK_DEBIAN_PACKAGE_NAME "libpmemkv-dev") 50 | set(CPACK_DEBIAN_PACKAGE_VERSION ${CPACK_PACKAGE_VERSION}) 51 | set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE amd64) 52 | set(CPACK_DEBIAN_PACKAGE_DEPENDS ${DEB_PACKAGE_REQUIRES}) 53 | set(CPACK_DEBIAN_PACKAGE_MAINTAINER "igor.chorazewicz@intel.com") 54 | 55 | if("${CPACK_GENERATOR}" STREQUAL "RPM") 56 | set(CPACK_PACKAGE_FILE_NAME 57 | ${CPACK_RPM_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}.${CPACK_RPM_PACKAGE_ARCHITECTURE}) 58 | elseif("${CPACK_GENERATOR}" STREQUAL "DEB") 59 | set(CPACK_PACKAGE_FILE_NAME 60 | ${CPACK_DEBIAN_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}) 61 | endif() 62 | 63 | set(targetDestDir ${CMAKE_INSTALL_TMPDIR}) 64 | include(CPack) 65 | -------------------------------------------------------------------------------- /tests/comparator/default_reopen.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2020, Intel Corporation */ 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include "unittest.h" 9 | 10 | static const char *EXPECTED_ERR_MSG = 11 | "[pmemkv_open] Comparator with name: \"__pmemkv_binary_comparator\" expected"; 12 | 13 | int compare(const char *k1, size_t kb1, const char *k2, size_t kb2, void *arg) 14 | { 15 | return 0; 16 | } 17 | 18 | static pmemkv_comparator *create_cmp(const char *name) 19 | { 20 | pmemkv_comparator *cmp = pmemkv_comparator_new(compare, name, NULL); 21 | UT_ASSERTne(cmp, NULL); 22 | 23 | return cmp; 24 | } 25 | 26 | static void insert(const char *engine, pmemkv_config *cfg) 27 | { 28 | pmemkv_db *db; 29 | int s = pmemkv_open(engine, cfg, &db); 30 | UT_ASSERTeq(s, PMEMKV_STATUS_OK); 31 | 32 | s = pmemkv_put(db, "A", 1, "A", 1); 33 | UT_ASSERTeq(s, PMEMKV_STATUS_OK); 34 | s = pmemkv_put(db, "B", 1, "B", 1); 35 | UT_ASSERTeq(s, PMEMKV_STATUS_OK); 36 | s = pmemkv_put(db, "C", 1, "C", 1); 37 | UT_ASSERTeq(s, PMEMKV_STATUS_OK); 38 | s = pmemkv_put(db, "D", 1, "D", 1); 39 | UT_ASSERTeq(s, PMEMKV_STATUS_OK); 40 | 41 | pmemkv_close(db); 42 | } 43 | 44 | static void check_valid(const char *engine, pmemkv_config *cfg) 45 | { 46 | pmemkv_db *db; 47 | int s = pmemkv_open(engine, cfg, &db); 48 | UT_ASSERTeq(s, PMEMKV_STATUS_OK); 49 | 50 | size_t cnt = UINT64_MAX; 51 | s = pmemkv_count_above(db, "B", 1, &cnt); 52 | UT_ASSERTeq(s, PMEMKV_STATUS_OK); 53 | UT_ASSERTeq(cnt, 2); 54 | 55 | cnt = UINT64_MAX; 56 | s = pmemkv_count_below(db, "B", 1, &cnt); 57 | UT_ASSERTeq(s, PMEMKV_STATUS_OK); 58 | UT_ASSERTeq(cnt, 1); 59 | 60 | pmemkv_close(db); 61 | } 62 | 63 | static void check_invalid(const char *engine, pmemkv_config *cfg) 64 | { 65 | pmemkv_comparator *cmp = create_cmp("invalid_cmp"); 66 | 67 | int s = pmemkv_config_put_object(cfg, "comparator", (void *)cmp, 68 | (void(*))pmemkv_comparator_delete); 69 | UT_ASSERTeq(s, PMEMKV_STATUS_OK); 70 | 71 | pmemkv_db *db; 72 | s = pmemkv_open(engine, cfg, &db); 73 | UT_ASSERTeq(s, PMEMKV_STATUS_COMPARATOR_MISMATCH); 74 | 75 | const char *err = pmemkv_errormsg(); 76 | UT_ASSERT(strcmp(err, EXPECTED_ERR_MSG) == 0); 77 | } 78 | 79 | int main(int argc, char *argv[]) 80 | { 81 | if (argc < 4) 82 | UT_FATAL("usage: %s engine json_config insert/check", argv[0]); 83 | 84 | const char *engine = argv[1]; 85 | const char *json_config = argv[2]; 86 | const char *mode = argv[3]; 87 | if (strcmp(mode, "insert") != 0 && strcmp(mode, "check") != 0) 88 | UT_FATAL("usage: %s engine json_config insert/check", argv[0]); 89 | 90 | if (strcmp(mode, "insert") == 0) { 91 | insert(engine, C_CONFIG_FROM_JSON(json_config)); 92 | } else { 93 | check_valid(engine, C_CONFIG_FROM_JSON(json_config)); 94 | check_invalid(engine, C_CONFIG_FROM_JSON(json_config)); 95 | } 96 | 97 | return 0; 98 | } 99 | -------------------------------------------------------------------------------- /utils/docker/images/Dockerfile.ubuntu-20.04_bindings: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2016-2021, Intel Corporation 3 | 4 | # 5 | # Dockerfile - a 'recipe' for Docker to build an image of ubuntu-based 6 | # environment prepared for executing build and tests 7 | # of pmemkv-* bindings repositories. 8 | # Rapidjson is installed from sources because of package bug. 9 | # 10 | 11 | # Pull base image 12 | FROM registry.hub.docker.com/library/ubuntu:20.04 13 | MAINTAINER igor.chorazewicz@intel.com 14 | 15 | # Set required environment variables 16 | ENV OS ubuntu 17 | ENV OS_VER 20.04_bindings 18 | ENV PACKAGE_MANAGER deb 19 | ENV NOTTY 1 20 | ENV JAVA_HOME /usr/lib/jvm/java-8-openjdk-amd64 21 | 22 | # Additional parameters to build docker without building components 23 | ARG SKIP_VALGRIND_BUILD 24 | ARG SKIP_PMDK_BUILD 25 | ARG SKIP_LIBPMEMOBJCPP_BUILD 26 | 27 | # Base development packages 28 | ARG BASE_DEPS="\ 29 | cmake \ 30 | build-essential \ 31 | git" 32 | 33 | # Dependencies for compiling pmemkv project 34 | ARG PMEMKV_DEPS="\ 35 | libmemkind-dev \ 36 | libtbb-dev" 37 | 38 | # Dependencies for compiling and testing pmemkv bindings 39 | ARG PMEMKV_BINDINGS_DEPS="\ 40 | maven \ 41 | npm \ 42 | openjdk-8-jdk \ 43 | python3-dev \ 44 | python3-pip \ 45 | ruby-dev" 46 | 47 | # PMDK's dependencies (optional; libpmemobj-dev package may be used instead) 48 | ARG PMDK_DEPS="\ 49 | autoconf \ 50 | automake \ 51 | debhelper \ 52 | devscripts \ 53 | gdb \ 54 | libdaxctl-dev \ 55 | libndctl-dev \ 56 | pandoc \ 57 | python3" 58 | 59 | # Dependencies for compiling libpmemobj-cpp project 60 | ARG LIBPMEMOBJ_CPP_DEPS="\ 61 | libatomic1 \ 62 | libtbb-dev" 63 | 64 | # Misc for our builds/CI (optional) 65 | ARG MISC_DEPS="\ 66 | pkg-config \ 67 | sudo \ 68 | whois" 69 | 70 | ENV DEBIAN_FRONTEND noninteractive 71 | 72 | # Update the apt cache and install basic tools 73 | RUN apt-get update \ 74 | && apt-get install -y --no-install-recommends \ 75 | ${BASE_DEPS} \ 76 | ${PMEMKV_DEPS} \ 77 | ${PMEMKV_BINDINGS_DEPS} \ 78 | ${PMDK_DEPS} \ 79 | ${LIBPMEMOBJ_CPP_DEPS} \ 80 | ${MISC_DEPS} \ 81 | && rm -rf /var/lib/apt/lists/* 82 | 83 | # Install rapidjson from sources 84 | COPY install-rapidjson.sh install-rapidjson.sh 85 | RUN ./install-rapidjson.sh 86 | 87 | # Install pmdk 88 | COPY install-pmdk.sh install-pmdk.sh 89 | RUN ./install-pmdk.sh dpkg 90 | 91 | # Install pmdk c++ bindings 92 | COPY install-libpmemobj-cpp.sh install-libpmemobj-cpp.sh 93 | RUN ./install-libpmemobj-cpp.sh DEB 94 | 95 | # Install bindings' dependencies 96 | RUN pip3 install pytest setuptools wheel 97 | COPY install-bindings-dependencies.sh install-bindings-dependencies.sh 98 | RUN ./install-bindings-dependencies.sh 99 | 100 | # Add user 101 | ENV USER user 102 | ENV USERPASS pass 103 | RUN useradd -m $USER -g sudo -p `mkpasswd $USERPASS` 104 | USER $USER 105 | -------------------------------------------------------------------------------- /utils/docker/images/Dockerfile.ubuntu-devel: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2016-2021, Intel Corporation 3 | 4 | # 5 | # Dockerfile - a 'recipe' for Docker to build an image of ubuntu-based 6 | # environment prepared for running pmemkv build and tests. 7 | # 8 | 9 | # Pull base image 10 | FROM registry.hub.docker.com/library/ubuntu:devel 11 | MAINTAINER igor.chorazewicz@intel.com 12 | 13 | # Set required environment variables 14 | ENV OS ubuntu 15 | ENV OS_VER devel 16 | ENV PACKAGE_MANAGER deb 17 | ENV NOTTY 1 18 | 19 | # Additional parameters to build docker without building components 20 | ARG SKIP_VALGRIND_BUILD 21 | ARG SKIP_PMDK_BUILD 22 | ARG SKIP_LIBPMEMOBJCPP_BUILD 23 | 24 | # Base development packages 25 | ARG BASE_DEPS="\ 26 | cmake \ 27 | build-essential \ 28 | git" 29 | 30 | # Dependencies for compiling pmemkv project 31 | ARG PMEMKV_DEPS="\ 32 | libmemkind-dev \ 33 | libtbb-dev \ 34 | rapidjson-dev" 35 | 36 | # PMDK's dependencies (optional; libpmemobj-dev package may be used instead) 37 | ARG PMDK_DEPS="\ 38 | autoconf \ 39 | automake \ 40 | debhelper \ 41 | devscripts \ 42 | gdb \ 43 | libdaxctl-dev \ 44 | libndctl-dev \ 45 | pandoc \ 46 | python3" 47 | 48 | # libpmemobj-cpp's dependencies (optional; libpmemobj-cpp-dev package may be used instead) 49 | ARG LIBPMEMOBJ_CPP_DEPS="\ 50 | libatomic1 \ 51 | libtbb-dev" 52 | 53 | # pmem's Valgrind dependencies (optional; valgrind package may be used instead) 54 | ARG VALGRIND_DEPS="\ 55 | autoconf \ 56 | automake" 57 | 58 | # Examples (optional) 59 | ARG EXAMPLES_DEPS="\ 60 | libncurses5-dev \ 61 | libsfml-dev" 62 | 63 | # Documentation (optional) 64 | ARG DOC_DEPS="\ 65 | doxygen \ 66 | graphviz" 67 | 68 | # Tests (optional) 69 | ARG TESTS_DEPS="\ 70 | gdb \ 71 | libc6-dbg \ 72 | libunwind-dev" 73 | 74 | # Misc for our builds/CI (optional) 75 | ARG MISC_DEPS="\ 76 | clang \ 77 | libtext-diff-perl \ 78 | pkg-config \ 79 | sudo \ 80 | whois" 81 | 82 | ENV DEBIAN_FRONTEND noninteractive 83 | 84 | # Update the apt cache and install basic tools 85 | RUN apt-get update \ 86 | && apt-get install -y --no-install-recommends \ 87 | ${BASE_DEPS} \ 88 | ${PMEMKV_DEPS} \ 89 | ${PMDK_DEPS} \ 90 | ${LIBPMEMOBJ_CPP_DEPS} \ 91 | ${VALGRIND_DEPS} \ 92 | ${EXAMPLES_DEPS} \ 93 | ${DOC_DEPS} \ 94 | ${TESTS_DEPS} \ 95 | ${MISC_DEPS} \ 96 | && rm -rf /var/lib/apt/lists/* 97 | 98 | # Install valgrind 99 | COPY install-valgrind.sh install-valgrind.sh 100 | RUN ./install-valgrind.sh 101 | 102 | # Install pmdk 103 | COPY install-pmdk.sh install-pmdk.sh 104 | RUN ./install-pmdk.sh dpkg 105 | 106 | # Install pmdk c++ bindings 107 | COPY install-libpmemobj-cpp.sh install-libpmemobj-cpp.sh 108 | RUN ./install-libpmemobj-cpp.sh DEB 109 | 110 | # Add user 111 | ENV USER user 112 | ENV USERPASS pass 113 | RUN useradd -m $USER -g sudo -p `mkpasswd $USERPASS` 114 | USER $USER 115 | -------------------------------------------------------------------------------- /utils/docker/images/Dockerfile.debian-latest: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2016-2021, Intel Corporation 3 | 4 | # 5 | # Dockerfile - a 'recipe' for Docker to build an image of debian-based 6 | # environment prepared for running pmemkv build and tests. 7 | # 8 | 9 | # Pull base image 10 | FROM registry.hub.docker.com/library/debian:latest 11 | MAINTAINER igor.chorazewicz@intel.com 12 | 13 | # Set required environment variables 14 | ENV OS debian 15 | ENV OS_VER latest 16 | ENV PACKAGE_MANAGER deb 17 | ENV NOTTY 1 18 | 19 | # Additional parameters to build docker without building components 20 | ARG SKIP_VALGRIND_BUILD 21 | ARG SKIP_PMDK_BUILD 22 | ARG SKIP_LIBPMEMOBJCPP_BUILD 23 | 24 | # Base development packages 25 | ARG BASE_DEPS="\ 26 | cmake \ 27 | build-essential \ 28 | git" 29 | 30 | # Dependencies for compiling pmemkv project 31 | ARG PMEMKV_DEPS="\ 32 | libmemkind-dev \ 33 | libtbb-dev \ 34 | rapidjson-dev" 35 | 36 | # PMDK's dependencies (optional; libpmemobj-dev package may be used instead) 37 | ARG PMDK_DEPS="\ 38 | autoconf \ 39 | automake \ 40 | debhelper \ 41 | devscripts \ 42 | gdb \ 43 | libdaxctl-dev \ 44 | libndctl-dev \ 45 | pandoc \ 46 | python3" 47 | 48 | # libpmemobj-cpp's dependencies (optional; libpmemobj-cpp-dev package may be used instead) 49 | ARG LIBPMEMOBJ_CPP_DEPS="\ 50 | libatomic1 \ 51 | libtbb-dev" 52 | 53 | # pmem's Valgrind dependencies (optional; valgrind package may be used instead) 54 | ARG VALGRIND_DEPS="\ 55 | autoconf \ 56 | automake" 57 | 58 | # Examples (optional) 59 | ARG EXAMPLES_DEPS="\ 60 | libncurses5-dev \ 61 | libsfml-dev" 62 | 63 | # Documentation (optional) 64 | ARG DOC_DEPS="\ 65 | doxygen \ 66 | graphviz" 67 | 68 | # Tests (optional) 69 | ARG TESTS_DEPS="\ 70 | gdb \ 71 | libc6-dbg \ 72 | libunwind-dev" 73 | 74 | # Misc for our builds/CI (optional) 75 | ARG MISC_DEPS="\ 76 | clang \ 77 | libtext-diff-perl \ 78 | pkg-config \ 79 | sudo \ 80 | whois" 81 | 82 | ENV DEBIAN_FRONTEND noninteractive 83 | 84 | # Update the apt cache and install basic tools 85 | RUN apt-get update \ 86 | && apt-get install -y --no-install-recommends \ 87 | ${BASE_DEPS} \ 88 | ${PMEMKV_DEPS} \ 89 | ${PMDK_DEPS} \ 90 | ${LIBPMEMOBJ_CPP_DEPS} \ 91 | ${VALGRIND_DEPS} \ 92 | ${EXAMPLES_DEPS} \ 93 | ${DOC_DEPS} \ 94 | ${TESTS_DEPS} \ 95 | ${MISC_DEPS} \ 96 | && rm -rf /var/lib/apt/lists/* 97 | 98 | # Install valgrind 99 | COPY install-valgrind.sh install-valgrind.sh 100 | RUN ./install-valgrind.sh 101 | 102 | # Install pmdk 103 | COPY install-pmdk.sh install-pmdk.sh 104 | RUN ./install-pmdk.sh dpkg 105 | 106 | # Install pmdk c++ bindings 107 | COPY install-libpmemobj-cpp.sh install-libpmemobj-cpp.sh 108 | RUN ./install-libpmemobj-cpp.sh DEB 109 | 110 | # Add user 111 | ENV USER user 112 | ENV USERPASS pass 113 | RUN useradd -m $USER -g sudo -p `mkpasswd $USERPASS` 114 | USER $USER 115 | -------------------------------------------------------------------------------- /utils/docker/images/Dockerfile.debian-testing: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2016-2021, Intel Corporation 3 | 4 | # 5 | # Dockerfile - a 'recipe' for Docker to build an image of debian-based 6 | # environment prepared for running pmemkv build and tests. 7 | # 8 | 9 | # Pull base image 10 | FROM registry.hub.docker.com/library/debian:testing 11 | MAINTAINER igor.chorazewicz@intel.com 12 | 13 | # Set required environment variables 14 | ENV OS debian 15 | ENV OS_VER testing 16 | ENV PACKAGE_MANAGER deb 17 | ENV NOTTY 1 18 | 19 | # Additional parameters to build docker without building components 20 | ARG SKIP_VALGRIND_BUILD 21 | ARG SKIP_PMDK_BUILD 22 | ARG SKIP_LIBPMEMOBJCPP_BUILD 23 | 24 | # Base development packages 25 | ARG BASE_DEPS="\ 26 | cmake \ 27 | build-essential \ 28 | git" 29 | 30 | # Dependencies for compiling pmemkv project 31 | ARG PMEMKV_DEPS="\ 32 | libmemkind-dev \ 33 | libtbb-dev \ 34 | rapidjson-dev" 35 | 36 | # PMDK's dependencies (optional; libpmemobj-dev package may be used instead) 37 | ARG PMDK_DEPS="\ 38 | autoconf \ 39 | automake \ 40 | debhelper \ 41 | devscripts \ 42 | gdb \ 43 | libdaxctl-dev \ 44 | libndctl-dev \ 45 | pandoc \ 46 | python3" 47 | 48 | # libpmemobj-cpp's dependencies (optional; libpmemobj-cpp-dev package may be used instead) 49 | ARG LIBPMEMOBJ_CPP_DEPS="\ 50 | libatomic1 \ 51 | libtbb-dev" 52 | 53 | # pmem's Valgrind dependencies (optional; valgrind package may be used instead) 54 | ARG VALGRIND_DEPS="\ 55 | autoconf \ 56 | automake" 57 | 58 | # Examples (optional) 59 | ARG EXAMPLES_DEPS="\ 60 | libncurses5-dev \ 61 | libsfml-dev" 62 | 63 | # Documentation (optional) 64 | ARG DOC_DEPS="\ 65 | doxygen \ 66 | graphviz" 67 | 68 | # Tests (optional) 69 | ARG TESTS_DEPS="\ 70 | gdb \ 71 | libc6-dbg \ 72 | libunwind-dev" 73 | 74 | # Misc for our builds/CI (optional) 75 | ARG MISC_DEPS="\ 76 | clang \ 77 | libtext-diff-perl \ 78 | pkg-config \ 79 | sudo \ 80 | whois" 81 | 82 | ENV DEBIAN_FRONTEND noninteractive 83 | 84 | # Update the apt cache and install basic tools 85 | RUN apt-get update \ 86 | && apt-get install -y --no-install-recommends \ 87 | ${BASE_DEPS} \ 88 | ${PMEMKV_DEPS} \ 89 | ${PMDK_DEPS} \ 90 | ${LIBPMEMOBJ_CPP_DEPS} \ 91 | ${VALGRIND_DEPS} \ 92 | ${EXAMPLES_DEPS} \ 93 | ${DOC_DEPS} \ 94 | ${TESTS_DEPS} \ 95 | ${MISC_DEPS} \ 96 | && rm -rf /var/lib/apt/lists/* 97 | 98 | # Install valgrind 99 | COPY install-valgrind.sh install-valgrind.sh 100 | RUN ./install-valgrind.sh 101 | 102 | # Install pmdk 103 | COPY install-pmdk.sh install-pmdk.sh 104 | RUN ./install-pmdk.sh dpkg 105 | 106 | # Install pmdk c++ bindings 107 | COPY install-libpmemobj-cpp.sh install-libpmemobj-cpp.sh 108 | RUN ./install-libpmemobj-cpp.sh DEB 109 | 110 | # Add user 111 | ENV USER user 112 | ENV USERPASS pass 113 | RUN useradd -m $USER -g sudo -p `mkpasswd $USERPASS` 114 | USER $USER 115 | -------------------------------------------------------------------------------- /utils/docker/images/Dockerfile.debian-unstable: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2016-2021, Intel Corporation 3 | 4 | # 5 | # Dockerfile - a 'recipe' for Docker to build an image of debian-based 6 | # environment prepared for running pmemkv build and tests. 7 | # 8 | 9 | # Pull base image 10 | FROM registry.hub.docker.com/library/debian:unstable 11 | MAINTAINER igor.chorazewicz@intel.com 12 | 13 | # Set required environment variables 14 | ENV OS debian 15 | ENV OS_VER unstable 16 | ENV PACKAGE_MANAGER deb 17 | ENV NOTTY 1 18 | 19 | # Additional parameters to build docker without building components 20 | ARG SKIP_VALGRIND_BUILD 21 | ARG SKIP_PMDK_BUILD 22 | ARG SKIP_LIBPMEMOBJCPP_BUILD 23 | 24 | # Base development packages 25 | ARG BASE_DEPS="\ 26 | cmake \ 27 | build-essential \ 28 | git" 29 | 30 | # Dependencies for compiling pmemkv project 31 | ARG PMEMKV_DEPS="\ 32 | libmemkind-dev \ 33 | libtbb-dev \ 34 | rapidjson-dev" 35 | 36 | # PMDK's dependencies (optional; libpmemobj-dev package may be used instead) 37 | ARG PMDK_DEPS="\ 38 | autoconf \ 39 | automake \ 40 | debhelper \ 41 | devscripts \ 42 | gdb \ 43 | libdaxctl-dev \ 44 | libndctl-dev \ 45 | pandoc \ 46 | python3" 47 | 48 | # libpmemobj-cpp's dependencies (optional; libpmemobj-cpp-dev package may be used instead) 49 | ARG LIBPMEMOBJ_CPP_DEPS="\ 50 | libatomic1 \ 51 | libtbb-dev" 52 | 53 | # pmem's Valgrind dependencies (optional; valgrind package may be used instead) 54 | ARG VALGRIND_DEPS="\ 55 | autoconf \ 56 | automake" 57 | 58 | # Examples (optional) 59 | ARG EXAMPLES_DEPS="\ 60 | libncurses5-dev \ 61 | libsfml-dev" 62 | 63 | # Documentation (optional) 64 | ARG DOC_DEPS="\ 65 | doxygen \ 66 | graphviz" 67 | 68 | # Tests (optional) 69 | ARG TESTS_DEPS="\ 70 | gdb \ 71 | libc6-dbg \ 72 | libunwind-dev" 73 | 74 | # Misc for our builds/CI (optional) 75 | ARG MISC_DEPS="\ 76 | clang \ 77 | libtext-diff-perl \ 78 | pkg-config \ 79 | sudo \ 80 | whois" 81 | 82 | ENV DEBIAN_FRONTEND noninteractive 83 | 84 | # Update the apt cache and install basic tools 85 | RUN apt-get update \ 86 | && apt-get install -y --no-install-recommends \ 87 | ${BASE_DEPS} \ 88 | ${PMEMKV_DEPS} \ 89 | ${PMDK_DEPS} \ 90 | ${LIBPMEMOBJ_CPP_DEPS} \ 91 | ${VALGRIND_DEPS} \ 92 | ${EXAMPLES_DEPS} \ 93 | ${DOC_DEPS} \ 94 | ${TESTS_DEPS} \ 95 | ${MISC_DEPS} \ 96 | && rm -rf /var/lib/apt/lists/* 97 | 98 | # Install valgrind 99 | COPY install-valgrind.sh install-valgrind.sh 100 | RUN ./install-valgrind.sh 101 | 102 | # Install pmdk 103 | COPY install-pmdk.sh install-pmdk.sh 104 | RUN ./install-pmdk.sh dpkg 105 | 106 | # Install pmdk c++ bindings 107 | COPY install-libpmemobj-cpp.sh install-libpmemobj-cpp.sh 108 | RUN ./install-libpmemobj-cpp.sh DEB 109 | 110 | # Add user 111 | ENV USER user 112 | ENV USERPASS pass 113 | RUN useradd -m $USER -g sudo -p `mkpasswd $USERPASS` 114 | USER $USER 115 | -------------------------------------------------------------------------------- /tests/engine_scenarios/concurrent/put_get_remove_single_op_params.cc: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2020, Intel Corporation */ 3 | 4 | #include "unittest.hpp" 5 | 6 | #include 7 | 8 | using namespace pmem::kv; 9 | 10 | static void MultithreadedGetAndRemove(const size_t threads_number, pmem::kv::db &kv) 11 | { 12 | std::vector keys(threads_number, 0); 13 | std::iota(keys.begin(), keys.end(), 0); 14 | 15 | for (auto &k : keys) 16 | UT_ASSERT(kv.put(uint64_to_strv(k), uint64_to_strv(k)) == status::OK); 17 | 18 | /* test reading and removing data */ 19 | parallel_exec(threads_number, [&](size_t thread_id) { 20 | if (thread_id % 2 == 1) { 21 | auto s = kv.get(uint64_to_strv(keys[thread_id]), 22 | [&](string_view value) { 23 | UT_ASSERTeq(value.compare(uint64_to_strv( 24 | keys[thread_id])), 25 | 0); 26 | }); 27 | UT_ASSERTeq(s, status::OK); 28 | 29 | s = kv.get(uint64_to_strv(keys[thread_id - 1]), 30 | [&](string_view value) { 31 | UT_ASSERTeq(value.compare(uint64_to_strv( 32 | keys[thread_id - 1])), 33 | 0); 34 | }); 35 | UT_ASSERT(s == status::OK || s == status::NOT_FOUND); 36 | 37 | if (thread_id == threads_number - 1) 38 | return; 39 | 40 | s = kv.get(uint64_to_strv(keys[thread_id + 1]), 41 | [&](string_view value) { 42 | UT_ASSERTeq(value.compare(uint64_to_strv( 43 | keys[thread_id + 1])), 44 | 0); 45 | }); 46 | UT_ASSERT(s == status::OK || s == status::NOT_FOUND); 47 | } else { 48 | UT_ASSERTeq(kv.remove(uint64_to_strv(keys[thread_id])), 49 | status::OK); 50 | } 51 | }); 52 | } 53 | 54 | static void MultithreadedPutAndRemove(const size_t threads_number, pmem::kv::db &kv) 55 | { 56 | std::vector keys(threads_number, 0); 57 | std::iota(keys.begin(), keys.end(), 0); 58 | 59 | for (size_t i = 0; i < threads_number; i += 2) 60 | UT_ASSERTeq(kv.put(uint64_to_strv(keys[i]), uint64_to_strv(keys[i])), 61 | status::OK); 62 | 63 | /* test adding and removing data */ 64 | parallel_exec(threads_number, [&](size_t thread_id) { 65 | if (thread_id % 2 == 0) { 66 | UT_ASSERTeq(kv.remove(uint64_to_strv(keys[thread_id])), 67 | status::OK); 68 | } else { 69 | UT_ASSERTeq(kv.put(uint64_to_strv(keys[thread_id]), 70 | uint64_to_strv(keys[thread_id])), 71 | status::OK); 72 | } 73 | }); 74 | } 75 | 76 | static void test(int argc, char *argv[]) 77 | { 78 | using namespace std::placeholders; 79 | 80 | if (argc < 4) 81 | UT_FATAL("usage: %s engine json_config threads", argv[0]); 82 | 83 | size_t threads_number = std::stoull(argv[3]); 84 | run_engine_tests(argv[1], argv[2], 85 | { 86 | std::bind(MultithreadedGetAndRemove, threads_number, _1), 87 | std::bind(MultithreadedPutAndRemove, threads_number, _1), 88 | }); 89 | } 90 | 91 | int main(int argc, char *argv[]) 92 | { 93 | return run_test([&] { test(argc, argv); }); 94 | } 95 | -------------------------------------------------------------------------------- /utils/docker/images/Dockerfile.ubuntu-21.04: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2016-2021, Intel Corporation 3 | 4 | # 5 | # Dockerfile - a 'recipe' for Docker to build an image of ubuntu-based 6 | # environment prepared for running pmemkv build and tests. 7 | # 8 | 9 | # Pull base image 10 | FROM registry.hub.docker.com/library/ubuntu:21.04 11 | MAINTAINER igor.chorazewicz@intel.com 12 | 13 | # Set required environment variables 14 | ENV OS ubuntu 15 | ENV OS_VER 21.04 16 | ENV PACKAGE_MANAGER deb 17 | ENV NOTTY 1 18 | 19 | # Additional parameters to build docker without building components 20 | ARG SKIP_VALGRIND_BUILD 21 | ARG SKIP_PMDK_BUILD 22 | ARG SKIP_LIBPMEMOBJCPP_BUILD 23 | ARG SKIP_SCRIPTS_DOWNLOAD 24 | 25 | # Base development packages 26 | ARG BASE_DEPS="\ 27 | cmake \ 28 | build-essential \ 29 | git" 30 | 31 | # Dependencies for compiling pmemkv project 32 | ARG PMEMKV_DEPS="\ 33 | libmemkind-dev \ 34 | libtbb-dev \ 35 | rapidjson-dev" 36 | 37 | # PMDK's dependencies (optional; libpmemobj-dev package may be used instead) 38 | ARG PMDK_DEPS="\ 39 | autoconf \ 40 | automake \ 41 | debhelper \ 42 | devscripts \ 43 | gdb \ 44 | libdaxctl-dev \ 45 | libndctl-dev \ 46 | pandoc \ 47 | python3" 48 | 49 | # libpmemobj-cpp's dependencies (optional; libpmemobj-cpp-dev package may be used instead) 50 | ARG LIBPMEMOBJ_CPP_DEPS="\ 51 | libatomic1 \ 52 | libtbb-dev" 53 | 54 | # pmem's Valgrind dependencies (optional; valgrind package may be used instead) 55 | ARG VALGRIND_DEPS="\ 56 | autoconf \ 57 | automake" 58 | 59 | # Examples (optional) 60 | ARG EXAMPLES_DEPS="\ 61 | libncurses5-dev \ 62 | libsfml-dev" 63 | 64 | # Documentation (optional) 65 | ARG DOC_DEPS="\ 66 | doxygen \ 67 | graphviz" 68 | 69 | # Tests (optional) 70 | ARG TESTS_DEPS="\ 71 | gdb \ 72 | libc6-dbg \ 73 | libunwind-dev" 74 | 75 | # Misc for our builds/CI (optional) 76 | ARG MISC_DEPS="\ 77 | clang \ 78 | libtext-diff-perl \ 79 | pkg-config \ 80 | sudo \ 81 | whois" 82 | 83 | ENV DEBIAN_FRONTEND noninteractive 84 | 85 | # Update the apt cache and install basic tools 86 | RUN apt-get update \ 87 | && apt-get install -y --no-install-recommends \ 88 | ${BASE_DEPS} \ 89 | ${PMEMKV_DEPS} \ 90 | ${PMDK_DEPS} \ 91 | ${LIBPMEMOBJ_CPP_DEPS} \ 92 | ${VALGRIND_DEPS} \ 93 | ${EXAMPLES_DEPS} \ 94 | ${DOC_DEPS} \ 95 | ${TESTS_DEPS} \ 96 | ${MISC_DEPS} \ 97 | && rm -rf /var/lib/apt/lists/* 98 | 99 | # Install valgrind 100 | COPY install-valgrind.sh install-valgrind.sh 101 | RUN ./install-valgrind.sh 102 | 103 | # Install pmdk 104 | COPY install-pmdk.sh install-pmdk.sh 105 | RUN ./install-pmdk.sh dpkg 106 | 107 | # Install pmdk c++ bindings 108 | COPY install-libpmemobj-cpp.sh install-libpmemobj-cpp.sh 109 | RUN ./install-libpmemobj-cpp.sh DEB 110 | 111 | # Add user 112 | ENV USER user 113 | ENV USERPASS pass 114 | RUN useradd -m $USER -g sudo -p `mkpasswd $USERPASS` 115 | USER $USER 116 | -------------------------------------------------------------------------------- /utils/docker/images/Dockerfile.fedora-33: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2016-2021, Intel Corporation 3 | 4 | # 5 | # Dockerfile - a 'recipe' for Docker to build an image of Fedora-based 6 | # environment prepared for running pmemkv build and tests. 7 | # 8 | 9 | # Pull base image 10 | FROM registry.fedoraproject.org/fedora:33 11 | MAINTAINER igor.chorazewicz@intel.com 12 | 13 | # Set required environment variables 14 | ENV OS fedora 15 | ENV OS_VER 33 16 | ENV PACKAGE_MANAGER rpm 17 | ENV NOTTY 1 18 | 19 | # Additional parameters to build docker without building components 20 | ARG SKIP_VALGRIND_BUILD 21 | ARG SKIP_PMDK_BUILD 22 | ARG SKIP_LIBPMEMOBJCPP_BUILD 23 | 24 | # Base development packages 25 | ARG BASE_DEPS="\ 26 | cmake \ 27 | gcc \ 28 | gcc-c++ \ 29 | git \ 30 | make" 31 | 32 | # Dependencies for compiling pmemkv project 33 | ARG PMEMKV_DEPS="\ 34 | memkind-devel \ 35 | rapidjson-devel \ 36 | tbb-devel" 37 | 38 | # PMDK's dependencies (optional; libpmemobj-devel package may be used instead) 39 | ARG PMDK_DEPS="\ 40 | autoconf \ 41 | automake \ 42 | daxctl-devel \ 43 | gdb \ 44 | man \ 45 | ndctl-devel \ 46 | pandoc \ 47 | python3 \ 48 | rpm-build \ 49 | rpm-build-libs \ 50 | rpmdevtools \ 51 | which" 52 | 53 | # libpmemobj-cpp's dependencies (optional; libpmemobj++-devel package may be used instead) 54 | ARG LIBPMEMOBJ_CPP_DEPS="\ 55 | libatomic \ 56 | tbb-devel" 57 | 58 | # pmem's Valgrind dependencies (optional; valgrind-devel package may be used instead) 59 | ARG VALGRIND_DEPS="\ 60 | autoconf \ 61 | automake" 62 | 63 | # Examples (optional) 64 | ARG EXAMPLES_DEPS="\ 65 | ncurses-devel \ 66 | SFML-devel" 67 | 68 | # Documentation (optional) 69 | ARG DOC_DEPS="\ 70 | doxygen \ 71 | graphviz" 72 | 73 | # Tests (optional) 74 | # NOTE: glibc is installed as a separate command; see below 75 | ARG TESTS_DEPS="\ 76 | gdb \ 77 | libunwind-devel" 78 | 79 | # Misc for our builds/CI (optional) 80 | ARG MISC_DEPS="\ 81 | clang \ 82 | perl-Text-Diff \ 83 | pkgconf \ 84 | sudo" 85 | 86 | # Install basic tools 87 | RUN dnf update -y \ 88 | && dnf install -y \ 89 | ${BASE_DEPS} \ 90 | ${PMEMKV_DEPS} \ 91 | ${PMDK_DEPS} \ 92 | ${LIBPMEMOBJ_CPP_DEPS} \ 93 | ${VALGRIND_DEPS} \ 94 | ${EXAMPLES_DEPS} \ 95 | ${DOC_DEPS} \ 96 | ${TESTS_DEPS} \ 97 | ${MISC_DEPS} \ 98 | && dnf debuginfo-install -y glibc \ 99 | && dnf clean all 100 | 101 | # Install valgrind 102 | COPY install-valgrind.sh install-valgrind.sh 103 | RUN ./install-valgrind.sh 104 | 105 | # Install pmdk 106 | COPY install-pmdk.sh install-pmdk.sh 107 | RUN ./install-pmdk.sh rpm 108 | 109 | # Install pmdk c++ bindings 110 | COPY install-libpmemobj-cpp.sh install-libpmemobj-cpp.sh 111 | RUN ./install-libpmemobj-cpp.sh RPM 112 | 113 | # Add user 114 | ENV USER user 115 | ENV USERPASS pass 116 | RUN useradd -m $USER \ 117 | && echo "$USER:$USERPASS" | chpasswd \ 118 | && gpasswd wheel -a $USER 119 | USER $USER 120 | -------------------------------------------------------------------------------- /utils/docker/images/Dockerfile.fedora-34: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright 2016-2022, Intel Corporation 3 | 4 | # 5 | # Dockerfile - a 'recipe' for Docker to build an image of Fedora-based 6 | # environment prepared for running pmemkv build and tests. 7 | # 8 | 9 | # Pull base image 10 | FROM registry.fedoraproject.org/fedora:34 11 | MAINTAINER igor.chorazewicz@intel.com 12 | 13 | # Set required environment variables 14 | ENV OS fedora 15 | ENV OS_VER 34 16 | ENV PACKAGE_MANAGER rpm 17 | ENV NOTTY 1 18 | 19 | # Additional parameters to build docker without building components 20 | ARG SKIP_VALGRIND_BUILD 21 | ARG SKIP_PMDK_BUILD 22 | ARG SKIP_LIBPMEMOBJCPP_BUILD 23 | 24 | # Base development packages 25 | ARG BASE_DEPS="\ 26 | cmake \ 27 | gcc \ 28 | gcc-c++ \ 29 | git \ 30 | make" 31 | 32 | # Dependencies for compiling pmemkv project 33 | ARG PMEMKV_DEPS="\ 34 | memkind-devel \ 35 | rapidjson-devel \ 36 | tbb-devel" 37 | 38 | # PMDK's dependencies (optional; libpmemobj-devel package may be used instead) 39 | ARG PMDK_DEPS="\ 40 | autoconf \ 41 | automake \ 42 | daxctl-devel \ 43 | gdb \ 44 | man \ 45 | ndctl-devel \ 46 | pandoc \ 47 | python3 \ 48 | rpm-build \ 49 | rpm-build-libs \ 50 | rpmdevtools \ 51 | which" 52 | 53 | # libpmemobj-cpp's dependencies (optional; libpmemobj++-devel package may be used instead) 54 | ARG LIBPMEMOBJ_CPP_DEPS="\ 55 | libatomic \ 56 | tbb-devel" 57 | 58 | # pmem's Valgrind dependencies (optional; valgrind-devel package may be used instead) 59 | ARG VALGRIND_DEPS="\ 60 | autoconf \ 61 | automake" 62 | 63 | # Examples (optional) 64 | ARG EXAMPLES_DEPS="\ 65 | ncurses-devel \ 66 | SFML-devel" 67 | 68 | # Documentation (optional) 69 | ARG DOC_DEPS="\ 70 | doxygen \ 71 | graphviz" 72 | 73 | # Tests (optional) 74 | # NOTE: glibc is installed as a separate command; see below 75 | ARG TESTS_DEPS="\ 76 | gdb \ 77 | libunwind-devel" 78 | 79 | # Misc for our builds/CI (optional) 80 | ARG MISC_DEPS="\ 81 | clang \ 82 | perl-Text-Diff \ 83 | pkgconf \ 84 | sudo" 85 | 86 | # Install basic tools 87 | RUN dnf update -y \ 88 | && dnf install -y \ 89 | ${BASE_DEPS} \ 90 | ${PMEMKV_DEPS} \ 91 | ${PMDK_DEPS} \ 92 | ${LIBPMEMOBJ_CPP_DEPS} \ 93 | ${VALGRIND_DEPS} \ 94 | ${EXAMPLES_DEPS} \ 95 | ${DOC_DEPS} \ 96 | ${TESTS_DEPS} \ 97 | ${MISC_DEPS} \ 98 | && dnf debuginfo-install -y glibc \ 99 | && dnf clean all 100 | 101 | # Install valgrind 102 | COPY install-valgrind.sh install-valgrind.sh 103 | RUN ./install-valgrind.sh 104 | 105 | # Install pmdk 106 | COPY install-pmdk.sh install-pmdk.sh 107 | RUN ./install-pmdk.sh rpm 108 | 109 | # Install pmdk c++ bindings 110 | COPY install-libpmemobj-cpp.sh install-libpmemobj-cpp.sh 111 | RUN ./install-libpmemobj-cpp.sh RPM 112 | 113 | # Add user 114 | ENV USER user 115 | ENV USERPASS pass 116 | RUN useradd -m $USER \ 117 | && echo "$USER:$USERPASS" | chpasswd \ 118 | && gpasswd wheel -a $USER 119 | USER $USER 120 | -------------------------------------------------------------------------------- /examples/pmemkv_config_c/pmemkv_basic_config.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2019-2021, Intel Corporation */ 3 | 4 | /* 5 | * pmemkv_basic_config.c -- example usage for part of the pmemkv config API, 6 | * which should be preferred. E.g. `put_size(...)` is less error-prone 7 | * than `put_int64("size", ...)` and hence recommended. 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #define ASSERT(expr) \ 18 | do { \ 19 | if (!(expr)) \ 20 | puts(pmemkv_errormsg()); \ 21 | assert(expr); \ 22 | } while (0) 23 | 24 | static const uint64_t SIZE = 1024UL * 1024UL * 1024UL; 25 | 26 | int key_length_compare(const char *key1, size_t keybytes1, const char *key2, 27 | size_t keybytes2, void *arg) 28 | { 29 | if (keybytes2 < keybytes1) 30 | return -1; 31 | else if (keybytes2 > keybytes1) 32 | return 1; 33 | else 34 | return 0; 35 | } 36 | 37 | int main(int argc, char *argv[]) 38 | { 39 | if (argc < 2) { 40 | fprintf(stderr, "Usage: %s file\n", argv[0]); 41 | exit(1); 42 | } 43 | 44 | /* Create config. */ 45 | pmemkv_config *config = pmemkv_config_new(); 46 | ASSERT(config != NULL); 47 | 48 | /* Add path parameter to config. Value is dependent on chosen engine. 49 | * E.g. if config is used for cmap engine, it is a path to a database file or 50 | * a poolset file. However for vcmap it is a path to an existing directory. 51 | * For details see documentation of selected engine. */ 52 | int status = pmemkv_config_put_path(config, argv[1]); 53 | ASSERT(status == PMEMKV_STATUS_OK); 54 | 55 | /* Specify size of the database (to create). */ 56 | status = pmemkv_config_put_size(config, SIZE); 57 | ASSERT(status == PMEMKV_STATUS_OK); 58 | 59 | /* Specify value of create_if_missing flag. 60 | * Alternatively, another flag - 'create_or_error_if_exists' can be set using: 61 | * `pmemkv_config_put_create_or_error_if_exists` 62 | * For differences between the two, see manpage libpmemkv(7). */ 63 | status = pmemkv_config_put_create_if_missing(config, true); 64 | ASSERT(status == PMEMKV_STATUS_OK); 65 | 66 | /* Specify comparator used by the (sorted) engine. */ 67 | pmemkv_comparator *cmp = 68 | pmemkv_comparator_new(&key_length_compare, "key_length_compare", NULL); 69 | ASSERT(cmp != NULL); 70 | status = pmemkv_config_put_comparator(config, cmp); 71 | ASSERT(status == PMEMKV_STATUS_OK); 72 | 73 | /* Add pointer to OID to the config. For details see libpmemkv(7) manpage. */ 74 | PMEMoid oid; 75 | status = pmemkv_config_put_oid(config, &oid); 76 | ASSERT(status == PMEMKV_STATUS_OK); 77 | 78 | pmemkv_config_delete(config); 79 | 80 | return 0; 81 | } 82 | -------------------------------------------------------------------------------- /examples/pmemkv_transaction_cpp/pmemkv_transaction.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2020-2021, Intel Corporation */ 3 | 4 | /* 5 | * pmemkv_transaction.cpp -- example usage of pmemkv transactions. 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #define ASSERT(expr) \ 14 | do { \ 15 | if (!(expr)) \ 16 | std::cout << pmemkv_errormsg() << std::endl; \ 17 | assert(expr); \ 18 | } while (0) 19 | #define LOG(msg) std::cout << msg << std::endl 20 | 21 | using namespace pmem::kv; 22 | 23 | /* 24 | * This example expects a path to already created database pool. 25 | * 26 | * To create a pool use one of the following commands. 27 | * 28 | * For regular pools use: 29 | * pmempool create -l -s 1G "pmemkv_radix" obj path_to_a_pool 30 | * 31 | * For poolsets use: 32 | * pmempool create -l "pmemkv_radix" obj ../examples/example.poolset 33 | */ 34 | //! [transaction] 35 | int main(int argc, char *argv[]) 36 | { 37 | if (argc < 2) { 38 | std::cerr << "Usage: " << argv[0] << " pool\n"; 39 | exit(1); 40 | } 41 | 42 | /* See libpmemkv_config(3) for more detailed example of creating a config */ 43 | LOG("Creating config"); 44 | config cfg; 45 | 46 | status s = cfg.put_path(argv[1]); 47 | ASSERT(s == status::OK); 48 | 49 | LOG("Opening pmemkv database with 'radix' engine"); 50 | db kv; 51 | s = kv.open("radix", std::move(cfg)); 52 | ASSERT(s == status::OK); 53 | 54 | LOG("Putting new key"); 55 | s = kv.put("key1", "value1"); 56 | ASSERT(s == status::OK); 57 | 58 | auto result_tx = kv.tx_begin(); 59 | ASSERT(result_tx.is_ok()); 60 | 61 | /* This function is guaranteed to not throw if is_ok is true */ 62 | auto &tx = result_tx.get_value(); 63 | s = tx.remove("key1"); 64 | s = tx.put("key2", "value2"); 65 | s = tx.put("key3", "value3"); 66 | 67 | /* Until transaction is committed, changes are not visible */ 68 | ASSERT(kv.exists("key1") == status::OK); 69 | ASSERT(kv.exists("key2") == status::NOT_FOUND); 70 | ASSERT(kv.exists("key3") == status::NOT_FOUND); 71 | 72 | s = tx.commit(); 73 | ASSERT(s == status::OK); 74 | 75 | ASSERT(kv.exists("key1") == status::NOT_FOUND); 76 | ASSERT(kv.exists("key2") == status::OK); 77 | ASSERT(kv.exists("key3") == status::OK); 78 | 79 | { 80 | /* Alternative method of obtaining tx object. This line can throw if 81 | * tx_begin() fails. */ 82 | auto tx = kv.tx_begin().get_value(); 83 | 84 | s = tx.put("key4", "value4"); 85 | s = tx.put("key5", "value5"); 86 | } 87 | 88 | /* The second tx was not committed, so the changes are not visible. */ 89 | ASSERT(kv.exists("key4") == status::NOT_FOUND); 90 | ASSERT(kv.exists("key5") == status::NOT_FOUND); 91 | 92 | return 0; 93 | } 94 | //! [transaction] 95 | --------------------------------------------------------------------------------