├── 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 │ │ ├── open.cc │ │ └── put_get_remove_params.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 │ ├── memkind │ │ └── error_handling.cc │ ├── put_get_std_map.hpp │ ├── pmreorder │ │ ├── recover.cc │ │ ├── insert.cc │ │ └── erase.cc │ └── iterator.hpp ├── 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 │ └── pskiplist │ │ ├── helpers.cmake │ │ └── default.cmake ├── memcheck-stdcpp.supp ├── common │ ├── test_backtrace.h │ └── check_is_pmem.cpp ├── memcheck-libunwind.supp ├── ld.supp ├── config │ ├── deprecated_config.cc │ ├── deprecated_config.c │ └── json_to_config.cc ├── error_msg_test.cc ├── comparator │ ├── basic_persistent.c │ ├── basic.c │ └── default_reopen.cc ├── README.md └── wrong_engine_name_test.cc ├── .gitattributes ├── 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 ├── iterator.h ├── fast_hash.h ├── iterator.cc ├── exceptions.h ├── transaction.h ├── fast_hash.cc └── libpmemkv.map ├── examples ├── example.poolset ├── pmemkv_basic_c │ └── CMakeLists.txt ├── pmemkv_basic_cpp │ └── CMakeLists.txt ├── pmemkv_open_cpp │ ├── CMakeLists.txt │ └── pmemkv_open.cpp ├── pmemkv_comparator_c │ └── CMakeLists.txt ├── pmemkv_iterator_c │ └── CMakeLists.txt ├── pmemkv_comparator_cpp │ ├── CMakeLists.txt │ └── pmemkv_comparator.cpp ├── pmemkv_iterator_cpp │ └── CMakeLists.txt ├── pmemkv_config_c │ ├── CMakeLists.txt │ └── pmemkv_basic_config.c ├── pmemkv_transaction_c │ └── CMakeLists.txt ├── pmemkv_transaction_cpp │ └── CMakeLists.txt ├── pmemkv_pmemobj_cpp │ └── CMakeLists.txt └── README ├── .gitmodules ├── .gitignore ├── 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-libpmemobj-cpp.sh │ │ ├── install-libndctl.sh │ │ ├── 0001-fix-generating-gcov-files-and-turn-off-verbose-log.patch │ │ ├── push-image.sh │ │ ├── Dockerfile.debian-testing │ │ ├── Dockerfile.fedora-32 │ │ ├── Dockerfile.fedora-33 │ │ ├── Dockerfile.ubuntu-rolling │ │ ├── Dockerfile.debian-unstable │ │ ├── Dockerfile.fedora-rawhide │ │ ├── Dockerfile.centos-8 │ │ ├── Dockerfile.archlinux-base-latest │ │ ├── Dockerfile.ubuntu-20.04 │ │ ├── Dockerfile.ubuntu-20.10 │ │ ├── Dockerfile.ubuntu-20.04_bindings │ │ ├── Dockerfile.opensuse-tumbleweed-latest │ │ ├── Dockerfile.ubuntu-18.04 │ │ └── Dockerfile.opensuse-leap-latest │ ├── 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 │ └── other_OSes.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 ├── doc ├── ENGINES-testing.md ├── RELEASE_STEPS.md └── libpmemkv_json_config.3.md ├── .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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "src/engines-experimental/pskiplist"] 2 | path = src/engines-experimental/pskiplist 3 | url = https://github.com/4paradigm/pskiplist.git 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 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .* 2 | !.gitignore 3 | !.gitattributes 4 | !.github/ 5 | !.clang-format 6 | *.d 7 | /bin/ 8 | /build/ 9 | cmake-build-debug/ 10 | /googletest-*.zip 11 | *~ 12 | -------------------------------------------------------------------------------- /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, Intel Corporation 3 | 4 | include(${PARENT_SRC_DIR}/helpers.cmake) 5 | 6 | setup() 7 | 8 | execute(${TEST_EXECUTABLE} ${ENGINE} ${DIR}/nope/nope ${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/pskiplist/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/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_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_iterator_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_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}) 14 | -------------------------------------------------------------------------------- /examples/pmemkv_config_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_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 | add_executable(pmemkv_config_c pmemkv_config.c) 13 | target_link_libraries(pmemkv_config_c ${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_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/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-2020, Intel Corporation 4 | 5 | # removeNamespaces.sh - clear all existing namespaces. 6 | set -e 7 | 8 | MOUNT_POINT="/mnt/pmem*" 9 | 10 | echo "Clearing all existing namespaces" 11 | sudo umount $MOUNT_POINT || true 12 | 13 | namespace_names=$(ndctl list -X | jq -r '.[].dev') 14 | 15 | for n in $namespace_names 16 | do 17 | sudo ndctl clear-errors $n -v 18 | done 19 | sudo ndctl disable-namespace all || true 20 | sudo ndctl destroy-namespace all || true 21 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /tests/engines/pskiplist/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 | execute_process(COMMAND ${CMAKE_COMMAND} -E remove_directory /mnt/pmem0/${TEST_NAME}) 14 | execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory /mnt/pmem0/${TEST_NAME}) 15 | pmempool_execute(create -l ${LAYOUT} -s ${DB_SIZE} obj /mnt/pmem0/${TEST_NAME}/testfile) 16 | 17 | make_config({"path":"/mnt/pmem0/${TEST_NAME}/testfile"}) 18 | execute(${TEST_EXECUTABLE} ${ENGINE} ${CONFIG} ${PARAMS}) 19 | 20 | finish() 21 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | # contains new libmemkind namespace 13 | MEMKIND_VERSION=v1.11.0 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-2020, Intel Corporation 4 | 5 | # 6 | # install-valgrind.sh - installs valgrind for persistent memory 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.15: Merge pull request #81 from marcinslusarz/pmem-3.15 21 | git checkout 09f75f69683d862f8456f75484fcdc0dc5508900 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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | } 40 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /.github/workflows/coverity.yml: -------------------------------------------------------------------------------- 1 | 2 | name: pmemkv-coverity 3 | on: 4 | schedule: 5 | # run this job at 00:00 UTC everyday 6 | - cron: '0 0 * * *' 7 | 8 | env: 9 | REPO: pmemkv 10 | GITHUB_REPO: pmem/pmemkv 11 | CONTAINER_REG: ghcr.io/pmem/pmemkv 12 | HOST_WORKDIR: ${{ github.workspace }} 13 | WORKDIR: utils/docker 14 | IMG_VER: latest 15 | COVERITY_SCAN_NOTIFICATION_EMAIL: ${{ secrets.COVERITY_SCAN_NOTIFICATION_EMAIL }} 16 | COVERITY_SCAN_TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }} 17 | 18 | jobs: 19 | linux: 20 | name: Linux-coverity 21 | runs-on: ubuntu-latest 22 | strategy: 23 | matrix: 24 | CONFIG: ["TYPE=coverity OS=ubuntu OS_VER=20.04"] 25 | steps: 26 | - name: Clone the git repo 27 | uses: actions/checkout@v2 28 | 29 | # coverity workflow should just reuse (pull) the most recent, available image 30 | - name: Pull the image 31 | run: cd $WORKDIR && ${{ matrix.CONFIG }} ./pull-or-rebuild-image.sh pull 32 | 33 | - name: Run the build 34 | run: cd $WORKDIR && ${{ matrix.CONFIG }} ./build.sh 35 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | size_t count = std::numeric_limits::max(); 30 | auto s = kv.count_all(count); 31 | ASSERT_STATUS(s, pmem::kv::status::OK); 32 | UT_ASSERTeq(count, 0); 33 | } 34 | 35 | static void test(int argc, char *argv[]) 36 | { 37 | if (argc < 3) 38 | UT_FATAL("usage: %s engine json_config", argv[0]); 39 | 40 | run_engine_tests(argv[1], argv[2], {OOM}); 41 | } 42 | 43 | int main(int argc, char *argv[]) 44 | { 45 | return run_test([&] { test(argc, argv); }); 46 | } 47 | -------------------------------------------------------------------------------- /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 | auto kv = INITIALIZE_KV(engine, std::move(cfg)); 40 | 41 | TransactionTest(pmemobj_pool, kv); 42 | 43 | pmemobj_pool.close(); 44 | } 45 | 46 | int main(int argc, char *argv[]) 47 | { 48 | return run_test([&] { test(argc, argv); }); 49 | } 50 | -------------------------------------------------------------------------------- /src/iterator.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2020, 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 | } /* namespace internal */ 50 | } /* namespace kv */ 51 | } /* namespace pmem */ 52 | 53 | #endif /* LIBPMEMKV_ITERATOR_H */ 54 | -------------------------------------------------------------------------------- /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-2021, Intel Corporation 4 | 5 | # 6 | # install-pmdk.sh - installs PMDK 7 | # 8 | 9 | set -e 10 | 11 | if [ "${SKIP_PMDK_BUILD}" ]; then 12 | echo "Variable 'SKIP_PMDK_BUILD' is set; skipping building PMDK" 13 | exit 14 | fi 15 | 16 | PACKAGE_TYPE=$1 17 | PREFIX=${2:-/usr} 18 | 19 | # master: Merge pull request #5150 from kilobyte/rpm-no-lto, 16.02.2021 20 | # contains fix for packaging 21 | PMDK_VERSION="7f88d9fae088b81936d2f6d5235169e90e7478c7" 22 | 23 | git clone https://github.com/pmem/pmdk 24 | cd pmdk 25 | git checkout $PMDK_VERSION 26 | 27 | if [ "$PACKAGE_TYPE" = "" ]; then 28 | make -j$(nproc) install prefix=$PREFIX 29 | else 30 | make -j$(nproc) BUILD_PACKAGE_CHECK=n $PACKAGE_TYPE 31 | if [ "$PACKAGE_TYPE" = "dpkg" ]; then 32 | sudo dpkg -i dpkg/libpmem_*.deb dpkg/libpmem-dev_*.deb 33 | sudo dpkg -i dpkg/libpmemobj_*.deb dpkg/libpmemobj-dev_*.deb 34 | sudo dpkg -i dpkg/pmreorder_*.deb 35 | sudo dpkg -i dpkg/libpmempool_*.deb dpkg/libpmempool-dev_*.deb 36 | sudo dpkg -i dpkg/libpmemblk_*.deb dpkg/libpmemlog_*.deb dpkg/libpmempool_*.deb dpkg/pmempool_*.deb 37 | elif [ "$PACKAGE_TYPE" = "rpm" ]; then 38 | sudo rpm -i rpm/*/pmdk-debuginfo-*.rpm 39 | sudo rpm -i rpm/*/libpmem*-*.rpm 40 | sudo rpm -i rpm/*/pmreorder-*.rpm 41 | sudo rpm -i 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 | -------------------------------------------------------------------------------- /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-libpmemobj-cpp.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | # Copyright 2019-2021, 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 | # Merge pull request #1048 from lukaszstolarczuk/tests-gdb; 04.03.2021 22 | # It contains new exception: pool_invalid_argument 23 | LIBPMEMOBJ_CPP_VERSION="7cc2f387fa261f370a3c5f0f9e122756bc2fffb0" 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 | 40 | if [ "${PACKAGE_TYPE}" = "" ]; then 41 | make -j$(nproc) install 42 | else 43 | make -j$(nproc) package 44 | if [ "${PACKAGE_TYPE}" = "DEB" ]; then 45 | sudo dpkg -i libpmemobj++*.deb 46 | elif [ "${PACKAGE_TYPE}" = "RPM" ]; then 47 | sudo rpm -iv libpmemobj++*.rpm 48 | fi 49 | fi 50 | 51 | popd 52 | rm -r ${build_dir} 53 | -------------------------------------------------------------------------------- /utils/docker/images/install-libndctl.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | # Copyright 2018-2020, 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 | -------------------------------------------------------------------------------- /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/memkind/error_handling.cc: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2020, Intel Corporation */ 3 | 4 | #include "unittest.hpp" 5 | 6 | static void FailsToOpenInstanceWithInvalidPath(std::string engine, 7 | std::string non_existent_path) 8 | { 9 | pmem::kv::config cfg; 10 | auto s = cfg.put_path(non_existent_path); 11 | ASSERT_STATUS(s, pmem::kv::status::OK); 12 | s = cfg.put_size(83886080); 13 | ASSERT_STATUS(s, pmem::kv::status::OK); 14 | 15 | pmem::kv::db kv; 16 | s = kv.open(engine, std::move(cfg)); 17 | 18 | /* Not-existent path supplied */ 19 | // XXX - should be WRONG_PATH 20 | ASSERT_STATUS(s, pmem::kv::status::UNKNOWN_ERROR); 21 | } 22 | 23 | static void NoSizeInConfig(std::string engine) 24 | { 25 | pmem::kv::config cfg; 26 | auto s = cfg.put_path("some_path"); 27 | ASSERT_STATUS(s, pmem::kv::status::OK); 28 | 29 | pmem::kv::db kv; 30 | s = kv.open(engine, std::move(cfg)); 31 | 32 | ASSERT_STATUS(s, pmem::kv::status::INVALID_ARGUMENT); 33 | } 34 | 35 | static void NoPathInConfig(std::string engine) 36 | { 37 | pmem::kv::config cfg; 38 | auto s = cfg.put_size(83886080); 39 | ASSERT_STATUS(s, pmem::kv::status::OK); 40 | 41 | pmem::kv::db kv; 42 | s = kv.open(engine, std::move(cfg)); 43 | 44 | ASSERT_STATUS(s, pmem::kv::status::INVALID_ARGUMENT); 45 | } 46 | 47 | static void test(int argc, char *argv[]) 48 | { 49 | if (argc < 2) 50 | UT_FATAL("usage: %s engine non_existent_path", argv[0]); 51 | 52 | FailsToOpenInstanceWithInvalidPath(argv[1], argv[2]); 53 | NoSizeInConfig(argv[1]); 54 | NoPathInConfig(argv[1]); 55 | } 56 | 57 | int main(int argc, char *argv[]) 58 | { 59 | return run_test([&] { test(argc, argv); }); 60 | } 61 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /examples/README: -------------------------------------------------------------------------------- 1 | This directory contains C and C++ examples for pmemkv, the library 2 | providing key-value datastore optimized for persistent memory. 3 | For more information see libpmemkv(3). 4 | 5 | pmemkv_basic_c/pmemkv_basic.c -- contains basic example workflow 6 | of C application 7 | 8 | pmemkv_basic_cpp/pmemkv_basic.cpp -- contains basic example workflow 9 | of C++ application 10 | 11 | pmemkv_comparator_c/pmemkv_comparator.c -- example of pmemkv used with 12 | custom comparator (C API) 13 | 14 | pmemkv_comparator_c/pmemkv_comparator.cpp -- example of pmemkv used with 15 | custom comparator (C++ API) 16 | 17 | pmemkv_config_c/ 18 | * pmemkv_basic_config.c -- example usage of the part of the pmemkv config API, 19 | which should be preferred. 20 | 21 | * pmemkv_config.c -- example usage of the part of the pmemkv config API 22 | to set and get data based on their data types. 23 | It requires to be built: 24 | - 'rapidjson-devel' package to be installed in the OS and 25 | - 'BUILD_JSON_CONFIG' pmemkv's CMake variable to be set to ON 26 | 27 | pmemkv_iterator_c/pmemkv_iterator.c -- example of pmemkv's iterator 28 | 29 | pmemkv_iterator_cpp/pmemkv_iterator.cpp -- example of pmemkv's iterators. 30 | It shows how to use it in single-threaded and concurrent approach. 31 | It requires to be built: 32 | - pthread available in the OS 33 | 34 | pmemkv_open_cpp/pmemkv_open_cpp -- contains example of pmemkv usage 35 | for already existing pools (and poolsets) 36 | 37 | pmemkv_pmemobj_cpp/pmemkv_pmemobj_basic.cpp -- contains example 38 | of pmemkv supporting multiple engines 39 | 40 | pmemkv_transaction_c/pmemkv_transaction.c -- example with pmemkv transactions (C API) 41 | 42 | pmemkv_transaction_cpp/pmemkv_transaction.cpp -- example with pmemkv transactions (C++ API) 43 | -------------------------------------------------------------------------------- /tests/engine_scenarios/put_get_std_map.hpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2020, 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 | size_t cnt; 46 | ASSERT_STATUS(kv.count_all(cnt), pmem::kv::status::OK); 47 | UT_ASSERTeq(prototype.size(), cnt); 48 | 49 | /* Retrieve data from db and compare with prototype */ 50 | for (const auto &record : prototype) { 51 | const auto &key = record.first; 52 | const auto &val = record.second; 53 | 54 | auto s = kv.get(key, [&](string_view value) { 55 | UT_ASSERT(value.compare(val) == 0); 56 | }); 57 | ASSERT_STATUS(s, status::OK); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/engines/vcmap.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2017-2021, Intel Corporation */ 3 | 4 | #pragma once 5 | 6 | #include "basic_vcmap.h" 7 | #include "pmem_allocator.h" 8 | 9 | #ifdef USE_LIBMEMKIND_NAMESPACE 10 | namespace memkind_ns = libmemkind::pmem; 11 | #else 12 | namespace memkind_ns = pmem; 13 | #endif 14 | 15 | namespace pmem 16 | { 17 | namespace kv 18 | { 19 | namespace internal 20 | { 21 | 22 | class memkind_allocator_factory { 23 | public: 24 | template 25 | using allocator_type = memkind_ns::allocator; 26 | 27 | template 28 | static allocator_type create(internal::config &cfg) 29 | { 30 | return allocator_type(get_path(cfg), get_size(cfg)); 31 | } 32 | 33 | private: 34 | static std::string get_path(internal::config &cfg) 35 | { 36 | const char *path; 37 | if (!cfg.get_string("path", &path)) 38 | throw internal::invalid_argument( 39 | "Config does not contain item with key: \"path\""); 40 | 41 | return std::string(path); 42 | } 43 | 44 | static uint64_t get_size(internal::config &cfg) 45 | { 46 | std::size_t size; 47 | if (!cfg.get_uint64("size", &size)) 48 | throw internal::invalid_argument( 49 | "Config does not contain item with key: \"size\""); 50 | 51 | return size; 52 | } 53 | }; 54 | } 55 | 56 | using vcmap = basic_vcmap; 57 | 58 | class vcmap_factory : public engine_base::factory_base { 59 | public: 60 | virtual std::unique_ptr create(std::unique_ptr cfg) 61 | { 62 | check_config_null(get_name(), cfg); 63 | return std::unique_ptr(new vcmap(std::move(cfg))); 64 | }; 65 | virtual std::string get_name() 66 | { 67 | return "vcmap"; 68 | }; 69 | }; 70 | 71 | } /* namespace kv */ 72 | } /* namespace pmem */ 73 | -------------------------------------------------------------------------------- /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 | std::size_t cnt = std::numeric_limits::max(); 29 | ASSERT_STATUS(kv.count_all(cnt), status::OK); 30 | UT_ASSERT(cnt == iterations); 31 | } 32 | 33 | static void test(int argc, char *argv[]) 34 | { 35 | if (argc < 5) 36 | UT_FATAL("usage: %s engine json_config insert/check iterations", argv[0]); 37 | 38 | std::string mode = argv[3]; 39 | if (mode != "insert" && mode != "check") 40 | UT_FATAL("usage: %s engine json_config insert/check iterations", argv[0]); 41 | 42 | auto iterations = std::stoull(argv[4]); 43 | 44 | auto kv = INITIALIZE_KV(argv[1], CONFIG_FROM_JSON(argv[2])); 45 | 46 | if (mode == "insert") { 47 | insert(iterations, kv); 48 | } else { 49 | check(iterations, 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 | -------------------------------------------------------------------------------- /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 | std::size_t cnt = std::numeric_limits::max(); 30 | ASSERT_STATUS(kv.count_all(cnt), status::OK); 31 | UT_ASSERT(cnt == iterations); 32 | } 33 | 34 | static void test(int argc, char *argv[]) 35 | { 36 | if (argc < 5) 37 | UT_FATAL("usage: %s engine json_config insert/check iterations", argv[0]); 38 | 39 | std::string mode = argv[3]; 40 | if (mode != "insert" && mode != "check") 41 | UT_FATAL("usage: %s engine json_config insert/check iterations", argv[0]); 42 | 43 | auto iterations = std::stoull(argv[4]); 44 | 45 | auto kv = INITIALIZE_KV(argv[1], CONFIG_FROM_JSON(argv[2])); 46 | 47 | if (mode == "insert") { 48 | insert(iterations, kv); 49 | } else { 50 | check(iterations, kv); 51 | } 52 | 53 | kv.close(); 54 | } 55 | 56 | int main(int argc, char *argv[]) 57 | { 58 | return run_test([&] { test(argc, argv); }); 59 | } 60 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /.github/workflows/other_OSes.yml: -------------------------------------------------------------------------------- 1 | 2 | name: pmemkv-other 3 | on: 4 | schedule: 5 | # run this job at 01:00 UTC everyday 6 | - cron: '0 1 * * *' 7 | 8 | env: 9 | REPO: pmemkv 10 | GITHUB_REPO: pmem/pmemkv 11 | CONTAINER_REG: ghcr.io/pmem/pmemkv 12 | HOST_WORKDIR: ${{ github.workspace }} 13 | WORKDIR: utils/docker 14 | IMG_VER: latest 15 | TYPE: debug 16 | PUSH_IMAGE: 1 17 | # use org's Private Access Token to log in to GitHub Container Registry 18 | CONTAINER_REG_USER: ${{ secrets.GH_CR_USER }} 19 | CONTAINER_REG_PASS: ${{ secrets.GH_CR_PAT }} 20 | 21 | jobs: 22 | linux: 23 | name: Linux-other 24 | runs-on: ubuntu-latest 25 | strategy: 26 | fail-fast: false 27 | matrix: 28 | CONFIG: ["OS=centos OS_VER=8", 29 | "OS=archlinux-base OS_VER=latest", 30 | "OS=debian OS_VER=testing", 31 | "OS=debian OS_VER=unstable", 32 | "OS=fedora OS_VER=33", 33 | "OS=fedora OS_VER=rawhide PUSH_IMAGE=0", 34 | "TYPE=building OS=fedora OS_VER=rawhide", 35 | "OS=opensuse-leap OS_VER=latest", 36 | "OS=opensuse-tumbleweed OS_VER=latest", 37 | "OS=ubuntu OS_VER=18.04", 38 | "OS=ubuntu OS_VER=rolling PUSH_IMAGE=0", 39 | "TYPE=building OS=ubuntu OS_VER=rolling"] 40 | steps: 41 | - name: Clone the git repo 42 | uses: actions/checkout@v2 43 | 44 | # other_OSes workflow rebuilds images every time and push them to the container registry 45 | - name: Rebuild and push the image 46 | run: cd $WORKDIR && ${{ matrix.CONFIG }} ./pull-or-rebuild-image.sh rebuild 47 | 48 | - name: Run the build 49 | run: cd $WORKDIR && ${{ matrix.CONFIG }} ./build.sh 50 | -------------------------------------------------------------------------------- /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 | - once gh-pages branch contains new documentation: 37 | - add there (in index.md) new links to manpages and Doxygen docs 38 | - update there "Releases' support status" table (update any other release's status if needed) 39 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | 14 | size_t cnt = std::numeric_limits::max(); 15 | 16 | ASSERT_STATUS(kv.count_all(cnt), pmem::kv::status::OK); 17 | UT_ASSERTeq(cnt, 0); 18 | 19 | for (size_t i = 0; i < 100; ++i) 20 | ASSERT_STATUS(kv.put(entry_from_number(i, "", "key"), 21 | entry_from_number(i, "", "val")), 22 | pmem::kv::status::OK); 23 | 24 | ASSERT_STATUS(kv.count_all(cnt), pmem::kv::status::OK); 25 | UT_ASSERTeq(cnt, 100); 26 | 27 | for (size_t i = 0; i < 100; ++i) { 28 | std::string val; 29 | ASSERT_STATUS(kv.get(entry_from_number(i, "", "key"), &val), 30 | pmem::kv::status::OK); 31 | UT_ASSERT(val == entry_from_number(i, "", "val")); 32 | 33 | ASSERT_STATUS(kv.remove(entry_from_number(i, "", "key")), 34 | pmem::kv::status::OK); 35 | } 36 | 37 | ASSERT_STATUS(kv.count_all(cnt), pmem::kv::status::OK); 38 | UT_ASSERTeq(cnt, 0); 39 | 40 | kv.close(); 41 | } 42 | 43 | static void test(int argc, char *argv[]) 44 | { 45 | if (argc < 4) 46 | UT_FATAL("usage: %s engine json_config ", argv[0]); 47 | 48 | std::string mode = argv[3]; 49 | if (mode != "open" && mode != "create") 50 | UT_FATAL("usage: %s engine json_config ", argv[0]); 51 | 52 | if (mode == "open") { 53 | check_consistency(argv[1], argv[2]); 54 | } else if (mode == "create") { 55 | INITIALIZE_KV(argv[1], CONFIG_FROM_JSON(argv[2])); 56 | } 57 | } 58 | 59 | int main(int argc, char *argv[]) 60 | { 61 | return run_test([&] { test(argc, argv); }); 62 | } 63 | -------------------------------------------------------------------------------- /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 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 | # Update the Apt cache and install basic tools 25 | RUN apt-get update 26 | RUN DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ 27 | autoconf \ 28 | automake \ 29 | build-essential \ 30 | clang \ 31 | clang-format-9 \ 32 | cmake \ 33 | curl \ 34 | debhelper \ 35 | devscripts \ 36 | doxygen \ 37 | fakeroot \ 38 | git \ 39 | gdb \ 40 | graphviz \ 41 | gzip \ 42 | libc6-dbg \ 43 | libdaxctl-dev \ 44 | libndctl-dev \ 45 | libmemkind-dev \ 46 | libnode-dev \ 47 | libnuma-dev \ 48 | libtbb-dev \ 49 | libtext-diff-perl \ 50 | libtool \ 51 | libunwind8-dev \ 52 | numactl \ 53 | pandoc \ 54 | pkg-config \ 55 | rapidjson-dev \ 56 | sudo \ 57 | wget \ 58 | whois \ 59 | && rm -rf /var/lib/apt/lists/* 60 | 61 | # Install valgrind 62 | COPY install-valgrind.sh install-valgrind.sh 63 | RUN ./install-valgrind.sh 64 | 65 | # Install pmdk 66 | COPY install-pmdk.sh install-pmdk.sh 67 | RUN ./install-pmdk.sh dpkg 68 | 69 | # Install pmdk c++ bindings 70 | COPY install-libpmemobj-cpp.sh install-libpmemobj-cpp.sh 71 | RUN ./install-libpmemobj-cpp.sh DEB 72 | 73 | # Add user 74 | ENV USER user 75 | ENV USERPASS pass 76 | RUN useradd -m $USER -g sudo -p `mkpasswd $USERPASS` 77 | USER $USER 78 | -------------------------------------------------------------------------------- /utils/docker/images/Dockerfile.fedora-32: -------------------------------------------------------------------------------- 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 fedora:32 11 | MAINTAINER igor.chorazewicz@intel.com 12 | 13 | # Set required environment variables 14 | ENV OS fedora 15 | ENV OS_VER 32 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 | ARG LIBPMEMOBJ_CPP_DEPS="\ 25 | libatomic" 26 | 27 | # Install basic tools 28 | RUN dnf update -y \ 29 | && dnf install -y \ 30 | autoconf \ 31 | automake \ 32 | clang \ 33 | cmake \ 34 | daxctl-devel \ 35 | doxygen \ 36 | gcc \ 37 | gcc-c++ \ 38 | gdb \ 39 | git \ 40 | graphviz \ 41 | gzip \ 42 | hub \ 43 | libtool \ 44 | libunwind-devel \ 45 | make \ 46 | man \ 47 | memkind-devel \ 48 | ndctl-devel \ 49 | numactl-devel \ 50 | pandoc \ 51 | passwd \ 52 | perl-Text-Diff \ 53 | rapidjson-devel \ 54 | rpm-build \ 55 | sudo \ 56 | tbb-devel \ 57 | wget \ 58 | which \ 59 | $LIBPMEMOBJ_CPP_DEPS \ 60 | && dnf clean all 61 | 62 | # Install glibc-debuginfo 63 | RUN dnf debuginfo-install -y glibc 64 | 65 | # Install valgrind 66 | COPY install-valgrind.sh install-valgrind.sh 67 | RUN ./install-valgrind.sh 68 | 69 | # Install pmdk 70 | COPY install-pmdk.sh install-pmdk.sh 71 | RUN ./install-pmdk.sh rpm 72 | 73 | # Install pmdk c++ bindings 74 | COPY install-libpmemobj-cpp.sh install-libpmemobj-cpp.sh 75 | RUN ./install-libpmemobj-cpp.sh rpm 76 | 77 | # Add user 78 | ENV USER user 79 | ENV USERPASS pass 80 | RUN useradd -m $USER 81 | RUN echo "$USER:$USERPASS" | chpasswd 82 | RUN gpasswd wheel -a $USER 83 | USER $USER 84 | -------------------------------------------------------------------------------- /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 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 | ARG LIBPMEMOBJ_CPP_DEPS="\ 25 | libatomic" 26 | 27 | # Install basic tools 28 | RUN dnf update -y \ 29 | && dnf install -y \ 30 | autoconf \ 31 | automake \ 32 | clang \ 33 | cmake \ 34 | daxctl-devel \ 35 | doxygen \ 36 | gcc \ 37 | gcc-c++ \ 38 | gdb \ 39 | git \ 40 | graphviz \ 41 | gzip \ 42 | hub \ 43 | libtool \ 44 | libunwind-devel \ 45 | make \ 46 | man \ 47 | memkind-devel \ 48 | ndctl-devel \ 49 | numactl-devel \ 50 | pandoc \ 51 | passwd \ 52 | perl-Text-Diff \ 53 | rapidjson-devel \ 54 | rpm-build \ 55 | sudo \ 56 | tbb-devel \ 57 | wget \ 58 | which \ 59 | $LIBPMEMOBJ_CPP_DEPS \ 60 | && dnf clean all 61 | 62 | # Install glibc-debuginfo 63 | RUN dnf debuginfo-install -y glibc 64 | 65 | # Install valgrind 66 | COPY install-valgrind.sh install-valgrind.sh 67 | RUN ./install-valgrind.sh 68 | 69 | # Install pmdk 70 | COPY install-pmdk.sh install-pmdk.sh 71 | RUN ./install-pmdk.sh rpm 72 | 73 | # Install pmdk c++ bindings 74 | COPY install-libpmemobj-cpp.sh install-libpmemobj-cpp.sh 75 | RUN ./install-libpmemobj-cpp.sh RPM 76 | 77 | # Add user 78 | ENV USER user 79 | ENV USERPASS pass 80 | RUN useradd -m $USER 81 | RUN echo "$USER:$USERPASS" | chpasswd 82 | RUN gpasswd wheel -a $USER 83 | USER $USER 84 | -------------------------------------------------------------------------------- /utils/docker/images/Dockerfile.ubuntu-rolling: -------------------------------------------------------------------------------- 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 ubuntu:rolling 11 | MAINTAINER igor.chorazewicz@intel.com 12 | 13 | # Set required environment variables 14 | ENV OS ubuntu 15 | ENV OS_VER rolling 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 | # Update the Apt cache and install basic tools 25 | RUN apt-get update 26 | RUN DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ 27 | autoconf \ 28 | automake \ 29 | build-essential \ 30 | clang \ 31 | clang-format-9 \ 32 | cmake \ 33 | curl \ 34 | debhelper \ 35 | devscripts \ 36 | doxygen \ 37 | fakeroot \ 38 | gdb \ 39 | git \ 40 | graphviz \ 41 | gzip \ 42 | libc6-dbg \ 43 | libdaxctl-dev \ 44 | libndctl-dev \ 45 | libmemkind-dev \ 46 | libnode-dev \ 47 | libnuma-dev \ 48 | libtbb-dev \ 49 | libtext-diff-perl \ 50 | libtool \ 51 | libunwind8-dev \ 52 | numactl \ 53 | pandoc \ 54 | pkg-config \ 55 | rapidjson-dev \ 56 | sudo \ 57 | wget \ 58 | whois \ 59 | && rm -rf /var/lib/apt/lists/* 60 | 61 | # Install valgrind 62 | COPY install-valgrind.sh install-valgrind.sh 63 | RUN ./install-valgrind.sh 64 | 65 | # Install pmdk 66 | COPY install-pmdk.sh install-pmdk.sh 67 | RUN ./install-pmdk.sh dpkg 68 | 69 | # Install pmdk c++ bindings 70 | COPY install-libpmemobj-cpp.sh install-libpmemobj-cpp.sh 71 | RUN ./install-libpmemobj-cpp.sh DEB 72 | 73 | # Add user 74 | ENV USER user 75 | ENV USERPASS pass 76 | RUN useradd -m $USER -g sudo -p `mkpasswd $USERPASS` 77 | USER $USER 78 | -------------------------------------------------------------------------------- /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 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 | # Update the Apt cache and install basic tools 25 | RUN apt-get update 26 | RUN DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ 27 | autoconf \ 28 | automake \ 29 | build-essential \ 30 | clang \ 31 | clang-format-9 \ 32 | cmake \ 33 | curl \ 34 | debhelper \ 35 | devscripts \ 36 | doxygen \ 37 | fakeroot \ 38 | git \ 39 | gdb \ 40 | graphviz \ 41 | gzip \ 42 | libc6-dbg \ 43 | libdaxctl-dev \ 44 | libndctl-dev \ 45 | libmemkind-dev \ 46 | libnode-dev \ 47 | libnuma-dev \ 48 | libtbb-dev \ 49 | libtext-diff-perl \ 50 | libtool \ 51 | libunwind8-dev \ 52 | numactl \ 53 | pandoc \ 54 | pkg-config \ 55 | rapidjson-dev \ 56 | sudo \ 57 | wget \ 58 | whois \ 59 | && rm -rf /var/lib/apt/lists/* 60 | 61 | # Install valgrind 62 | COPY install-valgrind.sh install-valgrind.sh 63 | RUN ./install-valgrind.sh 64 | 65 | # Install pmdk 66 | COPY install-pmdk.sh install-pmdk.sh 67 | RUN ./install-pmdk.sh dpkg 68 | 69 | # Install pmdk c++ bindings 70 | COPY install-libpmemobj-cpp.sh install-libpmemobj-cpp.sh 71 | RUN ./install-libpmemobj-cpp.sh DEB 72 | 73 | # Add user 74 | ENV USER user 75 | ENV USERPASS pass 76 | RUN useradd -m $USER -g sudo -p `mkpasswd $USERPASS` 77 | USER $USER 78 | -------------------------------------------------------------------------------- /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 | # 8 | 9 | # Pull base image 10 | FROM fedora:rawhide 11 | MAINTAINER igor.chorazewicz@intel.com 12 | 13 | # Set required environment variables 14 | ENV OS fedora 15 | ENV OS_VER rawhide 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 | ARG LIBPMEMOBJ_CPP_DEPS="\ 25 | libatomic" 26 | 27 | # Install basic tools 28 | RUN dnf update -y \ 29 | && dnf install -y \ 30 | autoconf \ 31 | automake \ 32 | clang \ 33 | cmake \ 34 | daxctl-devel \ 35 | doxygen \ 36 | gcc \ 37 | gcc-c++ \ 38 | gdb \ 39 | git \ 40 | graphviz \ 41 | gzip \ 42 | libtool \ 43 | libunwind-devel \ 44 | make \ 45 | man \ 46 | memkind-devel \ 47 | ndctl-devel \ 48 | numactl-devel \ 49 | pandoc \ 50 | passwd \ 51 | perl-Text-Diff \ 52 | rapidjson-devel \ 53 | rpm-build \ 54 | sudo \ 55 | tbb-devel \ 56 | unzip \ 57 | wget \ 58 | which \ 59 | $LIBPMEMOBJ_CPP_DEPS \ 60 | && dnf clean all 61 | 62 | # Install glibc-debuginfo 63 | RUN dnf debuginfo-install -y glibc 64 | 65 | # Install valgrind 66 | COPY install-valgrind.sh install-valgrind.sh 67 | RUN ./install-valgrind.sh 68 | 69 | # Install pmdk 70 | COPY install-pmdk.sh install-pmdk.sh 71 | RUN ./install-pmdk.sh rpm 72 | 73 | # Install pmdk c++ bindings 74 | COPY install-libpmemobj-cpp.sh install-libpmemobj-cpp.sh 75 | RUN ./install-libpmemobj-cpp.sh RPM 76 | 77 | # Add user 78 | ENV USER user 79 | ENV USERPASS pass 80 | RUN useradd -m $USER 81 | RUN echo "$USER:$USERPASS" | chpasswd 82 | RUN gpasswd wheel -a $USER 83 | USER $USER 84 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /utils/docker/images/Dockerfile.centos-8: -------------------------------------------------------------------------------- 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 centos-based 6 | # environment prepared for running pmemkv build and tests. 7 | # 8 | 9 | # Pull base image 10 | FROM centos:8 11 | MAINTAINER igor.chorazewicz@intel.com 12 | 13 | # Set required environment variables 14 | ENV OS centos 15 | ENV OS_VER 8 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 | RUN dnf update -y 25 | RUN dnf install -y epel-release 26 | RUN dnf install -y 'dnf-command(config-manager)' 27 | RUN dnf config-manager --set-enabled powertools 28 | 29 | ARG LIBPMEMOBJ_CPP_DEPS="\ 30 | libatomic" 31 | 32 | # Install basic tools 33 | RUN dnf install -y \ 34 | autoconf \ 35 | automake \ 36 | clang \ 37 | cmake \ 38 | daxctl-devel \ 39 | doxygen \ 40 | gcc \ 41 | gcc-c++ \ 42 | gdb \ 43 | git \ 44 | graphviz \ 45 | gzip \ 46 | libunwind-devel \ 47 | libtool \ 48 | make \ 49 | man \ 50 | ndctl-devel \ 51 | numactl-devel \ 52 | pandoc \ 53 | passwd \ 54 | perl-Text-Diff \ 55 | python36 \ 56 | rapidjson-devel \ 57 | rpm-build \ 58 | sudo \ 59 | tbb-devel \ 60 | wget \ 61 | which \ 62 | $LIBPMEMOBJ_CPP_DEPS \ 63 | && dnf clean all 64 | 65 | # Install glibc-debuginfo 66 | RUN dnf debuginfo-install -y glibc 67 | 68 | # Install valgrind 69 | COPY install-valgrind.sh install-valgrind.sh 70 | RUN ./install-valgrind.sh centos 71 | 72 | # Install pmdk 73 | COPY install-pmdk.sh install-pmdk.sh 74 | RUN ./install-pmdk.sh rpm 75 | 76 | # Install pmdk c++ bindings 77 | COPY install-libpmemobj-cpp.sh install-libpmemobj-cpp.sh 78 | RUN ./install-libpmemobj-cpp.sh RPM 79 | 80 | # Install memkind 81 | COPY install-memkind.sh install-memkind.sh 82 | RUN ./install-memkind.sh 83 | 84 | # Add user 85 | ENV USER user 86 | ENV USERPASS pass 87 | RUN useradd -m $USER 88 | RUN echo "$USER:$USERPASS" | chpasswd 89 | RUN gpasswd wheel -a $USER 90 | USER $USER 91 | -------------------------------------------------------------------------------- /.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, 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_ASSERT(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_ASSERT(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 | -------------------------------------------------------------------------------- /tests/engine_scenarios/all/put_get_remove_long_key.cc: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2017-2020, 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 | std::size_t cnt = std::numeric_limits::max(); 13 | ASSERT_STATUS(kv.count_all(cnt), status::OK); 14 | UT_ASSERT(cnt == 1); 15 | ASSERT_STATUS(kv.get("123456789ABCDE", &value), status::OK); 16 | UT_ASSERT(value == "A"); 17 | 18 | std::string value2; 19 | ASSERT_STATUS(kv.put("123456789ABCDEF", "B"), status::OK); 20 | cnt = std::numeric_limits::max(); 21 | ASSERT_STATUS(kv.count_all(cnt), status::OK); 22 | UT_ASSERT(cnt == 2); 23 | ASSERT_STATUS(kv.get("123456789ABCDEF", &value2), status::OK); 24 | UT_ASSERT(value2 == "B"); 25 | 26 | std::string value3; 27 | ASSERT_STATUS(kv.put("12345678ABCDEFG", "C"), status::OK); 28 | cnt = std::numeric_limits::max(); 29 | ASSERT_STATUS(kv.count_all(cnt), status::OK); 30 | UT_ASSERT(cnt == 3); 31 | ASSERT_STATUS(kv.get("12345678ABCDEFG", &value3), status::OK); 32 | UT_ASSERT(value3 == "C"); 33 | 34 | std::string value4; 35 | ASSERT_STATUS(kv.put("123456789", "D"), status::OK); 36 | cnt = std::numeric_limits::max(); 37 | ASSERT_STATUS(kv.count_all(cnt), status::OK); 38 | UT_ASSERT(cnt == 4); 39 | ASSERT_STATUS(kv.get("123456789", &value4), status::OK); 40 | UT_ASSERT(value4 == "D"); 41 | 42 | std::string value5; 43 | ASSERT_STATUS(kv.put("123456789ABCDEFGHI", "E"), status::OK); 44 | cnt = std::numeric_limits::max(); 45 | ASSERT_STATUS(kv.count_all(cnt), status::OK); 46 | UT_ASSERT(cnt == 5); 47 | ASSERT_STATUS(kv.get("123456789ABCDEFGHI", &value5), status::OK); 48 | UT_ASSERT(value5 == "E"); 49 | } 50 | 51 | static void test(int argc, char *argv[]) 52 | { 53 | if (argc < 3) 54 | UT_FATAL("usage: %s engine json_config", argv[0]); 55 | 56 | run_engine_tests(argv[1], argv[2], 57 | { 58 | PutKeysOfDifferentSizesTest, 59 | }); 60 | } 61 | 62 | int main(int argc, char *argv[]) 63 | { 64 | return run_test([&] { test(argc, argv); }); 65 | } 66 | -------------------------------------------------------------------------------- /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/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/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 | std::size_t cnt = std::numeric_limits::max(); 24 | ASSERT_STATUS(kv.count_all(cnt), status::OK); 25 | UT_ASSERT(cnt == iterations); 26 | } 27 | 28 | static void LargeDescendingTest(const size_t iterations, pmem::kv::db &kv) 29 | { 30 | for (size_t i = iterations; i >= 1; i--) { 31 | std::string istr = entry_from_number(i); 32 | ASSERT_STATUS(kv.put(istr, entry_from_number(i, "ABC")), status::OK); 33 | std::string value; 34 | ASSERT_STATUS(kv.get(istr, &value), status::OK); 35 | UT_ASSERT(value == entry_from_number(i, "ABC")); 36 | } 37 | for (size_t i = iterations; i >= 1; i--) { 38 | std::string istr = entry_from_number(i); 39 | std::string value; 40 | ASSERT_STATUS(kv.get(istr, &value), status::OK); 41 | UT_ASSERT(value == entry_from_number(i, "ABC")); 42 | } 43 | std::size_t cnt = std::numeric_limits::max(); 44 | ASSERT_STATUS(kv.count_all(cnt), status::OK); 45 | UT_ASSERT(cnt == iterations); 46 | } 47 | 48 | static void test(int argc, char *argv[]) 49 | { 50 | using namespace std::placeholders; 51 | 52 | if (argc < 4) 53 | UT_FATAL("usage: %s engine json_config iterations", argv[0]); 54 | 55 | auto iterations = std::stoull(argv[3]); 56 | 57 | run_engine_tests(argv[1], argv[2], 58 | { 59 | std::bind(LargeAscendingTest, iterations, _1), 60 | std::bind(LargeDescendingTest, iterations, _1), 61 | }); 62 | } 63 | 64 | int main(int argc, char *argv[]) 65 | { 66 | return run_test([&] { test(argc, argv); }); 67 | } 68 | -------------------------------------------------------------------------------- /utils/docker/images/Dockerfile.archlinux-base-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 archlinux-based 6 | # environment prepared for running pmemkv tests. 7 | # 8 | 9 | # Pull base image 10 | FROM archlinux/base:latest 11 | MAINTAINER igor.chorazewicz@intel.com 12 | 13 | # Set required environment variables 14 | ENV OS archlinux-base 15 | ENV OS_VER latest 16 | ENV NOTTY 1 17 | 18 | # Additional parameters to build docker without building components 19 | ARG SKIP_VALGRIND_BUILD 20 | ARG SKIP_PMDK_BUILD 21 | ARG SKIP_LIBPMEMOBJCPP_BUILD 22 | 23 | # Update the pacman cache and install basic tools 24 | RUN pacman -Syu --noconfirm 25 | RUN pacman -S --noconfirm \ 26 | asciidoc \ 27 | autoconf \ 28 | automake \ 29 | bash-completion \ 30 | clang \ 31 | cmake \ 32 | doxygen \ 33 | file \ 34 | gcc \ 35 | gdb \ 36 | git \ 37 | graphviz \ 38 | gzip \ 39 | intel-tbb \ 40 | libunwind \ 41 | llvm \ 42 | make \ 43 | numactl \ 44 | pandoc \ 45 | perl-text-diff \ 46 | pkg-config \ 47 | sfml \ 48 | sudo \ 49 | wget \ 50 | which \ 51 | whois \ 52 | xmlto 53 | 54 | # Install rapidjson from sources 55 | COPY install-rapidjson.sh install-rapidjson.sh 56 | RUN ./install-rapidjson.sh 57 | 58 | # Install libndctl 59 | COPY install-libndctl.sh install-libndctl.sh 60 | RUN ./install-libndctl.sh archlinux-base 61 | 62 | # Install valgrind 63 | COPY install-valgrind.sh install-valgrind.sh 64 | RUN ./install-valgrind.sh 65 | 66 | # Install pmdk 67 | COPY install-pmdk.sh install-pmdk.sh 68 | RUN ./install-pmdk.sh 69 | 70 | # Install pmdk c++ bindings 71 | COPY install-libpmemobj-cpp.sh install-libpmemobj-cpp.sh 72 | RUN ./install-libpmemobj-cpp.sh 73 | 74 | # Install memkind 75 | COPY install-memkind.sh install-memkind.sh 76 | RUN ./install-memkind.sh 77 | 78 | # Add user 79 | ENV USER user 80 | ENV USERPASS p1a2s3s4 81 | ENV PFILE ./password 82 | RUN useradd -m $USER 83 | RUN echo $USERPASS > $PFILE 84 | RUN echo $USERPASS >> $PFILE 85 | RUN passwd $USER < $PFILE 86 | RUN rm -f $PFILE 87 | RUN sed -i 's/# %wheel ALL=(ALL) NOPASSWD: ALL/%wheel ALL=(ALL) NOPASSWD: ALL/g' /etc/sudoers 88 | RUN gpasswd wheel -a $USER 89 | USER $USER 90 | 91 | # Clean the cache of packages 92 | RUN rm -rf /var/cache/pacman/pkg/* 93 | -------------------------------------------------------------------------------- /utils/docker/images/Dockerfile.ubuntu-20.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 ubuntu:20.04 11 | MAINTAINER igor.chorazewicz@intel.com 12 | 13 | # Set required environment variables 14 | ENV OS ubuntu 15 | ENV OS_VER 20.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 | ENV COVERITY_DEPS "\ 26 | ruby \ 27 | wget" 28 | 29 | # Update the Apt cache and install basic tools 30 | RUN apt-get update 31 | RUN DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ 32 | autoconf \ 33 | automake \ 34 | build-essential \ 35 | clang \ 36 | clang-format-9 \ 37 | cmake \ 38 | curl \ 39 | debhelper \ 40 | devscripts \ 41 | doxygen \ 42 | fakeroot \ 43 | gdb \ 44 | git \ 45 | graphviz \ 46 | libc6-dbg \ 47 | libdaxctl-dev \ 48 | libndctl-dev \ 49 | libmemkind-dev \ 50 | libnode-dev \ 51 | libnuma-dev \ 52 | libtbb-dev \ 53 | libtext-diff-perl \ 54 | libtool \ 55 | libunwind8-dev \ 56 | numactl \ 57 | pandoc \ 58 | pkg-config \ 59 | sudo \ 60 | wget \ 61 | whois \ 62 | $COVERITY_DEPS \ 63 | && rm -rf /var/lib/apt/lists/* 64 | 65 | # Install rapidjson from sources 66 | COPY install-rapidjson.sh install-rapidjson.sh 67 | RUN ./install-rapidjson.sh 68 | 69 | # Install valgrind 70 | COPY install-valgrind.sh install-valgrind.sh 71 | RUN ./install-valgrind.sh 72 | 73 | # Install pmdk 74 | COPY install-pmdk.sh install-pmdk.sh 75 | RUN ./install-pmdk.sh dpkg 76 | 77 | # Install pmdk c++ bindings 78 | COPY install-libpmemobj-cpp.sh install-libpmemobj-cpp.sh 79 | RUN ./install-libpmemobj-cpp.sh DEB 80 | 81 | # Download scripts required in run-*.sh 82 | COPY download-scripts.sh download-scripts.sh 83 | COPY 0001-fix-generating-gcov-files-and-turn-off-verbose-log.patch 0001-fix-generating-gcov-files-and-turn-off-verbose-log.patch 84 | RUN ./download-scripts.sh 85 | 86 | # Add user 87 | ENV USER user 88 | ENV USERPASS pass 89 | RUN useradd -m $USER -g sudo -p `mkpasswd $USERPASS` 90 | USER $USER 91 | -------------------------------------------------------------------------------- /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.ubuntu-20.10: -------------------------------------------------------------------------------- 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 | # Separate image for testing rapidjson installed from package. 8 | # 9 | 10 | # Pull base image 11 | FROM ubuntu:20.10 12 | MAINTAINER igor.chorazewicz@intel.com 13 | 14 | # Set required environment variables 15 | ENV OS ubuntu 16 | ENV OS_VER 20.10 17 | ENV PACKAGE_MANAGER deb 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 | ARG SKIP_SCRIPTS_DOWNLOAD 25 | 26 | ENV COVERITY_DEPS "\ 27 | ruby \ 28 | wget" 29 | 30 | ARG PMEMKV_DEPS="\ 31 | rapidjson-dev" 32 | 33 | # Update the Apt cache and install basic tools 34 | RUN apt-get update 35 | RUN DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ 36 | autoconf \ 37 | automake \ 38 | build-essential \ 39 | clang \ 40 | clang-format-9 \ 41 | cmake \ 42 | curl \ 43 | debhelper \ 44 | devscripts \ 45 | doxygen \ 46 | fakeroot \ 47 | gdb \ 48 | git \ 49 | graphviz \ 50 | libc6-dbg \ 51 | libdaxctl-dev \ 52 | libndctl-dev \ 53 | libmemkind-dev \ 54 | libnode-dev \ 55 | libnuma-dev \ 56 | libtbb-dev \ 57 | libtext-diff-perl \ 58 | libtool \ 59 | libunwind8-dev \ 60 | numactl \ 61 | pandoc \ 62 | pkg-config \ 63 | sudo \ 64 | wget \ 65 | whois \ 66 | $COVERITY_DEPS \ 67 | $PMEMKV_DEPS \ 68 | && rm -rf /var/lib/apt/lists/* 69 | 70 | # Install valgrind 71 | COPY install-valgrind.sh install-valgrind.sh 72 | RUN ./install-valgrind.sh 73 | 74 | # Install pmdk 75 | COPY install-pmdk.sh install-pmdk.sh 76 | RUN ./install-pmdk.sh dpkg 77 | 78 | # Install pmdk c++ bindings 79 | COPY install-libpmemobj-cpp.sh install-libpmemobj-cpp.sh 80 | RUN ./install-libpmemobj-cpp.sh DEB 81 | 82 | # Download scripts required in run-*.sh 83 | COPY download-scripts.sh download-scripts.sh 84 | COPY 0001-fix-generating-gcov-files-and-turn-off-verbose-log.patch 0001-fix-generating-gcov-files-and-turn-off-verbose-log.patch 85 | RUN ./download-scripts.sh 86 | 87 | # Add user 88 | ENV USER user 89 | ENV USERPASS pass 90 | RUN useradd -m $USER -g sudo -p `mkpasswd $USERPASS` 91 | USER $USER 92 | -------------------------------------------------------------------------------- /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 | #ifndef ENGINE_PSKIPLIST 86 | UT_ASSERT(wrong_engine_name_test("pskiplist")); 87 | #endif 88 | 89 | errormsg_test(); 90 | 91 | return 0; 92 | } 93 | -------------------------------------------------------------------------------- /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 | # 9 | 10 | # Pull base image 11 | FROM ubuntu:20.04 12 | MAINTAINER igor.chorazewicz@intel.com 13 | 14 | # Set required environment variables 15 | ENV OS ubuntu 16 | ENV OS_VER 20.04_bindings 17 | ENV PACKAGE_MANAGER deb 18 | ENV NOTTY 1 19 | ENV JAVA_HOME /usr/lib/jvm/java-8-openjdk-amd64 20 | 21 | # Additional parameters to build docker without building components 22 | ARG SKIP_VALGRIND_BUILD 23 | ARG SKIP_PMDK_BUILD 24 | ARG SKIP_LIBPMEMOBJCPP_BUILD 25 | 26 | # Update the Apt cache and install basic tools 27 | RUN apt-get update 28 | RUN DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ 29 | autoconf \ 30 | automake \ 31 | build-essential \ 32 | clang \ 33 | clang-format-9 \ 34 | cmake \ 35 | curl \ 36 | debhelper \ 37 | devscripts \ 38 | doxygen \ 39 | fakeroot \ 40 | gdb \ 41 | git \ 42 | graphviz \ 43 | libc6-dbg \ 44 | libdaxctl-dev \ 45 | libgtest-dev \ 46 | libndctl-dev \ 47 | libnode-dev \ 48 | libnuma-dev \ 49 | libmemkind-dev \ 50 | libtbb-dev \ 51 | libtext-diff-perl \ 52 | libtool \ 53 | libunwind8-dev \ 54 | maven \ 55 | npm \ 56 | numactl \ 57 | openjdk-8-jdk \ 58 | pandoc \ 59 | pkg-config \ 60 | python3-dev \ 61 | python3-distutils \ 62 | python3-pip \ 63 | ruby-dev \ 64 | sudo \ 65 | wget \ 66 | whois \ 67 | && rm -rf /var/lib/apt/lists/* 68 | 69 | # Install rapidjson from sources 70 | COPY install-rapidjson.sh install-rapidjson.sh 71 | RUN ./install-rapidjson.sh 72 | 73 | # Install valgrind 74 | COPY install-valgrind.sh install-valgrind.sh 75 | RUN ./install-valgrind.sh 76 | 77 | # Install pmdk 78 | COPY install-pmdk.sh install-pmdk.sh 79 | RUN ./install-pmdk.sh dpkg 80 | 81 | # Install pmdk c++ bindings 82 | COPY install-libpmemobj-cpp.sh install-libpmemobj-cpp.sh 83 | RUN ./install-libpmemobj-cpp.sh DEB 84 | 85 | # Bindings 86 | RUN pip3 install pytest setuptools wheel 87 | COPY install-bindings-dependencies.sh install-bindings-dependencies.sh 88 | RUN ./install-bindings-dependencies.sh 89 | 90 | # Add user 91 | ENV USER user 92 | ENV USERPASS pass 93 | RUN useradd -m $USER -g sudo -p `mkpasswd $USERPASS` 94 | USER $USER 95 | -------------------------------------------------------------------------------- /utils/docker/run-coverity.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | # Copyright 2018-2020, 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 | -------------------------------------------------------------------------------- /src/engines/blackhole.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2017-2021, Intel Corporation */ 3 | 4 | #pragma once 5 | 6 | #include "../engine.h" 7 | 8 | namespace pmem 9 | { 10 | namespace kv 11 | { 12 | 13 | class blackhole : public engine_base { 14 | class blackhole_iterator; 15 | 16 | public: 17 | blackhole(std::unique_ptr cfg); 18 | ~blackhole(); 19 | 20 | std::string name() final; 21 | 22 | status count_all(std::size_t &cnt) final; 23 | status count_above(string_view key, std::size_t &cnt) final; 24 | status count_equal_above(string_view key, std::size_t &cnt) final; 25 | status count_equal_below(string_view key, std::size_t &cnt) final; 26 | status count_below(string_view key, std::size_t &cnt) final; 27 | status count_between(string_view key1, string_view key2, std::size_t &cnt) final; 28 | 29 | status get_all(get_kv_callback *callback, void *arg) final; 30 | status get_above(string_view key, get_kv_callback *callback, void *arg) final; 31 | status get_equal_above(string_view key, get_kv_callback *callback, 32 | void *arg) final; 33 | status get_equal_below(string_view key, get_kv_callback *callback, 34 | void *arg) final; 35 | status get_below(string_view key, get_kv_callback *callback, void *arg) final; 36 | status get_between(string_view key1, string_view key2, get_kv_callback *callback, 37 | void *arg) final; 38 | 39 | status exists(string_view key) final; 40 | 41 | status get(string_view key, get_v_callback *callback, void *arg) final; 42 | 43 | status put(string_view key, string_view value) final; 44 | 45 | status remove(string_view key) final; 46 | 47 | internal::iterator_base *new_iterator() final; 48 | internal::iterator_base *new_const_iterator() final; 49 | }; 50 | 51 | class blackhole::blackhole_iterator : public internal::iterator_base { 52 | public: 53 | status seek(string_view key) final; 54 | 55 | result key() final; 56 | 57 | result> read_range(size_t pos, size_t n) final; 58 | 59 | private: 60 | std::string name(); 61 | }; 62 | 63 | class blackhole_factory : public engine_base::factory_base { 64 | public: 65 | std::unique_ptr 66 | create(std::unique_ptr cfg) override 67 | { 68 | return std::unique_ptr(new blackhole(std::move(cfg))); 69 | }; 70 | std::string get_name() override 71 | { 72 | return "blackhole"; 73 | }; 74 | }; 75 | 76 | } /* namespace kv */ 77 | } /* namespace pmem */ 78 | -------------------------------------------------------------------------------- /utils/docker/images/Dockerfile.opensuse-tumbleweed-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 opensuse-based 6 | # environment prepared for running pmemkv build and tests. 7 | # 8 | 9 | # Pull base image 10 | FROM opensuse/tumbleweed:latest 11 | MAINTAINER igor.chorazewicz@intel.com 12 | 13 | # Set required environment variables 14 | ENV OS opensuse-tumbleweed 15 | ENV OS_VER latest 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 | # Update the OS 25 | RUN zypper dup -y 26 | 27 | # Update all packages 28 | RUN zypper update -y 29 | 30 | # Enable the debuginfo repo 31 | RUN zypper mr -e repo-debug 32 | 33 | # Install basic tools 34 | RUN zypper install -y \ 35 | autoconf \ 36 | automake \ 37 | bash-completion \ 38 | clang9 \ 39 | cmake \ 40 | doxygen \ 41 | fdupes \ 42 | gcc \ 43 | gcc-c++ \ 44 | gdb \ 45 | glibc-debuginfo \ 46 | git \ 47 | graphviz \ 48 | gzip \ 49 | keyutils-devel \ 50 | make \ 51 | man \ 52 | memkind-devel \ 53 | libjson-c-devel \ 54 | libkmod-devel \ 55 | libndctl-devel \ 56 | libnuma-devel \ 57 | libtool \ 58 | libudev-devel \ 59 | libunwind-devel \ 60 | libuuid-devel \ 61 | pandoc \ 62 | perl-Text-Diff \ 63 | 'pkgconfig(bash-completion)' \ 64 | rapidjson-devel \ 65 | rpm-build \ 66 | sudo \ 67 | tbb-devel \ 68 | wget \ 69 | which 70 | 71 | RUN zypper clean all 72 | 73 | # Install libndctl 74 | COPY install-libndctl.sh install-libndctl.sh 75 | RUN ./install-libndctl.sh opensuse 76 | 77 | # Install valgrind 78 | COPY install-valgrind.sh install-valgrind.sh 79 | RUN ./install-valgrind.sh opensuse 80 | 81 | # Install pmdk 82 | COPY install-pmdk.sh install-pmdk.sh 83 | RUN ./install-pmdk.sh rpm 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 p1a2s3s4 92 | ENV PFILE ./password 93 | RUN useradd -m $USER 94 | RUN echo $USERPASS > $PFILE 95 | RUN echo $USERPASS >> $PFILE 96 | RUN passwd $USER < $PFILE 97 | RUN rm -f $PFILE 98 | RUN sed -i 's/# %wheel ALL=(ALL) NOPASSWD: ALL/%wheel ALL=(ALL) NOPASSWD: ALL/g' /etc/sudoers 99 | RUN groupadd wheel 100 | RUN gpasswd wheel -a $USER 101 | USER $USER 102 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /utils/docker/images/Dockerfile.ubuntu-18.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 | # It's using rapidjson installed from package. 8 | # 9 | 10 | # Pull base image 11 | FROM ubuntu:18.04 12 | MAINTAINER igor.chorazewicz@intel.com 13 | 14 | # Set required environment variables 15 | ENV OS ubuntu 16 | ENV OS_VER 18.04 17 | ENV PACKAGE_MANAGER deb 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 | ARG NDCTL_DEPS="\ 26 | bash-completion \ 27 | libkeyutils-dev \ 28 | libkmod-dev \ 29 | libudev-dev \ 30 | systemd" 31 | 32 | ARG LIBPMEMOBJ_CPP_DEPS="\ 33 | libatomic1" 34 | 35 | ARG PMEMKV_DEPS="\ 36 | rapidjson-dev" 37 | 38 | # Update the Apt cache and install basic tools 39 | RUN apt-get update \ 40 | && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ 41 | autoconf \ 42 | automake \ 43 | build-essential \ 44 | clang \ 45 | clang-format-9 \ 46 | cmake \ 47 | curl \ 48 | debhelper \ 49 | devscripts \ 50 | doxygen \ 51 | fakeroot \ 52 | gdb \ 53 | git \ 54 | graphviz \ 55 | libc6-dbg \ 56 | libnuma-dev \ 57 | libjson-c-dev \ 58 | libkmod-dev \ 59 | libtbb-dev \ 60 | libtext-diff-perl \ 61 | libudev-dev \ 62 | libunwind-dev \ 63 | numactl \ 64 | libtool \ 65 | pandoc \ 66 | pkg-config \ 67 | software-properties-common \ 68 | sudo \ 69 | uuid-dev \ 70 | whois \ 71 | $NDCTL_DEPS \ 72 | $LIBPMEMOBJ_CPP_DEPS \ 73 | $PMEMKV_DEPS \ 74 | && rm -rf /var/lib/apt/lists/* 75 | 76 | # Install libndctl 77 | COPY install-libndctl.sh install-libndctl.sh 78 | RUN ./install-libndctl.sh ubuntu 79 | 80 | # Install valgrind 81 | COPY install-valgrind.sh install-valgrind.sh 82 | RUN ./install-valgrind.sh 83 | 84 | # Install pmdk from sources (because there are no ndctl packages) 85 | COPY install-pmdk.sh install-pmdk.sh 86 | RUN ./install-pmdk.sh 87 | 88 | # Install pmdk c++ bindings (also from sources) 89 | COPY install-libpmemobj-cpp.sh install-libpmemobj-cpp.sh 90 | RUN ./install-libpmemobj-cpp.sh 91 | 92 | # Install memkind 93 | COPY install-memkind.sh install-memkind.sh 94 | RUN ./install-memkind.sh 95 | 96 | # Add user 97 | ENV USER user 98 | ENV USERPASS pass 99 | RUN useradd -m $USER -g sudo -p `mkpasswd $USERPASS` 100 | USER $USER 101 | -------------------------------------------------------------------------------- /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/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 | std::size_t size; 35 | ASSERT_STATUS(kv.count_all(size), pmem::kv::status::OK); 36 | UT_ASSERT(size == len_elements); 37 | 38 | std::string element = entry_from_number(len_elements); 39 | ASSERT_STATUS(kv.put(element, element), pmem::kv::status::OK); 40 | check_exist(kv, element, pmem::kv::status::OK); 41 | } 42 | 43 | static void check_consistency(pmem::kv::db &kv) 44 | { 45 | std::size_t size; 46 | ASSERT_STATUS(kv.count_all(size), pmem::kv::status::OK); 47 | std::size_t count = 0; 48 | 49 | for (size_t i = 0; i <= len_elements; i++) { 50 | std::string element = entry_from_number(i); 51 | if (kv.exists(element) == pmem::kv::status::OK) { 52 | ++count; 53 | check_exist(kv, element, pmem::kv::status::OK); 54 | } else { 55 | check_exist(kv, element, pmem::kv::status::NOT_FOUND); 56 | } 57 | } 58 | 59 | UT_ASSERTeq(count, size); 60 | } 61 | 62 | static void test(int argc, char *argv[]) 63 | { 64 | std::cout << "ARGC: " << argc << std::endl; 65 | for (int i = 0; i < argc; ++i) { 66 | std::cout << "ARGV " << i << " : " << argv[i] << std::endl; 67 | } 68 | if (argc < 4) 69 | UT_FATAL("usage: %s engine json_config ", argv[0]); 70 | 71 | std::string mode = argv[3]; 72 | if (mode != "create" && mode != "open" && mode != "insert") 73 | UT_FATAL("usage: %s engine json_config ", argv[0]); 74 | 75 | auto kv = INITIALIZE_KV(argv[1], CONFIG_FROM_JSON(argv[2])); 76 | 77 | if (mode == "create") { 78 | test_init(kv); 79 | } else if (mode == "open") { 80 | check_consistency(kv); 81 | } else if (mode == "insert") { 82 | test_insert(kv); 83 | } 84 | 85 | kv.close(); 86 | } 87 | 88 | int main(int argc, char *argv[]) 89 | { 90 | return run_test([&] { test(argc, argv); }); 91 | } 92 | -------------------------------------------------------------------------------- /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 | std::size_t size; 35 | ASSERT_STATUS(kv.count_all(size), pmem::kv::status::OK); 36 | UT_ASSERT(size == len_elements); 37 | 38 | std::string element = entry_from_number(1); /* remove this element */ 39 | check_exist(kv, element, pmem::kv::status::OK); 40 | 41 | ASSERT_STATUS(kv.remove(element), pmem::kv::status::OK); 42 | check_exist(kv, element, pmem::kv::status::NOT_FOUND); 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 | -------------------------------------------------------------------------------- /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-2020, 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 can be found in **libpmemkv_config**(3). 78 | 79 | # SEE ALSO # 80 | 81 | **libpmemkv**(7), **libpmemkv**(3), **libpmemkv_config**(3) and **** 82 | -------------------------------------------------------------------------------- /tests/config/json_to_config.cc: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2019-2020, Intel Corporation */ 3 | 4 | #include 5 | #include 6 | 7 | #include "unittest.hpp" 8 | 9 | /** 10 | * Tests pmemkv_config_from_json method in C API 11 | */ 12 | 13 | static void simple_test() 14 | { 15 | /** 16 | * TEST: basic data types put into json, to be read using 17 | * pmemkv_config_from_json() 18 | */ 19 | auto config = pmemkv_config_new(); 20 | UT_ASSERT(config != nullptr); 21 | 22 | auto ret = pmemkv_config_from_json( 23 | config, "{\"string\": \"abc\", \"int\": 123, \"bool\": true}"); 24 | // XXX: extend by adding "false", subconfig, negative value 25 | UT_ASSERTeq(ret, PMEMKV_STATUS_OK); 26 | 27 | const char *value_string; 28 | ret = pmemkv_config_get_string(config, "string", &value_string); 29 | UT_ASSERTeq(ret, PMEMKV_STATUS_OK); 30 | UT_ASSERT(std::string(value_string) == "abc"); 31 | 32 | int64_t value_int; 33 | ret = pmemkv_config_get_int64(config, "int", &value_int); 34 | UT_ASSERTeq(ret, PMEMKV_STATUS_OK); 35 | UT_ASSERTeq(value_int, 123); 36 | 37 | int64_t value_bool; 38 | ret = pmemkv_config_get_int64(config, "bool", &value_bool); 39 | UT_ASSERTeq(ret, PMEMKV_STATUS_OK); 40 | UT_ASSERTeq(value_bool, 1); 41 | 42 | ret = pmemkv_config_get_int64(config, "string", &value_int); 43 | UT_ASSERTeq(ret, PMEMKV_STATUS_CONFIG_TYPE_ERROR); 44 | 45 | pmemkv_config_delete(config); 46 | } 47 | 48 | static void double_test() 49 | { 50 | /** 51 | * TEST: floating point numbers are not supported 52 | */ 53 | auto config = pmemkv_config_new(); 54 | UT_ASSERT(config != nullptr); 55 | 56 | auto ret = pmemkv_config_from_json(config, "{\"double\": 12.34}"); 57 | UT_ASSERTeq(ret, PMEMKV_STATUS_CONFIG_PARSING_ERROR); 58 | UT_ASSERT( 59 | std::string(pmemkv_config_from_json_errormsg()) == 60 | "[pmemkv_config_from_json] Unsupported data type in JSON string: Number"); 61 | 62 | pmemkv_config_delete(config); 63 | } 64 | 65 | static void malformed_input_test() 66 | { 67 | /** 68 | * TEST: improperly formatted/malformed json string should return an error 69 | */ 70 | auto config = pmemkv_config_new(); 71 | UT_ASSERT(config != nullptr); 72 | 73 | auto ret = pmemkv_config_from_json(config, "{\"int\": 12"); 74 | UT_ASSERTeq(ret, PMEMKV_STATUS_CONFIG_PARSING_ERROR); 75 | UT_ASSERT(std::string(pmemkv_config_from_json_errormsg()) == 76 | "[pmemkv_config_from_json] Config parsing failed"); 77 | 78 | pmemkv_config_delete(config); 79 | } 80 | 81 | static void test(int argc, char *argv[]) 82 | { 83 | simple_test(); 84 | double_test(); 85 | malformed_input_test(); 86 | } 87 | 88 | int main(int argc, char *argv[]) 89 | { 90 | return run_test([&] { test(argc, argv); }); 91 | } 92 | -------------------------------------------------------------------------------- /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 = new db(); 71 | ASSERT(kv != nullptr); 72 | s = kv->open("csmap", std::move(cfg)); 73 | ASSERT(s == status::OK); 74 | 75 | LOG("Putting new keys"); 76 | s = kv->put("key1", "value1"); 77 | ASSERT(s == status::OK); 78 | s = kv->put("key2", "value2"); 79 | ASSERT(s == status::OK); 80 | s = kv->put("key3", "value3"); 81 | ASSERT(s == status::OK); 82 | 83 | LOG("Iterating over existing keys in order specified by the comparator"); 84 | kv->get_all([](string_view k, string_view v) { 85 | LOG(" visited: " << k.data()); 86 | return 0; 87 | }); 88 | //! [comparator-usage] 89 | 90 | LOG("Closing database"); 91 | delete kv; 92 | 93 | return 0; 94 | } 95 | -------------------------------------------------------------------------------- /examples/pmemkv_open_cpp/pmemkv_open.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /* Copyright 2019-2021, Intel Corporation */ 3 | 4 | /* 5 | * pmemkv_open.cpp -- example usage of pmemkv with already existing pools. 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 | //! [open] 24 | /* 25 | * This example expects a path to already created database pool. 26 | * 27 | * If you want to create pool, use one of the following commands. 28 | * 29 | * For regular pools use: 30 | * pmempool create -l -s 1G "pmemkv" obj path_to_a_pool 31 | * 32 | * For poolsets use: 33 | * pmempool create -l "pmemkv" obj ../examples/example.poolset 34 | */ 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 | /* Instead of expecting already created database pool, we could simply 47 | * set 'create_if_missing' flag in the config, to provide a pool if needed. */ 48 | status s = cfg.put_path(argv[1]); 49 | ASSERT(s == status::OK); 50 | 51 | LOG("Opening pmemkv database with 'cmap' engine"); 52 | db *kv = new db(); 53 | ASSERT(kv != nullptr); 54 | s = kv->open("cmap", std::move(cfg)); 55 | ASSERT(s == status::OK); 56 | 57 | LOG("Putting new key"); 58 | s = kv->put("key1", "value1"); 59 | ASSERT(s == status::OK); 60 | 61 | size_t cnt; 62 | s = kv->count_all(cnt); 63 | ASSERT(s == status::OK && cnt == 1); 64 | 65 | LOG("Reading key back"); 66 | std::string value; 67 | s = kv->get("key1", &value); 68 | ASSERT(s == status::OK && value == "value1"); 69 | 70 | LOG("Iterating existing keys"); 71 | s = kv->put("key2", "value2"); 72 | ASSERT(s == status::OK); 73 | s = kv->put("key3", "value3"); 74 | ASSERT(s == status::OK); 75 | kv->get_all([](string_view k, string_view v) { 76 | LOG(" visited: " << k.data()); 77 | return 0; 78 | }); 79 | 80 | LOG("Removing existing key"); 81 | s = kv->remove("key1"); 82 | ASSERT(s == status::OK); 83 | s = kv->exists("key1"); 84 | ASSERT(s == status::NOT_FOUND); 85 | 86 | LOG("Closing database"); 87 | delete kv; 88 | 89 | return 0; 90 | } 91 | //! [open] 92 | -------------------------------------------------------------------------------- /utils/docker/images/Dockerfile.opensuse-leap-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 opensuse-based 6 | # environment prepared for running pmemkv build and tests. 7 | # 8 | 9 | # Pull base image 10 | FROM opensuse/leap:latest 11 | MAINTAINER igor.chorazewicz@intel.com 12 | 13 | # Set required environment variables 14 | ENV OS opensuse-leap 15 | ENV OS_VER latest 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 | # Update the OS 25 | RUN zypper dup -y 26 | 27 | # Update all packages 28 | RUN zypper update -y 29 | 30 | # Install basic tools 31 | RUN zypper install -y \ 32 | autoconf \ 33 | automake \ 34 | bash-completion \ 35 | clang \ 36 | cmake \ 37 | doxygen \ 38 | fdupes \ 39 | gcc \ 40 | gcc-c++ \ 41 | gdb \ 42 | git \ 43 | graphviz \ 44 | gzip \ 45 | keyutils-devel \ 46 | make \ 47 | man \ 48 | memkind-devel \ 49 | libjson-c-devel \ 50 | libkmod-devel \ 51 | libndctl-devel \ 52 | libnuma-devel \ 53 | libtool \ 54 | libudev-devel \ 55 | libunwind-devel \ 56 | libuuid-devel \ 57 | pandoc \ 58 | perl-Text-Diff \ 59 | 'pkgconfig(bash-completion)' \ 60 | rapidjson-devel \ 61 | rpm-build \ 62 | sudo \ 63 | unzip \ 64 | wget \ 65 | which 66 | 67 | # Enable the debuginfo repo 68 | RUN zypper mr -e repo-debug 69 | RUN zypper install -y \ 70 | glibc-debuginfo 71 | 72 | # Install a newer version of TBB from the Education repository 73 | RUN zypper addrepo https://download.opensuse.org/repositories/Education/openSUSE_Leap_15.1/ education 74 | RUN zypper --gpg-auto-import-keys install -y \ 75 | tbb-devel 76 | 77 | RUN zypper clean all 78 | 79 | # Install libndctl 80 | COPY install-libndctl.sh install-libndctl.sh 81 | RUN ./install-libndctl.sh opensuse 82 | 83 | # Install valgrind 84 | COPY install-valgrind.sh install-valgrind.sh 85 | RUN ./install-valgrind.sh opensuse 86 | 87 | # Install pmdk 88 | COPY install-pmdk.sh install-pmdk.sh 89 | RUN ./install-pmdk.sh rpm 90 | 91 | # Install pmdk c++ bindings 92 | COPY install-libpmemobj-cpp.sh install-libpmemobj-cpp.sh 93 | RUN ./install-libpmemobj-cpp.sh RPM 94 | 95 | # Add user 96 | ENV USER user 97 | ENV USERPASS p1a2s3s4 98 | ENV PFILE ./password 99 | RUN useradd -m $USER 100 | RUN echo $USERPASS > $PFILE 101 | RUN echo $USERPASS >> $PFILE 102 | RUN passwd $USER < $PFILE 103 | RUN rm -f $PFILE 104 | RUN sed -i 's/# %wheel ALL=(ALL) NOPASSWD: ALL/%wheel ALL=(ALL) NOPASSWD: ALL/g' /etc/sudoers 105 | RUN groupadd wheel 106 | RUN gpasswd wheel -a $USER 107 | USER $USER 108 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 of the part of the pmemkv config API, 6 | * which should be preferred. 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #define ASSERT(expr) \ 17 | do { \ 18 | if (!(expr)) \ 19 | puts(pmemkv_errormsg()); \ 20 | assert(expr); \ 21 | } while (0) 22 | 23 | static const uint64_t SIZE = 1024UL * 1024UL * 1024UL; 24 | 25 | int key_length_compare(const char *key1, size_t keybytes1, const char *key2, 26 | size_t keybytes2, void *arg) 27 | { 28 | if (keybytes2 < keybytes1) 29 | return -1; 30 | else if (keybytes2 > keybytes1) 31 | return 1; 32 | else 33 | return 0; 34 | } 35 | 36 | int main(int argc, char *argv[]) 37 | { 38 | if (argc < 2) { 39 | fprintf(stderr, "Usage: %s file\n", argv[0]); 40 | exit(1); 41 | } 42 | 43 | /* Create config */ 44 | pmemkv_config *config = pmemkv_config_new(); 45 | ASSERT(config != NULL); 46 | 47 | /* Add path parameter to config. Meaning of this is dependent on chosen engine. 48 | * E.g. if config is used with cmap engine, 49 | * it is a path to a database file or to a poolset file. However for 50 | * vcmap it is a path to an existing directory */ 51 | int status = pmemkv_config_put_path(config, argv[1]); 52 | ASSERT(status == PMEMKV_STATUS_OK); 53 | 54 | /* Specifies size of the database */ 55 | status = pmemkv_config_put_size(config, SIZE); 56 | ASSERT(status == PMEMKV_STATUS_OK); 57 | 58 | /* Specifies value of create_if_missing flag. 59 | * Alternatively, another flag - 'create_or_error_if_exists' can be set using: 60 | * `pmemkv_config_put_create_or_error_if_exists` 61 | * For differences between the two, see manpage libpmemkv(7). */ 62 | status = pmemkv_config_put_create_if_missing(config, true); 63 | ASSERT(status == PMEMKV_STATUS_OK); 64 | 65 | /* Specifies comparator used by the engine */ 66 | pmemkv_comparator *cmp = 67 | pmemkv_comparator_new(&key_length_compare, "key_length_compare", NULL); 68 | ASSERT(cmp != NULL); 69 | status = pmemkv_config_put_comparator(config, cmp); 70 | ASSERT(status == PMEMKV_STATUS_OK); 71 | 72 | /* Adds pointer to oid (for details see libpmemkv(7)) to the config */ 73 | PMEMoid oid; 74 | status = pmemkv_config_put_oid(config, &oid); 75 | ASSERT(status == PMEMKV_STATUS_OK); 76 | 77 | pmemkv_config_delete(config); 78 | 79 | return 0; 80 | } 81 | --------------------------------------------------------------------------------